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
@@ -1,4 +1,4 @@
1
- // Copyright 2009 the V8 project authors. All rights reserved.
1
+ // Copyright 2010 the V8 project authors. All rights reserved.
2
2
  // Redistribution and use in source and binary forms, with or without
3
3
  // modification, are permitted provided that the following conditions are
4
4
  // met:
@@ -27,6 +27,8 @@
27
27
 
28
28
  #include "v8.h"
29
29
 
30
+ #if defined(V8_TARGET_ARCH_IA32)
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 edi.
85
88
  __ push(edi);
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 eax and esi. It replaces the context
89
97
  // passed to us. It's saved in the stack and kept live in esi.
@@ -140,7 +148,18 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
140
148
  }
141
149
 
142
150
  { Comment cmnt(masm_, "[ Declarations");
143
- VisitDeclarations(scope()->declarations());
151
+ // For named function expressions, declare the function name as a
152
+ // constant.
153
+ if (scope()->is_function_scope() && scope()->function() != NULL) {
154
+ EmitDeclaration(scope()->function(), Variable::CONST, NULL);
155
+ }
156
+ // Visit all the explicit declarations unless there is an illegal
157
+ // redeclaration.
158
+ if (scope()->HasIllegalRedeclaration()) {
159
+ scope()->VisitIllegalRedeclaration(this);
160
+ } else {
161
+ VisitDeclarations(scope()->declarations());
162
+ }
144
163
  }
145
164
 
146
165
  { Comment cmnt(masm_, "[ Stack check");
@@ -167,12 +186,12 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
167
186
  { Comment cmnt(masm_, "[ return <undefined>;");
168
187
  // Emit a 'return undefined' in case control fell off the end of the body.
169
188
  __ mov(eax, Factory::undefined_value());
170
- EmitReturnSequence(function()->end_position());
189
+ EmitReturnSequence();
171
190
  }
172
191
  }
173
192
 
174
193
 
