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