libv8 3.3.10.4 → 3.5.10.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (538) hide show
  1. data/lib/libv8/scons/CHANGES.txt +24 -231
  2. data/lib/libv8/scons/LICENSE.txt +1 -1
  3. data/lib/libv8/scons/MANIFEST +0 -1
  4. data/lib/libv8/scons/PKG-INFO +1 -1
  5. data/lib/libv8/scons/README.txt +9 -9
  6. data/lib/libv8/scons/RELEASE.txt +75 -77
  7. data/lib/libv8/scons/engine/SCons/Action.py +6 -22
  8. data/lib/libv8/scons/engine/SCons/Builder.py +2 -2
  9. data/lib/libv8/scons/engine/SCons/CacheDir.py +2 -2
  10. data/lib/libv8/scons/engine/SCons/Debug.py +2 -2
  11. data/lib/libv8/scons/engine/SCons/Defaults.py +10 -24
  12. data/lib/libv8/scons/engine/SCons/Environment.py +19 -118
  13. data/lib/libv8/scons/engine/SCons/Errors.py +2 -2
  14. data/lib/libv8/scons/engine/SCons/Executor.py +2 -2
  15. data/lib/libv8/scons/engine/SCons/Job.py +2 -2
  16. data/lib/libv8/scons/engine/SCons/Memoize.py +2 -2
  17. data/lib/libv8/scons/engine/SCons/Node/Alias.py +2 -2
  18. data/lib/libv8/scons/engine/SCons/Node/FS.py +121 -281
  19. data/lib/libv8/scons/engine/SCons/Node/Python.py +2 -2
  20. data/lib/libv8/scons/engine/SCons/Node/__init__.py +5 -6
  21. data/lib/libv8/scons/engine/SCons/Options/BoolOption.py +2 -2
  22. data/lib/libv8/scons/engine/SCons/Options/EnumOption.py +2 -2
  23. data/lib/libv8/scons/engine/SCons/Options/ListOption.py +2 -2
  24. data/lib/libv8/scons/engine/SCons/Options/PackageOption.py +2 -2
  25. data/lib/libv8/scons/engine/SCons/Options/PathOption.py +2 -2
  26. data/lib/libv8/scons/engine/SCons/Options/__init__.py +2 -2
  27. data/lib/libv8/scons/engine/SCons/PathList.py +2 -2
  28. data/lib/libv8/scons/engine/SCons/Platform/__init__.py +2 -2
  29. data/lib/libv8/scons/engine/SCons/Platform/aix.py +2 -2
  30. data/lib/libv8/scons/engine/SCons/Platform/cygwin.py +2 -2
  31. data/lib/libv8/scons/engine/SCons/Platform/darwin.py +3 -27
  32. data/lib/libv8/scons/engine/SCons/Platform/hpux.py +2 -2
  33. data/lib/libv8/scons/engine/SCons/Platform/irix.py +2 -2
  34. data/lib/libv8/scons/engine/SCons/Platform/os2.py +2 -2
  35. data/lib/libv8/scons/engine/SCons/Platform/posix.py +2 -2
  36. data/lib/libv8/scons/engine/SCons/Platform/sunos.py +2 -2
  37. data/lib/libv8/scons/engine/SCons/Platform/win32.py +2 -2
  38. data/lib/libv8/scons/engine/SCons/SConf.py +2 -2
  39. data/lib/libv8/scons/engine/SCons/SConsign.py +3 -9
  40. data/lib/libv8/scons/engine/SCons/Scanner/C.py +2 -2
  41. data/lib/libv8/scons/engine/SCons/Scanner/D.py +2 -2
  42. data/lib/libv8/scons/engine/SCons/Scanner/Dir.py +2 -2
  43. data/lib/libv8/scons/engine/SCons/Scanner/Fortran.py +2 -2
  44. data/lib/libv8/scons/engine/SCons/Scanner/IDL.py +2 -2
  45. data/lib/libv8/scons/engine/SCons/Scanner/LaTeX.py +2 -5
  46. data/lib/libv8/scons/engine/SCons/Scanner/Prog.py +2 -2
  47. data/lib/libv8/scons/engine/SCons/Scanner/RC.py +3 -3
  48. data/lib/libv8/scons/engine/SCons/Scanner/__init__.py +2 -2
  49. data/lib/libv8/scons/engine/SCons/Script/Interactive.py +2 -2
  50. data/lib/libv8/scons/engine/SCons/Script/Main.py +11 -82
  51. data/lib/libv8/scons/engine/SCons/Script/SConsOptions.py +5 -5
  52. data/lib/libv8/scons/engine/SCons/Script/SConscript.py +2 -2
  53. data/lib/libv8/scons/engine/SCons/Script/__init__.py +2 -2
  54. data/lib/libv8/scons/engine/SCons/Sig.py +2 -2
  55. data/lib/libv8/scons/engine/SCons/Subst.py +2 -2
  56. data/lib/libv8/scons/engine/SCons/Taskmaster.py +2 -10
  57. data/lib/libv8/scons/engine/SCons/Tool/386asm.py +2 -2
  58. data/lib/libv8/scons/engine/SCons/Tool/BitKeeper.py +2 -2
  59. data/lib/libv8/scons/engine/SCons/Tool/CVS.py +2 -2
  60. data/lib/libv8/scons/engine/SCons/Tool/FortranCommon.py +2 -19
  61. data/lib/libv8/scons/engine/SCons/Tool/JavaCommon.py +2 -2
  62. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/__init__.py +2 -2
  63. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/arch.py +2 -2
  64. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/common.py +2 -2
  65. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/netframework.py +2 -2
  66. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/sdk.py +2 -2
  67. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/vc.py +6 -9
  68. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/vs.py +2 -29
  69. data/lib/libv8/scons/engine/SCons/Tool/Perforce.py +2 -2
  70. data/lib/libv8/scons/engine/SCons/Tool/PharLapCommon.py +2 -2
  71. data/lib/libv8/scons/engine/SCons/Tool/RCS.py +2 -2
  72. data/lib/libv8/scons/engine/SCons/Tool/SCCS.py +2 -2
  73. data/lib/libv8/scons/engine/SCons/Tool/Subversion.py +2 -2
  74. data/lib/libv8/scons/engine/SCons/Tool/__init__.py +3 -3
  75. data/lib/libv8/scons/engine/SCons/Tool/aixc++.py +2 -2
  76. data/lib/libv8/scons/engine/SCons/Tool/aixcc.py +2 -2
  77. data/lib/libv8/scons/engine/SCons/Tool/aixf77.py +2 -2
  78. data/lib/libv8/scons/engine/SCons/Tool/aixlink.py +2 -2
  79. data/lib/libv8/scons/engine/SCons/Tool/applelink.py +2 -2
  80. data/lib/libv8/scons/engine/SCons/Tool/ar.py +2 -2
  81. data/lib/libv8/scons/engine/SCons/Tool/as.py +2 -2
  82. data/lib/libv8/scons/engine/SCons/Tool/bcc32.py +2 -2
  83. data/lib/libv8/scons/engine/SCons/Tool/c++.py +2 -2
  84. data/lib/libv8/scons/engine/SCons/Tool/cc.py +2 -2
  85. data/lib/libv8/scons/engine/SCons/Tool/cvf.py +2 -2
  86. data/lib/libv8/scons/engine/SCons/Tool/default.py +2 -2
  87. data/lib/libv8/scons/engine/SCons/Tool/dmd.py +7 -24
  88. data/lib/libv8/scons/engine/SCons/Tool/dvi.py +2 -2
  89. data/lib/libv8/scons/engine/SCons/Tool/dvipdf.py +2 -3
  90. data/lib/libv8/scons/engine/SCons/Tool/dvips.py +2 -3
  91. data/lib/libv8/scons/engine/SCons/Tool/f77.py +2 -2
  92. data/lib/libv8/scons/engine/SCons/Tool/f90.py +2 -2
  93. data/lib/libv8/scons/engine/SCons/Tool/f95.py +2 -2
  94. data/lib/libv8/scons/engine/SCons/Tool/filesystem.py +2 -2
  95. data/lib/libv8/scons/engine/SCons/Tool/fortran.py +2 -2
  96. data/lib/libv8/scons/engine/SCons/Tool/g++.py +2 -2
  97. data/lib/libv8/scons/engine/SCons/Tool/g77.py +2 -2
  98. data/lib/libv8/scons/engine/SCons/Tool/gas.py +2 -2
  99. data/lib/libv8/scons/engine/SCons/Tool/gcc.py +2 -2
  100. data/lib/libv8/scons/engine/SCons/Tool/gfortran.py +3 -3
  101. data/lib/libv8/scons/engine/SCons/Tool/gnulink.py +3 -2
  102. data/lib/libv8/scons/engine/SCons/Tool/gs.py +2 -2
  103. data/lib/libv8/scons/engine/SCons/Tool/hpc++.py +2 -2
  104. data/lib/libv8/scons/engine/SCons/Tool/hpcc.py +2 -2
  105. data/lib/libv8/scons/engine/SCons/Tool/hplink.py +2 -2
  106. data/lib/libv8/scons/engine/SCons/Tool/icc.py +2 -2
  107. data/lib/libv8/scons/engine/SCons/Tool/icl.py +2 -2
  108. data/lib/libv8/scons/engine/SCons/Tool/ifl.py +2 -2
  109. data/lib/libv8/scons/engine/SCons/Tool/ifort.py +2 -2
  110. data/lib/libv8/scons/engine/SCons/Tool/ilink.py +2 -2
  111. data/lib/libv8/scons/engine/SCons/Tool/ilink32.py +2 -2
  112. data/lib/libv8/scons/engine/SCons/Tool/install.py +3 -57
  113. data/lib/libv8/scons/engine/SCons/Tool/intelc.py +25 -65
  114. data/lib/libv8/scons/engine/SCons/Tool/ipkg.py +2 -2
  115. data/lib/libv8/scons/engine/SCons/Tool/jar.py +3 -9
  116. data/lib/libv8/scons/engine/SCons/Tool/javac.py +2 -2
  117. data/lib/libv8/scons/engine/SCons/Tool/javah.py +2 -2
  118. data/lib/libv8/scons/engine/SCons/Tool/latex.py +2 -3
  119. data/lib/libv8/scons/engine/SCons/Tool/lex.py +2 -2
  120. data/lib/libv8/scons/engine/SCons/Tool/link.py +5 -6
  121. data/lib/libv8/scons/engine/SCons/Tool/linkloc.py +2 -2
  122. data/lib/libv8/scons/engine/SCons/Tool/m4.py +2 -2
  123. data/lib/libv8/scons/engine/SCons/Tool/masm.py +2 -2
  124. data/lib/libv8/scons/engine/SCons/Tool/midl.py +2 -2
  125. data/lib/libv8/scons/engine/SCons/Tool/mingw.py +10 -31
  126. data/lib/libv8/scons/engine/SCons/Tool/mslib.py +2 -2
  127. data/lib/libv8/scons/engine/SCons/Tool/mslink.py +9 -61
  128. data/lib/libv8/scons/engine/SCons/Tool/mssdk.py +2 -2
  129. data/lib/libv8/scons/engine/SCons/Tool/msvc.py +11 -21
  130. data/lib/libv8/scons/engine/SCons/Tool/msvs.py +59 -477
  131. data/lib/libv8/scons/engine/SCons/Tool/mwcc.py +2 -2
  132. data/lib/libv8/scons/engine/SCons/Tool/mwld.py +2 -2
  133. data/lib/libv8/scons/engine/SCons/Tool/nasm.py +2 -2
  134. data/lib/libv8/scons/engine/SCons/Tool/packaging/__init__.py +2 -2
  135. data/lib/libv8/scons/engine/SCons/Tool/packaging/ipk.py +2 -2
  136. data/lib/libv8/scons/engine/SCons/Tool/packaging/msi.py +2 -2
  137. data/lib/libv8/scons/engine/SCons/Tool/packaging/rpm.py +2 -2
  138. data/lib/libv8/scons/engine/SCons/Tool/packaging/src_tarbz2.py +2 -2
  139. data/lib/libv8/scons/engine/SCons/Tool/packaging/src_targz.py +2 -2
  140. data/lib/libv8/scons/engine/SCons/Tool/packaging/src_zip.py +2 -2
  141. data/lib/libv8/scons/engine/SCons/Tool/packaging/tarbz2.py +2 -2
  142. data/lib/libv8/scons/engine/SCons/Tool/packaging/targz.py +2 -2
  143. data/lib/libv8/scons/engine/SCons/Tool/packaging/zip.py +2 -2
  144. data/lib/libv8/scons/engine/SCons/Tool/pdf.py +2 -2
  145. data/lib/libv8/scons/engine/SCons/Tool/pdflatex.py +2 -3
  146. data/lib/libv8/scons/engine/SCons/Tool/pdftex.py +2 -3
  147. data/lib/libv8/scons/engine/SCons/Tool/qt.py +2 -2
  148. data/lib/libv8/scons/engine/SCons/Tool/rmic.py +3 -9
  149. data/lib/libv8/scons/engine/SCons/Tool/rpcgen.py +2 -2
  150. data/lib/libv8/scons/engine/SCons/Tool/rpm.py +2 -2
  151. data/lib/libv8/scons/engine/SCons/Tool/sgiar.py +2 -2
  152. data/lib/libv8/scons/engine/SCons/Tool/sgic++.py +2 -2
  153. data/lib/libv8/scons/engine/SCons/Tool/sgicc.py +2 -2
  154. data/lib/libv8/scons/engine/SCons/Tool/sgilink.py +3 -2
  155. data/lib/libv8/scons/engine/SCons/Tool/sunar.py +2 -2
  156. data/lib/libv8/scons/engine/SCons/Tool/sunc++.py +2 -2
  157. data/lib/libv8/scons/engine/SCons/Tool/suncc.py +2 -2
  158. data/lib/libv8/scons/engine/SCons/Tool/sunf77.py +2 -2
  159. data/lib/libv8/scons/engine/SCons/Tool/sunf90.py +2 -2
  160. data/lib/libv8/scons/engine/SCons/Tool/sunf95.py +2 -2
  161. data/lib/libv8/scons/engine/SCons/Tool/sunlink.py +3 -2
  162. data/lib/libv8/scons/engine/SCons/Tool/swig.py +5 -6
  163. data/lib/libv8/scons/engine/SCons/Tool/tar.py +2 -2
  164. data/lib/libv8/scons/engine/SCons/Tool/tex.py +43 -96
  165. data/lib/libv8/scons/engine/SCons/Tool/textfile.py +2 -2
  166. data/lib/libv8/scons/engine/SCons/Tool/tlib.py +2 -2
  167. data/lib/libv8/scons/engine/SCons/Tool/wix.py +2 -2
  168. data/lib/libv8/scons/engine/SCons/Tool/yacc.py +2 -12
  169. data/lib/libv8/scons/engine/SCons/Tool/zip.py +2 -2
  170. data/lib/libv8/scons/engine/SCons/Util.py +3 -3
  171. data/lib/libv8/scons/engine/SCons/Variables/BoolVariable.py +2 -2
  172. data/lib/libv8/scons/engine/SCons/Variables/EnumVariable.py +3 -3
  173. data/lib/libv8/scons/engine/SCons/Variables/ListVariable.py +2 -2
  174. data/lib/libv8/scons/engine/SCons/Variables/PackageVariable.py +2 -2
  175. data/lib/libv8/scons/engine/SCons/Variables/PathVariable.py +2 -2
  176. data/lib/libv8/scons/engine/SCons/Variables/__init__.py +2 -2
  177. data/lib/libv8/scons/engine/SCons/Warnings.py +2 -2
  178. data/lib/libv8/scons/engine/SCons/__init__.py +6 -6
  179. data/lib/libv8/scons/engine/SCons/compat/__init__.py +2 -2
  180. data/lib/libv8/scons/engine/SCons/compat/_scons_builtins.py +2 -2
  181. data/lib/libv8/scons/engine/SCons/compat/_scons_collections.py +2 -2
  182. data/lib/libv8/scons/engine/SCons/compat/_scons_dbm.py +2 -2
  183. data/lib/libv8/scons/engine/SCons/compat/_scons_hashlib.py +2 -2
  184. data/lib/libv8/scons/engine/SCons/compat/_scons_io.py +2 -2
  185. data/lib/libv8/scons/engine/SCons/cpp.py +2 -2
  186. data/lib/libv8/scons/engine/SCons/dblite.py +1 -4
  187. data/lib/libv8/scons/engine/SCons/exitfuncs.py +2 -2
  188. data/lib/libv8/scons/scons-time.1 +3 -3
  189. data/lib/libv8/scons/scons.1 +1164 -1170
  190. data/lib/libv8/scons/sconsign.1 +3 -3
  191. data/lib/libv8/scons/script/scons +22 -22
  192. data/lib/libv8/scons/script/scons-time +2 -2
  193. data/lib/libv8/scons/script/scons.bat +4 -7
  194. data/lib/libv8/scons/script/sconsign +20 -21
  195. data/lib/libv8/scons/setup.cfg +1 -0
  196. data/lib/libv8/scons/setup.py +40 -38
  197. data/lib/libv8/v8/.gitignore +1 -1
  198. data/lib/libv8/v8/AUTHORS +2 -0
  199. data/lib/libv8/v8/ChangeLog +387 -0
  200. data/lib/libv8/v8/Makefile +171 -0
  201. data/lib/libv8/v8/SConstruct +124 -51
  202. data/lib/libv8/v8/build/README.txt +31 -14
  203. data/lib/libv8/v8/build/all.gyp +11 -4
  204. data/lib/libv8/v8/build/armu.gypi +6 -2
  205. data/lib/libv8/v8/build/common.gypi +240 -94
  206. data/lib/libv8/v8/build/gyp_v8 +32 -4
  207. data/lib/libv8/v8/build/standalone.gypi +200 -0
  208. data/lib/libv8/v8/include/v8-debug.h +0 -0
  209. data/lib/libv8/v8/include/v8-profiler.h +8 -11
  210. data/lib/libv8/v8/include/v8.h +191 -108
  211. data/lib/libv8/v8/preparser/SConscript +2 -2
  212. data/lib/libv8/v8/preparser/preparser-process.cc +3 -3
  213. data/lib/libv8/v8/preparser/preparser.gyp +42 -0
  214. data/lib/libv8/v8/src/SConscript +33 -8
  215. data/lib/libv8/v8/src/accessors.cc +77 -43
  216. data/lib/libv8/v8/src/api.cc +393 -191
  217. data/lib/libv8/v8/src/api.h +4 -8
  218. data/lib/libv8/v8/src/apinatives.js +15 -3
  219. data/lib/libv8/v8/src/arguments.h +8 -0
  220. data/lib/libv8/v8/src/arm/assembler-arm.cc +120 -120
  221. data/lib/libv8/v8/src/arm/assembler-arm.h +92 -43
  222. data/lib/libv8/v8/src/arm/builtins-arm.cc +32 -39
  223. data/lib/libv8/v8/src/arm/code-stubs-arm.cc +572 -351
  224. data/lib/libv8/v8/src/arm/code-stubs-arm.h +8 -77
  225. data/lib/libv8/v8/src/arm/codegen-arm.h +0 -2
  226. data/lib/libv8/v8/src/arm/deoptimizer-arm.cc +50 -30
  227. data/lib/libv8/v8/src/arm/disasm-arm.cc +1 -1
  228. data/lib/libv8/v8/src/arm/frames-arm.h +9 -5
  229. data/lib/libv8/v8/src/arm/full-codegen-arm.cc +331 -432
  230. data/lib/libv8/v8/src/arm/ic-arm.cc +192 -124
  231. data/lib/libv8/v8/src/arm/lithium-arm.cc +216 -232
  232. data/lib/libv8/v8/src/arm/lithium-arm.h +106 -259
  233. data/lib/libv8/v8/src/arm/lithium-codegen-arm.cc +633 -642
  234. data/lib/libv8/v8/src/arm/lithium-codegen-arm.h +4 -4
  235. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.cc +1 -3
  236. data/lib/libv8/v8/src/arm/macro-assembler-arm.cc +260 -185
  237. data/lib/libv8/v8/src/arm/macro-assembler-arm.h +45 -25
  238. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.cc +25 -13
  239. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.h +3 -0
  240. data/lib/libv8/v8/src/arm/stub-cache-arm.cc +413 -226
  241. data/lib/libv8/v8/src/array.js +38 -18
  242. data/lib/libv8/v8/src/assembler.cc +12 -5
  243. data/lib/libv8/v8/src/assembler.h +15 -9
  244. data/lib/libv8/v8/src/ast-inl.h +34 -25
  245. data/lib/libv8/v8/src/ast.cc +141 -72
  246. data/lib/libv8/v8/src/ast.h +255 -181
  247. data/lib/libv8/v8/src/bignum.cc +3 -4
  248. data/lib/libv8/v8/src/bootstrapper.cc +55 -11
  249. data/lib/libv8/v8/src/bootstrapper.h +3 -2
  250. data/lib/libv8/v8/src/builtins.cc +8 -2
  251. data/lib/libv8/v8/src/builtins.h +4 -0
  252. data/lib/libv8/v8/src/cached-powers.cc +8 -4
  253. data/lib/libv8/v8/src/checks.h +3 -3
  254. data/lib/libv8/v8/src/code-stubs.cc +173 -28
  255. data/lib/libv8/v8/src/code-stubs.h +104 -148
  256. data/lib/libv8/v8/src/codegen.cc +8 -8
  257. data/lib/libv8/v8/src/compilation-cache.cc +2 -47
  258. data/lib/libv8/v8/src/compilation-cache.h +0 -10
  259. data/lib/libv8/v8/src/compiler.cc +27 -16
  260. data/lib/libv8/v8/src/compiler.h +13 -18
  261. data/lib/libv8/v8/src/contexts.cc +107 -72
  262. data/lib/libv8/v8/src/contexts.h +70 -34
  263. data/lib/libv8/v8/src/conversions-inl.h +572 -14
  264. data/lib/libv8/v8/src/conversions.cc +9 -707
  265. data/lib/libv8/v8/src/conversions.h +23 -12
  266. data/lib/libv8/v8/src/cpu-profiler-inl.h +2 -19
  267. data/lib/libv8/v8/src/cpu-profiler.cc +4 -21
  268. data/lib/libv8/v8/src/cpu-profiler.h +8 -17
  269. data/lib/libv8/v8/src/d8-debug.cc +5 -3
  270. data/lib/libv8/v8/src/d8-debug.h +6 -7
  271. data/lib/libv8/v8/src/d8-posix.cc +1 -10
  272. data/lib/libv8/v8/src/d8.cc +721 -219
  273. data/lib/libv8/v8/src/d8.gyp +37 -12
  274. data/lib/libv8/v8/src/d8.h +141 -19
  275. data/lib/libv8/v8/src/d8.js +17 -8
  276. data/lib/libv8/v8/src/date.js +16 -5
  277. data/lib/libv8/v8/src/dateparser-inl.h +242 -39
  278. data/lib/libv8/v8/src/dateparser.cc +38 -4
  279. data/lib/libv8/v8/src/dateparser.h +170 -28
  280. data/lib/libv8/v8/src/debug-agent.cc +5 -3
  281. data/lib/libv8/v8/src/debug-agent.h +11 -7
  282. data/lib/libv8/v8/src/debug-debugger.js +65 -34
  283. data/lib/libv8/v8/src/debug.cc +30 -60
  284. data/lib/libv8/v8/src/debug.h +5 -3
  285. data/lib/libv8/v8/src/deoptimizer.cc +227 -10
  286. data/lib/libv8/v8/src/deoptimizer.h +133 -9
  287. data/lib/libv8/v8/src/disassembler.cc +22 -14
  288. data/lib/libv8/v8/src/diy-fp.cc +4 -3
  289. data/lib/libv8/v8/src/diy-fp.h +3 -3
  290. data/lib/libv8/v8/src/elements.cc +634 -0
  291. data/lib/libv8/v8/src/elements.h +95 -0
  292. data/lib/libv8/v8/src/execution.cc +5 -21
  293. data/lib/libv8/v8/src/extensions/experimental/break-iterator.cc +3 -1
  294. data/lib/libv8/v8/src/extensions/experimental/break-iterator.h +1 -1
  295. data/lib/libv8/v8/src/extensions/experimental/collator.cc +6 -2
  296. data/lib/libv8/v8/src/extensions/experimental/collator.h +1 -2
  297. data/lib/libv8/v8/src/extensions/experimental/datetime-format.cc +384 -0
  298. data/lib/libv8/v8/src/extensions/experimental/datetime-format.h +83 -0
  299. data/lib/libv8/v8/src/extensions/experimental/experimental.gyp +18 -7
  300. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.cc +12 -16
  301. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.h +1 -1
  302. data/lib/libv8/v8/src/extensions/experimental/i18n-js2c.py +126 -0
  303. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.cc +3 -4
  304. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.h +1 -1
  305. data/lib/libv8/v8/src/{shell.h → extensions/experimental/i18n-natives.h} +8 -20
  306. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.cc +45 -1
  307. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.h +21 -1
  308. data/lib/libv8/v8/src/extensions/experimental/i18n.js +211 -11
  309. data/lib/libv8/v8/src/extensions/experimental/language-matcher.cc +4 -3
  310. data/lib/libv8/v8/src/extensions/experimental/language-matcher.h +1 -1
  311. data/lib/libv8/v8/src/extensions/experimental/number-format.cc +374 -0
  312. data/lib/libv8/v8/src/extensions/experimental/number-format.h +71 -0
  313. data/lib/libv8/v8/src/factory.cc +89 -18
  314. data/lib/libv8/v8/src/factory.h +36 -8
  315. data/lib/libv8/v8/src/flag-definitions.h +11 -44
  316. data/lib/libv8/v8/src/frames-inl.h +8 -1
  317. data/lib/libv8/v8/src/frames.cc +39 -3
  318. data/lib/libv8/v8/src/frames.h +10 -3
  319. data/lib/libv8/v8/src/full-codegen.cc +311 -293
  320. data/lib/libv8/v8/src/full-codegen.h +183 -143
  321. data/lib/libv8/v8/src/func-name-inferrer.cc +29 -15
  322. data/lib/libv8/v8/src/func-name-inferrer.h +19 -9
  323. data/lib/libv8/v8/src/gdb-jit.cc +658 -55
  324. data/lib/libv8/v8/src/gdb-jit.h +6 -2
  325. data/lib/libv8/v8/src/global-handles.cc +368 -312
  326. data/lib/libv8/v8/src/global-handles.h +29 -36
  327. data/lib/libv8/v8/src/globals.h +3 -1
  328. data/lib/libv8/v8/src/handles.cc +43 -69
  329. data/lib/libv8/v8/src/handles.h +21 -16
  330. data/lib/libv8/v8/src/heap-inl.h +11 -13
  331. data/lib/libv8/v8/src/heap-profiler.cc +0 -999
  332. data/lib/libv8/v8/src/heap-profiler.h +0 -303
  333. data/lib/libv8/v8/src/heap.cc +366 -141
  334. data/lib/libv8/v8/src/heap.h +87 -26
  335. data/lib/libv8/v8/src/hydrogen-instructions.cc +192 -81
  336. data/lib/libv8/v8/src/hydrogen-instructions.h +711 -482
  337. data/lib/libv8/v8/src/hydrogen.cc +1146 -629
  338. data/lib/libv8/v8/src/hydrogen.h +100 -64
  339. data/lib/libv8/v8/src/ia32/assembler-ia32.cc +19 -0
  340. data/lib/libv8/v8/src/ia32/assembler-ia32.h +15 -2
  341. data/lib/libv8/v8/src/ia32/builtins-ia32.cc +34 -39
  342. data/lib/libv8/v8/src/ia32/code-stubs-ia32.cc +675 -377
  343. data/lib/libv8/v8/src/ia32/code-stubs-ia32.h +8 -69
  344. data/lib/libv8/v8/src/ia32/codegen-ia32.cc +1 -0
  345. data/lib/libv8/v8/src/ia32/codegen-ia32.h +0 -2
  346. data/lib/libv8/v8/src/ia32/cpu-ia32.cc +3 -2
  347. data/lib/libv8/v8/src/ia32/deoptimizer-ia32.cc +28 -3
  348. data/lib/libv8/v8/src/ia32/disasm-ia32.cc +21 -10
  349. data/lib/libv8/v8/src/ia32/frames-ia32.h +6 -5
  350. data/lib/libv8/v8/src/ia32/full-codegen-ia32.cc +459 -465
  351. data/lib/libv8/v8/src/ia32/ic-ia32.cc +196 -147
  352. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.cc +575 -650
  353. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.h +19 -21
  354. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.cc +7 -2
  355. data/lib/libv8/v8/src/ia32/lithium-ia32.cc +261 -256
  356. data/lib/libv8/v8/src/ia32/lithium-ia32.h +234 -335
  357. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.cc +224 -67
  358. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.h +63 -19
  359. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.cc +22 -8
  360. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.h +3 -0
  361. data/lib/libv8/v8/src/ia32/stub-cache-ia32.cc +380 -239
  362. data/lib/libv8/v8/src/ic.cc +198 -234
  363. data/lib/libv8/v8/src/ic.h +32 -30
  364. data/lib/libv8/v8/src/interpreter-irregexp.cc +6 -4
  365. data/lib/libv8/v8/src/isolate.cc +112 -95
  366. data/lib/libv8/v8/src/isolate.h +55 -71
  367. data/lib/libv8/v8/src/json-parser.h +486 -48
  368. data/lib/libv8/v8/src/json.js +28 -23
  369. data/lib/libv8/v8/src/jsregexp.cc +163 -208
  370. data/lib/libv8/v8/src/jsregexp.h +0 -1
  371. data/lib/libv8/v8/src/lithium-allocator-inl.h +29 -27
  372. data/lib/libv8/v8/src/lithium-allocator.cc +22 -17
  373. data/lib/libv8/v8/src/lithium-allocator.h +8 -8
  374. data/lib/libv8/v8/src/lithium.cc +16 -11
  375. data/lib/libv8/v8/src/lithium.h +31 -34
  376. data/lib/libv8/v8/src/liveedit.cc +111 -15
  377. data/lib/libv8/v8/src/liveedit.h +3 -4
  378. data/lib/libv8/v8/src/liveobjectlist.cc +116 -80
  379. data/lib/libv8/v8/src/liveobjectlist.h +2 -2
  380. data/lib/libv8/v8/src/log-inl.h +0 -4
  381. data/lib/libv8/v8/src/log-utils.cc +25 -143
  382. data/lib/libv8/v8/src/log-utils.h +13 -92
  383. data/lib/libv8/v8/src/log.cc +26 -249
  384. data/lib/libv8/v8/src/log.h +6 -17
  385. data/lib/libv8/v8/src/macros.py +9 -6
  386. data/lib/libv8/v8/src/mark-compact.cc +276 -56
  387. data/lib/libv8/v8/src/mark-compact.h +20 -0
  388. data/lib/libv8/v8/src/messages.js +93 -39
  389. data/lib/libv8/v8/src/mips/assembler-mips-inl.h +9 -3
  390. data/lib/libv8/v8/src/mips/assembler-mips.cc +297 -189
  391. data/lib/libv8/v8/src/mips/assembler-mips.h +121 -54
  392. data/lib/libv8/v8/src/mips/builtins-mips.cc +23 -24
  393. data/lib/libv8/v8/src/mips/code-stubs-mips.cc +484 -263
  394. data/lib/libv8/v8/src/mips/code-stubs-mips.h +8 -83
  395. data/lib/libv8/v8/src/mips/codegen-mips.h +0 -2
  396. data/lib/libv8/v8/src/mips/constants-mips.h +37 -11
  397. data/lib/libv8/v8/src/mips/deoptimizer-mips.cc +6 -1
  398. data/lib/libv8/v8/src/mips/frames-mips.h +8 -7
  399. data/lib/libv8/v8/src/mips/full-codegen-mips.cc +258 -419
  400. data/lib/libv8/v8/src/mips/ic-mips.cc +181 -121
  401. data/lib/libv8/v8/src/mips/macro-assembler-mips.cc +640 -382
  402. data/lib/libv8/v8/src/mips/macro-assembler-mips.h +94 -89
  403. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.cc +23 -10
  404. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.h +6 -1
  405. data/lib/libv8/v8/src/mips/simulator-mips.cc +249 -49
  406. data/lib/libv8/v8/src/mips/simulator-mips.h +25 -1
  407. data/lib/libv8/v8/src/mips/stub-cache-mips.cc +373 -161
  408. data/lib/libv8/v8/src/mirror-debugger.js +55 -8
  409. data/lib/libv8/v8/src/misc-intrinsics.h +89 -0
  410. data/lib/libv8/v8/src/mksnapshot.cc +36 -4
  411. data/lib/libv8/v8/src/natives.h +5 -2
  412. data/lib/libv8/v8/src/objects-debug.cc +73 -6
  413. data/lib/libv8/v8/src/objects-inl.h +529 -164
  414. data/lib/libv8/v8/src/objects-printer.cc +67 -12
  415. data/lib/libv8/v8/src/objects-visiting.cc +13 -2
  416. data/lib/libv8/v8/src/objects-visiting.h +41 -1
  417. data/lib/libv8/v8/src/objects.cc +2200 -1177
  418. data/lib/libv8/v8/src/objects.h +912 -283
  419. data/lib/libv8/v8/src/parser.cc +566 -371
  420. data/lib/libv8/v8/src/parser.h +35 -33
  421. data/lib/libv8/v8/src/platform-cygwin.cc +10 -25
  422. data/lib/libv8/v8/src/platform-freebsd.cc +4 -29
  423. data/lib/libv8/v8/src/platform-linux.cc +60 -57
  424. data/lib/libv8/v8/src/platform-macos.cc +4 -27
  425. data/lib/libv8/v8/src/platform-nullos.cc +3 -16
  426. data/lib/libv8/v8/src/platform-openbsd.cc +247 -85
  427. data/lib/libv8/v8/src/platform-posix.cc +43 -1
  428. data/lib/libv8/v8/src/platform-solaris.cc +151 -112
  429. data/lib/libv8/v8/src/platform-tls.h +1 -1
  430. data/lib/libv8/v8/src/platform-win32.cc +65 -39
  431. data/lib/libv8/v8/src/platform.h +17 -14
  432. data/lib/libv8/v8/src/preparse-data-format.h +2 -2
  433. data/lib/libv8/v8/src/preparse-data.h +8 -2
  434. data/lib/libv8/v8/src/preparser-api.cc +2 -18
  435. data/lib/libv8/v8/src/preparser.cc +106 -65
  436. data/lib/libv8/v8/src/preparser.h +26 -5
  437. data/lib/libv8/v8/src/prettyprinter.cc +25 -43
  438. data/lib/libv8/v8/src/profile-generator-inl.h +0 -4
  439. data/lib/libv8/v8/src/profile-generator.cc +213 -34
  440. data/lib/libv8/v8/src/profile-generator.h +9 -9
  441. data/lib/libv8/v8/src/property.h +1 -0
  442. data/lib/libv8/v8/src/proxy.js +74 -4
  443. data/lib/libv8/v8/src/regexp-macro-assembler.cc +10 -6
  444. data/lib/libv8/v8/src/regexp.js +16 -11
  445. data/lib/libv8/v8/src/rewriter.cc +24 -133
  446. data/lib/libv8/v8/src/runtime-profiler.cc +27 -151
  447. data/lib/libv8/v8/src/runtime-profiler.h +5 -31
  448. data/lib/libv8/v8/src/runtime.cc +1450 -681
  449. data/lib/libv8/v8/src/runtime.h +47 -31
  450. data/lib/libv8/v8/src/runtime.js +2 -1
  451. data/lib/libv8/v8/src/scanner-base.cc +358 -220
  452. data/lib/libv8/v8/src/scanner-base.h +30 -138
  453. data/lib/libv8/v8/src/scanner.cc +0 -18
  454. data/lib/libv8/v8/src/scanner.h +0 -15
  455. data/lib/libv8/v8/src/scopeinfo.cc +3 -1
  456. data/lib/libv8/v8/src/scopeinfo.h +1 -6
  457. data/lib/libv8/v8/src/scopes.cc +243 -253
  458. data/lib/libv8/v8/src/scopes.h +58 -109
  459. data/lib/libv8/v8/src/serialize.cc +12 -54
  460. data/lib/libv8/v8/src/serialize.h +47 -0
  461. data/lib/libv8/v8/src/small-pointer-list.h +25 -0
  462. data/lib/libv8/v8/src/spaces-inl.h +4 -50
  463. data/lib/libv8/v8/src/spaces.cc +64 -131
  464. data/lib/libv8/v8/src/spaces.h +19 -70
  465. data/lib/libv8/v8/src/string-stream.cc +3 -1
  466. data/lib/libv8/v8/src/string.js +10 -6
  467. data/lib/libv8/v8/src/strtod.cc +7 -3
  468. data/lib/libv8/v8/src/stub-cache.cc +59 -129
  469. data/lib/libv8/v8/src/stub-cache.h +42 -54
  470. data/lib/libv8/v8/src/third_party/valgrind/valgrind.h +1447 -1339
  471. data/lib/libv8/v8/src/token.cc +4 -4
  472. data/lib/libv8/v8/src/token.h +6 -5
  473. data/lib/libv8/v8/src/type-info.cc +173 -129
  474. data/lib/libv8/v8/src/type-info.h +40 -22
  475. data/lib/libv8/v8/src/utils.cc +25 -304
  476. data/lib/libv8/v8/src/utils.h +118 -3
  477. data/lib/libv8/v8/src/v8-counters.h +3 -6
  478. data/lib/libv8/v8/src/v8.cc +34 -27
  479. data/lib/libv8/v8/src/v8.h +7 -7
  480. data/lib/libv8/v8/src/v8conversions.cc +129 -0
  481. data/lib/libv8/v8/src/v8conversions.h +60 -0
  482. data/lib/libv8/v8/src/v8globals.h +15 -6
  483. data/lib/libv8/v8/src/v8natives.js +300 -78
  484. data/lib/libv8/v8/src/v8threads.cc +14 -6
  485. data/lib/libv8/v8/src/v8threads.h +4 -1
  486. data/lib/libv8/v8/src/v8utils.cc +360 -0
  487. data/lib/libv8/v8/src/v8utils.h +17 -66
  488. data/lib/libv8/v8/src/variables.cc +7 -12
  489. data/lib/libv8/v8/src/variables.h +12 -10
  490. data/lib/libv8/v8/src/version.cc +2 -2
  491. data/lib/libv8/v8/src/vm-state-inl.h +0 -41
  492. data/lib/libv8/v8/src/vm-state.h +0 -11
  493. data/lib/libv8/v8/src/weakmap.js +103 -0
  494. data/lib/libv8/v8/src/x64/assembler-x64.h +6 -3
  495. data/lib/libv8/v8/src/x64/builtins-x64.cc +25 -22
  496. data/lib/libv8/v8/src/x64/code-stubs-x64.cc +523 -250
  497. data/lib/libv8/v8/src/x64/code-stubs-x64.h +8 -71
  498. data/lib/libv8/v8/src/x64/codegen-x64.cc +1 -0
  499. data/lib/libv8/v8/src/x64/codegen-x64.h +0 -2
  500. data/lib/libv8/v8/src/x64/cpu-x64.cc +2 -1
  501. data/lib/libv8/v8/src/x64/deoptimizer-x64.cc +40 -8
  502. data/lib/libv8/v8/src/x64/disasm-x64.cc +12 -10
  503. data/lib/libv8/v8/src/x64/frames-x64.h +7 -6
  504. data/lib/libv8/v8/src/x64/full-codegen-x64.cc +310 -415
  505. data/lib/libv8/v8/src/x64/ic-x64.cc +180 -117
  506. data/lib/libv8/v8/src/x64/lithium-codegen-x64.cc +411 -523
  507. data/lib/libv8/v8/src/x64/lithium-codegen-x64.h +11 -6
  508. data/lib/libv8/v8/src/x64/lithium-x64.cc +191 -216
  509. data/lib/libv8/v8/src/x64/lithium-x64.h +112 -263
  510. data/lib/libv8/v8/src/x64/macro-assembler-x64.cc +177 -61
  511. data/lib/libv8/v8/src/x64/macro-assembler-x64.h +23 -7
  512. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.cc +21 -9
  513. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.h +6 -0
  514. data/lib/libv8/v8/src/x64/stub-cache-x64.cc +273 -107
  515. data/lib/libv8/v8/src/zone.cc +31 -22
  516. data/lib/libv8/v8/src/zone.h +12 -6
  517. data/lib/libv8/v8/tools/codemap.js +8 -0
  518. data/lib/libv8/v8/tools/gcmole/Makefile +43 -0
  519. data/lib/libv8/v8/tools/gcmole/gcmole.lua +0 -2
  520. data/lib/libv8/v8/tools/gdb-v8-support.py +154 -0
  521. data/lib/libv8/v8/tools/grokdump.py +44 -35
  522. data/lib/libv8/v8/tools/gyp/v8.gyp +94 -248
  523. data/lib/libv8/v8/tools/js2c.py +83 -52
  524. data/lib/libv8/v8/tools/linux-tick-processor +4 -6
  525. data/lib/libv8/v8/tools/ll_prof.py +3 -3
  526. data/lib/libv8/v8/tools/oom_dump/README +3 -1
  527. data/lib/libv8/v8/tools/presubmit.py +11 -4
  528. data/lib/libv8/v8/tools/profile.js +46 -2
  529. data/lib/libv8/v8/tools/splaytree.js +11 -0
  530. data/lib/libv8/v8/tools/stats-viewer.py +15 -11
  531. data/lib/libv8/v8/tools/test-wrapper-gypbuild.py +227 -0
  532. data/lib/libv8/v8/tools/test.py +28 -8
  533. data/lib/libv8/v8/tools/tickprocessor.js +0 -16
  534. data/lib/libv8/version.rb +1 -1
  535. data/libv8.gemspec +2 -2
  536. metadata +31 -19
  537. data/lib/libv8/scons/engine/SCons/Tool/f03.py +0 -63
  538. data/lib/libv8/v8/src/json-parser.cc +0 -504
