therubyracer 0.7.4 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of therubyracer might be problematic. Click here for more details.

Files changed (482) hide show
  1. data/History.txt +11 -0
  2. data/Rakefile +1 -1
  3. data/ext/v8/extconf.rb +0 -18
  4. data/ext/v8/rr.cpp +2 -2
  5. data/ext/v8/upstream/{2.1.10 → 2.3.3}/AUTHORS +1 -0
  6. data/ext/v8/upstream/{2.1.10 → 2.3.3}/ChangeLog +239 -0
  7. data/ext/v8/upstream/{2.1.10 → 2.3.3}/LICENSE +0 -0
  8. data/ext/v8/upstream/{2.1.10 → 2.3.3}/SConstruct +29 -17
  9. data/ext/v8/upstream/{2.1.10 → 2.3.3}/include/v8-debug.h +61 -3
  10. data/ext/v8/upstream/{2.1.10 → 2.3.3}/include/v8-profiler.h +182 -5
  11. data/ext/v8/upstream/{2.1.10 → 2.3.3}/include/v8.h +458 -257
  12. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/SConscript +2 -5
  13. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/accessors.cc +2 -2
  14. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/accessors.h +0 -0
  15. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/allocation.cc +0 -0
  16. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/allocation.h +0 -0
  17. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/api.cc +574 -30
  18. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/api.h +12 -10
  19. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/apinatives.js +0 -0
  20. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/apiutils.h +0 -0
  21. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arguments.h +0 -0
  22. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/assembler-arm-inl.h +38 -15
  23. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/assembler-arm.cc +646 -101
  24. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/assembler-arm.h +174 -15
  25. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/builtins-arm.cc +56 -47
  26. data/ext/v8/upstream/2.3.3/src/arm/codegen-arm-inl.h +48 -0
  27. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/codegen-arm.cc +2957 -1448
  28. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/codegen-arm.h +230 -74
  29. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/constants-arm.cc +25 -1
  30. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/constants-arm.h +16 -1
  31. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/cpu-arm.cc +4 -0
  32. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/debug-arm.cc +76 -6
  33. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/disasm-arm.cc +168 -20
  34. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/fast-codegen-arm.cc +5 -2
  35. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/frames-arm.cc +4 -4
  36. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/frames-arm.h +0 -0
  37. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/full-codegen-arm.cc +1558 -248
  38. data/ext/v8/upstream/2.3.3/src/arm/ic-arm.cc +2258 -0
  39. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/jump-target-arm.cc +55 -103
  40. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/macro-assembler-arm.cc +358 -185
  41. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/macro-assembler-arm.h +136 -41
  42. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/regexp-macro-assembler-arm.cc +26 -5
  43. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/regexp-macro-assembler-arm.h +0 -0
  44. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/register-allocator-arm-inl.h +0 -0
  45. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/register-allocator-arm.cc +4 -0
  46. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/register-allocator-arm.h +0 -0
  47. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/simulator-arm.cc +203 -22
  48. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/simulator-arm.h +7 -0
  49. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/stub-cache-arm.cc +531 -324
  50. data/ext/v8/upstream/2.3.3/src/arm/virtual-frame-arm-inl.h +59 -0
  51. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/virtual-frame-arm.cc +247 -81
  52. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/virtual-frame-arm.h +99 -83
  53. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/array.js +2 -2
  54. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/assembler.cc +6 -13
  55. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/assembler.h +36 -10
  56. data/ext/v8/upstream/2.3.3/src/ast-inl.h +81 -0
  57. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ast.cc +14 -0
  58. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ast.h +20 -35
  59. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/bootstrapper.cc +32 -1
  60. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/bootstrapper.h +0 -4
  61. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/builtins.cc +50 -33
  62. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/builtins.h +2 -0
  63. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/bytecodes-irregexp.h +0 -0
  64. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cached-powers.h +0 -0
  65. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/char-predicates-inl.h +0 -0
  66. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/char-predicates.h +0 -0
  67. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/checks.cc +0 -0
  68. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/checks.h +8 -6
  69. data/ext/v8/upstream/2.3.3/src/circular-queue-inl.h +53 -0
  70. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/circular-queue.cc +0 -0
  71. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/circular-queue.h +0 -26
  72. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/code-stubs.cc +2 -4
  73. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/code-stubs.h +1 -0
  74. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/code.h +0 -0
  75. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/codegen-inl.h +0 -0
  76. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/codegen.cc +44 -13
  77. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/codegen.h +310 -31
  78. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compilation-cache.cc +28 -0
  79. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compilation-cache.h +3 -0
  80. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compiler.cc +45 -14
  81. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compiler.h +0 -0
  82. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/contexts.cc +11 -11
  83. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/contexts.h +0 -0
  84. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/conversions-inl.h +0 -0
  85. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/conversions.cc +25 -11
  86. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/conversions.h +0 -0
  87. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/counters.cc +0 -0
  88. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/counters.h +0 -0
  89. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu-profiler-inl.h +2 -1
  90. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu-profiler.cc +68 -24
  91. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu-profiler.h +19 -11
  92. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu.h +0 -0
  93. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-debug.cc +0 -0
  94. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-debug.h +0 -0
  95. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-posix.cc +0 -0
  96. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-readline.cc +0 -0
  97. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-windows.cc +0 -0
  98. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8.cc +3 -0
  99. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8.h +0 -0
  100. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8.js +55 -2
  101. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/data-flow.cc +3 -0
  102. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/data-flow.h +0 -0
  103. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/date.js +68 -137
  104. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dateparser-inl.h +0 -0
  105. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dateparser.cc +2 -8
  106. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dateparser.h +0 -0
  107. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug-agent.cc +3 -3
  108. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug-agent.h +0 -0
  109. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug-debugger.js +81 -23
  110. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug.cc +275 -81
  111. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug.h +85 -6
  112. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/disasm.h +0 -0
  113. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/disassembler.cc +1 -1
  114. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/disassembler.h +0 -0
  115. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/diy-fp.cc +0 -0
  116. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/diy-fp.h +0 -0
  117. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/double.h +0 -0
  118. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dtoa-config.c +0 -0
  119. data/ext/v8/upstream/2.3.3/src/dtoa.cc +77 -0
  120. data/ext/v8/upstream/2.3.3/src/dtoa.h +81 -0
  121. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/execution.cc +111 -3
  122. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/execution.h +12 -1
  123. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/factory.cc +25 -3
  124. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/factory.h +16 -9
  125. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-codegen.cc +0 -0
  126. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-codegen.h +0 -0
  127. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-dtoa.cc +2 -9
  128. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-dtoa.h +1 -2
  129. data/ext/v8/upstream/2.3.3/src/fixed-dtoa.cc +405 -0
  130. data/ext/v8/upstream/{2.1.10/src/jump-target-light.cc → 2.3.3/src/fixed-dtoa.h} +22 -53
  131. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flag-definitions.h +14 -6
  132. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flags.cc +5 -9
  133. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flags.h +0 -0
  134. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flow-graph.cc +0 -0
  135. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flow-graph.h +0 -0
  136. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frame-element.cc +0 -0
  137. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frame-element.h +0 -0
  138. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frames-inl.h +0 -0
  139. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frames.cc +5 -2
  140. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frames.h +1 -0
  141. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/full-codegen.cc +387 -20
  142. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/full-codegen.h +102 -5
  143. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/func-name-inferrer.cc +0 -0
  144. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/func-name-inferrer.h +0 -0
  145. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/global-handles.cc +8 -4
  146. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/global-handles.h +0 -0
  147. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/globals.h +44 -7
  148. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/handles-inl.h +0 -0
  149. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/handles.cc +19 -0
  150. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/handles.h +8 -0
  151. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/hashmap.cc +0 -0
  152. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/hashmap.h +0 -0
  153. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap-inl.h +56 -14
  154. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap-profiler.cc +85 -1
  155. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap-profiler.h +45 -1
  156. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap.cc +994 -396
  157. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap.h +220 -65
  158. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/assembler-ia32-inl.h +41 -12
  159. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/assembler-ia32.cc +94 -24
  160. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/assembler-ia32.h +32 -4
  161. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/builtins-ia32.cc +42 -30
  162. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/codegen-ia32-inl.h +0 -0
  163. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/codegen-ia32.cc +1758 -916
  164. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/codegen-ia32.h +67 -74
  165. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/cpu-ia32.cc +4 -0
  166. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/debug-ia32.cc +46 -0
  167. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/disasm-ia32.cc +37 -6
  168. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/fast-codegen-ia32.cc +4 -0
  169. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/fast-codegen-ia32.h +0 -0
  170. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/frames-ia32.cc +4 -0
  171. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/frames-ia32.h +0 -0
  172. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/full-codegen-ia32.cc +1465 -198
  173. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/ic-ia32.cc +688 -367
  174. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/jump-target-ia32.cc +4 -0
  175. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/macro-assembler-ia32.cc +82 -180
  176. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/macro-assembler-ia32.h +41 -25
  177. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/regexp-macro-assembler-ia32.cc +68 -24
  178. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/regexp-macro-assembler-ia32.h +1 -2
  179. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/register-allocator-ia32-inl.h +0 -0
  180. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/register-allocator-ia32.cc +4 -0
  181. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/register-allocator-ia32.h +0 -0
  182. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/simulator-ia32.cc +0 -0
  183. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/simulator-ia32.h +0 -0
  184. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/stub-cache-ia32.cc +649 -302
  185. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/virtual-frame-ia32.cc +23 -1
  186. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/virtual-frame-ia32.h +18 -27
  187. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ic-inl.h +30 -3
  188. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ic.cc +384 -66
  189. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ic.h +65 -24
  190. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/interpreter-irregexp.cc +0 -0
  191. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/interpreter-irregexp.h +0 -0
  192. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/json.js +3 -3
  193. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jsregexp.cc +20 -4
  194. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jsregexp.h +0 -0
  195. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-heavy-inl.h +0 -0
  196. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-heavy.cc +79 -13
  197. data/ext/v8/upstream/{2.1.10/src/jump-target.h → 2.3.3/src/jump-target-heavy.h} +5 -47
  198. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-inl.h +0 -0
  199. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-light-inl.h +16 -2
  200. data/ext/v8/upstream/2.3.3/src/jump-target-light.cc +110 -0
  201. data/ext/v8/upstream/2.3.3/src/jump-target-light.h +192 -0
  202. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target.cc +0 -64
  203. data/ext/v8/upstream/2.3.3/src/jump-target.h +90 -0
  204. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/list-inl.h +0 -0
  205. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/list.h +0 -0
  206. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/liveedit-debugger.js +141 -28
  207. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/liveedit.cc +19 -7
  208. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/liveedit.h +0 -0
  209. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log-inl.h +0 -0
  210. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log-utils.cc +0 -0
  211. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log-utils.h +0 -0
  212. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log.cc +12 -11
  213. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log.h +12 -0
  214. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/macro-assembler.h +0 -16
  215. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/macros.py +21 -0
  216. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mark-compact.cc +120 -109
  217. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mark-compact.h +25 -37
  218. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/math.js +0 -0
  219. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/memory.h +0 -0
  220. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/messages.cc +8 -3
  221. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/messages.h +2 -1
  222. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/messages.js +15 -7
  223. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/assembler-mips-inl.h +0 -0
  224. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/assembler-mips.cc +12 -1
  225. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/assembler-mips.h +4 -1
  226. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/builtins-mips.cc +3 -0
  227. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/codegen-mips-inl.h +0 -0
  228. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/codegen-mips.cc +9 -0
  229. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/codegen-mips.h +1 -0
  230. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/constants-mips.cc +5 -0
  231. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/constants-mips.h +0 -0
  232. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/cpu-mips.cc +4 -0
  233. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/debug-mips.cc +3 -0
  234. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/disasm-mips.cc +3 -0
  235. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/fast-codegen-mips.cc +3 -0
  236. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/frames-mips.cc +3 -0
  237. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/frames-mips.h +0 -0
  238. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/full-codegen-mips.cc +5 -1
  239. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/ic-mips.cc +3 -0
  240. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/jump-target-mips.cc +3 -0
  241. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/macro-assembler-mips.cc +3 -0
  242. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/macro-assembler-mips.h +0 -0
  243. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/register-allocator-mips-inl.h +0 -0
  244. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/register-allocator-mips.cc +3 -0
  245. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/register-allocator-mips.h +0 -0
  246. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/simulator-mips.cc +3 -0
  247. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/simulator-mips.h +0 -0
  248. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/stub-cache-mips.cc +3 -0
  249. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/virtual-frame-mips.cc +3 -0
  250. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/virtual-frame-mips.h +0 -0
  251. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mirror-debugger.js +46 -4
  252. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mksnapshot.cc +0 -0
  253. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/natives.h +0 -0
  254. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects-debug.cc +8 -1
  255. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects-inl.h +235 -62
  256. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects.cc +497 -231
  257. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects.h +355 -149
  258. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/oprofile-agent.cc +0 -0
  259. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/oprofile-agent.h +0 -0
  260. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/parser.cc +31 -6
  261. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/parser.h +1 -1
  262. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-freebsd.cc +9 -6
  263. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-linux.cc +26 -6
  264. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-macos.cc +11 -6
  265. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-nullos.cc +0 -0
  266. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-openbsd.cc +6 -0
  267. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-posix.cc +0 -0
  268. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-solaris.cc +69 -23
  269. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-win32.cc +15 -11
  270. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform.h +10 -6
  271. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/powers-ten.h +0 -0
  272. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/prettyprinter.cc +0 -0
  273. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/prettyprinter.h +0 -0
  274. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/profile-generator-inl.h +26 -2
  275. data/ext/v8/upstream/2.3.3/src/profile-generator.cc +1830 -0
  276. data/ext/v8/upstream/2.3.3/src/profile-generator.h +853 -0
  277. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/property.cc +0 -0
  278. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/property.h +0 -0
  279. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-irregexp-inl.h +0 -0
  280. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-irregexp.cc +0 -0
  281. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-irregexp.h +0 -0
  282. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-tracer.cc +0 -0
  283. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-tracer.h +0 -0
  284. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler.cc +1 -3
  285. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler.h +0 -0
  286. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-stack.cc +0 -0
  287. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-stack.h +0 -0
  288. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp.js +25 -4
  289. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/register-allocator-inl.h +0 -0
  290. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/register-allocator.cc +4 -3
  291. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/register-allocator.h +0 -0
  292. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/rewriter.cc +85 -8
  293. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/rewriter.h +0 -0
  294. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/runtime.cc +547 -221
  295. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/runtime.h +5 -1
  296. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/runtime.js +23 -31
  297. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scanner.cc +12 -6
  298. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scanner.h +60 -53
  299. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopeinfo.cc +156 -168
  300. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopeinfo.h +58 -62
  301. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopes.cc +0 -0
  302. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopes.h +0 -0
  303. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/serialize.cc +320 -242
  304. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/serialize.h +81 -48
  305. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/shell.h +0 -0
  306. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/simulator.h +0 -0
  307. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/smart-pointer.h +0 -0
  308. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/snapshot-common.cc +0 -0
  309. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/snapshot-empty.cc +0 -0
  310. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/snapshot.h +0 -0
  311. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/spaces-inl.h +177 -74
  312. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/spaces.cc +138 -315
  313. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/spaces.h +155 -124
  314. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/splay-tree-inl.h +0 -0
  315. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/splay-tree.h +0 -0
  316. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/string-stream.cc +0 -0
  317. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/string-stream.h +0 -0
  318. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/string.js +113 -119
  319. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/stub-cache.cc +242 -97
  320. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/stub-cache.h +118 -55
  321. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/third_party/dtoa/COPYING +0 -0
  322. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/third_party/dtoa/dtoa.c +4 -0
  323. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/third_party/valgrind/valgrind.h +0 -0
  324. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/token.cc +0 -0
  325. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/token.h +0 -0
  326. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/top.cc +107 -26
  327. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/top.h +9 -4
  328. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/type-info.cc +0 -0
  329. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/type-info.h +2 -2
  330. data/ext/v8/upstream/2.3.3/src/unbound-queue-inl.h +95 -0
  331. data/ext/v8/upstream/2.3.3/src/unbound-queue.h +67 -0
  332. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/unicode-inl.h +0 -0
  333. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/unicode.cc +0 -0
  334. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/unicode.h +0 -0
  335. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/uri.js +0 -0
  336. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/utils.cc +0 -0
  337. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/utils.h +83 -1
  338. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8-counters.cc +0 -0
  339. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8-counters.h +20 -0
  340. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8.cc +5 -1
  341. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8.h +0 -0
  342. data/ext/v8/upstream/2.3.3/src/v8dll-main.cc +39 -0
  343. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8natives.js +210 -33
  344. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8threads.cc +1 -1
  345. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8threads.h +1 -1
  346. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/variables.cc +0 -0
  347. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/variables.h +0 -0
  348. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/version.cc +3 -3
  349. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/version.h +0 -0
  350. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-heavy-inl.h +40 -0
  351. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-heavy.cc +0 -0
  352. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-inl.h +0 -0
  353. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-light-inl.h +106 -5
  354. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-light.cc +4 -1
  355. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame.cc +0 -0
  356. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame.h +0 -0
  357. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/vm-state-inl.h +6 -3
  358. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/vm-state.cc +1 -1
  359. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/vm-state.h +6 -4
  360. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/assembler-x64-inl.h +42 -5
  361. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/assembler-x64.cc +285 -53
  362. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/assembler-x64.h +54 -18
  363. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/builtins-x64.cc +31 -33
  364. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/codegen-x64-inl.h +0 -0
  365. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/codegen-x64.cc +9787 -8722
  366. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/codegen-x64.h +82 -47
  367. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/cpu-x64.cc +4 -0
  368. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/debug-x64.cc +55 -6
  369. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/disasm-x64.cc +42 -19
  370. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/fast-codegen-x64.cc +4 -0
  371. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/frames-x64.cc +4 -0
  372. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/frames-x64.h +4 -0
  373. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/full-codegen-x64.cc +1487 -210
  374. data/ext/v8/upstream/2.3.3/src/x64/ic-x64.cc +1907 -0
  375. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/jump-target-x64.cc +4 -0
  376. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/macro-assembler-x64.cc +366 -338
  377. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/macro-assembler-x64.h +83 -38
  378. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/regexp-macro-assembler-x64.cc +82 -23
  379. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/regexp-macro-assembler-x64.h +1 -2
  380. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/register-allocator-x64-inl.h +6 -5
  381. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/register-allocator-x64.cc +4 -0
  382. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/register-allocator-x64.h +1 -1
  383. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/simulator-x64.cc +0 -0
  384. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/simulator-x64.h +0 -0
  385. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/stub-cache-x64.cc +556 -377
  386. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/virtual-frame-x64.cc +197 -98
  387. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/virtual-frame-x64.h +37 -28
  388. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/zone-inl.h +0 -0
  389. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/zone.cc +0 -0
  390. data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/zone.h +0 -0
  391. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/codemap.js +0 -0
  392. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/consarray.js +0 -0
  393. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/csvparser.js +0 -0
  394. data/ext/v8/upstream/2.3.3/tools/gc-nvp-trace-processor.py +317 -0
  395. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/generate-ten-powers.scm +0 -0
  396. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/gyp/v8.gyp +87 -20
  397. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/js2c.py +19 -15
  398. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/jsmin.py +0 -0
  399. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/linux-tick-processor +0 -0
  400. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/linux-tick-processor.py +0 -0
  401. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/logreader.js +0 -0
  402. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/mac-nm +0 -0
  403. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/mac-tick-processor +0 -0
  404. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/annotate +0 -0
  405. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/common +0 -0
  406. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/dump +0 -0
  407. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/report +0 -0
  408. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/reset +0 -0
  409. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/run +0 -0
  410. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/shutdown +0 -0
  411. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/start +0 -0
  412. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/presubmit.py +0 -0
  413. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/process-heap-prof.py +0 -0
  414. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/profile.js +0 -0
  415. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/profile_view.js +0 -0
  416. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/run-valgrind.py +0 -0
  417. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/splaytree.js +0 -0
  418. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/splaytree.py +0 -0
  419. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/stats-viewer.py +25 -13
  420. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/test.py +0 -0
  421. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/tickprocessor-driver.js +0 -0
  422. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/tickprocessor.js +0 -0
  423. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/tickprocessor.py +0 -0
  424. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/utils.py +0 -0
  425. data/ext/v8/upstream/2.3.3/tools/v8.xcodeproj/project.pbxproj +1855 -0
  426. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/README.txt +0 -0
  427. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/arm.vsprops +0 -0
  428. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/common.vsprops +0 -0
  429. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8.vcproj +0 -0
  430. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8_arm.vcproj +0 -0
  431. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8_x64.vcproj +0 -0
  432. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8js2c.cmd +0 -0
  433. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/debug.vsprops +0 -0
  434. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/ia32.vsprops +0 -0
  435. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/js2c.cmd +0 -0
  436. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/release.vsprops +0 -0
  437. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8.sln +0 -0
  438. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8.vcproj +0 -0
  439. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_arm.sln +0 -0
  440. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_arm.vcproj +0 -0
  441. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_base.vcproj +40 -0
  442. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_base_arm.vcproj +20 -0
  443. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_base_x64.vcproj +16 -0
  444. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_cctest.vcproj +4 -0
  445. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_cctest_arm.vcproj +0 -0
  446. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_cctest_x64.vcproj +0 -0
  447. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_mksnapshot.vcproj +0 -0
  448. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_mksnapshot_x64.vcproj +0 -0
  449. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_process_sample.vcproj +0 -0
  450. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_process_sample_arm.vcproj +0 -0
  451. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_process_sample_x64.vcproj +0 -0
  452. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_shell_sample.vcproj +0 -0
  453. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_shell_sample_arm.vcproj +0 -0
  454. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_shell_sample_x64.vcproj +0 -0
  455. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot.vcproj +0 -0
  456. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot_cc.vcproj +0 -0
  457. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot_cc_x64.vcproj +0 -0
  458. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot_x64.vcproj +0 -0
  459. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_x64.sln +0 -0
  460. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_x64.vcproj +0 -0
  461. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/x64.vsprops +0 -0
  462. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/windows-tick-processor.bat +0 -0
  463. data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/windows-tick-processor.py +0 -0
  464. data/ext/v8/upstream/Makefile +1 -1
  465. data/ext/v8/v8_template.cpp +94 -2
  466. data/ext/v8/v8_try_catch.cpp +2 -2
  467. data/lib/v8.rb +1 -1
  468. data/lib/v8/access.rb +93 -40
  469. data/lib/v8/cli.rb +1 -1
  470. data/lib/v8/function.rb +14 -2
  471. data/spec/redjs/jsapi_spec.rb +231 -42
  472. data/therubyracer.gemspec +3 -3
  473. metadata +463 -453
  474. data/ext/v8/upstream/2.1.10/src/arm/assembler-thumb2-inl.h +0 -263
  475. data/ext/v8/upstream/2.1.10/src/arm/assembler-thumb2.cc +0 -1878
  476. data/ext/v8/upstream/2.1.10/src/arm/assembler-thumb2.h +0 -1036
  477. data/ext/v8/upstream/2.1.10/src/arm/codegen-arm-inl.h +0 -72
  478. data/ext/v8/upstream/2.1.10/src/arm/ic-arm.cc +0 -1833
  479. data/ext/v8/upstream/2.1.10/src/circular-queue-inl.h +0 -101
  480. data/ext/v8/upstream/2.1.10/src/profile-generator.cc +0 -583
  481. data/ext/v8/upstream/2.1.10/src/profile-generator.h +0 -364
  482. data/ext/v8/upstream/2.1.10/src/x64/ic-x64.cc +0 -1621