175
- void FullCodeGenerator::EmitReturnSequence(int position) {
194
+ void FullCodeGenerator::EmitReturnSequence() {
176
195
  Comment cmnt(masm_, "[ Return sequence");
177
196
  if (return_label_.is_bound()) {
178
197
  __ 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.
@@ -425,6 +444,39 @@ void FullCodeGenerator::DropAndApply(int count,
425
444
  }
426
445
 
427
446
 
447
+ void FullCodeGenerator::PrepareTest(Label* materialize_true,
448
+ Label* materialize_false,
449
+ Label** if_true,
450
+ Label** if_false) {
451
+ switch (context_) {
452
+ case Expression::kUninitialized:
453
+ UNREACHABLE();
454
+ break;
455
+ case Expression::kEffect:
456
+ // In an effect context, the true and the false case branch to the
457
+ // same label.
458
+ *if_true = *if_false = materialize_true;
459
+ break;
460
+ case Expression::kValue:
461
+ *if_true = materialize_true;
462
+ *if_false = materialize_false;
463
+ break;
464
+ case Expression::kTest:
465
+ *if_true = true_label_;
466
+ *if_false = false_label_;
467
+ break;
468
+ case Expression::kValueTest:
469
+ *if_true = materialize_true;
470
+ *if_false = false_label_;
471
+ break;
472
+ case Expression::kTestValue:
473
+ *if_true = true_label_;
474
+ *if_false = materialize_false;
475
+ break;
476
+ }
477
+ }
478
+
479
+
428
480
  void FullCodeGenerator::Apply(Expression::Context context,
429
481
  Label* materialize_true,
430
482
  Label* materialize_false) {
@@ -490,6 +542,61 @@ void FullCodeGenerator::Apply(Expression::Context context,
490
542
  }
491
543
 
492
544
 
545
+ // Convert constant control flow (true or false) to the result expected for
546
+ // a given expression context.
547
+ void FullCodeGenerator::Apply(Expression::Context context, bool flag) {
548
+ switch (context) {
549
+ case Expression::kUninitialized:
550
+ UNREACHABLE();
551
+ break;
552
+ case Expression::kEffect:
553
+ break;
554
+ case Expression::kValue: {
555
+ Handle<Object> value =
556
+ flag ? Factory::true_value() : Factory::false_value();
557
+ switch (location_) {
558
+ case kAccumulator:
559
+ __ mov(result_register(), value);
560
+ break;
561
+ case kStack:
562
+ __ push(Immediate(value));
563
+ break;
564
+ }
565
+ break;
566
+ }
567
+ case Expression::kTest:
568
+ __ jmp(flag ? true_label_ : false_label_);
569
+ break;
570
+ case Expression::kTestValue:
571
+ switch (location_) {
572
+ case kAccumulator:
573
+ // If value is false it's needed.
574
+ if (!flag) __ mov(result_register(), Factory::false_value());
575
+ break;
576
+ case kStack:
577
+ // If value is false it's needed.
578
+ if (!flag) __ push(Immediate(Factory::false_value()));
579
+ break;
580
+ }
581
+ __ jmp(flag ? true_label_ : false_label_);
582
+ break;
583
+ case Expression::kValueTest:
584
+ switch (location_) {
585
+ case kAccumulator:
586
+ // If value is true it's needed.
587
+ if (flag) __ mov(result_register(), Factory::true_value());
588
+ break;
589
+ case kStack:
590
+ // If value is true it's needed.
591
+ if (flag) __ push(Immediate(Factory::true_value()));
592
+ break;
593
+ }
594
+ __ jmp(flag ? true_label_ : false_label_);
595
+ break;
596
+ }
597
+ }
598
+
599
+
493
600
  void FullCodeGenerator::DoTest(Expression::Context context) {
494
601
  // The value to test is in the accumulator. If the value might be needed
495
602
  // on the stack (value/test and test/value contexts with a stack location
@@ -665,22 +772,22 @@ void FullCodeGenerator::Move(Slot* dst,
665
772
  }
666
773
 
667
774
 
668
- void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
775
+ void FullCodeGenerator::EmitDeclaration(Variable* variable,
776
+ Variable::Mode mode,
777
+ FunctionLiteral* function) {
669
778
  Comment cmnt(masm_, "[ Declaration");
670
- Variable* var = decl->proxy()->var();
671
- ASSERT(var != NULL); // Must have been resolved.
672
- Slot* slot = var->slot();
673
- Property* prop = var->AsProperty();
674
-
779
+ ASSERT(variable != NULL); // Must have been resolved.
780
+ Slot* slot = variable->slot();
781
+ Property* prop = variable->AsProperty();
675
782
  if (slot != NULL) {
676
783
  switch (slot->type()) {
677
784
  case Slot::PARAMETER:
678
785
  case Slot::LOCAL:
679
- if (decl->mode() == Variable::CONST) {
786
+ if (mode == Variable::CONST) {
680
787
  __ mov(Operand(ebp, SlotOffset(slot)),
681
788
  Immediate(Factory::the_hole_value()));
682
- } else if (decl->fun() != NULL) {
683
- VisitForValue(decl->fun(), kAccumulator);
789
+ } else if (function != NULL) {
790
+ VisitForValue(function, kAccumulator);
684
791
  __ mov(Operand(ebp, SlotOffset(slot)), result_register());
685
792
  }
686
793
  break;
@@ -690,7 +797,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
690
797
  // this specific context.
691
798
 
692
799
  // The variable in the decl always resides in the current context.
693
- ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
800
+ ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
694
801
  if (FLAG_debug_code) {
695
802
  // Check if we have the correct context pointer.
696
803
  __ mov(ebx,
@@ -698,12 +805,12 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
698
805
  __ cmp(ebx, Operand(esi));
699
806
  __ Check(equal, "Unexpected declaration in current context.");
700
807
  }
701
- if (decl->mode() == Variable::CONST) {
702
- __ mov(eax, Immediate(Factory::the_hole_value()));
703
- __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax);
808
+ if (mode == Variable::CONST) {
809
+ __ mov(CodeGenerator::ContextOperand(esi, slot->index()),
810
+ Immediate(Factory::the_hole_value()));
704
811
  // No write barrier since the hole value is in old space.
705
- } else if (decl->fun() != NULL) {
706
- VisitForValue(decl->fun(), kAccumulator);
812
+ } else if (function != NULL) {
813
+ VisitForValue(function, kAccumulator);
707
814
  __ mov(CodeGenerator::ContextOperand(esi, slot->index()),
708
815
  result_register());
709
816
  int offset = Context::SlotOffset(slot->index());
@@ -714,21 +821,19 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
714
821
 
715
822
  case Slot::LOOKUP: {
716
823
  __ push(esi);
717
- __ push(Immediate(var->name()));
824
+ __ push(Immediate(variable->name()));
718
825
  // Declaration nodes are always introduced in one of two modes.
719
- ASSERT(decl->mode() == Variable::VAR ||
720
- decl->mode() == Variable::CONST);
721
- PropertyAttributes attr =
722
- (decl->mode() == Variable::VAR) ? NONE : READ_ONLY;
826
+ ASSERT(mode == Variable::VAR || mode == Variable::CONST);
827
+ PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
723
828
  __ push(Immediate(Smi::FromInt(attr)));
724
829
  // Push initial value, if any.
725
830
  // Note: For variables we must not push an initial value (such as
726
831
  // 'undefined') because we may have a (legal) redeclaration and we
727
832
  // must not destroy the current value.
728
- if (decl->mode() == Variable::CONST) {
833
+ if (mode == Variable::CONST) {
729
834
  __ push(Immediate(Factory::the_hole_value()));
730
- } else if (decl->fun() != NULL) {
731
- VisitForValue(decl->fun(), kStack);
835
+ } else if (function != NULL) {
836
+ VisitForValue(function, kStack);
732
837
  } else {
733
838
  __ push(Immediate(Smi::FromInt(0))); // No initial value!
734
839
  }
@@ -738,13 +843,13 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
738
843
  }
739
844
 
740
845
  } else if (prop != NULL) {
741
- if (decl->fun() != NULL || decl->mode() == Variable::CONST) {
846
+ if (function != NULL || mode == Variable::CONST) {
742
847
  // We are declaring a function or constant that rewrites to a
743
848
  // property. Use (keyed) IC to set the initial value.
744
849
  VisitForValue(prop->obj(), kStack);
745
- if (decl->fun() != NULL) {
850
+ if (function != NULL) {
746
851
  VisitForValue(prop->key(), kStack);
747
- VisitForValue(decl->fun(), kAccumulator);
852
+ VisitForValue(function, kAccumulator);
748
853
  __ pop(ecx);
749
854
  } else {
750
855
  VisitForValue(prop->key(), kAccumulator);
@@ -763,6 +868,11 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
763
868
  }
764
869
 
765
870
 
871
+ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
872
+ EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
873
+ }
874
+
875
+
766
876
  void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
767
877
  // Call the runtime to declare the globals.
768
878
  __ push(esi); // The context is the first argument.
@@ -773,19 +883,223 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
773
883
  }
774
884
 
775
885
 
776
- void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
777
- Comment cmnt(masm_, "[ FunctionLiteral");
886
+ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
887
+ Comment cmnt(masm_, "[ SwitchStatement");
888
+ Breakable nested_statement(this, stmt);
889
+ SetStatementPosition(stmt);
890
+ // Keep the switch value on the stack until a case matches.
891
+ VisitForValue(stmt->tag(), kStack);
892
+
893
+ ZoneList<CaseClause*>* clauses = stmt->cases();
894
+ CaseClause* default_clause = NULL; // Can occur anywhere in the list.
895
+
896
+ Label next_test; // Recycled for each test.
897
+ // Compile all the tests with branches to their bodies.
898
+ for (int i = 0; i < clauses->length(); i++) {
899
+ CaseClause* clause = clauses->at(i);
900
+ // The default is not a test, but remember it as final fall through.
901
+ if (clause->is_default()) {
902
+ default_clause = clause;
903
+ continue;
904
+ }
905
+
906
+ Comment cmnt(masm_, "[ Case comparison");
907
+ __ bind(&next_test);
908
+ next_test.Unuse();
909
+
910
+ // Compile the label expression.
911
+ VisitForValue(clause->label(), kAccumulator);
912
+
913
+ // Perform the comparison as if via '==='. The comparison stub expects
914
+ // the smi vs. smi case to be handled before it is called.
915
+ Label slow_case;
916
+ __ mov(edx, Operand(esp, 0)); // Switch value.
917
+ __ mov(ecx, edx);
918
+ __ or_(ecx, Operand(eax));
919
+ __ test(ecx, Immediate(kSmiTagMask));
920
+ __ j(not_zero, &slow_case, not_taken);
921
+ __ cmp(edx, Operand(eax));
922
+ __ j(not_equal, &next_test);
923
+ __ Drop(1); // Switch value is no longer needed.
924
+ __ jmp(clause->body_target()->entry_label());
925
+
926
+ __ bind(&slow_case);
927
+ CompareStub stub(equal, true);
928
+ __ CallStub(&stub);
929
+ __ test(eax, Operand(eax));
930
+ __ j(not_equal, &next_test);
931
+ __ Drop(1); // Switch value is no longer needed.
932
+ __ jmp(clause->body_target()->entry_label());
933
+ }
934
+
935
+ // Discard the test value and jump to the default if present, otherwise to
936
+ // the end of the statement.
937
+ __ bind(&next_test);
938
+ __ Drop(1); // Switch value is no longer needed.
939
+ if (default_clause == NULL) {
940
+ __ jmp(nested_statement.break_target());
941
+ } else {
942
+ __ jmp(default_clause->body_target()->entry_label());
943
+ }
944
+
945
+ // Compile all the case bodies.
946
+ for (int i = 0; i < clauses->length(); i++) {
947
+ Comment cmnt(masm_, "[ Case body");
948
+ CaseClause* clause = clauses->at(i);
949
+ __ bind(clause->body_target()->entry_label());
950
+ VisitStatements(clause->statements());
951
+ }
952
+
953
+ __ bind(nested_statement.break_target());
954
+ }
955
+
956
+
957
+ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
958
+ Comment cmnt(masm_, "[ ForInStatement");
959
+ SetStatementPosition(stmt);
960
+
961
+ Label loop, exit;
962
+ ForIn loop_statement(this, stmt);
963
+ increment_loop_depth();
964
+
965
+ // Get the object to enumerate over. Both SpiderMonkey and JSC
966
+ // ignore null and undefined in contrast to the specification; see
967
+ // ECMA-262 section 12.6.4.
968
+ VisitForValue(stmt->enumerable(), kAccumulator);
969
+ __ cmp(eax, Factory::undefined_value());
970
+ __ j(equal, &exit);
971
+ __ cmp(eax, Factory::null_value());
972
+ __ j(equal, &exit);
973
+
974
+ // Convert the object to a JS object.
975
+ Label convert, done_convert;
976
+ __ test(eax, Immediate(kSmiTagMask));
977
+ __ j(zero, &convert);
978
+ __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
979
+ __ j(above_equal, &done_convert);
980
+ __ bind(&convert);
981
+ __ push(eax);
982
+ __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
983
+ __ bind(&done_convert);
984
+ __ push(eax);
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(eax); // 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
+ __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map());
1001
+ __ j(not_equal, &fixed_array);
1002
+
1003
+ // We got a map in register eax. Get the enumeration cache from it.
1004
+ __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset));
1005
+ __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
1006
+ __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1007
+
1008
+ // Setup the four remaining stack slots.
1009
+ __ push(eax); // Map.
1010
+ __ push(edx); // Enumeration cache.
1011
+ __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
1012
+ __ push(eax); // Enumeration cache length (as smi).
1013
+ __ push(Immediate(Smi::FromInt(0))); // Initial index.
1014
+ __ jmp(&loop);
1015
+
1016
+ // We got a fixed array in register eax. Iterate through that.
1017
+ __ bind(&fixed_array);
1018
+ __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check.
1019
+ __ push(eax);
1020
+ __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
1021
+ __ push(eax); // Fixed array length (as smi).
1022
+ __ push(Immediate(Smi::FromInt(0))); // Initial index.
1023
+
1024
+ // Generate code for doing the condition check.
1025
+ __ bind(&loop);
1026
+ __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
1027
+ __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
1028
+ __ j(above_equal, loop_statement.break_target());
1029
+
1030
+ // Get the current entry of the array into register ebx.
1031
+ __ mov(ebx, Operand(esp, 2 * kPointerSize));
1032
+ __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
1033
+
1034
+ // Get the expected map from the stack or a zero map in the
1035
+ // permanent slow case into register edx.
1036
+ __ mov(edx, Operand(esp, 3 * kPointerSize));
1037
+
1038
+ // Check if the expected map still matches that of the enumerable.
1039
+ // If not, we have to filter the key.
1040
+ Label update_each;
1041
+ __ mov(ecx, Operand(esp, 4 * kPointerSize));
1042
+ __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1043
+ __ j(equal, &update_each);
1044
+
1045
+ // Convert the entry to a string or null if it isn't a property
1046
+ // anymore. If the property has been removed while iterating, we
1047
+ // just skip it.
1048
+ __ push(ecx); // Enumerable.
1049
+ __ push(ebx); // Current entry.
1050
+ __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1051
+ __ cmp(eax, Factory::null_value());
1052
+ __ j(equal, loop_statement.continue_target());
1053
+ __ mov(ebx, Operand(eax));
1054
+
1055
+ // Update the 'each' property or variable from the possibly filtered
1056
+ // entry in register ebx.
1057
+ __ bind(&update_each);
1058
+ __ mov(result_register(), ebx);
1059
+ // Perform the assignment as if via '='.
1060
+ EmitAssignment(stmt->each());
1061
+
1062
+ // Generate code for the body of the loop.
1063
+ Label stack_limit_hit, stack_check_done;
1064
+ Visit(stmt->body());
1065
+
1066
+ __ StackLimitCheck(&stack_limit_hit);
1067
+ __ bind(&stack_check_done);
1068
+
1069
+ // Generate code for going to the next element by incrementing the
1070
+ // index (smi) stored on top of the stack.
1071
+ __ bind(loop_statement.continue_target());
1072
+ __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1073
+ __ jmp(&loop);
1074
+
1075
+ // Slow case for the stack limit check.
1076
+ StackCheckStub stack_check_stub;
1077
+ __ bind(&stack_limit_hit);
1078
+ __ CallStub(&stack_check_stub);
1079
+ __ jmp(&stack_check_done);
1080
+
1081
+ // Remove the pointers stored on the stack.
1082
+ __ bind(loop_statement.break_target());
1083
+ __ add(Operand(esp), Immediate(5 * kPointerSize));
1084
+
1085
+ // Exit and decrement the loop depth.
1086
+ __ bind(&exit);
1087
+ decrement_loop_depth();
1088
+ }
778
1089
 
779
- // Build the shared function info and instantiate the function based
780
- // on it.
781
- Handle<SharedFunctionInfo> function_info =
782
- Compiler::BuildFunctionInfo(expr, script(), this);
783
- if (HasStackOverflow()) return;
784
1090
 
785
- // Create a new closure.
786
- __ push(esi);
787
- __ push(Immediate(function_info));
788
- __ CallRuntime(Runtime::kNewClosure, 2);
1091
+ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
1092
+ // Use the fast case closure allocation code that allocates in new
1093
+ // space for nested functions that don't need literals cloning.
1094
+ if (scope()->is_function_scope() && info->num_literals() == 0) {
1095
+ FastNewClosureStub stub;
1096
+ __ push(Immediate(info));
1097
+ __ CallStub(&stub);
1098
+ } else {
1099
+ __ push(esi);
1100
+ __ push(Immediate(info));
1101
+ __ CallRuntime(Runtime::kNewClosure, 2);
1102
+ }
789
1103
  Apply(context_, eax);
790
1104
  }
791
1105
 
@@ -830,7 +1144,20 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
830
1144
  Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
831
1145
  ? "Context slot"
832
1146
  : "Stack slot");
833
- Apply(context, slot);
1147
+ if (var->mode() == Variable::CONST) {
1148
+ // Constants may be the hole value if they have not been initialized.
1149
+ // Unhole them.
1150
+ Label done;
1151
+ MemOperand slot_operand = EmitSlotSearch(slot, eax);
1152
+ __ mov(eax, slot_operand);
1153
+ __ cmp(eax, Factory::the_hole_value());
1154
+ __ j(not_equal, &done);
1155
+ __ mov(eax, Factory::undefined_value());
1156
+ __ bind(&done);
1157
+ Apply(context, eax);
1158
+ } else {
1159
+ Apply(context, slot);
1160
+ }
834
1161
 
835
1162
  } else {
836
1163
  Comment cmnt(masm_, "Rewritten parameter");
@@ -966,22 +1293,28 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
966
1293
 
967
1294
  void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
968
1295
  Comment cmnt(masm_, "[ ArrayLiteral");
1296
+
1297
+ ZoneList<Expression*>* subexprs = expr->values();
1298
+ int length = subexprs->length();
1299
+
969
1300
  __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
970
1301
  __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
971
1302
  __ push(Immediate(Smi::FromInt(expr->literal_index())));
972
1303
  __ push(Immediate(expr->constant_elements()));
973
1304
  if (expr->depth() > 1) {
974
1305
  __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
975
- } else {
1306
+ } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
976
1307
  __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1308
+ } else {
1309
+ FastCloneShallowArrayStub stub(length);
1310
+ __ CallStub(&stub);
977
1311
  }
978
1312
 
979
1313
  bool result_saved = false; // Is the result saved to the stack?
980
1314
 
981
1315
  // Emit code to evaluate all the non-constant subexpressions and to store
982
1316
  // them into the newly cloned array.
983
- ZoneList<Expression*>* subexprs = expr->values();
984
- for (int i = 0, len = subexprs->length(); i < len; i++) {
1317
+ for (int i = 0; i < length; i++) {
985
1318
  Expression* subexpr = subexprs->at(i);
986
1319
  // If the subexpression is a literal or a simple materialized literal it
987
1320
  // is already set in the cloned array.
@@ -1016,7 +1349,13 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1016
1349
 
1017
1350
  void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1018
1351
  Comment cmnt(masm_, "[ Assignment");
1019
- ASSERT(expr->op() != Token::INIT_CONST);
1352
+ // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1353
+ // on the left-hand side.
1354
+ if (!expr->target()->IsValidLeftHandSide()) {
1355
+ VisitForEffect(expr->target());
1356
+ return;
1357
+ }
1358
+
1020
1359
  // Left-hand side can only be a property, a global or a (parameter or local)
1021
1360
  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1022
1361
  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
@@ -1095,6 +1434,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1095
1434
  switch (assign_type) {
1096
1435
  case VARIABLE:
1097
1436
  EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1437
+ expr->op(),
1098
1438
  context_);
1099
1439
  break;
1100
1440
  case NAMED_PROPERTY:
@@ -1137,15 +1477,66 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
1137
1477
  }
1138
1478
 
1139
1479
 
1480
+ void FullCodeGenerator::EmitAssignment(Expression* expr) {
1481
+ // Invalid left-hand sides are rewritten to have a 'throw
1482
+ // ReferenceError' on the left-hand side.
1483
+ if (!expr->IsValidLeftHandSide()) {
1484
+ VisitForEffect(expr);
1485
+ return;
1486
+ }
1487
+
1488
+ // Left-hand side can only be a property, a global or a (parameter or local)
1489
+ // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1490
+ enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1491
+ LhsKind assign_type = VARIABLE;
1492
+ Property* prop = expr->AsProperty();
1493
+ if (prop != NULL) {
1494
+ assign_type = (prop->key()->IsPropertyName())
1495
+ ? NAMED_PROPERTY
1496
+ : KEYED_PROPERTY;
1497
+ }
1498
+
1499
+ switch (assign_type) {
1500
+ case VARIABLE: {
1501
+ Variable* var = expr->AsVariableProxy()->var();
1502
+ EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
1503
+ break;
1504
+ }
1505
+ case NAMED_PROPERTY: {
1506
+ __ push(eax); // Preserve value.
1507
+ VisitForValue(prop->obj(), kAccumulator);
1508
+ __ mov(edx, eax);
1509
+ __ pop(eax); // Restore value.
1510
+ __ mov(ecx, prop->key()->AsLiteral()->handle());
1511
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1512
+ __ call(ic, RelocInfo::CODE_TARGET);
1513
+ __ nop(); // Signal no inlined code.
1514
+ break;
1515
+ }
1516
+ case KEYED_PROPERTY: {
1517
+ __ push(eax); // Preserve value.
1518
+ VisitForValue(prop->obj(), kStack);
1519
+ VisitForValue(prop->key(), kAccumulator);
1520
+ __ mov(ecx, eax);
1521
+ __ pop(edx);
1522
+ __ pop(eax); // Restore value.
1523
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1524
+ __ call(ic, RelocInfo::CODE_TARGET);
1525
+ __ nop(); // Signal no inlined code.
1526
+ break;
1527
+ }
1528
+ }
1529
+ }
1530
+
1531
+
1140
1532
  void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1533
+ Token::Value op,
1141
1534
  Expression::Context context) {
1142
- // Three main cases: global variables, lookup slots, and all other
1143
- // types of slots. Left-hand-side parameters that rewrite to
1144
- // explicit property accesses do not reach here.
1535
+ // Left-hand sides that rewrite to explicit property accesses do not reach
1536
+ // here.
1145
1537
  ASSERT(var != NULL);
1146
1538
  ASSERT(var->is_global() || var->slot() != NULL);
1147
1539
 
1148
- Slot* slot = var->slot();
1149
1540
  if (var->is_global()) {
1150
1541
  ASSERT(!var->is_this());
1151
1542
  // Assignment to a global variable. Use inline caching for the
@@ -1156,44 +1547,61 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1156
1547
  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1157
1548
  __ call(ic, RelocInfo::CODE_TARGET);
1158
1549
  __ nop();
1159
- Apply(context, eax);
1160
-
1161
- } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1162
- __ push(result_register()); // Value.
1163
- __ push(esi); // Context.
1164
- __ push(Immediate(var->name()));
1165
- __ CallRuntime(Runtime::kStoreContextSlot, 3);
1166
- Apply(context, eax);
1167
1550
 
1168
- } else if (slot != NULL) {
1551
+ } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1552
+ // Perform the assignment for non-const variables and for initialization
1553
+ // of const variables. Const assignments are simply skipped.
1554
+ Label done;
1555
+ Slot* slot = var->slot();
1169
1556
  switch (slot->type()) {
1170
- case Slot::LOCAL:
1171
1557
  case Slot::PARAMETER:
1172
- __ mov(Operand(ebp, SlotOffset(slot)), result_register());
1558
+ case Slot::LOCAL:
1559
+ if (op == Token::INIT_CONST) {
1560
+ // Detect const reinitialization by checking for the hole value.
1561
+ __ mov(edx, Operand(ebp, SlotOffset(slot)));
1562
+ __ cmp(edx, Factory::the_hole_value());
1563
+ __ j(not_equal, &done);
1564
+ }
1565
+ // Perform the assignment.
1566
+ __ mov(Operand(ebp, SlotOffset(slot)), eax);
1173
1567
  break;
1174
1568
 
1175
1569
  case Slot::CONTEXT: {
1176
1570
  MemOperand target = EmitSlotSearch(slot, ecx);
1177
- __ mov(target, result_register());
1178
-
1179
- // RecordWrite may destroy all its register arguments.
1180
- __ mov(edx, result_register());
1571
+ if (op == Token::INIT_CONST) {
1572
+ // Detect const reinitialization by checking for the hole value.
1573
+ __ mov(edx, target);
1574
+ __ cmp(edx, Factory::the_hole_value());
1575
+ __ j(not_equal, &done);
1576
+ }
1577
+ // Perform the assignment and issue the write barrier.
1578
+ __ mov(target, eax);
1579
+ // The value of the assignment is in eax. RecordWrite clobbers its
1580
+ // register arguments.
1581
+ __ mov(edx, eax);
1181
1582
  int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1182
1583
  __ RecordWrite(ecx, offset, edx, ebx);
1183
1584
  break;
1184
1585
  }
1185
1586
 
1186
1587
  case Slot::LOOKUP:
1187
- UNREACHABLE();
1588
+ // Call the runtime for the assignment. The runtime will ignore
1589
+ // const reinitialization.
1590
+ __ push(eax); // Value.
1591
+ __ push(esi); // Context.
1592
+ __ push(Immediate(var->name()));
1593
+ if (op == Token::INIT_CONST) {
1594
+ // The runtime will ignore const redeclaration.
1595
+ __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1596
+ } else {
1597
+ __ CallRuntime(Runtime::kStoreContextSlot, 3);
1598
+ }
1188
1599
  break;
1189
1600
  }
1190
- Apply(context, result_register());
1191
-
1192
- } else {
1193
- // Variables rewritten as properties are not treated as variables in
1194
- // assignments.
1195
- UNREACHABLE();
1601
+ __ bind(&done);
1196
1602
  }
1603
+
1604
+ Apply(context, eax);
1197
1605
  }
1198
1606
 
1199
1607
 
@@ -1318,6 +1726,29 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
1318
1726
  }
1319
1727
 
1320
1728
 
1729
+ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
1730
+ Expression* key,
1731
+ RelocInfo::Mode mode) {
1732
+ // Code common for calls using the IC.
1733
+ ZoneList<Expression*>* args = expr->arguments();
1734
+ int arg_count = args->length();
1735
+ for (int i = 0; i < arg_count; i++) {
1736
+ VisitForValue(args->at(i), kStack);
1737
+ }
1738
+ VisitForValue(key, kAccumulator);
1739
+ __ mov(ecx, eax);
1740
+ // Record source position of the IC call.
1741
+ SetSourcePosition(expr->position());
1742
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1743
+ Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(
1744
+ arg_count, in_loop);
1745
+ __ call(ic, mode);
1746
+ // Restore context register.
1747
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1748
+ Apply(context_, eax);
1749
+ }
1750
+
1751
+
1321
1752
  void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1322
1753
  // Code common for calls using the call stub.
1323
1754
  ZoneList<Expression*>* args = expr->arguments();
@@ -1327,7 +1758,8 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1327
1758
  }