@@ -60,32 +60,14 @@ class TranscendentalCacheStub: public CodeStub {
60
60
  };
61
61
 
62
62
 
63
- class ToBooleanStub: public CodeStub {
64
- public:
65
- ToBooleanStub() { }
66
-
67
- void Generate(MacroAssembler* masm);
68
-
69
- private:
70
- Major MajorKey() { return ToBoolean; }
71
- int MinorKey() { return 0; }
72
- };
73
-
74
-
75
63
  class UnaryOpStub: public CodeStub {
76
64
  public:
77
- UnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
65
+ UnaryOpStub(Token::Value op,
66
+ UnaryOverwriteMode mode,
67
+ UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
78
68
  : op_(op),
79
69
  mode_(mode),
80
- operand_type_(UnaryOpIC::UNINITIALIZED),
81
- name_(NULL) {
82
- }
83
-
84
- UnaryOpStub(int key, UnaryOpIC::TypeInfo operand_type)
85
- : op_(OpBits::decode(key)),
86
- mode_(ModeBits::decode(key)),
87
- operand_type_(operand_type),
88
- name_(NULL) {
70
+ operand_type_(operand_type) {
89
71
  }
90
72
 
91
73
  private:
@@ -95,20 +77,7 @@ class UnaryOpStub: public CodeStub {
95
77
  // Operand type information determined at runtime.
96
78
  UnaryOpIC::TypeInfo operand_type_;
97
79
 
98
- char* name_;
99
-
100
- const char* GetName();
101
-
102
- #ifdef DEBUG
103
- void Print() {
104
- PrintF("TypeRecordingUnaryOpStub %d (op %s), "
105
- "(mode %d, runtime_type_info %s)\n",
106
- MinorKey(),
107
- Token::String(op_),
108
- static_cast<int>(mode_),
109
- UnaryOpIC::GetName(operand_type_));
110
- }
111
- #endif
80
+ virtual void PrintName(StringStream* stream);
112
81
 
113
82
  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
114
83
  class OpBits: public BitField<Token::Value, 1, 7> {};
@@ -171,8 +140,7 @@ class BinaryOpStub: public CodeStub {
171
140
  : op_(op),
172
141
  mode_(mode),
173
142
  operands_type_(BinaryOpIC::UNINITIALIZED),
174
- result_type_(BinaryOpIC::UNINITIALIZED),
175
- name_(NULL) {
143
+ result_type_(BinaryOpIC::UNINITIALIZED) {
176
144
  use_sse3_ = CpuFeatures::IsSupported(SSE3);
177
145
  ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
178
146
  }
@@ -185,8 +153,7 @@ class BinaryOpStub: public CodeStub {
185
153
  mode_(ModeBits::decode(key)),
186
154
  use_sse3_(SSE3Bits::decode(key)),
187
155
  operands_type_(operands_type),
188
- result_type_(result_type),
189
- name_(NULL) { }
156
+ result_type_(result_type) { }
190
157
 
191
158
  private:
192
159
  enum SmiCodeGenerateHeapNumberResults {
@@ -202,20 +169,7 @@ class BinaryOpStub: public CodeStub {
202
169
  BinaryOpIC::TypeInfo operands_type_;
203
170
  BinaryOpIC::TypeInfo result_type_;
204
171
 
205
- char* name_;
206
-
207
- const char* GetName();
208
-
209
- #ifdef DEBUG
210
- void Print() {
211
- PrintF("BinaryOpStub %d (op %s), "
212
- "(mode %d, runtime_type_info %s)\n",
213
- MinorKey(),
214
- Token::String(op_),
215
- static_cast<int>(mode_),
216
- BinaryOpIC::GetName(operands_type_));
217
- }
218
- #endif
172
+ virtual void PrintName(StringStream* stream);
219
173
 
220
174
  // Minor key encoding in 16 bits RRRTTTSOOOOOOOMM.
221
175
  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
@@ -433,14 +387,6 @@ class NumberToStringStub: public CodeStub {
433
387
  int MinorKey() { return 0; }
434
388
 
435
389
  void Generate(MacroAssembler* masm);
436
-
437
- const char* GetName() { return "NumberToStringStub"; }
438
-
439
- #ifdef DEBUG
440
- void Print() {
441
- PrintF("NumberToStringStub\n");
442
- }
443
- #endif
444
390
  };
445
391
 
446
392
 
@@ -484,13 +430,6 @@ class StringDictionaryLookupStub: public CodeStub {
484
430
  StringDictionary::kHeaderSize +
485
431
  StringDictionary::kElementsStartIndex * kPointerSize;
486
432
 
487
-
488
- #ifdef DEBUG
489
- void Print() {
490
- PrintF("StringDictionaryLookupStub\n");
491
- }
492
- #endif
493
-
494
433
  Major MajorKey() { return StringDictionaryNegativeLookup; }
495
434
 
496
435
  int MinorKey() {
@@ -255,6 +255,7 @@ OS::MemCopyFunction CreateMemCopyFunction() {
255
255
  ASSERT(desc.reloc_size == 0);
256
256
 
257
257
  CPU::FlushICache(buffer, actual_size);
258
+ OS::ProtectCode(buffer, actual_size);
258
259
  return FUNCTION_CAST<OS::MemCopyFunction>(buffer);
259
260
  }
260
261
 
@@ -53,9 +53,7 @@ class CodeGenerator {
53
53
  // Print the code after compiling it.
54
54
  static void PrintCode(Handle<Code> code, CompilationInfo* info);
55
55
 
56
- #ifdef ENABLE_LOGGING_AND_PROFILING
57
56
  static bool ShouldGenerateLog(Expression* type);
58
- #endif
59
57
 
60
58
  static bool RecordPositions(MacroAssembler* masm,
61
59
  int pos,
@@ -1,4 +1,4 @@
1
- // Copyright 2006-2008 the V8 project authors. All rights reserved.
1
+ // Copyright 2011 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:
@@ -67,7 +67,8 @@ void CPU::FlushICache(void* start, size_t size) {
67
67
  // solution is to run valgrind with --smc-check=all, but this comes at a big
68
68
  // performance cost. We can notify valgrind to invalidate its cache.
69
69
  #ifdef VALGRIND_DISCARD_TRANSLATIONS
70
- VALGRIND_DISCARD_TRANSLATIONS(start, size);
70
+ unsigned res = VALGRIND_DISCARD_TRANSLATIONS(start, size);
71
+ USE(res);
71
72
  #endif
72
73
  }
73
74
 
@@ -37,7 +37,7 @@
37
37
  namespace v8 {
38
38
  namespace internal {
39
39
 
40
- int Deoptimizer::table_entry_size_ = 10;
40
+ const int Deoptimizer::table_entry_size_ = 10;
41
41
 
42
42
 
43
43
  int Deoptimizer::patch_size() {
@@ -348,6 +348,9 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
348
348
  output_ = new FrameDescription*[1];
349
349
  output_[0] = new(output_frame_size) FrameDescription(
350
350
  output_frame_size, function_);
351
+ #ifdef DEBUG
352
+ output_[0]->SetKind(Code::OPTIMIZED_FUNCTION);
353
+ #endif
351
354
 
352
355
  // Clear the incoming parameters in the optimized frame to avoid
353
356
  // confusing the garbage collector.
@@ -461,6 +464,9 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
461
464
  // Allocate and store the output frame description.
462
465
  FrameDescription* output_frame =
463
466
  new(output_frame_size) FrameDescription(output_frame_size, function);
467
+ #ifdef DEBUG
468
+ output_frame->SetKind(Code::FUNCTION);
469
+ #endif
464
470
 
465
471
  bool is_bottommost = (0 == frame_index);
466
472
  bool is_topmost = (output_count_ - 1 == frame_index);
@@ -587,7 +593,7 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
587
593
  output_frame->SetState(Smi::FromInt(state));
588
594
 
589
595
  // Set the continuation for the topmost frame.
590
- if (is_topmost) {
596
+ if (is_topmost && bailout_type_ != DEBUGGER) {
591
597
  Builtins* builtins = isolate_->builtins();
592
598
  Code* continuation = (bailout_type_ == EAGER)
593
599
  ? builtins->builtin(Builtins::kNotifyDeoptimized)
@@ -595,8 +601,27 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
595
601
  output_frame->SetContinuation(
596
602
  reinterpret_cast<uint32_t>(continuation->entry()));
597
603
  }
604
+ }
605
+
598
606
 
599
- if (output_count_ - 1 == frame_index) iterator->Done();
607
+ void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
608
+ // Set the register values. The values are not important as there are no
609
+ // callee saved registers in JavaScript frames, so all registers are
610
+ // spilled. Registers ebp and esp are set to the correct values though.
611
+
612
+ for (int i = 0; i < Register::kNumRegisters; i++) {
613
+ input_->SetRegister(i, i * 4);
614
+ }
615
+ input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp()));
616
+ input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp()));
617
+ for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) {
618
+ input_->SetDoubleRegister(i, 0.0);
619
+ }
620
+
621
+ // Fill the frame content from the actual data on the frame.
622
+ for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) {
623
+ input_->SetFrameSlot(i, Memory::uint32_at(tos + i));
624
+ }
600
625
  }
601
626
 
602
627
 
@@ -54,7 +54,7 @@ struct ByteMnemonic {
54
54
  };
55
55
 
56
56
 
57
- static ByteMnemonic two_operands_instr[] = {
57
+ static const ByteMnemonic two_operands_instr[] = {
58
58
  {0x03, "add", REG_OPER_OP_ORDER},
59
59
  {0x09, "or", OPER_REG_OP_ORDER},
60
60
  {0x0B, "or", REG_OPER_OP_ORDER},
@@ -79,7 +79,7 @@ static ByteMnemonic two_operands_instr[] = {
79
79
  };
80
80
 
81
81
 
82
- static ByteMnemonic zero_operands_instr[] = {
82
+ static const ByteMnemonic zero_operands_instr[] = {
83
83
  {0xC3, "ret", UNSET_OP_ORDER},
84
84
  {0xC9, "leave", UNSET_OP_ORDER},
85
85
  {0x90, "nop", UNSET_OP_ORDER},
@@ -98,14 +98,14 @@ static ByteMnemonic zero_operands_instr[] = {
98
98
  };
99
99
 
100
100
 
101
- static ByteMnemonic call_jump_instr[] = {
101
+ static const ByteMnemonic call_jump_instr[] = {
102
102
  {0xE8, "call", UNSET_OP_ORDER},
103
103
  {0xE9, "jmp", UNSET_OP_ORDER},
104
104
  {-1, "", UNSET_OP_ORDER}
105
105
  };
106
106
 
107
107
 
108
- static ByteMnemonic short_immediate_instr[] = {
108
+ static const ByteMnemonic short_immediate_instr[] = {
109
109
  {0x05, "add", UNSET_OP_ORDER},
110
110
  {0x0D, "or", UNSET_OP_ORDER},
111
111
  {0x15, "adc", UNSET_OP_ORDER},
@@ -117,7 +117,7 @@ static ByteMnemonic short_immediate_instr[] = {
117
117
  };
118
118
 
119
119
 
120
- static const char* jump_conditional_mnem[] = {
120
+ static const char* const jump_conditional_mnem[] = {
121
121
  /*0*/ "jo", "jno", "jc", "jnc",
122
122
  /*4*/ "jz", "jnz", "jna", "ja",
123
123
  /*8*/ "js", "jns", "jpe", "jpo",
@@ -125,7 +125,7 @@ static const char* jump_conditional_mnem[] = {
125
125
  };
126
126
 
127
127
 
128
- static const char* set_conditional_mnem[] = {
128
+ static const char* const set_conditional_mnem[] = {
129
129
  /*0*/ "seto", "setno", "setc", "setnc",
130
130
  /*4*/ "setz", "setnz", "setna", "seta",
131
131
  /*8*/ "sets", "setns", "setpe", "setpo",
@@ -133,7 +133,7 @@ static const char* set_conditional_mnem[] = {
133
133
  };
134
134
 
135
135
 
136
- static const char* conditional_move_mnem[] = {
136
+ static const char* const conditional_move_mnem[] = {
137
137
  /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc",
138
138
  /*4*/ "cmovz", "cmovnz", "cmovna", "cmova",
139
139
  /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo",
@@ -169,7 +169,7 @@ class InstructionTable {
169
169
  InstructionDesc instructions_[256];
170
170
  void Clear();
171
171
  void Init();
172
- void CopyTable(ByteMnemonic bm[], InstructionType type);
172
+ void CopyTable(const ByteMnemonic bm[], InstructionType type);
173
173
  void SetTableRange(InstructionType type,
174
174
  byte start,
175
175
  byte end,
@@ -208,7 +208,8 @@ void InstructionTable::Init() {
208
208
  }
209
209
 
210
210
 
211
- void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) {
211
+ void InstructionTable::CopyTable(const ByteMnemonic bm[],
212
+ InstructionType type) {
212
213
  for (int i = 0; bm[i].b >= 0; i++) {
213
214
  InstructionDesc* id = &instructions_[bm[i].b];
214
215
  id->mnem = bm[i].mnem;
@@ -1140,7 +1141,17 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
1140
1141
  }
1141
1142
  } else if (*data == 0x3A) {
1142
1143
  data++;
1143
- if (*data == 0x16) {
1144
+ if (*data == 0x0B) {
1145
+ data++;
1146
+ int mod, regop, rm;
1147
+ get_modrm(*data, &mod, &regop, &rm);
1148
+ int8_t imm8 = static_cast<int8_t>(data[1]);
1149
+ AppendToBuffer("roundsd %s,%s,%d",
1150
+ NameOfXMMRegister(regop),
1151
+ NameOfXMMRegister(rm),
1152
+ static_cast<int>(imm8));
1153
+ data += 2;
1154
+ } else if (*data == 0x16) {
1144
1155
  data++;
1145
1156
  int mod, regop, rm;
1146
1157
  get_modrm(*data, &mod, &regop, &rm);
@@ -1,4 +1,4 @@
1
- // Copyright 2006-2008 the V8 project authors. All rights reserved.
1
+ // Copyright 2011 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:
@@ -58,10 +58,11 @@ static const int kNumSafepointRegisters = 8;
58
58
 
59
59
  class StackHandlerConstants : public AllStatic {
60
60
  public:
61
- static const int kNextOffset = 0 * kPointerSize;
62
- static const int kFPOffset = 1 * kPointerSize;
63
- static const int kStateOffset = 2 * kPointerSize;
64
- static const int kPCOffset = 3 * kPointerSize;
61
+ static const int kNextOffset = 0 * kPointerSize;
62
+ static const int kContextOffset = 1 * kPointerSize;
63
+ static const int kFPOffset = 2 * kPointerSize;
64
+ static const int kStateOffset = 3 * kPointerSize;
65
+ static const int kPCOffset = 4 * kPointerSize;
65
66
 
66
67
  static const int kSize = kPCOffset + kPointerSize;
67
68
  };
@@ -46,7 +46,6 @@ namespace internal {
46
46
 
47
47
 
48
48
  static unsigned GetPropertyId(Property* property) {
49
- if (property->is_synthetic()) return AstNode::kNoNumber;
50
49
  return property->id();
51
50
  }
52
51
 
@@ -78,16 +77,18 @@ class JumpPatchSite BASE_EMBEDDED {
78
77
  }
79
78
 
80
79
  void EmitPatchInfo() {
81
- int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
82
- ASSERT(is_int8(delta_to_patch_site));
83
- __ test(eax, Immediate(delta_to_patch_site));
80
+ if (patch_site_.is_bound()) {
81
+ int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
82
+ ASSERT(is_int8(delta_to_patch_site));
83
+ __ test(eax, Immediate(delta_to_patch_site));
84
84
  #ifdef DEBUG
85
- info_emitted_ = true;
85
+ info_emitted_ = true;
86
86
  #endif
87
+ } else {
88
+ __ nop(); // Signals no inlined code.
89
+ }
87
90
  }
88
91
 
89
- bool is_bound() const { return patch_site_.is_bound(); }
90
-
91
92
  private:
92
93
  // jc will be patched with jz, jnc will become jnz.
93
94
  void EmitJump(Condition cc, Label* target, Label::Distance distance) {
@@ -121,6 +122,7 @@ class JumpPatchSite BASE_EMBEDDED {
121
122
  void FullCodeGenerator::Generate(CompilationInfo* info) {
122
123
  ASSERT(info_ == NULL);
123
124
  info_ = info;
125
+ scope_ = info->scope();
124
126
  SetFunctionPosition(function());
125
127
  Comment cmnt(masm_, "[ function compiled by full code generator");
126
128
 
@@ -131,16 +133,16 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
131
133
  }
132
134
  #endif
133
135
 
134
- // Strict mode functions need to replace the receiver with undefined
135
- // when called as functions (without an explicit receiver
136
- // object). ecx is zero for method calls and non-zero for function
137
- // calls.
138
- if (info->is_strict_mode()) {
136
+ // Strict mode functions and builtins need to replace the receiver
137
+ // with undefined when called as functions (without an explicit
138
+ // receiver object). ecx is zero for method calls and non-zero for
139
+ // function calls.
140
+ if (info->is_strict_mode() || info->is_native()) {
139
141
  Label ok;
140
142
  __ test(ecx, Operand(ecx));
141
143
  __ j(zero, &ok, Label::kNear);
142
144
  // +1 for return address.
143
- int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
145
+ int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
144
146
  __ mov(Operand(esp, receiver_offset),
145
147
  Immediate(isolate()->factory()->undefined_value()));
146
148
  __ bind(&ok);
@@ -152,7 +154,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
152
154
  __ push(edi); // Callee's JS Function.
153
155
 
154
156
  { Comment cmnt(masm_, "[ Allocate locals");
155
- int locals_count = scope()->num_stack_slots();
157
+ int locals_count = info->scope()->num_stack_slots();
156
158
  if (locals_count == 1) {
157
159
  __ push(Immediate(isolate()->factory()->undefined_value()));
158
160
  } else if (locals_count > 1) {
@@ -163,10 +165,15 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
163
165
  }
164
166
  }
165
167
 
168
+ set_stack_height(2 + scope()->num_stack_slots());
169
+ if (FLAG_verify_stack_height) {
170
+ verify_stack_height();
171
+ }
172
+
166
173
  bool function_in_register = true;
167
174
 
168
175
  // Possibly allocate a local context.
169
- int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
176
+ int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
170
177
  if (heap_slots > 0) {
171
178
  Comment cmnt(masm_, "[ Allocate local context");
172
179
  // Argument to NewContext is the function, which is still in edi.
@@ -175,7 +182,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
175
182
  FastNewContextStub stub(heap_slots);
176
183
  __ CallStub(&stub);
177
184
  } else {
178
- __ CallRuntime(Runtime::kNewContext, 1);
185
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
179
186
  }
180
187
  function_in_register = false;
181
188
  // Context is returned in both eax and esi. It replaces the context
@@ -183,7 +190,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
183
190
  __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
184
191
 
185
192
  // Copy parameters into context if necessary.
186
- int num_parameters = scope()->num_parameters();
193
+ int num_parameters = info->scope()->num_parameters();
187
194
  for (int i = 0; i < num_parameters; i++) {
188
195
  Slot* slot = scope()->parameter(i)->AsSlot();
189
196
  if (slot != NULL && slot->type() == Slot::CONTEXT) {
@@ -213,25 +220,27 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
213
220
  __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
214
221
  }
215
222
  // Receiver is just before the parameters on the caller's stack.
216
- int offset = scope()->num_parameters() * kPointerSize;
223
+ int num_parameters = info->scope()->num_parameters();
224
+ int offset = num_parameters * kPointerSize;
217
225
  __ lea(edx,
218
226
  Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
219
227
  __ push(edx);
220
- __ SafePush(Immediate(Smi::FromInt(scope()->num_parameters())));
221
- // Arguments to ArgumentsAccessStub:
228
+ __ SafePush(Immediate(Smi::FromInt(num_parameters)));
229
+ // Arguments to ArgumentsAccessStub and/or New...:
222
230
  // function, receiver address, parameter count.
223
231
  // The stub will rewrite receiver and parameter count if the previous
224
232
  // stack frame was an arguments adapter frame.
225
- ArgumentsAccessStub stub(
226
- is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
227
- : ArgumentsAccessStub::NEW_NON_STRICT);
233
+ ArgumentsAccessStub::Type type;
234
+ if (is_strict_mode()) {
235
+ type = ArgumentsAccessStub::NEW_STRICT;
236
+ } else if (function()->has_duplicate_parameters()) {
237
+ type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
238
+ } else {
239
+ type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
240
+ }
241
+ ArgumentsAccessStub stub(type);
228
242
  __ CallStub(&stub);
229
243
 
230
- Variable* arguments_shadow = scope()->arguments_shadow();
231
- if (arguments_shadow != NULL) {
232
- __ mov(ecx, eax); // Duplicate result.
233
- Move(arguments_shadow->AsSlot(), ecx, ebx, edx);
234
- }
235
244
  Move(arguments->AsSlot(), eax, ebx, edx);
236
245
  }
237
246
 
@@ -341,7 +350,7 @@ void FullCodeGenerator::EmitReturnSequence() {
341
350
  __ mov(esp, ebp);
342
351
  __ pop(ebp);
343
352
 
344
- int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
353
+ int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
345
354
  __ Ret(arguments_bytes, ecx);
346
355
  #ifdef ENABLE_DEBUGGER_SUPPORT
347
356
  // Check that the size of the code used for returning is large enough
@@ -353,6 +362,15 @@ void FullCodeGenerator::EmitReturnSequence() {
353
362
  }
354
363
 
355
364
 
365
+ void FullCodeGenerator::verify_stack_height() {
366
+ ASSERT(FLAG_verify_stack_height);
367
+ __ sub(Operand(ebp), Immediate(kPointerSize * stack_height()));
368
+ __ cmp(ebp, Operand(esp));
369
+ __ Assert(equal, "Full codegen stack height not as expected.");
370
+ __ add(Operand(ebp), Immediate(kPointerSize * stack_height()));
371
+ }
372
+
373
+
356
374
  void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
357
375
  }
358
376
 
@@ -367,6 +385,7 @@ void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
367
385
  MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
368
386
  // Memory operands can be pushed directly.
369
387
  __ push(slot_operand);
388
+ codegen()->increment_stack_height();
370
389
  }
371
390
 
372
391
 
@@ -374,7 +393,7 @@ void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
374
393
  // For simplicity we always test the accumulator register.
375
394
  codegen()->Move(result_register(), slot);
376
395
  codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
377
- codegen()->DoTest(true_label_, false_label_, fall_through_);
396
+ codegen()->DoTest(this);
378
397
  }
379
398
 
380
399
 
@@ -420,6 +439,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
420
439
  } else {
421
440
  __ push(Immediate(lit));
422
441
  }
442
+ codegen()->increment_stack_height();
423
443
  }
424
444
 
425
445
 
@@ -448,7 +468,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
448
468
  } else {
449
469
  // For simplicity we always test the accumulator register.
450
470
  __ mov(result_register(), lit);
451
- codegen()->DoTest(true_label_, false_label_, fall_through_);
471
+ codegen()->DoTest(this);
452
472
  }
453
473
  }
454
474
 
@@ -457,6 +477,7 @@ void FullCodeGenerator::EffectContext::DropAndPlug(int count,
457
477
  Register reg) const {
458
478
  ASSERT(count > 0);
459
479
  __ Drop(count);
480
+ codegen()->decrement_stack_height(count);
460
481
  }
461
482
 
462
483
 
@@ -466,6 +487,7 @@ void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
466
487
  ASSERT(count > 0);
467
488
  __ Drop(count);
468
489
  __ Move(result_register(), reg);
490
+ codegen()->decrement_stack_height(count);
469
491
  }
470
492
 
471
493
 
@@ -474,6 +496,7 @@ void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
474
496
  ASSERT(count > 0);
475
497
  if (count > 1) __ Drop(count - 1);
476
498
  __ mov(Operand(esp, 0), reg);
499
+ codegen()->decrement_stack_height(count - 1);
477
500
  }
478
501
 
479
502
 
@@ -484,7 +507,8 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
484
507
  __ Drop(count);
485
508
  __ Move(result_register(), reg);
486
509
  codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
487
- codegen()->DoTest(true_label_, false_label_, fall_through_);
510
+ codegen()->DoTest(this);
511
+ codegen()->decrement_stack_height(count);
488
512
  }
489
513
 
490
514
 
@@ -518,6 +542,7 @@ void FullCodeGenerator::StackValueContext::Plug(
518
542
  __ bind(materialize_false);
519
543
  __ push(Immediate(isolate()->factory()->false_value()));
520
544
  __ bind(&done);
545
+ codegen()->increment_stack_height();
521
546
  }
522
547
 
523
548
 
@@ -545,6 +570,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
545
570
  ? isolate()->factory()->true_value()
546
571
  : isolate()->factory()->false_value();
547
572
  __ push(Immediate(value));
573
+ codegen()->increment_stack_height();
548
574
  }
549
575
 
550
576
 
@@ -561,13 +587,14 @@ void FullCodeGenerator::TestContext::Plug(bool flag) const {
561
587
  }
562
588
 
563
589
 
564
- void FullCodeGenerator::DoTest(Label* if_true,
590
+ void FullCodeGenerator::DoTest(Expression* condition,
591
+ Label* if_true,
565
592
  Label* if_false,
566
593
  Label* fall_through) {
567
- ToBooleanStub stub;
594
+ ToBooleanStub stub(result_register());
568
595
  __ push(result_register());
569
- __ CallStub(&stub);
570
- __ test(eax, Operand(eax));
596
+ __ CallStub(&stub, condition->test_id());
597
+ __ test(result_register(), Operand(result_register()));
571
598
  // The stub returns nonzero for true.
572
599
  Split(not_zero, if_true, if_false, fall_through);
573
600
  }
@@ -662,95 +689,73 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
662
689
  Comment cmnt(masm_, "[ Declaration");
663
690
  ASSERT(variable != NULL); // Must have been resolved.
664
691
  Slot* slot = variable->AsSlot();
665
- Property* prop = variable->AsProperty();
666
-
667
- if (slot != NULL) {
668
- switch (slot->type()) {
669
- case Slot::PARAMETER:
670
- case Slot::LOCAL:
671
- if (mode == Variable::CONST) {
672
- __ mov(Operand(ebp, SlotOffset(slot)),
673
- Immediate(isolate()->factory()->the_hole_value()));
674
- } else if (function != NULL) {
675
- VisitForAccumulatorValue(function);
676
- __ mov(Operand(ebp, SlotOffset(slot)), result_register());
677
- }
678
- break;
679
-
680
- case Slot::CONTEXT:
681
- // We bypass the general EmitSlotSearch because we know more about
682
- // this specific context.
683
-
684
- // The variable in the decl always resides in the current function
685
- // context.
686
- ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
687
- if (FLAG_debug_code) {
688
- // Check that we're not inside a 'with'.
689
- __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX));
690
- __ cmp(ebx, Operand(esi));
691
- __ Check(equal, "Unexpected declaration in current context.");
692
- }
693
- if (mode == Variable::CONST) {
694
- __ mov(ContextOperand(esi, slot->index()),
695
- Immediate(isolate()->factory()->the_hole_value()));
696
- // No write barrier since the hole value is in old space.
697
- } else if (function != NULL) {
698
- VisitForAccumulatorValue(function);
699
- __ mov(ContextOperand(esi, slot->index()), result_register());
700
- int offset = Context::SlotOffset(slot->index());
701
- __ mov(ebx, esi);
702
- __ RecordWrite(ebx, offset, result_register(), ecx);
703
- }
704
- break;
705
-
706
- case Slot::LOOKUP: {
707
- __ push(esi);
708
- __ push(Immediate(variable->name()));
709
- // Declaration nodes are always introduced in one of two modes.
710
- ASSERT(mode == Variable::VAR || mode == Variable::CONST);
711
- PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
712
- __ push(Immediate(Smi::FromInt(attr)));
713
- // Push initial value, if any.
714
- // Note: For variables we must not push an initial value (such as
715
- // 'undefined') because we may have a (legal) redeclaration and we
716
- // must not destroy the current value.
717
- if (mode == Variable::CONST) {
718
- __ push(Immediate(isolate()->factory()->the_hole_value()));
719
- } else if (function != NULL) {
720
- VisitForStackValue(function);
721
- } else {
722
- __ push(Immediate(Smi::FromInt(0))); // No initial value!
723
- }
724
- __ CallRuntime(Runtime::kDeclareContextSlot, 4);
725
- break;
692
+ ASSERT(slot != NULL);
693
+ switch (slot->type()) {
694
+ case Slot::PARAMETER:
695
+ case Slot::LOCAL:
696
+ if (function != NULL) {
697
+ VisitForAccumulatorValue(function);
698
+ __ mov(Operand(ebp, SlotOffset(slot)), result_register());
699
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
700
+ __ mov(Operand(ebp, SlotOffset(slot)),
701
+ Immediate(isolate()->factory()->the_hole_value()));
726
702
  }
727
- }
703
+ break;
728
704
 
729
- } else if (prop != NULL) {
730
- // A const declaration aliasing a parameter is an illegal redeclaration.
731
- ASSERT(mode != Variable::CONST);
732
- if (function != NULL) {
733
- // We are declaring a function that rewrites to a property.
734
- // Use (keyed) IC to set the initial value. We cannot visit the
735
- // rewrite because it's shared and we risk recording duplicate AST
736
- // IDs for bailouts from optimized code.
737
- ASSERT(prop->obj()->AsVariableProxy() != NULL);
738
- { AccumulatorValueContext for_object(this);
739
- EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
705
+ case Slot::CONTEXT:
706
+ // We bypass the general EmitSlotSearch because we know more about
707
+ // this specific context.
708
+
709
+ // The variable in the decl always resides in the current function
710
+ // context.
711
+ ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
712
+ if (FLAG_debug_code) {
713
+ // Check that we're not inside a with or catch context.
714
+ __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
715
+ __ cmp(ebx, isolate()->factory()->with_context_map());
716
+ __ Check(not_equal, "Declaration in with context.");
717
+ __ cmp(ebx, isolate()->factory()->catch_context_map());
718
+ __ Check(not_equal, "Declaration in catch context.");
740
719
  }
720
+ if (function != NULL) {
721
+ VisitForAccumulatorValue(function);
722
+ __ mov(ContextOperand(esi, slot->index()), result_register());
723
+ int offset = Context::SlotOffset(slot->index());
724
+ __ mov(ebx, esi);
725
+ __ RecordWrite(ebx, offset, result_register(), ecx);
726
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
727
+ __ mov(ContextOperand(esi, slot->index()),
728
+ Immediate(isolate()->factory()->the_hole_value()));
729
+ // No write barrier since the hole value is in old space.
730
+ }
731
+ break;
741
732
 
742
- __ push(eax);
743
- VisitForAccumulatorValue(function);
744
- __ pop(edx);
745
-
746
- ASSERT(prop->key()->AsLiteral() != NULL &&
747
- prop->key()->AsLiteral()->handle()->IsSmi());
748
- __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle()));
749
-
750
- Handle<Code> ic = is_strict_mode()
751
- ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
752
- : isolate()->builtins()->KeyedStoreIC_Initialize();
753
- EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber);
733
+ case Slot::LOOKUP: {
734
+ __ push(esi);
735
+ __ push(Immediate(variable->name()));
736
+ // Declaration nodes are always introduced in one of two modes.
737
+ ASSERT(mode == Variable::VAR ||
738
+ mode == Variable::CONST ||
739
+ mode == Variable::LET);
740
+ PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
741
+ __ push(Immediate(Smi::FromInt(attr)));
742
+ // Push initial value, if any.
743
+ // Note: For variables we must not push an initial value (such as
744
+ // 'undefined') because we may have a (legal) redeclaration and we
745
+ // must not destroy the current value.
746
+ increment_stack_height(3);
747
+ if (function != NULL) {
748
+ VisitForStackValue(function);
749
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
750
+ __ push(Immediate(isolate()->factory()->the_hole_value()));
751
+ increment_stack_height();
752
+ } else {
753
+ __ push(Immediate(Smi::FromInt(0))); // No initial value!
754
+ increment_stack_height();
755
+ }
756
+ __ CallRuntime(Runtime::kDeclareContextSlot, 4);
757
+ decrement_stack_height(4);
758
+ break;
754
759
  }
755
760
  }
756
761
  }
@@ -777,6 +782,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
777
782
  Breakable nested_statement(this, stmt);
778
783
  SetStatementPosition(stmt);
779
784
 
785
+ int switch_clause_stack_height = stack_height();
780
786
  // Keep the switch value on the stack until a case matches.
781
787
  VisitForStackValue(stmt->tag());
782
788
  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
@@ -823,7 +829,8 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
823
829
  // Record position before stub call for type feedback.
824
830
  SetSourcePosition(clause->position());
825
831
  Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
826
- EmitCallIC(ic, &patch_site, clause->CompareId());
832
+ __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
833
+ patch_site.EmitPatchInfo();
827
834
  __ test(eax, Operand(eax));
828
835
  __ j(not_equal, &next_test);
829
836
  __ Drop(1); // Switch value is no longer needed.
@@ -835,11 +842,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
835
842
  __ bind(&next_test);
836
843
  __ Drop(1); // Switch value is no longer needed.
837
844
  if (default_clause == NULL) {
838
- __ jmp(nested_statement.break_target());
845
+ __ jmp(nested_statement.break_label());
839
846
  } else {
840
847
  __ jmp(default_clause->body_target());
841
848
  }
842
849
 
850
+ set_stack_height(switch_clause_stack_height);
843
851
  // Compile all the case bodies.
844
852
  for (int i = 0; i < clauses->length(); i++) {
845
853
  Comment cmnt(masm_, "[ Case body");
@@ -849,7 +857,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
849
857
  VisitStatements(clause->statements());
850
858
  }
851
859
 
852
- __ bind(nested_statement.break_target());
860
+ __ bind(nested_statement.break_label());
853
861
  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
854
862
  }
855
863
 
@@ -873,15 +881,15 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
873
881
 
874
882
  // Convert the object to a JS object.
875
883
  Label convert, done_convert;
876
- __ test(eax, Immediate(kSmiTagMask));
877
- __ j(zero, &convert, Label::kNear);
878
- __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
884
+ __ JumpIfSmi(eax, &convert, Label::kNear);
885
+ __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
879
886
  __ j(above_equal, &done_convert, Label::kNear);
880
887
  __ bind(&convert);
881
888
  __ push(eax);
882
889
  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
883
890
  __ bind(&done_convert);
884
891
  __ push(eax);
892
+ increment_stack_height();
885
893
 
886
894
  // Check cache validity in generated code. This is a fast case for
887
895
  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
@@ -908,8 +916,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
908
916
  // descriptors (edx). This is the case if the next enumeration
909
917
  // index field does not contain a smi.
910
918
  __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
911
- __ test(edx, Immediate(kSmiTagMask));
912
- __ j(zero, &call_runtime);
919
+ __ JumpIfSmi(edx, &call_runtime);
913
920
 
914
921
  // For all objects but the receiver, check that the cache is empty.
915
922
  Label check_prototype;
@@ -966,11 +973,13 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
966
973
  __ push(eax); // Fixed array length (as smi).
967
974
  __ push(Immediate(Smi::FromInt(0))); // Initial index.
968
975
 
976
+ // 1 ~ The object has already been pushed.
977
+ increment_stack_height(ForIn::kElementCount - 1);
969
978
  // Generate code for doing the condition check.
970
979
  __ bind(&loop);
971
980
  __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
972
981
  __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
973
- __ j(above_equal, loop_statement.break_target());
982
+ __ j(above_equal, loop_statement.break_label());
974
983
 
975
984
  // Get the current entry of the array into register ebx.
976
985
  __ mov(ebx, Operand(esp, 2 * kPointerSize));
@@ -994,7 +1003,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
994
1003
  __ push(ebx); // Current entry.
995
1004
  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
996
1005
  __ test(eax, Operand(eax));
997
- __ j(equal, loop_statement.continue_target());
1006
+ __ j(equal, loop_statement.continue_label());
998
1007
  __ mov(ebx, Operand(eax));
999
1008
 
1000
1009
  // Update the 'each' property or variable from the possibly filtered
@@ -1011,16 +1020,17 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1011
1020
 
1012
1021
  // Generate code for going to the next element by incrementing the
1013
1022
  // index (smi) stored on top of the stack.
1014
- __ bind(loop_statement.continue_target());
1023
+ __ bind(loop_statement.continue_label());
1015
1024
  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1016
1025
 
1017
1026
  EmitStackCheck(stmt);
1018
1027
  __ jmp(&loop);
1019
1028
 
1020
1029
  // Remove the pointers stored on the stack.
1021
- __ bind(loop_statement.break_target());
1030
+ __ bind(loop_statement.break_label());
1022
1031
  __ add(Operand(esp), Immediate(5 * kPointerSize));
1023
1032
 
1033
+ decrement_stack_height(ForIn::kElementCount);
1024
1034
  // Exit and decrement the loop depth.
1025
1035
  __ bind(&exit);
1026
1036
  decrement_loop_depth();
@@ -1057,7 +1067,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1057
1067
 
1058
1068
  void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1059
1069
  Comment cmnt(masm_, "[ VariableProxy");
1060
- EmitVariableLoad(expr->var());
1070
+ EmitVariableLoad(expr);
1061
1071
  }
1062
1072
 
1063
1073
 
@@ -1078,8 +1088,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
1078
1088
  __ j(not_equal, slow);
1079
1089
  }
1080
1090
  // Load next context in chain.
1081
- __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
1082
- __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
1091
+ __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1083
1092
  // Walk the rest of the chain without clobbering esi.
1084
1093
  context = temp;
1085
1094
  }
@@ -1106,8 +1115,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
1106
1115
  __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
1107
1116
  __ j(not_equal, slow);
1108
1117
  // Load next context in chain.
1109
- __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX));
1110
- __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
1118
+ __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1111
1119
  __ jmp(&next);
1112
1120
  __ bind(&fast);
1113
1121
  }
@@ -1120,7 +1128,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
1120
1128
  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
1121
1129
  ? RelocInfo::CODE_TARGET
1122
1130
  : RelocInfo::CODE_TARGET_CONTEXT;
1123
- EmitCallIC(ic, mode, AstNode::kNoNumber);
1131
+ __ call(ic, mode);
1124
1132
  }
1125
1133
 
1126
1134
 
@@ -1139,8 +1147,7 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
1139
1147
  Immediate(0));
1140
1148
  __ j(not_equal, slow);
1141
1149
  }
1142
- __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
1143
- __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
1150
+ __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1144
1151
  // Walk the rest of the chain without clobbering esi.
1145
1152
  context = temp;
1146
1153
  }
@@ -1201,7 +1208,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
1201
1208
  __ SafeSet(eax, Immediate(key_literal->handle()));
1202
1209
  Handle<Code> ic =
1203
1210
  isolate()->builtins()->KeyedLoadIC_Initialize();
1204
- EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1211
+ __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1205
1212
  __ jmp(done);
1206
1213
  }
1207
1214
  }
@@ -1210,24 +1217,27 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
1210
1217
  }
1211
1218
 
1212
1219
 
1213
- void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1214
- // Four cases: non-this global variables, lookup slots, all other
1215
- // types of slots, and parameters that rewrite to explicit property
1216
- // accesses on the arguments object.
1220
+ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1221
+ // Record position before possible IC call.
1222
+ SetSourcePosition(proxy->position());
1223
+ Variable* var = proxy->var();
1224
+
1225
+ // Three cases: non-this global variables, lookup slots, and all other
1226
+ // types of slots.
1217
1227
  Slot* slot = var->AsSlot();
1218
- Property* property = var->AsProperty();
1228
+ ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
1219
1229
 
1220
- if (var->is_global() && !var->is_this()) {
1230
+ if (slot == NULL) {
1221
1231
  Comment cmnt(masm_, "Global variable");
1222
1232
  // Use inline caching. Variable name is passed in ecx and the global
1223
1233
  // object on the stack.
1224
1234
  __ mov(eax, GlobalObjectOperand());
1225
1235
  __ mov(ecx, var->name());
1226
1236
  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1227
- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber);
1237
+ __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1228
1238
  context()->Plug(eax);
1229
1239
 
1230
- } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1240
+ } else if (slot->type() == Slot::LOOKUP) {
1231
1241
  Label done, slow;
1232
1242
 
1233
1243
  // Generate code for loading from variables potentially shadowed
@@ -1243,7 +1253,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1243
1253
 
1244
1254
  context()->Plug(eax);
1245
1255
 
1246
- } else if (slot != NULL) {
1256
+ } else {
1247
1257
  Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1248
1258
  ? "Context slot"
1249
1259
  : "Stack slot");
@@ -1258,39 +1268,21 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1258
1268
  __ mov(eax, isolate()->factory()->undefined_value());
1259
1269
  __ bind(&done);
1260
1270
  context()->Plug(eax);
1271
+ } else if (var->mode() == Variable::LET) {
1272
+ // Let bindings may be the hole value if they have not been initialized.
1273
+ // Throw a type error in this case.
1274
+ Label done;
1275
+ MemOperand slot_operand = EmitSlotSearch(slot, eax);
1276
+ __ mov(eax, slot_operand);
1277
+ __ cmp(eax, isolate()->factory()->the_hole_value());
1278
+ __ j(not_equal, &done, Label::kNear);
1279
+ __ push(Immediate(var->name()));
1280
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
1281
+ __ bind(&done);
1282
+ context()->Plug(eax);
1261
1283
  } else {
1262
1284
  context()->Plug(slot);
1263
1285
  }
1264
-
1265
- } else {
1266
- Comment cmnt(masm_, "Rewritten parameter");
1267
- ASSERT_NOT_NULL(property);
1268
- // Rewritten parameter accesses are of the form "slot[literal]".
1269
-
1270
- // Assert that the object is in a slot.
1271
- Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1272
- ASSERT_NOT_NULL(object_var);
1273
- Slot* object_slot = object_var->AsSlot();
1274
- ASSERT_NOT_NULL(object_slot);
1275
-
1276
- // Load the object.
1277
- MemOperand object_loc = EmitSlotSearch(object_slot, eax);
1278
- __ mov(edx, object_loc);
1279
-
1280
- // Assert that the key is a smi.
1281
- Literal* key_literal = property->key()->AsLiteral();
1282
- ASSERT_NOT_NULL(key_literal);
1283
- ASSERT(key_literal->handle()->IsSmi());
1284
-
1285
- // Load the key.
1286
- __ SafeSet(eax, Immediate(key_literal->handle()));
1287
-
1288
- // Do a keyed property load.
1289
- Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1290
- EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1291
-
1292
- // Drop key and object left on the stack by IC.
1293
- context()->Plug(eax);
1294
1286
  }
1295
1287
  }
1296
1288
 
@@ -1386,6 +1378,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1386
1378
  if (!result_saved) {
1387
1379
  __ push(eax); // Save result on the stack
1388
1380
  result_saved = true;
1381
+ increment_stack_height();
1389
1382
  }
1390
1383
  switch (property->kind()) {
1391
1384
  case ObjectLiteral::Property::MATERIALIZED_LITERAL:
@@ -1400,7 +1393,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1400
1393
  Handle<Code> ic = is_strict_mode()
1401
1394
  ? isolate()->builtins()->StoreIC_Initialize_Strict()
1402
1395
  : isolate()->builtins()->StoreIC_Initialize();
1403
- EmitCallIC(ic, RelocInfo::CODE_TARGET, key->id());
1396
+ __ call(ic, RelocInfo::CODE_TARGET, key->id());
1404
1397
  PrepareForBailoutForId(key->id(), NO_REGISTERS);
1405
1398
  } else {
1406
1399
  VisitForEffect(value);
@@ -1410,6 +1403,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1410
1403
  // Fall through.
1411
1404
  case ObjectLiteral::Property::PROTOTYPE:
1412
1405
  __ push(Operand(esp, 0)); // Duplicate receiver.
1406
+ increment_stack_height();
1413
1407
  VisitForStackValue(key);
1414
1408
  VisitForStackValue(value);
1415
1409
  if (property->emit_store()) {
@@ -1418,16 +1412,20 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1418
1412
  } else {
1419
1413
  __ Drop(3);
1420
1414
  }
1415
+ decrement_stack_height(3);
1421
1416
  break;
1422
1417
  case ObjectLiteral::Property::SETTER:
1423
1418
  case ObjectLiteral::Property::GETTER:
1424
1419
  __ push(Operand(esp, 0)); // Duplicate receiver.
1420
+ increment_stack_height();
1425
1421
  VisitForStackValue(key);
1426
1422
  __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
1427
1423
  Smi::FromInt(1) :
1428
1424
  Smi::FromInt(0)));
1425
+ increment_stack_height();
1429
1426
  VisitForStackValue(value);
1430
1427
  __ CallRuntime(Runtime::kDefineAccessor, 4);
1428
+ decrement_stack_height(4);
1431
1429
  break;
1432
1430
  default: UNREACHABLE();
1433
1431
  }
@@ -1490,6 +1488,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1490
1488
  if (!result_saved) {
1491
1489
  __ push(eax);
1492
1490
  result_saved = true;
1491
+ increment_stack_height();
1493
1492
  }
1494
1493
  VisitForAccumulatorValue(subexpr);
1495
1494
 
@@ -1518,12 +1517,14 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1518
1517
  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1519
1518
  // on the left-hand side.
1520
1519
  if (!expr->target()->IsValidLeftHandSide()) {
1521
- VisitForEffect(expr->target());
1520
+ ASSERT(expr->target()->AsThrow() != NULL);
1521
+ VisitInCurrentContext(expr->target()); // Throw does not plug the context
1522
+ context()->Plug(eax);
1522
1523
  return;
1523
1524
  }
1524
1525
 
1525
1526
  // Left-hand side can only be a property, a global or a (parameter or local)
1526
- // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1527
+ // slot.
1527
1528
  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1528
1529
  LhsKind assign_type = VARIABLE;
1529
1530
  Property* property = expr->target()->AsProperty();
@@ -1543,35 +1544,21 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1543
1544
  // We need the receiver both on the stack and in the accumulator.
1544
1545
  VisitForAccumulatorValue(property->obj());
1545
1546
  __ push(result_register());
1547
+ increment_stack_height();
1546
1548
  } else {
1547
1549
  VisitForStackValue(property->obj());
1548
1550
  }
1549
1551
  break;
1550
1552
  case KEYED_PROPERTY: {
1551
1553
  if (expr->is_compound()) {
1552
- if (property->is_arguments_access()) {
1553
- VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1554
- MemOperand slot_operand =
1555
- EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1556
- __ push(slot_operand);
1557
- __ SafeSet(eax, Immediate(property->key()->AsLiteral()->handle()));
1558
- } else {
1559
- VisitForStackValue(property->obj());
1560
- VisitForAccumulatorValue(property->key());
1561
- }
1554
+ VisitForStackValue(property->obj());
1555
+ VisitForAccumulatorValue(property->key());
1562
1556
  __ mov(edx, Operand(esp, 0));
1563
1557
  __ push(eax);
1558
+ increment_stack_height();
1564
1559
  } else {
1565
- if (property->is_arguments_access()) {
1566
- VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1567
- MemOperand slot_operand =
1568
- EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1569
- __ push(slot_operand);
1570
- __ SafePush(Immediate(property->key()->AsLiteral()->handle()));
1571
- } else {
1572
- VisitForStackValue(property->obj());
1573
- VisitForStackValue(property->key());
1574
- }
1560
+ VisitForStackValue(property->obj());
1561
+ VisitForStackValue(property->key());
1575
1562
  }
1576
1563
  break;
1577
1564
  }
@@ -1580,10 +1567,11 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1580
1567
  // For compound assignments we need another deoptimization point after the
1581
1568
  // variable/property load.
1582
1569
  if (expr->is_compound()) {
1583
- { AccumulatorValueContext context(this);
1570
+ AccumulatorValueContext result_context(this);
1571
+ { AccumulatorValueContext left_operand_context(this);
1584
1572
  switch (assign_type) {
1585
1573
  case VARIABLE:
1586
- EmitVariableLoad(expr->target()->AsVariableProxy()->var());
1574
+ EmitVariableLoad(expr->target()->AsVariableProxy());
1587
1575
  PrepareForBailout(expr->target(), TOS_REG);
1588
1576
  break;
1589
1577
  case NAMED_PROPERTY:
@@ -1599,13 +1587,13 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1599
1587
 
1600
1588
  Token::Value op = expr->binary_op();
1601
1589
  __ push(eax); // Left operand goes on the stack.
1590
+ increment_stack_height();
1602
1591
  VisitForAccumulatorValue(expr->value());
1603
1592
 
1604
1593
  OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1605
1594
  ? OVERWRITE_RIGHT
1606
1595
  : NO_OVERWRITE;
1607
1596
  SetSourcePosition(expr->position() + 1);
1608
- AccumulatorValueContext context(this);
1609
1597
  if (ShouldInlineSmiCase(op)) {
1610
1598
  EmitInlineSmiBinaryOp(expr->binary_operation(),
1611
1599
  op,
@@ -1649,14 +1637,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1649
1637
  ASSERT(!key->handle()->IsSmi());
1650
1638
  __ mov(ecx, Immediate(key->handle()));
1651
1639
  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1652
- EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1640
+ __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1653
1641
  }
1654
1642
 
1655
1643
 
1656
1644
  void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1657
1645
  SetSourcePosition(prop->position());
1658
1646
  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1659
- EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1647
+ __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1660
1648
  }
1661
1649
 
1662
1650
 
@@ -1669,6 +1657,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1669
1657
  // stack. Right operand is in eax.
1670
1658
  Label smi_case, done, stub_call;
1671
1659
  __ pop(edx);
1660
+ decrement_stack_height();
1672
1661
  __ mov(ecx, eax);
1673
1662
  __ or_(eax, Operand(edx));
1674
1663
  JumpPatchSite patch_site(masm_);
@@ -1677,7 +1666,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1677
1666
  __ bind(&stub_call);
1678
1667
  __ mov(eax, ecx);
1679
1668
  BinaryOpStub stub(op, mode);
1680
- EmitCallIC(stub.GetCode(), &patch_site, expr->id());
1669
+ __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1670
+ patch_site.EmitPatchInfo();
1681
1671
  __ jmp(&done, Label::kNear);
1682
1672
 
1683
1673
  // Smi case.
@@ -1759,9 +1749,11 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
1759
1749
  Token::Value op,
1760
1750
  OverwriteMode mode) {
1761
1751
  __ pop(edx);
1752
+ decrement_stack_height();
1762
1753
  BinaryOpStub stub(op, mode);
1763
- // NULL signals no inlined smi code.
1764
- EmitCallIC(stub.GetCode(), NULL, expr->id());
1754
+ JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
1755
+ __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1756
+ patch_site.EmitPatchInfo();
1765
1757
  context()->Plug(eax);
1766
1758
  }
1767
1759
 
@@ -1770,12 +1762,14 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1770
1762
  // Invalid left-hand sides are rewritten to have a 'throw
1771
1763
  // ReferenceError' on the left-hand side.
1772
1764
  if (!expr->IsValidLeftHandSide()) {
1773
- VisitForEffect(expr);
1765
+ ASSERT(expr->AsThrow() != NULL);
1766
+ VisitInCurrentContext(expr); // Throw does not plug the context
1767
+ context()->Plug(eax);
1774
1768
  return;
1775
1769
  }
1776
1770
 
1777
1771
  // Left-hand side can only be a property, a global or a (parameter or local)
1778
- // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1772
+ // slot.
1779
1773
  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1780
1774
  LhsKind assign_type = VARIABLE;
1781
1775
  Property* prop = expr->AsProperty();
@@ -1794,37 +1788,32 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1794
1788
  }
1795
1789
  case NAMED_PROPERTY: {
1796
1790
  __ push(eax); // Preserve value.
1791
+ increment_stack_height();
1797
1792
  VisitForAccumulatorValue(prop->obj());
1798
1793
  __ mov(edx, eax);
1799
1794
  __ pop(eax); // Restore value.
1795
+ decrement_stack_height();
1800
1796
  __ mov(ecx, prop->key()->AsLiteral()->handle());
1801
1797
  Handle<Code> ic = is_strict_mode()
1802
1798
  ? isolate()->builtins()->StoreIC_Initialize_Strict()
1803
1799
  : isolate()->builtins()->StoreIC_Initialize();
1804
- EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber);
1800
+ __ call(ic);
1805
1801
  break;
1806
1802
  }
1807
1803
  case KEYED_PROPERTY: {
1808
1804
  __ push(eax); // Preserve value.
1809
- if (prop->is_synthetic()) {
1810
- ASSERT(prop->obj()->AsVariableProxy() != NULL);
1811
- ASSERT(prop->key()->AsLiteral() != NULL);
1812
- { AccumulatorValueContext for_object(this);
1813
- EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1814
- }
1815
- __ mov(edx, eax);
1816
- __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle()));
1817
- } else {
1818
- VisitForStackValue(prop->obj());
1819
- VisitForAccumulatorValue(prop->key());
1820
- __ mov(ecx, eax);
1821
- __ pop(edx);
1822
- }
1805
+ increment_stack_height();
1806
+ VisitForStackValue(prop->obj());
1807
+ VisitForAccumulatorValue(prop->key());
1808
+ __ mov(ecx, eax);
1809
+ __ pop(edx);
1810
+ decrement_stack_height();
1823
1811
  __ pop(eax); // Restore value.
1812
+ decrement_stack_height();
1824
1813
  Handle<Code> ic = is_strict_mode()
1825
1814
  ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
1826
1815
  : isolate()->builtins()->KeyedStoreIC_Initialize();
1827
- EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber);
1816
+ __ call(ic);
1828
1817
  break;