@@ -27,6 +27,8 @@
27
27
 
28
28
  #include "v8.h"
29
29
 
30
+ #if defined(V8_TARGET_ARCH_X64)
31
+
30
32
  #include "codegen-inl.h"
31
33
  #include "fast-codegen.h"
32
34
  #include "scopes.h"
@@ -244,3 +246,5 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
244
246
 
245
247
 
246
248
  } } // namespace v8::internal
249
+
250
+ #endif // V8_TARGET_ARCH_X64
@@ -27,6 +27,8 @@
27
27
 
28
28
  #include "v8.h"
29
29
 
30
+ #if defined(V8_TARGET_ARCH_X64)
31
+
30
32
  #include "frames-inl.h"
31
33
 
32
34
  namespace v8 {
@@ -107,3 +109,5 @@ byte* ArgumentsAdaptorFrame::GetCallerStackPointer() const {
107
109
 
108
110
 
109
111
  } } // namespace v8::internal
112
+
113
+ #endif // V8_TARGET_ARCH_X64
@@ -56,7 +56,11 @@ class StackHandlerConstants : public AllStatic {
56
56
 
57
57
  class EntryFrameConstants : public AllStatic {
58
58
  public:
59
+ #ifdef _WIN64
59
60
  static const int kCallerFPOffset = -10 * kPointerSize;
61
+ #else
62
+ static const int kCallerFPOffset = -8 * kPointerSize;
63
+ #endif
60
64
  static const int kArgvOffset = 6 * kPointerSize;
61
65
  };
62
66
 
@@ -27,6 +27,8 @@
27
27
 
28
28
  #include "v8.h"
29
29
 
30
+ #if defined(V8_TARGET_ARCH_X64)
31
+
30
32
  #include "codegen-inl.h"
31
33
  #include "compiler.h"
32
34
  #include "debug.h"
@@ -79,11 +81,17 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
79
81
  bool function_in_register = true;
80
82
 
81
83
  // Possibly allocate a local context.
82
- if (scope()->num_heap_slots() > 0) {
84
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
85
+ if (heap_slots > 0) {
83
86
  Comment cmnt(masm_, "[ Allocate local context");
84
87
  // Argument to NewContext is the function, which is still in rdi.
85
88
  __ push(rdi);
86
- __ CallRuntime(Runtime::kNewContext, 1);
89
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
90
+ FastNewContextStub stub(heap_slots);
91
+ __ CallStub(&stub);
92
+ } else {
93
+ __ CallRuntime(Runtime::kNewContext, 1);
94
+ }
87
95
  function_in_register = false;
88
96
  // Context is returned in both rax and rsi. It replaces the context
89
97
  // passed to us. It's saved in the stack and kept live in rsi.
@@ -143,7 +151,18 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
143
151
  }
144
152
 
145
153
  { Comment cmnt(masm_, "[ Declarations");
146
- VisitDeclarations(scope()->declarations());
154
+ // For named function expressions, declare the function name as a
155
+ // constant.
156
+ if (scope()->is_function_scope() && scope()->function() != NULL) {
157
+ EmitDeclaration(scope()->function(), Variable::CONST, NULL);
158
+ }
159
+ // Visit all the explicit declarations unless there is an illegal
160
+ // redeclaration.
161
+ if (scope()->HasIllegalRedeclaration()) {
162
+ scope()->VisitIllegalRedeclaration(this);
163
+ } else {
164
+ VisitDeclarations(scope()->declarations());
165
+ }
147
166
  }
148
167
 
149
168
  { Comment cmnt(masm_, "[ Stack check");
@@ -168,12 +187,12 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
168
187
  { Comment cmnt(masm_, "[ return <undefined>;");
169
188
  // Emit a 'return undefined' in case control fell off the end of the body.
170
189
  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
171
- EmitReturnSequence(function()->end_position());
190
+ EmitReturnSequence();
172
191
  }
173
192
  }
174
193
 
175
194
 
176
- void FullCodeGenerator::EmitReturnSequence(int position) {
195
+ void FullCodeGenerator::EmitReturnSequence() {
177
196
  Comment cmnt(masm_, "[ Return sequence");
178
197
  if (return_label_.is_bound()) {
179
198
  __ jmp(&return_label_);
@@ -188,7 +207,7 @@ void FullCodeGenerator::EmitReturnSequence(int position) {
188
207
  Label check_exit_codesize;
189
208
  masm_->bind(&check_exit_codesize);
190
209
  #endif
191
- CodeGenerator::RecordPositions(masm_, position);
210
+ CodeGenerator::RecordPositions(masm_, function()->end_position());
192
211
  __ RecordJSReturn();
193
212
  // Do not use the leave instruction here because it is too short to
194
213
  // patch with the code required by the debugger.
@@ -427,6 +446,39 @@ void FullCodeGenerator::DropAndApply(int count,
427
446
  }
428
447
 
429
448
 
449
+ void FullCodeGenerator::PrepareTest(Label* materialize_true,
450
+ Label* materialize_false,
451
+ Label** if_true,
452
+ Label** if_false) {
453
+ switch (context_) {
454
+ case Expression::kUninitialized:
455
+ UNREACHABLE();
456
+ break;
457
+ case Expression::kEffect:
458
+ // In an effect context, the true and the false case branch to the
459
+ // same label.
460
+ *if_true = *if_false = materialize_true;
461
+ break;
462
+ case Expression::kValue:
463
+ *if_true = materialize_true;
464
+ *if_false = materialize_false;
465
+ break;
466
+ case Expression::kTest:
467
+ *if_true = true_label_;
468
+ *if_false = false_label_;
469
+ break;
470
+ case Expression::kValueTest:
471
+ *if_true = materialize_true;
472
+ *if_false = false_label_;
473
+ break;
474
+ case Expression::kTestValue:
475
+ *if_true = true_label_;
476
+ *if_false = materialize_false;
477
+ break;
478
+ }
479
+ }
480
+
481
+
430
482
  void FullCodeGenerator::Apply(Expression::Context context,
431
483
  Label* materialize_true,
432
484
  Label* materialize_false) {
@@ -492,6 +544,61 @@ void FullCodeGenerator::Apply(Expression::Context context,
492
544
  }
493
545
 
494
546
 
547
+ // Convert constant control flow (true or false) to the result expected for
548
+ // a given expression context.
549
+ void FullCodeGenerator::Apply(Expression::Context context, bool flag) {
550
+ switch (context) {
551
+ case Expression::kUninitialized:
552
+ UNREACHABLE();
553
+ break;
554
+ case Expression::kEffect:
555
+ break;
556
+ case Expression::kValue: {
557
+ Heap::RootListIndex value_root_index =
558
+ flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
559
+ switch (location_) {
560
+ case kAccumulator:
561
+ __ LoadRoot(result_register(), value_root_index);
562
+ break;
563
+ case kStack:
564
+ __ PushRoot(value_root_index);
565
+ break;
566
+ }
567
+ break;
568
+ }
569
+ case Expression::kTest:
570
+ __ jmp(flag ? true_label_ : false_label_);
571
+ break;
572
+ case Expression::kTestValue:
573
+ switch (location_) {
574
+ case kAccumulator:
575
+ // If value is false it's needed.
576
+ if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
577
+ break;
578
+ case kStack:
579
+ // If value is false it's needed.
580
+ if (!flag) __ PushRoot(Heap::kFalseValueRootIndex);
581
+ break;
582
+ }
583
+ __ jmp(flag ? true_label_ : false_label_);
584
+ break;
585
+ case Expression::kValueTest:
586
+ switch (location_) {
587
+ case kAccumulator:
588
+ // If value is true it's needed.
589
+ if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
590
+ break;
591
+ case kStack:
592
+ // If value is true it's needed.
593
+ if (flag) __ PushRoot(Heap::kTrueValueRootIndex);
594
+ break;
595
+ }
596
+ __ jmp(flag ? true_label_ : false_label_);
597
+ break;
598
+ }
599
+ }
600
+
601
+
495
602
  void FullCodeGenerator::DoTest(Expression::Context context) {
496
603
  // The value to test is in the accumulator. If the value might be needed
497
604
  // on the stack (value/test and test/value contexts with a stack location
@@ -667,22 +774,23 @@ void FullCodeGenerator::Move(Slot* dst,
667
774
  }
668
775
 
669
776
 
670
- void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
777
+ void FullCodeGenerator::EmitDeclaration(Variable* variable,
778
+ Variable::Mode mode,
779
+ FunctionLiteral* function) {
671
780
  Comment cmnt(masm_, "[ Declaration");
672
- Variable* var = decl->proxy()->var();
673
- ASSERT(var != NULL); // Must have been resolved.
674
- Slot* slot = var->slot();
675
- Property* prop = var->AsProperty();
781
+ ASSERT(variable != NULL); // Must have been resolved.
782
+ Slot* slot = variable->slot();
783
+ Property* prop = variable->AsProperty();
676
784
 
677
785
  if (slot != NULL) {
678
786
  switch (slot->type()) {
679
787
  case Slot::PARAMETER:
680
788
  case Slot::LOCAL:
681
- if (decl->mode() == Variable::CONST) {
789
+ if (mode == Variable::CONST) {
682
790
  __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
683
791
  __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
684
- } else if (decl->fun() != NULL) {
685
- VisitForValue(decl->fun(), kAccumulator);
792
+ } else if (function != NULL) {
793
+ VisitForValue(function, kAccumulator);
686
794
  __ movq(Operand(rbp, SlotOffset(slot)), result_register());
687
795
  }
688
796
  break;
@@ -692,7 +800,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
692
800
  // this specific context.
693
801
 
694
802
  // The variable in the decl always resides in the current context.
695
- ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
803
+ ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
696
804
  if (FLAG_debug_code) {
697
805
  // Check if we have the correct context pointer.
698
806
  __ movq(rbx,
@@ -700,13 +808,13 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
700
808
  __ cmpq(rbx, rsi);
701
809
  __ Check(equal, "Unexpected declaration in current context.");
702
810
  }
703
- if (decl->mode() == Variable::CONST) {
811
+ if (mode == Variable::CONST) {
704
812
  __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
705
813
  __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
706
814
  kScratchRegister);
707
815
  // No write barrier since the hole value is in old space.
708
- } else if (decl->fun() != NULL) {
709
- VisitForValue(decl->fun(), kAccumulator);
816
+ } else if (function != NULL) {
817
+ VisitForValue(function, kAccumulator);
710
818
  __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
711
819
  result_register());
712
820
  int offset = Context::SlotOffset(slot->index());
@@ -717,21 +825,19 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
717
825
 
718
826
  case Slot::LOOKUP: {
719
827
  __ push(rsi);
720
- __ Push(var->name());
828
+ __ Push(variable->name());
721
829
  // Declaration nodes are always introduced in one of two modes.
722
- ASSERT(decl->mode() == Variable::VAR ||
723
- decl->mode() == Variable::CONST);
724
- PropertyAttributes attr =
725
- (decl->mode() == Variable::VAR) ? NONE : READ_ONLY;
830
+ ASSERT(mode == Variable::VAR || mode == Variable::CONST);
831
+ PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
726
832
  __ Push(Smi::FromInt(attr));
727
833
  // Push initial value, if any.
728
834
  // Note: For variables we must not push an initial value (such as
729
835
  // 'undefined') because we may have a (legal) redeclaration and we
730
836
  // must not destroy the current value.
731
- if (decl->mode() == Variable::CONST) {
837
+ if (mode == Variable::CONST) {
732
838
  __ PushRoot(Heap::kTheHoleValueRootIndex);
733
- } else if (decl->fun() != NULL) {
734
- VisitForValue(decl->fun(), kStack);
839
+ } else if (function != NULL) {
840
+ VisitForValue(function, kStack);
735
841
  } else {
736
842
  __ Push(Smi::FromInt(0)); // no initial value!
737
843
  }
@@ -741,32 +847,36 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
741
847
  }
742
848
 
743
849
  } else if (prop != NULL) {
744
- if (decl->fun() != NULL || decl->mode() == Variable::CONST) {
850
+ if (function != NULL || mode == Variable::CONST) {
745
851
  // We are declaring a function or constant that rewrites to a
746
852
  // property. Use (keyed) IC to set the initial value.
747
853
  VisitForValue(prop->obj(), kStack);
748
- VisitForValue(prop->key(), kStack);
749
-
750
- if (decl->fun() != NULL) {
751
- VisitForValue(decl->fun(), kAccumulator);
854
+ if (function != NULL) {
855
+ VisitForValue(prop->key(), kStack);
856
+ VisitForValue(function, kAccumulator);
857
+ __ pop(rcx);
752
858
  } else {
859
+ VisitForValue(prop->key(), kAccumulator);
860
+ __ movq(rcx, result_register());
753
861
  __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
754
862
  }
863
+ __ pop(rdx);
755
864
 
756
865
  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
757
866
  __ call(ic, RelocInfo::CODE_TARGET);
758
867
  // Absence of a test rax instruction following the call
759
868
  // indicates that none of the load was inlined.
760
869
  __ nop();
761
-
762
- // Value in rax is ignored (declarations are statements). Receiver
763
- // and key on stack are discarded.
764
- __ Drop(2);
765
870
  }
766
871
  }
767
872
  }
768
873
 
769
874
 
875
+ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
876
+ EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
877
+ }
878
+
879
+
770
880
  void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
771
881
  // Call the runtime to declare the globals.
772
882
  __ push(rsi); // The context is the first argument.
@@ -777,19 +887,224 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
777
887
  }
778
888
 
779
889
 
780
- void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
781
- Comment cmnt(masm_, "[ FunctionLiteral");
890
+ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
891
+ Comment cmnt(masm_, "[ SwitchStatement");
892
+ Breakable nested_statement(this, stmt);
893
+ SetStatementPosition(stmt);
894
+ // Keep the switch value on the stack until a case matches.
895
+ VisitForValue(stmt->tag(), kStack);
896
+
897
+ ZoneList<CaseClause*>* clauses = stmt->cases();
898
+ CaseClause* default_clause = NULL; // Can occur anywhere in the list.
899
+
900
+ Label next_test; // Recycled for each test.
901
+ // Compile all the tests with branches to their bodies.
902
+ for (int i = 0; i < clauses->length(); i++) {
903
+ CaseClause* clause = clauses->at(i);
904
+ // The default is not a test, but remember it as final fall through.
905
+ if (clause->is_default()) {
906
+ default_clause = clause;
907
+ continue;
908
+ }
909
+
910
+ Comment cmnt(masm_, "[ Case comparison");
911
+ __ bind(&next_test);
912
+ next_test.Unuse();
913
+
914
+ // Compile the label expression.
915
+ VisitForValue(clause->label(), kAccumulator);
916
+
917
+ // Perform the comparison as if via '==='. The comparison stub expects
918
+ // the smi vs. smi case to be handled before it is called.
919
+ Label slow_case;
920
+ __ movq(rdx, Operand(rsp, 0)); // Switch value.
921
+ __ JumpIfNotBothSmi(rdx, rax, &slow_case);
922
+ __ SmiCompare(rdx, rax);
923
+ __ j(not_equal, &next_test);
924
+ __ Drop(1); // Switch value is no longer needed.
925
+ __ jmp(clause->body_target()->entry_label());
926
+
927
+ __ bind(&slow_case);
928
+ CompareStub stub(equal, true);
929
+ __ CallStub(&stub);
930
+ __ testq(rax, rax);
931
+ __ j(not_equal, &next_test);
932
+ __ Drop(1); // Switch value is no longer needed.
933
+ __ jmp(clause->body_target()->entry_label());
934
+ }
935
+
936
+ // Discard the test value and jump to the default if present, otherwise to
937
+ // the end of the statement.
938
+ __ bind(&next_test);
939
+ __ Drop(1); // Switch value is no longer needed.
940
+ if (default_clause == NULL) {
941
+ __ jmp(nested_statement.break_target());
942
+ } else {
943
+ __ jmp(default_clause->body_target()->entry_label());
944
+ }
945
+
946
+ // Compile all the case bodies.
947
+ for (int i = 0; i < clauses->length(); i++) {
948
+ Comment cmnt(masm_, "[ Case body");
949
+ CaseClause* clause = clauses->at(i);
950
+ __ bind(clause->body_target()->entry_label());
951
+ VisitStatements(clause->statements());
952
+ }
953
+
954
+ __ bind(nested_statement.break_target());
955
+ }
956
+
957
+
958
+ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
959
+ Comment cmnt(masm_, "[ ForInStatement");
960
+ SetStatementPosition(stmt);
961
+
962
+ Label loop, exit;
963
+ ForIn loop_statement(this, stmt);
964
+ increment_loop_depth();
782
965
 
783
- // Build the shared function info and instantiate the function based
784
- // on it.
785
- Handle<SharedFunctionInfo> function_info =
786
- Compiler::BuildFunctionInfo(expr, script(), this);
787
- if (HasStackOverflow()) return;
966
+ // Get the object to enumerate over. Both SpiderMonkey and JSC
967
+ // ignore null and undefined in contrast to the specification; see
968
+ // ECMA-262 section 12.6.4.
969
+ VisitForValue(stmt->enumerable(), kAccumulator);
970
+ __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
971
+ __ j(equal, &exit);
972
+ __ CompareRoot(rax, Heap::kNullValueRootIndex);
973
+ __ j(equal, &exit);
974
+
975
+ // Convert the object to a JS object.
976
+ Label convert, done_convert;
977
+ __ JumpIfSmi(rax, &convert);
978
+ __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
979
+ __ j(above_equal, &done_convert);
980
+ __ bind(&convert);
981
+ __ push(rax);
982
+ __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
983
+ __ bind(&done_convert);
984
+ __ push(rax);
985
+
986
+ // TODO(kasperl): Check cache validity in generated code. This is a
987
+ // fast case for the JSObject::IsSimpleEnum cache validity
988
+ // checks. If we cannot guarantee cache validity, call the runtime
989
+ // system to check cache validity or get the property names in a
990
+ // fixed array.
991
+
992
+ // Get the set of properties to enumerate.
993
+ __ push(rax); // Duplicate the enumerable object on the stack.
994
+ __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
995
+
996
+ // If we got a map from the runtime call, we can do a fast
997
+ // modification check. Otherwise, we got a fixed array, and we have
998
+ // to do a slow check.
999
+ Label fixed_array;
1000
+ __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1001
+ Heap::kMetaMapRootIndex);
1002
+ __ j(not_equal, &fixed_array);
1003
+
1004
+ // We got a map in register rax. Get the enumeration cache from it.
1005
+ __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset));
1006
+ __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
1007
+ __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1008
+
1009
+ // Setup the four remaining stack slots.
1010
+ __ push(rax); // Map.
1011
+ __ push(rdx); // Enumeration cache.
1012
+ __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
1013
+ __ push(rax); // Enumeration cache length (as smi).
1014
+ __ Push(Smi::FromInt(0)); // Initial index.
1015
+ __ jmp(&loop);
1016
+
1017
+ // We got a fixed array in register rax. Iterate through that.
1018
+ __ bind(&fixed_array);
1019
+ __ Push(Smi::FromInt(0)); // Map (0) - force slow check.
1020
+ __ push(rax);
1021
+ __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1022
+ __ push(rax); // Fixed array length (as smi).
1023
+ __ Push(Smi::FromInt(0)); // Initial index.
1024
+
1025
+ // Generate code for doing the condition check.
1026
+ __ bind(&loop);
1027
+ __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
1028
+ __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
1029
+ __ j(above_equal, loop_statement.break_target());
1030
+
1031
+ // Get the current entry of the array into register rbx.
1032
+ __ movq(rbx, Operand(rsp, 2 * kPointerSize));
1033
+ SmiIndex index = __ SmiToIndex(rax, rax, kPointerSizeLog2);
1034
+ __ movq(rbx, FieldOperand(rbx,
1035
+ index.reg,
1036
+ index.scale,
1037
+ FixedArray::kHeaderSize));
1038
+
1039
+ // Get the expected map from the stack or a zero map in the
1040
+ // permanent slow case into register rdx.
1041
+ __ movq(rdx, Operand(rsp, 3 * kPointerSize));
1042
+
1043
+ // Check if the expected map still matches that of the enumerable.
1044
+ // If not, we have to filter the key.
1045
+ Label update_each;
1046
+ __ movq(rcx, Operand(rsp, 4 * kPointerSize));
1047
+ __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1048
+ __ j(equal, &update_each);
1049
+
1050
+ // Convert the entry to a string or null if it isn't a property
1051
+ // anymore. If the property has been removed while iterating, we
1052
+ // just skip it.
1053
+ __ push(rcx); // Enumerable.
1054
+ __ push(rbx); // Current entry.
1055
+ __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1056
+ __ CompareRoot(rax, Heap::kNullValueRootIndex);
1057
+ __ j(equal, loop_statement.continue_target());
1058
+ __ movq(rbx, rax);
1059
+
1060
+ // Update the 'each' property or variable from the possibly filtered
1061
+ // entry in register rbx.
1062
+ __ bind(&update_each);
1063
+ __ movq(result_register(), rbx);
1064
+ // Perform the assignment as if via '='.
1065
+ EmitAssignment(stmt->each());
1066
+
1067
+ // Generate code for the body of the loop.
1068
+ Label stack_limit_hit, stack_check_done;
1069
+ Visit(stmt->body());
1070
+
1071
+ __ StackLimitCheck(&stack_limit_hit);
1072
+ __ bind(&stack_check_done);
1073
+
1074
+ // Generate code for going to the next element by incrementing the
1075
+ // index (smi) stored on top of the stack.
1076
+ __ bind(loop_statement.continue_target());
1077
+ __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1078
+ __ jmp(&loop);
1079
+
1080
+ // Slow case for the stack limit check.
1081
+ StackCheckStub stack_check_stub;
1082
+ __ bind(&stack_limit_hit);
1083
+ __ CallStub(&stack_check_stub);
1084
+ __ jmp(&stack_check_done);
1085
+
1086
+ // Remove the pointers stored on the stack.
1087
+ __ bind(loop_statement.break_target());
1088
+ __ addq(rsp, Immediate(5 * kPointerSize));
1089
+
1090
+ // Exit and decrement the loop depth.
1091
+ __ bind(&exit);
1092
+ decrement_loop_depth();
1093
+ }
788
1094
 
789
- // Create a new closure.
790
- __ push(rsi);
791
- __ Push(function_info);
792
- __ CallRuntime(Runtime::kNewClosure, 2);
1095
+
1096
+ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
1097
+ // Use the fast case closure allocation code that allocates in new
1098
+ // space for nested functions that don't need literals cloning.
1099
+ if (scope()->is_function_scope() && info->num_literals() == 0) {
1100
+ FastNewClosureStub stub;
1101
+ __ Push(info);
1102
+ __ CallStub(&stub);
1103
+ } else {
1104
+ __ push(rsi);
1105
+ __ Push(info);
1106
+ __ CallRuntime(Runtime::kNewClosure, 2);
1107
+ }
793
1108
  Apply(context_, rax);
794
1109
  }
795
1110
 
@@ -812,15 +1127,15 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
812
1127
  Comment cmnt(masm_, "Global variable");
813
1128
  // Use inline caching. Variable name is passed in rcx and the global
814
1129
  // object on the stack.
815
- __ push(CodeGenerator::GlobalObject());
816
1130
  __ Move(rcx, var->name());
1131
+ __ movq(rax, CodeGenerator::GlobalObject());
817
1132
  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
818
1133
  __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
819
1134
  // A test rax instruction following the call is used by the IC to
820
1135
  // indicate that the inobject property case was inlined. Ensure there
821
1136
  // is no test rax instruction here.
822
1137
  __ nop();
823
- DropAndApply(1, context, rax);
1138
+ Apply(context, rax);
824
1139
 
825
1140
  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
826
1141
  Comment cmnt(masm_, "Lookup slot");
@@ -833,7 +1148,20 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
833
1148
  Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
834
1149
  ? "Context slot"
835
1150
  : "Stack slot");
836
- Apply(context, slot);
1151
+ if (var->mode() == Variable::CONST) {
1152
+ // Constants may be the hole value if they have not been initialized.
1153
+ // Unhole them.
1154
+ Label done;
1155
+ MemOperand slot_operand = EmitSlotSearch(slot, rax);
1156
+ __ movq(rax, slot_operand);
1157
+ __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1158
+ __ j(not_equal, &done);
1159
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1160
+ __ bind(&done);
1161
+ Apply(context, rax);
1162
+ } else {
1163
+ Apply(context, slot);
1164
+ }
837
1165
 
838
1166
  } else {
839
1167
  Comment cmnt(masm_, "Rewritten parameter");
@@ -848,7 +1176,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
848
1176
 
849
1177
  // Load the object.
850
1178
  MemOperand object_loc = EmitSlotSearch(object_slot, rax);
851
- __ push(object_loc);
1179
+ __ movq(rdx, object_loc);
852
1180
 
853
1181
  // Assert that the key is a smi.
854
1182
  Literal* key_literal = property->key()->AsLiteral();
@@ -856,7 +1184,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
856
1184
  ASSERT(key_literal->handle()->IsSmi());
857
1185
 
858
1186
  // Load the key.
859
- __ Push(key_literal->handle());
1187
+ __ Move(rax, key_literal->handle());
860
1188
 
861
1189
  // Do a keyed property load.
862
1190
  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
@@ -864,8 +1192,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
864
1192
  // Notice: We must not have a "test rax, ..." instruction after the
865
1193
  // call. It is treated specially by the LoadIC code.
866
1194
  __ nop();
867
- // Drop key and object left on the stack by IC, and push the result.
868
- DropAndApply(2, context, rax);
1195
+ Apply(context, rax);
869
1196
  }
870
1197
  }
871
1198
 
@@ -969,22 +1296,28 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
969
1296
 
970
1297
  void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
971
1298
  Comment cmnt(masm_, "[ ArrayLiteral");
1299
+
1300
+ ZoneList<Expression*>* subexprs = expr->values();
1301
+ int length = subexprs->length();
1302
+
972
1303
  __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
973
1304
  __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
974
1305
  __ Push(Smi::FromInt(expr->literal_index()));
975
1306
  __ Push(expr->constant_elements());
976
1307
  if (expr->depth() > 1) {
977
1308
  __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
978
- } else {
1309
+ } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
979
1310
  __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1311
+ } else {
1312
+ FastCloneShallowArrayStub stub(length);
1313
+ __ CallStub(&stub);
980
1314
  }
981
1315
 
982
1316
  bool result_saved = false; // Is the result saved to the stack?
983
1317
 
984
1318
  // Emit code to evaluate all the non-constant subexpressions and to store
985
1319
  // them into the newly cloned array.
986
- ZoneList<Expression*>* subexprs = expr->values();
987
- for (int i = 0, len = subexprs->length(); i < len; i++) {
1320
+ for (int i = 0; i < length; i++) {
988
1321
  Expression* subexpr = subexprs->at(i);
989
1322
  // If the subexpression is a literal or a simple materialized literal it
990
1323
  // is already set in the cloned array.
@@ -1019,7 +1352,13 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1019
1352
 
1020
1353
  void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1021
1354
  Comment cmnt(masm_, "[ Assignment");
1022
- ASSERT(expr->op() != Token::INIT_CONST);
1355
+ // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1356
+ // on the left-hand side.
1357
+ if (!expr->target()->IsValidLeftHandSide()) {
1358
+ VisitForEffect(expr->target());
1359
+ return;
1360
+ }
1361
+
1023
1362
  // Left-hand side can only be a property, a global or a (parameter or local)
1024
1363
  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1025
1364
  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
@@ -1045,8 +1384,15 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1045
1384
  }
1046
1385
  break;
1047
1386
  case KEYED_PROPERTY:
1048
- VisitForValue(prop->obj(), kStack);
1049
- VisitForValue(prop->key(), kStack);
1387
+ if (expr->is_compound()) {
1388
+ VisitForValue(prop->obj(), kStack);
1389
+ VisitForValue(prop->key(), kAccumulator);
1390
+ __ movq(rdx, Operand(rsp, 0));
1391
+ __ push(rax);
1392
+ } else {
1393
+ VisitForValue(prop->obj(), kStack);
1394
+ VisitForValue(prop->key(), kStack);
1395
+ }
1050
1396
  break;
1051
1397
  }
1052
1398
 
@@ -1091,6 +1437,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1091
1437
  switch (assign_type) {
1092
1438
  case VARIABLE:
1093
1439
  EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1440
+ expr->op(),
1094
1441
  context_);
1095
1442
  break;
1096
1443
  case NAMED_PROPERTY:
@@ -1132,61 +1479,131 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
1132
1479
  }
