therubyracer 0.7.4 → 0.7.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of therubyracer might be problematic. Click here for more details.
- data/History.txt +11 -0
- data/Rakefile +1 -1
- data/ext/v8/extconf.rb +0 -18
- data/ext/v8/rr.cpp +2 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/AUTHORS +1 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/ChangeLog +239 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/LICENSE +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/SConstruct +29 -17
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/include/v8-debug.h +61 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/include/v8-profiler.h +182 -5
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/include/v8.h +458 -257
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/SConscript +2 -5
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/accessors.cc +2 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/accessors.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/allocation.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/allocation.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/api.cc +574 -30
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/api.h +12 -10
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/apinatives.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/apiutils.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arguments.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/assembler-arm-inl.h +38 -15
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/assembler-arm.cc +646 -101
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/assembler-arm.h +174 -15
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/builtins-arm.cc +56 -47
- data/ext/v8/upstream/2.3.3/src/arm/codegen-arm-inl.h +48 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/codegen-arm.cc +2957 -1448
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/codegen-arm.h +230 -74
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/constants-arm.cc +25 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/constants-arm.h +16 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/cpu-arm.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/debug-arm.cc +76 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/disasm-arm.cc +168 -20
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/fast-codegen-arm.cc +5 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/frames-arm.cc +4 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/frames-arm.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/full-codegen-arm.cc +1558 -248
- data/ext/v8/upstream/2.3.3/src/arm/ic-arm.cc +2258 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/jump-target-arm.cc +55 -103
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/macro-assembler-arm.cc +358 -185
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/macro-assembler-arm.h +136 -41
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/regexp-macro-assembler-arm.cc +26 -5
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/regexp-macro-assembler-arm.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/register-allocator-arm-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/register-allocator-arm.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/register-allocator-arm.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/simulator-arm.cc +203 -22
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/simulator-arm.h +7 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/stub-cache-arm.cc +531 -324
- data/ext/v8/upstream/2.3.3/src/arm/virtual-frame-arm-inl.h +59 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/virtual-frame-arm.cc +247 -81
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/arm/virtual-frame-arm.h +99 -83
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/array.js +2 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/assembler.cc +6 -13
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/assembler.h +36 -10
- data/ext/v8/upstream/2.3.3/src/ast-inl.h +81 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ast.cc +14 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ast.h +20 -35
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/bootstrapper.cc +32 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/bootstrapper.h +0 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/builtins.cc +50 -33
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/builtins.h +2 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/bytecodes-irregexp.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cached-powers.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/char-predicates-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/char-predicates.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/checks.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/checks.h +8 -6
- data/ext/v8/upstream/2.3.3/src/circular-queue-inl.h +53 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/circular-queue.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/circular-queue.h +0 -26
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/code-stubs.cc +2 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/code-stubs.h +1 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/code.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/codegen-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/codegen.cc +44 -13
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/codegen.h +310 -31
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compilation-cache.cc +28 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compilation-cache.h +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compiler.cc +45 -14
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/compiler.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/contexts.cc +11 -11
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/contexts.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/conversions-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/conversions.cc +25 -11
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/conversions.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/counters.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/counters.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu-profiler-inl.h +2 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu-profiler.cc +68 -24
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu-profiler.h +19 -11
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/cpu.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-debug.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-debug.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-posix.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-readline.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8-windows.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/d8.js +55 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/data-flow.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/data-flow.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/date.js +68 -137
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dateparser-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dateparser.cc +2 -8
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dateparser.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug-agent.cc +3 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug-agent.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug-debugger.js +81 -23
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug.cc +275 -81
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/debug.h +85 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/disasm.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/disassembler.cc +1 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/disassembler.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/diy-fp.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/diy-fp.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/double.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/dtoa-config.c +0 -0
- data/ext/v8/upstream/2.3.3/src/dtoa.cc +77 -0
- data/ext/v8/upstream/2.3.3/src/dtoa.h +81 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/execution.cc +111 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/execution.h +12 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/factory.cc +25 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/factory.h +16 -9
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-codegen.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-codegen.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-dtoa.cc +2 -9
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/fast-dtoa.h +1 -2
- data/ext/v8/upstream/2.3.3/src/fixed-dtoa.cc +405 -0
- data/ext/v8/upstream/{2.1.10/src/jump-target-light.cc → 2.3.3/src/fixed-dtoa.h} +22 -53
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flag-definitions.h +14 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flags.cc +5 -9
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flags.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flow-graph.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/flow-graph.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frame-element.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frame-element.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frames-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frames.cc +5 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/frames.h +1 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/full-codegen.cc +387 -20
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/full-codegen.h +102 -5
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/func-name-inferrer.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/func-name-inferrer.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/global-handles.cc +8 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/global-handles.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/globals.h +44 -7
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/handles-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/handles.cc +19 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/handles.h +8 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/hashmap.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/hashmap.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap-inl.h +56 -14
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap-profiler.cc +85 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap-profiler.h +45 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap.cc +994 -396
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/heap.h +220 -65
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/assembler-ia32-inl.h +41 -12
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/assembler-ia32.cc +94 -24
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/assembler-ia32.h +32 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/builtins-ia32.cc +42 -30
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/codegen-ia32-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/codegen-ia32.cc +1758 -916
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/codegen-ia32.h +67 -74
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/cpu-ia32.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/debug-ia32.cc +46 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/disasm-ia32.cc +37 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/fast-codegen-ia32.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/fast-codegen-ia32.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/frames-ia32.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/frames-ia32.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/full-codegen-ia32.cc +1465 -198
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/ic-ia32.cc +688 -367
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/jump-target-ia32.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/macro-assembler-ia32.cc +82 -180
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/macro-assembler-ia32.h +41 -25
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/regexp-macro-assembler-ia32.cc +68 -24
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/regexp-macro-assembler-ia32.h +1 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/register-allocator-ia32-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/register-allocator-ia32.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/register-allocator-ia32.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/simulator-ia32.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/simulator-ia32.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/stub-cache-ia32.cc +649 -302
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/virtual-frame-ia32.cc +23 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ia32/virtual-frame-ia32.h +18 -27
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ic-inl.h +30 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ic.cc +384 -66
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/ic.h +65 -24
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/interpreter-irregexp.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/interpreter-irregexp.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/json.js +3 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jsregexp.cc +20 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jsregexp.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-heavy-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-heavy.cc +79 -13
- data/ext/v8/upstream/{2.1.10/src/jump-target.h → 2.3.3/src/jump-target-heavy.h} +5 -47
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target-light-inl.h +16 -2
- data/ext/v8/upstream/2.3.3/src/jump-target-light.cc +110 -0
- data/ext/v8/upstream/2.3.3/src/jump-target-light.h +192 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/jump-target.cc +0 -64
- data/ext/v8/upstream/2.3.3/src/jump-target.h +90 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/list-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/list.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/liveedit-debugger.js +141 -28
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/liveedit.cc +19 -7
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/liveedit.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log-utils.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log-utils.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log.cc +12 -11
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/log.h +12 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/macro-assembler.h +0 -16
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/macros.py +21 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mark-compact.cc +120 -109
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mark-compact.h +25 -37
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/math.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/memory.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/messages.cc +8 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/messages.h +2 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/messages.js +15 -7
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/assembler-mips-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/assembler-mips.cc +12 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/assembler-mips.h +4 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/builtins-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/codegen-mips-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/codegen-mips.cc +9 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/codegen-mips.h +1 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/constants-mips.cc +5 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/constants-mips.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/cpu-mips.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/debug-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/disasm-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/fast-codegen-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/frames-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/frames-mips.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/full-codegen-mips.cc +5 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/ic-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/jump-target-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/macro-assembler-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/macro-assembler-mips.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/register-allocator-mips-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/register-allocator-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/register-allocator-mips.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/simulator-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/simulator-mips.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/stub-cache-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/virtual-frame-mips.cc +3 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mips/virtual-frame-mips.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mirror-debugger.js +46 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/mksnapshot.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/natives.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects-debug.cc +8 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects-inl.h +235 -62
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects.cc +497 -231
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/objects.h +355 -149
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/oprofile-agent.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/oprofile-agent.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/parser.cc +31 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/parser.h +1 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-freebsd.cc +9 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-linux.cc +26 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-macos.cc +11 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-nullos.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-openbsd.cc +6 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-posix.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-solaris.cc +69 -23
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform-win32.cc +15 -11
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/platform.h +10 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/powers-ten.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/prettyprinter.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/prettyprinter.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/profile-generator-inl.h +26 -2
- data/ext/v8/upstream/2.3.3/src/profile-generator.cc +1830 -0
- data/ext/v8/upstream/2.3.3/src/profile-generator.h +853 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/property.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/property.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-irregexp-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-irregexp.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-irregexp.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-tracer.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler-tracer.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler.cc +1 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-macro-assembler.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-stack.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp-stack.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/regexp.js +25 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/register-allocator-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/register-allocator.cc +4 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/register-allocator.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/rewriter.cc +85 -8
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/rewriter.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/runtime.cc +547 -221
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/runtime.h +5 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/runtime.js +23 -31
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scanner.cc +12 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scanner.h +60 -53
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopeinfo.cc +156 -168
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopeinfo.h +58 -62
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopes.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/scopes.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/serialize.cc +320 -242
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/serialize.h +81 -48
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/shell.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/simulator.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/smart-pointer.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/snapshot-common.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/snapshot-empty.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/snapshot.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/spaces-inl.h +177 -74
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/spaces.cc +138 -315
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/spaces.h +155 -124
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/splay-tree-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/splay-tree.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/string-stream.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/string-stream.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/string.js +113 -119
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/stub-cache.cc +242 -97
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/stub-cache.h +118 -55
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/third_party/dtoa/COPYING +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/third_party/dtoa/dtoa.c +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/third_party/valgrind/valgrind.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/token.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/token.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/top.cc +107 -26
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/top.h +9 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/type-info.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/type-info.h +2 -2
- data/ext/v8/upstream/2.3.3/src/unbound-queue-inl.h +95 -0
- data/ext/v8/upstream/2.3.3/src/unbound-queue.h +67 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/unicode-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/unicode.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/unicode.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/uri.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/utils.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/utils.h +83 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8-counters.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8-counters.h +20 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8.cc +5 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8.h +0 -0
- data/ext/v8/upstream/2.3.3/src/v8dll-main.cc +39 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8natives.js +210 -33
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8threads.cc +1 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/v8threads.h +1 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/variables.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/variables.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/version.cc +3 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/version.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-heavy-inl.h +40 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-heavy.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-light-inl.h +106 -5
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame-light.cc +4 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/virtual-frame.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/vm-state-inl.h +6 -3
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/vm-state.cc +1 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/vm-state.h +6 -4
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/assembler-x64-inl.h +42 -5
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/assembler-x64.cc +285 -53
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/assembler-x64.h +54 -18
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/builtins-x64.cc +31 -33
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/codegen-x64-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/codegen-x64.cc +9787 -8722
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/codegen-x64.h +82 -47
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/cpu-x64.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/debug-x64.cc +55 -6
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/disasm-x64.cc +42 -19
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/fast-codegen-x64.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/frames-x64.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/frames-x64.h +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/full-codegen-x64.cc +1487 -210
- data/ext/v8/upstream/2.3.3/src/x64/ic-x64.cc +1907 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/jump-target-x64.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/macro-assembler-x64.cc +366 -338
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/macro-assembler-x64.h +83 -38
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/regexp-macro-assembler-x64.cc +82 -23
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/regexp-macro-assembler-x64.h +1 -2
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/register-allocator-x64-inl.h +6 -5
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/register-allocator-x64.cc +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/register-allocator-x64.h +1 -1
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/simulator-x64.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/simulator-x64.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/stub-cache-x64.cc +556 -377
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/virtual-frame-x64.cc +197 -98
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/x64/virtual-frame-x64.h +37 -28
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/zone-inl.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/zone.cc +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/src/zone.h +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/codemap.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/consarray.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/csvparser.js +0 -0
- data/ext/v8/upstream/2.3.3/tools/gc-nvp-trace-processor.py +317 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/generate-ten-powers.scm +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/gyp/v8.gyp +87 -20
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/js2c.py +19 -15
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/jsmin.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/linux-tick-processor +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/linux-tick-processor.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/logreader.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/mac-nm +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/mac-tick-processor +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/annotate +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/common +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/dump +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/report +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/reset +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/run +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/shutdown +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/oprofile/start +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/presubmit.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/process-heap-prof.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/profile.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/profile_view.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/run-valgrind.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/splaytree.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/splaytree.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/stats-viewer.py +25 -13
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/test.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/tickprocessor-driver.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/tickprocessor.js +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/tickprocessor.py +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/utils.py +0 -0
- data/ext/v8/upstream/2.3.3/tools/v8.xcodeproj/project.pbxproj +1855 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/README.txt +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/arm.vsprops +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/common.vsprops +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8_arm.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/d8js2c.cmd +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/debug.vsprops +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/ia32.vsprops +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/js2c.cmd +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/release.vsprops +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8.sln +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_arm.sln +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_arm.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_base.vcproj +40 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_base_arm.vcproj +20 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_base_x64.vcproj +16 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_cctest.vcproj +4 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_cctest_arm.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_cctest_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_mksnapshot.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_mksnapshot_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_process_sample.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_process_sample_arm.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_process_sample_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_shell_sample.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_shell_sample_arm.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_shell_sample_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot_cc.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot_cc_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_snapshot_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_x64.sln +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/v8_x64.vcproj +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/visual_studio/x64.vsprops +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/windows-tick-processor.bat +0 -0
- data/ext/v8/upstream/{2.1.10 → 2.3.3}/tools/windows-tick-processor.py +0 -0
- data/ext/v8/upstream/Makefile +1 -1
- data/ext/v8/v8_template.cpp +94 -2
- data/ext/v8/v8_try_catch.cpp +2 -2
- data/lib/v8.rb +1 -1
- data/lib/v8/access.rb +93 -40
- data/lib/v8/cli.rb +1 -1
- data/lib/v8/function.rb +14 -2
- data/spec/redjs/jsapi_spec.rb +231 -42
- data/therubyracer.gemspec +3 -3
- metadata +463 -453
- data/ext/v8/upstream/2.1.10/src/arm/assembler-thumb2-inl.h +0 -263
- data/ext/v8/upstream/2.1.10/src/arm/assembler-thumb2.cc +0 -1878
- data/ext/v8/upstream/2.1.10/src/arm/assembler-thumb2.h +0 -1036
- data/ext/v8/upstream/2.1.10/src/arm/codegen-arm-inl.h +0 -72
- data/ext/v8/upstream/2.1.10/src/arm/ic-arm.cc +0 -1833
- data/ext/v8/upstream/2.1.10/src/circular-queue-inl.h +0 -101
- data/ext/v8/upstream/2.1.10/src/profile-generator.cc +0 -583
- data/ext/v8/upstream/2.1.10/src/profile-generator.h +0 -364
- data/ext/v8/upstream/2.1.10/src/x64/ic-x64.cc +0 -1621
File without changes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
// Copyright
|
1
|
+
// Copyright 2010 the V8 project authors. All rights reserved.
|
2
2
|
// Redistribution and use in source and binary forms, with or without
|
3
3
|
// modification, are permitted provided that the following conditions are
|
4
4
|
// met:
|
@@ -27,6 +27,8 @@
|
|
27
27
|
|
28
28
|
#include "v8.h"
|
29
29
|
|
30
|
+
#if defined(V8_TARGET_ARCH_IA32)
|
31
|
+
|
30
32
|
#include "codegen-inl.h"
|
31
33
|
#include "compiler.h"
|
32
34
|
#include "debug.h"
|
@@ -79,11 +81,17 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
79
81
|
bool function_in_register = true;
|
80
82
|
|
81
83
|
// Possibly allocate a local context.
|
82
|
-
|
84
|
+
int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
|
85
|
+
if (heap_slots > 0) {
|
83
86
|
Comment cmnt(masm_, "[ Allocate local context");
|
84
87
|
// Argument to NewContext is the function, which is still in edi.
|
85
88
|
__ push(edi);
|
86
|
-
|
89
|
+
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
|
90
|
+
FastNewContextStub stub(heap_slots);
|
91
|
+
__ CallStub(&stub);
|
92
|
+
} else {
|
93
|
+
__ CallRuntime(Runtime::kNewContext, 1);
|
94
|
+
}
|
87
95
|
function_in_register = false;
|
88
96
|
// Context is returned in both eax and esi. It replaces the context
|
89
97
|
// passed to us. It's saved in the stack and kept live in esi.
|
@@ -140,7 +148,18 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
140
148
|
}
|
141
149
|
|
142
150
|
{ Comment cmnt(masm_, "[ Declarations");
|
143
|
-
|
151
|
+
// For named function expressions, declare the function name as a
|
152
|
+
// constant.
|
153
|
+
if (scope()->is_function_scope() && scope()->function() != NULL) {
|
154
|
+
EmitDeclaration(scope()->function(), Variable::CONST, NULL);
|
155
|
+
}
|
156
|
+
// Visit all the explicit declarations unless there is an illegal
|
157
|
+
// redeclaration.
|
158
|
+
if (scope()->HasIllegalRedeclaration()) {
|
159
|
+
scope()->VisitIllegalRedeclaration(this);
|
160
|
+
} else {
|
161
|
+
VisitDeclarations(scope()->declarations());
|
162
|
+
}
|
144
163
|
}
|
145
164
|
|
146
165
|
{ Comment cmnt(masm_, "[ Stack check");
|
@@ -167,12 +186,12 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
167
186
|
{ Comment cmnt(masm_, "[ return <undefined>;");
|
168
187
|
// Emit a 'return undefined' in case control fell off the end of the body.
|
169
188
|
__ mov(eax, Factory::undefined_value());
|
170
|
-
EmitReturnSequence(
|
189
|
+
EmitReturnSequence();
|
171
190
|
}
|
172
191
|
}
|
173
192
|
|
174
193
|
|
175
|
-
void FullCodeGenerator::EmitReturnSequence(
|
194
|
+
void FullCodeGenerator::EmitReturnSequence() {
|
176
195
|
Comment cmnt(masm_, "[ Return sequence");
|
177
196
|
if (return_label_.is_bound()) {
|
178
197
|
__ jmp(&return_label_);
|
@@ -188,7 +207,7 @@ void FullCodeGenerator::EmitReturnSequence(int position) {
|
|
188
207
|
Label check_exit_codesize;
|
189
208
|
masm_->bind(&check_exit_codesize);
|
190
209
|
#endif
|
191
|
-
CodeGenerator::RecordPositions(masm_,
|
210
|
+
CodeGenerator::RecordPositions(masm_, function()->end_position());
|
192
211
|
__ RecordJSReturn();
|
193
212
|
// Do not use the leave instruction here because it is too short to
|
194
213
|
// patch with the code required by the debugger.
|
@@ -425,6 +444,39 @@ void FullCodeGenerator::DropAndApply(int count,
|
|
425
444
|
}
|
426
445
|
|
427
446
|
|
447
|
+
void FullCodeGenerator::PrepareTest(Label* materialize_true,
|
448
|
+
Label* materialize_false,
|
449
|
+
Label** if_true,
|
450
|
+
Label** if_false) {
|
451
|
+
switch (context_) {
|
452
|
+
case Expression::kUninitialized:
|
453
|
+
UNREACHABLE();
|
454
|
+
break;
|
455
|
+
case Expression::kEffect:
|
456
|
+
// In an effect context, the true and the false case branch to the
|
457
|
+
// same label.
|
458
|
+
*if_true = *if_false = materialize_true;
|
459
|
+
break;
|
460
|
+
case Expression::kValue:
|
461
|
+
*if_true = materialize_true;
|
462
|
+
*if_false = materialize_false;
|
463
|
+
break;
|
464
|
+
case Expression::kTest:
|
465
|
+
*if_true = true_label_;
|
466
|
+
*if_false = false_label_;
|
467
|
+
break;
|
468
|
+
case Expression::kValueTest:
|
469
|
+
*if_true = materialize_true;
|
470
|
+
*if_false = false_label_;
|
471
|
+
break;
|
472
|
+
case Expression::kTestValue:
|
473
|
+
*if_true = true_label_;
|
474
|
+
*if_false = materialize_false;
|
475
|
+
break;
|
476
|
+
}
|
477
|
+
}
|
478
|
+
|
479
|
+
|
428
480
|
void FullCodeGenerator::Apply(Expression::Context context,
|
429
481
|
Label* materialize_true,
|
430
482
|
Label* materialize_false) {
|
@@ -490,6 +542,61 @@ void FullCodeGenerator::Apply(Expression::Context context,
|
|
490
542
|
}
|
491
543
|
|
492
544
|
|
545
|
+
// Convert constant control flow (true or false) to the result expected for
|
546
|
+
// a given expression context.
|
547
|
+
void FullCodeGenerator::Apply(Expression::Context context, bool flag) {
|
548
|
+
switch (context) {
|
549
|
+
case Expression::kUninitialized:
|
550
|
+
UNREACHABLE();
|
551
|
+
break;
|
552
|
+
case Expression::kEffect:
|
553
|
+
break;
|
554
|
+
case Expression::kValue: {
|
555
|
+
Handle<Object> value =
|
556
|
+
flag ? Factory::true_value() : Factory::false_value();
|
557
|
+
switch (location_) {
|
558
|
+
case kAccumulator:
|
559
|
+
__ mov(result_register(), value);
|
560
|
+
break;
|
561
|
+
case kStack:
|
562
|
+
__ push(Immediate(value));
|
563
|
+
break;
|
564
|
+
}
|
565
|
+
break;
|
566
|
+
}
|
567
|
+
case Expression::kTest:
|
568
|
+
__ jmp(flag ? true_label_ : false_label_);
|
569
|
+
break;
|
570
|
+
case Expression::kTestValue:
|
571
|
+
switch (location_) {
|
572
|
+
case kAccumulator:
|
573
|
+
// If value is false it's needed.
|
574
|
+
if (!flag) __ mov(result_register(), Factory::false_value());
|
575
|
+
break;
|
576
|
+
case kStack:
|
577
|
+
// If value is false it's needed.
|
578
|
+
if (!flag) __ push(Immediate(Factory::false_value()));
|
579
|
+
break;
|
580
|
+
}
|
581
|
+
__ jmp(flag ? true_label_ : false_label_);
|
582
|
+
break;
|
583
|
+
case Expression::kValueTest:
|
584
|
+
switch (location_) {
|
585
|
+
case kAccumulator:
|
586
|
+
// If value is true it's needed.
|
587
|
+
if (flag) __ mov(result_register(), Factory::true_value());
|
588
|
+
break;
|
589
|
+
case kStack:
|
590
|
+
// If value is true it's needed.
|
591
|
+
if (flag) __ push(Immediate(Factory::true_value()));
|
592
|
+
break;
|
593
|
+
}
|
594
|
+
__ jmp(flag ? true_label_ : false_label_);
|
595
|
+
break;
|
596
|
+
}
|
597
|
+
}
|
598
|
+
|
599
|
+
|
493
600
|
void FullCodeGenerator::DoTest(Expression::Context context) {
|
494
601
|
// The value to test is in the accumulator. If the value might be needed
|
495
602
|
// on the stack (value/test and test/value contexts with a stack location
|
@@ -665,22 +772,22 @@ void FullCodeGenerator::Move(Slot* dst,
|
|
665
772
|
}
|
666
773
|
|
667
774
|
|
668
|
-
void FullCodeGenerator::
|
775
|
+
void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
776
|
+
Variable::Mode mode,
|
777
|
+
FunctionLiteral* function) {
|
669
778
|
Comment cmnt(masm_, "[ Declaration");
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
Property* prop = var->AsProperty();
|
674
|
-
|
779
|
+
ASSERT(variable != NULL); // Must have been resolved.
|
780
|
+
Slot* slot = variable->slot();
|
781
|
+
Property* prop = variable->AsProperty();
|
675
782
|
if (slot != NULL) {
|
676
783
|
switch (slot->type()) {
|
677
784
|
case Slot::PARAMETER:
|
678
785
|
case Slot::LOCAL:
|
679
|
-
if (
|
786
|
+
if (mode == Variable::CONST) {
|
680
787
|
__ mov(Operand(ebp, SlotOffset(slot)),
|
681
788
|
Immediate(Factory::the_hole_value()));
|
682
|
-
} else if (
|
683
|
-
VisitForValue(
|
789
|
+
} else if (function != NULL) {
|
790
|
+
VisitForValue(function, kAccumulator);
|
684
791
|
__ mov(Operand(ebp, SlotOffset(slot)), result_register());
|
685
792
|
}
|
686
793
|
break;
|
@@ -690,7 +797,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
690
797
|
// this specific context.
|
691
798
|
|
692
799
|
// The variable in the decl always resides in the current context.
|
693
|
-
ASSERT_EQ(0, scope()->ContextChainLength(
|
800
|
+
ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
|
694
801
|
if (FLAG_debug_code) {
|
695
802
|
// Check if we have the correct context pointer.
|
696
803
|
__ mov(ebx,
|
@@ -698,12 +805,12 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
698
805
|
__ cmp(ebx, Operand(esi));
|
699
806
|
__ Check(equal, "Unexpected declaration in current context.");
|
700
807
|
}
|
701
|
-
if (
|
702
|
-
__ mov(
|
703
|
-
|
808
|
+
if (mode == Variable::CONST) {
|
809
|
+
__ mov(CodeGenerator::ContextOperand(esi, slot->index()),
|
810
|
+
Immediate(Factory::the_hole_value()));
|
704
811
|
// No write barrier since the hole value is in old space.
|
705
|
-
} else if (
|
706
|
-
VisitForValue(
|
812
|
+
} else if (function != NULL) {
|
813
|
+
VisitForValue(function, kAccumulator);
|
707
814
|
__ mov(CodeGenerator::ContextOperand(esi, slot->index()),
|
708
815
|
result_register());
|
709
816
|
int offset = Context::SlotOffset(slot->index());
|
@@ -714,21 +821,19 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
714
821
|
|
715
822
|
case Slot::LOOKUP: {
|
716
823
|
__ push(esi);
|
717
|
-
__ push(Immediate(
|
824
|
+
__ push(Immediate(variable->name()));
|
718
825
|
// Declaration nodes are always introduced in one of two modes.
|
719
|
-
ASSERT(
|
720
|
-
|
721
|
-
PropertyAttributes attr =
|
722
|
-
(decl->mode() == Variable::VAR) ? NONE : READ_ONLY;
|
826
|
+
ASSERT(mode == Variable::VAR || mode == Variable::CONST);
|
827
|
+
PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
|
723
828
|
__ push(Immediate(Smi::FromInt(attr)));
|
724
829
|
// Push initial value, if any.
|
725
830
|
// Note: For variables we must not push an initial value (such as
|
726
831
|
// 'undefined') because we may have a (legal) redeclaration and we
|
727
832
|
// must not destroy the current value.
|
728
|
-
if (
|
833
|
+
if (mode == Variable::CONST) {
|
729
834
|
__ push(Immediate(Factory::the_hole_value()));
|
730
|
-
} else if (
|
731
|
-
VisitForValue(
|
835
|
+
} else if (function != NULL) {
|
836
|
+
VisitForValue(function, kStack);
|
732
837
|
} else {
|
733
838
|
__ push(Immediate(Smi::FromInt(0))); // No initial value!
|
734
839
|
}
|
@@ -738,13 +843,13 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
738
843
|
}
|
739
844
|
|
740
845
|
} else if (prop != NULL) {
|
741
|
-
if (
|
846
|
+
if (function != NULL || mode == Variable::CONST) {
|
742
847
|
// We are declaring a function or constant that rewrites to a
|
743
848
|
// property. Use (keyed) IC to set the initial value.
|
744
849
|
VisitForValue(prop->obj(), kStack);
|
745
|
-
if (
|
850
|
+
if (function != NULL) {
|
746
851
|
VisitForValue(prop->key(), kStack);
|
747
|
-
VisitForValue(
|
852
|
+
VisitForValue(function, kAccumulator);
|
748
853
|
__ pop(ecx);
|
749
854
|
} else {
|
750
855
|
VisitForValue(prop->key(), kAccumulator);
|
@@ -763,6 +868,11 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
763
868
|
}
|
764
869
|
|
765
870
|
|
871
|
+
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
872
|
+
EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
|
873
|
+
}
|
874
|
+
|
875
|
+
|
766
876
|
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
767
877
|
// Call the runtime to declare the globals.
|
768
878
|
__ push(esi); // The context is the first argument.
|
@@ -773,19 +883,223 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
|
773
883
|
}
|
774
884
|
|
775
885
|
|
776
|
-
void FullCodeGenerator::
|
777
|
-
Comment cmnt(masm_, "[
|
886
|
+
void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
887
|
+
Comment cmnt(masm_, "[ SwitchStatement");
|
888
|
+
Breakable nested_statement(this, stmt);
|
889
|
+
SetStatementPosition(stmt);
|
890
|
+
// Keep the switch value on the stack until a case matches.
|
891
|
+
VisitForValue(stmt->tag(), kStack);
|
892
|
+
|
893
|
+
ZoneList<CaseClause*>* clauses = stmt->cases();
|
894
|
+
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
|
895
|
+
|
896
|
+
Label next_test; // Recycled for each test.
|
897
|
+
// Compile all the tests with branches to their bodies.
|
898
|
+
for (int i = 0; i < clauses->length(); i++) {
|
899
|
+
CaseClause* clause = clauses->at(i);
|
900
|
+
// The default is not a test, but remember it as final fall through.
|
901
|
+
if (clause->is_default()) {
|
902
|
+
default_clause = clause;
|
903
|
+
continue;
|
904
|
+
}
|
905
|
+
|
906
|
+
Comment cmnt(masm_, "[ Case comparison");
|
907
|
+
__ bind(&next_test);
|
908
|
+
next_test.Unuse();
|
909
|
+
|
910
|
+
// Compile the label expression.
|
911
|
+
VisitForValue(clause->label(), kAccumulator);
|
912
|
+
|
913
|
+
// Perform the comparison as if via '==='. The comparison stub expects
|
914
|
+
// the smi vs. smi case to be handled before it is called.
|
915
|
+
Label slow_case;
|
916
|
+
__ mov(edx, Operand(esp, 0)); // Switch value.
|
917
|
+
__ mov(ecx, edx);
|
918
|
+
__ or_(ecx, Operand(eax));
|
919
|
+
__ test(ecx, Immediate(kSmiTagMask));
|
920
|
+
__ j(not_zero, &slow_case, not_taken);
|
921
|
+
__ cmp(edx, Operand(eax));
|
922
|
+
__ j(not_equal, &next_test);
|
923
|
+
__ Drop(1); // Switch value is no longer needed.
|
924
|
+
__ jmp(clause->body_target()->entry_label());
|
925
|
+
|
926
|
+
__ bind(&slow_case);
|
927
|
+
CompareStub stub(equal, true);
|
928
|
+
__ CallStub(&stub);
|
929
|
+
__ test(eax, Operand(eax));
|
930
|
+
__ j(not_equal, &next_test);
|
931
|
+
__ Drop(1); // Switch value is no longer needed.
|
932
|
+
__ jmp(clause->body_target()->entry_label());
|
933
|
+
}
|
934
|
+
|
935
|
+
// Discard the test value and jump to the default if present, otherwise to
|
936
|
+
// the end of the statement.
|
937
|
+
__ bind(&next_test);
|
938
|
+
__ Drop(1); // Switch value is no longer needed.
|
939
|
+
if (default_clause == NULL) {
|
940
|
+
__ jmp(nested_statement.break_target());
|
941
|
+
} else {
|
942
|
+
__ jmp(default_clause->body_target()->entry_label());
|
943
|
+
}
|
944
|
+
|
945
|
+
// Compile all the case bodies.
|
946
|
+
for (int i = 0; i < clauses->length(); i++) {
|
947
|
+
Comment cmnt(masm_, "[ Case body");
|
948
|
+
CaseClause* clause = clauses->at(i);
|
949
|
+
__ bind(clause->body_target()->entry_label());
|
950
|
+
VisitStatements(clause->statements());
|
951
|
+
}
|
952
|
+
|
953
|
+
__ bind(nested_statement.break_target());
|
954
|
+
}
|
955
|
+
|
956
|
+
|
957
|
+
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
958
|
+
Comment cmnt(masm_, "[ ForInStatement");
|
959
|
+
SetStatementPosition(stmt);
|
960
|
+
|
961
|
+
Label loop, exit;
|
962
|
+
ForIn loop_statement(this, stmt);
|
963
|
+
increment_loop_depth();
|
964
|
+
|
965
|
+
// Get the object to enumerate over. Both SpiderMonkey and JSC
|
966
|
+
// ignore null and undefined in contrast to the specification; see
|
967
|
+
// ECMA-262 section 12.6.4.
|
968
|
+
VisitForValue(stmt->enumerable(), kAccumulator);
|
969
|
+
__ cmp(eax, Factory::undefined_value());
|
970
|
+
__ j(equal, &exit);
|
971
|
+
__ cmp(eax, Factory::null_value());
|
972
|
+
__ j(equal, &exit);
|
973
|
+
|
974
|
+
// Convert the object to a JS object.
|
975
|
+
Label convert, done_convert;
|
976
|
+
__ test(eax, Immediate(kSmiTagMask));
|
977
|
+
__ j(zero, &convert);
|
978
|
+
__ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
|
979
|
+
__ j(above_equal, &done_convert);
|
980
|
+
__ bind(&convert);
|
981
|
+
__ push(eax);
|
982
|
+
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
983
|
+
__ bind(&done_convert);
|
984
|
+
__ push(eax);
|
985
|
+
|
986
|
+
// TODO(kasperl): Check cache validity in generated code. This is a
|
987
|
+
// fast case for the JSObject::IsSimpleEnum cache validity
|
988
|
+
// checks. If we cannot guarantee cache validity, call the runtime
|
989
|
+
// system to check cache validity or get the property names in a
|
990
|
+
// fixed array.
|
991
|
+
|
992
|
+
// Get the set of properties to enumerate.
|
993
|
+
__ push(eax); // Duplicate the enumerable object on the stack.
|
994
|
+
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
|
995
|
+
|
996
|
+
// If we got a map from the runtime call, we can do a fast
|
997
|
+
// modification check. Otherwise, we got a fixed array, and we have
|
998
|
+
// to do a slow check.
|
999
|
+
Label fixed_array;
|
1000
|
+
__ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map());
|
1001
|
+
__ j(not_equal, &fixed_array);
|
1002
|
+
|
1003
|
+
// We got a map in register eax. Get the enumeration cache from it.
|
1004
|
+
__ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset));
|
1005
|
+
__ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
|
1006
|
+
__ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
|
1007
|
+
|
1008
|
+
// Setup the four remaining stack slots.
|
1009
|
+
__ push(eax); // Map.
|
1010
|
+
__ push(edx); // Enumeration cache.
|
1011
|
+
__ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
|
1012
|
+
__ push(eax); // Enumeration cache length (as smi).
|
1013
|
+
__ push(Immediate(Smi::FromInt(0))); // Initial index.
|
1014
|
+
__ jmp(&loop);
|
1015
|
+
|
1016
|
+
// We got a fixed array in register eax. Iterate through that.
|
1017
|
+
__ bind(&fixed_array);
|
1018
|
+
__ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check.
|
1019
|
+
__ push(eax);
|
1020
|
+
__ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
|
1021
|
+
__ push(eax); // Fixed array length (as smi).
|
1022
|
+
__ push(Immediate(Smi::FromInt(0))); // Initial index.
|
1023
|
+
|
1024
|
+
// Generate code for doing the condition check.
|
1025
|
+
__ bind(&loop);
|
1026
|
+
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
|
1027
|
+
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
|
1028
|
+
__ j(above_equal, loop_statement.break_target());
|
1029
|
+
|
1030
|
+
// Get the current entry of the array into register ebx.
|
1031
|
+
__ mov(ebx, Operand(esp, 2 * kPointerSize));
|
1032
|
+
__ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
|
1033
|
+
|
1034
|
+
// Get the expected map from the stack or a zero map in the
|
1035
|
+
// permanent slow case into register edx.
|
1036
|
+
__ mov(edx, Operand(esp, 3 * kPointerSize));
|
1037
|
+
|
1038
|
+
// Check if the expected map still matches that of the enumerable.
|
1039
|
+
// If not, we have to filter the key.
|
1040
|
+
Label update_each;
|
1041
|
+
__ mov(ecx, Operand(esp, 4 * kPointerSize));
|
1042
|
+
__ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
|
1043
|
+
__ j(equal, &update_each);
|
1044
|
+
|
1045
|
+
// Convert the entry to a string or null if it isn't a property
|
1046
|
+
// anymore. If the property has been removed while iterating, we
|
1047
|
+
// just skip it.
|
1048
|
+
__ push(ecx); // Enumerable.
|
1049
|
+
__ push(ebx); // Current entry.
|
1050
|
+
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
|
1051
|
+
__ cmp(eax, Factory::null_value());
|
1052
|
+
__ j(equal, loop_statement.continue_target());
|
1053
|
+
__ mov(ebx, Operand(eax));
|
1054
|
+
|
1055
|
+
// Update the 'each' property or variable from the possibly filtered
|
1056
|
+
// entry in register ebx.
|
1057
|
+
__ bind(&update_each);
|
1058
|
+
__ mov(result_register(), ebx);
|
1059
|
+
// Perform the assignment as if via '='.
|
1060
|
+
EmitAssignment(stmt->each());
|
1061
|
+
|
1062
|
+
// Generate code for the body of the loop.
|
1063
|
+
Label stack_limit_hit, stack_check_done;
|
1064
|
+
Visit(stmt->body());
|
1065
|
+
|
1066
|
+
__ StackLimitCheck(&stack_limit_hit);
|
1067
|
+
__ bind(&stack_check_done);
|
1068
|
+
|
1069
|
+
// Generate code for going to the next element by incrementing the
|
1070
|
+
// index (smi) stored on top of the stack.
|
1071
|
+
__ bind(loop_statement.continue_target());
|
1072
|
+
__ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
|
1073
|
+
__ jmp(&loop);
|
1074
|
+
|
1075
|
+
// Slow case for the stack limit check.
|
1076
|
+
StackCheckStub stack_check_stub;
|
1077
|
+
__ bind(&stack_limit_hit);
|
1078
|
+
__ CallStub(&stack_check_stub);
|
1079
|
+
__ jmp(&stack_check_done);
|
1080
|
+
|
1081
|
+
// Remove the pointers stored on the stack.
|
1082
|
+
__ bind(loop_statement.break_target());
|
1083
|
+
__ add(Operand(esp), Immediate(5 * kPointerSize));
|
1084
|
+
|
1085
|
+
// Exit and decrement the loop depth.
|
1086
|
+
__ bind(&exit);
|
1087
|
+
decrement_loop_depth();
|
1088
|
+
}
|
778
1089
|
|
779
|
-
// Build the shared function info and instantiate the function based
|
780
|
-
// on it.
|
781
|
-
Handle<SharedFunctionInfo> function_info =
|
782
|
-
Compiler::BuildFunctionInfo(expr, script(), this);
|
783
|
-
if (HasStackOverflow()) return;
|
784
1090
|
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
1091
|
+
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
|
1092
|
+
// Use the fast case closure allocation code that allocates in new
|
1093
|
+
// space for nested functions that don't need literals cloning.
|
1094
|
+
if (scope()->is_function_scope() && info->num_literals() == 0) {
|
1095
|
+
FastNewClosureStub stub;
|
1096
|
+
__ push(Immediate(info));
|
1097
|
+
__ CallStub(&stub);
|
1098
|
+
} else {
|
1099
|
+
__ push(esi);
|
1100
|
+
__ push(Immediate(info));
|
1101
|
+
__ CallRuntime(Runtime::kNewClosure, 2);
|
1102
|
+
}
|
789
1103
|
Apply(context_, eax);
|
790
1104
|
}
|
791
1105
|
|
@@ -830,7 +1144,20 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
|
830
1144
|
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
|
831
1145
|
? "Context slot"
|
832
1146
|
: "Stack slot");
|
833
|
-
|
1147
|
+
if (var->mode() == Variable::CONST) {
|
1148
|
+
// Constants may be the hole value if they have not been initialized.
|
1149
|
+
// Unhole them.
|
1150
|
+
Label done;
|
1151
|
+
MemOperand slot_operand = EmitSlotSearch(slot, eax);
|
1152
|
+
__ mov(eax, slot_operand);
|
1153
|
+
__ cmp(eax, Factory::the_hole_value());
|
1154
|
+
__ j(not_equal, &done);
|
1155
|
+
__ mov(eax, Factory::undefined_value());
|
1156
|
+
__ bind(&done);
|
1157
|
+
Apply(context, eax);
|
1158
|
+
} else {
|
1159
|
+
Apply(context, slot);
|
1160
|
+
}
|
834
1161
|
|
835
1162
|
} else {
|
836
1163
|
Comment cmnt(masm_, "Rewritten parameter");
|
@@ -966,22 +1293,28 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|
966
1293
|
|
967
1294
|
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
968
1295
|
Comment cmnt(masm_, "[ ArrayLiteral");
|
1296
|
+
|
1297
|
+
ZoneList<Expression*>* subexprs = expr->values();
|
1298
|
+
int length = subexprs->length();
|
1299
|
+
|
969
1300
|
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
970
1301
|
__ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
|
971
1302
|
__ push(Immediate(Smi::FromInt(expr->literal_index())));
|
972
1303
|
__ push(Immediate(expr->constant_elements()));
|
973
1304
|
if (expr->depth() > 1) {
|
974
1305
|
__ CallRuntime(Runtime::kCreateArrayLiteral, 3);
|
975
|
-
} else {
|
1306
|
+
} else if (length > FastCloneShallowArrayStub::kMaximumLength) {
|
976
1307
|
__ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
|
1308
|
+
} else {
|
1309
|
+
FastCloneShallowArrayStub stub(length);
|
1310
|
+
__ CallStub(&stub);
|
977
1311
|
}
|
978
1312
|
|
979
1313
|
bool result_saved = false; // Is the result saved to the stack?
|
980
1314
|
|
981
1315
|
// Emit code to evaluate all the non-constant subexpressions and to store
|
982
1316
|
// them into the newly cloned array.
|
983
|
-
|
984
|
-
for (int i = 0, len = subexprs->length(); i < len; i++) {
|
1317
|
+
for (int i = 0; i < length; i++) {
|
985
1318
|
Expression* subexpr = subexprs->at(i);
|
986
1319
|
// If the subexpression is a literal or a simple materialized literal it
|
987
1320
|
// is already set in the cloned array.
|
@@ -1016,7 +1349,13 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|
1016
1349
|
|
1017
1350
|
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
1018
1351
|
Comment cmnt(masm_, "[ Assignment");
|
1019
|
-
|
1352
|
+
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
|
1353
|
+
// on the left-hand side.
|
1354
|
+
if (!expr->target()->IsValidLeftHandSide()) {
|
1355
|
+
VisitForEffect(expr->target());
|
1356
|
+
return;
|
1357
|
+
}
|
1358
|
+
|
1020
1359
|
// Left-hand side can only be a property, a global or a (parameter or local)
|
1021
1360
|
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
|
1022
1361
|
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
|
@@ -1095,6 +1434,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
|
1095
1434
|
switch (assign_type) {
|
1096
1435
|
case VARIABLE:
|
1097
1436
|
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
|
1437
|
+
expr->op(),
|
1098
1438
|
context_);
|
1099
1439
|
break;
|
1100
1440
|
case NAMED_PROPERTY:
|
@@ -1137,15 +1477,66 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
|
|
1137
1477
|
}
|
1138
1478
|
|
1139
1479
|
|
1480
|
+
void FullCodeGenerator::EmitAssignment(Expression* expr) {
|
1481
|
+
// Invalid left-hand sides are rewritten to have a 'throw
|
1482
|
+
// ReferenceError' on the left-hand side.
|
1483
|
+
if (!expr->IsValidLeftHandSide()) {
|
1484
|
+
VisitForEffect(expr);
|
1485
|
+
return;
|
1486
|
+
}
|
1487
|
+
|
1488
|
+
// Left-hand side can only be a property, a global or a (parameter or local)
|
1489
|
+
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
|
1490
|
+
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
|
1491
|
+
LhsKind assign_type = VARIABLE;
|
1492
|
+
Property* prop = expr->AsProperty();
|
1493
|
+
if (prop != NULL) {
|
1494
|
+
assign_type = (prop->key()->IsPropertyName())
|
1495
|
+
? NAMED_PROPERTY
|
1496
|
+
: KEYED_PROPERTY;
|
1497
|
+
}
|
1498
|
+
|
1499
|
+
switch (assign_type) {
|
1500
|
+
case VARIABLE: {
|
1501
|
+
Variable* var = expr->AsVariableProxy()->var();
|
1502
|
+
EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
|
1503
|
+
break;
|
1504
|
+
}
|
1505
|
+
case NAMED_PROPERTY: {
|
1506
|
+
__ push(eax); // Preserve value.
|
1507
|
+
VisitForValue(prop->obj(), kAccumulator);
|
1508
|
+
__ mov(edx, eax);
|
1509
|
+
__ pop(eax); // Restore value.
|
1510
|
+
__ mov(ecx, prop->key()->AsLiteral()->handle());
|
1511
|
+
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
1512
|
+
__ call(ic, RelocInfo::CODE_TARGET);
|
1513
|
+
__ nop(); // Signal no inlined code.
|
1514
|
+
break;
|
1515
|
+
}
|
1516
|
+
case KEYED_PROPERTY: {
|
1517
|
+
__ push(eax); // Preserve value.
|
1518
|
+
VisitForValue(prop->obj(), kStack);
|
1519
|
+
VisitForValue(prop->key(), kAccumulator);
|
1520
|
+
__ mov(ecx, eax);
|
1521
|
+
__ pop(edx);
|
1522
|
+
__ pop(eax); // Restore value.
|
1523
|
+
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
1524
|
+
__ call(ic, RelocInfo::CODE_TARGET);
|
1525
|
+
__ nop(); // Signal no inlined code.
|
1526
|
+
break;
|
1527
|
+
}
|
1528
|
+
}
|
1529
|
+
}
|
1530
|
+
|
1531
|
+
|
1140
1532
|
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
1533
|
+
Token::Value op,
|
1141
1534
|
Expression::Context context) {
|
1142
|
-
//
|
1143
|
-
//
|
1144
|
-
// explicit property accesses do not reach here.
|
1535
|
+
// Left-hand sides that rewrite to explicit property accesses do not reach
|
1536
|
+
// here.
|
1145
1537
|
ASSERT(var != NULL);
|
1146
1538
|
ASSERT(var->is_global() || var->slot() != NULL);
|
1147
1539
|
|
1148
|
-
Slot* slot = var->slot();
|
1149
1540
|
if (var->is_global()) {
|
1150
1541
|
ASSERT(!var->is_this());
|
1151
1542
|
// Assignment to a global variable. Use inline caching for the
|
@@ -1156,44 +1547,61 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
|
1156
1547
|
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
1157
1548
|
__ call(ic, RelocInfo::CODE_TARGET);
|
1158
1549
|
__ nop();
|
1159
|
-
Apply(context, eax);
|
1160
|
-
|
1161
|
-
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
|
1162
|
-
__ push(result_register()); // Value.
|
1163
|
-
__ push(esi); // Context.
|
1164
|
-
__ push(Immediate(var->name()));
|
1165
|
-
__ CallRuntime(Runtime::kStoreContextSlot, 3);
|
1166
|
-
Apply(context, eax);
|
1167
1550
|
|
1168
|
-
} else if (
|
1551
|
+
} else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
|
1552
|
+
// Perform the assignment for non-const variables and for initialization
|
1553
|
+
// of const variables. Const assignments are simply skipped.
|
1554
|
+
Label done;
|
1555
|
+
Slot* slot = var->slot();
|
1169
1556
|
switch (slot->type()) {
|
1170
|
-
case Slot::LOCAL:
|
1171
1557
|
case Slot::PARAMETER:
|
1172
|
-
|
1558
|
+
case Slot::LOCAL:
|
1559
|
+
if (op == Token::INIT_CONST) {
|
1560
|
+
// Detect const reinitialization by checking for the hole value.
|
1561
|
+
__ mov(edx, Operand(ebp, SlotOffset(slot)));
|
1562
|
+
__ cmp(edx, Factory::the_hole_value());
|
1563
|
+
__ j(not_equal, &done);
|
1564
|
+
}
|
1565
|
+
// Perform the assignment.
|
1566
|
+
__ mov(Operand(ebp, SlotOffset(slot)), eax);
|
1173
1567
|
break;
|
1174
1568
|
|
1175
1569
|
case Slot::CONTEXT: {
|
1176
1570
|
MemOperand target = EmitSlotSearch(slot, ecx);
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1571
|
+
if (op == Token::INIT_CONST) {
|
1572
|
+
// Detect const reinitialization by checking for the hole value.
|
1573
|
+
__ mov(edx, target);
|
1574
|
+
__ cmp(edx, Factory::the_hole_value());
|
1575
|
+
__ j(not_equal, &done);
|
1576
|
+
}
|
1577
|
+
// Perform the assignment and issue the write barrier.
|
1578
|
+
__ mov(target, eax);
|
1579
|
+
// The value of the assignment is in eax. RecordWrite clobbers its
|
1580
|
+
// register arguments.
|
1581
|
+
__ mov(edx, eax);
|
1181
1582
|
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
|
1182
1583
|
__ RecordWrite(ecx, offset, edx, ebx);
|
1183
1584
|
break;
|
1184
1585
|
}
|
1185
1586
|
|
1186
1587
|
case Slot::LOOKUP:
|
1187
|
-
|
1588
|
+
// Call the runtime for the assignment. The runtime will ignore
|
1589
|
+
// const reinitialization.
|
1590
|
+
__ push(eax); // Value.
|
1591
|
+
__ push(esi); // Context.
|
1592
|
+
__ push(Immediate(var->name()));
|
1593
|
+
if (op == Token::INIT_CONST) {
|
1594
|
+
// The runtime will ignore const redeclaration.
|
1595
|
+
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
|
1596
|
+
} else {
|
1597
|
+
__ CallRuntime(Runtime::kStoreContextSlot, 3);
|
1598
|
+
}
|
1188
1599
|
break;
|
1189
1600
|
}
|
1190
|
-
|
1191
|
-
|
1192
|
-
} else {
|
1193
|
-
// Variables rewritten as properties are not treated as variables in
|
1194
|
-
// assignments.
|
1195
|
-
UNREACHABLE();
|
1601
|
+
__ bind(&done);
|
1196
1602
|
}
|
1603
|
+
|
1604
|
+
Apply(context, eax);
|
1197
1605
|
}
|
1198
1606
|
|
1199
1607
|
|
@@ -1318,6 +1726,29 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
|
1318
1726
|
}
|
1319
1727
|
|
1320
1728
|
|
1729
|
+
void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
|
1730
|
+
Expression* key,
|
1731
|
+
RelocInfo::Mode mode) {
|
1732
|
+
// Code common for calls using the IC.
|
1733
|
+
ZoneList<Expression*>* args = expr->arguments();
|
1734
|
+
int arg_count = args->length();
|
1735
|
+
for (int i = 0; i < arg_count; i++) {
|
1736
|
+
VisitForValue(args->at(i), kStack);
|
1737
|
+
}
|
1738
|
+
VisitForValue(key, kAccumulator);
|
1739
|
+
__ mov(ecx, eax);
|
1740
|
+
// Record source position of the IC call.
|
1741
|
+
SetSourcePosition(expr->position());
|
1742
|
+
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
|
1743
|
+
Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(
|
1744
|
+
arg_count, in_loop);
|
1745
|
+
__ call(ic, mode);
|
1746
|
+
// Restore context register.
|
1747
|
+
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
1748
|
+
Apply(context_, eax);
|
1749
|
+
}
|
1750
|
+
|
1751
|
+
|
1321
1752
|
void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
1322
1753
|
// Code common for calls using the call stub.
|
1323
1754
|
ZoneList<Expression*>* args = expr->arguments();
|
@@ -1327,7 +1758,8 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
|
1327
1758
|
}
|
1328
1759
|
// Record source position for debugger.
|
1329
1760
|
SetSourcePosition(expr->position());
|
1330
|
-
|
1761
|
+
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
|
1762
|
+
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
|
1331
1763
|
__ CallStub(&stub);
|
1332
1764
|
// Restore context register.
|
1333
1765
|
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
@@ -1341,16 +1773,62 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
|
1341
1773
|
Variable* var = fun->AsVariableProxy()->AsVariable();
|
1342
1774
|
|
1343
1775
|
if (var != NULL && var->is_possibly_eval()) {
|
1344
|
-
//
|
1345
|
-
|
1776
|
+
// In a call to eval, we first call %ResolvePossiblyDirectEval to
|
1777
|
+
// resolve the function we need to call and the receiver of the
|
1778
|
+
// call. Then we call the resolved function using the given
|
1779
|
+
// arguments.
|
1780
|
+
VisitForValue(fun, kStack);
|
1781
|
+
__ push(Immediate(Factory::undefined_value())); // Reserved receiver slot.
|
1782
|
+
|
1783
|
+
// Push the arguments.
|
1784
|
+
ZoneList<Expression*>* args = expr->arguments();
|
1785
|
+
int arg_count = args->length();
|
1786
|
+
for (int i = 0; i < arg_count; i++) {
|
1787
|
+
VisitForValue(args->at(i), kStack);
|
1788
|
+
}
|
1789
|
+
|
1790
|
+
// Push copy of the function - found below the arguments.
|
1791
|
+
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
|
1792
|
+
|
1793
|
+
// Push copy of the first argument or undefined if it doesn't exist.
|
1794
|
+
if (arg_count > 0) {
|
1795
|
+
__ push(Operand(esp, arg_count * kPointerSize));
|
1796
|
+
} else {
|
1797
|
+
__ push(Immediate(Factory::undefined_value()));
|
1798
|
+
}
|
1799
|
+
|
1800
|
+
// Push the receiver of the enclosing function and do runtime call.
|
1801
|
+
__ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
|
1802
|
+
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
|
1803
|
+
|
1804
|
+
// The runtime call returns a pair of values in eax (function) and
|
1805
|
+
// edx (receiver). Touch up the stack with the right values.
|
1806
|
+
__ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
|
1807
|
+
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
|
1808
|
+
|
1809
|
+
// Record source position for debugger.
|
1810
|
+
SetSourcePosition(expr->position());
|
1811
|
+
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
|
1812
|
+
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
|
1813
|
+
__ CallStub(&stub);
|
1814
|
+
// Restore context register.
|
1815
|
+
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
1816
|
+
DropAndApply(1, context_, eax);
|
1346
1817
|
} else if (var != NULL && !var->is_this() && var->is_global()) {
|
1347
1818
|
// Push global object as receiver for the call IC.
|
1348
1819
|
__ push(CodeGenerator::GlobalObject());
|
1349
1820
|
EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
|
1350
1821
|
} else if (var != NULL && var->slot() != NULL &&
|
1351
1822
|
var->slot()->type() == Slot::LOOKUP) {
|
1352
|
-
// Call to a lookup slot.
|
1353
|
-
|
1823
|
+
// Call to a lookup slot (dynamically introduced variable). Call the
|
1824
|
+
// runtime to find the function to call (returned in eax) and the object
|
1825
|
+
// holding it (returned in edx).
|
1826
|
+
__ push(context_register());
|
1827
|
+
__ push(Immediate(var->name()));
|
1828
|
+
__ CallRuntime(Runtime::kLoadContextSlot, 2);
|
1829
|
+
__ push(eax); // Function.
|
1830
|
+
__ push(edx); // Receiver.
|
1831
|
+
EmitCallWithStub(expr);
|
1354
1832
|
} else if (fun->AsProperty() != NULL) {
|
1355
1833
|
// Call to an object property.
|
1356
1834
|
Property* prop = fun->AsProperty();
|
@@ -1360,37 +1838,31 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
|
1360
1838
|
VisitForValue(prop->obj(), kStack);
|
1361
1839
|
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
|
1362
1840
|
} else {
|
1363
|
-
// Call to a keyed property
|
1364
|
-
// call
|
1841
|
+
// Call to a keyed property.
|
1842
|
+
// For a synthetic property use keyed load IC followed by function call,
|
1843
|
+
// for a regular property use keyed CallIC.
|
1365
1844
|
VisitForValue(prop->obj(), kStack);
|
1366
|
-
VisitForValue(prop->key(), kAccumulator);
|
1367
|
-
// Record source code position for IC call.
|
1368
|
-
SetSourcePosition(prop->position());
|
1369
1845
|
if (prop->is_synthetic()) {
|
1846
|
+
VisitForValue(prop->key(), kAccumulator);
|
1847
|
+
// Record source code position for IC call.
|
1848
|
+
SetSourcePosition(prop->position());
|
1370
1849
|
__ pop(edx); // We do not need to keep the receiver.
|
1371
|
-
} else {
|
1372
|
-
__ mov(edx, Operand(esp, 0)); // Keep receiver, to call function on.
|
1373
|
-
}
|
1374
1850
|
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1851
|
+
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
1852
|
+
__ call(ic, RelocInfo::CODE_TARGET);
|
1853
|
+
// By emitting a nop we make sure that we do not have a "test eax,..."
|
1854
|
+
// instruction after the call as it is treated specially
|
1855
|
+
// by the LoadIC code.
|
1856
|
+
__ nop();
|
1381
1857
|
// Push result (function).
|
1382
1858
|
__ push(eax);
|
1383
1859
|
// Push Global receiver.
|
1384
1860
|
__ mov(ecx, CodeGenerator::GlobalObject());
|
1385
1861
|
__ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
|
1862
|
+
EmitCallWithStub(expr);
|
1386
1863
|
} else {
|
1387
|
-
|
1388
|
-
__ pop(ebx);
|
1389
|
-
// Push result (function).
|
1390
|
-
__ push(eax);
|
1391
|
-
__ push(ebx);
|
1864
|
+
EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
|
1392
1865
|
}
|
1393
|
-
EmitCallWithStub(expr);
|
1394
1866
|
}
|
1395
1867
|
} else {
|
1396
1868
|
// Call to some other expression. If the expression is an anonymous
|
@@ -1447,55 +1919,833 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|
1447
1919
|
}
|
1448
1920
|
|
1449
1921
|
|
1450
|
-
void FullCodeGenerator::
|
1451
|
-
|
1452
|
-
ZoneList<Expression*>* args = expr->arguments();
|
1922
|
+
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
1923
|
+
ASSERT(args->length() == 1);
|
1453
1924
|
|
1454
|
-
|
1455
|
-
// Prepare for calling JS runtime function.
|
1456
|
-
__ mov(eax, CodeGenerator::GlobalObject());
|
1457
|
-
__ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
|
1458
|
-
}
|
1925
|
+
VisitForValue(args->at(0), kAccumulator);
|
1459
1926
|
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
}
|
1927
|
+
Label materialize_true, materialize_false;
|
1928
|
+
Label* if_true = NULL;
|
1929
|
+
Label* if_false = NULL;
|
1930
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1465
1931
|
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
__ call(ic, RelocInfo::CODE_TARGET);
|
1472
|
-
// Restore context register.
|
1473
|
-
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
1474
|
-
} else {
|
1475
|
-
// Call the C runtime function.
|
1476
|
-
__ CallRuntime(expr->function(), arg_count);
|
1477
|
-
}
|
1478
|
-
Apply(context_, eax);
|
1932
|
+
__ test(eax, Immediate(kSmiTagMask));
|
1933
|
+
__ j(zero, if_true);
|
1934
|
+
__ jmp(if_false);
|
1935
|
+
|
1936
|
+
Apply(context_, if_true, if_false);
|
1479
1937
|
}
|
1480
1938
|
|
1481
1939
|
|
1482
|
-
void FullCodeGenerator::
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1940
|
+
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
1941
|
+
ASSERT(args->length() == 1);
|
1942
|
+
|
1943
|
+
VisitForValue(args->at(0), kAccumulator);
|
1944
|
+
|
1945
|
+
Label materialize_true, materialize_false;
|
1946
|
+
Label* if_true = NULL;
|
1947
|
+
Label* if_false = NULL;
|
1948
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1949
|
+
|
1950
|
+
__ test(eax, Immediate(kSmiTagMask | 0x80000000));
|
1951
|
+
__ j(zero, if_true);
|
1952
|
+
__ jmp(if_false);
|
1953
|
+
|
1954
|
+
Apply(context_, if_true, if_false);
|
1955
|
+
}
|
1956
|
+
|
1957
|
+
|
1958
|
+
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
1959
|
+
ASSERT(args->length() == 1);
|
1960
|
+
|
1961
|
+
VisitForValue(args->at(0), kAccumulator);
|
1962
|
+
|
1963
|
+
Label materialize_true, materialize_false;
|
1964
|
+
Label* if_true = NULL;
|
1965
|
+
Label* if_false = NULL;
|
1966
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1967
|
+
|
1968
|
+
__ test(eax, Immediate(kSmiTagMask));
|
1969
|
+
__ j(zero, if_false);
|
1970
|
+
__ cmp(eax, Factory::null_value());
|
1971
|
+
__ j(equal, if_true);
|
1972
|
+
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
1973
|
+
// Undetectable objects behave like undefined when tested with typeof.
|
1974
|
+
__ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
|
1975
|
+
__ test(ecx, Immediate(1 << Map::kIsUndetectable));
|
1976
|
+
__ j(not_zero, if_false);
|
1977
|
+
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
1978
|
+
__ cmp(ecx, FIRST_JS_OBJECT_TYPE);
|
1979
|
+
__ j(below, if_false);
|
1980
|
+
__ cmp(ecx, LAST_JS_OBJECT_TYPE);
|
1981
|
+
__ j(below_equal, if_true);
|
1982
|
+
__ jmp(if_false);
|
1983
|
+
|
1984
|
+
Apply(context_, if_true, if_false);
|
1985
|
+
}
|
1986
|
+
|
1987
|
+
|
1988
|
+
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
1989
|
+
ASSERT(args->length() == 1);
|
1990
|
+
|
1991
|
+
VisitForValue(args->at(0), kAccumulator);
|
1992
|
+
|
1993
|
+
Label materialize_true, materialize_false;
|
1994
|
+
Label* if_true = NULL;
|
1995
|
+
Label* if_false = NULL;
|
1996
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1997
|
+
|
1998
|
+
__ test(eax, Immediate(kSmiTagMask));
|
1999
|
+
__ j(equal, if_false);
|
2000
|
+
__ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx);
|
2001
|
+
__ j(above_equal, if_true);
|
2002
|
+
__ jmp(if_false);
|
2003
|
+
|
2004
|
+
Apply(context_, if_true, if_false);
|
2005
|
+
}
|
2006
|
+
|
2007
|
+
|
2008
|
+
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
2009
|
+
ASSERT(args->length() == 1);
|
2010
|
+
|
2011
|
+
VisitForValue(args->at(0), kAccumulator);
|
2012
|
+
|
2013
|
+
Label materialize_true, materialize_false;
|
2014
|
+
Label* if_true = NULL;
|
2015
|
+
Label* if_false = NULL;
|
2016
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2017
|
+
|
2018
|
+
__ test(eax, Immediate(kSmiTagMask));
|
2019
|
+
__ j(zero, if_false);
|
2020
|
+
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
2021
|
+
__ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
|
2022
|
+
__ test(ebx, Immediate(1 << Map::kIsUndetectable));
|
2023
|
+
__ j(not_zero, if_true);
|
2024
|
+
__ jmp(if_false);
|
2025
|
+
|
2026
|
+
Apply(context_, if_true, if_false);
|
2027
|
+
}
|
2028
|
+
|
2029
|
+
|
2030
|
+
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
2031
|
+
ASSERT(args->length() == 1);
|
2032
|
+
|
2033
|
+
VisitForValue(args->at(0), kAccumulator);
|
2034
|
+
|
2035
|
+
Label materialize_true, materialize_false;
|
2036
|
+
Label* if_true = NULL;
|
2037
|
+
Label* if_false = NULL;
|
2038
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2039
|
+
|
2040
|
+
__ test(eax, Immediate(kSmiTagMask));
|
2041
|
+
__ j(zero, if_false);
|
2042
|
+
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
|
2043
|
+
__ j(equal, if_true);
|
2044
|
+
__ jmp(if_false);
|
2045
|
+
|
2046
|
+
Apply(context_, if_true, if_false);
|
2047
|
+
}
|
2048
|
+
|
2049
|
+
|
2050
|
+
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
2051
|
+
ASSERT(args->length() == 1);
|
2052
|
+
|
2053
|
+
VisitForValue(args->at(0), kAccumulator);
|
2054
|
+
|
2055
|
+
Label materialize_true, materialize_false;
|
2056
|
+
Label* if_true = NULL;
|
2057
|
+
Label* if_false = NULL;
|
2058
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2059
|
+
|
2060
|
+
__ test(eax, Immediate(kSmiTagMask));
|
2061
|
+
__ j(equal, if_false);
|
2062
|
+
__ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
|
2063
|
+
__ j(equal, if_true);
|
2064
|
+
__ jmp(if_false);
|
2065
|
+
|
2066
|
+
Apply(context_, if_true, if_false);
|
2067
|
+
}
|
2068
|
+
|
2069
|
+
|
2070
|
+
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
2071
|
+
ASSERT(args->length() == 1);
|
2072
|
+
|
2073
|
+
VisitForValue(args->at(0), kAccumulator);
|
2074
|
+
|
2075
|
+
Label materialize_true, materialize_false;
|
2076
|
+
Label* if_true = NULL;
|
2077
|
+
Label* if_false = NULL;
|
2078
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2079
|
+
|
2080
|
+
__ test(eax, Immediate(kSmiTagMask));
|
2081
|
+
__ j(equal, if_false);
|
2082
|
+
__ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
|
2083
|
+
__ j(equal, if_true);
|
2084
|
+
__ jmp(if_false);
|
2085
|
+
|
2086
|
+
Apply(context_, if_true, if_false);
|
2087
|
+
}
|
2088
|
+
|
2089
|
+
|
2090
|
+
|
2091
|
+
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
2092
|
+
ASSERT(args->length() == 0);
|
2093
|
+
|
2094
|
+
Label materialize_true, materialize_false;
|
2095
|
+
Label* if_true = NULL;
|
2096
|
+
Label* if_false = NULL;
|
2097
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2098
|
+
|
2099
|
+
// Get the frame pointer for the calling frame.
|
2100
|
+
__ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
2101
|
+
|
2102
|
+
// Skip the arguments adaptor frame if it exists.
|
2103
|
+
Label check_frame_marker;
|
2104
|
+
__ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
|
2105
|
+
Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
2106
|
+
__ j(not_equal, &check_frame_marker);
|
2107
|
+
__ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
|
2108
|
+
|
2109
|
+
// Check the marker in the calling frame.
|
2110
|
+
__ bind(&check_frame_marker);
|
2111
|
+
__ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
|
2112
|
+
Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
|
2113
|
+
__ j(equal, if_true);
|
2114
|
+
__ jmp(if_false);
|
2115
|
+
|
2116
|
+
Apply(context_, if_true, if_false);
|
2117
|
+
}
|
2118
|
+
|
2119
|
+
|
2120
|
+
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
2121
|
+
ASSERT(args->length() == 2);
|
2122
|
+
|
2123
|
+
// Load the two objects into registers and perform the comparison.
|
2124
|
+
VisitForValue(args->at(0), kStack);
|
2125
|
+
VisitForValue(args->at(1), kAccumulator);
|
2126
|
+
|
2127
|
+
Label materialize_true, materialize_false;
|
2128
|
+
Label* if_true = NULL;
|
2129
|
+
Label* if_false = NULL;
|
2130
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2131
|
+
|
2132
|
+
__ pop(ebx);
|
2133
|
+
__ cmp(eax, Operand(ebx));
|
2134
|
+
__ j(equal, if_true);
|
2135
|
+
__ jmp(if_false);
|
2136
|
+
|
2137
|
+
Apply(context_, if_true, if_false);
|
2138
|
+
}
|
2139
|
+
|
2140
|
+
|
2141
|
+
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
2142
|
+
ASSERT(args->length() == 1);
|
2143
|
+
|
2144
|
+
// ArgumentsAccessStub expects the key in edx and the formal
|
2145
|
+
// parameter count in eax.
|
2146
|
+
VisitForValue(args->at(0), kAccumulator);
|
2147
|
+
__ mov(edx, eax);
|
2148
|
+
__ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
|
2149
|
+
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
|
2150
|
+
__ CallStub(&stub);
|
2151
|
+
Apply(context_, eax);
|
2152
|
+
}
|
2153
|
+
|
2154
|
+
|
2155
|
+
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
2156
|
+
ASSERT(args->length() == 0);
|
2157
|
+
|
2158
|
+
Label exit;
|
2159
|
+
// Get the number of formal parameters.
|
2160
|
+
__ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
|
2161
|
+
|
2162
|
+
// Check if the calling frame is an arguments adaptor frame.
|
2163
|
+
__ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
2164
|
+
__ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
|
2165
|
+
Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
2166
|
+
__ j(not_equal, &exit);
|
2167
|
+
|
2168
|
+
// Arguments adaptor case: Read the arguments length from the
|
2169
|
+
// adaptor frame.
|
2170
|
+
__ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
2171
|
+
|
2172
|
+
__ bind(&exit);
|
2173
|
+
if (FLAG_debug_code) __ AbortIfNotSmi(eax);
|
2174
|
+
Apply(context_, eax);
|
2175
|
+
}
|
2176
|
+
|
2177
|
+
|
2178
|
+
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
2179
|
+
ASSERT(args->length() == 1);
|
2180
|
+
Label done, null, function, non_function_constructor;
|
2181
|
+
|
2182
|
+
VisitForValue(args->at(0), kAccumulator);
|
2183
|
+
|
2184
|
+
// If the object is a smi, we return null.
|
2185
|
+
__ test(eax, Immediate(kSmiTagMask));
|
2186
|
+
__ j(zero, &null);
|
2187
|
+
|
2188
|
+
// Check that the object is a JS object but take special care of JS
|
2189
|
+
// functions to make sure they have 'Function' as their class.
|
2190
|
+
__ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, eax); // Map is now in eax.
|
2191
|
+
__ j(below, &null);
|
2192
|
+
|
2193
|
+
// As long as JS_FUNCTION_TYPE is the last instance type and it is
|
2194
|
+
// right after LAST_JS_OBJECT_TYPE, we can avoid checking for
|
2195
|
+
// LAST_JS_OBJECT_TYPE.
|
2196
|
+
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
2197
|
+
ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
|
2198
|
+
__ CmpInstanceType(eax, JS_FUNCTION_TYPE);
|
2199
|
+
__ j(equal, &function);
|
2200
|
+
|
2201
|
+
// Check if the constructor in the map is a function.
|
2202
|
+
__ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
|
2203
|
+
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
|
2204
|
+
__ j(not_equal, &non_function_constructor);
|
2205
|
+
|
2206
|
+
// eax now contains the constructor function. Grab the
|
2207
|
+
// instance class name from there.
|
2208
|
+
__ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
|
2209
|
+
__ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
|
2210
|
+
__ jmp(&done);
|
2211
|
+
|
2212
|
+
// Functions have class 'Function'.
|
2213
|
+
__ bind(&function);
|
2214
|
+
__ mov(eax, Factory::function_class_symbol());
|
2215
|
+
__ jmp(&done);
|
2216
|
+
|
2217
|
+
// Objects with a non-function constructor have class 'Object'.
|
2218
|
+
__ bind(&non_function_constructor);
|
2219
|
+
__ mov(eax, Factory::Object_symbol());
|
2220
|
+
__ jmp(&done);
|
2221
|
+
|
2222
|
+
// Non-JS objects have class null.
|
2223
|
+
__ bind(&null);
|
2224
|
+
__ mov(eax, Factory::null_value());
|
2225
|
+
|
2226
|
+
// All done.
|
2227
|
+
__ bind(&done);
|
2228
|
+
|
2229
|
+
Apply(context_, eax);
|
2230
|
+
}
|
2231
|
+
|
2232
|
+
|
2233
|
+
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
2234
|
+
// Conditionally generate a log call.
|
2235
|
+
// Args:
|
2236
|
+
// 0 (literal string): The type of logging (corresponds to the flags).
|
2237
|
+
// This is used to determine whether or not to generate the log call.
|
2238
|
+
// 1 (string): Format string. Access the string at argument index 2
|
2239
|
+
// with '%2s' (see Logger::LogRuntime for all the formats).
|
2240
|
+
// 2 (array): Arguments to the format string.
|
2241
|
+
ASSERT_EQ(args->length(), 3);
|
2242
|
+
#ifdef ENABLE_LOGGING_AND_PROFILING
|
2243
|
+
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
2244
|
+
VisitForValue(args->at(1), kStack);
|
2245
|
+
VisitForValue(args->at(2), kStack);
|
2246
|
+
__ CallRuntime(Runtime::kLog, 2);
|
2247
|
+
}
|
2248
|
+
#endif
|
2249
|
+
// Finally, we're expected to leave a value on the top of the stack.
|
2250
|
+
__ mov(eax, Factory::undefined_value());
|
2251
|
+
Apply(context_, eax);
|
2252
|
+
}
|
2253
|
+
|
2254
|
+
|
2255
|
+
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
2256
|
+
ASSERT(args->length() == 0);
|
2257
|
+
|
2258
|
+
Label slow_allocate_heapnumber;
|
2259
|
+
Label heapnumber_allocated;
|
2260
|
+
|
2261
|
+
__ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber);
|
2262
|
+
__ jmp(&heapnumber_allocated);
|
2263
|
+
|
2264
|
+
__ bind(&slow_allocate_heapnumber);
|
2265
|
+
// Allocate a heap number.
|
2266
|
+
__ CallRuntime(Runtime::kNumberAlloc, 0);
|
2267
|
+
__ mov(edi, eax);
|
2268
|
+
|
2269
|
+
__ bind(&heapnumber_allocated);
|
2270
|
+
|
2271
|
+
__ PrepareCallCFunction(0, ebx);
|
2272
|
+
__ CallCFunction(ExternalReference::random_uint32_function(), 0);
|
2273
|
+
|
2274
|
+
// Convert 32 random bits in eax to 0.(32 random bits) in a double
|
2275
|
+
// by computing:
|
2276
|
+
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
|
2277
|
+
// This is implemented on both SSE2 and FPU.
|
2278
|
+
if (CpuFeatures::IsSupported(SSE2)) {
|
2279
|
+
CpuFeatures::Scope fscope(SSE2);
|
2280
|
+
__ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
|
2281
|
+
__ movd(xmm1, Operand(ebx));
|
2282
|
+
__ movd(xmm0, Operand(eax));
|
2283
|
+
__ cvtss2sd(xmm1, xmm1);
|
2284
|
+
__ pxor(xmm0, xmm1);
|
2285
|
+
__ subsd(xmm0, xmm1);
|
2286
|
+
__ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
|
2287
|
+
} else {
|
2288
|
+
// 0x4130000000000000 is 1.0 x 2^20 as a double.
|
2289
|
+
__ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
|
2290
|
+
Immediate(0x41300000));
|
2291
|
+
__ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
|
2292
|
+
__ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
|
2293
|
+
__ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
|
2294
|
+
__ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
|
2295
|
+
__ fsubp(1);
|
2296
|
+
__ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
|
2297
|
+
}
|
2298
|
+
__ mov(eax, edi);
|
2299
|
+
Apply(context_, eax);
|
2300
|
+
}
|
2301
|
+
|
2302
|
+
|
2303
|
+
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
2304
|
+
// Load the arguments on the stack and call the stub.
|
2305
|
+
SubStringStub stub;
|
2306
|
+
ASSERT(args->length() == 3);
|
2307
|
+
VisitForValue(args->at(0), kStack);
|
2308
|
+
VisitForValue(args->at(1), kStack);
|
2309
|
+
VisitForValue(args->at(2), kStack);
|
2310
|
+
__ CallStub(&stub);
|
2311
|
+
Apply(context_, eax);
|
2312
|
+
}
|
2313
|
+
|
2314
|
+
|
2315
|
+
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
2316
|
+
// Load the arguments on the stack and call the stub.
|
2317
|
+
RegExpExecStub stub;
|
2318
|
+
ASSERT(args->length() == 4);
|
2319
|
+
VisitForValue(args->at(0), kStack);
|
2320
|
+
VisitForValue(args->at(1), kStack);
|
2321
|
+
VisitForValue(args->at(2), kStack);
|
2322
|
+
VisitForValue(args->at(3), kStack);
|
2323
|
+
__ CallStub(&stub);
|
2324
|
+
Apply(context_, eax);
|
2325
|
+
}
|
2326
|
+
|
2327
|
+
|
2328
|
+
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
2329
|
+
ASSERT(args->length() == 1);
|
2330
|
+
|
2331
|
+
VisitForValue(args->at(0), kAccumulator); // Load the object.
|
2332
|
+
|
2333
|
+
Label done;
|
2334
|
+
// If the object is a smi return the object.
|
2335
|
+
__ test(eax, Immediate(kSmiTagMask));
|
2336
|
+
__ j(zero, &done);
|
2337
|
+
// If the object is not a value type, return the object.
|
2338
|
+
__ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
|
2339
|
+
__ j(not_equal, &done);
|
2340
|
+
__ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
|
2341
|
+
|
2342
|
+
__ bind(&done);
|
2343
|
+
Apply(context_, eax);
|
2344
|
+
}
|
2345
|
+
|
2346
|
+
|
2347
|
+
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
2348
|
+
// Load the arguments on the stack and call the runtime function.
|
2349
|
+
ASSERT(args->length() == 2);
|
2350
|
+
VisitForValue(args->at(0), kStack);
|
2351
|
+
VisitForValue(args->at(1), kStack);
|
2352
|
+
__ CallRuntime(Runtime::kMath_pow, 2);
|
2353
|
+
Apply(context_, eax);
|
2354
|
+
}
|
2355
|
+
|
2356
|
+
|
2357
|
+
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
2358
|
+
ASSERT(args->length() == 2);
|
2359
|
+
|
2360
|
+
VisitForValue(args->at(0), kStack); // Load the object.
|
2361
|
+
VisitForValue(args->at(1), kAccumulator); // Load the value.
|
2362
|
+
__ pop(ebx); // eax = value. ebx = object.
|
2363
|
+
|
2364
|
+
Label done;
|
2365
|
+
// If the object is a smi, return the value.
|
2366
|
+
__ test(ebx, Immediate(kSmiTagMask));
|
2367
|
+
__ j(zero, &done);
|
2368
|
+
|
2369
|
+
// If the object is not a value type, return the value.
|
2370
|
+
__ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
|
2371
|
+
__ j(not_equal, &done);
|
2372
|
+
|
2373
|
+
// Store the value.
|
2374
|
+
__ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
|
2375
|
+
// Update the write barrier. Save the value as it will be
|
2376
|
+
// overwritten by the write barrier code and is needed afterward.
|
2377
|
+
__ mov(edx, eax);
|
2378
|
+
__ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx);
|
2379
|
+
|
2380
|
+
__ bind(&done);
|
2381
|
+
Apply(context_, eax);
|
2382
|
+
}
|
2383
|
+
|
2384
|
+
|
2385
|
+
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
2386
|
+
ASSERT_EQ(args->length(), 1);
|
2387
|
+
|
2388
|
+
// Load the argument on the stack and call the stub.
|
2389
|
+
VisitForValue(args->at(0), kStack);
|
2390
|
+
|
2391
|
+
NumberToStringStub stub;
|
2392
|
+
__ CallStub(&stub);
|
2393
|
+
Apply(context_, eax);
|
2394
|
+
}
|
2395
|
+
|
2396
|
+
|
2397
|
+
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
2398
|
+
ASSERT(args->length() == 1);
|
2399
|
+
|
2400
|
+
VisitForValue(args->at(0), kAccumulator);
|
2401
|
+
|
2402
|
+
Label done;
|
2403
|
+
StringCharFromCodeGenerator generator(eax, ebx);
|
2404
|
+
generator.GenerateFast(masm_);
|
2405
|
+
__ jmp(&done);
|
2406
|
+
|
2407
|
+
NopRuntimeCallHelper call_helper;
|
2408
|
+
generator.GenerateSlow(masm_, call_helper);
|
2409
|
+
|
2410
|
+
__ bind(&done);
|
2411
|
+
Apply(context_, ebx);
|
2412
|
+
}
|
2413
|
+
|
2414
|
+
|
2415
|
+
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
2416
|
+
ASSERT(args->length() == 2);
|
2417
|
+
|
2418
|
+
VisitForValue(args->at(0), kStack);
|
2419
|
+
VisitForValue(args->at(1), kAccumulator);
|
2420
|
+
|
2421
|
+
Register object = ebx;
|
2422
|
+
Register index = eax;
|
2423
|
+
Register scratch = ecx;
|
2424
|
+
Register result = edx;
|
2425
|
+
|
2426
|
+
__ pop(object);
|
2427
|
+
|
2428
|
+
Label need_conversion;
|
2429
|
+
Label index_out_of_range;
|
2430
|
+
Label done;
|
2431
|
+
StringCharCodeAtGenerator generator(object,
|
2432
|
+
index,
|
2433
|
+
scratch,
|
2434
|
+
result,
|
2435
|
+
&need_conversion,
|
2436
|
+
&need_conversion,
|
2437
|
+
&index_out_of_range,
|
2438
|
+
STRING_INDEX_IS_NUMBER);
|
2439
|
+
generator.GenerateFast(masm_);
|
2440
|
+
__ jmp(&done);
|
2441
|
+
|
2442
|
+
__ bind(&index_out_of_range);
|
2443
|
+
// When the index is out of range, the spec requires us to return
|
2444
|
+
// NaN.
|
2445
|
+
__ Set(result, Immediate(Factory::nan_value()));
|
2446
|
+
__ jmp(&done);
|
2447
|
+
|
2448
|
+
__ bind(&need_conversion);
|
2449
|
+
// Move the undefined value into the result register, which will
|
2450
|
+
// trigger conversion.
|
2451
|
+
__ Set(result, Immediate(Factory::undefined_value()));
|
2452
|
+
__ jmp(&done);
|
2453
|
+
|
2454
|
+
NopRuntimeCallHelper call_helper;
|
2455
|
+
generator.GenerateSlow(masm_, call_helper);
|
2456
|
+
|
2457
|
+
__ bind(&done);
|
2458
|
+
Apply(context_, result);
|
2459
|
+
}
|
2460
|
+
|
2461
|
+
|
2462
|
+
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
2463
|
+
ASSERT(args->length() == 2);
|
2464
|
+
|
2465
|
+
VisitForValue(args->at(0), kStack);
|
2466
|
+
VisitForValue(args->at(1), kAccumulator);
|
2467
|
+
|
2468
|
+
Register object = ebx;
|
2469
|
+
Register index = eax;
|
2470
|
+
Register scratch1 = ecx;
|
2471
|
+
Register scratch2 = edx;
|
2472
|
+
Register result = eax;
|
2473
|
+
|
2474
|
+
__ pop(object);
|
2475
|
+
|
2476
|
+
Label need_conversion;
|
2477
|
+
Label index_out_of_range;
|
2478
|
+
Label done;
|
2479
|
+
StringCharAtGenerator generator(object,
|
2480
|
+
index,
|
2481
|
+
scratch1,
|
2482
|
+
scratch2,
|
2483
|
+
result,
|
2484
|
+
&need_conversion,
|
2485
|
+
&need_conversion,
|
2486
|
+
&index_out_of_range,
|
2487
|
+
STRING_INDEX_IS_NUMBER);
|
2488
|
+
generator.GenerateFast(masm_);
|
2489
|
+
__ jmp(&done);
|
2490
|
+
|
2491
|
+
__ bind(&index_out_of_range);
|
2492
|
+
// When the index is out of range, the spec requires us to return
|
2493
|
+
// the empty string.
|
2494
|
+
__ Set(result, Immediate(Factory::empty_string()));
|
2495
|
+
__ jmp(&done);
|
2496
|
+
|
2497
|
+
__ bind(&need_conversion);
|
2498
|
+
// Move smi zero into the result register, which will trigger
|
2499
|
+
// conversion.
|
2500
|
+
__ Set(result, Immediate(Smi::FromInt(0)));
|
2501
|
+
__ jmp(&done);
|
2502
|
+
|
2503
|
+
NopRuntimeCallHelper call_helper;
|
2504
|
+
generator.GenerateSlow(masm_, call_helper);
|
2505
|
+
|
2506
|
+
__ bind(&done);
|
2507
|
+
Apply(context_, result);
|
2508
|
+
}
|
2509
|
+
|
2510
|
+
|
2511
|
+
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
2512
|
+
ASSERT_EQ(2, args->length());
|
2513
|
+
|
2514
|
+
VisitForValue(args->at(0), kStack);
|
2515
|
+
VisitForValue(args->at(1), kStack);
|
2516
|
+
|
2517
|
+
StringAddStub stub(NO_STRING_ADD_FLAGS);
|
2518
|
+
__ CallStub(&stub);
|
2519
|
+
Apply(context_, eax);
|
2520
|
+
}
|
2521
|
+
|
2522
|
+
|
2523
|
+
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
2524
|
+
ASSERT_EQ(2, args->length());
|
2525
|
+
|
2526
|
+
VisitForValue(args->at(0), kStack);
|
2527
|
+
VisitForValue(args->at(1), kStack);
|
2528
|
+
|
2529
|
+
StringCompareStub stub;
|
2530
|
+
__ CallStub(&stub);
|
2531
|
+
Apply(context_, eax);
|
2532
|
+
}
|
2533
|
+
|
2534
|
+
|
2535
|
+
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
2536
|
+
// Load the argument on the stack and call the stub.
|
2537
|
+
TranscendentalCacheStub stub(TranscendentalCache::SIN);
|
2538
|
+
ASSERT(args->length() == 1);
|
2539
|
+
VisitForValue(args->at(0), kStack);
|
2540
|
+
__ CallStub(&stub);
|
2541
|
+
Apply(context_, eax);
|
2542
|
+
}
|
2543
|
+
|
2544
|
+
|
2545
|
+
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
2546
|
+
// Load the argument on the stack and call the stub.
|
2547
|
+
TranscendentalCacheStub stub(TranscendentalCache::COS);
|
2548
|
+
ASSERT(args->length() == 1);
|
2549
|
+
VisitForValue(args->at(0), kStack);
|
2550
|
+
__ CallStub(&stub);
|
2551
|
+
Apply(context_, eax);
|
2552
|
+
}
|
2553
|
+
|
2554
|
+
|
2555
|
+
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
2556
|
+
// Load the argument on the stack and call the runtime function.
|
2557
|
+
ASSERT(args->length() == 1);
|
2558
|
+
VisitForValue(args->at(0), kStack);
|
2559
|
+
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
2560
|
+
Apply(context_, eax);
|
2561
|
+
}
|
2562
|
+
|
2563
|
+
|
2564
|
+
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
2565
|
+
ASSERT(args->length() >= 2);
|
2566
|
+
|
2567
|
+
int arg_count = args->length() - 2; // For receiver and function.
|
2568
|
+
VisitForValue(args->at(0), kStack); // Receiver.
|
2569
|
+
for (int i = 0; i < arg_count; i++) {
|
2570
|
+
VisitForValue(args->at(i + 1), kStack);
|
2571
|
+
}
|
2572
|
+
VisitForValue(args->at(arg_count + 1), kAccumulator); // Function.
|
2573
|
+
|
2574
|
+
// InvokeFunction requires function in edi. Move it in there.
|
2575
|
+
if (!result_register().is(edi)) __ mov(edi, result_register());
|
2576
|
+
ParameterCount count(arg_count);
|
2577
|
+
__ InvokeFunction(edi, count, CALL_FUNCTION);
|
2578
|
+
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
2579
|
+
Apply(context_, eax);
|
2580
|
+
}
|
2581
|
+
|
2582
|
+
|
2583
|
+
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
2584
|
+
ASSERT(args->length() == 3);
|
2585
|
+
VisitForValue(args->at(0), kStack);
|
2586
|
+
VisitForValue(args->at(1), kStack);
|
2587
|
+
VisitForValue(args->at(2), kStack);
|
2588
|
+
__ CallRuntime(Runtime::kRegExpConstructResult, 3);
|
2589
|
+
Apply(context_, eax);
|
2590
|
+
}
|
2591
|
+
|
2592
|
+
|
2593
|
+
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
2594
|
+
ASSERT(args->length() == 3);
|
2595
|
+
VisitForValue(args->at(0), kStack);
|
2596
|
+
VisitForValue(args->at(1), kStack);
|
2597
|
+
VisitForValue(args->at(2), kStack);
|
2598
|
+
__ CallRuntime(Runtime::kSwapElements, 3);
|
2599
|
+
Apply(context_, eax);
|
2600
|
+
}
|
2601
|
+
|
2602
|
+
|
2603
|
+
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
2604
|
+
ASSERT_EQ(2, args->length());
|
2605
|
+
|
2606
|
+
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
2607
|
+
int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
|
2608
|
+
|
2609
|
+
Handle<FixedArray> jsfunction_result_caches(
|
2610
|
+
Top::global_context()->jsfunction_result_caches());
|
2611
|
+
if (jsfunction_result_caches->length() <= cache_id) {
|
2612
|
+
__ Abort("Attempt to use undefined cache.");
|
2613
|
+
__ mov(eax, Factory::undefined_value());
|
2614
|
+
Apply(context_, eax);
|
2615
|
+
return;
|
2616
|
+
}
|
2617
|
+
|
2618
|
+
VisitForValue(args->at(1), kAccumulator);
|
2619
|
+
|
2620
|
+
Register key = eax;
|
2621
|
+
Register cache = ebx;
|
2622
|
+
Register tmp = ecx;
|
2623
|
+
__ mov(cache, CodeGenerator::ContextOperand(esi, Context::GLOBAL_INDEX));
|
2624
|
+
__ mov(cache,
|
2625
|
+
FieldOperand(cache, GlobalObject::kGlobalContextOffset));
|
2626
|
+
__ mov(cache,
|
2627
|
+
CodeGenerator::ContextOperand(
|
2628
|
+
cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
|
2629
|
+
__ mov(cache,
|
2630
|
+
FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
|
2631
|
+
|
2632
|
+
Label done, not_found;
|
2633
|
+
// tmp now holds finger offset as a smi.
|
2634
|
+
ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
2635
|
+
__ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
|
2636
|
+
__ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
|
2637
|
+
__ j(not_equal, ¬_found);
|
2638
|
+
|
2639
|
+
__ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1));
|
2640
|
+
__ jmp(&done);
|
2641
|
+
|
2642
|
+
__ bind(¬_found);
|
2643
|
+
// Call runtime to perform the lookup.
|
2644
|
+
__ push(cache);
|
2645
|
+
__ push(key);
|
2646
|
+
__ CallRuntime(Runtime::kGetFromCache, 2);
|
2647
|
+
|
2648
|
+
__ bind(&done);
|
2649
|
+
Apply(context_, eax);
|
2650
|
+
}
|
2651
|
+
|
2652
|
+
|
2653
|
+
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
2654
|
+
Handle<String> name = expr->name();
|
2655
|
+
if (name->length() > 0 && name->Get(0) == '_') {
|
2656
|
+
Comment cmnt(masm_, "[ InlineRuntimeCall");
|
2657
|
+
EmitInlineRuntimeCall(expr);
|
2658
|
+
return;
|
2659
|
+
}
|
2660
|
+
|
2661
|
+
Comment cmnt(masm_, "[ CallRuntime");
|
2662
|
+
ZoneList<Expression*>* args = expr->arguments();
|
2663
|
+
|
2664
|
+
if (expr->is_jsruntime()) {
|
2665
|
+
// Prepare for calling JS runtime function.
|
2666
|
+
__ mov(eax, CodeGenerator::GlobalObject());
|
2667
|
+
__ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
|
2668
|
+
}
|
2669
|
+
|
2670
|
+
// Push the arguments ("left-to-right").
|
2671
|
+
int arg_count = args->length();
|
2672
|
+
for (int i = 0; i < arg_count; i++) {
|
2673
|
+
VisitForValue(args->at(i), kStack);
|
2674
|
+
}
|
2675
|
+
|
2676
|
+
if (expr->is_jsruntime()) {
|
2677
|
+
// Call the JS runtime function via a call IC.
|
2678
|
+
__ Set(ecx, Immediate(expr->name()));
|
2679
|
+
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
|
2680
|
+
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
|
2681
|
+
__ call(ic, RelocInfo::CODE_TARGET);
|
2682
|
+
// Restore context register.
|
2683
|
+
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
2684
|
+
} else {
|
2685
|
+
// Call the C runtime function.
|
2686
|
+
__ CallRuntime(expr->function(), arg_count);
|
2687
|
+
}
|
2688
|
+
Apply(context_, eax);
|
2689
|
+
}
|
2690
|
+
|
2691
|
+
|
2692
|
+
void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
2693
|
+
switch (expr->op()) {
|
2694
|
+
case Token::DELETE: {
|
2695
|
+
Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
|
2696
|
+
Property* prop = expr->expression()->AsProperty();
|
2697
|
+
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
|
2698
|
+
if (prop == NULL && var == NULL) {
|
2699
|
+
// Result of deleting non-property, non-variable reference is true.
|
2700
|
+
// The subexpression may have side effects.
|
2701
|
+
VisitForEffect(expr->expression());
|
2702
|
+
Apply(context_, true);
|
2703
|
+
} else if (var != NULL &&
|
2704
|
+
!var->is_global() &&
|
2705
|
+
var->slot() != NULL &&
|
2706
|
+
var->slot()->type() != Slot::LOOKUP) {
|
2707
|
+
// Result of deleting non-global, non-dynamic variables is false.
|
2708
|
+
// The subexpression does not have side effects.
|
2709
|
+
Apply(context_, false);
|
2710
|
+
} else {
|
2711
|
+
// Property or variable reference. Call the delete builtin with
|
2712
|
+
// object and property name as arguments.
|
2713
|
+
if (prop != NULL) {
|
2714
|
+
VisitForValue(prop->obj(), kStack);
|
2715
|
+
VisitForValue(prop->key(), kStack);
|
2716
|
+
} else if (var->is_global()) {
|
2717
|
+
__ push(CodeGenerator::GlobalObject());
|
2718
|
+
__ push(Immediate(var->name()));
|
2719
|
+
} else {
|
2720
|
+
// Non-global variable. Call the runtime to look up the context
|
2721
|
+
// where the variable was introduced.
|
2722
|
+
__ push(context_register());
|
2723
|
+
__ push(Immediate(var->name()));
|
2724
|
+
__ CallRuntime(Runtime::kLookupContext, 2);
|
2725
|
+
__ push(eax);
|
2726
|
+
__ push(Immediate(var->name()));
|
2727
|
+
}
|
2728
|
+
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
|
2729
|
+
Apply(context_, eax);
|
2730
|
+
}
|
2731
|
+
break;
|
2732
|
+
}
|
2733
|
+
|
2734
|
+
case Token::VOID: {
|
2735
|
+
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
2736
|
+
VisitForEffect(expr->expression());
|
2737
|
+
switch (context_) {
|
2738
|
+
case Expression::kUninitialized:
|
2739
|
+
UNREACHABLE();
|
2740
|
+
break;
|
2741
|
+
case Expression::kEffect:
|
2742
|
+
break;
|
2743
|
+
case Expression::kValue:
|
2744
|
+
switch (location_) {
|
2745
|
+
case kAccumulator:
|
2746
|
+
__ mov(result_register(), Factory::undefined_value());
|
2747
|
+
break;
|
2748
|
+
case kStack:
|
1499
2749
|
__ push(Immediate(Factory::undefined_value()));
|
1500
2750
|
break;
|
1501
2751
|
}
|
@@ -1521,33 +2771,15 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1521
2771
|
|
1522
2772
|
case Token::NOT: {
|
1523
2773
|
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
|
1524
|
-
Label materialize_true, materialize_false
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
UNREACHABLE();
|
1532
|
-
break;
|
1533
|
-
case Expression::kEffect:
|
1534
|
-
if_true = &done;
|
1535
|
-
if_false = &done;
|
1536
|
-
break;
|
1537
|
-
case Expression::kValue:
|
1538
|
-
if_true = &materialize_false;
|
1539
|
-
if_false = &materialize_true;
|
1540
|
-
break;
|
1541
|
-
case Expression::kTest:
|
1542
|
-
break;
|
1543
|
-
case Expression::kValueTest:
|
1544
|
-
if_false = &materialize_true;
|
1545
|
-
break;
|
1546
|
-
case Expression::kTestValue:
|
1547
|
-
if_true = &materialize_false;
|
1548
|
-
break;
|
1549
|
-
}
|
2774
|
+
Label materialize_true, materialize_false;
|
2775
|
+
Label* if_true = NULL;
|
2776
|
+
Label* if_false = NULL;
|
2777
|
+
|
2778
|
+
// Notice that the labels are swapped.
|
2779
|
+
PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
|
2780
|
+
|
1550
2781
|
VisitForControl(expr->expression(), if_true, if_false);
|
2782
|
+
|
1551
2783
|
Apply(context_, if_false, if_true); // Labels swapped.
|
1552
2784
|
break;
|
1553
2785
|
}
|
@@ -1598,9 +2830,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1598
2830
|
|
1599
2831
|
case Token::SUB: {
|
1600
2832
|
Comment cmt(masm_, "[ UnaryOperation (SUB)");
|
1601
|
-
bool
|
2833
|
+
bool can_overwrite =
|
1602
2834
|
(expr->expression()->AsBinaryOperation() != NULL &&
|
1603
2835
|
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
|
2836
|
+
UnaryOverwriteMode overwrite =
|
2837
|
+
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
1604
2838
|
GenericUnaryOpStub stub(Token::SUB, overwrite);
|
1605
2839
|
// GenericUnaryOpStub expects the argument to be in the
|
1606
2840
|
// accumulator register eax.
|
@@ -1612,9 +2846,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1612
2846
|
|
1613
2847
|
case Token::BIT_NOT: {
|
1614
2848
|
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
|
1615
|
-
bool
|
2849
|
+
bool can_overwrite =
|
1616
2850
|
(expr->expression()->AsBinaryOperation() != NULL &&
|
1617
2851
|
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
|
2852
|
+
UnaryOverwriteMode overwrite =
|
2853
|
+
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
1618
2854
|
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
|
1619
2855
|
// GenericUnaryOpStub expects the argument to be in the
|
1620
2856
|
// accumulator register eax.
|
@@ -1643,6 +2879,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1643
2879
|
|
1644
2880
|
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
1645
2881
|
Comment cmnt(masm_, "[ CountOperation");
|
2882
|
+
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
|
2883
|
+
// as the left-hand side.
|
2884
|
+
if (!expr->expression()->IsValidLeftHandSide()) {
|
2885
|
+
VisitForEffect(expr->expression());
|
2886
|
+
return;
|
2887
|
+
}
|
1646
2888
|
|
1647
2889
|
// Expression can only be a property, a global or a (parameter or local)
|
1648
2890
|
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
|
@@ -1664,7 +2906,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1664
2906
|
EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
|
1665
2907
|
Expression::kValue);
|
1666
2908
|
location_ = saved_location;
|
1667
|
-
} else
|
2909
|
+
} else {
|
1668
2910
|
// Reserve space for result of postfix operation.
|
1669
2911
|
if (expr->is_postfix() && context_ != Expression::kEffect) {
|
1670
2912
|
__ push(Immediate(Smi::FromInt(0)));
|
@@ -1754,7 +2996,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1754
2996
|
switch (assign_type) {
|
1755
2997
|
case VARIABLE:
|
1756
2998
|
if (expr->is_postfix()) {
|
2999
|
+
// Perform the assignment as if via '='.
|
1757
3000
|
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
3001
|
+
Token::ASSIGN,
|
1758
3002
|
Expression::kEffect);
|
1759
3003
|
// For all contexts except kEffect: We have the result on
|
1760
3004
|
// top of the stack.
|
@@ -1762,7 +3006,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1762
3006
|
ApplyTOS(context_);
|
1763
3007
|
}
|
1764
3008
|
} else {
|
3009
|
+
// Perform the assignment as if via '='.
|
1765
3010
|
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
3011
|
+
Token::ASSIGN,
|
1766
3012
|
context_);
|
1767
3013
|
}
|
1768
3014
|
break;
|
@@ -1840,36 +3086,41 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
|
1840
3086
|
}
|
1841
3087
|
|
1842
3088
|
|
3089
|
+
void FullCodeGenerator::EmitNullCompare(bool strict,
|
3090
|
+
Register obj,
|
3091
|
+
Register null_const,
|
3092
|
+
Label* if_true,
|
3093
|
+
Label* if_false,
|
3094
|
+
Register scratch) {
|
3095
|
+
__ cmp(obj, Operand(null_const));
|
3096
|
+
if (strict) {
|
3097
|
+
__ j(equal, if_true);
|
3098
|
+
} else {
|
3099
|
+
__ j(equal, if_true);
|
3100
|
+
__ cmp(obj, Factory::undefined_value());
|
3101
|
+
__ j(equal, if_true);
|
3102
|
+
__ test(obj, Immediate(kSmiTagMask));
|
3103
|
+
__ j(zero, if_false);
|
3104
|
+
// It can be an undetectable object.
|
3105
|
+
__ mov(scratch, FieldOperand(obj, HeapObject::kMapOffset));
|
3106
|
+
__ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
|
3107
|
+
__ test(scratch, Immediate(1 << Map::kIsUndetectable));
|
3108
|
+
__ j(not_zero, if_true);
|
3109
|
+
}
|
3110
|
+
__ jmp(if_false);
|
3111
|
+
}
|
3112
|
+
|
3113
|
+
|
1843
3114
|
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
1844
3115
|
Comment cmnt(masm_, "[ CompareOperation");
|
1845
3116
|
|
1846
3117
|
// Always perform the comparison for its control flow. Pack the result
|
1847
3118
|
// into the expression's context after the comparison is performed.
|
1848
|
-
|
1849
|
-
|
1850
|
-
Label* if_true =
|
1851
|
-
Label* if_false =
|
1852
|
-
|
1853
|
-
case Expression::kUninitialized:
|
1854
|
-
UNREACHABLE();
|
1855
|
-
break;
|
1856
|
-
case Expression::kEffect:
|
1857
|
-
if_true = &done;
|
1858
|
-
if_false = &done;
|
1859
|
-
break;
|
1860
|
-
case Expression::kValue:
|
1861
|
-
if_true = &materialize_true;
|
1862
|
-
if_false = &materialize_false;
|
1863
|
-
break;
|
1864
|
-
case Expression::kTest:
|
1865
|
-
break;
|
1866
|
-
case Expression::kValueTest:
|
1867
|
-
if_true = &materialize_true;
|
1868
|
-
break;
|
1869
|
-
case Expression::kTestValue:
|
1870
|
-
if_false = &materialize_false;
|
1871
|
-
break;
|
1872
|
-
}
|
3119
|
+
|
3120
|
+
Label materialize_true, materialize_false;
|
3121
|
+
Label* if_true = NULL;
|
3122
|
+
Label* if_false = NULL;
|
3123
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1873
3124
|
|
1874
3125
|
VisitForValue(expr->left(), kStack);
|
1875
3126
|
switch (expr->op()) {
|
@@ -1899,10 +3150,24 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|
1899
3150
|
case Token::EQ_STRICT:
|
1900
3151
|
strict = true;
|
1901
3152
|
// Fall through
|
1902
|
-
case Token::EQ:
|
3153
|
+
case Token::EQ: {
|
1903
3154
|
cc = equal;
|
1904
3155
|
__ pop(edx);
|
3156
|
+
// If either operand is constant null we do a fast compare
|
3157
|
+
// against null.
|
3158
|
+
Literal* right_literal = expr->right()->AsLiteral();
|
3159
|
+
Literal* left_literal = expr->left()->AsLiteral();
|
3160
|
+
if (right_literal != NULL && right_literal->handle()->IsNull()) {
|
3161
|
+
EmitNullCompare(strict, edx, eax, if_true, if_false, ecx);
|
3162
|
+
Apply(context_, if_true, if_false);
|
3163
|
+
return;
|
3164
|
+
} else if (left_literal != NULL && left_literal->handle()->IsNull()) {
|
3165
|
+
EmitNullCompare(strict, eax, edx, if_true, if_false, ecx);
|
3166
|
+
Apply(context_, if_true, if_false);
|
3167
|
+
return;
|
3168
|
+
}
|
1905
3169
|
break;
|
3170
|
+
}
|
1906
3171
|
case Token::LT:
|
1907
3172
|
cc = less;
|
1908
3173
|
__ pop(edx);
|
@@ -2012,3 +3277,5 @@ void FullCodeGenerator::ExitFinallyBlock() {
|
|
2012
3277
|
#undef __
|
2013
3278
|
|
2014
3279
|
} } // namespace v8::internal
|
3280
|
+
|
3281
|
+
#endif // V8_TARGET_ARCH_IA32
|