1829
1818
  }
1830
1819
  }
@@ -1835,8 +1824,6 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1835
1824
 
1836
1825
  void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1837
1826
  Token::Value op) {
1838
- // Left-hand sides that rewrite to explicit property accesses do not reach
1839
- // here.
1840
1827
  ASSERT(var != NULL);
1841
1828
  ASSERT(var->is_global() || var->AsSlot() != NULL);
1842
1829
 
@@ -1850,7 +1837,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1850
1837
  Handle<Code> ic = is_strict_mode()
1851
1838
  ? isolate()->builtins()->StoreIC_Initialize_Strict()
1852
1839
  : isolate()->builtins()->StoreIC_Initialize();
1853
- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber);
1840
+ __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1854
1841
 
1855
1842
  } else if (op == Token::INIT_CONST) {
1856
1843
  // Like var declarations, const declarations are hoisted to function
@@ -1870,26 +1857,67 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1870
1857
  __ j(not_equal, &skip);
1871
1858
  __ mov(Operand(ebp, SlotOffset(slot)), eax);
1872
1859
  break;
1860
+ case Slot::CONTEXT:
1861
+ case Slot::LOOKUP:
1862
+ __ push(eax);
1863
+ __ push(esi);
1864
+ __ push(Immediate(var->name()));
1865
+ __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1866
+ break;
1867
+ }
1868
+ __ bind(&skip);
1869
+
1870
+ } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
1871
+ // Perform the assignment for non-const variables. Const assignments
1872
+ // are simply skipped.
1873
+ Slot* slot = var->AsSlot();
1874
+ switch (slot->type()) {
1875
+ case Slot::PARAMETER:
1876
+ case Slot::LOCAL: {
1877
+ Label assign;
1878
+ // Check for an initialized let binding.
1879
+ __ mov(edx, Operand(ebp, SlotOffset(slot)));
1880
+ __ cmp(edx, isolate()->factory()->the_hole_value());
1881
+ __ j(not_equal, &assign);
1882
+ __ push(Immediate(var->name()));
1883
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
1884
+ // Perform the assignment.
1885
+ __ bind(&assign);
1886
+ __ mov(Operand(ebp, SlotOffset(slot)), eax);
1887
+ break;
1888
+ }
1889
+
1873
1890
  case Slot::CONTEXT: {
1874
- __ mov(ecx, ContextOperand(esi, Context::FCONTEXT_INDEX));
1875
- __ mov(edx, ContextOperand(ecx, slot->index()));
1891
+ // Let variables may be the hole value if they have not been
1892
+ // initialized. Throw a type error in this case.
1893
+ Label assign;
1894
+ MemOperand target = EmitSlotSearch(slot, ecx);
1895
+ // Check for an initialized let binding.
1896
+ __ mov(edx, target);
1876
1897
  __ cmp(edx, isolate()->factory()->the_hole_value());
1877
- __ j(not_equal, &skip);
1878
- __ mov(ContextOperand(ecx, slot->index()), eax);
1898
+ __ j(not_equal, &assign, Label::kNear);
1899
+ __ push(Immediate(var->name()));
1900
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
1901
+ // Perform the assignment.
1902
+ __ bind(&assign);
1903
+ __ mov(target, eax);
1904
+ // The value of the assignment is in eax. RecordWrite clobbers its
1905
+ // register arguments.
1906
+ __ mov(edx, eax);
1879
1907
  int offset = Context::SlotOffset(slot->index());
1880
- __ mov(edx, eax); // Preserve the stored value in eax.
1881
1908
  __ RecordWrite(ecx, offset, edx, ebx);
1882
1909
  break;
1883
1910
  }
1911
+
1884
1912
  case Slot::LOOKUP:
1885
- __ push(eax);
1886
- __ push(esi);
1913
+ // Call the runtime for the assignment.
1914
+ __ push(eax); // Value.
1915
+ __ push(esi); // Context.
1887
1916
  __ push(Immediate(var->name()));
1888
- __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1917
+ __ push(Immediate(Smi::FromInt(strict_mode_flag())));
1918
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
1889
1919
  break;
1890
1920
  }