1133
1480
 
1134
1481
 
1482
+ void FullCodeGenerator::EmitAssignment(Expression* expr) {
1483
+ // Invalid left-hand sides are rewritten to have a 'throw
1484
+ // ReferenceError' on the left-hand side.
1485
+ if (!expr->IsValidLeftHandSide()) {
1486
+ VisitForEffect(expr);
1487
+ return;
1488
+ }
1489
+
1490
+ // Left-hand side can only be a property, a global or a (parameter or local)
1491
+ // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1492
+ enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1493
+ LhsKind assign_type = VARIABLE;
1494
+ Property* prop = expr->AsProperty();
1495
+ if (prop != NULL) {
1496
+ assign_type = (prop->key()->IsPropertyName())
1497
+ ? NAMED_PROPERTY
1498
+ : KEYED_PROPERTY;
1499
+ }
1500
+
1501
+ switch (assign_type) {
1502
+ case VARIABLE: {
1503
+ Variable* var = expr->AsVariableProxy()->var();
1504
+ EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
1505
+ break;
1506
+ }
1507
+ case NAMED_PROPERTY: {
1508
+ __ push(rax); // Preserve value.
1509
+ VisitForValue(prop->obj(), kAccumulator);
1510
+ __ movq(rdx, rax);
1511
+ __ pop(rax); // Restore value.
1512
+ __ Move(rcx, prop->key()->AsLiteral()->handle());
1513
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1514
+ __ call(ic, RelocInfo::CODE_TARGET);
1515
+ __ nop(); // Signal no inlined code.
1516
+ break;
1517
+ }
1518
+ case KEYED_PROPERTY: {
1519
+ __ push(rax); // Preserve value.
1520
+ VisitForValue(prop->obj(), kStack);
1521
+ VisitForValue(prop->key(), kAccumulator);
1522
+ __ movq(rcx, rax);
1523
+ __ pop(rdx);
1524
+ __ pop(rax);
1525
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1526
+ __ call(ic, RelocInfo::CODE_TARGET);
1527
+ __ nop(); // Signal no inlined code.
1528
+ break;
1529
+ }
1530
+ }
1531
+ }
1532
+
1533
+
1135
1534
  void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1535
