libv8 3.3.10.4 → 3.5.10.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/libv8/scons/CHANGES.txt +24 -231
- data/lib/libv8/scons/LICENSE.txt +1 -1
- data/lib/libv8/scons/MANIFEST +0 -1
- data/lib/libv8/scons/PKG-INFO +1 -1
- data/lib/libv8/scons/README.txt +9 -9
- data/lib/libv8/scons/RELEASE.txt +75 -77
- data/lib/libv8/scons/engine/SCons/Action.py +6 -22
- data/lib/libv8/scons/engine/SCons/Builder.py +2 -2
- data/lib/libv8/scons/engine/SCons/CacheDir.py +2 -2
- data/lib/libv8/scons/engine/SCons/Debug.py +2 -2
- data/lib/libv8/scons/engine/SCons/Defaults.py +10 -24
- data/lib/libv8/scons/engine/SCons/Environment.py +19 -118
- data/lib/libv8/scons/engine/SCons/Errors.py +2 -2
- data/lib/libv8/scons/engine/SCons/Executor.py +2 -2
- data/lib/libv8/scons/engine/SCons/Job.py +2 -2
- data/lib/libv8/scons/engine/SCons/Memoize.py +2 -2
- data/lib/libv8/scons/engine/SCons/Node/Alias.py +2 -2
- data/lib/libv8/scons/engine/SCons/Node/FS.py +121 -281
- data/lib/libv8/scons/engine/SCons/Node/Python.py +2 -2
- data/lib/libv8/scons/engine/SCons/Node/__init__.py +5 -6
- data/lib/libv8/scons/engine/SCons/Options/BoolOption.py +2 -2
- data/lib/libv8/scons/engine/SCons/Options/EnumOption.py +2 -2
- data/lib/libv8/scons/engine/SCons/Options/ListOption.py +2 -2
- data/lib/libv8/scons/engine/SCons/Options/PackageOption.py +2 -2
- data/lib/libv8/scons/engine/SCons/Options/PathOption.py +2 -2
- data/lib/libv8/scons/engine/SCons/Options/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/PathList.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/aix.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/cygwin.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/darwin.py +3 -27
- data/lib/libv8/scons/engine/SCons/Platform/hpux.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/irix.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/os2.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/posix.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/sunos.py +2 -2
- data/lib/libv8/scons/engine/SCons/Platform/win32.py +2 -2
- data/lib/libv8/scons/engine/SCons/SConf.py +2 -2
- data/lib/libv8/scons/engine/SCons/SConsign.py +3 -9
- data/lib/libv8/scons/engine/SCons/Scanner/C.py +2 -2
- data/lib/libv8/scons/engine/SCons/Scanner/D.py +2 -2
- data/lib/libv8/scons/engine/SCons/Scanner/Dir.py +2 -2
- data/lib/libv8/scons/engine/SCons/Scanner/Fortran.py +2 -2
- data/lib/libv8/scons/engine/SCons/Scanner/IDL.py +2 -2
- data/lib/libv8/scons/engine/SCons/Scanner/LaTeX.py +2 -5
- data/lib/libv8/scons/engine/SCons/Scanner/Prog.py +2 -2
- data/lib/libv8/scons/engine/SCons/Scanner/RC.py +3 -3
- data/lib/libv8/scons/engine/SCons/Scanner/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/Script/Interactive.py +2 -2
- data/lib/libv8/scons/engine/SCons/Script/Main.py +11 -82
- data/lib/libv8/scons/engine/SCons/Script/SConsOptions.py +5 -5
- data/lib/libv8/scons/engine/SCons/Script/SConscript.py +2 -2
- data/lib/libv8/scons/engine/SCons/Script/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/Sig.py +2 -2
- data/lib/libv8/scons/engine/SCons/Subst.py +2 -2
- data/lib/libv8/scons/engine/SCons/Taskmaster.py +2 -10
- data/lib/libv8/scons/engine/SCons/Tool/386asm.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/BitKeeper.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/CVS.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/FortranCommon.py +2 -19
- data/lib/libv8/scons/engine/SCons/Tool/JavaCommon.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/MSCommon/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/MSCommon/arch.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/MSCommon/common.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/MSCommon/netframework.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/MSCommon/sdk.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/MSCommon/vc.py +6 -9
- data/lib/libv8/scons/engine/SCons/Tool/MSCommon/vs.py +2 -29
- data/lib/libv8/scons/engine/SCons/Tool/Perforce.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/PharLapCommon.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/RCS.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/SCCS.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/Subversion.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/__init__.py +3 -3
- data/lib/libv8/scons/engine/SCons/Tool/aixc++.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/aixcc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/aixf77.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/aixlink.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/applelink.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/ar.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/as.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/bcc32.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/c++.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/cc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/cvf.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/default.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/dmd.py +7 -24
- data/lib/libv8/scons/engine/SCons/Tool/dvi.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/dvipdf.py +2 -3
- data/lib/libv8/scons/engine/SCons/Tool/dvips.py +2 -3
- data/lib/libv8/scons/engine/SCons/Tool/f77.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/f90.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/f95.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/filesystem.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/fortran.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/g++.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/g77.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/gas.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/gcc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/gfortran.py +3 -3
- data/lib/libv8/scons/engine/SCons/Tool/gnulink.py +3 -2
- data/lib/libv8/scons/engine/SCons/Tool/gs.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/hpc++.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/hpcc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/hplink.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/icc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/icl.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/ifl.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/ifort.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/ilink.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/ilink32.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/install.py +3 -57
- data/lib/libv8/scons/engine/SCons/Tool/intelc.py +25 -65
- data/lib/libv8/scons/engine/SCons/Tool/ipkg.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/jar.py +3 -9
- data/lib/libv8/scons/engine/SCons/Tool/javac.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/javah.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/latex.py +2 -3
- data/lib/libv8/scons/engine/SCons/Tool/lex.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/link.py +5 -6
- data/lib/libv8/scons/engine/SCons/Tool/linkloc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/m4.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/masm.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/midl.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/mingw.py +10 -31
- data/lib/libv8/scons/engine/SCons/Tool/mslib.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/mslink.py +9 -61
- data/lib/libv8/scons/engine/SCons/Tool/mssdk.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/msvc.py +11 -21
- data/lib/libv8/scons/engine/SCons/Tool/msvs.py +59 -477
- data/lib/libv8/scons/engine/SCons/Tool/mwcc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/mwld.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/nasm.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/ipk.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/msi.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/rpm.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/src_tarbz2.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/src_targz.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/src_zip.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/tarbz2.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/targz.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/packaging/zip.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/pdf.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/pdflatex.py +2 -3
- data/lib/libv8/scons/engine/SCons/Tool/pdftex.py +2 -3
- data/lib/libv8/scons/engine/SCons/Tool/qt.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/rmic.py +3 -9
- data/lib/libv8/scons/engine/SCons/Tool/rpcgen.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/rpm.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sgiar.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sgic++.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sgicc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sgilink.py +3 -2
- data/lib/libv8/scons/engine/SCons/Tool/sunar.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sunc++.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/suncc.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sunf77.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sunf90.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sunf95.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/sunlink.py +3 -2
- data/lib/libv8/scons/engine/SCons/Tool/swig.py +5 -6
- data/lib/libv8/scons/engine/SCons/Tool/tar.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/tex.py +43 -96
- data/lib/libv8/scons/engine/SCons/Tool/textfile.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/tlib.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/wix.py +2 -2
- data/lib/libv8/scons/engine/SCons/Tool/yacc.py +2 -12
- data/lib/libv8/scons/engine/SCons/Tool/zip.py +2 -2
- data/lib/libv8/scons/engine/SCons/Util.py +3 -3
- data/lib/libv8/scons/engine/SCons/Variables/BoolVariable.py +2 -2
- data/lib/libv8/scons/engine/SCons/Variables/EnumVariable.py +3 -3
- data/lib/libv8/scons/engine/SCons/Variables/ListVariable.py +2 -2
- data/lib/libv8/scons/engine/SCons/Variables/PackageVariable.py +2 -2
- data/lib/libv8/scons/engine/SCons/Variables/PathVariable.py +2 -2
- data/lib/libv8/scons/engine/SCons/Variables/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/Warnings.py +2 -2
- data/lib/libv8/scons/engine/SCons/__init__.py +6 -6
- data/lib/libv8/scons/engine/SCons/compat/__init__.py +2 -2
- data/lib/libv8/scons/engine/SCons/compat/_scons_builtins.py +2 -2
- data/lib/libv8/scons/engine/SCons/compat/_scons_collections.py +2 -2
- data/lib/libv8/scons/engine/SCons/compat/_scons_dbm.py +2 -2
- data/lib/libv8/scons/engine/SCons/compat/_scons_hashlib.py +2 -2
- data/lib/libv8/scons/engine/SCons/compat/_scons_io.py +2 -2
- data/lib/libv8/scons/engine/SCons/cpp.py +2 -2
- data/lib/libv8/scons/engine/SCons/dblite.py +1 -4
- data/lib/libv8/scons/engine/SCons/exitfuncs.py +2 -2
- data/lib/libv8/scons/scons-time.1 +3 -3
- data/lib/libv8/scons/scons.1 +1164 -1170
- data/lib/libv8/scons/sconsign.1 +3 -3
- data/lib/libv8/scons/script/scons +22 -22
- data/lib/libv8/scons/script/scons-time +2 -2
- data/lib/libv8/scons/script/scons.bat +4 -7
- data/lib/libv8/scons/script/sconsign +20 -21
- data/lib/libv8/scons/setup.cfg +1 -0
- data/lib/libv8/scons/setup.py +40 -38
- data/lib/libv8/v8/.gitignore +1 -1
- data/lib/libv8/v8/AUTHORS +2 -0
- data/lib/libv8/v8/ChangeLog +387 -0
- data/lib/libv8/v8/Makefile +171 -0
- data/lib/libv8/v8/SConstruct +124 -51
- data/lib/libv8/v8/build/README.txt +31 -14
- data/lib/libv8/v8/build/all.gyp +11 -4
- data/lib/libv8/v8/build/armu.gypi +6 -2
- data/lib/libv8/v8/build/common.gypi +240 -94
- data/lib/libv8/v8/build/gyp_v8 +32 -4
- data/lib/libv8/v8/build/standalone.gypi +200 -0
- data/lib/libv8/v8/include/v8-debug.h +0 -0
- data/lib/libv8/v8/include/v8-profiler.h +8 -11
- data/lib/libv8/v8/include/v8.h +191 -108
- data/lib/libv8/v8/preparser/SConscript +2 -2
- data/lib/libv8/v8/preparser/preparser-process.cc +3 -3
- data/lib/libv8/v8/preparser/preparser.gyp +42 -0
- data/lib/libv8/v8/src/SConscript +33 -8
- data/lib/libv8/v8/src/accessors.cc +77 -43
- data/lib/libv8/v8/src/api.cc +393 -191
- data/lib/libv8/v8/src/api.h +4 -8
- data/lib/libv8/v8/src/apinatives.js +15 -3
- data/lib/libv8/v8/src/arguments.h +8 -0
- data/lib/libv8/v8/src/arm/assembler-arm.cc +120 -120
- data/lib/libv8/v8/src/arm/assembler-arm.h +92 -43
- data/lib/libv8/v8/src/arm/builtins-arm.cc +32 -39
- data/lib/libv8/v8/src/arm/code-stubs-arm.cc +572 -351
- data/lib/libv8/v8/src/arm/code-stubs-arm.h +8 -77
- data/lib/libv8/v8/src/arm/codegen-arm.h +0 -2
- data/lib/libv8/v8/src/arm/deoptimizer-arm.cc +50 -30
- data/lib/libv8/v8/src/arm/disasm-arm.cc +1 -1
- data/lib/libv8/v8/src/arm/frames-arm.h +9 -5
- data/lib/libv8/v8/src/arm/full-codegen-arm.cc +331 -432
- data/lib/libv8/v8/src/arm/ic-arm.cc +192 -124
- data/lib/libv8/v8/src/arm/lithium-arm.cc +216 -232
- data/lib/libv8/v8/src/arm/lithium-arm.h +106 -259
- data/lib/libv8/v8/src/arm/lithium-codegen-arm.cc +633 -642
- data/lib/libv8/v8/src/arm/lithium-codegen-arm.h +4 -4
- data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.cc +1 -3
- data/lib/libv8/v8/src/arm/macro-assembler-arm.cc +260 -185
- data/lib/libv8/v8/src/arm/macro-assembler-arm.h +45 -25
- data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.cc +25 -13
- data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.h +3 -0
- data/lib/libv8/v8/src/arm/stub-cache-arm.cc +413 -226
- data/lib/libv8/v8/src/array.js +38 -18
- data/lib/libv8/v8/src/assembler.cc +12 -5
- data/lib/libv8/v8/src/assembler.h +15 -9
- data/lib/libv8/v8/src/ast-inl.h +34 -25
- data/lib/libv8/v8/src/ast.cc +141 -72
- data/lib/libv8/v8/src/ast.h +255 -181
- data/lib/libv8/v8/src/bignum.cc +3 -4
- data/lib/libv8/v8/src/bootstrapper.cc +55 -11
- data/lib/libv8/v8/src/bootstrapper.h +3 -2
- data/lib/libv8/v8/src/builtins.cc +8 -2
- data/lib/libv8/v8/src/builtins.h +4 -0
- data/lib/libv8/v8/src/cached-powers.cc +8 -4
- data/lib/libv8/v8/src/checks.h +3 -3
- data/lib/libv8/v8/src/code-stubs.cc +173 -28
- data/lib/libv8/v8/src/code-stubs.h +104 -148
- data/lib/libv8/v8/src/codegen.cc +8 -8
- data/lib/libv8/v8/src/compilation-cache.cc +2 -47
- data/lib/libv8/v8/src/compilation-cache.h +0 -10
- data/lib/libv8/v8/src/compiler.cc +27 -16
- data/lib/libv8/v8/src/compiler.h +13 -18
- data/lib/libv8/v8/src/contexts.cc +107 -72
- data/lib/libv8/v8/src/contexts.h +70 -34
- data/lib/libv8/v8/src/conversions-inl.h +572 -14
- data/lib/libv8/v8/src/conversions.cc +9 -707
- data/lib/libv8/v8/src/conversions.h +23 -12
- data/lib/libv8/v8/src/cpu-profiler-inl.h +2 -19
- data/lib/libv8/v8/src/cpu-profiler.cc +4 -21
- data/lib/libv8/v8/src/cpu-profiler.h +8 -17
- data/lib/libv8/v8/src/d8-debug.cc +5 -3
- data/lib/libv8/v8/src/d8-debug.h +6 -7
- data/lib/libv8/v8/src/d8-posix.cc +1 -10
- data/lib/libv8/v8/src/d8.cc +721 -219
- data/lib/libv8/v8/src/d8.gyp +37 -12
- data/lib/libv8/v8/src/d8.h +141 -19
- data/lib/libv8/v8/src/d8.js +17 -8
- data/lib/libv8/v8/src/date.js +16 -5
- data/lib/libv8/v8/src/dateparser-inl.h +242 -39
- data/lib/libv8/v8/src/dateparser.cc +38 -4
- data/lib/libv8/v8/src/dateparser.h +170 -28
- data/lib/libv8/v8/src/debug-agent.cc +5 -3
- data/lib/libv8/v8/src/debug-agent.h +11 -7
- data/lib/libv8/v8/src/debug-debugger.js +65 -34
- data/lib/libv8/v8/src/debug.cc +30 -60
- data/lib/libv8/v8/src/debug.h +5 -3
- data/lib/libv8/v8/src/deoptimizer.cc +227 -10
- data/lib/libv8/v8/src/deoptimizer.h +133 -9
- data/lib/libv8/v8/src/disassembler.cc +22 -14
- data/lib/libv8/v8/src/diy-fp.cc +4 -3
- data/lib/libv8/v8/src/diy-fp.h +3 -3
- data/lib/libv8/v8/src/elements.cc +634 -0
- data/lib/libv8/v8/src/elements.h +95 -0
- data/lib/libv8/v8/src/execution.cc +5 -21
- data/lib/libv8/v8/src/extensions/experimental/break-iterator.cc +3 -1
- data/lib/libv8/v8/src/extensions/experimental/break-iterator.h +1 -1
- data/lib/libv8/v8/src/extensions/experimental/collator.cc +6 -2
- data/lib/libv8/v8/src/extensions/experimental/collator.h +1 -2
- data/lib/libv8/v8/src/extensions/experimental/datetime-format.cc +384 -0
- data/lib/libv8/v8/src/extensions/experimental/datetime-format.h +83 -0
- data/lib/libv8/v8/src/extensions/experimental/experimental.gyp +18 -7
- data/lib/libv8/v8/src/extensions/experimental/i18n-extension.cc +12 -16
- data/lib/libv8/v8/src/extensions/experimental/i18n-extension.h +1 -1
- data/lib/libv8/v8/src/extensions/experimental/i18n-js2c.py +126 -0
- data/lib/libv8/v8/src/extensions/experimental/i18n-locale.cc +3 -4
- data/lib/libv8/v8/src/extensions/experimental/i18n-locale.h +1 -1
- data/lib/libv8/v8/src/{shell.h → extensions/experimental/i18n-natives.h} +8 -20
- data/lib/libv8/v8/src/extensions/experimental/i18n-utils.cc +45 -1
- data/lib/libv8/v8/src/extensions/experimental/i18n-utils.h +21 -1
- data/lib/libv8/v8/src/extensions/experimental/i18n.js +211 -11
- data/lib/libv8/v8/src/extensions/experimental/language-matcher.cc +4 -3
- data/lib/libv8/v8/src/extensions/experimental/language-matcher.h +1 -1
- data/lib/libv8/v8/src/extensions/experimental/number-format.cc +374 -0
- data/lib/libv8/v8/src/extensions/experimental/number-format.h +71 -0
- data/lib/libv8/v8/src/factory.cc +89 -18
- data/lib/libv8/v8/src/factory.h +36 -8
- data/lib/libv8/v8/src/flag-definitions.h +11 -44
- data/lib/libv8/v8/src/frames-inl.h +8 -1
- data/lib/libv8/v8/src/frames.cc +39 -3
- data/lib/libv8/v8/src/frames.h +10 -3
- data/lib/libv8/v8/src/full-codegen.cc +311 -293
- data/lib/libv8/v8/src/full-codegen.h +183 -143
- data/lib/libv8/v8/src/func-name-inferrer.cc +29 -15
- data/lib/libv8/v8/src/func-name-inferrer.h +19 -9
- data/lib/libv8/v8/src/gdb-jit.cc +658 -55
- data/lib/libv8/v8/src/gdb-jit.h +6 -2
- data/lib/libv8/v8/src/global-handles.cc +368 -312
- data/lib/libv8/v8/src/global-handles.h +29 -36
- data/lib/libv8/v8/src/globals.h +3 -1
- data/lib/libv8/v8/src/handles.cc +43 -69
- data/lib/libv8/v8/src/handles.h +21 -16
- data/lib/libv8/v8/src/heap-inl.h +11 -13
- data/lib/libv8/v8/src/heap-profiler.cc +0 -999
- data/lib/libv8/v8/src/heap-profiler.h +0 -303
- data/lib/libv8/v8/src/heap.cc +366 -141
- data/lib/libv8/v8/src/heap.h +87 -26
- data/lib/libv8/v8/src/hydrogen-instructions.cc +192 -81
- data/lib/libv8/v8/src/hydrogen-instructions.h +711 -482
- data/lib/libv8/v8/src/hydrogen.cc +1146 -629
- data/lib/libv8/v8/src/hydrogen.h +100 -64
- data/lib/libv8/v8/src/ia32/assembler-ia32.cc +19 -0
- data/lib/libv8/v8/src/ia32/assembler-ia32.h +15 -2
- data/lib/libv8/v8/src/ia32/builtins-ia32.cc +34 -39
- data/lib/libv8/v8/src/ia32/code-stubs-ia32.cc +675 -377
- data/lib/libv8/v8/src/ia32/code-stubs-ia32.h +8 -69
- data/lib/libv8/v8/src/ia32/codegen-ia32.cc +1 -0
- data/lib/libv8/v8/src/ia32/codegen-ia32.h +0 -2
- data/lib/libv8/v8/src/ia32/cpu-ia32.cc +3 -2
- data/lib/libv8/v8/src/ia32/deoptimizer-ia32.cc +28 -3
- data/lib/libv8/v8/src/ia32/disasm-ia32.cc +21 -10
- data/lib/libv8/v8/src/ia32/frames-ia32.h +6 -5
- data/lib/libv8/v8/src/ia32/full-codegen-ia32.cc +459 -465
- data/lib/libv8/v8/src/ia32/ic-ia32.cc +196 -147
- data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.cc +575 -650
- data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.h +19 -21
- data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.cc +7 -2
- data/lib/libv8/v8/src/ia32/lithium-ia32.cc +261 -256
- data/lib/libv8/v8/src/ia32/lithium-ia32.h +234 -335
- data/lib/libv8/v8/src/ia32/macro-assembler-ia32.cc +224 -67
- data/lib/libv8/v8/src/ia32/macro-assembler-ia32.h +63 -19
- data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.cc +22 -8
- data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.h +3 -0
- data/lib/libv8/v8/src/ia32/stub-cache-ia32.cc +380 -239
- data/lib/libv8/v8/src/ic.cc +198 -234
- data/lib/libv8/v8/src/ic.h +32 -30
- data/lib/libv8/v8/src/interpreter-irregexp.cc +6 -4
- data/lib/libv8/v8/src/isolate.cc +112 -95
- data/lib/libv8/v8/src/isolate.h +55 -71
- data/lib/libv8/v8/src/json-parser.h +486 -48
- data/lib/libv8/v8/src/json.js +28 -23
- data/lib/libv8/v8/src/jsregexp.cc +163 -208
- data/lib/libv8/v8/src/jsregexp.h +0 -1
- data/lib/libv8/v8/src/lithium-allocator-inl.h +29 -27
- data/lib/libv8/v8/src/lithium-allocator.cc +22 -17
- data/lib/libv8/v8/src/lithium-allocator.h +8 -8
- data/lib/libv8/v8/src/lithium.cc +16 -11
- data/lib/libv8/v8/src/lithium.h +31 -34
- data/lib/libv8/v8/src/liveedit.cc +111 -15
- data/lib/libv8/v8/src/liveedit.h +3 -4
- data/lib/libv8/v8/src/liveobjectlist.cc +116 -80
- data/lib/libv8/v8/src/liveobjectlist.h +2 -2
- data/lib/libv8/v8/src/log-inl.h +0 -4
- data/lib/libv8/v8/src/log-utils.cc +25 -143
- data/lib/libv8/v8/src/log-utils.h +13 -92
- data/lib/libv8/v8/src/log.cc +26 -249
- data/lib/libv8/v8/src/log.h +6 -17
- data/lib/libv8/v8/src/macros.py +9 -6
- data/lib/libv8/v8/src/mark-compact.cc +276 -56
- data/lib/libv8/v8/src/mark-compact.h +20 -0
- data/lib/libv8/v8/src/messages.js +93 -39
- data/lib/libv8/v8/src/mips/assembler-mips-inl.h +9 -3
- data/lib/libv8/v8/src/mips/assembler-mips.cc +297 -189
- data/lib/libv8/v8/src/mips/assembler-mips.h +121 -54
- data/lib/libv8/v8/src/mips/builtins-mips.cc +23 -24
- data/lib/libv8/v8/src/mips/code-stubs-mips.cc +484 -263
- data/lib/libv8/v8/src/mips/code-stubs-mips.h +8 -83
- data/lib/libv8/v8/src/mips/codegen-mips.h +0 -2
- data/lib/libv8/v8/src/mips/constants-mips.h +37 -11
- data/lib/libv8/v8/src/mips/deoptimizer-mips.cc +6 -1
- data/lib/libv8/v8/src/mips/frames-mips.h +8 -7
- data/lib/libv8/v8/src/mips/full-codegen-mips.cc +258 -419
- data/lib/libv8/v8/src/mips/ic-mips.cc +181 -121
- data/lib/libv8/v8/src/mips/macro-assembler-mips.cc +640 -382
- data/lib/libv8/v8/src/mips/macro-assembler-mips.h +94 -89
- data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.cc +23 -10
- data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.h +6 -1
- data/lib/libv8/v8/src/mips/simulator-mips.cc +249 -49
- data/lib/libv8/v8/src/mips/simulator-mips.h +25 -1
- data/lib/libv8/v8/src/mips/stub-cache-mips.cc +373 -161
- data/lib/libv8/v8/src/mirror-debugger.js +55 -8
- data/lib/libv8/v8/src/misc-intrinsics.h +89 -0
- data/lib/libv8/v8/src/mksnapshot.cc +36 -4
- data/lib/libv8/v8/src/natives.h +5 -2
- data/lib/libv8/v8/src/objects-debug.cc +73 -6
- data/lib/libv8/v8/src/objects-inl.h +529 -164
- data/lib/libv8/v8/src/objects-printer.cc +67 -12
- data/lib/libv8/v8/src/objects-visiting.cc +13 -2
- data/lib/libv8/v8/src/objects-visiting.h +41 -1
- data/lib/libv8/v8/src/objects.cc +2200 -1177
- data/lib/libv8/v8/src/objects.h +912 -283
- data/lib/libv8/v8/src/parser.cc +566 -371
- data/lib/libv8/v8/src/parser.h +35 -33
- data/lib/libv8/v8/src/platform-cygwin.cc +10 -25
- data/lib/libv8/v8/src/platform-freebsd.cc +4 -29
- data/lib/libv8/v8/src/platform-linux.cc +60 -57
- data/lib/libv8/v8/src/platform-macos.cc +4 -27
- data/lib/libv8/v8/src/platform-nullos.cc +3 -16
- data/lib/libv8/v8/src/platform-openbsd.cc +247 -85
- data/lib/libv8/v8/src/platform-posix.cc +43 -1
- data/lib/libv8/v8/src/platform-solaris.cc +151 -112
- data/lib/libv8/v8/src/platform-tls.h +1 -1
- data/lib/libv8/v8/src/platform-win32.cc +65 -39
- data/lib/libv8/v8/src/platform.h +17 -14
- data/lib/libv8/v8/src/preparse-data-format.h +2 -2
- data/lib/libv8/v8/src/preparse-data.h +8 -2
- data/lib/libv8/v8/src/preparser-api.cc +2 -18
- data/lib/libv8/v8/src/preparser.cc +106 -65
- data/lib/libv8/v8/src/preparser.h +26 -5
- data/lib/libv8/v8/src/prettyprinter.cc +25 -43
- data/lib/libv8/v8/src/profile-generator-inl.h +0 -4
- data/lib/libv8/v8/src/profile-generator.cc +213 -34
- data/lib/libv8/v8/src/profile-generator.h +9 -9
- data/lib/libv8/v8/src/property.h +1 -0
- data/lib/libv8/v8/src/proxy.js +74 -4
- data/lib/libv8/v8/src/regexp-macro-assembler.cc +10 -6
- data/lib/libv8/v8/src/regexp.js +16 -11
- data/lib/libv8/v8/src/rewriter.cc +24 -133
- data/lib/libv8/v8/src/runtime-profiler.cc +27 -151
- data/lib/libv8/v8/src/runtime-profiler.h +5 -31
- data/lib/libv8/v8/src/runtime.cc +1450 -681
- data/lib/libv8/v8/src/runtime.h +47 -31
- data/lib/libv8/v8/src/runtime.js +2 -1
- data/lib/libv8/v8/src/scanner-base.cc +358 -220
- data/lib/libv8/v8/src/scanner-base.h +30 -138
- data/lib/libv8/v8/src/scanner.cc +0 -18
- data/lib/libv8/v8/src/scanner.h +0 -15
- data/lib/libv8/v8/src/scopeinfo.cc +3 -1
- data/lib/libv8/v8/src/scopeinfo.h +1 -6
- data/lib/libv8/v8/src/scopes.cc +243 -253
- data/lib/libv8/v8/src/scopes.h +58 -109
- data/lib/libv8/v8/src/serialize.cc +12 -54
- data/lib/libv8/v8/src/serialize.h +47 -0
- data/lib/libv8/v8/src/small-pointer-list.h +25 -0
- data/lib/libv8/v8/src/spaces-inl.h +4 -50
- data/lib/libv8/v8/src/spaces.cc +64 -131
- data/lib/libv8/v8/src/spaces.h +19 -70
- data/lib/libv8/v8/src/string-stream.cc +3 -1
- data/lib/libv8/v8/src/string.js +10 -6
- data/lib/libv8/v8/src/strtod.cc +7 -3
- data/lib/libv8/v8/src/stub-cache.cc +59 -129
- data/lib/libv8/v8/src/stub-cache.h +42 -54
- data/lib/libv8/v8/src/third_party/valgrind/valgrind.h +1447 -1339
- data/lib/libv8/v8/src/token.cc +4 -4
- data/lib/libv8/v8/src/token.h +6 -5
- data/lib/libv8/v8/src/type-info.cc +173 -129
- data/lib/libv8/v8/src/type-info.h +40 -22
- data/lib/libv8/v8/src/utils.cc +25 -304
- data/lib/libv8/v8/src/utils.h +118 -3
- data/lib/libv8/v8/src/v8-counters.h +3 -6
- data/lib/libv8/v8/src/v8.cc +34 -27
- data/lib/libv8/v8/src/v8.h +7 -7
- data/lib/libv8/v8/src/v8conversions.cc +129 -0
- data/lib/libv8/v8/src/v8conversions.h +60 -0
- data/lib/libv8/v8/src/v8globals.h +15 -6
- data/lib/libv8/v8/src/v8natives.js +300 -78
- data/lib/libv8/v8/src/v8threads.cc +14 -6
- data/lib/libv8/v8/src/v8threads.h +4 -1
- data/lib/libv8/v8/src/v8utils.cc +360 -0
- data/lib/libv8/v8/src/v8utils.h +17 -66
- data/lib/libv8/v8/src/variables.cc +7 -12
- data/lib/libv8/v8/src/variables.h +12 -10
- data/lib/libv8/v8/src/version.cc +2 -2
- data/lib/libv8/v8/src/vm-state-inl.h +0 -41
- data/lib/libv8/v8/src/vm-state.h +0 -11
- data/lib/libv8/v8/src/weakmap.js +103 -0
- data/lib/libv8/v8/src/x64/assembler-x64.h +6 -3
- data/lib/libv8/v8/src/x64/builtins-x64.cc +25 -22
- data/lib/libv8/v8/src/x64/code-stubs-x64.cc +523 -250
- data/lib/libv8/v8/src/x64/code-stubs-x64.h +8 -71
- data/lib/libv8/v8/src/x64/codegen-x64.cc +1 -0
- data/lib/libv8/v8/src/x64/codegen-x64.h +0 -2
- data/lib/libv8/v8/src/x64/cpu-x64.cc +2 -1
- data/lib/libv8/v8/src/x64/deoptimizer-x64.cc +40 -8
- data/lib/libv8/v8/src/x64/disasm-x64.cc +12 -10
- data/lib/libv8/v8/src/x64/frames-x64.h +7 -6
- data/lib/libv8/v8/src/x64/full-codegen-x64.cc +310 -415
- data/lib/libv8/v8/src/x64/ic-x64.cc +180 -117
- data/lib/libv8/v8/src/x64/lithium-codegen-x64.cc +411 -523
- data/lib/libv8/v8/src/x64/lithium-codegen-x64.h +11 -6
- data/lib/libv8/v8/src/x64/lithium-x64.cc +191 -216
- data/lib/libv8/v8/src/x64/lithium-x64.h +112 -263
- data/lib/libv8/v8/src/x64/macro-assembler-x64.cc +177 -61
- data/lib/libv8/v8/src/x64/macro-assembler-x64.h +23 -7
- data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.cc +21 -9
- data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.h +6 -0
- data/lib/libv8/v8/src/x64/stub-cache-x64.cc +273 -107
- data/lib/libv8/v8/src/zone.cc +31 -22
- data/lib/libv8/v8/src/zone.h +12 -6
- data/lib/libv8/v8/tools/codemap.js +8 -0
- data/lib/libv8/v8/tools/gcmole/Makefile +43 -0
- data/lib/libv8/v8/tools/gcmole/gcmole.lua +0 -2
- data/lib/libv8/v8/tools/gdb-v8-support.py +154 -0
- data/lib/libv8/v8/tools/grokdump.py +44 -35
- data/lib/libv8/v8/tools/gyp/v8.gyp +94 -248
- data/lib/libv8/v8/tools/js2c.py +83 -52
- data/lib/libv8/v8/tools/linux-tick-processor +4 -6
- data/lib/libv8/v8/tools/ll_prof.py +3 -3
- data/lib/libv8/v8/tools/oom_dump/README +3 -1
- data/lib/libv8/v8/tools/presubmit.py +11 -4
- data/lib/libv8/v8/tools/profile.js +46 -2
- data/lib/libv8/v8/tools/splaytree.js +11 -0
- data/lib/libv8/v8/tools/stats-viewer.py +15 -11
- data/lib/libv8/v8/tools/test-wrapper-gypbuild.py +227 -0
- data/lib/libv8/v8/tools/test.py +28 -8
- data/lib/libv8/v8/tools/tickprocessor.js +0 -16
- data/lib/libv8/version.rb +1 -1
- data/libv8.gemspec +2 -2
- metadata +31 -19
- data/lib/libv8/scons/engine/SCons/Tool/f03.py +0 -63
- data/lib/libv8/v8/src/json-parser.cc +0 -504
|
@@ -128,11 +128,11 @@ bool LCodeGen::GeneratePrologue() {
|
|
|
128
128
|
}
|
|
129
129
|
#endif
|
|
130
130
|
|
|
131
|
-
// Strict mode functions need to replace the receiver
|
|
132
|
-
// when called as functions (without an explicit
|
|
133
|
-
// object). ecx is zero for method calls and non-zero for
|
|
134
|
-
// calls.
|
|
135
|
-
if (info_->is_strict_mode()) {
|
|
131
|
+
// Strict mode functions and builtins need to replace the receiver
|
|
132
|
+
// with undefined when called as functions (without an explicit
|
|
133
|
+
// receiver object). ecx is zero for method calls and non-zero for
|
|
134
|
+
// function calls.
|
|
135
|
+
if (info_->is_strict_mode() || info_->is_native()) {
|
|
136
136
|
Label ok;
|
|
137
137
|
__ test(ecx, Operand(ecx));
|
|
138
138
|
__ j(zero, &ok, Label::kNear);
|
|
@@ -184,7 +184,7 @@ bool LCodeGen::GeneratePrologue() {
|
|
|
184
184
|
FastNewContextStub stub(heap_slots);
|
|
185
185
|
__ CallStub(&stub);
|
|
186
186
|
} else {
|
|
187
|
-
__ CallRuntime(Runtime::
|
|
187
|
+
__ CallRuntime(Runtime::kNewFunctionContext, 1);
|
|
188
188
|
}
|
|
189
189
|
RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
|
|
190
190
|
// Context is returned in both eax and esi. It replaces the context
|
|
@@ -255,11 +255,20 @@ LInstruction* LCodeGen::GetNextInstruction() {
|
|
|
255
255
|
|
|
256
256
|
bool LCodeGen::GenerateDeferredCode() {
|
|
257
257
|
ASSERT(is_generating());
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
if (deferred_.length() > 0) {
|
|
259
|
+
for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
|
|
260
|
+
LDeferredCode* code = deferred_[i];
|
|
261
|
+
__ bind(code->entry());
|
|
262
|
+
code->Generate();
|
|
263
|
+
__ jmp(code->exit());
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Pad code to ensure that the last piece of deferred code have
|
|
267
|
+
// room for lazy bailout.
|
|
268
|
+
while ((masm()->pc_offset() - LastSafepointEnd())
|
|
269
|
+
< Deoptimizer::patch_size()) {
|
|
270
|
+
__ nop();
|
|
271
|
+
}
|
|
263
272
|
}
|
|
264
273
|
|
|
265
274
|
// Deferred code is the last part of the instruction sequence. Mark
|
|
@@ -428,15 +437,11 @@ void LCodeGen::AddToTranslation(Translation* translation,
|
|
|
428
437
|
void LCodeGen::CallCodeGeneric(Handle<Code> code,
|
|
429
438
|
RelocInfo::Mode mode,
|
|
430
439
|
LInstruction* instr,
|
|
431
|
-
ContextMode context_mode,
|
|
432
440
|
SafepointMode safepoint_mode) {
|
|
433
441
|
ASSERT(instr != NULL);
|
|
434
442
|
LPointerMap* pointers = instr->pointer_map();
|
|
435
443
|
RecordPosition(pointers->position());
|
|
436
444
|
|
|
437
|
-
if (context_mode == RESTORE_CONTEXT) {
|
|
438
|
-
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
439
|
-
}
|
|
440
445
|
__ call(code, mode);
|
|
441
446
|
|
|
442
447
|
RegisterLazyDeoptimization(instr, safepoint_mode);
|
|
@@ -452,24 +457,19 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
|
|
|
452
457
|
|
|
453
458
|
void LCodeGen::CallCode(Handle<Code> code,
|
|
454
459
|
RelocInfo::Mode mode,
|
|
455
|
-
LInstruction* instr
|
|
456
|
-
|
|
457
|
-
CallCodeGeneric(code, mode, instr, context_mode, RECORD_SIMPLE_SAFEPOINT);
|
|
460
|
+
LInstruction* instr) {
|
|
461
|
+
CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
|
|
458
462
|
}
|
|
459
463
|
|
|
460
464
|
|
|
461
465
|
void LCodeGen::CallRuntime(const Runtime::Function* fun,
|
|
462
466
|
int argc,
|
|
463
|
-
LInstruction* instr
|
|
464
|
-
ContextMode context_mode) {
|
|
467
|
+
LInstruction* instr) {
|
|
465
468
|
ASSERT(instr != NULL);
|
|
466
469
|
ASSERT(instr->HasPointerMap());
|
|
467
470
|
LPointerMap* pointers = instr->pointer_map();
|
|
468
471
|
RecordPosition(pointers->position());
|
|
469
472
|
|
|
470
|
-
if (context_mode == RESTORE_CONTEXT) {
|
|
471
|
-
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
472
|
-
}
|
|
473
473
|
__ CallRuntime(fun, argc);
|
|
474
474
|
|
|
475
475
|
RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
|
|
@@ -478,8 +478,18 @@ void LCodeGen::CallRuntime(const Runtime::Function* fun,
|
|
|
478
478
|
|
|
479
479
|
void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
|
|
480
480
|
int argc,
|
|
481
|
-
LInstruction* instr
|
|
482
|
-
|
|
481
|
+
LInstruction* instr,
|
|
482
|
+
LOperand* context) {
|
|
483
|
+
ASSERT(context->IsRegister() || context->IsStackSlot());
|
|
484
|
+
if (context->IsRegister()) {
|
|
485
|
+
if (!ToRegister(context).is(esi)) {
|
|
486
|
+
__ mov(esi, ToRegister(context));
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
// Context is stack slot.
|
|
490
|
+
__ mov(esi, ToOperand(context));
|
|
491
|
+
}
|
|
492
|
+
|
|
483
493
|
__ CallRuntimeSaveDoubles(id);
|
|
484
494
|
RecordSafepointWithRegisters(
|
|
485
495
|
instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex);
|
|
@@ -693,7 +703,7 @@ void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
|
|
|
693
703
|
|
|
694
704
|
|
|
695
705
|
void LCodeGen::RecordPosition(int position) {
|
|
696
|
-
if (
|
|
706
|
+
if (position == RelocInfo::kNoPosition) return;
|
|
697
707
|
masm()->positions_recorder()->RecordPosition(position);
|
|
698
708
|
}
|
|
699
709
|
|
|
@@ -748,38 +758,38 @@ void LCodeGen::DoCallStub(LCallStub* instr) {
|
|
|
748
758
|
switch (instr->hydrogen()->major_key()) {
|
|
749
759
|
case CodeStub::RegExpConstructResult: {
|
|
750
760
|
RegExpConstructResultStub stub;
|
|
751
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
761
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
752
762
|
break;
|
|
753
763
|
}
|
|
754
764
|
case CodeStub::RegExpExec: {
|
|
755
765
|
RegExpExecStub stub;
|
|
756
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
766
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
757
767
|
break;
|
|
758
768
|
}
|
|
759
769
|
case CodeStub::SubString: {
|
|
760
770
|
SubStringStub stub;
|
|
761
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
771
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
762
772
|
break;
|
|
763
773
|
}
|
|
764
774
|
case CodeStub::NumberToString: {
|
|
765
775
|
NumberToStringStub stub;
|
|
766
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
776
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
767
777
|
break;
|
|
768
778
|
}
|
|
769
779
|
case CodeStub::StringAdd: {
|
|
770
780
|
StringAddStub stub(NO_STRING_ADD_FLAGS);
|
|
771
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
781
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
772
782
|
break;
|
|
773
783
|
}
|
|
774
784
|
case CodeStub::StringCompare: {
|
|
775
785
|
StringCompareStub stub;
|
|
776
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
786
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
777
787
|
break;
|
|
778
788
|
}
|
|
779
789
|
case CodeStub::TranscendentalCache: {
|
|
780
790
|
TranscendentalCacheStub stub(instr->transcendental_type(),
|
|
781
791
|
TranscendentalCacheStub::TAGGED);
|
|
782
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
792
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
783
793
|
break;
|
|
784
794
|
}
|
|
785
795
|
default:
|
|
@@ -811,6 +821,8 @@ void LCodeGen::DoModI(LModI* instr) {
|
|
|
811
821
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
|
812
822
|
__ j(not_zero, &done, Label::kNear);
|
|
813
823
|
DeoptimizeIf(no_condition, instr->environment());
|
|
824
|
+
} else {
|
|
825
|
+
__ jmp(&done, Label::kNear);
|
|
814
826
|
}
|
|
815
827
|
__ bind(&positive_dividend);
|
|
816
828
|
__ and_(dividend, divisor - 1);
|
|
@@ -1199,17 +1211,26 @@ void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
|
|
|
1199
1211
|
}
|
|
1200
1212
|
|
|
1201
1213
|
|
|
1202
|
-
void LCodeGen::
|
|
1214
|
+
void LCodeGen::DoFixedArrayBaseLength(
|
|
1215
|
+
LFixedArrayBaseLength* instr) {
|
|
1203
1216
|
Register result = ToRegister(instr->result());
|
|
1204
1217
|
Register array = ToRegister(instr->InputAt(0));
|
|
1205
|
-
__ mov(result, FieldOperand(array,
|
|
1218
|
+
__ mov(result, FieldOperand(array, FixedArrayBase::kLengthOffset));
|
|
1206
1219
|
}
|
|
1207
1220
|
|
|
1208
1221
|
|
|
1209
|
-
void LCodeGen::
|
|
1222
|
+
void LCodeGen::DoElementsKind(LElementsKind* instr) {
|
|
1210
1223
|
Register result = ToRegister(instr->result());
|
|
1211
|
-
Register
|
|
1212
|
-
|
|
1224
|
+
Register input = ToRegister(instr->InputAt(0));
|
|
1225
|
+
|
|
1226
|
+
// Load map into |result|.
|
|
1227
|
+
__ mov(result, FieldOperand(input, HeapObject::kMapOffset));
|
|
1228
|
+
// Load the map's "bit field 2" into |result|. We only need the first byte,
|
|
1229
|
+
// but the following masking takes care of that anyway.
|
|
1230
|
+
__ mov(result, FieldOperand(result, Map::kBitField2Offset));
|
|
1231
|
+
// Retrieve elements_kind from bit field 2.
|
|
1232
|
+
__ and_(result, Map::kElementsKindMask);
|
|
1233
|
+
__ shr(result, Map::kElementsKindShift);
|
|
1213
1234
|
}
|
|
1214
1235
|
|
|
1215
1236
|
|
|
@@ -1220,8 +1241,7 @@ void LCodeGen::DoValueOf(LValueOf* instr) {
|
|
|
1220
1241
|
ASSERT(input.is(result));
|
|
1221
1242
|
Label done;
|
|
1222
1243
|
// If the object is a smi return the object.
|
|
1223
|
-
__
|
|
1224
|
-
__ j(zero, &done, Label::kNear);
|
|
1244
|
+
__ JumpIfSmi(input, &done, Label::kNear);
|
|
1225
1245
|
|
|
1226
1246
|
// If the object is not a value type, return the object.
|
|
1227
1247
|
__ CmpObjectType(input, JS_VALUE_TYPE, map);
|
|
@@ -1240,8 +1260,9 @@ void LCodeGen::DoBitNotI(LBitNotI* instr) {
|
|
|
1240
1260
|
|
|
1241
1261
|
|
|
1242
1262
|
void LCodeGen::DoThrow(LThrow* instr) {
|
|
1243
|
-
__ push(ToOperand(instr->
|
|
1244
|
-
|
|
1263
|
+
__ push(ToOperand(instr->value()));
|
|
1264
|
+
ASSERT(ToRegister(instr->context()).is(esi));
|
|
1265
|
+
CallRuntime(Runtime::kThrow, 1, instr);
|
|
1245
1266
|
|
|
1246
1267
|
if (FLAG_debug_code) {
|
|
1247
1268
|
Comment("Unreachable code.");
|
|
@@ -1311,12 +1332,14 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
|
|
1311
1332
|
|
|
1312
1333
|
|
|
1313
1334
|
void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
|
|
1314
|
-
ASSERT(ToRegister(instr->
|
|
1315
|
-
ASSERT(ToRegister(instr->
|
|
1335
|
+
ASSERT(ToRegister(instr->context()).is(esi));
|
|
1336
|
+
ASSERT(ToRegister(instr->left()).is(edx));
|
|
1337
|
+
ASSERT(ToRegister(instr->right()).is(eax));
|
|
1316
1338
|
ASSERT(ToRegister(instr->result()).is(eax));
|
|
1317
1339
|
|
|
1318
1340
|
BinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
|
1319
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
1341
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
1342
|
+
__ nop(); // Signals no inlined code.
|
|
1320
1343
|
}
|
|
1321
1344
|
|
|
1322
1345
|
|
|
@@ -1351,7 +1374,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
|
|
|
1351
1374
|
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
|
1352
1375
|
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
1353
1376
|
|
|
1354
|
-
Representation r = instr->hydrogen()->representation();
|
|
1377
|
+
Representation r = instr->hydrogen()->value()->representation();
|
|
1355
1378
|
if (r.IsInteger32()) {
|
|
1356
1379
|
Register reg = ToRegister(instr->InputAt(0));
|
|
1357
1380
|
__ test(reg, Operand(reg));
|
|
@@ -1364,89 +1387,114 @@ void LCodeGen::DoBranch(LBranch* instr) {
|
|
|
1364
1387
|
} else {
|
|
1365
1388
|
ASSERT(r.IsTagged());
|
|
1366
1389
|
Register reg = ToRegister(instr->InputAt(0));
|
|
1367
|
-
|
|
1390
|
+
HType type = instr->hydrogen()->value()->type();
|
|
1391
|
+
if (type.IsBoolean()) {
|
|
1368
1392
|
__ cmp(reg, factory()->true_value());
|
|
1369
1393
|
EmitBranch(true_block, false_block, equal);
|
|
1394
|
+
} else if (type.IsSmi()) {
|
|
1395
|
+
__ test(reg, Operand(reg));
|
|
1396
|
+
EmitBranch(true_block, false_block, not_equal);
|
|
1370
1397
|
} else {
|
|
1371
1398
|
Label* true_label = chunk_->GetAssemblyLabel(true_block);
|
|
1372
1399
|
Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
|
1373
1400
|
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1401
|
+
ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
|
|
1402
|
+
// Avoid deopts in the case where we've never executed this path before.
|
|
1403
|
+
if (expected.IsEmpty()) expected = ToBooleanStub::all_types();
|
|
1404
|
+
|
|
1405
|
+
if (expected.Contains(ToBooleanStub::UNDEFINED)) {
|
|
1406
|
+
// undefined -> false.
|
|
1407
|
+
__ cmp(reg, factory()->undefined_value());
|
|
1408
|
+
__ j(equal, false_label);
|
|
1409
|
+
}
|
|
1410
|
+
if (expected.Contains(ToBooleanStub::BOOLEAN)) {
|
|
1411
|
+
// true -> true.
|
|
1412
|
+
__ cmp(reg, factory()->true_value());
|
|
1413
|
+
__ j(equal, true_label);
|
|
1414
|
+
// false -> false.
|
|
1415
|
+
__ cmp(reg, factory()->false_value());
|
|
1416
|
+
__ j(equal, false_label);
|
|
1417
|
+
}
|
|
1418
|
+
if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
|
|
1419
|
+
// 'null' -> false.
|
|
1420
|
+
__ cmp(reg, factory()->null_value());
|
|
1421
|
+
__ j(equal, false_label);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
if (expected.Contains(ToBooleanStub::SMI)) {
|
|
1425
|
+
// Smis: 0 -> false, all other -> true.
|
|
1426
|
+
__ test(reg, Operand(reg));
|
|
1427
|
+
__ j(equal, false_label);
|
|
1428
|
+
__ JumpIfSmi(reg, true_label);
|
|
1429
|
+
} else if (expected.NeedsMap()) {
|
|
1430
|
+
// If we need a map later and have a Smi -> deopt.
|
|
1431
|
+
__ test(reg, Immediate(kSmiTagMask));
|
|
1432
|
+
DeoptimizeIf(zero, instr->environment());
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
Register map = no_reg; // Keep the compiler happy.
|
|
1436
|
+
if (expected.NeedsMap()) {
|
|
1437
|
+
map = ToRegister(instr->TempAt(0));
|
|
1438
|
+
ASSERT(!map.is(reg));
|
|
1439
|
+
__ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
|
|
1440
|
+
|
|
1441
|
+
if (expected.CanBeUndetectable()) {
|
|
1442
|
+
// Undetectable -> false.
|
|
1443
|
+
__ test_b(FieldOperand(map, Map::kBitFieldOffset),
|
|
1444
|
+
1 << Map::kIsUndetectable);
|
|
1445
|
+
__ j(not_zero, false_label);
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
|
|
1450
|
+
// spec object -> true.
|
|
1451
|
+
__ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
|
|
1452
|
+
__ j(above_equal, true_label);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
if (expected.Contains(ToBooleanStub::STRING)) {
|
|
1456
|
+
// String value -> false iff empty.
|
|
1457
|
+
Label not_string;
|
|
1458
|
+
__ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
|
|
1459
|
+
__ j(above_equal, ¬_string, Label::kNear);
|
|
1460
|
+
__ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
|
|
1461
|
+
__ j(not_zero, true_label);
|
|
1462
|
+
__ jmp(false_label);
|
|
1463
|
+
__ bind(¬_string);
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
|
|
1467
|
+
// heap number -> false iff +0, -0, or NaN.
|
|
1468
|
+
Label not_heap_number;
|
|
1469
|
+
__ cmp(FieldOperand(reg, HeapObject::kMapOffset),
|
|
1470
|
+
factory()->heap_number_map());
|
|
1471
|
+
__ j(not_equal, ¬_heap_number, Label::kNear);
|
|
1472
|
+
__ fldz();
|
|
1473
|
+
__ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
|
|
1474
|
+
__ FCmp();
|
|
1475
|
+
__ j(zero, false_label);
|
|
1476
|
+
__ jmp(true_label);
|
|
1477
|
+
__ bind(¬_heap_number);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
// We've seen something for the first time -> deopt.
|
|
1481
|
+
DeoptimizeIf(no_condition, instr->environment());
|
|
1406
1482
|
}
|
|
1407
1483
|
}
|
|
1408
1484
|
}
|
|
1409
1485
|
|
|
1410
1486
|
|
|
1411
|
-
void LCodeGen::EmitGoto(int block
|
|
1487
|
+
void LCodeGen::EmitGoto(int block) {
|
|
1412
1488
|
block = chunk_->LookupDestination(block);
|
|
1413
1489
|
int next_block = GetNextEmittedBlock(current_block_);
|
|
1414
1490
|
if (block != next_block) {
|
|
1415
|
-
|
|
1416
|
-
if (deferred_stack_check != NULL) {
|
|
1417
|
-
ExternalReference stack_limit =
|
|
1418
|
-
ExternalReference::address_of_stack_limit(isolate());
|
|
1419
|
-
__ cmp(esp, Operand::StaticVariable(stack_limit));
|
|
1420
|
-
__ j(above_equal, chunk_->GetAssemblyLabel(block));
|
|
1421
|
-
__ jmp(deferred_stack_check->entry());
|
|
1422
|
-
deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block));
|
|
1423
|
-
} else {
|
|
1424
|
-
__ jmp(chunk_->GetAssemblyLabel(block));
|
|
1425
|
-
}
|
|
1491
|
+
__ jmp(chunk_->GetAssemblyLabel(block));
|
|
1426
1492
|
}
|
|
1427
1493
|
}
|
|
1428
1494
|
|
|
1429
1495
|
|
|
1430
|
-
void LCodeGen::DoDeferredStackCheck(LGoto* instr) {
|
|
1431
|
-
PushSafepointRegistersScope scope(this);
|
|
1432
|
-
CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr);
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
1496
|
void LCodeGen::DoGoto(LGoto* instr) {
|
|
1436
|
-
|
|
1437
|
-
public:
|
|
1438
|
-
DeferredStackCheck(LCodeGen* codegen, LGoto* instr)
|
|
1439
|
-
: LDeferredCode(codegen), instr_(instr) { }
|
|
1440
|
-
virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
|
|
1441
|
-
private:
|
|
1442
|
-
LGoto* instr_;
|
|
1443
|
-
};
|
|
1444
|
-
|
|
1445
|
-
DeferredStackCheck* deferred = NULL;
|
|
1446
|
-
if (instr->include_stack_check()) {
|
|
1447
|
-
deferred = new DeferredStackCheck(this, instr);
|
|
1448
|
-
}
|
|
1449
|
-
EmitGoto(instr->block_id(), deferred);
|
|
1497
|
+
EmitGoto(instr->block_id());
|
|
1450
1498
|
}
|
|
1451
1499
|
|
|
1452
1500
|
|
|
@@ -1487,32 +1535,6 @@ void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
|
|
|
1487
1535
|
}
|
|
1488
1536
|
|
|
1489
1537
|
|
|
1490
|
-
void LCodeGen::DoCmpID(LCmpID* instr) {
|
|
1491
|
-
LOperand* left = instr->InputAt(0);
|
|
1492
|
-
LOperand* right = instr->InputAt(1);
|
|
1493
|
-
LOperand* result = instr->result();
|
|
1494
|
-
|
|
1495
|
-
Label unordered;
|
|
1496
|
-
if (instr->is_double()) {
|
|
1497
|
-
// Don't base result on EFLAGS when a NaN is involved. Instead
|
|
1498
|
-
// jump to the unordered case, which produces a false value.
|
|
1499
|
-
__ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
|
|
1500
|
-
__ j(parity_even, &unordered, Label::kNear);
|
|
1501
|
-
} else {
|
|
1502
|
-
EmitCmpI(left, right);
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
Label done;
|
|
1506
|
-
Condition cc = TokenToCondition(instr->op(), instr->is_double());
|
|
1507
|
-
__ mov(ToRegister(result), factory()->true_value());
|
|
1508
|
-
__ j(cc, &done, Label::kNear);
|
|
1509
|
-
|
|
1510
|
-
__ bind(&unordered);
|
|
1511
|
-
__ mov(ToRegister(result), factory()->false_value());
|
|
1512
|
-
__ bind(&done);
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
1538
|
void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
|
|
1517
1539
|
LOperand* left = instr->InputAt(0);
|
|
1518
1540
|
LOperand* right = instr->InputAt(1);
|
|
@@ -1533,23 +1555,9 @@ void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
|
|
|
1533
1555
|
}
|
|
1534
1556
|
|
|
1535
1557
|
|
|
1536
|
-
void LCodeGen::
|
|
1558
|
+
void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
|
|
1537
1559
|
Register left = ToRegister(instr->InputAt(0));
|
|
1538
|
-
|
|
1539
|
-
Register result = ToRegister(instr->result());
|
|
1540
|
-
|
|
1541
|
-
__ cmp(left, Operand(right));
|
|
1542
|
-
__ mov(result, factory()->true_value());
|
|
1543
|
-
Label done;
|
|
1544
|
-
__ j(equal, &done, Label::kNear);
|
|
1545
|
-
__ mov(result, factory()->false_value());
|
|
1546
|
-
__ bind(&done);
|
|
1547
|
-
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
|
|
1551
|
-
Register left = ToRegister(instr->InputAt(0));
|
|
1552
|
-
Register right = ToRegister(instr->InputAt(1));
|
|
1560
|
+
Operand right = ToOperand(instr->InputAt(1));
|
|
1553
1561
|
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
1554
1562
|
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
|
1555
1563
|
|
|
@@ -1558,69 +1566,16 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
|
|
|
1558
1566
|
}
|
|
1559
1567
|
|
|
1560
1568
|
|
|
1561
|
-
void LCodeGen::
|
|
1562
|
-
Register left = ToRegister(instr->InputAt(0));
|
|
1563
|
-
Register right = ToRegister(instr->InputAt(1));
|
|
1564
|
-
Register result = ToRegister(instr->result());
|
|
1565
|
-
|
|
1566
|
-
Label done;
|
|
1567
|
-
__ cmp(left, Operand(right));
|
|
1568
|
-
__ mov(result, factory()->false_value());
|
|
1569
|
-
__ j(not_equal, &done, Label::kNear);
|
|
1570
|
-
__ mov(result, factory()->true_value());
|
|
1571
|
-
__ bind(&done);
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
|
|
1569
|
+
void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
|
|
1576
1570
|
Register left = ToRegister(instr->InputAt(0));
|
|
1577
|
-
Register right = ToRegister(instr->InputAt(1));
|
|
1578
|
-
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
1579
1571
|
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
|
1572
|
+
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
1580
1573
|
|
|
1581
|
-
__ cmp(left,
|
|
1574
|
+
__ cmp(left, instr->hydrogen()->right());
|
|
1582
1575
|
EmitBranch(true_block, false_block, equal);
|
|
1583
1576
|
}
|
|
1584
1577
|
|
|
1585
1578
|
|
|
1586
|
-
void LCodeGen::DoIsNull(LIsNull* instr) {
|
|
1587
|
-
Register reg = ToRegister(instr->InputAt(0));
|
|
1588
|
-
Register result = ToRegister(instr->result());
|
|
1589
|
-
|
|
1590
|
-
// TODO(fsc): If the expression is known to be a smi, then it's
|
|
1591
|
-
// definitely not null. Materialize false.
|
|
1592
|
-
|
|
1593
|
-
__ cmp(reg, factory()->null_value());
|
|
1594
|
-
if (instr->is_strict()) {
|
|
1595
|
-
__ mov(result, factory()->true_value());
|
|
1596
|
-
Label done;
|
|
1597
|
-
__ j(equal, &done, Label::kNear);
|
|
1598
|
-
__ mov(result, factory()->false_value());
|
|
1599
|
-
__ bind(&done);
|
|
1600
|
-
} else {
|
|
1601
|
-
Label true_value, false_value, done;
|
|
1602
|
-
__ j(equal, &true_value, Label::kNear);
|
|
1603
|
-
__ cmp(reg, factory()->undefined_value());
|
|
1604
|
-
__ j(equal, &true_value, Label::kNear);
|
|
1605
|
-
__ test(reg, Immediate(kSmiTagMask));
|
|
1606
|
-
__ j(zero, &false_value, Label::kNear);
|
|
1607
|
-
// Check for undetectable objects by looking in the bit field in
|
|
1608
|
-
// the map. The object has already been smi checked.
|
|
1609
|
-
Register scratch = result;
|
|
1610
|
-
__ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
|
|
1611
|
-
__ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
|
|
1612
|
-
__ test(scratch, Immediate(1 << Map::kIsUndetectable));
|
|
1613
|
-
__ j(not_zero, &true_value, Label::kNear);
|
|
1614
|
-
__ bind(&false_value);
|
|
1615
|
-
__ mov(result, factory()->false_value());
|
|
1616
|
-
__ jmp(&done, Label::kNear);
|
|
1617
|
-
__ bind(&true_value);
|
|
1618
|
-
__ mov(result, factory()->true_value());
|
|
1619
|
-
__ bind(&done);
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
1579
|
void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
|
1625
1580
|
Register reg = ToRegister(instr->InputAt(0));
|
|
1626
1581
|
|
|
@@ -1639,8 +1594,7 @@ void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
|
|
1639
1594
|
__ j(equal, true_label);
|
|
1640
1595
|
__ cmp(reg, factory()->undefined_value());
|
|
1641
1596
|
__ j(equal, true_label);
|
|
1642
|
-
__
|
|
1643
|
-
__ j(zero, false_label);
|
|
1597
|
+
__ JumpIfSmi(reg, false_label);
|
|
1644
1598
|
// Check for undetectable objects by looking in the bit field in
|
|
1645
1599
|
// the map. The object has already been smi checked.
|
|
1646
1600
|
Register scratch = ToRegister(instr->TempAt(0));
|
|
@@ -1654,83 +1608,42 @@ void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
|
|
1654
1608
|
|
|
1655
1609
|
Condition LCodeGen::EmitIsObject(Register input,
|
|
1656
1610
|
Register temp1,
|
|
1657
|
-
Register temp2,
|
|
1658
1611
|
Label* is_not_object,
|
|
1659
1612
|
Label* is_object) {
|
|
1660
|
-
|
|
1661
|
-
ASSERT(!input.is(temp2));
|
|
1662
|
-
ASSERT(!temp1.is(temp2));
|
|
1663
|
-
|
|
1664
|
-
__ test(input, Immediate(kSmiTagMask));
|
|
1665
|
-
__ j(equal, is_not_object);
|
|
1613
|
+
__ JumpIfSmi(input, is_not_object);
|
|
1666
1614
|
|
|
1667
1615
|
__ cmp(input, isolate()->factory()->null_value());
|
|
1668
1616
|
__ j(equal, is_object);
|
|
1669
1617
|
|
|
1670
1618
|
__ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
|
|
1671
1619
|
// Undetectable objects behave like undefined.
|
|
1672
|
-
__
|
|
1673
|
-
|
|
1620
|
+
__ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
|
|
1621
|
+
1 << Map::kIsUndetectable);
|
|
1674
1622
|
__ j(not_zero, is_not_object);
|
|
1675
1623
|
|
|
1676
|
-
__ movzx_b(
|
|
1677
|
-
__ cmp(
|
|
1624
|
+
__ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
|
|
1625
|
+
__ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
|
1678
1626
|
__ j(below, is_not_object);
|
|
1679
|
-
__ cmp(
|
|
1627
|
+
__ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
|
1680
1628
|
return below_equal;
|
|
1681
1629
|
}
|
|
1682
1630
|
|
|
1683
1631
|
|
|
1684
|
-
void LCodeGen::DoIsObject(LIsObject* instr) {
|
|
1685
|
-
Register reg = ToRegister(instr->InputAt(0));
|
|
1686
|
-
Register result = ToRegister(instr->result());
|
|
1687
|
-
Register temp = ToRegister(instr->TempAt(0));
|
|
1688
|
-
Label is_false, is_true, done;
|
|
1689
|
-
|
|
1690
|
-
Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
|
|
1691
|
-
__ j(true_cond, &is_true);
|
|
1692
|
-
|
|
1693
|
-
__ bind(&is_false);
|
|
1694
|
-
__ mov(result, factory()->false_value());
|
|
1695
|
-
__ jmp(&done);
|
|
1696
|
-
|
|
1697
|
-
__ bind(&is_true);
|
|
1698
|
-
__ mov(result, factory()->true_value());
|
|
1699
|
-
|
|
1700
|
-
__ bind(&done);
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
1632
|
void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
|
|
1705
1633
|
Register reg = ToRegister(instr->InputAt(0));
|
|
1706
1634
|
Register temp = ToRegister(instr->TempAt(0));
|
|
1707
|
-
Register temp2 = ToRegister(instr->TempAt(1));
|
|
1708
1635
|
|
|
1709
1636
|
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
|
1710
1637
|
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
1711
1638
|
Label* true_label = chunk_->GetAssemblyLabel(true_block);
|
|
1712
1639
|
Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
|
1713
1640
|
|
|
1714
|
-
Condition true_cond = EmitIsObject(reg, temp,
|
|
1641
|
+
Condition true_cond = EmitIsObject(reg, temp, false_label, true_label);
|
|
1715
1642
|
|
|
1716
1643
|
EmitBranch(true_block, false_block, true_cond);
|
|
1717
1644
|
}
|
|
1718
1645
|
|
|
1719
1646
|
|
|
1720
|
-
void LCodeGen::DoIsSmi(LIsSmi* instr) {
|
|
1721
|
-
Operand input = ToOperand(instr->InputAt(0));
|
|
1722
|
-
Register result = ToRegister(instr->result());
|
|
1723
|
-
|
|
1724
|
-
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
|
1725
|
-
__ test(input, Immediate(kSmiTagMask));
|
|
1726
|
-
__ mov(result, factory()->true_value());
|
|
1727
|
-
Label done;
|
|
1728
|
-
__ j(zero, &done, Label::kNear);
|
|
1729
|
-
__ mov(result, factory()->false_value());
|
|
1730
|
-
__ bind(&done);
|
|
1731
|
-
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
1647
|
void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
|
|
1735
1648
|
Operand input = ToOperand(instr->InputAt(0));
|
|
1736
1649
|
|
|
@@ -1742,27 +1655,6 @@ void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
|
|
|
1742
1655
|
}
|
|
1743
1656
|
|
|
1744
1657
|
|
|
1745
|
-
void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
|
|
1746
|
-
Register input = ToRegister(instr->InputAt(0));
|
|
1747
|
-
Register result = ToRegister(instr->result());
|
|
1748
|
-
|
|
1749
|
-
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
|
1750
|
-
Label false_label, done;
|
|
1751
|
-
STATIC_ASSERT(kSmiTag == 0);
|
|
1752
|
-
__ test(input, Immediate(kSmiTagMask));
|
|
1753
|
-
__ j(zero, &false_label, Label::kNear);
|
|
1754
|
-
__ mov(result, FieldOperand(input, HeapObject::kMapOffset));
|
|
1755
|
-
__ test_b(FieldOperand(result, Map::kBitFieldOffset),
|
|
1756
|
-
1 << Map::kIsUndetectable);
|
|
1757
|
-
__ j(zero, &false_label, Label::kNear);
|
|
1758
|
-
__ mov(result, factory()->true_value());
|
|
1759
|
-
__ jmp(&done);
|
|
1760
|
-
__ bind(&false_label);
|
|
1761
|
-
__ mov(result, factory()->false_value());
|
|
1762
|
-
__ bind(&done);
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
1658
|
void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
|
|
1767
1659
|
Register input = ToRegister(instr->InputAt(0));
|
|
1768
1660
|
Register temp = ToRegister(instr->TempAt(0));
|
|
@@ -1771,8 +1663,7 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
|
|
|
1771
1663
|
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
1772
1664
|
|
|
1773
1665
|
STATIC_ASSERT(kSmiTag == 0);
|
|
1774
|
-
__
|
|
1775
|
-
__ j(zero, chunk_->GetAssemblyLabel(false_block));
|
|
1666
|
+
__ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
|
|
1776
1667
|
__ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
|
|
1777
1668
|
__ test_b(FieldOperand(temp, Map::kBitFieldOffset),
|
|
1778
1669
|
1 << Map::kIsUndetectable);
|
|
@@ -1780,7 +1671,7 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
|
|
|
1780
1671
|
}
|
|
1781
1672
|
|
|
1782
1673
|
|
|
1783
|
-
static InstanceType TestType(
|
|
1674
|
+
static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
|
|
1784
1675
|
InstanceType from = instr->from();
|
|
1785
1676
|
InstanceType to = instr->to();
|
|
1786
1677
|
if (from == FIRST_TYPE) return to;
|
|
@@ -1789,7 +1680,7 @@ static InstanceType TestType(HHasInstanceType* instr) {
|
|
|
1789
1680
|
}
|
|
1790
1681
|
|
|
1791
1682
|
|
|
1792
|
-
static Condition BranchCondition(
|
|
1683
|
+
static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
|
|
1793
1684
|
InstanceType from = instr->from();
|
|
1794
1685
|
InstanceType to = instr->to();
|
|
1795
1686
|
if (from == to) return equal;
|
|
@@ -1800,25 +1691,6 @@ static Condition BranchCondition(HHasInstanceType* instr) {
|
|
|
1800
1691
|
}
|
|
1801
1692
|
|
|
1802
1693
|
|
|
1803
|
-
void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
|
|
1804
|
-
Register input = ToRegister(instr->InputAt(0));
|
|
1805
|
-
Register result = ToRegister(instr->result());
|
|
1806
|
-
|
|
1807
|
-
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
|
1808
|
-
__ test(input, Immediate(kSmiTagMask));
|
|
1809
|
-
Label done, is_false;
|
|
1810
|
-
__ j(zero, &is_false, Label::kNear);
|
|
1811
|
-
__ CmpObjectType(input, TestType(instr->hydrogen()), result);
|
|
1812
|
-
__ j(NegateCondition(BranchCondition(instr->hydrogen())),
|
|
1813
|
-
&is_false, Label::kNear);
|
|
1814
|
-
__ mov(result, factory()->true_value());
|
|
1815
|
-
__ jmp(&done, Label::kNear);
|
|
1816
|
-
__ bind(&is_false);
|
|
1817
|
-
__ mov(result, factory()->false_value());
|
|
1818
|
-
__ bind(&done);
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
1694
|
void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
|
|
1823
1695
|
Register input = ToRegister(instr->InputAt(0));
|
|
1824
1696
|
Register temp = ToRegister(instr->TempAt(0));
|
|
@@ -1828,8 +1700,7 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
|
|
|
1828
1700
|
|
|
1829
1701
|
Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
|
1830
1702
|
|
|
1831
|
-
__
|
|
1832
|
-
__ j(zero, false_label);
|
|
1703
|
+
__ JumpIfSmi(input, false_label);
|
|
1833
1704
|
|
|
1834
1705
|
__ CmpObjectType(input, TestType(instr->hydrogen()), temp);
|
|
1835
1706
|
EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
|
|
@@ -1849,21 +1720,6 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
|
|
|
1849
1720
|
}
|
|
1850
1721
|
|
|
1851
1722
|
|
|
1852
|
-
void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
|
|
1853
|
-
Register input = ToRegister(instr->InputAt(0));
|
|
1854
|
-
Register result = ToRegister(instr->result());
|
|
1855
|
-
|
|
1856
|
-
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
|
1857
|
-
__ mov(result, factory()->true_value());
|
|
1858
|
-
__ test(FieldOperand(input, String::kHashFieldOffset),
|
|
1859
|
-
Immediate(String::kContainsCachedArrayIndexMask));
|
|
1860
|
-
Label done;
|
|
1861
|
-
__ j(zero, &done, Label::kNear);
|
|
1862
|
-
__ mov(result, factory()->false_value());
|
|
1863
|
-
__ bind(&done);
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
1723
|
void LCodeGen::DoHasCachedArrayIndexAndBranch(
|
|
1868
1724
|
LHasCachedArrayIndexAndBranch* instr) {
|
|
1869
1725
|
Register input = ToRegister(instr->InputAt(0));
|
|
@@ -1887,28 +1743,28 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
|
|
1887
1743
|
Register temp2) {
|
|
1888
1744
|
ASSERT(!input.is(temp));
|
|
1889
1745
|
ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register.
|
|
1890
|
-
__
|
|
1891
|
-
__
|
|
1892
|
-
__ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, temp);
|
|
1746
|
+
__ JumpIfSmi(input, is_false);
|
|
1747
|
+
__ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
|
|
1893
1748
|
__ j(below, is_false);
|
|
1894
1749
|
|
|
1895
1750
|
// Map is now in temp.
|
|
1896
1751
|
// Functions have class 'Function'.
|
|
1897
|
-
__ CmpInstanceType(temp,
|
|
1752
|
+
__ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
|
|
1898
1753
|
if (class_name->IsEqualTo(CStrVector("Function"))) {
|
|
1899
|
-
__ j(
|
|
1754
|
+
__ j(above_equal, is_true);
|
|
1900
1755
|
} else {
|
|
1901
|
-
__ j(
|
|
1756
|
+
__ j(above_equal, is_false);
|
|
1902
1757
|
}
|
|
1903
1758
|
|
|
1904
1759
|
// Check if the constructor in the map is a function.
|
|
1905
1760
|
__ mov(temp, FieldOperand(temp, Map::kConstructorOffset));
|
|
1906
1761
|
|
|
1907
|
-
// As long as
|
|
1908
|
-
// right after
|
|
1909
|
-
//
|
|
1910
|
-
|
|
1911
|
-
|
|
1762
|
+
// As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and
|
|
1763
|
+
// FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
|
|
1764
|
+
// LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
|
|
1765
|
+
STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
|
|
1766
|
+
STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
|
|
1767
|
+
LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
|
|
1912
1768
|
|
|
1913
1769
|
// Objects with a non-function constructor have class 'Object'.
|
|
1914
1770
|
__ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2);
|
|
@@ -1934,29 +1790,6 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
|
|
1934
1790
|
}
|
|
1935
1791
|
|
|
1936
1792
|
|
|
1937
|
-
void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
|
|
1938
|
-
Register input = ToRegister(instr->InputAt(0));
|
|
1939
|
-
Register result = ToRegister(instr->result());
|
|
1940
|
-
ASSERT(input.is(result));
|
|
1941
|
-
Register temp = ToRegister(instr->TempAt(0));
|
|
1942
|
-
Handle<String> class_name = instr->hydrogen()->class_name();
|
|
1943
|
-
Label done;
|
|
1944
|
-
Label is_true, is_false;
|
|
1945
|
-
|
|
1946
|
-
EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input);
|
|
1947
|
-
|
|
1948
|
-
__ j(not_equal, &is_false, Label::kNear);
|
|
1949
|
-
|
|
1950
|
-
__ bind(&is_true);
|
|
1951
|
-
__ mov(result, factory()->true_value());
|
|
1952
|
-
__ jmp(&done, Label::kNear);
|
|
1953
|
-
|
|
1954
|
-
__ bind(&is_false);
|
|
1955
|
-
__ mov(result, factory()->false_value());
|
|
1956
|
-
__ bind(&done);
|
|
1957
|
-
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
1793
|
void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
|
|
1961
1794
|
Register input = ToRegister(instr->InputAt(0));
|
|
1962
1795
|
Register temp = ToRegister(instr->TempAt(0));
|
|
@@ -1995,7 +1828,7 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
|
|
|
1995
1828
|
// Object and function are in fixed registers defined by the stub.
|
|
1996
1829
|
ASSERT(ToRegister(instr->context()).is(esi));
|
|
1997
1830
|
InstanceofStub stub(InstanceofStub::kArgsInRegisters);
|
|
1998
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
1831
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
1999
1832
|
|
|
2000
1833
|
Label true_value, done;
|
|
2001
1834
|
__ test(eax, Operand(eax));
|
|
@@ -2008,18 +1841,6 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
|
|
|
2008
1841
|
}
|
|
2009
1842
|
|
|
2010
1843
|
|
|
2011
|
-
void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
|
|
2012
|
-
ASSERT(ToRegister(instr->context()).is(esi));
|
|
2013
|
-
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
|
2014
|
-
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
2015
|
-
|
|
2016
|
-
InstanceofStub stub(InstanceofStub::kArgsInRegisters);
|
|
2017
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED);
|
|
2018
|
-
__ test(eax, Operand(eax));
|
|
2019
|
-
EmitBranch(true_block, false_block, zero);
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
1844
|
void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
|
2024
1845
|
class DeferredInstanceOfKnownGlobal: public LDeferredCode {
|
|
2025
1846
|
public:
|
|
@@ -2041,12 +1862,11 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
|
|
2041
1862
|
deferred = new DeferredInstanceOfKnownGlobal(this, instr);
|
|
2042
1863
|
|
|
2043
1864
|
Label done, false_result;
|
|
2044
|
-
Register object = ToRegister(instr->InputAt(
|
|
1865
|
+
Register object = ToRegister(instr->InputAt(1));
|
|
2045
1866
|
Register temp = ToRegister(instr->TempAt(0));
|
|
2046
1867
|
|
|
2047
1868
|
// A Smi is not an instance of anything.
|
|
2048
|
-
__
|
|
2049
|
-
__ j(zero, &false_result);
|
|
1869
|
+
__ JumpIfSmi(object, &false_result);
|
|
2050
1870
|
|
|
2051
1871
|
// This is the inlined call site instanceof cache. The two occurences of the
|
|
2052
1872
|
// hole value will be patched to the last map/result pair generated by the
|
|
@@ -2104,14 +1924,13 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
|
|
2104
1924
|
Register temp = ToRegister(instr->TempAt(0));
|
|
2105
1925
|
ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0);
|
|
2106
1926
|
__ mov(InstanceofStub::right(), Immediate(instr->function()));
|
|
2107
|
-
static const int kAdditionalDelta =
|
|
1927
|
+
static const int kAdditionalDelta = 13;
|
|
2108
1928
|
int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
|
|
2109
1929
|
__ mov(temp, Immediate(delta));
|
|
2110
1930
|
__ StoreToSafepointRegisterSlot(temp, temp);
|
|
2111
1931
|
CallCodeGeneric(stub.GetCode(),
|
|
2112
1932
|
RelocInfo::CODE_TARGET,
|
|
2113
1933
|
instr,
|
|
2114
|
-
RESTORE_CONTEXT,
|
|
2115
1934
|
RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
|
2116
1935
|
// Put the result value into the eax slot and restore all registers.
|
|
2117
1936
|
__ StoreToSafepointRegisterSlot(eax, eax);
|
|
@@ -2142,7 +1961,7 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
|
|
|
2142
1961
|
Token::Value op = instr->op();
|
|
2143
1962
|
|
|
2144
1963
|
Handle<Code> ic = CompareIC::GetUninitialized(op);
|
|
2145
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
1964
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
2146
1965
|
|
|
2147
1966
|
Condition condition = ComputeCompareCondition(op);
|
|
2148
1967
|
if (op == Token::GT || op == Token::LTE) {
|
|
@@ -2159,25 +1978,6 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
|
|
|
2159
1978
|
}
|
|
2160
1979
|
|
|
2161
1980
|
|
|
2162
|
-
void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
|
|
2163
|
-
Token::Value op = instr->op();
|
|
2164
|
-
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
|
2165
|
-
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
|
2166
|
-
|
|
2167
|
-
Handle<Code> ic = CompareIC::GetUninitialized(op);
|
|
2168
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
|
|
2169
|
-
|
|
2170
|
-
// The compare stub expects compare condition and the input operands
|
|
2171
|
-
// reversed for GT and LTE.
|
|
2172
|
-
Condition condition = ComputeCompareCondition(op);
|
|
2173
|
-
if (op == Token::GT || op == Token::LTE) {
|
|
2174
|
-
condition = ReverseCondition(condition);
|
|
2175
|
-
}
|
|
2176
|
-
__ test(eax, Operand(eax));
|
|
2177
|
-
EmitBranch(true_block, false_block, condition);
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
1981
|
void LCodeGen::DoReturn(LReturn* instr) {
|
|
2182
1982
|
if (FLAG_trace) {
|
|
2183
1983
|
// Preserve the return value on the stack and rely on the runtime call
|
|
@@ -2213,7 +2013,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
|
|
2213
2013
|
RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET :
|
|
2214
2014
|
RelocInfo::CODE_TARGET_CONTEXT;
|
|
2215
2015
|
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
|
2216
|
-
CallCode(ic, mode, instr
|
|
2016
|
+
CallCode(ic, mode, instr);
|
|
2217
2017
|
}
|
|
2218
2018
|
|
|
2219
2019
|
|
|
@@ -2244,7 +2044,7 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
|
|
|
2244
2044
|
Handle<Code> ic = instr->strict_mode()
|
|
2245
2045
|
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
|
2246
2046
|
: isolate()->builtins()->StoreIC_Initialize();
|
|
2247
|
-
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr
|
|
2047
|
+
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
|
|
2248
2048
|
}
|
|
2249
2049
|
|
|
2250
2050
|
|
|
@@ -2316,7 +2116,7 @@ void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
|
|
|
2316
2116
|
ASSERT(instr->hydrogen()->need_generic());
|
|
2317
2117
|
__ mov(ecx, name);
|
|
2318
2118
|
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
|
2319
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
2119
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
2320
2120
|
} else {
|
|
2321
2121
|
Label done;
|
|
2322
2122
|
for (int i = 0; i < map_count - 1; ++i) {
|
|
@@ -2338,7 +2138,7 @@ void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
|
|
|
2338
2138
|
__ bind(&generic);
|
|
2339
2139
|
__ mov(ecx, name);
|
|
2340
2140
|
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
|
2341
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
2141
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
2342
2142
|
} else {
|
|
2343
2143
|
DeoptimizeIf(not_equal, instr->environment());
|
|
2344
2144
|
EmitLoadFieldOrConstantFunction(result, object, map, name);
|
|
@@ -2355,7 +2155,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
|
|
2355
2155
|
|
|
2356
2156
|
__ mov(ecx, instr->name());
|
|
2357
2157
|
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
|
2358
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
2158
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
2359
2159
|
}
|
|
2360
2160
|
|
|
2361
2161
|
|
|
@@ -2406,7 +2206,7 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) {
|
|
|
2406
2206
|
Register input = ToRegister(instr->InputAt(0));
|
|
2407
2207
|
__ mov(result, FieldOperand(input, JSObject::kElementsOffset));
|
|
2408
2208
|
if (FLAG_debug_code) {
|
|
2409
|
-
Label done;
|
|
2209
|
+
Label done, ok, fail;
|
|
2410
2210
|
__ cmp(FieldOperand(result, HeapObject::kMapOffset),
|
|
2411
2211
|
Immediate(factory()->fixed_array_map()));
|
|
2412
2212
|
__ j(equal, &done, Label::kNear);
|
|
@@ -2416,11 +2216,19 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) {
|
|
|
2416
2216
|
Register temp((result.is(eax)) ? ebx : eax);
|
|
2417
2217
|
__ push(temp);
|
|
2418
2218
|
__ mov(temp, FieldOperand(result, HeapObject::kMapOffset));
|
|
2419
|
-
__ movzx_b(temp, FieldOperand(temp, Map::
|
|
2420
|
-
__
|
|
2421
|
-
__
|
|
2219
|
+
__ movzx_b(temp, FieldOperand(temp, Map::kBitField2Offset));
|
|
2220
|
+
__ and_(temp, Map::kElementsKindMask);
|
|
2221
|
+
__ shr(temp, Map::kElementsKindShift);
|
|
2222
|
+
__ cmp(temp, JSObject::FAST_ELEMENTS);
|
|
2223
|
+
__ j(equal, &ok, Label::kNear);
|
|
2224
|
+
__ cmp(temp, JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
|
|
2225
|
+
__ j(less, &fail, Label::kNear);
|
|
2226
|
+
__ cmp(temp, JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
|
|
2227
|
+
__ j(less_equal, &ok, Label::kNear);
|
|
2228
|
+
__ bind(&fail);
|
|
2229
|
+
__ Abort("Check for fast or external elements failed.");
|
|
2230
|
+
__ bind(&ok);
|
|
2422
2231
|
__ pop(temp);
|
|
2423
|
-
__ Check(below, "Check for fast elements or pixel array failed.");
|
|
2424
2232
|
__ bind(&done);
|
|
2425
2233
|
}
|
|
2426
2234
|
}
|
|
@@ -2451,16 +2259,13 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
|
|
|
2451
2259
|
|
|
2452
2260
|
|
|
2453
2261
|
void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
|
2454
|
-
Register elements = ToRegister(instr->elements());
|
|
2455
|
-
Register key = ToRegister(instr->key());
|
|
2456
2262
|
Register result = ToRegister(instr->result());
|
|
2457
|
-
ASSERT(result.is(elements));
|
|
2458
2263
|
|
|
2459
2264
|
// Load the result.
|
|
2460
|
-
__ mov(result,
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2265
|
+
__ mov(result,
|
|
2266
|
+
BuildFastArrayOperand(instr->elements(), instr->key(),
|
|
2267
|
+
JSObject::FAST_ELEMENTS,
|
|
2268
|
+
FixedArray::kHeaderSize - kHeapObjectTag));
|
|
2464
2269
|
|
|
2465
2270
|
// Check for the hole value.
|
|
2466
2271
|
if (instr->hydrogen()->RequiresHoleCheck()) {
|
|
@@ -2470,55 +2275,80 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
|
|
2470
2275
|
}
|
|
2471
2276
|
|
|
2472
2277
|
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2278
|
+
void LCodeGen::DoLoadKeyedFastDoubleElement(
|
|
2279
|
+
LLoadKeyedFastDoubleElement* instr) {
|
|
2280
|
+
XMMRegister result = ToDoubleRegister(instr->result());
|
|
2281
|
+
|
|
2282
|
+
if (instr->hydrogen()->RequiresHoleCheck()) {
|
|
2283
|
+
int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
|
|
2284
|
+
sizeof(kHoleNanLower32);
|
|
2285
|
+
Operand hole_check_operand = BuildFastArrayOperand(
|
|
2286
|
+
instr->elements(), instr->key(),
|
|
2287
|
+
JSObject::FAST_DOUBLE_ELEMENTS,
|
|
2288
|
+
offset);
|
|
2289
|
+
__ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
|
|
2290
|
+
DeoptimizeIf(equal, instr->environment());
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
Operand double_load_operand = BuildFastArrayOperand(
|
|
2294
|
+
instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
|
|
2295
|
+
FixedDoubleArray::kHeaderSize - kHeapObjectTag);
|
|
2296
|
+
__ movdbl(result, double_load_operand);
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
|
|
2300
|
+
Operand LCodeGen::BuildFastArrayOperand(
|
|
2301
|
+
LOperand* elements_pointer,
|
|
2302
|
+
LOperand* key,
|
|
2303
|
+
JSObject::ElementsKind elements_kind,
|
|
2304
|
+
uint32_t offset) {
|
|
2305
|
+
Register elements_pointer_reg = ToRegister(elements_pointer);
|
|
2306
|
+
int shift_size = ElementsKindToShiftSize(elements_kind);
|
|
2478
2307
|
if (key->IsConstantOperand()) {
|
|
2479
2308
|
int constant_value = ToInteger32(LConstantOperand::cast(key));
|
|
2480
2309
|
if (constant_value & 0xF0000000) {
|
|
2481
2310
|
Abort("array index constant value too big");
|
|
2482
2311
|
}
|
|
2483
|
-
return Operand(
|
|
2312
|
+
return Operand(elements_pointer_reg,
|
|
2313
|
+
constant_value * (1 << shift_size) + offset);
|
|
2484
2314
|
} else {
|
|
2485
2315
|
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
|
|
2486
|
-
return Operand(
|
|
2316
|
+
return Operand(elements_pointer_reg, ToRegister(key), scale_factor, offset);
|
|
2487
2317
|
}
|
|
2488
2318
|
}
|
|
2489
2319
|
|
|
2490
2320
|
|
|
2491
2321
|
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
|
2492
2322
|
LLoadKeyedSpecializedArrayElement* instr) {
|
|
2493
|
-
|
|
2494
|
-
Operand operand(
|
|
2495
|
-
|
|
2496
|
-
if (
|
|
2323
|
+
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
|
2324
|
+
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
|
|
2325
|
+
instr->key(), elements_kind, 0));
|
|
2326
|
+
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
|
2497
2327
|
XMMRegister result(ToDoubleRegister(instr->result()));
|
|
2498
2328
|
__ movss(result, operand);
|
|
2499
2329
|
__ cvtss2sd(result, result);
|
|
2500
|
-
} else if (
|
|
2330
|
+
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
|
2501
2331
|
__ movdbl(ToDoubleRegister(instr->result()), operand);
|
|
2502
2332
|
} else {
|
|
2503
2333
|
Register result(ToRegister(instr->result()));
|
|
2504
|
-
switch (
|
|
2505
|
-
case
|
|
2334
|
+
switch (elements_kind) {
|
|
2335
|
+
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
|
2506
2336
|
__ movsx_b(result, operand);
|
|
2507
2337
|
break;
|
|
2508
|
-
case
|
|
2509
|
-
case
|
|
2338
|
+
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
|
2339
|
+
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
|
2510
2340
|
__ movzx_b(result, operand);
|
|
2511
2341
|
break;
|
|
2512
|
-
case
|
|
2342
|
+
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
|
2513
2343
|
__ movsx_w(result, operand);
|
|
2514
2344
|
break;
|
|
2515
|
-
case
|
|
2345
|
+
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
|
2516
2346
|
__ movzx_w(result, operand);
|
|
2517
2347
|
break;
|
|
2518
|
-
case
|
|
2348
|
+
case JSObject::EXTERNAL_INT_ELEMENTS:
|
|
2519
2349
|
__ mov(result, operand);
|
|
2520
2350
|
break;
|
|
2521
|
-
case
|
|
2351
|
+
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
|
2522
2352
|
__ mov(result, operand);
|
|
2523
2353
|
__ test(result, Operand(result));
|
|
2524
2354
|
// TODO(danno): we could be more clever here, perhaps having a special
|
|
@@ -2526,8 +2356,12 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
|
|
2526
2356
|
// happens, and generate code that returns a double rather than int.
|
|
2527
2357
|
DeoptimizeIf(negative, instr->environment());
|
|
2528
2358
|
break;
|
|
2529
|
-
case
|
|
2530
|
-
case
|
|
2359
|
+
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
|
2360
|
+
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
|
2361
|
+
case JSObject::FAST_ELEMENTS:
|
|
2362
|
+
case JSObject::FAST_DOUBLE_ELEMENTS:
|
|
2363
|
+
case JSObject::DICTIONARY_ELEMENTS:
|
|
2364
|
+
case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
|
|
2531
2365
|
UNREACHABLE();
|
|
2532
2366
|
break;
|
|
2533
2367
|
}
|
|
@@ -2541,7 +2375,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
|
|
2541
2375
|
ASSERT(ToRegister(instr->key()).is(eax));
|
|
2542
2376
|
|
|
2543
2377
|
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
|
2544
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
2378
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
2545
2379
|
}
|
|
2546
2380
|
|
|
2547
2381
|
|
|
@@ -2602,9 +2436,25 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
|
|
2602
2436
|
ASSERT(function.is(edi)); // Required by InvokeFunction.
|
|
2603
2437
|
ASSERT(ToRegister(instr->result()).is(eax));
|
|
2604
2438
|
|
|
2605
|
-
// If the receiver is null or undefined, we have to pass the global
|
|
2606
|
-
// as a receiver.
|
|
2439
|
+
// If the receiver is null or undefined, we have to pass the global
|
|
2440
|
+
// object as a receiver to normal functions. Values have to be
|
|
2441
|
+
// passed unchanged to builtins and strict-mode functions.
|
|
2607
2442
|
Label global_object, receiver_ok;
|
|
2443
|
+
|
|
2444
|
+
// Do not transform the receiver to object for strict mode
|
|
2445
|
+
// functions.
|
|
2446
|
+
__ mov(scratch,
|
|
2447
|
+
FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
|
2448
|
+
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
|
|
2449
|
+
1 << SharedFunctionInfo::kStrictModeBitWithinByte);
|
|
2450
|
+
__ j(not_equal, &receiver_ok, Label::kNear);
|
|
2451
|
+
|
|
2452
|
+
// Do not transform the receiver to object for builtins.
|
|
2453
|
+
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
|
|
2454
|
+
1 << SharedFunctionInfo::kNativeBitWithinByte);
|
|
2455
|
+
__ j(not_equal, &receiver_ok, Label::kNear);
|
|
2456
|
+
|
|
2457
|
+
// Normal function. Replace undefined or null with global receiver.
|
|
2608
2458
|
__ cmp(receiver, factory()->null_value());
|
|
2609
2459
|
__ j(equal, &global_object, Label::kNear);
|
|
2610
2460
|
__ cmp(receiver, factory()->undefined_value());
|
|
@@ -2613,7 +2463,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
|
|
2613
2463
|
// The receiver should be a JS object.
|
|
2614
2464
|
__ test(receiver, Immediate(kSmiTagMask));
|
|
2615
2465
|
DeoptimizeIf(equal, instr->environment());
|
|
2616
|
-
__ CmpObjectType(receiver,
|
|
2466
|
+
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
|
|
2617
2467
|
DeoptimizeIf(below, instr->environment());
|
|
2618
2468
|
__ jmp(&receiver_ok, Label::kNear);
|
|
2619
2469
|
|
|
@@ -2623,6 +2473,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
|
|
2623
2473
|
// here.
|
|
2624
2474
|
__ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
2625
2475
|
__ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
|
|
2476
|
+
__ mov(receiver,
|
|
2477
|
+
FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
|
|
2626
2478
|
__ bind(&receiver_ok);
|
|
2627
2479
|
|
|
2628
2480
|
// Copy the arguments to this function possibly from the
|
|
@@ -2656,7 +2508,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
|
|
2656
2508
|
pointers,
|
|
2657
2509
|
env->deoptimization_index());
|
|
2658
2510
|
ParameterCount actual(eax);
|
|
2659
|
-
__ InvokeFunction(function, actual, CALL_FUNCTION,
|
|
2511
|
+
__ InvokeFunction(function, actual, CALL_FUNCTION,
|
|
2512
|
+
safepoint_generator, CALL_AS_METHOD);
|
|
2660
2513
|
}
|
|
2661
2514
|
|
|
2662
2515
|
|
|
@@ -2670,6 +2523,12 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
|
|
|
2670
2523
|
}
|
|
2671
2524
|
|
|
2672
2525
|
|
|
2526
|
+
void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
|
2527
|
+
Register result = ToRegister(instr->result());
|
|
2528
|
+
__ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
|
|
2673
2532
|
void LCodeGen::DoContext(LContext* instr) {
|
|
2674
2533
|
Register result = ToRegister(instr->result());
|
|
2675
2534
|
__ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
@@ -2679,8 +2538,8 @@ void LCodeGen::DoContext(LContext* instr) {
|
|
|
2679
2538
|
void LCodeGen::DoOuterContext(LOuterContext* instr) {
|
|
2680
2539
|
Register context = ToRegister(instr->context());
|
|
2681
2540
|
Register result = ToRegister(instr->result());
|
|
2682
|
-
__ mov(result,
|
|
2683
|
-
|
|
2541
|
+
__ mov(result,
|
|
2542
|
+
Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
|
|
2684
2543
|
}
|
|
2685
2544
|
|
|
2686
2545
|
|
|
@@ -2746,7 +2605,7 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
|
|
2746
2605
|
|
|
2747
2606
|
|
|
2748
2607
|
void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
|
|
2749
|
-
Register input_reg = ToRegister(instr->
|
|
2608
|
+
Register input_reg = ToRegister(instr->value());
|
|
2750
2609
|
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
|
|
2751
2610
|
factory()->heap_number_map());
|
|
2752
2611
|
DeoptimizeIf(not_equal, instr->environment());
|
|
@@ -2777,7 +2636,8 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
|
|
|
2777
2636
|
// Slow case: Call the runtime system to do the number allocation.
|
|
2778
2637
|
__ bind(&slow);
|
|
2779
2638
|
|
|
2780
|
-
CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
|
|
2639
|
+
CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
|
|
2640
|
+
instr, instr->context());
|
|
2781
2641
|
|
|
2782
2642
|
// Set the pointer to the new heap number in tmp.
|
|
2783
2643
|
if (!tmp.is(eax)) __ mov(tmp, eax);
|
|
@@ -2798,7 +2658,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
|
|
|
2798
2658
|
|
|
2799
2659
|
|
|
2800
2660
|
void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
|
|
2801
|
-
Register input_reg = ToRegister(instr->
|
|
2661
|
+
Register input_reg = ToRegister(instr->value());
|
|
2802
2662
|
__ test(input_reg, Operand(input_reg));
|
|
2803
2663
|
Label is_positive;
|
|
2804
2664
|
__ j(not_sign, &is_positive);
|
|
@@ -2823,12 +2683,12 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
|
|
2823
2683
|
LUnaryMathOperation* instr_;
|
|
2824
2684
|
};
|
|
2825
2685
|
|
|
2826
|
-
ASSERT(instr->
|
|
2686
|
+
ASSERT(instr->value()->Equals(instr->result()));
|
|
2827
2687
|
Representation r = instr->hydrogen()->value()->representation();
|
|
2828
2688
|
|
|
2829
2689
|
if (r.IsDouble()) {
|
|
2830
2690
|
XMMRegister scratch = xmm0;
|
|
2831
|
-
XMMRegister input_reg = ToDoubleRegister(instr->
|
|
2691
|
+
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
2832
2692
|
__ xorps(scratch, scratch);
|
|
2833
2693
|
__ subsd(scratch, input_reg);
|
|
2834
2694
|
__ pand(input_reg, scratch);
|
|
@@ -2837,10 +2697,9 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
|
|
2837
2697
|
} else { // Tagged case.
|
|
2838
2698
|
DeferredMathAbsTaggedHeapNumber* deferred =
|
|
2839
2699
|
new DeferredMathAbsTaggedHeapNumber(this, instr);
|
|
2840
|
-
Register input_reg = ToRegister(instr->
|
|
2700
|
+
Register input_reg = ToRegister(instr->value());
|
|
2841
2701
|
// Smi check.
|
|
2842
|
-
__
|
|
2843
|
-
__ j(not_zero, deferred->entry());
|
|
2702
|
+
__ JumpIfNotSmi(input_reg, deferred->entry());
|
|
2844
2703
|
EmitIntegerMathAbs(instr);
|
|
2845
2704
|
__ bind(deferred->exit());
|
|
2846
2705
|
}
|
|
@@ -2850,41 +2709,69 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
|
|
2850
2709
|
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
|
|
2851
2710
|
XMMRegister xmm_scratch = xmm0;
|
|
2852
2711
|
Register output_reg = ToRegister(instr->result());
|
|
2853
|
-
XMMRegister input_reg = ToDoubleRegister(instr->
|
|
2854
|
-
__ xorps(xmm_scratch, xmm_scratch); // Zero the register.
|
|
2855
|
-
__ ucomisd(input_reg, xmm_scratch);
|
|
2712
|
+
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
2856
2713
|
|
|
2857
|
-
if (
|
|
2858
|
-
|
|
2714
|
+
if (CpuFeatures::IsSupported(SSE4_1)) {
|
|
2715
|
+
CpuFeatures::Scope scope(SSE4_1);
|
|
2716
|
+
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
|
2717
|
+
// Deoptimize on negative zero.
|
|
2718
|
+
Label non_zero;
|
|
2719
|
+
__ xorps(xmm_scratch, xmm_scratch); // Zero the register.
|
|
2720
|
+
__ ucomisd(input_reg, xmm_scratch);
|
|
2721
|
+
__ j(not_equal, &non_zero, Label::kNear);
|
|
2722
|
+
__ movmskpd(output_reg, input_reg);
|
|
2723
|
+
__ test(output_reg, Immediate(1));
|
|
2724
|
+
DeoptimizeIf(not_zero, instr->environment());
|
|
2725
|
+
__ bind(&non_zero);
|
|
2726
|
+
}
|
|
2727
|
+
__ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
|
|
2728
|
+
__ cvttsd2si(output_reg, Operand(xmm_scratch));
|
|
2729
|
+
// Overflow is signalled with minint.
|
|
2730
|
+
__ cmp(output_reg, 0x80000000u);
|
|
2731
|
+
DeoptimizeIf(equal, instr->environment());
|
|
2859
2732
|
} else {
|
|
2733
|
+
Label done;
|
|
2734
|
+
// Deoptimize on negative numbers.
|
|
2735
|
+
__ xorps(xmm_scratch, xmm_scratch); // Zero the register.
|
|
2736
|
+
__ ucomisd(input_reg, xmm_scratch);
|
|
2860
2737
|
DeoptimizeIf(below, instr->environment());
|
|
2861
|
-
}
|
|
2862
2738
|
|
|
2863
|
-
|
|
2864
|
-
|
|
2739
|
+
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
|
2740
|
+
// Check for negative zero.
|
|
2741
|
+
Label positive_sign;
|
|
2742
|
+
__ j(above, &positive_sign, Label::kNear);
|
|
2743
|
+
__ movmskpd(output_reg, input_reg);
|
|
2744
|
+
__ test(output_reg, Immediate(1));
|
|
2745
|
+
DeoptimizeIf(not_zero, instr->environment());
|
|
2746
|
+
__ Set(output_reg, Immediate(0));
|
|
2747
|
+
__ jmp(&done, Label::kNear);
|
|
2748
|
+
__ bind(&positive_sign);
|
|
2749
|
+
}
|
|
2865
2750
|
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
DeoptimizeIf(equal, instr->environment());
|
|
2869
|
-
}
|
|
2751
|
+
// Use truncating instruction (OK because input is positive).
|
|
2752
|
+
__ cvttsd2si(output_reg, Operand(input_reg));
|
|
2870
2753
|
|
|
2754
|
+
// Overflow is signalled with minint.
|
|
2755
|
+
__ cmp(output_reg, 0x80000000u);
|
|
2756
|
+
DeoptimizeIf(equal, instr->environment());
|
|
2757
|
+
__ bind(&done);
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2871
2760
|
|
|
2872
2761
|
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
|
2873
2762
|
XMMRegister xmm_scratch = xmm0;
|
|
2874
2763
|
Register output_reg = ToRegister(instr->result());
|
|
2875
|
-
XMMRegister input_reg = ToDoubleRegister(instr->
|
|
2764
|
+
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
2876
2765
|
|
|
2877
2766
|
Label below_half, done;
|
|
2878
2767
|
// xmm_scratch = 0.5
|
|
2879
2768
|
ExternalReference one_half = ExternalReference::address_of_one_half();
|
|
2880
2769
|
__ movdbl(xmm_scratch, Operand::StaticVariable(one_half));
|
|
2881
|
-
|
|
2882
2770
|
__ ucomisd(xmm_scratch, input_reg);
|
|
2883
2771
|
__ j(above, &below_half);
|
|
2884
2772
|
// input = input + 0.5
|
|
2885
2773
|
__ addsd(input_reg, xmm_scratch);
|
|
2886
2774
|
|
|
2887
|
-
|
|
2888
2775
|
// Compute Math.floor(value + 0.5).
|
|
2889
2776
|
// Use truncating instruction (OK because input is positive).
|
|
2890
2777
|
__ cvttsd2si(output_reg, Operand(input_reg));
|
|
@@ -2917,7 +2804,7 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
|
|
2917
2804
|
|
|
2918
2805
|
|
|
2919
2806
|
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
|
|
2920
|
-
XMMRegister input_reg = ToDoubleRegister(instr->
|
|
2807
|
+
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
2921
2808
|
ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
|
|
2922
2809
|
__ sqrtsd(input_reg, input_reg);
|
|
2923
2810
|
}
|
|
@@ -2925,7 +2812,7 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
|
|
|
2925
2812
|
|
|
2926
2813
|
void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
|
|
2927
2814
|
XMMRegister xmm_scratch = xmm0;
|
|
2928
|
-
XMMRegister input_reg = ToDoubleRegister(instr->
|
|
2815
|
+
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
2929
2816
|
ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
|
|
2930
2817
|
__ xorps(xmm_scratch, xmm_scratch);
|
|
2931
2818
|
__ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
|
|
@@ -2962,8 +2849,7 @@ void LCodeGen::DoPower(LPower* instr) {
|
|
|
2962
2849
|
Register right_reg = ToRegister(right);
|
|
2963
2850
|
|
|
2964
2851
|
Label non_smi, call;
|
|
2965
|
-
__
|
|
2966
|
-
__ j(not_zero, &non_smi);
|
|
2852
|
+
__ JumpIfNotSmi(right_reg, &non_smi);
|
|
2967
2853
|
__ SmiUntag(right_reg);
|
|
2968
2854
|
__ cvtsi2sd(result_reg, Operand(right_reg));
|
|
2969
2855
|
__ jmp(&call);
|
|
@@ -2994,14 +2880,15 @@ void LCodeGen::DoPower(LPower* instr) {
|
|
|
2994
2880
|
|
|
2995
2881
|
|
|
2996
2882
|
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
|
|
2997
|
-
ASSERT(instr->
|
|
2998
|
-
XMMRegister input_reg = ToDoubleRegister(instr->
|
|
2883
|
+
ASSERT(instr->value()->Equals(instr->result()));
|
|
2884
|
+
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
2999
2885
|
Label positive, done, zero;
|
|
3000
2886
|
__ xorps(xmm0, xmm0);
|
|
3001
2887
|
__ ucomisd(input_reg, xmm0);
|
|
3002
2888
|
__ j(above, &positive, Label::kNear);
|
|
3003
2889
|
__ j(equal, &zero, Label::kNear);
|
|
3004
|
-
ExternalReference nan =
|
|
2890
|
+
ExternalReference nan =
|
|
2891
|
+
ExternalReference::address_of_canonical_non_hole_nan();
|
|
3005
2892
|
__ movdbl(input_reg, Operand::StaticVariable(nan));
|
|
3006
2893
|
__ jmp(&done, Label::kNear);
|
|
3007
2894
|
__ bind(&zero);
|
|
@@ -3027,7 +2914,7 @@ void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
|
|
|
3027
2914
|
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
|
|
3028
2915
|
TranscendentalCacheStub stub(TranscendentalCache::COS,
|
|
3029
2916
|
TranscendentalCacheStub::UNTAGGED);
|
|
3030
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
2917
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
3031
2918
|
}
|
|
3032
2919
|
|
|
3033
2920
|
|
|
@@ -3035,7 +2922,7 @@ void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
|
|
|
3035
2922
|
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
|
|
3036
2923
|
TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
|
3037
2924
|
TranscendentalCacheStub::UNTAGGED);
|
|
3038
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
2925
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
3039
2926
|
}
|
|
3040
2927
|
|
|
3041
2928
|
|
|
@@ -3083,7 +2970,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
|
|
3083
2970
|
RegisterEnvironmentForDeoptimization(env);
|
|
3084
2971
|
SafepointGenerator generator(this, pointers, env->deoptimization_index());
|
|
3085
2972
|
ParameterCount count(instr->arity());
|
|
3086
|
-
__ InvokeFunction(edi, count, CALL_FUNCTION, generator);
|
|
2973
|
+
__ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
|
3087
2974
|
}
|
|
3088
2975
|
|
|
3089
2976
|
|
|
@@ -3095,7 +2982,7 @@ void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
|
|
|
3095
2982
|
int arity = instr->arity();
|
|
3096
2983
|
Handle<Code> ic = isolate()->stub_cache()->
|
|
3097
2984
|
ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
|
|
3098
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
2985
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
3099
2986
|
}
|
|
3100
2987
|
|
|
3101
2988
|
|
|
@@ -3108,7 +2995,7 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
|
|
|
3108
2995
|
Handle<Code> ic =
|
|
3109
2996
|
isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode);
|
|
3110
2997
|
__ mov(ecx, instr->name());
|
|
3111
|
-
CallCode(ic, mode, instr
|
|
2998
|
+
CallCode(ic, mode, instr);
|
|
3112
2999
|
}
|
|
3113
3000
|
|
|
3114
3001
|
|
|
@@ -3118,7 +3005,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
|
|
|
3118
3005
|
|
|
3119
3006
|
int arity = instr->arity();
|
|
3120
3007
|
CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT);
|
|
3121
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
3008
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
3122
3009
|
__ Drop(1);
|
|
3123
3010
|
}
|
|
3124
3011
|
|
|
@@ -3132,7 +3019,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
|
|
3132
3019
|
Handle<Code> ic =
|
|
3133
3020
|
isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode);
|
|
3134
3021
|
__ mov(ecx, instr->name());
|
|
3135
|
-
CallCode(ic, mode, instr
|
|
3022
|
+
CallCode(ic, mode, instr);
|
|
3136
3023
|
}
|
|
3137
3024
|
|
|
3138
3025
|
|
|
@@ -3150,12 +3037,12 @@ void LCodeGen::DoCallNew(LCallNew* instr) {
|
|
|
3150
3037
|
|
|
3151
3038
|
Handle<Code> builtin = isolate()->builtins()->JSConstructCall();
|
|
3152
3039
|
__ Set(eax, Immediate(instr->arity()));
|
|
3153
|
-
CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr
|
|
3040
|
+
CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr);
|
|
3154
3041
|
}
|
|
3155
3042
|
|
|
3156
3043
|
|
|
3157
3044
|
void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
|
|
3158
|
-
CallRuntime(instr->function(), instr->arity(), instr
|
|
3045
|
+
CallRuntime(instr->function(), instr->arity(), instr);
|
|
3159
3046
|
}
|
|
3160
3047
|
|
|
3161
3048
|
|
|
@@ -3198,44 +3085,54 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
|
|
3198
3085
|
Handle<Code> ic = instr->strict_mode()
|
|
3199
3086
|
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
|
3200
3087
|
: isolate()->builtins()->StoreIC_Initialize();
|
|
3201
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
3088
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
3202
3089
|
}
|
|
3203
3090
|
|
|
3204
3091
|
|
|
3205
3092
|
void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
|
|
3206
|
-
|
|
3207
|
-
|
|
3093
|
+
if (instr->index()->IsConstantOperand()) {
|
|
3094
|
+
__ cmp(ToOperand(instr->length()),
|
|
3095
|
+
ToImmediate(LConstantOperand::cast(instr->index())));
|
|
3096
|
+
DeoptimizeIf(below_equal, instr->environment());
|
|
3097
|
+
} else {
|
|
3098
|
+
__ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
|
|
3099
|
+
DeoptimizeIf(above_equal, instr->environment());
|
|
3100
|
+
}
|
|
3208
3101
|
}
|
|
3209
3102
|
|
|
3210
3103
|
|
|
3211
3104
|
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
|
3212
3105
|
LStoreKeyedSpecializedArrayElement* instr) {
|
|
3213
|
-
|
|
3214
|
-
Operand operand(
|
|
3215
|
-
|
|
3216
|
-
if (
|
|
3106
|
+
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
|
3107
|
+
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
|
|
3108
|
+
instr->key(), elements_kind, 0));
|
|
3109
|
+
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
|
3217
3110
|
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
|
|
3218
3111
|
__ movss(operand, xmm0);
|
|
3219
|
-
} else if (
|
|
3112
|
+
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
|
3220
3113
|
__ movdbl(operand, ToDoubleRegister(instr->value()));
|
|
3221
3114
|
} else {
|
|
3222
3115
|
Register value = ToRegister(instr->value());
|
|
3223
|
-
switch (
|
|
3224
|
-
case
|
|
3225
|
-
case
|
|
3226
|
-
case
|
|
3116
|
+
switch (elements_kind) {
|
|
3117
|
+
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
|
3118
|
+
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
|
3119
|
+
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
|
3227
3120
|
__ mov_b(operand, value);
|
|
3228
3121
|
break;
|
|
3229
|
-
case
|
|
3230
|
-
case
|
|
3122
|
+
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
|
3123
|
+
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
|
3231
3124
|
__ mov_w(operand, value);
|
|
3232
3125
|
break;
|
|
3233
|
-
case
|
|
3234
|
-
case
|
|
3126
|
+
case JSObject::EXTERNAL_INT_ELEMENTS:
|
|
3127
|
+
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
|
3235
3128
|
__ mov(operand, value);
|
|
3236
3129
|
break;
|
|
3237
|
-
case
|
|
3238
|
-
case
|
|
3130
|
+
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
|
3131
|
+
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
|
3132
|
+
case JSObject::FAST_ELEMENTS:
|
|
3133
|
+
case JSObject::FAST_DOUBLE_ELEMENTS:
|
|
3134
|
+
case JSObject::DICTIONARY_ELEMENTS:
|
|
3135
|
+
case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
|
|
3239
3136
|
UNREACHABLE();
|
|
3240
3137
|
break;
|
|
3241
3138
|
}
|
|
@@ -3275,6 +3172,27 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
|
|
|
3275
3172
|
}
|
|
3276
3173
|
|
|
3277
3174
|
|
|
3175
|
+
void LCodeGen::DoStoreKeyedFastDoubleElement(
|
|
3176
|
+
LStoreKeyedFastDoubleElement* instr) {
|
|
3177
|
+
XMMRegister value = ToDoubleRegister(instr->value());
|
|
3178
|
+
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
|
|
3179
|
+
Label have_value;
|
|
3180
|
+
|
|
3181
|
+
__ ucomisd(value, value);
|
|
3182
|
+
__ j(parity_odd, &have_value); // NaN.
|
|
3183
|
+
|
|
3184
|
+
ExternalReference canonical_nan_reference =
|
|
3185
|
+
ExternalReference::address_of_canonical_non_hole_nan();
|
|
3186
|
+
__ movdbl(value, Operand::StaticVariable(canonical_nan_reference));
|
|
3187
|
+
__ bind(&have_value);
|
|
3188
|
+
|
|
3189
|
+
Operand double_store_operand = BuildFastArrayOperand(
|
|
3190
|
+
instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
|
|
3191
|
+
FixedDoubleArray::kHeaderSize - kHeapObjectTag);
|
|
3192
|
+
__ movdbl(double_store_operand, value);
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
|
|
3278
3196
|
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
|
|
3279
3197
|
ASSERT(ToRegister(instr->context()).is(esi));
|
|
3280
3198
|
ASSERT(ToRegister(instr->object()).is(edx));
|
|
@@ -3284,7 +3202,7 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
|
|
|
3284
3202
|
Handle<Code> ic = instr->strict_mode()
|
|
3285
3203
|
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
|
|
3286
3204
|
: isolate()->builtins()->KeyedStoreIC_Initialize();
|
|
3287
|
-
CallCode(ic, RelocInfo::CODE_TARGET, instr
|
|
3205
|
+
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
3288
3206
|
}
|
|
3289
3207
|
|
|
3290
3208
|
|
|
@@ -3299,95 +3217,79 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
|
|
3299
3217
|
};
|
|
3300
3218
|
|
|
3301
3219
|
Register string = ToRegister(instr->string());
|
|
3302
|
-
Register index =
|
|
3303
|
-
int const_index = -1;
|
|
3304
|
-
if (instr->index()->IsConstantOperand()) {
|
|
3305
|
-
const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
|
3306
|
-
STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
|
|
3307
|
-
if (!Smi::IsValid(const_index)) {
|
|
3308
|
-
// Guaranteed to be out of bounds because of the assert above.
|
|
3309
|
-
// So the bounds check that must dominate this instruction must
|
|
3310
|
-
// have deoptimized already.
|
|
3311
|
-
if (FLAG_debug_code) {
|
|
3312
|
-
__ Abort("StringCharCodeAt: out of bounds index.");
|
|
3313
|
-
}
|
|
3314
|
-
// No code needs to be generated.
|
|
3315
|
-
return;
|
|
3316
|
-
}
|
|
3317
|
-
} else {
|
|
3318
|
-
index = ToRegister(instr->index());
|
|
3319
|
-
}
|
|
3220
|
+
Register index = ToRegister(instr->index());
|
|
3320
3221
|
Register result = ToRegister(instr->result());
|
|
3321
3222
|
|
|
3322
3223
|
DeferredStringCharCodeAt* deferred =
|
|
3323
3224
|
new DeferredStringCharCodeAt(this, instr);
|
|
3324
3225
|
|
|
3325
|
-
Label flat_string, ascii_string, done;
|
|
3326
|
-
|
|
3327
3226
|
// Fetch the instance type of the receiver into result register.
|
|
3328
3227
|
__ mov(result, FieldOperand(string, HeapObject::kMapOffset));
|
|
3329
3228
|
__ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
|
|
3330
3229
|
|
|
3331
|
-
// We need special handling for
|
|
3332
|
-
|
|
3333
|
-
__ test(result, Immediate(
|
|
3334
|
-
__ j(zero, &
|
|
3230
|
+
// We need special handling for indirect strings.
|
|
3231
|
+
Label check_sequential;
|
|
3232
|
+
__ test(result, Immediate(kIsIndirectStringMask));
|
|
3233
|
+
__ j(zero, &check_sequential, Label::kNear);
|
|
3335
3234
|
|
|
3336
|
-
//
|
|
3337
|
-
|
|
3338
|
-
__
|
|
3235
|
+
// Dispatch on the indirect string shape: slice or cons.
|
|
3236
|
+
Label cons_string;
|
|
3237
|
+
__ test(result, Immediate(kSlicedNotConsMask));
|
|
3238
|
+
__ j(zero, &cons_string, Label::kNear);
|
|
3339
3239
|
|
|
3340
|
-
//
|
|
3240
|
+
// Handle slices.
|
|
3241
|
+
Label indirect_string_loaded;
|
|
3242
|
+
__ mov(result, FieldOperand(string, SlicedString::kOffsetOffset));
|
|
3243
|
+
__ SmiUntag(result);
|
|
3244
|
+
__ add(index, Operand(result));
|
|
3245
|
+
__ mov(string, FieldOperand(string, SlicedString::kParentOffset));
|
|
3246
|
+
__ jmp(&indirect_string_loaded, Label::kNear);
|
|
3247
|
+
|
|
3248
|
+
// Handle conses.
|
|
3341
3249
|
// Check whether the right hand side is the empty string (i.e. if
|
|
3342
3250
|
// this is really a flat string in a cons string). If that is not
|
|
3343
3251
|
// the case we would rather go to the runtime system now to flatten
|
|
3344
3252
|
// the string.
|
|
3253
|
+
__ bind(&cons_string);
|
|
3345
3254
|
__ cmp(FieldOperand(string, ConsString::kSecondOffset),
|
|
3346
3255
|
Immediate(factory()->empty_string()));
|
|
3347
3256
|
__ j(not_equal, deferred->entry());
|
|
3348
|
-
// Get the first of the two strings and load its instance type.
|
|
3349
3257
|
__ mov(string, FieldOperand(string, ConsString::kFirstOffset));
|
|
3258
|
+
|
|
3259
|
+
__ bind(&indirect_string_loaded);
|
|
3350
3260
|
__ mov(result, FieldOperand(string, HeapObject::kMapOffset));
|
|
3351
3261
|
__ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
|
|
3352
|
-
|
|
3262
|
+
|
|
3263
|
+
// Check whether the string is sequential. The only non-sequential
|
|
3264
|
+
// shapes we support have just been unwrapped above.
|
|
3265
|
+
__ bind(&check_sequential);
|
|
3353
3266
|
STATIC_ASSERT(kSeqStringTag == 0);
|
|
3354
3267
|
__ test(result, Immediate(kStringRepresentationMask));
|
|
3355
3268
|
__ j(not_zero, deferred->entry());
|
|
3356
3269
|
|
|
3357
|
-
//
|
|
3358
|
-
|
|
3270
|
+
// Dispatch on the encoding: ASCII or two-byte.
|
|
3271
|
+
Label ascii_string;
|
|
3359
3272
|
STATIC_ASSERT(kAsciiStringTag != 0);
|
|
3360
3273
|
__ test(result, Immediate(kStringEncodingMask));
|
|
3361
3274
|
__ j(not_zero, &ascii_string, Label::kNear);
|
|
3362
3275
|
|
|
3363
3276
|
// Two-byte string.
|
|
3364
3277
|
// Load the two-byte character code into the result register.
|
|
3278
|
+
Label done;
|
|
3365
3279
|
STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
(kUC16Size * const_index)));
|
|
3371
|
-
} else {
|
|
3372
|
-
__ movzx_w(result, FieldOperand(string,
|
|
3373
|
-
index,
|
|
3374
|
-
times_2,
|
|
3375
|
-
SeqTwoByteString::kHeaderSize));
|
|
3376
|
-
}
|
|
3280
|
+
__ movzx_w(result, FieldOperand(string,
|
|
3281
|
+
index,
|
|
3282
|
+
times_2,
|
|
3283
|
+
SeqTwoByteString::kHeaderSize));
|
|
3377
3284
|
__ jmp(&done, Label::kNear);
|
|
3378
3285
|
|
|
3379
3286
|
// ASCII string.
|
|
3380
3287
|
// Load the byte into the result register.
|
|
3381
3288
|
__ bind(&ascii_string);
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
__ movzx_b(result, FieldOperand(string,
|
|
3387
|
-
index,
|
|
3388
|
-
times_1,
|
|
3389
|
-
SeqAsciiString::kHeaderSize));
|
|
3390
|
-
}
|
|
3289
|
+
__ movzx_b(result, FieldOperand(string,
|
|
3290
|
+
index,
|
|
3291
|
+
times_1,
|
|
3292
|
+
SeqAsciiString::kHeaderSize));
|
|
3391
3293
|
__ bind(&done);
|
|
3392
3294
|
__ bind(deferred->exit());
|
|
3393
3295
|
}
|
|
@@ -3415,7 +3317,8 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
|
|
|
3415
3317
|
__ SmiTag(index);
|
|
3416
3318
|
__ push(index);
|
|
3417
3319
|
}
|
|
3418
|
-
CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2,
|
|
3320
|
+
CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2,
|
|
3321
|
+
instr, instr->context());
|
|
3419
3322
|
if (FLAG_debug_code) {
|
|
3420
3323
|
__ AbortIfNotSmi(eax);
|
|
3421
3324
|
}
|
|
@@ -3466,7 +3369,7 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
|
|
|
3466
3369
|
PushSafepointRegistersScope scope(this);
|
|
3467
3370
|
__ SmiTag(char_code);
|
|
3468
3371
|
__ push(char_code);
|
|
3469
|
-
CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
|
|
3372
|
+
CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
|
|
3470
3373
|
__ StoreToSafepointRegisterSlot(result, eax);
|
|
3471
3374
|
}
|
|
3472
3375
|
|
|
@@ -3490,7 +3393,7 @@ void LCodeGen::DoStringAdd(LStringAdd* instr) {
|
|
|
3490
3393
|
__ push(ToOperand(instr->right()));
|
|
3491
3394
|
}
|
|
3492
3395
|
StringAddStub stub(NO_STRING_CHECK_IN_STUB);
|
|
3493
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
3396
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
3494
3397
|
}
|
|
3495
3398
|
|
|
3496
3399
|
|
|
@@ -3551,8 +3454,15 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
|
|
|
3551
3454
|
// register is stored, as this register is in the pointer map, but contains an
|
|
3552
3455
|
// integer value.
|
|
3553
3456
|
__ StoreToSafepointRegisterSlot(reg, Immediate(0));
|
|
3554
|
-
|
|
3555
|
-
|
|
3457
|
+
// NumberTagI and NumberTagD use the context from the frame, rather than
|
|
3458
|
+
// the environment's HContext or HInlinedContext value.
|
|
3459
|
+
// They only call Runtime::kAllocateHeapNumber.
|
|
3460
|
+
// The corresponding HChange instructions are added in a phase that does
|
|
3461
|
+
// not have easy access to the local context.
|
|
3462
|
+
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
3463
|
+
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
|
|
3464
|
+
RecordSafepointWithRegisters(
|
|
3465
|
+
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
|
|
3556
3466
|
if (!reg.is(eax)) __ mov(reg, eax);
|
|
3557
3467
|
|
|
3558
3468
|
// Done. Put the value in xmm0 into the value of the allocated heap
|
|
@@ -3596,7 +3506,15 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
|
|
|
3596
3506
|
__ Set(reg, Immediate(0));
|
|
3597
3507
|
|
|
3598
3508
|
PushSafepointRegistersScope scope(this);
|
|
3599
|
-
|
|
3509
|
+
// NumberTagI and NumberTagD use the context from the frame, rather than
|
|
3510
|
+
// the environment's HContext or HInlinedContext value.
|
|
3511
|
+
// They only call Runtime::kAllocateHeapNumber.
|
|
3512
|
+
// The corresponding HChange instructions are added in a phase that does
|
|
3513
|
+
// not have easy access to the local context.
|
|
3514
|
+
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
3515
|
+
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
|
|
3516
|
+
RecordSafepointWithRegisters(instr->pointer_map(), 0,
|
|
3517
|
+
Safepoint::kNoDeoptimizationIndex);
|
|
3600
3518
|
__ StoreToSafepointRegisterSlot(reg, eax);
|
|
3601
3519
|
}
|
|
3602
3520
|
|
|
@@ -3622,28 +3540,34 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
|
|
3622
3540
|
|
|
3623
3541
|
void LCodeGen::EmitNumberUntagD(Register input_reg,
|
|
3624
3542
|
XMMRegister result_reg,
|
|
3543
|
+
bool deoptimize_on_undefined,
|
|
3625
3544
|
LEnvironment* env) {
|
|
3626
|
-
Label load_smi,
|
|
3545
|
+
Label load_smi, done;
|
|
3627
3546
|
|
|
3628
3547
|
// Smi check.
|
|
3629
|
-
__
|
|
3630
|
-
__ j(zero, &load_smi, Label::kNear);
|
|
3548
|
+
__ JumpIfSmi(input_reg, &load_smi, Label::kNear);
|
|
3631
3549
|
|
|
3632
3550
|
// Heap number map check.
|
|
3633
3551
|
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
|
|
3634
3552
|
factory()->heap_number_map());
|
|
3635
|
-
|
|
3553
|
+
if (deoptimize_on_undefined) {
|
|
3554
|
+
DeoptimizeIf(not_equal, env);
|
|
3555
|
+
} else {
|
|
3556
|
+
Label heap_number;
|
|
3557
|
+
__ j(equal, &heap_number, Label::kNear);
|
|
3636
3558
|
|
|
3637
|
-
|
|
3638
|
-
|
|
3559
|
+
__ cmp(input_reg, factory()->undefined_value());
|
|
3560
|
+
DeoptimizeIf(not_equal, env);
|
|
3639
3561
|
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3562
|
+
// Convert undefined to NaN.
|
|
3563
|
+
ExternalReference nan =
|
|
3564
|
+
ExternalReference::address_of_canonical_non_hole_nan();
|
|
3565
|
+
__ movdbl(result_reg, Operand::StaticVariable(nan));
|
|
3566
|
+
__ jmp(&done, Label::kNear);
|
|
3644
3567
|
|
|
3568
|
+
__ bind(&heap_number);
|
|
3569
|
+
}
|
|
3645
3570
|
// Heap number to XMM conversion.
|
|
3646
|
-
__ bind(&heap_number);
|
|
3647
3571
|
__ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
|
|
3648
3572
|
__ jmp(&done, Label::kNear);
|
|
3649
3573
|
|
|
@@ -3756,8 +3680,7 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
|
|
|
3756
3680
|
DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr);
|
|
3757
3681
|
|
|
3758
3682
|
// Smi check.
|
|
3759
|
-
__
|
|
3760
|
-
__ j(not_zero, deferred->entry());
|
|
3683
|
+
__ JumpIfNotSmi(input_reg, deferred->entry());
|
|
3761
3684
|
|
|
3762
3685
|
// Smi to int32 conversion
|
|
3763
3686
|
__ SmiUntag(input_reg); // Untag smi.
|
|
@@ -3775,7 +3698,9 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
|
|
|
3775
3698
|
Register input_reg = ToRegister(input);
|
|
3776
3699
|
XMMRegister result_reg = ToDoubleRegister(result);
|
|
3777
3700
|
|
|
3778
|
-
EmitNumberUntagD(input_reg, result_reg,
|
|
3701
|
+
EmitNumberUntagD(input_reg, result_reg,
|
|
3702
|
+
instr->hydrogen()->deoptimize_on_undefined(),
|
|
3703
|
+
instr->environment());
|
|
3779
3704
|
}
|
|
3780
3705
|
|
|
3781
3706
|
|
|
@@ -3898,14 +3823,14 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
|
|
3898
3823
|
|
|
3899
3824
|
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
|
|
3900
3825
|
LOperand* input = instr->InputAt(0);
|
|
3901
|
-
__ test(
|
|
3826
|
+
__ test(ToOperand(input), Immediate(kSmiTagMask));
|
|
3902
3827
|
DeoptimizeIf(not_zero, instr->environment());
|
|
3903
3828
|
}
|
|
3904
3829
|
|
|
3905
3830
|
|
|
3906
3831
|
void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
|
|
3907
3832
|
LOperand* input = instr->InputAt(0);
|
|
3908
|
-
__ test(
|
|
3833
|
+
__ test(ToOperand(input), Immediate(kSmiTagMask));
|
|
3909
3834
|
DeoptimizeIf(zero, instr->environment());
|
|
3910
3835
|
}
|
|
3911
3836
|
|
|
@@ -3957,8 +3882,8 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
|
|
|
3957
3882
|
|
|
3958
3883
|
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
|
|
3959
3884
|
ASSERT(instr->InputAt(0)->IsRegister());
|
|
3960
|
-
|
|
3961
|
-
__ cmp(
|
|
3885
|
+
Operand operand = ToOperand(instr->InputAt(0));
|
|
3886
|
+
__ cmp(operand, instr->hydrogen()->target());
|
|
3962
3887
|
DeoptimizeIf(not_equal, instr->environment());
|
|
3963
3888
|
}
|
|
3964
3889
|
|
|
@@ -4060,6 +3985,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
|
|
4060
3985
|
|
|
4061
3986
|
|
|
4062
3987
|
void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
|
|
3988
|
+
ASSERT(ToRegister(instr->context()).is(esi));
|
|
4063
3989
|
// Setup the parameters to the stub/runtime call.
|
|
4064
3990
|
__ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
|
4065
3991
|
__ push(FieldOperand(eax, JSFunction::kLiteralsOffset));
|
|
@@ -4073,16 +3999,16 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
|
|
|
4073
3999
|
FastCloneShallowArrayStub::Mode mode =
|
|
4074
4000
|
FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
|
|
4075
4001
|
FastCloneShallowArrayStub stub(mode, length);
|
|
4076
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
4002
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
4077
4003
|
} else if (instr->hydrogen()->depth() > 1) {
|
|
4078
|
-
CallRuntime(Runtime::kCreateArrayLiteral, 3, instr
|
|
4004
|
+
CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
|
|
4079
4005
|
} else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
|
|
4080
|
-
CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr
|
|
4006
|
+
CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
|
|
4081
4007
|
} else {
|
|
4082
4008
|
FastCloneShallowArrayStub::Mode mode =
|
|
4083
4009
|
FastCloneShallowArrayStub::CLONE_ELEMENTS;
|
|
4084
4010
|
FastCloneShallowArrayStub stub(mode, length);
|
|
4085
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
4011
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
4086
4012
|
}
|
|
4087
4013
|
}
|
|
4088
4014
|
|
|
@@ -4104,12 +4030,9 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
|
|
|
4104
4030
|
|
|
4105
4031
|
// Pick the right runtime function to call.
|
|
4106
4032
|
if (instr->hydrogen()->depth() > 1) {
|
|
4107
|
-
CallRuntime(Runtime::kCreateObjectLiteral, 4, instr
|
|
4033
|
+
CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
|
|
4108
4034
|
} else {
|
|
4109
|
-
CallRuntime(Runtime::kCreateObjectLiteralShallow,
|
|
4110
|
-
4,
|
|
4111
|
-
instr,
|
|
4112
|
-
CONTEXT_ADJUSTED);
|
|
4035
|
+
CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
|
|
4113
4036
|
}
|
|
4114
4037
|
}
|
|
4115
4038
|
|
|
@@ -4117,17 +4040,19 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
|
|
|
4117
4040
|
void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
|
|
4118
4041
|
ASSERT(ToRegister(instr->InputAt(0)).is(eax));
|
|
4119
4042
|
__ push(eax);
|
|
4120
|
-
CallRuntime(Runtime::kToFastProperties, 1, instr
|
|
4043
|
+
CallRuntime(Runtime::kToFastProperties, 1, instr);
|
|
4121
4044
|
}
|
|
4122
4045
|
|
|
4123
4046
|
|
|
4124
4047
|
void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
|
4048
|
+
ASSERT(ToRegister(instr->context()).is(esi));
|
|
4125
4049
|
Label materialized;
|
|
4126
4050
|
// Registers will be used as follows:
|
|
4127
4051
|
// edi = JS function.
|
|
4128
4052
|
// ecx = literals array.
|
|
4129
4053
|
// ebx = regexp literal.
|
|
4130
4054
|
// eax = regexp literal clone.
|
|
4055
|
+
// esi = context.
|
|
4131
4056
|
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
|
4132
4057
|
__ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
|
|
4133
4058
|
int literal_offset = FixedArray::kHeaderSize +
|
|
@@ -4142,7 +4067,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
|
|
4142
4067
|
__ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
|
|
4143
4068
|
__ push(Immediate(instr->hydrogen()->pattern()));
|
|
4144
4069
|
__ push(Immediate(instr->hydrogen()->flags()));
|
|
4145
|
-
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr
|
|
4070
|
+
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
|
|
4146
4071
|
__ mov(ebx, eax);
|
|
4147
4072
|
|
|
4148
4073
|
__ bind(&materialized);
|
|
@@ -4154,7 +4079,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
|
|
4154
4079
|
__ bind(&runtime_allocate);
|
|
4155
4080
|
__ push(ebx);
|
|
4156
4081
|
__ push(Immediate(Smi::FromInt(size)));
|
|
4157
|
-
CallRuntime(Runtime::kAllocateInNewSpace, 1, instr
|
|
4082
|
+
CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
|
|
4158
4083
|
__ pop(ebx);
|
|
4159
4084
|
|
|
4160
4085
|
__ bind(&allocated);
|
|
@@ -4174,6 +4099,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
|
|
4174
4099
|
|
|
4175
4100
|
|
|
4176
4101
|
void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|
4102
|
+
ASSERT(ToRegister(instr->context()).is(esi));
|
|
4177
4103
|
// Use the fast case closure allocation code that allocates in new
|
|
4178
4104
|
// space for nested functions that don't need literals cloning.
|
|
4179
4105
|
Handle<SharedFunctionInfo> shared_info = instr->shared_info();
|
|
@@ -4182,49 +4108,26 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|
|
4182
4108
|
FastNewClosureStub stub(
|
|
4183
4109
|
shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
|
|
4184
4110
|
__ push(Immediate(shared_info));
|
|
4185
|
-
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr
|
|
4111
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
4186
4112
|
} else {
|
|
4187
4113
|
__ push(Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
4188
4114
|
__ push(Immediate(shared_info));
|
|
4189
4115
|
__ push(Immediate(pretenure
|
|
4190
4116
|
? factory()->true_value()
|
|
4191
4117
|
: factory()->false_value()));
|
|
4192
|
-
CallRuntime(Runtime::kNewClosure, 3, instr
|
|
4118
|
+
CallRuntime(Runtime::kNewClosure, 3, instr);
|
|
4193
4119
|
}
|
|
4194
4120
|
}
|
|
4195
4121
|
|
|
4196
4122
|
|
|
4197
4123
|
void LCodeGen::DoTypeof(LTypeof* instr) {
|
|
4198
|
-
LOperand* input = instr->InputAt(
|
|
4124
|
+
LOperand* input = instr->InputAt(1);
|
|
4199
4125
|
if (input->IsConstantOperand()) {
|
|
4200
4126
|
__ push(ToImmediate(input));
|
|
4201
4127
|
} else {
|
|
4202
4128
|
__ push(ToOperand(input));
|
|
4203
4129
|
}
|
|
4204
|
-
CallRuntime(Runtime::kTypeof, 1, instr
|
|
4205
|
-
}
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
|
|
4209
|
-
Register input = ToRegister(instr->InputAt(0));
|
|
4210
|
-
Register result = ToRegister(instr->result());
|
|
4211
|
-
Label true_label;
|
|
4212
|
-
Label false_label;
|
|
4213
|
-
Label done;
|
|
4214
|
-
|
|
4215
|
-
Condition final_branch_condition = EmitTypeofIs(&true_label,
|
|
4216
|
-
&false_label,
|
|
4217
|
-
input,
|
|
4218
|
-
instr->type_literal());
|
|
4219
|
-
__ j(final_branch_condition, &true_label, Label::kNear);
|
|
4220
|
-
__ bind(&false_label);
|
|
4221
|
-
__ mov(result, factory()->false_value());
|
|
4222
|
-
__ jmp(&done, Label::kNear);
|
|
4223
|
-
|
|
4224
|
-
__ bind(&true_label);
|
|
4225
|
-
__ mov(result, factory()->true_value());
|
|
4226
|
-
|
|
4227
|
-
__ bind(&done);
|
|
4130
|
+
CallRuntime(Runtime::kTypeof, 1, instr);
|
|
4228
4131
|
}
|
|
4229
4132
|
|
|
4230
4133
|
|
|
@@ -4269,6 +4172,10 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|
|
4269
4172
|
__ cmp(input, factory()->false_value());
|
|
4270
4173
|
final_branch_condition = equal;
|
|
4271
4174
|
|
|
4175
|
+
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
|
|
4176
|
+
__ cmp(input, factory()->null_value());
|
|
4177
|
+
final_branch_condition = equal;
|
|
4178
|
+
|
|
4272
4179
|
} else if (type_name->Equals(heap()->undefined_symbol())) {
|
|
4273
4180
|
__ cmp(input, factory()->undefined_value());
|
|
4274
4181
|
__ j(equal, true_label);
|
|
@@ -4280,22 +4187,21 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|
|
4280
4187
|
final_branch_condition = not_zero;
|
|
4281
4188
|
|
|
4282
4189
|
} else if (type_name->Equals(heap()->function_symbol())) {
|
|
4190
|
+
STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
|
|
4283
4191
|
__ JumpIfSmi(input, false_label);
|
|
4284
|
-
__ CmpObjectType(input,
|
|
4285
|
-
|
|
4286
|
-
// Regular expressions => 'function' (they are callable).
|
|
4287
|
-
__ CmpInstanceType(input, JS_REGEXP_TYPE);
|
|
4288
|
-
final_branch_condition = equal;
|
|
4192
|
+
__ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input);
|
|
4193
|
+
final_branch_condition = above_equal;
|
|
4289
4194
|
|
|
4290
4195
|
} else if (type_name->Equals(heap()->object_symbol())) {
|
|
4291
4196
|
__ JumpIfSmi(input, false_label);
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4197
|
+
if (!FLAG_harmony_typeof) {
|
|
4198
|
+
__ cmp(input, factory()->null_value());
|
|
4199
|
+
__ j(equal, true_label);
|
|
4200
|
+
}
|
|
4201
|
+
__ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
|
|
4296
4202
|
__ j(below, false_label);
|
|
4297
|
-
__ CmpInstanceType(input,
|
|
4298
|
-
__ j(
|
|
4203
|
+
__ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
|
4204
|
+
__ j(above, false_label);
|
|
4299
4205
|
// Check for undetectable objects => false.
|
|
4300
4206
|
__ test_b(FieldOperand(input, Map::kBitFieldOffset),
|
|
4301
4207
|
1 << Map::kIsUndetectable);
|
|
@@ -4311,24 +4217,6 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|
|
4311
4217
|
}
|
|
4312
4218
|
|
|
4313
4219
|
|
|
4314
|
-
void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
|
|
4315
|
-
Register result = ToRegister(instr->result());
|
|
4316
|
-
Label true_label;
|
|
4317
|
-
Label done;
|
|
4318
|
-
|
|
4319
|
-
EmitIsConstructCall(result);
|
|
4320
|
-
__ j(equal, &true_label, Label::kNear);
|
|
4321
|
-
|
|
4322
|
-
__ mov(result, factory()->false_value());
|
|
4323
|
-
__ jmp(&done, Label::kNear);
|
|
4324
|
-
|
|
4325
|
-
__ bind(&true_label);
|
|
4326
|
-
__ mov(result, factory()->true_value());
|
|
4327
|
-
|
|
4328
|
-
__ bind(&done);
|
|
4329
|
-
}
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
4220
|
void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
|
|
4333
4221
|
Register temp = ToRegister(instr->TempAt(0));
|
|
4334
4222
|
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
|
@@ -4388,23 +4276,61 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
|
|
|
4388
4276
|
SafepointGenerator safepoint_generator(this,
|
|
4389
4277
|
pointers,
|
|
4390
4278
|
env->deoptimization_index());
|
|
4391
|
-
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
4392
4279
|
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
|
|
4393
4280
|
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
|
|
4394
4281
|
}
|
|
4395
4282
|
|
|
4396
4283
|
|
|
4284
|
+
void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
|
|
4285
|
+
{
|
|
4286
|
+
PushSafepointRegistersScope scope(this);
|
|
4287
|
+
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
4288
|
+
__ CallRuntimeSaveDoubles(Runtime::kStackGuard);
|
|
4289
|
+
RegisterLazyDeoptimization(
|
|
4290
|
+
instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
// The gap code includes the restoring of the safepoint registers.
|
|
4294
|
+
int pc = masm()->pc_offset();
|
|
4295
|
+
safepoints_.SetPcAfterGap(pc);
|
|
4296
|
+
}
|
|
4297
|
+
|
|
4298
|
+
|
|
4397
4299
|
void LCodeGen::DoStackCheck(LStackCheck* instr) {
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4300
|
+
class DeferredStackCheck: public LDeferredCode {
|
|
4301
|
+
public:
|
|
4302
|
+
DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
|
|
4303
|
+
: LDeferredCode(codegen), instr_(instr) { }
|
|
4304
|
+
virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
|
|
4305
|
+
private:
|
|
4306
|
+
LStackCheck* instr_;
|
|
4307
|
+
};
|
|
4404
4308
|
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4309
|
+
if (instr->hydrogen()->is_function_entry()) {
|
|
4310
|
+
// Perform stack overflow check.
|
|
4311
|
+
Label done;
|
|
4312
|
+
ExternalReference stack_limit =
|
|
4313
|
+
ExternalReference::address_of_stack_limit(isolate());
|
|
4314
|
+
__ cmp(esp, Operand::StaticVariable(stack_limit));
|
|
4315
|
+
__ j(above_equal, &done, Label::kNear);
|
|
4316
|
+
|
|
4317
|
+
ASSERT(instr->context()->IsRegister());
|
|
4318
|
+
ASSERT(ToRegister(instr->context()).is(esi));
|
|
4319
|
+
StackCheckStub stub;
|
|
4320
|
+
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
4321
|
+
__ bind(&done);
|
|
4322
|
+
} else {
|
|
4323
|
+
ASSERT(instr->hydrogen()->is_backwards_branch());
|
|
4324
|
+
// Perform stack overflow check if this goto needs it before jumping.
|
|
4325
|
+
DeferredStackCheck* deferred_stack_check =
|
|
4326
|
+
new DeferredStackCheck(this, instr);
|
|
4327
|
+
ExternalReference stack_limit =
|
|
4328
|
+
ExternalReference::address_of_stack_limit(isolate());
|
|
4329
|
+
__ cmp(esp, Operand::StaticVariable(stack_limit));
|
|
4330
|
+
__ j(below, deferred_stack_check->entry());
|
|
4331
|
+
__ bind(instr->done_label());
|
|
4332
|
+
deferred_stack_check->SetExit(instr->done_label());
|
|
4333
|
+
}
|
|
4408
4334
|
}
|
|
4409
4335
|
|
|
4410
4336
|
|
|
@@ -4449,7 +4375,6 @@ void LCodeGen::DoIn(LIn* instr) {
|
|
|
4449
4375
|
SafepointGenerator safepoint_generator(this,
|
|
4450
4376
|
pointers,
|
|
4451
4377
|
env->deoptimization_index());
|
|
4452
|
-
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
|
4453
4378
|
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
|
|
4454
4379
|
}
|
|
4455
4380
|
|