1891
- __ bind(&skip);
1892
-
1893
1921
  } else if (var->mode() != Variable::CONST) {
1894
1922
  // Perform the assignment for non-const variables. Const assignments
1895
1923
  // are simply skipped.
@@ -1949,11 +1977,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1949
1977
  __ mov(edx, Operand(esp, 0));
1950
1978
  } else {
1951
1979
  __ pop(edx);
1980
+ decrement_stack_height();
1952
1981
  }
1953
1982
  Handle<Code> ic = is_strict_mode()
1954
1983
  ? isolate()->builtins()->StoreIC_Initialize_Strict()
1955
1984
  : isolate()->builtins()->StoreIC_Initialize();
1956
- EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id());
1985
+ __ call(ic, RelocInfo::CODE_TARGET, expr->id());
1957
1986
 
1958
1987
  // If the assignment ends an initialization block, revert to fast case.
1959
1988
  if (expr->ends_initialization_block()) {
@@ -1962,6 +1991,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1962
1991
  __ CallRuntime(Runtime::kToFastProperties, 1);
1963
1992
  __ pop(eax);
1964
1993
  __ Drop(1);
1994
+ decrement_stack_height();
1965
1995
  }
1966
1996
  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1967
1997
  context()->Plug(eax);
@@ -1983,17 +2013,19 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1983
2013
  }