+ Token::Value op,
1136
1536
  Expression::Context context) {
1137
- // Three main cases: non-this global variables, lookup slots, and
1138
- // all other types of slots. Left-hand-side parameters that rewrite
1139
- // to explicit property accesses do not reach here.
1537
+ // Left-hand sides that rewrite to explicit property accesses do not reach
1538
+ // here.
1140
1539
  ASSERT(var != NULL);
1141
1540
  ASSERT(var->is_global() || var->slot() != NULL);
1142
- Slot* slot = var->slot();
1541
+
1143
1542
  if (var->is_global()) {
1144
1543
  ASSERT(!var->is_this());
1145
1544
  // Assignment to a global variable. Use inline caching for the
1146
1545
  // assignment. Right-hand-side value is passed in rax, variable name in
1147
- // rcx, and the global object in rdx.
1546
+ // rcx, and the global object on the stack.
1148
1547
  __ Move(rcx, var->name());
1149
1548
  __ movq(rdx, CodeGenerator::GlobalObject());
1150
1549
  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1151
1550
  __ Call(ic, RelocInfo::CODE_TARGET);
1152
- Apply(context, rax);
1153
-
1154
- } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1155
- __ push(result_register()); // Value.
1156
- __ push(rsi); // Context.
1157
- __ Push(var->name());
1158
- __ CallRuntime(Runtime::kStoreContextSlot, 3);
1159
- Apply(context, rax);
1551
+ __ nop();
1160
1552
 
1161
- } else if (var->slot() != NULL) {
1553
+ } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1554
+ // Perform the assignment for non-const variables and for initialization
1555
+ // of const variables. Const assignments are simply skipped.
1556
+ Label done;
1557
+ Slot* slot = var->slot();
1162
1558
  switch (slot->type()) {
1163
- case Slot::LOCAL:
1164
1559
  case Slot::PARAMETER:
1165
- __ movq(Operand(rbp, SlotOffset(slot)), result_register());
1560
+ case Slot::LOCAL:
1561
+ if (op == Token::INIT_CONST) {
1562
+ // Detect const reinitialization by checking for the hole value.
1563
+ __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1564
+ __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1565
+ __ j(not_equal, &done);
1566
+ }
1567
+ // Perform the assignment.
1568
+ __ movq(Operand(rbp, SlotOffset(slot)), rax);
1166
1569
  break;
1167
1570
 
1168
1571
  case Slot::CONTEXT: {
1169
1572
  MemOperand target = EmitSlotSearch(slot, rcx);
1170
- __ movq(target, result_register());
1171
-
1172
- // RecordWrite may destroy all its register arguments.
1173
- __ movq(rdx, result_register());
1573
+ if (op == Token::INIT_CONST) {
1574
+ // Detect const reinitialization by checking for the hole value.
1575
+ __ movq(rdx, target);
1576
+ __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1577
+ __ j(not_equal, &done);
1578
+ }
1579
+ // Perform the assignment and issue the write barrier.
1580
+ __ movq(target, rax);
1581
+ // The value of the assignment is in rax. RecordWrite clobbers its
1582
+ // register arguments.
1583
+ __ movq(rdx, rax);
1174
1584
  int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1175
1585
  __ RecordWrite(rcx, offset, rdx, rbx);
1176
1586
  break;
1177
1587
  }
1178
1588
 
1179
1589
  case Slot::LOOKUP:
1180
- UNREACHABLE();
1590
+ // Call the runtime for the assignment. The runtime will ignore
1591
+ // const reinitialization.
1592
+ __ push(rax); // Value.
1593
+ __ push(rsi); // Context.
1594
+ __ Push(var->name());
1595
+ if (op == Token::INIT_CONST) {
1596
+ // The runtime will ignore const redeclaration.
1597
+ __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1598
+ } else {
1599
+ __ CallRuntime(Runtime::kStoreContextSlot, 3);
1600
+ }
1181
1601
  break;
1182
1602
  }
