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