1984
2014
 
1985
2015
  __ pop(ecx);
2016
+ decrement_stack_height();
1986
2017
  if (expr->ends_initialization_block()) {
1987
2018
  __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later.
1988
2019
  } else {
1989
2020
  __ pop(edx);
2021
+ decrement_stack_height();
1990
2022
  }
1991
2023
  // Record source code position before IC call.
1992
2024
  SetSourcePosition(expr->position());
1993
2025
  Handle<Code> ic = is_strict_mode()
1994
2026
  ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
1995
2027
  : isolate()->builtins()->KeyedStoreIC_Initialize();
1996
- EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2028
+ __ call(ic, RelocInfo::CODE_TARGET, expr->id());
1997
2029
 
1998
2030
  // If the assignment ends an initialization block, revert to fast case.
1999
2031
  if (expr->ends_initialization_block()) {
@@ -2002,6 +2034,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2002
2034
  __ push(edx);
2003
2035
  __ CallRuntime(Runtime::kToFastProperties, 1);
2004
2036
  __ pop(eax);
2037
+ decrement_stack_height();
2005
2038
  }
2006
2039
 
2007
2040
  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
@@ -2021,6 +2054,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
2021
2054
  VisitForStackValue(expr->obj());
2022
2055
  VisitForAccumulatorValue(expr->key());