1183
- Apply(context, result_register());
1184
-
1185
- } else {
1186
- // Variables rewritten as properties are not treated as variables in
1187
- // assignments.
1188
- UNREACHABLE();
1603
+ __ bind(&done);
1189
1604
  }
1605
+
1606
+ Apply(context, rax);
1190
1607
  }
1191
1608
 
1192
1609
 
@@ -1245,6 +1662,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1245
1662
  __ pop(result_register());
1246
1663
  }
1247
1664
 
1665
+ __ pop(rcx);
1666
+ if (expr->ends_initialization_block()) {
1667
+ __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later.
1668
+ } else {
1669
+ __ pop(rdx);
1670
+ }
1248
1671
  // Record source code position before IC call.
1249
1672
  SetSourcePosition(expr->position());
1250
1673
  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
@@ -1255,15 +1678,14 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1255
1678
 
1256
1679
  // If the assignment ends an initialization block, revert to fast case.
1257
1680
  if (expr->ends_initialization_block()) {
1681
+ __ pop(rdx);
1258
1682
  __ push(rax); // Result of assignment, saved even if not needed.
1259
- // Receiver is under the key and value.
1260
- __ push(Operand(rsp, 2 * kPointerSize));
1683
+ __ push(rdx);
1261
1684
  __ CallRuntime(Runtime::kToFastProperties, 1);
1262
1685
  __ pop(rax);
1263
1686
  }
1264
1687
 
1265
- // Receiver and key are still on stack.
1266
- DropAndApply(2, context_, rax);
1688
+ Apply(context_, rax);
1267
1689
  }
1268
1690
 
1269
1691
 
@@ -1271,18 +1693,16 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
1271
1693
  Comment cmnt(masm_, "[ Property");
1272
1694
  Expression* key = expr->key();
1273
1695
 
1274
- // Evaluate receiver.
1275
- VisitForValue(expr->obj(), kStack);
1276
-
1277
1696
  if (key->IsPropertyName()) {
1697
+ VisitForValue(expr->obj(), kAccumulator);
1278
1698
  EmitNamedPropertyLoad(expr);
1279
- // Drop receiver left on the stack by IC.
1280
- DropAndApply(1, context_, rax);
1699
+ Apply(context_, rax);
1281
1700
  } else {
1282
- VisitForValue(expr->key(), kStack);
1701
+ VisitForValue(expr->obj(), kStack);
1702
+ VisitForValue(expr->key(), kAccumulator);
1703
+ __ pop(rdx);
1283
1704
  EmitKeyedPropertyLoad(expr);
1284
- // Drop key and receiver left on the stack by IC.
1285
- DropAndApply(2, context_, rax);
1705
+ Apply(context_, rax);
1286
1706
  }
1287
1707
  }
1288
1708
 
@@ -1310,6 +1730,30 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
1310
1730
  }
1311
1731
 
1312
1732
 
1733
+ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
1734
+ Expression* key,
1735
+ RelocInfo::Mode mode) {
1736
+ // Code common for calls using the IC.
1737
+ ZoneList<Expression*>* args = expr->arguments();
1738
+ int arg_count = args->length();
1739
+ for (int i = 0; i < arg_count; i++) {
1740
+ VisitForValue(args->at(i), kStack);
1741
+ }
1742
+ VisitForValue(key, kAccumulator);
1743
+ __ movq(rcx, rax);
1744
+ // Record source position for debugger.
1745
+ SetSourcePosition(expr->position());
1746
+ // Call the IC initialization code.
1747
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1748
+ Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
1749
+ in_loop);
1750
+ __ Call(ic, mode);
1751
+ // Restore context register.
1752
+ __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1753
+ Apply(context_, rax);
1754
+ }
1755
+
1756
+
1313
1757
  void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1314
1758
  // Code common for calls using the call stub.
1315
1759
  ZoneList<Expression*>* args = expr->arguments();
@@ -1319,7 +1763,8 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1319
1763
  }
1320
1764
  // Record source position for debugger.
1321
1765
  SetSourcePosition(expr->position());
1322
- CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
1766
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1767
+ CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1323
1768
  __ CallStub(&stub);
1324
1769
  // Restore context register.
1325
1770
  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
