libv8 3.3.10.4 → 3.5.10.beta1

Sign up to get free protection for your applications and to get access to all the features.
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