2023
2056
  __ pop(edx);
2057
+ decrement_stack_height();
2024
2058
  EmitKeyedPropertyLoad(expr);
2025
2059
  context()->Plug(eax);
2026
2060
  }
@@ -2044,10 +2078,11 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
2044
2078
  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2045
2079
  Handle<Code> ic =
2046
2080
  isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode);
2047
- EmitCallIC(ic, mode, expr->id());
2081
+ __ call(ic, mode, expr->id());
2048
2082
  RecordJSReturnSite(expr);
2049
2083
  // Restore context register.
2050
2084
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2085
+ decrement_stack_height(arg_count + 1);
2051
2086
  context()->Plug(eax);
2052
2087
  }
2053
2088
 
@@ -2062,6 +2097,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2062
2097
  __ pop(ecx);
2063
2098
  __ push(eax);
2064
2099
  __ push(ecx);
2100
+ increment_stack_height();
2065
2101
 
2066
2102
  // Load the arguments.
2067
2103
  ZoneList<Expression*>* args = expr->arguments();
@@ -2077,10 +2113,11 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2077
2113
  Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(
2078
2114
  arg_count, in_loop);
2079
2115
  __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key.
2080
- EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2116
+ __ call(ic, RelocInfo::CODE_TARGET, expr->id());
2081
2117
  RecordJSReturnSite(expr);
2082
2118
  // Restore context register.
2083
2119
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2120
+ decrement_stack_height(arg_count + 1);
2084
2121
  context()->DropAndPlug(1, eax); // Drop the key still on the stack.
2085
2122
  }
2086
2123
 
@@ -2102,6 +2139,8 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2102
2139
  RecordJSReturnSite(expr);
2103
2140
  // Restore context register.
2104
2141
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2142
+
2143
+ decrement_stack_height(arg_count + 1);
2105
2144
  context()->DropAndPlug(1, eax);
2106
2145
  }
2107
2146
 
@@ -2116,7 +2155,7 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
2116
2155
  }
2117
2156
 
2118
2157
  // Push the receiver of the enclosing function.
2119
- __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
2158
+ __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2120
2159
 
2121
2160
  // Push the strict mode flag.
2122
2161
  __ push(Immediate(Smi::FromInt(strict_mode_flag())));
@@ -2149,7 +2188,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
2149
2188
  VisitForStackValue(fun);
2150
2189
  // Reserved receiver slot.
2151
2190
  __ push(Immediate(isolate()->factory()->undefined_value()));
2152
-
2191
+ increment_stack_height();
2153
2192
  // Push the arguments.
2154
2193
  for (int i = 0; i < arg_count; i++) {
2155
2194
  VisitForStackValue(args->at(i));
@@ -2193,10 +2232,12 @@ void FullCodeGenerator::VisitCall(Call* expr) {
2193
2232
  RecordJSReturnSite(expr);
2194
2233
  // Restore context register.
2195
2234
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2235
+ decrement_stack_height(arg_count + 1); // Function is left on the stack.
2196
2236
  context()->DropAndPlug(1, eax);
2197
2237
  } else if (var != NULL && !var->is_this() && var->is_global()) {
2198
2238
  // Push global object as receiver for the call IC.
2199
2239
  __ push(GlobalObjectOperand());
2240
+ increment_stack_height();
2200
2241
  EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
2201
2242
  } else if (var != NULL && var->AsSlot() != NULL &&
2202
2243
  var->AsSlot()->type() == Slot::LOOKUP) {
@@ -2219,7 +2260,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
2219
2260
  __ push(Immediate(var->name()));
2220
2261
  __ CallRuntime(Runtime::kLoadContextSlot, 2);
2221
2262
  __ push(eax); // Function.
2263
+ increment_stack_height();
2222
2264
  __ push(edx); // Receiver.
2265
+ increment_stack_height();
2223
2266
 
2224
2267
  // If fast case code has been generated, emit code to push the
2225
2268
  // function and receiver and have the slow path jump around this
@@ -2228,11 +2271,11 @@ void FullCodeGenerator::VisitCall(Call* expr) {
2228
2271
  Label call;
2229
2272
  __ jmp(&call);
2230
2273
  __ bind(&done);
2231
- // Push function.
2274
+ // Push function. Stack height already incremented in slow case above.
2232
2275
  __ push(eax);
2233
- // Push global receiver.
2234
- __ mov(ebx, GlobalObjectOperand());
2235
- __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2276
+ // The receiver is implicitly the global receiver. Indicate this
2277
+ // by passing the hole to the call function stub.
2278
+ __ push(Immediate(isolate()->factory()->the_hole_value()));
2236
2279
  __ bind(&call);
2237
2280
  }
2238
2281
 
@@ -2252,38 +2295,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
2252
2295
  EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2253
2296
  } else {
2254
2297
  // Call to a keyed property.
2255
- // For a synthetic property use keyed load IC followed by function call,
2256
- // for a regular property use keyed EmitCallIC.
2257
- if (prop->is_synthetic()) {
2258
- // Do not visit the object and key subexpressions (they are shared
2259
- // by all occurrences of the same rewritten parameter).
2260
- ASSERT(prop->obj()->AsVariableProxy() != NULL);
2261
- ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2262
- Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2263
- MemOperand operand = EmitSlotSearch(slot, edx);
2264
- __ mov(edx, operand);
2265
-
2266
- ASSERT(prop->key()->AsLiteral() != NULL);
2267
- ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2268
- __ mov(eax, prop->key()->AsLiteral()->handle());
2269
-
2270
- // Record source code position for IC call.
2271
- SetSourcePosition(prop->position());
2272
-
2273
- Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2274
- EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
2275
- // Push result (function).
2276
- __ push(eax);
2277
- // Push Global receiver.
2278
- __ mov(ecx, GlobalObjectOperand());
2279
- __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
2280
- EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2281
- } else {
2282
- { PreservePositionScope scope(masm()->positions_recorder());
2283
- VisitForStackValue(prop->obj());
2284
- }
2285
- EmitKeyedCallWithIC(expr, prop->key());
2298
+ { PreservePositionScope scope(masm()->positions_recorder());
2299
+ VisitForStackValue(prop->obj());
2286
2300
  }
2301
+ EmitKeyedCallWithIC(expr, prop->key());
2287
2302
  }
2288
2303
  } else {
2289
2304
  { PreservePositionScope scope(masm()->positions_recorder());
@@ -2292,6 +2307,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
2292
2307
  // Load global receiver object.
2293
2308
  __ mov(ebx, GlobalObjectOperand());
2294
2309
  __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2310
+ increment_stack_height();
2295
2311
  // Emit function call.
2296
2312
  EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2297
2313
  }
@@ -2332,6 +2348,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2332
2348
  Handle<Code> construct_builtin =
2333
2349
  isolate()->builtins()->JSConstructCall();
2334
2350
  __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
2351
+
2352
+ decrement_stack_height(arg_count + 1);
2335
2353
  context()->Plug(eax);
2336
2354
  }
2337
2355
 
@@ -2388,8 +2406,7 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2388
2406
  context()->PrepareTest(&materialize_true, &materialize_false,
2389
2407
  &if_true, &if_false, &fall_through);
2390
2408
 
2391
- __ test(eax, Immediate(kSmiTagMask));
2392
- __ j(zero, if_false);
2409
+ __ JumpIfSmi(eax, if_false);
2393
2410
  __ cmp(eax, isolate()->factory()->null_value());
2394
2411
  __ j(equal, if_true);
2395
2412
  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
@@ -2398,9 +2415,9 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2398
2415
  __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2399
2416
  __ j(not_zero, if_false);
2400
2417
  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2401
- __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
2418
+ __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
2402
2419
  __ j(below, if_false);
2403
- __ cmp(ecx, LAST_JS_OBJECT_TYPE);
2420
+ __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
2404
2421
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2405
2422
  Split(below_equal, if_true, if_false, fall_through);
2406
2423
 
@@ -2420,9 +2437,8 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2420
2437
  context()->PrepareTest(&materialize_true, &materialize_false,
2421
2438
  &if_true, &if_false, &fall_through);
2422
2439
 
2423
- __ test(eax, Immediate(kSmiTagMask));
2424
- __ j(equal, if_false);
2425
- __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx);
2440
+ __ JumpIfSmi(eax, if_false);
2441
+ __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
2426
2442
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2427
2443
  Split(above_equal, if_true, if_false, fall_through);
