mustang 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/Isolate +9 -0
- data/README.md +6 -12
- data/Rakefile +30 -4
- data/TODO.md +9 -0
- data/ext/v8/extconf.rb +56 -0
- data/ext/v8/v8.cpp +37 -0
- data/ext/v8/v8_array.cpp +161 -0
- data/ext/v8/v8_array.h +17 -0
- data/ext/v8/v8_base.cpp +147 -0
- data/ext/v8/v8_base.h +23 -0
- data/ext/v8/v8_cast.cpp +151 -0
- data/ext/v8/v8_cast.h +64 -0
- data/ext/v8/v8_context.cpp +174 -0
- data/ext/v8/v8_context.h +12 -0
- data/ext/v8/v8_date.cpp +61 -0
- data/ext/v8/v8_date.h +16 -0
- data/ext/v8/v8_errors.cpp +147 -0
- data/ext/v8/v8_errors.h +19 -0
- data/ext/v8/v8_external.cpp +66 -0
- data/ext/v8/v8_external.h +16 -0
- data/ext/v8/v8_function.cpp +182 -0
- data/ext/v8/v8_function.h +14 -0
- data/ext/v8/v8_integer.cpp +70 -0
- data/ext/v8/v8_integer.h +16 -0
- data/ext/v8/v8_macros.h +30 -0
- data/ext/v8/v8_main.cpp +53 -0
- data/ext/v8/v8_main.h +13 -0
- data/ext/v8/v8_number.cpp +62 -0
- data/ext/v8/v8_number.h +16 -0
- data/ext/v8/v8_object.cpp +172 -0
- data/ext/v8/v8_object.h +17 -0
- data/ext/v8/v8_ref.cpp +72 -0
- data/ext/v8/v8_ref.h +43 -0
- data/ext/v8/v8_regexp.cpp +148 -0
- data/ext/v8/v8_regexp.h +16 -0
- data/ext/v8/v8_string.cpp +78 -0
- data/ext/v8/v8_string.h +16 -0
- data/ext/v8/v8_value.cpp +370 -0
- data/ext/v8/v8_value.h +19 -0
- data/gemspec.yml +2 -1
- data/lib/core_ext/class.rb +14 -0
- data/lib/core_ext/object.rb +12 -0
- data/lib/core_ext/symbol.rb +23 -0
- data/lib/mustang.rb +44 -0
- data/lib/mustang/context.rb +69 -0
- data/lib/mustang/errors.rb +36 -0
- data/lib/support/delegated.rb +25 -0
- data/lib/v8/array.rb +21 -0
- data/lib/v8/context.rb +13 -0
- data/lib/v8/date.rb +20 -0
- data/lib/v8/error.rb +15 -0
- data/lib/v8/external.rb +16 -0
- data/lib/v8/function.rb +11 -0
- data/lib/v8/integer.rb +16 -0
- data/lib/v8/number.rb +16 -0
- data/lib/v8/object.rb +66 -0
- data/lib/v8/regexp.rb +23 -0
- data/lib/v8/string.rb +27 -0
- data/mustang.gemspec +3 -0
- data/spec/core_ext/class_spec.rb +19 -0
- data/spec/core_ext/object_spec.rb +19 -0
- data/spec/core_ext/symbol_spec.rb +27 -0
- data/spec/fixtures/test1.js +2 -0
- data/spec/fixtures/test2.js +2 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/v8/array_spec.rb +88 -0
- data/spec/v8/cast_spec.rb +151 -0
- data/spec/v8/context_spec.rb +78 -0
- data/spec/v8/data_spec.rb +39 -0
- data/spec/v8/date_spec.rb +45 -0
- data/spec/v8/empty_spec.rb +27 -0
- data/spec/v8/errors_spec.rb +142 -0
- data/spec/v8/external_spec.rb +44 -0
- data/spec/v8/function_spec.rb +170 -0
- data/spec/v8/integer_spec.rb +41 -0
- data/spec/v8/main_spec.rb +18 -0
- data/spec/v8/null_spec.rb +27 -0
- data/spec/v8/number_spec.rb +40 -0
- data/spec/v8/object_spec.rb +79 -0
- data/spec/v8/primitive_spec.rb +9 -0
- data/spec/v8/regexp_spec.rb +65 -0
- data/spec/v8/string_spec.rb +48 -0
- data/spec/v8/undefined_spec.rb +27 -0
- data/spec/v8/value_spec.rb +215 -0
- data/vendor/v8/.gitignore +2 -0
- data/vendor/v8/AUTHORS +3 -1
- data/vendor/v8/ChangeLog +117 -0
- data/vendor/v8/SConstruct +334 -53
- data/vendor/v8/include/v8-debug.h +21 -11
- data/vendor/v8/include/v8-preparser.h +1 -1
- data/vendor/v8/include/v8-profiler.h +122 -43
- data/vendor/v8/include/v8-testing.h +5 -0
- data/vendor/v8/include/v8.h +171 -17
- data/vendor/v8/preparser/SConscript +38 -0
- data/vendor/v8/preparser/preparser-process.cc +77 -114
- data/vendor/v8/samples/shell.cc +232 -46
- data/vendor/v8/src/SConscript +29 -5
- data/vendor/v8/src/accessors.cc +70 -211
- data/vendor/v8/{test/cctest/test-mips.cc → src/allocation-inl.h} +15 -18
- data/vendor/v8/src/allocation.cc +0 -82
- data/vendor/v8/src/allocation.h +9 -42
- data/vendor/v8/src/api.cc +1645 -1156
- data/vendor/v8/src/api.h +76 -12
- data/vendor/v8/src/apiutils.h +0 -7
- data/vendor/v8/src/arguments.h +15 -4
- data/vendor/v8/src/arm/assembler-arm-inl.h +10 -9
- data/vendor/v8/src/arm/assembler-arm.cc +62 -23
- data/vendor/v8/src/arm/assembler-arm.h +76 -11
- data/vendor/v8/src/arm/builtins-arm.cc +39 -33
- data/vendor/v8/src/arm/code-stubs-arm.cc +1182 -402
- data/vendor/v8/src/arm/code-stubs-arm.h +20 -54
- data/vendor/v8/src/arm/codegen-arm.cc +159 -106
- data/vendor/v8/src/arm/codegen-arm.h +6 -6
- data/vendor/v8/src/arm/constants-arm.h +16 -1
- data/vendor/v8/src/arm/cpu-arm.cc +7 -5
- data/vendor/v8/src/arm/debug-arm.cc +6 -4
- data/vendor/v8/src/arm/deoptimizer-arm.cc +51 -14
- data/vendor/v8/src/arm/disasm-arm.cc +47 -15
- data/vendor/v8/src/arm/frames-arm.h +1 -1
- data/vendor/v8/src/arm/full-codegen-arm.cc +724 -408
- data/vendor/v8/src/arm/ic-arm.cc +90 -85
- data/vendor/v8/src/arm/lithium-arm.cc +140 -69
- data/vendor/v8/src/arm/lithium-arm.h +161 -46
- data/vendor/v8/src/arm/lithium-codegen-arm.cc +567 -297
- data/vendor/v8/src/arm/lithium-codegen-arm.h +21 -9
- data/vendor/v8/src/arm/lithium-gap-resolver-arm.cc +2 -0
- data/vendor/v8/src/arm/macro-assembler-arm.cc +457 -96
- data/vendor/v8/src/arm/macro-assembler-arm.h +115 -18
- data/vendor/v8/src/arm/regexp-macro-assembler-arm.cc +20 -13
- data/vendor/v8/src/arm/regexp-macro-assembler-arm.h +1 -0
- data/vendor/v8/src/arm/simulator-arm.cc +184 -101
- data/vendor/v8/src/arm/simulator-arm.h +26 -21
- data/vendor/v8/src/arm/stub-cache-arm.cc +450 -467
- data/vendor/v8/src/arm/virtual-frame-arm.cc +14 -12
- data/vendor/v8/src/arm/virtual-frame-arm.h +11 -8
- data/vendor/v8/src/array.js +35 -18
- data/vendor/v8/src/assembler.cc +186 -92
- data/vendor/v8/src/assembler.h +106 -69
- data/vendor/v8/src/ast-inl.h +5 -0
- data/vendor/v8/src/ast.cc +46 -35
- data/vendor/v8/src/ast.h +107 -50
- data/vendor/v8/src/atomicops.h +2 -0
- data/vendor/v8/src/atomicops_internals_mips_gcc.h +169 -0
- data/vendor/v8/src/bootstrapper.cc +649 -399
- data/vendor/v8/src/bootstrapper.h +94 -27
- data/vendor/v8/src/builtins.cc +359 -227
- data/vendor/v8/src/builtins.h +157 -123
- data/vendor/v8/src/checks.cc +2 -2
- data/vendor/v8/src/checks.h +4 -0
- data/vendor/v8/src/code-stubs.cc +27 -17
- data/vendor/v8/src/code-stubs.h +38 -17
- data/vendor/v8/src/codegen-inl.h +5 -1
- data/vendor/v8/src/codegen.cc +27 -17
- data/vendor/v8/src/codegen.h +9 -9
- data/vendor/v8/src/compilation-cache.cc +92 -206
- data/vendor/v8/src/compilation-cache.h +205 -30
- data/vendor/v8/src/compiler.cc +107 -120
- data/vendor/v8/src/compiler.h +17 -2
- data/vendor/v8/src/contexts.cc +22 -15
- data/vendor/v8/src/contexts.h +14 -8
- data/vendor/v8/src/conversions.cc +86 -30
- data/vendor/v8/src/counters.cc +19 -4
- data/vendor/v8/src/counters.h +28 -16
- data/vendor/v8/src/cpu-profiler-inl.h +4 -3
- data/vendor/v8/src/cpu-profiler.cc +123 -72
- data/vendor/v8/src/cpu-profiler.h +33 -19
- data/vendor/v8/src/cpu.h +2 -0
- data/vendor/v8/src/d8-debug.cc +3 -3
- data/vendor/v8/src/d8-debug.h +7 -6
- data/vendor/v8/src/d8-posix.cc +2 -0
- data/vendor/v8/src/d8.cc +22 -12
- data/vendor/v8/src/d8.gyp +3 -0
- data/vendor/v8/src/d8.js +618 -0
- data/vendor/v8/src/data-flow.h +3 -3
- data/vendor/v8/src/dateparser.h +4 -2
- data/vendor/v8/src/debug-agent.cc +10 -9
- data/vendor/v8/src/debug-agent.h +9 -11
- data/vendor/v8/src/debug-debugger.js +121 -0
- data/vendor/v8/src/debug.cc +331 -227
- data/vendor/v8/src/debug.h +248 -219
- data/vendor/v8/src/deoptimizer.cc +173 -62
- data/vendor/v8/src/deoptimizer.h +119 -19
- data/vendor/v8/src/disasm.h +3 -0
- data/vendor/v8/src/disassembler.cc +10 -9
- data/vendor/v8/src/execution.cc +185 -129
- data/vendor/v8/src/execution.h +47 -78
- data/vendor/v8/src/extensions/experimental/break-iterator.cc +250 -0
- data/vendor/v8/src/extensions/experimental/break-iterator.h +89 -0
- data/vendor/v8/src/extensions/experimental/experimental.gyp +2 -0
- data/vendor/v8/src/extensions/experimental/i18n-extension.cc +22 -2
- data/vendor/v8/src/extensions/externalize-string-extension.cc +2 -2
- data/vendor/v8/src/extensions/gc-extension.cc +1 -1
- data/vendor/v8/src/factory.cc +261 -154
- data/vendor/v8/src/factory.h +162 -158
- data/vendor/v8/src/flag-definitions.h +17 -11
- data/vendor/v8/src/frame-element.cc +0 -5
- data/vendor/v8/src/frame-element.h +9 -13
- data/vendor/v8/src/frames-inl.h +7 -0
- data/vendor/v8/src/frames.cc +56 -46
- data/vendor/v8/src/frames.h +36 -25
- data/vendor/v8/src/full-codegen.cc +15 -24
- data/vendor/v8/src/full-codegen.h +13 -41
- data/vendor/v8/src/func-name-inferrer.cc +7 -6
- data/vendor/v8/src/func-name-inferrer.h +1 -1
- data/vendor/v8/src/gdb-jit.cc +1 -0
- data/vendor/v8/src/global-handles.cc +118 -56
- data/vendor/v8/src/global-handles.h +98 -40
- data/vendor/v8/src/globals.h +2 -2
- data/vendor/v8/src/handles-inl.h +106 -9
- data/vendor/v8/src/handles.cc +220 -157
- data/vendor/v8/src/handles.h +38 -59
- data/vendor/v8/src/hashmap.h +3 -3
- data/vendor/v8/src/heap-inl.h +141 -25
- data/vendor/v8/src/heap-profiler.cc +117 -63
- data/vendor/v8/src/heap-profiler.h +38 -21
- data/vendor/v8/src/heap.cc +805 -564
- data/vendor/v8/src/heap.h +640 -594
- data/vendor/v8/src/hydrogen-instructions.cc +216 -73
- data/vendor/v8/src/hydrogen-instructions.h +259 -124
- data/vendor/v8/src/hydrogen.cc +996 -1171
- data/vendor/v8/src/hydrogen.h +163 -144
- data/vendor/v8/src/ia32/assembler-ia32-inl.h +12 -11
- data/vendor/v8/src/ia32/assembler-ia32.cc +85 -39
- data/vendor/v8/src/ia32/assembler-ia32.h +82 -16
- data/vendor/v8/src/ia32/builtins-ia32.cc +64 -58
- data/vendor/v8/src/ia32/code-stubs-ia32.cc +248 -324
- data/vendor/v8/src/ia32/code-stubs-ia32.h +3 -44
- data/vendor/v8/src/ia32/codegen-ia32.cc +217 -165
- data/vendor/v8/src/ia32/codegen-ia32.h +3 -0
- data/vendor/v8/src/ia32/cpu-ia32.cc +6 -5
- data/vendor/v8/src/ia32/debug-ia32.cc +8 -5
- data/vendor/v8/src/ia32/deoptimizer-ia32.cc +124 -14
- data/vendor/v8/src/ia32/disasm-ia32.cc +85 -62
- data/vendor/v8/src/ia32/frames-ia32.h +1 -1
- data/vendor/v8/src/ia32/full-codegen-ia32.cc +348 -435
- data/vendor/v8/src/ia32/ic-ia32.cc +91 -91
- data/vendor/v8/src/ia32/lithium-codegen-ia32.cc +500 -255
- data/vendor/v8/src/ia32/lithium-codegen-ia32.h +13 -4
- data/vendor/v8/src/ia32/lithium-gap-resolver-ia32.cc +6 -0
- data/vendor/v8/src/ia32/lithium-ia32.cc +122 -45
- data/vendor/v8/src/ia32/lithium-ia32.h +128 -41
- data/vendor/v8/src/ia32/macro-assembler-ia32.cc +109 -84
- data/vendor/v8/src/ia32/macro-assembler-ia32.h +18 -9
- data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.cc +26 -15
- data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.h +1 -0
- data/vendor/v8/src/ia32/register-allocator-ia32.cc +30 -30
- data/vendor/v8/src/ia32/simulator-ia32.h +4 -4
- data/vendor/v8/src/ia32/stub-cache-ia32.cc +383 -400
- data/vendor/v8/src/ia32/virtual-frame-ia32.cc +36 -13
- data/vendor/v8/src/ia32/virtual-frame-ia32.h +11 -5
- data/vendor/v8/src/ic-inl.h +12 -2
- data/vendor/v8/src/ic.cc +304 -221
- data/vendor/v8/src/ic.h +115 -58
- data/vendor/v8/src/interpreter-irregexp.cc +25 -21
- data/vendor/v8/src/interpreter-irregexp.h +2 -1
- data/vendor/v8/src/isolate.cc +883 -0
- data/vendor/v8/src/isolate.h +1304 -0
- data/vendor/v8/src/json.js +10 -10
- data/vendor/v8/src/jsregexp.cc +111 -80
- data/vendor/v8/src/jsregexp.h +6 -7
- data/vendor/v8/src/jump-target-heavy.cc +5 -8
- data/vendor/v8/src/jump-target-heavy.h +0 -6
- data/vendor/v8/src/jump-target-inl.h +1 -1
- data/vendor/v8/src/jump-target-light.cc +3 -3
- data/vendor/v8/src/lithium-allocator-inl.h +2 -0
- data/vendor/v8/src/lithium-allocator.cc +42 -30
- data/vendor/v8/src/lithium-allocator.h +8 -22
- data/vendor/v8/src/lithium.cc +1 -0
- data/vendor/v8/src/liveedit.cc +141 -99
- data/vendor/v8/src/liveedit.h +7 -2
- data/vendor/v8/src/liveobjectlist-inl.h +90 -0
- data/vendor/v8/src/liveobjectlist.cc +2537 -1
- data/vendor/v8/src/liveobjectlist.h +245 -35
- data/vendor/v8/src/log-utils.cc +122 -35
- data/vendor/v8/src/log-utils.h +33 -36
- data/vendor/v8/src/log.cc +299 -241
- data/vendor/v8/src/log.h +177 -110
- data/vendor/v8/src/mark-compact.cc +612 -470
- data/vendor/v8/src/mark-compact.h +153 -80
- data/vendor/v8/src/messages.cc +16 -14
- data/vendor/v8/src/messages.js +30 -7
- data/vendor/v8/src/mips/assembler-mips-inl.h +155 -35
- data/vendor/v8/src/mips/assembler-mips.cc +1093 -219
- data/vendor/v8/src/mips/assembler-mips.h +552 -153
- data/vendor/v8/src/mips/builtins-mips.cc +43 -100
- data/vendor/v8/src/mips/code-stubs-mips.cc +752 -0
- data/vendor/v8/src/mips/code-stubs-mips.h +511 -0
- data/vendor/v8/src/mips/codegen-mips-inl.h +8 -14
- data/vendor/v8/src/mips/codegen-mips.cc +672 -896
- data/vendor/v8/src/mips/codegen-mips.h +271 -69
- data/vendor/v8/src/mips/constants-mips.cc +44 -20
- data/vendor/v8/src/mips/constants-mips.h +238 -40
- data/vendor/v8/src/mips/cpu-mips.cc +20 -3
- data/vendor/v8/src/mips/debug-mips.cc +35 -7
- data/vendor/v8/src/mips/deoptimizer-mips.cc +91 -0
- data/vendor/v8/src/mips/disasm-mips.cc +329 -93
- data/vendor/v8/src/mips/frames-mips.cc +2 -50
- data/vendor/v8/src/mips/frames-mips.h +24 -9
- data/vendor/v8/src/mips/full-codegen-mips.cc +473 -23
- data/vendor/v8/src/mips/ic-mips.cc +81 -45
- data/vendor/v8/src/mips/jump-target-mips.cc +11 -106
- data/vendor/v8/src/mips/lithium-codegen-mips.h +65 -0
- data/vendor/v8/src/mips/lithium-mips.h +304 -0
- data/vendor/v8/src/mips/macro-assembler-mips.cc +2391 -390
- data/vendor/v8/src/mips/macro-assembler-mips.h +718 -121
- data/vendor/v8/src/mips/regexp-macro-assembler-mips.cc +478 -0
- data/vendor/v8/src/mips/regexp-macro-assembler-mips.h +250 -0
- data/vendor/v8/src/mips/register-allocator-mips-inl.h +0 -3
- data/vendor/v8/src/mips/register-allocator-mips.h +3 -2
- data/vendor/v8/src/mips/simulator-mips.cc +1009 -221
- data/vendor/v8/src/mips/simulator-mips.h +119 -36
- data/vendor/v8/src/mips/stub-cache-mips.cc +331 -148
- data/vendor/v8/src/mips/{fast-codegen-mips.cc → virtual-frame-mips-inl.h} +11 -30
- data/vendor/v8/src/mips/virtual-frame-mips.cc +137 -149
- data/vendor/v8/src/mips/virtual-frame-mips.h +294 -312
- data/vendor/v8/src/mirror-debugger.js +9 -8
- data/vendor/v8/src/mksnapshot.cc +2 -2
- data/vendor/v8/src/objects-debug.cc +16 -16
- data/vendor/v8/src/objects-inl.h +421 -195
- data/vendor/v8/src/objects-printer.cc +7 -7
- data/vendor/v8/src/objects-visiting.cc +1 -1
- data/vendor/v8/src/objects-visiting.h +33 -12
- data/vendor/v8/src/objects.cc +935 -658
- data/vendor/v8/src/objects.h +234 -139
- data/vendor/v8/src/parser.cc +484 -439
- data/vendor/v8/src/parser.h +35 -14
- data/vendor/v8/src/platform-cygwin.cc +173 -107
- data/vendor/v8/src/platform-freebsd.cc +224 -72
- data/vendor/v8/src/platform-linux.cc +234 -95
- data/vendor/v8/src/platform-macos.cc +215 -82
- data/vendor/v8/src/platform-nullos.cc +9 -3
- data/vendor/v8/src/platform-openbsd.cc +22 -7
- data/vendor/v8/src/platform-posix.cc +30 -5
- data/vendor/v8/src/platform-solaris.cc +120 -38
- data/vendor/v8/src/platform-tls-mac.h +62 -0
- data/vendor/v8/src/platform-tls-win32.h +62 -0
- data/vendor/v8/src/platform-tls.h +50 -0
- data/vendor/v8/src/platform-win32.cc +195 -97
- data/vendor/v8/src/platform.h +72 -15
- data/vendor/v8/src/preparse-data.cc +2 -0
- data/vendor/v8/src/preparser-api.cc +8 -2
- data/vendor/v8/src/preparser.cc +1 -1
- data/vendor/v8/src/prettyprinter.cc +43 -52
- data/vendor/v8/src/prettyprinter.h +1 -1
- data/vendor/v8/src/profile-generator-inl.h +0 -28
- data/vendor/v8/src/profile-generator.cc +942 -685
- data/vendor/v8/src/profile-generator.h +210 -176
- data/vendor/v8/src/property.cc +6 -0
- data/vendor/v8/src/property.h +14 -3
- data/vendor/v8/src/regexp-macro-assembler-irregexp.cc +1 -1
- data/vendor/v8/src/regexp-macro-assembler.cc +28 -19
- data/vendor/v8/src/regexp-macro-assembler.h +11 -6
- data/vendor/v8/src/regexp-stack.cc +18 -10
- data/vendor/v8/src/regexp-stack.h +45 -21
- data/vendor/v8/src/regexp.js +3 -3
- data/vendor/v8/src/register-allocator-inl.h +3 -3
- data/vendor/v8/src/register-allocator.cc +1 -7
- data/vendor/v8/src/register-allocator.h +5 -15
- data/vendor/v8/src/rewriter.cc +2 -1
- data/vendor/v8/src/runtime-profiler.cc +158 -128
- data/vendor/v8/src/runtime-profiler.h +131 -15
- data/vendor/v8/src/runtime.cc +2409 -1692
- data/vendor/v8/src/runtime.h +93 -17
- data/vendor/v8/src/safepoint-table.cc +3 -0
- data/vendor/v8/src/safepoint-table.h +9 -3
- data/vendor/v8/src/scanner-base.cc +21 -28
- data/vendor/v8/src/scanner-base.h +22 -11
- data/vendor/v8/src/scanner.cc +3 -5
- data/vendor/v8/src/scanner.h +4 -2
- data/vendor/v8/src/scopeinfo.cc +11 -16
- data/vendor/v8/src/scopeinfo.h +26 -15
- data/vendor/v8/src/scopes.cc +67 -37
- data/vendor/v8/src/scopes.h +26 -12
- data/vendor/v8/src/serialize.cc +193 -154
- data/vendor/v8/src/serialize.h +41 -36
- data/vendor/v8/src/small-pointer-list.h +163 -0
- data/vendor/v8/src/snapshot-common.cc +1 -1
- data/vendor/v8/src/snapshot.h +3 -1
- data/vendor/v8/src/spaces-inl.h +30 -25
- data/vendor/v8/src/spaces.cc +263 -370
- data/vendor/v8/src/spaces.h +178 -166
- data/vendor/v8/src/string-search.cc +4 -3
- data/vendor/v8/src/string-search.h +21 -20
- data/vendor/v8/src/string-stream.cc +32 -24
- data/vendor/v8/src/string.js +7 -7
- data/vendor/v8/src/stub-cache.cc +324 -248
- data/vendor/v8/src/stub-cache.h +181 -155
- data/vendor/v8/src/token.cc +3 -3
- data/vendor/v8/src/token.h +3 -3
- data/vendor/v8/src/top.cc +218 -390
- data/vendor/v8/src/type-info.cc +98 -32
- data/vendor/v8/src/type-info.h +10 -3
- data/vendor/v8/src/unicode.cc +1 -1
- data/vendor/v8/src/unicode.h +1 -1
- data/vendor/v8/src/utils.h +3 -0
- data/vendor/v8/src/v8-counters.cc +18 -11
- data/vendor/v8/src/v8-counters.h +34 -13
- data/vendor/v8/src/v8.cc +66 -121
- data/vendor/v8/src/v8.h +7 -4
- data/vendor/v8/src/v8globals.h +18 -12
- data/vendor/v8/src/{memory.h → v8memory.h} +0 -0
- data/vendor/v8/src/v8natives.js +59 -18
- data/vendor/v8/src/v8threads.cc +127 -114
- data/vendor/v8/src/v8threads.h +42 -35
- data/vendor/v8/src/v8utils.h +2 -39
- data/vendor/v8/src/variables.h +1 -1
- data/vendor/v8/src/version.cc +26 -5
- data/vendor/v8/src/version.h +4 -0
- data/vendor/v8/src/virtual-frame-heavy-inl.h +2 -4
- data/vendor/v8/src/virtual-frame-light-inl.h +5 -4
- data/vendor/v8/src/vm-state-inl.h +21 -17
- data/vendor/v8/src/vm-state.h +7 -5
- data/vendor/v8/src/win32-headers.h +1 -0
- data/vendor/v8/src/x64/assembler-x64-inl.h +12 -11
- data/vendor/v8/src/x64/assembler-x64.cc +80 -40
- data/vendor/v8/src/x64/assembler-x64.h +67 -17
- data/vendor/v8/src/x64/builtins-x64.cc +34 -33
- data/vendor/v8/src/x64/code-stubs-x64.cc +636 -377
- data/vendor/v8/src/x64/code-stubs-x64.h +14 -48
- data/vendor/v8/src/x64/codegen-x64-inl.h +1 -1
- data/vendor/v8/src/x64/codegen-x64.cc +158 -136
- data/vendor/v8/src/x64/codegen-x64.h +4 -1
- data/vendor/v8/src/x64/cpu-x64.cc +7 -5
- data/vendor/v8/src/x64/debug-x64.cc +8 -6
- data/vendor/v8/src/x64/deoptimizer-x64.cc +195 -20
- data/vendor/v8/src/x64/disasm-x64.cc +42 -23
- data/vendor/v8/src/x64/frames-x64.cc +1 -1
- data/vendor/v8/src/x64/frames-x64.h +2 -2
- data/vendor/v8/src/x64/full-codegen-x64.cc +780 -218
- data/vendor/v8/src/x64/ic-x64.cc +77 -79
- data/vendor/v8/src/x64/jump-target-x64.cc +1 -1
- data/vendor/v8/src/x64/lithium-codegen-x64.cc +698 -181
- data/vendor/v8/src/x64/lithium-codegen-x64.h +31 -6
- data/vendor/v8/src/x64/lithium-x64.cc +136 -54
- data/vendor/v8/src/x64/lithium-x64.h +142 -51
- data/vendor/v8/src/x64/macro-assembler-x64.cc +456 -187
- data/vendor/v8/src/x64/macro-assembler-x64.h +166 -34
- data/vendor/v8/src/x64/regexp-macro-assembler-x64.cc +44 -28
- data/vendor/v8/src/x64/regexp-macro-assembler-x64.h +8 -4
- data/vendor/v8/src/x64/register-allocator-x64-inl.h +3 -3
- data/vendor/v8/src/x64/register-allocator-x64.cc +12 -8
- data/vendor/v8/src/x64/simulator-x64.h +5 -5
- data/vendor/v8/src/x64/stub-cache-x64.cc +299 -344
- data/vendor/v8/src/x64/virtual-frame-x64.cc +37 -13
- data/vendor/v8/src/x64/virtual-frame-x64.h +13 -7
- data/vendor/v8/src/zone-inl.h +49 -3
- data/vendor/v8/src/zone.cc +42 -41
- data/vendor/v8/src/zone.h +37 -34
- data/vendor/v8/test/benchmarks/testcfg.py +100 -0
- data/vendor/v8/test/cctest/SConscript +5 -4
- data/vendor/v8/test/cctest/cctest.h +3 -2
- data/vendor/v8/test/cctest/cctest.status +6 -11
- data/vendor/v8/test/cctest/test-accessors.cc +3 -3
- data/vendor/v8/test/cctest/test-alloc.cc +39 -33
- data/vendor/v8/test/cctest/test-api.cc +1092 -205
- data/vendor/v8/test/cctest/test-assembler-arm.cc +39 -25
- data/vendor/v8/test/cctest/test-assembler-ia32.cc +36 -37
- data/vendor/v8/test/cctest/test-assembler-mips.cc +1098 -40
- data/vendor/v8/test/cctest/test-assembler-x64.cc +32 -25
- data/vendor/v8/test/cctest/test-ast.cc +1 -0
- data/vendor/v8/test/cctest/test-circular-queue.cc +8 -5
- data/vendor/v8/test/cctest/test-compiler.cc +24 -24
- data/vendor/v8/test/cctest/test-cpu-profiler.cc +140 -5
- data/vendor/v8/test/cctest/test-dataflow.cc +1 -0
- data/vendor/v8/test/cctest/test-debug.cc +136 -77
- data/vendor/v8/test/cctest/test-decls.cc +1 -1
- data/vendor/v8/test/cctest/test-deoptimization.cc +25 -24
- data/vendor/v8/test/cctest/test-disasm-arm.cc +9 -4
- data/vendor/v8/test/cctest/test-disasm-ia32.cc +10 -8
- data/vendor/v8/test/cctest/test-func-name-inference.cc +10 -4
- data/vendor/v8/test/cctest/test-heap-profiler.cc +226 -164
- data/vendor/v8/test/cctest/test-heap.cc +240 -217
- data/vendor/v8/test/cctest/test-liveedit.cc +1 -0
- data/vendor/v8/test/cctest/test-log-stack-tracer.cc +18 -20
- data/vendor/v8/test/cctest/test-log.cc +114 -108
- data/vendor/v8/test/cctest/test-macro-assembler-x64.cc +247 -177
- data/vendor/v8/test/cctest/test-mark-compact.cc +129 -90
- data/vendor/v8/test/cctest/test-parsing.cc +15 -14
- data/vendor/v8/test/cctest/test-platform-linux.cc +1 -0
- data/vendor/v8/test/cctest/test-platform-tls.cc +66 -0
- data/vendor/v8/test/cctest/test-platform-win32.cc +1 -0
- data/vendor/v8/test/cctest/test-profile-generator.cc +1 -1
- data/vendor/v8/test/cctest/test-regexp.cc +53 -41
- data/vendor/v8/test/cctest/test-reloc-info.cc +18 -11
- data/vendor/v8/test/cctest/test-serialize.cc +44 -43
- data/vendor/v8/test/cctest/test-sockets.cc +8 -3
- data/vendor/v8/test/cctest/test-spaces.cc +47 -29
- data/vendor/v8/test/cctest/test-strings.cc +20 -20
- data/vendor/v8/test/cctest/test-thread-termination.cc +8 -3
- data/vendor/v8/test/cctest/test-threads.cc +5 -3
- data/vendor/v8/test/cctest/test-utils.cc +5 -4
- data/vendor/v8/test/cctest/testcfg.py +7 -3
- data/vendor/v8/test/es5conform/es5conform.status +2 -77
- data/vendor/v8/test/es5conform/testcfg.py +1 -1
- data/vendor/v8/test/message/testcfg.py +1 -1
- data/vendor/v8/test/mjsunit/accessors-on-global-object.js +3 -3
- data/vendor/v8/test/mjsunit/array-concat.js +43 -1
- data/vendor/v8/test/mjsunit/array-join.js +25 -0
- data/vendor/v8/test/mjsunit/bitops-info.js +7 -1
- data/vendor/v8/test/mjsunit/compiler/array-length.js +2 -2
- data/vendor/v8/test/mjsunit/compiler/global-accessors.js +47 -0
- data/vendor/v8/test/mjsunit/compiler/pic.js +1 -1
- data/vendor/v8/test/mjsunit/compiler/regress-loadfield.js +65 -0
- data/vendor/v8/test/mjsunit/math-sqrt.js +5 -1
- data/vendor/v8/test/mjsunit/mjsunit.js +59 -8
- data/vendor/v8/test/mjsunit/mjsunit.status +0 -12
- data/vendor/v8/test/mjsunit/mul-exhaustive.js +129 -11
- data/vendor/v8/test/mjsunit/negate-zero.js +1 -1
- data/vendor/v8/test/mjsunit/object-freeze.js +5 -13
- data/vendor/v8/test/mjsunit/object-prevent-extensions.js +9 -50
- data/vendor/v8/test/mjsunit/object-seal.js +4 -13
- data/vendor/v8/test/mjsunit/override-eval-with-non-function.js +36 -0
- data/vendor/v8/test/mjsunit/regress/regress-1145.js +54 -0
- data/vendor/v8/test/mjsunit/regress/regress-1172-bis.js +37 -0
- data/vendor/v8/test/mjsunit/regress/regress-1181.js +54 -0
- data/vendor/v8/test/mjsunit/regress/regress-1207.js +35 -0
- data/vendor/v8/test/mjsunit/regress/regress-1209.js +34 -0
- data/vendor/v8/test/mjsunit/regress/regress-1210.js +48 -0
- data/vendor/v8/test/mjsunit/regress/regress-1213.js +43 -0
- data/vendor/v8/test/mjsunit/regress/regress-1218.js +29 -0
- data/vendor/v8/test/mjsunit/regress/regress-1229.js +79 -0
- data/vendor/v8/test/mjsunit/regress/regress-1233.js +47 -0
- data/vendor/v8/test/mjsunit/regress/regress-1236.js +34 -0
- data/vendor/v8/test/mjsunit/regress/regress-1237.js +36 -0
- data/vendor/v8/test/mjsunit/regress/regress-1240.js +39 -0
- data/vendor/v8/test/mjsunit/regress/regress-1257.js +58 -0
- data/vendor/v8/test/mjsunit/regress/regress-1278.js +69 -0
- data/vendor/v8/test/mjsunit/regress/regress-create-exception.js +1 -0
- data/vendor/v8/test/mjsunit/regress/regress-lazy-deopt-reloc.js +52 -0
- data/vendor/v8/test/mjsunit/sin-cos.js +15 -10
- data/vendor/v8/test/mjsunit/smi-negative-zero.js +2 -2
- data/vendor/v8/test/mjsunit/str-to-num.js +1 -1
- data/vendor/v8/test/mjsunit/strict-mode.js +435 -0
- data/vendor/v8/test/mjsunit/testcfg.py +23 -6
- data/vendor/v8/test/mozilla/mozilla.status +0 -2
- data/vendor/v8/test/mozilla/testcfg.py +1 -1
- data/vendor/v8/test/preparser/empty.js +28 -0
- data/vendor/v8/test/preparser/functions-only.js +38 -0
- data/vendor/v8/test/preparser/non-alphanum.js +34 -0
- data/vendor/v8/test/preparser/symbols-only.js +49 -0
- data/vendor/v8/test/preparser/testcfg.py +90 -0
- data/vendor/v8/test/sputnik/testcfg.py +1 -1
- data/vendor/v8/test/test262/README +16 -0
- data/vendor/v8/test/test262/harness-adapt.js +80 -0
- data/vendor/v8/test/test262/test262.status +1506 -0
- data/vendor/v8/test/test262/testcfg.py +123 -0
- data/vendor/v8/tools/freebsd-tick-processor +10 -0
- data/vendor/v8/tools/gyp/v8.gyp +8 -33
- data/vendor/v8/tools/linux-tick-processor +5 -3
- data/vendor/v8/tools/test.py +37 -14
- data/vendor/v8/tools/tickprocessor.js +22 -8
- data/vendor/v8/tools/visual_studio/v8_base.vcproj +13 -1
- data/vendor/v8/tools/visual_studio/v8_base_arm.vcproj +5 -1
- data/vendor/v8/tools/visual_studio/v8_base_x64.vcproj +5 -1
- data/vendor/v8/tools/visual_studio/x64.vsprops +1 -0
- metadata +1495 -1341
- data/ext/extconf.rb +0 -22
- data/ext/mustang.cpp +0 -58
- data/vendor/v8/src/top.h +0 -608
@@ -68,7 +68,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|
68
68
|
// JumpToExternalReference expects r0 to contain the number of arguments
|
69
69
|
// including the receiver and the extra arguments.
|
70
70
|
__ add(r0, r0, Operand(num_extra_args + 1));
|
71
|
-
__ JumpToExternalReference(ExternalReference(id));
|
71
|
+
__ JumpToExternalReference(ExternalReference(id, masm->isolate()));
|
72
72
|
}
|
73
73
|
|
74
74
|
|
@@ -310,6 +310,7 @@ static void AllocateJSArray(MacroAssembler* masm,
|
|
310
310
|
// construct call and normal call.
|
311
311
|
static void ArrayNativeCode(MacroAssembler* masm,
|
312
312
|
Label* call_generic_code) {
|
313
|
+
Counters* counters = masm->isolate()->counters();
|
313
314
|
Label argc_one_or_more, argc_two_or_more;
|
314
315
|
|
315
316
|
// Check for array construction with zero arguments or one.
|
@@ -325,7 +326,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
|
|
325
326
|
r5,
|
326
327
|
JSArray::kPreallocatedArrayElements,
|
327
328
|
call_generic_code);
|
328
|
-
__ IncrementCounter(
|
329
|
+
__ IncrementCounter(counters->array_function_native(), 1, r3, r4);
|
329
330
|
// Setup return value, remove receiver from stack and return.
|
330
331
|
__ mov(r0, r2);
|
331
332
|
__ add(sp, sp, Operand(kPointerSize));
|
@@ -361,7 +362,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
|
|
361
362
|
r7,
|
362
363
|
true,
|
363
364
|
call_generic_code);
|
364
|
-
__ IncrementCounter(
|
365
|
+
__ IncrementCounter(counters->array_function_native(), 1, r2, r4);
|
365
366
|
// Setup return value, remove receiver and argument from stack and return.
|
366
367
|
__ mov(r0, r3);
|
367
368
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
@@ -385,7 +386,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
|
|
385
386
|
r7,
|
386
387
|
false,
|
387
388
|
call_generic_code);
|
388
|
-
__ IncrementCounter(
|
389
|
+
__ IncrementCounter(counters->array_function_native(), 1, r2, r6);
|
389
390
|
|
390
391
|
// Fill arguments as array elements. Copy from the top of the stack (last
|
391
392
|
// element) to the array backing store filling it backwards. Note:
|
@@ -428,7 +429,7 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
|
|
428
429
|
GenerateLoadArrayFunction(masm, r1);
|
429
430
|
|
430
431
|
if (FLAG_debug_code) {
|
431
|
-
// Initial map for the builtin Array
|
432
|
+
// Initial map for the builtin Array functions should be maps.
|
432
433
|
__ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
|
433
434
|
__ tst(r2, Operand(kSmiTagMask));
|
434
435
|
__ Assert(ne, "Unexpected initial map for Array function");
|
@@ -442,8 +443,9 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
|
|
442
443
|
// Jump to the generic array code if the specialized code cannot handle
|
443
444
|
// the construction.
|
444
445
|
__ bind(&generic_array_code);
|
445
|
-
|
446
|
-
Handle<Code> array_code
|
446
|
+
|
447
|
+
Handle<Code> array_code =
|
448
|
+
masm->isolate()->builtins()->ArrayCodeGeneric();
|
447
449
|
__ Jump(array_code, RelocInfo::CODE_TARGET);
|
448
450
|
}
|
449
451
|
|
@@ -458,11 +460,8 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
|
|
458
460
|
Label generic_constructor;
|
459
461
|
|
460
462
|
if (FLAG_debug_code) {
|
461
|
-
// The array construct code is only set for the builtin
|
462
|
-
// always have a map.
|
463
|
-
GenerateLoadArrayFunction(masm, r2);
|
464
|
-
__ cmp(r1, r2);
|
465
|
-
__ Assert(eq, "Unexpected Array function");
|
463
|
+
// The array construct code is only set for the builtin and internal
|
464
|
+
// Array functions which always have a map.
|
466
465
|
// Initial map for the builtin Array function should be a map.
|
467
466
|
__ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
|
468
467
|
__ tst(r2, Operand(kSmiTagMask));
|
@@ -477,8 +476,8 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
|
|
477
476
|
// Jump to the generic construct code in case the specialized code cannot
|
478
477
|
// handle the construction.
|
479
478
|
__ bind(&generic_constructor);
|
480
|
-
Code
|
481
|
-
|
479
|
+
Handle<Code> generic_construct_stub =
|
480
|
+
masm->isolate()->builtins()->JSConstructStubGeneric();
|
482
481
|
__ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
|
483
482
|
}
|
484
483
|
|
@@ -491,7 +490,8 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
|
491
490
|
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
|
492
491
|
// -- sp[argc * 4] : receiver
|
493
492
|
// -----------------------------------
|
494
|
-
|
493
|
+
Counters* counters = masm->isolate()->counters();
|
494
|
+
__ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3);
|
495
495
|
|
496
496
|
Register function = r1;
|
497
497
|
if (FLAG_debug_code) {
|
@@ -521,7 +521,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
|
521
521
|
r5, // Scratch.
|
522
522
|
false, // Is it a Smi?
|
523
523
|
¬_cached);
|
524
|
-
__ IncrementCounter(
|
524
|
+
__ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4);
|
525
525
|
__ bind(&argument_is_string);
|
526
526
|
|
527
527
|
// ----------- S t a t e -------------
|
@@ -575,13 +575,13 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
|
575
575
|
__ tst(r3, Operand(kIsNotStringMask));
|
576
576
|
__ b(ne, &convert_argument);
|
577
577
|
__ mov(argument, r0);
|
578
|
-
__ IncrementCounter(
|
578
|
+
__ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
|
579
579
|
__ b(&argument_is_string);
|
580
580
|
|
581
581
|
// Invoke the conversion builtin and put the result into r2.
|
582
582
|
__ bind(&convert_argument);
|
583
583
|
__ push(function); // Preserve the function.
|
584
|
-
__ IncrementCounter(
|
584
|
+
__ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
|
585
585
|
__ EnterInternalFrame();
|
586
586
|
__ push(r0);
|
587
587
|
__ InvokeBuiltin(Builtins::TO_STRING, CALL_JS);
|
@@ -600,7 +600,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
|
600
600
|
// At this point the argument is already a string. Call runtime to
|
601
601
|
// create a string wrapper.
|
602
602
|
__ bind(&gc_required);
|
603
|
-
__ IncrementCounter(
|
603
|
+
__ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4);
|
604
604
|
__ EnterInternalFrame();
|
605
605
|
__ push(argument);
|
606
606
|
__ CallRuntime(Runtime::kNewStringWrapper, 1);
|
@@ -636,7 +636,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
|
636
636
|
// Set expected number of arguments to zero (not changing r0).
|
637
637
|
__ mov(r2, Operand(0, RelocInfo::NONE));
|
638
638
|
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
|
639
|
-
__ Jump(
|
639
|
+
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
|
640
640
|
RelocInfo::CODE_TARGET);
|
641
641
|
}
|
642
642
|
|
@@ -647,6 +647,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|
647
647
|
// Should never count constructions for api objects.
|
648
648
|
ASSERT(!is_api_function || !count_constructions);
|
649
649
|
|
650
|
+
Isolate* isolate = masm->isolate();
|
651
|
+
|
650
652
|
// Enter a construct frame.
|
651
653
|
__ EnterConstructFrame();
|
652
654
|
|
@@ -662,7 +664,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|
662
664
|
Label undo_allocation;
|
663
665
|
#ifdef ENABLE_DEBUGGER_SUPPORT
|
664
666
|
ExternalReference debug_step_in_fp =
|
665
|
-
ExternalReference::debug_step_in_fp_address();
|
667
|
+
ExternalReference::debug_step_in_fp_address(isolate);
|
666
668
|
__ mov(r2, Operand(debug_step_in_fp));
|
667
669
|
__ ldr(r2, MemOperand(r2));
|
668
670
|
__ tst(r2, r2);
|
@@ -908,8 +910,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|
908
910
|
// r1: constructor function
|
909
911
|
if (is_api_function) {
|
910
912
|
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
|
911
|
-
Handle<Code> code =
|
912
|
-
|
913
|
+
Handle<Code> code =
|
914
|
+
masm->isolate()->builtins()->HandleApiCallConstruct();
|
913
915
|
ParameterCount expected(0);
|
914
916
|
__ InvokeCode(code, expected, expected,
|
915
917
|
RelocInfo::CODE_TARGET, CALL_FUNCTION);
|
@@ -966,7 +968,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|
966
968
|
__ LeaveConstructFrame();
|
967
969
|
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
|
968
970
|
__ add(sp, sp, Operand(kPointerSize));
|
969
|
-
__ IncrementCounter(
|
971
|
+
__ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
|
970
972
|
__ Jump(lr);
|
971
973
|
}
|
972
974
|
|
@@ -1006,7 +1008,8 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
|
1006
1008
|
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
|
1007
1009
|
|
1008
1010
|
// Set up the roots register.
|
1009
|
-
ExternalReference roots_address =
|
1011
|
+
ExternalReference roots_address =
|
1012
|
+
ExternalReference::roots_address(masm->isolate());
|
1010
1013
|
__ mov(r10, Operand(roots_address));
|
1011
1014
|
|
1012
1015
|
// Push the function and the receiver onto the stack.
|
@@ -1042,7 +1045,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
|
1042
1045
|
// Invoke the code and pass argc as r0.
|
1043
1046
|
__ mov(r0, Operand(r3));
|
1044
1047
|
if (is_construct) {
|
1045
|
-
__ Call(
|
1048
|
+
__ Call(masm->isolate()->builtins()->JSConstructCall(),
|
1046
1049
|
RelocInfo::CODE_TARGET);
|
1047
1050
|
} else {
|
1048
1051
|
ParameterCount actual(r0);
|
@@ -1170,9 +1173,11 @@ void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
|
|
1170
1173
|
|
1171
1174
|
|
1172
1175
|
void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
+
CpuFeatures::TryForceFeatureScope scope(VFP3);
|
1177
|
+
if (!CpuFeatures::IsSupported(VFP3)) {
|
1178
|
+
__ Abort("Unreachable code: Cannot optimize without VFP3 support.");
|
1179
|
+
return;
|
1180
|
+
}
|
1176
1181
|
|
1177
1182
|
// Lookup the function in the JavaScript frame and push it as an
|
1178
1183
|
// argument to the on-stack replacement function.
|
@@ -1335,8 +1340,8 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|
1335
1340
|
// Expected number of arguments is 0 for CALL_NON_FUNCTION.
|
1336
1341
|
__ mov(r2, Operand(0, RelocInfo::NONE));
|
1337
1342
|
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
|
1338
|
-
__ Jump(
|
1339
|
-
|
1343
|
+
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
|
1344
|
+
RelocInfo::CODE_TARGET);
|
1340
1345
|
__ bind(&function);
|
1341
1346
|
}
|
1342
1347
|
|
@@ -1351,8 +1356,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|
1351
1356
|
__ mov(r2, Operand(r2, ASR, kSmiTagSize));
|
1352
1357
|
__ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
|
1353
1358
|
__ cmp(r2, r0); // Check formal and actual parameter counts.
|
1354
|
-
__ Jump(
|
1355
|
-
RelocInfo::CODE_TARGET,
|
1359
|
+
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
|
1360
|
+
RelocInfo::CODE_TARGET,
|
1361
|
+
ne);
|
1356
1362
|
|
1357
1363
|
ParameterCount expected(0);
|
1358
1364
|
__ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
|
@@ -91,11 +91,15 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
|
|
91
91
|
&gc,
|
92
92
|
TAG_OBJECT);
|
93
93
|
|
94
|
+
int map_index = strict_mode_ == kStrictMode
|
95
|
+
? Context::STRICT_MODE_FUNCTION_MAP_INDEX
|
96
|
+
: Context::FUNCTION_MAP_INDEX;
|
97
|
+
|
94
98
|
// Compute the function map in the current global context and set that
|
95
99
|
// as the map of the allocated object.
|
96
100
|
__ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
|
97
101
|
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
|
98
|
-
__ ldr(r2, MemOperand(r2, Context::SlotOffset(
|
102
|
+
__ ldr(r2, MemOperand(r2, Context::SlotOffset(map_index)));
|
99
103
|
__ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
|
100
104
|
|
101
105
|
// Initialize the rest of the function. We don't have to update the
|
@@ -397,17 +401,88 @@ class FloatingPointHelper : public AllStatic {
|
|
397
401
|
Register scratch2,
|
398
402
|
Label* not_number);
|
399
403
|
|
400
|
-
//
|
401
|
-
//
|
402
|
-
//
|
403
|
-
static void
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
404
|
+
// Convert the smi or heap number in object to an int32 using the rules
|
405
|
+
// for ToInt32 as described in ECMAScript 9.5.: the value is truncated
|
406
|
+
// and brought into the range -2^31 .. +2^31 - 1.
|
407
|
+
static void ConvertNumberToInt32(MacroAssembler* masm,
|
408
|
+
Register object,
|
409
|
+
Register dst,
|
410
|
+
Register heap_number_map,
|
411
|
+
Register scratch1,
|
412
|
+
Register scratch2,
|
413
|
+
Register scratch3,
|
414
|
+
DwVfpRegister double_scratch,
|
415
|
+
Label* not_int32);
|
416
|
+
|
417
|
+
// Load the number from object into double_dst in the double format.
|
418
|
+
// Control will jump to not_int32 if the value cannot be exactly represented
|
419
|
+
// by a 32-bit integer.
|
420
|
+
// Floating point value in the 32-bit integer range that are not exact integer
|
421
|
+
// won't be loaded.
|
422
|
+
static void LoadNumberAsInt32Double(MacroAssembler* masm,
|
423
|
+
Register object,
|
424
|
+
Destination destination,
|
425
|
+
DwVfpRegister double_dst,
|
426
|
+
Register dst1,
|
427
|
+
Register dst2,
|
428
|
+
Register heap_number_map,
|
429
|
+
Register scratch1,
|
430
|
+
Register scratch2,
|
431
|
+
SwVfpRegister single_scratch,
|
432
|
+
Label* not_int32);
|
433
|
+
|
434
|
+
// Loads the number from object into dst as a 32-bit integer.
|
435
|
+
// Control will jump to not_int32 if the object cannot be exactly represented
|
436
|
+
// by a 32-bit integer.
|
437
|
+
// Floating point value in the 32-bit integer range that are not exact integer
|
438
|
+
// won't be converted.
|
439
|
+
// scratch3 is not used when VFP3 is supported.
|
440
|
+
static void LoadNumberAsInt32(MacroAssembler* masm,
|
441
|
+
Register object,
|
442
|
+
Register dst,
|
443
|
+
Register heap_number_map,
|
444
|
+
Register scratch1,
|
445
|
+
Register scratch2,
|
446
|
+
Register scratch3,
|
447
|
+
DwVfpRegister double_scratch,
|
448
|
+
Label* not_int32);
|
449
|
+
|
450
|
+
// Generate non VFP3 code to check if a double can be exactly represented by a
|
451
|
+
// 32-bit integer. This does not check for 0 or -0, which need
|
452
|
+
// to be checked for separately.
|
453
|
+
// Control jumps to not_int32 if the value is not a 32-bit integer, and falls
|
454
|
+
// through otherwise.
|
455
|
+
// src1 and src2 will be cloberred.
|
456
|
+
//
|
457
|
+
// Expected input:
|
458
|
+
// - src1: higher (exponent) part of the double value.
|
459
|
+
// - src2: lower (mantissa) part of the double value.
|
460
|
+
// Output status:
|
461
|
+
// - dst: 32 higher bits of the mantissa. (mantissa[51:20])
|
462
|
+
// - src2: contains 1.
|
463
|
+
// - other registers are clobbered.
|
464
|
+
static void DoubleIs32BitInteger(MacroAssembler* masm,
|
465
|
+
Register src1,
|
466
|
+
Register src2,
|
467
|
+
Register dst,
|
468
|
+
Register scratch,
|
469
|
+
Label* not_int32);
|
470
|
+
|
471
|
+
// Generates code to call a C function to do a double operation using core
|
472
|
+
// registers. (Used when VFP3 is not supported.)
|
473
|
+
// This code never falls through, but returns with a heap number containing
|
474
|
+
// the result in r0.
|
475
|
+
// Register heapnumber_result must be a heap number in which the
|
476
|
+
// result of the operation will be stored.
|
477
|
+
// Requires the following layout on entry:
|
478
|
+
// r0: Left value (least significant part of mantissa).
|
479
|
+
// r1: Left value (sign, exponent, top of mantissa).
|
480
|
+
// r2: Right value (least significant part of mantissa).
|
481
|
+
// r3: Right value (sign, exponent, top of mantissa).
|
482
|
+
static void CallCCodeForDoubleOperation(MacroAssembler* masm,
|
483
|
+
Token::Value op,
|
484
|
+
Register heap_number_result,
|
485
|
+
Register scratch);
|
411
486
|
|
412
487
|
private:
|
413
488
|
static void LoadNumber(MacroAssembler* masm,
|
@@ -495,7 +570,8 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
|
|
495
570
|
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
|
496
571
|
|
497
572
|
// Handle loading a double from a heap number.
|
498
|
-
if (CpuFeatures::IsSupported(VFP3) &&
|
573
|
+
if (CpuFeatures::IsSupported(VFP3) &&
|
574
|
+
destination == kVFPRegisters) {
|
499
575
|
CpuFeatures::Scope scope(VFP3);
|
500
576
|
// Load the double from tagged HeapNumber to double register.
|
501
577
|
__ sub(scratch1, object, Operand(kHeapObjectTag));
|
@@ -533,33 +609,365 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
|
|
533
609
|
}
|
534
610
|
|
535
611
|
|
536
|
-
void FloatingPointHelper::
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
612
|
+
void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
|
613
|
+
Register object,
|
614
|
+
Register dst,
|
615
|
+
Register heap_number_map,
|
616
|
+
Register scratch1,
|
617
|
+
Register scratch2,
|
618
|
+
Register scratch3,
|
619
|
+
DwVfpRegister double_scratch,
|
620
|
+
Label* not_number) {
|
544
621
|
if (FLAG_debug_code) {
|
545
622
|
__ AbortIfNotRootValue(heap_number_map,
|
546
623
|
Heap::kHeapNumberMapRootIndex,
|
547
624
|
"HeapNumberMap register clobbered.");
|
548
625
|
}
|
549
|
-
Label is_smi
|
626
|
+
Label is_smi;
|
627
|
+
Label done;
|
628
|
+
Label not_in_int32_range;
|
629
|
+
|
550
630
|
__ JumpIfSmi(object, &is_smi);
|
551
631
|
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
|
552
632
|
__ cmp(scratch1, heap_number_map);
|
553
|
-
__ b(ne,
|
554
|
-
__ ConvertToInt32(
|
555
|
-
|
633
|
+
__ b(ne, not_number);
|
634
|
+
__ ConvertToInt32(object,
|
635
|
+
dst,
|
636
|
+
scratch1,
|
637
|
+
scratch2,
|
638
|
+
double_scratch,
|
639
|
+
¬_in_int32_range);
|
556
640
|
__ jmp(&done);
|
641
|
+
|
642
|
+
__ bind(¬_in_int32_range);
|
643
|
+
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
|
644
|
+
__ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
|
645
|
+
|
646
|
+
__ EmitOutOfInt32RangeTruncate(dst,
|
647
|
+
scratch1,
|
648
|
+
scratch2,
|
649
|
+
scratch3);
|
650
|
+
__ jmp(&done);
|
651
|
+
|
557
652
|
__ bind(&is_smi);
|
558
653
|
__ SmiUntag(dst, object);
|
559
654
|
__ bind(&done);
|
560
655
|
}
|
561
656
|
|
562
657
|
|
658
|
+
void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
|
659
|
+
Register object,
|
660
|
+
Destination destination,
|
661
|
+
DwVfpRegister double_dst,
|
662
|
+
Register dst1,
|
663
|
+
Register dst2,
|
664
|
+
Register heap_number_map,
|
665
|
+
Register scratch1,
|
666
|
+
Register scratch2,
|
667
|
+
SwVfpRegister single_scratch,
|
668
|
+
Label* not_int32) {
|
669
|
+
ASSERT(!scratch1.is(object) && !scratch2.is(object));
|
670
|
+
ASSERT(!scratch1.is(scratch2));
|
671
|
+
ASSERT(!heap_number_map.is(object) &&
|
672
|
+
!heap_number_map.is(scratch1) &&
|
673
|
+
!heap_number_map.is(scratch2));
|
674
|
+
|
675
|
+
Label done, obj_is_not_smi;
|
676
|
+
|
677
|
+
__ JumpIfNotSmi(object, &obj_is_not_smi);
|
678
|
+
__ SmiUntag(scratch1, object);
|
679
|
+
if (CpuFeatures::IsSupported(VFP3)) {
|
680
|
+
CpuFeatures::Scope scope(VFP3);
|
681
|
+
__ vmov(single_scratch, scratch1);
|
682
|
+
__ vcvt_f64_s32(double_dst, single_scratch);
|
683
|
+
if (destination == kCoreRegisters) {
|
684
|
+
__ vmov(dst1, dst2, double_dst);
|
685
|
+
}
|
686
|
+
} else {
|
687
|
+
Label fewer_than_20_useful_bits;
|
688
|
+
// Expected output:
|
689
|
+
// | dst1 | dst2 |
|
690
|
+
// | s | exp | mantissa |
|
691
|
+
|
692
|
+
// Check for zero.
|
693
|
+
__ cmp(scratch1, Operand(0));
|
694
|
+
__ mov(dst1, scratch1);
|
695
|
+
__ mov(dst2, scratch1);
|
696
|
+
__ b(eq, &done);
|
697
|
+
|
698
|
+
// Preload the sign of the value.
|
699
|
+
__ and_(dst1, scratch1, Operand(HeapNumber::kSignMask), SetCC);
|
700
|
+
// Get the absolute value of the object (as an unsigned integer).
|
701
|
+
__ rsb(scratch1, scratch1, Operand(0), SetCC, mi);
|
702
|
+
|
703
|
+
// Get mantisssa[51:20].
|
704
|
+
|
705
|
+
// Get the position of the first set bit.
|
706
|
+
__ CountLeadingZeros(dst2, scratch1, scratch2);
|
707
|
+
__ rsb(dst2, dst2, Operand(31));
|
708
|
+
|
709
|
+
// Set the exponent.
|
710
|
+
__ add(scratch2, dst2, Operand(HeapNumber::kExponentBias));
|
711
|
+
__ Bfi(dst1, scratch2, scratch2,
|
712
|
+
HeapNumber::kExponentShift, HeapNumber::kExponentBits);
|
713
|
+
|
714
|
+
// Clear the first non null bit.
|
715
|
+
__ mov(scratch2, Operand(1));
|
716
|
+
__ bic(scratch1, scratch1, Operand(scratch2, LSL, dst2));
|
717
|
+
|
718
|
+
__ cmp(dst2, Operand(HeapNumber::kMantissaBitsInTopWord));
|
719
|
+
// Get the number of bits to set in the lower part of the mantissa.
|
720
|
+
__ sub(scratch2, dst2, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
|
721
|
+
__ b(mi, &fewer_than_20_useful_bits);
|
722
|
+
// Set the higher 20 bits of the mantissa.
|
723
|
+
__ orr(dst1, dst1, Operand(scratch1, LSR, scratch2));
|
724
|
+
__ rsb(scratch2, scratch2, Operand(32));
|
725
|
+
__ mov(dst2, Operand(scratch1, LSL, scratch2));
|
726
|
+
__ b(&done);
|
727
|
+
|
728
|
+
__ bind(&fewer_than_20_useful_bits);
|
729
|
+
__ rsb(scratch2, dst2, Operand(HeapNumber::kMantissaBitsInTopWord));
|
730
|
+
__ mov(scratch2, Operand(scratch1, LSL, scratch2));
|
731
|
+
__ orr(dst1, dst1, scratch2);
|
732
|
+
// Set dst2 to 0.
|
733
|
+
__ mov(dst2, Operand(0));
|
734
|
+
}
|
735
|
+
|
736
|
+
__ b(&done);
|
737
|
+
|
738
|
+
__ bind(&obj_is_not_smi);
|
739
|
+
if (FLAG_debug_code) {
|
740
|
+
__ AbortIfNotRootValue(heap_number_map,
|
741
|
+
Heap::kHeapNumberMapRootIndex,
|
742
|
+
"HeapNumberMap register clobbered.");
|
743
|
+
}
|
744
|
+
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
|
745
|
+
|
746
|
+
// Load the number.
|
747
|
+
if (CpuFeatures::IsSupported(VFP3)) {
|
748
|
+
CpuFeatures::Scope scope(VFP3);
|
749
|
+
// Load the double value.
|
750
|
+
__ sub(scratch1, object, Operand(kHeapObjectTag));
|
751
|
+
__ vldr(double_dst, scratch1, HeapNumber::kValueOffset);
|
752
|
+
|
753
|
+
__ EmitVFPTruncate(kRoundToZero,
|
754
|
+
single_scratch,
|
755
|
+
double_dst,
|
756
|
+
scratch1,
|
757
|
+
scratch2,
|
758
|
+
kCheckForInexactConversion);
|
759
|
+
|
760
|
+
// Jump to not_int32 if the operation did not succeed.
|
761
|
+
__ b(ne, not_int32);
|
762
|
+
|
763
|
+
if (destination == kCoreRegisters) {
|
764
|
+
__ vmov(dst1, dst2, double_dst);
|
765
|
+
}
|
766
|
+
|
767
|
+
} else {
|
768
|
+
ASSERT(!scratch1.is(object) && !scratch2.is(object));
|
769
|
+
// Load the double value in the destination registers..
|
770
|
+
__ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset));
|
771
|
+
|
772
|
+
// Check for 0 and -0.
|
773
|
+
__ bic(scratch1, dst1, Operand(HeapNumber::kSignMask));
|
774
|
+
__ orr(scratch1, scratch1, Operand(dst2));
|
775
|
+
__ cmp(scratch1, Operand(0));
|
776
|
+
__ b(eq, &done);
|
777
|
+
|
778
|
+
// Check that the value can be exactly represented by a 32-bit integer.
|
779
|
+
// Jump to not_int32 if that's not the case.
|
780
|
+
DoubleIs32BitInteger(masm, dst1, dst2, scratch1, scratch2, not_int32);
|
781
|
+
|
782
|
+
// dst1 and dst2 were trashed. Reload the double value.
|
783
|
+
__ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset));
|
784
|
+
}
|
785
|
+
|
786
|
+
__ bind(&done);
|
787
|
+
}
|
788
|
+
|
789
|
+
|
790
|
+
void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
|
791
|
+
Register object,
|
792
|
+
Register dst,
|
793
|
+
Register heap_number_map,
|
794
|
+
Register scratch1,
|
795
|
+
Register scratch2,
|
796
|
+
Register scratch3,
|
797
|
+
DwVfpRegister double_scratch,
|
798
|
+
Label* not_int32) {
|
799
|
+
ASSERT(!dst.is(object));
|
800
|
+
ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
|
801
|
+
ASSERT(!scratch1.is(scratch2) &&
|
802
|
+
!scratch1.is(scratch3) &&
|
803
|
+
!scratch2.is(scratch3));
|
804
|
+
|
805
|
+
Label done;
|
806
|
+
|
807
|
+
// Untag the object into the destination register.
|
808
|
+
__ SmiUntag(dst, object);
|
809
|
+
// Just return if the object is a smi.
|
810
|
+
__ JumpIfSmi(object, &done);
|
811
|
+
|
812
|
+
if (FLAG_debug_code) {
|
813
|
+
__ AbortIfNotRootValue(heap_number_map,
|
814
|
+
Heap::kHeapNumberMapRootIndex,
|
815
|
+
"HeapNumberMap register clobbered.");
|
816
|
+
}
|
817
|
+
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
|
818
|
+
|
819
|
+
// Object is a heap number.
|
820
|
+
// Convert the floating point value to a 32-bit integer.
|
821
|
+
if (CpuFeatures::IsSupported(VFP3)) {
|
822
|
+
CpuFeatures::Scope scope(VFP3);
|
823
|
+
SwVfpRegister single_scratch = double_scratch.low();
|
824
|
+
// Load the double value.
|
825
|
+
__ sub(scratch1, object, Operand(kHeapObjectTag));
|
826
|
+
__ vldr(double_scratch, scratch1, HeapNumber::kValueOffset);
|
827
|
+
|
828
|
+
__ EmitVFPTruncate(kRoundToZero,
|
829
|
+
single_scratch,
|
830
|
+
double_scratch,
|
831
|
+
scratch1,
|
832
|
+
scratch2,
|
833
|
+
kCheckForInexactConversion);
|
834
|
+
|
835
|
+
// Jump to not_int32 if the operation did not succeed.
|
836
|
+
__ b(ne, not_int32);
|
837
|
+
// Get the result in the destination register.
|
838
|
+
__ vmov(dst, single_scratch);
|
839
|
+
|
840
|
+
} else {
|
841
|
+
// Load the double value in the destination registers.
|
842
|
+
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
|
843
|
+
__ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
|
844
|
+
|
845
|
+
// Check for 0 and -0.
|
846
|
+
__ bic(dst, scratch1, Operand(HeapNumber::kSignMask));
|
847
|
+
__ orr(dst, scratch2, Operand(dst));
|
848
|
+
__ cmp(dst, Operand(0));
|
849
|
+
__ b(eq, &done);
|
850
|
+
|
851
|
+
DoubleIs32BitInteger(masm, scratch1, scratch2, dst, scratch3, not_int32);
|
852
|
+
|
853
|
+
// Registers state after DoubleIs32BitInteger.
|
854
|
+
// dst: mantissa[51:20].
|
855
|
+
// scratch2: 1
|
856
|
+
|
857
|
+
// Shift back the higher bits of the mantissa.
|
858
|
+
__ mov(dst, Operand(dst, LSR, scratch3));
|
859
|
+
// Set the implicit first bit.
|
860
|
+
__ rsb(scratch3, scratch3, Operand(32));
|
861
|
+
__ orr(dst, dst, Operand(scratch2, LSL, scratch3));
|
862
|
+
// Set the sign.
|
863
|
+
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
|
864
|
+
__ tst(scratch1, Operand(HeapNumber::kSignMask));
|
865
|
+
__ rsb(dst, dst, Operand(0), LeaveCC, mi);
|
866
|
+
}
|
867
|
+
|
868
|
+
__ bind(&done);
|
869
|
+
}
|
870
|
+
|
871
|
+
|
872
|
+
void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm,
|
873
|
+
Register src1,
|
874
|
+
Register src2,
|
875
|
+
Register dst,
|
876
|
+
Register scratch,
|
877
|
+
Label* not_int32) {
|
878
|
+
// Get exponent alone in scratch.
|
879
|
+
__ Ubfx(scratch,
|
880
|
+
src1,
|
881
|
+
HeapNumber::kExponentShift,
|
882
|
+
HeapNumber::kExponentBits);
|
883
|
+
|
884
|
+
// Substract the bias from the exponent.
|
885
|
+
__ sub(scratch, scratch, Operand(HeapNumber::kExponentBias), SetCC);
|
886
|
+
|
887
|
+
// src1: higher (exponent) part of the double value.
|
888
|
+
// src2: lower (mantissa) part of the double value.
|
889
|
+
// scratch: unbiased exponent.
|
890
|
+
|
891
|
+
// Fast cases. Check for obvious non 32-bit integer values.
|
892
|
+
// Negative exponent cannot yield 32-bit integers.
|
893
|
+
__ b(mi, not_int32);
|
894
|
+
// Exponent greater than 31 cannot yield 32-bit integers.
|
895
|
+
// Also, a positive value with an exponent equal to 31 is outside of the
|
896
|
+
// signed 32-bit integer range.
|
897
|
+
// Another way to put it is that if (exponent - signbit) > 30 then the
|
898
|
+
// number cannot be represented as an int32.
|
899
|
+
Register tmp = dst;
|
900
|
+
__ sub(tmp, scratch, Operand(src1, LSR, 31));
|
901
|
+
__ cmp(tmp, Operand(30));
|
902
|
+
__ b(gt, not_int32);
|
903
|
+
// - Bits [21:0] in the mantissa are not null.
|
904
|
+
__ tst(src2, Operand(0x3fffff));
|
905
|
+
__ b(ne, not_int32);
|
906
|
+
|
907
|
+
// Otherwise the exponent needs to be big enough to shift left all the
|
908
|
+
// non zero bits left. So we need the (30 - exponent) last bits of the
|
909
|
+
// 31 higher bits of the mantissa to be null.
|
910
|
+
// Because bits [21:0] are null, we can check instead that the
|
911
|
+
// (32 - exponent) last bits of the 32 higher bits of the mantisssa are null.
|
912
|
+
|
913
|
+
// Get the 32 higher bits of the mantissa in dst.
|
914
|
+
__ Ubfx(dst,
|
915
|
+
src2,
|
916
|
+
HeapNumber::kMantissaBitsInTopWord,
|
917
|
+
32 - HeapNumber::kMantissaBitsInTopWord);
|
918
|
+
__ orr(dst,
|
919
|
+
dst,
|
920
|
+
Operand(src1, LSL, HeapNumber::kNonMantissaBitsInTopWord));
|
921
|
+
|
922
|
+
// Create the mask and test the lower bits (of the higher bits).
|
923
|
+
__ rsb(scratch, scratch, Operand(32));
|
924
|
+
__ mov(src2, Operand(1));
|
925
|
+
__ mov(src1, Operand(src2, LSL, scratch));
|
926
|
+
__ sub(src1, src1, Operand(1));
|
927
|
+
__ tst(dst, src1);
|
928
|
+
__ b(ne, not_int32);
|
929
|
+
}
|
930
|
+
|
931
|
+
|
932
|
+
void FloatingPointHelper::CallCCodeForDoubleOperation(
|
933
|
+
MacroAssembler* masm,
|
934
|
+
Token::Value op,
|
935
|
+
Register heap_number_result,
|
936
|
+
Register scratch) {
|
937
|
+
// Using core registers:
|
938
|
+
// r0: Left value (least significant part of mantissa).
|
939
|
+
// r1: Left value (sign, exponent, top of mantissa).
|
940
|
+
// r2: Right value (least significant part of mantissa).
|
941
|
+
// r3: Right value (sign, exponent, top of mantissa).
|
942
|
+
|
943
|
+
// Assert that heap_number_result is callee-saved.
|
944
|
+
// We currently always use r5 to pass it.
|
945
|
+
ASSERT(heap_number_result.is(r5));
|
946
|
+
|
947
|
+
// Push the current return address before the C call. Return will be
|
948
|
+
// through pop(pc) below.
|
949
|
+
__ push(lr);
|
950
|
+
__ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments.
|
951
|
+
// Call C routine that may not cause GC or other trouble.
|
952
|
+
__ CallCFunction(ExternalReference::double_fp_operation(op, masm->isolate()),
|
953
|
+
4);
|
954
|
+
// Store answer in the overwritable heap number.
|
955
|
+
#if !defined(USE_ARM_EABI)
|
956
|
+
// Double returned in fp coprocessor register 0 and 1, encoded as
|
957
|
+
// register cr8. Offsets must be divisible by 4 for coprocessor so we
|
958
|
+
// need to substract the tag from heap_number_result.
|
959
|
+
__ sub(scratch, heap_number_result, Operand(kHeapObjectTag));
|
960
|
+
__ stc(p1, cr8, MemOperand(scratch, HeapNumber::kValueOffset));
|
961
|
+
#else
|
962
|
+
// Double returned in registers 0 and 1.
|
963
|
+
__ Strd(r0, r1, FieldMemOperand(heap_number_result,
|
964
|
+
HeapNumber::kValueOffset));
|
965
|
+
#endif
|
966
|
+
// Place heap_number_result in r0 and return to the pushed return address.
|
967
|
+
__ mov(r0, Operand(heap_number_result));
|
968
|
+
__ pop(pc);
|
969
|
+
}
|
970
|
+
|
563
971
|
|
564
972
|
// See comment for class.
|
565
973
|
void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
|
@@ -622,7 +1030,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
|
|
622
1030
|
// The two objects are identical. If we know that one of them isn't NaN then
|
623
1031
|
// we now know they test equal.
|
624
1032
|
if (cond != eq || !never_nan_nan) {
|
625
|
-
// Test for NaN. Sadly, we can't just compare to
|
1033
|
+
// Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
|
626
1034
|
// so we do the second best thing - test it ourselves.
|
627
1035
|
// They are both equal and they are not both Smis so both of them are not
|
628
1036
|
// Smis. If it's not a heap number, then return equal.
|
@@ -897,7 +1305,7 @@ static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm,
|
|
897
1305
|
// Call C routine that may not cause GC or other trouble.
|
898
1306
|
__ push(lr);
|
899
1307
|
__ PrepareCallCFunction(4, r5); // Two doubles count as 4 arguments.
|
900
|
-
__ CallCFunction(ExternalReference::compare_doubles(), 4);
|
1308
|
+
__ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), 4);
|
901
1309
|
__ pop(pc); // Return.
|
902
1310
|
}
|
903
1311
|
}
|
@@ -1050,6 +1458,7 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
|
|
1050
1458
|
// number string cache for smis is just the smi value, and the hash for
|
1051
1459
|
// doubles is the xor of the upper and lower words. See
|
1052
1460
|
// Heap::GetNumberStringCache.
|
1461
|
+
Isolate* isolate = masm->isolate();
|
1053
1462
|
Label is_smi;
|
1054
1463
|
Label load_result_from_cache;
|
1055
1464
|
if (!object_is_smi) {
|
@@ -1111,7 +1520,7 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
|
|
1111
1520
|
__ bind(&load_result_from_cache);
|
1112
1521
|
__ ldr(result,
|
1113
1522
|
FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
|
1114
|
-
__ IncrementCounter(
|
1523
|
+
__ IncrementCounter(isolate->counters()->number_to_string_native(),
|
1115
1524
|
1,
|
1116
1525
|
scratch1,
|
1117
1526
|
scratch2);
|
@@ -1187,6 +1596,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
|
1187
1596
|
__ bind(&both_loaded_as_doubles);
|
1188
1597
|
// The arguments have been converted to doubles and stored in d6 and d7, if
|
1189
1598
|
// VFP3 is supported, or in r0, r1, r2, and r3.
|
1599
|
+
Isolate* isolate = masm->isolate();
|
1190
1600
|
if (CpuFeatures::IsSupported(VFP3)) {
|
1191
1601
|
__ bind(&lhs_not_nan);
|
1192
1602
|
CpuFeatures::Scope scope(VFP3);
|
@@ -1257,7 +1667,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
|
1257
1667
|
|
1258
1668
|
__ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow);
|
1259
1669
|
|
1260
|
-
__ IncrementCounter(
|
1670
|
+
__ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3);
|
1261
1671
|
StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
|
1262
1672
|
lhs_,
|
1263
1673
|
rhs_,
|
@@ -1296,6 +1706,9 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
|
1296
1706
|
// This stub does not handle the inlined cases (Smis, Booleans, undefined).
|
1297
1707
|
// The stub returns zero for false, and a non-zero value for true.
|
1298
1708
|
void ToBooleanStub::Generate(MacroAssembler* masm) {
|
1709
|
+
// This stub uses VFP3 instructions.
|
1710
|
+
ASSERT(CpuFeatures::IsEnabled(VFP3));
|
1711
|
+
|
1299
1712
|
Label false_result;
|
1300
1713
|
Label not_heap_number;
|
1301
1714
|
Register scratch = r9.is(tos_) ? r7 : r9;
|
@@ -1380,7 +1793,9 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
|
|
1380
1793
|
Register rhs,
|
1381
1794
|
const Builtins::JavaScript& builtin) {
|
1382
1795
|
Label slow, slow_reverse, do_the_call;
|
1383
|
-
bool use_fp_registers =
|
1796
|
+
bool use_fp_registers =
|
1797
|
+
CpuFeatures::IsSupported(VFP3) &&
|
1798
|
+
Token::MOD != op_;
|
1384
1799
|
|
1385
1800
|
ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0)));
|
1386
1801
|
Register heap_number_map = r6;
|
@@ -1606,7 +2021,8 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
|
|
1606
2021
|
__ PrepareCallCFunction(4, r4); // Two doubles count as 4 arguments.
|
1607
2022
|
// Call C routine that may not cause GC or other trouble. r5 is callee
|
1608
2023
|
// save.
|
1609
|
-
__ CallCFunction(
|
2024
|
+
__ CallCFunction(
|
2025
|
+
ExternalReference::double_fp_operation(op_, masm->isolate()), 4);
|
1610
2026
|
// Store answer in the overwritable heap number.
|
1611
2027
|
#if !defined(USE_ARM_EABI)
|
1612
2028
|
// Double returned in fp coprocessor register 0 and 1, encoded as
|
@@ -2410,7 +2826,7 @@ void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|
2410
2826
|
__ Push(r2, r1, r0);
|
2411
2827
|
|
2412
2828
|
__ TailCallExternalReference(
|
2413
|
-
ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
|
2829
|
+
ExternalReference(IC_Utility(IC::kBinaryOp_Patch), masm->isolate()),
|
2414
2830
|
5,
|
2415
2831
|
1);
|
2416
2832
|
}
|
@@ -2441,7 +2857,8 @@ void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|
2441
2857
|
__ Push(r2, r1, r0);
|
2442
2858
|
|
2443
2859
|
__ TailCallExternalReference(
|
2444
|
-
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)
|
2860
|
+
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
|
2861
|
+
masm->isolate()),
|
2445
2862
|
5,
|
2446
2863
|
1);
|
2447
2864
|
}
|
@@ -2467,6 +2884,9 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
|
2467
2884
|
case TRBinaryOpIC::HEAP_NUMBER:
|
2468
2885
|
GenerateHeapNumberStub(masm);
|
2469
2886
|
break;
|
2887
|
+
case TRBinaryOpIC::ODDBALL:
|
2888
|
+
GenerateOddballStub(masm);
|
2889
|
+
break;
|
2470
2890
|
case TRBinaryOpIC::STRING:
|
2471
2891
|
GenerateStringStub(masm);
|
2472
2892
|
break;
|
@@ -2482,7 +2902,8 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
|
2482
2902
|
const char* TypeRecordingBinaryOpStub::GetName() {
|
2483
2903
|
if (name_ != NULL) return name_;
|
2484
2904
|
const int kMaxNameLength = 100;
|
2485
|
-
name_ =
|
2905
|
+
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
2906
|
+
kMaxNameLength);
|
2486
2907
|
if (name_ == NULL) return "OOM";
|
2487
2908
|
const char* op_name = Token::Name(op_);
|
2488
2909
|
const char* overwrite_name;
|
@@ -2636,6 +3057,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
|
2636
3057
|
Register right = r0;
|
2637
3058
|
Register scratch1 = r7;
|
2638
3059
|
Register scratch2 = r9;
|
3060
|
+
Register scratch3 = r4;
|
2639
3061
|
|
2640
3062
|
ASSERT(smi_operands || (not_numbers != NULL));
|
2641
3063
|
if (smi_operands && FLAG_debug_code) {
|
@@ -2655,7 +3077,8 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
|
2655
3077
|
// Load left and right operands into d6 and d7 or r0/r1 and r2/r3
|
2656
3078
|
// depending on whether VFP3 is available or not.
|
2657
3079
|
FloatingPointHelper::Destination destination =
|
2658
|
-
CpuFeatures::IsSupported(VFP3) &&
|
3080
|
+
CpuFeatures::IsSupported(VFP3) &&
|
3081
|
+
op_ != Token::MOD ?
|
2659
3082
|
FloatingPointHelper::kVFPRegisters :
|
2660
3083
|
FloatingPointHelper::kCoreRegisters;
|
2661
3084
|
|
@@ -2704,33 +3127,11 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
|
2704
3127
|
__ add(r0, r0, Operand(kHeapObjectTag));
|
2705
3128
|
__ Ret();
|
2706
3129
|
} else {
|
2707
|
-
//
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
// Push the current return address before the C call. Return will be
|
2714
|
-
// through pop(pc) below.
|
2715
|
-
__ push(lr);
|
2716
|
-
__ PrepareCallCFunction(4, scratch1); // Two doubles are 4 arguments.
|
2717
|
-
// Call C routine that may not cause GC or other trouble. r5 is callee
|
2718
|
-
// save.
|
2719
|
-
__ CallCFunction(ExternalReference::double_fp_operation(op_), 4);
|
2720
|
-
// Store answer in the overwritable heap number.
|
2721
|
-
#if !defined(USE_ARM_EABI)
|
2722
|
-
// Double returned in fp coprocessor register 0 and 1, encoded as
|
2723
|
-
// register cr8. Offsets must be divisible by 4 for coprocessor so we
|
2724
|
-
// need to substract the tag from r5.
|
2725
|
-
__ sub(scratch1, result, Operand(kHeapObjectTag));
|
2726
|
-
__ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset));
|
2727
|
-
#else
|
2728
|
-
// Double returned in registers 0 and 1.
|
2729
|
-
__ Strd(r0, r1, FieldMemOperand(result, HeapNumber::kValueOffset));
|
2730
|
-
#endif
|
2731
|
-
// Plase result in r0 and return to the pushed return address.
|
2732
|
-
__ mov(r0, Operand(result));
|
2733
|
-
__ pop(pc);
|
3130
|
+
// Call the C function to handle the double operation.
|
3131
|
+
FloatingPointHelper::CallCCodeForDoubleOperation(masm,
|
3132
|
+
op_,
|
3133
|
+
result,
|
3134
|
+
scratch1);
|
2734
3135
|
}
|
2735
3136
|
break;
|
2736
3137
|
}
|
@@ -2745,22 +3146,24 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
|
2745
3146
|
__ SmiUntag(r2, right);
|
2746
3147
|
} else {
|
2747
3148
|
// Convert operands to 32-bit integers. Right in r2 and left in r3.
|
2748
|
-
FloatingPointHelper::
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
3149
|
+
FloatingPointHelper::ConvertNumberToInt32(masm,
|
3150
|
+
left,
|
3151
|
+
r3,
|
3152
|
+
heap_number_map,
|
3153
|
+
scratch1,
|
3154
|
+
scratch2,
|
3155
|
+
scratch3,
|
3156
|
+
d0,
|
3157
|
+
not_numbers);
|
3158
|
+
FloatingPointHelper::ConvertNumberToInt32(masm,
|
3159
|
+
right,
|
3160
|
+
r2,
|
3161
|
+
heap_number_map,
|
3162
|
+
scratch1,
|
3163
|
+
scratch2,
|
3164
|
+
scratch3,
|
3165
|
+
d0,
|
3166
|
+
not_numbers);
|
2764
3167
|
}
|
2765
3168
|
|
2766
3169
|
Label result_not_a_smi;
|
@@ -2776,7 +3179,6 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
|
2776
3179
|
break;
|
2777
3180
|
case Token::SAR:
|
2778
3181
|
// Use only the 5 least significant bits of the shift count.
|
2779
|
-
__ and_(r2, r2, Operand(0x1f));
|
2780
3182
|
__ GetLeastBitsFromInt32(r2, r2, 5);
|
2781
3183
|
__ mov(r2, Operand(r3, ASR, r2));
|
2782
3184
|
break;
|
@@ -2921,18 +3323,339 @@ void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
|
2921
3323
|
void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
2922
3324
|
ASSERT(operands_type_ == TRBinaryOpIC::INT32);
|
2923
3325
|
|
2924
|
-
|
3326
|
+
Register left = r1;
|
3327
|
+
Register right = r0;
|
3328
|
+
Register scratch1 = r7;
|
3329
|
+
Register scratch2 = r9;
|
3330
|
+
DwVfpRegister double_scratch = d0;
|
3331
|
+
SwVfpRegister single_scratch = s3;
|
3332
|
+
|
3333
|
+
Register heap_number_result = no_reg;
|
3334
|
+
Register heap_number_map = r6;
|
3335
|
+
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
3336
|
+
|
3337
|
+
Label call_runtime;
|
3338
|
+
// Labels for type transition, used for wrong input or output types.
|
3339
|
+
// Both label are currently actually bound to the same position. We use two
|
3340
|
+
// different label to differentiate the cause leading to type transition.
|
3341
|
+
Label transition;
|
3342
|
+
|
3343
|
+
// Smi-smi fast case.
|
3344
|
+
Label skip;
|
3345
|
+
__ orr(scratch1, left, right);
|
3346
|
+
__ JumpIfNotSmi(scratch1, &skip);
|
3347
|
+
GenerateSmiSmiOperation(masm);
|
3348
|
+
// Fall through if the result is not a smi.
|
3349
|
+
__ bind(&skip);
|
3350
|
+
|
3351
|
+
switch (op_) {
|
3352
|
+
case Token::ADD:
|
3353
|
+
case Token::SUB:
|
3354
|
+
case Token::MUL:
|
3355
|
+
case Token::DIV:
|
3356
|
+
case Token::MOD: {
|
3357
|
+
// Load both operands and check that they are 32-bit integer.
|
3358
|
+
// Jump to type transition if they are not. The registers r0 and r1 (right
|
3359
|
+
// and left) are preserved for the runtime call.
|
3360
|
+
FloatingPointHelper::Destination destination =
|
3361
|
+
CpuFeatures::IsSupported(VFP3) &&
|
3362
|
+
op_ != Token::MOD ?
|
3363
|
+
FloatingPointHelper::kVFPRegisters :
|
3364
|
+
FloatingPointHelper::kCoreRegisters;
|
3365
|
+
|
3366
|
+
FloatingPointHelper::LoadNumberAsInt32Double(masm,
|
3367
|
+
right,
|
3368
|
+
destination,
|
3369
|
+
d7,
|
3370
|
+
r2,
|
3371
|
+
r3,
|
3372
|
+
heap_number_map,
|
3373
|
+
scratch1,
|
3374
|
+
scratch2,
|
3375
|
+
s0,
|
3376
|
+
&transition);
|
3377
|
+
FloatingPointHelper::LoadNumberAsInt32Double(masm,
|
3378
|
+
left,
|
3379
|
+
destination,
|
3380
|
+
d6,
|
3381
|
+
r4,
|
3382
|
+
r5,
|
3383
|
+
heap_number_map,
|
3384
|
+
scratch1,
|
3385
|
+
scratch2,
|
3386
|
+
s0,
|
3387
|
+
&transition);
|
3388
|
+
|
3389
|
+
if (destination == FloatingPointHelper::kVFPRegisters) {
|
3390
|
+
CpuFeatures::Scope scope(VFP3);
|
3391
|
+
Label return_heap_number;
|
3392
|
+
switch (op_) {
|
3393
|
+
case Token::ADD:
|
3394
|
+
__ vadd(d5, d6, d7);
|
3395
|
+
break;
|
3396
|
+
case Token::SUB:
|
3397
|
+
__ vsub(d5, d6, d7);
|
3398
|
+
break;
|
3399
|
+
case Token::MUL:
|
3400
|
+
__ vmul(d5, d6, d7);
|
3401
|
+
break;
|
3402
|
+
case Token::DIV:
|
3403
|
+
__ vdiv(d5, d6, d7);
|
3404
|
+
break;
|
3405
|
+
default:
|
3406
|
+
UNREACHABLE();
|
3407
|
+
}
|
3408
|
+
|
3409
|
+
if (op_ != Token::DIV) {
|
3410
|
+
// These operations produce an integer result.
|
3411
|
+
// Try to return a smi if we can.
|
3412
|
+
// Otherwise return a heap number if allowed, or jump to type
|
3413
|
+
// transition.
|
3414
|
+
|
3415
|
+
__ EmitVFPTruncate(kRoundToZero,
|
3416
|
+
single_scratch,
|
3417
|
+
d5,
|
3418
|
+
scratch1,
|
3419
|
+
scratch2);
|
3420
|
+
|
3421
|
+
if (result_type_ <= TRBinaryOpIC::INT32) {
|
3422
|
+
// If the ne condition is set, result does
|
3423
|
+
// not fit in a 32-bit integer.
|
3424
|
+
__ b(ne, &transition);
|
3425
|
+
}
|
3426
|
+
|
3427
|
+
// Check if the result fits in a smi.
|
3428
|
+
__ vmov(scratch1, single_scratch);
|
3429
|
+
__ add(scratch2, scratch1, Operand(0x40000000), SetCC);
|
3430
|
+
// If not try to return a heap number.
|
3431
|
+
__ b(mi, &return_heap_number);
|
3432
|
+
// Check for minus zero. Return heap number for minus zero.
|
3433
|
+
Label not_zero;
|
3434
|
+
__ cmp(scratch1, Operand(0));
|
3435
|
+
__ b(ne, ¬_zero);
|
3436
|
+
__ vmov(scratch2, d5.high());
|
3437
|
+
__ tst(scratch2, Operand(HeapNumber::kSignMask));
|
3438
|
+
__ b(ne, &return_heap_number);
|
3439
|
+
__ bind(¬_zero);
|
3440
|
+
|
3441
|
+
// Tag the result and return.
|
3442
|
+
__ SmiTag(r0, scratch1);
|
3443
|
+
__ Ret();
|
3444
|
+
} else {
|
3445
|
+
// DIV just falls through to allocating a heap number.
|
3446
|
+
}
|
3447
|
+
|
3448
|
+
if (result_type_ >= (op_ == Token::DIV) ? TRBinaryOpIC::HEAP_NUMBER
|
3449
|
+
: TRBinaryOpIC::INT32) {
|
3450
|
+
__ bind(&return_heap_number);
|
3451
|
+
// We are using vfp registers so r5 is available.
|
3452
|
+
heap_number_result = r5;
|
3453
|
+
GenerateHeapResultAllocation(masm,
|
3454
|
+
heap_number_result,
|
3455
|
+
heap_number_map,
|
3456
|
+
scratch1,
|
3457
|
+
scratch2,
|
3458
|
+
&call_runtime);
|
3459
|
+
__ sub(r0, heap_number_result, Operand(kHeapObjectTag));
|
3460
|
+
__ vstr(d5, r0, HeapNumber::kValueOffset);
|
3461
|
+
__ mov(r0, heap_number_result);
|
3462
|
+
__ Ret();
|
3463
|
+
}
|
3464
|
+
|
3465
|
+
// A DIV operation expecting an integer result falls through
|
3466
|
+
// to type transition.
|
3467
|
+
|
3468
|
+
} else {
|
3469
|
+
// We preserved r0 and r1 to be able to call runtime.
|
3470
|
+
// Save the left value on the stack.
|
3471
|
+
__ Push(r5, r4);
|
3472
|
+
|
3473
|
+
// Allocate a heap number to store the result.
|
3474
|
+
heap_number_result = r5;
|
3475
|
+
GenerateHeapResultAllocation(masm,
|
3476
|
+
heap_number_result,
|
3477
|
+
heap_number_map,
|
3478
|
+
scratch1,
|
3479
|
+
scratch2,
|
3480
|
+
&call_runtime);
|
3481
|
+
|
3482
|
+
// Load the left value from the value saved on the stack.
|
3483
|
+
__ Pop(r1, r0);
|
3484
|
+
|
3485
|
+
// Call the C function to handle the double operation.
|
3486
|
+
FloatingPointHelper::CallCCodeForDoubleOperation(
|
3487
|
+
masm, op_, heap_number_result, scratch1);
|
3488
|
+
}
|
3489
|
+
|
3490
|
+
break;
|
3491
|
+
}
|
3492
|
+
|
3493
|
+
case Token::BIT_OR:
|
3494
|
+
case Token::BIT_XOR:
|
3495
|
+
case Token::BIT_AND:
|
3496
|
+
case Token::SAR:
|
3497
|
+
case Token::SHR:
|
3498
|
+
case Token::SHL: {
|
3499
|
+
Label return_heap_number;
|
3500
|
+
Register scratch3 = r5;
|
3501
|
+
// Convert operands to 32-bit integers. Right in r2 and left in r3. The
|
3502
|
+
// registers r0 and r1 (right and left) are preserved for the runtime
|
3503
|
+
// call.
|
3504
|
+
FloatingPointHelper::LoadNumberAsInt32(masm,
|
3505
|
+
left,
|
3506
|
+
r3,
|
3507
|
+
heap_number_map,
|
3508
|
+
scratch1,
|
3509
|
+
scratch2,
|
3510
|
+
scratch3,
|
3511
|
+
d0,
|
3512
|
+
&transition);
|
3513
|
+
FloatingPointHelper::LoadNumberAsInt32(masm,
|
3514
|
+
right,
|
3515
|
+
r2,
|
3516
|
+
heap_number_map,
|
3517
|
+
scratch1,
|
3518
|
+
scratch2,
|
3519
|
+
scratch3,
|
3520
|
+
d0,
|
3521
|
+
&transition);
|
3522
|
+
|
3523
|
+
// The ECMA-262 standard specifies that, for shift operations, only the
|
3524
|
+
// 5 least significant bits of the shift value should be used.
|
3525
|
+
switch (op_) {
|
3526
|
+
case Token::BIT_OR:
|
3527
|
+
__ orr(r2, r3, Operand(r2));
|
3528
|
+
break;
|
3529
|
+
case Token::BIT_XOR:
|
3530
|
+
__ eor(r2, r3, Operand(r2));
|
3531
|
+
break;
|
3532
|
+
case Token::BIT_AND:
|
3533
|
+
__ and_(r2, r3, Operand(r2));
|
3534
|
+
break;
|
3535
|
+
case Token::SAR:
|
3536
|
+
__ and_(r2, r2, Operand(0x1f));
|
3537
|
+
__ mov(r2, Operand(r3, ASR, r2));
|
3538
|
+
break;
|
3539
|
+
case Token::SHR:
|
3540
|
+
__ and_(r2, r2, Operand(0x1f));
|
3541
|
+
__ mov(r2, Operand(r3, LSR, r2), SetCC);
|
3542
|
+
// SHR is special because it is required to produce a positive answer.
|
3543
|
+
// We only get a negative result if the shift value (r2) is 0.
|
3544
|
+
// This result cannot be respresented as a signed 32-bit integer, try
|
3545
|
+
// to return a heap number if we can.
|
3546
|
+
// The non vfp3 code does not support this special case, so jump to
|
3547
|
+
// runtime if we don't support it.
|
3548
|
+
if (CpuFeatures::IsSupported(VFP3)) {
|
3549
|
+
__ b(mi,
|
3550
|
+
(result_type_ <= TRBinaryOpIC::INT32) ? &transition
|
3551
|
+
: &return_heap_number);
|
3552
|
+
} else {
|
3553
|
+
__ b(mi, (result_type_ <= TRBinaryOpIC::INT32) ? &transition
|
3554
|
+
: &call_runtime);
|
3555
|
+
}
|
3556
|
+
break;
|
3557
|
+
case Token::SHL:
|
3558
|
+
__ and_(r2, r2, Operand(0x1f));
|
3559
|
+
__ mov(r2, Operand(r3, LSL, r2));
|
3560
|
+
break;
|
3561
|
+
default:
|
3562
|
+
UNREACHABLE();
|
3563
|
+
}
|
3564
|
+
|
3565
|
+
// Check if the result fits in a smi.
|
3566
|
+
__ add(scratch1, r2, Operand(0x40000000), SetCC);
|
3567
|
+
// If not try to return a heap number. (We know the result is an int32.)
|
3568
|
+
__ b(mi, &return_heap_number);
|
3569
|
+
// Tag the result and return.
|
3570
|
+
__ SmiTag(r0, r2);
|
3571
|
+
__ Ret();
|
3572
|
+
|
3573
|
+
__ bind(&return_heap_number);
|
3574
|
+
if (CpuFeatures::IsSupported(VFP3)) {
|
3575
|
+
CpuFeatures::Scope scope(VFP3);
|
3576
|
+
heap_number_result = r5;
|
3577
|
+
GenerateHeapResultAllocation(masm,
|
3578
|
+
heap_number_result,
|
3579
|
+
heap_number_map,
|
3580
|
+
scratch1,
|
3581
|
+
scratch2,
|
3582
|
+
&call_runtime);
|
3583
|
+
|
3584
|
+
if (op_ != Token::SHR) {
|
3585
|
+
// Convert the result to a floating point value.
|
3586
|
+
__ vmov(double_scratch.low(), r2);
|
3587
|
+
__ vcvt_f64_s32(double_scratch, double_scratch.low());
|
3588
|
+
} else {
|
3589
|
+
// The result must be interpreted as an unsigned 32-bit integer.
|
3590
|
+
__ vmov(double_scratch.low(), r2);
|
3591
|
+
__ vcvt_f64_u32(double_scratch, double_scratch.low());
|
3592
|
+
}
|
3593
|
+
|
3594
|
+
// Store the result.
|
3595
|
+
__ sub(r0, heap_number_result, Operand(kHeapObjectTag));
|
3596
|
+
__ vstr(double_scratch, r0, HeapNumber::kValueOffset);
|
3597
|
+
__ mov(r0, heap_number_result);
|
3598
|
+
__ Ret();
|
3599
|
+
} else {
|
3600
|
+
// Tail call that writes the int32 in r2 to the heap number in r0, using
|
3601
|
+
// r3 as scratch. r0 is preserved and returned.
|
3602
|
+
WriteInt32ToHeapNumberStub stub(r2, r0, r3);
|
3603
|
+
__ TailCallStub(&stub);
|
3604
|
+
}
|
3605
|
+
|
3606
|
+
break;
|
3607
|
+
}
|
3608
|
+
|
3609
|
+
default:
|
3610
|
+
UNREACHABLE();
|
3611
|
+
}
|
3612
|
+
|
3613
|
+
if (transition.is_linked()) {
|
3614
|
+
__ bind(&transition);
|
3615
|
+
GenerateTypeTransition(masm);
|
3616
|
+
}
|
3617
|
+
|
3618
|
+
__ bind(&call_runtime);
|
3619
|
+
GenerateCallRuntime(masm);
|
2925
3620
|
}
|
2926
3621
|
|
2927
3622
|
|
2928
|
-
void TypeRecordingBinaryOpStub::
|
2929
|
-
Label
|
2930
|
-
ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);
|
3623
|
+
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
3624
|
+
Label call_runtime;
|
2931
3625
|
|
2932
|
-
|
3626
|
+
if (op_ == Token::ADD) {
|
3627
|
+
// Handle string addition here, because it is the only operation
|
3628
|
+
// that does not do a ToNumber conversion on the operands.
|
3629
|
+
GenerateAddStrings(masm);
|
3630
|
+
}
|
2933
3631
|
|
2934
|
-
|
2935
|
-
|
3632
|
+
// Convert oddball arguments to numbers.
|
3633
|
+
Label check, done;
|
3634
|
+
__ CompareRoot(r1, Heap::kUndefinedValueRootIndex);
|
3635
|
+
__ b(ne, &check);
|
3636
|
+
if (Token::IsBitOp(op_)) {
|
3637
|
+
__ mov(r1, Operand(Smi::FromInt(0)));
|
3638
|
+
} else {
|
3639
|
+
__ LoadRoot(r1, Heap::kNanValueRootIndex);
|
3640
|
+
}
|
3641
|
+
__ jmp(&done);
|
3642
|
+
__ bind(&check);
|
3643
|
+
__ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
|
3644
|
+
__ b(ne, &done);
|
3645
|
+
if (Token::IsBitOp(op_)) {
|
3646
|
+
__ mov(r0, Operand(Smi::FromInt(0)));
|
3647
|
+
} else {
|
3648
|
+
__ LoadRoot(r0, Heap::kNanValueRootIndex);
|
3649
|
+
}
|
3650
|
+
__ bind(&done);
|
3651
|
+
|
3652
|
+
GenerateHeapNumberStub(masm);
|
3653
|
+
}
|
3654
|
+
|
3655
|
+
|
3656
|
+
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
3657
|
+
Label call_runtime;
|
3658
|
+
GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
|
2936
3659
|
|
2937
3660
|
__ bind(&call_runtime);
|
2938
3661
|
GenerateCallRuntime(masm);
|
@@ -3069,32 +3792,47 @@ void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
|
3069
3792
|
|
3070
3793
|
|
3071
3794
|
void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
3072
|
-
//
|
3073
|
-
|
3795
|
+
// Untagged case: double input in d2, double result goes
|
3796
|
+
// into d2.
|
3797
|
+
// Tagged case: tagged input on top of stack and in r0,
|
3798
|
+
// tagged result (heap number) goes into r0.
|
3799
|
+
|
3074
3800
|
Label input_not_smi;
|
3075
3801
|
Label loaded;
|
3802
|
+
Label calculate;
|
3803
|
+
Label invalid_cache;
|
3804
|
+
const Register scratch0 = r9;
|
3805
|
+
const Register scratch1 = r7;
|
3806
|
+
const Register cache_entry = r0;
|
3807
|
+
const bool tagged = (argument_type_ == TAGGED);
|
3076
3808
|
|
3077
3809
|
if (CpuFeatures::IsSupported(VFP3)) {
|
3078
|
-
// Load argument and check if it is a smi.
|
3079
|
-
__ JumpIfNotSmi(r0, &input_not_smi);
|
3080
|
-
|
3081
3810
|
CpuFeatures::Scope scope(VFP3);
|
3082
|
-
|
3083
|
-
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3088
|
-
|
3089
|
-
|
3090
|
-
|
3091
|
-
|
3092
|
-
|
3093
|
-
|
3094
|
-
|
3095
|
-
|
3096
|
-
|
3097
|
-
|
3811
|
+
if (tagged) {
|
3812
|
+
// Argument is a number and is on stack and in r0.
|
3813
|
+
// Load argument and check if it is a smi.
|
3814
|
+
__ JumpIfNotSmi(r0, &input_not_smi);
|
3815
|
+
|
3816
|
+
// Input is a smi. Convert to double and load the low and high words
|
3817
|
+
// of the double into r2, r3.
|
3818
|
+
__ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
|
3819
|
+
__ b(&loaded);
|
3820
|
+
|
3821
|
+
__ bind(&input_not_smi);
|
3822
|
+
// Check if input is a HeapNumber.
|
3823
|
+
__ CheckMap(r0,
|
3824
|
+
r1,
|
3825
|
+
Heap::kHeapNumberMapRootIndex,
|
3826
|
+
&calculate,
|
3827
|
+
true);
|
3828
|
+
// Input is a HeapNumber. Load it to a double register and store the
|
3829
|
+
// low and high words into r2, r3.
|
3830
|
+
__ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
3831
|
+
__ vmov(r2, r3, d0);
|
3832
|
+
} else {
|
3833
|
+
// Input is untagged double in d2. Output goes to d2.
|
3834
|
+
__ vmov(r2, r3, d2);
|
3835
|
+
}
|
3098
3836
|
__ bind(&loaded);
|
3099
3837
|
// r2 = low 32 bits of double value
|
3100
3838
|
// r3 = high 32 bits of double value
|
@@ -3103,24 +3841,28 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
|
3103
3841
|
__ eor(r1, r2, Operand(r3));
|
3104
3842
|
__ eor(r1, r1, Operand(r1, ASR, 16));
|
3105
3843
|
__ eor(r1, r1, Operand(r1, ASR, 8));
|
3106
|
-
ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
|
3107
|
-
__ And(r1, r1, Operand(TranscendentalCache::kCacheSize - 1));
|
3844
|
+
ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
|
3845
|
+
__ And(r1, r1, Operand(TranscendentalCache::SubCache::kCacheSize - 1));
|
3108
3846
|
|
3109
3847
|
// r2 = low 32 bits of double value.
|
3110
3848
|
// r3 = high 32 bits of double value.
|
3111
3849
|
// r1 = TranscendentalCache::hash(double value).
|
3112
|
-
|
3113
|
-
|
3114
|
-
|
3115
|
-
__
|
3850
|
+
Isolate* isolate = masm->isolate();
|
3851
|
+
ExternalReference cache_array =
|
3852
|
+
ExternalReference::transcendental_cache_array_address(isolate);
|
3853
|
+
__ mov(cache_entry, Operand(cache_array));
|
3854
|
+
// cache_entry points to cache array.
|
3855
|
+
int cache_array_index
|
3856
|
+
= type_ * sizeof(isolate->transcendental_cache()->caches_[0]);
|
3857
|
+
__ ldr(cache_entry, MemOperand(cache_entry, cache_array_index));
|
3116
3858
|
// r0 points to the cache for the type type_.
|
3117
3859
|
// If NULL, the cache hasn't been initialized yet, so go through runtime.
|
3118
|
-
__ cmp(
|
3119
|
-
__ b(eq, &
|
3860
|
+
__ cmp(cache_entry, Operand(0, RelocInfo::NONE));
|
3861
|
+
__ b(eq, &invalid_cache);
|
3120
3862
|
|
3121
3863
|
#ifdef DEBUG
|
3122
3864
|
// Check that the layout of cache elements match expectations.
|
3123
|
-
{ TranscendentalCache::Element test_elem[2];
|
3865
|
+
{ TranscendentalCache::SubCache::Element test_elem[2];
|
3124
3866
|
char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
|
3125
3867
|
char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
|
3126
3868
|
char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
|
@@ -3135,21 +3877,113 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
|
3135
3877
|
|
3136
3878
|
// Find the address of the r1'st entry in the cache, i.e., &r0[r1*12].
|
3137
3879
|
__ add(r1, r1, Operand(r1, LSL, 1));
|
3138
|
-
__ add(
|
3880
|
+
__ add(cache_entry, cache_entry, Operand(r1, LSL, 2));
|
3139
3881
|
// Check if cache matches: Double value is stored in uint32_t[2] array.
|
3140
|
-
__ ldm(ia,
|
3882
|
+
__ ldm(ia, cache_entry, r4.bit() | r5.bit() | r6.bit());
|
3141
3883
|
__ cmp(r2, r4);
|
3142
|
-
__ b(ne, &
|
3884
|
+
__ b(ne, &calculate);
|
3143
3885
|
__ cmp(r3, r5);
|
3144
|
-
__ b(ne, &
|
3145
|
-
// Cache hit. Load result,
|
3146
|
-
|
3147
|
-
|
3886
|
+
__ b(ne, &calculate);
|
3887
|
+
// Cache hit. Load result, cleanup and return.
|
3888
|
+
if (tagged) {
|
3889
|
+
// Pop input value from stack and load result into r0.
|
3890
|
+
__ pop();
|
3891
|
+
__ mov(r0, Operand(r6));
|
3892
|
+
} else {
|
3893
|
+
// Load result into d2.
|
3894
|
+
__ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
|
3895
|
+
}
|
3896
|
+
__ Ret();
|
3897
|
+
} // if (CpuFeatures::IsSupported(VFP3))
|
3898
|
+
|
3899
|
+
__ bind(&calculate);
|
3900
|
+
if (tagged) {
|
3901
|
+
__ bind(&invalid_cache);
|
3902
|
+
ExternalReference runtime_function =
|
3903
|
+
ExternalReference(RuntimeFunction(), masm->isolate());
|
3904
|
+
__ TailCallExternalReference(runtime_function, 1, 1);
|
3905
|
+
} else {
|
3906
|
+
if (!CpuFeatures::IsSupported(VFP3)) UNREACHABLE();
|
3907
|
+
CpuFeatures::Scope scope(VFP3);
|
3908
|
+
|
3909
|
+
Label no_update;
|
3910
|
+
Label skip_cache;
|
3911
|
+
const Register heap_number_map = r5;
|
3912
|
+
|
3913
|
+
// Call C function to calculate the result and update the cache.
|
3914
|
+
// Register r0 holds precalculated cache entry address; preserve
|
3915
|
+
// it on the stack and pop it into register cache_entry after the
|
3916
|
+
// call.
|
3917
|
+
__ push(cache_entry);
|
3918
|
+
GenerateCallCFunction(masm, scratch0);
|
3919
|
+
__ GetCFunctionDoubleResult(d2);
|
3920
|
+
|
3921
|
+
// Try to update the cache. If we cannot allocate a
|
3922
|
+
// heap number, we return the result without updating.
|
3923
|
+
__ pop(cache_entry);
|
3924
|
+
__ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
|
3925
|
+
__ AllocateHeapNumber(r6, scratch0, scratch1, r5, &no_update);
|
3926
|
+
__ vstr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
|
3927
|
+
__ stm(ia, cache_entry, r2.bit() | r3.bit() | r6.bit());
|
3928
|
+
__ Ret();
|
3929
|
+
|
3930
|
+
__ bind(&invalid_cache);
|
3931
|
+
// The cache is invalid. Call runtime which will recreate the
|
3932
|
+
// cache.
|
3933
|
+
__ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
|
3934
|
+
__ AllocateHeapNumber(r0, scratch0, scratch1, r5, &skip_cache);
|
3935
|
+
__ vstr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
3936
|
+
__ EnterInternalFrame();
|
3937
|
+
__ push(r0);
|
3938
|
+
__ CallRuntime(RuntimeFunction(), 1);
|
3939
|
+
__ LeaveInternalFrame();
|
3940
|
+
__ vldr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
3941
|
+
__ Ret();
|
3942
|
+
|
3943
|
+
__ bind(&skip_cache);
|
3944
|
+
// Call C function to calculate the result and answer directly
|
3945
|
+
// without updating the cache.
|
3946
|
+
GenerateCallCFunction(masm, scratch0);
|
3947
|
+
__ GetCFunctionDoubleResult(d2);
|
3948
|
+
__ bind(&no_update);
|
3949
|
+
|
3950
|
+
// We return the value in d2 without adding it to the cache, but
|
3951
|
+
// we cause a scavenging GC so that future allocations will succeed.
|
3952
|
+
__ EnterInternalFrame();
|
3953
|
+
|
3954
|
+
// Allocate an aligned object larger than a HeapNumber.
|
3955
|
+
ASSERT(4 * kPointerSize >= HeapNumber::kSize);
|
3956
|
+
__ mov(scratch0, Operand(4 * kPointerSize));
|
3957
|
+
__ push(scratch0);
|
3958
|
+
__ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
|
3959
|
+
__ LeaveInternalFrame();
|
3148
3960
|
__ Ret();
|
3149
3961
|
}
|
3962
|
+
}
|
3963
|
+
|
3964
|
+
|
3965
|
+
void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
|
3966
|
+
Register scratch) {
|
3967
|
+
Isolate* isolate = masm->isolate();
|
3150
3968
|
|
3151
|
-
__
|
3152
|
-
__
|
3969
|
+
__ push(lr);
|
3970
|
+
__ PrepareCallCFunction(2, scratch);
|
3971
|
+
__ vmov(r0, r1, d2);
|
3972
|
+
switch (type_) {
|
3973
|
+
case TranscendentalCache::SIN:
|
3974
|
+
__ CallCFunction(ExternalReference::math_sin_double_function(isolate), 2);
|
3975
|
+
break;
|
3976
|
+
case TranscendentalCache::COS:
|
3977
|
+
__ CallCFunction(ExternalReference::math_cos_double_function(isolate), 2);
|
3978
|
+
break;
|
3979
|
+
case TranscendentalCache::LOG:
|
3980
|
+
__ CallCFunction(ExternalReference::math_log_double_function(isolate), 2);
|
3981
|
+
break;
|
3982
|
+
default:
|
3983
|
+
UNIMPLEMENTED();
|
3984
|
+
break;
|
3985
|
+
}
|
3986
|
+
__ pop(lr);
|
3153
3987
|
}
|
3154
3988
|
|
3155
3989
|
|
@@ -3306,6 +4140,113 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
|
|
3306
4140
|
}
|
3307
4141
|
|
3308
4142
|
|
4143
|
+
void MathPowStub::Generate(MacroAssembler* masm) {
|
4144
|
+
Label call_runtime;
|
4145
|
+
|
4146
|
+
if (CpuFeatures::IsSupported(VFP3)) {
|
4147
|
+
CpuFeatures::Scope scope(VFP3);
|
4148
|
+
|
4149
|
+
Label base_not_smi;
|
4150
|
+
Label exponent_not_smi;
|
4151
|
+
Label convert_exponent;
|
4152
|
+
|
4153
|
+
const Register base = r0;
|
4154
|
+
const Register exponent = r1;
|
4155
|
+
const Register heapnumbermap = r5;
|
4156
|
+
const Register heapnumber = r6;
|
4157
|
+
const DoubleRegister double_base = d0;
|
4158
|
+
const DoubleRegister double_exponent = d1;
|
4159
|
+
const DoubleRegister double_result = d2;
|
4160
|
+
const SwVfpRegister single_scratch = s0;
|
4161
|
+
const Register scratch = r9;
|
4162
|
+
const Register scratch2 = r7;
|
4163
|
+
|
4164
|
+
__ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
|
4165
|
+
__ ldr(base, MemOperand(sp, 1 * kPointerSize));
|
4166
|
+
__ ldr(exponent, MemOperand(sp, 0 * kPointerSize));
|
4167
|
+
|
4168
|
+
// Convert base to double value and store it in d0.
|
4169
|
+
__ JumpIfNotSmi(base, &base_not_smi);
|
4170
|
+
// Base is a Smi. Untag and convert it.
|
4171
|
+
__ SmiUntag(base);
|
4172
|
+
__ vmov(single_scratch, base);
|
4173
|
+
__ vcvt_f64_s32(double_base, single_scratch);
|
4174
|
+
__ b(&convert_exponent);
|
4175
|
+
|
4176
|
+
__ bind(&base_not_smi);
|
4177
|
+
__ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset));
|
4178
|
+
__ cmp(scratch, heapnumbermap);
|
4179
|
+
__ b(ne, &call_runtime);
|
4180
|
+
// Base is a heapnumber. Load it into double register.
|
4181
|
+
__ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
|
4182
|
+
|
4183
|
+
__ bind(&convert_exponent);
|
4184
|
+
__ JumpIfNotSmi(exponent, &exponent_not_smi);
|
4185
|
+
__ SmiUntag(exponent);
|
4186
|
+
|
4187
|
+
// The base is in a double register and the exponent is
|
4188
|
+
// an untagged smi. Allocate a heap number and call a
|
4189
|
+
// C function for integer exponents. The register containing
|
4190
|
+
// the heap number is callee-saved.
|
4191
|
+
__ AllocateHeapNumber(heapnumber,
|
4192
|
+
scratch,
|
4193
|
+
scratch2,
|
4194
|
+
heapnumbermap,
|
4195
|
+
&call_runtime);
|
4196
|
+
__ push(lr);
|
4197
|
+
__ PrepareCallCFunction(3, scratch);
|
4198
|
+
__ mov(r2, exponent);
|
4199
|
+
__ vmov(r0, r1, double_base);
|
4200
|
+
__ CallCFunction(
|
4201
|
+
ExternalReference::power_double_int_function(masm->isolate()), 3);
|
4202
|
+
__ pop(lr);
|
4203
|
+
__ GetCFunctionDoubleResult(double_result);
|
4204
|
+
__ vstr(double_result,
|
4205
|
+
FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
|
4206
|
+
__ mov(r0, heapnumber);
|
4207
|
+
__ Ret(2 * kPointerSize);
|
4208
|
+
|
4209
|
+
__ bind(&exponent_not_smi);
|
4210
|
+
__ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
|
4211
|
+
__ cmp(scratch, heapnumbermap);
|
4212
|
+
__ b(ne, &call_runtime);
|
4213
|
+
// Exponent is a heapnumber. Load it into double register.
|
4214
|
+
__ vldr(double_exponent,
|
4215
|
+
FieldMemOperand(exponent, HeapNumber::kValueOffset));
|
4216
|
+
|
4217
|
+
// The base and the exponent are in double registers.
|
4218
|
+
// Allocate a heap number and call a C function for
|
4219
|
+
// double exponents. The register containing
|
4220
|
+
// the heap number is callee-saved.
|
4221
|
+
__ AllocateHeapNumber(heapnumber,
|
4222
|
+
scratch,
|
4223
|
+
scratch2,
|
4224
|
+
heapnumbermap,
|
4225
|
+
&call_runtime);
|
4226
|
+
__ push(lr);
|
4227
|
+
__ PrepareCallCFunction(4, scratch);
|
4228
|
+
__ vmov(r0, r1, double_base);
|
4229
|
+
__ vmov(r2, r3, double_exponent);
|
4230
|
+
__ CallCFunction(
|
4231
|
+
ExternalReference::power_double_double_function(masm->isolate()), 4);
|
4232
|
+
__ pop(lr);
|
4233
|
+
__ GetCFunctionDoubleResult(double_result);
|
4234
|
+
__ vstr(double_result,
|
4235
|
+
FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
|
4236
|
+
__ mov(r0, heapnumber);
|
4237
|
+
__ Ret(2 * kPointerSize);
|
4238
|
+
}
|
4239
|
+
|
4240
|
+
__ bind(&call_runtime);
|
4241
|
+
__ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
|
4242
|
+
}
|
4243
|
+
|
4244
|
+
|
4245
|
+
bool CEntryStub::NeedsImmovableCode() {
|
4246
|
+
return true;
|
4247
|
+
}
|
4248
|
+
|
4249
|
+
|
3309
4250
|
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
|
3310
4251
|
__ Throw(r0);
|
3311
4252
|
}
|
@@ -3327,15 +4268,16 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
|
3327
4268
|
// r4: number of arguments including receiver (C callee-saved)
|
3328
4269
|
// r5: pointer to builtin function (C callee-saved)
|
3329
4270
|
// r6: pointer to the first argument (C callee-saved)
|
4271
|
+
Isolate* isolate = masm->isolate();
|
3330
4272
|
|
3331
4273
|
if (do_gc) {
|
3332
4274
|
// Passing r0.
|
3333
4275
|
__ PrepareCallCFunction(1, r1);
|
3334
|
-
__ CallCFunction(ExternalReference::perform_gc_function(), 1);
|
4276
|
+
__ CallCFunction(ExternalReference::perform_gc_function(isolate), 1);
|
3335
4277
|
}
|
3336
4278
|
|
3337
4279
|
ExternalReference scope_depth =
|
3338
|
-
ExternalReference::heap_always_allocate_scope_depth();
|
4280
|
+
ExternalReference::heap_always_allocate_scope_depth(isolate);
|
3339
4281
|
if (always_allocate) {
|
3340
4282
|
__ mov(r0, Operand(scope_depth));
|
3341
4283
|
__ ldr(r1, MemOperand(r0));
|
@@ -3364,6 +4306,9 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
|
3364
4306
|
}
|
3365
4307
|
#endif
|
3366
4308
|
|
4309
|
+
__ mov(r2, Operand(ExternalReference::isolate_address()));
|
4310
|
+
|
4311
|
+
|
3367
4312
|
// TODO(1242173): To let the GC traverse the return address of the exit
|
3368
4313
|
// frames, we need to know where the return address is. Right now,
|
3369
4314
|
// we store it on the stack to be able to find it again, but we never
|
@@ -3417,15 +4362,16 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
|
3417
4362
|
__ b(eq, throw_out_of_memory_exception);
|
3418
4363
|
|
3419
4364
|
// Retrieve the pending exception and clear the variable.
|
3420
|
-
__ mov(ip, Operand(ExternalReference::the_hole_value_location()));
|
4365
|
+
__ mov(ip, Operand(ExternalReference::the_hole_value_location(isolate)));
|
3421
4366
|
__ ldr(r3, MemOperand(ip));
|
3422
|
-
__ mov(ip, Operand(ExternalReference(
|
4367
|
+
__ mov(ip, Operand(ExternalReference(Isolate::k_pending_exception_address,
|
4368
|
+
isolate)));
|
3423
4369
|
__ ldr(r0, MemOperand(ip));
|
3424
4370
|
__ str(r3, MemOperand(ip));
|
3425
4371
|
|
3426
4372
|
// Special handling of termination exceptions which are uncatchable
|
3427
4373
|
// by javascript code.
|
3428
|
-
__ cmp(r0, Operand(
|
4374
|
+
__ cmp(r0, Operand(isolate->factory()->termination_exception()));
|
3429
4375
|
__ b(eq, throw_termination_exception);
|
3430
4376
|
|
3431
4377
|
// Handle normal exception.
|
@@ -3533,11 +4479,13 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|
3533
4479
|
// r2: receiver
|
3534
4480
|
// r3: argc
|
3535
4481
|
// r4: argv
|
4482
|
+
Isolate* isolate = masm->isolate();
|
3536
4483
|
__ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used.
|
3537
4484
|
int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
|
3538
4485
|
__ mov(r7, Operand(Smi::FromInt(marker)));
|
3539
4486
|
__ mov(r6, Operand(Smi::FromInt(marker)));
|
3540
|
-
__ mov(r5,
|
4487
|
+
__ mov(r5,
|
4488
|
+
Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate)));
|
3541
4489
|
__ ldr(r5, MemOperand(r5));
|
3542
4490
|
__ Push(r8, r7, r6, r5);
|
3543
4491
|
|
@@ -3546,7 +4494,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|
3546
4494
|
|
3547
4495
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
3548
4496
|
// If this is the outermost JS call, set js_entry_sp value.
|
3549
|
-
ExternalReference js_entry_sp(
|
4497
|
+
ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate);
|
3550
4498
|
__ mov(r5, Operand(ExternalReference(js_entry_sp)));
|
3551
4499
|
__ ldr(r6, MemOperand(r5));
|
3552
4500
|
__ cmp(r6, Operand(0, RelocInfo::NONE));
|
@@ -3560,7 +4508,8 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|
3560
4508
|
// exception field in the JSEnv and return a failure sentinel.
|
3561
4509
|
// Coming in here the fp will be invalid because the PushTryHandler below
|
3562
4510
|
// sets it to 0 to signal the existence of the JSEntry frame.
|
3563
|
-
__ mov(ip, Operand(ExternalReference(
|
4511
|
+
__ mov(ip, Operand(ExternalReference(Isolate::k_pending_exception_address,
|
4512
|
+
isolate)));
|
3564
4513
|
__ str(r0, MemOperand(ip));
|
3565
4514
|
__ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
|
3566
4515
|
__ b(&exit);
|
@@ -3575,9 +4524,10 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|
3575
4524
|
// saved values before returning a failure to C.
|
3576
4525
|
|
3577
4526
|
// Clear any pending exceptions.
|
3578
|
-
__ mov(ip, Operand(ExternalReference::the_hole_value_location()));
|
4527
|
+
__ mov(ip, Operand(ExternalReference::the_hole_value_location(isolate)));
|
3579
4528
|
__ ldr(r5, MemOperand(ip));
|
3580
|
-
__ mov(ip, Operand(ExternalReference(
|
4529
|
+
__ mov(ip, Operand(ExternalReference(Isolate::k_pending_exception_address,
|
4530
|
+
isolate)));
|
3581
4531
|
__ str(r5, MemOperand(ip));
|
3582
4532
|
|
3583
4533
|
// Invoke the function by calling through JS entry trampoline builtin.
|
@@ -3591,10 +4541,11 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|
3591
4541
|
// r3: argc
|
3592
4542
|
// r4: argv
|
3593
4543
|
if (is_construct) {
|
3594
|
-
ExternalReference construct_entry(Builtins::
|
4544
|
+
ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
|
4545
|
+
isolate);
|
3595
4546
|
__ mov(ip, Operand(construct_entry));
|
3596
4547
|
} else {
|
3597
|
-
ExternalReference entry(Builtins::
|
4548
|
+
ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
|
3598
4549
|
__ mov(ip, Operand(entry));
|
3599
4550
|
}
|
3600
4551
|
__ ldr(ip, MemOperand(ip)); // deref address
|
@@ -3610,7 +4561,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|
3610
4561
|
// displacement since the current stack pointer (sp) points directly
|
3611
4562
|
// to the stack handler.
|
3612
4563
|
__ ldr(r3, MemOperand(sp, StackHandlerConstants::kNextOffset));
|
3613
|
-
__ mov(ip, Operand(ExternalReference(
|
4564
|
+
__ mov(ip, Operand(ExternalReference(Isolate::k_handler_address, isolate)));
|
3614
4565
|
__ str(r3, MemOperand(ip));
|
3615
4566
|
// No need to restore registers
|
3616
4567
|
__ add(sp, sp, Operand(StackHandlerConstants::kSize));
|
@@ -3628,7 +4579,8 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|
3628
4579
|
__ bind(&exit); // r0 holds result
|
3629
4580
|
// Restore the top frame descriptors from the stack.
|
3630
4581
|
__ pop(r3);
|
3631
|
-
__ mov(ip,
|
4582
|
+
__ mov(ip,
|
4583
|
+
Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate)));
|
3632
4584
|
__ str(r3, MemOperand(ip));
|
3633
4585
|
|
3634
4586
|
// Reset the stack to the callee saved registers.
|
@@ -3785,7 +4737,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
|
|
3785
4737
|
__ b(ne, &slow);
|
3786
4738
|
|
3787
4739
|
// Null is not instance of anything.
|
3788
|
-
__ cmp(scratch, Operand(
|
4740
|
+
__ cmp(scratch, Operand(FACTORY->null_value()));
|
3789
4741
|
__ b(ne, &object_not_null);
|
3790
4742
|
__ mov(r0, Operand(Smi::FromInt(1)));
|
3791
4743
|
__ Ret(HasArgsInRegisters() ? 0 : 2);
|
@@ -3912,7 +4864,7 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
|
|
3912
4864
|
__ mov(r1, Operand(r1, LSR, kSmiTagSize));
|
3913
4865
|
__ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
|
3914
4866
|
__ bind(&add_arguments_object);
|
3915
|
-
__ add(r1, r1, Operand(
|
4867
|
+
__ add(r1, r1, Operand(GetArgumentsObjectSize() / kPointerSize));
|
3916
4868
|
|
3917
4869
|
// Do the allocation of both objects in one go.
|
3918
4870
|
__ AllocateInNewSpace(
|
@@ -3924,23 +4876,28 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
|
|
3924
4876
|
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
|
3925
4877
|
|
3926
4878
|
// Get the arguments boilerplate from the current (global) context.
|
3927
|
-
int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
|
3928
4879
|
__ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
|
3929
4880
|
__ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset));
|
3930
|
-
__ ldr(r4, MemOperand(r4,
|
4881
|
+
__ ldr(r4, MemOperand(r4,
|
4882
|
+
Context::SlotOffset(GetArgumentsBoilerplateIndex())));
|
3931
4883
|
|
3932
4884
|
// Copy the JS object part.
|
3933
4885
|
__ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize);
|
3934
4886
|
|
3935
|
-
|
3936
|
-
|
3937
|
-
|
3938
|
-
|
4887
|
+
if (type_ == NEW_NON_STRICT) {
|
4888
|
+
// Setup the callee in-object property.
|
4889
|
+
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
|
4890
|
+
__ ldr(r3, MemOperand(sp, 2 * kPointerSize));
|
4891
|
+
const int kCalleeOffset = JSObject::kHeaderSize +
|
4892
|
+
Heap::kArgumentsCalleeIndex * kPointerSize;
|
4893
|
+
__ str(r3, FieldMemOperand(r0, kCalleeOffset));
|
4894
|
+
}
|
3939
4895
|
|
3940
4896
|
// Get the length (smi tagged) and set that as an in-object property too.
|
3941
|
-
STATIC_ASSERT(Heap::
|
4897
|
+
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
3942
4898
|
__ ldr(r1, MemOperand(sp, 0 * kPointerSize));
|
3943
|
-
__ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize +
|
4899
|
+
__ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize +
|
4900
|
+
Heap::kArgumentsLengthIndex * kPointerSize));
|
3944
4901
|
|
3945
4902
|
// If there are no actual arguments, we're done.
|
3946
4903
|
Label done;
|
@@ -3952,7 +4909,7 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
|
|
3952
4909
|
|
3953
4910
|
// Setup the elements pointer in the allocated arguments object and
|
3954
4911
|
// initialize the header in the elements fixed array.
|
3955
|
-
__ add(r4, r0, Operand(
|
4912
|
+
__ add(r4, r0, Operand(GetArgumentsObjectSize()));
|
3956
4913
|
__ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
|
3957
4914
|
__ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
|
3958
4915
|
__ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset));
|
@@ -4019,10 +4976,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
4019
4976
|
Register last_match_info_elements = r6;
|
4020
4977
|
|
4021
4978
|
// Ensure that a RegExp stack is allocated.
|
4979
|
+
Isolate* isolate = masm->isolate();
|
4022
4980
|
ExternalReference address_of_regexp_stack_memory_address =
|
4023
|
-
ExternalReference::address_of_regexp_stack_memory_address();
|
4981
|
+
ExternalReference::address_of_regexp_stack_memory_address(isolate);
|
4024
4982
|
ExternalReference address_of_regexp_stack_memory_size =
|
4025
|
-
ExternalReference::address_of_regexp_stack_memory_size();
|
4983
|
+
ExternalReference::address_of_regexp_stack_memory_size(isolate);
|
4026
4984
|
__ mov(r0, Operand(address_of_regexp_stack_memory_size));
|
4027
4985
|
__ ldr(r0, MemOperand(r0, 0));
|
4028
4986
|
__ tst(r0, Operand(r0));
|
@@ -4163,7 +5121,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
4163
5121
|
__ CompareObjectType(r7, r0, r0, CODE_TYPE);
|
4164
5122
|
__ b(ne, &runtime);
|
4165
5123
|
|
4166
|
-
// r3: encoding of subject string (1 if
|
5124
|
+
// r3: encoding of subject string (1 if ASCII, 0 if two_byte);
|
4167
5125
|
// r7: code
|
4168
5126
|
// subject: Subject string
|
4169
5127
|
// regexp_data: RegExp data (FixedArray)
|
@@ -4173,20 +5131,25 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
4173
5131
|
__ mov(r1, Operand(r1, ASR, kSmiTagSize));
|
4174
5132
|
|
4175
5133
|
// r1: previous index
|
4176
|
-
// r3: encoding of subject string (1 if
|
5134
|
+
// r3: encoding of subject string (1 if ASCII, 0 if two_byte);
|
4177
5135
|
// r7: code
|
4178
5136
|
// subject: Subject string
|
4179
5137
|
// regexp_data: RegExp data (FixedArray)
|
4180
5138
|
// All checks done. Now push arguments for native regexp code.
|
4181
|
-
__ IncrementCounter(
|
5139
|
+
__ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2);
|
4182
5140
|
|
4183
|
-
|
5141
|
+
// Isolates: note we add an additional parameter here (isolate pointer).
|
5142
|
+
static const int kRegExpExecuteArguments = 8;
|
4184
5143
|
static const int kParameterRegisters = 4;
|
4185
5144
|
__ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
|
4186
5145
|
|
4187
5146
|
// Stack pointer now points to cell where return address is to be written.
|
4188
5147
|
// Arguments are before that on the stack or in registers.
|
4189
5148
|
|
5149
|
+
// Argument 8 (sp[16]): Pass current isolate address.
|
5150
|
+
__ mov(r0, Operand(ExternalReference::isolate_address()));
|
5151
|
+
__ str(r0, MemOperand(sp, 4 * kPointerSize));
|
5152
|
+
|
4190
5153
|
// Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript.
|
4191
5154
|
__ mov(r0, Operand(1));
|
4192
5155
|
__ str(r0, MemOperand(sp, 3 * kPointerSize));
|
@@ -4200,7 +5163,8 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
4200
5163
|
__ str(r0, MemOperand(sp, 2 * kPointerSize));
|
4201
5164
|
|
4202
5165
|
// Argument 5 (sp[4]): static offsets vector buffer.
|
4203
|
-
__ mov(r0,
|
5166
|
+
__ mov(r0,
|
5167
|
+
Operand(ExternalReference::address_of_static_offsets_vector(isolate)));
|
4204
5168
|
__ str(r0, MemOperand(sp, 1 * kPointerSize));
|
4205
5169
|
|
4206
5170
|
// For arguments 4 and 3 get string length, calculate start of string data and
|
@@ -4248,9 +5212,10 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
4248
5212
|
// stack overflow (on the backtrack stack) was detected in RegExp code but
|
4249
5213
|
// haven't created the exception yet. Handle that in the runtime system.
|
4250
5214
|
// TODO(592): Rerunning the RegExp to get the stack overflow exception.
|
4251
|
-
__ mov(r1, Operand(ExternalReference::the_hole_value_location()));
|
5215
|
+
__ mov(r1, Operand(ExternalReference::the_hole_value_location(isolate)));
|
4252
5216
|
__ ldr(r1, MemOperand(r1, 0));
|
4253
|
-
__ mov(r2, Operand(ExternalReference(
|
5217
|
+
__ mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address,
|
5218
|
+
isolate)));
|
4254
5219
|
__ ldr(r0, MemOperand(r2, 0));
|
4255
5220
|
__ cmp(r0, r1);
|
4256
5221
|
__ b(eq, &runtime);
|
@@ -4270,7 +5235,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
4270
5235
|
|
4271
5236
|
__ bind(&failure);
|
4272
5237
|
// For failure and exception return null.
|
4273
|
-
__ mov(r0, Operand(
|
5238
|
+
__ mov(r0, Operand(FACTORY->null_value()));
|
4274
5239
|
__ add(sp, sp, Operand(4 * kPointerSize));
|
4275
5240
|
__ Ret();
|
4276
5241
|
|
@@ -4303,7 +5268,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
4303
5268
|
|
4304
5269
|
// Get the static offsets vector filled by the native regexp code.
|
4305
5270
|
ExternalReference address_of_static_offsets_vector =
|
4306
|
-
ExternalReference::address_of_static_offsets_vector();
|
5271
|
+
ExternalReference::address_of_static_offsets_vector(isolate);
|
4307
5272
|
__ mov(r2, Operand(address_of_static_offsets_vector));
|
4308
5273
|
|
4309
5274
|
// r1: number of capture registers
|
@@ -4375,7 +5340,7 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
|
|
4375
5340
|
// Interleave operations for better latency.
|
4376
5341
|
__ ldr(r2, ContextOperand(cp, Context::GLOBAL_INDEX));
|
4377
5342
|
__ add(r3, r0, Operand(JSRegExpResult::kSize));
|
4378
|
-
__ mov(r4, Operand(
|
5343
|
+
__ mov(r4, Operand(FACTORY->empty_fixed_array()));
|
4379
5344
|
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
|
4380
5345
|
__ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
|
4381
5346
|
__ ldr(r2, ContextOperand(r2, Context::REGEXP_RESULT_MAP_INDEX));
|
@@ -4396,13 +5361,13 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
|
|
4396
5361
|
// r5: Number of elements in array, untagged.
|
4397
5362
|
|
4398
5363
|
// Set map.
|
4399
|
-
__ mov(r2, Operand(
|
5364
|
+
__ mov(r2, Operand(FACTORY->fixed_array_map()));
|
4400
5365
|
__ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
|
4401
5366
|
// Set FixedArray length.
|
4402
5367
|
__ mov(r6, Operand(r5, LSL, kSmiTagSize));
|
4403
5368
|
__ str(r6, FieldMemOperand(r3, FixedArray::kLengthOffset));
|
4404
5369
|
// Fill contents of fixed-array with the-hole.
|
4405
|
-
__ mov(r2, Operand(
|
5370
|
+
__ mov(r2, Operand(FACTORY->the_hole_value()));
|
4406
5371
|
__ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
4407
5372
|
// Fill fixed array elements with hole.
|
4408
5373
|
// r0: JSArray, tagged.
|
@@ -4479,7 +5444,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
|
|
4479
5444
|
__ mov(r0, Operand(argc_)); // Setup the number of arguments.
|
4480
5445
|
__ mov(r2, Operand(0, RelocInfo::NONE));
|
4481
5446
|
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
|
4482
|
-
__ Jump(
|
5447
|
+
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
|
4483
5448
|
RelocInfo::CODE_TARGET);
|
4484
5449
|
}
|
4485
5450
|
|
@@ -4492,7 +5457,8 @@ const char* CompareStub::GetName() {
|
|
4492
5457
|
|
4493
5458
|
if (name_ != NULL) return name_;
|
4494
5459
|
const int kMaxNameLength = 100;
|
4495
|
-
name_ =
|
5460
|
+
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
5461
|
+
kMaxNameLength);
|
4496
5462
|
if (name_ == NULL) return "OOM";
|
4497
5463
|
|
4498
5464
|
const char* cc_name;
|
@@ -4705,7 +5671,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
|
|
4705
5671
|
__ b(ne, &slow_case_);
|
4706
5672
|
|
4707
5673
|
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
|
4708
|
-
// At this point code register contains smi tagged
|
5674
|
+
// At this point code register contains smi tagged ASCII char code.
|
4709
5675
|
STATIC_ASSERT(kSmiTag == 0);
|
4710
5676
|
__ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize));
|
4711
5677
|
__ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
|
@@ -5037,7 +6003,6 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
|
5037
6003
|
Register symbol_table = c2;
|
5038
6004
|
__ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
|
5039
6005
|
|
5040
|
-
// Load undefined value
|
5041
6006
|
Register undefined = scratch4;
|
5042
6007
|
__ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
|
5043
6008
|
|
@@ -5058,6 +6023,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
|
5058
6023
|
// mask: capacity mask
|
5059
6024
|
// first_symbol_table_element: address of the first element of
|
5060
6025
|
// the symbol table
|
6026
|
+
// undefined: the undefined object
|
5061
6027
|
// scratch: -
|
5062
6028
|
|
5063
6029
|
// Perform a number of probes in the symbol table.
|
@@ -5085,20 +6051,32 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
|
5085
6051
|
kPointerSizeLog2));
|
5086
6052
|
|
5087
6053
|
// If entry is undefined no string with this hash can be found.
|
5088
|
-
|
6054
|
+
Label is_string;
|
6055
|
+
__ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE);
|
6056
|
+
__ b(ne, &is_string);
|
6057
|
+
|
6058
|
+
__ cmp(undefined, candidate);
|
5089
6059
|
__ b(eq, not_found);
|
6060
|
+
// Must be null (deleted entry).
|
6061
|
+
if (FLAG_debug_code) {
|
6062
|
+
__ LoadRoot(ip, Heap::kNullValueRootIndex);
|
6063
|
+
__ cmp(ip, candidate);
|
6064
|
+
__ Assert(eq, "oddball in symbol table is not undefined or null");
|
6065
|
+
}
|
6066
|
+
__ jmp(&next_probe[i]);
|
6067
|
+
|
6068
|
+
__ bind(&is_string);
|
6069
|
+
|
6070
|
+
// Check that the candidate is a non-external ASCII string. The instance
|
6071
|
+
// type is still in the scratch register from the CompareObjectType
|
6072
|
+
// operation.
|
6073
|
+
__ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]);
|
5090
6074
|
|
5091
6075
|
// If length is not 2 the string is not a candidate.
|
5092
6076
|
__ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset));
|
5093
6077
|
__ cmp(scratch, Operand(Smi::FromInt(2)));
|
5094
6078
|
__ b(ne, &next_probe[i]);
|
5095
6079
|
|
5096
|
-
// Check that the candidate is a non-external ascii string.
|
5097
|
-
__ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset));
|
5098
|
-
__ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
|
5099
|
-
__ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch,
|
5100
|
-
&next_probe[i]);
|
5101
|
-
|
5102
6080
|
// Check if the two characters match.
|
5103
6081
|
// Assumes that word load is little endian.
|
5104
6082
|
__ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize));
|
@@ -5173,7 +6151,6 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|
5173
6151
|
static const int kFromOffset = 1 * kPointerSize;
|
5174
6152
|
static const int kStringOffset = 2 * kPointerSize;
|
5175
6153
|
|
5176
|
-
|
5177
6154
|
// Check bounds and smi-ness.
|
5178
6155
|
Register to = r6;
|
5179
6156
|
Register from = r7;
|
@@ -5254,7 +6231,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|
5254
6231
|
// r3: from index (untaged smi)
|
5255
6232
|
// r5: string.
|
5256
6233
|
// r7 (a.k.a. from): from offset (smi)
|
5257
|
-
// Check for flat
|
6234
|
+
// Check for flat ASCII string.
|
5258
6235
|
Label non_ascii_flat;
|
5259
6236
|
__ tst(r1, Operand(kStringEncodingMask));
|
5260
6237
|
STATIC_ASSERT(kTwoByteStringTag == 0);
|
@@ -5274,7 +6251,8 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|
5274
6251
|
Label make_two_character_string;
|
5275
6252
|
StringHelper::GenerateTwoCharacterSymbolTableProbe(
|
5276
6253
|
masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string);
|
5277
|
-
|
6254
|
+
Counters* counters = masm->isolate()->counters();
|
6255
|
+
__ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
|
5278
6256
|
__ add(sp, sp, Operand(3 * kPointerSize));
|
5279
6257
|
__ Ret();
|
5280
6258
|
|
@@ -5283,7 +6261,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|
5283
6261
|
__ bind(&make_two_character_string);
|
5284
6262
|
__ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime);
|
5285
6263
|
__ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
|
5286
|
-
__ IncrementCounter(
|
6264
|
+
__ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
|
5287
6265
|
__ add(sp, sp, Operand(3 * kPointerSize));
|
5288
6266
|
__ Ret();
|
5289
6267
|
|
@@ -5309,7 +6287,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|
5309
6287
|
STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
|
5310
6288
|
StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
|
5311
6289
|
COPY_ASCII | DEST_ALWAYS_ALIGNED);
|
5312
|
-
__ IncrementCounter(
|
6290
|
+
__ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
|
5313
6291
|
__ add(sp, sp, Operand(3 * kPointerSize));
|
5314
6292
|
__ Ret();
|
5315
6293
|
|
@@ -5341,7 +6319,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|
5341
6319
|
STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
|
5342
6320
|
StringHelper::GenerateCopyCharactersLong(
|
5343
6321
|
masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
|
5344
|
-
__ IncrementCounter(
|
6322
|
+
__ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
|
5345
6323
|
__ add(sp, sp, Operand(3 * kPointerSize));
|
5346
6324
|
__ Ret();
|
5347
6325
|
|
@@ -5413,6 +6391,8 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
|
|
5413
6391
|
void StringCompareStub::Generate(MacroAssembler* masm) {
|
5414
6392
|
Label runtime;
|
5415
6393
|
|
6394
|
+
Counters* counters = masm->isolate()->counters();
|
6395
|
+
|
5416
6396
|
// Stack frame on entry.
|
5417
6397
|
// sp[0]: right string
|
5418
6398
|
// sp[4]: left string
|
@@ -5424,17 +6404,17 @@ void StringCompareStub::Generate(MacroAssembler* masm) {
|
|
5424
6404
|
STATIC_ASSERT(EQUAL == 0);
|
5425
6405
|
STATIC_ASSERT(kSmiTag == 0);
|
5426
6406
|
__ mov(r0, Operand(Smi::FromInt(EQUAL)));
|
5427
|
-
__ IncrementCounter(
|
6407
|
+
__ IncrementCounter(counters->string_compare_native(), 1, r1, r2);
|
5428
6408
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5429
6409
|
__ Ret();
|
5430
6410
|
|
5431
6411
|
__ bind(¬_same);
|
5432
6412
|
|
5433
|
-
// Check that both objects are sequential
|
6413
|
+
// Check that both objects are sequential ASCII strings.
|
5434
6414
|
__ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime);
|
5435
6415
|
|
5436
|
-
// Compare flat
|
5437
|
-
__ IncrementCounter(
|
6416
|
+
// Compare flat ASCII strings natively. Remove arguments from stack first.
|
6417
|
+
__ IncrementCounter(counters->string_compare_native(), 1, r2, r3);
|
5438
6418
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5439
6419
|
GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5);
|
5440
6420
|
|
@@ -5449,6 +6429,8 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5449
6429
|
Label string_add_runtime, call_builtin;
|
5450
6430
|
Builtins::JavaScript builtin_id = Builtins::ADD;
|
5451
6431
|
|
6432
|
+
Counters* counters = masm->isolate()->counters();
|
6433
|
+
|
5452
6434
|
// Stack on entry:
|
5453
6435
|
// sp[0]: second argument (right).
|
5454
6436
|
// sp[4]: first argument (left).
|
@@ -5504,7 +6486,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5504
6486
|
__ cmp(r3, Operand(Smi::FromInt(0)), ne);
|
5505
6487
|
__ b(ne, &strings_not_empty); // If either string was empty, return r0.
|
5506
6488
|
|
5507
|
-
__ IncrementCounter(
|
6489
|
+
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
5508
6490
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5509
6491
|
__ Ret();
|
5510
6492
|
|
@@ -5525,12 +6507,12 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5525
6507
|
// Adding two lengths can't overflow.
|
5526
6508
|
STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
|
5527
6509
|
__ add(r6, r2, Operand(r3));
|
5528
|
-
// Use the
|
5529
|
-
//
|
6510
|
+
// Use the symbol table when adding two one character strings, as it
|
6511
|
+
// helps later optimizations to return a symbol here.
|
5530
6512
|
__ cmp(r6, Operand(2));
|
5531
6513
|
__ b(ne, &longer_than_two);
|
5532
6514
|
|
5533
|
-
// Check that both strings are non-external
|
6515
|
+
// Check that both strings are non-external ASCII strings.
|
5534
6516
|
if (flags_ != NO_STRING_ADD_FLAGS) {
|
5535
6517
|
__ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
|
5536
6518
|
__ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
|
@@ -5549,7 +6531,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5549
6531
|
Label make_two_character_string;
|
5550
6532
|
StringHelper::GenerateTwoCharacterSymbolTableProbe(
|
5551
6533
|
masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string);
|
5552
|
-
__ IncrementCounter(
|
6534
|
+
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
5553
6535
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5554
6536
|
__ Ret();
|
5555
6537
|
|
@@ -5562,7 +6544,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5562
6544
|
__ mov(r6, Operand(2));
|
5563
6545
|
__ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime);
|
5564
6546
|
__ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
|
5565
|
-
__ IncrementCounter(
|
6547
|
+
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
5566
6548
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5567
6549
|
__ Ret();
|
5568
6550
|
|
@@ -5578,7 +6560,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5578
6560
|
__ b(hs, &string_add_runtime);
|
5579
6561
|
|
5580
6562
|
// If result is not supposed to be flat, allocate a cons string object.
|
5581
|
-
// If both strings are
|
6563
|
+
// If both strings are ASCII the result is an ASCII cons string.
|
5582
6564
|
if (flags_ != NO_STRING_ADD_FLAGS) {
|
5583
6565
|
__ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
|
5584
6566
|
__ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
|
@@ -5599,13 +6581,13 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5599
6581
|
__ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
|
5600
6582
|
__ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
|
5601
6583
|
__ mov(r0, Operand(r7));
|
5602
|
-
__ IncrementCounter(
|
6584
|
+
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
5603
6585
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5604
6586
|
__ Ret();
|
5605
6587
|
|
5606
6588
|
__ bind(&non_ascii);
|
5607
6589
|
// At least one of the strings is two-byte. Check whether it happens
|
5608
|
-
// to contain only
|
6590
|
+
// to contain only ASCII characters.
|
5609
6591
|
// r4: first instance type.
|
5610
6592
|
// r5: second instance type.
|
5611
6593
|
__ tst(r4, Operand(kAsciiDataHintMask));
|
@@ -5681,7 +6663,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5681
6663
|
// r7: result string.
|
5682
6664
|
StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true);
|
5683
6665
|
__ mov(r0, Operand(r7));
|
5684
|
-
__ IncrementCounter(
|
6666
|
+
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
5685
6667
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5686
6668
|
__ Ret();
|
5687
6669
|
|
@@ -5722,7 +6704,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|
5722
6704
|
StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
|
5723
6705
|
|
5724
6706
|
__ mov(r0, Operand(r7));
|
5725
|
-
__ IncrementCounter(
|
6707
|
+
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
5726
6708
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
5727
6709
|
__ Ret();
|
5728
6710
|
|
@@ -5786,56 +6768,6 @@ void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
|
|
5786
6768
|
}
|
5787
6769
|
|
5788
6770
|
|
5789
|
-
void StringCharAtStub::Generate(MacroAssembler* masm) {
|
5790
|
-
// Expects two arguments (object, index) on the stack:
|
5791
|
-
// lr: return address
|
5792
|
-
// sp[0]: index
|
5793
|
-
// sp[4]: object
|
5794
|
-
Register object = r1;
|
5795
|
-
Register index = r0;
|
5796
|
-
Register scratch1 = r2;
|
5797
|
-
Register scratch2 = r3;
|
5798
|
-
Register result = r0;
|
5799
|
-
|
5800
|
-
// Get object and index from the stack.
|
5801
|
-
__ pop(index);
|
5802
|
-
__ pop(object);
|
5803
|
-
|
5804
|
-
Label need_conversion;
|
5805
|
-
Label index_out_of_range;
|
5806
|
-
Label done;
|
5807
|
-
StringCharAtGenerator generator(object,
|
5808
|
-
index,
|
5809
|
-
scratch1,
|
5810
|
-
scratch2,
|
5811
|
-
result,
|
5812
|
-
&need_conversion,
|
5813
|
-
&need_conversion,
|
5814
|
-
&index_out_of_range,
|
5815
|
-
STRING_INDEX_IS_NUMBER);
|
5816
|
-
generator.GenerateFast(masm);
|
5817
|
-
__ b(&done);
|
5818
|
-
|
5819
|
-
__ bind(&index_out_of_range);
|
5820
|
-
// When the index is out of range, the spec requires us to return
|
5821
|
-
// the empty string.
|
5822
|
-
__ LoadRoot(result, Heap::kEmptyStringRootIndex);
|
5823
|
-
__ jmp(&done);
|
5824
|
-
|
5825
|
-
__ bind(&need_conversion);
|
5826
|
-
// Move smi zero into the result register, which will trigger
|
5827
|
-
// conversion.
|
5828
|
-
__ mov(result, Operand(Smi::FromInt(0)));
|
5829
|
-
__ b(&done);
|
5830
|
-
|
5831
|
-
StubRuntimeCallHelper call_helper;
|
5832
|
-
generator.GenerateSlow(masm, call_helper);
|
5833
|
-
|
5834
|
-
__ bind(&done);
|
5835
|
-
__ Ret();
|
5836
|
-
}
|
5837
|
-
|
5838
|
-
|
5839
6771
|
void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
|
5840
6772
|
ASSERT(state_ == CompareIC::SMIS);
|
5841
6773
|
Label miss;
|
@@ -5934,7 +6866,8 @@ void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
|
|
5934
6866
|
__ push(lr);
|
5935
6867
|
|
5936
6868
|
// Call the runtime system in a fresh internal frame.
|
5937
|
-
ExternalReference miss =
|
6869
|
+
ExternalReference miss =
|
6870
|
+
ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate());
|
5938
6871
|
__ EnterInternalFrame();
|
5939
6872
|
__ Push(r1, r0);
|
5940
6873
|
__ mov(ip, Operand(Smi::FromInt(op_)));
|
@@ -5957,11 +6890,10 @@ void DirectCEntryStub::Generate(MacroAssembler* masm) {
|
|
5957
6890
|
|
5958
6891
|
|
5959
6892
|
void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
5960
|
-
|
6893
|
+
ExternalReference function) {
|
5961
6894
|
__ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
|
5962
6895
|
RelocInfo::CODE_TARGET));
|
5963
|
-
__ mov(r2,
|
5964
|
-
Operand(ExternalReference(function, ExternalReference::DIRECT_CALL)));
|
6896
|
+
__ mov(r2, Operand(function));
|
5965
6897
|
// Push return address (accessible to GC through exit frame pc).
|
5966
6898
|
__ str(pc, MemOperand(sp, 0));
|
5967
6899
|
__ Jump(r2); // Call the api function.
|
@@ -5978,158 +6910,6 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
|
5978
6910
|
}
|
5979
6911
|
|
5980
6912
|
|
5981
|
-
void GenerateFastPixelArrayLoad(MacroAssembler* masm,
|
5982
|
-
Register receiver,
|
5983
|
-
Register key,
|
5984
|
-
Register elements_map,
|
5985
|
-
Register elements,
|
5986
|
-
Register scratch1,
|
5987
|
-
Register scratch2,
|
5988
|
-
Register result,
|
5989
|
-
Label* not_pixel_array,
|
5990
|
-
Label* key_not_smi,
|
5991
|
-
Label* out_of_range) {
|
5992
|
-
// Register use:
|
5993
|
-
//
|
5994
|
-
// receiver - holds the receiver on entry.
|
5995
|
-
// Unchanged unless 'result' is the same register.
|
5996
|
-
//
|
5997
|
-
// key - holds the smi key on entry.
|
5998
|
-
// Unchanged unless 'result' is the same register.
|
5999
|
-
//
|
6000
|
-
// elements - set to be the receiver's elements on exit.
|
6001
|
-
//
|
6002
|
-
// elements_map - set to be the map of the receiver's elements
|
6003
|
-
// on exit.
|
6004
|
-
//
|
6005
|
-
// result - holds the result of the pixel array load on exit,
|
6006
|
-
// tagged as a smi if successful.
|
6007
|
-
//
|
6008
|
-
// Scratch registers:
|
6009
|
-
//
|
6010
|
-
// scratch1 - used a scratch register in map check, if map
|
6011
|
-
// check is successful, contains the length of the
|
6012
|
-
// pixel array, the pointer to external elements and
|
6013
|
-
// the untagged result.
|
6014
|
-
//
|
6015
|
-
// scratch2 - holds the untaged key.
|
6016
|
-
|
6017
|
-
// Some callers already have verified that the key is a smi. key_not_smi is
|
6018
|
-
// set to NULL as a sentinel for that case. Otherwise, add an explicit check
|
6019
|
-
// to ensure the key is a smi must be added.
|
6020
|
-
if (key_not_smi != NULL) {
|
6021
|
-
__ JumpIfNotSmi(key, key_not_smi);
|
6022
|
-
} else {
|
6023
|
-
if (FLAG_debug_code) {
|
6024
|
-
__ AbortIfNotSmi(key);
|
6025
|
-
}
|
6026
|
-
}
|
6027
|
-
__ SmiUntag(scratch2, key);
|
6028
|
-
|
6029
|
-
// Verify that the receiver has pixel array elements.
|
6030
|
-
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
6031
|
-
__ CheckMap(elements, scratch1, Heap::kPixelArrayMapRootIndex,
|
6032
|
-
not_pixel_array, true);
|
6033
|
-
|
6034
|
-
// Key must be in range of the pixel array.
|
6035
|
-
__ ldr(scratch1, FieldMemOperand(elements, PixelArray::kLengthOffset));
|
6036
|
-
__ cmp(scratch2, scratch1);
|
6037
|
-
__ b(hs, out_of_range); // unsigned check handles negative keys.
|
6038
|
-
|
6039
|
-
// Perform the indexed load and tag the result as a smi.
|
6040
|
-
__ ldr(scratch1,
|
6041
|
-
FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
|
6042
|
-
__ ldrb(scratch1, MemOperand(scratch1, scratch2));
|
6043
|
-
__ SmiTag(r0, scratch1);
|
6044
|
-
__ Ret();
|
6045
|
-
}
|
6046
|
-
|
6047
|
-
|
6048
|
-
void GenerateFastPixelArrayStore(MacroAssembler* masm,
|
6049
|
-
Register receiver,
|
6050
|
-
Register key,
|
6051
|
-
Register value,
|
6052
|
-
Register elements,
|
6053
|
-
Register elements_map,
|
6054
|
-
Register scratch1,
|
6055
|
-
Register scratch2,
|
6056
|
-
bool load_elements_from_receiver,
|
6057
|
-
bool load_elements_map_from_elements,
|
6058
|
-
Label* key_not_smi,
|
6059
|
-
Label* value_not_smi,
|
6060
|
-
Label* not_pixel_array,
|
6061
|
-
Label* out_of_range) {
|
6062
|
-
// Register use:
|
6063
|
-
// receiver - holds the receiver and is unchanged unless the
|
6064
|
-
// store succeeds.
|
6065
|
-
// key - holds the key (must be a smi) and is unchanged.
|
6066
|
-
// value - holds the value (must be a smi) and is unchanged.
|
6067
|
-
// elements - holds the element object of the receiver on entry if
|
6068
|
-
// load_elements_from_receiver is false, otherwise used
|
6069
|
-
// internally to store the pixel arrays elements and
|
6070
|
-
// external array pointer.
|
6071
|
-
// elements_map - holds the map of the element object if
|
6072
|
-
// load_elements_map_from_elements is false, otherwise
|
6073
|
-
// loaded with the element map.
|
6074
|
-
//
|
6075
|
-
Register external_pointer = elements;
|
6076
|
-
Register untagged_key = scratch1;
|
6077
|
-
Register untagged_value = scratch2;
|
6078
|
-
|
6079
|
-
if (load_elements_from_receiver) {
|
6080
|
-
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
6081
|
-
}
|
6082
|
-
|
6083
|
-
// By passing NULL as not_pixel_array, callers signal that they have already
|
6084
|
-
// verified that the receiver has pixel array elements.
|
6085
|
-
if (not_pixel_array != NULL) {
|
6086
|
-
if (load_elements_map_from_elements) {
|
6087
|
-
__ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
|
6088
|
-
}
|
6089
|
-
__ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
|
6090
|
-
__ cmp(elements_map, ip);
|
6091
|
-
__ b(ne, not_pixel_array);
|
6092
|
-
} else {
|
6093
|
-
if (FLAG_debug_code) {
|
6094
|
-
// Map check should have already made sure that elements is a pixel array.
|
6095
|
-
__ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
|
6096
|
-
__ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
|
6097
|
-
__ cmp(elements_map, ip);
|
6098
|
-
__ Assert(eq, "Elements isn't a pixel array");
|
6099
|
-
}
|
6100
|
-
}
|
6101
|
-
|
6102
|
-
// Some callers already have verified that the key is a smi. key_not_smi is
|
6103
|
-
// set to NULL as a sentinel for that case. Otherwise, add an explicit check
|
6104
|
-
// to ensure the key is a smi must be added.
|
6105
|
-
if (key_not_smi != NULL) {
|
6106
|
-
__ JumpIfNotSmi(key, key_not_smi);
|
6107
|
-
} else {
|
6108
|
-
if (FLAG_debug_code) {
|
6109
|
-
__ AbortIfNotSmi(key);
|
6110
|
-
}
|
6111
|
-
}
|
6112
|
-
|
6113
|
-
__ SmiUntag(untagged_key, key);
|
6114
|
-
|
6115
|
-
// Perform bounds check.
|
6116
|
-
__ ldr(scratch2, FieldMemOperand(elements, PixelArray::kLengthOffset));
|
6117
|
-
__ cmp(untagged_key, scratch2);
|
6118
|
-
__ b(hs, out_of_range); // unsigned check handles negative keys.
|
6119
|
-
|
6120
|
-
__ JumpIfNotSmi(value, value_not_smi);
|
6121
|
-
__ SmiUntag(untagged_value, value);
|
6122
|
-
|
6123
|
-
// Clamp the value to [0..255].
|
6124
|
-
__ Usat(untagged_value, 8, Operand(untagged_value));
|
6125
|
-
// Get the pointer to the external array. This clobbers elements.
|
6126
|
-
__ ldr(external_pointer,
|
6127
|
-
FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
|
6128
|
-
__ strb(untagged_value, MemOperand(external_pointer, untagged_key));
|
6129
|
-
__ Ret();
|
6130
|
-
}
|
6131
|
-
|
6132
|
-
|
6133
6913
|
#undef __
|
6134
6914
|
|
6135
6915
|
} } // namespace v8::internal
|