libv8 3.3.10.4 → 3.5.10.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (538) hide show
  1. data/lib/libv8/scons/CHANGES.txt +24 -231
  2. data/lib/libv8/scons/LICENSE.txt +1 -1
  3. data/lib/libv8/scons/MANIFEST +0 -1
  4. data/lib/libv8/scons/PKG-INFO +1 -1
  5. data/lib/libv8/scons/README.txt +9 -9
  6. data/lib/libv8/scons/RELEASE.txt +75 -77
  7. data/lib/libv8/scons/engine/SCons/Action.py +6 -22
  8. data/lib/libv8/scons/engine/SCons/Builder.py +2 -2
  9. data/lib/libv8/scons/engine/SCons/CacheDir.py +2 -2
  10. data/lib/libv8/scons/engine/SCons/Debug.py +2 -2
  11. data/lib/libv8/scons/engine/SCons/Defaults.py +10 -24
  12. data/lib/libv8/scons/engine/SCons/Environment.py +19 -118
  13. data/lib/libv8/scons/engine/SCons/Errors.py +2 -2
  14. data/lib/libv8/scons/engine/SCons/Executor.py +2 -2
  15. data/lib/libv8/scons/engine/SCons/Job.py +2 -2
  16. data/lib/libv8/scons/engine/SCons/Memoize.py +2 -2
  17. data/lib/libv8/scons/engine/SCons/Node/Alias.py +2 -2
  18. data/lib/libv8/scons/engine/SCons/Node/FS.py +121 -281
  19. data/lib/libv8/scons/engine/SCons/Node/Python.py +2 -2
  20. data/lib/libv8/scons/engine/SCons/Node/__init__.py +5 -6
  21. data/lib/libv8/scons/engine/SCons/Options/BoolOption.py +2 -2
  22. data/lib/libv8/scons/engine/SCons/Options/EnumOption.py +2 -2
  23. data/lib/libv8/scons/engine/SCons/Options/ListOption.py +2 -2
  24. data/lib/libv8/scons/engine/SCons/Options/PackageOption.py +2 -2
  25. data/lib/libv8/scons/engine/SCons/Options/PathOption.py +2 -2
  26. data/lib/libv8/scons/engine/SCons/Options/__init__.py +2 -2
  27. data/lib/libv8/scons/engine/SCons/PathList.py +2 -2
  28. data/lib/libv8/scons/engine/SCons/Platform/__init__.py +2 -2
  29. data/lib/libv8/scons/engine/SCons/Platform/aix.py +2 -2
  30. data/lib/libv8/scons/engine/SCons/Platform/cygwin.py +2 -2
  31. data/lib/libv8/scons/engine/SCons/Platform/darwin.py +3 -27
  32. data/lib/libv8/scons/engine/SCons/Platform/hpux.py +2 -2
  33. data/lib/libv8/scons/engine/SCons/Platform/irix.py +2 -2
  34. data/lib/libv8/scons/engine/SCons/Platform/os2.py +2 -2
  35. data/lib/libv8/scons/engine/SCons/Platform/posix.py +2 -2
  36. data/lib/libv8/scons/engine/SCons/Platform/sunos.py +2 -2
  37. data/lib/libv8/scons/engine/SCons/Platform/win32.py +2 -2
  38. data/lib/libv8/scons/engine/SCons/SConf.py +2 -2
  39. data/lib/libv8/scons/engine/SCons/SConsign.py +3 -9
  40. data/lib/libv8/scons/engine/SCons/Scanner/C.py +2 -2
  41. data/lib/libv8/scons/engine/SCons/Scanner/D.py +2 -2
  42. data/lib/libv8/scons/engine/SCons/Scanner/Dir.py +2 -2
  43. data/lib/libv8/scons/engine/SCons/Scanner/Fortran.py +2 -2
  44. data/lib/libv8/scons/engine/SCons/Scanner/IDL.py +2 -2
  45. data/lib/libv8/scons/engine/SCons/Scanner/LaTeX.py +2 -5
  46. data/lib/libv8/scons/engine/SCons/Scanner/Prog.py +2 -2
  47. data/lib/libv8/scons/engine/SCons/Scanner/RC.py +3 -3
  48. data/lib/libv8/scons/engine/SCons/Scanner/__init__.py +2 -2
  49. data/lib/libv8/scons/engine/SCons/Script/Interactive.py +2 -2
  50. data/lib/libv8/scons/engine/SCons/Script/Main.py +11 -82
  51. data/lib/libv8/scons/engine/SCons/Script/SConsOptions.py +5 -5
  52. data/lib/libv8/scons/engine/SCons/Script/SConscript.py +2 -2
  53. data/lib/libv8/scons/engine/SCons/Script/__init__.py +2 -2
  54. data/lib/libv8/scons/engine/SCons/Sig.py +2 -2
  55. data/lib/libv8/scons/engine/SCons/Subst.py +2 -2
  56. data/lib/libv8/scons/engine/SCons/Taskmaster.py +2 -10
  57. data/lib/libv8/scons/engine/SCons/Tool/386asm.py +2 -2
  58. data/lib/libv8/scons/engine/SCons/Tool/BitKeeper.py +2 -2
  59. data/lib/libv8/scons/engine/SCons/Tool/CVS.py +2 -2
  60. data/lib/libv8/scons/engine/SCons/Tool/FortranCommon.py +2 -19
  61. data/lib/libv8/scons/engine/SCons/Tool/JavaCommon.py +2 -2
  62. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/__init__.py +2 -2
  63. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/arch.py +2 -2
  64. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/common.py +2 -2
  65. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/netframework.py +2 -2
  66. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/sdk.py +2 -2
  67. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/vc.py +6 -9
  68. data/lib/libv8/scons/engine/SCons/Tool/MSCommon/vs.py +2 -29
  69. data/lib/libv8/scons/engine/SCons/Tool/Perforce.py +2 -2
  70. data/lib/libv8/scons/engine/SCons/Tool/PharLapCommon.py +2 -2
  71. data/lib/libv8/scons/engine/SCons/Tool/RCS.py +2 -2
  72. data/lib/libv8/scons/engine/SCons/Tool/SCCS.py +2 -2
  73. data/lib/libv8/scons/engine/SCons/Tool/Subversion.py +2 -2
  74. data/lib/libv8/scons/engine/SCons/Tool/__init__.py +3 -3
  75. data/lib/libv8/scons/engine/SCons/Tool/aixc++.py +2 -2
  76. data/lib/libv8/scons/engine/SCons/Tool/aixcc.py +2 -2
  77. data/lib/libv8/scons/engine/SCons/Tool/aixf77.py +2 -2
  78. data/lib/libv8/scons/engine/SCons/Tool/aixlink.py +2 -2
  79. data/lib/libv8/scons/engine/SCons/Tool/applelink.py +2 -2
  80. data/lib/libv8/scons/engine/SCons/Tool/ar.py +2 -2
  81. data/lib/libv8/scons/engine/SCons/Tool/as.py +2 -2
  82. data/lib/libv8/scons/engine/SCons/Tool/bcc32.py +2 -2
  83. data/lib/libv8/scons/engine/SCons/Tool/c++.py +2 -2
  84. data/lib/libv8/scons/engine/SCons/Tool/cc.py +2 -2
  85. data/lib/libv8/scons/engine/SCons/Tool/cvf.py +2 -2
  86. data/lib/libv8/scons/engine/SCons/Tool/default.py +2 -2
  87. data/lib/libv8/scons/engine/SCons/Tool/dmd.py +7 -24
  88. data/lib/libv8/scons/engine/SCons/Tool/dvi.py +2 -2
  89. data/lib/libv8/scons/engine/SCons/Tool/dvipdf.py +2 -3
  90. data/lib/libv8/scons/engine/SCons/Tool/dvips.py +2 -3
  91. data/lib/libv8/scons/engine/SCons/Tool/f77.py +2 -2
  92. data/lib/libv8/scons/engine/SCons/Tool/f90.py +2 -2
  93. data/lib/libv8/scons/engine/SCons/Tool/f95.py +2 -2
  94. data/lib/libv8/scons/engine/SCons/Tool/filesystem.py +2 -2
  95. data/lib/libv8/scons/engine/SCons/Tool/fortran.py +2 -2
  96. data/lib/libv8/scons/engine/SCons/Tool/g++.py +2 -2
  97. data/lib/libv8/scons/engine/SCons/Tool/g77.py +2 -2
  98. data/lib/libv8/scons/engine/SCons/Tool/gas.py +2 -2
  99. data/lib/libv8/scons/engine/SCons/Tool/gcc.py +2 -2
  100. data/lib/libv8/scons/engine/SCons/Tool/gfortran.py +3 -3
  101. data/lib/libv8/scons/engine/SCons/Tool/gnulink.py +3 -2
  102. data/lib/libv8/scons/engine/SCons/Tool/gs.py +2 -2
  103. data/lib/libv8/scons/engine/SCons/Tool/hpc++.py +2 -2
  104. data/lib/libv8/scons/engine/SCons/Tool/hpcc.py +2 -2
  105. data/lib/libv8/scons/engine/SCons/Tool/hplink.py +2 -2
  106. data/lib/libv8/scons/engine/SCons/Tool/icc.py +2 -2
  107. data/lib/libv8/scons/engine/SCons/Tool/icl.py +2 -2
  108. data/lib/libv8/scons/engine/SCons/Tool/ifl.py +2 -2
  109. data/lib/libv8/scons/engine/SCons/Tool/ifort.py +2 -2
  110. data/lib/libv8/scons/engine/SCons/Tool/ilink.py +2 -2
  111. data/lib/libv8/scons/engine/SCons/Tool/ilink32.py +2 -2
  112. data/lib/libv8/scons/engine/SCons/Tool/install.py +3 -57
  113. data/lib/libv8/scons/engine/SCons/Tool/intelc.py +25 -65
  114. data/lib/libv8/scons/engine/SCons/Tool/ipkg.py +2 -2
  115. data/lib/libv8/scons/engine/SCons/Tool/jar.py +3 -9
  116. data/lib/libv8/scons/engine/SCons/Tool/javac.py +2 -2
  117. data/lib/libv8/scons/engine/SCons/Tool/javah.py +2 -2
  118. data/lib/libv8/scons/engine/SCons/Tool/latex.py +2 -3
  119. data/lib/libv8/scons/engine/SCons/Tool/lex.py +2 -2
  120. data/lib/libv8/scons/engine/SCons/Tool/link.py +5 -6
  121. data/lib/libv8/scons/engine/SCons/Tool/linkloc.py +2 -2
  122. data/lib/libv8/scons/engine/SCons/Tool/m4.py +2 -2
  123. data/lib/libv8/scons/engine/SCons/Tool/masm.py +2 -2
  124. data/lib/libv8/scons/engine/SCons/Tool/midl.py +2 -2
  125. data/lib/libv8/scons/engine/SCons/Tool/mingw.py +10 -31
  126. data/lib/libv8/scons/engine/SCons/Tool/mslib.py +2 -2
  127. data/lib/libv8/scons/engine/SCons/Tool/mslink.py +9 -61
  128. data/lib/libv8/scons/engine/SCons/Tool/mssdk.py +2 -2
  129. data/lib/libv8/scons/engine/SCons/Tool/msvc.py +11 -21
  130. data/lib/libv8/scons/engine/SCons/Tool/msvs.py +59 -477
  131. data/lib/libv8/scons/engine/SCons/Tool/mwcc.py +2 -2
  132. data/lib/libv8/scons/engine/SCons/Tool/mwld.py +2 -2
  133. data/lib/libv8/scons/engine/SCons/Tool/nasm.py +2 -2
  134. data/lib/libv8/scons/engine/SCons/Tool/packaging/__init__.py +2 -2
  135. data/lib/libv8/scons/engine/SCons/Tool/packaging/ipk.py +2 -2
  136. data/lib/libv8/scons/engine/SCons/Tool/packaging/msi.py +2 -2
  137. data/lib/libv8/scons/engine/SCons/Tool/packaging/rpm.py +2 -2
  138. data/lib/libv8/scons/engine/SCons/Tool/packaging/src_tarbz2.py +2 -2
  139. data/lib/libv8/scons/engine/SCons/Tool/packaging/src_targz.py +2 -2
  140. data/lib/libv8/scons/engine/SCons/Tool/packaging/src_zip.py +2 -2
  141. data/lib/libv8/scons/engine/SCons/Tool/packaging/tarbz2.py +2 -2
  142. data/lib/libv8/scons/engine/SCons/Tool/packaging/targz.py +2 -2
  143. data/lib/libv8/scons/engine/SCons/Tool/packaging/zip.py +2 -2
  144. data/lib/libv8/scons/engine/SCons/Tool/pdf.py +2 -2
  145. data/lib/libv8/scons/engine/SCons/Tool/pdflatex.py +2 -3
  146. data/lib/libv8/scons/engine/SCons/Tool/pdftex.py +2 -3
  147. data/lib/libv8/scons/engine/SCons/Tool/qt.py +2 -2
  148. data/lib/libv8/scons/engine/SCons/Tool/rmic.py +3 -9
  149. data/lib/libv8/scons/engine/SCons/Tool/rpcgen.py +2 -2
  150. data/lib/libv8/scons/engine/SCons/Tool/rpm.py +2 -2
  151. data/lib/libv8/scons/engine/SCons/Tool/sgiar.py +2 -2
  152. data/lib/libv8/scons/engine/SCons/Tool/sgic++.py +2 -2
  153. data/lib/libv8/scons/engine/SCons/Tool/sgicc.py +2 -2
  154. data/lib/libv8/scons/engine/SCons/Tool/sgilink.py +3 -2
  155. data/lib/libv8/scons/engine/SCons/Tool/sunar.py +2 -2
  156. data/lib/libv8/scons/engine/SCons/Tool/sunc++.py +2 -2
  157. data/lib/libv8/scons/engine/SCons/Tool/suncc.py +2 -2
  158. data/lib/libv8/scons/engine/SCons/Tool/sunf77.py +2 -2
  159. data/lib/libv8/scons/engine/SCons/Tool/sunf90.py +2 -2
  160. data/lib/libv8/scons/engine/SCons/Tool/sunf95.py +2 -2
  161. data/lib/libv8/scons/engine/SCons/Tool/sunlink.py +3 -2
  162. data/lib/libv8/scons/engine/SCons/Tool/swig.py +5 -6
  163. data/lib/libv8/scons/engine/SCons/Tool/tar.py +2 -2
  164. data/lib/libv8/scons/engine/SCons/Tool/tex.py +43 -96
  165. data/lib/libv8/scons/engine/SCons/Tool/textfile.py +2 -2
  166. data/lib/libv8/scons/engine/SCons/Tool/tlib.py +2 -2
  167. data/lib/libv8/scons/engine/SCons/Tool/wix.py +2 -2
  168. data/lib/libv8/scons/engine/SCons/Tool/yacc.py +2 -12
  169. data/lib/libv8/scons/engine/SCons/Tool/zip.py +2 -2
  170. data/lib/libv8/scons/engine/SCons/Util.py +3 -3
  171. data/lib/libv8/scons/engine/SCons/Variables/BoolVariable.py +2 -2
  172. data/lib/libv8/scons/engine/SCons/Variables/EnumVariable.py +3 -3
  173. data/lib/libv8/scons/engine/SCons/Variables/ListVariable.py +2 -2
  174. data/lib/libv8/scons/engine/SCons/Variables/PackageVariable.py +2 -2
  175. data/lib/libv8/scons/engine/SCons/Variables/PathVariable.py +2 -2
  176. data/lib/libv8/scons/engine/SCons/Variables/__init__.py +2 -2
  177. data/lib/libv8/scons/engine/SCons/Warnings.py +2 -2
  178. data/lib/libv8/scons/engine/SCons/__init__.py +6 -6
  179. data/lib/libv8/scons/engine/SCons/compat/__init__.py +2 -2
  180. data/lib/libv8/scons/engine/SCons/compat/_scons_builtins.py +2 -2
  181. data/lib/libv8/scons/engine/SCons/compat/_scons_collections.py +2 -2
  182. data/lib/libv8/scons/engine/SCons/compat/_scons_dbm.py +2 -2
  183. data/lib/libv8/scons/engine/SCons/compat/_scons_hashlib.py +2 -2
  184. data/lib/libv8/scons/engine/SCons/compat/_scons_io.py +2 -2
  185. data/lib/libv8/scons/engine/SCons/cpp.py +2 -2
  186. data/lib/libv8/scons/engine/SCons/dblite.py +1 -4
  187. data/lib/libv8/scons/engine/SCons/exitfuncs.py +2 -2
  188. data/lib/libv8/scons/scons-time.1 +3 -3
  189. data/lib/libv8/scons/scons.1 +1164 -1170
  190. data/lib/libv8/scons/sconsign.1 +3 -3
  191. data/lib/libv8/scons/script/scons +22 -22
  192. data/lib/libv8/scons/script/scons-time +2 -2
  193. data/lib/libv8/scons/script/scons.bat +4 -7
  194. data/lib/libv8/scons/script/sconsign +20 -21
  195. data/lib/libv8/scons/setup.cfg +1 -0
  196. data/lib/libv8/scons/setup.py +40 -38
  197. data/lib/libv8/v8/.gitignore +1 -1
  198. data/lib/libv8/v8/AUTHORS +2 -0
  199. data/lib/libv8/v8/ChangeLog +387 -0
  200. data/lib/libv8/v8/Makefile +171 -0
  201. data/lib/libv8/v8/SConstruct +124 -51
  202. data/lib/libv8/v8/build/README.txt +31 -14
  203. data/lib/libv8/v8/build/all.gyp +11 -4
  204. data/lib/libv8/v8/build/armu.gypi +6 -2
  205. data/lib/libv8/v8/build/common.gypi +240 -94
  206. data/lib/libv8/v8/build/gyp_v8 +32 -4
  207. data/lib/libv8/v8/build/standalone.gypi +200 -0
  208. data/lib/libv8/v8/include/v8-debug.h +0 -0
  209. data/lib/libv8/v8/include/v8-profiler.h +8 -11
  210. data/lib/libv8/v8/include/v8.h +191 -108
  211. data/lib/libv8/v8/preparser/SConscript +2 -2
  212. data/lib/libv8/v8/preparser/preparser-process.cc +3 -3
  213. data/lib/libv8/v8/preparser/preparser.gyp +42 -0
  214. data/lib/libv8/v8/src/SConscript +33 -8
  215. data/lib/libv8/v8/src/accessors.cc +77 -43
  216. data/lib/libv8/v8/src/api.cc +393 -191
  217. data/lib/libv8/v8/src/api.h +4 -8
  218. data/lib/libv8/v8/src/apinatives.js +15 -3
  219. data/lib/libv8/v8/src/arguments.h +8 -0
  220. data/lib/libv8/v8/src/arm/assembler-arm.cc +120 -120
  221. data/lib/libv8/v8/src/arm/assembler-arm.h +92 -43
  222. data/lib/libv8/v8/src/arm/builtins-arm.cc +32 -39
  223. data/lib/libv8/v8/src/arm/code-stubs-arm.cc +572 -351
  224. data/lib/libv8/v8/src/arm/code-stubs-arm.h +8 -77
  225. data/lib/libv8/v8/src/arm/codegen-arm.h +0 -2
  226. data/lib/libv8/v8/src/arm/deoptimizer-arm.cc +50 -30
  227. data/lib/libv8/v8/src/arm/disasm-arm.cc +1 -1
  228. data/lib/libv8/v8/src/arm/frames-arm.h +9 -5
  229. data/lib/libv8/v8/src/arm/full-codegen-arm.cc +331 -432
  230. data/lib/libv8/v8/src/arm/ic-arm.cc +192 -124
  231. data/lib/libv8/v8/src/arm/lithium-arm.cc +216 -232
  232. data/lib/libv8/v8/src/arm/lithium-arm.h +106 -259
  233. data/lib/libv8/v8/src/arm/lithium-codegen-arm.cc +633 -642
  234. data/lib/libv8/v8/src/arm/lithium-codegen-arm.h +4 -4
  235. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.cc +1 -3
  236. data/lib/libv8/v8/src/arm/macro-assembler-arm.cc +260 -185
  237. data/lib/libv8/v8/src/arm/macro-assembler-arm.h +45 -25
  238. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.cc +25 -13
  239. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.h +3 -0
  240. data/lib/libv8/v8/src/arm/stub-cache-arm.cc +413 -226
  241. data/lib/libv8/v8/src/array.js +38 -18
  242. data/lib/libv8/v8/src/assembler.cc +12 -5
  243. data/lib/libv8/v8/src/assembler.h +15 -9
  244. data/lib/libv8/v8/src/ast-inl.h +34 -25
  245. data/lib/libv8/v8/src/ast.cc +141 -72
  246. data/lib/libv8/v8/src/ast.h +255 -181
  247. data/lib/libv8/v8/src/bignum.cc +3 -4
  248. data/lib/libv8/v8/src/bootstrapper.cc +55 -11
  249. data/lib/libv8/v8/src/bootstrapper.h +3 -2
  250. data/lib/libv8/v8/src/builtins.cc +8 -2
  251. data/lib/libv8/v8/src/builtins.h +4 -0
  252. data/lib/libv8/v8/src/cached-powers.cc +8 -4
  253. data/lib/libv8/v8/src/checks.h +3 -3
  254. data/lib/libv8/v8/src/code-stubs.cc +173 -28
  255. data/lib/libv8/v8/src/code-stubs.h +104 -148
  256. data/lib/libv8/v8/src/codegen.cc +8 -8
  257. data/lib/libv8/v8/src/compilation-cache.cc +2 -47
  258. data/lib/libv8/v8/src/compilation-cache.h +0 -10
  259. data/lib/libv8/v8/src/compiler.cc +27 -16
  260. data/lib/libv8/v8/src/compiler.h +13 -18
  261. data/lib/libv8/v8/src/contexts.cc +107 -72
  262. data/lib/libv8/v8/src/contexts.h +70 -34
  263. data/lib/libv8/v8/src/conversions-inl.h +572 -14
  264. data/lib/libv8/v8/src/conversions.cc +9 -707
  265. data/lib/libv8/v8/src/conversions.h +23 -12
  266. data/lib/libv8/v8/src/cpu-profiler-inl.h +2 -19
  267. data/lib/libv8/v8/src/cpu-profiler.cc +4 -21
  268. data/lib/libv8/v8/src/cpu-profiler.h +8 -17
  269. data/lib/libv8/v8/src/d8-debug.cc +5 -3
  270. data/lib/libv8/v8/src/d8-debug.h +6 -7
  271. data/lib/libv8/v8/src/d8-posix.cc +1 -10
  272. data/lib/libv8/v8/src/d8.cc +721 -219
  273. data/lib/libv8/v8/src/d8.gyp +37 -12
  274. data/lib/libv8/v8/src/d8.h +141 -19
  275. data/lib/libv8/v8/src/d8.js +17 -8
  276. data/lib/libv8/v8/src/date.js +16 -5
  277. data/lib/libv8/v8/src/dateparser-inl.h +242 -39
  278. data/lib/libv8/v8/src/dateparser.cc +38 -4
  279. data/lib/libv8/v8/src/dateparser.h +170 -28
  280. data/lib/libv8/v8/src/debug-agent.cc +5 -3
  281. data/lib/libv8/v8/src/debug-agent.h +11 -7
  282. data/lib/libv8/v8/src/debug-debugger.js +65 -34
  283. data/lib/libv8/v8/src/debug.cc +30 -60
  284. data/lib/libv8/v8/src/debug.h +5 -3
  285. data/lib/libv8/v8/src/deoptimizer.cc +227 -10
  286. data/lib/libv8/v8/src/deoptimizer.h +133 -9
  287. data/lib/libv8/v8/src/disassembler.cc +22 -14
  288. data/lib/libv8/v8/src/diy-fp.cc +4 -3
  289. data/lib/libv8/v8/src/diy-fp.h +3 -3
  290. data/lib/libv8/v8/src/elements.cc +634 -0
  291. data/lib/libv8/v8/src/elements.h +95 -0
  292. data/lib/libv8/v8/src/execution.cc +5 -21
  293. data/lib/libv8/v8/src/extensions/experimental/break-iterator.cc +3 -1
  294. data/lib/libv8/v8/src/extensions/experimental/break-iterator.h +1 -1
  295. data/lib/libv8/v8/src/extensions/experimental/collator.cc +6 -2
  296. data/lib/libv8/v8/src/extensions/experimental/collator.h +1 -2
  297. data/lib/libv8/v8/src/extensions/experimental/datetime-format.cc +384 -0
  298. data/lib/libv8/v8/src/extensions/experimental/datetime-format.h +83 -0
  299. data/lib/libv8/v8/src/extensions/experimental/experimental.gyp +18 -7
  300. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.cc +12 -16
  301. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.h +1 -1
  302. data/lib/libv8/v8/src/extensions/experimental/i18n-js2c.py +126 -0
  303. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.cc +3 -4
  304. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.h +1 -1
  305. data/lib/libv8/v8/src/{shell.h → extensions/experimental/i18n-natives.h} +8 -20
  306. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.cc +45 -1
  307. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.h +21 -1
  308. data/lib/libv8/v8/src/extensions/experimental/i18n.js +211 -11
  309. data/lib/libv8/v8/src/extensions/experimental/language-matcher.cc +4 -3
  310. data/lib/libv8/v8/src/extensions/experimental/language-matcher.h +1 -1
  311. data/lib/libv8/v8/src/extensions/experimental/number-format.cc +374 -0
  312. data/lib/libv8/v8/src/extensions/experimental/number-format.h +71 -0
  313. data/lib/libv8/v8/src/factory.cc +89 -18
  314. data/lib/libv8/v8/src/factory.h +36 -8
  315. data/lib/libv8/v8/src/flag-definitions.h +11 -44
  316. data/lib/libv8/v8/src/frames-inl.h +8 -1
  317. data/lib/libv8/v8/src/frames.cc +39 -3
  318. data/lib/libv8/v8/src/frames.h +10 -3
  319. data/lib/libv8/v8/src/full-codegen.cc +311 -293
  320. data/lib/libv8/v8/src/full-codegen.h +183 -143
  321. data/lib/libv8/v8/src/func-name-inferrer.cc +29 -15
  322. data/lib/libv8/v8/src/func-name-inferrer.h +19 -9
  323. data/lib/libv8/v8/src/gdb-jit.cc +658 -55
  324. data/lib/libv8/v8/src/gdb-jit.h +6 -2
  325. data/lib/libv8/v8/src/global-handles.cc +368 -312
  326. data/lib/libv8/v8/src/global-handles.h +29 -36
  327. data/lib/libv8/v8/src/globals.h +3 -1
  328. data/lib/libv8/v8/src/handles.cc +43 -69
  329. data/lib/libv8/v8/src/handles.h +21 -16
  330. data/lib/libv8/v8/src/heap-inl.h +11 -13
  331. data/lib/libv8/v8/src/heap-profiler.cc +0 -999
  332. data/lib/libv8/v8/src/heap-profiler.h +0 -303
  333. data/lib/libv8/v8/src/heap.cc +366 -141
  334. data/lib/libv8/v8/src/heap.h +87 -26
  335. data/lib/libv8/v8/src/hydrogen-instructions.cc +192 -81
  336. data/lib/libv8/v8/src/hydrogen-instructions.h +711 -482
  337. data/lib/libv8/v8/src/hydrogen.cc +1146 -629
  338. data/lib/libv8/v8/src/hydrogen.h +100 -64
  339. data/lib/libv8/v8/src/ia32/assembler-ia32.cc +19 -0
  340. data/lib/libv8/v8/src/ia32/assembler-ia32.h +15 -2
  341. data/lib/libv8/v8/src/ia32/builtins-ia32.cc +34 -39
  342. data/lib/libv8/v8/src/ia32/code-stubs-ia32.cc +675 -377
  343. data/lib/libv8/v8/src/ia32/code-stubs-ia32.h +8 -69
  344. data/lib/libv8/v8/src/ia32/codegen-ia32.cc +1 -0
  345. data/lib/libv8/v8/src/ia32/codegen-ia32.h +0 -2
  346. data/lib/libv8/v8/src/ia32/cpu-ia32.cc +3 -2
  347. data/lib/libv8/v8/src/ia32/deoptimizer-ia32.cc +28 -3
  348. data/lib/libv8/v8/src/ia32/disasm-ia32.cc +21 -10
  349. data/lib/libv8/v8/src/ia32/frames-ia32.h +6 -5
  350. data/lib/libv8/v8/src/ia32/full-codegen-ia32.cc +459 -465
  351. data/lib/libv8/v8/src/ia32/ic-ia32.cc +196 -147
  352. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.cc +575 -650
  353. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.h +19 -21
  354. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.cc +7 -2
  355. data/lib/libv8/v8/src/ia32/lithium-ia32.cc +261 -256
  356. data/lib/libv8/v8/src/ia32/lithium-ia32.h +234 -335
  357. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.cc +224 -67
  358. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.h +63 -19
  359. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.cc +22 -8
  360. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.h +3 -0
  361. data/lib/libv8/v8/src/ia32/stub-cache-ia32.cc +380 -239
  362. data/lib/libv8/v8/src/ic.cc +198 -234
  363. data/lib/libv8/v8/src/ic.h +32 -30
  364. data/lib/libv8/v8/src/interpreter-irregexp.cc +6 -4
  365. data/lib/libv8/v8/src/isolate.cc +112 -95
  366. data/lib/libv8/v8/src/isolate.h +55 -71
  367. data/lib/libv8/v8/src/json-parser.h +486 -48
  368. data/lib/libv8/v8/src/json.js +28 -23
  369. data/lib/libv8/v8/src/jsregexp.cc +163 -208
  370. data/lib/libv8/v8/src/jsregexp.h +0 -1
  371. data/lib/libv8/v8/src/lithium-allocator-inl.h +29 -27
  372. data/lib/libv8/v8/src/lithium-allocator.cc +22 -17
  373. data/lib/libv8/v8/src/lithium-allocator.h +8 -8
  374. data/lib/libv8/v8/src/lithium.cc +16 -11
  375. data/lib/libv8/v8/src/lithium.h +31 -34
  376. data/lib/libv8/v8/src/liveedit.cc +111 -15
  377. data/lib/libv8/v8/src/liveedit.h +3 -4
  378. data/lib/libv8/v8/src/liveobjectlist.cc +116 -80
  379. data/lib/libv8/v8/src/liveobjectlist.h +2 -2
  380. data/lib/libv8/v8/src/log-inl.h +0 -4
  381. data/lib/libv8/v8/src/log-utils.cc +25 -143
  382. data/lib/libv8/v8/src/log-utils.h +13 -92
  383. data/lib/libv8/v8/src/log.cc +26 -249
  384. data/lib/libv8/v8/src/log.h +6 -17
  385. data/lib/libv8/v8/src/macros.py +9 -6
  386. data/lib/libv8/v8/src/mark-compact.cc +276 -56
  387. data/lib/libv8/v8/src/mark-compact.h +20 -0
  388. data/lib/libv8/v8/src/messages.js +93 -39
  389. data/lib/libv8/v8/src/mips/assembler-mips-inl.h +9 -3
  390. data/lib/libv8/v8/src/mips/assembler-mips.cc +297 -189
  391. data/lib/libv8/v8/src/mips/assembler-mips.h +121 -54
  392. data/lib/libv8/v8/src/mips/builtins-mips.cc +23 -24
  393. data/lib/libv8/v8/src/mips/code-stubs-mips.cc +484 -263
  394. data/lib/libv8/v8/src/mips/code-stubs-mips.h +8 -83
  395. data/lib/libv8/v8/src/mips/codegen-mips.h +0 -2
  396. data/lib/libv8/v8/src/mips/constants-mips.h +37 -11
  397. data/lib/libv8/v8/src/mips/deoptimizer-mips.cc +6 -1
  398. data/lib/libv8/v8/src/mips/frames-mips.h +8 -7
  399. data/lib/libv8/v8/src/mips/full-codegen-mips.cc +258 -419
  400. data/lib/libv8/v8/src/mips/ic-mips.cc +181 -121
  401. data/lib/libv8/v8/src/mips/macro-assembler-mips.cc +640 -382
  402. data/lib/libv8/v8/src/mips/macro-assembler-mips.h +94 -89
  403. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.cc +23 -10
  404. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.h +6 -1
  405. data/lib/libv8/v8/src/mips/simulator-mips.cc +249 -49
  406. data/lib/libv8/v8/src/mips/simulator-mips.h +25 -1
  407. data/lib/libv8/v8/src/mips/stub-cache-mips.cc +373 -161
  408. data/lib/libv8/v8/src/mirror-debugger.js +55 -8
  409. data/lib/libv8/v8/src/misc-intrinsics.h +89 -0
  410. data/lib/libv8/v8/src/mksnapshot.cc +36 -4
  411. data/lib/libv8/v8/src/natives.h +5 -2
  412. data/lib/libv8/v8/src/objects-debug.cc +73 -6
  413. data/lib/libv8/v8/src/objects-inl.h +529 -164
  414. data/lib/libv8/v8/src/objects-printer.cc +67 -12
  415. data/lib/libv8/v8/src/objects-visiting.cc +13 -2
  416. data/lib/libv8/v8/src/objects-visiting.h +41 -1
  417. data/lib/libv8/v8/src/objects.cc +2200 -1177
  418. data/lib/libv8/v8/src/objects.h +912 -283
  419. data/lib/libv8/v8/src/parser.cc +566 -371
  420. data/lib/libv8/v8/src/parser.h +35 -33
  421. data/lib/libv8/v8/src/platform-cygwin.cc +10 -25
  422. data/lib/libv8/v8/src/platform-freebsd.cc +4 -29
  423. data/lib/libv8/v8/src/platform-linux.cc +60 -57
  424. data/lib/libv8/v8/src/platform-macos.cc +4 -27
  425. data/lib/libv8/v8/src/platform-nullos.cc +3 -16
  426. data/lib/libv8/v8/src/platform-openbsd.cc +247 -85
  427. data/lib/libv8/v8/src/platform-posix.cc +43 -1
  428. data/lib/libv8/v8/src/platform-solaris.cc +151 -112
  429. data/lib/libv8/v8/src/platform-tls.h +1 -1
  430. data/lib/libv8/v8/src/platform-win32.cc +65 -39
  431. data/lib/libv8/v8/src/platform.h +17 -14
  432. data/lib/libv8/v8/src/preparse-data-format.h +2 -2
  433. data/lib/libv8/v8/src/preparse-data.h +8 -2
  434. data/lib/libv8/v8/src/preparser-api.cc +2 -18
  435. data/lib/libv8/v8/src/preparser.cc +106 -65
  436. data/lib/libv8/v8/src/preparser.h +26 -5
  437. data/lib/libv8/v8/src/prettyprinter.cc +25 -43
  438. data/lib/libv8/v8/src/profile-generator-inl.h +0 -4
  439. data/lib/libv8/v8/src/profile-generator.cc +213 -34
  440. data/lib/libv8/v8/src/profile-generator.h +9 -9
  441. data/lib/libv8/v8/src/property.h +1 -0
  442. data/lib/libv8/v8/src/proxy.js +74 -4
  443. data/lib/libv8/v8/src/regexp-macro-assembler.cc +10 -6
  444. data/lib/libv8/v8/src/regexp.js +16 -11
  445. data/lib/libv8/v8/src/rewriter.cc +24 -133
  446. data/lib/libv8/v8/src/runtime-profiler.cc +27 -151
  447. data/lib/libv8/v8/src/runtime-profiler.h +5 -31
  448. data/lib/libv8/v8/src/runtime.cc +1450 -681
  449. data/lib/libv8/v8/src/runtime.h +47 -31
  450. data/lib/libv8/v8/src/runtime.js +2 -1
  451. data/lib/libv8/v8/src/scanner-base.cc +358 -220
  452. data/lib/libv8/v8/src/scanner-base.h +30 -138
  453. data/lib/libv8/v8/src/scanner.cc +0 -18
  454. data/lib/libv8/v8/src/scanner.h +0 -15
  455. data/lib/libv8/v8/src/scopeinfo.cc +3 -1
  456. data/lib/libv8/v8/src/scopeinfo.h +1 -6
  457. data/lib/libv8/v8/src/scopes.cc +243 -253
  458. data/lib/libv8/v8/src/scopes.h +58 -109
  459. data/lib/libv8/v8/src/serialize.cc +12 -54
  460. data/lib/libv8/v8/src/serialize.h +47 -0
  461. data/lib/libv8/v8/src/small-pointer-list.h +25 -0
  462. data/lib/libv8/v8/src/spaces-inl.h +4 -50
  463. data/lib/libv8/v8/src/spaces.cc +64 -131
  464. data/lib/libv8/v8/src/spaces.h +19 -70
  465. data/lib/libv8/v8/src/string-stream.cc +3 -1
  466. data/lib/libv8/v8/src/string.js +10 -6
  467. data/lib/libv8/v8/src/strtod.cc +7 -3
  468. data/lib/libv8/v8/src/stub-cache.cc +59 -129
  469. data/lib/libv8/v8/src/stub-cache.h +42 -54
  470. data/lib/libv8/v8/src/third_party/valgrind/valgrind.h +1447 -1339
  471. data/lib/libv8/v8/src/token.cc +4 -4
  472. data/lib/libv8/v8/src/token.h +6 -5
  473. data/lib/libv8/v8/src/type-info.cc +173 -129
  474. data/lib/libv8/v8/src/type-info.h +40 -22
  475. data/lib/libv8/v8/src/utils.cc +25 -304
  476. data/lib/libv8/v8/src/utils.h +118 -3
  477. data/lib/libv8/v8/src/v8-counters.h +3 -6
  478. data/lib/libv8/v8/src/v8.cc +34 -27
  479. data/lib/libv8/v8/src/v8.h +7 -7
  480. data/lib/libv8/v8/src/v8conversions.cc +129 -0
  481. data/lib/libv8/v8/src/v8conversions.h +60 -0
  482. data/lib/libv8/v8/src/v8globals.h +15 -6
  483. data/lib/libv8/v8/src/v8natives.js +300 -78
  484. data/lib/libv8/v8/src/v8threads.cc +14 -6
  485. data/lib/libv8/v8/src/v8threads.h +4 -1
  486. data/lib/libv8/v8/src/v8utils.cc +360 -0
  487. data/lib/libv8/v8/src/v8utils.h +17 -66
  488. data/lib/libv8/v8/src/variables.cc +7 -12
  489. data/lib/libv8/v8/src/variables.h +12 -10
  490. data/lib/libv8/v8/src/version.cc +2 -2
  491. data/lib/libv8/v8/src/vm-state-inl.h +0 -41
  492. data/lib/libv8/v8/src/vm-state.h +0 -11
  493. data/lib/libv8/v8/src/weakmap.js +103 -0
  494. data/lib/libv8/v8/src/x64/assembler-x64.h +6 -3
  495. data/lib/libv8/v8/src/x64/builtins-x64.cc +25 -22
  496. data/lib/libv8/v8/src/x64/code-stubs-x64.cc +523 -250
  497. data/lib/libv8/v8/src/x64/code-stubs-x64.h +8 -71
  498. data/lib/libv8/v8/src/x64/codegen-x64.cc +1 -0
  499. data/lib/libv8/v8/src/x64/codegen-x64.h +0 -2
  500. data/lib/libv8/v8/src/x64/cpu-x64.cc +2 -1
  501. data/lib/libv8/v8/src/x64/deoptimizer-x64.cc +40 -8
  502. data/lib/libv8/v8/src/x64/disasm-x64.cc +12 -10
  503. data/lib/libv8/v8/src/x64/frames-x64.h +7 -6
  504. data/lib/libv8/v8/src/x64/full-codegen-x64.cc +310 -415
  505. data/lib/libv8/v8/src/x64/ic-x64.cc +180 -117
  506. data/lib/libv8/v8/src/x64/lithium-codegen-x64.cc +411 -523
  507. data/lib/libv8/v8/src/x64/lithium-codegen-x64.h +11 -6
  508. data/lib/libv8/v8/src/x64/lithium-x64.cc +191 -216
  509. data/lib/libv8/v8/src/x64/lithium-x64.h +112 -263
  510. data/lib/libv8/v8/src/x64/macro-assembler-x64.cc +177 -61
  511. data/lib/libv8/v8/src/x64/macro-assembler-x64.h +23 -7
  512. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.cc +21 -9
  513. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.h +6 -0
  514. data/lib/libv8/v8/src/x64/stub-cache-x64.cc +273 -107
  515. data/lib/libv8/v8/src/zone.cc +31 -22
  516. data/lib/libv8/v8/src/zone.h +12 -6
  517. data/lib/libv8/v8/tools/codemap.js +8 -0
  518. data/lib/libv8/v8/tools/gcmole/Makefile +43 -0
  519. data/lib/libv8/v8/tools/gcmole/gcmole.lua +0 -2
  520. data/lib/libv8/v8/tools/gdb-v8-support.py +154 -0
  521. data/lib/libv8/v8/tools/grokdump.py +44 -35
  522. data/lib/libv8/v8/tools/gyp/v8.gyp +94 -248
  523. data/lib/libv8/v8/tools/js2c.py +83 -52
  524. data/lib/libv8/v8/tools/linux-tick-processor +4 -6
  525. data/lib/libv8/v8/tools/ll_prof.py +3 -3
  526. data/lib/libv8/v8/tools/oom_dump/README +3 -1
  527. data/lib/libv8/v8/tools/presubmit.py +11 -4
  528. data/lib/libv8/v8/tools/profile.js +46 -2
  529. data/lib/libv8/v8/tools/splaytree.js +11 -0
  530. data/lib/libv8/v8/tools/stats-viewer.py +15 -11
  531. data/lib/libv8/v8/tools/test-wrapper-gypbuild.py +227 -0
  532. data/lib/libv8/v8/tools/test.py +28 -8
  533. data/lib/libv8/v8/tools/tickprocessor.js +0 -16
  534. data/lib/libv8/version.rb +1 -1
  535. data/libv8.gemspec +2 -2
  536. metadata +31 -19
  537. data/lib/libv8/scons/engine/SCons/Tool/f03.py +0 -63
  538. data/lib/libv8/v8/src/json-parser.cc +0 -504