2428
2444
 
@@ -2442,8 +2458,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2442
2458
  context()->PrepareTest(&materialize_true, &materialize_false,
2443
2459
  &if_true, &if_false, &fall_through);
2444
2460
 
2445
- __ test(eax, Immediate(kSmiTagMask));
2446
- __ j(zero, if_false);
2461
+ __ JumpIfSmi(eax, if_false);
2447
2462
  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2448
2463
  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2449
2464
  __ test(ebx, Immediate(1 << Map::kIsUndetectable));
@@ -2517,8 +2532,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2517
2532
  // If a valueOf property is not found on the object check that it's
2518
2533
  // prototype is the un-modified String prototype. If not result is false.
2519
2534
  __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
2520
- __ test(ecx, Immediate(kSmiTagMask));
2521
- __ j(zero, if_false);
2535
+ __ JumpIfSmi(ecx, if_false);
2522
2536
  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
2523
2537
  __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2524
2538
  __ mov(edx,
@@ -2550,8 +2564,7 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2550
2564
  context()->PrepareTest(&materialize_true, &materialize_false,
2551
2565
  &if_true, &if_false, &fall_through);
2552
2566
 
2553
- __ test(eax, Immediate(kSmiTagMask));
2554
- __ j(zero, if_false);
2567
+ __ JumpIfSmi(eax, if_false);
2555
2568
  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2556
2569
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2557
2570
  Split(equal, if_true, if_false, fall_through);
@@ -2572,8 +2585,7 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2572
2585
  context()->PrepareTest(&materialize_true, &materialize_false,
2573
2586
  &if_true, &if_false, &fall_through);
2574
2587
 
2575
- __ test(eax, Immediate(kSmiTagMask));
2576
- __ j(equal, if_false);
2588
+ __ JumpIfSmi(eax, if_false);
2577
2589
  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
2578
2590
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2579
2591
  Split(equal, if_true, if_false, fall_through);
@@ -2594,8 +2606,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2594
2606
  context()->PrepareTest(&materialize_true, &materialize_false,
2595
2607
  &if_true, &if_false, &fall_through);
2596
2608
 
2597
- __ test(eax, Immediate(kSmiTagMask));
2598
- __ j(equal, if_false);
2609
+ __ JumpIfSmi(eax, if_false);
2599
2610
  __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
2600
2611
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2601
2612
  Split(equal, if_true, if_false, fall_through);
@@ -2651,6 +2662,7 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2651
2662
  &if_true, &if_false, &fall_through);
2652
2663
 
2653
2664
  __ pop(ebx);
2665
+ decrement_stack_height();
2654
2666
  __ cmp(eax, Operand(ebx));
2655
2667
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2656
2668
  Split(equal, if_true, if_false, fall_through);
@@ -2666,7 +2678,7 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2666
2678
  // parameter count in eax.
2667
2679
  VisitForAccumulatorValue(args->at(0));
2668
2680
  __ mov(edx, eax);
2669
- __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2681
+ __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2670
2682
  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2671
2683
  __ CallStub(&stub);
2672
2684
  context()->Plug(eax);
@@ -2678,7 +2690,7 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2678
2690
 
2679
2691
  Label exit;
2680
2692
  // Get the number of formal parameters.
2681
- __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2693
+ __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2682
2694
 
2683
2695
  // Check if the calling frame is an arguments adaptor frame.
2684
2696
  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
@@ -2703,21 +2715,22 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2703
2715
  VisitForAccumulatorValue(args->at(0));
2704
2716
 
2705
2717
  // If the object is a smi, we return null.
2706
- __ test(eax, Immediate(kSmiTagMask));
2707
- __ j(zero, &null);
2718
+ __ JumpIfSmi(eax, &null);
2708
2719
 
2709
2720
  // Check that the object is a JS object but take special care of JS
2710
2721
  // functions to make sure they have 'Function' as their class.
2711
- __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, eax); // Map is now in eax.
2722
+ __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax);
2723
+ // Map is now in eax.
2712
2724
  __ j(below, &null);
2713
2725
 
2714
- // As long as JS_FUNCTION_TYPE is the last instance type and it is
2715
- // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2716
- // LAST_JS_OBJECT_TYPE.
2717
- ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2718
- ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
2719
- __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
2720
- __ j(equal, &function);
2726
+ // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and
2727
+ // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
2728
+ // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
2729
+ STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
2730
+ STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
2731
+ LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
2732
+ __ CmpInstanceType(eax, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
2733
+ __ j(above_equal, &function);
2721
2734
 
2722
2735
  // Check if the constructor in the map is a function.
2723
2736
  __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
@@ -2760,13 +2773,12 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2760
2773
  // with '%2s' (see Logger::LogRuntime for all the formats).
2761
2774
  // 2 (array): Arguments to the format string.
2762
2775
  ASSERT_EQ(args->length(), 3);
2763
- #ifdef ENABLE_LOGGING_AND_PROFILING
2764
2776
  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2765
2777
  VisitForStackValue(args->at(1));
2766
2778
  VisitForStackValue(args->at(2));
2767
2779
  __ CallRuntime(Runtime::kLog, 2);
2780
+ decrement_stack_height(2);
2768
2781
  }
2769
- #endif
2770
2782
  // Finally, we're expected to leave a value on the top of the stack.
2771
2783
  __ mov(eax, isolate()->factory()->undefined_value());
2772
2784
  context()->Plug(eax);
@@ -2831,6 +2843,7 @@ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2831
2843
  VisitForStackValue(args->at(1));
2832
2844
  VisitForStackValue(args->at(2));
2833
2845
  __ CallStub(&stub);
2846
+ decrement_stack_height(3);
2834
2847
  context()->Plug(eax);
2835
2848
  }
2836
2849
 
@@ -2844,6 +2857,7 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2844
2857
  VisitForStackValue(args->at(2));
2845
2858
  VisitForStackValue(args->at(3));
2846
2859
  __ CallStub(&stub);
2860
+ decrement_stack_height(4);
2847
2861
  context()->Plug(eax);
2848
2862
  }
2849
2863
 
@@ -2855,8 +2869,7 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2855
2869
 
2856
2870
  Label done;
2857
2871
  // If the object is a smi return the object.
2858
- __ test(eax, Immediate(kSmiTagMask));
2859
- __ j(zero, &done, Label::kNear);
2872
+ __ JumpIfSmi(eax, &done, Label::kNear);
2860
2873
  // If the object is not a value type, return the object.
2861
2874
  __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2862
2875
  __ j(not_equal, &done, Label::kNear);
@@ -2879,6 +2892,7 @@ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2879
2892
  } else {
2880
2893
  __ CallRuntime(Runtime::kMath_pow, 2);
2881
2894
  }
2895
+ decrement_stack_height(2);
2882
2896
  context()->Plug(eax);
2883
2897
  }
2884
2898
 
@@ -2889,11 +2903,11 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2889
2903
  VisitForStackValue(args->at(0)); // Load the object.
2890
2904
  VisitForAccumulatorValue(args->at(1)); // Load the value.
2891
2905
  __ pop(ebx); // eax = value. ebx = object.
2906
+ decrement_stack_height();
2892
2907
 
2893
2908
  Label done;
2894
2909
  // If the object is a smi, return the value.
2895
- __ test(ebx, Immediate(kSmiTagMask));
2896
- __ j(zero, &done, Label::kNear);
2910
+ __ JumpIfSmi(ebx, &done, Label::kNear);
2897
2911
 
2898
2912
  // If the object is not a value type, return the value.
2899
2913
  __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
@@ -2919,6 +2933,7 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2919
2933
 
2920
2934
  NumberToStringStub stub;
2921
2935
  __ CallStub(&stub);
2936
+ decrement_stack_height();
2922
2937
  context()->Plug(eax);
2923
2938
  }
2924
2939
 
@@ -2953,6 +2968,7 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
2953
2968
  Register result = edx;
2954
2969
 
2955
2970
  __ pop(object);
2971
+ decrement_stack_height();
2956
2972
 
2957
2973
  Label need_conversion;
2958
2974
  Label index_out_of_range;
@@ -3001,6 +3017,7 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
3001
3017
  Register result = eax;
3002
3018
 
3003
3019
  __ pop(object);
3020
+ decrement_stack_height();
3004
3021
 
3005
3022
  Label need_conversion;
3006
3023
  Label index_out_of_range;
@@ -3045,6 +3062,7 @@ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
3045
3062
 
3046
3063
  StringAddStub stub(NO_STRING_ADD_FLAGS);
3047
3064
  __ CallStub(&stub);
3065
+ decrement_stack_height(2);
3048
3066
  context()->Plug(eax);
3049
3067
  }
3050
3068
 
@@ -3057,6 +3075,7 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
3057
3075
 
3058
3076
  StringCompareStub stub;
3059
3077
  __ CallStub(&stub);
3078
+ decrement_stack_height(2);
3060
3079
  context()->Plug(eax);
3061
3080
  }
3062
3081
 
@@ -3068,6 +3087,7 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
3068
3087
  ASSERT(args->length() == 1);
3069
3088
  VisitForStackValue(args->at(0));
3070
3089
  __ CallStub(&stub);
3090
+ decrement_stack_height();
3071
3091
  context()->Plug(eax);
3072
3092
  }
3073
3093
 
@@ -3079,6 +3099,7 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
3079
3099
  ASSERT(args->length() == 1);
3080
3100
  VisitForStackValue(args->at(0));
3081
3101
  __ CallStub(&stub);
3102
+ decrement_stack_height();
3082
3103
  context()->Plug(eax);
3083
3104
  }
3084
3105
 
@@ -3090,6 +3111,7 @@ void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
3090
3111
  ASSERT(args->length() == 1);
3091
3112
  VisitForStackValue(args->at(0));
3092
3113
  __ CallStub(&stub);
3114
+ decrement_stack_height();
3093
3115
  context()->Plug(eax);
3094
3116
  }
3095
3117
 
@@ -3099,6 +3121,7 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
3099
3121
  ASSERT(args->length() == 1);
3100
3122
  VisitForStackValue(args->at(0));
3101
3123
  __ CallRuntime(Runtime::kMath_sqrt, 1);
3124
+ decrement_stack_height();
3102
3125
  context()->Plug(eax);
3103
3126
  }
3104
3127
 
@@ -3115,8 +3138,10 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
3115
3138
  // InvokeFunction requires the function in edi. Move it in there.
3116
3139
  __ mov(edi, result_register());
3117
3140
  ParameterCount count(arg_count);
3118
- __ InvokeFunction(edi, count, CALL_FUNCTION);
3141
+ __ InvokeFunction(edi, count, CALL_FUNCTION,
3142
+ NullCallWrapper(), CALL_AS_METHOD);
3119
3143
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3144
+ decrement_stack_height(arg_count + 1);
3120
3145
  context()->Plug(eax);
3121
3146
  }
3122
3147
 
@@ -3129,6 +3154,7 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
3129
3154
  VisitForStackValue(args->at(1));
3130
3155
  VisitForStackValue(args->at(2));
3131
3156
  __ CallStub(&stub);
3157
+ decrement_stack_height(3);
3132
3158
  context()->Plug(eax);
3133
3159
  }
3134
3160
 
@@ -3166,8 +3192,7 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
3166
3192
  __ mov(index_2, Operand(esp, 0));
3167
3193
  __ mov(temp, index_1);
3168
3194
  __ or_(temp, Operand(index_2));
3169
- __ test(temp, Immediate(kSmiTagMask));
3170
- __ j(not_zero, &slow_case);
3195
+ __ JumpIfNotSmi(temp, &slow_case);
3171
3196
 
3172
3197
  // Check that both indices are valid.
3173
3198
  __ mov(temp, FieldOperand(object, JSArray::kLengthOffset));
@@ -3203,6 +3228,7 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
3203
3228
  __ CallRuntime(Runtime::kSwapElements, 3);
3204
3229
 
3205
3230
  __ bind(&done);
3231
+ decrement_stack_height(3);
3206
3232
  context()->Plug(eax);
3207
3233
  }
3208
3234
 
@@ -3236,7 +3262,7 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
3236
3262
 
3237
3263
  Label done, not_found;
3238
3264
  // tmp now holds finger offset as a smi.
3239
- ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3265
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3240
3266
  __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3241
3267
  __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
3242
3268
  __ j(not_equal, &not_found);
@@ -3272,8 +3298,7 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
3272
3298
  // Fail if either is a non-HeapObject.
3273
3299
  __ mov(tmp, left);
3274
3300
  __ and_(Operand(tmp), right);
3275
- __ test(Operand(tmp), Immediate(kSmiTagMask));
3276
- __ j(zero, &fail);
3301
+ __ JumpIfSmi(tmp, &fail);
3277
3302
  __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset));
3278
3303
  __ CmpInstanceType(tmp, JS_REGEXP_TYPE);
3279
3304
  __ j(not_equal, &fail);
@@ -3289,6 +3314,7 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
3289
3314
  __ mov(eax, Immediate(isolate()->factory()->true_value()));
3290
3315
  __ bind(&done);
3291
3316
 
3317
+ decrement_stack_height();
3292
3318
  context()->Plug(eax);
3293
3319
  }
3294
3320
 
@@ -3365,15 +3391,12 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3365
3391
  __ sub(Operand(esp), Immediate(2 * kPointerSize));
3366
3392
  __ cld();
3367
3393
  // Check that the array is a JSArray
3368
- __ test(array, Immediate(kSmiTagMask));
3369
- __ j(zero, &bailout);
3394
+ __ JumpIfSmi(array, &bailout);
3370
3395
  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3371
3396
  __ j(not_equal, &bailout);
3372
3397
 
3373
3398
  // Check that the array has fast elements.
3374
- __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
3375
- 1 << Map::kHasFastElements);
3376
- __ j(zero, &bailout);
3399
+ __ CheckFastElements(scratch, &bailout);
3377
3400
 
3378
3401
  // If the array has length zero, return the empty string.
3379
3402
  __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
@@ -3409,8 +3432,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3409
3432
  index,
3410
3433
  times_pointer_size,
3411
3434
  FixedArray::kHeaderSize));
3412
- __ test(string, Immediate(kSmiTagMask));
3413
- __ j(zero, &bailout);
3435
+ __ JumpIfSmi(string, &bailout);
3414
3436
  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3415
3437
  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3416
3438
  __ and_(scratch, Immediate(
@@ -3443,8 +3465,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3443
3465
 
3444
3466
  // Check that the separator is a flat ASCII string.
3445
3467
  __ mov(string, separator_operand);
3446
- __ test(string, Immediate(kSmiTagMask));
3447
- __ j(zero, &bailout);
3468
+ __ JumpIfSmi(string, &bailout);
3448
3469
  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3449
3470
  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3450
3471
  __ and_(scratch, Immediate(
@@ -3597,6 +3618,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3597
3618
  __ add(Operand(esp), Immediate(3 * kPointerSize));
3598
3619
 
3599
3620
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3621
+ decrement_stack_height();
3600
3622
  context()->Plug(eax);
3601
3623
  }
3602
3624
 
@@ -3616,6 +3638,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3616
3638
  // Prepare for calling JS runtime function.
3617
3639
  __ mov(eax, GlobalObjectOperand());
3618
3640
  __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
3641
+ increment_stack_height();
3619
3642
  }
3620
3643
 
3621
3644
  // Push the arguments ("left-to-right").
@@ -3631,13 +3654,18 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3631
3654
  RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
3632
3655
  Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(
3633
3656
  arg_count, in_loop, mode);
3634
- EmitCallIC(ic, mode, expr->id());
3657
+ __ call(ic, mode, expr->id());
3635
3658
  // Restore context register.
3636
3659
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3637
3660
  } else {
3638
3661
  // Call the C runtime function.
3639
3662
  __ CallRuntime(expr->function(), arg_count);
3640
3663
  }
3664
+ decrement_stack_height(arg_count);
3665
+ if (expr->is_jsruntime()) {
3666
+ decrement_stack_height();
3667
+ }
3668
+
3641
3669
  context()->Plug(eax);
3642
3670
  }
3643
3671
 
@@ -3650,17 +3678,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3650
3678
  Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3651
3679
 
3652
3680
  if (prop != NULL) {
3653
- if (prop->is_synthetic()) {
3654
- // Result of deleting parameters is false, even when they rewrite
3655
- // to accesses on the arguments object.
3656
- context()->Plug(false);
3657
- } else {
3658
- VisitForStackValue(prop->obj());
3659
- VisitForStackValue(prop->key());
3660
- __ push(Immediate(Smi::FromInt(strict_mode_flag())));
3661
- __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3662
- context()->Plug(eax);
3663
- }
3681
+ VisitForStackValue(prop->obj());
3682
+ VisitForStackValue(prop->key());
3683
+ __ push(Immediate(Smi::FromInt(strict_mode_flag())));
3684
+ __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3685
+ decrement_stack_height(2);
3686
+ context()->Plug(eax);
3664
3687
  } else if (var != NULL) {
3665
3688
  // Delete of an unqualified identifier is disallowed in strict mode
3666
3689
  // but "delete this" is.
@@ -3728,6 +3751,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3728
3751
  VisitForTypeofValue(expr->expression());
3729
3752
  }
3730
3753
  __ CallRuntime(Runtime::kTypeof, 1);
3754
+ decrement_stack_height();
3731
3755
  context()->Plug(eax);
3732
3756
  break;
3733
3757
  }
@@ -3736,8 +3760,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3736
3760
  Comment cmt(masm_, "[ UnaryOperation (ADD)");
3737
3761
  VisitForAccumulatorValue(expr->expression());
3738
3762
  Label no_conversion;
3739
- __ test(result_register(), Immediate(kSmiTagMask));
3740
- __ j(zero, &no_conversion);
3763
+ __ JumpIfSmi(result_register(), &no_conversion);
3741
3764
  ToNumberStub convert_stub;