@@ -1334,8 +1779,47 @@ void FullCodeGenerator::VisitCall(Call* expr) {
1334
1779
  Variable* var = fun->AsVariableProxy()->AsVariable();
1335
1780
 
1336
1781
  if (var != NULL && var->is_possibly_eval()) {
1337
- // Call to the identifier 'eval'.
1338
- UNREACHABLE();
1782
+ // In a call to eval, we first call %ResolvePossiblyDirectEval to
1783
+ // resolve the function we need to call and the receiver of the
1784
+ // call. The we call the resolved function using the given
1785
+ // arguments.
1786
+ VisitForValue(fun, kStack);
1787
+ __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
1788
+
1789
+ // Push the arguments.
1790
+ ZoneList<Expression*>* args = expr->arguments();
1791
+ int arg_count = args->length();
1792
+ for (int i = 0; i < arg_count; i++) {
1793
+ VisitForValue(args->at(i), kStack);
1794
+ }
1795
+
1796
+ // Push copy of the function - found below the arguments.
1797
+ __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
1798
+
1799
+ // Push copy of the first argument or undefined if it doesn't exist.
1800
+ if (arg_count > 0) {
1801
+ __ push(Operand(rsp, arg_count * kPointerSize));
1802
+ } else {
1803
+ __ PushRoot(Heap::kUndefinedValueRootIndex);
1804
+ }
1805
+
1806
+ // Push the receiver of the enclosing function and do runtime call.
1807
+ __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
1808
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
1809
+
1810
+ // The runtime call returns a pair of values in rax (function) and
1811
+ // rdx (receiver). Touch up the stack with the right values.
1812
+ __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
1813
+ __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
1814
+
1815
+ // Record source position for debugger.
1816
+ SetSourcePosition(expr->position());
1817
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1818
+ CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1819
+ __ CallStub(&stub);
1820
+ // Restore context register.
1821
+ __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1822
+ DropAndApply(1, context_, rax);
1339
1823
  } else if (var != NULL && !var->is_this() && var->is_global()) {
1340
1824
  // Call to a global variable.
1341
1825
  // Push global object as receiver for the call IC lookup.
@@ -1343,8 +1827,15 @@ void FullCodeGenerator::VisitCall(Call* expr) {
1343
1827
  EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1344
1828
  } else if (var != NULL && var->slot() != NULL &&
1345
1829
  var->slot()->type() == Slot::LOOKUP) {
1346
- // Call to a lookup slot.
1347
- UNREACHABLE();
1830
+ // Call to a lookup slot (dynamically introduced variable). Call
1831
+ // the runtime to find the function to call (returned in rax) and
1832
+ // the object holding it (returned in rdx).
1833
+ __ push(context_register());
1834
+ __ Push(var->name());
1835
+ __ CallRuntime(Runtime::kLoadContextSlot, 2);
1836
+ __ push(rax); // Function.
1837
+ __ push(rdx); // Receiver.
1838
+ EmitCallWithStub(expr);
1348
1839
  } else if (fun->AsProperty() != NULL) {
1349
1840
  // Call to an object property.
1350
1841
  Property* prop = fun->AsProperty();
@@ -1354,31 +1845,32 @@ void FullCodeGenerator::VisitCall(Call* expr) {
1354
1845
  VisitForValue(prop->obj(), kStack);
1355
1846
  EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1356
1847
  } else {
1357
- // Call to a keyed property, use keyed load IC followed by function
1358
- // call.
1848
+ // Call to a keyed property.
1849
+ // For a synthetic property use keyed load IC followed by function call,
1850
+ // for a regular property use KeyedCallIC.
1359
1851
  VisitForValue(prop->obj(), kStack);
1360
- VisitForValue(prop->key(), kStack);
1361
- // Record source code position for IC call.
1362
- SetSourcePosition(prop->position());
1363
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1364
- __ call(ic, RelocInfo::CODE_TARGET);
1365
- // By emitting a nop we make sure that we do not have a "test rax,..."
1366
- // instruction after the call it is treated specially by the LoadIC code.
1367
- __ nop();
1368
- // Drop key left on the stack by IC.
1369
- __ Drop(1);
1370
- // Pop receiver.
1371
- __ pop(rbx);
1372
- // Push result (function).
1373
- __ push(rax);
1374
- // Push receiver object on stack.
1375
1852
  if (prop->is_synthetic()) {
1853
+ VisitForValue(prop->key(), kAccumulator);
1854
+ __ movq(rdx, Operand(rsp, 0));
1855
+ // Record source code position for IC call.
1856
+ SetSourcePosition(prop->position());
1857
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1858
+ __ call(ic, RelocInfo::CODE_TARGET);
1859
+ // By emitting a nop we make sure that we do not have a "test rax,..."
1860
+ // instruction after the call as it is treated specially
1861
+ // by the LoadIC code.
1862
+ __ nop();
1863
+ // Pop receiver.
1864
+ __ pop(rbx);
1865
+ // Push result (function).
1866
+ __ push(rax);
1867
+ // Push receiver object on stack.
1376
1868
  __ movq(rcx, CodeGenerator::GlobalObject());
1377
1869
  __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
1870
+ EmitCallWithStub(expr);
1378
1871
  } else {
1379
- __ push(rbx);
1872
+ EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1380
1873
  }
1381
- EmitCallWithStub(expr);
1382
1874
  }
1383
1875
  } else {
1384
1876
  // Call to some other expression. If the expression is an anonymous
@@ -1435,39 +1927,803 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
1435
1927
  }
1436
1928
 
1437
1929
 
1438
- void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1439
- Comment cmnt(masm_, "[ CallRuntime");
1440
- ZoneList<Expression*>* args = expr->arguments();
1930
+ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
1931
+ ASSERT(args->length() == 1);
1441
1932
 
1442
- if (expr->is_jsruntime()) {
1443
- // Prepare for calling JS runtime function.
1444
- __ movq(rax, CodeGenerator::GlobalObject());
1445
- __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
1446
- }
1933
+ VisitForValue(args->at(0), kAccumulator);
1447
1934
 
1448
- // Push the arguments ("left-to-right").
1449
- int arg_count = args->length();
1450
- for (int i = 0; i < arg_count; i++) {
1451
- VisitForValue(args->at(i), kStack);
1452
- }
1935
+ Label materialize_true, materialize_false;
1936
+ Label* if_true = NULL;
1937
+ Label* if_false = NULL;
1938
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1453
1939
 
1454
- if (expr->is_jsruntime()) {
1455
- // Call the JS runtime function using a call IC.
1456
- __ Move(rcx, expr->name());
1457
- InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1458
- Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1459
- __ call(ic, RelocInfo::CODE_TARGET);
1460
- // Restore context register.
1461
- __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1462
- } else {
1463
- __ CallRuntime(expr->function(), arg_count);
1464
- }
1465
- Apply(context_, rax);
1940
+ __ JumpIfSmi(rax, if_true);
1941
+ __ jmp(if_false);
1942
+
1943
+ Apply(context_, if_true, if_false);
1466
1944
  }
1467
1945
 
1468
1946
 
1469
- void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1470
- switch (expr->op()) {
1947
+ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1948
+ ASSERT(args->length() == 1);
1949
+
1950
+ VisitForValue(args->at(0), kAccumulator);
1951
+
1952
+ Label materialize_true, materialize_false;
1953
+ Label* if_true = NULL;
1954
+ Label* if_false = NULL;
1955
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1956
+
1957
+ Condition positive_smi = __ CheckPositiveSmi(rax);
1958
+ __ j(positive_smi, if_true);
1959
+ __ jmp(if_false);
1960
+
1961
+ Apply(context_, if_true, if_false);
1962
+ }
1963
+
1964
+
1965
+ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
1966
+ ASSERT(args->length() == 1);
1967
+
1968
+ VisitForValue(args->at(0), kAccumulator);
1969
+
1970
+ Label materialize_true, materialize_false;
1971
+ Label* if_true = NULL;
1972
+ Label* if_false = NULL;
1973
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1974
+
1975
+ __ JumpIfSmi(rax, if_false);
1976
+ __ CompareRoot(rax, Heap::kNullValueRootIndex);
1977
+ __ j(equal, if_true);
1978
+ __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
1979
+ // Undetectable objects behave like undefined when tested with typeof.
1980
+ __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
1981
+ Immediate(1 << Map::kIsUndetectable));
1982
+ __ j(not_zero, if_false);
1983
+ __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
1984
+ __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
1985
+ __ j(below, if_false);
1986
+ __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
1987
+ __ j(below_equal, if_true);
1988
+ __ jmp(if_false);
1989
+
1990
+ Apply(context_, if_true, if_false);
1991
+ }
1992
+
1993
+
1994
+ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
1995
+ ASSERT(args->length() == 1);
1996
+
1997
+ VisitForValue(args->at(0), kAccumulator);
1998
+
1999
+ Label materialize_true, materialize_false;
2000
+ Label* if_true = NULL;
2001
+ Label* if_false = NULL;
2002
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2003
+
2004
+ __ JumpIfSmi(rax, if_false);
2005
+ __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
2006
+ __ j(above_equal, if_true);
2007
+ __ jmp(if_false);
2008
+
2009
+ Apply(context_, if_true, if_false);
2010
+ }
2011
+
2012
+
2013
+ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2014
+ ASSERT(args->length() == 1);
2015
+
2016
+ VisitForValue(args->at(0), kAccumulator);
2017
+
2018
+ Label materialize_true, materialize_false;
2019
+ Label* if_true = NULL;
2020
+ Label* if_false = NULL;
2021
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2022
+
2023
+ __ JumpIfSmi(rax, if_false);
2024
+ __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2025
+ __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2026
+ Immediate(1 << Map::kIsUndetectable));
2027
+ __ j(not_zero, if_true);
2028
+ __ jmp(if_false);
2029
+
2030
+ Apply(context_, if_true, if_false);
2031
+ }
2032
+
2033
+
2034
+ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2035
+ ASSERT(args->length() == 1);
2036
+
2037
+ VisitForValue(args->at(0), kAccumulator);
2038
+
2039
+ Label materialize_true, materialize_false;
2040
+ Label* if_true = NULL;
2041
+ Label* if_false = NULL;
2042
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2043
+
2044
+ __ JumpIfSmi(rax, if_false);
2045
+ __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2046
+ __ j(equal, if_true);
2047
+ __ jmp(if_false);
2048
+
2049
+ Apply(context_, if_true, if_false);
2050
+ }
2051
+
2052
+
2053
+ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2054
+ ASSERT(args->length() == 1);
2055
+
2056
+ VisitForValue(args->at(0), kAccumulator);
2057
+
2058
+ Label materialize_true, materialize_false;
2059
+ Label* if_true = NULL;
2060
+ Label* if_false = NULL;
2061
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2062
+
2063
+ __ JumpIfSmi(rax, if_false);
2064
+ __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2065
+ __ j(equal, if_true);
2066
+ __ jmp(if_false);
2067
+
2068
+ Apply(context_, if_true, if_false);
2069
+ }
2070
+
2071
+
2072
+ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2073
+ ASSERT(args->length() == 1);
2074
+
2075
+ VisitForValue(args->at(0), kAccumulator);
2076
+
2077
+ Label materialize_true, materialize_false;
2078
+ Label* if_true = NULL;
2079
+ Label* if_false = NULL;
2080
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2081
+
2082
+ __ JumpIfSmi(rax, if_false);
2083
+ __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2084
+ __ j(equal, if_true);
2085
+ __ jmp(if_false);
2086
+
2087
+ Apply(context_, if_true, if_false);
2088
+ }
2089
+
2090
+
2091
+
2092
+ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2093
+ ASSERT(args->length() == 0);
2094
+
2095
+ Label materialize_true, materialize_false;
2096
+ Label* if_true = NULL;
2097
+ Label* if_false = NULL;
2098
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2099
+
2100
+ // Get the frame pointer for the calling frame.
2101
+ __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2102
+
2103
+ // Skip the arguments adaptor frame if it exists.
2104
+ Label check_frame_marker;
2105
+ __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
2106
+ Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2107
+ __ j(not_equal, &check_frame_marker);
2108
+ __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2109
+
2110
+ // Check the marker in the calling frame.
2111
+ __ bind(&check_frame_marker);
2112
+ __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
2113
+ Smi::FromInt(StackFrame::CONSTRUCT));
2114
+ __ j(equal, if_true);
2115
+ __ jmp(if_false);
2116
+
2117
+ Apply(context_, if_true, if_false);
2118
+ }
2119
+
2120
+
2121
+ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2122
+ ASSERT(args->length() == 2);
2123
+
2124
+ // Load the two objects into registers and perform the comparison.
2125
+ VisitForValue(args->at(0), kStack);
2126
+ VisitForValue(args->at(1), kAccumulator);
2127
+
2128
+ Label materialize_true, materialize_false;
2129
+ Label* if_true = NULL;
2130
+ Label* if_false = NULL;
2131
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2132
+
2133
+ __ pop(rbx);
2134
+ __ cmpq(rax, rbx);
2135
+ __ j(equal, if_true);
2136
+ __ jmp(if_false);
2137
+
2138
+ Apply(context_, if_true, if_false);
2139
+ }
2140
+
2141
+
2142
+ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2143
+ ASSERT(args->length() == 1);
2144
+
2145
+ // ArgumentsAccessStub expects the key in edx and the formal
2146
+ // parameter count in eax.
2147
+ VisitForValue(args->at(0), kAccumulator);
2148
+ __ movq(rdx, rax);
2149
+ __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2150
+ ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2151
+ __ CallStub(&stub);
2152
+ Apply(context_, rax);
2153
+ }
2154
+
2155
+
2156
+ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2157
+ ASSERT(args->length() == 0);
2158
+
2159
+ Label exit;
2160
+ // Get the number of formal parameters.
2161
+ __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2162
+
2163
+ // Check if the calling frame is an arguments adaptor frame.
2164
+ __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2165
+ __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset),
2166
+ Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2167
+ __ j(not_equal, &exit);
2168
+
2169
+ // Arguments adaptor case: Read the arguments length from the
2170
+ // adaptor frame.
2171
+ __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2172
+
2173
+ __ bind(&exit);
2174
+ if (FLAG_debug_code) __ AbortIfNotSmi(rax);
2175
+ Apply(context_, rax);
2176
+ }
2177
+
2178
+
2179
+ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2180
+ ASSERT(args->length() == 1);
2181
+ Label done, null, function, non_function_constructor;
2182
+
2183
+ VisitForValue(args->at(0), kAccumulator);
2184
+
2185
+ // If the object is a smi, we return null.
2186
+ __ JumpIfSmi(rax, &null);
2187
+
2188
+ // Check that the object is a JS object but take special care of JS
2189
+ // functions to make sure they have 'Function' as their class.
2190
+ __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); // Map is now in rax.
2191
+ __ j(below, &null);
2192
+
2193
+ // As long as JS_FUNCTION_TYPE is the last instance type and it is
2194
+ // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2195
+ // LAST_JS_OBJECT_TYPE.
2196
+ ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2197
+ ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
2198
+ __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
2199
+ __ j(equal, &function);
2200
+
2201
+ // Check if the constructor in the map is a function.
2202
+ __ movq(rax, FieldOperand(rax, Map::kConstructorOffset));
2203
+ __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2204
+ __ j(not_equal, &non_function_constructor);
2205
+
2206
+ // rax now contains the constructor function. Grab the
2207
+ // instance class name from there.
2208
+ __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
2209
+ __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
2210
+ __ jmp(&done);
2211
+
2212
+ // Functions have class 'Function'.
2213
+ __ bind(&function);
2214
+ __ Move(rax, Factory::function_class_symbol());
2215
+ __ jmp(&done);
2216
+
2217
+ // Objects with a non-function constructor have class 'Object'.
2218
+ __ bind(&non_function_constructor);
2219
+ __ Move(rax, Factory::Object_symbol());
2220
+ __ jmp(&done);
2221
+
2222
+ // Non-JS objects have class null.
2223
+ __ bind(&null);
2224
+ __ LoadRoot(rax, Heap::kNullValueRootIndex);
2225
+
2226
+ // All done.
2227
+ __ bind(&done);
2228
+
2229
+ Apply(context_, rax);
2230
+ }
2231
+
2232
+
2233
+ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2234
+ // Conditionally generate a log call.
2235
+ // Args:
2236
+ // 0 (literal string): The type of logging (corresponds to the flags).
2237
+ // This is used to determine whether or not to generate the log call.
2238
+ // 1 (string): Format string. Access the string at argument index 2
2239
+ // with '%2s' (see Logger::LogRuntime for all the formats).
2240
+ // 2 (array): Arguments to the format string.
2241
+ ASSERT_EQ(args->length(), 3);
2242
+ #ifdef ENABLE_LOGGING_AND_PROFILING
2243
+ if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2244
+ VisitForValue(args->at(1), kStack);
2245
+ VisitForValue(args->at(2), kStack);
2246
+ __ CallRuntime(Runtime::kLog, 2);
2247
+ }
2248
+ #endif
2249
+ // Finally, we're expected to leave a value on the top of the stack.
2250
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2251
+ Apply(context_, rax);
2252
+ }
2253
+
2254
+
2255
+ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2256
+ ASSERT(args->length() == 0);
2257
+
2258
+ Label slow_allocate_heapnumber;
2259
+ Label heapnumber_allocated;
2260
+
2261
+ __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
2262
+ __ jmp(&heapnumber_allocated);
2263
+
2264
+ __ bind(&slow_allocate_heapnumber);
2265
+ // Allocate a heap number.
2266
+ __ CallRuntime(Runtime::kNumberAlloc, 0);
2267
+ __ movq(rbx, rax);
2268
+
2269
+ __ bind(&heapnumber_allocated);
2270
+
2271
+ // Return a random uint32 number in rax.
2272
+ // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
2273
+ __ PrepareCallCFunction(0);
2274
+ __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2275
+
2276
+ // Convert 32 random bits in rax to 0.(32 random bits) in a double
2277
+ // by computing:
2278
+ // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2279
+ __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
2280
+ __ movd(xmm1, rcx);
2281
+ __ movd(xmm0, rax);
2282
+ __ cvtss2sd(xmm1, xmm1);
2283
+ __ xorpd(xmm0, xmm1);
2284
+ __ subsd(xmm0, xmm1);
2285
+ __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
2286
+
2287
+ __ movq(rax, rbx);
2288
+ Apply(context_, rax);
2289
+ }
2290
+
2291
+
2292
+ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2293
+ // Load the arguments on the stack and call the stub.
2294
+ SubStringStub stub;
2295
+ ASSERT(args->length() == 3);
2296
+ VisitForValue(args->at(0), kStack);
2297
+ VisitForValue(args->at(1), kStack);
2298
+ VisitForValue(args->at(2), kStack);
2299
+ __ CallStub(&stub);
2300
+ Apply(context_, rax);
2301
+ }
2302
+
2303
+
2304
+ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2305
+ // Load the arguments on the stack and call the stub.
2306
+ RegExpExecStub stub;
2307
+ ASSERT(args->length() == 4);
2308
+ VisitForValue(args->at(0), kStack);
2309
+ VisitForValue(args->at(1), kStack);
2310
+ VisitForValue(args->at(2), kStack);
2311
+ VisitForValue(args->at(3), kStack);
2312
+ __ CallStub(&stub);
2313
+ Apply(context_, rax);
2314
+ }
2315
+
2316
+
2317
+ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2318
+ ASSERT(args->length() == 1);
2319
+
2320
+ VisitForValue(args->at(0), kAccumulator); // Load the object.
2321
+
2322
+ Label done;
2323
+ // If the object is a smi return the object.
2324
+ __ JumpIfSmi(rax, &done);
2325
+ // If the object is not a value type, return the object.
2326
+ __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2327
+ __ j(not_equal, &done);
2328
+ __ movq(rax, FieldOperand(rax, JSValue::kValueOffset));
2329
+
2330
+ __ bind(&done);
2331
+ Apply(context_, rax);
2332
+ }
2333
+
2334
+
2335
+ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2336
+ // Load the arguments on the stack and call the runtime function.
2337
+ ASSERT(args->length() == 2);
2338
+ VisitForValue(args->at(0), kStack);
2339
+ VisitForValue(args->at(1), kStack);
2340
+ __ CallRuntime(Runtime::kMath_pow, 2);
2341
+ Apply(context_, rax);
2342
+ }
2343
+
2344
+
2345
+ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2346
+ ASSERT(args->length() == 2);
2347
+
2348
+ VisitForValue(args->at(0), kStack); // Load the object.
2349
+ VisitForValue(args->at(1), kAccumulator); // Load the value.
2350
+ __ pop(rbx); // rax = value. ebx = object.
2351
+
2352
+ Label done;
2353
+ // If the object is a smi, return the value.
2354
+ __ JumpIfSmi(rbx, &done);
2355
+
2356
+ // If the object is not a value type, return the value.
2357
+ __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2358
+ __ j(not_equal, &done);
2359
+
2360
+ // Store the value.
2361
+ __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax);
2362
+ // Update the write barrier. Save the value as it will be
2363
+ // overwritten by the write barrier code and is needed afterward.
2364
+ __ movq(rdx, rax);
2365
+ __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx);
2366
+
2367
+ __ bind(&done);
2368
+ Apply(context_, rax);
2369
+ }
2370
+
2371
+
2372
+ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2373
+ ASSERT_EQ(args->length(), 1);
2374
+
2375
+ // Load the argument on the stack and call the stub.
2376
+ VisitForValue(args->at(0), kStack);
2377
+
2378
+ NumberToStringStub stub;
2379
+ __ CallStub(&stub);
2380
+ Apply(context_, rax);
2381
+ }
2382
+
2383
+
2384
+ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2385
+ ASSERT(args->length() == 1);
2386
+
2387
+ VisitForValue(args->at(0), kAccumulator);
2388
+
2389
+ Label done;
2390
+ StringCharFromCodeGenerator generator(rax, rbx);
2391
+ generator.GenerateFast(masm_);
2392
+ __ jmp(&done);
2393
+
2394
+ NopRuntimeCallHelper call_helper;
2395
+ generator.GenerateSlow(masm_, call_helper);
2396
+
2397
+ __ bind(&done);
2398
+ Apply(context_, rbx);
2399
+ }
2400
+
2401
+
2402
+ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
2403
+ ASSERT(args->length() == 2);
2404
+
2405
+ VisitForValue(args->at(0), kStack);
2406
+ VisitForValue(args->at(1), kAccumulator);
2407
+
2408
+ Register object = rbx;
2409
+ Register index = rax;
2410
+ Register scratch = rcx;
2411
+ Register result = rdx;
2412
+
2413
+ __ pop(object);
2414
+
2415
+ Label need_conversion;
2416
+ Label index_out_of_range;
2417
+ Label done;
2418
+ StringCharCodeAtGenerator generator(object,
2419
+ index,
2420
+ scratch,
2421
+ result,
2422
+ &need_conversion,
2423
+ &need_conversion,
2424
+ &index_out_of_range,
2425
+ STRING_INDEX_IS_NUMBER);
2426
+ generator.GenerateFast(masm_);
2427
+ __ jmp(&done);
2428
+
2429
+ __ bind(&index_out_of_range);
2430
+ // When the index is out of range, the spec requires us to return
2431
+ // NaN.
2432
+ __ LoadRoot(result, Heap::kNanValueRootIndex);
2433
+ __ jmp(&done);
2434
+
2435
+ __ bind(&need_conversion);
2436
+ // Move the undefined value into the result register, which will
2437
+ // trigger conversion.
2438
+ __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2439
+ __ jmp(&done);
2440
+
2441
+ NopRuntimeCallHelper call_helper;
2442
+ generator.GenerateSlow(masm_, call_helper);
2443
+
2444
+ __ bind(&done);
2445
+ Apply(context_, result);
2446
+ }
2447
+
2448
+
2449
+ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
2450
+ ASSERT(args->length() == 2);
2451
+
2452
+ VisitForValue(args->at(0), kStack);
2453
+ VisitForValue(args->at(1), kAccumulator);
2454
+
2455
+ Register object = rbx;
2456
+ Register index = rax;
2457
+ Register scratch1 = rcx;
2458
+ Register scratch2 = rdx;
2459
+ Register result = rax;
2460
+
2461
+ __ pop(object);
2462
+
2463
+ Label need_conversion;
2464
+ Label index_out_of_range;
2465
+ Label done;
2466
+ StringCharAtGenerator generator(object,
2467
+ index,
2468
+ scratch1,
2469
+ scratch2,
2470
+ result,
2471
+ &need_conversion,
2472
+ &need_conversion,
2473
+ &index_out_of_range,
2474
+ STRING_INDEX_IS_NUMBER);
2475
+ generator.GenerateFast(masm_);
2476
+ __ jmp(&done);
2477
+
2478
+ __ bind(&index_out_of_range);
2479
+ // When the index is out of range, the spec requires us to return
2480
+ // the empty string.
2481
+ __ LoadRoot(result, Heap::kEmptyStringRootIndex);
2482
+ __ jmp(&done);
2483
+
2484
+ __ bind(&need_conversion);
2485
+ // Move smi zero into the result register, which will trigger
2486
+ // conversion.
2487
+ __ Move(result, Smi::FromInt(0));
2488
+ __ jmp(&done);
2489
+
2490
+ NopRuntimeCallHelper call_helper;
2491
+ generator.GenerateSlow(masm_, call_helper);
2492
+
2493
+ __ bind(&done);
2494
+ Apply(context_, result);
2495
+ }
2496
+
2497
+
2498
+ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2499
+ ASSERT_EQ(2, args->length());
2500
+
2501
+ VisitForValue(args->at(0), kStack);
2502
+ VisitForValue(args->at(1), kStack);
2503
+
2504
+ StringAddStub stub(NO_STRING_ADD_FLAGS);
2505
+ __ CallStub(&stub);
2506
+ Apply(context_, rax);
2507
+ }
2508
+
2509
+
2510
+ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2511
+ ASSERT_EQ(2, args->length());
2512
+
2513
+ VisitForValue(args->at(0), kStack);
2514
+ VisitForValue(args->at(1), kStack);
2515
+
2516
+ StringCompareStub stub;
2517
+ __ CallStub(&stub);
2518
+ Apply(context_, rax);
2519
+ }
2520
+
2521
+
2522
+ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2523
+ // Load the argument on the stack and call the stub.
2524
+ TranscendentalCacheStub stub(TranscendentalCache::SIN);
2525
+ ASSERT(args->length() == 1);
2526
+ VisitForValue(args->at(0), kStack);
2527
+ __ CallStub(&stub);
2528
+ Apply(context_, rax);
2529
+ }
2530
+
2531
+
2532
+ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2533
+ // Load the argument on the stack and call the stub.
2534
+ TranscendentalCacheStub stub(TranscendentalCache::COS);
2535
+ ASSERT(args->length() == 1);
2536
+ VisitForValue(args->at(0), kStack);
2537
+ __ CallStub(&stub);
2538
+ Apply(context_, rax);
2539
+ }
2540
+
2541
+
2542
+ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2543
+ // Load the argument on the stack and call the runtime function.
2544
+ ASSERT(args->length() == 1);
2545
+ VisitForValue(args->at(0), kStack);
2546
+ __ CallRuntime(Runtime::kMath_sqrt, 1);
2547
+ Apply(context_, rax);
2548
+ }
2549
+
2550
+
2551
+ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2552
+ ASSERT(args->length() >= 2);
2553
+
2554
+ int arg_count = args->length() - 2; // For receiver and function.
2555
+ VisitForValue(args->at(0), kStack); // Receiver.
2556
+ for (int i = 0; i < arg_count; i++) {
2557
+ VisitForValue(args->at(i + 1), kStack);
2558
+ }
2559
+ VisitForValue(args->at(arg_count + 1), kAccumulator); // Function.
2560
+
2561
+ // InvokeFunction requires function in rdi. Move it in there.
2562
+ if (!result_register().is(rdi)) __ movq(rdi, result_register());
2563
+ ParameterCount count(arg_count);
2564
+ __ InvokeFunction(rdi, count, CALL_FUNCTION);
2565
+ __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2566
+ Apply(context_, rax);
2567
+ }
2568
+
2569
+
2570
+ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2571
+ ASSERT(args->length() == 3);
2572
+ VisitForValue(args->at(0), kStack);
2573
+ VisitForValue(args->at(1), kStack);
2574
+ VisitForValue(args->at(2), kStack);
2575
+ __ CallRuntime(Runtime::kRegExpConstructResult, 3);
2576
+ Apply(context_, rax);
2577
+ }
2578
+
2579
+
2580
+ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2581
+ ASSERT(args->length() == 3);
2582
+ VisitForValue(args->at(0), kStack);
2583
+ VisitForValue(args->at(1), kStack);
2584
+ VisitForValue(args->at(2), kStack);
2585
+ __ CallRuntime(Runtime::kSwapElements, 3);
2586
+ Apply(context_, rax);
2587
+ }
2588
+
2589
+
2590
+ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2591
+ ASSERT_EQ(2, args->length());
2592
+
2593
+ ASSERT_NE(NULL, args->at(0)->AsLiteral());
2594
+ int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2595
+
2596
+ Handle<FixedArray> jsfunction_result_caches(
2597
+ Top::global_context()->jsfunction_result_caches());
2598
+ if (jsfunction_result_caches->length() <= cache_id) {
2599
+ __ Abort("Attempt to use undefined cache.");
2600
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2601
+ Apply(context_, rax);
2602
+ return;
2603
+ }
2604
+
2605
+ VisitForValue(args->at(1), kAccumulator);
2606
+
2607
+ Register key = rax;
2608
+ Register cache = rbx;
2609
+ Register tmp = rcx;
2610
+ __ movq(cache, CodeGenerator::ContextOperand(rsi, Context::GLOBAL_INDEX));
2611
+ __ movq(cache,
2612
+ FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2613
+ __ movq(cache,
2614
+ CodeGenerator::ContextOperand(
2615
+ cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2616
+ __ movq(cache,
2617
+ FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2618
+
2619
+ Label done, not_found;
2620
+ // tmp now holds finger offset as a smi.
2621
+ ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2622
+ __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
2623
+ SmiIndex index =
2624
+ __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
2625
+ __ cmpq(key, FieldOperand(cache,
2626
+ index.reg,
2627
+ index.scale,
2628
+ FixedArray::kHeaderSize));
2629
+ __ j(not_equal, &not_found);
2630
+ __ movq(rax, FieldOperand(cache,
2631
+ index.reg,
2632
+ index.scale,
2633
+ FixedArray::kHeaderSize + kPointerSize));
2634
+ __ jmp(&done);
2635
+
2636
+ __ bind(&not_found);
2637
+ // Call runtime to perform the lookup.
2638
+ __ push(cache);
2639
+ __ push(key);
2640
+ __ CallRuntime(Runtime::kGetFromCache, 2);
2641
+
2642
+ __ bind(&done);
2643
+ Apply(context_, rax);
2644
+ }
2645
+
2646
+
2647
+ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2648
+ Handle<String> name = expr->name();
2649
+ if (name->length() > 0 && name->Get(0) == '_') {
2650
+ Comment cmnt(masm_, "[ InlineRuntimeCall");
2651
+ EmitInlineRuntimeCall(expr);
2652
+ return;
2653
+ }
2654
+
2655
+ Comment cmnt(masm_, "[ CallRuntime");
2656
+ ZoneList<Expression*>* args = expr->arguments();
2657
+
2658
+ if (expr->is_jsruntime()) {
2659
+ // Prepare for calling JS runtime function.
2660
+ __ movq(rax, CodeGenerator::GlobalObject());
2661
+ __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
2662
+ }
2663
+
2664
+ // Push the arguments ("left-to-right").
2665
+ int arg_count = args->length();
2666
+ for (int i = 0; i < arg_count; i++) {
2667
+ VisitForValue(args->at(i), kStack);
2668
+ }
2669
+
2670
+ if (expr->is_jsruntime()) {
2671
+ // Call the JS runtime function using a call IC.
2672
+ __ Move(rcx, expr->name());
2673
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2674
+ Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
2675
+ __ call(ic, RelocInfo::CODE_TARGET);
2676
+ // Restore context register.
2677
+ __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2678
+ } else {
2679
+ __ CallRuntime(expr->function(), arg_count);
2680
+ }
2681
+ Apply(context_, rax);
2682
+ }
2683
+
2684
+
2685
+ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2686
+ switch (expr->op()) {
2687
+ case Token::DELETE: {
2688
+ Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2689
+ Property* prop = expr->expression()->AsProperty();
2690
+ Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2691
+ if (prop == NULL && var == NULL) {
2692
+ // Result of deleting non-property, non-variable reference is true.
2693
+ // The subexpression may have side effects.
2694
+ VisitForEffect(expr->expression());
2695
+ Apply(context_, true);
2696
+ } else if (var != NULL &&
2697
+ !var->is_global() &&
2698
+ var->slot() != NULL &&
2699
+ var->slot()->type() != Slot::LOOKUP) {
2700
+ // Result of deleting non-global, non-dynamic variables is false.
2701
+ // The subexpression does not have side effects.
2702
+ Apply(context_, false);
2703
+ } else {
2704
+ // Property or variable reference. Call the delete builtin with
2705
+ // object and property name as arguments.
2706
+ if (prop != NULL) {
2707
+ VisitForValue(prop->obj(), kStack);
2708
+ VisitForValue(prop->key(), kStack);
2709
+ } else if (var->is_global()) {
2710
+ __ push(CodeGenerator::GlobalObject());
2711
+ __ Push(var->name());
2712
+ } else {
2713
+ // Non-global variable. Call the runtime to look up the context
2714
+ // where the variable was introduced.
2715
+ __ push(context_register());
2716
+ __ Push(var->name());
2717
+ __ CallRuntime(Runtime::kLookupContext, 2);
2718
+ __ push(rax);
2719
+ __ Push(var->name());
2720
+ }
2721
+ __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
2722
+ Apply(context_, rax);
2723
+ }
2724
+ break;
2725
+ }
2726
+
1471
2727
  case Token::VOID: {
1472
2728
  Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1473
2729
  VisitForEffect(expr->expression());
@@ -1508,33 +2764,15 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1508
2764
 
1509
2765
  case Token::NOT: {
1510
2766
  Comment cmnt(masm_, "[ UnaryOperation (NOT)");
1511
- Label materialize_true, materialize_false, done;
1512
- // Initially assume a pure test context. Notice that the labels are
1513
- // swapped.
1514
- Label* if_true = false_label_;
1515
- Label* if_false = true_label_;
1516
- switch (context_) {
1517
- case Expression::kUninitialized:
1518
- UNREACHABLE();
1519
- break;
1520
- case Expression::kEffect:
1521
- if_true = &done;
1522
- if_false = &done;
1523
- break;
1524
- case Expression::kValue:
1525
- if_true = &materialize_false;
1526
- if_false = &materialize_true;
1527
- break;
1528
- case Expression::kTest:
1529
- break;
1530
- case Expression::kValueTest:
1531
- if_false = &materialize_true;
1532
- break;
1533
- case Expression::kTestValue:
1534
- if_true = &materialize_false;
1535
- break;
1536
- }
2767
+ Label materialize_true, materialize_false;
2768
+ Label* if_true = NULL;
2769
+ Label* if_false = NULL;
2770
+
2771
+ // Notice that the labels are swapped.
2772
+ PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2773
+
1537
2774
  VisitForControl(expr->expression(), if_true, if_false);
2775
+
1538
2776
  Apply(context_, if_false, if_true); // Labels swapped.
1539
2777
  break;
1540
2778
  }
@@ -1546,13 +2784,13 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1546
2784
  !proxy->var()->is_this() &&
1547
2785
  proxy->var()->is_global()) {
1548
2786
  Comment cmnt(masm_, "Global variable");
1549
- __ push(CodeGenerator::GlobalObject());
1550
2787
  __ Move(rcx, proxy->name());
2788
+ __ movq(rax, CodeGenerator::GlobalObject());
1551
2789
  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1552
2790
  // Use a regular load, not a contextual load, to avoid a reference
1553
2791
  // error.
1554
2792
  __ Call(ic, RelocInfo::CODE_TARGET);
1555
- __ movq(Operand(rsp, 0), rax);
2793
+ __ push(rax);
1556
2794
  } else if (proxy != NULL &&
1557
2795
  proxy->var()->slot() != NULL &&
1558
2796
  proxy->var()->slot()->type() == Slot::LOOKUP) {
@@ -1585,9 +2823,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1585
2823
 
1586
2824
  case Token::SUB: {
1587
2825
  Comment cmt(masm_, "[ UnaryOperation (SUB)");
1588
- bool overwrite =
2826
+ bool can_overwrite =
1589
2827
  (expr->expression()->AsBinaryOperation() != NULL &&
1590
2828
  expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2829
+ UnaryOverwriteMode overwrite =
2830
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
1591
2831
  GenericUnaryOpStub stub(Token::SUB, overwrite);
1592
2832
  // GenericUnaryOpStub expects the argument to be in the
1593
2833
  // accumulator register rax.
@@ -1599,9 +2839,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1599
2839
 
1600
2840
  case Token::BIT_NOT: {
1601
2841
  Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
1602
- bool overwrite =
2842
+ bool can_overwrite =
1603
2843
  (expr->expression()->AsBinaryOperation() != NULL &&
1604
2844
  expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2845
+ UnaryOverwriteMode overwrite =
2846
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
1605
2847
  GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
1606
2848
  // GenericUnaryOpStub expects the argument to be in the
1607
2849
  // accumulator register rax.
@@ -1630,6 +2872,13 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1630
2872
  void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1631
2873
  Comment cmnt(masm_, "[ CountOperation");
1632
2874
 
2875
+ // Invalid left-hand-sides are rewritten to have a 'throw
2876
+ // ReferenceError' as the left-hand side.
2877
+ if (!expr->expression()->IsValidLeftHandSide()) {
2878
+ VisitForEffect(expr->expression());
2879
+ return;
2880
+ }
2881
+
1633
2882
  // Expression can only be a property, a global or a (parameter or local)
1634
2883
  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1635
2884
  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
@@ -1650,16 +2899,20 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1650
2899
  EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1651
2900
  Expression::kValue);
1652
2901
  location_ = saved_location;
1653
- } else {
2902
+ } else {
1654
2903
  // Reserve space for result of postfix operation.
1655
2904
  if (expr->is_postfix() && context_ != Expression::kEffect) {
1656
2905
  __ Push(Smi::FromInt(0));
1657
2906
  }
1658
- VisitForValue(prop->obj(), kStack);
1659
2907
  if (assign_type == NAMED_PROPERTY) {
2908
+ VisitForValue(prop->obj(), kAccumulator);
2909
+ __ push(rax); // Copy of receiver, needed for later store.
1660
2910
  EmitNamedPropertyLoad(prop);
1661
2911
  } else {
1662
- VisitForValue(prop->key(), kStack);
2912
+ VisitForValue(prop->obj(), kStack);
2913
+ VisitForValue(prop->key(), kAccumulator);
2914
+ __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
2915
+ __ push(rax); // Copy of key, needed for later store.
1663
2916
  EmitKeyedPropertyLoad(prop);
1664
2917
  }
1665
2918
  }
@@ -1735,7 +2988,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1735
2988
  switch (assign_type) {
1736
2989
  case VARIABLE:
1737
2990
  if (expr->is_postfix()) {
2991
+ // Perform the assignment as if via '='.
1738
2992
  EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
2993
+ Token::ASSIGN,
1739
2994
  Expression::kEffect);
1740
2995
  // For all contexts except kEffect: We have the result on
1741
2996
  // top of the stack.
@@ -1743,7 +2998,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1743
2998
  ApplyTOS(context_);
1744
2999
  }
1745
3000
  } else {
3001
+ // Perform the assignment as if via '='.
1746
3002
  EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3003
+ Token::ASSIGN,
1747
3004
  context_);
1748
3005
  }
1749
3006
  break;
@@ -1765,18 +3022,19 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1765
3022
  break;
1766
3023
  }
1767
3024
  case KEYED_PROPERTY: {
3025
+ __ pop(rcx);
3026
+ __ pop(rdx);
1768
3027
  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1769
3028
  __ call(ic, RelocInfo::CODE_TARGET);
1770
3029
  // This nop signals to the IC that there is no inlined code at the call
1771
3030
  // site for it to patch.
1772
3031
  __ nop();
1773
3032
  if (expr->is_postfix()) {
1774
- __ Drop(2); // Result is on the stack under the key and the receiver.
1775
3033
  if (context_ != Expression::kEffect) {
1776
3034
  ApplyTOS(context_);
1777
3035
  }
1778
3036
  } else {
1779
- DropAndApply(2, context_, rax);
3037
+ Apply(context_, rax);
1780
3038
  }
1781
3039
  break;
1782
3040
  }
@@ -1818,36 +3076,39 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1818
3076
  }
1819
3077
 
1820
3078
 
3079
+ void FullCodeGenerator::EmitNullCompare(bool strict,
3080
+ Register obj,
3081
+ Register null_const,
3082
+ Label* if_true,
3083
+ Label* if_false,
3084
+ Register scratch) {
3085
+ __ cmpq(obj, null_const);
3086
+ if (strict) {
3087
+ __ j(equal, if_true);
3088
+ } else {
3089
+ __ j(equal, if_true);
3090
+ __ CompareRoot(obj, Heap::kUndefinedValueRootIndex);
3091
+ __ j(equal, if_true);
3092
+ __ JumpIfSmi(obj, if_false);
3093
+ // It can be an undetectable object.
3094
+ __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset));
3095
+ __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
3096
+ Immediate(1 << Map::kIsUndetectable));
3097
+ __ j(not_zero, if_true);
3098
+ }
3099
+ __ jmp(if_false);
3100
+ }
3101
+
3102
+
1821
3103
  void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1822