@@ -33,6 +33,7 @@
33
33
  #include "hashmap.h"
34
34
  #include "lithium-allocator.h"
35
35
  #include "parser.h"
36
+ #include "scopeinfo.h"
36
37
  #include "scopes.h"
37
38
  #include "stub-cache.h"
38
39
 
@@ -68,8 +69,8 @@ HBasicBlock::HBasicBlock(HGraph* graph)
68
69
  last_instruction_index_(-1),
69
70
  deleted_phis_(4),
70
71
  parent_loop_header_(NULL),
71
- is_inline_return_target_(false) {
72
- }
72
+ is_inline_return_target_(false),
73
+ is_deoptimizing_(false) { }
73
74
 
74
75
 
75
76
  void HBasicBlock::AttachLoopInformation() {
@@ -131,16 +132,16 @@ HDeoptimize* HBasicBlock::CreateDeoptimize(
131
132
  }
132
133
 
133
134
 
134
- HSimulate* HBasicBlock::CreateSimulate(int id) {
135
+ HSimulate* HBasicBlock::CreateSimulate(int ast_id) {
135
136
  ASSERT(HasEnvironment());
136
137
  HEnvironment* environment = last_environment();
137
- ASSERT(id == AstNode::kNoNumber ||
138
- environment->closure()->shared()->VerifyBailoutId(id));
138
+ ASSERT(ast_id == AstNode::kNoNumber ||
139
+ environment->closure()->shared()->VerifyBailoutId(ast_id));
139
140
 
140
141
  int push_count = environment->push_count();
141
142
  int pop_count = environment->pop_count();
142
143
 
143
- HSimulate* instr = new(zone()) HSimulate(id, pop_count);
144
+ HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count);
144
145
  for (int i = push_count - 1; i >= 0; --i) {
145
146
  instr->AddPushedValue(environment->ExpressionStackAt(i));
146
147
  }
@@ -157,23 +158,19 @@ void HBasicBlock::Finish(HControlInstruction* end) {
157
158
  ASSERT(!IsFinished());
158
159
  AddInstruction(end);
159
160
  end_ = end;
160
- if (end->FirstSuccessor() != NULL) {
161
- end->FirstSuccessor()->RegisterPredecessor(this);
162
- if (end->SecondSuccessor() != NULL) {
163
- end->SecondSuccessor()->RegisterPredecessor(this);
164
- }
161
+ for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
162
+ it.Current()->RegisterPredecessor(this);
165
163
  }
166
164
  }
167
165
 
168
166
 
169
- void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) {
167
+ void HBasicBlock::Goto(HBasicBlock* block) {
170
168
  if (block->IsInlineReturnTarget()) {
171
169
  AddInstruction(new(zone()) HLeaveInlined);
172
170
  last_environment_ = last_environment()->outer();
173
171
  }
174
172
  AddSimulate(AstNode::kNoNumber);
175
173
  HGoto* instr = new(zone()) HGoto(block);
176
- instr->set_include_stack_check(include_stack_check);
177
174
  Finish(instr);
178
175
  }
179
176
 
@@ -197,7 +194,7 @@ void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
197
194
  }
198
195
 
199
196
 
200
- void HBasicBlock::SetJoinId(int id) {
197
+ void HBasicBlock::SetJoinId(int ast_id) {
201
198
  int length = predecessors_.length();
202
199
  ASSERT(length > 0);
203
200
  for (int i = 0; i < length; i++) {
@@ -207,8 +204,8 @@ void HBasicBlock::SetJoinId(int id) {
207
204
  // We only need to verify the ID once.
208
205
  ASSERT(i != 0 ||
209
206
  predecessor->last_environment()->closure()->shared()
210
- ->VerifyBailoutId(id));
211
- simulate->set_ast_id(id);
207
+ ->VerifyBailoutId(ast_id));
208
+ simulate->set_ast_id(ast_id);
212
209
  }
213
210
  }
214
211
 
@@ -401,8 +398,9 @@ class ReachabilityAnalyzer BASE_EMBEDDED {
401
398
  void Analyze() {
402
399
  while (!stack_.is_empty()) {
403
400
  HControlInstruction* end = stack_.RemoveLast()->end();
404
- PushBlock(end->FirstSuccessor());
405
- PushBlock(end->SecondSuccessor());
401
+ for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
402
+ PushBlock(it.Current());
403
+ }
406
404
  }
407
405
  }
408
406
 
@@ -521,6 +519,12 @@ HConstant* HGraph::GetConstantFalse() {
521
519
  return GetConstant(&constant_false_, isolate()->heap()->false_value());
522
520
  }
523
521
 
522
+
523
+ HConstant* HGraph::GetConstantHole() {
524
+ return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
525
+ }
526
+
527
+
524
528
  HGraphBuilder::HGraphBuilder(CompilationInfo* info,
525
529
  TypeFeedbackOracle* oracle)
526
530
  : function_state_(NULL),
@@ -572,7 +576,7 @@ HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
572
576
  HBasicBlock* body_exit,
573
577
  HBasicBlock* loop_successor,
574
578
  HBasicBlock* break_block) {
575
- if (body_exit != NULL) body_exit->Goto(loop_entry, true);
579
+ if (body_exit != NULL) body_exit->Goto(loop_entry);
576
580
  loop_entry->PostProcessLoopHeader(statement);
577
581
  if (break_block != NULL) {
578
582
  if (loop_successor != NULL) loop_successor->Goto(break_block);
@@ -691,8 +695,9 @@ void HGraph::PostorderLoopBlocks(HLoopInformation* loop,
691
695
  HBasicBlock* loop_header) {
692
696
  for (int i = 0; i < loop->blocks()->length(); ++i) {
693
697
  HBasicBlock* b = loop->blocks()->at(i);
694
- Postorder(b->end()->SecondSuccessor(), visited, order, loop_header);
695
- Postorder(b->end()->FirstSuccessor(), visited, order, loop_header);
698
+ for (HSuccessorIterator it(b->end()); !it.Done(); it.Advance()) {
699
+ Postorder(it.Current(), visited, order, loop_header);
700
+ }
696
701
  if (b->IsLoopHeader() && b != loop->loop_header()) {
697
702
  PostorderLoopBlocks(b->loop_information(), visited, order, loop_header);
698
703
  }
@@ -709,11 +714,13 @@ void HGraph::Postorder(HBasicBlock* block,
709
714
  visited->Add(block->block_id());
710
715
  if (block->IsLoopHeader()) {
711
716
  PostorderLoopBlocks(block->loop_information(), visited, order, loop_header);
712
- Postorder(block->end()->SecondSuccessor(), visited, order, block);
713
- Postorder(block->end()->FirstSuccessor(), visited, order, block);
717
+ for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
718
+ Postorder(it.Current(), visited, order, block);
719
+ }
714
720
  } else {
715
- Postorder(block->end()->SecondSuccessor(), visited, order, loop_header);
716
- Postorder(block->end()->FirstSuccessor(), visited, order, loop_header);
721
+ for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
722
+ Postorder(it.Current(), visited, order, loop_header);
723
+ }
717
724
  }
718
725
  ASSERT(block->end()->FirstSuccessor() == NULL ||
719
726
  order->Contains(block->end()->FirstSuccessor()) ||
@@ -729,6 +736,8 @@ void HGraph::AssignDominators() {
729
736
  HPhase phase("Assign dominators", this);
730
737
  for (int i = 0; i < blocks_.length(); ++i) {
731
738
  if (blocks_[i]->IsLoopHeader()) {
739
+ // Only the first predecessor of a loop header is from outside the loop.
740
+ // All others are back edges, and thus cannot dominate the loop header.
732
741
  blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first());
733
742
  } else {
734
743
  for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) {
@@ -738,6 +747,20 @@ void HGraph::AssignDominators() {
738
747
  }
739
748
  }
740
749
 
750
+ // Mark all blocks that are dominated by an unconditional soft deoptimize to
751
+ // prevent code motion across those blocks.
752
+ void HGraph::PropagateDeoptimizingMark() {
753
+ HPhase phase("Propagate deoptimizing mark", this);
754
+ MarkAsDeoptimizingRecursively(entry_block());
755
+ }
756
+
757
+ void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
758
+ for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
759
+ HBasicBlock* dominated = block->dominated_blocks()->at(i);
760
+ if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
761
+ MarkAsDeoptimizingRecursively(dominated);
762
+ }
763
+ }
741
764
 
742
765
  void HGraph::EliminateRedundantPhis() {
743
766
  HPhase phase("Redundant phi elimination", this);
@@ -817,6 +840,19 @@ void HGraph::EliminateUnreachablePhis() {
817
840
  }
818
841
 
819
842
 
843
+ bool HGraph::CheckPhis() {
844
+ int block_count = blocks_.length();
845
+ for (int i = 0; i < block_count; ++i) {
846
+ for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
847
+ HPhi* phi = blocks_[i]->phis()->at(j);
848
+ // We don't support phi uses of arguments for now.
849
+ if (phi->CheckFlag(HValue::kIsArguments)) return false;
850
+ }
851
+ }
852
+ return true;
853
+ }
854
+
855
+
820
856
  bool HGraph::CollectPhis() {
821
857
  int block_count = blocks_.length();
822
858
  phi_list_ = new ZoneList<HPhi*>(block_count);
@@ -824,8 +860,10 @@ bool HGraph::CollectPhis() {
824
860
  for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
825
861
  HPhi* phi = blocks_[i]->phis()->at(j);
826
862
  phi_list_->Add(phi);
827
- // We don't support phi uses of arguments for now.
828
- if (phi->CheckFlag(HValue::kIsArguments)) return false;
863
+ // Check for the hole value (from an uninitialized const).
864
+ for (int k = 0; k < phi->OperandCount(); k++) {
865
+ if (phi->OperandAt(k) == GetConstantHole()) return false;
866
+ }
829
867
  }
830
868
  }
831
869
  return true;
@@ -864,9 +902,8 @@ class HRangeAnalysis BASE_EMBEDDED {
864
902
  private:
865
903
  void TraceRange(const char* msg, ...);
866
904
  void Analyze(HBasicBlock* block);
867
- void InferControlFlowRange(HTest* test, HBasicBlock* dest);
868
- void InferControlFlowRange(Token::Value op, HValue* value, HValue* other);
869
- void InferPhiRange(HPhi* phi);
905
+ void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
906
+ void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
870
907
  void InferRange(HValue* value);
871
908
  void RollBackTo(int index);
872
909
  void AddRange(HValue* value, Range* range);
@@ -888,7 +925,7 @@ void HRangeAnalysis::TraceRange(const char* msg, ...) {
888
925
 
889
926
  void HRangeAnalysis::Analyze() {
890
927
  HPhase phase("Range analysis", graph_);
891
- Analyze(graph_->blocks()->at(0));
928
+ Analyze(graph_->entry_block());
892
929
  }
893
930
 
894
931
 
@@ -900,15 +937,15 @@ void HRangeAnalysis::Analyze(HBasicBlock* block) {
900
937
  // Infer range based on control flow.
901
938
  if (block->predecessors()->length() == 1) {
902
939
  HBasicBlock* pred = block->predecessors()->first();
903
- if (pred->end()->IsTest()) {
904
- InferControlFlowRange(HTest::cast(pred->end()), block);
940
+ if (pred->end()->IsCompareIDAndBranch()) {
941
+ InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
905
942
  }
906
943
  }
907
944
 
908
945
  // Process phi instructions.
909
946
  for (int i = 0; i < block->phis()->length(); ++i) {
910
947
  HPhi* phi = block->phis()->at(i);
911
- InferPhiRange(phi);
948
+ InferRange(phi);
912
949
  }
913
950
 
914
951
  // Go through all instructions of the current block.
@@ -927,28 +964,26 @@ void HRangeAnalysis::Analyze(HBasicBlock* block) {
927
964
  }
928
965
 
929
966
 
930
- void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
967
+ void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
968
+ HBasicBlock* dest) {
931
969
  ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
932
- if (test->value()->IsCompare()) {
933
- HCompare* compare = HCompare::cast(test->value());
934
- if (compare->GetInputRepresentation().IsInteger32()) {
935
- Token::Value op = compare->token();
936
- if (test->SecondSuccessor() == dest) {
937
- op = Token::NegateCompareOp(op);
938
- }
939
- Token::Value inverted_op = Token::InvertCompareOp(op);
940
- InferControlFlowRange(op, compare->left(), compare->right());
941
- InferControlFlowRange(inverted_op, compare->right(), compare->left());
970
+ if (test->GetInputRepresentation().IsInteger32()) {
971
+ Token::Value op = test->token();
972
+ if (test->SecondSuccessor() == dest) {
973
+ op = Token::NegateCompareOp(op);
942
974
  }
975
+ Token::Value inverted_op = Token::InvertCompareOp(op);
976
+ UpdateControlFlowRange(op, test->left(), test->right());
977
+ UpdateControlFlowRange(inverted_op, test->right(), test->left());
943
978
  }
944
979
  }
945
980
 
946
981
 
947
982
  // We know that value [op] other. Use this information to update the range on
948
983
  // value.
949
- void HRangeAnalysis::InferControlFlowRange(Token::Value op,
950
- HValue* value,
951
- HValue* other) {
984
+ void HRangeAnalysis::UpdateControlFlowRange(Token::Value op,
985
+ HValue* value,
986
+ HValue* other) {
952
987
  Range temp_range;
953
988
  Range* range = other->range() != NULL ? other->range() : &temp_range;
954
989
  Range* new_range = NULL;
@@ -979,12 +1014,6 @@ void HRangeAnalysis::InferControlFlowRange(Token::Value op,
979
1014
  }
980
1015
 
981
1016
 
982
- void HRangeAnalysis::InferPhiRange(HPhi* phi) {
983
- // TODO(twuerthinger): Infer loop phi ranges.
984
- InferRange(phi);
985
- }
986
-
987
-
988
1017
  void HRangeAnalysis::InferRange(HValue* value) {
989
1018
  ASSERT(!value->HasRange());
990
1019
  if (!value->representation().IsNone()) {
@@ -1211,8 +1240,6 @@ class HStackCheckEliminator BASE_EMBEDDED {
1211
1240
  void Process();
1212
1241
 
1213
1242
  private:
1214
- void RemoveStackCheck(HBasicBlock* block);
1215
-
1216
1243
  HGraph* graph_;
1217
1244
  };
1218
1245
 
@@ -1227,31 +1254,23 @@ void HStackCheckEliminator::Process() {
1227
1254
  if (block->IsLoopHeader()) {
1228
1255
  HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1229
1256
  HBasicBlock* dominator = back_edge;
1230
- bool back_edge_dominated_by_call = false;
1231
- while (dominator != block && !back_edge_dominated_by_call) {
1257
+ while (true) {
1232
1258
  HInstruction* instr = dominator->first();
1233
- while (instr != NULL && !back_edge_dominated_by_call) {
1259
+ while (instr != NULL) {
1234
1260
  if (instr->IsCall()) {
1235
- RemoveStackCheck(back_edge);
1236
- back_edge_dominated_by_call = true;
1261
+ block->loop_information()->stack_check()->Eliminate();
1262
+ break;
1237
1263
  }
1238
1264
  instr = instr->next();
1239
1265
  }
1240
- dominator = dominator->dominator();
1241
- }
1242
- }
1243
- }
1244
- }
1245
1266
 
1267
+ // Done when the loop header is processed.
1268
+ if (dominator == block) break;
1246
1269
 
1247
- void HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) {
1248
- HInstruction* instr = block->first();
1249
- while (instr != NULL) {
1250
- if (instr->IsGoto()) {
1251
- HGoto::cast(instr)->set_include_stack_check(false);
1252
- return;
1270
+ // Move up the dominator tree.
1271
+ dominator = dominator->dominator();
1272
+ }
1253
1273
  }
1254
- instr = instr->next();
1255
1274
  }
1256
1275
  }
1257
1276
 
@@ -1263,7 +1282,12 @@ class SparseSet {
1263
1282
  : capacity_(capacity),
1264
1283
  length_(0),
1265
1284
  dense_(zone->NewArray<int>(capacity)),
1266
- sparse_(zone->NewArray<int>(capacity)) {}
1285
+ sparse_(zone->NewArray<int>(capacity)) {
1286
+ #ifndef NVALGRIND
1287
+ // Initialize the sparse array to make valgrind happy.
1288
+ memset(sparse_, 0, sizeof(sparse_[0]) * capacity);
1289
+ #endif
1290
+ }
1267
1291
 
1268
1292
  bool Contains(int n) const {
1269
1293
  ASSERT(0 <= n && n < capacity_);
@@ -1346,7 +1370,7 @@ void HGlobalValueNumberer::Analyze() {
1346
1370
  LoopInvariantCodeMotion();
1347
1371
  }
1348
1372
  HValueMap* map = new(zone()) HValueMap();
1349
- AnalyzeBlock(graph_->blocks()->at(0), map);
1373
+ AnalyzeBlock(graph_->entry_block(), map);
1350
1374
  }
1351
1375
 
1352
1376
 
@@ -1438,37 +1462,9 @@ bool HGlobalValueNumberer::AllowCodeMotion() {
1438
1462
 
1439
1463
  bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1440
1464
  HBasicBlock* loop_header) {
1441
- // If we've disabled code motion, don't move any instructions.
1442
- if (!AllowCodeMotion()) return false;
1443
-
1444
- // If --aggressive-loop-invariant-motion, move everything except change
1445
- // instructions.
1446
- if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) {
1447
- return true;
1448
- }
1449
-
1450
- // Otherwise only move instructions that postdominate the loop header
1451
- // (i.e. are always executed inside the loop). This is to avoid
1452
- // unnecessary deoptimizations assuming the loop is executed at least
1453
- // once. TODO(fschneider): Better type feedback should give us
1454
- // information about code that was never executed.
1455
- HBasicBlock* block = instr->block();
1456
- bool result = true;
1457
- if (block != loop_header) {
1458
- for (int i = 1; i < loop_header->predecessors()->length(); ++i) {
1459
- bool found = false;
1460
- HBasicBlock* pred = loop_header->predecessors()->at(i);
1461
- while (pred != loop_header) {
1462
- if (pred == block) found = true;
1463
- pred = pred->dominator();
1464
- }
1465
- if (!found) {
1466
- result = false;
1467
- break;
1468
- }
1469
- }
1470
- }
1471
- return result;
1465
+ // If we've disabled code motion or we're in a block that unconditionally
1466
+ // deoptimizes, don't move any instructions.
1467
+ return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
1472
1468
  }
1473
1469
 
1474
1470
 
@@ -1685,8 +1681,8 @@ void HInferRepresentation::Analyze() {
1685
1681
  HValue* use = it.value();
1686
1682
  if (use->IsPhi()) {
1687
1683
  int id = HPhi::cast(use)->phi_id();
1688
- change = change ||
1689
- connected_phis[i]->UnionIsChanged(*connected_phis[id]);
1684
+ if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
1685
+ change = true;
1690
1686
  }
1691
1687
  }
1692
1688
  }
@@ -1841,6 +1837,8 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
1841
1837
  // change instructions for them.
1842
1838
  HInstruction* new_value = NULL;
1843
1839
  bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
1840
+ bool deoptimize_on_undefined =
1841
+ use_value->CheckFlag(HValue::kDeoptimizeOnUndefined);
1844
1842
  if (value->IsConstant()) {
1845
1843
  HConstant* constant = HConstant::cast(value);
1846
1844
  // Try to create a new copy of the constant with the new representation.
@@ -1850,8 +1848,8 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
1850
1848
  }
1851
1849
 
1852
1850
  if (new_value == NULL) {
1853
- new_value =
1854
- new(zone()) HChange(value, value->representation(), to, is_truncating);
1851
+ new_value = new(zone()) HChange(value, value->representation(), to,
1852
+ is_truncating, deoptimize_on_undefined);
1855
1853
  }
1856
1854
 
1857
1855
  new_value->InsertBefore(next);
@@ -1933,6 +1931,40 @@ void HGraph::InsertRepresentationChanges() {
1933
1931
  }
1934
1932
 
1935
1933
 
1934
+ void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
1935
+ if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return;
1936
+ phi->SetFlag(HValue::kDeoptimizeOnUndefined);
1937
+ for (int i = 0; i < phi->OperandCount(); ++i) {
1938
+ HValue* input = phi->OperandAt(i);
1939
+ if (input->IsPhi()) {
1940
+ RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
1941
+ }
1942
+ }
1943
+ }
1944
+
1945
+
1946
+ void HGraph::MarkDeoptimizeOnUndefined() {
1947
+ HPhase phase("MarkDeoptimizeOnUndefined", this);
1948
+ // Compute DeoptimizeOnUndefined flag for phis.
1949
+ // Any phi that can reach a use with DeoptimizeOnUndefined set must
1950
+ // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with
1951
+ // double input representation, has this flag set.
1952
+ // The flag is used by HChange tagged->double, which must deoptimize
1953
+ // if one of its uses has this flag set.
1954
+ for (int i = 0; i < phi_list()->length(); i++) {
1955
+ HPhi* phi = phi_list()->at(i);
1956
+ if (phi->representation().IsDouble()) {
1957
+ for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
1958
+ if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
1959
+ RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
1960
+ break;
1961
+ }
1962
+ }
1963
+ }
1964
+ }
1965
+ }
1966
+
1967
+
1936
1968
  void HGraph::ComputeMinusZeroChecks() {
1937
1969
  BitVector visited(GetMaximumValueID());
1938
1970
  for (int i = 0; i < blocks_.length(); ++i) {
@@ -1976,9 +2008,10 @@ FunctionState::FunctionState(HGraphBuilder* owner,
1976
2008
  HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
1977
2009
  if_true->MarkAsInlineReturnTarget();
1978
2010
  if_false->MarkAsInlineReturnTarget();
2011
+ Expression* cond = TestContext::cast(owner->ast_context())->condition();
1979
2012
  // The AstContext constructor pushed on the context stack. This newed
1980
2013
  // instance is the reason that AstContext can't be BASE_EMBEDDED.
1981
- test_context_ = new TestContext(owner, if_true, if_false);
2014
+ test_context_ = new TestContext(owner, cond, if_true, if_false);
1982
2015
  } else {
1983
2016
  function_return_ = owner->graph()->CreateBasicBlock();
1984
2017
  function_return()->MarkAsInlineReturnTarget();
@@ -2052,14 +2085,28 @@ void TestContext::ReturnValue(HValue* value) {
2052
2085
 
2053
2086
 
2054
2087
  void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2088
+ ASSERT(!instr->IsControlInstruction());
2055
2089
  owner()->AddInstruction(instr);
2056
2090
  if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2057
2091
  }
2058
2092
 
2059
2093
 
2094
+ void EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2095
+ ASSERT(!instr->HasSideEffects());
2096
+ HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2097
+ HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2098
+ instr->SetSuccessorAt(0, empty_true);
2099
+ instr->SetSuccessorAt(1, empty_false);
2100
+ owner()->current_block()->Finish(instr);
2101
+ HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
2102
+ owner()->set_current_block(join);
2103
+ }
2104
+
2105
+
2060
2106
  void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2107
+ ASSERT(!instr->IsControlInstruction());
2061
2108
  if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
2062
- owner()->Bailout("bad value context for arguments object value");
2109
+ return owner()->Bailout("bad value context for arguments object value");
2063
2110
  }
2064
2111
  owner()->AddInstruction(instr);
2065
2112
  owner()->Push(instr);
@@ -2067,7 +2114,28 @@ void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2067
2114
  }
2068
2115
 
2069
2116
 
2117
+ void ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2118
+ ASSERT(!instr->HasSideEffects());
2119
+ if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
2120
+ return owner()->Bailout("bad value context for arguments object value");
2121
+ }
2122
+ HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
2123
+ HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
2124
+ instr->SetSuccessorAt(0, materialize_true);
2125
+ instr->SetSuccessorAt(1, materialize_false);
2126
+ owner()->current_block()->Finish(instr);
2127
+ owner()->set_current_block(materialize_true);
2128
+ owner()->Push(owner()->graph()->GetConstantTrue());
2129
+ owner()->set_current_block(materialize_false);
2130
+ owner()->Push(owner()->graph()->GetConstantFalse());
2131
+ HBasicBlock* join =
2132
+ owner()->CreateJoin(materialize_true, materialize_false, ast_id);
2133
+ owner()->set_current_block(join);
2134
+ }
2135
+
2136
+
2070
2137
  void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2138
+ ASSERT(!instr->IsControlInstruction());
2071
2139
  HGraphBuilder* builder = owner();
2072
2140
  builder->AddInstruction(instr);
2073
2141
  // We expect a simulate after every expression with side effects, though
@@ -2081,22 +2149,37 @@ void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2081
2149
  }
2082
2150
 
2083
2151
 
2152
+ void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2153
+ ASSERT(!instr->HasSideEffects());
2154
+ HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2155
+ HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2156
+ instr->SetSuccessorAt(0, empty_true);
2157
+ instr->SetSuccessorAt(1, empty_false);
2158
+ owner()->current_block()->Finish(instr);
2159
+ empty_true->Goto(if_true());
2160
+ empty_false->Goto(if_false());
2161
+ owner()->set_current_block(NULL);
2162
+ }
2163
+
2164
+
2084
2165
  void TestContext::BuildBranch(HValue* value) {
2085
2166
  // We expect the graph to be in edge-split form: there is no edge that
2086
2167
  // connects a branch node to a join node. We conservatively ensure that
2087
2168
  // property by always adding an empty block on the outgoing edges of this
2088
2169
  // branch.
2089
2170
  HGraphBuilder* builder = owner();
2090
- if (value->CheckFlag(HValue::kIsArguments)) {
2171
+ if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2091
2172
  builder->Bailout("arguments object value in a test context");
2092
2173
  }
2093
2174
  HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2094
2175
  HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2095
- HTest* test = new(zone()) HTest(value, empty_true, empty_false);
2176
+ unsigned test_id = condition()->test_id();
2177
+ ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id));
2178
+ HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
2096
2179
  builder->current_block()->Finish(test);
2097
2180
 
2098
- empty_true->Goto(if_true(), false);
2099
- empty_false->Goto(if_false(), false);
2181
+ empty_true->Goto(if_true());
2182
+ empty_false->Goto(if_false());
2100
2183
  builder->set_current_block(NULL);
2101
2184
  }
2102
2185
 
@@ -2148,14 +2231,17 @@ void HGraphBuilder::VisitForTypeOf(Expression* expr) {
2148
2231
  void HGraphBuilder::VisitForControl(Expression* expr,
2149
2232
  HBasicBlock* true_block,
2150
2233
  HBasicBlock* false_block) {
2151
- TestContext for_test(this, true_block, false_block);
2234
+ TestContext for_test(this, expr, true_block, false_block);
2152
2235
  Visit(expr);
2153
2236
  }
2154
2237
 
2155
2238
 
2156
- void HGraphBuilder::VisitArgument(Expression* expr) {
2157
- CHECK_ALIVE(VisitForValue(expr));
2158
- Push(AddInstruction(new(zone()) HPushArgument(Pop())));
2239
+ HValue* HGraphBuilder::VisitArgument(Expression* expr) {
2240
+ VisitForValue(expr);
2241
+ if (HasStackOverflow() || current_block() == NULL) return NULL;
2242
+ HValue* value = Pop();
2243
+ Push(AddInstruction(new(zone()) HPushArgument(value)));
2244
+ return value;
2159
2245
  }
2160
2246
 
2161
2247
 
@@ -2188,7 +2274,9 @@ HGraph* HGraphBuilder::CreateGraph() {
2188
2274
  }
2189
2275
  SetupScope(scope);
2190
2276
  VisitDeclarations(scope->declarations());
2191
- AddInstruction(new(zone()) HStackCheck());
2277
+ HValue* context = environment()->LookupContext();
2278
+ AddInstruction(
2279
+ new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
2192
2280
 
2193
2281
  // Add an edge to the body entry. This is warty: the graph's start
2194
2282
  // environment will be used by the Lithium translation as the initial
@@ -2222,29 +2310,26 @@ HGraph* HGraphBuilder::CreateGraph() {
2222
2310
 
2223
2311
  graph()->OrderBlocks();
2224
2312
  graph()->AssignDominators();
2313
+ graph()->PropagateDeoptimizingMark();
2225
2314
  graph()->EliminateRedundantPhis();
2315
+ if (!graph()->CheckPhis()) {
2316
+ Bailout("Unsupported phi use of arguments object");
2317
+ return NULL;
2318
+ }
2226
2319
  if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
2227
2320
  if (!graph()->CollectPhis()) {
2228
- Bailout("Phi-use of arguments object");
2321
+ Bailout("Unsupported phi use of uninitialized constant");
2229
2322
  return NULL;
2230
2323
  }
2231
2324
 
2232
2325
  HInferRepresentation rep(graph());
2233
2326
  rep.Analyze();
2234
2327
 
2235
- if (FLAG_use_range) {
2236
- HRangeAnalysis rangeAnalysis(graph());
2237
- rangeAnalysis.Analyze();
2238
- }
2328
+ graph()->MarkDeoptimizeOnUndefined();
2329
+ graph()->InsertRepresentationChanges();
2239
2330
 
2240
2331
  graph()->InitializeInferredTypes();
2241
2332
  graph()->Canonicalize();
2242
- graph()->InsertRepresentationChanges();
2243
- graph()->ComputeMinusZeroChecks();
2244
-
2245
- // Eliminate redundant stack checks on backwards branches.
2246
- HStackCheckEliminator sce(graph());
2247
- sce.Process();
2248
2333
 
2249
2334
  // Perform common subexpression elimination and loop-invariant code motion.
2250
2335
  if (FLAG_use_gvn) {
@@ -2253,10 +2338,42 @@ HGraph* HGraphBuilder::CreateGraph() {
2253
2338
  gvn.Analyze();
2254
2339
  }
2255
2340
 
2341
+ if (FLAG_use_range) {
2342
+ HRangeAnalysis rangeAnalysis(graph());
2343
+ rangeAnalysis.Analyze();
2344
+ }
2345
+ graph()->ComputeMinusZeroChecks();
2346
+
2347
+ // Eliminate redundant stack checks on backwards branches.
2348
+ HStackCheckEliminator sce(graph());
2349
+ sce.Process();
2350
+
2351
+ // Replace the results of check instructions with the original value, if the
2352
+ // result is used. This is safe now, since we don't do code motion after this
2353
+ // point. It enables better register allocation since the value produced by
2354
+ // check instructions is really a copy of the original value.
2355
+ graph()->ReplaceCheckedValues();
2356
+
2256
2357
  return graph();
2257
2358
  }
2258
2359
 
2259
2360
 
2361
+ void HGraph::ReplaceCheckedValues() {
2362
+ HPhase phase("Replace checked values", this);
2363
+ for (int i = 0; i < blocks()->length(); ++i) {
2364
+ HInstruction* instr = blocks()->at(i)->first();
2365
+ while (instr != NULL) {
2366
+ if (instr->IsBoundsCheck()) {
2367
+ // Replace all uses of the checked value with the original input.
2368
+ ASSERT(instr->UseCount() > 0);
2369
+ instr->ReplaceAllUsesWith(HBoundsCheck::cast(instr)->index());
2370
+ }
2371
+ instr = instr->next();
2372
+ }
2373
+ }
2374
+ }
2375
+
2376
+
2260
2377
  HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2261
2378
  ASSERT(current_block() != NULL);
2262
2379
  current_block()->AddInstruction(instr);
@@ -2264,9 +2381,9 @@ HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2264
2381
  }
2265
2382
 
2266
2383
 
2267
- void HGraphBuilder::AddSimulate(int id) {
2384
+ void HGraphBuilder::AddSimulate(int ast_id) {
2268
2385
  ASSERT(current_block() != NULL);
2269
- current_block()->AddSimulate(id);
2386
+ current_block()->AddSimulate(ast_id);
2270
2387
  }
2271
2388
 
2272
2389
 
@@ -2298,9 +2415,6 @@ HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) {
2298
2415
 
2299
2416
 
2300
2417
  void HGraphBuilder::SetupScope(Scope* scope) {
2301
- // We don't yet handle the function name for named function expressions.
2302
- if (scope->function() != NULL) return Bailout("named function expression");
2303
-
2304
2418
  HConstant* undefined_constant = new(zone()) HConstant(
2305
2419
  isolate()->factory()->undefined_value(), Representation::Tagged());
2306
2420
  AddInstruction(undefined_constant);
@@ -2329,18 +2443,13 @@ void HGraphBuilder::SetupScope(Scope* scope) {
2329
2443
  // Handle the arguments and arguments shadow variables specially (they do
2330
2444
  // not have declarations).
2331
2445
  if (scope->arguments() != NULL) {
2332
- if (!scope->arguments()->IsStackAllocated() ||
2333
- (scope->arguments_shadow() != NULL &&
2334
- !scope->arguments_shadow()->IsStackAllocated())) {
2446
+ if (!scope->arguments()->IsStackAllocated()) {
2335
2447
  return Bailout("context-allocated arguments");
2336
2448
  }
2337
2449
  HArgumentsObject* object = new(zone()) HArgumentsObject;
2338
2450
  AddInstruction(object);
2339
2451
  graph()->SetArgumentsObject(object);
2340
2452
  environment()->Bind(scope->arguments(), object);
2341
- if (scope->arguments_shadow() != NULL) {
2342
- environment()->Bind(scope->arguments_shadow(), object);
2343
- }
2344
2453
  }
2345
2454
  }
2346
2455
 
@@ -2372,6 +2481,9 @@ void HGraphBuilder::VisitBlock(Block* stmt) {
2372
2481
  ASSERT(!HasStackOverflow());
2373
2482
  ASSERT(current_block() != NULL);
2374
2483
  ASSERT(current_block()->HasPredecessor());
2484
+ if (stmt->block_scope() != NULL) {
2485
+ return Bailout("ScopedBlock");
2486
+ }
2375
2487
  BreakAndContinueInfo break_info(stmt);
2376
2488
  { BreakAndContinueScope push(&break_info, this);
2377
2489
  CHECK_BAILOUT(VisitStatements(stmt->statements()));
@@ -2433,7 +2545,7 @@ void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
2433
2545
  cond_false = NULL;
2434
2546
  }
2435
2547
 
2436
- HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->id());
2548
+ HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
2437
2549
  set_current_block(join);
2438
2550
  }
2439
2551
  }
@@ -2511,7 +2623,7 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2511
2623
  test->if_false());
2512
2624
  } else if (context->IsEffect()) {
2513
2625
  CHECK_ALIVE(VisitForEffect(stmt->expression()));
2514
- current_block()->Goto(function_return(), false);
2626
+ current_block()->Goto(function_return());
2515
2627
  } else {
2516
2628
  ASSERT(context->IsValue());
2517
2629
  CHECK_ALIVE(VisitForValue(stmt->expression()));
@@ -2523,19 +2635,19 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2523
2635
  }
2524
2636
 
2525
2637
 
2526
- void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
2638
+ void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2527
2639
  ASSERT(!HasStackOverflow());
2528
2640
  ASSERT(current_block() != NULL);
2529
2641
  ASSERT(current_block()->HasPredecessor());
2530
- return Bailout("WithEnterStatement");
2642
+ return Bailout("WithStatement");
2531
2643
  }
2532
2644
 
2533
2645
 
2534
- void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
2646
+ void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
2535
2647
  ASSERT(!HasStackOverflow());
2536
2648
  ASSERT(current_block() != NULL);
2537
2649
  ASSERT(current_block()->HasPredecessor());
2538
- return Bailout("WithExitStatement");
2650
+ return Bailout("ExitContextStatement");
2539
2651
  }
2540
2652
 
2541
2653
 
@@ -2579,15 +2691,16 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2579
2691
  // Otherwise generate a compare and branch.
2580
2692
  CHECK_ALIVE(VisitForValue(clause->label()));
2581
2693
  HValue* label_value = Pop();
2582
- HCompare* compare =
2583
- new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT);
2694
+ HCompareIDAndBranch* compare =
2695
+ new(zone()) HCompareIDAndBranch(tag_value,
2696
+ label_value,
2697
+ Token::EQ_STRICT);
2584
2698
  compare->SetInputRepresentation(Representation::Integer32());
2585
- ASSERT(!compare->HasSideEffects());
2586
- AddInstruction(compare);
2587
2699
  HBasicBlock* body_block = graph()->CreateBasicBlock();
2588
2700
  HBasicBlock* next_test_block = graph()->CreateBasicBlock();
2589
- HTest* branch = new(zone()) HTest(compare, body_block, next_test_block);
2590
- current_block()->Finish(branch);
2701
+ compare->SetSuccessorAt(0, body_block);
2702
+ compare->SetSuccessorAt(1, next_test_block);
2703
+ current_block()->Finish(compare);
2591
2704
  set_current_block(next_test_block);
2592
2705
  }
