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
@@ -27,6 +27,8 @@
|
|
27
27
|
|
28
28
|
#include "v8.h"
|
29
29
|
|
30
|
+
#if defined(V8_TARGET_ARCH_ARM)
|
31
|
+
|
30
32
|
#include "codegen-inl.h"
|
31
33
|
#include "fast-codegen.h"
|
32
34
|
#include "scopes.h"
|
@@ -100,8 +102,7 @@ void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) {
|
|
100
102
|
}
|
101
103
|
|
102
104
|
if (needs_write_barrier) {
|
103
|
-
__
|
104
|
-
__ RecordWrite(scratch0(), scratch1(), scratch2());
|
105
|
+
__ RecordWrite(scratch0(), Operand(offset), scratch1(), scratch2());
|
105
106
|
}
|
106
107
|
|
107
108
|
if (destination().is(accumulator1())) {
|
@@ -236,3 +237,5 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
|
|
236
237
|
|
237
238
|
|
238
239
|
} } // namespace v8::internal
|
240
|
+
|
241
|
+
#endif // V8_TARGET_ARCH_ARM
|
@@ -27,12 +27,10 @@
|
|
27
27
|
|
28
28
|
#include "v8.h"
|
29
29
|
|
30
|
+
#if defined(V8_TARGET_ARCH_ARM)
|
31
|
+
|
30
32
|
#include "frames-inl.h"
|
31
|
-
#ifdef V8_ARM_VARIANT_THUMB
|
32
|
-
#include "arm/assembler-thumb2-inl.h"
|
33
|
-
#else
|
34
33
|
#include "arm/assembler-arm-inl.h"
|
35
|
-
#endif
|
36
34
|
|
37
35
|
|
38
36
|
namespace v8 {
|
@@ -121,3 +119,5 @@ Address InternalFrame::GetCallerStackPointer() const {
|
|
121
119
|
|
122
120
|
|
123
121
|
} } // namespace v8::internal
|
122
|
+
|
123
|
+
#endif // V8_TARGET_ARCH_ARM
|
File without changes
|
@@ -27,6 +27,8 @@
|
|
27
27
|
|
28
28
|
#include "v8.h"
|
29
29
|
|
30
|
+
#if defined(V8_TARGET_ARCH_ARM)
|
31
|
+
|
30
32
|
#include "codegen-inl.h"
|
31
33
|
#include "compiler.h"
|
32
34
|
#include "debug.h"
|
@@ -62,7 +64,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
62
64
|
if (mode == PRIMARY) {
|
63
65
|
int locals_count = scope()->num_stack_slots();
|
64
66
|
|
65
|
-
__
|
67
|
+
__ Push(lr, fp, cp, r1);
|
66
68
|
if (locals_count > 0) {
|
67
69
|
// Load undefined value here, so the value is ready for the loop
|
68
70
|
// below.
|
@@ -80,11 +82,17 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
80
82
|
bool function_in_register = true;
|
81
83
|
|
82
84
|
// Possibly allocate a local context.
|
83
|
-
|
85
|
+
int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
|
86
|
+
if (heap_slots > 0) {
|
84
87
|
Comment cmnt(masm_, "[ Allocate local context");
|
85
88
|
// Argument to NewContext is the function, which is in r1.
|
86
89
|
__ push(r1);
|
87
|
-
|
90
|
+
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
|
91
|
+
FastNewContextStub stub(heap_slots);
|
92
|
+
__ CallStub(&stub);
|
93
|
+
} else {
|
94
|
+
__ CallRuntime(Runtime::kNewContext, 1);
|
95
|
+
}
|
88
96
|
function_in_register = false;
|
89
97
|
// Context is returned in both r0 and cp. It replaces the context
|
90
98
|
// passed to us. It's saved in the stack and kept live in cp.
|
@@ -102,10 +110,10 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
102
110
|
__ mov(r1, Operand(Context::SlotOffset(slot->index())));
|
103
111
|
__ str(r0, MemOperand(cp, r1));
|
104
112
|
// Update the write barrier. This clobbers all involved
|
105
|
-
// registers, so we have use
|
113
|
+
// registers, so we have to use two more registers to avoid
|
106
114
|
// clobbering cp.
|
107
115
|
__ mov(r2, Operand(cp));
|
108
|
-
__ RecordWrite(r2, r1, r0);
|
116
|
+
__ RecordWrite(r2, Operand(r1), r3, r0);
|
109
117
|
}
|
110
118
|
}
|
111
119
|
}
|
@@ -142,6 +150,21 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
142
150
|
}
|
143
151
|
}
|
144
152
|
|
153
|
+
{ Comment cmnt(masm_, "[ Declarations");
|
154
|
+
// For named function expressions, declare the function name as a
|
155
|
+
// constant.
|
156
|
+
if (scope()->is_function_scope() && scope()->function() != NULL) {
|
157
|
+
EmitDeclaration(scope()->function(), Variable::CONST, NULL);
|
158
|
+
}
|
159
|
+
// Visit all the explicit declarations unless there is an illegal
|
160
|
+
// redeclaration.
|
161
|
+
if (scope()->HasIllegalRedeclaration()) {
|
162
|
+
scope()->VisitIllegalRedeclaration(this);
|
163
|
+
} else {
|
164
|
+
VisitDeclarations(scope()->declarations());
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
145
168
|
// Check the stack for overflow or break request.
|
146
169
|
// Put the lr setup instruction in the delay slot. The kInstrSize is
|
147
170
|
// added to the implicit 8 byte offset that always applies to operations
|
@@ -158,10 +181,6 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
158
181
|
lo);
|
159
182
|
}
|
160
183
|
|
161
|
-
{ Comment cmnt(masm_, "[ Declarations");
|
162
|
-
VisitDeclarations(scope()->declarations());
|
163
|
-
}
|
164
|
-
|
165
184
|
if (FLAG_trace) {
|
166
185
|
__ CallRuntime(Runtime::kTraceEnter, 0);
|
167
186
|
}
|
@@ -177,11 +196,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
|
|
177
196
|
// body.
|
178
197
|
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
179
198
|
}
|
180
|
-
EmitReturnSequence(
|
199
|
+
EmitReturnSequence();
|
181
200
|
}
|
182
201
|
|
183
202
|
|
184
|
-
void FullCodeGenerator::EmitReturnSequence(
|
203
|
+
void FullCodeGenerator::EmitReturnSequence() {
|
185
204
|
Comment cmnt(masm_, "[ Return sequence");
|
186
205
|
if (return_label_.is_bound()) {
|
187
206
|
__ b(&return_label_);
|
@@ -205,7 +224,7 @@ void FullCodeGenerator::EmitReturnSequence(int position) {
|
|
205
224
|
// Here we use masm_-> instead of the __ macro to avoid the code coverage
|
206
225
|
// tool from instrumenting as we rely on the code size here.
|
207
226
|
int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
|
208
|
-
CodeGenerator::RecordPositions(masm_,
|
227
|
+
CodeGenerator::RecordPositions(masm_, function()->end_position());
|
209
228
|
__ RecordJSReturn();
|
210
229
|
masm_->mov(sp, fp);
|
211
230
|
masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
|
@@ -219,8 +238,10 @@ void FullCodeGenerator::EmitReturnSequence(int position) {
|
|
219
238
|
// add instruction the add will generate two instructions.
|
220
239
|
int return_sequence_length =
|
221
240
|
masm_->InstructionsGeneratedSince(&check_exit_codesize);
|
222
|
-
CHECK(return_sequence_length ==
|
223
|
-
|
241
|
+
CHECK(return_sequence_length ==
|
242
|
+
Assembler::kJSReturnSequenceInstructions ||
|
243
|
+
return_sequence_length ==
|
244
|
+
Assembler::kJSReturnSequenceInstructions + 1);
|
224
245
|
#endif
|
225
246
|
}
|
226
247
|
}
|
@@ -382,6 +403,38 @@ void FullCodeGenerator::DropAndApply(int count,
|
|
382
403
|
}
|
383
404
|
}
|
384
405
|
|
406
|
+
void FullCodeGenerator::PrepareTest(Label* materialize_true,
|
407
|
+
Label* materialize_false,
|
408
|
+
Label** if_true,
|
409
|
+
Label** if_false) {
|
410
|
+
switch (context_) {
|
411
|
+
case Expression::kUninitialized:
|
412
|
+
UNREACHABLE();
|
413
|
+
break;
|
414
|
+
case Expression::kEffect:
|
415
|
+
// In an effect context, the true and the false case branch to the
|
416
|
+
// same label.
|
417
|
+
*if_true = *if_false = materialize_true;
|
418
|
+
break;
|
419
|
+
case Expression::kValue:
|
420
|
+
*if_true = materialize_true;
|
421
|
+
*if_false = materialize_false;
|
422
|
+
break;
|
423
|
+
case Expression::kTest:
|
424
|
+
*if_true = true_label_;
|
425
|
+
*if_false = false_label_;
|
426
|
+
break;
|
427
|
+
case Expression::kValueTest:
|
428
|
+
*if_true = materialize_true;
|
429
|
+
*if_false = false_label_;
|
430
|
+
break;
|
431
|
+
case Expression::kTestValue:
|
432
|
+
*if_true = true_label_;
|
433
|
+
*if_false = materialize_false;
|
434
|
+
break;
|
435
|
+
}
|
436
|
+
}
|
437
|
+
|
385
438
|
|
386
439
|
void FullCodeGenerator::Apply(Expression::Context context,
|
387
440
|
Label* materialize_true,
|
@@ -396,19 +449,25 @@ void FullCodeGenerator::Apply(Expression::Context context,
|
|
396
449
|
|
397
450
|
case Expression::kValue: {
|
398
451
|
Label done;
|
399
|
-
__ bind(materialize_true);
|
400
|
-
__ mov(result_register(), Operand(Factory::true_value()));
|
401
|
-
__ jmp(&done);
|
402
|
-
__ bind(materialize_false);
|
403
|
-
__ mov(result_register(), Operand(Factory::false_value()));
|
404
|
-
__ bind(&done);
|
405
452
|
switch (location_) {
|
406
453
|
case kAccumulator:
|
454
|
+
__ bind(materialize_true);
|
455
|
+
__ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
|
456
|
+
__ jmp(&done);
|
457
|
+
__ bind(materialize_false);
|
458
|
+
__ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
|
407
459
|
break;
|
408
460
|
case kStack:
|
409
|
-
__
|
461
|
+
__ bind(materialize_true);
|
462
|
+
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
463
|
+
__ push(ip);
|
464
|
+
__ jmp(&done);
|
465
|
+
__ bind(materialize_false);
|
466
|
+
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
|
467
|
+
__ push(ip);
|
410
468
|
break;
|
411
469
|
}
|
470
|
+
__ bind(&done);
|
412
471
|
break;
|
413
472
|
}
|
414
473
|
|
@@ -417,12 +476,13 @@ void FullCodeGenerator::Apply(Expression::Context context,
|
|
417
476
|
|
418
477
|
case Expression::kValueTest:
|
419
478
|
__ bind(materialize_true);
|
420
|
-
__ mov(result_register(), Operand(Factory::true_value()));
|
421
479
|
switch (location_) {
|
422
480
|
case kAccumulator:
|
481
|
+
__ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
|
423
482
|
break;
|
424
483
|
case kStack:
|
425
|
-
__
|
484
|
+
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
485
|
+
__ push(ip);
|
426
486
|
break;
|
427
487
|
}
|
428
488
|
__ jmp(true_label_);
|
@@ -430,12 +490,13 @@ void FullCodeGenerator::Apply(Expression::Context context,
|
|
430
490
|
|
431
491
|
case Expression::kTestValue:
|
432
492
|
__ bind(materialize_false);
|
433
|
-
__ mov(result_register(), Operand(Factory::false_value()));
|
434
493
|
switch (location_) {
|
435
494
|
case kAccumulator:
|
495
|
+
__ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
|
436
496
|
break;
|
437
497
|
case kStack:
|
438
|
-
__
|
498
|
+
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
|
499
|
+
__ push(ip);
|
439
500
|
break;
|
440
501
|
}
|
441
502
|
__ jmp(false_label_);
|
@@ -444,6 +505,68 @@ void FullCodeGenerator::Apply(Expression::Context context,
|
|
444
505
|
}
|
445
506
|
|
446
507
|
|
508
|
+
// Convert constant control flow (true or false) to the result expected for
|
509
|
+
// a given expression context.
|
510
|
+
void FullCodeGenerator::Apply(Expression::Context context, bool flag) {
|
511
|
+
switch (context) {
|
512
|
+
case Expression::kUninitialized:
|
513
|
+
UNREACHABLE();
|
514
|
+
break;
|
515
|
+
case Expression::kEffect:
|
516
|
+
break;
|
517
|
+
case Expression::kValue: {
|
518
|
+
Heap::RootListIndex value_root_index =
|
519
|
+
flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
|
520
|
+
switch (location_) {
|
521
|
+
case kAccumulator:
|
522
|
+
__ LoadRoot(result_register(), value_root_index);
|
523
|
+
break;
|
524
|
+
case kStack:
|
525
|
+
__ LoadRoot(ip, value_root_index);
|
526
|
+
__ push(ip);
|
527
|
+
break;
|
528
|
+
}
|
529
|
+
break;
|
530
|
+
}
|
531
|
+
case Expression::kTest:
|
532
|
+
__ b(flag ? true_label_ : false_label_);
|
533
|
+
break;
|
534
|
+
case Expression::kTestValue:
|
535
|
+
switch (location_) {
|
536
|
+
case kAccumulator:
|
537
|
+
// If value is false it's needed.
|
538
|
+
if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
|
539
|
+
break;
|
540
|
+
case kStack:
|
541
|
+
// If value is false it's needed.
|
542
|
+
if (!flag) {
|
543
|
+
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
|
544
|
+
__ push(ip);
|
545
|
+
}
|
546
|
+
break;
|
547
|
+
}
|
548
|
+
__ b(flag ? true_label_ : false_label_);
|
549
|
+
break;
|
550
|
+
case Expression::kValueTest:
|
551
|
+
switch (location_) {
|
552
|
+
case kAccumulator:
|
553
|
+
// If value is true it's needed.
|
554
|
+
if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
|
555
|
+
break;
|
556
|
+
case kStack:
|
557
|
+
// If value is true it's needed.
|
558
|
+
if (flag) {
|
559
|
+
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
560
|
+
__ push(ip);
|
561
|
+
}
|
562
|
+
break;
|
563
|
+
}
|
564
|
+
__ b(flag ? true_label_ : false_label_);
|
565
|
+
break;
|
566
|
+
}
|
567
|
+
}
|
568
|
+
|
569
|
+
|
447
570
|
void FullCodeGenerator::DoTest(Expression::Context context) {
|
448
571
|
// The value to test is pushed on the stack, and duplicated on the stack
|
449
572
|
// if necessary (for value/test and test/value contexts).
|
@@ -543,28 +666,31 @@ void FullCodeGenerator::Move(Slot* dst,
|
|
543
666
|
__ str(src, location);
|
544
667
|
// Emit the write barrier code if the location is in the heap.
|
545
668
|
if (dst->type() == Slot::CONTEXT) {
|
546
|
-
__
|
547
|
-
|
669
|
+
__ RecordWrite(scratch1,
|
670
|
+
Operand(Context::SlotOffset(dst->index())),
|
671
|
+
scratch2,
|
672
|
+
src);
|
548
673
|
}
|
549
674
|
}
|
550
675
|
|
551
676
|
|
552
|
-
void FullCodeGenerator::
|
677
|
+
void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
678
|
+
Variable::Mode mode,
|
679
|
+
FunctionLiteral* function) {
|
553
680
|
Comment cmnt(masm_, "[ Declaration");
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
Property* prop = var->AsProperty();
|
681
|
+
ASSERT(variable != NULL); // Must have been resolved.
|
682
|
+
Slot* slot = variable->slot();
|
683
|
+
Property* prop = variable->AsProperty();
|
558
684
|
|
559
685
|
if (slot != NULL) {
|
560
686
|
switch (slot->type()) {
|
561
687
|
case Slot::PARAMETER:
|
562
688
|
case Slot::LOCAL:
|
563
|
-
if (
|
689
|
+
if (mode == Variable::CONST) {
|
564
690
|
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
565
691
|
__ str(ip, MemOperand(fp, SlotOffset(slot)));
|
566
|
-
} else if (
|
567
|
-
VisitForValue(
|
692
|
+
} else if (function != NULL) {
|
693
|
+
VisitForValue(function, kAccumulator);
|
568
694
|
__ str(result_register(), MemOperand(fp, SlotOffset(slot)));
|
569
695
|
}
|
570
696
|
break;
|
@@ -574,7 +700,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
574
700
|
// this specific context.
|
575
701
|
|
576
702
|
// The variable in the decl always resides in the current context.
|
577
|
-
ASSERT_EQ(0, scope()->ContextChainLength(
|
703
|
+
ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
|
578
704
|
if (FLAG_debug_code) {
|
579
705
|
// Check if we have the correct context pointer.
|
580
706
|
__ ldr(r1,
|
@@ -582,44 +708,43 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
582
708
|
__ cmp(r1, cp);
|
583
709
|
__ Check(eq, "Unexpected declaration in current context.");
|
584
710
|
}
|
585
|
-
if (
|
711
|
+
if (mode == Variable::CONST) {
|
586
712
|
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
587
713
|
__ str(ip, CodeGenerator::ContextOperand(cp, slot->index()));
|
588
714
|
// No write barrier since the_hole_value is in old space.
|
589
|
-
} else if (
|
590
|
-
VisitForValue(
|
715
|
+
} else if (function != NULL) {
|
716
|
+
VisitForValue(function, kAccumulator);
|
591
717
|
__ str(result_register(),
|
592
718
|
CodeGenerator::ContextOperand(cp, slot->index()));
|
593
719
|
int offset = Context::SlotOffset(slot->index());
|
594
|
-
__ mov(r2, Operand(offset));
|
595
720
|
// We know that we have written a function, which is not a smi.
|
596
721
|
__ mov(r1, Operand(cp));
|
597
|
-
__ RecordWrite(r1, r2, result_register());
|
722
|
+
__ RecordWrite(r1, Operand(offset), r2, result_register());
|
598
723
|
}
|
599
724
|
break;
|
600
725
|
|
601
726
|
case Slot::LOOKUP: {
|
602
|
-
__ mov(r2, Operand(
|
727
|
+
__ mov(r2, Operand(variable->name()));
|
603
728
|
// Declaration nodes are always introduced in one of two modes.
|
604
|
-
ASSERT(
|
605
|
-
|
729
|
+
ASSERT(mode == Variable::VAR ||
|
730
|
+
mode == Variable::CONST);
|
606
731
|
PropertyAttributes attr =
|
607
|
-
(
|
732
|
+
(mode == Variable::VAR) ? NONE : READ_ONLY;
|
608
733
|
__ mov(r1, Operand(Smi::FromInt(attr)));
|
609
734
|
// Push initial value, if any.
|
610
735
|
// Note: For variables we must not push an initial value (such as
|
611
736
|
// 'undefined') because we may have a (legal) redeclaration and we
|
612
737
|
// must not destroy the current value.
|
613
|
-
if (
|
738
|
+
if (mode == Variable::CONST) {
|
614
739
|
__ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
|
615
|
-
__
|
616
|
-
} else if (
|
617
|
-
__
|
740
|
+
__ Push(cp, r2, r1, r0);
|
741
|
+
} else if (function != NULL) {
|
742
|
+
__ Push(cp, r2, r1);
|
618
743
|
// Push initial value for function declaration.
|
619
|
-
VisitForValue(
|
744
|
+
VisitForValue(function, kStack);
|
620
745
|
} else {
|
621
746
|
__ mov(r0, Operand(Smi::FromInt(0))); // No initial value!
|
622
|
-
__
|
747
|
+
__ Push(cp, r2, r1, r0);
|
623
748
|
}
|
624
749
|
__ CallRuntime(Runtime::kDeclareContextSlot, 4);
|
625
750
|
break;
|
@@ -627,53 +752,272 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
|
627
752
|
}
|
628
753
|
|
629
754
|
} else if (prop != NULL) {
|
630
|
-
if (
|
755
|
+
if (function != NULL || mode == Variable::CONST) {
|
631
756
|
// We are declaring a function or constant that rewrites to a
|
632
757
|
// property. Use (keyed) IC to set the initial value.
|
633
758
|
VisitForValue(prop->obj(), kStack);
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
759
|
+
if (function != NULL) {
|
760
|
+
VisitForValue(prop->key(), kStack);
|
761
|
+
VisitForValue(function, kAccumulator);
|
762
|
+
__ pop(r1); // Key.
|
638
763
|
} else {
|
764
|
+
VisitForValue(prop->key(), kAccumulator);
|
765
|
+
__ mov(r1, result_register()); // Key.
|
639
766
|
__ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
|
640
767
|
}
|
768
|
+
__ pop(r2); // Receiver.
|
641
769
|
|
642
770
|
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
643
771
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
644
|
-
|
645
|
-
// Value in r0 is ignored (declarations are statements). Receiver
|
646
|
-
// and key on stack are discarded.
|
647
|
-
__ Drop(2);
|
772
|
+
// Value in r0 is ignored (declarations are statements).
|
648
773
|
}
|
649
774
|
}
|
650
775
|
}
|
651
776
|
|
652
777
|
|
778
|
+
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
779
|
+
EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
|
780
|
+
}
|
781
|
+
|
782
|
+
|
653
783
|
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
654
784
|
// Call the runtime to declare the globals.
|
655
785
|
// The context is the first argument.
|
656
786
|
__ mov(r1, Operand(pairs));
|
657
787
|
__ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
|
658
|
-
__
|
788
|
+
__ Push(cp, r1, r0);
|
659
789
|
__ CallRuntime(Runtime::kDeclareGlobals, 3);
|
660
790
|
// Return value is ignored.
|
661
791
|
}
|
662
792
|
|
663
793
|
|
664
|
-
void FullCodeGenerator::
|
665
|
-
Comment cmnt(masm_, "[
|
794
|
+
void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
795
|
+
Comment cmnt(masm_, "[ SwitchStatement");
|
796
|
+
Breakable nested_statement(this, stmt);
|
797
|
+
SetStatementPosition(stmt);
|
798
|
+
// Keep the switch value on the stack until a case matches.
|
799
|
+
VisitForValue(stmt->tag(), kStack);
|
800
|
+
|
801
|
+
ZoneList<CaseClause*>* clauses = stmt->cases();
|
802
|
+
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
|
803
|
+
|
804
|
+
Label next_test; // Recycled for each test.
|
805
|
+
// Compile all the tests with branches to their bodies.
|
806
|
+
for (int i = 0; i < clauses->length(); i++) {
|
807
|
+
CaseClause* clause = clauses->at(i);
|
808
|
+
// The default is not a test, but remember it as final fall through.
|
809
|
+
if (clause->is_default()) {
|
810
|
+
default_clause = clause;
|
811
|
+
continue;
|
812
|
+
}
|
813
|
+
|
814
|
+
Comment cmnt(masm_, "[ Case comparison");
|
815
|
+
__ bind(&next_test);
|
816
|
+
next_test.Unuse();
|
817
|
+
|
818
|
+
// Compile the label expression.
|
819
|
+
VisitForValue(clause->label(), kAccumulator);
|
820
|
+
|
821
|
+
// Perform the comparison as if via '==='. The comparison stub expects
|
822
|
+
// the smi vs. smi case to be handled before it is called.
|
823
|
+
Label slow_case;
|
824
|
+
__ ldr(r1, MemOperand(sp, 0)); // Switch value.
|
825
|
+
__ orr(r2, r1, r0);
|
826
|
+
__ tst(r2, Operand(kSmiTagMask));
|
827
|
+
__ b(ne, &slow_case);
|
828
|
+
__ cmp(r1, r0);
|
829
|
+
__ b(ne, &next_test);
|
830
|
+
__ Drop(1); // Switch value is no longer needed.
|
831
|
+
__ b(clause->body_target()->entry_label());
|
832
|
+
|
833
|
+
__ bind(&slow_case);
|
834
|
+
CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
|
835
|
+
__ CallStub(&stub);
|
836
|
+
__ cmp(r0, Operand(0));
|
837
|
+
__ b(ne, &next_test);
|
838
|
+
__ Drop(1); // Switch value is no longer needed.
|
839
|
+
__ b(clause->body_target()->entry_label());
|
840
|
+
}
|
841
|
+
|
842
|
+
// Discard the test value and jump to the default if present, otherwise to
|
843
|
+
// the end of the statement.
|
844
|
+
__ bind(&next_test);
|
845
|
+
__ Drop(1); // Switch value is no longer needed.
|
846
|
+
if (default_clause == NULL) {
|
847
|
+
__ b(nested_statement.break_target());
|
848
|
+
} else {
|
849
|
+
__ b(default_clause->body_target()->entry_label());
|
850
|
+
}
|
851
|
+
|
852
|
+
// Compile all the case bodies.
|
853
|
+
for (int i = 0; i < clauses->length(); i++) {
|
854
|
+
Comment cmnt(masm_, "[ Case body");
|
855
|
+
CaseClause* clause = clauses->at(i);
|
856
|
+
__ bind(clause->body_target()->entry_label());
|
857
|
+
VisitStatements(clause->statements());
|
858
|
+
}
|
859
|
+
|
860
|
+
__ bind(nested_statement.break_target());
|
861
|
+
}
|
862
|
+
|
863
|
+
|
864
|
+
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
865
|
+
Comment cmnt(masm_, "[ ForInStatement");
|
866
|
+
SetStatementPosition(stmt);
|
867
|
+
|
868
|
+
Label loop, exit;
|
869
|
+
ForIn loop_statement(this, stmt);
|
870
|
+
increment_loop_depth();
|
666
871
|
|
667
|
-
//
|
668
|
-
//
|
669
|
-
|
670
|
-
|
671
|
-
|
872
|
+
// Get the object to enumerate over. Both SpiderMonkey and JSC
|
873
|
+
// ignore null and undefined in contrast to the specification; see
|
874
|
+
// ECMA-262 section 12.6.4.
|
875
|
+
VisitForValue(stmt->enumerable(), kAccumulator);
|
876
|
+
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
877
|
+
__ cmp(r0, ip);
|
878
|
+
__ b(eq, &exit);
|
879
|
+
__ LoadRoot(ip, Heap::kNullValueRootIndex);
|
880
|
+
__ cmp(r0, ip);
|
881
|
+
__ b(eq, &exit);
|
882
|
+
|
883
|
+
// Convert the object to a JS object.
|
884
|
+
Label convert, done_convert;
|
885
|
+
__ BranchOnSmi(r0, &convert);
|
886
|
+
__ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
|
887
|
+
__ b(hs, &done_convert);
|
888
|
+
__ bind(&convert);
|
889
|
+
__ push(r0);
|
890
|
+
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
|
891
|
+
__ bind(&done_convert);
|
892
|
+
__ push(r0);
|
893
|
+
|
894
|
+
// TODO(kasperl): Check cache validity in generated code. This is a
|
895
|
+
// fast case for the JSObject::IsSimpleEnum cache validity
|
896
|
+
// checks. If we cannot guarantee cache validity, call the runtime
|
897
|
+
// system to check cache validity or get the property names in a
|
898
|
+
// fixed array.
|
899
|
+
|
900
|
+
// Get the set of properties to enumerate.
|
901
|
+
__ push(r0); // Duplicate the enumerable object on the stack.
|
902
|
+
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
|
903
|
+
|
904
|
+
// If we got a map from the runtime call, we can do a fast
|
905
|
+
// modification check. Otherwise, we got a fixed array, and we have
|
906
|
+
// to do a slow check.
|
907
|
+
Label fixed_array;
|
908
|
+
__ mov(r2, r0);
|
909
|
+
__ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
|
910
|
+
__ LoadRoot(ip, Heap::kMetaMapRootIndex);
|
911
|
+
__ cmp(r1, ip);
|
912
|
+
__ b(ne, &fixed_array);
|
913
|
+
|
914
|
+
// We got a map in register r0. Get the enumeration cache from it.
|
915
|
+
__ ldr(r1, FieldMemOperand(r0, Map::kInstanceDescriptorsOffset));
|
916
|
+
__ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
|
917
|
+
__ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
|
918
|
+
|
919
|
+
// Setup the four remaining stack slots.
|
920
|
+
__ push(r0); // Map.
|
921
|
+
__ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset));
|
922
|
+
__ mov(r0, Operand(Smi::FromInt(0)));
|
923
|
+
// Push enumeration cache, enumeration cache length (as smi) and zero.
|
924
|
+
__ Push(r2, r1, r0);
|
925
|
+
__ jmp(&loop);
|
926
|
+
|
927
|
+
// We got a fixed array in register r0. Iterate through that.
|
928
|
+
__ bind(&fixed_array);
|
929
|
+
__ mov(r1, Operand(Smi::FromInt(0))); // Map (0) - force slow check.
|
930
|
+
__ Push(r1, r0);
|
931
|
+
__ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
|
932
|
+
__ mov(r0, Operand(Smi::FromInt(0)));
|
933
|
+
__ Push(r1, r0); // Fixed array length (as smi) and initial index.
|
934
|
+
|
935
|
+
// Generate code for doing the condition check.
|
936
|
+
__ bind(&loop);
|
937
|
+
// Load the current count to r0, load the length to r1.
|
938
|
+
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
|
939
|
+
__ cmp(r0, r1); // Compare to the array length.
|
940
|
+
__ b(hs, loop_statement.break_target());
|
941
|
+
|
942
|
+
// Get the current entry of the array into register r3.
|
943
|
+
__ ldr(r2, MemOperand(sp, 2 * kPointerSize));
|
944
|
+
__ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
945
|
+
__ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
|
946
|
+
|
947
|
+
// Get the expected map from the stack or a zero map in the
|
948
|
+
// permanent slow case into register r2.
|
949
|
+
__ ldr(r2, MemOperand(sp, 3 * kPointerSize));
|
950
|
+
|
951
|
+
// Check if the expected map still matches that of the enumerable.
|
952
|
+
// If not, we have to filter the key.
|
953
|
+
Label update_each;
|
954
|
+
__ ldr(r1, MemOperand(sp, 4 * kPointerSize));
|
955
|
+
__ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
|
956
|
+
__ cmp(r4, Operand(r2));
|
957
|
+
__ b(eq, &update_each);
|
958
|
+
|
959
|
+
// Convert the entry to a string or null if it isn't a property
|
960
|
+
// anymore. If the property has been removed while iterating, we
|
961
|
+
// just skip it.
|
962
|
+
__ push(r1); // Enumerable.
|
963
|
+
__ push(r3); // Current entry.
|
964
|
+
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
|
965
|
+
__ mov(r3, Operand(r0));
|
966
|
+
__ LoadRoot(ip, Heap::kNullValueRootIndex);
|
967
|
+
__ cmp(r3, ip);
|
968
|
+
__ b(eq, loop_statement.continue_target());
|
969
|
+
|
970
|
+
// Update the 'each' property or variable from the possibly filtered
|
971
|
+
// entry in register r3.
|
972
|
+
__ bind(&update_each);
|
973
|
+
__ mov(result_register(), r3);
|
974
|
+
// Perform the assignment as if via '='.
|
975
|
+
EmitAssignment(stmt->each());
|
976
|
+
|
977
|
+
// Generate code for the body of the loop.
|
978
|
+
Label stack_limit_hit, stack_check_done;
|
979
|
+
Visit(stmt->body());
|
980
|
+
|
981
|
+
__ StackLimitCheck(&stack_limit_hit);
|
982
|
+
__ bind(&stack_check_done);
|
983
|
+
|
984
|
+
// Generate code for the going to the next element by incrementing
|
985
|
+
// the index (smi) stored on top of the stack.
|
986
|
+
__ bind(loop_statement.continue_target());
|
987
|
+
__ pop(r0);
|
988
|
+
__ add(r0, r0, Operand(Smi::FromInt(1)));
|
989
|
+
__ push(r0);
|
990
|
+
__ b(&loop);
|
991
|
+
|
992
|
+
// Slow case for the stack limit check.
|
993
|
+
StackCheckStub stack_check_stub;
|
994
|
+
__ bind(&stack_limit_hit);
|
995
|
+
__ CallStub(&stack_check_stub);
|
996
|
+
__ b(&stack_check_done);
|
672
997
|
|
673
|
-
//
|
674
|
-
__
|
675
|
-
__
|
676
|
-
|
998
|
+
// Remove the pointers stored on the stack.
|
999
|
+
__ bind(loop_statement.break_target());
|
1000
|
+
__ Drop(5);
|
1001
|
+
|
1002
|
+
// Exit and decrement the loop depth.
|
1003
|
+
__ bind(&exit);
|
1004
|
+
decrement_loop_depth();
|
1005
|
+
}
|
1006
|
+
|
1007
|
+
|
1008
|
+
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
|
1009
|
+
// Use the fast case closure allocation code that allocates in new
|
1010
|
+
// space for nested functions that don't need literals cloning.
|
1011
|
+
if (scope()->is_function_scope() && info->num_literals() == 0) {
|
1012
|
+
FastNewClosureStub stub;
|
1013
|
+
__ mov(r0, Operand(info));
|
1014
|
+
__ push(r0);
|
1015
|
+
__ CallStub(&stub);
|
1016
|
+
} else {
|
1017
|
+
__ mov(r0, Operand(info));
|
1018
|
+
__ Push(cp, r0);
|
1019
|
+
__ CallRuntime(Runtime::kNewClosure, 2);
|
1020
|
+
}
|
677
1021
|
Apply(context_, r0);
|
678
1022
|
}
|
679
1023
|
|
@@ -695,18 +1039,17 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
|
695
1039
|
if (var->is_global() && !var->is_this()) {
|
696
1040
|
Comment cmnt(masm_, "Global variable");
|
697
1041
|
// Use inline caching. Variable name is passed in r2 and the global
|
698
|
-
// object
|
1042
|
+
// object (receiver) in r0.
|
699
1043
|
__ ldr(r0, CodeGenerator::GlobalObject());
|
700
|
-
__ push(r0);
|
701
1044
|
__ mov(r2, Operand(var->name()));
|
702
1045
|
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
703
1046
|
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
704
|
-
|
1047
|
+
Apply(context, r0);
|
705
1048
|
|
706
1049
|
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
|
707
1050
|
Comment cmnt(masm_, "Lookup slot");
|
708
1051
|
__ mov(r1, Operand(var->name()));
|
709
|
-
__
|
1052
|
+
__ Push(cp, r1); // Context and name.
|
710
1053
|
__ CallRuntime(Runtime::kLoadContextSlot, 2);
|
711
1054
|
Apply(context, r0);
|
712
1055
|
|
@@ -714,8 +1057,21 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
|
714
1057
|
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
|
715
1058
|
? "Context slot"
|
716
1059
|
: "Stack slot");
|
717
|
-
|
718
|
-
|
1060
|
+
if (var->mode() == Variable::CONST) {
|
1061
|
+
// Constants may be the hole value if they have not been initialized.
|
1062
|
+
// Unhole them.
|
1063
|
+
Label done;
|
1064
|
+
MemOperand slot_operand = EmitSlotSearch(slot, r0);
|
1065
|
+
__ ldr(r0, slot_operand);
|
1066
|
+
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
1067
|
+
__ cmp(r0, ip);
|
1068
|
+
__ b(ne, &done);
|
1069
|
+
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
1070
|
+
__ bind(&done);
|
1071
|
+
Apply(context, r0);
|
1072
|
+
} else {
|
1073
|
+
Apply(context, slot);
|
1074
|
+
}
|
719
1075
|
} else {
|
720
1076
|
Comment cmnt(masm_, "Rewritten parameter");
|
721
1077
|
ASSERT_NOT_NULL(property);
|
@@ -738,15 +1094,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
|
738
1094
|
// Load the key.
|
739
1095
|
__ mov(r0, Operand(key_literal->handle()));
|
740
1096
|
|
741
|
-
//
|
742
|
-
__ Push(r1, r0);
|
743
|
-
|
744
|
-
// Call keyed load IC. It has all arguments on the stack and the key in r0.
|
1097
|
+
// Call keyed load IC. It has arguments key and receiver in r0 and r1.
|
745
1098
|
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
746
1099
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
747
|
-
|
748
|
-
// Drop key and object left on the stack by IC, and push the result.
|
749
|
-
DropAndApply(2, context, r0);
|
1100
|
+
Apply(context, r0);
|
750
1101
|
}
|
751
1102
|
}
|
752
1103
|
|
@@ -856,6 +1207,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|
856
1207
|
|
857
1208
|
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
858
1209
|
Comment cmnt(masm_, "[ ArrayLiteral");
|
1210
|
+
|
1211
|
+
ZoneList<Expression*>* subexprs = expr->values();
|
1212
|
+
int length = subexprs->length();
|
1213
|
+
|
859
1214
|
__ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
860
1215
|
__ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
861
1216
|
__ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
@@ -863,16 +1218,18 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|
863
1218
|
__ Push(r3, r2, r1);
|
864
1219
|
if (expr->depth() > 1) {
|
865
1220
|
__ CallRuntime(Runtime::kCreateArrayLiteral, 3);
|
866
|
-
} else {
|
1221
|
+
} else if (length > FastCloneShallowArrayStub::kMaximumLength) {
|
867
1222
|
__ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
|
1223
|
+
} else {
|
1224
|
+
FastCloneShallowArrayStub stub(length);
|
1225
|
+
__ CallStub(&stub);
|
868
1226
|
}
|
869
1227
|
|
870
1228
|
bool result_saved = false; // Is the result saved to the stack?
|
871
1229
|
|
872
1230
|
// Emit code to evaluate all the non-constant subexpressions and to store
|
873
1231
|
// them into the newly cloned array.
|
874
|
-
|
875
|
-
for (int i = 0, len = subexprs->length(); i < len; i++) {
|
1232
|
+
for (int i = 0; i < length; i++) {
|
876
1233
|
Expression* subexpr = subexprs->at(i);
|
877
1234
|
// If the subexpression is a literal or a simple materialized literal it
|
878
1235
|
// is already set in the cloned array.
|
@@ -895,8 +1252,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|
895
1252
|
|
896
1253
|
// Update the write barrier for the array store with r0 as the scratch
|
897
1254
|
// register.
|
898
|
-
__
|
899
|
-
__ RecordWrite(r1, r2, result_register());
|
1255
|
+
__ RecordWrite(r1, Operand(offset), r2, result_register());
|
900
1256
|
}
|
901
1257
|
|
902
1258
|
if (result_saved) {
|
@@ -909,7 +1265,13 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|
909
1265
|
|
910
1266
|
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
911
1267
|
Comment cmnt(masm_, "[ Assignment");
|
912
|
-
|
1268
|
+
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
|
1269
|
+
// on the left-hand side.
|
1270
|
+
if (!expr->target()->IsValidLeftHandSide()) {
|
1271
|
+
VisitForEffect(expr->target());
|
1272
|
+
return;
|
1273
|
+
}
|
1274
|
+
|
913
1275
|
// Left-hand side can only be a property, a global or a (parameter or local)
|
914
1276
|
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
|
915
1277
|
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
|
@@ -935,8 +1297,16 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
|
935
1297
|
}
|
936
1298
|
break;
|
937
1299
|
case KEYED_PROPERTY:
|
938
|
-
|
939
|
-
|
1300
|
+
// We need the key and receiver on both the stack and in r0 and r1.
|
1301
|
+
if (expr->is_compound()) {
|
1302
|
+
VisitForValue(prop->obj(), kStack);
|
1303
|
+
VisitForValue(prop->key(), kAccumulator);
|
1304
|
+
__ ldr(r1, MemOperand(sp, 0));
|
1305
|
+
__ push(r0);
|
1306
|
+
} else {
|
1307
|
+
VisitForValue(prop->obj(), kStack);
|
1308
|
+
VisitForValue(prop->key(), kStack);
|
1309
|
+
}
|
940
1310
|
break;
|
941
1311
|
}
|
942
1312
|
|
@@ -981,6 +1351,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
|
981
1351
|
switch (assign_type) {
|
982
1352
|
case VARIABLE:
|
983
1353
|
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
|
1354
|
+
expr->op(),
|
984
1355
|
context_);
|
985
1356
|
break;
|
986
1357
|
case NAMED_PROPERTY:
|
@@ -997,7 +1368,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
|
997
1368
|
SetSourcePosition(prop->position());
|
998
1369
|
Literal* key = prop->key()->AsLiteral();
|
999
1370
|
__ mov(r2, Operand(key->handle()));
|
1000
|
-
|
1371
|
+
// Call load IC. It has arguments receiver and property name r0 and r2.
|
1001
1372
|
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
1002
1373
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
1003
1374
|
}
|
@@ -1005,8 +1376,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
|
1005
1376
|
|
1006
1377
|
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
1007
1378
|
SetSourcePosition(prop->position());
|
1008
|
-
// Call keyed load IC. It has
|
1009
|
-
__ ldr(r0, MemOperand(sp, 0));
|
1379
|
+
// Call keyed load IC. It has arguments key and receiver in r0 and r1.
|
1010
1380
|
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
1011
1381
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
1012
1382
|
}
|
@@ -1021,15 +1391,64 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
|
|
1021
1391
|
}
|
1022
1392
|
|
1023
1393
|
|
1394
|
+
void FullCodeGenerator::EmitAssignment(Expression* expr) {
|
1395
|
+
// Invalid left-hand sides are rewritten to have a 'throw
|
1396
|
+
// ReferenceError' on the left-hand side.
|
1397
|
+
if (!expr->IsValidLeftHandSide()) {
|
1398
|
+
VisitForEffect(expr);
|
1399
|
+
return;
|
1400
|
+
}
|
1401
|
+
|
1402
|
+
// Left-hand side can only be a property, a global or a (parameter or local)
|
1403
|
+
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
|
1404
|
+
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
|
1405
|
+
LhsKind assign_type = VARIABLE;
|
1406
|
+
Property* prop = expr->AsProperty();
|
1407
|
+
if (prop != NULL) {
|
1408
|
+
assign_type = (prop->key()->IsPropertyName())
|
1409
|
+
? NAMED_PROPERTY
|
1410
|
+
: KEYED_PROPERTY;
|
1411
|
+
}
|
1412
|
+
|
1413
|
+
switch (assign_type) {
|
1414
|
+
case VARIABLE: {
|
1415
|
+
Variable* var = expr->AsVariableProxy()->var();
|
1416
|
+
EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
|
1417
|
+
break;
|
1418
|
+
}
|
1419
|
+
case NAMED_PROPERTY: {
|
1420
|
+
__ push(r0); // Preserve value.
|
1421
|
+
VisitForValue(prop->obj(), kAccumulator);
|
1422
|
+
__ mov(r1, r0);
|
1423
|
+
__ pop(r0); // Restore value.
|
1424
|
+
__ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
|
1425
|
+
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
1426
|
+
__ Call(ic, RelocInfo::CODE_TARGET);
|
1427
|
+
break;
|
1428
|
+
}
|
1429
|
+
case KEYED_PROPERTY: {
|
1430
|
+
__ push(r0); // Preserve value.
|
1431
|
+
VisitForValue(prop->obj(), kStack);
|
1432
|
+
VisitForValue(prop->key(), kAccumulator);
|
1433
|
+
__ mov(r1, r0);
|
1434
|
+
__ pop(r2);
|
1435
|
+
__ pop(r0); // Restore value.
|
1436
|
+
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
1437
|
+
__ Call(ic, RelocInfo::CODE_TARGET);
|
1438
|
+
break;
|
1439
|
+
}
|
1440
|
+
}
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
|
1024
1444
|
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
1445
|
+
Token::Value op,
|
1025
1446
|
Expression::Context context) {
|
1026
|
-
//
|
1027
|
-
//
|
1028
|
-
// explicit property accesses do not reach here.
|
1447
|
+
// Left-hand sides that rewrite to explicit property accesses do not reach
|
1448
|
+
// here.
|
1029
1449
|
ASSERT(var != NULL);
|
1030
1450
|
ASSERT(var->is_global() || var->slot() != NULL);
|
1031
1451
|
|
1032
|
-
Slot* slot = var->slot();
|
1033
1452
|
if (var->is_global()) {
|
1034
1453
|
ASSERT(!var->is_this());
|
1035
1454
|
// Assignment to a global variable. Use inline caching for the
|
@@ -1040,43 +1459,60 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
|
1040
1459
|
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
1041
1460
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
1042
1461
|
|
1043
|
-
} else if (
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
__ CallRuntime(Runtime::kStoreContextSlot, 3);
|
1048
|
-
|
1049
|
-
} else if (var->slot() != NULL) {
|
1462
|
+
} else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
|
1463
|
+
// Perform the assignment for non-const variables and for initialization
|
1464
|
+
// of const variables. Const assignments are simply skipped.
|
1465
|
+
Label done;
|
1050
1466
|
Slot* slot = var->slot();
|
1051
1467
|
switch (slot->type()) {
|
1052
|
-
case Slot::LOCAL:
|
1053
1468
|
case Slot::PARAMETER:
|
1469
|
+
case Slot::LOCAL:
|
1470
|
+
if (op == Token::INIT_CONST) {
|
1471
|
+
// Detect const reinitialization by checking for the hole value.
|
1472
|
+
__ ldr(r1, MemOperand(fp, SlotOffset(slot)));
|
1473
|
+
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
1474
|
+
__ cmp(r1, ip);
|
1475
|
+
__ b(ne, &done);
|
1476
|
+
}
|
1477
|
+
// Perform the assignment.
|
1054
1478
|
__ str(result_register(), MemOperand(fp, SlotOffset(slot)));
|
1055
1479
|
break;
|
1056
1480
|
|
1057
1481
|
case Slot::CONTEXT: {
|
1058
1482
|
MemOperand target = EmitSlotSearch(slot, r1);
|
1483
|
+
if (op == Token::INIT_CONST) {
|
1484
|
+
// Detect const reinitialization by checking for the hole value.
|
1485
|
+
__ ldr(r2, target);
|
1486
|
+
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
1487
|
+
__ cmp(r2, ip);
|
1488
|
+
__ b(ne, &done);
|
1489
|
+
}
|
1490
|
+
// Perform the assignment and issue the write barrier.
|
1059
1491
|
__ str(result_register(), target);
|
1060
|
-
|
1061
1492
|
// RecordWrite may destroy all its register arguments.
|
1062
1493
|
__ mov(r3, result_register());
|
1063
1494
|
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
|
1064
|
-
|
1065
|
-
__ mov(r2, Operand(offset));
|
1066
|
-
__ RecordWrite(r1, r2, r3);
|
1495
|
+
__ RecordWrite(r1, Operand(offset), r2, r3);
|
1067
1496
|
break;
|
1068
1497
|
}
|
1069
1498
|
|
1070
1499
|
case Slot::LOOKUP:
|
1071
|
-
|
1500
|
+
// Call the runtime for the assignment. The runtime will ignore
|
1501
|
+
// const reinitialization.
|
1502
|
+
__ push(r0); // Value.
|
1503
|
+
__ mov(r0, Operand(slot->var()->name()));
|
1504
|
+
__ Push(cp, r0); // Context and name.
|
1505
|
+
if (op == Token::INIT_CONST) {
|
1506
|
+
// The runtime will ignore const redeclaration.
|
1507
|
+
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
|
1508
|
+
} else {
|
1509
|
+
__ CallRuntime(Runtime::kStoreContextSlot, 3);
|
1510
|
+
}
|
1072
1511
|
break;
|
1073
1512
|
}
|
1074
|
-
|
1075
|
-
} else {
|
1076
|
-
// Variables rewritten as properties are not treated as variables in
|
1077
|
-
// assignments.
|
1078
|
-
UNREACHABLE();
|
1513
|
+
__ bind(&done);
|
1079
1514
|
}
|
1515
|
+
|
1080
1516
|
Apply(context, result_register());
|
1081
1517
|
}
|
1082
1518
|
|
@@ -1101,6 +1537,8 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
|
1101
1537
|
// Record source code position before IC call.
|
1102
1538
|
SetSourcePosition(expr->position());
|
1103
1539
|
__ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
|
1540
|
+
// Load receiver to r1. Leave a copy in the stack if needed for turning the
|
1541
|
+
// receiver into fast case.
|
1104
1542
|
if (expr->ends_initialization_block()) {
|
1105
1543
|
__ ldr(r1, MemOperand(sp));
|
1106
1544
|
} else {
|
@@ -1113,7 +1551,8 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
|
1113
1551
|
// If the assignment ends an initialization block, revert to fast case.
|
1114
1552
|
if (expr->ends_initialization_block()) {
|
1115
1553
|
__ push(r0); // Result of assignment, saved even if not needed.
|
1116
|
-
|
1554
|
+
// Receiver is under the result value.
|
1555
|
+
__ ldr(ip, MemOperand(sp, kPointerSize));
|
1117
1556
|
__ push(ip);
|
1118
1557
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
1119
1558
|
__ pop(r0);
|
@@ -1141,21 +1580,30 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
|
1141
1580
|
|
1142
1581
|
// Record source code position before IC call.
|
1143
1582
|
SetSourcePosition(expr->position());
|
1583
|
+
__ pop(r1); // Key.
|
1584
|
+
// Load receiver to r2. Leave a copy in the stack if needed for turning the
|
1585
|
+
// receiver into fast case.
|
1586
|
+
if (expr->ends_initialization_block()) {
|
1587
|
+
__ ldr(r2, MemOperand(sp));
|
1588
|
+
} else {
|
1589
|
+
__ pop(r2);
|
1590
|
+
}
|
1591
|
+
|
1144
1592
|
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
1145
1593
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
1146
1594
|
|
1147
1595
|
// If the assignment ends an initialization block, revert to fast case.
|
1148
1596
|
if (expr->ends_initialization_block()) {
|
1149
1597
|
__ push(r0); // Result of assignment, saved even if not needed.
|
1150
|
-
// Receiver is under the
|
1151
|
-
__ ldr(ip, MemOperand(sp,
|
1598
|
+
// Receiver is under the result value.
|
1599
|
+
__ ldr(ip, MemOperand(sp, kPointerSize));
|
1152
1600
|
__ push(ip);
|
1153
1601
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
1154
1602
|
__ pop(r0);
|
1603
|
+
DropAndApply(1, context_, r0);
|
1604
|
+
} else {
|
1605
|
+
Apply(context_, r0);
|
1155
1606
|
}
|
1156
|
-
|
1157
|
-
// Receiver and key are still on stack.
|
1158
|
-
DropAndApply(2, context_, r0);
|
1159
1607
|
}
|
1160
1608
|
|
1161
1609
|
|
@@ -1163,18 +1611,16 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
|
1163
1611
|
Comment cmnt(masm_, "[ Property");
|
1164
1612
|
Expression* key = expr->key();
|
1165
1613
|
|
1166
|
-
// Evaluate receiver.
|
1167
|
-
VisitForValue(expr->obj(), kStack);
|
1168
|
-
|
1169
1614
|
if (key->IsPropertyName()) {
|
1615
|
+
VisitForValue(expr->obj(), kAccumulator);
|
1170
1616
|
EmitNamedPropertyLoad(expr);
|
1171
|
-
|
1172
|
-
DropAndApply(1, context_, r0);
|
1617
|
+
Apply(context_, r0);
|
1173
1618
|
} else {
|
1174
|
-
VisitForValue(expr->
|
1619
|
+
VisitForValue(expr->obj(), kStack);
|
1620
|
+
VisitForValue(expr->key(), kAccumulator);
|
1621
|
+
__ pop(r1);
|
1175
1622
|
EmitKeyedPropertyLoad(expr);
|
1176
|
-
|
1177
|
-
DropAndApply(2, context_, r0);
|
1623
|
+
Apply(context_, r0);
|
1178
1624
|
}
|
1179
1625
|
}
|
1180
1626
|
|
@@ -1200,6 +1646,30 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
|
1200
1646
|
}
|
1201
1647
|
|
1202
1648
|
|
1649
|
+
void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
|
1650
|
+
Expression* key,
|
1651
|
+
RelocInfo::Mode mode) {
|
1652
|
+
// Code common for calls using the IC.
|
1653
|
+
ZoneList<Expression*>* args = expr->arguments();
|
1654
|
+
int arg_count = args->length();
|
1655
|
+
for (int i = 0; i < arg_count; i++) {
|
1656
|
+
VisitForValue(args->at(i), kStack);
|
1657
|
+
}
|
1658
|
+
VisitForValue(key, kAccumulator);
|
1659
|
+
__ mov(r2, r0);
|
1660
|
+
// Record source position for debugger.
|
1661
|
+
SetSourcePosition(expr->position());
|
1662
|
+
// Call the IC initialization code.
|
1663
|
+
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
|
1664
|
+
Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
|
1665
|
+
in_loop);
|
1666
|
+
__ Call(ic, mode);
|
1667
|
+
// Restore context register.
|
1668
|
+
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
1669
|
+
Apply(context_, r0);
|
1670
|
+
}
|
1671
|
+
|
1672
|
+
|
1203
1673
|
void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
1204
1674
|
// Code common for calls using the call stub.
|
1205
1675
|
ZoneList<Expression*>* args = expr->arguments();
|
@@ -1209,7 +1679,8 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
|
1209
1679
|
}
|
1210
1680
|
// Record source position for debugger.
|
1211
1681
|
SetSourcePosition(expr->position());
|
1212
|
-
|
1682
|
+
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
|
1683
|
+
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
|
1213
1684
|
__ CallStub(&stub);
|
1214
1685
|
// Restore context register.
|
1215
1686
|
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
@@ -1223,8 +1694,51 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
|
1223
1694
|
Variable* var = fun->AsVariableProxy()->AsVariable();
|
1224
1695
|
|
1225
1696
|
if (var != NULL && var->is_possibly_eval()) {
|
1226
|
-
//
|
1227
|
-
|
1697
|
+
// In a call to eval, we first call %ResolvePossiblyDirectEval to
|
1698
|
+
// resolve the function we need to call and the receiver of the
|
1699
|
+
// call. Then we call the resolved function using the given
|
1700
|
+
// arguments.
|
1701
|
+
VisitForValue(fun, kStack);
|
1702
|
+
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
|
1703
|
+
__ push(r2); // Reserved receiver slot.
|
1704
|
+
|
1705
|
+
// Push the arguments.
|
1706
|
+
ZoneList<Expression*>* args = expr->arguments();
|
1707
|
+
int arg_count = args->length();
|
1708
|
+
for (int i = 0; i < arg_count; i++) {
|
1709
|
+
VisitForValue(args->at(i), kStack);
|
1710
|
+
}
|
1711
|
+
|
1712
|
+
// Push copy of the function - found below the arguments.
|
1713
|
+
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
1714
|
+
__ push(r1);
|
1715
|
+
|
1716
|
+
// Push copy of the first argument or undefined if it doesn't exist.
|
1717
|
+
if (arg_count > 0) {
|
1718
|
+
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
|
1719
|
+
__ push(r1);
|
1720
|
+
} else {
|
1721
|
+
__ push(r2);
|
1722
|
+
}
|
1723
|
+
|
1724
|
+
// Push the receiver of the enclosing function and do runtime call.
|
1725
|
+
__ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
|
1726
|
+
__ push(r1);
|
1727
|
+
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
|
1728
|
+
|
1729
|
+
// The runtime call returns a pair of values in r0 (function) and
|
1730
|
+
// r1 (receiver). Touch up the stack with the right values.
|
1731
|
+
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
1732
|
+
__ str(r1, MemOperand(sp, arg_count * kPointerSize));
|
1733
|
+
|
1734
|
+
// Record source position for debugger.
|
1735
|
+
SetSourcePosition(expr->position());
|
1736
|
+
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
|
1737
|
+
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
|
1738
|
+
__ CallStub(&stub);
|
1739
|
+
// Restore context register.
|
1740
|
+
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
1741
|
+
DropAndApply(1, context_, r0);
|
1228
1742
|
} else if (var != NULL && !var->is_this() && var->is_global()) {
|
1229
1743
|
// Push global object as receiver for the call IC.
|
1230
1744
|
__ ldr(r0, CodeGenerator::GlobalObject());
|
@@ -1232,8 +1746,16 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
|
1232
1746
|
EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
|
1233
1747
|
} else if (var != NULL && var->slot() != NULL &&
|
1234
1748
|
var->slot()->type() == Slot::LOOKUP) {
|
1235
|
-
// Call to a lookup slot.
|
1236
|
-
|
1749
|
+
// Call to a lookup slot (dynamically introduced variable). Call the
|
1750
|
+
// runtime to find the function to call (returned in eax) and the object
|
1751
|
+
// holding it (returned in edx).
|
1752
|
+
__ push(context_register());
|
1753
|
+
__ mov(r2, Operand(var->name()));
|
1754
|
+
__ push(r2);
|
1755
|
+
__ CallRuntime(Runtime::kLoadContextSlot, 2);
|
1756
|
+
__ push(r0); // Function.
|
1757
|
+
__ push(r1); // Receiver.
|
1758
|
+
EmitCallWithStub(expr);
|
1237
1759
|
} else if (fun->AsProperty() != NULL) {
|
1238
1760
|
// Call to an object property.
|
1239
1761
|
Property* prop = fun->AsProperty();
|
@@ -1243,28 +1765,28 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
|
1243
1765
|
VisitForValue(prop->obj(), kStack);
|
1244
1766
|
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
|
1245
1767
|
} else {
|
1246
|
-
// Call to a keyed property
|
1247
|
-
// call
|
1768
|
+
// Call to a keyed property.
|
1769
|
+
// For a synthetic property use keyed load IC followed by function call,
|
1770
|
+
// for a regular property use keyed CallIC.
|
1248
1771
|
VisitForValue(prop->obj(), kStack);
|
1249
|
-
VisitForValue(prop->key(), kStack);
|
1250
|
-
// Record source code position for IC call.
|
1251
|
-
SetSourcePosition(prop->position());
|
1252
|
-
// Call keyed load IC. It has all arguments on the stack and the key in
|
1253
|
-
// r0.
|
1254
|
-
__ ldr(r0, MemOperand(sp, 0));
|
1255
|
-
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
1256
|
-
__ Call(ic, RelocInfo::CODE_TARGET);
|
1257
|
-
// Load receiver object into r1.
|
1258
1772
|
if (prop->is_synthetic()) {
|
1773
|
+
VisitForValue(prop->key(), kAccumulator);
|
1774
|
+
// Record source code position for IC call.
|
1775
|
+
SetSourcePosition(prop->position());
|
1776
|
+
__ pop(r1); // We do not need to keep the receiver.
|
1777
|
+
|
1778
|
+
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
1779
|
+
__ Call(ic, RelocInfo::CODE_TARGET);
|
1780
|
+
// Push result (function).
|
1781
|
+
__ push(r0);
|
1782
|
+
// Push Global receiver.
|
1259
1783
|
__ ldr(r1, CodeGenerator::GlobalObject());
|
1260
1784
|
__ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
|
1785
|
+
__ push(r1);
|
1786
|
+
EmitCallWithStub(expr);
|
1261
1787
|
} else {
|
1262
|
-
|
1788
|
+
EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
|
1263
1789
|
}
|
1264
|
-
// Overwrite (object, key) with (function, receiver).
|
1265
|
-
__ str(r0, MemOperand(sp, kPointerSize));
|
1266
|
-
__ str(r1, MemOperand(sp));
|
1267
|
-
EmitCallWithStub(expr);
|
1268
1790
|
}
|
1269
1791
|
} else {
|
1270
1792
|
// Call to some other expression. If the expression is an anonymous
|
@@ -1322,34 +1844,763 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|
1322
1844
|
}
|
1323
1845
|
|
1324
1846
|
|
1325
|
-
void FullCodeGenerator::
|
1326
|
-
|
1327
|
-
ZoneList<Expression*>* args = expr->arguments();
|
1847
|
+
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
1848
|
+
ASSERT(args->length() == 1);
|
1328
1849
|
|
1329
|
-
|
1330
|
-
// Prepare for calling JS runtime function.
|
1331
|
-
__ ldr(r0, CodeGenerator::GlobalObject());
|
1332
|
-
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
|
1333
|
-
__ push(r0);
|
1334
|
-
}
|
1850
|
+
VisitForValue(args->at(0), kAccumulator);
|
1335
1851
|
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
}
|
1852
|
+
Label materialize_true, materialize_false;
|
1853
|
+
Label* if_true = NULL;
|
1854
|
+
Label* if_false = NULL;
|
1855
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1341
1856
|
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1857
|
+
__ BranchOnSmi(r0, if_true);
|
1858
|
+
__ b(if_false);
|
1859
|
+
|
1860
|
+
Apply(context_, if_true, if_false);
|
1861
|
+
}
|
1862
|
+
|
1863
|
+
|
1864
|
+
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
1865
|
+
ASSERT(args->length() == 1);
|
1866
|
+
|
1867
|
+
VisitForValue(args->at(0), kAccumulator);
|
1868
|
+
|
1869
|
+
Label materialize_true, materialize_false;
|
1870
|
+
Label* if_true = NULL;
|
1871
|
+
Label* if_false = NULL;
|
1872
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1873
|
+
|
1874
|
+
__ tst(r0, Operand(kSmiTagMask | 0x80000000));
|
1875
|
+
__ b(eq, if_true);
|
1876
|
+
__ b(if_false);
|
1877
|
+
|
1878
|
+
Apply(context_, if_true, if_false);
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
|
1882
|
+
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
1883
|
+
ASSERT(args->length() == 1);
|
1884
|
+
|
1885
|
+
VisitForValue(args->at(0), kAccumulator);
|
1886
|
+
|
1887
|
+
Label materialize_true, materialize_false;
|
1888
|
+
Label* if_true = NULL;
|
1889
|
+
Label* if_false = NULL;
|
1890
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1891
|
+
__ BranchOnSmi(r0, if_false);
|
1892
|
+
__ LoadRoot(ip, Heap::kNullValueRootIndex);
|
1893
|
+
__ cmp(r0, ip);
|
1894
|
+
__ b(eq, if_true);
|
1895
|
+
__ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
|
1896
|
+
// Undetectable objects behave like undefined when tested with typeof.
|
1897
|
+
__ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
|
1898
|
+
__ tst(r1, Operand(1 << Map::kIsUndetectable));
|
1899
|
+
__ b(ne, if_false);
|
1900
|
+
__ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
|
1901
|
+
__ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
|
1902
|
+
__ b(lt, if_false);
|
1903
|
+
__ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
|
1904
|
+
__ b(le, if_true);
|
1905
|
+
__ b(if_false);
|
1906
|
+
|
1907
|
+
Apply(context_, if_true, if_false);
|
1908
|
+
}
|
1909
|
+
|
1910
|
+
|
1911
|
+
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
1912
|
+
ASSERT(args->length() == 1);
|
1913
|
+
|
1914
|
+
VisitForValue(args->at(0), kAccumulator);
|
1915
|
+
|
1916
|
+
Label materialize_true, materialize_false;
|
1917
|
+
Label* if_true = NULL;
|
1918
|
+
Label* if_false = NULL;
|
1919
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1920
|
+
|
1921
|
+
__ BranchOnSmi(r0, if_false);
|
1922
|
+
__ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
|
1923
|
+
__ b(ge, if_true);
|
1924
|
+
__ b(if_false);
|
1925
|
+
|
1926
|
+
Apply(context_, if_true, if_false);
|
1927
|
+
}
|
1928
|
+
|
1929
|
+
|
1930
|
+
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
1931
|
+
ASSERT(args->length() == 1);
|
1932
|
+
|
1933
|
+
VisitForValue(args->at(0), kAccumulator);
|
1934
|
+
|
1935
|
+
Label materialize_true, materialize_false;
|
1936
|
+
Label* if_true = NULL;
|
1937
|
+
Label* if_false = NULL;
|
1938
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1939
|
+
|
1940
|
+
__ BranchOnSmi(r0, if_false);
|
1941
|
+
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
|
1942
|
+
__ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
|
1943
|
+
__ tst(r1, Operand(1 << Map::kIsUndetectable));
|
1944
|
+
__ b(ne, if_true);
|
1945
|
+
__ b(if_false);
|
1946
|
+
|
1947
|
+
Apply(context_, if_true, if_false);
|
1948
|
+
}
|
1949
|
+
|
1950
|
+
|
1951
|
+
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
1952
|
+
ASSERT(args->length() == 1);
|
1953
|
+
|
1954
|
+
VisitForValue(args->at(0), kAccumulator);
|
1955
|
+
|
1956
|
+
Label materialize_true, materialize_false;
|
1957
|
+
Label* if_true = NULL;
|
1958
|
+
Label* if_false = NULL;
|
1959
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1960
|
+
|
1961
|
+
__ BranchOnSmi(r0, if_false);
|
1962
|
+
__ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
|
1963
|
+
__ b(eq, if_true);
|
1964
|
+
__ b(if_false);
|
1965
|
+
|
1966
|
+
Apply(context_, if_true, if_false);
|
1967
|
+
}
|
1968
|
+
|
1969
|
+
|
1970
|
+
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
1971
|
+
ASSERT(args->length() == 1);
|
1972
|
+
|
1973
|
+
VisitForValue(args->at(0), kAccumulator);
|
1974
|
+
|
1975
|
+
Label materialize_true, materialize_false;
|
1976
|
+
Label* if_true = NULL;
|
1977
|
+
Label* if_false = NULL;
|
1978
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1979
|
+
|
1980
|
+
__ BranchOnSmi(r0, if_false);
|
1981
|
+
__ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
|
1982
|
+
__ b(eq, if_true);
|
1983
|
+
__ b(if_false);
|
1984
|
+
|
1985
|
+
Apply(context_, if_true, if_false);
|
1986
|
+
}
|
1987
|
+
|
1988
|
+
|
1989
|
+
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
1990
|
+
ASSERT(args->length() == 1);
|
1991
|
+
|
1992
|
+
VisitForValue(args->at(0), kAccumulator);
|
1993
|
+
|
1994
|
+
Label materialize_true, materialize_false;
|
1995
|
+
Label* if_true = NULL;
|
1996
|
+
Label* if_false = NULL;
|
1997
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1998
|
+
|
1999
|
+
__ BranchOnSmi(r0, if_false);
|
2000
|
+
__ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
|
2001
|
+
__ b(eq, if_true);
|
2002
|
+
__ b(if_false);
|
2003
|
+
|
2004
|
+
Apply(context_, if_true, if_false);
|
2005
|
+
}
|
2006
|
+
|
2007
|
+
|
2008
|
+
|
2009
|
+
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
2010
|
+
ASSERT(args->length() == 0);
|
2011
|
+
|
2012
|
+
Label materialize_true, materialize_false;
|
2013
|
+
Label* if_true = NULL;
|
2014
|
+
Label* if_false = NULL;
|
2015
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2016
|
+
|
2017
|
+
// Get the frame pointer for the calling frame.
|
2018
|
+
__ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
2019
|
+
|
2020
|
+
// Skip the arguments adaptor frame if it exists.
|
2021
|
+
Label check_frame_marker;
|
2022
|
+
__ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
|
2023
|
+
__ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
2024
|
+
__ b(ne, &check_frame_marker);
|
2025
|
+
__ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
|
2026
|
+
|
2027
|
+
// Check the marker in the calling frame.
|
2028
|
+
__ bind(&check_frame_marker);
|
2029
|
+
__ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
|
2030
|
+
__ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
|
2031
|
+
__ b(eq, if_true);
|
2032
|
+
__ b(if_false);
|
2033
|
+
|
2034
|
+
Apply(context_, if_true, if_false);
|
2035
|
+
}
|
2036
|
+
|
2037
|
+
|
2038
|
+
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
2039
|
+
ASSERT(args->length() == 2);
|
2040
|
+
|
2041
|
+
// Load the two objects into registers and perform the comparison.
|
2042
|
+
VisitForValue(args->at(0), kStack);
|
2043
|
+
VisitForValue(args->at(1), kAccumulator);
|
2044
|
+
|
2045
|
+
Label materialize_true, materialize_false;
|
2046
|
+
Label* if_true = NULL;
|
2047
|
+
Label* if_false = NULL;
|
2048
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
2049
|
+
|
2050
|
+
__ pop(r1);
|
2051
|
+
__ cmp(r0, r1);
|
2052
|
+
__ b(eq, if_true);
|
2053
|
+
__ b(if_false);
|
2054
|
+
|
2055
|
+
Apply(context_, if_true, if_false);
|
2056
|
+
}
|
2057
|
+
|
2058
|
+
|
2059
|
+
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
2060
|
+
ASSERT(args->length() == 1);
|
2061
|
+
|
2062
|
+
// ArgumentsAccessStub expects the key in edx and the formal
|
2063
|
+
// parameter count in eax.
|
2064
|
+
VisitForValue(args->at(0), kAccumulator);
|
2065
|
+
__ mov(r1, r0);
|
2066
|
+
__ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
|
2067
|
+
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
|
2068
|
+
__ CallStub(&stub);
|
2069
|
+
Apply(context_, r0);
|
2070
|
+
}
|
2071
|
+
|
2072
|
+
|
2073
|
+
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
2074
|
+
ASSERT(args->length() == 0);
|
2075
|
+
|
2076
|
+
Label exit;
|
2077
|
+
// Get the number of formal parameters.
|
2078
|
+
__ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
|
2079
|
+
|
2080
|
+
// Check if the calling frame is an arguments adaptor frame.
|
2081
|
+
__ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
2082
|
+
__ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
|
2083
|
+
__ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
2084
|
+
__ b(ne, &exit);
|
2085
|
+
|
2086
|
+
// Arguments adaptor case: Read the arguments length from the
|
2087
|
+
// adaptor frame.
|
2088
|
+
__ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
2089
|
+
|
2090
|
+
__ bind(&exit);
|
2091
|
+
Apply(context_, r0);
|
2092
|
+
}
|
2093
|
+
|
2094
|
+
|
2095
|
+
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
2096
|
+
ASSERT(args->length() == 1);
|
2097
|
+
Label done, null, function, non_function_constructor;
|
2098
|
+
|
2099
|
+
VisitForValue(args->at(0), kAccumulator);
|
2100
|
+
|
2101
|
+
// If the object is a smi, we return null.
|
2102
|
+
__ BranchOnSmi(r0, &null);
|
2103
|
+
|
2104
|
+
// Check that the object is a JS object but take special care of JS
|
2105
|
+
// functions to make sure they have 'Function' as their class.
|
2106
|
+
__ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0.
|
2107
|
+
__ b(lt, &null);
|
2108
|
+
|
2109
|
+
// As long as JS_FUNCTION_TYPE is the last instance type and it is
|
2110
|
+
// right after LAST_JS_OBJECT_TYPE, we can avoid checking for
|
2111
|
+
// LAST_JS_OBJECT_TYPE.
|
2112
|
+
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
2113
|
+
ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
|
2114
|
+
__ cmp(r1, Operand(JS_FUNCTION_TYPE));
|
2115
|
+
__ b(eq, &function);
|
2116
|
+
|
2117
|
+
// Check if the constructor in the map is a function.
|
2118
|
+
__ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
|
2119
|
+
__ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
|
2120
|
+
__ b(ne, &non_function_constructor);
|
2121
|
+
|
2122
|
+
// r0 now contains the constructor function. Grab the
|
2123
|
+
// instance class name from there.
|
2124
|
+
__ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
|
2125
|
+
__ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
|
2126
|
+
__ b(&done);
|
2127
|
+
|
2128
|
+
// Functions have class 'Function'.
|
2129
|
+
__ bind(&function);
|
2130
|
+
__ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
|
2131
|
+
__ jmp(&done);
|
2132
|
+
|
2133
|
+
// Objects with a non-function constructor have class 'Object'.
|
2134
|
+
__ bind(&non_function_constructor);
|
2135
|
+
__ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
|
2136
|
+
__ jmp(&done);
|
2137
|
+
|
2138
|
+
// Non-JS objects have class null.
|
2139
|
+
__ bind(&null);
|
2140
|
+
__ LoadRoot(r0, Heap::kNullValueRootIndex);
|
2141
|
+
|
2142
|
+
// All done.
|
2143
|
+
__ bind(&done);
|
2144
|
+
|
2145
|
+
Apply(context_, r0);
|
2146
|
+
}
|
2147
|
+
|
2148
|
+
|
2149
|
+
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
2150
|
+
// Conditionally generate a log call.
|
2151
|
+
// Args:
|
2152
|
+
// 0 (literal string): The type of logging (corresponds to the flags).
|
2153
|
+
// This is used to determine whether or not to generate the log call.
|
2154
|
+
// 1 (string): Format string. Access the string at argument index 2
|
2155
|
+
// with '%2s' (see Logger::LogRuntime for all the formats).
|
2156
|
+
// 2 (array): Arguments to the format string.
|
2157
|
+
ASSERT_EQ(args->length(), 3);
|
2158
|
+
#ifdef ENABLE_LOGGING_AND_PROFILING
|
2159
|
+
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
2160
|
+
VisitForValue(args->at(1), kStack);
|
2161
|
+
VisitForValue(args->at(2), kStack);
|
2162
|
+
__ CallRuntime(Runtime::kLog, 2);
|
2163
|
+
}
|
2164
|
+
#endif
|
2165
|
+
// Finally, we're expected to leave a value on the top of the stack.
|
2166
|
+
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
2167
|
+
Apply(context_, r0);
|
2168
|
+
}
|
2169
|
+
|
2170
|
+
|
2171
|
+
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
2172
|
+
ASSERT(args->length() == 0);
|
2173
|
+
|
2174
|
+
Label slow_allocate_heapnumber;
|
2175
|
+
Label heapnumber_allocated;
|
2176
|
+
|
2177
|
+
__ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
|
2178
|
+
__ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
|
2179
|
+
__ jmp(&heapnumber_allocated);
|
2180
|
+
|
2181
|
+
__ bind(&slow_allocate_heapnumber);
|
2182
|
+
// Allocate a heap number.
|
2183
|
+
__ CallRuntime(Runtime::kNumberAlloc, 0);
|
2184
|
+
__ mov(r4, Operand(r0));
|
2185
|
+
|
2186
|
+
__ bind(&heapnumber_allocated);
|
2187
|
+
|
2188
|
+
// Convert 32 random bits in r0 to 0.(32 random bits) in a double
|
2189
|
+
// by computing:
|
2190
|
+
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
|
2191
|
+
if (CpuFeatures::IsSupported(VFP3)) {
|
2192
|
+
__ PrepareCallCFunction(0, r1);
|
2193
|
+
__ CallCFunction(ExternalReference::random_uint32_function(), 0);
|
2194
|
+
|
2195
|
+
CpuFeatures::Scope scope(VFP3);
|
2196
|
+
// 0x41300000 is the top half of 1.0 x 2^20 as a double.
|
2197
|
+
// Create this constant using mov/orr to avoid PC relative load.
|
2198
|
+
__ mov(r1, Operand(0x41000000));
|
2199
|
+
__ orr(r1, r1, Operand(0x300000));
|
2200
|
+
// Move 0x41300000xxxxxxxx (x = random bits) to VFP.
|
2201
|
+
__ vmov(d7, r0, r1);
|
2202
|
+
// Move 0x4130000000000000 to VFP.
|
2203
|
+
__ mov(r0, Operand(0));
|
2204
|
+
__ vmov(d8, r0, r1);
|
2205
|
+
// Subtract and store the result in the heap number.
|
2206
|
+
__ vsub(d7, d7, d8);
|
2207
|
+
__ sub(r0, r4, Operand(kHeapObjectTag));
|
2208
|
+
__ vstr(d7, r0, HeapNumber::kValueOffset);
|
2209
|
+
__ mov(r0, r4);
|
2210
|
+
} else {
|
2211
|
+
__ mov(r0, Operand(r4));
|
2212
|
+
__ PrepareCallCFunction(1, r1);
|
2213
|
+
__ CallCFunction(
|
2214
|
+
ExternalReference::fill_heap_number_with_random_function(), 1);
|
2215
|
+
}
|
2216
|
+
|
2217
|
+
Apply(context_, r0);
|
2218
|
+
}
|
2219
|
+
|
2220
|
+
|
2221
|
+
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
2222
|
+
// Load the arguments on the stack and call the stub.
|
2223
|
+
SubStringStub stub;
|
2224
|
+
ASSERT(args->length() == 3);
|
2225
|
+
VisitForValue(args->at(0), kStack);
|
2226
|
+
VisitForValue(args->at(1), kStack);
|
2227
|
+
VisitForValue(args->at(2), kStack);
|
2228
|
+
__ CallStub(&stub);
|
2229
|
+
Apply(context_, r0);
|
2230
|
+
}
|
2231
|
+
|
2232
|
+
|
2233
|
+
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
2234
|
+
// Load the arguments on the stack and call the stub.
|
2235
|
+
RegExpExecStub stub;
|
2236
|
+
ASSERT(args->length() == 4);
|
2237
|
+
VisitForValue(args->at(0), kStack);
|
2238
|
+
VisitForValue(args->at(1), kStack);
|
2239
|
+
VisitForValue(args->at(2), kStack);
|
2240
|
+
VisitForValue(args->at(3), kStack);
|
2241
|
+
__ CallStub(&stub);
|
2242
|
+
Apply(context_, r0);
|
2243
|
+
}
|
2244
|
+
|
2245
|
+
|
2246
|
+
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
2247
|
+
ASSERT(args->length() == 1);
|
2248
|
+
|
2249
|
+
VisitForValue(args->at(0), kAccumulator); // Load the object.
|
2250
|
+
|
2251
|
+
Label done;
|
2252
|
+
// If the object is a smi return the object.
|
2253
|
+
__ BranchOnSmi(r0, &done);
|
2254
|
+
// If the object is not a value type, return the object.
|
2255
|
+
__ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
|
2256
|
+
__ b(ne, &done);
|
2257
|
+
__ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
|
2258
|
+
|
2259
|
+
__ bind(&done);
|
2260
|
+
Apply(context_, r0);
|
2261
|
+
}
|
2262
|
+
|
2263
|
+
|
2264
|
+
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
2265
|
+
// Load the arguments on the stack and call the runtime function.
|
2266
|
+
ASSERT(args->length() == 2);
|
2267
|
+
VisitForValue(args->at(0), kStack);
|
2268
|
+
VisitForValue(args->at(1), kStack);
|
2269
|
+
__ CallRuntime(Runtime::kMath_pow, 2);
|
2270
|
+
Apply(context_, r0);
|
2271
|
+
}
|
2272
|
+
|
2273
|
+
|
2274
|
+
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
2275
|
+
ASSERT(args->length() == 2);
|
2276
|
+
|
2277
|
+
VisitForValue(args->at(0), kStack); // Load the object.
|
2278
|
+
VisitForValue(args->at(1), kAccumulator); // Load the value.
|
2279
|
+
__ pop(r1); // r0 = value. r1 = object.
|
2280
|
+
|
2281
|
+
Label done;
|
2282
|
+
// If the object is a smi, return the value.
|
2283
|
+
__ BranchOnSmi(r1, &done);
|
2284
|
+
|
2285
|
+
// If the object is not a value type, return the value.
|
2286
|
+
__ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
|
2287
|
+
__ b(ne, &done);
|
2288
|
+
|
2289
|
+
// Store the value.
|
2290
|
+
__ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
|
2291
|
+
// Update the write barrier. Save the value as it will be
|
2292
|
+
// overwritten by the write barrier code and is needed afterward.
|
2293
|
+
__ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3);
|
2294
|
+
|
2295
|
+
__ bind(&done);
|
2296
|
+
Apply(context_, r0);
|
2297
|
+
}
|
2298
|
+
|
2299
|
+
|
2300
|
+
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
2301
|
+
ASSERT_EQ(args->length(), 1);
|
2302
|
+
|
2303
|
+
// Load the argument on the stack and call the stub.
|
2304
|
+
VisitForValue(args->at(0), kStack);
|
2305
|
+
|
2306
|
+
NumberToStringStub stub;
|
2307
|
+
__ CallStub(&stub);
|
2308
|
+
Apply(context_, r0);
|
2309
|
+
}
|
2310
|
+
|
2311
|
+
|
2312
|
+
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
2313
|
+
ASSERT(args->length() == 1);
|
2314
|
+
|
2315
|
+
VisitForValue(args->at(0), kAccumulator);
|
2316
|
+
|
2317
|
+
Label done;
|
2318
|
+
StringCharFromCodeGenerator generator(r0, r1);
|
2319
|
+
generator.GenerateFast(masm_);
|
2320
|
+
__ jmp(&done);
|
2321
|
+
|
2322
|
+
NopRuntimeCallHelper call_helper;
|
2323
|
+
generator.GenerateSlow(masm_, call_helper);
|
2324
|
+
|
2325
|
+
__ bind(&done);
|
2326
|
+
Apply(context_, r1);
|
2327
|
+
}
|
2328
|
+
|
2329
|
+
|
2330
|
+
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
2331
|
+
ASSERT(args->length() == 2);
|
2332
|
+
|
2333
|
+
VisitForValue(args->at(0), kStack);
|
2334
|
+
VisitForValue(args->at(1), kAccumulator);
|
2335
|
+
|
2336
|
+
Register object = r1;
|
2337
|
+
Register index = r0;
|
2338
|
+
Register scratch = r2;
|
2339
|
+
Register result = r3;
|
2340
|
+
|
2341
|
+
__ pop(object);
|
2342
|
+
|
2343
|
+
Label need_conversion;
|
2344
|
+
Label index_out_of_range;
|
2345
|
+
Label done;
|
2346
|
+
StringCharCodeAtGenerator generator(object,
|
2347
|
+
index,
|
2348
|
+
scratch,
|
2349
|
+
result,
|
2350
|
+
&need_conversion,
|
2351
|
+
&need_conversion,
|
2352
|
+
&index_out_of_range,
|
2353
|
+
STRING_INDEX_IS_NUMBER);
|
2354
|
+
generator.GenerateFast(masm_);
|
2355
|
+
__ jmp(&done);
|
2356
|
+
|
2357
|
+
__ bind(&index_out_of_range);
|
2358
|
+
// When the index is out of range, the spec requires us to return
|
2359
|
+
// NaN.
|
2360
|
+
__ LoadRoot(result, Heap::kNanValueRootIndex);
|
2361
|
+
__ jmp(&done);
|
2362
|
+
|
2363
|
+
__ bind(&need_conversion);
|
2364
|
+
// Load the undefined value into the result register, which will
|
2365
|
+
// trigger conversion.
|
2366
|
+
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
2367
|
+
__ jmp(&done);
|
2368
|
+
|
2369
|
+
NopRuntimeCallHelper call_helper;
|
2370
|
+
generator.GenerateSlow(masm_, call_helper);
|
2371
|
+
|
2372
|
+
__ bind(&done);
|
2373
|
+
Apply(context_, result);
|
2374
|
+
}
|
2375
|
+
|
2376
|
+
|
2377
|
+
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
2378
|
+
ASSERT(args->length() == 2);
|
2379
|
+
|
2380
|
+
VisitForValue(args->at(0), kStack);
|
2381
|
+
VisitForValue(args->at(1), kAccumulator);
|
2382
|
+
|
2383
|
+
Register object = r1;
|
2384
|
+
Register index = r0;
|
2385
|
+
Register scratch1 = r2;
|
2386
|
+
Register scratch2 = r3;
|
2387
|
+
Register result = r0;
|
2388
|
+
|
2389
|
+
__ pop(object);
|
2390
|
+
|
2391
|
+
Label need_conversion;
|
2392
|
+
Label index_out_of_range;
|
2393
|
+
Label done;
|
2394
|
+
StringCharAtGenerator generator(object,
|
2395
|
+
index,
|
2396
|
+
scratch1,
|
2397
|
+
scratch2,
|
2398
|
+
result,
|
2399
|
+
&need_conversion,
|
2400
|
+
&need_conversion,
|
2401
|
+
&index_out_of_range,
|
2402
|
+
STRING_INDEX_IS_NUMBER);
|
2403
|
+
generator.GenerateFast(masm_);
|
2404
|
+
__ jmp(&done);
|
2405
|
+
|
2406
|
+
__ bind(&index_out_of_range);
|
2407
|
+
// When the index is out of range, the spec requires us to return
|
2408
|
+
// the empty string.
|
2409
|
+
__ LoadRoot(result, Heap::kEmptyStringRootIndex);
|
2410
|
+
__ jmp(&done);
|
2411
|
+
|
2412
|
+
__ bind(&need_conversion);
|
2413
|
+
// Move smi zero into the result register, which will trigger
|
2414
|
+
// conversion.
|
2415
|
+
__ mov(result, Operand(Smi::FromInt(0)));
|
2416
|
+
__ jmp(&done);
|
2417
|
+
|
2418
|
+
NopRuntimeCallHelper call_helper;
|
2419
|
+
generator.GenerateSlow(masm_, call_helper);
|
2420
|
+
|
2421
|
+
__ bind(&done);
|
2422
|
+
Apply(context_, result);
|
2423
|
+
}
|
2424
|
+
|
2425
|
+
|
2426
|
+
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
2427
|
+
ASSERT_EQ(2, args->length());
|
2428
|
+
|
2429
|
+
VisitForValue(args->at(0), kStack);
|
2430
|
+
VisitForValue(args->at(1), kStack);
|
2431
|
+
|
2432
|
+
StringAddStub stub(NO_STRING_ADD_FLAGS);
|
2433
|
+
__ CallStub(&stub);
|
2434
|
+
Apply(context_, r0);
|
2435
|
+
}
|
2436
|
+
|
2437
|
+
|
2438
|
+
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
2439
|
+
ASSERT_EQ(2, args->length());
|
2440
|
+
|
2441
|
+
VisitForValue(args->at(0), kStack);
|
2442
|
+
VisitForValue(args->at(1), kStack);
|
2443
|
+
|
2444
|
+
StringCompareStub stub;
|
2445
|
+
__ CallStub(&stub);
|
2446
|
+
Apply(context_, r0);
|
2447
|
+
}
|
2448
|
+
|
2449
|
+
|
2450
|
+
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
2451
|
+
// Load the argument on the stack and call the runtime.
|
2452
|
+
ASSERT(args->length() == 1);
|
2453
|
+
VisitForValue(args->at(0), kStack);
|
2454
|
+
__ CallRuntime(Runtime::kMath_sin, 1);
|
2455
|
+
Apply(context_, r0);
|
2456
|
+
}
|
2457
|
+
|
2458
|
+
|
2459
|
+
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
2460
|
+
// Load the argument on the stack and call the runtime.
|
2461
|
+
ASSERT(args->length() == 1);
|
2462
|
+
VisitForValue(args->at(0), kStack);
|
2463
|
+
__ CallRuntime(Runtime::kMath_cos, 1);
|
2464
|
+
Apply(context_, r0);
|
2465
|
+
}
|
2466
|
+
|
2467
|
+
|
2468
|
+
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
2469
|
+
// Load the argument on the stack and call the runtime function.
|
2470
|
+
ASSERT(args->length() == 1);
|
2471
|
+
VisitForValue(args->at(0), kStack);
|
2472
|
+
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
2473
|
+
Apply(context_, r0);
|
2474
|
+
}
|
2475
|
+
|
2476
|
+
|
2477
|
+
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
2478
|
+
ASSERT(args->length() >= 2);
|
2479
|
+
|
2480
|
+
int arg_count = args->length() - 2; // For receiver and function.
|
2481
|
+
VisitForValue(args->at(0), kStack); // Receiver.
|
2482
|
+
for (int i = 0; i < arg_count; i++) {
|
2483
|
+
VisitForValue(args->at(i + 1), kStack);
|
2484
|
+
}
|
2485
|
+
VisitForValue(args->at(arg_count + 1), kAccumulator); // Function.
|
2486
|
+
|
2487
|
+
// InvokeFunction requires function in r1. Move it in there.
|
2488
|
+
if (!result_register().is(r1)) __ mov(r1, result_register());
|
2489
|
+
ParameterCount count(arg_count);
|
2490
|
+
__ InvokeFunction(r1, count, CALL_FUNCTION);
|
2491
|
+
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
2492
|
+
Apply(context_, r0);
|
2493
|
+
}
|
2494
|
+
|
2495
|
+
|
2496
|
+
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
2497
|
+
ASSERT(args->length() == 3);
|
2498
|
+
VisitForValue(args->at(0), kStack);
|
2499
|
+
VisitForValue(args->at(1), kStack);
|
2500
|
+
VisitForValue(args->at(2), kStack);
|
2501
|
+
__ CallRuntime(Runtime::kRegExpConstructResult, 3);
|
2502
|
+
Apply(context_, r0);
|
2503
|
+
}
|
2504
|
+
|
2505
|
+
|
2506
|
+
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
2507
|
+
ASSERT(args->length() == 3);
|
2508
|
+
VisitForValue(args->at(0), kStack);
|
2509
|
+
VisitForValue(args->at(1), kStack);
|
2510
|
+
VisitForValue(args->at(2), kStack);
|
2511
|
+
__ CallRuntime(Runtime::kSwapElements, 3);
|
2512
|
+
Apply(context_, r0);
|
2513
|
+
}
|
2514
|
+
|
2515
|
+
|
2516
|
+
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
2517
|
+
ASSERT_EQ(2, args->length());
|
2518
|
+
|
2519
|
+
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
2520
|
+
int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
|
2521
|
+
|
2522
|
+
Handle<FixedArray> jsfunction_result_caches(
|
2523
|
+
Top::global_context()->jsfunction_result_caches());
|
2524
|
+
if (jsfunction_result_caches->length() <= cache_id) {
|
2525
|
+
__ Abort("Attempt to use undefined cache.");
|
2526
|
+
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
2527
|
+
Apply(context_, r0);
|
2528
|
+
return;
|
2529
|
+
}
|
2530
|
+
|
2531
|
+
VisitForValue(args->at(1), kAccumulator);
|
2532
|
+
|
2533
|
+
Register key = r0;
|
2534
|
+
Register cache = r1;
|
2535
|
+
__ ldr(cache, CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX));
|
2536
|
+
__ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset));
|
2537
|
+
__ ldr(cache,
|
2538
|
+
CodeGenerator::ContextOperand(
|
2539
|
+
cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
|
2540
|
+
__ ldr(cache,
|
2541
|
+
FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
|
2542
|
+
|
2543
|
+
|
2544
|
+
Label done, not_found;
|
2545
|
+
// tmp now holds finger offset as a smi.
|
2546
|
+
ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
2547
|
+
__ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
|
2548
|
+
// r2 now holds finger offset as a smi.
|
2549
|
+
__ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
2550
|
+
// r3 now points to the start of fixed array elements.
|
2551
|
+
__ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex));
|
2552
|
+
// Note side effect of PreIndex: r3 now points to the key of the pair.
|
2553
|
+
__ cmp(key, r2);
|
2554
|
+
__ b(ne, ¬_found);
|
2555
|
+
|
2556
|
+
__ ldr(r0, MemOperand(r3, kPointerSize));
|
2557
|
+
__ b(&done);
|
2558
|
+
|
2559
|
+
__ bind(¬_found);
|
2560
|
+
// Call runtime to perform the lookup.
|
2561
|
+
__ Push(cache, key);
|
2562
|
+
__ CallRuntime(Runtime::kGetFromCache, 2);
|
2563
|
+
|
2564
|
+
__ bind(&done);
|
2565
|
+
Apply(context_, r0);
|
2566
|
+
}
|
2567
|
+
|
2568
|
+
|
2569
|
+
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
2570
|
+
Handle<String> name = expr->name();
|
2571
|
+
if (name->length() > 0 && name->Get(0) == '_') {
|
2572
|
+
Comment cmnt(masm_, "[ InlineRuntimeCall");
|
2573
|
+
EmitInlineRuntimeCall(expr);
|
2574
|
+
return;
|
2575
|
+
}
|
2576
|
+
|
2577
|
+
Comment cmnt(masm_, "[ CallRuntime");
|
2578
|
+
ZoneList<Expression*>* args = expr->arguments();
|
2579
|
+
|
2580
|
+
if (expr->is_jsruntime()) {
|
2581
|
+
// Prepare for calling JS runtime function.
|
2582
|
+
__ ldr(r0, CodeGenerator::GlobalObject());
|
2583
|
+
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
|
2584
|
+
__ push(r0);
|
2585
|
+
}
|
2586
|
+
|
2587
|
+
// Push the arguments ("left-to-right").
|
2588
|
+
int arg_count = args->length();
|
2589
|
+
for (int i = 0; i < arg_count; i++) {
|
2590
|
+
VisitForValue(args->at(i), kStack);
|
2591
|
+
}
|
2592
|
+
|
2593
|
+
if (expr->is_jsruntime()) {
|
2594
|
+
// Call the JS runtime function.
|
2595
|
+
__ mov(r2, Operand(expr->name()));
|
2596
|
+
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
|
2597
|
+
NOT_IN_LOOP);
|
2598
|
+
__ Call(ic, RelocInfo::CODE_TARGET);
|
2599
|
+
// Restore context register.
|
2600
|
+
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
2601
|
+
} else {
|
2602
|
+
// Call the C runtime function.
|
2603
|
+
__ CallRuntime(expr->function(), arg_count);
|
1353
2604
|
}
|
1354
2605
|
Apply(context_, r0);
|
1355
2606
|
}
|
@@ -1357,6 +2608,49 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
|
1357
2608
|
|
1358
2609
|
void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
1359
2610
|
switch (expr->op()) {
|
2611
|
+
case Token::DELETE: {
|
2612
|
+
Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
|
2613
|
+
Property* prop = expr->expression()->AsProperty();
|
2614
|
+
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
|
2615
|
+
if (prop == NULL && var == NULL) {
|
2616
|
+
// Result of deleting non-property, non-variable reference is true.
|
2617
|
+
// The subexpression may have side effects.
|
2618
|
+
VisitForEffect(expr->expression());
|
2619
|
+
Apply(context_, true);
|
2620
|
+
} else if (var != NULL &&
|
2621
|
+
!var->is_global() &&
|
2622
|
+
var->slot() != NULL &&
|
2623
|
+
var->slot()->type() != Slot::LOOKUP) {
|
2624
|
+
// Result of deleting non-global, non-dynamic variables is false.
|
2625
|
+
// The subexpression does not have side effects.
|
2626
|
+
Apply(context_, false);
|
2627
|
+
} else {
|
2628
|
+
// Property or variable reference. Call the delete builtin with
|
2629
|
+
// object and property name as arguments.
|
2630
|
+
if (prop != NULL) {
|
2631
|
+
VisitForValue(prop->obj(), kStack);
|
2632
|
+
VisitForValue(prop->key(), kStack);
|
2633
|
+
} else if (var->is_global()) {
|
2634
|
+
__ ldr(r1, CodeGenerator::GlobalObject());
|
2635
|
+
__ mov(r0, Operand(var->name()));
|
2636
|
+
__ Push(r1, r0);
|
2637
|
+
} else {
|
2638
|
+
// Non-global variable. Call the runtime to look up the context
|
2639
|
+
// where the variable was introduced.
|
2640
|
+
__ push(context_register());
|
2641
|
+
__ mov(r2, Operand(var->name()));
|
2642
|
+
__ push(r2);
|
2643
|
+
__ CallRuntime(Runtime::kLookupContext, 2);
|
2644
|
+
__ push(r0);
|
2645
|
+
__ mov(r2, Operand(var->name()));
|
2646
|
+
__ push(r2);
|
2647
|
+
}
|
2648
|
+
__ InvokeBuiltin(Builtins::DELETE, CALL_JS);
|
2649
|
+
Apply(context_, r0);
|
2650
|
+
}
|
2651
|
+
break;
|
2652
|
+
}
|
2653
|
+
|
1360
2654
|
case Token::VOID: {
|
1361
2655
|
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
1362
2656
|
VisitForEffect(expr->expression());
|
@@ -1397,33 +2691,15 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1397
2691
|
|
1398
2692
|
case Token::NOT: {
|
1399
2693
|
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
|
1400
|
-
Label materialize_true, materialize_false
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
UNREACHABLE();
|
1408
|
-
break;
|
1409
|
-
case Expression::kEffect:
|
1410
|
-
if_true = &done;
|
1411
|
-
if_false = &done;
|
1412
|
-
break;
|
1413
|
-
case Expression::kValue:
|
1414
|
-
if_true = &materialize_false;
|
1415
|
-
if_false = &materialize_true;
|
1416
|
-
break;
|
1417
|
-
case Expression::kTest:
|
1418
|
-
break;
|
1419
|
-
case Expression::kValueTest:
|
1420
|
-
if_false = &materialize_true;
|
1421
|
-
break;
|
1422
|
-
case Expression::kTestValue:
|
1423
|
-
if_true = &materialize_false;
|
1424
|
-
break;
|
1425
|
-
}
|
2694
|
+
Label materialize_true, materialize_false;
|
2695
|
+
Label* if_true = NULL;
|
2696
|
+
Label* if_false = NULL;
|
2697
|
+
|
2698
|
+
// Notice that the labels are swapped.
|
2699
|
+
PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
|
2700
|
+
|
1426
2701
|
VisitForControl(expr->expression(), if_true, if_false);
|
2702
|
+
|
1427
2703
|
Apply(context_, if_false, if_true); // Labels swapped.
|
1428
2704
|
break;
|
1429
2705
|
}
|
@@ -1436,18 +2712,17 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1436
2712
|
proxy->var()->is_global()) {
|
1437
2713
|
Comment cmnt(masm_, "Global variable");
|
1438
2714
|
__ ldr(r0, CodeGenerator::GlobalObject());
|
1439
|
-
__ push(r0);
|
1440
2715
|
__ mov(r2, Operand(proxy->name()));
|
1441
2716
|
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
1442
2717
|
// Use a regular load, not a contextual load, to avoid a reference
|
1443
2718
|
// error.
|
1444
2719
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
1445
|
-
__
|
2720
|
+
__ push(r0);
|
1446
2721
|
} else if (proxy != NULL &&
|
1447
2722
|
proxy->var()->slot() != NULL &&
|
1448
2723
|
proxy->var()->slot()->type() == Slot::LOOKUP) {
|
1449
2724
|
__ mov(r0, Operand(proxy->name()));
|
1450
|
-
__
|
2725
|
+
__ Push(cp, r0);
|
1451
2726
|
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
|
1452
2727
|
__ push(r0);
|
1453
2728
|
} else {
|
@@ -1475,9 +2750,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1475
2750
|
|
1476
2751
|
case Token::SUB: {
|
1477
2752
|
Comment cmt(masm_, "[ UnaryOperation (SUB)");
|
1478
|
-
bool
|
2753
|
+
bool can_overwrite =
|
1479
2754
|
(expr->expression()->AsBinaryOperation() != NULL &&
|
1480
2755
|
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
|
2756
|
+
UnaryOverwriteMode overwrite =
|
2757
|
+
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
1481
2758
|
GenericUnaryOpStub stub(Token::SUB, overwrite);
|
1482
2759
|
// GenericUnaryOpStub expects the argument to be in the
|
1483
2760
|
// accumulator register r0.
|
@@ -1489,17 +2766,18 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1489
2766
|
|
1490
2767
|
case Token::BIT_NOT: {
|
1491
2768
|
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
|
1492
|
-
bool
|
2769
|
+
bool can_overwrite =
|
1493
2770
|
(expr->expression()->AsBinaryOperation() != NULL &&
|
1494
2771
|
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
|
2772
|
+
UnaryOverwriteMode overwrite =
|
2773
|
+
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
1495
2774
|
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
|
1496
2775
|
// GenericUnaryOpStub expects the argument to be in the
|
1497
2776
|
// accumulator register r0.
|
1498
2777
|
VisitForValue(expr->expression(), kAccumulator);
|
1499
2778
|
// Avoid calling the stub for Smis.
|
1500
2779
|
Label smi, done;
|
1501
|
-
__
|
1502
|
-
__ b(eq, &smi);
|
2780
|
+
__ BranchOnSmi(result_register(), &smi);
|
1503
2781
|
// Non-smi: call stub leaving result in accumulator register.
|
1504
2782
|
__ CallStub(&stub);
|
1505
2783
|
__ b(&done);
|
@@ -1521,6 +2799,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|
1521
2799
|
|
1522
2800
|
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
1523
2801
|
Comment cmnt(masm_, "[ CountOperation");
|
2802
|
+
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
|
2803
|
+
// as the left-hand side.
|
2804
|
+
if (!expr->expression()->IsValidLeftHandSide()) {
|
2805
|
+
VisitForEffect(expr->expression());
|
2806
|
+
return;
|
2807
|
+
}
|
1524
2808
|
|
1525
2809
|
// Expression can only be a property, a global or a (parameter or local)
|
1526
2810
|
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
|
@@ -1548,19 +2832,23 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1548
2832
|
__ mov(ip, Operand(Smi::FromInt(0)));
|
1549
2833
|
__ push(ip);
|
1550
2834
|
}
|
1551
|
-
VisitForValue(prop->obj(), kStack);
|
1552
2835
|
if (assign_type == NAMED_PROPERTY) {
|
2836
|
+
// Put the object both on the stack and in the accumulator.
|
2837
|
+
VisitForValue(prop->obj(), kAccumulator);
|
2838
|
+
__ push(r0);
|
1553
2839
|
EmitNamedPropertyLoad(prop);
|
1554
2840
|
} else {
|
1555
|
-
VisitForValue(prop->
|
2841
|
+
VisitForValue(prop->obj(), kStack);
|
2842
|
+
VisitForValue(prop->key(), kAccumulator);
|
2843
|
+
__ ldr(r1, MemOperand(sp, 0));
|
2844
|
+
__ push(r0);
|
1556
2845
|
EmitKeyedPropertyLoad(prop);
|
1557
2846
|
}
|
1558
2847
|
}
|
1559
2848
|
|
1560
2849
|
// Call ToNumber only if operand is not a smi.
|
1561
2850
|
Label no_conversion;
|
1562
|
-
__
|
1563
|
-
__ b(eq, &no_conversion);
|
2851
|
+
__ BranchOnSmi(r0, &no_conversion);
|
1564
2852
|
__ push(r0);
|
1565
2853
|
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
|
1566
2854
|
__ bind(&no_conversion);
|
@@ -1604,8 +2892,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1604
2892
|
__ b(vs, &stub_call);
|
1605
2893
|
// We could eliminate this smi check if we split the code at
|
1606
2894
|
// the first smi check before calling ToNumber.
|
1607
|
-
__
|
1608
|
-
__ b(eq, &done);
|
2895
|
+
__ BranchOnSmi(r0, &done);
|
1609
2896
|
__ bind(&stub_call);
|
1610
2897
|
// Call stub. Undo operation first.
|
1611
2898
|
__ sub(r0, r0, Operand(Smi::FromInt(count_value)));
|
@@ -1620,6 +2907,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1620
2907
|
case VARIABLE:
|
1621
2908
|
if (expr->is_postfix()) {
|
1622
2909
|
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
2910
|
+
Token::ASSIGN,
|
1623
2911
|
Expression::kEffect);
|
1624
2912
|
// For all contexts except kEffect: We have the result on
|
1625
2913
|
// top of the stack.
|
@@ -1628,6 +2916,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1628
2916
|
}
|
1629
2917
|
} else {
|
1630
2918
|
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
2919
|
+
Token::ASSIGN,
|
1631
2920
|
context_);
|
1632
2921
|
}
|
1633
2922
|
break;
|
@@ -1646,15 +2935,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
1646
2935
|
break;
|
1647
2936
|
}
|
1648
2937
|
case KEYED_PROPERTY: {
|
2938
|
+
__ pop(r1); // Key.
|
2939
|
+
__ pop(r2); // Receiver.
|
1649
2940
|
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
1650
2941
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
1651
2942
|
if (expr->is_postfix()) {
|
1652
|
-
__ Drop(2); // Result is on the stack under the key and the receiver.
|
1653
2943
|
if (context_ != Expression::kEffect) {
|
1654
2944
|
ApplyTOS(context_);
|
1655
2945
|
}
|
1656
2946
|
} else {
|
1657
|
-
|
2947
|
+
Apply(context_, r0);
|
1658
2948
|
}
|
1659
2949
|
break;
|
1660
2950
|
}
|
@@ -1697,36 +2987,41 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
|
1697
2987
|
}
|
1698
2988
|
|
1699
2989
|
|
2990
|
+
void FullCodeGenerator::EmitNullCompare(bool strict,
|
2991
|
+
Register obj,
|
2992
|
+
Register null_const,
|
2993
|
+
Label* if_true,
|
2994
|
+
Label* if_false,
|
2995
|
+
Register scratch) {
|
2996
|
+
__ cmp(obj, null_const);
|
2997
|
+
if (strict) {
|
2998
|
+
__ b(eq, if_true);
|
2999
|
+
} else {
|
3000
|
+
__ b(eq, if_true);
|
3001
|
+
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
3002
|
+
__ cmp(obj, ip);
|
3003
|
+
__ b(eq, if_true);
|
3004
|
+
__ BranchOnSmi(obj, if_false);
|
3005
|
+
// It can be an undetectable object.
|
3006
|
+
__ ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
|
3007
|
+
__ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
3008
|
+
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
3009
|
+
__ b(ne, if_true);
|
3010
|
+
}
|
3011
|
+
__ jmp(if_false);
|
3012
|
+
}
|
3013
|
+
|
3014
|
+
|
1700
3015
|
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
1701
3016
|
Comment cmnt(masm_, "[ CompareOperation");
|
1702
3017
|
|
1703
3018
|
// Always perform the comparison for its control flow. Pack the result
|
1704
3019
|
// into the expression's context after the comparison is performed.
|
1705
|
-
|
1706
|
-
|
1707
|
-
Label* if_true =
|
1708
|
-
Label* if_false =
|
1709
|
-
|
1710
|
-
case Expression::kUninitialized:
|
1711
|
-
UNREACHABLE();
|
1712
|
-
break;
|
1713
|
-
case Expression::kEffect:
|
1714
|
-
if_true = &done;
|
1715
|
-
if_false = &done;
|
1716
|
-
break;
|
1717
|
-
case Expression::kValue:
|
1718
|
-
if_true = &materialize_true;
|
1719
|
-
if_false = &materialize_false;
|
1720
|
-
break;
|
1721
|
-
case Expression::kTest:
|
1722
|
-
break;
|
1723
|
-
case Expression::kValueTest:
|
1724
|
-
if_true = &materialize_true;
|
1725
|
-
break;
|
1726
|
-
case Expression::kTestValue:
|
1727
|
-
if_false = &materialize_false;
|
1728
|
-
break;
|
1729
|
-
}
|
3020
|
+
|
3021
|
+
Label materialize_true, materialize_false;
|
3022
|
+
Label* if_true = NULL;
|
3023
|
+
Label* if_false = NULL;
|
3024
|
+
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
1730
3025
|
|
1731
3026
|
VisitForValue(expr->left(), kStack);
|
1732
3027
|
switch (expr->op()) {
|
@@ -1757,10 +3052,24 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|
1757
3052
|
case Token::EQ_STRICT:
|
1758
3053
|
strict = true;
|
1759
3054
|
// Fall through
|
1760
|
-
case Token::EQ:
|
3055
|
+
case Token::EQ: {
|
1761
3056
|
cc = eq;
|
1762
3057
|
__ pop(r1);
|
3058
|
+
// If either operand is constant null we do a fast compare
|
3059
|
+
// against null.
|
3060
|
+
Literal* right_literal = expr->right()->AsLiteral();
|
3061
|
+
Literal* left_literal = expr->left()->AsLiteral();
|
3062
|
+
if (right_literal != NULL && right_literal->handle()->IsNull()) {
|
3063
|
+
EmitNullCompare(strict, r1, r0, if_true, if_false, r2);
|
3064
|
+
Apply(context_, if_true, if_false);
|
3065
|
+
return;
|
3066
|
+
} else if (left_literal != NULL && left_literal->handle()->IsNull()) {
|
3067
|
+
EmitNullCompare(strict, r0, r1, if_true, if_false, r2);
|
3068
|
+
Apply(context_, if_true, if_false);
|
3069
|
+
return;
|
3070
|
+
}
|
1763
3071
|
break;
|
3072
|
+
}
|
1764
3073
|
case Token::LT:
|
1765
3074
|
cc = lt;
|
1766
3075
|
__ pop(r1);
|
@@ -1791,14 +3100,13 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|
1791
3100
|
// before it is called.
|
1792
3101
|
Label slow_case;
|
1793
3102
|
__ orr(r2, r0, Operand(r1));
|
1794
|
-
__
|
1795
|
-
__ b(ne, &slow_case);
|
3103
|
+
__ BranchOnNotSmi(r2, &slow_case);
|
1796
3104
|
__ cmp(r1, r0);
|
1797
3105
|
__ b(cc, if_true);
|
1798
3106
|
__ jmp(if_false);
|
1799
3107
|
|
1800
3108
|
__ bind(&slow_case);
|
1801
|
-
CompareStub stub(cc, strict);
|
3109
|
+
CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
|
1802
3110
|
__ CallStub(&stub);
|
1803
3111
|
__ cmp(r0, Operand(0));
|
1804
3112
|
__ b(cc, if_true);
|
@@ -1866,3 +3174,5 @@ void FullCodeGenerator::ExitFinallyBlock() {
|
|
1866
3174
|
#undef __
|
1867
3175
|
|
1868
3176
|
} } // namespace v8::internal
|
3177
|
+
|
3178
|
+
#endif // V8_TARGET_ARCH_ARM
|