3104
  Comment cmnt(masm_, "[ CompareOperation");
1823
3105
 
1824
3106
  // Always perform the comparison for its control flow. Pack the result
1825
3107
  // into the expression's context after the comparison is performed.
1826
- Label materialize_true, materialize_false, done;
1827
- // Initially assume we are in a test context.
1828
- Label* if_true = true_label_;
1829
- Label* if_false = false_label_;
1830
- switch (context_) {
1831
- case Expression::kUninitialized:
1832
- UNREACHABLE();
1833
- break;
1834
- case Expression::kEffect:
1835
- if_true = &done;
1836
- if_false = &done;
1837
- break;
1838
- case Expression::kValue:
1839
- if_true = &materialize_true;
1840
- if_false = &materialize_false;
1841
- break;
1842
- case Expression::kTest:
1843
- break;
1844
- case Expression::kValueTest:
1845
- if_true = &materialize_true;
1846
- break;
1847
- case Expression::kTestValue:
1848
- if_false = &materialize_false;
1849
- break;
1850
- }
3108
+ Label materialize_true, materialize_false;
3109
+ Label* if_true = NULL;
3110
+ Label* if_false = NULL;
3111
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1851
3112
 
1852
3113
  VisitForValue(expr->left(), kStack);
1853
3114
  switch (expr->op()) {
@@ -1877,10 +3138,24 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1877
3138
  case Token::EQ_STRICT:
1878
3139
  strict = true;
1879
3140
  // Fall through.
1880
- case Token::EQ:
3141
+ case Token::EQ: {
1881
3142
  cc = equal;
1882
3143
  __ pop(rdx);
3144
+ // If either operand is constant null we do a fast compare
3145
+ // against null.
3146
+ Literal* right_literal = expr->right()->AsLiteral();
3147
+ Literal* left_literal = expr->left()->AsLiteral();
3148
+ if (right_literal != NULL && right_literal->handle()->IsNull()) {
3149
+ EmitNullCompare(strict, rdx, rax, if_true, if_false, rcx);
3150
+ Apply(context_, if_true, if_false);
3151
+ return;
3152
+ } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
3153
+ EmitNullCompare(strict, rax, rdx, if_true, if_false, rcx);
3154
+ Apply(context_, if_true, if_false);
3155
+ return;
3156
+ }
1883
3157
  break;
3158
+ }
1884
3159
  case Token::LT:
1885
3160
  cc = less;
1886
3161
  __ pop(rdx);
@@ -1991,3 +3266,5 @@ void FullCodeGenerator::ExitFinallyBlock() {
1991
3266
 
1992
3267
 
1993
3268
  } } // namespace v8::internal
3269
+
3270
+ #endif // V8_TARGET_ARCH_X64