2593
2706
 
@@ -2673,7 +2786,7 @@ void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2673
2786
  HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2674
2787
  HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2675
2788
  HValue* true_value = graph()->GetConstantTrue();
2676
- HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry);
2789
+ HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
2677
2790
  current_block()->Finish(test);
2678
2791
 
2679
2792
  HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
@@ -2701,6 +2814,21 @@ void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2701
2814
  }
2702
2815
 
2703
2816
 
2817
+ void HGraphBuilder::VisitLoopBody(IterationStatement* stmt,
2818
+ HBasicBlock* loop_entry,
2819
+ BreakAndContinueInfo* break_info) {
2820
+ BreakAndContinueScope push(break_info, this);
2821
+ AddSimulate(stmt->StackCheckId());
2822
+ HValue* context = environment()->LookupContext();
2823
+ HStackCheck* stack_check =
2824
+ new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch);
2825
+ AddInstruction(stack_check);
2826
+ ASSERT(loop_entry->IsLoopHeader());
2827
+ loop_entry->loop_information()->set_stack_check(stack_check);
2828
+ CHECK_BAILOUT(Visit(stmt->body()));
2829
+ }
2830
+
2831
+
2704
2832
  void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
2705
2833
  ASSERT(!HasStackOverflow());
2706
2834
  ASSERT(current_block() != NULL);