1328
1759
  // Record source position for debugger.
1329
1760
  SetSourcePosition(expr->position());
1330
- CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
1761
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1762
+ CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1331
1763
  __ CallStub(&stub);
1332
1764
  // Restore context register.
1333
1765
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -1341,16 +1773,62 @@ void FullCodeGenerator::VisitCall(Call* expr) {
1341
1773
  Variable* var = fun->AsVariableProxy()->AsVariable();
1342
1774
 
1343
1775
  if (var != NULL && var->is_possibly_eval()) {
1344
- // Call to the identifier 'eval'.
1345
- UNREACHABLE();
1776
+ // In a call to eval, we first call %ResolvePossiblyDirectEval to
1777
+ // resolve the function we need to call and the receiver of the
1778
+ // call. Then we call the resolved function using the given
1779
+ // arguments.
1780
+ VisitForValue(fun, kStack);
1781
+ __ push(Immediate(Factory::undefined_value())); // Reserved receiver slot.
1782
+
1783
+ // Push the arguments.
1784
+ ZoneList<Expression*>* args = expr->arguments();
1785
+ int arg_count = args->length();
1786
+ for (int i = 0; i < arg_count; i++) {
1787
+ VisitForValue(args->at(i), kStack);
1788
+ }
1789
+
1790
+ // Push copy of the function - found below the arguments.
1791
+ __ push(Operand(esp, (arg_count + 1) * kPointerSize));
1792
+
1793
+ // Push copy of the first argument or undefined if it doesn't exist.
1794
+ if (arg_count > 0) {
1795
+ __ push(Operand(esp, arg_count * kPointerSize));
1796
+ } else {
1797
+ __ push(Immediate(Factory::undefined_value()));
1798
+ }
1799
+
1800
+ // Push the receiver of the enclosing function and do runtime call.
1801
+ __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
1802
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
1803
+
1804
+ // The runtime call returns a pair of values in eax (function) and
1805
+ // edx (receiver). Touch up the stack with the right values.
1806
+ __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
1807
+ __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
1808
+
1809
+ // Record source position for debugger.
1810
+ SetSourcePosition(expr->position());
1811
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1812
+ CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1813
+ __ CallStub(&stub);
1814
+ // Restore context register.
1815
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1816
+ DropAndApply(1, context_, eax);
1346
1817
  } else if (var != NULL && !var->is_this() && var->is_global()) {
1347
1818
  // Push global object as receiver for the call IC.
1348
1819
  __ push(CodeGenerator::GlobalObject());
1349
1820
  EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1350
1821
  } else if (var != NULL && var->slot() != NULL &&
1351
1822
  var->slot()->type() == Slot::LOOKUP) {
1352
- // Call to a lookup slot.
1353
- UNREACHABLE();
1823
+ // Call to a lookup slot (dynamically introduced variable). Call the
1824
+ // runtime to find the function to call (returned in eax) and the object
1825
+ // holding it (returned in edx).
1826
+ __ push(context_register());
1827
+ __ push(Immediate(var->name()));
1828
+ __ CallRuntime(Runtime::kLoadContextSlot, 2);
1829
+ __ push(eax); // Function.
1830
+ __ push(edx); // Receiver.
1831
+ EmitCallWithStub(expr);
1354
1832
  } else if (fun->AsProperty() != NULL) {
1355
1833
  // Call to an object property.
1356
1834
  Property* prop = fun->AsProperty();
@@ -1360,37 +1838,31 @@ void FullCodeGenerator::VisitCall(Call* expr) {
1360
1838
  VisitForValue(prop->obj(), kStack);
1361
1839
  EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1362
1840
  } else {
1363
- // Call to a keyed property, use keyed load IC followed by function
1364
- // call.
1841
+ // Call to a keyed property.
1842
+ // For a synthetic property use keyed load IC followed by function call,
1843
+ // for a regular property use keyed CallIC.
1365
1844
  VisitForValue(prop->obj(), kStack);
1366
- VisitForValue(prop->key(), kAccumulator);
1367
- // Record source code position for IC call.
1368
- SetSourcePosition(prop->position());
1369
1845
  if (prop->is_synthetic()) {
1846
+ VisitForValue(prop->key(), kAccumulator);
1847
+ // Record source code position for IC call.
1848
+ SetSourcePosition(prop->position());
1370
1849
  __ pop(edx); // We do not need to keep the receiver.
1371
- } else {
1372
- __ mov(edx, Operand(esp, 0)); // Keep receiver, to call function on.
1373
- }
1374
1850
 
1375
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1376
- __ call(ic, RelocInfo::CODE_TARGET);
1377
- // By emitting a nop we make sure that we do not have a "test eax,..."
1378
- // instruction after the call it is treated specially by the LoadIC code.
1379
- __ nop();
1380
- if (prop->is_synthetic()) {
1851
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1852
+ __ call(ic, RelocInfo::CODE_TARGET);
1853
+ // By emitting a nop we make sure that we do not have a "test eax,..."
1854
+ // instruction after the call as it is treated specially
1855
+ // by the LoadIC code.
1856
+ __ nop();
1381
1857
  // Push result (function).
1382
1858
  __ push(eax);
1383
1859
  // Push Global receiver.
1384
1860
  __ mov(ecx, CodeGenerator::GlobalObject());
1385
1861
  __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
1862
+ EmitCallWithStub(expr);
1386
1863
  } else {
1387
- // Pop receiver.
1388
- __ pop(ebx);
1389
- // Push result (function).
1390
- __ push(eax);
1391
- __ push(ebx);
1864
+ EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1392
1865
  }
1393
- EmitCallWithStub(expr);
1394
1866
  }
1395
1867
  } else {
1396
1868
  // Call to some other expression. If the expression is an anonymous
@@ -1447,55 +1919,833 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
1447
1919
  }
1448
1920
 
1449
1921
 
1450
- void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1451
- Comment cmnt(masm_, "[ CallRuntime");
1452
- ZoneList<Expression*>* args = expr->arguments();
1922
+ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
1923
+ ASSERT(args->length() == 1);
1453
1924
 
1454
- if (expr->is_jsruntime()) {
1455
- // Prepare for calling JS runtime function.
1456
- __ mov(eax, CodeGenerator::GlobalObject());
1457
- __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
1458
- }
1925
+ VisitForValue(args->at(0), kAccumulator);
1459
1926
 
1460
- // Push the arguments ("left-to-right").
1461
- int arg_count = args->length();
1462
- for (int i = 0; i < arg_count; i++) {
1463
- VisitForValue(args->at(i), kStack);
1464
- }
1927
+ Label materialize_true, materialize_false;
1928
+ Label* if_true = NULL;
1929
+ Label* if_false = NULL;
1930
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1465
1931
 
1466
- if (expr->is_jsruntime()) {
1467
- // Call the JS runtime function via a call IC.
1468
- __ Set(ecx, Immediate(expr->name()));
1469
- InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1470
- Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1471
- __ call(ic, RelocInfo::CODE_TARGET);
1472
- // Restore context register.
1473
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1474
- } else {
1475
- // Call the C runtime function.
1476
- __ CallRuntime(expr->function(), arg_count);
1477
- }
1478
- Apply(context_, eax);
1932
+ __ test(eax, Immediate(kSmiTagMask));
1933
+ __ j(zero, if_true);
1934
+ __ jmp(if_false);
1935
+
1936
+ Apply(context_, if_true, if_false);
1479
1937
  }