3742
3765
  __ CallStub(&convert_stub);
3743
3766
  __ bind(&no_conversion);
@@ -3761,7 +3784,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3761
3784
 
3762
3785
  void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
3763
3786
  const char* comment) {
3764
- // TODO(svenpanne): Allowing format strings in Comment would be nice here...
3765
3787
  Comment cmt(masm_, comment);
3766
3788
  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3767
3789
  UnaryOverwriteMode overwrite =
@@ -3771,7 +3793,7 @@ void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
3771
3793
  // accumulator register eax.
3772
3794
  VisitForAccumulatorValue(expr->expression());
3773
3795
  SetSourcePosition(expr->position());
3774
- EmitCallIC(stub.GetCode(), NULL, expr->id());
3796
+ __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
3775
3797
  context()->Plug(eax);
3776
3798
  }
3777
3799
 
@@ -3783,12 +3805,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3783
3805
  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3784
3806
  // as the left-hand side.
3785
3807
  if (!expr->expression()->IsValidLeftHandSide()) {
3786
- VisitForEffect(expr->expression());
3808
+ ASSERT(expr->expression()->AsThrow() != NULL);
3809
+ VisitInCurrentContext(expr->expression());
3810
+ // Visiting Throw does not plug the context.
3811
+ context()->Plug(eax);
3787
3812
  return;
3788
3813
  }
3789
3814
 
3790
3815
  // Expression can only be a property, a global or a (parameter or local)
3791
- // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
3816
+ // slot.
3792
3817
  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3793
3818
  LhsKind assign_type = VARIABLE;
3794
3819
  Property* prop = expr->expression()->AsProperty();
@@ -3803,30 +3828,25 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3803
3828
  if (assign_type == VARIABLE) {
3804
3829
  ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3805
3830
  AccumulatorValueContext context(this);
3806
- EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3831
+ EmitVariableLoad(expr->expression()->AsVariableProxy());
3807
3832
  } else {
3808
3833
  // Reserve space for result of postfix operation.
3809
3834
  if (expr->is_postfix() && !context()->IsEffect()) {
3810
3835
  __ push(Immediate(Smi::FromInt(0)));
3836
+ increment_stack_height();
3811
3837
  }
3812
3838
  if (assign_type == NAMED_PROPERTY) {
3813
3839
  // Put the object both on the stack and in the accumulator.
3814
3840
  VisitForAccumulatorValue(prop->obj());
3815
3841
  __ push(eax);
3842
+ increment_stack_height();
3816
3843
  EmitNamedPropertyLoad(prop);
3817
3844
  } else {
3818
- if (prop->is_arguments_access()) {
3819
- VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
3820
- MemOperand slot_operand =
3821
- EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
3822
- __ push(slot_operand);
3823
- __ SafeSet(eax, Immediate(prop->key()->AsLiteral()->handle()));
3824
- } else {
3825
- VisitForStackValue(prop->obj());
3826
- VisitForAccumulatorValue(prop->key());
3827
- }
3845
+ VisitForStackValue(prop->obj());
3846
+ VisitForAccumulatorValue(prop->key());
3828
3847
  __ mov(edx, Operand(esp, 0));
3829
3848
  __ push(eax);
3849
+ increment_stack_height();
3830
3850
  EmitKeyedPropertyLoad(prop);
3831
3851
  }
3832
3852
  }
@@ -3842,8 +3862,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3842
3862
  // Call ToNumber only if operand is not a smi.
3843
3863
  Label no_conversion;
3844
3864
  if (ShouldInlineSmiCase(expr->op())) {
3845
- __ test(eax, Immediate(kSmiTagMask));
3846
- __ j(zero, &no_conversion, Label::kNear);
3865
+ __ JumpIfSmi(eax, &no_conversion, Label::kNear);
3847
3866
  }
3848
3867
  ToNumberStub convert_stub;
3849
3868
  __ CallStub(&convert_stub);
@@ -3858,6 +3877,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3858
3877
  switch (assign_type) {
3859
3878
  case VARIABLE:
3860
3879
  __ push(eax);
3880
+ increment_stack_height();
3861
3881
  break;
3862
3882
  case NAMED_PROPERTY:
3863
3883
  __ mov(Operand(esp, kPointerSize), eax);
@@ -3900,7 +3920,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3900
3920
  __ mov(edx, eax);
3901
3921
  __ mov(eax, Immediate(Smi::FromInt(1)));
3902
3922
  BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
3903
- EmitCallIC(stub.GetCode(), &patch_site, expr->CountId());
3923
+ __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
3924
+ patch_site.EmitPatchInfo();
3904
3925
  __ bind(&done);
3905
3926
 
3906
3927
  // Store the value returned in eax.
@@ -3930,10 +3951,11 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3930
3951
  case NAMED_PROPERTY: {
3931
3952
  __ mov(ecx, prop->key()->AsLiteral()->handle());
3932
3953
  __ pop(edx);
3954
+ decrement_stack_height();
3933
3955
  Handle<Code> ic = is_strict_mode()
3934
3956
  ? isolate()->builtins()->StoreIC_Initialize_Strict()
3935
3957
  : isolate()->builtins()->StoreIC_Initialize();
3936
- EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id());
3958
+ __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3937
3959
  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3938
3960
  if (expr->is_postfix()) {
3939
3961
  if (!context()->IsEffect()) {
@@ -3947,10 +3969,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3947
3969
  case KEYED_PROPERTY: {
3948
3970
  __ pop(ecx);
3949
3971
  __ pop(edx);
3972
+ decrement_stack_height();
3973
+ decrement_stack_height();
3950
3974
  Handle<Code> ic = is_strict_mode()
3951
3975
  ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
3952
3976
  : isolate()->builtins()->KeyedStoreIC_Initialize();
3953
- EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id());
3977
+ __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3954
3978
  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3955
3979
  if (expr->is_postfix()) {
3956
3980
  // Result is on the stack
@@ -3978,7 +4002,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
3978
4002
  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
3979
4003
  // Use a regular load, not a contextual load, to avoid a reference
3980
4004
  // error.
3981
- EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber);
4005
+ __ call(ic);
3982
4006
  PrepareForBailout(expr, TOS_REG);
3983
4007
  context()->Plug(eax);
3984
4008
  } else if (proxy != NULL &&
@@ -4001,30 +4025,18 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4001
4025
  context()->Plug(eax);
4002
4026
  } else {
4003
4027
  // This expression cannot throw a reference error at the top level.
4004
- context()->HandleExpression(expr);
4028
+ VisitInCurrentContext(expr);
4005
4029
  }
4006
4030
  }
4007
4031
 
4008
4032
 
4009
- bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
4010
- Expression* left,
4011
- Expression* right,
4012
- Label* if_true,
4013
- Label* if_false,
4014
- Label* fall_through) {
4015
- if (op != Token::EQ && op != Token::EQ_STRICT) return false;
4016
-
4017
- // Check for the pattern: typeof <expression> == <string literal>.
4018
- Literal* right_literal = right->AsLiteral();
4019
- if (right_literal == NULL) return false;
4020
- Handle<Object> right_literal_value = right_literal->handle();
4021
- if (!right_literal_value->IsString()) return false;
4022
- UnaryOperation* left_unary = left->AsUnaryOperation();
4023
- if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
4024
- Handle<String> check = Handle<String>::cast(right_literal_value);
4025
-
4033
+ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4034
+ Handle<String> check,
4035
+ Label* if_true,
4036
+ Label* if_false,
4037
+ Label* fall_through) {
4026
4038
  { AccumulatorValueContext context(this);
4027
- VisitForTypeofValue(left_unary->expression());
4039
+ VisitForTypeofValue(expr);
4028
4040
  }
4029
4041
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4030
4042
 
@@ -4046,6 +4058,10 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
4046
4058
  __ j(equal, if_true);
4047
4059
  __ cmp(eax, isolate()->factory()->false_value());
4048
4060
  Split(equal, if_true, if_false, fall_through);
4061
+ } else if (FLAG_harmony_typeof &&
4062
+ check->Equals(isolate()->heap()->null_symbol())) {
4063
+ __ cmp(eax, isolate()->factory()->null_value());
4064
+ Split(equal, if_true, if_false, fall_through);
4049
4065
  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
4050
4066
  __ cmp(eax, isolate()->factory()->undefined_value());
4051
4067
  __ j(equal, if_true);
@@ -4057,16 +4073,18 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
4057
4073
  Split(not_zero, if_true, if_false, fall_through);
4058
4074
  } else if (check->Equals(isolate()->heap()->function_symbol())) {
4059
4075
  __ JumpIfSmi(eax, if_false);
4060
- __ CmpObjectType(eax, FIRST_FUNCTION_CLASS_TYPE, edx);
4076
+ __ CmpObjectType(eax, FIRST_CALLABLE_SPEC_OBJECT_TYPE, edx);
4061
4077
  Split(above_equal, if_true, if_false, fall_through);
4062
4078
  } else if (check->Equals(isolate()->heap()->object_symbol())) {
4063
4079
  __ JumpIfSmi(eax, if_false);
4064
- __ cmp(eax, isolate()->factory()->null_value());
4065
- __ j(equal, if_true);
4066
- __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edx);
4080
+ if (!FLAG_harmony_typeof) {
4081
+ __ cmp(eax, isolate()->factory()->null_value());
4082
+ __ j(equal, if_true);
4083
+ }
4084
+ __ CmpObjectType(eax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, edx);
4067
4085
  __ j(below, if_false);
4068
- __ CmpInstanceType(edx, FIRST_FUNCTION_CLASS_TYPE);
4069
- __ j(above_equal, if_false);
4086
+ __ CmpInstanceType(edx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4087
+ __ j(above, if_false);
4070
4088
  // Check for undetectable objects => false.
4071
4089
  __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4072
4090
  1 << Map::kIsUndetectable);
@@ -4074,8 +4092,18 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
4074
4092
  } else {
4075
4093
  if (if_false != fall_through) __ jmp(if_false);
4076
4094
  }
4095
+ }
4077
4096
 
4078
- return true;
4097
+
4098
+ void FullCodeGenerator::EmitLiteralCompareUndefined(Expression* expr,
4099
+ Label* if_true,
4100
+ Label* if_false,
4101
+ Label* fall_through) {
4102
+ VisitForAccumulatorValue(expr);
4103
+ PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4104
+
4105
+ __ cmp(eax, isolate()->factory()->undefined_value());
4106
+ Split(equal, if_true, if_false, fall_through);
4079
4107
  }
4080
4108
 
4081
4109
 
@@ -4095,19 +4123,18 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4095
4123
 
4096
4124
  // First we try a fast inlined version of the compare when one of
4097
4125
  // the operands is a literal.
4098
- Token::Value op = expr->op();
4099
- Expression* left = expr->left();
4100
- Expression* right = expr->right();
4101
- if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
4126
+ if (TryLiteralCompare(expr, if_true, if_false, fall_through)) {
4102
4127
  context()->Plug(if_true, if_false);
4103
4128
  return;
4104
4129
  }
4105
4130
 
4131
+ Token::Value op = expr->op();
4106
4132
  VisitForStackValue(expr->left());
4107
4133
  switch (expr->op()) {
4108
4134
  case Token::IN:
4109
4135
  VisitForStackValue(expr->right());
4110
4136
  __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4137
+ decrement_stack_height(2);
4111
4138
  PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4112
4139
  __ cmp(eax, isolate()->factory()->true_value());
4113
4140
  Split(equal, if_true, if_false, fall_through);
@@ -4117,6 +4144,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4117
4144
  VisitForStackValue(expr->right());
4118
4145
  InstanceofStub stub(InstanceofStub::kNoFlags);
4119
4146
  __ CallStub(&stub);
4147
+ decrement_stack_height(2);
4120
4148
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4121
4149
  __ test(eax, Operand(eax));
4122
4150
  // The stub returns 0 for true.
@@ -4161,6 +4189,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4161
4189
  default:
4162
4190
  UNREACHABLE();
4163
4191
  }
4192
+ decrement_stack_height();
4164
4193
 
4165
4194
  bool inline_smi_code = ShouldInlineSmiCase(op);
4166
4195
  JumpPatchSite patch_site(masm_);
@@ -4177,7 +4206,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4177
4206
  // Record position and call the compare IC.
4178
4207
  SetSourcePosition(expr->position());
4179
4208
  Handle<Code> ic = CompareIC::GetUninitialized(op);
4180
- EmitCallIC(ic, &patch_site, expr->id());
4209
+ __ call(ic, RelocInfo::CODE_TARGET, expr->id());
4210
+ patch_site.EmitPatchInfo();
4181
4211
 
4182
4212
  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4183
4213
  __ test(eax, Operand(eax));
@@ -4209,8 +4239,7 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
4209
4239
  __ j(equal, if_true);
4210
4240
  __ cmp(eax, isolate()->factory()->undefined_value());
4211
4241
  __ j(equal, if_true);
4212
- __ test(eax, Immediate(kSmiTagMask));
4213
- __ j(zero, if_false);
4242
+ __ JumpIfSmi(eax, if_false);
4214
4243
  // It can be an undetectable object.
4215
4244
  __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
4216
4245
  __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset));
@@ -4237,58 +4266,6 @@ Register FullCodeGenerator::context_register() {
4237
4266
  }
4238
4267
 
4239
4268
 
4240
- void FullCodeGenerator::EmitCallIC(Handle<Code> ic,
4241
- RelocInfo::Mode mode,
4242
- unsigned ast_id) {
4243
- ASSERT(mode == RelocInfo::CODE_TARGET ||
4244
- mode == RelocInfo::CODE_TARGET_CONTEXT);
4245
- switch (ic->kind()) {
4246
- case Code::LOAD_IC:
4247
- __ IncrementCounter(isolate()->counters()->named_load_full(), 1);
4248
- break;
4249
- case Code::KEYED_LOAD_IC:
4250
- __ IncrementCounter(isolate()->counters()->keyed_load_full(), 1);
4251
- break;
4252
- case Code::STORE_IC:
4253
- __ IncrementCounter(isolate()->counters()->named_store_full(), 1);
4254
- break;
4255
- case Code::KEYED_STORE_IC:
4256
- __ IncrementCounter(isolate()->counters()->keyed_store_full(), 1);
4257
- default:
4258
- break;
4259
- }
4260
- __ call(ic, mode, ast_id);
4261
- }
4262
-
4263
-
4264
- void FullCodeGenerator::EmitCallIC(Handle<Code> ic,
4265
- JumpPatchSite* patch_site,
4266
- unsigned ast_id) {
4267
- Counters* counters = isolate()->counters();
4268
- switch (ic->kind()) {
4269
- case Code::LOAD_IC:
4270
- __ IncrementCounter(counters->named_load_full(), 1);
4271
- break;
4272
- case Code::KEYED_LOAD_IC:
4273
- __ IncrementCounter(counters->keyed_load_full(), 1);
4274
- break;
4275
- case Code::STORE_IC:
4276
- __ IncrementCounter(counters->named_store_full(), 1);
4277
- break;
4278
- case Code::KEYED_STORE_IC:
4279
- __ IncrementCounter(counters->keyed_store_full(), 1);
4280
- default:
4281
- break;
4282
- }
4283
- __ call(ic, RelocInfo::CODE_TARGET, ast_id);
4284
- if (patch_site != NULL && patch_site->is_bound()) {
4285
- patch_site->EmitPatchInfo();
4286
- } else {
4287
- __ nop(); // Signals no inlined code.
4288
- }
4289
- }
4290
-
4291
-
4292
4269
  void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4293
4270
  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4294
4271
  __ mov(Operand(ebp, frame_offset), value);
@@ -4300,18 +4277,38 @@ void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4300
4277
  }
4301
4278
 
4302
4279
 
4280
+ void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4281
+ Scope* declaration_scope = scope()->DeclarationScope();
4282
+ if (declaration_scope->is_global_scope()) {
4283
+ // Contexts nested in the global context have a canonical empty function
4284
+ // as their closure, not the anonymous closure containing the global
4285
+ // code. Pass a smi sentinel and let the runtime look up the empty
4286
+ // function.
4287
+ __ push(Immediate(Smi::FromInt(0)));
4288
+ } else if (declaration_scope->is_eval_scope()) {
4289
+ // Contexts nested inside eval code have the same closure as the context
4290
+ // calling eval, not the anonymous closure containing the eval code.
4291
+ // Fetch it from the context.
4292
+ __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
4293
+ } else {
4294
+ ASSERT(declaration_scope->is_function_scope());
4295
+ __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4296
+ }
4297
+ }
4298
+
4299
+
4303
4300
  // ----------------------------------------------------------------------------
4304
4301
  // Non-local control flow support.
4305
4302
 
4306
4303
  void FullCodeGenerator::EnterFinallyBlock() {
4307
4304
  // Cook return address on top of stack (smi encoded Code* delta)
4308
4305
  ASSERT(!result_register().is(edx));
4309
- __ mov(edx, Operand(esp, 0));
4306
+ __ pop(edx);
4310
4307
  __ sub(Operand(edx), Immediate(masm_->CodeObject()));
4311
- ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
4312
- ASSERT_EQ(0, kSmiTag);
4313
- __ add(edx, Operand(edx)); // Convert to smi.
4314
- __ mov(Operand(esp, 0), edx);
4308
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4309
+ STATIC_ASSERT(kSmiTag == 0);
4310
+ __ SmiTag(edx);
4311
+ __ push(edx);
4315
4312
  // Store result register while executing finally block.
4316
4313
  __ push(result_register());
4317
4314
  }
@@ -4319,15 +4316,12 @@ void FullCodeGenerator::EnterFinallyBlock() {
4319
4316
 
4320
4317
  void FullCodeGenerator::ExitFinallyBlock() {
4321
4318
  ASSERT(!result_register().is(edx));
4322
- // Restore result register from stack.
4323
4319
  __ pop(result_register());
4324
4320
  // Uncook return address.
4325
- __ mov(edx, Operand(esp, 0));
4326
- __ sar(edx, 1); // Convert smi to int.
4321
+ __ pop(edx);
4322
+ __ SmiUntag(edx);
4327
4323
  __ add(Operand(edx), Immediate(masm_->CodeObject()));
4328
- __ mov(Operand(esp, 0), edx);
4329
- // And return.
4330
- __ ret(0);
4324
+ __ jmp(Operand(edx));
4331
4325
  }
4332
4326
 
4333
4327