@@ -2708,13 +2836,11 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
2708
2836
  ASSERT(current_block() != NULL);
2709
2837
  PreProcessOsrEntry(stmt);
2710
2838
  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2711
- current_block()->Goto(loop_entry, false);
2839
+ current_block()->Goto(loop_entry);
2712
2840
  set_current_block(loop_entry);
2713
2841
 
2714
2842
  BreakAndContinueInfo break_info(stmt);
2715
- { BreakAndContinueScope push(&break_info, this);
2716
- CHECK_BAILOUT(Visit(stmt->body()));
2717
- }
2843
+ CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
2718
2844
  HBasicBlock* body_exit =
2719
2845
  JoinContinue(stmt, current_block(), break_info.continue_block());
2720
2846
  HBasicBlock* loop_successor = NULL;
@@ -2752,7 +2878,7 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2752
2878
  ASSERT(current_block() != NULL);
2753
2879
  PreProcessOsrEntry(stmt);
2754
2880
  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2755
- current_block()->Goto(loop_entry, false);
2881
+ current_block()->Goto(loop_entry);
2756
2882
  set_current_block(loop_entry);
2757
2883
 
2758
2884
  // If the condition is constant true, do not generate a branch.
@@ -2775,7 +2901,7 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2775
2901
  BreakAndContinueInfo break_info(stmt);
2776
2902
  if (current_block() != NULL) {
2777
2903
  BreakAndContinueScope push(&break_info, this);
2778
- CHECK_BAILOUT(Visit(stmt->body()));
2904
+ CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
2779
2905
  }
2780
2906
  HBasicBlock* body_exit =
2781
2907
  JoinContinue(stmt, current_block(), break_info.continue_block());
@@ -2798,7 +2924,7 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
2798
2924
  ASSERT(current_block() != NULL);
2799
2925
  PreProcessOsrEntry(stmt);
2800
2926
  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2801
- current_block()->Goto(loop_entry, false);
2927
+ current_block()->Goto(loop_entry);
2802
2928
  set_current_block(loop_entry);
2803
2929
 
2804
2930
  HBasicBlock* loop_successor = NULL;
@@ -2820,7 +2946,7 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
2820
2946
  BreakAndContinueInfo break_info(stmt);
2821
2947
  if (current_block() != NULL) {
2822
2948
  BreakAndContinueScope push(&break_info, this);
2823
- CHECK_BAILOUT(Visit(stmt->body()));
2949
+ CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
2824
2950
  }
2825
2951
  HBasicBlock* body_exit =
2826
2952
  JoinContinue(stmt, current_block(), break_info.continue_block());
@@ -2904,9 +3030,10 @@ void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
2904
3030
  }
2905
3031
  // We also have a stack overflow if the recursive compilation did.
2906
3032
  if (HasStackOverflow()) return;
3033
+ HValue* context = environment()->LookupContext();
2907
3034
  HFunctionLiteral* instr =
2908
- new(zone()) HFunctionLiteral(shared_info, expr->pretenure());
2909
- ast_context()->ReturnInstruction(instr, expr->id());
3035
+ new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
3036
+ return ast_context()->ReturnInstruction(instr, expr->id());
2910
3037
  }
2911
3038
 
2912
3039
 
@@ -2951,7 +3078,7 @@ void HGraphBuilder::VisitConditional(Conditional* expr) {
2951
3078
  HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
2952
3079
  set_current_block(join);
2953
3080
  if (join != NULL && !ast_context()->IsEffect()) {
2954
- ast_context()->ReturnValue(Pop());
3081
+ return ast_context()->ReturnValue(Pop());
2955
3082
  }
2956
3083
  }
2957
3084
  }
@@ -2995,8 +3122,15 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2995
3122
  Variable* variable = expr->AsVariable();
2996
3123
  if (variable == NULL) {
2997
3124
  return Bailout("reference to rewritten variable");
3125
+ } else if (variable->mode() == Variable::LET) {
3126
+ return Bailout("reference to let variable");
2998
3127
  } else if (variable->IsStackAllocated()) {
2999
- ast_context()->ReturnValue(environment()->Lookup(variable));
3128
+ HValue* value = environment()->Lookup(variable);
3129
+ if (variable->mode() == Variable::CONST &&
3130
+ value == graph()->GetConstantHole()) {
3131
+ return Bailout("reference to uninitialized const variable");
3132
+ }
3133
+ return ast_context()->ReturnValue(value);
3000
3134
  } else if (variable->IsContextSlot()) {
3001
3135
  if (variable->mode() == Variable::CONST) {
3002
3136
  return Bailout("reference to const context slot");
@@ -3004,7 +3138,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3004
3138
  HValue* context = BuildContextChainWalk(variable);
3005
3139
  int index = variable->AsSlot()->index();
3006
3140
  HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index);
3007
- ast_context()->ReturnInstruction(instr, expr->id());
3141
+ return ast_context()->ReturnInstruction(instr, expr->id());
3008
3142
  } else if (variable->is_global()) {
3009
3143
  LookupResult lookup;
3010
3144
  GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
@@ -3019,7 +3153,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3019
3153
  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3020
3154
  bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3021
3155
  HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
3022
- ast_context()->ReturnInstruction(instr, expr->id());
3156
+ return ast_context()->ReturnInstruction(instr, expr->id());
3023
3157
  } else {
3024
3158
  HValue* context = environment()->LookupContext();
3025
3159
  HGlobalObject* global_object = new(zone()) HGlobalObject(context);
@@ -3031,7 +3165,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3031
3165
  ast_context()->is_for_typeof());
3032
3166
  instr->set_position(expr->position());
3033
3167
  ASSERT(instr->HasSideEffects());
3034
- ast_context()->ReturnInstruction(instr, expr->id());
3168
+ return ast_context()->ReturnInstruction(instr, expr->id());
3035
3169
  }
3036
3170
  } else {
3037
3171
  return Bailout("reference to a variable which requires dynamic lookup");
@@ -3045,7 +3179,7 @@ void HGraphBuilder::VisitLiteral(Literal* expr) {
3045
3179
  ASSERT(current_block()->HasPredecessor());
3046
3180
  HConstant* instr =
3047
3181
  new(zone()) HConstant(expr->handle(), Representation::Tagged());
3048
- ast_context()->ReturnInstruction(instr, expr->id());
3182
+ return ast_context()->ReturnInstruction(instr, expr->id());
3049
3183
  }
3050
3184
 
3051
3185
 
@@ -3053,10 +3187,13 @@ void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
3053
3187
  ASSERT(!HasStackOverflow());
3054
3188
  ASSERT(current_block() != NULL);
3055
3189
  ASSERT(current_block()->HasPredecessor());
3056
- HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(),
3190
+ HValue* context = environment()->LookupContext();
3191
+
3192
+ HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
3193
+ expr->pattern(),
3057
3194
  expr->flags(),
3058
3195
  expr->literal_index());
3059
- ast_context()->ReturnInstruction(instr, expr->id());
3196
+ return ast_context()->ReturnInstruction(instr, expr->id());
3060
3197
  }
3061
3198
 
3062
3199
 
@@ -3126,9 +3263,9 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3126
3263
  // (e.g. because of code motion).
3127
3264
  HToFastProperties* result = new(zone()) HToFastProperties(Pop());
3128
3265
  AddInstruction(result);
3129
- ast_context()->ReturnValue(result);
3266
+ return ast_context()->ReturnValue(result);
3130
3267
  } else {
3131
- ast_context()->ReturnValue(Pop());
3268
+ return ast_context()->ReturnValue(Pop());
3132
3269
  }
3133
3270
  }
3134
3271
 
@@ -3139,8 +3276,10 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3139
3276
  ASSERT(current_block()->HasPredecessor());
3140
3277
  ZoneList<Expression*>* subexprs = expr->values();
3141
3278
  int length = subexprs->length();
3279
+ HValue* context = environment()->LookupContext();
3142
3280
 
3143
- HArrayLiteral* literal = new(zone()) HArrayLiteral(expr->constant_elements(),
3281
+ HArrayLiteral* literal = new(zone()) HArrayLiteral(context,
3282
+ expr->constant_elements(),
3144
3283
  length,
3145
3284
  expr->literal_index(),
3146
3285
  expr->depth());
@@ -3162,8 +3301,8 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3162
3301
 
3163
3302
  // Load the elements array before the first store.
3164
3303
  if (elements == NULL) {
3165
- elements = new(zone()) HLoadElements(literal);
3166
- AddInstruction(elements);
3304
+ elements = new(zone()) HLoadElements(literal);
3305
+ AddInstruction(elements);
3167
3306
  }
3168
3307
 
3169
3308
  HValue* key = AddInstruction(
@@ -3172,15 +3311,7 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3172
3311
  AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
3173
3312
  AddSimulate(expr->GetIdForElement(i));
3174
3313
  }
3175
- ast_context()->ReturnValue(Pop());
3176
- }
3177
-
3178
-
3179
- void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3180
- ASSERT(!HasStackOverflow());
3181
- ASSERT(current_block() != NULL);
3182
- ASSERT(current_block()->HasPredecessor());
3183
- return Bailout("CatchExtensionObject");
3314
+ return ast_context()->ReturnValue(Pop());
3184
3315
  }
3185
3316
 
3186
3317
 
@@ -3267,7 +3398,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3267
3398
  ASSERT(!name.is_null());
3268
3399
 
3269
3400
  LookupResult lookup;
3270
- ZoneMapList* types = expr->GetReceiverTypes();
3401
+ SmallMapList* types = expr->GetReceiverTypes();
3271
3402
  bool is_monomorphic = expr->IsMonomorphic() &&
3272
3403
  ComputeStoredField(types->first(), name, &lookup);
3273
3404
 
@@ -3281,7 +3412,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3281
3412
  void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3282
3413
  HValue* object,
3283
3414
  HValue* value,
3284
- ZoneMapList* types,
3415
+ SmallMapList* types,
3285
3416
  Handle<String> name) {
3286
3417
  // TODO(ager): We should recognize when the prototype chains for different
3287
3418
  // maps are identical. In that case we can avoid repeatedly generating the
@@ -3342,15 +3473,14 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3342
3473
  Drop(1);
3343
3474
  }
3344
3475
  }
3345
- ast_context()->ReturnValue(value);
3346
- return;
3476
+ return ast_context()->ReturnValue(value);
3347
3477
  }
3348
3478
  }
3349
3479
 
3350
3480
  ASSERT(join != NULL);
3351
3481
  join->SetJoinId(expr->id());
3352
3482
  set_current_block(join);
3353
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3483
+ if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
3354
3484
  }
3355
3485
 
3356
3486
 
@@ -3373,7 +3503,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3373
3503
  Handle<String> name = Handle<String>::cast(key->handle());
3374
3504
  ASSERT(!name.is_null());
3375
3505
 
3376
- ZoneMapList* types = expr->GetReceiverTypes();
3506
+ SmallMapList* types = expr->GetReceiverTypes();
3377
3507
  LookupResult lookup;
3378
3508
 
3379
3509
  if (expr->IsMonomorphic()) {
@@ -3394,13 +3524,21 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3394
3524
  value = Pop();
3395
3525
  HValue* key = Pop();
3396
3526
  HValue* object = Pop();
3397
- instr = BuildStoreKeyed(object, key, value, expr);
3527
+ bool has_side_effects = false;
3528
+ HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
3529
+ expr->position(),
3530
+ true, // is_store
3531
+ &has_side_effects);
3532
+ Push(value);
3533
+ ASSERT(has_side_effects); // Stores always have side effects.
3534
+ AddSimulate(expr->AssignmentId());
3535
+ return ast_context()->ReturnValue(Pop());
3398
3536
  }
3399
3537
  Push(value);
3400
3538
  instr->set_position(expr->position());
3401
3539
  AddInstruction(instr);
3402
3540
  if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3403
- ast_context()->ReturnValue(Pop());
3541
+ return ast_context()->ReturnValue(Pop());
3404
3542
  }
3405
3543
 
3406
3544
 
@@ -3451,6 +3589,11 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3451
3589
  BinaryOperation* operation = expr->binary_operation();
3452
3590
 
3453
3591
  if (var != NULL) {
3592
+ if (var->mode() == Variable::CONST ||
3593
+ var->mode() == Variable::LET) {
3594
+ return Bailout("unsupported let or const compound assignment");
3595
+ }
3596
+
3454
3597
  CHECK_ALIVE(VisitForValue(operation));
3455
3598
 
3456
3599
  if (var->is_global()) {
@@ -3461,6 +3604,20 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3461
3604
  } else if (var->IsStackAllocated()) {
3462
3605
  Bind(var, Top());
3463
3606
  } else if (var->IsContextSlot()) {
3607
+ // Bail out if we try to mutate a parameter value in a function using
3608
+ // the arguments object. We do not (yet) correctly handle the
3609
+ // arguments property of the function.
3610
+ if (info()->scope()->arguments() != NULL) {
3611
+ // Parameters will rewrite to context slots. We have no direct way
3612
+ // to detect that the variable is a parameter.
3613
+ int count = info()->scope()->num_parameters();
3614
+ for (int i = 0; i < count; ++i) {
3615
+ if (var == info()->scope()->parameter(i)) {
3616
+ Bailout("assignment to parameter, function uses arguments object");
3617
+ }
3618
+ }
3619
+ }
3620
+
3464
3621
  HValue* context = BuildContextChainWalk(var);
3465
3622
  int index = var->AsSlot()->index();
3466
3623
  HStoreContextSlot* instr =
@@ -3470,7 +3627,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3470
3627
  } else {
3471
3628
  return Bailout("compound assignment to lookup slot");
3472
3629
  }
3473
- ast_context()->ReturnValue(Pop());
3630
+ return ast_context()->ReturnValue(Pop());
3474
3631
 
3475
3632
  } else if (prop != NULL) {
3476
3633
  prop->RecordTypeFeedback(oracle());
@@ -3505,7 +3662,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3505
3662
  Drop(2);
3506
3663
  Push(instr);
3507
3664
  if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3508
- ast_context()->ReturnValue(Pop());
3665
+ return ast_context()->ReturnValue(Pop());
3509
3666
 
3510
3667
  } else {
3511
3668
  // Keyed property.
@@ -3514,9 +3671,14 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3514
3671
  HValue* obj = environment()->ExpressionStackAt(1);
3515
3672
  HValue* key = environment()->ExpressionStackAt(0);
3516
3673
 
3517
- HInstruction* load = BuildLoadKeyed(obj, key, prop);
3518
- PushAndAdd(load);
3519
- if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3674
+ bool has_side_effects = false;
3675
+ HValue* load = HandleKeyedElementAccess(
3676
+ obj, key, NULL, prop, expr->CompoundLoadId(), RelocInfo::kNoPosition,
3677
+ false, // is_store
3678
+ &has_side_effects);
3679
+ Push(load);
3680
+ if (has_side_effects) AddSimulate(expr->CompoundLoadId());
3681
+
3520
3682
 
3521
3683
  CHECK_ALIVE(VisitForValue(expr->value()));
3522
3684
  HValue* right = Pop();
@@ -3527,13 +3689,17 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3527
3689
  if (instr->HasSideEffects()) AddSimulate(operation->id());
3528
3690
 
3529
3691
  expr->RecordTypeFeedback(oracle());
3530
- HInstruction* store = BuildStoreKeyed(obj, key, instr, expr);
3531
- AddInstruction(store);
3692
+ HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
3693
+ RelocInfo::kNoPosition,
3694
+ true, // is_store
3695
+ &has_side_effects);
3696
+
3532
3697
  // Drop the simulated receiver, key, and value. Return the value.