1480
1938
 
1481
1939
 
1482
- void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1483
- switch (expr->op()) {
1484
- case Token::VOID: {
1485
- Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1486
- VisitForEffect(expr->expression());
1487
- switch (context_) {
1488
- case Expression::kUninitialized:
1489
- UNREACHABLE();
1490
- break;
1491
- case Expression::kEffect:
1492
- break;
1493
- case Expression::kValue:
1494
- switch (location_) {
1495
- case kAccumulator:
1496
- __ mov(result_register(), Factory::undefined_value());
1497
- break;
1498
- case kStack:
1940
+ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1941
+ ASSERT(args->length() == 1);
1942
+
1943
+ VisitForValue(args->at(0), kAccumulator);
1944
+
1945
+ Label materialize_true, materialize_false;
1946
+ Label* if_true = NULL;
1947
+ Label* if_false = NULL;
1948
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1949
+
1950
+ __ test(eax, Immediate(kSmiTagMask | 0x80000000));
1951
+ __ j(zero, if_true);
1952
+ __ jmp(if_false);
1953
+
1954
+ Apply(context_, if_true, if_false);
1955
+ }
1956
+
1957
+
1958
+ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
1959
+ ASSERT(args->length() == 1);
1960
+
1961
+ VisitForValue(args->at(0), kAccumulator);
1962
+
1963
+ Label materialize_true, materialize_false;
1964
+ Label* if_true = NULL;
1965
+ Label* if_false = NULL;
1966
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1967
+
1968
+ __ test(eax, Immediate(kSmiTagMask));
1969
+ __ j(zero, if_false);
1970
+ __ cmp(eax, Factory::null_value());
1971
+ __ j(equal, if_true);
1972
+ __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1973
+ // Undetectable objects behave like undefined when tested with typeof.
1974
+ __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
1975
+ __ test(ecx, Immediate(1 << Map::kIsUndetectable));
1976
+ __ j(not_zero, if_false);
1977
+ __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1978
+ __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
1979
+ __ j(below, if_false);
1980
+ __ cmp(ecx, LAST_JS_OBJECT_TYPE);
1981
+ __ j(below_equal, if_true);
1982
+ __ jmp(if_false);
1983
+
1984
+ Apply(context_, if_true, if_false);
1985
+ }
1986
+
1987
+
1988
+ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
1989
+ ASSERT(args->length() == 1);
1990
+
1991
+ VisitForValue(args->at(0), kAccumulator);
1992
+
1993
+ Label materialize_true, materialize_false;
1994
+ Label* if_true = NULL;
1995
+ Label* if_false = NULL;
1996
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1997
+
1998
+ __ test(eax, Immediate(kSmiTagMask));
1999
+ __ j(equal, if_false);
2000
+ __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx);
2001
+ __ j(above_equal, if_true);
2002
+ __ jmp(if_false);
2003
+
2004
+ Apply(context_, if_true, if_false);
2005
+ }
2006
+
2007
+
2008
+ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2009
+ ASSERT(args->length() == 1);
2010
+
2011
+ VisitForValue(args->at(0), kAccumulator);
2012
+
2013
+ Label materialize_true, materialize_false;
2014
+ Label* if_true = NULL;
2015
+ Label* if_false = NULL;
2016
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2017
+
2018
+ __ test(eax, Immediate(kSmiTagMask));
2019
+ __ j(zero, if_false);
2020
+ __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2021
+ __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2022
+ __ test(ebx, Immediate(1 << Map::kIsUndetectable));
2023
+ __ j(not_zero, if_true);
2024
+ __ jmp(if_false);
2025
+
2026
+ Apply(context_, if_true, if_false);
2027
+ }
2028
+
2029
+
2030
+ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2031
+ ASSERT(args->length() == 1);
2032
+
2033
+ VisitForValue(args->at(0), kAccumulator);
2034
+
2035
+ Label materialize_true, materialize_false;
2036
+ Label* if_true = NULL;
2037
+ Label* if_false = NULL;
2038
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2039
+
2040
+ __ test(eax, Immediate(kSmiTagMask));
2041
+ __ j(zero, if_false);
2042
+ __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2043
+ __ j(equal, if_true);
2044
+ __ jmp(if_false);
2045
+
2046
+ Apply(context_, if_true, if_false);
2047
+ }
2048
+
2049
+
2050
+ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2051
+ ASSERT(args->length() == 1);
2052
+
2053
+ VisitForValue(args->at(0), kAccumulator);
2054
+
2055
+ Label materialize_true, materialize_false;
2056
+ Label* if_true = NULL;
2057
+ Label* if_false = NULL;
2058
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2059
+
2060
+ __ test(eax, Immediate(kSmiTagMask));
2061
+ __ j(equal, if_false);
2062
+ __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
2063
+ __ j(equal, if_true);
2064
+ __ jmp(if_false);
2065
+
2066
+ Apply(context_, if_true, if_false);
2067
+ }
2068
+
2069
+
2070
+ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2071
+ ASSERT(args->length() == 1);
2072
+
2073
+ VisitForValue(args->at(0), kAccumulator);
2074
+
2075
+ Label materialize_true, materialize_false;
2076
+ Label* if_true = NULL;
2077
+ Label* if_false = NULL;
2078
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2079
+
2080
+ __ test(eax, Immediate(kSmiTagMask));
2081
+ __ j(equal, if_false);
2082
+ __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
2083
+ __ j(equal, if_true);
2084
+ __ jmp(if_false);
2085
+
2086
+ Apply(context_, if_true, if_false);
2087
+ }
2088
+
2089
+
2090
+
2091
+ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2092
+ ASSERT(args->length() == 0);
2093
+
2094
+ Label materialize_true, materialize_false;
2095
+ Label* if_true = NULL;
2096
+ Label* if_false = NULL;
2097
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2098
+
2099
+ // Get the frame pointer for the calling frame.
2100
+ __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2101
+
2102
+ // Skip the arguments adaptor frame if it exists.
2103
+ Label check_frame_marker;
2104
+ __ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
2105
+ Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2106
+ __ j(not_equal, &check_frame_marker);
2107
+ __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
2108
+
2109
+ // Check the marker in the calling frame.
2110
+ __ bind(&check_frame_marker);
2111
+ __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
2112
+ Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
2113
+ __ j(equal, if_true);
2114
+ __ jmp(if_false);
2115
+
2116
+ Apply(context_, if_true, if_false);
2117
+ }
2118
+
2119
+
2120
+ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2121
+ ASSERT(args->length() == 2);
2122
+
2123
+ // Load the two objects into registers and perform the comparison.
2124
+ VisitForValue(args->at(0), kStack);
2125
+ VisitForValue(args->at(1), kAccumulator);
2126
+
2127
+ Label materialize_true, materialize_false;
2128
+ Label* if_true = NULL;
2129
+ Label* if_false = NULL;
2130
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2131
+
2132
+ __ pop(ebx);
2133
+ __ cmp(eax, Operand(ebx));
2134
+ __ j(equal, if_true);
2135
+ __ jmp(if_false);
2136
+
2137
+ Apply(context_, if_true, if_false);
2138
+ }
2139
+
2140
+
2141
+ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2142
+ ASSERT(args->length() == 1);
2143
+
2144
+ // ArgumentsAccessStub expects the key in edx and the formal
2145
+ // parameter count in eax.
2146
+ VisitForValue(args->at(0), kAccumulator);
2147
+ __ mov(edx, eax);
2148
+ __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2149
+ ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2150
+ __ CallStub(&stub);
2151
+ Apply(context_, eax);
2152
+ }
2153
+
2154
+
2155
+ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2156
+ ASSERT(args->length() == 0);
2157
+
2158
+ Label exit;
2159
+ // Get the number of formal parameters.
2160
+ __ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2161
+
2162
+ // Check if the calling frame is an arguments adaptor frame.
2163
+ __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2164
+ __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2165
+ Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2166
+ __ j(not_equal, &exit);
2167
+
2168
+ // Arguments adaptor case: Read the arguments length from the
2169
+ // adaptor frame.
2170
+ __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2171
+
2172
+ __ bind(&exit);
2173
+ if (FLAG_debug_code) __ AbortIfNotSmi(eax);
2174
+ Apply(context_, eax);
2175
+ }
2176
+
2177
+
2178
+ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2179
+ ASSERT(args->length() == 1);
2180
+ Label done, null, function, non_function_constructor;
2181
+
2182
+ VisitForValue(args->at(0), kAccumulator);
2183
+
2184
+ // If the object is a smi, we return null.
2185
+ __ test(eax, Immediate(kSmiTagMask));
2186
+ __ j(zero, &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(eax, FIRST_JS_OBJECT_TYPE, eax); // Map is now in eax.
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(eax, JS_FUNCTION_TYPE);
2199
+ __ j(equal, &function);
2200
+
2201
+ // Check if the constructor in the map is a function.
2202
+ __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
2203
+ __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2204
+ __ j(not_equal, &non_function_constructor);
2205
+
2206
+ // eax now contains the constructor function. Grab the
2207
+ // instance class name from there.
2208
+ __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
2209
+ __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
2210
+ __ jmp(&done);
2211
+
2212
+ // Functions have class 'Function'.
2213
+ __ bind(&function);
2214
+ __ mov(eax, Factory::function_class_symbol());
2215
+ __ jmp(&done);
2216
+
2217
+ // Objects with a non-function constructor have class 'Object'.
2218
+ __ bind(&non_function_constructor);
2219
+ __ mov(eax, Factory::Object_symbol());
2220
+ __ jmp(&done);
2221
+
2222
+ // Non-JS objects have class null.
2223
+ __ bind(&null);
2224
+ __ mov(eax, Factory::null_value());
2225
+
2226
+ // All done.
2227
+ __ bind(&done);
2228
+
2229
+ Apply(context_, eax);
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
+ __ mov(eax, Factory::undefined_value());
2251
+ Apply(context_, eax);
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(edi, ebx, ecx, &slow_allocate_heapnumber);
2262
+ __ jmp(&heapnumber_allocated);
2263
+
2264
+ __ bind(&slow_allocate_heapnumber);
2265
+ // Allocate a heap number.
2266
+ __ CallRuntime(Runtime::kNumberAlloc, 0);
2267
+ __ mov(edi, eax);
2268
+
2269
+ __ bind(&heapnumber_allocated);
2270
+
2271
+ __ PrepareCallCFunction(0, ebx);
2272
+ __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2273
+
2274
+ // Convert 32 random bits in eax to 0.(32 random bits) in a double
2275
+ // by computing:
2276
+ // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2277
+ // This is implemented on both SSE2 and FPU.
2278
+ if (CpuFeatures::IsSupported(SSE2)) {
2279
+ CpuFeatures::Scope fscope(SSE2);
2280
+ __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
2281
+ __ movd(xmm1, Operand(ebx));
2282
+ __ movd(xmm0, Operand(eax));
2283
+ __ cvtss2sd(xmm1, xmm1);
2284
+ __ pxor(xmm0, xmm1);
2285
+ __ subsd(xmm0, xmm1);
2286
+ __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
2287
+ } else {
2288
+ // 0x4130000000000000 is 1.0 x 2^20 as a double.
2289
+ __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
2290
+ Immediate(0x41300000));
2291
+ __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
2292
+ __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2293
+ __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
2294
+ __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2295
+ __ fsubp(1);
2296
+ __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
2297
+ }
2298
+ __ mov(eax, edi);
2299
+ Apply(context_, eax);
2300
+ }
2301
+
2302
+
2303
+ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2304
+ // Load the arguments on the stack and call the stub.
2305
+ SubStringStub stub;
2306
+ ASSERT(args->length() == 3);
2307
+ VisitForValue(args->at(0), kStack);
2308
+ VisitForValue(args->at(1), kStack);
2309
+ VisitForValue(args->at(2), kStack);
2310
+ __ CallStub(&stub);
2311
+ Apply(context_, eax);
2312
+ }
2313
+
2314
+
2315
+ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2316
+ // Load the arguments on the stack and call the stub.
2317
+ RegExpExecStub stub;
2318
+ ASSERT(args->length() == 4);
2319
+ VisitForValue(args->at(0), kStack);
2320
+ VisitForValue(args->at(1), kStack);
2321
+ VisitForValue(args->at(2), kStack);
2322
+ VisitForValue(args->at(3), kStack);
2323
+ __ CallStub(&stub);
2324
+ Apply(context_, eax);
2325
+ }
2326
+
2327
+
2328
+ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2329
+ ASSERT(args->length() == 1);
2330
+
2331
+ VisitForValue(args->at(0), kAccumulator); // Load the object.
2332
+
2333
+ Label done;
2334
+ // If the object is a smi return the object.
2335
+ __ test(eax, Immediate(kSmiTagMask));
2336
+ __ j(zero, &done);
2337
+ // If the object is not a value type, return the object.
2338
+ __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2339
+ __ j(not_equal, &done);
2340
+ __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2341
+
2342
+ __ bind(&done);
2343
+ Apply(context_, eax);
2344
+ }
2345
+
2346
+
2347
+ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2348
+ // Load the arguments on the stack and call the runtime function.
2349
+ ASSERT(args->length() == 2);
2350
+ VisitForValue(args->at(0), kStack);
2351
+ VisitForValue(args->at(1), kStack);
2352
+ __ CallRuntime(Runtime::kMath_pow, 2);
2353
+ Apply(context_, eax);
2354
+ }
2355
+
2356
+
2357
+ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2358
+ ASSERT(args->length() == 2);
2359
+
2360
+ VisitForValue(args->at(0), kStack); // Load the object.
2361
+ VisitForValue(args->at(1), kAccumulator); // Load the value.
2362
+ __ pop(ebx); // eax = value. ebx = object.
2363
+
2364
+ Label done;
2365
+ // If the object is a smi, return the value.
2366
+ __ test(ebx, Immediate(kSmiTagMask));
2367
+ __ j(zero, &done);
2368
+
2369
+ // If the object is not a value type, return the value.
2370
+ __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
2371
+ __ j(not_equal, &done);
2372
+
2373
+ // Store the value.
2374
+ __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
2375
+ // Update the write barrier. Save the value as it will be
2376
+ // overwritten by the write barrier code and is needed afterward.
2377
+ __ mov(edx, eax);
2378
+ __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx);
2379
+
2380
+ __ bind(&done);
2381
+ Apply(context_, eax);
2382
+ }
2383
+
2384
+
2385
+ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2386
+ ASSERT_EQ(args->length(), 1);
2387
+
2388
+ // Load the argument on the stack and call the stub.
2389
+ VisitForValue(args->at(0), kStack);
2390
+
2391
+ NumberToStringStub stub;
2392
+ __ CallStub(&stub);
2393
+ Apply(context_, eax);
2394
+ }
2395
+
2396
+
2397
+ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2398
+ ASSERT(args->length() == 1);
2399
+
2400
+ VisitForValue(args->at(0), kAccumulator);
2401
+
2402
+ Label done;
2403
+ StringCharFromCodeGenerator generator(eax, ebx);
2404
+ generator.GenerateFast(masm_);
2405
+ __ jmp(&done);
2406
+
2407
+ NopRuntimeCallHelper call_helper;
2408
+ generator.GenerateSlow(masm_, call_helper);
2409
+
2410
+ __ bind(&done);
2411
+ Apply(context_, ebx);
2412
+ }
2413
+
2414
+
2415
+ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
2416
+ ASSERT(args->length() == 2);
2417
+
2418
+ VisitForValue(args->at(0), kStack);
2419
+ VisitForValue(args->at(1), kAccumulator);
2420
+
2421
+ Register object = ebx;
2422
+ Register index = eax;
2423
+ Register scratch = ecx;
2424
+ Register result = edx;
2425
+
2426
+ __ pop(object);
2427
+
2428
+ Label need_conversion;
2429
+ Label index_out_of_range;
2430
+ Label done;
2431
+ StringCharCodeAtGenerator generator(object,
2432
+ index,
2433
+ scratch,
2434
+ result,
2435
+ &need_conversion,
2436
+ &need_conversion,
2437
+ &index_out_of_range,
2438
+ STRING_INDEX_IS_NUMBER);
2439
+ generator.GenerateFast(masm_);
2440
+ __ jmp(&done);
2441
+
2442
+ __ bind(&index_out_of_range);
2443
+ // When the index is out of range, the spec requires us to return
2444
+ // NaN.
2445
+ __ Set(result, Immediate(Factory::nan_value()));
2446
+ __ jmp(&done);
2447
+
2448
+ __ bind(&need_conversion);
2449
+ // Move the undefined value into the result register, which will
2450
+ // trigger conversion.
2451
+ __ Set(result, Immediate(Factory::undefined_value()));
2452
+ __ jmp(&done);
2453
+
2454
+ NopRuntimeCallHelper call_helper;
2455
+ generator.GenerateSlow(masm_, call_helper);
2456
+
2457
+ __ bind(&done);
2458
+ Apply(context_, result);
2459
+ }
2460
+
2461
+
2462
+ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
2463
+ ASSERT(args->length() == 2);
2464
+
2465
+ VisitForValue(args->at(0), kStack);
2466
+ VisitForValue(args->at(1), kAccumulator);
2467
+
2468
+ Register object = ebx;
2469
+ Register index = eax;
2470
+ Register scratch1 = ecx;
2471
+ Register scratch2 = edx;
2472
+ Register result = eax;
2473
+
2474
+ __ pop(object);
2475
+
2476
+ Label need_conversion;
2477
+ Label index_out_of_range;
2478
+ Label done;
2479
+ StringCharAtGenerator generator(object,
2480
+ index,
2481
+ scratch1,
2482
+ scratch2,
2483
+ result,
2484
+ &need_conversion,
2485
+ &need_conversion,
2486
+ &index_out_of_range,
2487
+ STRING_INDEX_IS_NUMBER);
2488
+ generator.GenerateFast(masm_);
2489
+ __ jmp(&done);
2490
+
2491
+ __ bind(&index_out_of_range);
2492
+ // When the index is out of range, the spec requires us to return
2493
+ // the empty string.
2494
+ __ Set(result, Immediate(Factory::empty_string()));
2495
+ __ jmp(&done);
2496
+
2497
+ __ bind(&need_conversion);
2498
+ // Move smi zero into the result register, which will trigger
2499
+ // conversion.
2500
+ __ Set(result, Immediate(Smi::FromInt(0)));
2501
+ __ jmp(&done);
2502
+
2503
+ NopRuntimeCallHelper call_helper;
2504
+ generator.GenerateSlow(masm_, call_helper);
2505
+
2506
+ __ bind(&done);
2507
+ Apply(context_, result);
2508
+ }
2509
+
2510
+
2511
+ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2512
+ ASSERT_EQ(2, args->length());
2513
+
2514
+ VisitForValue(args->at(0), kStack);
2515
+ VisitForValue(args->at(1), kStack);
2516
+
2517
+ StringAddStub stub(NO_STRING_ADD_FLAGS);
2518
+ __ CallStub(&stub);
2519
+ Apply(context_, eax);
2520
+ }
2521
+
2522
+
2523
+ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2524
+ ASSERT_EQ(2, args->length());
2525
+
2526
+ VisitForValue(args->at(0), kStack);
2527
+ VisitForValue(args->at(1), kStack);
2528
+
2529
+ StringCompareStub stub;
2530
+ __ CallStub(&stub);
2531
+ Apply(context_, eax);
2532
+ }
2533
+
2534
+
2535
+ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2536
+ // Load the argument on the stack and call the stub.
2537
+ TranscendentalCacheStub stub(TranscendentalCache::SIN);
2538
+ ASSERT(args->length() == 1);
2539
+ VisitForValue(args->at(0), kStack);
2540
+ __ CallStub(&stub);
2541
+ Apply(context_, eax);
2542
+ }
2543
+
2544
+
2545
+ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2546
+ // Load the argument on the stack and call the stub.
2547
+ TranscendentalCacheStub stub(TranscendentalCache::COS);
2548
+ ASSERT(args->length() == 1);
2549
+ VisitForValue(args->at(0), kStack);
2550
+ __ CallStub(&stub);
2551
+ Apply(context_, eax);
2552
+ }
2553
+
2554
+
2555
+ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2556
+ // Load the argument on the stack and call the runtime function.
2557
+ ASSERT(args->length() == 1);
2558
+ VisitForValue(args->at(0), kStack);
2559
+ __ CallRuntime(Runtime::kMath_sqrt, 1);
2560
+ Apply(context_, eax);
2561
+ }
2562
+
2563
+
2564
+ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2565
+ ASSERT(args->length() >= 2);
2566
+
2567
+ int arg_count = args->length() - 2; // For receiver and function.
2568
+ VisitForValue(args->at(0), kStack); // Receiver.
2569
+ for (int i = 0; i < arg_count; i++) {
2570
+ VisitForValue(args->at(i + 1), kStack);
2571
+ }
2572
+ VisitForValue(args->at(arg_count + 1), kAccumulator); // Function.
2573
+
2574
+ // InvokeFunction requires function in edi. Move it in there.
2575
+ if (!result_register().is(edi)) __ mov(edi, result_register());
2576
+ ParameterCount count(arg_count);
2577
+ __ InvokeFunction(edi, count, CALL_FUNCTION);
2578
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2579
+ Apply(context_, eax);
2580
+ }
2581
+
2582
+
2583
+ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2584
+ ASSERT(args->length() == 3);
2585
+ VisitForValue(args->at(0), kStack);
2586
+ VisitForValue(args->at(1), kStack);
2587
+ VisitForValue(args->at(2), kStack);
2588
+ __ CallRuntime(Runtime::kRegExpConstructResult, 3);
2589
+ Apply(context_, eax);
2590
+ }
2591
+
2592
+
2593
+ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2594
+ ASSERT(args->length() == 3);
2595
+ VisitForValue(args->at(0), kStack);
2596
+ VisitForValue(args->at(1), kStack);
2597
+ VisitForValue(args->at(2), kStack);
2598
+ __ CallRuntime(Runtime::kSwapElements, 3);
2599
+ Apply(context_, eax);
2600
+ }
2601
+
2602
+
2603
+ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2604
+ ASSERT_EQ(2, args->length());
2605
+
2606
+ ASSERT_NE(NULL, args->at(0)->AsLiteral());
2607
+ int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2608
+
2609
+ Handle<FixedArray> jsfunction_result_caches(
2610
+ Top::global_context()->jsfunction_result_caches());
2611
+ if (jsfunction_result_caches->length() <= cache_id) {
2612
+ __ Abort("Attempt to use undefined cache.");
2613
+ __ mov(eax, Factory::undefined_value());
2614
+ Apply(context_, eax);
2615
+ return;
2616
+ }
2617
+
2618
+ VisitForValue(args->at(1), kAccumulator);
2619
+
2620
+ Register key = eax;
2621
+ Register cache = ebx;
2622
+ Register tmp = ecx;
2623
+ __ mov(cache, CodeGenerator::ContextOperand(esi, Context::GLOBAL_INDEX));
2624
+ __ mov(cache,
2625
+ FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2626
+ __ mov(cache,
2627
+ CodeGenerator::ContextOperand(
2628
+ cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2629
+ __ mov(cache,
2630
+ FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2631
+
2632
+ Label done, not_found;
2633
+ // tmp now holds finger offset as a smi.
2634
+ ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2635
+ __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
2636
+ __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
2637
+ __ j(not_equal, &not_found);
2638
+
2639
+ __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1));
2640
+ __ jmp(&done);
2641
+
2642
+ __ bind(&not_found);
2643
+ // Call runtime to perform the lookup.
2644
+ __ push(cache);
2645
+ __ push(key);
2646
+ __ CallRuntime(Runtime::kGetFromCache, 2);
2647
+
2648
+ __ bind(&done);
2649
+ Apply(context_, eax);
2650
+ }
2651
+
2652
+
2653
+ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2654
+ Handle<String> name = expr->name();
2655
+ if (name->length() > 0 && name->Get(0) == '_') {
2656
+ Comment cmnt(masm_, "[ InlineRuntimeCall");
2657
+ EmitInlineRuntimeCall(expr);
2658
+ return;
2659
+ }
2660
+
2661
+ Comment cmnt(masm_, "[ CallRuntime");
2662
+ ZoneList<Expression*>* args = expr->arguments();
2663
+
2664
+ if (expr->is_jsruntime()) {
2665
+ // Prepare for calling JS runtime function.
2666
+ __ mov(eax, CodeGenerator::GlobalObject());
2667
+ __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
2668
+ }
2669
+
2670
+ // Push the arguments ("left-to-right").
2671
+ int arg_count = args->length();
2672
+ for (int i = 0; i < arg_count; i++) {
2673
+ VisitForValue(args->at(i), kStack);
2674
+ }
2675
+
2676
+ if (expr->is_jsruntime()) {
2677
+ // Call the JS runtime function via a call IC.
2678
+ __ Set(ecx, Immediate(expr->name()));
2679
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2680
+ Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
2681
+ __ call(ic, RelocInfo::CODE_TARGET);
2682
+ // Restore context register.
2683
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2684
+ } else {
2685
+ // Call the C runtime function.
2686
+ __ CallRuntime(expr->function(), arg_count);
2687
+ }
2688
+ Apply(context_, eax);
2689
+ }
2690
+
2691
+
2692
+ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2693
+ switch (expr->op()) {
2694
+ case Token::DELETE: {
2695
+ Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2696
+ Property* prop = expr->expression()->AsProperty();
2697
+ Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2698
+ if (prop == NULL && var == NULL) {
2699
+ // Result of deleting non-property, non-variable reference is true.
2700
+ // The subexpression may have side effects.
2701
+ VisitForEffect(expr->expression());
2702
+ Apply(context_, true);
2703
+ } else if (var != NULL &&
2704
+ !var->is_global() &&
2705
+ var->slot() != NULL &&
2706
+ var->slot()->type() != Slot::LOOKUP) {
2707
+ // Result of deleting non-global, non-dynamic variables is false.
2708
+ // The subexpression does not have side effects.
2709
+ Apply(context_, false);
2710
+ } else {
2711
+ // Property or variable reference. Call the delete builtin with
2712
+ // object and property name as arguments.
2713
+ if (prop != NULL) {
2714
+ VisitForValue(prop->obj(), kStack);
2715
+ VisitForValue(prop->key(), kStack);
2716
+ } else if (var->is_global()) {
2717
+ __ push(CodeGenerator::GlobalObject());
2718
+ __ push(Immediate(var->name()));
2719
+ } else {
2720
+ // Non-global variable. Call the runtime to look up the context
2721
+ // where the variable was introduced.
2722
+ __ push(context_register());
2723
+ __ push(Immediate(var->name()));
2724
+ __ CallRuntime(Runtime::kLookupContext, 2);
2725
+ __ push(eax);
2726
+ __ push(Immediate(var->name()));
2727
+ }
2728
+ __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
2729
+ Apply(context_, eax);
2730
+ }
2731
+ break;
2732
+ }
2733
+
2734
+ case Token::VOID: {
2735
+ Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2736
+ VisitForEffect(expr->expression());
2737
+ switch (context_) {
2738
+ case Expression::kUninitialized:
2739
+ UNREACHABLE();
2740
+ break;
2741
+ case Expression::kEffect:
2742
+ break;
2743
+ case Expression::kValue:
2744
+ switch (location_) {
2745
+ case kAccumulator:
2746
+ __ mov(result_register(), Factory::undefined_value());
2747
+ break;
2748
+ case kStack:
1499
2749
  __ push(Immediate(Factory::undefined_value()));
1500
2750
  break;
1501
2751
  }
@@ -1521,33 +2771,15 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1521
2771
 
1522
2772
  case Token::NOT: {
1523
2773
  Comment cmnt(masm_, "[ UnaryOperation (NOT)");
1524
- Label materialize_true, materialize_false, done;
1525
- // Initially assume a pure test context. Notice that the labels are
1526
- // swapped.
1527
- Label* if_true = false_label_;
1528
- Label* if_false = true_label_;
1529
- switch (context_) {
1530
- case Expression::kUninitialized:
1531
- UNREACHABLE();
1532
- break;
1533
- case Expression::kEffect:
1534
- if_true = &done;
1535
- if_false = &done;
1536
- break;
1537
- case Expression::kValue:
1538
- if_true = &materialize_false;
1539
- if_false = &materialize_true;
1540
- break;
1541
- case Expression::kTest:
1542
- break;
1543
- case Expression::kValueTest:
1544
- if_false = &materialize_true;
1545
- break;
1546
- case Expression::kTestValue:
1547
- if_true = &materialize_false;
1548
- break;
1549
- }
2774
+ Label materialize_true, materialize_false;
2775
+ Label* if_true = NULL;
2776
+ Label* if_false = NULL;
2777
+
2778
+ // Notice that the labels are swapped.
2779
+ PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2780
+
1550
2781
  VisitForControl(expr->expression(), if_true, if_false);
2782
+
1551
2783
  Apply(context_, if_false, if_true); // Labels swapped.
1552
2784
  break;
1553
2785
  }
@@ -1598,9 +2830,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1598
2830
 
1599
2831
  case Token::SUB: {
1600
2832
  Comment cmt(masm_, "[ UnaryOperation (SUB)");
1601
- bool overwrite =
2833
+ bool can_overwrite =
1602
2834
  (expr->expression()->AsBinaryOperation() != NULL &&
1603
2835
  expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2836
+ UnaryOverwriteMode overwrite =
2837
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
1604
2838
  GenericUnaryOpStub stub(Token::SUB, overwrite);
1605
2839
  // GenericUnaryOpStub expects the argument to be in the
1606
2840
  // accumulator register eax.
@@ -1612,9 +2846,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1612
2846
 
1613
2847
  case Token::BIT_NOT: {
1614
2848
  Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
1615
- bool overwrite =
2849
+ bool can_overwrite =
1616
2850
  (expr->expression()->AsBinaryOperation() != NULL &&
1617
2851
  expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2852
+ UnaryOverwriteMode overwrite =
2853
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
1618
2854
  GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
1619
2855
  // GenericUnaryOpStub expects the argument to be in the
1620
2856
  // accumulator register eax.
@@ -1643,6 +2879,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1643
2879
 
1644
2880
  void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1645
2881
  Comment cmnt(masm_, "[ CountOperation");
2882
+ // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
2883
+ // as the left-hand side.
2884
+ if (!expr->expression()->IsValidLeftHandSide()) {
2885
+ VisitForEffect(expr->expression());
2886
+ return;
2887
+ }
1646
2888
 
1647
2889
  // Expression can only be a property, a global or a (parameter or local)
1648
2890
  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
@@ -1664,7 +2906,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1664
2906
  EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1665
2907
  Expression::kValue);
1666
2908
  location_ = saved_location;
1667
- } else {
2909
+ } else {
1668
2910
  // Reserve space for result of postfix operation.
1669
2911
  if (expr->is_postfix() && context_ != Expression::kEffect) {
1670
2912
  __ push(Immediate(Smi::FromInt(0)));
@@ -1754,7 +2996,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1754
2996
  switch (assign_type) {
1755
2997
  case VARIABLE:
1756
2998
  if (expr->is_postfix()) {
2999
+ // Perform the assignment as if via '='.
1757
3000
  EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3001
+ Token::ASSIGN,
1758
3002
  Expression::kEffect);
1759
3003
  // For all contexts except kEffect: We have the result on
1760
3004
  // top of the stack.
@@ -1762,7 +3006,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1762
3006
  ApplyTOS(context_);
1763
3007
  }
1764
3008
  } else {
3009
+ // Perform the assignment as if via '='.
1765
3010
  EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3011
+ Token::ASSIGN,
1766
3012
  context_);
1767
3013
  }
1768
3014
  break;
@@ -1840,36 +3086,41 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1840
3086
  }
1841
3087
 
1842
3088
 
3089
+ void FullCodeGenerator::EmitNullCompare(bool strict,
3090
+ Register obj,
3091
+ Register null_const,
3092
+ Label* if_true,
3093
+ Label* if_false,
3094
+ Register scratch) {
3095
+ __ cmp(obj, Operand(null_const));
3096
+ if (strict) {
3097
+ __ j(equal, if_true);
3098
+ } else {
3099
+ __ j(equal, if_true);
3100
+ __ cmp(obj, Factory::undefined_value());
3101
+ __ j(equal, if_true);
3102
+ __ test(obj, Immediate(kSmiTagMask));
3103
+ __ j(zero, if_false);
3104
+ // It can be an undetectable object.
3105
+ __ mov(scratch, FieldOperand(obj, HeapObject::kMapOffset));
3106
+ __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
3107
+ __ test(scratch, Immediate(1 << Map::kIsUndetectable));
3108
+ __ j(not_zero, if_true);
3109
+ }
3110
+ __ jmp(if_false);
3111
+ }
3112
+
3113
+
1843
3114
  void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1844
3115
  Comment cmnt(masm_, "[ CompareOperation");
1845
3116
 
1846
3117
  // Always perform the comparison for its control flow. Pack the result
1847
3118
  // into the expression's context after the comparison is performed.
1848
- Label materialize_true, materialize_false, done;
1849
- // Initially assume we are in a test context.
1850
- Label* if_true = true_label_;
1851
- Label* if_false = false_label_;
1852
- switch (context_) {
1853
- case Expression::kUninitialized:
1854
- UNREACHABLE();
1855
- break;
1856
- case Expression::kEffect:
1857
- if_true = &done;
1858
- if_false = &done;
1859
- break;
1860
- case Expression::kValue:
1861
- if_true = &materialize_true;
1862
- if_false = &materialize_false;
1863
- break;
1864
- case Expression::kTest:
1865
- break;
1866
- case Expression::kValueTest:
1867
- if_true = &materialize_true;
1868
- break;
1869
- case Expression::kTestValue:
1870
- if_false = &materialize_false;
1871
- break;
1872
- }
3119
+
3120
+ Label materialize_true, materialize_false;
3121
+ Label* if_true = NULL;
3122
+ Label* if_false = NULL;
3123
+ PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1873
3124
 
1874
3125
  VisitForValue(expr->left(), kStack);
1875
3126
  switch (expr->op()) {
@@ -1899,10 +3150,24 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1899
3150
  case Token::EQ_STRICT:
1900
3151
  strict = true;
1901
3152
  // Fall through
1902
- case Token::EQ:
3153
+ case Token::EQ: {
1903
3154
  cc = equal;
1904
3155
  __ pop(edx);
3156
+ // If either operand is constant null we do a fast compare
3157
+ // against null.
3158
+ Literal* right_literal = expr->right()->AsLiteral();
3159
+ Literal* left_literal = expr->left()->AsLiteral();
3160
+ if (right_literal != NULL && right_literal->handle()->IsNull()) {
3161
+ EmitNullCompare(strict, edx, eax, if_true, if_false, ecx);
3162
+ Apply(context_, if_true, if_false);
3163
+ return;
3164
+ } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
3165
+ EmitNullCompare(strict, eax, edx, if_true, if_false, ecx);
3166
+ Apply(context_, if_true, if_false);
3167
+ return;
3168
+ }
1905
3169
  break;
3170
+ }
1906
3171
  case Token::LT:
1907
3172
  cc = less;
1908
3173
  __ pop(edx);
@@ -2012,3 +3277,5 @@ void FullCodeGenerator::ExitFinallyBlock() {
2012
3277
  #undef __
2013
3278
 
2014
3279
  } } // namespace v8::internal
3280
+
3281
+ #endif // V8_TARGET_ARCH_IA32