3533
3698
  Drop(3);
3534
3699
  Push(instr);
3535
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3536
- ast_context()->ReturnValue(Pop());
3700
+ ASSERT(has_side_effects); // Stores always have side effects.
3701
+ AddSimulate(expr->AssignmentId());
3702
+ return ast_context()->ReturnValue(Pop());
3537
3703
  }
3538
3704
 
3539
3705
  } else {
@@ -3557,6 +3723,21 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
3557
3723
  }
3558
3724
 
3559
3725
  if (var != NULL) {
3726
+ if (var->mode() == Variable::CONST) {
3727
+ if (expr->op() != Token::INIT_CONST) {
3728
+ return Bailout("non-initializer assignment to const");
3729
+ }
3730
+ if (!var->IsStackAllocated()) {
3731
+ return Bailout("assignment to const context slot");
3732
+ }
3733
+ // We insert a use of the old value to detect unsupported uses of const
3734
+ // variables (e.g. initialization inside a loop).
3735
+ HValue* old_value = environment()->Lookup(var);
3736
+ AddInstruction(new HUseConst(old_value));
3737
+ } else if (var->mode() == Variable::LET) {
3738
+ return Bailout("unsupported assignment to let");
3739
+ }
3740
+
3560
3741
  if (proxy->IsArguments()) return Bailout("assignment to arguments");
3561
3742
 
3562
3743
  // Handle the assignment.
@@ -3567,9 +3748,24 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
3567
3748
  CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
3568
3749
  HValue* value = Pop();
3569
3750
  Bind(var, value);
3570
- ast_context()->ReturnValue(value);
3751
+ return ast_context()->ReturnValue(value);
3752
+
3753
+ } else if (var->IsContextSlot()) {
3754
+ ASSERT(var->mode() != Variable::CONST);
3755
+ // Bail out if we try to mutate a parameter value in a function using
3756
+ // the arguments object. We do not (yet) correctly handle the
3757
+ // arguments property of the function.
3758
+ if (info()->scope()->arguments() != NULL) {
3759
+ // Parameters will rewrite to context slots. We have no direct way
3760
+ // to detect that the variable is a parameter.
3761
+ int count = info()->scope()->num_parameters();
3762
+ for (int i = 0; i < count; ++i) {
3763
+ if (var == info()->scope()->parameter(i)) {
3764
+ Bailout("assignment to parameter, function uses arguments object");
3765
+ }
3766
+ }
3767
+ }
3571
3768
 
3572
- } else if (var->IsContextSlot() && var->mode() != Variable::CONST) {
3573
3769
  CHECK_ALIVE(VisitForValue(expr->value()));
3574
3770
  HValue* context = BuildContextChainWalk(var);
3575
3771
  int index = var->AsSlot()->index();
@@ -3577,7 +3773,7 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
3577
3773
  new(zone()) HStoreContextSlot(context, index, Top());
3578
3774
  AddInstruction(instr);
3579
3775
  if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3580
- ast_context()->ReturnValue(Pop());
3776
+ return ast_context()->ReturnValue(Pop());
3581
3777
 
3582
3778
  } else if (var->is_global()) {
3583
3779
  CHECK_ALIVE(VisitForValue(expr->value()));
@@ -3585,7 +3781,7 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
3585
3781
  Top(),
3586
3782
  expr->position(),
3587
3783
  expr->AssignmentId());
3588
- ast_context()->ReturnValue(Pop());
3784
+ return ast_context()->ReturnValue(Pop());
3589
3785
 
3590
3786
  } else {
3591
3787
  return Bailout("assignment to LOOKUP or const CONTEXT variable");
@@ -3609,8 +3805,9 @@ void HGraphBuilder::VisitThrow(Throw* expr) {
3609
3805
  ASSERT(ast_context()->IsEffect());
3610
3806
  CHECK_ALIVE(VisitForValue(expr->exception()));
3611
3807
 
3808
+ HValue* context = environment()->LookupContext();
3612
3809
  HValue* value = environment()->Pop();
3613
- HThrow* instr = new(zone()) HThrow(value);
3810
+ HThrow* instr = new(zone()) HThrow(context, value);
3614
3811
  instr->set_position(expr->position());
3615
3812
  AddInstruction(instr);
3616
3813
  AddSimulate(expr->id());
@@ -3682,70 +3879,299 @@ HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3682
3879
  }
3683
3880
 
3684
3881
 
3685
- HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
3686
- HValue* key,
3687
- Property* expr) {
3688
- ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3689
- AddInstruction(new(zone()) HCheckNonSmi(object));
3882
+ HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
3883
+ HValue* external_elements,
3884
+ HValue* checked_key,
3885
+ HValue* val,
3886
+ JSObject::ElementsKind elements_kind,
3887
+ bool is_store) {
3888
+ if (is_store) {
3889
+ ASSERT(val != NULL);
3890
+ switch (elements_kind) {
3891
+ case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
3892
+ HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3893
+ AddInstruction(clamp);
3894
+ val = clamp;
3895
+ break;
3896
+ }
3897
+ case JSObject::EXTERNAL_BYTE_ELEMENTS:
3898
+ case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3899
+ case JSObject::EXTERNAL_SHORT_ELEMENTS:
3900
+ case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3901
+ case JSObject::EXTERNAL_INT_ELEMENTS:
3902
+ case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
3903
+ HToInt32* floor_val = new(zone()) HToInt32(val);
3904
+ AddInstruction(floor_val);
3905
+ val = floor_val;
3906
+ break;
3907
+ }
3908
+ case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3909
+ case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3910
+ break;
3911
+ case JSObject::FAST_ELEMENTS:
3912
+ case JSObject::FAST_DOUBLE_ELEMENTS:
3913
+ case JSObject::DICTIONARY_ELEMENTS:
3914
+ case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3915
+ UNREACHABLE();
3916
+ break;
3917
+ }
3918
+ return new(zone()) HStoreKeyedSpecializedArrayElement(
3919
+ external_elements, checked_key, val, elements_kind);
3920
+ } else {
3921
+ return new(zone()) HLoadKeyedSpecializedArrayElement(
3922
+ external_elements, checked_key, elements_kind);
3923
+ }
3924
+ }
3925
+
3926
+
3927
+ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
3928
+ HValue* key,
3929
+ HValue* val,
3930
+ Expression* expr,
3931
+ bool is_store) {
3932
+ ASSERT(expr->IsMonomorphic());
3690
3933
  Handle<Map> map = expr->GetMonomorphicReceiverType();
3691
- ASSERT(map->has_fast_elements());
3692
- AddInstruction(new(zone()) HCheckMap(object, map));
3693
- bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3694
- HLoadElements* elements = new(zone()) HLoadElements(object);
3934
+ if (!map->has_fast_elements() &&
3935
+ !map->has_fast_double_elements() &&
3936
+ !map->has_external_array_elements()) {
3937
+ return is_store ? BuildStoreKeyedGeneric(object, key, val)
3938
+ : BuildLoadKeyedGeneric(object, key);
3939
+ }
3940
+ AddInstruction(new(zone()) HCheckNonSmi(object));
3941
+ HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
3942
+ HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
3943
+ bool fast_double_elements = map->has_fast_double_elements();
3944
+ if (is_store && map->has_fast_elements()) {
3945
+ AddInstruction(new(zone()) HCheckMap(
3946
+ elements, isolate()->factory()->fixed_array_map()));
3947
+ }
3695
3948
  HInstruction* length = NULL;
3696
- if (is_array) {
3697
- length = AddInstruction(new(zone()) HJSArrayLength(object));
3698
- AddInstruction(new(zone()) HBoundsCheck(key, length));
3699
- AddInstruction(elements);
3949
+ HInstruction* checked_key = NULL;
3950
+ if (map->has_external_array_elements()) {
3951
+ length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
3952
+ checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3953
+ HLoadExternalArrayPointer* external_elements =
3954
+ new(zone()) HLoadExternalArrayPointer(elements);
3955
+ AddInstruction(external_elements);
3956
+ return BuildExternalArrayElementAccess(external_elements, checked_key,
3957
+ val, map->elements_kind(), is_store);
3958
+ }
3959
+ ASSERT(map->has_fast_elements() || fast_double_elements);
3960
+ if (map->instance_type() == JS_ARRAY_TYPE) {
3961
+ length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck));
3962
+ } else {
3963
+ length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
3964
+ }
3965
+ checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3966
+ if (is_store) {
3967
+ if (fast_double_elements) {
3968
+ return new(zone()) HStoreKeyedFastDoubleElement(elements,
3969
+ checked_key,
3970
+ val);
3971
+ } else {
3972
+ return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
3973
+ }
3700
3974
  } else {
3701
- AddInstruction(elements);
3702
- length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3703
- AddInstruction(new(zone()) HBoundsCheck(key, length));
3975
+ if (fast_double_elements) {
3976
+ return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
3977
+ } else {
3978
+ return new(zone()) HLoadKeyedFastElement(elements, checked_key);
3979
+ }
3704
3980
  }
3705
- return new(zone()) HLoadKeyedFastElement(elements, key);
3706
3981
  }
3707
3982
 
3708
3983
 
3709
- HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement(
3710
- HValue* object,
3711
- HValue* key,
3712
- Property* expr) {
3713
- ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3984
+ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
3985
+ HValue* key,
3986
+ HValue* val,
3987
+ Expression* prop,
3988
+ int ast_id,
3989
+ int position,
3990
+ bool is_store,
3991
+ bool* has_side_effects) {
3992
+ *has_side_effects = false;
3714
3993
  AddInstruction(new(zone()) HCheckNonSmi(object));
3715
- Handle<Map> map = expr->GetMonomorphicReceiverType();
3716
- ASSERT(!map->has_fast_elements());
3717
- ASSERT(map->has_external_array_elements());
3718
- AddInstruction(new(zone()) HCheckMap(object, map));
3719
- HLoadElements* elements = new(zone()) HLoadElements(object);
3720
- AddInstruction(elements);
3721
- HInstruction* length = new(zone()) HExternalArrayLength(elements);
3722
- AddInstruction(length);
3723
- AddInstruction(new(zone()) HBoundsCheck(key, length));
3724
- HLoadExternalArrayPointer* external_elements =
3725
- new(zone()) HLoadExternalArrayPointer(elements);
3726
- AddInstruction(external_elements);
3727
- HLoadKeyedSpecializedArrayElement* pixel_array_value =
3728
- new(zone()) HLoadKeyedSpecializedArrayElement(
3729
- external_elements, key, expr->external_array_type());
3730
- return pixel_array_value;
3994
+ AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
3995
+ SmallMapList* maps = prop->GetReceiverTypes();
3996
+ bool todo_external_array = false;
3997
+
3998
+ static const int kNumElementTypes = JSObject::kElementsKindCount;
3999
+ bool type_todo[kNumElementTypes];
4000
+ for (int i = 0; i < kNumElementTypes; ++i) {
4001
+ type_todo[i] = false;
4002
+ }
4003
+
4004
+ for (int i = 0; i < maps->length(); ++i) {
4005
+ ASSERT(maps->at(i)->IsMap());
4006
+ type_todo[maps->at(i)->elements_kind()] = true;
4007
+ if (maps->at(i)->elements_kind()
4008
+ >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
4009
+ todo_external_array = true;
4010
+ }
4011
+ }
4012
+
4013
+ HBasicBlock* join = graph()->CreateBasicBlock();
4014
+
4015
+ HInstruction* elements_kind_instr =
4016
+ AddInstruction(new(zone()) HElementsKind(object));
4017
+ HCompareConstantEqAndBranch* elements_kind_branch = NULL;
4018
+ HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
4019
+ HLoadExternalArrayPointer* external_elements = NULL;
4020
+ HInstruction* checked_key = NULL;
4021
+
4022
+ // FAST_ELEMENTS is assumed to be the first case.
4023
+ STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
4024
+
4025
+ for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS;
4026
+ elements_kind <= JSObject::LAST_ELEMENTS_KIND;
4027
+ elements_kind = JSObject::ElementsKind(elements_kind + 1)) {
4028
+ // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we
4029
+ // need to add some code that's executed for all external array cases.
4030
+ STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
4031
+ JSObject::LAST_ELEMENTS_KIND);
4032
+ if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
4033
+ && todo_external_array) {
4034
+ HInstruction* length =
4035
+ AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
4036
+ checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4037
+ external_elements = new(zone()) HLoadExternalArrayPointer(elements);
4038
+ AddInstruction(external_elements);
4039
+ }
4040
+ if (type_todo[elements_kind]) {
4041
+ HBasicBlock* if_true = graph()->CreateBasicBlock();
4042
+ HBasicBlock* if_false = graph()->CreateBasicBlock();
4043
+ elements_kind_branch = new(zone()) HCompareConstantEqAndBranch(
4044
+ elements_kind_instr, elements_kind, Token::EQ_STRICT);
4045
+ elements_kind_branch->SetSuccessorAt(0, if_true);
4046
+ elements_kind_branch->SetSuccessorAt(1, if_false);
4047
+ current_block()->Finish(elements_kind_branch);
4048
+
4049
+ set_current_block(if_true);
4050
+ HInstruction* access;
4051
+ if (elements_kind == JSObject::FAST_ELEMENTS ||
4052
+ elements_kind == JSObject::FAST_DOUBLE_ELEMENTS) {
4053
+ bool fast_double_elements =
4054
+ elements_kind == JSObject::FAST_DOUBLE_ELEMENTS;
4055
+ if (is_store && elements_kind == JSObject::FAST_ELEMENTS) {
4056
+ AddInstruction(new(zone()) HCheckMap(
4057
+ elements, isolate()->factory()->fixed_array_map(),
4058
+ elements_kind_branch));
4059
+ }
4060
+ HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
4061
+ HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
4062
+ HHasInstanceTypeAndBranch* typecheck =
4063
+ new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
4064
+ typecheck->SetSuccessorAt(0, if_jsarray);
4065
+ typecheck->SetSuccessorAt(1, if_fastobject);
4066
+ current_block()->Finish(typecheck);
4067
+
4068
+ set_current_block(if_jsarray);
4069
+ HInstruction* length = new(zone()) HJSArrayLength(object, typecheck);
4070
+ AddInstruction(length);
4071
+ checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4072
+ if (is_store) {
4073
+ if (fast_double_elements) {
4074
+ access = AddInstruction(
4075
+ new(zone()) HStoreKeyedFastDoubleElement(elements,
4076
+ checked_key,
4077
+ val));
4078
+ } else {
4079
+ access = AddInstruction(
4080
+ new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4081
+ }
4082
+ } else {
4083
+ if (fast_double_elements) {
4084
+ access = AddInstruction(
4085
+ new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
4086
+ } else {
4087
+ access = AddInstruction(
4088
+ new(zone()) HLoadKeyedFastElement(elements, checked_key));
4089
+ }
4090
+ Push(access);
4091
+ }
4092
+ *has_side_effects |= access->HasSideEffects();
4093
+ if (position != -1) {
4094
+ access->set_position(position);
4095
+ }
4096
+ if_jsarray->Goto(join);
4097
+
4098
+ set_current_block(if_fastobject);
4099
+ length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
4100
+ checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4101
+ if (is_store) {
4102
+ if (fast_double_elements) {
4103
+ access = AddInstruction(
4104
+ new(zone()) HStoreKeyedFastDoubleElement(elements,
4105
+ checked_key,
4106
+ val));
4107
+ } else {
4108
+ access = AddInstruction(
4109
+ new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4110
+ }
4111
+ } else {
4112
+ if (fast_double_elements) {
4113
+ access = AddInstruction(
4114
+ new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
4115
+ } else {
4116
+ access = AddInstruction(
4117
+ new(zone()) HLoadKeyedFastElement(elements, checked_key));
4118
+ }
4119
+ }
4120
+ } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) {
4121
+ if (is_store) {
4122
+ access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
4123
+ } else {
4124
+ access = AddInstruction(BuildLoadKeyedGeneric(object, key));
4125
+ }
4126
+ } else { // External array elements.
4127
+ access = AddInstruction(BuildExternalArrayElementAccess(
4128
+ external_elements, checked_key, val, elements_kind, is_store));
4129
+ }
4130
+ *has_side_effects |= access->HasSideEffects();
4131
+ access->set_position(position);
4132
+ if (!is_store) {
4133
+ Push(access);
4134
+ }
4135
+ current_block()->Goto(join);
4136
+ set_current_block(if_false);
4137
+ }
4138
+ }
4139
+
4140
+ // Deopt if none of the cases matched.
4141
+ current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
4142
+ join->SetJoinId(ast_id);
4143
+ set_current_block(join);
4144
+ return is_store ? NULL : Pop();
3731
4145
  }
3732
4146
 
3733
4147
 
3734
- HInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj,
3735
- HValue* key,
3736
- Property* prop) {
3737
- if (prop->IsMonomorphic()) {
3738
- Handle<Map> receiver_type(prop->GetMonomorphicReceiverType());
3739
- // An object has either fast elements or pixel array elements, but never
3740
- // both. Pixel array maps that are assigned to pixel array elements are
3741
- // always created with the fast elements flag cleared.
3742
- if (receiver_type->has_external_array_elements()) {
3743
- return BuildLoadKeyedSpecializedArrayElement(obj, key, prop);
3744
- } else if (receiver_type->has_fast_elements()) {
3745
- return BuildLoadKeyedFastElement(obj, key, prop);
4148
+ HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
4149
+ HValue* key,
4150
+ HValue* val,
4151
+ Expression* expr,
4152
+ int ast_id,
4153
+ int position,
4154
+ bool is_store,
4155
+ bool* has_side_effects) {
4156
+ ASSERT(!expr->IsPropertyName());
4157
+ HInstruction* instr = NULL;
4158
+ if (expr->IsMonomorphic()) {
4159
+ instr = BuildMonomorphicElementAccess(obj, key, val, expr, is_store);
4160
+ } else if (expr->GetReceiverTypes() != NULL &&
4161
+ !expr->GetReceiverTypes()->is_empty()) {
4162
+ return HandlePolymorphicElementAccess(
4163
+ obj, key, val, expr, ast_id, position, is_store, has_side_effects);
4164
+ } else {
4165
+ if (is_store) {
4166
+ instr = BuildStoreKeyedGeneric(obj, key, val);
4167
+ } else {
4168
+ instr = BuildLoadKeyedGeneric(obj, key);
3746
4169
  }
3747
4170
  }
3748
- return BuildLoadKeyedGeneric(obj, key);
4171
+ instr->set_position(position);
4172
+ AddInstruction(instr);
4173
+ *has_side_effects = instr->HasSideEffects();
4174
+ return instr;
3749
4175
  }
3750
4176
 
3751
4177
 
@@ -3761,85 +4187,6 @@ HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3761
4187
  function_strict_mode());
3762
4188
  }
3763
4189
 
3764
-
3765
- HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3766
- HValue* key,
3767
- HValue* val,
3768
- Expression* expr) {
3769
- ASSERT(expr->IsMonomorphic());
3770
- AddInstruction(new(zone()) HCheckNonSmi(object));
3771
- Handle<Map> map = expr->GetMonomorphicReceiverType();
3772
- ASSERT(map->has_fast_elements());
3773
- AddInstruction(new(zone()) HCheckMap(object, map));
3774
- HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
3775
- AddInstruction(new(zone()) HCheckMap(
3776
- elements, isolate()->factory()->fixed_array_map()));
3777
- bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3778
- HInstruction* length = NULL;
3779
- if (is_array) {
3780
- length = AddInstruction(new(zone()) HJSArrayLength(object));
3781
- } else {
3782
- length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3783
- }
3784
- AddInstruction(new(zone()) HBoundsCheck(key, length));
3785
- return new(zone()) HStoreKeyedFastElement(elements, key, val);
3786
- }
3787
-
3788
-
3789
- HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
3790
- HValue* object,
3791
- HValue* key,
3792
- HValue* val,
3793
- Expression* expr) {
3794
- ASSERT(expr->IsMonomorphic());
3795
- AddInstruction(new(zone()) HCheckNonSmi(object));
3796
- Handle<Map> map = expr->GetMonomorphicReceiverType();
3797
- ASSERT(!map->has_fast_elements());
3798
- ASSERT(map->has_external_array_elements());
3799
- AddInstruction(new(zone()) HCheckMap(object, map));
3800
- HLoadElements* elements = new(zone()) HLoadElements(object);
3801
- AddInstruction(elements);
3802
- HInstruction* length = AddInstruction(
3803
- new(zone()) HExternalArrayLength(elements));
3804
- AddInstruction(new(zone()) HBoundsCheck(key, length));
3805
- HLoadExternalArrayPointer* external_elements =
3806
- new(zone()) HLoadExternalArrayPointer(elements);
3807
- AddInstruction(external_elements);
3808
- if (expr->external_array_type() == kExternalPixelArray) {
3809
- HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3810
- AddInstruction(clamp);
3811
- val = clamp;
3812
- }
3813
- return new(zone()) HStoreKeyedSpecializedArrayElement(
3814
- external_elements,
3815
- key,
3816
- val,
3817
- expr->external_array_type());
3818
- }
3819
-
3820
-
3821
- HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object,
3822
- HValue* key,
3823
- HValue* value,
3824
- Expression* expr) {
3825
- if (expr->IsMonomorphic()) {
3826
- Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3827
- // An object has either fast elements or external array elements, but
3828
- // never both. Pixel array maps that are assigned to pixel array elements
3829
- // are always created with the fast elements flag cleared.
3830
- if (receiver_type->has_external_array_elements()) {
3831
- return BuildStoreKeyedSpecializedArrayElement(object,
3832
- key,
3833
- value,
3834
- expr);
3835
- } else if (receiver_type->has_fast_elements()) {
3836
- return BuildStoreKeyedFastElement(object, key, value, expr);
3837
- }
3838
- }
3839
- return BuildStoreKeyedGeneric(object, key, value);
3840
- }
3841
-
3842
-
3843
4190
  bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3844
4191
  VariableProxy* proxy = expr->obj()->AsVariableProxy();
3845
4192
  if (proxy == NULL) return false;
@@ -3848,6 +4195,13 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3848
4195
  return false;
3849
4196
  }
3850
4197
 
4198
+ // Our implementation of arguments (based on this stack frame or an
4199
+ // adapter below it) does not work for inlined functions.
4200
+ if (function_state()->outer() != NULL) {
4201
+ Bailout("arguments access in inlined function");
4202
+ return true;
4203
+ }
4204
+
3851
4205
  HInstruction* result = NULL;
3852
4206
  if (expr->key()->IsPropertyName()) {
3853
4207
  Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
@@ -3863,8 +4217,9 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3863
4217
  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
3864
4218
  HInstruction* length = AddInstruction(
3865
4219
  new(zone()) HArgumentsLength(elements));
3866
- AddInstruction(new(zone()) HBoundsCheck(key, length));
3867
- result = new(zone()) HAccessArgumentsAt(elements, length, key);
4220
+ HInstruction* checked_key =
4221
+ AddInstruction(new(zone()) HBoundsCheck(key, length));
4222
+ result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
3868
4223
  }
3869
4224
  ast_context()->ReturnInstruction(result, expr->id());
3870
4225
  return true;
@@ -3885,8 +4240,9 @@ void HGraphBuilder::VisitProperty(Property* expr) {
3885
4240
  if (expr->IsArrayLength()) {
3886
4241
  HValue* array = Pop();
3887
4242
  AddInstruction(new(zone()) HCheckNonSmi(array));
3888
- AddInstruction(HCheckInstanceType::NewIsJSArray(array));
3889
- instr = new(zone()) HJSArrayLength(array);
4243
+ HInstruction* mapcheck =
4244
+ AddInstruction(HCheckInstanceType::NewIsJSArray(array));
4245
+ instr = new(zone()) HJSArrayLength(array, mapcheck);
3890
4246
 
3891
4247
  } else if (expr->IsStringLength()) {
3892
4248
  HValue* string = Pop();
@@ -3897,9 +4253,11 @@ void HGraphBuilder::VisitProperty(Property* expr) {
3897
4253
  CHECK_ALIVE(VisitForValue(expr->key()));
3898
4254
  HValue* index = Pop();
3899
4255
  HValue* string = Pop();
3900
- HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
4256
+ HValue* context = environment()->LookupContext();
4257
+ HStringCharCodeAt* char_code =
4258
+ BuildStringCharCodeAt(context, string, index);
3901
4259
  AddInstruction(char_code);
3902
- instr = new(zone()) HStringCharFromCode(char_code);
4260
+ instr = new(zone()) HStringCharFromCode(context, char_code);
3903
4261
 
3904
4262
  } else if (expr->IsFunctionPrototype()) {
3905
4263
  HValue* function = Pop();
@@ -3908,14 +4266,15 @@ void HGraphBuilder::VisitProperty(Property* expr) {
3908
4266
 
3909
4267
  } else if (expr->key()->IsPropertyName()) {
3910
4268
  Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3911
- ZoneMapList* types = expr->GetReceiverTypes();
4269
+ SmallMapList* types = expr->GetReceiverTypes();
3912
4270
 
3913
4271
  HValue* obj = Pop();
3914
4272
  if (expr->IsMonomorphic()) {
3915
4273
  instr = BuildLoadNamed(obj, expr, types->first(), name);
3916
4274
  } else if (types != NULL && types->length() > 1) {
3917
4275
  AddInstruction(new(zone()) HCheckNonSmi(obj));
3918
- instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name);
4276
+ HValue* context = environment()->LookupContext();
4277
+ instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name);
3919
4278
  } else {
3920
4279
  instr = BuildLoadNamedGeneric(obj, expr);
3921
4280
  }
@@ -3925,10 +4284,25 @@ void HGraphBuilder::VisitProperty(Property* expr) {
3925
4284
 
3926
4285
  HValue* key = Pop();
3927
4286
  HValue* obj = Pop();
3928
- instr = BuildLoadKeyed(obj, key, expr);
4287
+
4288
+ bool has_side_effects = false;
4289
+ HValue* load = HandleKeyedElementAccess(
4290
+ obj, key, NULL, expr, expr->id(), expr->position(),
4291
+ false, // is_store
4292
+ &has_side_effects);
4293
+ if (has_side_effects) {
4294
+ if (ast_context()->IsEffect()) {
4295
+ AddSimulate(expr->id());
4296
+ } else {
4297
+ Push(load);
4298
+ AddSimulate(expr->id());
4299
+ Drop(1);
4300
+ }
4301
+ }
4302
+ return ast_context()->ReturnValue(load);
3929
4303
  }
3930
4304
  instr->set_position(expr->position());
3931
- ast_context()->ReturnInstruction(instr, expr->id());
4305
+ return ast_context()->ReturnInstruction(instr, expr->id());
3932
4306
  }
3933
4307
 
3934
4308
 
@@ -3953,7 +4327,7 @@ void HGraphBuilder::AddCheckConstantFunction(Call* expr,
3953
4327
 
3954
4328
  void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3955
4329
  HValue* receiver,
3956
- ZoneMapList* types,
4330
+ SmallMapList* types,
3957
4331
  Handle<String> name) {
3958
4332
  // TODO(ager): We should recognize when the prototype chains for different
3959
4333
  // maps are identical. In that case we can avoid repeatedly generating the
@@ -4016,8 +4390,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
4016
4390
  if (!ast_context()->IsEffect()) Push(call);
4017
4391
  current_block()->Goto(join);
4018
4392
  } else {
4019
- ast_context()->ReturnInstruction(call, expr->id());
4020
- return;
4393
+ return ast_context()->ReturnInstruction(call, expr->id());
4021
4394
  }
4022
4395
  }
4023
4396
 
@@ -4028,7 +4401,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
4028
4401
  if (join->HasPredecessor()) {
4029
4402
  set_current_block(join);
4030
4403
  join->SetJoinId(expr->id());
4031
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4404
+ if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
4032
4405
  } else {
4033
4406
  set_current_block(NULL);
4034
4407
  }
@@ -4140,14 +4513,6 @@ bool HGraphBuilder::TryInline(Call* expr) {
4140
4513
  return false;
4141
4514
  }
4142
4515
 
4143
- // Check if we can handle all declarations in the inlined functions.
4144
- VisitDeclarations(target_info.scope()->declarations());
4145
- if (HasStackOverflow()) {
4146
- TraceInline(target, caller, "target has non-trivial declaration");
4147
- ClearStackOverflow();
4148
- return false;
4149
- }
4150
-
4151
4516
  // Don't inline functions that uses the arguments object or that
4152
4517
  // have a mismatching number of parameters.
4153
4518
  int arity = expr->arguments()->length();
@@ -4157,6 +4522,15 @@ bool HGraphBuilder::TryInline(Call* expr) {
4157
4522
  return false;
4158
4523
  }
4159
4524
 
4525
+ // All declarations must be inlineable.
4526
+ ZoneList<Declaration*>* decls = target_info.scope()->declarations();
4527
+ int decl_count = decls->length();
4528
+ for (int i = 0; i < decl_count; ++i) {
4529
+ if (!decls->at(i)->IsInlineable()) {
4530
+ TraceInline(target, caller, "target has non-trivial declaration");
4531
+ return false;
4532
+ }
4533
+ }
4160
4534
  // All statements in the body must be inlineable.
4161
4535
  for (int i = 0, count = function->body()->length(); i < count; ++i) {
4162
4536
  if (!function->body()->at(i)->IsInlineable()) {
@@ -4175,6 +4549,13 @@ bool HGraphBuilder::TryInline(Call* expr) {
4175
4549
  TraceInline(target, caller, "could not generate deoptimization info");
4176
4550
  return false;
4177
4551
  }
4552
+ if (target_shared->scope_info() == SerializedScopeInfo::Empty()) {
4553
+ // The scope info might not have been set if a lazily compiled
4554
+ // function is inlined before being called for the first time.
4555
+ Handle<SerializedScopeInfo> target_scope_info =
4556
+ SerializedScopeInfo::Create(target_info.scope());
4557
+ target_shared->set_scope_info(*target_scope_info);
4558
+ }
4178
4559
  target_shared->EnableDeoptimizationSupport(*target_info.code());
4179
4560
  Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
4180
4561
  &target_info,
@@ -4182,6 +4563,9 @@ bool HGraphBuilder::TryInline(Call* expr) {
4182
4563
  }
4183
4564
 
4184
4565
  // ----------------------------------------------------------------
4566
+ // After this point, we've made a decision to inline this function (so
4567
+ // TryInline should always return true).
4568
+
4185
4569
  // Save the pending call context and type feedback oracle. Set up new ones
4186
4570
  // for the inlined function.
4187
4571
  ASSERT(target_shared->has_deoptimization_support());
@@ -4194,17 +4578,16 @@ bool HGraphBuilder::TryInline(Call* expr) {
4194
4578
  HEnvironment* inner_env =
4195
4579
  environment()->CopyForInlining(target,
4196
4580
  function,
4197
- HEnvironment::HYDROGEN,
4198
4581
  undefined,
4199
4582
  call_kind);
4200
4583
  HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4201
4584
  current_block()->Goto(body_entry);
4202
-
4203
4585
  body_entry->SetJoinId(expr->ReturnId());
4204
4586
  set_current_block(body_entry);
4205
4587
  AddInstruction(new(zone()) HEnterInlined(target,
4206
4588
  function,
4207
4589
  call_kind));
4590
+ VisitDeclarations(target_info.scope()->declarations());
4208
4591
  VisitStatements(function->body());
4209
4592
  if (HasStackOverflow()) {
4210
4593
  // Bail out if the inline function did, as we cannot residualize a call
@@ -4227,7 +4610,7 @@ bool HGraphBuilder::TryInline(Call* expr) {
4227
4610
  ASSERT(function_return() != NULL);
4228
4611
  ASSERT(call_context()->IsEffect() || call_context()->IsValue());
4229
4612
  if (call_context()->IsEffect()) {
4230
- current_block()->Goto(function_return(), false);
4613
+ current_block()->Goto(function_return());
4231
4614
  } else {
4232
4615
  current_block()->AddLeaveInlined(undefined, function_return());
4233
4616
  }
@@ -4239,11 +4622,11 @@ bool HGraphBuilder::TryInline(Call* expr) {
4239
4622
  // TODO(3168478): refactor to avoid this.
4240
4623
  HBasicBlock* empty_true = graph()->CreateBasicBlock();
4241
4624
  HBasicBlock* empty_false = graph()->CreateBasicBlock();
4242
- HTest* test = new(zone()) HTest(undefined, empty_true, empty_false);
4625
+ HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false);
4243
4626
  current_block()->Finish(test);
4244
4627
 
4245
- empty_true->Goto(inlined_test_context()->if_true(), false);
4246
- empty_false->Goto(inlined_test_context()->if_false(), false);
4628
+ empty_true->Goto(inlined_test_context()->if_true());
4629
+ empty_false->Goto(inlined_test_context()->if_false());
4247
4630
  }
4248
4631
  }
4249
4632
 
@@ -4251,21 +4634,22 @@ bool HGraphBuilder::TryInline(Call* expr) {
4251
4634
  if (inlined_test_context() != NULL) {
4252
4635
  HBasicBlock* if_true = inlined_test_context()->if_true();
4253
4636
  HBasicBlock* if_false = inlined_test_context()->if_false();
4254
- if_true->SetJoinId(expr->id());
4255
- if_false->SetJoinId(expr->id());
4256
- ASSERT(ast_context() == inlined_test_context());
4637
+
4257
4638
  // Pop the return test context from the expression context stack.
4639
+ ASSERT(ast_context() == inlined_test_context());
4258
4640
  ClearInlinedTestContext();
4259
4641
 
4260
4642
  // Forward to the real test context.
4261
- HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4262
- HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4263
- if_true->Goto(true_target, false);
4264
- if_false->Goto(false_target, false);
4265
-
4266
- // TODO(kmillikin): Come up with a better way to handle this. It is too
4267
- // subtle. NULL here indicates that the enclosing context has no control
4268
- // flow to handle.
4643
+ if (if_true->HasPredecessor()) {
4644
+ if_true->SetJoinId(expr->id());
4645
+ HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4646
+ if_true->Goto(true_target);
4647
+ }
4648
+ if (if_false->HasPredecessor()) {
4649
+ if_false->SetJoinId(expr->id());
4650
+ HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4651
+ if_false->Goto(false_target);
4652
+ }
4269
4653
  set_current_block(NULL);
4270
4654
 
4271
4655
  } else if (function_return()->HasPredecessor()) {
@@ -4294,18 +4678,20 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4294
4678
  if (argument_count == 2 && check_type == STRING_CHECK) {
4295
4679
  HValue* index = Pop();
4296
4680
  HValue* string = Pop();
4681
+ HValue* context = environment()->LookupContext();
4297
4682
  ASSERT(!expr->holder().is_null());
4298
4683
  AddInstruction(new(zone()) HCheckPrototypeMaps(
4299
4684
  oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
4300
4685
  expr->holder()));
4301
- HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
4686
+ HStringCharCodeAt* char_code =
4687
+ BuildStringCharCodeAt(context, string, index);
4302
4688
  if (id == kStringCharCodeAt) {
4303
4689
  ast_context()->ReturnInstruction(char_code, expr->id());
4304
4690
  return true;
4305
4691
  }
4306
4692
  AddInstruction(char_code);
4307
4693
  HStringCharFromCode* result =
4308
- new(zone()) HStringCharFromCode(char_code);
4694
+ new(zone()) HStringCharFromCode(context, char_code);
4309
4695
  ast_context()->ReturnInstruction(result, expr->id());
4310
4696
  return true;
4311
4697
  }
@@ -4320,8 +4706,10 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4320
4706
  if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
4321
4707
  AddCheckConstantFunction(expr, receiver, receiver_map, true);
4322
4708
  HValue* argument = Pop();
4709
+ HValue* context = environment()->LookupContext();
4323
4710
  Drop(1); // Receiver.
4324
- HUnaryMathOperation* op = new(zone()) HUnaryMathOperation(argument, id);
4711
+ HUnaryMathOperation* op =
4712
+ new(zone()) HUnaryMathOperation(context, argument, id);
4325
4713
  op->set_position(expr->position());
4326
4714
  ast_context()->ReturnInstruction(op, expr->id());
4327
4715
  return true;
@@ -4333,31 +4721,33 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4333
4721
  HValue* right = Pop();
4334
4722
  HValue* left = Pop();
4335
4723
  Pop(); // Pop receiver.
4724
+ HValue* context = environment()->LookupContext();
4336
4725
  HInstruction* result = NULL;
4337
4726
  // Use sqrt() if exponent is 0.5 or -0.5.
4338
4727
  if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4339
4728
  double exponent = HConstant::cast(right)->DoubleValue();
4340
4729
  if (exponent == 0.5) {
4341
- result = new(zone()) HUnaryMathOperation(left, kMathPowHalf);
4730
+ result =
4731
+ new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
4342
4732
  } else if (exponent == -0.5) {
4343
4733
  HConstant* double_one =
4344
4734
  new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)),
4345
4735
  Representation::Double());
4346
4736
  AddInstruction(double_one);
4347
4737
  HUnaryMathOperation* square_root =
4348
- new(zone()) HUnaryMathOperation(left, kMathPowHalf);
4738
+ new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
4349
4739
  AddInstruction(square_root);
4350
4740
  // MathPowHalf doesn't have side effects so there's no need for
4351
4741
  // an environment simulation here.
4352
4742
  ASSERT(!square_root->HasSideEffects());
4353
- result = new(zone()) HDiv(double_one, square_root);
4743
+ result = new(zone()) HDiv(context, double_one, square_root);
4354
4744
  } else if (exponent == 2.0) {
4355
- result = new(zone()) HMul(left, left);
4745
+ result = new(zone()) HMul(context, left, left);
4356
4746
  }
4357
4747
  } else if (right->IsConstant() &&
4358
4748
  HConstant::cast(right)->HasInteger32Value() &&
4359
4749
  HConstant::cast(right)->Integer32Value() == 2) {
4360
- result = new(zone()) HMul(left, left);
4750
+ result = new(zone()) HMul(context, left, left);
4361
4751
  }
4362
4752
 
4363
4753
  if (result == NULL) {
@@ -4380,10 +4770,17 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
4380
4770
  Property* prop = callee->AsProperty();
4381
4771
  ASSERT(prop != NULL);
4382
4772
 
4383
- if (info()->scope()->arguments() == NULL) return false;
4773
+ if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
4774
+ return false;
4775
+ }
4776
+ Handle<Map> function_map = expr->GetReceiverTypes()->first();
4777
+ if (function_map->instance_type() != JS_FUNCTION_TYPE ||
4778
+ !expr->target()->shared()->HasBuiltinFunctionId() ||
4779
+ expr->target()->shared()->builtin_function_id() != kFunctionApply) {
4780
+ return false;
4781
+ }
4384
4782
 
4385
- Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4386
- if (!name->IsEqualTo(CStrVector("apply"))) return false;
4783
+ if (info()->scope()->arguments() == NULL) return false;
4387
4784
 
4388
4785
  ZoneList<Expression*>* args = expr->arguments();
4389
4786
  if (args->length() != 2) return false;
@@ -4393,8 +4790,12 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
4393
4790
  HValue* arg_two_value = environment()->Lookup(arg_two->var());
4394
4791
  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
4395
4792
 
4396
- if (!expr->IsMonomorphic() ||
4397
- expr->check_type() != RECEIVER_MAP_CHECK) return false;
4793
+ // Our implementation of arguments (based on this stack frame or an
4794
+ // adapter below it) does not work for inlined functions.
4795
+ if (function_state()->outer() != NULL) {
4796
+ Bailout("Function.prototype.apply optimization in inlined function");
4797
+ return true;
4798
+ }
4398
4799
 
4399
4800
  // Found pattern f.apply(receiver, arguments).
4400
4801
  VisitForValue(prop->obj());
@@ -4405,10 +4806,7 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
4405
4806
  HValue* receiver = Pop();
4406
4807
  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
4407
4808
  HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
4408
- AddCheckConstantFunction(expr,
4409
- function,
4410
- expr->GetReceiverTypes()->first(),
4411
- true);
4809
+ AddCheckConstantFunction(expr, function, function_map, true);
4412
4810
  HInstruction* result =
4413
4811
  new(zone()) HApplyArguments(function, receiver, length, elements);
4414
4812
  result->set_position(expr->position());
@@ -4429,7 +4827,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
4429
4827
  if (prop != NULL) {
4430
4828
  if (!prop->key()->IsPropertyName()) {
4431
4829
  // Keyed function call.
4432
- CHECK_ALIVE(VisitForValue(prop->obj()));
4830
+ CHECK_ALIVE(VisitArgument(prop->obj()));
4433
4831
 
4434
4832
  CHECK_ALIVE(VisitForValue(prop->key()));
4435
4833
  // Push receiver and key like the non-optimized code generator expects it.
@@ -4438,15 +4836,13 @@ void HGraphBuilder::VisitCall(Call* expr) {
4438
4836
  Push(key);
4439
4837
  Push(receiver);
4440
4838
 
4441
- CHECK_ALIVE(VisitExpressions(expr->arguments()));
4839
+ CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4442
4840
 
4443
4841
  HValue* context = environment()->LookupContext();
4444
- call = PreProcessCall(
4445
- new(zone()) HCallKeyed(context, key, argument_count));
4842
+ call = new(zone()) HCallKeyed(context, key, argument_count);
4446
4843
  call->set_position(expr->position());
4447
- Drop(1); // Key.
4448
- ast_context()->ReturnInstruction(call, expr->id());
4449
- return;
4844
+ Drop(argument_count + 1); // 1 is the key.
4845
+ return ast_context()->ReturnInstruction(call, expr->id());
4450
4846
  }
4451
4847
 
4452
4848
  // Named function call.
@@ -4459,13 +4855,14 @@ void HGraphBuilder::VisitCall(Call* expr) {
4459
4855
 
4460
4856
  Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4461
4857
 
4462
- ZoneMapList* types = expr->GetReceiverTypes();
4858
+ SmallMapList* types = expr->GetReceiverTypes();
4463
4859
 
4464
4860
  HValue* receiver =
4465
4861
  environment()->ExpressionStackAt(expr->arguments()->length());
4466
4862
  if (expr->IsMonomorphic()) {
4467
- Handle<Map> receiver_map =
4468
- (types == NULL) ? Handle<Map>::null() : types->first();
4863
+ Handle<Map> receiver_map = (types == NULL || types->is_empty())
4864
+ ? Handle<Map>::null()
4865
+ : types->first();
4469
4866
  if (TryInlineBuiltinFunction(expr,
4470
4867
  receiver,
4471
4868
  receiver_map,
@@ -4504,11 +4901,6 @@ void HGraphBuilder::VisitCall(Call* expr) {
4504
4901
  Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4505
4902
  bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4506
4903
 
4507
- if (!global_call) {
4508
- ++argument_count;
4509
- CHECK_ALIVE(VisitForValue(expr->expression()));
4510
- }
4511
-
4512
4904
  if (global_call) {
4513
4905
  bool known_global_function = false;
4514
4906
  // If there is a global property cell for the name at compile time and
@@ -4548,27 +4940,34 @@ void HGraphBuilder::VisitCall(Call* expr) {
4548
4940
  argument_count));
4549
4941
  } else {
4550
4942
  HValue* context = environment()->LookupContext();
4551
- PushAndAdd(new(zone()) HGlobalObject(context));
4552
- CHECK_ALIVE(VisitExpressions(expr->arguments()));
4943
+ HGlobalObject* receiver = new(zone()) HGlobalObject(context);
4944
+ AddInstruction(receiver);
4945
+ PushAndAdd(new(zone()) HPushArgument(receiver));
4946
+ CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4553
4947
 
4554
- call = PreProcessCall(new(zone()) HCallGlobal(context,
4555
- var->name(),
4556
- argument_count));
4948
+ call = new(zone()) HCallGlobal(context, var->name(), argument_count);
4949
+ Drop(argument_count);
4557
4950
  }
4558
4951
 
4559
4952
  } else {
4953
+ CHECK_ALIVE(VisitArgument(expr->expression()));
4560
4954
  HValue* context = environment()->LookupContext();
4561
4955
  HGlobalObject* global_object = new(zone()) HGlobalObject(context);
4956
+ HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
4562
4957
  AddInstruction(global_object);
4563
- PushAndAdd(new(zone()) HGlobalReceiver(global_object));
4564
- CHECK_ALIVE(VisitExpressions(expr->arguments()));
4958
+ AddInstruction(receiver);
4959
+ PushAndAdd(new(zone()) HPushArgument(receiver));
4960
+ CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4565
4961
 
4566
- call = PreProcessCall(new(zone()) HCallFunction(context, argument_count));
4962
+ // The function to call is treated as an argument to the call function
4963
+ // stub.
4964
+ call = new(zone()) HCallFunction(context, argument_count + 1);
4965
+ Drop(argument_count + 1);
4567
4966
  }
4568
4967
  }
4569
4968
 
4570
4969
  call->set_position(expr->position());
4571
- ast_context()->ReturnInstruction(call, expr->id());
4970
+ return ast_context()->ReturnInstruction(call, expr->id());
4572
4971
  }
4573
4972
 
4574
4973
 
@@ -4578,19 +4977,19 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) {
4578
4977
  ASSERT(current_block()->HasPredecessor());
4579
4978
  // The constructor function is also used as the receiver argument to the
4580
4979
  // JS construct call builtin.
4581
- CHECK_ALIVE(VisitForValue(expr->expression()));
4582
- CHECK_ALIVE(VisitExpressions(expr->arguments()));
4980
+ HValue* constructor = NULL;
4981
+ CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
4982
+ CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4583
4983
 
4584
4984
  HValue* context = environment()->LookupContext();
4585
4985
 
4586
4986
  // The constructor is both an operand to the instruction and an argument
4587
4987
  // to the construct call.
4588
4988
  int arg_count = expr->arguments()->length() + 1; // Plus constructor.
4589
- HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
4590
4989
  HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count);
4591
4990
  call->set_position(expr->position());
4592
- PreProcessCall(call);
4593
- ast_context()->ReturnInstruction(call, expr->id());
4991
+ Drop(arg_count);
4992
+ return ast_context()->ReturnInstruction(call, expr->id());
4594
4993
  }
4595
4994
 
4596
4995
 
@@ -4636,13 +5035,14 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
4636
5035
  ASSERT(function->intrinsic_type == Runtime::RUNTIME);
4637
5036
  CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4638
5037
 
5038
+ HValue* context = environment()->LookupContext();
4639
5039
  Handle<String> name = expr->name();
4640
5040
  int argument_count = expr->arguments()->length();
4641
5041
  HCallRuntime* call =
4642
- new(zone()) HCallRuntime(name, function, argument_count);
5042
+ new(zone()) HCallRuntime(context, name, function, argument_count);
4643
5043
  call->set_position(RelocInfo::kNoPosition);
4644
5044
  Drop(argument_count);
4645
- ast_context()->ReturnInstruction(call, expr->id());
5045
+ return ast_context()->ReturnInstruction(call, expr->id());
4646
5046
  }
4647
5047
  }
4648
5048
 
@@ -4670,27 +5070,22 @@ void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
4670
5070
  // Result of deleting non-property, non-variable reference is true.
4671
5071
  // Evaluate the subexpression for side effects.
4672
5072
  CHECK_ALIVE(VisitForEffect(expr->expression()));
4673
- ast_context()->ReturnValue(graph()->GetConstantTrue());
5073
+ return ast_context()->ReturnValue(graph()->GetConstantTrue());
4674
5074
  } else if (var != NULL &&
4675
5075
  !var->is_global() &&
4676
5076
  var->AsSlot() != NULL &&
4677
5077
  var->AsSlot()->type() != Slot::LOOKUP) {
4678
5078
  // Result of deleting non-global, non-dynamic variables is false.
4679
5079
  // The subexpression does not have side effects.
4680
- ast_context()->ReturnValue(graph()->GetConstantFalse());
5080
+ return ast_context()->ReturnValue(graph()->GetConstantFalse());
4681
5081
  } else if (prop != NULL) {
4682
- if (prop->is_synthetic()) {
4683
- // Result of deleting parameters is false, even when they rewrite
4684
- // to accesses on the arguments object.
4685
- ast_context()->ReturnValue(graph()->GetConstantFalse());
4686
- } else {
4687
- CHECK_ALIVE(VisitForValue(prop->obj()));
4688
- CHECK_ALIVE(VisitForValue(prop->key()));
4689
- HValue* key = Pop();
4690
- HValue* obj = Pop();
4691
- HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key);
4692
- ast_context()->ReturnInstruction(instr, expr->id());
4693
- }
5082
+ CHECK_ALIVE(VisitForValue(prop->obj()));
5083
+ CHECK_ALIVE(VisitForValue(prop->key()));
5084
+ HValue* key = Pop();
5085
+ HValue* obj = Pop();
5086
+ HValue* context = environment()->LookupContext();
5087
+ HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
5088
+ return ast_context()->ReturnInstruction(instr, expr->id());
4694
5089
  } else if (var->is_global()) {
4695
5090
  Bailout("delete with global variable");
4696
5091
  } else {
@@ -4701,42 +5096,58 @@ void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
4701
5096
 
4702
5097
  void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
4703
5098
  CHECK_ALIVE(VisitForEffect(expr->expression()));
4704
- ast_context()->ReturnValue(graph()->GetConstantUndefined());
5099
+ return ast_context()->ReturnValue(graph()->GetConstantUndefined());
4705
5100
  }
4706
5101
 
4707
5102
 
4708
5103
  void HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
4709
5104
  CHECK_ALIVE(VisitForTypeOf(expr->expression()));
4710
5105
  HValue* value = Pop();
4711
- ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id());
5106
+ HValue* context = environment()->LookupContext();
5107
+ HInstruction* instr = new(zone()) HTypeof(context, value);
5108
+ return ast_context()->ReturnInstruction(instr, expr->id());
4712
5109
  }
4713
5110
 
4714
5111
 
4715
5112
  void HGraphBuilder::VisitAdd(UnaryOperation* expr) {
4716
5113
  CHECK_ALIVE(VisitForValue(expr->expression()));
4717
5114
  HValue* value = Pop();
4718
- HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1());
4719
- ast_context()->ReturnInstruction(instr, expr->id());
5115
+ HValue* context = environment()->LookupContext();
5116
+ HInstruction* instr =
5117
+ new(zone()) HMul(context, value, graph_->GetConstant1());
5118
+ return ast_context()->ReturnInstruction(instr, expr->id());
4720
5119
  }
4721
5120
 
4722
5121
 
4723
5122
  void HGraphBuilder::VisitSub(UnaryOperation* expr) {
4724
5123
  CHECK_ALIVE(VisitForValue(expr->expression()));
4725
5124
  HValue* value = Pop();
4726
- HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
5125
+ HValue* context = environment()->LookupContext();
5126
+ HInstruction* instr =
5127
+ new(zone()) HMul(context, value, graph_->GetConstantMinus1());
4727
5128
  TypeInfo info = oracle()->UnaryType(expr);
5129
+ if (info.IsUninitialized()) {
5130
+ AddInstruction(new(zone()) HSoftDeoptimize);
5131
+ current_block()->MarkAsDeoptimizing();
5132
+ info = TypeInfo::Unknown();
5133
+ }
4728
5134
  Representation rep = ToRepresentation(info);
4729
5135
  TraceRepresentation(expr->op(), info, instr, rep);
4730
5136
  instr->AssumeRepresentation(rep);
4731
- ast_context()->ReturnInstruction(instr, expr->id());
5137
+ return ast_context()->ReturnInstruction(instr, expr->id());
4732
5138
  }
4733
5139
 
4734
5140
 
4735
5141
  void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
4736
5142
  CHECK_ALIVE(VisitForValue(expr->expression()));
4737
5143
  HValue* value = Pop();
5144
+ TypeInfo info = oracle()->UnaryType(expr);
5145
+ if (info.IsUninitialized()) {
5146
+ AddInstruction(new(zone()) HSoftDeoptimize);
5147
+ current_block()->MarkAsDeoptimizing();
5148
+ }
4738
5149
  HInstruction* instr = new(zone()) HBitNot(value);
4739
- ast_context()->ReturnInstruction(instr, expr->id());
5150
+ return ast_context()->ReturnInstruction(instr, expr->id());
4740
5151
  }
4741
5152
 
4742
5153
 
@@ -4781,7 +5192,7 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) {
4781
5192
  HBasicBlock* join =
4782
5193
  CreateJoin(materialize_false, materialize_true, expr->id());
4783
5194
  set_current_block(join);
4784
- if (join != NULL) ast_context()->ReturnValue(Pop());
5195
+ if (join != NULL) return ast_context()->ReturnValue(Pop());
4785
5196
  }
4786
5197
 
4787
5198
 
@@ -4810,7 +5221,8 @@ HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input,
4810
5221
  HConstant* delta = (expr->op() == Token::INC)
4811
5222
  ? graph_->GetConstant1()
4812
5223
  : graph_->GetConstantMinus1();
4813
- HInstruction* instr = new(zone()) HAdd(Top(), delta);
5224
+ HValue* context = environment()->LookupContext();
5225
+ HInstruction* instr = new(zone()) HAdd(context, Top(), delta);
4814
5226
  TraceRepresentation(expr->op(), info, instr, rep);
4815
5227
  instr->AssumeRepresentation(rep);
4816
5228
  AddInstruction(instr);
@@ -4839,6 +5251,9 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4839
5251
  HValue* after = NULL; // The result after incrementing or decrementing.
4840
5252
 
4841
5253
  if (var != NULL) {
5254
+ if (var->mode() == Variable::CONST) {
5255
+ return Bailout("unsupported count operation with const");
5256
+ }
4842
5257
  // Argument of the count operation is a variable, not a property.
4843
5258
  ASSERT(prop == NULL);
4844
5259
  CHECK_ALIVE(VisitForValue(target));
@@ -4855,6 +5270,20 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4855
5270
  } else if (var->IsStackAllocated()) {
4856
5271
  Bind(var, after);
4857
5272
  } else if (var->IsContextSlot()) {
5273
+ // Bail out if we try to mutate a parameter value in a function using
5274
+ // the arguments object. We do not (yet) correctly handle the
5275
+ // arguments property of the function.
5276
+ if (info()->scope()->arguments() != NULL) {
5277
+ // Parameters will rewrite to context slots. We have no direct way
5278
+ // to detect that the variable is a parameter.
5279
+ int count = info()->scope()->num_parameters();
5280
+ for (int i = 0; i < count; ++i) {
5281
+ if (var == info()->scope()->parameter(i)) {
5282
+ Bailout("assignment to parameter, function uses arguments object");
5283
+ }
5284
+ }
5285
+ }
5286
+
4858
5287
  HValue* context = BuildContextChainWalk(var);
4859
5288
  int index = var->AsSlot()->index();
4860
5289
  HStoreContextSlot* instr =
@@ -4910,16 +5339,22 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4910
5339
  HValue* obj = environment()->ExpressionStackAt(1);
4911
5340
  HValue* key = environment()->ExpressionStackAt(0);
4912
5341
 
4913
- HInstruction* load = BuildLoadKeyed(obj, key, prop);
4914
- PushAndAdd(load);
4915
- if (load->HasSideEffects()) AddSimulate(expr->CountId());
5342
+ bool has_side_effects = false;
5343
+ HValue* load = HandleKeyedElementAccess(
5344
+ obj, key, NULL, prop, expr->CountId(), RelocInfo::kNoPosition,
5345
+ false, // is_store
5346
+ &has_side_effects);
5347
+ Push(load);
5348
+ if (has_side_effects) AddSimulate(expr->CountId());
4916
5349
 
4917
5350
  after = BuildIncrement(returns_original_input, expr);
4918
5351
  input = Pop();
4919
5352
 
4920
5353
  expr->RecordTypeFeedback(oracle());
4921
- HInstruction* store = BuildStoreKeyed(obj, key, after, expr);
4922
- AddInstruction(store);
5354
+ HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
5355
+ RelocInfo::kNoPosition,
5356
+ true, // is_store
5357
+ &has_side_effects);
4923
5358
 
4924
5359
  // Drop the key from the bailout environment. Overwrite the receiver
4925
5360
  // with the result of the operation, and the placeholder with the
@@ -4927,43 +5362,86 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4927
5362
  Drop(1);
4928
5363
  environment()->SetExpressionStackAt(0, after);
4929
5364
  if (returns_original_input) environment()->SetExpressionStackAt(1, input);
4930
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
5365
+ ASSERT(has_side_effects); // Stores always have side effects.
5366
+ AddSimulate(expr->AssignmentId());
4931
5367
  }
4932
5368
  }
4933
5369
 
4934
5370
  Drop(returns_original_input ? 2 : 1);
4935
- ast_context()->ReturnValue(expr->is_postfix() ? input : after);
4936
- }
4937
-
4938
-
4939
- HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left,
4940
- HValue* right,
4941
- Token::Value op) {
4942
- ASSERT(op == Token::EQ || op == Token::EQ_STRICT);
4943
- AddInstruction(new(zone()) HCheckNonSmi(left));
4944
- AddInstruction(HCheckInstanceType::NewIsSymbol(left));
4945
- AddInstruction(new(zone()) HCheckNonSmi(right));
4946
- AddInstruction(HCheckInstanceType::NewIsSymbol(right));
4947
- return new(zone()) HCompareSymbolEq(left, right, op);
5371
+ return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
4948
5372
  }
4949
5373
 
4950
5374
 
4951
- HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
5375
+ HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
5376
+ HValue* string,
4952
5377
  HValue* index) {
4953
5378
  AddInstruction(new(zone()) HCheckNonSmi(string));
4954
5379
  AddInstruction(HCheckInstanceType::NewIsString(string));
4955
5380
  HStringLength* length = new(zone()) HStringLength(string);
4956
5381
  AddInstruction(length);
4957
- AddInstruction(new(zone()) HBoundsCheck(index, length));
4958
- return new(zone()) HStringCharCodeAt(string, index);
5382
+ HInstruction* checked_index =
5383
+ AddInstruction(new(zone()) HBoundsCheck(index, length));
5384
+ return new(zone()) HStringCharCodeAt(context, string, checked_index);
4959
5385
  }
4960
5386
 
4961
5387
 
4962
5388
  HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4963
5389
  HValue* left,
4964
5390
  HValue* right) {
5391
+ HValue* context = environment()->LookupContext();
4965
5392
  TypeInfo info = oracle()->BinaryType(expr);
4966
- HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info);
5393
+ if (info.IsUninitialized()) {
5394
+ AddInstruction(new(zone()) HSoftDeoptimize);
5395
+ current_block()->MarkAsDeoptimizing();
5396
+ info = TypeInfo::Unknown();
5397
+ }
5398
+ HInstruction* instr = NULL;
5399
+ switch (expr->op()) {
5400
+ case Token::ADD:
5401
+ if (info.IsString()) {
5402
+ AddInstruction(new(zone()) HCheckNonSmi(left));
5403
+ AddInstruction(HCheckInstanceType::NewIsString(left));
5404
+ AddInstruction(new(zone()) HCheckNonSmi(right));
5405
+ AddInstruction(HCheckInstanceType::NewIsString(right));
5406
+ instr = new(zone()) HStringAdd(context, left, right);
5407
+ } else {
5408
+ instr = new(zone()) HAdd(context, left, right);
5409
+ }
5410
+ break;
5411
+ case Token::SUB:
5412
+ instr = new(zone()) HSub(context, left, right);
5413
+ break;
5414
+ case Token::MUL:
5415
+ instr = new(zone()) HMul(context, left, right);
5416
+ break;
5417
+ case Token::MOD:
5418
+ instr = new(zone()) HMod(context, left, right);
5419
+ break;
5420
+ case Token::DIV:
5421
+ instr = new(zone()) HDiv(context, left, right);
5422
+ break;
5423
+ case Token::BIT_XOR:
5424
+ instr = new(zone()) HBitXor(context, left, right);
5425
+ break;
5426
+ case Token::BIT_AND:
5427
+ instr = new(zone()) HBitAnd(context, left, right);
5428
+ break;
5429
+ case Token::BIT_OR:
5430
+ instr = new(zone()) HBitOr(context, left, right);
5431
+ break;
5432
+ case Token::SAR:
5433
+ instr = new(zone()) HSar(context, left, right);
5434
+ break;
5435
+ case Token::SHR:
5436
+ instr = new(zone()) HShr(context, left, right);
5437
+ break;
5438
+ case Token::SHL:
5439
+ instr = new(zone()) HShl(context, left, right);
5440
+ break;
5441
+ default:
5442
+ UNREACHABLE();
5443
+ }
5444
+
4967
5445
  // If we hit an uninitialized binary op stub we will get type info
4968
5446
  // for a smi operation. If one of the operands is a constant string
4969
5447
  // do not generate code assuming it is a smi operation.
@@ -4983,36 +5461,6 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4983
5461
  }
4984
5462
 
4985
5463
 
4986
- HInstruction* HGraphBuilder::BuildBinaryOperation(
4987
- Token::Value op, HValue* left, HValue* right, TypeInfo info) {
4988
- switch (op) {
4989
- case Token::ADD:
4990
- if (info.IsString()) {
4991
- AddInstruction(new(zone()) HCheckNonSmi(left));
4992
- AddInstruction(HCheckInstanceType::NewIsString(left));
4993
- AddInstruction(new(zone()) HCheckNonSmi(right));
4994
- AddInstruction(HCheckInstanceType::NewIsString(right));
4995
- return new(zone()) HStringAdd(left, right);
4996
- } else {
4997
- return new(zone()) HAdd(left, right);
4998
- }
4999
- case Token::SUB: return new(zone()) HSub(left, right);
5000
- case Token::MUL: return new(zone()) HMul(left, right);
5001
- case Token::MOD: return new(zone()) HMod(left, right);
5002
- case Token::DIV: return new(zone()) HDiv(left, right);
5003
- case Token::BIT_XOR: return new(zone()) HBitXor(left, right);
5004
- case Token::BIT_AND: return new(zone()) HBitAnd(left, right);
5005
- case Token::BIT_OR: return new(zone()) HBitOr(left, right);
5006
- case Token::SAR: return new(zone()) HSar(left, right);
5007
- case Token::SHR: return new(zone()) HShr(left, right);
5008
- case Token::SHL: return new(zone()) HShl(left, right);
5009
- default:
5010
- UNREACHABLE();
5011
- return NULL;
5012
- }
5013
- }
5014
-
5015
-
5016
5464
  // Check for the form (%_ClassOf(foo) === 'BarClass').
5017
5465
  static bool IsClassOfTest(CompareOperation* expr) {
5018
5466
  if (expr->op() != Token::EQ_STRICT) return false;
@@ -5032,10 +5480,13 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
5032
5480
  ASSERT(current_block() != NULL);
5033
5481
  ASSERT(current_block()->HasPredecessor());
5034
5482
  switch (expr->op()) {
5035
- case Token::COMMA: return VisitComma(expr);
5036
- case Token::OR: return VisitAndOr(expr, false);
5037
- case Token::AND: return VisitAndOr(expr, true);
5038
- default: return VisitCommon(expr);
5483
+ case Token::COMMA:
5484
+ return VisitComma(expr);
5485
+ case Token::OR:
5486
+ case Token::AND:
5487
+ return VisitLogicalExpression(expr);
5488
+ default:
5489
+ return VisitArithmeticExpression(expr);
5039
5490
  }
5040
5491
  }
5041
5492
 
@@ -5048,7 +5499,8 @@ void HGraphBuilder::VisitComma(BinaryOperation* expr) {
5048
5499
  }
5049
5500
 
5050
5501
 
5051
- void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) {
5502
+ void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
5503
+ bool is_logical_and = expr->op() == Token::AND;
5052
5504
  if (ast_context()->IsTest()) {
5053
5505
  TestContext* context = TestContext::cast(ast_context());
5054
5506
  // Translate left subexpression.
@@ -5078,9 +5530,11 @@ void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) {
5078
5530
  // We need an extra block to maintain edge-split form.
5079
5531
  HBasicBlock* empty_block = graph()->CreateBasicBlock();
5080
5532
  HBasicBlock* eval_right = graph()->CreateBasicBlock();
5081
- HTest* test = is_logical_and
5082
- ? new(zone()) HTest(Top(), eval_right, empty_block)
5083
- : new(zone()) HTest(Top(), empty_block, eval_right);
5533
+ unsigned test_id = expr->left()->test_id();
5534
+ ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id));
5535
+ HBranch* test = is_logical_and
5536
+ ? new(zone()) HBranch(Top(), eval_right, empty_block, expected)
5537
+ : new(zone()) HBranch(Top(), empty_block, eval_right, expected);
5084
5538
  current_block()->Finish(test);
5085
5539
 
5086
5540
  set_current_block(eval_right);
@@ -5090,7 +5544,7 @@ void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) {
5090
5544
  HBasicBlock* join_block =
5091
5545
  CreateJoin(empty_block, current_block(), expr->id());
5092
5546
  set_current_block(join_block);
5093
- ast_context()->ReturnValue(Pop());
5547
+ return ast_context()->ReturnValue(Pop());
5094
5548
 
5095
5549
  } else {
5096
5550
  ASSERT(ast_context()->IsEffect());
@@ -5135,14 +5589,14 @@ void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) {
5135
5589
  }
5136
5590
 
5137
5591
 
5138
- void HGraphBuilder::VisitCommon(BinaryOperation* expr) {
5592
+ void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
5139
5593
  CHECK_ALIVE(VisitForValue(expr->left()));
5140
5594
  CHECK_ALIVE(VisitForValue(expr->right()));
5141
5595
  HValue* right = Pop();
5142
5596
  HValue* left = Pop();
5143
5597
  HInstruction* instr = BuildBinaryOperation(expr, left, right);
5144
5598
  instr->set_position(expr->position());
5145
- ast_context()->ReturnInstruction(instr, expr->id());
5599
+ return ast_context()->ReturnInstruction(instr, expr->id());
5146
5600
  }
5147
5601
 
5148
5602
 
@@ -5175,46 +5629,75 @@ Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
5175
5629
  }
5176
5630
 
5177
5631
 
5632
+ void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr,
5633
+ Expression* expr,
5634
+ Handle<String> check) {
5635
+ CHECK_ALIVE(VisitForTypeOf(expr));
5636
+ HValue* expr_value = Pop();
5637
+ HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(expr_value, check);
5638
+ instr->set_position(compare_expr->position());
5639
+ return ast_context()->ReturnControl(instr, compare_expr->id());
5640
+ }
5641
+
5642
+
5643
+ void HGraphBuilder::HandleLiteralCompareUndefined(
5644
+ CompareOperation* compare_expr, Expression* expr) {
5645
+ CHECK_ALIVE(VisitForValue(expr));
5646
+ HValue* lhs = Pop();
5647
+ HValue* rhs = graph()->GetConstantUndefined();
5648
+ HCompareObjectEqAndBranch* instr =
5649
+ new(zone()) HCompareObjectEqAndBranch(lhs, rhs);
5650
+ instr->set_position(compare_expr->position());
5651
+ return ast_context()->ReturnControl(instr, compare_expr->id());
5652
+ }
5653
+
5654
+
5178
5655
  void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5179
5656
  ASSERT(!HasStackOverflow());
5180
5657
  ASSERT(current_block() != NULL);
5181
5658
  ASSERT(current_block()->HasPredecessor());
5182
5659
  if (IsClassOfTest(expr)) {
5183
5660
  CallRuntime* call = expr->left()->AsCallRuntime();
5661
+ ASSERT(call->arguments()->length() == 1);
5184
5662
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5185
5663
  HValue* value = Pop();
5186
5664
  Literal* literal = expr->right()->AsLiteral();
5187
5665
  Handle<String> rhs = Handle<String>::cast(literal->handle());
5188
- HInstruction* instr = new(zone()) HClassOfTest(value, rhs);
5666
+ HClassOfTestAndBranch* instr =
5667
+ new(zone()) HClassOfTestAndBranch(value, rhs);
5189
5668
  instr->set_position(expr->position());
5190
- ast_context()->ReturnInstruction(instr, expr->id());
5669
+ return ast_context()->ReturnControl(instr, expr->id());
5670
+ }
5671
+
5672
+ // Check for special cases that compare against literals.
5673
+ Expression *sub_expr;
5674
+ Handle<String> check;
5675
+ if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
5676
+ HandleLiteralCompareTypeof(expr, sub_expr, check);
5191
5677
  return;
5192
5678
  }
5193
5679
 
5194
- // Check for the pattern: typeof <expression> == <string literal>.
5195
- UnaryOperation* left_unary = expr->left()->AsUnaryOperation();
5196
- Literal* right_literal = expr->right()->AsLiteral();
5197
- if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
5198
- left_unary != NULL && left_unary->op() == Token::TYPEOF &&
5199
- right_literal != NULL && right_literal->handle()->IsString()) {
5200
- CHECK_ALIVE(VisitForTypeOf(left_unary->expression()));
5201
- HValue* left = Pop();
5202
- HInstruction* instr = new(zone()) HTypeofIs(left,
5203
- Handle<String>::cast(right_literal->handle()));
5204
- instr->set_position(expr->position());
5205
- ast_context()->ReturnInstruction(instr, expr->id());
5680
+ if (expr->IsLiteralCompareUndefined(&sub_expr)) {
5681
+ HandleLiteralCompareUndefined(expr, sub_expr);
5206
5682
  return;
5207
5683
  }
5208
5684
 
5685
+ TypeInfo type_info = oracle()->CompareType(expr);
5686
+ // Check if this expression was ever executed according to type feedback.
5687
+ if (type_info.IsUninitialized()) {
5688
+ AddInstruction(new(zone()) HSoftDeoptimize);
5689
+ current_block()->MarkAsDeoptimizing();
5690
+ type_info = TypeInfo::Unknown();
5691
+ }
5692
+
5209
5693
  CHECK_ALIVE(VisitForValue(expr->left()));
5210
5694
  CHECK_ALIVE(VisitForValue(expr->right()));
5211
5695
 
5696
+ HValue* context = environment()->LookupContext();
5212
5697
  HValue* right = Pop();
5213
5698
  HValue* left = Pop();
5214
5699
  Token::Value op = expr->op();
5215
5700
 
5216
- TypeInfo type_info = oracle()->CompareType(expr);
5217
- HInstruction* instr = NULL;
5218
5701
  if (op == Token::INSTANCEOF) {
5219
5702
  // Check to see if the rhs of the instanceof is a global function not
5220
5703
  // residing in new space. If it is we assume that the function will stay the
@@ -5244,40 +5727,61 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5244
5727
  // If the target is not null we have found a known global function that is
5245
5728
  // assumed to stay the same for this instanceof.
5246
5729
  if (target.is_null()) {
5247
- HValue* context = environment()->LookupContext();
5248
- instr = new(zone()) HInstanceOf(context, left, right);
5730
+ HInstanceOf* result = new(zone()) HInstanceOf(context, left, right);
5731
+ result->set_position(expr->position());
5732
+ return ast_context()->ReturnInstruction(result, expr->id());
5249
5733
  } else {
5250
5734
  AddInstruction(new(zone()) HCheckFunction(right, target));
5251
- instr = new(zone()) HInstanceOfKnownGlobal(left, target);
5735
+ HInstanceOfKnownGlobal* result =
5736
+ new(zone()) HInstanceOfKnownGlobal(context, left, target);
5737
+ result->set_position(expr->position());
5738
+ return ast_context()->ReturnInstruction(result, expr->id());
5252
5739
  }
5253
5740
  } else if (op == Token::IN) {
5254
- instr = new(zone()) HIn(left, right);
5741
+ HIn* result = new(zone()) HIn(context, left, right);
5742
+ result->set_position(expr->position());
5743
+ return ast_context()->ReturnInstruction(result, expr->id());
5255
5744
  } else if (type_info.IsNonPrimitive()) {
5256
5745
  switch (op) {
5257
5746
  case Token::EQ:
5258
5747
  case Token::EQ_STRICT: {
5259
5748
  AddInstruction(new(zone()) HCheckNonSmi(left));
5260
- AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
5749
+ AddInstruction(HCheckInstanceType::NewIsSpecObject(left));
5261
5750
  AddInstruction(new(zone()) HCheckNonSmi(right));
5262
- AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
5263
- instr = new(zone()) HCompareJSObjectEq(left, right);
5264
- break;
5751
+ AddInstruction(HCheckInstanceType::NewIsSpecObject(right));
5752
+ HCompareObjectEqAndBranch* result =
5753
+ new(zone()) HCompareObjectEqAndBranch(left, right);
5754
+ result->set_position(expr->position());
5755
+ return ast_context()->ReturnControl(result, expr->id());
5265
5756
  }
5266
5757
  default:
5267
5758
  return Bailout("Unsupported non-primitive compare");
5268
- break;
5269
5759
  }
5270
5760
  } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) &&
5271
5761
  (op == Token::EQ || op == Token::EQ_STRICT)) {
5272
- instr = BuildSymbolCompare(left, right, op);
5762
+ AddInstruction(new(zone()) HCheckNonSmi(left));
5763
+ AddInstruction(HCheckInstanceType::NewIsSymbol(left));
5764
+ AddInstruction(new(zone()) HCheckNonSmi(right));
5765
+ AddInstruction(HCheckInstanceType::NewIsSymbol(right));
5766
+ HCompareObjectEqAndBranch* result =
5767
+ new(zone()) HCompareObjectEqAndBranch(left, right);
5768
+ result->set_position(expr->position());
5769
+ return ast_context()->ReturnControl(result, expr->id());
5273
5770
  } else {
5274
- HCompare* compare = new(zone()) HCompare(left, right, op);
5275
5771
  Representation r = ToRepresentation(type_info);
5276
- compare->SetInputRepresentation(r);
5277
- instr = compare;
5772
+ if (r.IsTagged()) {
5773
+ HCompareGeneric* result =
5774
+ new(zone()) HCompareGeneric(context, left, right, op);
5775
+ result->set_position(expr->position());
5776
+ return ast_context()->ReturnInstruction(result, expr->id());
5777
+ } else {
5778
+ HCompareIDAndBranch* result =
5779
+ new(zone()) HCompareIDAndBranch(left, right, op);
5780
+ result->set_position(expr->position());
5781
+ result->SetInputRepresentation(r);
5782
+ return ast_context()->ReturnControl(result, expr->id());
5783
+ }
5278
5784
  }
5279
- instr->set_position(expr->position());
5280
- ast_context()->ReturnInstruction(instr, expr->id());
5281
5785
  }
5282
5786
 
5283
5787
 
@@ -5286,10 +5790,10 @@ void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
5286
5790
  ASSERT(current_block() != NULL);
5287
5791
  ASSERT(current_block()->HasPredecessor());
5288
5792
  CHECK_ALIVE(VisitForValue(expr->expression()));
5289
-
5290
5793
  HValue* value = Pop();
5291
- HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict());
5292
- ast_context()->ReturnInstruction(compare, expr->id());
5794
+ HIsNullAndBranch* instr =
5795
+ new(zone()) HIsNullAndBranch(value, expr->is_strict());
5796
+ return ast_context()->ReturnControl(instr, expr->id());
5293
5797
  }
5294
5798
 
5295
5799
 
@@ -5297,23 +5801,24 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
5297
5801
  ASSERT(!HasStackOverflow());
5298
5802
  ASSERT(current_block() != NULL);
5299
5803
  ASSERT(current_block()->HasPredecessor());
5300
- return Bailout("ThisFunction");
5804
+ HThisFunction* self = new(zone()) HThisFunction;
5805
+ return ast_context()->ReturnInstruction(self, expr->id());
5301
5806
  }
5302
5807
 
5303
5808
 
5304
5809
  void HGraphBuilder::VisitDeclaration(Declaration* decl) {
5305
- // We allow only declarations that do not require code generation.
5306
- // The following all require code generation: global variables and
5307
- // functions, variables with slot type LOOKUP, declarations with
5308
- // mode CONST, and functions.
5810
+ // We support only declarations that do not require code generation.
5309
5811
  Variable* var = decl->proxy()->var();
5310
- Slot* slot = var->AsSlot();
5311
- if (var->is_global() ||
5312
- (slot != NULL && slot->type() == Slot::LOOKUP) ||
5313
- decl->mode() == Variable::CONST ||
5314
- decl->fun() != NULL) {
5812
+ if (!var->IsStackAllocated() ||
5813
+ decl->fun() != NULL ||
5814
+ decl->mode() == Variable::LET) {
5315
5815
  return Bailout("unsupported declaration");
5316
5816
  }
5817
+
5818
+ if (decl->mode() == Variable::CONST) {
5819
+ ASSERT(var->IsStackAllocated());
5820
+ environment()->Bind(var, graph()->GetConstantHole());
5821
+ }
5317
5822
  }
5318
5823
 
5319
5824
 
@@ -5323,8 +5828,8 @@ void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
5323
5828
  ASSERT(call->arguments()->length() == 1);
5324
5829
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5325
5830
  HValue* value = Pop();
5326
- HIsSmi* result = new(zone()) HIsSmi(value);
5327
- ast_context()->ReturnInstruction(result, call->id());
5831
+ HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value);
5832
+ return ast_context()->ReturnControl(result, call->id());
5328
5833
  }
5329
5834
 
5330
5835
 
@@ -5332,9 +5837,11 @@ void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
5332
5837
  ASSERT(call->arguments()->length() == 1);
5333
5838
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5334
5839
  HValue* value = Pop();
5335
- HHasInstanceType* result =
5336
- new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
5337
- ast_context()->ReturnInstruction(result, call->id());
5840
+ HHasInstanceTypeAndBranch* result =
5841
+ new(zone()) HHasInstanceTypeAndBranch(value,
5842
+ FIRST_SPEC_OBJECT_TYPE,
5843
+ LAST_SPEC_OBJECT_TYPE);
5844
+ return ast_context()->ReturnControl(result, call->id());
5338
5845
  }
5339
5846
 
5340
5847
 
@@ -5342,9 +5849,9 @@ void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
5342
5849
  ASSERT(call->arguments()->length() == 1);
5343
5850
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5344
5851
  HValue* value = Pop();
5345
- HHasInstanceType* result =
5346
- new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE);
5347
- ast_context()->ReturnInstruction(result, call->id());
5852
+ HHasInstanceTypeAndBranch* result =
5853
+ new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE);
5854
+ return ast_context()->ReturnControl(result, call->id());
5348
5855
  }
5349
5856
 
5350
5857
 
@@ -5352,8 +5859,9 @@ void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
5352
5859
  ASSERT(call->arguments()->length() == 1);
5353
5860
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5354
5861
  HValue* value = Pop();
5355
- HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value);
5356
- ast_context()->ReturnInstruction(result, call->id());
5862
+ HHasCachedArrayIndexAndBranch* result =
5863
+ new(zone()) HHasCachedArrayIndexAndBranch(value);
5864
+ return ast_context()->ReturnControl(result, call->id());
5357
5865
  }
5358
5866
 
5359
5867
 
@@ -5361,8 +5869,9 @@ void HGraphBuilder::GenerateIsArray(CallRuntime* call) {
5361
5869
  ASSERT(call->arguments()->length() == 1);
5362
5870
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5363
5871
  HValue* value = Pop();
5364
- HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE);
5365
- ast_context()->ReturnInstruction(result, call->id());
5872
+ HHasInstanceTypeAndBranch* result =
5873
+ new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE);
5874
+ return ast_context()->ReturnControl(result, call->id());
5366
5875
  }
5367
5876
 
5368
5877
 
@@ -5370,9 +5879,9 @@ void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
5370
5879
  ASSERT(call->arguments()->length() == 1);
5371
5880
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5372
5881
  HValue* value = Pop();
5373
- HHasInstanceType* result =
5374
- new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE);
5375
- ast_context()->ReturnInstruction(result, call->id());
5882
+ HHasInstanceTypeAndBranch* result =
5883
+ new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE);
5884
+ return ast_context()->ReturnControl(result, call->id());
5376
5885
  }
5377
5886
 
5378
5887
 
@@ -5380,8 +5889,8 @@ void HGraphBuilder::GenerateIsObject(CallRuntime* call) {
5380
5889
  ASSERT(call->arguments()->length() == 1);
5381
5890
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5382
5891
  HValue* value = Pop();
5383
- HIsObject* test = new(zone()) HIsObject(value);
5384
- ast_context()->ReturnInstruction(test, call->id());
5892
+ HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value);
5893
+ return ast_context()->ReturnControl(result, call->id());
5385
5894
  }
5386
5895
 
5387
5896
 
@@ -5394,8 +5903,9 @@ void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
5394
5903
  ASSERT(call->arguments()->length() == 1);
5395
5904
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5396
5905
  HValue* value = Pop();
5397
- ast_context()->ReturnInstruction(new(zone()) HIsUndetectable(value),
5398
- call->id());
5906
+ HIsUndetectableAndBranch* result =
5907
+ new(zone()) HIsUndetectableAndBranch(value);
5908
+ return ast_context()->ReturnControl(result, call->id());
5399
5909
  }
5400
5910
 
5401
5911
 
@@ -5413,23 +5923,32 @@ void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
5413
5923
  // We are generating graph for inlined function. Currently
5414
5924
  // constructor inlining is not supported and we can just return
5415
5925
  // false from %_IsConstructCall().
5416
- ast_context()->ReturnValue(graph()->GetConstantFalse());
5926
+ return ast_context()->ReturnValue(graph()->GetConstantFalse());
5417
5927
  } else {
5418
- ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id());
5928
+ return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
5929
+ call->id());
5419
5930
  }
5420
5931
  }
5421
5932
 
5422
5933
 
5423
5934
  // Support for arguments.length and arguments[?].
5424
5935
  void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
5936
+ // Our implementation of arguments (based on this stack frame or an
5937
+ // adapter below it) does not work for inlined functions. This runtime
5938
+ // function is blacklisted by AstNode::IsInlineable.
5939
+ ASSERT(function_state()->outer() == NULL);
5425
5940
  ASSERT(call->arguments()->length() == 0);
5426
5941
  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
5427
5942
  HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
5428
- ast_context()->ReturnInstruction(result, call->id());
5943
+ return ast_context()->ReturnInstruction(result, call->id());
5429
5944
  }
5430
5945
 
5431
5946
 
5432
5947
  void HGraphBuilder::GenerateArguments(CallRuntime* call) {
5948
+ // Our implementation of arguments (based on this stack frame or an
5949
+ // adapter below it) does not work for inlined functions. This runtime
5950
+ // function is blacklisted by AstNode::IsInlineable.
5951
+ ASSERT(function_state()->outer() == NULL);
5433
5952
  ASSERT(call->arguments()->length() == 1);
5434
5953
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5435
5954
  HValue* index = Pop();
@@ -5437,7 +5956,7 @@ void HGraphBuilder::GenerateArguments(CallRuntime* call) {
5437
5956
  HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
5438
5957
  HAccessArgumentsAt* result =
5439
5958
  new(zone()) HAccessArgumentsAt(elements, length, index);
5440
- ast_context()->ReturnInstruction(result, call->id());
5959
+ return ast_context()->ReturnInstruction(result, call->id());
5441
5960
  }
5442
5961
 
5443
5962
 
@@ -5454,7 +5973,7 @@ void HGraphBuilder::GenerateValueOf(CallRuntime* call) {
5454
5973
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5455
5974
  HValue* value = Pop();
5456
5975
  HValueOf* result = new(zone()) HValueOf(value);
5457
- ast_context()->ReturnInstruction(result, call->id());
5976
+ return ast_context()->ReturnInstruction(result, call->id());
5458
5977
  }
5459
5978
 
5460
5979
 
@@ -5470,8 +5989,9 @@ void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
5470
5989
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5471
5990
  HValue* index = Pop();
5472
5991
  HValue* string = Pop();
5473
- HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
5474
- ast_context()->ReturnInstruction(result, call->id());
5992
+ HValue* context = environment()->LookupContext();
5993
+ HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index);
5994
+ return ast_context()->ReturnInstruction(result, call->id());
5475
5995
  }
5476
5996
 
5477
5997
 
@@ -5480,8 +6000,10 @@ void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
5480
6000
  ASSERT(call->arguments()->length() == 1);
5481
6001
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5482
6002
  HValue* char_code = Pop();
5483
- HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code);
5484
- ast_context()->ReturnInstruction(result, call->id());
6003
+ HValue* context = environment()->LookupContext();
6004
+ HStringCharFromCode* result =
6005
+ new(zone()) HStringCharFromCode(context, char_code);
6006
+ return ast_context()->ReturnInstruction(result, call->id());
5485
6007
  }
5486
6008
 
5487
6009
 
@@ -5492,10 +6014,12 @@ void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
5492
6014
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5493
6015
  HValue* index = Pop();
5494
6016
  HValue* string = Pop();
5495
- HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
6017
+ HValue* context = environment()->LookupContext();
6018
+ HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index);
5496
6019
  AddInstruction(char_code);
5497
- HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code);
5498
- ast_context()->ReturnInstruction(result, call->id());
6020
+ HStringCharFromCode* result =
6021
+ new(zone()) HStringCharFromCode(context, char_code);
6022
+ return ast_context()->ReturnInstruction(result, call->id());
5499
6023
  }
5500
6024
 
5501
6025
 
@@ -5506,14 +6030,15 @@ void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
5506
6030
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5507
6031
  HValue* right = Pop();
5508
6032
  HValue* left = Pop();
5509
- HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right);
5510
- ast_context()->ReturnInstruction(result, call->id());
6033
+ HCompareObjectEqAndBranch* result =
6034
+ new(zone()) HCompareObjectEqAndBranch(left, right);
6035
+ return ast_context()->ReturnControl(result, call->id());
5511
6036
  }
5512
6037
 
5513
6038
 
5514
6039
  void HGraphBuilder::GenerateLog(CallRuntime* call) {
5515
6040
  // %_Log is ignored in optimized code.
5516
- ast_context()->ReturnValue(graph()->GetConstantUndefined());
6041
+ return ast_context()->ReturnValue(graph()->GetConstantUndefined());
5517
6042
  }
5518
6043
 
5519
6044
 
@@ -5530,7 +6055,7 @@ void HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
5530
6055
  HValue* context = environment()->LookupContext();
5531
6056
  HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
5532
6057
  Drop(2);
5533
- ast_context()->ReturnInstruction(result, call->id());
6058
+ return ast_context()->ReturnInstruction(result, call->id());
5534
6059
  }
5535
6060
 
5536
6061
 
@@ -5541,7 +6066,7 @@ void HGraphBuilder::GenerateSubString(CallRuntime* call) {
5541
6066
  HValue* context = environment()->LookupContext();
5542
6067
  HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
5543
6068
  Drop(3);
5544
- ast_context()->ReturnInstruction(result, call->id());
6069
+ return ast_context()->ReturnInstruction(result, call->id());
5545
6070
  }
5546
6071
 
5547
6072
 
@@ -5553,7 +6078,7 @@ void HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
5553
6078
  HCallStub* result =
5554
6079
  new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
5555
6080
  Drop(2);
5556
- ast_context()->ReturnInstruction(result, call->id());
6081
+ return ast_context()->ReturnInstruction(result, call->id());
5557
6082
  }
5558
6083
 
5559
6084
 
@@ -5564,7 +6089,7 @@ void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
5564
6089
  HValue* context = environment()->LookupContext();
5565
6090
  HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
5566
6091
  Drop(4);
5567
- ast_context()->ReturnInstruction(result, call->id());
6092
+ return ast_context()->ReturnInstruction(result, call->id());
5568
6093
  }
5569
6094
 
5570
6095
 
@@ -5576,7 +6101,7 @@ void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
5576
6101
  HCallStub* result =
5577
6102
  new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
5578
6103
  Drop(3);
5579
- ast_context()->ReturnInstruction(result, call->id());
6104
+ return ast_context()->ReturnInstruction(result, call->id());
5580
6105
  }
5581
6106
 
5582
6107
 
@@ -5594,7 +6119,7 @@ void HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
5594
6119
  HCallStub* result =
5595
6120
  new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
5596
6121
  Drop(1);
5597
- ast_context()->ReturnInstruction(result, call->id());
6122
+ return ast_context()->ReturnInstruction(result, call->id());
5598
6123
  }
5599
6124
 
5600
6125
 
@@ -5621,7 +6146,7 @@ void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
5621
6146
  HInvokeFunction* result =
5622
6147
  new(zone()) HInvokeFunction(context, function, arg_count);
5623
6148
  Drop(arg_count);
5624
- ast_context()->ReturnInstruction(result, call->id());
6149
+ return ast_context()->ReturnInstruction(result, call->id());
5625
6150
  }
5626
6151
 
5627
6152
 
@@ -5633,7 +6158,7 @@ void HGraphBuilder::GenerateMathPow(CallRuntime* call) {
5633
6158
  HValue* right = Pop();
5634
6159
  HValue* left = Pop();
5635
6160
  HPower* result = new(zone()) HPower(left, right);
5636
- ast_context()->ReturnInstruction(result, call->id());
6161
+ return ast_context()->ReturnInstruction(result, call->id());
5637
6162
  }
5638
6163
 
5639
6164
 
@@ -5645,7 +6170,7 @@ void HGraphBuilder::GenerateMathSin(CallRuntime* call) {
5645
6170
  new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5646
6171
  result->set_transcendental_type(TranscendentalCache::SIN);
5647
6172
  Drop(1);
5648
- ast_context()->ReturnInstruction(result, call->id());
6173
+ return ast_context()->ReturnInstruction(result, call->id());
5649
6174
  }
5650
6175
 
5651
6176
 
@@ -5657,7 +6182,7 @@ void HGraphBuilder::GenerateMathCos(CallRuntime* call) {
5657
6182
  new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5658
6183
  result->set_transcendental_type(TranscendentalCache::COS);
5659
6184
  Drop(1);
5660
- ast_context()->ReturnInstruction(result, call->id());
6185
+ return ast_context()->ReturnInstruction(result, call->id());
5661
6186
  }
5662
6187
 
5663
6188
 
@@ -5669,7 +6194,7 @@ void HGraphBuilder::GenerateMathLog(CallRuntime* call) {
5669
6194
  new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5670
6195
  result->set_transcendental_type(TranscendentalCache::LOG);
5671
6196
  Drop(1);
5672
- ast_context()->ReturnInstruction(result, call->id());
6197
+ return ast_context()->ReturnInstruction(result, call->id());
5673
6198
  }
5674
6199
 
5675
6200
 
@@ -5689,7 +6214,7 @@ void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
5689
6214
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5690
6215
  HValue* value = Pop();
5691
6216
  HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
5692
- ast_context()->ReturnInstruction(result, call->id());
6217
+ return ast_context()->ReturnInstruction(result, call->id());
5693
6218
  }
5694
6219
 
5695
6220
 
@@ -5860,7 +6385,6 @@ HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
5860
6385
  HEnvironment* HEnvironment::CopyForInlining(
5861
6386
  Handle<JSFunction> target,
5862
6387
  FunctionLiteral* function,
5863
- CompilationPhase compilation_phase,
5864
6388
  HConstant* undefined,
5865
6389
  CallKind call_kind) const {
5866
6390
  // Outer environment is a copy of this one without the arguments.
@@ -5872,22 +6396,15 @@ HEnvironment* HEnvironment::CopyForInlining(
5872
6396
  HEnvironment* inner =
5873
6397
  new(zone) HEnvironment(outer, function->scope(), target);
5874
6398
  // Get the argument values from the original environment.
5875
- if (compilation_phase == HYDROGEN) {
5876
- for (int i = 0; i <= arity; ++i) { // Include receiver.
5877
- HValue* push = ExpressionStackAt(arity - i);
5878
- inner->SetValueAt(i, push);
5879
- }
5880
- } else {
5881
- ASSERT(compilation_phase == LITHIUM);
5882
- for (int i = 0; i <= arity; ++i) { // Include receiver.
5883
- HValue* push = ExpressionStackAt(arity - i);
5884
- inner->SetValueAt(i, push);
5885
- }
5886
- }
5887
- // If the function we are inlining is a strict mode function, pass
5888
- // undefined as the receiver for function calls (instead of the
5889
- // global receiver).
5890
- if (function->strict_mode() && call_kind == CALL_AS_FUNCTION) {
6399
+ for (int i = 0; i <= arity; ++i) { // Include receiver.
6400
+ HValue* push = ExpressionStackAt(arity - i);
6401
+ inner->SetValueAt(i, push);
6402
+ }
6403
+ // If the function we are inlining is a strict mode function or a
6404
+ // builtin function, pass undefined as the receiver for function
6405
+ // calls (instead of the global receiver).
6406
+ if ((target->shared()->native() || function->strict_mode()) &&
6407
+ call_kind == CALL_AS_FUNCTION) {
5891
6408
  inner->SetValueAt(0, undefined);
5892
6409
  }
5893
6410
  inner->SetValueAt(arity + 1, outer->LookupContext());
@@ -5969,15 +6486,15 @@ void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
5969
6486
  PrintEmptyProperty("predecessors");
5970
6487
  }
5971
6488
 
5972
- if (current->end() == NULL || current->end()->FirstSuccessor() == NULL) {
6489
+ if (current->end()->SuccessorCount() == 0) {
5973
6490
  PrintEmptyProperty("successors");
5974
- } else if (current->end()->SecondSuccessor() == NULL) {
5975
- PrintBlockProperty("successors",
5976
- current->end()->FirstSuccessor()->block_id());
5977
- } else {
5978
- PrintBlockProperty("successors",
5979
- current->end()->FirstSuccessor()->block_id(),
5980
- current->end()->SecondSuccessor()->block_id());
6491
+ } else {
6492
+ PrintIndent();
6493
+ trace_.Add("successors");
6494
+ for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
6495
+ trace_.Add(" \"B%d\"", it.Current()->block_id());
6496
+ }
6497
+ trace_.Add("\n");
5981
6498
  }
5982
6499
 
5983
6500
  PrintEmptyProperty("xhandlers");