From 5d1b6d3e0fa4b97a490ef964be48aed9872e3ec1 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 14 Nov 2014 00:52:27 +0100 Subject: [PATCH] deps: upgrade v8 to 3.30.37 --- deps/v8/.gitignore | 4 + deps/v8/AUTHORS | 5 + deps/v8/BUILD.gn | 65 +- deps/v8/ChangeLog | 284 + deps/v8/Makefile | 22 +- deps/v8/Makefile.nacl | 51 +- deps/v8/OWNERS | 1 - deps/v8/README.md | 26 + deps/v8/build/all.gyp | 8 +- deps/v8/build/standalone.gypi | 23 +- deps/v8/build/toolchain.gypi | 33 +- deps/v8/include/v8-platform.h | 9 + deps/v8/include/v8-profiler.h | 20 + deps/v8/include/v8.h | 628 +- deps/v8/include/v8config.h | 16 +- deps/v8/include/v8stdint.h | 33 - deps/v8/src/DEPS | 3 +- deps/v8/src/accessors.cc | 39 +- deps/v8/src/accessors.h | 5 +- deps/v8/src/allocation.cc | 2 +- deps/v8/src/api.cc | 795 +- deps/v8/src/api.h | 6 +- deps/v8/src/arm/assembler-arm.cc | 132 +- deps/v8/src/arm/assembler-arm.h | 26 +- deps/v8/src/arm/code-stubs-arm.cc | 89 +- deps/v8/src/arm/codegen-arm.cc | 16 +- deps/v8/src/arm/constants-arm.h | 52 +- deps/v8/src/arm/debug-arm.cc | 6 +- deps/v8/src/arm/disasm-arm.cc | 65 +- deps/v8/src/arm/full-codegen-arm.cc | 467 +- deps/v8/src/arm/interface-descriptors-arm.cc | 12 + deps/v8/src/arm/lithium-arm.cc | 12 +- deps/v8/src/arm/lithium-codegen-arm.cc | 18 +- deps/v8/src/arm/macro-assembler-arm.cc | 27 +- deps/v8/src/arm/macro-assembler-arm.h | 68 +- deps/v8/src/arm/simulator-arm.cc | 80 +- deps/v8/src/arm64/assembler-arm64.cc | 6 + deps/v8/src/arm64/assembler-arm64.h | 3 + deps/v8/src/arm64/builtins-arm64.cc | 2 +- deps/v8/src/arm64/code-stubs-arm64.cc | 87 +- deps/v8/src/arm64/codegen-arm64.cc | 19 +- deps/v8/src/arm64/debug-arm64.cc | 6 +- deps/v8/src/arm64/delayed-masm-arm64.cc | 4 +- deps/v8/src/arm64/disasm-arm64.cc | 2 +- deps/v8/src/arm64/full-codegen-arm64.cc | 499 +- .../src/arm64/interface-descriptors-arm64.cc | 11 + deps/v8/src/arm64/lithium-arm64.cc | 12 +- deps/v8/src/arm64/lithium-codegen-arm64.cc | 18 +- deps/v8/src/arm64/macro-assembler-arm64-inl.h | 14 + deps/v8/src/arm64/macro-assembler-arm64.cc | 7 + deps/v8/src/arm64/macro-assembler-arm64.h | 3 + deps/v8/src/arm64/simulator-arm64.cc | 10 + deps/v8/src/array-iterator.js | 4 +- deps/v8/src/array.js | 117 +- deps/v8/src/arraybuffer.js | 3 + deps/v8/src/assembler.cc | 37 +- deps/v8/src/assembler.h | 46 +- deps/v8/src/assert-scope.h | 2 +- deps/v8/src/ast-numbering.cc | 479 + deps/v8/src/ast-numbering.h | 19 + deps/v8/src/ast-value-factory.cc | 121 +- deps/v8/src/ast-value-factory.h | 121 +- deps/v8/src/ast.cc | 130 +- deps/v8/src/ast.h | 1155 +- deps/v8/src/base/atomicops.h | 12 +- deps/v8/src/base/atomicops_internals_mac.h | 23 +- .../src/base/atomicops_internals_portable.h | 138 + deps/v8/src/base/base.gyp | 46 - deps/v8/src/base/bits.cc | 28 + deps/v8/src/base/bits.h | 96 +- deps/v8/src/base/build_config.h | 4 + deps/v8/src/base/compiler-specific.h | 12 +- deps/v8/src/base/cpu.cc | 66 +- deps/v8/src/base/division-by-constant.cc | 4 +- deps/v8/src/base/flags.h | 79 +- deps/v8/src/base/functional.cc | 111 + deps/v8/src/base/functional.h | 227 + deps/v8/src/base/logging.h | 2 +- deps/v8/src/base/macros.h | 53 +- deps/v8/src/base/once.h | 2 + deps/v8/src/base/platform/platform-linux.cc | 2 +- deps/v8/src/base/platform/platform-posix.cc | 12 +- deps/v8/src/base/platform/platform-solaris.cc | 20 - deps/v8/src/base/platform/platform-win32.cc | 61 +- deps/v8/src/base/platform/platform.h | 42 +- deps/v8/src/base/sys-info.h | 2 +- .../src/base/utils/random-number-generator.cc | 7 + .../src/base/utils/random-number-generator.h | 7 + deps/v8/src/base/win32-math.cc | 82 - deps/v8/src/base/win32-math.h | 42 - deps/v8/src/basic-block-profiler.cc | 36 +- deps/v8/src/basic-block-profiler.h | 22 +- deps/v8/src/bignum-dtoa.cc | 1 - deps/v8/src/{data-flow.cc => bit-vector.cc} | 14 +- deps/v8/src/{data-flow.h => bit-vector.h} | 63 +- deps/v8/src/bootstrapper.cc | 181 +- deps/v8/src/builtins.cc | 89 +- deps/v8/src/builtins.h | 4 +- deps/v8/src/cached-powers.cc | 2 +- deps/v8/src/char-predicates.cc | 42 + deps/v8/src/char-predicates.h | 52 +- deps/v8/src/code-factory.cc | 31 +- deps/v8/src/code-factory.h | 10 +- deps/v8/src/code-stubs-hydrogen.cc | 151 +- deps/v8/src/code-stubs.cc | 92 +- deps/v8/src/code-stubs.h | 328 +- deps/v8/src/codegen.cc | 2 - deps/v8/src/collection-iterator.js | 4 + deps/v8/src/collection.js | 22 +- deps/v8/src/compilation-cache.cc | 70 +- deps/v8/src/compilation-cache.h | 20 +- deps/v8/src/compilation-statistics.cc | 144 + deps/v8/src/compilation-statistics.h | 86 + deps/v8/src/compiler.cc | 141 +- deps/v8/src/compiler.h | 31 +- deps/v8/src/compiler/access-builder.cc | 66 +- deps/v8/src/compiler/access-builder.h | 9 + .../v8/src/compiler/arm/code-generator-arm.cc | 45 +- .../src/compiler/arm/instruction-codes-arm.h | 7 + .../compiler/arm/instruction-selector-arm.cc | 407 +- deps/v8/src/compiler/arm/linkage-arm.cc | 7 +- .../compiler/arm64/code-generator-arm64.cc | 170 +- .../compiler/arm64/instruction-codes-arm64.h | 34 +- .../arm64/instruction-selector-arm64.cc | 775 +- deps/v8/src/compiler/arm64/linkage-arm64.cc | 7 +- deps/v8/src/compiler/ast-graph-builder.cc | 381 +- deps/v8/src/compiler/ast-graph-builder.h | 55 +- .../compiler/ast-loop-assignment-analyzer.cc | 305 + .../compiler/ast-loop-assignment-analyzer.h | 78 + .../src/compiler/basic-block-instrumentor.cc | 22 +- deps/v8/src/compiler/change-lowering.cc | 246 +- deps/v8/src/compiler/change-lowering.h | 21 +- deps/v8/src/compiler/code-generator-impl.h | 20 +- deps/v8/src/compiler/code-generator.cc | 168 +- deps/v8/src/compiler/code-generator.h | 29 +- deps/v8/src/compiler/common-node-cache.h | 20 +- .../src/compiler/common-operator-unittest.cc | 183 - deps/v8/src/compiler/common-operator.cc | 356 +- deps/v8/src/compiler/common-operator.h | 113 +- deps/v8/src/compiler/compiler.gyp | 60 - deps/v8/src/compiler/control-builders.cc | 8 +- deps/v8/src/compiler/control-builders.h | 7 +- deps/v8/src/compiler/control-reducer.cc | 574 + deps/v8/src/compiler/control-reducer.h | 39 + deps/v8/src/compiler/diamond.h | 85 + deps/v8/src/compiler/frame.h | 2 +- deps/v8/src/compiler/generic-algorithm.h | 33 +- deps/v8/src/compiler/generic-graph.h | 4 +- deps/v8/src/compiler/generic-node-inl.h | 27 +- deps/v8/src/compiler/generic-node.h | 13 +- deps/v8/src/compiler/graph-builder.cc | 92 +- deps/v8/src/compiler/graph-builder.h | 70 +- deps/v8/src/compiler/graph-reducer.cc | 5 +- deps/v8/src/compiler/graph-replay.cc | 7 +- deps/v8/src/compiler/graph-replay.h | 2 +- deps/v8/src/compiler/graph-visualizer.cc | 809 +- deps/v8/src/compiler/graph-visualizer.h | 54 +- deps/v8/src/compiler/graph.cc | 19 +- deps/v8/src/compiler/graph.h | 10 +- .../src/compiler/ia32/code-generator-ia32.cc | 123 +- .../compiler/ia32/instruction-codes-ia32.h | 6 + .../ia32/instruction-selector-ia32.cc | 684 +- deps/v8/src/compiler/ia32/linkage-ia32.cc | 7 +- deps/v8/src/compiler/instruction-codes.h | 16 +- .../src/compiler/instruction-selector-impl.h | 28 +- deps/v8/src/compiler/instruction-selector.cc | 624 +- deps/v8/src/compiler/instruction-selector.h | 76 +- deps/v8/src/compiler/instruction.cc | 354 +- deps/v8/src/compiler/instruction.h | 341 +- .../compiler/js-builtin-reducer-unittest.cc | 236 - deps/v8/src/compiler/js-builtin-reducer.cc | 67 +- deps/v8/src/compiler/js-builtin-reducer.h | 2 + .../src/compiler/js-context-specialization.cc | 15 +- deps/v8/src/compiler/js-generic-lowering.cc | 119 +- deps/v8/src/compiler/js-generic-lowering.h | 6 +- deps/v8/src/compiler/js-graph.cc | 57 +- deps/v8/src/compiler/js-graph.h | 37 +- deps/v8/src/compiler/js-inlining.cc | 141 +- deps/v8/src/compiler/js-inlining.h | 8 +- deps/v8/src/compiler/js-intrinsic-builder.cc | 141 + deps/v8/src/compiler/js-intrinsic-builder.h | 40 + deps/v8/src/compiler/js-operator.cc | 398 + deps/v8/src/compiler/js-operator.h | 384 +- deps/v8/src/compiler/js-typed-lowering.cc | 268 +- deps/v8/src/compiler/js-typed-lowering.h | 7 +- deps/v8/src/compiler/linkage-impl.h | 92 +- deps/v8/src/compiler/linkage.cc | 148 +- deps/v8/src/compiler/linkage.h | 78 +- .../machine-operator-reducer-unittest.cc | 659 - .../src/compiler/machine-operator-reducer.cc | 414 +- .../src/compiler/machine-operator-reducer.h | 18 + deps/v8/src/compiler/machine-operator.cc | 270 +- deps/v8/src/compiler/machine-operator.h | 87 +- deps/v8/src/compiler/machine-type.cc | 2 +- deps/v8/src/compiler/machine-type.h | 36 +- deps/v8/src/compiler/mips/OWNERS | 5 + .../src/compiler/mips/code-generator-mips.cc | 970 + .../compiler/mips/instruction-codes-mips.h | 88 + .../mips/instruction-selector-mips.cc | 726 + deps/v8/src/compiler/mips/linkage-mips.cc | 67 + deps/v8/src/compiler/node-aux-data-inl.h | 2 +- deps/v8/src/compiler/node-aux-data.h | 2 +- deps/v8/src/compiler/node-cache.cc | 113 +- deps/v8/src/compiler/node-cache.h | 34 +- deps/v8/src/compiler/node-matchers.h | 101 +- deps/v8/src/compiler/node-properties-inl.h | 52 +- deps/v8/src/compiler/node-properties.h | 2 + deps/v8/src/compiler/node.cc | 9 +- deps/v8/src/compiler/node.h | 11 +- deps/v8/src/compiler/opcodes.h | 56 +- .../v8/src/compiler/operator-properties-inl.h | 122 +- deps/v8/src/compiler/operator-properties.h | 14 - deps/v8/src/compiler/operator.cc | 35 +- deps/v8/src/compiler/operator.h | 209 +- deps/v8/src/compiler/phi-reducer.h | 1 + deps/v8/src/compiler/pipeline-statistics.cc | 103 + deps/v8/src/compiler/pipeline-statistics.h | 95 + deps/v8/src/compiler/pipeline.cc | 499 +- deps/v8/src/compiler/pipeline.h | 13 +- deps/v8/src/compiler/raw-machine-assembler.cc | 15 +- deps/v8/src/compiler/raw-machine-assembler.h | 61 +- deps/v8/src/compiler/register-allocator.cc | 670 +- deps/v8/src/compiler/register-allocator.h | 165 +- .../v8/src/compiler/register-configuration.cc | 68 + deps/v8/src/compiler/register-configuration.h | 56 + deps/v8/src/compiler/representation-change.h | 52 +- deps/v8/src/compiler/schedule.cc | 276 +- deps/v8/src/compiler/schedule.h | 383 +- deps/v8/src/compiler/scheduler.cc | 2149 +- deps/v8/src/compiler/scheduler.h | 92 +- deps/v8/src/compiler/select-lowering.cc | 51 + deps/v8/src/compiler/select-lowering.h | 46 + deps/v8/src/compiler/simplified-lowering.cc | 731 +- deps/v8/src/compiler/simplified-lowering.h | 14 +- .../compiler/simplified-operator-reducer.cc | 36 + .../compiler/simplified-operator-reducer.h | 5 +- deps/v8/src/compiler/simplified-operator.cc | 150 +- deps/v8/src/compiler/simplified-operator.h | 36 +- deps/v8/src/compiler/source-position.cc | 2 +- deps/v8/src/compiler/source-position.h | 2 +- deps/v8/src/compiler/typer.cc | 1700 +- deps/v8/src/compiler/typer.h | 39 +- .../src/compiler/value-numbering-reducer.cc | 119 +- .../v8/src/compiler/value-numbering-reducer.h | 11 +- deps/v8/src/compiler/verifier.cc | 759 +- deps/v8/src/compiler/verifier.h | 4 +- .../v8/src/compiler/x64/code-generator-x64.cc | 477 +- .../src/compiler/x64/instruction-codes-x64.h | 9 +- .../x64/instruction-selector-x64-unittest.cc | 294 - .../compiler/x64/instruction-selector-x64.cc | 838 +- deps/v8/src/compiler/x64/linkage-x64.cc | 7 +- deps/v8/src/compiler/zone-pool.cc | 140 + deps/v8/src/compiler/zone-pool.h | 93 + deps/v8/src/contexts.cc | 20 +- deps/v8/src/contexts.h | 38 - deps/v8/src/conversions.cc | 28 +- deps/v8/src/conversions.h | 6 +- deps/v8/src/counters.cc | 5 +- deps/v8/src/cpu-profiler.cc | 66 +- deps/v8/src/cpu-profiler.h | 4 +- deps/v8/src/d8-debug.cc | 2 +- deps/v8/src/d8.cc | 97 +- deps/v8/src/date.h | 48 +- deps/v8/src/debug-debugger.js | 3 +- deps/v8/src/debug.cc | 284 +- deps/v8/src/debug.h | 53 +- deps/v8/src/deoptimizer.cc | 5 +- deps/v8/src/disassembler.cc | 14 +- deps/v8/src/disassembler.h | 2 +- deps/v8/src/diy-fp.cc | 2 +- deps/v8/src/dtoa.cc | 1 - deps/v8/src/execution.cc | 12 + .../v8/src/extensions/statistics-extension.cc | 3 +- deps/v8/src/factory.cc | 138 +- deps/v8/src/factory.h | 24 +- deps/v8/src/fast-dtoa.cc | 2 +- deps/v8/src/feedback-slots.h | 27 - deps/v8/src/fixed-dtoa.cc | 3 +- deps/v8/src/flag-definitions.h | 124 +- deps/v8/src/flags.cc | 19 +- deps/v8/src/frames-inl.h | 4 +- deps/v8/src/frames.cc | 8 +- deps/v8/src/frames.h | 5 + deps/v8/src/full-codegen.cc | 59 +- deps/v8/src/full-codegen.h | 61 +- deps/v8/src/gdb-jit.cc | 2 +- deps/v8/src/generator.js | 2 + deps/v8/src/global-handles.cc | 74 +- deps/v8/src/global-handles.h | 23 +- deps/v8/src/globals.h | 85 +- deps/v8/src/handles.h | 3 +- deps/v8/src/harmony-array.js | 16 +- deps/v8/src/harmony-string.js | 15 +- deps/v8/src/harmony-tostring.js | 74 + deps/v8/src/harmony-typedarray.js | 79 + deps/v8/src/heap-snapshot-generator-inl.h | 2 +- deps/v8/src/heap-snapshot-generator.cc | 16 +- deps/v8/src/heap-snapshot-generator.h | 22 +- deps/v8/src/heap/gc-idle-time-handler.cc | 103 +- deps/v8/src/heap/gc-idle-time-handler.h | 16 +- deps/v8/src/heap/heap-inl.h | 8 +- deps/v8/src/heap/heap.cc | 268 +- deps/v8/src/heap/heap.gyp | 52 - deps/v8/src/heap/heap.h | 343 +- deps/v8/src/heap/incremental-marking.cc | 45 +- deps/v8/src/heap/incremental-marking.h | 20 +- deps/v8/src/heap/mark-compact.cc | 242 +- deps/v8/src/heap/mark-compact.h | 9 +- deps/v8/src/heap/objects-visiting-inl.h | 19 + deps/v8/src/heap/objects-visiting.cc | 3 + deps/v8/src/heap/objects-visiting.h | 2 + deps/v8/src/heap/spaces.cc | 110 +- deps/v8/src/heap/spaces.h | 38 +- deps/v8/src/heap/sweeper-thread.cc | 82 - deps/v8/src/heap/sweeper-thread.h | 45 - deps/v8/src/hydrogen-bch.cc | 7 +- deps/v8/src/hydrogen-dce.cc | 2 +- deps/v8/src/hydrogen-gvn.cc | 14 +- deps/v8/src/hydrogen-gvn.h | 8 +- deps/v8/src/hydrogen-instructions.cc | 436 +- deps/v8/src/hydrogen-instructions.h | 635 +- .../v8/src/hydrogen-representation-changes.cc | 12 +- deps/v8/src/hydrogen-types.cc | 2 +- deps/v8/src/hydrogen-types.h | 6 +- deps/v8/src/hydrogen.cc | 397 +- deps/v8/src/hydrogen.h | 41 +- deps/v8/src/i18n.cc | 2 + deps/v8/src/ia32/assembler-ia32.cc | 72 +- deps/v8/src/ia32/assembler-ia32.h | 31 +- deps/v8/src/ia32/builtins-ia32.cc | 22 +- deps/v8/src/ia32/code-stubs-ia32.cc | 76 +- deps/v8/src/ia32/codegen-ia32.cc | 13 + deps/v8/src/ia32/debug-ia32.cc | 6 +- deps/v8/src/ia32/disasm-ia32.cc | 15 +- deps/v8/src/ia32/full-codegen-ia32.cc | 443 +- .../v8/src/ia32/interface-descriptors-ia32.cc | 12 + deps/v8/src/ia32/lithium-codegen-ia32.cc | 17 +- deps/v8/src/ia32/lithium-ia32.cc | 12 +- deps/v8/src/ia32/macro-assembler-ia32.cc | 84 +- deps/v8/src/ia32/macro-assembler-ia32.h | 10 +- deps/v8/src/ic/arm/handler-compiler-arm.cc | 204 +- deps/v8/src/ic/arm/ic-arm.cc | 61 +- .../v8/src/ic/arm64/handler-compiler-arm64.cc | 197 +- deps/v8/src/ic/arm64/ic-arm64.cc | 62 +- deps/v8/src/ic/handler-compiler.cc | 50 +- deps/v8/src/ic/handler-compiler.h | 13 +- deps/v8/src/ic/ia32/handler-compiler-ia32.cc | 189 +- deps/v8/src/ic/ia32/ic-ia32.cc | 61 +- deps/v8/src/ic/ic-compiler.cc | 39 +- deps/v8/src/ic/ic-compiler.h | 5 +- deps/v8/src/ic/ic-inl.h | 19 +- deps/v8/src/ic/ic-state.cc | 18 +- deps/v8/src/ic/ic-state.h | 10 +- deps/v8/src/ic/ic.cc | 306 +- deps/v8/src/ic/ic.h | 95 +- deps/v8/src/ic/mips/handler-compiler-mips.cc | 208 +- deps/v8/src/ic/mips/ic-mips.cc | 61 +- .../src/ic/mips64/handler-compiler-mips64.cc | 208 +- deps/v8/src/ic/mips64/ic-mips64.cc | 61 +- deps/v8/src/ic/x64/handler-compiler-x64.cc | 188 +- deps/v8/src/ic/x64/ic-x64.cc | 59 +- deps/v8/src/ic/x64/stub-cache-x64.cc | 8 +- deps/v8/src/ic/x87/handler-compiler-x87.cc | 191 +- deps/v8/src/ic/x87/ic-x87.cc | 61 +- deps/v8/src/interface-descriptors.cc | 9 +- deps/v8/src/interface-descriptors.h | 26 +- deps/v8/src/interface.cc | 96 +- deps/v8/src/interface.h | 12 +- deps/v8/src/isolate.cc | 709 +- deps/v8/src/isolate.h | 90 +- deps/v8/src/json-parser.h | 56 +- deps/v8/src/json.js | 2 + deps/v8/src/jsregexp.cc | 23 +- deps/v8/src/libplatform/default-platform.cc | 6 + deps/v8/src/libplatform/default-platform.h | 1 + deps/v8/src/libplatform/libplatform.gyp | 39 - deps/v8/src/list-inl.h | 7 +- deps/v8/src/list.h | 4 +- deps/v8/src/lithium-codegen.cc | 10 +- deps/v8/src/lithium.cc | 4 +- deps/v8/src/liveedit.cc | 27 +- deps/v8/src/liveedit.h | 14 +- deps/v8/src/log-inl.h | 11 + deps/v8/src/log.cc | 57 +- deps/v8/src/log.h | 6 +- deps/v8/src/lookup.cc | 22 + deps/v8/src/lookup.h | 4 + deps/v8/src/macro-assembler.h | 68 + deps/v8/src/macros.py | 3 +- deps/v8/src/math.js | 4 +- deps/v8/src/messages.js | 35 +- deps/v8/src/mips/assembler-mips.cc | 1 + deps/v8/src/mips/code-stubs-mips.cc | 96 +- deps/v8/src/mips/codegen-mips.cc | 16 +- deps/v8/src/mips/constants-mips.h | 2 +- deps/v8/src/mips/debug-mips.cc | 6 +- deps/v8/src/mips/disasm-mips.cc | 8 +- deps/v8/src/mips/full-codegen-mips.cc | 460 +- .../v8/src/mips/interface-descriptors-mips.cc | 12 + deps/v8/src/mips/lithium-codegen-mips.cc | 18 +- deps/v8/src/mips/lithium-mips.cc | 16 +- deps/v8/src/mips/macro-assembler-mips.cc | 96 +- deps/v8/src/mips/macro-assembler-mips.h | 3 + deps/v8/src/mips64/builtins-mips64.cc | 7 +- deps/v8/src/mips64/code-stubs-mips64.cc | 95 +- deps/v8/src/mips64/codegen-mips64.cc | 16 +- deps/v8/src/mips64/debug-mips64.cc | 6 +- deps/v8/src/mips64/full-codegen-mips64.cc | 460 +- .../mips64/interface-descriptors-mips64.cc | 12 + deps/v8/src/mips64/lithium-codegen-mips64.cc | 18 +- deps/v8/src/mips64/lithium-mips64.cc | 12 +- deps/v8/src/mips64/macro-assembler-mips64.cc | 11 +- deps/v8/src/mips64/macro-assembler-mips64.h | 1 + deps/v8/src/mips64/simulator-mips64.cc | 3 +- deps/v8/src/mips64/simulator-mips64.h | 9 +- deps/v8/src/mirror-debugger.js | 51 +- deps/v8/src/misc-intrinsics.h | 66 - deps/v8/src/mksnapshot.cc | 55 +- deps/v8/src/object-observe.js | 116 +- deps/v8/src/objects-debug.cc | 87 +- deps/v8/src/objects-inl.h | 281 +- deps/v8/src/objects-printer.cc | 286 +- deps/v8/src/objects.cc | 1021 +- deps/v8/src/objects.h | 369 +- deps/v8/src/optimizing-compiler-thread.cc | 97 +- deps/v8/src/optimizing-compiler-thread.h | 17 +- deps/v8/src/ostreams.cc | 174 +- deps/v8/src/ostreams.h | 126 +- deps/v8/src/parser.cc | 126 +- deps/v8/src/parser.h | 45 +- deps/v8/src/preparse-data.cc | 1 - deps/v8/src/preparser.cc | 55 +- deps/v8/src/preparser.h | 465 +- deps/v8/src/profile-generator-inl.h | 22 +- deps/v8/src/profile-generator.cc | 164 +- deps/v8/src/profile-generator.h | 74 +- deps/v8/src/promise.js | 51 +- deps/v8/src/property-details.h | 4 + deps/v8/src/property.cc | 40 +- deps/v8/src/property.h | 8 +- deps/v8/src/rewriter.cc | 18 +- deps/v8/src/runtime-profiler.cc | 20 +- deps/v8/src/runtime/runtime-api.cc | 127 + deps/v8/src/runtime/runtime-array.cc | 1196 + deps/v8/src/runtime/runtime-classes.cc | 459 + deps/v8/src/runtime/runtime-collections.cc | 37 +- deps/v8/src/runtime/runtime-compiler.cc | 27 +- deps/v8/src/runtime/runtime-date.cc | 189 + deps/v8/src/runtime/runtime-debug.cc | 2730 + deps/v8/src/runtime/runtime-function.cc | 625 + deps/v8/src/runtime/runtime-generator.cc | 229 + deps/v8/src/runtime/runtime-i18n.cc | 24 +- deps/v8/src/runtime/runtime-internal.cc | 282 + deps/v8/src/runtime/runtime-json.cc | 1 - deps/v8/src/runtime/runtime-literals.cc | 466 + deps/v8/src/runtime/runtime-liveedit.cc | 293 + deps/v8/src/runtime/runtime-maths.cc | 5 +- deps/v8/src/runtime/runtime-numbers.cc | 45 +- deps/v8/src/runtime/runtime-object.cc | 1587 + deps/v8/src/runtime/runtime-observe.cc | 147 + deps/v8/src/runtime/runtime-proxy.cc | 85 + deps/v8/src/runtime/runtime-regexp.cc | 44 +- deps/v8/src/runtime/runtime-scopes.cc | 1028 + deps/v8/src/runtime/runtime-strings.cc | 55 +- deps/v8/src/runtime/runtime-symbol.cc | 100 + deps/v8/src/runtime/runtime-test.cc | 97 +- deps/v8/src/runtime/runtime-typedarray.cc | 8 + deps/v8/src/runtime/runtime-uri.cc | 1 - deps/v8/src/runtime/runtime-utils.h | 7 +- deps/v8/src/runtime/runtime.cc | 9217 +--- deps/v8/src/runtime/runtime.h | 88 +- deps/v8/src/runtime/string-builder.h | 6 +- deps/v8/src/safepoint-table.cc | 5 +- deps/v8/src/safepoint-table.h | 4 +- deps/v8/src/sampler.cc | 86 +- deps/v8/src/sampler.h | 23 +- deps/v8/src/scanner-character-streams.cc | 23 +- deps/v8/src/scanner-character-streams.h | 2 +- deps/v8/src/scanner.cc | 84 +- deps/v8/src/scanner.h | 44 +- deps/v8/src/scopeinfo.cc | 10 +- deps/v8/src/scopes.cc | 27 +- deps/v8/src/scopes.h | 26 +- deps/v8/src/serialize.cc | 686 +- deps/v8/src/serialize.h | 467 +- deps/v8/src/snapshot-common.cc | 34 +- deps/v8/src/snapshot-external.cc | 53 +- deps/v8/src/snapshot-source-sink.cc | 10 +- deps/v8/src/snapshot-source-sink.h | 50 +- deps/v8/src/string-iterator.js | 2 + deps/v8/src/string-stream.cc | 3 +- deps/v8/src/symbol.js | 11 +- deps/v8/src/test/DEPS | 3 - deps/v8/src/test/test-utils.cc | 58 - deps/v8/src/test/test.gyp | 71 - deps/v8/{ => src}/third_party/fdlibm/LICENSE | 0 .../v8/{ => src}/third_party/fdlibm/README.v8 | 0 .../v8/{ => src}/third_party/fdlibm/fdlibm.cc | 2 +- deps/v8/{ => src}/third_party/fdlibm/fdlibm.h | 0 .../v8/{ => src}/third_party/fdlibm/fdlibm.js | 2 +- deps/v8/src/third_party/vtune/v8-vtune.h | 2 +- deps/v8/src/third_party/vtune/vtune-jit.cc | 4 +- deps/v8/src/token.cc | 2 +- deps/v8/src/token.h | 19 + deps/v8/src/transitions-inl.h | 89 +- deps/v8/src/transitions.cc | 157 +- deps/v8/src/transitions.h | 95 +- deps/v8/src/type-feedback-vector-inl.h | 7 +- deps/v8/src/type-feedback-vector.cc | 271 + deps/v8/src/type-feedback-vector.h | 220 + deps/v8/src/type-info.cc | 78 +- deps/v8/src/type-info.h | 26 +- deps/v8/src/typedarray.js | 12 +- deps/v8/src/types-inl.h | 14 + deps/v8/src/types.cc | 44 +- deps/v8/src/types.h | 35 +- deps/v8/src/typing.cc | 14 +- deps/v8/src/typing.h | 6 +- deps/v8/src/unicode-decoder.cc | 78 + deps/v8/src/unicode-decoder.h | 121 + deps/v8/src/unicode-inl.h | 65 +- deps/v8/src/unicode.cc | 3598 +- deps/v8/src/unicode.h | 84 +- deps/v8/src/unique.h | 14 +- deps/v8/src/utils.cc | 12 + deps/v8/src/utils.h | 80 +- deps/v8/src/v8natives.js | 113 +- deps/v8/src/v8threads.cc | 19 +- deps/v8/src/vector.h | 4 + deps/v8/src/version.cc | 6 +- deps/v8/src/vm-state.h | 5 + deps/v8/src/weak-collection.js | 4 + deps/v8/src/x64/assembler-x64-inl.h | 5 + deps/v8/src/x64/assembler-x64.cc | 142 +- deps/v8/src/x64/assembler-x64.h | 76 +- deps/v8/src/x64/builtins-x64.cc | 19 +- deps/v8/src/x64/code-stubs-x64.cc | 76 +- deps/v8/src/x64/codegen-x64.cc | 14 + deps/v8/src/x64/debug-x64.cc | 6 +- deps/v8/src/x64/disasm-x64.cc | 138 +- deps/v8/src/x64/full-codegen-x64.cc | 447 +- deps/v8/src/x64/interface-descriptors-x64.cc | 12 + deps/v8/src/x64/lithium-codegen-x64.cc | 18 +- deps/v8/src/x64/lithium-x64.cc | 12 +- deps/v8/src/x64/macro-assembler-x64.cc | 59 + deps/v8/src/x64/macro-assembler-x64.h | 4 + deps/v8/src/x87/assembler-x87.cc | 10 +- deps/v8/src/x87/assembler-x87.h | 7 +- deps/v8/src/x87/builtins-x87.cc | 22 +- deps/v8/src/x87/code-stubs-x87.cc | 41 +- deps/v8/src/x87/codegen-x87.cc | 13 + deps/v8/src/x87/debug-x87.cc | 6 +- deps/v8/src/x87/disasm-x87.cc | 6 +- deps/v8/src/x87/full-codegen-x87.cc | 443 +- deps/v8/src/x87/interface-descriptors-x87.cc | 12 + deps/v8/src/x87/lithium-codegen-x87.cc | 27 +- deps/v8/src/x87/lithium-x87.cc | 12 +- deps/v8/src/x87/macro-assembler-x87.cc | 18 +- deps/v8/src/x87/macro-assembler-x87.h | 7 +- deps/v8/src/zone-containers.h | 6 + deps/v8/src/zone.cc | 1 + deps/v8/test/benchmarks/testcfg.py | 2 +- deps/v8/test/cctest/cctest.cc | 18 +- deps/v8/test/cctest/cctest.gyp | 11 +- deps/v8/test/cctest/cctest.h | 34 +- deps/v8/test/cctest/cctest.status | 11 + deps/v8/test/cctest/compiler/call-tester.h | 2 +- .../v8/test/cctest/compiler/codegen-tester.cc | 7 +- deps/v8/test/cctest/compiler/codegen-tester.h | 13 +- .../v8/test/cctest/compiler/function-tester.h | 124 +- .../cctest/compiler/graph-builder-tester.cc | 2 +- .../cctest/compiler/graph-builder-tester.h | 4 +- .../compiler/simplified-graph-builder.cc | 20 +- .../compiler/simplified-graph-builder.h | 6 +- .../cctest/compiler/test-changes-lowering.cc | 50 +- .../cctest/compiler/test-codegen-deopt.cc | 61 +- .../cctest/compiler/test-control-reducer.cc | 1681 + .../test/cctest/compiler/test-gap-resolver.cc | 7 +- .../cctest/compiler/test-graph-reducer.cc | 18 +- .../cctest/compiler/test-graph-visualizer.cc | 92 + .../test/cctest/compiler/test-instruction.cc | 137 +- .../cctest/compiler/test-js-constant-cache.cc | 191 +- .../test-js-context-specialization.cc | 13 +- .../cctest/compiler/test-js-typed-lowering.cc | 127 +- deps/v8/test/cctest/compiler/test-linkage.cc | 15 +- .../compiler/test-loop-assignment-analysis.cc | 294 + .../compiler/test-machine-operator-reducer.cc | 46 +- .../cctest/compiler/test-node-algorithm.cc | 146 +- .../test/cctest/compiler/test-node-cache.cc | 60 + deps/v8/test/cctest/compiler/test-node.cc | 4 +- deps/v8/test/cctest/compiler/test-operator.cc | 185 +- deps/v8/test/cctest/compiler/test-pipeline.cc | 6 +- .../compiler/test-representation-change.cc | 8 +- .../test/cctest/compiler/test-run-inlining.cc | 97 + .../cctest/compiler/test-run-intrinsics.cc | 76 +- .../cctest/compiler/test-run-jsbranches.cc | 75 + .../test/cctest/compiler/test-run-machops.cc | 515 +- .../cctest/compiler/test-run-stackcheck.cc | 18 + deps/v8/test/cctest/compiler/test-schedule.cc | 82 +- .../v8/test/cctest/compiler/test-scheduler.cc | 718 +- .../compiler/test-simplified-lowering.cc | 638 +- deps/v8/test/cctest/compiler/test-typer.cc | 379 + deps/v8/test/cctest/compiler/value-helper.h | 2 + deps/v8/test/cctest/test-alloc.cc | 6 +- deps/v8/test/cctest/test-api.cc | 876 +- deps/v8/test/cctest/test-assembler-arm.cc | 225 +- deps/v8/test/cctest/test-assembler-arm64.cc | 89 + deps/v8/test/cctest/test-ast.cc | 4 +- .../{test-dataflow.cc => test-bit-vector.cc} | 4 +- deps/v8/test/cctest/test-code-stubs-mips64.cc | 2 +- deps/v8/test/cctest/test-compiler.cc | 24 +- deps/v8/test/cctest/test-cpu-profiler.cc | 98 + deps/v8/test/cctest/test-debug.cc | 102 + deps/v8/test/cctest/test-decls.cc | 34 + deps/v8/test/cctest/test-disasm-arm.cc | 30 + deps/v8/test/cctest/test-disasm-arm64.cc | 4 + deps/v8/test/cctest/test-disasm-ia32.cc | 13 + deps/v8/test/cctest/test-disasm-x64.cc | 46 +- deps/v8/test/cctest/test-disasm-x87.cc | 6 + deps/v8/test/cctest/test-feedback-vector.cc | 242 + .../test/cctest/test-func-name-inference.cc | 18 +- deps/v8/test/cctest/test-heap.cc | 260 +- deps/v8/test/cctest/test-lockers.cc | 1 + deps/v8/test/cctest/test-log-stack-tracer.cc | 4 +- deps/v8/test/cctest/test-object-observe.cc | 53 + deps/v8/test/cctest/test-ostreams.cc | 148 - deps/v8/test/cctest/test-parsing.cc | 409 +- deps/v8/test/cctest/test-platform.cc | 2 +- deps/v8/test/cctest/test-regexp.cc | 12 +- deps/v8/test/cctest/test-sampler-api.cc | 245 + deps/v8/test/cctest/test-serialize.cc | 584 +- deps/v8/test/cctest/test-spaces.cc | 60 +- deps/v8/test/cctest/test-strings.cc | 71 +- deps/v8/test/cctest/test-transitions.cc | 283 + deps/v8/test/cctest/test-types.cc | 289 +- deps/v8/test/cctest/test-utils.cc | 44 +- deps/v8/test/cctest/trace-extension.cc | 3 +- deps/v8/test/cctest/types-fuzz.h | 322 + .../compiler-unittests.status | 6 - deps/v8/test/fuzz-natives/base.js | 103 - deps/v8/test/fuzz-natives/fuzz-natives.status | 71 - deps/v8/test/fuzz-natives/testcfg.py | 52 - .../test/heap-unittests/heap-unittests.status | 6 - deps/v8/test/intl/general/smp-identifier.js | 43 + .../v8/test/js-perf-test/Classes/Classes.json | 13 + deps/v8/test/js-perf-test/Classes/run.js | 27 + deps/v8/test/js-perf-test/Classes/super.js | 59 + .../js-perf-test/Collections/Collections.json | 21 + .../test/js-perf-test/Collections/common.js | 31 + deps/v8/test/js-perf-test/Collections/map.js | 217 + .../Collections/run.js | 3 +- deps/v8/test/js-perf-test/Collections/set.js | 172 + .../Collections/weakmap.js | 21 +- .../Collections/weakset.js | 21 +- .../js-perf-test/Iterators/Iterators.json | 12 + deps/v8/test/js-perf-test/Iterators/forof.js | 94 + deps/v8/test/js-perf-test/Iterators/run.js | 27 + .../v8/test/js-perf-test/Strings/Strings.json | 13 + .../js-perf-test/Strings/harmony-string.js | 111 + deps/v8/test/js-perf-test/Strings/run.js | 27 + .../Collections => js-perf-test}/base.js | 0 .../libplatform-unittests.status | 6 - deps/v8/test/mjsunit/array-iteration.js | 85 + .../v8/test/mjsunit/array-natives-elements.js | 7 +- deps/v8/test/mjsunit/array-reduce.js | 10 + deps/v8/test/mjsunit/array-shift2.js | 16 +- deps/v8/test/mjsunit/array-unshift.js | 26 +- deps/v8/test/mjsunit/asm/do-while-false.js | 78 + deps/v8/test/mjsunit/asm/do-while.js | 30 + deps/v8/test/mjsunit/asm/embenchen/box2d.js | 20326 ++++++++ deps/v8/test/mjsunit/asm/embenchen/copy.js | 5980 +++ .../test/mjsunit/asm/embenchen/corrections.js | 5987 +++ .../v8/test/mjsunit/asm/embenchen/fannkuch.js | 8439 +++ deps/v8/test/mjsunit/asm/embenchen/fasta.js | 8609 ++++ .../mjsunit/asm/embenchen/lua_binarytrees.js | 42714 ++++++++++++++++ deps/v8/test/mjsunit/asm/embenchen/memops.js | 8091 +++ deps/v8/test/mjsunit/asm/embenchen/primes.js | 5988 +++ deps/v8/test/mjsunit/asm/embenchen/zlib.js | 14756 ++++++ .../mjsunit/asm/float32array-outofbounds.js | 30 + .../mjsunit/asm/float32array-store-div.js | 16 + .../mjsunit/asm/float64array-outofbounds.js | 30 + .../mjsunit/asm/float64array-store-div.js | 16 + deps/v8/test/mjsunit/asm/float64mul.js | 33 + deps/v8/test/mjsunit/asm/if-folding.js | 100 + deps/v8/test/mjsunit/asm/if-reduction.js | 111 + .../test/mjsunit/asm/infinite-loops-taken.js | 41 + deps/v8/test/mjsunit/asm/infinite-loops.js | 53 + .../mjsunit/asm/int16array-outofbounds.js | 42 + deps/v8/test/mjsunit/asm/int32-div.js | 33 + deps/v8/test/mjsunit/asm/int32-mod.js | 33 + deps/v8/test/mjsunit/asm/int32-mul.js | 33 + deps/v8/test/mjsunit/asm/int32-tmod.js | 38 + deps/v8/test/mjsunit/asm/int32-udiv.js | 33 + deps/v8/test/mjsunit/asm/int32-umod.js | 33 + .../mjsunit/asm/int32array-constant-key.js | 62 + .../mjsunit/asm/int32array-outofbounds.js | 30 + deps/v8/test/mjsunit/asm/int32div.js | 33 + deps/v8/test/mjsunit/asm/int32mod.js | 33 + deps/v8/test/mjsunit/asm/math-ceil.js | 38 + deps/v8/test/mjsunit/asm/math-floor.js | 38 + .../mjsunit/asm/uint32-less-than-shift.js | 61 + deps/v8/test/mjsunit/asm/uint32div.js | 45 + deps/v8/test/mjsunit/asm/uint32mod.js | 29 + .../mjsunit/asm/uint8array-outofbounds.js | 30 + deps/v8/test/mjsunit/asm/word32and.js | 29 + deps/v8/test/mjsunit/big-array-literal.js | 1 + deps/v8/test/mjsunit/boolean.js | 7 + deps/v8/test/mjsunit/bugs/bug-2615.js | 86 - .../compiler/deopt-inlined-from-call.js | 154 + .../mjsunit/compiler/inlined-call-mapcheck.js | 43 + deps/v8/test/mjsunit/compiler/inlined-call.js | 190 + .../compiler/regress-register-allocator.js | 33 + .../compiler/regress-register-allocator2.js | 17 + .../compiler/regress-register-allocator3.js | 46 + deps/v8/test/mjsunit/compiler/shift-shr.js | 2 +- deps/v8/test/mjsunit/debug-references.js | 2 +- deps/v8/test/mjsunit/debug-script.js | 3 +- deps/v8/test/mjsunit/debug-step-turbofan.js | 57 + deps/v8/test/mjsunit/debug-stepframe.js | 111 + .../v8/test/mjsunit/es6/arguments-iterator.js | 20 +- deps/v8/test/mjsunit/es6/array-iterator.js | 28 +- .../test/mjsunit/es6/collection-iterator.js | 20 +- deps/v8/test/mjsunit/es6/collections.js | 70 +- .../v8/test/mjsunit/es6/generators-objects.js | 3 +- deps/v8/test/mjsunit/es6/json.js | 15 + deps/v8/test/mjsunit/es6/math.js | 15 + deps/v8/test/mjsunit/es6/mirror-iterators.js | 62 + .../{harmony => es6}/numeric-literals.js | 0 deps/v8/test/mjsunit/es6/object-tostring.js | 133 + deps/v8/test/mjsunit/es6/promises.js | 14 +- deps/v8/test/mjsunit/es6/string-iterator.js | 7 + deps/v8/test/mjsunit/es6/symbols.js | 10 +- .../test/mjsunit/es6/typed-array-iterator.js | 4 +- deps/v8/test/mjsunit/fast-prototype.js | 4 +- deps/v8/test/mjsunit/function-call.js | 21 +- deps/v8/test/mjsunit/getters-on-elements.js | 2 +- deps/v8/test/mjsunit/harmony/array-find.js | 18 + .../test/mjsunit/harmony/array-findindex.js | 18 + deps/v8/test/mjsunit/harmony/classes.js | 603 + .../object-literals-property-shorthand.js | 51 + deps/v8/test/mjsunit/harmony/proxies.js | 2 +- .../mjsunit/harmony/regress/regress-343928.js | 2 +- deps/v8/test/mjsunit/harmony/string-repeat.js | 3 + deps/v8/test/mjsunit/harmony/super.js | 1721 +- .../mjsunit/harmony/typedarrays-foreach.js | 140 + deps/v8/test/mjsunit/harmony/typedarrays.js | 152 +- deps/v8/test/mjsunit/mjsunit.status | 44 +- deps/v8/test/mjsunit/nans.js | 17 +- .../mjsunit/object-get-own-property-names.js | 20 +- deps/v8/test/mjsunit/object-is.js | 4 +- deps/v8/test/mjsunit/parse-surrogates.js | 7 + deps/v8/test/mjsunit/polymorph-arrays.js | 7 +- deps/v8/test/mjsunit/regress/regress-2506.js | 78 + deps/v8/test/mjsunit/regress/regress-2615.js | 96 + deps/v8/test/mjsunit/regress/regress-3116.js | 314 + .../regress-3483.js} | 19 +- deps/v8/test/mjsunit/regress/regress-3612.js | 21 + deps/v8/test/mjsunit/regress/regress-3621.js | 11 + deps/v8/test/mjsunit/regress/regress-3643.js | 30 + .../v8/test/mjsunit/regress/regress-385565.js | 70 + .../test/mjsunit/regress/regress-417709a.js | 16 + .../test/mjsunit/regress/regress-417709b.js | 16 + .../v8/test/mjsunit/regress/regress-419663.js | 37 + .../v8/test/mjsunit/regress/regress-423633.js | 18 + .../v8/test/mjsunit/regress/regress-425551.js | 7 + deps/v8/test/mjsunit/regress/regress-78270.js | 2 + .../regress-assignment-in-test-context.js | 20 + .../mjsunit/regress/regress-crbug-137689.js | 3 +- .../mjsunit/regress/regress-crbug-409614.js | 37 + .../mjsunit/regress/regress-crbug-410033.js | 7 + .../mjsunit/regress/regress-crbug-412319.js | 2 +- .../mjsunit/regress/regress-crbug-417508.js | 29 + .../regress-crbug-423687.js} | 9 +- .../mjsunit/regress/regress-crbug-424142.js | 36 + .../mjsunit/regress/regress-crbug-425519.js | 15 + .../mjsunit/regress/regress-crbug-425585.js | 48 + .../mjsunit/regress/regress-crbug-429159.js | 12 + .../mjsunit/regress/regress-crbug-430846.js | 14 + .../mjsunit/regress/regress-eval-cache.js | 19 + .../regress/regress-shift-enumerable.js | 16 + .../test/mjsunit/serialize-embedded-error.js | 13 + deps/v8/test/mjsunit/serialize-ic.js | 9 + deps/v8/test/mjsunit/setters-on-elements.js | 4 +- deps/v8/test/mjsunit/sin-cos.js | 2 + deps/v8/test/mjsunit/strict-mode.js | 2 + .../test/mjsunit/third_party/object-keys.js | 4 +- .../mjsunit/tools/tickprocessor-test.default | 7 + .../tools/tickprocessor-test.func-info | 3 + .../mjsunit/tools/tickprocessor-test.gc-state | 3 + .../tools/tickprocessor-test.ignore-unknown | 7 + .../tools/tickprocessor-test.separate-ic | 7 + .../v8/test/mjsunit/unused-context-in-with.js | 13 + deps/v8/test/mjsunit/var.js | 19 + deps/v8/test/mozilla/mozilla.status | 11 +- .../perf-test/Collections/Collections.json | 15 - deps/v8/test/perf-test/Collections/map.js | 81 - deps/v8/test/perf-test/Collections/set.js | 66 - deps/v8/test/test262-es6/README | 4 +- deps/v8/test/test262-es6/test262-es6.status | 34 +- deps/v8/test/test262-es6/testcfg.py | 8 +- deps/v8/test/test262/test262.status | 11 + deps/v8/test/unittests/DEPS | 4 + .../unittests}/base/bits-unittest.cc | 114 + .../unittests}/base/cpu-unittest.cc | 0 .../base/division-by-constant-unittest.cc | 2 + .../unittests}/base/flags-unittest.cc | 2 +- .../unittests/base/functional-unittest.cc | 196 + .../platform/condition-variable-unittest.cc | 0 .../base/platform/mutex-unittest.cc | 0 .../base/platform/platform-unittest.cc | 0 .../base/platform/semaphore-unittest.cc | 0 .../unittests}/base/platform/time-unittest.cc | 0 .../unittests}/base/sys-info-unittest.cc | 0 .../utils/random-number-generator-unittest.cc | 0 .../unittests/char-predicates-unittest.cc | 121 + .../arm/instruction-selector-arm-unittest.cc | 348 +- .../instruction-selector-arm64-unittest.cc | 816 +- .../compiler/change-lowering-unittest.cc | 138 +- .../compiler/common-operator-unittest.cc | 292 + .../unittests}/compiler/compiler-test-utils.h | 6 +- .../unittests/compiler/diamond-unittest.cc | 161 + .../compiler/graph-reducer-unittest.cc | 14 +- .../test/unittests/compiler/graph-unittest.cc | 98 + .../test/unittests/compiler/graph-unittest.h | 79 + .../instruction-selector-ia32-unittest.cc | 215 +- .../compiler/instruction-selector-unittest.cc | 171 +- .../compiler/instruction-selector-unittest.h | 52 +- .../compiler/js-builtin-reducer-unittest.cc | 305 + .../compiler/js-operator-unittest.cc | 147 + .../compiler/js-typed-lowering-unittest.cc | 192 + .../machine-operator-reducer-unittest.cc | 1227 + .../compiler/machine-operator-unittest.cc | 131 +- deps/v8/test/unittests/compiler/mips/OWNERS | 5 + .../instruction-selector-mips-unittest.cc | 805 + .../unittests/compiler/node-test-utils.cc} | 589 +- .../unittests/compiler/node-test-utils.h} | 110 +- .../compiler/register-allocator-unittest.cc | 513 + .../compiler/select-lowering-unittest.cc | 62 + .../simplified-operator-reducer-unittest.cc | 128 +- .../compiler/simplified-operator-unittest.cc | 121 +- .../value-numbering-reducer-unittest.cc | 44 +- .../x64/instruction-selector-x64-unittest.cc | 370 + .../unittests/compiler/zone-pool-unittest.cc | 162 + .../heap/gc-idle-time-handler-unittest.cc | 100 +- .../libplatform/default-platform-unittest.cc | 0 .../libplatform/task-queue-unittest.cc | 0 .../libplatform/worker-thread-unittest.cc | 0 .../unittests}/run-all-unittests.cc | 0 deps/v8/test/unittests/test-utils.cc | 104 + .../{src/test => test/unittests}/test-utils.h | 28 +- deps/v8/test/unittests/unittests.gyp | 126 + .../unittests.status} | 0 .../Object-getOwnPropertyNames-expected.txt | 2 +- .../fast/js/Object-getOwnPropertyNames.js | 2 +- deps/v8/test/webkit/webkit.status | 11 + deps/v8/testing/gtest-support.h | 21 +- deps/v8/tools/codemap.js | 4 +- deps/v8/tools/gdbinit | 20 +- deps/v8/tools/gen-postmortem-metadata.py | 14 +- deps/v8/tools/gyp/v8.gyp | 246 +- deps/v8/tools/js2c.py | 13 +- deps/v8/tools/lexer-shell.cc | 236 - deps/v8/tools/logreader.js | 2 + deps/v8/tools/nacl-run.py | 18 +- .../{lexer-shell.gyp => parser-shell.gyp} | 23 - deps/v8/tools/presubmit.py | 3 +- deps/v8/tools/profile.js | 49 +- deps/v8/tools/push-to-trunk/auto_push.py | 42 +- deps/v8/tools/push-to-trunk/auto_roll.py | 3 + deps/v8/tools/push-to-trunk/auto_tag.py | 5 +- deps/v8/tools/push-to-trunk/chromium_roll.py | 13 +- .../v8/tools/push-to-trunk/common_includes.py | 134 +- deps/v8/tools/push-to-trunk/git_recipes.py | 15 +- .../v8/tools/push-to-trunk/merge_to_branch.py | 96 +- deps/v8/tools/push-to-trunk/push_to_trunk.py | 48 +- deps/v8/tools/push-to-trunk/releases.py | 78 +- deps/v8/tools/push-to-trunk/test_scripts.py | 694 +- deps/v8/tools/run-deopt-fuzzer.py | 1 + deps/v8/tools/run-llprof.sh | 2 +- deps/v8/tools/run-tests.py | 33 +- deps/v8/tools/run_perf.py | 33 +- .../v8/tools/sanitizers/tsan_suppressions.txt | 6 + deps/v8/tools/shell-utils.h | 2 +- deps/v8/tools/testrunner/local/statusfile.py | 7 +- deps/v8/tools/testrunner/local/testsuite.py | 13 + deps/v8/tools/tickprocessor.js | 9 + deps/v8/tools/unittests/run_perf_test.py | 23 +- deps/v8/tools/whitespace.txt | 4 +- 888 files changed, 192839 insertions(+), 31972 deletions(-) create mode 100644 deps/v8/README.md delete mode 100644 deps/v8/include/v8stdint.h create mode 100644 deps/v8/src/ast-numbering.cc create mode 100644 deps/v8/src/ast-numbering.h create mode 100644 deps/v8/src/base/atomicops_internals_portable.h delete mode 100644 deps/v8/src/base/base.gyp create mode 100644 deps/v8/src/base/functional.cc create mode 100644 deps/v8/src/base/functional.h delete mode 100644 deps/v8/src/base/win32-math.cc delete mode 100644 deps/v8/src/base/win32-math.h rename deps/v8/src/{data-flow.cc => bit-vector.cc} (74%) rename deps/v8/src/{data-flow.h => bit-vector.h} (79%) create mode 100644 deps/v8/src/char-predicates.cc create mode 100644 deps/v8/src/compilation-statistics.cc create mode 100644 deps/v8/src/compilation-statistics.h create mode 100644 deps/v8/src/compiler/ast-loop-assignment-analyzer.cc create mode 100644 deps/v8/src/compiler/ast-loop-assignment-analyzer.h delete mode 100644 deps/v8/src/compiler/common-operator-unittest.cc delete mode 100644 deps/v8/src/compiler/compiler.gyp create mode 100644 deps/v8/src/compiler/control-reducer.cc create mode 100644 deps/v8/src/compiler/control-reducer.h create mode 100644 deps/v8/src/compiler/diamond.h delete mode 100644 deps/v8/src/compiler/js-builtin-reducer-unittest.cc create mode 100644 deps/v8/src/compiler/js-intrinsic-builder.cc create mode 100644 deps/v8/src/compiler/js-intrinsic-builder.h create mode 100644 deps/v8/src/compiler/js-operator.cc delete mode 100644 deps/v8/src/compiler/machine-operator-reducer-unittest.cc create mode 100644 deps/v8/src/compiler/mips/OWNERS create mode 100644 deps/v8/src/compiler/mips/code-generator-mips.cc create mode 100644 deps/v8/src/compiler/mips/instruction-codes-mips.h create mode 100644 deps/v8/src/compiler/mips/instruction-selector-mips.cc create mode 100644 deps/v8/src/compiler/mips/linkage-mips.cc create mode 100644 deps/v8/src/compiler/pipeline-statistics.cc create mode 100644 deps/v8/src/compiler/pipeline-statistics.h create mode 100644 deps/v8/src/compiler/register-configuration.cc create mode 100644 deps/v8/src/compiler/register-configuration.h create mode 100644 deps/v8/src/compiler/select-lowering.cc create mode 100644 deps/v8/src/compiler/select-lowering.h delete mode 100644 deps/v8/src/compiler/x64/instruction-selector-x64-unittest.cc create mode 100644 deps/v8/src/compiler/zone-pool.cc create mode 100644 deps/v8/src/compiler/zone-pool.h delete mode 100644 deps/v8/src/feedback-slots.h create mode 100644 deps/v8/src/harmony-tostring.js create mode 100644 deps/v8/src/harmony-typedarray.js delete mode 100644 deps/v8/src/heap/heap.gyp delete mode 100644 deps/v8/src/heap/sweeper-thread.cc delete mode 100644 deps/v8/src/heap/sweeper-thread.h delete mode 100644 deps/v8/src/libplatform/libplatform.gyp delete mode 100644 deps/v8/src/misc-intrinsics.h create mode 100644 deps/v8/src/runtime/runtime-api.cc create mode 100644 deps/v8/src/runtime/runtime-array.cc create mode 100644 deps/v8/src/runtime/runtime-classes.cc create mode 100644 deps/v8/src/runtime/runtime-date.cc create mode 100644 deps/v8/src/runtime/runtime-debug.cc create mode 100644 deps/v8/src/runtime/runtime-function.cc create mode 100644 deps/v8/src/runtime/runtime-generator.cc create mode 100644 deps/v8/src/runtime/runtime-internal.cc create mode 100644 deps/v8/src/runtime/runtime-literals.cc create mode 100644 deps/v8/src/runtime/runtime-liveedit.cc create mode 100644 deps/v8/src/runtime/runtime-object.cc create mode 100644 deps/v8/src/runtime/runtime-observe.cc create mode 100644 deps/v8/src/runtime/runtime-proxy.cc create mode 100644 deps/v8/src/runtime/runtime-scopes.cc create mode 100644 deps/v8/src/runtime/runtime-symbol.cc delete mode 100644 deps/v8/src/test/DEPS delete mode 100644 deps/v8/src/test/test-utils.cc delete mode 100644 deps/v8/src/test/test.gyp rename deps/v8/{ => src}/third_party/fdlibm/LICENSE (100%) rename deps/v8/{ => src}/third_party/fdlibm/README.v8 (100%) rename deps/v8/{ => src}/third_party/fdlibm/fdlibm.cc (99%) rename deps/v8/{ => src}/third_party/fdlibm/fdlibm.h (100%) rename deps/v8/{ => src}/third_party/fdlibm/fdlibm.js (99%) create mode 100644 deps/v8/src/unicode-decoder.cc create mode 100644 deps/v8/src/unicode-decoder.h create mode 100644 deps/v8/test/cctest/compiler/test-control-reducer.cc create mode 100644 deps/v8/test/cctest/compiler/test-graph-visualizer.cc create mode 100644 deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc create mode 100644 deps/v8/test/cctest/compiler/test-run-stackcheck.cc create mode 100644 deps/v8/test/cctest/compiler/test-typer.cc rename deps/v8/test/cctest/{test-dataflow.cc => test-bit-vector.cc} (98%) create mode 100644 deps/v8/test/cctest/test-feedback-vector.cc delete mode 100644 deps/v8/test/cctest/test-ostreams.cc create mode 100644 deps/v8/test/cctest/test-sampler-api.cc create mode 100644 deps/v8/test/cctest/test-transitions.cc create mode 100644 deps/v8/test/cctest/types-fuzz.h delete mode 100644 deps/v8/test/compiler-unittests/compiler-unittests.status delete mode 100644 deps/v8/test/fuzz-natives/base.js delete mode 100644 deps/v8/test/fuzz-natives/fuzz-natives.status delete mode 100644 deps/v8/test/fuzz-natives/testcfg.py delete mode 100644 deps/v8/test/heap-unittests/heap-unittests.status create mode 100644 deps/v8/test/intl/general/smp-identifier.js create mode 100644 deps/v8/test/js-perf-test/Classes/Classes.json create mode 100644 deps/v8/test/js-perf-test/Classes/run.js create mode 100644 deps/v8/test/js-perf-test/Classes/super.js create mode 100644 deps/v8/test/js-perf-test/Collections/Collections.json create mode 100644 deps/v8/test/js-perf-test/Collections/common.js create mode 100644 deps/v8/test/js-perf-test/Collections/map.js rename deps/v8/test/{perf-test => js-perf-test}/Collections/run.js (94%) create mode 100644 deps/v8/test/js-perf-test/Collections/set.js rename deps/v8/test/{perf-test => js-perf-test}/Collections/weakmap.js (88%) rename deps/v8/test/{perf-test => js-perf-test}/Collections/weakset.js (85%) create mode 100644 deps/v8/test/js-perf-test/Iterators/Iterators.json create mode 100644 deps/v8/test/js-perf-test/Iterators/forof.js create mode 100644 deps/v8/test/js-perf-test/Iterators/run.js create mode 100644 deps/v8/test/js-perf-test/Strings/Strings.json create mode 100644 deps/v8/test/js-perf-test/Strings/harmony-string.js create mode 100644 deps/v8/test/js-perf-test/Strings/run.js rename deps/v8/test/{perf-test/Collections => js-perf-test}/base.js (100%) delete mode 100644 deps/v8/test/libplatform-unittests/libplatform-unittests.status create mode 100644 deps/v8/test/mjsunit/asm/do-while-false.js create mode 100644 deps/v8/test/mjsunit/asm/do-while.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/box2d.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/copy.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/corrections.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/fannkuch.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/fasta.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/lua_binarytrees.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/memops.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/primes.js create mode 100644 deps/v8/test/mjsunit/asm/embenchen/zlib.js create mode 100644 deps/v8/test/mjsunit/asm/float32array-outofbounds.js create mode 100644 deps/v8/test/mjsunit/asm/float32array-store-div.js create mode 100644 deps/v8/test/mjsunit/asm/float64array-outofbounds.js create mode 100644 deps/v8/test/mjsunit/asm/float64array-store-div.js create mode 100644 deps/v8/test/mjsunit/asm/float64mul.js create mode 100644 deps/v8/test/mjsunit/asm/if-folding.js create mode 100644 deps/v8/test/mjsunit/asm/if-reduction.js create mode 100644 deps/v8/test/mjsunit/asm/infinite-loops-taken.js create mode 100644 deps/v8/test/mjsunit/asm/infinite-loops.js create mode 100644 deps/v8/test/mjsunit/asm/int16array-outofbounds.js create mode 100644 deps/v8/test/mjsunit/asm/int32-div.js create mode 100644 deps/v8/test/mjsunit/asm/int32-mod.js create mode 100644 deps/v8/test/mjsunit/asm/int32-mul.js create mode 100644 deps/v8/test/mjsunit/asm/int32-tmod.js create mode 100644 deps/v8/test/mjsunit/asm/int32-udiv.js create mode 100644 deps/v8/test/mjsunit/asm/int32-umod.js create mode 100644 deps/v8/test/mjsunit/asm/int32array-constant-key.js create mode 100644 deps/v8/test/mjsunit/asm/int32array-outofbounds.js create mode 100644 deps/v8/test/mjsunit/asm/int32div.js create mode 100644 deps/v8/test/mjsunit/asm/int32mod.js create mode 100644 deps/v8/test/mjsunit/asm/math-ceil.js create mode 100644 deps/v8/test/mjsunit/asm/math-floor.js create mode 100644 deps/v8/test/mjsunit/asm/uint32-less-than-shift.js create mode 100644 deps/v8/test/mjsunit/asm/uint32div.js create mode 100644 deps/v8/test/mjsunit/asm/uint32mod.js create mode 100644 deps/v8/test/mjsunit/asm/uint8array-outofbounds.js create mode 100644 deps/v8/test/mjsunit/asm/word32and.js create mode 100644 deps/v8/test/mjsunit/compiler/deopt-inlined-from-call.js create mode 100644 deps/v8/test/mjsunit/compiler/inlined-call-mapcheck.js create mode 100644 deps/v8/test/mjsunit/compiler/inlined-call.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-register-allocator.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-register-allocator2.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-register-allocator3.js create mode 100644 deps/v8/test/mjsunit/debug-step-turbofan.js create mode 100644 deps/v8/test/mjsunit/debug-stepframe.js create mode 100644 deps/v8/test/mjsunit/es6/json.js create mode 100644 deps/v8/test/mjsunit/es6/math.js create mode 100644 deps/v8/test/mjsunit/es6/mirror-iterators.js rename deps/v8/test/mjsunit/{harmony => es6}/numeric-literals.js (100%) create mode 100644 deps/v8/test/mjsunit/es6/object-tostring.js create mode 100644 deps/v8/test/mjsunit/harmony/classes.js create mode 100644 deps/v8/test/mjsunit/harmony/object-literals-property-shorthand.js create mode 100644 deps/v8/test/mjsunit/harmony/typedarrays-foreach.js create mode 100644 deps/v8/test/mjsunit/parse-surrogates.js create mode 100644 deps/v8/test/mjsunit/regress/regress-2506.js create mode 100644 deps/v8/test/mjsunit/regress/regress-2615.js create mode 100644 deps/v8/test/mjsunit/regress/regress-3116.js rename deps/v8/test/mjsunit/{harmony/numeric-literals-off.js => regress/regress-3483.js} (77%) create mode 100644 deps/v8/test/mjsunit/regress/regress-3612.js create mode 100644 deps/v8/test/mjsunit/regress/regress-3621.js create mode 100644 deps/v8/test/mjsunit/regress/regress-3643.js create mode 100644 deps/v8/test/mjsunit/regress/regress-385565.js create mode 100644 deps/v8/test/mjsunit/regress/regress-417709a.js create mode 100644 deps/v8/test/mjsunit/regress/regress-417709b.js create mode 100644 deps/v8/test/mjsunit/regress/regress-419663.js create mode 100644 deps/v8/test/mjsunit/regress/regress-423633.js create mode 100644 deps/v8/test/mjsunit/regress/regress-425551.js create mode 100644 deps/v8/test/mjsunit/regress/regress-assignment-in-test-context.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-409614.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-410033.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-417508.js rename deps/v8/test/mjsunit/{test-hidden-string.js => regress/regress-crbug-423687.js} (58%) create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-424142.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-425519.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-425585.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-429159.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-430846.js create mode 100644 deps/v8/test/mjsunit/regress/regress-eval-cache.js create mode 100644 deps/v8/test/mjsunit/regress/regress-shift-enumerable.js create mode 100644 deps/v8/test/mjsunit/serialize-embedded-error.js create mode 100644 deps/v8/test/mjsunit/unused-context-in-with.js delete mode 100644 deps/v8/test/perf-test/Collections/Collections.json delete mode 100644 deps/v8/test/perf-test/Collections/map.js delete mode 100644 deps/v8/test/perf-test/Collections/set.js create mode 100644 deps/v8/test/unittests/DEPS rename deps/v8/{src => test/unittests}/base/bits-unittest.cc (57%) rename deps/v8/{src => test/unittests}/base/cpu-unittest.cc (100%) rename deps/v8/{src => test/unittests}/base/division-by-constant-unittest.cc (99%) rename deps/v8/{src => test/unittests}/base/flags-unittest.cc (98%) create mode 100644 deps/v8/test/unittests/base/functional-unittest.cc rename deps/v8/{src => test/unittests}/base/platform/condition-variable-unittest.cc (100%) rename deps/v8/{src => test/unittests}/base/platform/mutex-unittest.cc (100%) rename deps/v8/{src => test/unittests}/base/platform/platform-unittest.cc (100%) rename deps/v8/{src => test/unittests}/base/platform/semaphore-unittest.cc (100%) rename deps/v8/{src => test/unittests}/base/platform/time-unittest.cc (100%) rename deps/v8/{src => test/unittests}/base/sys-info-unittest.cc (100%) rename deps/v8/{src => test/unittests}/base/utils/random-number-generator-unittest.cc (100%) create mode 100644 deps/v8/test/unittests/char-predicates-unittest.cc rename deps/v8/{src => test/unittests}/compiler/arm/instruction-selector-arm-unittest.cc (86%) rename deps/v8/{src => test/unittests}/compiler/arm64/instruction-selector-arm64-unittest.cc (63%) rename deps/v8/{src => test/unittests}/compiler/change-lowering-unittest.cc (75%) create mode 100644 deps/v8/test/unittests/compiler/common-operator-unittest.cc rename deps/v8/{src => test/unittests}/compiler/compiler-test-utils.h (91%) create mode 100644 deps/v8/test/unittests/compiler/diamond-unittest.cc rename deps/v8/{src => test/unittests}/compiler/graph-reducer-unittest.cc (87%) create mode 100644 deps/v8/test/unittests/compiler/graph-unittest.cc create mode 100644 deps/v8/test/unittests/compiler/graph-unittest.h rename deps/v8/{src => test/unittests}/compiler/ia32/instruction-selector-ia32-unittest.cc (66%) rename deps/v8/{src => test/unittests}/compiler/instruction-selector-unittest.cc (71%) rename deps/v8/{src => test/unittests}/compiler/instruction-selector-unittest.h (86%) create mode 100644 deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc create mode 100644 deps/v8/test/unittests/compiler/js-operator-unittest.cc create mode 100644 deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc create mode 100644 deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc rename deps/v8/{src => test/unittests}/compiler/machine-operator-unittest.cc (66%) create mode 100644 deps/v8/test/unittests/compiler/mips/OWNERS create mode 100644 deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc rename deps/v8/{src/compiler/graph-unittest.cc => test/unittests/compiler/node-test-utils.cc} (54%) rename deps/v8/{src/compiler/graph-unittest.h => test/unittests/compiler/node-test-utils.h} (57%) create mode 100644 deps/v8/test/unittests/compiler/register-allocator-unittest.cc create mode 100644 deps/v8/test/unittests/compiler/select-lowering-unittest.cc rename deps/v8/{src => test/unittests}/compiler/simplified-operator-reducer-unittest.cc (78%) rename deps/v8/{src => test/unittests}/compiler/simplified-operator-unittest.cc (61%) rename deps/v8/{src => test/unittests}/compiler/value-numbering-reducer-unittest.cc (69%) create mode 100644 deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc create mode 100644 deps/v8/test/unittests/compiler/zone-pool-unittest.cc rename deps/v8/{src => test/unittests}/heap/gc-idle-time-handler-unittest.cc (76%) rename deps/v8/{src => test/unittests}/libplatform/default-platform-unittest.cc (100%) rename deps/v8/{src => test/unittests}/libplatform/task-queue-unittest.cc (100%) rename deps/v8/{src => test/unittests}/libplatform/worker-thread-unittest.cc (100%) rename deps/v8/{src/test => test/unittests}/run-all-unittests.cc (100%) create mode 100644 deps/v8/test/unittests/test-utils.cc rename deps/v8/{src/test => test/unittests}/test-utils.h (74%) create mode 100644 deps/v8/test/unittests/unittests.gyp rename deps/v8/test/{base-unittests/base-unittests.status => unittests/unittests.status} (100%) delete mode 100644 deps/v8/tools/lexer-shell.cc rename deps/v8/tools/{lexer-shell.gyp => parser-shell.gyp} (81%) create mode 100644 deps/v8/tools/sanitizers/tsan_suppressions.txt diff --git a/deps/v8/.gitignore b/deps/v8/.gitignore index 22f4e1c3b4..d0407f37f1 100644 --- a/deps/v8/.gitignore +++ b/deps/v8/.gitignore @@ -61,6 +61,9 @@ shell_g /test/test262/data /test/test262/data.old /test/test262/tc39-test262-* +/test/test262-es6/data +/test/test262-es6/data.old +/test/test262-es6/tc39-test262-* /testing/gmock /testing/gtest /third_party/icu @@ -80,5 +83,6 @@ GRTAGS GSYMS GPATH gtags.files +turbo*.cfg turbo*.dot turbo*.json diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index f18761e4ba..89caae648c 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -14,6 +14,9 @@ NVIDIA Corporation BlackBerry Limited Opera Software ASA Intel Corporation +MIPS Technologies, Inc. +Imagination Technologies, LLC +Loongson Technology Corporation Limited Akinori MUSHA Alexander Botero-Lowry @@ -24,6 +27,7 @@ Andreas Anyuru Baptiste Afsa Bert Belder Burcu Dogan +Caitlin Potter Craig Schlenter Chunyang Dai Daniel Andersson @@ -35,6 +39,7 @@ Fedor Indutny Filipe David Manana Haitao Feng Ioseb Dzmanashvili +Isiah Meadows Jacob Bramley Jan de Mooij Jay Freeman diff --git a/deps/v8/BUILD.gn b/deps/v8/BUILD.gn index bfe44395ff..1758ee9e1f 100644 --- a/deps/v8/BUILD.gn +++ b/deps/v8/BUILD.gn @@ -182,7 +182,7 @@ action("js2c") { "src/array.js", "src/string.js", "src/uri.js", - "third_party/fdlibm/fdlibm.js", + "src/third_party/fdlibm/fdlibm.js", "src/math.js", "src/apinatives.js", "src/date.js", @@ -243,7 +243,9 @@ action("js2c_experimental") { "src/generator.js", "src/harmony-string.js", "src/harmony-array.js", + "src/harmony-typedarray.js", "src/harmony-classes.js", + "src/harmony-tostring.js" ] outputs = [ @@ -432,6 +434,8 @@ source_set("v8_base") { "src/assembler.h", "src/assert-scope.h", "src/assert-scope.cc", + "src/ast-numbering.cc", + "src/ast-numbering.h", "src/ast-value-factory.cc", "src/ast-value-factory.h", "src/ast.cc", @@ -446,6 +450,8 @@ source_set("v8_base") { "src/bignum-dtoa.h", "src/bignum.cc", "src/bignum.h", + "src/bit-vector.cc", + "src/bit-vector.h", "src/bootstrapper.cc", "src/bootstrapper.h", "src/builtins.cc", @@ -453,6 +459,7 @@ source_set("v8_base") { "src/bytecodes-irregexp.h", "src/cached-powers.cc", "src/cached-powers.h", + "src/char-predicates.cc", "src/char-predicates-inl.h", "src/char-predicates.h", "src/checks.cc", @@ -469,10 +476,14 @@ source_set("v8_base") { "src/codegen.h", "src/compilation-cache.cc", "src/compilation-cache.h", + "src/compilation-statistics.cc", + "src/compilation-statistics.h", "src/compiler/access-builder.cc", "src/compiler/access-builder.h", "src/compiler/ast-graph-builder.cc", "src/compiler/ast-graph-builder.h", + "src/compiler/ast-loop-assignment-analyzer.cc", + "src/compiler/ast-loop-assignment-analyzer.h", "src/compiler/basic-block-instrumentor.cc", "src/compiler/basic-block-instrumentor.h", "src/compiler/change-lowering.cc", @@ -485,6 +496,9 @@ source_set("v8_base") { "src/compiler/common-operator.h", "src/compiler/control-builders.cc", "src/compiler/control-builders.h", + "src/compiler/control-reducer.cc", + "src/compiler/control-reducer.h", + "src/compiler/diamond.h", "src/compiler/frame.h", "src/compiler/gap-resolver.cc", "src/compiler/gap-resolver.h", @@ -520,6 +534,9 @@ source_set("v8_base") { "src/compiler/js-graph.h", "src/compiler/js-inlining.cc", "src/compiler/js-inlining.h", + "src/compiler/js-intrinsic-builder.cc", + "src/compiler/js-intrinsic-builder.h", + "src/compiler/js-operator.cc", "src/compiler/js-operator.h", "src/compiler/js-typed-lowering.cc", "src/compiler/js-typed-lowering.h", @@ -549,15 +566,21 @@ source_set("v8_base") { "src/compiler/phi-reducer.h", "src/compiler/pipeline.cc", "src/compiler/pipeline.h", + "src/compiler/pipeline-statistics.cc", + "src/compiler/pipeline-statistics.h", "src/compiler/raw-machine-assembler.cc", "src/compiler/raw-machine-assembler.h", "src/compiler/register-allocator.cc", "src/compiler/register-allocator.h", + "src/compiler/register-configuration.cc", + "src/compiler/register-configuration.h", "src/compiler/representation-change.h", "src/compiler/schedule.cc", "src/compiler/schedule.h", "src/compiler/scheduler.cc", "src/compiler/scheduler.h", + "src/compiler/select-lowering.cc", + "src/compiler/select-lowering.h", "src/compiler/simplified-lowering.cc", "src/compiler/simplified-lowering.h", "src/compiler/simplified-operator-reducer.cc", @@ -572,6 +595,8 @@ source_set("v8_base") { "src/compiler/value-numbering-reducer.h", "src/compiler/verifier.cc", "src/compiler/verifier.h", + "src/compiler/zone-pool.cc", + "src/compiler/zone-pool.h", "src/compiler.cc", "src/compiler.h", "src/contexts.cc", @@ -584,8 +609,6 @@ source_set("v8_base") { "src/cpu-profiler-inl.h", "src/cpu-profiler.cc", "src/cpu-profiler.h", - "src/data-flow.cc", - "src/data-flow.h", "src/date.cc", "src/date.h", "src/dateparser-inl.h", @@ -624,7 +647,6 @@ source_set("v8_base") { "src/factory.h", "src/fast-dtoa.cc", "src/fast-dtoa.h", - "src/feedback-slots.h", "src/field-index.h", "src/field-index-inl.h", "src/fixed-dtoa.cc", @@ -674,8 +696,6 @@ source_set("v8_base") { "src/heap/store-buffer-inl.h", "src/heap/store-buffer.cc", "src/heap/store-buffer.h", - "src/heap/sweeper-thread.h", - "src/heap/sweeper-thread.cc", "src/hydrogen-alias-analysis.h", "src/hydrogen-bce.cc", "src/hydrogen-bce.h", @@ -824,14 +844,29 @@ source_set("v8_base") { "src/rewriter.h", "src/runtime-profiler.cc", "src/runtime-profiler.h", + "src/runtime/runtime-api.cc", + "src/runtime/runtime-array.cc", + "src/runtime/runtime-classes.cc", "src/runtime/runtime-collections.cc", "src/runtime/runtime-compiler.cc", + "src/runtime/runtime-date.cc", + "src/runtime/runtime-debug.cc", + "src/runtime/runtime-function.cc", + "src/runtime/runtime-generator.cc", "src/runtime/runtime-i18n.cc", + "src/runtime/runtime-internal.cc", "src/runtime/runtime-json.cc", + "src/runtime/runtime-literals.cc", + "src/runtime/runtime-liveedit.cc", "src/runtime/runtime-maths.cc", "src/runtime/runtime-numbers.cc", + "src/runtime/runtime-object.cc", + "src/runtime/runtime-observe.cc", + "src/runtime/runtime-proxy.cc", "src/runtime/runtime-regexp.cc", + "src/runtime/runtime-scopes.cc", "src/runtime/runtime-strings.cc", + "src/runtime/runtime-symbol.cc", "src/runtime/runtime-test.cc", "src/runtime/runtime-typedarray.cc", "src/runtime/runtime-uri.cc", @@ -884,8 +919,9 @@ source_set("v8_base") { "src/unicode-inl.h", "src/unicode.cc", "src/unicode.h", + "src/unicode-decoder.cc", + "src/unicode-decoder.h", "src/unique.h", - "src/uri.h", "src/utils-inl.h", "src/utils.cc", "src/utils.h", @@ -903,8 +939,8 @@ source_set("v8_base") { "src/zone-inl.h", "src/zone.cc", "src/zone.h", - "third_party/fdlibm/fdlibm.cc", - "third_party/fdlibm/fdlibm.h", + "src/third_party/fdlibm/fdlibm.cc", + "src/third_party/fdlibm/fdlibm.h", ] if (v8_target_arch == "x86") { @@ -939,6 +975,8 @@ source_set("v8_base") { "src/compiler/ia32/instruction-codes-ia32.h", "src/compiler/ia32/instruction-selector-ia32.cc", "src/compiler/ia32/linkage-ia32.cc", + "src/ic/ia32/access-compiler-ia32.cc", + "src/ic/ia32/handler-compiler-ia32.cc", "src/ic/ia32/ic-ia32.cc", "src/ic/ia32/ic-compiler-ia32.cc", "src/ic/ia32/stub-cache-ia32.cc", @@ -1107,6 +1145,10 @@ source_set("v8_base") { "src/mips/regexp-macro-assembler-mips.cc", "src/mips/regexp-macro-assembler-mips.h", "src/mips/simulator-mips.cc", + "src/compiler/mips/code-generator-mips.cc", + "src/compiler/mips/instruction-codes-mips.h", + "src/compiler/mips/instruction-selector-mips.cc", + "src/compiler/mips/linkage-mips.cc", "src/ic/mips/access-compiler-mips.cc", "src/ic/mips/handler-compiler-mips.cc", "src/ic/mips/ic-mips.cc", @@ -1216,6 +1258,8 @@ source_set("v8_libbase") { "src/base/division-by-constant.cc", "src/base/division-by-constant.h", "src/base/flags.h", + "src/base/functional.cc", + "src/base/functional.h", "src/base/lazy-instance.h", "src/base/logging.cc", "src/base/logging.h", @@ -1287,8 +1331,6 @@ source_set("v8_libbase") { sources += [ "src/base/platform/platform-win32.cc", "src/base/win32-headers.h", - "src/base/win32-math.cc", - "src/base/win32-math.h", ] defines += [ "_CRT_RAND_S" ] # for rand_s() @@ -1344,6 +1386,7 @@ if (current_toolchain == host_toolchain) { ":v8_base", ":v8_libplatform", ":v8_nosnapshot", + "//build/config/sanitizers:deps", ] if (v8_compress_startup_data == "bz2") { diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 89e5b9f89f..1e298537ca 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,287 @@ +2014-11-05: Version 3.30.33 + + `1..isPrototypeOf.call(null)` should return false, not throw TypeError + (issue 3483). + + Refactor ObjectGetOwnPropertyKeys to accept bitmask rather than boolean + (issue 3549). + + Add debug mirror support for ES6 Map/Set iterators (Chromium issue + 427868). + + Performance and stability improvements on all platforms. + + +2014-11-04: Version 3.30.30 + + Performance and stability improvements on all platforms. + + +2014-11-02: Version 3.30.27 + + Performance and stability improvements on all platforms. + + +2014-11-02: Version 3.30.26 + + Performance and stability improvements on all platforms. + + +2014-11-01: Version 3.30.25 + + Performance and stability improvements on all platforms. + + +2014-11-01: Version 3.30.24 + + Ensure we don't try to inline raw access to indexed interceptor + receivers (Chromium issue 419220). + + Performance and stability improvements on all platforms. + + +2014-10-31: Version 3.30.23 + + Introduce v8::Exception::GetMessage to find location of an error object + (Chromium issue 427954). + + Performance and stability improvements on all platforms. + + +2014-10-30: Version 3.30.22 + + MIPS: Classes: Add super support in methods and accessors (issue 3330). + + Classes: Add super support in methods and accessors (issue 3330). + + Performance and stability improvements on all platforms. + + +2014-10-29: Version 3.30.21 + + MIPS: Classes: Add basic support for properties (issue 3330). + + Classes: Add more tests for prototype edge cases (Chromium issue 3655). + + Classes: Add test for method prototype (issue 3330). + + Get stack trace for uncaught exceptions/promise rejections from the + simple stack when available. + + Classes: Add basic support for properties (issue 3330). + + Allow duplicate property names in classes (issue 3570). + + Windows: use SystemTimeToTzSpecificLocalTime instead of localtime_s + (Chromium issue 417640). + + Performance and stability improvements on all platforms. + + +2014-10-28: Version 3.30.20 + + Performance and stability improvements on all platforms. + + +2014-10-27: Version 3.30.19 + + Check string literals with escapes in PreParserTraits::GetSymbol() + (issue 3606). + + only define ARRAYSIZE_UNSAFE for NaCl builds (Chromium issue 405225). + + Performance and stability improvements on all platforms. + + +2014-10-24: Version 3.30.18 + + Narrow cases where Sparse/Smart versions of Array methods are used + (issues 2615, 3612, 3621). + + Shrink new space in idle notification (Chromium issue 424423). + + Performance and stability improvements on all platforms. + + +2014-10-23: Version 3.30.17 + + ARM64: Fix stack manipulation (Chromium issue 425585). + + Speed up creation of Objects whose prototype has dictionary elements + (Chromium issue 422754). + + Enable libstdc++ debug mode in debug builds (issue 3638). + + Performance and stability improvements on all platforms. + + +2014-10-22: Version 3.30.16 + + Remove v8stdint.h, it doesn't serve a purpose anymore. + + Performance and stability improvements on all platforms. + + +2014-10-21: Version 3.30.15 + + Avoid the Marsaglia effect in 3D (Chromium issue 423311). + + Performance and stability improvements on all platforms. + + +2014-10-20: Version 3.30.14 + + Performance and stability improvements on all platforms. + + +2014-10-17: Version 3.30.13 + + Don't expose Array.prototype.values as it breaks webcompat (Chromium + issue 409858). + + Fix break location calculation (Chromium issue 419663). + + Enable libstdc++ debug mode in debug builds (issue 3638). + + Performance and stability improvements on all platforms. + + +2014-10-17: Version 3.30.12 + + Implement .forEach() on typed arrays (issue 3578). + + Introduce v8::Exception::GetStackTrace API method. + + Remove SmartMove, bringing Array methods further into spec compliance + (issue 2615). + + Convert argument toObject() in Object.getOwnPropertyNames/Descriptors + (issue 3443). + + Performance and stability improvements on all platforms. + + +2014-10-15: Version 3.30.11 + + Array.prototype.{every, filter, find, findIndex, forEach, map, some}: + Use fresh primitive wrapper for calls (issue 3536). + + Correctly expand literal buffer for surrogate pairs (Chromium issue + 423212). + + Performance and stability improvements on all platforms. + + +2014-10-15: Version 3.30.10 + + Squeeze the layout of various AST node types (Chromium issue 417697). + + Performance and stability improvements on all platforms. + + +2014-10-14: Version 3.30.9 + + Performance and stability improvements on all platforms. + + +2014-10-13: Version 3.30.8 + + AST nodes have at most one bailout/typefeedback ID now, saving lots of + memory (Chromium issue 417697). + + Allow identifier code points from supplementary multilingual planes + (issue 3617). + + Performance and stability improvements on all platforms. + + +2014-10-10: Version 3.30.7 + + Fix computation of UTC time from local time at DST change points (issue + 3116, Chromium issues 415424, 417640). + + Convert `obj` ToObject in Object.keys() (issue 3587). + + Performance and stability improvements on all platforms. + + +2014-10-09: Version 3.30.6 + + Update unicode to 7.0.0 (issue 2892). + + Classes: Add support for toString (issue 3330). + + Don't enable WPO on Win64 and require Server 2003 / x64 for win64 + (Chromium issue 421363). + + Performance and stability improvements on all platforms. + + +2014-10-08: Version 3.30.5 + + Performance and stability improvements on all platforms. + + +2014-10-08: Version 3.30.4 + + This uses a runtime function to set up the the constructor and its + prototype (issue 3330). + + Remove PersistentBase::ClearAndLeak. + + Squeeze the layout of variable proxy nodes (Chromium issue 417697). + + Add MonotonicallyIncreasingTime to V8 Platform (Chromium issue 417668). + + Fix representation of HLoadRoot (Chromium issue 419036). + + Performance and stability improvements on all platforms. + + +2014-10-03: Version 3.30.3 + + Removed the Isolate* field from literal nodes (Chromium issue 417697). + + Squeeze the layout of expression nodes a bit (Chromium issue 417697). + + Merged FeedbackSlotInterface into AstNode, removing the need for a 2nd + vtable (Chromium issue 417697). + + Extend CPU profiler with mapping ticks to source lines. + + Remove support for parallel sweeping. + + Introduce v8::Object::GetIsolate(). + + Performance and stability improvements on all platforms. + + +2014-10-02: Version 3.30.2 + + Fix Hydrogen's BuildStore() (Chromium issue 417508). + + Move unit tests to test/unittests (issue 3489). + + Changes to ALLOW_UNUSED to match upcoming changes to the Chromium trunk: + * Eliminate usage of ALLOW_UNUSED to define COMPILE_ASSERT and just use + static_assert() in all cases now that all platforms build with C++11. * + Convert remaining uses of ALLOW_UNUSED to ALLOW_UNUSED_TYPE to match how + Chromium will be splitting this functionality. (In Chromium we'll have + both ALLOW_UNUSED_TYPE and ALLOW_UNUSED_LOCAL, which have different + syntax to enable us to use these with MSVC.) (Chromium issue 81439). + + Performance and stability improvements on all platforms. + + +2014-10-01: Version 3.30.1 + + Introduce PromiseRejectCallback (issue 3093). + + ES6: Implement object literal property shorthand (issue 3584). + + Performance and stability improvements on all platforms. + + 2014-09-30: Version 3.29.93 Add a getter for the address and size of the code range to the pulic API diff --git a/deps/v8/Makefile b/deps/v8/Makefile index 2fbe1ba7db..3b02f52d2a 100644 --- a/deps/v8/Makefile +++ b/deps/v8/Makefile @@ -140,10 +140,15 @@ endif # asan=/path/to/clang++ ifneq ($(strip $(asan)),) GYPFLAGS += -Dasan=1 + export CC=$(dir $(asan))clang export CXX=$(asan) export CXX_host=$(asan) export LINK=$(asan) - export ASAN_SYMBOLIZER_PATH="$(dir $(asan))llvm-symbolizer" + export ASAN_SYMBOLIZER_PATH=$(dir $(asan))llvm-symbolizer + TESTFLAGS += --asan + ifeq ($(lsan), on) + GYPFLAGS += -Dlsan=1 + endif endif # arm specific flags. @@ -230,8 +235,8 @@ NACL_ARCHES = nacl_ia32 nacl_x64 # List of files that trigger Makefile regeneration: GYPFILES = build/all.gyp build/features.gypi build/standalone.gypi \ - build/toolchain.gypi samples/samples.gyp src/compiler/compiler.gyp \ - src/d8.gyp test/cctest/cctest.gyp tools/gyp/v8.gyp + build/toolchain.gypi samples/samples.gyp src/d8.gyp \ + test/cctest/cctest.gyp test/unittests/unittests.gyp tools/gyp/v8.gyp # If vtunejit=on, the v8vtune.gyp will be appended. ifeq ($(vtunejit), on) @@ -252,7 +257,7 @@ NACL_CHECKS = $(addsuffix .check,$(NACL_BUILDS)) ENVFILE = $(OUTDIR)/environment .PHONY: all check clean builddeps dependencies $(ENVFILE).new native \ - qc quickcheck $(QUICKCHECKS) \ + qc quickcheck $(QUICKCHECKS) turbocheck \ $(addsuffix .quickcheck,$(MODES)) $(addsuffix .quickcheck,$(ARCHES)) \ $(ARCHES) $(MODES) $(BUILDS) $(CHECKS) $(addsuffix .clean,$(ARCHES)) \ $(addsuffix .check,$(MODES)) $(addsuffix .check,$(ARCHES)) \ @@ -381,6 +386,15 @@ quickcheck: $(subst $(COMMA),$(SPACE),$(FASTCOMPILEMODES)) --arch-and-mode=$(FASTTESTMODES) $(TESTFLAGS) --quickcheck qc: quickcheck +turbocheck: $(subst $(COMMA),$(SPACE),$(FASTCOMPILEMODES)) + tools/run-tests.py $(TESTJOBS) --outdir=$(OUTDIR) \ + --arch-and-mode=$(SUPERFASTTESTMODES) $(TESTFLAGS) \ + --quickcheck --variants=turbofan --download-data mozilla webkit + tools/run-tests.py $(TESTJOBS) --outdir=$(OUTDIR) \ + --arch-and-mode=$(FASTTESTMODES) $(TESTFLAGS) \ + --quickcheck --variants=turbofan +tc: turbocheck + # Clean targets. You can clean each architecture individually, or everything. $(addsuffix .clean, $(ARCHES) $(ANDROID_ARCHES) $(NACL_ARCHES)): rm -f $(OUTDIR)/Makefile.$(basename $@)* diff --git a/deps/v8/Makefile.nacl b/deps/v8/Makefile.nacl index 34bd960fed..3459c42c0d 100644 --- a/deps/v8/Makefile.nacl +++ b/deps/v8/Makefile.nacl @@ -36,41 +36,29 @@ NACL_BUILDS = $(foreach mode,$(MODES), \ $(addsuffix .$(mode),$(NACL_ARCHES))) HOST_OS = $(shell uname -s | sed -e 's/Linux/linux/;s/Darwin/mac/') -ifeq ($(HOST_OS), linux) - TOOLCHAIN_DIR = linux_x86_glibc -else - ifeq ($(HOST_OS), mac) - TOOLCHAIN_DIR = mac_x86_glibc - else - $(error Host platform "${HOST_OS}" is not supported) - endif -endif - TOOLCHAIN_PATH = $(realpath ${NACL_SDK_ROOT}/toolchain) -NACL_TOOLCHAIN ?= ${TOOLCHAIN_PATH}/${TOOLCHAIN_DIR} - -ifeq ($(ARCH), nacl_ia32) - GYPENV = nacl_target_arch=nacl_ia32 v8_target_arch=arm v8_host_arch=ia32 - TOOLCHAIN_ARCH = x86-4.4 - NACL_CC = "$(NACL_TOOLCHAIN)/bin/i686-nacl-gcc" - NACL_CXX = "$(NACL_TOOLCHAIN)/bin/i686-nacl-g++" - NACL_LINK = "$(NACL_TOOLCHAIN)/bin/i686-nacl-g++" -else - ifeq ($(ARCH), nacl_x64) - GYPENV = nacl_target_arch=nacl_x64 v8_target_arch=arm v8_host_arch=ia32 - TOOLCHAIN_ARCH = x86-4.4 - NACL_CC = "$(NACL_TOOLCHAIN)/bin/x86_64-nacl-gcc" - NACL_CXX = "$(NACL_TOOLCHAIN)/bin/x86_64-nacl-g++" - NACL_LINK = "$(NACL_TOOLCHAIN)/bin/x86_64-nacl-g++" - else - $(error Target architecture "${ARCH}" is not supported) - endif -endif +NACL_TOOLCHAIN ?= ${TOOLCHAIN_PATH}/linux_pnacl ifeq ($(wildcard $(NACL_TOOLCHAIN)),) $(error Cannot find Native Client toolchain in "${NACL_TOOLCHAIN}") endif +ifeq ($(ARCH), nacl_ia32) + GYPENV = nacl_target_arch=nacl_ia32 v8_target_arch=arm v8_host_arch=ia32 + NACL_CC = "$(NACL_TOOLCHAIN)/bin/pnacl-clang" + NACL_CXX = "$(NACL_TOOLCHAIN)/bin/pnacl-clang++" + NACL_LINK = "$(NACL_TOOLCHAIN)/bin/pnacl-clang++ --pnacl-allow-native -arch x86-32" +else + ifeq ($(ARCH), nacl_x64) + GYPENV = nacl_target_arch=nacl_x64 v8_target_arch=arm v8_host_arch=ia32 + NACL_CC = "$(NACL_TOOLCHAIN)/bin/pnacl-clang" + NACL_CXX = "$(NACL_TOOLCHAIN)/bin/pnacl-clang++" + NACL_LINK = "$(NACL_TOOLCHAIN)/bin/pnacl-clang++ --pnacl-allow-native -arch x86-64" + else + $(error Target architecture "${ARCH}" is not supported) + endif +endif + # For mksnapshot host generation. GYPENV += host_os=${HOST_OS} @@ -85,7 +73,11 @@ NACL_MAKEFILES = $(addprefix $(OUTDIR)/Makefile.,$(NACL_BUILDS)) # For some reason the $$(basename $$@) expansion didn't work here... $(NACL_BUILDS): $(NACL_MAKEFILES) @$(MAKE) -C "$(OUTDIR)" -f Makefile.$@ \ + CC=${NACL_CC} \ CXX=${NACL_CXX} \ + AR="$(NACL_TOOLCHAIN)/bin/pnacl-ar" \ + RANLIB="$(NACL_TOOLCHAIN)/bin/pnacl-ranlib" \ + LD="$(NACL_TOOLCHAIN)/bin/pnacl-ld" \ LINK=${NACL_LINK} \ BUILDTYPE=$(shell echo $(subst .,,$(suffix $@)) | \ python -c "print raw_input().capitalize()") \ @@ -97,6 +89,7 @@ $(NACL_MAKEFILES): GYP_DEFINES="${GYPENV}" \ CC=${NACL_CC} \ CXX=${NACL_CXX} \ + LINK=${NACL_LINK} \ PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH)" \ build/gyp/gyp --generator-output="${OUTDIR}" build/all.gyp \ -Ibuild/standalone.gypi --depth=. \ diff --git a/deps/v8/OWNERS b/deps/v8/OWNERS index f67b3ec5c6..aa5f64449e 100644 --- a/deps/v8/OWNERS +++ b/deps/v8/OWNERS @@ -16,7 +16,6 @@ rossberg@chromium.org svenpanne@chromium.org titzer@chromium.org ulan@chromium.org -vegorov@chromium.org verwaest@chromium.org vogelheim@chromium.org yangguo@chromium.org diff --git a/deps/v8/README.md b/deps/v8/README.md new file mode 100644 index 0000000000..7ce52a0b03 --- /dev/null +++ b/deps/v8/README.md @@ -0,0 +1,26 @@ +V8 JavaScript Engine +============= + +V8 is Google's open source JavaScript engine. + +V8 implements ECMAScript as specified in ECMA-262. + +V8 is written in C++ and is used in Google Chrome, the open source +browser from Google. + +V8 can run standalone, or can be embedded into any C++ application. + +V8 Project page: https://code.google.com/p/v8/ + + +Getting the Code +============= + +V8 Git repository: https://chromium.googlesource.com/v8/v8.git +GitHub mirror: https://github.com/v8/v8-git-mirror + +For fetching all branches, add the following into your remote +configuration in `.git/config`: + + fetch = +refs/branch-heads/*:refs/remotes/branch-heads/* + fetch = +refs/tags/*:refs/tags/* diff --git a/deps/v8/build/all.gyp b/deps/v8/build/all.gyp index 1e420fad8e..4aeb507dca 100644 --- a/deps/v8/build/all.gyp +++ b/deps/v8/build/all.gyp @@ -9,18 +9,14 @@ 'type': 'none', 'dependencies': [ '../samples/samples.gyp:*', - '../src/base/base.gyp:base-unittests', - '../src/compiler/compiler.gyp:compiler-unittests', '../src/d8.gyp:d8', - '../src/heap/heap.gyp:heap-unittests', - '../src/libplatform/libplatform.gyp:libplatform-unittests', '../test/cctest/cctest.gyp:*', + '../test/unittests/unittests.gyp:*', ], 'conditions': [ ['component!="shared_library"', { 'dependencies': [ - '../tools/lexer-shell.gyp:lexer-shell', - '../tools/lexer-shell.gyp:parser-shell', + '../tools/parser-shell.gyp:parser-shell', ], }], ] diff --git a/deps/v8/build/standalone.gypi b/deps/v8/build/standalone.gypi index b09122b538..47b276311d 100644 --- a/deps/v8/build/standalone.gypi +++ b/deps/v8/build/standalone.gypi @@ -136,6 +136,14 @@ 'configurations': { 'DebugBaseCommon': { 'cflags': [ '-g', '-O0' ], + 'conditions': [ + ['(v8_target_arch=="ia32" or v8_target_arch=="x87") and \ + OS=="linux"', { + 'defines': [ + '_GLIBCXX_DEBUG' + ], + }], + ], }, 'Optdebug': { 'inherit_from': [ 'DebugBaseCommon', 'DebugBase2' ], @@ -313,9 +321,15 @@ }, 'VCLibrarianTool': { 'AdditionalOptions': ['/ignore:4221'], + 'conditions': [ + ['v8_target_arch=="x64"', { + 'TargetMachine': '17', # x64 + }, { + 'TargetMachine': '1', # ia32 + }], + ], }, 'VCLinkerTool': { - 'MinimumRequiredVersion': '5.01', # XP. 'AdditionalDependencies': [ 'ws2_32.lib', ], @@ -340,6 +354,13 @@ 'advapi32.lib', ], }], + ['v8_target_arch=="x64"', { + 'MinimumRequiredVersion': '5.02', # Server 2003. + 'TargetMachine': '17', # x64 + }, { + 'MinimumRequiredVersion': '5.01', # XP. + 'TargetMachine': '1', # ia32 + }], ], }, }, diff --git a/deps/v8/build/toolchain.gypi b/deps/v8/build/toolchain.gypi index 7f3b9e52d9..20c2c943bb 100644 --- a/deps/v8/build/toolchain.gypi +++ b/deps/v8/build/toolchain.gypi @@ -302,7 +302,7 @@ 'cflags': ['-mfp32'], }], ['mips_arch_variant=="r6"', { - 'cflags!': ['-mfp32'], + 'cflags!': ['-mfp32', '-mfpxx'], 'cflags': ['-mips32r6', '-Wa,-mips32r6'], 'ldflags': [ '-mips32r6', @@ -312,14 +312,17 @@ }], ['mips_arch_variant=="r2"', { 'cflags': ['-mips32r2', '-Wa,-mips32r2'], + 'ldflags': ['-mips32r2'], }], ['mips_arch_variant=="r1"', { - 'cflags!': ['-mfp64'], + 'cflags!': ['-mfp64', '-mfpxx'], 'cflags': ['-mips32', '-Wa,-mips32'], + 'ldflags': ['-mips32'], }], ['mips_arch_variant=="rx"', { - 'cflags!': ['-mfp64'], - 'cflags': ['-mips32', '-Wa,-mips32'], + 'cflags!': ['-mfp64', '-mfp32'], + 'cflags': ['-mips32', '-Wa,-mips32', '-mfpxx'], + 'ldflags': ['-mips32'], }], ], }], @@ -400,7 +403,7 @@ 'cflags': ['-mfp32'], }], ['mips_arch_variant=="r6"', { - 'cflags!': ['-mfp32'], + 'cflags!': ['-mfp32', '-mfpxx'], 'cflags': ['-mips32r6', '-Wa,-mips32r6'], 'ldflags': [ '-mips32r6', @@ -410,17 +413,20 @@ }], ['mips_arch_variant=="r2"', { 'cflags': ['-mips32r2', '-Wa,-mips32r2'], + 'ldflags': ['-mips32r2'], }], ['mips_arch_variant=="r1"', { - 'cflags!': ['-mfp64'], + 'cflags!': ['-mfp64', '-mfpxx'], 'cflags': ['-mips32', '-Wa,-mips32'], + 'ldflags': ['-mips32'], }], ['mips_arch_variant=="rx"', { - 'cflags!': ['-mfp64'], - 'cflags': ['-mips32', '-Wa,-mips32'], + 'cflags!': ['-mfp64', '-mfp32'], + 'cflags': ['-mips32', '-Wa,-mips32', '-mfpxx'], + 'ldflags': ['-mips32'], }], ['mips_arch_variant=="loongson"', { - 'cflags!': ['-mfp64'], + 'cflags!': ['-mfp64', '-mfp32', '-mfpxx'], 'cflags': ['-mips3', '-Wa,-mips3'], }], ], @@ -702,7 +708,6 @@ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \ OS=="qnx"', { 'cflags!': [ - '-O0', '-O3', '-O2', '-O1', @@ -791,10 +796,6 @@ }, { 'RuntimeLibrary': '1', #/MTd }], - ['v8_target_arch=="x64"', { - # TODO(2207): remove this option once the bug is fixed. - 'WholeProgramOptimization': 'true', - }], ], }, 'VCLinkerTool': { @@ -964,10 +965,6 @@ }, { 'RuntimeLibrary': '0', #/MT }], - ['v8_target_arch=="x64"', { - # TODO(2207): remove this option once the bug is fixed. - 'WholeProgramOptimization': 'true', - }], ], }, 'VCLinkerTool': { diff --git a/deps/v8/include/v8-platform.h b/deps/v8/include/v8-platform.h index 1f1679f0e0..67fb384c99 100644 --- a/deps/v8/include/v8-platform.h +++ b/deps/v8/include/v8-platform.h @@ -55,6 +55,15 @@ class Platform { * scheduling. The definition of "foreground" is opaque to V8. */ virtual void CallOnForegroundThread(Isolate* isolate, Task* task) = 0; + + /** + * Monotonically increasing time in seconds from an arbitrary fixed point in + * the past. This function is expected to return at least + * millisecond-precision values. For this reason, + * it is recommended that the fixed point be no further in the past than + * the epoch. + **/ + virtual double MonotonicallyIncreasingTime() = 0; }; } // namespace v8 diff --git a/deps/v8/include/v8-profiler.h b/deps/v8/include/v8-profiler.h index 7fc193db58..d0215205f5 100644 --- a/deps/v8/include/v8-profiler.h +++ b/deps/v8/include/v8-profiler.h @@ -22,6 +22,14 @@ typedef uint32_t SnapshotObjectId; */ class V8_EXPORT CpuProfileNode { public: + struct LineTick { + /** The 1-based number of the source line where the function originates. */ + int line; + + /** The count of samples associated with the source line. */ + unsigned int hit_count; + }; + /** Returns function name (empty string for anonymous functions.) */ Handle GetFunctionName() const; @@ -43,6 +51,18 @@ class V8_EXPORT CpuProfileNode { */ int GetColumnNumber() const; + /** + * Returns the number of the function's source lines that collect the samples. + */ + unsigned int GetHitLineCount() const; + + /** Returns the set of source lines that collect the samples. + * The caller allocates buffer and responsible for releasing it. + * True if all available entries are copied, otherwise false. + * The function copies nothing if buffer is not large enough. + */ + bool GetLineTicks(LineTick* entries, unsigned int length) const; + /** Returns bailout reason for the function * if the optimization was disabled for it. */ diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 63c67624a1..d5433a6a26 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -15,7 +15,11 @@ #ifndef V8_H_ #define V8_H_ -#include "v8stdint.h" +#include +#include +#include + +#include "v8config.h" // We reserve the V8_* prefix for macros defined in V8 public API and // assume there are no name conflicts with the embedder's code. @@ -85,6 +89,7 @@ class ObjectOperationDescriptor; class ObjectTemplate; class Platform; class Primitive; +class Promise; class RawOperationDescriptor; class Script; class Signature; @@ -511,6 +516,18 @@ template class PersistentBase { P* parameter, typename WeakCallbackData::Callback callback); + // Phantom persistents work like weak persistents, except that the pointer to + // the object being collected is not available in the finalization callback. + // This enables the garbage collector to collect the object and any objects + // it references transitively in one GC cycle. + template + V8_INLINE void SetPhantom(P* parameter, + typename WeakCallbackData::Callback callback); + + template + V8_INLINE void SetPhantom(P* parameter, + typename WeakCallbackData::Callback callback); + template V8_INLINE P* ClearWeak(); @@ -696,9 +713,6 @@ template class Persistent : public PersistentBase { return Persistent::Cast(*this); } - // This will be removed. - V8_INLINE T* ClearAndLeak(); - private: friend class Isolate; friend class Utils; @@ -1415,6 +1429,27 @@ class V8_EXPORT StackFrame { }; +// A StateTag represents a possible state of the VM. +enum StateTag { JS, GC, COMPILER, OTHER, EXTERNAL, IDLE }; + + +// A RegisterState represents the current state of registers used +// by the sampling profiler API. +struct RegisterState { + RegisterState() : pc(NULL), sp(NULL), fp(NULL) {} + void* pc; // Instruction pointer. + void* sp; // Stack pointer. + void* fp; // Frame pointer. +}; + + +// The output structure filled up by GetStackSample API function. +struct SampleInfo { + size_t frames_count; + StateTag vm_state; +}; + + /** * A JSON Parser. */ @@ -1590,6 +1625,18 @@ class V8_EXPORT Value : public Data { */ bool IsSet() const; + /** + * Returns true if this value is a Map Iterator. + * This is an experimental feature. + */ + bool IsMapIterator() const; + + /** + * Returns true if this value is a Set Iterator. + * This is an experimental feature. + */ + bool IsSetIterator() const; + /** * Returns true if this value is a WeakMap. * This is an experimental feature. @@ -1680,14 +1727,24 @@ class V8_EXPORT Value : public Data { */ bool IsDataView() const; - Local ToBoolean() const; - Local ToNumber() const; - Local ToString() const; - Local ToDetailString() const; - Local ToObject() const; - Local ToInteger() const; - Local ToUint32() const; - Local ToInt32() const; + Local ToBoolean(Isolate* isolate) const; + Local ToNumber(Isolate* isolate) const; + Local ToString(Isolate* isolate) const; + Local ToDetailString(Isolate* isolate) const; + Local ToObject(Isolate* isolate) const; + Local ToInteger(Isolate* isolate) const; + Local ToUint32(Isolate* isolate) const; + Local ToInt32(Isolate* isolate) const; + + // TODO(dcarney): deprecate all these. + inline Local ToBoolean() const; + inline Local ToNumber() const; + inline Local ToString() const; + inline Local ToDetailString() const; + inline Local ToObject() const; + inline Local ToInteger() const; + inline Local ToUint32() const; + inline Local ToInt32() const; /** * Attempts to convert a string to an array index. @@ -1754,7 +1811,6 @@ class V8_EXPORT String : public Name { enum Encoding { UNKNOWN_ENCODING = 0x1, TWO_BYTE_ENCODING = 0x0, - ASCII_ENCODING = 0x4, // TODO(yangguo): deprecate this. ONE_BYTE_ENCODING = 0x4 }; /** @@ -1810,7 +1866,6 @@ class V8_EXPORT String : public Name { NO_OPTIONS = 0, HINT_MANY_WRITES_EXPECTED = 1, NO_NULL_TERMINATION = 2, - PRESERVE_ASCII_NULL = 4, // TODO(yangguo): deprecate this. PRESERVE_ONE_BYTE_NULL = 4, // Used by WriteUtf8 to replace orphan surrogate code units with the // unicode replacement character. Needs to be set to guarantee valid UTF-8 @@ -1849,9 +1904,6 @@ class V8_EXPORT String : public Name { */ bool IsExternalOneByte() const; - // TODO(yangguo): deprecate this. - bool IsExternalAscii() const { return IsExternalOneByte(); } - class V8_EXPORT ExternalStringResourceBase { // NOLINT public: virtual ~ExternalStringResourceBase() {} @@ -1930,8 +1982,6 @@ class V8_EXPORT String : public Name { ExternalOneByteStringResource() {} }; - typedef ExternalOneByteStringResource ExternalAsciiStringResource; - /** * If the string is an external string, return the ExternalStringResourceBase * regardless of the encoding, otherwise return NULL. The encoding of the @@ -1952,11 +2002,6 @@ class V8_EXPORT String : public Name { */ const ExternalOneByteStringResource* GetExternalOneByteStringResource() const; - // TODO(yangguo): deprecate this. - const ExternalAsciiStringResource* GetExternalAsciiStringResource() const { - return GetExternalOneByteStringResource(); - } - V8_INLINE static String* Cast(v8::Value* obj); enum NewStringType { @@ -2119,6 +2164,7 @@ class V8_EXPORT Symbol : public Name { // Well-known symbols static Local GetIterator(Isolate* isolate); static Local GetUnscopables(Isolate* isolate); + static Local GetToStringTag(Isolate* isolate); V8_INLINE static Symbol* Cast(v8::Value* obj); @@ -2495,15 +2541,6 @@ class V8_EXPORT Object : public Value { Local GetHiddenValue(Handle key); bool DeleteHiddenValue(Handle key); - /** - * Returns true if this is an instance of an api function (one - * created from a function created from a function template) and has - * been modified since it was created. Note that this method is - * conservative and may return true for objects that haven't actually - * been modified. - */ - bool IsDirty(); - /** * Clone this object with a fast but shallow copy. Values will point * to the same values as the original object. @@ -2564,6 +2601,11 @@ class V8_EXPORT Object : public Value { */ Local CallAsConstructor(int argc, Handle argv[]); + /** + * Return the isolate to which the Object belongs to. + */ + Isolate* GetIsolate(); + static Local New(Isolate* isolate); V8_INLINE static Object* Cast(Value* obj); @@ -2830,6 +2872,12 @@ class V8_EXPORT Promise : public Object { Local Catch(Handle handler); Local Then(Handle handler); + /** + * Returns true if the promise has at least one derived promise, and + * therefore resolve/reject handlers (including default handler). + */ + bool HasHandler(); + V8_INLINE static Promise* Cast(Value* obj); private: @@ -2931,11 +2979,16 @@ class V8_EXPORT ArrayBuffer : public Object { */ bool IsExternal() const; + /** + * Returns true if this ArrayBuffer may be neutered. + */ + bool IsNeuterable() const; + /** * Neuters this ArrayBuffer and all its views (typed arrays). * Neutering sets the byte length of the buffer and all typed arrays to zero, * preventing JavaScript from ever accessing underlying backing store. - * ArrayBuffer should have been externalized. + * ArrayBuffer should have been externalized and must be neuterable. */ void Neuter(); @@ -4134,6 +4187,11 @@ class V8_EXPORT Exception { static Local SyntaxError(Handle message); static Local TypeError(Handle message); static Local Error(Handle message); + + static Local GetMessage(Handle exception); + + // DEPRECATED. Use GetMessage()->GetStackTrace() + static Local GetStackTrace(Handle exception); }; @@ -4175,6 +4233,37 @@ typedef void (*MemoryAllocationCallback)(ObjectSpace space, // --- Leave Script Callback --- typedef void (*CallCompletedCallback)(); +// --- Promise Reject Callback --- +enum PromiseRejectEvent { + kPromiseRejectWithNoHandler = 0, + kPromiseHandlerAddedAfterReject = 1 +}; + +class PromiseRejectMessage { + public: + PromiseRejectMessage(Handle promise, PromiseRejectEvent event, + Handle value, Handle stack_trace) + : promise_(promise), + event_(event), + value_(value), + stack_trace_(stack_trace) {} + + V8_INLINE Handle GetPromise() const { return promise_; } + V8_INLINE PromiseRejectEvent GetEvent() const { return event_; } + V8_INLINE Handle GetValue() const { return value_; } + + // DEPRECATED. Use v8::Exception::GetMessage(GetValue())->GetStackTrace() + V8_INLINE Handle GetStackTrace() const { return stack_trace_; } + + private: + Handle promise_; + PromiseRejectEvent event_; + Handle value_; + Handle stack_trace_; +}; + +typedef void (*PromiseRejectCallback)(PromiseRejectMessage message); + // --- Microtask Callback --- typedef void (*MicrotaskCallback)(void* data); @@ -4345,6 +4434,27 @@ enum JitCodeEventOptions { typedef void (*JitCodeEventHandler)(const JitCodeEvent* event); +/** + * Interface for iterating through all external resources in the heap. + */ +class V8_EXPORT ExternalResourceVisitor { // NOLINT + public: + virtual ~ExternalResourceVisitor() {} + virtual void VisitExternalString(Handle string) {} +}; + + +/** + * Interface for iterating through all the persistent handles in the heap. + */ +class V8_EXPORT PersistentHandleVisitor { // NOLINT + public: + virtual ~PersistentHandleVisitor() {} + virtual void VisitPersistentHandle(Persistent* value, + uint16_t class_id) {} +}; + + /** * Isolate represents an isolated instance of the V8 engine. V8 isolates have * completely separate states. Objects from one isolate must not be used in @@ -4485,6 +4595,7 @@ class V8_EXPORT Isolate { */ enum UseCounterFeature { kUseAsm = 0, + kBreakIterator = 1, kUseCounterFeatureCount // This enum value must be last. }; @@ -4559,6 +4670,21 @@ class V8_EXPORT Isolate { */ void GetHeapStatistics(HeapStatistics* heap_statistics); + /** + * Get a call stack sample from the isolate. + * \param state Execution state. + * \param frames Caller allocated buffer to store stack frames. + * \param frames_limit Maximum number of frames to capture. The buffer must + * be large enough to hold the number of frames. + * \param sample_info The sample info is filled up by the function + * provides number of actual captured stack frames and + * the current VM state. + * \note GetStackSample should only be called when the JS thread is paused or + * interrupted. Otherwise the behavior is undefined. + */ + void GetStackSample(const RegisterState& state, void** frames, + size_t frames_limit, SampleInfo* sample_info); + /** * Adjusts the amount of registered external memory. Used to give V8 an * indication of the amount of externally allocated memory that is kept alive @@ -4688,6 +4814,42 @@ class V8_EXPORT Isolate { */ void RemoveGCEpilogueCallback(GCEpilogueCallback callback); + + /** + * Forcefully terminate the current thread of JavaScript execution + * in the given isolate. + * + * This method can be used by any thread even if that thread has not + * acquired the V8 lock with a Locker object. + */ + void TerminateExecution(); + + /** + * Is V8 terminating JavaScript execution. + * + * Returns true if JavaScript execution is currently terminating + * because of a call to TerminateExecution. In that case there are + * still JavaScript frames on the stack and the termination + * exception is still active. + */ + bool IsExecutionTerminating(); + + /** + * Resume execution capability in the given isolate, whose execution + * was previously forcefully terminated using TerminateExecution(). + * + * When execution is forcefully terminated using TerminateExecution(), + * the isolate can not resume execution until all JavaScript frames + * have propagated the uncatchable exception which is generated. This + * method allows the program embedding the engine to handle the + * termination event and resume execution capability, even if + * JavaScript frames remain on the stack. + * + * This method can be used by any thread even if that thread has not + * acquired the V8 lock with a Locker object. + */ + void CancelTerminateExecution(); + /** * Request V8 to interrupt long running JavaScript code and invoke * the given |callback| passing the given |data| to it. After |callback| @@ -4735,6 +4897,13 @@ class V8_EXPORT Isolate { */ void RemoveCallCompletedCallback(CallCompletedCallback callback); + + /** + * Set callback to notify about promise reject with no handler, or + * revocation of such a previous notification once the handler is added. + */ + void SetPromiseRejectCallback(PromiseRejectCallback callback); + /** * Experimental: Runs the Microtask Work Queue until empty * Any exceptions thrown by microtask callbacks are swallowed. @@ -4853,12 +5022,93 @@ class V8_EXPORT Isolate { * On Win64, embedders are advised to install function table callbacks for * these ranges, as default SEH won't be able to unwind through jitted code. * + * The first page of the code range is reserved for the embedder and is + * committed, writable, and executable. + * * Might be empty on other platforms. * * https://code.google.com/p/v8/issues/detail?id=3598 */ void GetCodeRange(void** start, size_t* length_in_bytes); + /** Set the callback to invoke in case of fatal errors. */ + void SetFatalErrorHandler(FatalErrorCallback that); + + /** + * Set the callback to invoke to check if code generation from + * strings should be allowed. + */ + void SetAllowCodeGenerationFromStringsCallback( + AllowCodeGenerationFromStringsCallback callback); + + /** + * Check if V8 is dead and therefore unusable. This is the case after + * fatal errors such as out-of-memory situations. + */ + bool IsDead(); + + /** + * Adds a message listener. + * + * The same message listener can be added more than once and in that + * case it will be called more than once for each message. + * + * If data is specified, it will be passed to the callback when it is called. + * Otherwise, the exception object will be passed to the callback instead. + */ + bool AddMessageListener(MessageCallback that, + Handle data = Handle()); + + /** + * Remove all message listeners from the specified callback function. + */ + void RemoveMessageListeners(MessageCallback that); + + /** Callback function for reporting failed access checks.*/ + void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback); + + /** + * Tells V8 to capture current stack trace when uncaught exception occurs + * and report it to the message listeners. The option is off by default. + */ + void SetCaptureStackTraceForUncaughtExceptions( + bool capture, int frame_limit = 10, + StackTrace::StackTraceOptions options = StackTrace::kOverview); + + /** + * Enables the host application to provide a mechanism to be notified + * and perform custom logging when V8 Allocates Executable Memory. + */ + void AddMemoryAllocationCallback(MemoryAllocationCallback callback, + ObjectSpace space, AllocationAction action); + + /** + * Removes callback that was installed by AddMemoryAllocationCallback. + */ + void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback); + + /** + * Iterates through all external resources referenced from current isolate + * heap. GC is not invoked prior to iterating, therefore there is no + * guarantee that visited objects are still alive. + */ + void VisitExternalResources(ExternalResourceVisitor* visitor); + + /** + * Iterates through all the persistent handles in the current isolate's heap + * that have class_ids. + */ + void VisitHandlesWithClassIds(PersistentHandleVisitor* visitor); + + /** + * Iterates through all the persistent handles in the current isolate's heap + * that have class_ids and are candidates to be marked as partially dependent + * handles. This will visit handles to young objects created since the last + * garbage collection but is free to visit an arbitrary superset of these + * objects. + */ + void VisitHandlesForPartialDependence(PersistentHandleVisitor* visitor); + private: template friend class PersistentValueMap; @@ -4937,40 +5187,21 @@ typedef uintptr_t (*ReturnAddressLocationResolver)( uintptr_t return_addr_location); -/** - * Interface for iterating through all external resources in the heap. - */ -class V8_EXPORT ExternalResourceVisitor { // NOLINT - public: - virtual ~ExternalResourceVisitor() {} - virtual void VisitExternalString(Handle string) {} -}; - - -/** - * Interface for iterating through all the persistent handles in the heap. - */ -class V8_EXPORT PersistentHandleVisitor { // NOLINT - public: - virtual ~PersistentHandleVisitor() {} - virtual void VisitPersistentHandle(Persistent* value, - uint16_t class_id) {} -}; - - /** * Container class for static utility functions. */ class V8_EXPORT V8 { public: /** Set the callback to invoke in case of fatal errors. */ - static void SetFatalErrorHandler(FatalErrorCallback that); + // TODO(dcarney): deprecate this. + V8_INLINE static void SetFatalErrorHandler(FatalErrorCallback that); /** * Set the callback to invoke to check if code generation from * strings should be allowed. */ - static void SetAllowCodeGenerationFromStringsCallback( + // TODO(dcarney): deprecate this. + V8_INLINE static void SetAllowCodeGenerationFromStringsCallback( AllowCodeGenerationFromStringsCallback that); /** @@ -4982,10 +5213,11 @@ class V8_EXPORT V8 { static void SetArrayBufferAllocator(ArrayBuffer::Allocator* allocator); /** - * Check if V8 is dead and therefore unusable. This is the case after - * fatal errors such as out-of-memory situations. - */ - static bool IsDead(); + * Check if V8 is dead and therefore unusable. This is the case after + * fatal errors such as out-of-memory situations. + */ + // TODO(dcarney): deprecate this. + V8_INLINE static bool IsDead(); /** * The following 4 functions are to be used when V8 is built with @@ -5038,21 +5270,23 @@ class V8_EXPORT V8 { * If data is specified, it will be passed to the callback when it is called. * Otherwise, the exception object will be passed to the callback instead. */ - static bool AddMessageListener(MessageCallback that, - Handle data = Handle()); + // TODO(dcarney): deprecate this. + V8_INLINE static bool AddMessageListener( + MessageCallback that, Handle data = Handle()); /** * Remove all message listeners from the specified callback function. */ - static void RemoveMessageListeners(MessageCallback that); + // TODO(dcarney): deprecate this. + V8_INLINE static void RemoveMessageListeners(MessageCallback that); /** * Tells V8 to capture current stack trace when uncaught exception occurs * and report it to the message listeners. The option is off by default. */ - static void SetCaptureStackTraceForUncaughtExceptions( - bool capture, - int frame_limit = 10, + // TODO(dcarney): deprecate this. + V8_INLINE static void SetCaptureStackTraceForUncaughtExceptions( + bool capture, int frame_limit = 10, StackTrace::StackTraceOptions options = StackTrace::kOverview); /** @@ -5071,7 +5305,9 @@ class V8_EXPORT V8 { static const char* GetVersion(); /** Callback function for reporting failed access checks.*/ - static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback); + // TODO(dcarney): deprecate this. + V8_INLINE static void SetFailedAccessCheckCallbackFunction( + FailedAccessCheckCallback); /** * Enables the host application to receive a notification before a @@ -5083,6 +5319,7 @@ class V8_EXPORT V8 { * register the same callback function two times with different * GCType filters. */ + // TODO(dcarney): deprecate this. static void AddGCPrologueCallback( GCPrologueCallback callback, GCType gc_type_filter = kGCTypeAll); @@ -5090,7 +5327,8 @@ class V8_EXPORT V8 { * This function removes callback which was installed by * AddGCPrologueCallback function. */ - static void RemoveGCPrologueCallback(GCPrologueCallback callback); + // TODO(dcarney): deprecate this. + V8_INLINE static void RemoveGCPrologueCallback(GCPrologueCallback callback); /** * Enables the host application to receive a notification after a @@ -5102,6 +5340,7 @@ class V8_EXPORT V8 { * register the same callback function two times with different * GCType filters. */ + // TODO(dcarney): deprecate this. static void AddGCEpilogueCallback( GCEpilogueCallback callback, GCType gc_type_filter = kGCTypeAll); @@ -5109,20 +5348,24 @@ class V8_EXPORT V8 { * This function removes callback which was installed by * AddGCEpilogueCallback function. */ - static void RemoveGCEpilogueCallback(GCEpilogueCallback callback); + // TODO(dcarney): deprecate this. + V8_INLINE static void RemoveGCEpilogueCallback(GCEpilogueCallback callback); /** * Enables the host application to provide a mechanism to be notified * and perform custom logging when V8 Allocates Executable Memory. */ - static void AddMemoryAllocationCallback(MemoryAllocationCallback callback, - ObjectSpace space, - AllocationAction action); + // TODO(dcarney): deprecate this. + V8_INLINE static void AddMemoryAllocationCallback( + MemoryAllocationCallback callback, ObjectSpace space, + AllocationAction action); /** * Removes callback that was installed by AddMemoryAllocationCallback. */ - static void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback); + // TODO(dcarney): deprecate this. + V8_INLINE static void RemoveMemoryAllocationCallback( + MemoryAllocationCallback callback); /** * Initializes V8. This function needs to be called before the first Isolate @@ -5152,7 +5395,8 @@ class V8_EXPORT V8 { * * \param isolate The isolate in which to terminate the current JS execution. */ - static void TerminateExecution(Isolate* isolate); + // TODO(dcarney): deprecate this. + V8_INLINE static void TerminateExecution(Isolate* isolate); /** * Is V8 terminating JavaScript execution. @@ -5164,7 +5408,8 @@ class V8_EXPORT V8 { * * \param isolate The isolate in which to check. */ - static bool IsExecutionTerminating(Isolate* isolate = NULL); + // TODO(dcarney): deprecate this. + V8_INLINE static bool IsExecutionTerminating(Isolate* isolate = NULL); /** * Resume execution capability in the given isolate, whose execution @@ -5182,7 +5427,8 @@ class V8_EXPORT V8 { * * \param isolate The isolate in which to resume execution capability. */ - static void CancelTerminateExecution(Isolate* isolate); + // TODO(dcarney): deprecate this. + V8_INLINE static void CancelTerminateExecution(Isolate* isolate); /** * Releases any resources used by v8 and stops any utility threads @@ -5200,13 +5446,25 @@ class V8_EXPORT V8 { * heap. GC is not invoked prior to iterating, therefore there is no * guarantee that visited objects are still alive. */ - static void VisitExternalResources(ExternalResourceVisitor* visitor); + // TODO(dcarney): deprecate this. + V8_INLINE static void VisitExternalResources( + ExternalResourceVisitor* visitor); /** * Iterates through all the persistent handles in the current isolate's heap * that have class_ids. */ - static void VisitHandlesWithClassIds(PersistentHandleVisitor* visitor); + // TODO(dcarney): deprecate this. + V8_INLINE static void VisitHandlesWithClassIds( + PersistentHandleVisitor* visitor); + + /** + * Iterates through all the persistent handles in isolate's heap that have + * class_ids. + */ + // TODO(dcarney): deprecate this. + V8_INLINE static void VisitHandlesWithClassIds( + Isolate* isolate, PersistentHandleVisitor* visitor); /** * Iterates through all the persistent handles in the current isolate's heap @@ -5215,7 +5473,8 @@ class V8_EXPORT V8 { * garbage collection but is free to visit an arbitrary superset of these * objects. */ - static void VisitHandlesForPartialDependence( + // TODO(dcarney): deprecate this. + V8_INLINE static void VisitHandlesForPartialDependence( Isolate* isolate, PersistentHandleVisitor* visitor); /** @@ -5242,14 +5501,15 @@ class V8_EXPORT V8 { private: V8(); + enum WeakHandleType { PhantomHandle, NonphantomHandle }; + static internal::Object** GlobalizeReference(internal::Isolate* isolate, internal::Object** handle); static internal::Object** CopyPersistent(internal::Object** handle); static void DisposeGlobal(internal::Object** global_handle); typedef WeakCallbackData::Callback WeakCallback; - static void MakeWeak(internal::Object** global_handle, - void* data, - WeakCallback weak_callback); + static void MakeWeak(internal::Object** global_handle, void* data, + WeakCallback weak_callback, WeakHandleType phantom); static void* ClearWeak(internal::Object** global_handle); static void Eternalize(Isolate* isolate, Value* handle, @@ -5275,8 +5535,16 @@ class V8_EXPORT TryCatch { * all TryCatch blocks should be stack allocated because the memory * location itself is compared against JavaScript try/catch blocks. */ + // TODO(dcarney): deprecate. TryCatch(); + /** + * Creates a new try/catch block and registers it with v8. Note that + * all TryCatch blocks should be stack allocated because the memory + * location itself is compared against JavaScript try/catch blocks. + */ + TryCatch(Isolate* isolate); + /** * Unregisters and deletes this try/catch block. */ @@ -5716,8 +5984,6 @@ class V8_EXPORT Locker { bool top_level_; internal::Isolate* isolate_; - static bool active_; - // Disallow copying and assigning. Locker(const Locker&); void operator=(const Locker&); @@ -5826,7 +6092,7 @@ class Internals { static const int kJSObjectHeaderSize = 3 * kApiPointerSize; static const int kFixedArrayHeaderSize = 2 * kApiPointerSize; static const int kContextHeaderSize = 2 * kApiPointerSize; - static const int kContextEmbedderDataIndex = 95; + static const int kContextEmbedderDataIndex = 76; static const int kFullStringRepresentationMask = 0x07; static const int kStringEncodingMask = 0x4; static const int kExternalTwoByteRepresentationTag = 0x02; @@ -5844,7 +6110,7 @@ class Internals { static const int kNullValueRootIndex = 7; static const int kTrueValueRootIndex = 8; static const int kFalseValueRootIndex = 9; - static const int kEmptyStringRootIndex = 164; + static const int kEmptyStringRootIndex = 154; // The external allocation limit should be below 256 MB on all architectures // to avoid that resource-constrained embedders run low on memory. @@ -5859,7 +6125,7 @@ class Internals { static const int kNodeIsIndependentShift = 4; static const int kNodeIsPartiallyDependentShift = 5; - static const int kJSObjectType = 0xbc; + static const int kJSObjectType = 0xbd; static const int kFirstNonstringType = 0x80; static const int kOddballType = 0x83; static const int kForeignType = 0x88; @@ -6114,9 +6380,8 @@ void PersistentBase::SetWeak( typename WeakCallbackData::Callback callback) { TYPE_CHECK(S, T); typedef typename WeakCallbackData::Callback Callback; - V8::MakeWeak(reinterpret_cast(this->val_), - parameter, - reinterpret_cast(callback)); + V8::MakeWeak(reinterpret_cast(this->val_), parameter, + reinterpret_cast(callback), V8::NonphantomHandle); } @@ -6130,7 +6395,26 @@ void PersistentBase::SetWeak( template -template +template +void PersistentBase::SetPhantom( + P* parameter, typename WeakCallbackData::Callback callback) { + TYPE_CHECK(S, T); + typedef typename WeakCallbackData::Callback Callback; + V8::MakeWeak(reinterpret_cast(this->val_), parameter, + reinterpret_cast(callback), V8::PhantomHandle); +} + + +template +template +void PersistentBase::SetPhantom( + P* parameter, typename WeakCallbackData::Callback callback) { + SetPhantom(parameter, callback); +} + + +template +template P* PersistentBase::ClearWeak() { return reinterpret_cast( V8::ClearWeak(reinterpret_cast(this->val_))); @@ -6157,15 +6441,6 @@ void PersistentBase::MarkPartiallyDependent() { } -template -T* Persistent::ClearAndLeak() { - T* old; - old = this->val_; - this->val_ = NULL; - return old; -} - - template void PersistentBase::SetWrapperClassId(uint16_t class_id) { typedef internal::Internals I; @@ -6571,6 +6846,44 @@ template Value* Value::Cast(T* value) { } +Local Value::ToBoolean() const { + return ToBoolean(Isolate::GetCurrent()); +} + + +Local Value::ToNumber() const { + return ToNumber(Isolate::GetCurrent()); +} + + +Local Value::ToString() const { + return ToString(Isolate::GetCurrent()); +} + + +Local Value::ToDetailString() const { + return ToDetailString(Isolate::GetCurrent()); +} + + +Local Value::ToObject() const { + return ToObject(Isolate::GetCurrent()); +} + + +Local Value::ToInteger() const { + return ToInteger(Isolate::GetCurrent()); +} + + +Local Value::ToUint32() const { + return ToUint32(Isolate::GetCurrent()); +} + + +Local Value::ToInt32() const { return ToInt32(Isolate::GetCurrent()); } + + Name* Name::Cast(v8::Value* value) { #ifdef V8_ENABLE_CHECKS CheckCast(value); @@ -6961,6 +7274,119 @@ void* Context::GetAlignedPointerFromEmbedderData(int index) { } +void V8::SetAllowCodeGenerationFromStringsCallback( + AllowCodeGenerationFromStringsCallback callback) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->SetAllowCodeGenerationFromStringsCallback(callback); +} + + +bool V8::IsDead() { + Isolate* isolate = Isolate::GetCurrent(); + return isolate->IsDead(); +} + + +bool V8::AddMessageListener(MessageCallback that, Handle data) { + Isolate* isolate = Isolate::GetCurrent(); + return isolate->AddMessageListener(that, data); +} + + +void V8::RemoveMessageListeners(MessageCallback that) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->RemoveMessageListeners(that); +} + + +void V8::SetFailedAccessCheckCallbackFunction( + FailedAccessCheckCallback callback) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->SetFailedAccessCheckCallbackFunction(callback); +} + + +void V8::SetCaptureStackTraceForUncaughtExceptions( + bool capture, int frame_limit, StackTrace::StackTraceOptions options) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->SetCaptureStackTraceForUncaughtExceptions(capture, frame_limit, + options); +} + + +void V8::SetFatalErrorHandler(FatalErrorCallback callback) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->SetFatalErrorHandler(callback); +} + + +void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->RemoveGCPrologueCallback( + reinterpret_cast(callback)); +} + + +void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->RemoveGCEpilogueCallback( + reinterpret_cast(callback)); +} + + +void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback, + ObjectSpace space, + AllocationAction action) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->AddMemoryAllocationCallback(callback, space, action); +} + + +void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->RemoveMemoryAllocationCallback(callback); +} + + +void V8::TerminateExecution(Isolate* isolate) { isolate->TerminateExecution(); } + + +bool V8::IsExecutionTerminating(Isolate* isolate) { + if (isolate == NULL) { + isolate = Isolate::GetCurrent(); + } + return isolate->IsExecutionTerminating(); +} + + +void V8::CancelTerminateExecution(Isolate* isolate) { + isolate->CancelTerminateExecution(); +} + + +void V8::VisitExternalResources(ExternalResourceVisitor* visitor) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->VisitExternalResources(visitor); +} + + +void V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) { + Isolate* isolate = Isolate::GetCurrent(); + isolate->VisitHandlesWithClassIds(visitor); +} + + +void V8::VisitHandlesWithClassIds(Isolate* isolate, + PersistentHandleVisitor* visitor) { + isolate->VisitHandlesWithClassIds(visitor); +} + + +void V8::VisitHandlesForPartialDependence(Isolate* isolate, + PersistentHandleVisitor* visitor) { + isolate->VisitHandlesForPartialDependence(visitor); +} + /** * \example shell.cc * A simple shell that takes a list of expressions on the diff --git a/deps/v8/include/v8config.h b/deps/v8/include/v8config.h index 87de994170..721ef37322 100644 --- a/deps/v8/include/v8config.h +++ b/deps/v8/include/v8config.h @@ -120,7 +120,6 @@ // V8_LIBC_BIONIC - Bionic libc // V8_LIBC_BSD - BSD libc derivate // V8_LIBC_GLIBC - GNU C library -// V8_LIBC_UCLIBC - uClibc // // Note that testing for libc must be done using #if not #ifdef. For example, // to test for the GNU C library, use: @@ -133,8 +132,6 @@ #elif defined(__BIONIC__) # define V8_LIBC_BIONIC 1 # define V8_LIBC_BSD 1 -#elif defined(__UCLIBC__) -# define V8_LIBC_UCLIBC 1 #elif defined(__GLIBC__) || defined(__GNU_LIBRARY__) # define V8_LIBC_GLIBC 1 #else @@ -178,6 +175,7 @@ // V8_HAS_BUILTIN_CLZ - __builtin_clz() supported // V8_HAS_BUILTIN_CTZ - __builtin_ctz() supported // V8_HAS_BUILTIN_EXPECT - __builtin_expect() supported +// V8_HAS_BUILTIN_FRAME_ADDRESS - __builtin_frame_address() supported // V8_HAS_BUILTIN_POPCOUNT - __builtin_popcount() supported // V8_HAS_BUILTIN_SADD_OVERFLOW - __builtin_sadd_overflow() supported // V8_HAS_BUILTIN_SSUB_OVERFLOW - __builtin_ssub_overflow() supported @@ -186,7 +184,6 @@ // V8_HAS_DECLSPEC_NOINLINE - __declspec(noinline) supported // V8_HAS___FINAL - __final supported in non-C++11 mode // V8_HAS___FORCEINLINE - __forceinline supported -// V8_HAS_SEALED - MSVC style sealed marker supported // // Note that testing for compilers and/or features must be done using #if // not #ifdef. For example, to test for Intel C++ Compiler, use: @@ -214,6 +211,7 @@ # define V8_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz)) # define V8_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz)) # define V8_HAS_BUILTIN_EXPECT (__has_builtin(__builtin_expect)) +# define V8_HAS_BUILTIN_FRAME_ADDRESS (__has_builtin(__builtin_frame_address)) # define V8_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount)) # define V8_HAS_BUILTIN_SADD_OVERFLOW (__has_builtin(__builtin_sadd_overflow)) # define V8_HAS_BUILTIN_SSUB_OVERFLOW (__has_builtin(__builtin_ssub_overflow)) @@ -251,6 +249,7 @@ # define V8_HAS_BUILTIN_CLZ (V8_GNUC_PREREQ(3, 4, 0)) # define V8_HAS_BUILTIN_CTZ (V8_GNUC_PREREQ(3, 4, 0)) # define V8_HAS_BUILTIN_EXPECT (V8_GNUC_PREREQ(2, 96, 0)) +# define V8_HAS_BUILTIN_FRAME_ADDRESS (V8_GNUC_PREREQ(2, 96, 0)) # define V8_HAS_BUILTIN_POPCOUNT (V8_GNUC_PREREQ(3, 4, 0)) // g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality @@ -277,14 +276,11 @@ # define V8_HAS___ALIGNOF 1 -// Override control was added with Visual Studio 2005, but -// Visual Studio 2010 and earlier spell "final" as "sealed". -# define V8_HAS_CXX11_FINAL (_MSC_VER >= 1700) -# define V8_HAS_CXX11_OVERRIDE (_MSC_VER >= 1400) -# define V8_HAS_SEALED (_MSC_VER >= 1400) +# define V8_HAS_CXX11_FINAL 1 +# define V8_HAS_CXX11_OVERRIDE 1 # define V8_HAS_DECLSPEC_ALIGN 1 -# define V8_HAS_DECLSPEC_DEPRECATED (_MSC_VER >= 1300) +# define V8_HAS_DECLSPEC_DEPRECATED 1 # define V8_HAS_DECLSPEC_NOINLINE 1 # define V8_HAS___FORCEINLINE 1 diff --git a/deps/v8/include/v8stdint.h b/deps/v8/include/v8stdint.h deleted file mode 100644 index 9a935dddeb..0000000000 --- a/deps/v8/include/v8stdint.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Load definitions of standard types. - -#ifndef V8STDINT_H_ -#define V8STDINT_H_ - -#include -#include - -#include "v8config.h" - -#if V8_OS_WIN && !V8_CC_MINGW - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include // NOLINT - -#endif - -#endif // V8STDINT_H_ diff --git a/deps/v8/src/DEPS b/deps/v8/src/DEPS index 260f5b2e5f..4dbb3c756a 100644 --- a/deps/v8/src/DEPS +++ b/deps/v8/src/DEPS @@ -3,8 +3,7 @@ include_rules = [ "-src/compiler", "+src/compiler/pipeline.h", "-src/libplatform", - "-include/libplatform", - "+testing", + "-include/libplatform" ] specific_include_rules = { diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc index 011372cbff..ed9d2940e6 100644 --- a/deps/v8/src/accessors.cc +++ b/deps/v8/src/accessors.cc @@ -56,17 +56,6 @@ Handle Accessors::CloneAccessor( } -template -static C* FindInstanceOf(Isolate* isolate, Object* obj) { - for (PrototypeIterator iter(isolate, obj, - PrototypeIterator::START_AT_RECEIVER); - !iter.IsAtEnd(); iter.Advance()) { - if (Is(iter.GetCurrent())) return C::cast(iter.GetCurrent()); - } - return NULL; -} - - static V8_INLINE bool CheckForName(Handle name, Handle property_name, int offset, @@ -183,7 +172,10 @@ void Accessors::ArgumentsIteratorSetter( LookupIterator it(object, Utils::OpenHandle(*name)); CHECK_EQ(LookupIterator::ACCESSOR, it.state()); DCHECK(it.HolderIsReceiverOrHiddenPrototype()); - Object::SetDataProperty(&it, value); + + if (Object::SetDataProperty(&it, value).is_null()) { + isolate->OptionalRescheduleException(false); + } } @@ -258,7 +250,7 @@ void Accessors::ArrayLengthSetter( if (uint32_v->Number() == number_v->Number()) { maybe = JSArray::SetElementsLength(array_handle, uint32_v); - maybe.Check(); + if (maybe.is_null()) isolate->OptionalRescheduleException(false); return; } @@ -892,9 +884,8 @@ static Handle GetFunctionPrototype(Isolate* isolate, } -static Handle SetFunctionPrototype(Isolate* isolate, - Handle function, - Handle value) { +MUST_USE_RESULT static MaybeHandle SetFunctionPrototype( + Isolate* isolate, Handle function, Handle value) { Handle old_value; bool is_observed = function->map()->is_observed(); if (is_observed) { @@ -908,21 +899,17 @@ static Handle SetFunctionPrototype(Isolate* isolate, DCHECK(function->prototype() == *value); if (is_observed && !old_value->SameValue(*value)) { - JSObject::EnqueueChangeRecord( + MaybeHandle result = JSObject::EnqueueChangeRecord( function, "update", isolate->factory()->prototype_string(), old_value); + if (result.is_null()) return MaybeHandle(); } return function; } -Handle Accessors::FunctionGetPrototype(Handle function) { - return GetFunctionPrototype(function->GetIsolate(), function); -} - - -Handle Accessors::FunctionSetPrototype(Handle function, - Handle prototype) { +MaybeHandle Accessors::FunctionSetPrototype(Handle function, + Handle prototype) { DCHECK(function->should_have_prototype()); Isolate* isolate = function->GetIsolate(); return SetFunctionPrototype(isolate, function, prototype); @@ -953,7 +940,9 @@ void Accessors::FunctionPrototypeSetter( } Handle object = Handle::cast(Utils::OpenHandle(*info.Holder())); - SetFunctionPrototype(isolate, object, value); + if (SetFunctionPrototype(isolate, object, value).is_null()) { + isolate->OptionalRescheduleException(false); + } } diff --git a/deps/v8/src/accessors.h b/deps/v8/src/accessors.h index 8fc1f84be3..678064df16 100644 --- a/deps/v8/src/accessors.h +++ b/deps/v8/src/accessors.h @@ -66,9 +66,8 @@ class Accessors : public AllStatic { }; // Accessor functions called directly from the runtime system. - static Handle FunctionSetPrototype(Handle object, - Handle value); - static Handle FunctionGetPrototype(Handle object); + MUST_USE_RESULT static MaybeHandle FunctionSetPrototype( + Handle object, Handle value); static Handle FunctionGetArguments(Handle object); // Accessor infos. diff --git a/deps/v8/src/allocation.cc b/deps/v8/src/allocation.cc index cae1c10251..96fd71f11b 100644 --- a/deps/v8/src/allocation.cc +++ b/deps/v8/src/allocation.cc @@ -85,7 +85,7 @@ char* StrNDup(const char* str, int n) { void* AlignedAlloc(size_t size, size_t alignment) { DCHECK_LE(V8_ALIGNOF(void*), alignment); - DCHECK(base::bits::IsPowerOfTwo32(alignment)); + DCHECK(base::bits::IsPowerOfTwo64(alignment)); void* ptr; #if V8_OS_WIN ptr = _aligned_malloc(size, alignment); diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 0fbdf7bd9b..75fc2d700a 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -40,6 +40,7 @@ #include "src/prototype.h" #include "src/runtime/runtime.h" #include "src/runtime-profiler.h" +#include "src/sampler.h" #include "src/scanner-character-streams.h" #include "src/simulator.h" #include "src/snapshot.h" @@ -51,9 +52,8 @@ #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr)) -#define ENTER_V8(isolate) \ - DCHECK((isolate)->IsInitialized()); \ - i::VMState __state__((isolate)) +#define ENTER_V8(isolate) \ + i::VMState __state__((isolate)) namespace v8 { @@ -186,14 +186,7 @@ void Utils::ReportApiFailure(const char* location, const char* message) { } -bool V8::IsDead() { - i::Isolate* isolate = i::Isolate::Current(); - return isolate->IsDead(); -} - - static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { - if (!isolate->IsInitialized()) return false; if (isolate->has_scheduled_exception()) { return isolate->scheduled_exception() == isolate->heap()->termination_exception(); @@ -348,19 +341,6 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) { } -void V8::SetFatalErrorHandler(FatalErrorCallback that) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->set_exception_behavior(that); -} - - -void V8::SetAllowCodeGenerationFromStringsCallback( - AllowCodeGenerationFromStringsCallback callback) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->set_allow_code_gen_callback(callback); -} - - void V8::SetFlagsFromString(const char* str, int length) { i::FlagList::SetFlagsFromString(str, length); } @@ -510,10 +490,12 @@ i::Object** V8::CopyPersistent(i::Object** obj) { } -void V8::MakeWeak(i::Object** object, - void* parameters, - WeakCallback weak_callback) { - i::GlobalHandles::MakeWeak(object, parameters, weak_callback); +void V8::MakeWeak(i::Object** object, void* parameters, + WeakCallback weak_callback, V8::WeakHandleType weak_type) { + i::GlobalHandles::PhantomState phantom; + phantom = weak_type == V8::PhantomHandle ? i::GlobalHandles::Phantom + : i::GlobalHandles::Nonphantom; + i::GlobalHandles::MakeWeak(object, parameters, weak_callback, phantom); } @@ -750,11 +732,11 @@ i::Object* NeanderArray::get(int offset) { // about this there is no HandleScope in this method. When you add one to the // site calling this method you should check that you ensured the VM was not // dead first. -void NeanderArray::add(i::Handle value) { +void NeanderArray::add(i::Isolate* isolate, i::Handle value) { int length = this->length(); int size = obj_.size(); if (length == size - 1) { - i::Factory* factory = i::Isolate::Current()->factory(); + i::Factory* factory = isolate->factory(); i::Handle new_elms = factory->NewFixedArray(2 * size); for (int i = 0; i < length; i++) new_elms->set(i + 1, get(i)); @@ -789,12 +771,12 @@ static void TemplateSet(i::Isolate* isolate, Utils::OpenHandle(templ)->set_property_list(*list); } NeanderArray array(list); - array.add(isolate->factory()->NewNumberFromInt(length)); + array.add(isolate, isolate->factory()->NewNumberFromInt(length)); for (int i = 0; i < length; i++) { i::Handle value = data[i].IsEmpty() ? i::Handle(isolate->factory()->undefined_value()) : Utils::OpenHandle(*data[i]); - array.add(value); + array.add(isolate, value); } } @@ -802,7 +784,7 @@ static void TemplateSet(i::Isolate* isolate, void Template::Set(v8::Handle name, v8::Handle value, v8::PropertyAttribute attribute) { - i::Isolate* isolate = i::Isolate::Current(); + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ENTER_V8(isolate); i::HandleScope scope(isolate); const int kSize = 3; @@ -1084,11 +1066,9 @@ Local TypeSwitch::New(int argc, Handle types[]) { int TypeSwitch::match(v8::Handle value) { - i::Isolate* isolate = i::Isolate::Current(); - LOG_API(isolate, "TypeSwitch::match"); - USE(isolate); - i::Handle obj = Utils::OpenHandle(*value); i::Handle info = Utils::OpenHandle(this); + LOG_API(info->GetIsolate(), "TypeSwitch::match"); + i::Handle obj = Utils::OpenHandle(*value); i::FixedArray* types = i::FixedArray::cast(info->types()); for (int i = 0; i < types->length(); i++) { if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj)) @@ -1292,7 +1272,7 @@ static inline void AddPropertyToTemplate( info->set_property_accessors(*list); } NeanderArray array(list); - array.add(obj); + array.add(isolate, obj); } @@ -1920,8 +1900,24 @@ v8::TryCatch::TryCatch() } +v8::TryCatch::TryCatch(v8::Isolate* isolate) + : isolate_(reinterpret_cast(isolate)), + next_(isolate_->try_catch_handler()), + is_verbose_(false), + can_continue_(true), + capture_message_(true), + rethrow_(false), + has_terminated_(false) { + ResetInternal(); + // Special handling for simulators which have a separate JS stack. + js_stack_comparable_address_ = + reinterpret_cast(v8::internal::SimulatorStack::RegisterCTryCatch( + v8::internal::GetCurrentStackPosition())); + isolate_->RegisterTryCatchHandler(this); +} + + v8::TryCatch::~TryCatch() { - DCHECK(isolate_ == i::Isolate::Current()); if (rethrow_) { v8::Isolate* isolate = reinterpret_cast(isolate_); v8::HandleScope scope(isolate); @@ -1974,7 +1970,6 @@ v8::Handle v8::TryCatch::ReThrow() { v8::Local v8::TryCatch::Exception() const { - DCHECK(isolate_ == i::Isolate::Current()); if (HasCaught()) { // Check for out of memory exception. i::Object* exception = reinterpret_cast(exception_); @@ -1986,7 +1981,6 @@ v8::Local v8::TryCatch::Exception() const { v8::Local v8::TryCatch::StackTrace() const { - DCHECK(isolate_ == i::Isolate::Current()); if (HasCaught()) { i::Object* raw_obj = reinterpret_cast(exception_); if (!raw_obj->IsJSObject()) return v8::Local(); @@ -2010,7 +2004,6 @@ v8::Local v8::TryCatch::StackTrace() const { v8::Local v8::TryCatch::Message() const { - DCHECK(isolate_ == i::Isolate::Current()); i::Object* message = reinterpret_cast(message_obj_); DCHECK(message->IsJSMessageObject() || message->IsTheHole()); if (HasCaught() && !message->IsTheHole()) { @@ -2022,7 +2015,6 @@ v8::Local v8::TryCatch::Message() const { void v8::TryCatch::Reset() { - DCHECK(isolate_ == i::Isolate::Current()); if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) { // If an exception was caught but is still scheduled because no API call // promoted it, then it is canceled to prevent it from being propagated. @@ -2110,11 +2102,8 @@ v8::Handle Message::GetStackTrace() const { MUST_USE_RESULT static i::MaybeHandle CallV8HeapFunction( - const char* name, - i::Handle recv, - int argc, + i::Isolate* isolate, const char* name, i::Handle recv, int argc, i::Handle argv[]) { - i::Isolate* isolate = i::Isolate::Current(); i::Handle object_fun = i::Object::GetProperty( isolate, isolate->js_builtins_object(), name).ToHandleChecked(); @@ -2124,13 +2113,10 @@ MUST_USE_RESULT static i::MaybeHandle CallV8HeapFunction( MUST_USE_RESULT static i::MaybeHandle CallV8HeapFunction( - const char* name, - i::Handle data) { + i::Isolate* isolate, const char* name, i::Handle data) { i::Handle argv[] = { data }; - return CallV8HeapFunction(name, - i::Isolate::Current()->js_builtins_object(), - arraysize(argv), - argv); + return CallV8HeapFunction(isolate, name, isolate->js_builtins_object(), + arraysize(argv), argv); } @@ -2142,8 +2128,9 @@ int Message::GetLineNumber() const { EXCEPTION_PREAMBLE(isolate); i::Handle result; - has_pending_exception = !CallV8HeapFunction( - "GetLineNumber", Utils::OpenHandle(this)).ToHandle(&result); + has_pending_exception = + !CallV8HeapFunction(isolate, "GetLineNumber", Utils::OpenHandle(this)) + .ToHandle(&result); EXCEPTION_BAILOUT_CHECK(isolate, 0); return static_cast(result->Number()); } @@ -2177,8 +2164,9 @@ int Message::GetStartColumn() const { i::Handle data_obj = Utils::OpenHandle(this); EXCEPTION_PREAMBLE(isolate); i::Handle start_col_obj; - has_pending_exception = !CallV8HeapFunction( - "GetPositionInLine", data_obj).ToHandle(&start_col_obj); + has_pending_exception = + !CallV8HeapFunction(isolate, "GetPositionInLine", data_obj) + .ToHandle(&start_col_obj); EXCEPTION_BAILOUT_CHECK(isolate, 0); return static_cast(start_col_obj->Number()); } @@ -2192,8 +2180,9 @@ int Message::GetEndColumn() const { i::Handle data_obj = Utils::OpenHandle(this); EXCEPTION_PREAMBLE(isolate); i::Handle start_col_obj; - has_pending_exception = !CallV8HeapFunction( - "GetPositionInLine", data_obj).ToHandle(&start_col_obj); + has_pending_exception = + !CallV8HeapFunction(isolate, "GetPositionInLine", data_obj) + .ToHandle(&start_col_obj); EXCEPTION_BAILOUT_CHECK(isolate, 0); i::Handle message = i::Handle::cast(data_obj); @@ -2223,8 +2212,9 @@ Local Message::GetSourceLine() const { EscapableHandleScope scope(reinterpret_cast(isolate)); EXCEPTION_PREAMBLE(isolate); i::Handle result; - has_pending_exception = !CallV8HeapFunction( - "GetSourceLine", Utils::OpenHandle(this)).ToHandle(&result); + has_pending_exception = + !CallV8HeapFunction(isolate, "GetSourceLine", Utils::OpenHandle(this)) + .ToHandle(&result); EXCEPTION_BAILOUT_CHECK(isolate, Local()); if (result->IsString()) { return scope.Escape(Utils::ToLocal(i::Handle::cast(result))); @@ -2581,13 +2571,23 @@ bool Value::IsGeneratorObject() const { } -Local Value::ToString() const { +bool Value::IsMapIterator() const { + return Utils::OpenHandle(this)->IsJSMapIterator(); +} + + +bool Value::IsSetIterator() const { + return Utils::OpenHandle(this)->IsJSSetIterator(); +} + + +Local Value::ToString(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); i::Handle str; if (obj->IsString()) { str = obj; } else { - i::Isolate* isolate = i::Isolate::Current(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToString"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); @@ -2599,13 +2599,13 @@ Local Value::ToString() const { } -Local Value::ToDetailString() const { +Local Value::ToDetailString(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); i::Handle str; if (obj->IsString()) { str = obj; } else { - i::Isolate* isolate = i::Isolate::Current(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToDetailString"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); @@ -2617,13 +2617,13 @@ Local Value::ToDetailString() const { } -Local Value::ToObject() const { +Local Value::ToObject(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); i::Handle val; if (obj->IsJSObject()) { val = obj; } else { - i::Isolate* isolate = i::Isolate::Current(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToObject"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); @@ -2635,12 +2635,12 @@ Local Value::ToObject() const { } -Local Value::ToBoolean() const { +Local Value::ToBoolean(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); if (obj->IsBoolean()) { return ToApiHandle(obj); } else { - i::Isolate* isolate = i::Isolate::Current(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToBoolean"); ENTER_V8(isolate); i::Handle val = @@ -2650,13 +2650,13 @@ Local Value::ToBoolean() const { } -Local Value::ToNumber() const { +Local Value::ToNumber(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); i::Handle num; if (obj->IsNumber()) { num = obj; } else { - i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToNumber"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); @@ -2668,13 +2668,13 @@ Local Value::ToNumber() const { } -Local Value::ToInteger() const { +Local Value::ToInteger(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); i::Handle num; if (obj->IsSmi()) { num = obj; } else { - i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToInteger"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); @@ -2689,7 +2689,6 @@ Local Value::ToInteger() const { void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) { i::Isolate* isolate = reinterpret_cast(external_isolate); Utils::ApiCheck(isolate != NULL && - isolate->IsInitialized() && !isolate->IsDead(), "v8::internal::Internals::CheckInitialized()", "Isolate is not initialized or V8 has died"); @@ -2937,13 +2936,13 @@ int64_t Value::IntegerValue() const { } -Local Value::ToInt32() const { +Local Value::ToInt32(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); i::Handle num; if (obj->IsSmi()) { num = obj; } else { - i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToInt32"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); @@ -2954,13 +2953,13 @@ Local Value::ToInt32() const { } -Local Value::ToUint32() const { +Local Value::ToUint32(Isolate* v8_isolate) const { i::Handle obj = Utils::OpenHandle(this); i::Handle num; if (obj->IsSmi()) { num = obj; } else { - i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); + i::Isolate* isolate = reinterpret_cast(v8_isolate); LOG_API(isolate, "ToUInt32"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); @@ -3042,8 +3041,9 @@ bool Value::Equals(Handle that) const { i::Handle args[] = { other }; EXCEPTION_PREAMBLE(isolate); i::Handle result; - has_pending_exception = !CallV8HeapFunction( - "EQUALS", obj, arraysize(args), args).ToHandle(&result); + has_pending_exception = + !CallV8HeapFunction(isolate, "EQUALS", obj, arraysize(args), args) + .ToHandle(&result); EXCEPTION_BAILOUT_CHECK(isolate, false); return *result == i::Smi::FromInt(i::EQUAL); } @@ -3175,6 +3175,44 @@ bool v8::Object::SetPrivate(v8::Handle key, v8::Handle value) { } +i::MaybeHandle DeleteObjectProperty( + i::Isolate* isolate, i::Handle receiver, + i::Handle key, i::JSReceiver::DeleteMode mode) { + // Check if the given key is an array index. + uint32_t index; + if (key->ToArrayIndex(&index)) { + // In Firefox/SpiderMonkey, Safari and Opera you can access the + // characters of a string using [] notation. In the case of a + // String object we just need to redirect the deletion to the + // underlying string if the index is in range. Since the + // underlying string does nothing with the deletion, we can ignore + // such deletions. + if (receiver->IsStringObjectWithCharacterAt(index)) { + return isolate->factory()->true_value(); + } + + return i::JSReceiver::DeleteElement(receiver, index, mode); + } + + i::Handle name; + if (key->IsName()) { + name = i::Handle::cast(key); + } else { + // Call-back into JavaScript to convert the key to a string. + i::Handle converted; + if (!i::Execution::ToString(isolate, key).ToHandle(&converted)) { + return i::MaybeHandle(); + } + name = i::Handle::cast(converted); + } + + if (name->IsString()) { + name = i::String::Flatten(i::Handle::cast(name)); + } + return i::JSReceiver::DeleteProperty(receiver, name, mode); +} + + bool v8::Object::ForceDelete(v8::Handle key) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false); @@ -3193,8 +3231,9 @@ bool v8::Object::ForceDelete(v8::Handle key) { EXCEPTION_PREAMBLE(isolate); i::Handle obj; - has_pending_exception = !i::Runtime::DeleteObjectProperty( - isolate, self, key_obj, i::JSReceiver::FORCE_DELETION).ToHandle(&obj); + has_pending_exception = + !DeleteObjectProperty(isolate, self, key_obj, + i::JSReceiver::FORCE_DELETION).ToHandle(&obj); EXCEPTION_BAILOUT_CHECK(isolate, false); return obj->IsTrue(); } @@ -3269,11 +3308,10 @@ Local v8::Object::GetOwnPropertyDescriptor(Local key) { i::Handle args[] = { obj, key_name }; EXCEPTION_PREAMBLE(isolate); i::Handle result; - has_pending_exception = !CallV8HeapFunction( - "ObjectGetOwnPropertyDescriptor", - isolate->factory()->undefined_value(), - arraysize(args), - args).ToHandle(&result); + has_pending_exception = + !CallV8HeapFunction(isolate, "ObjectGetOwnPropertyDescriptor", + isolate->factory()->undefined_value(), + arraysize(args), args).ToHandle(&result); EXCEPTION_BAILOUT_CHECK(isolate, Local()); return Utils::ToLocal(result); } @@ -3372,6 +3410,37 @@ Local v8::Object::GetOwnPropertyNames() { } +static bool GetPredefinedToString(i::Handle tag, + Local* result) { + i::Isolate* i_isolate = tag->GetIsolate(); + Isolate* isolate = reinterpret_cast(i_isolate); + i::Factory* factory = i_isolate->factory(); + + if (i::String::Equals(tag, factory->Arguments_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~Arguments]"); + } else if (i::String::Equals(tag, factory->Array_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~Array]"); + } else if (i::String::Equals(tag, factory->Boolean_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~Boolean]"); + } else if (i::String::Equals(tag, factory->Date_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~Date]"); + } else if (i::String::Equals(tag, factory->Error_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~Error]"); + } else if (i::String::Equals(tag, factory->Function_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~Function]"); + } else if (i::String::Equals(tag, factory->Number_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~Number]"); + } else if (i::String::Equals(tag, factory->RegExp_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~RegExp]"); + } else if (i::String::Equals(tag, factory->String_string())) { + *result = v8::String::NewFromUtf8(isolate, "[object ~String]"); + } else { + return false; + } + return true; +} + + Local v8::Object::ObjectProtoToString() { i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); Isolate* isolate = reinterpret_cast(i_isolate); @@ -3381,6 +3450,7 @@ Local v8::Object::ObjectProtoToString() { i::Handle self = Utils::OpenHandle(this); i::Handle name(self->class_name(), i_isolate); + i::Handle tag; // Native implementation of Object.prototype.toString (v8natives.js): // var c = %_ClassOf(this); @@ -3395,6 +3465,27 @@ Local v8::Object::ObjectProtoToString() { i_isolate->factory()->Arguments_string())) { return v8::String::NewFromUtf8(isolate, "[object Object]"); } else { + if (internal::FLAG_harmony_tostring) { + i::Handle toStringTag = + Utils::OpenHandle(*Symbol::GetToStringTag(isolate)); + EXCEPTION_PREAMBLE(i_isolate); + has_pending_exception = + !i::Runtime::GetObjectProperty(i_isolate, self, toStringTag) + .ToHandle(&tag); + EXCEPTION_BAILOUT_CHECK(i_isolate, Local()); + + if (!tag->IsUndefined()) { + if (!tag->IsString()) + return v8::String::NewFromUtf8(isolate, "[object ???]"); + i::Handle tag_name = i::Handle::cast(tag); + if (!i::String::Equals(class_name, tag_name)) { + Local result; + if (GetPredefinedToString(tag_name, &result)) return result; + + class_name = tag_name; + } + } + } const char* prefix = "[object "; Local str = Utils::ToLocal(class_name); const char* postfix = "]"; @@ -3447,8 +3538,9 @@ bool v8::Object::Delete(v8::Handle key) { i::Handle key_obj = Utils::OpenHandle(*key); EXCEPTION_PREAMBLE(isolate); i::Handle obj; - has_pending_exception = !i::Runtime::DeleteObjectProperty( - isolate, self, key_obj, i::JSReceiver::NORMAL_DELETION).ToHandle(&obj); + has_pending_exception = + !DeleteObjectProperty(isolate, self, key_obj, + i::JSReceiver::NORMAL_DELETION).ToHandle(&obj); EXCEPTION_BAILOUT_CHECK(isolate, false); return obj->IsTrue(); } @@ -3466,11 +3558,22 @@ bool v8::Object::Has(v8::Handle key) { i::Handle self = Utils::OpenHandle(this); i::Handle key_obj = Utils::OpenHandle(*key); EXCEPTION_PREAMBLE(isolate); - i::Handle obj; - has_pending_exception = !i::Runtime::HasObjectProperty( - isolate, self, key_obj).ToHandle(&obj); + Maybe maybe; + // Check if the given key is an array index. + uint32_t index; + if (key_obj->ToArrayIndex(&index)) { + maybe = i::JSReceiver::HasElement(self, index); + } else { + // Convert the key to a name - possibly by calling back into JavaScript. + i::Handle name; + if (i::Runtime::ToName(isolate, key_obj).ToHandle(&name)) { + maybe = i::JSReceiver::HasProperty(self, name); + } + } + if (!maybe.has_value) has_pending_exception = true; EXCEPTION_BAILOUT_CHECK(isolate, false); - return obj->IsTrue(); + DCHECK(maybe.has_value); + return maybe.value; } @@ -3725,11 +3828,6 @@ void v8::Object::TurnOnAccessCheck() { } -bool v8::Object::IsDirty() { - return Utils::OpenHandle(this)->IsDirty(); -} - - Local v8::Object::Clone() { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::Clone()", return Local()); @@ -5094,50 +5192,6 @@ HeapStatistics::HeapStatistics(): total_heap_size_(0), heap_size_limit_(0) { } -void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->heap()->VisitExternalResources(visitor); -} - - -class VisitorAdapter : public i::ObjectVisitor { - public: - explicit VisitorAdapter(PersistentHandleVisitor* visitor) - : visitor_(visitor) {} - virtual void VisitPointers(i::Object** start, i::Object** end) { - UNREACHABLE(); - } - virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) { - Value* value = ToApi(i::Handle(p)); - visitor_->VisitPersistentHandle( - reinterpret_cast*>(&value), class_id); - } - private: - PersistentHandleVisitor* visitor_; -}; - - -void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) { - i::Isolate* isolate = i::Isolate::Current(); - i::DisallowHeapAllocation no_allocation; - - VisitorAdapter visitor_adapter(visitor); - isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter); -} - - -void v8::V8::VisitHandlesForPartialDependence( - Isolate* exported_isolate, PersistentHandleVisitor* visitor) { - i::Isolate* isolate = reinterpret_cast(exported_isolate); - DCHECK(isolate == i::Isolate::Current()); - i::DisallowHeapAllocation no_allocation; - - VisitorAdapter visitor_adapter(visitor); - isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds( - &visitor_adapter); -} - - bool v8::V8::InitializeICU(const char* icu_data_file) { return i::InitializeICU(icu_data_file); } @@ -5233,25 +5287,25 @@ Local v8::Context::New( void v8::Context::SetSecurityToken(Handle token) { - i::Isolate* isolate = i::Isolate::Current(); - ENTER_V8(isolate); i::Handle env = Utils::OpenHandle(this); + i::Isolate* isolate = env->GetIsolate(); + ENTER_V8(isolate); i::Handle token_handle = Utils::OpenHandle(*token); env->set_security_token(*token_handle); } void v8::Context::UseDefaultSecurityToken() { - i::Isolate* isolate = i::Isolate::Current(); - ENTER_V8(isolate); i::Handle env = Utils::OpenHandle(this); + i::Isolate* isolate = env->GetIsolate(); + ENTER_V8(isolate); env->set_security_token(env->global_object()); } Handle v8::Context::GetSecurityToken() { - i::Isolate* isolate = i::Isolate::Current(); i::Handle env = Utils::OpenHandle(this); + i::Isolate* isolate = env->GetIsolate(); i::Object* security_token = env->security_token(); i::Handle token_handle(security_token, isolate); return Utils::ToLocal(token_handle); @@ -5310,40 +5364,42 @@ void Context::SetErrorMessageForCodeGenerationFromStrings( Local ObjectTemplate::NewInstance() { - i::Isolate* isolate = i::Isolate::Current(); + i::Handle info = Utils::OpenHandle(this); + i::Isolate* isolate = info->GetIsolate(); ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()", return Local()); LOG_API(isolate, "ObjectTemplate::NewInstance"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); i::Handle obj; - has_pending_exception = !i::Execution::InstantiateObject( - Utils::OpenHandle(this)).ToHandle(&obj); + has_pending_exception = !i::Execution::InstantiateObject(info).ToHandle(&obj); EXCEPTION_BAILOUT_CHECK(isolate, Local()); return Utils::ToLocal(i::Handle::cast(obj)); } Local FunctionTemplate::GetFunction() { - i::Isolate* isolate = i::Isolate::Current(); + i::Handle info = Utils::OpenHandle(this); + i::Isolate* isolate = info->GetIsolate(); ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()", return Local()); LOG_API(isolate, "FunctionTemplate::GetFunction"); ENTER_V8(isolate); EXCEPTION_PREAMBLE(isolate); i::Handle obj; - has_pending_exception = !i::Execution::InstantiateFunction( - Utils::OpenHandle(this)).ToHandle(&obj); + has_pending_exception = + !i::Execution::InstantiateFunction(info).ToHandle(&obj); EXCEPTION_BAILOUT_CHECK(isolate, Local()); return Utils::ToLocal(i::Handle::cast(obj)); } bool FunctionTemplate::HasInstance(v8::Handle value) { - ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()", - return false); + i::Handle info = Utils::OpenHandle(this); + i::Isolate* isolate = info->GetIsolate(); + ON_BAILOUT(isolate, "v8::FunctionTemplate::HasInstanceOf()", return false); i::Object* obj = *Utils::OpenHandle(*value); - return Utils::OpenHandle(this)->IsTemplateFor(obj); + return info->IsTemplateFor(obj); } @@ -5607,6 +5663,12 @@ bool v8::String::CanMakeExternal() { } +Isolate* v8::Object::GetIsolate() { + i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); + return reinterpret_cast(i_isolate); +} + + Local v8::Object::New(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast(isolate); LOG_API(i_isolate, "Object::New"); @@ -5729,7 +5791,6 @@ double v8::Date::ValueOf() const { void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast(isolate); - if (!i_isolate->IsInitialized()) return; ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()", return); LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification"); @@ -5984,11 +6045,26 @@ Local Promise::Then(Handle handler) { } +bool Promise::HasHandler() { + i::Handle promise = Utils::OpenHandle(this); + i::Isolate* isolate = promise->GetIsolate(); + LOG_API(isolate, "Promise::HasRejectHandler"); + ENTER_V8(isolate); + i::Handle key = isolate->factory()->promise_has_handler_symbol(); + return i::JSObject::GetDataProperty(promise, key)->IsTrue(); +} + + bool v8::ArrayBuffer::IsExternal() const { return Utils::OpenHandle(this)->is_external(); } +bool v8::ArrayBuffer::IsNeuterable() const { + return Utils::OpenHandle(this)->is_neuterable(); +} + + v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() { i::Handle obj = Utils::OpenHandle(this); Utils::ApiCheck(!obj->is_external(), @@ -6009,6 +6085,8 @@ void v8::ArrayBuffer::Neuter() { Utils::ApiCheck(obj->is_external(), "v8::ArrayBuffer::Neuter", "Only externalized ArrayBuffers can be neutered"); + Utils::ApiCheck(obj->is_neuterable(), "v8::ArrayBuffer::Neuter", + "Only neuterable ArrayBuffers can be neutered"); LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()"); ENTER_V8(isolate); i::Runtime::NeuterArrayBuffer(obj); @@ -6077,78 +6155,22 @@ size_t v8::TypedArray::Length() { } -static inline void SetupArrayBufferView( - i::Isolate* isolate, - i::Handle obj, - i::Handle buffer, - size_t byte_offset, - size_t byte_length) { - DCHECK(byte_offset + byte_length <= - static_cast(buffer->byte_length()->Number())); - - obj->set_buffer(*buffer); - - obj->set_weak_next(buffer->weak_first_view()); - buffer->set_weak_first_view(*obj); - - i::Handle byte_offset_object = - isolate->factory()->NewNumberFromSize(byte_offset); - obj->set_byte_offset(*byte_offset_object); - - i::Handle byte_length_object = - isolate->factory()->NewNumberFromSize(byte_length); - obj->set_byte_length(*byte_length_object); -} - -template -i::Handle NewTypedArray( - i::Isolate* isolate, - Handle array_buffer, size_t byte_offset, size_t length) { - i::Handle obj = - isolate->factory()->NewJSTypedArray(array_type); - i::Handle buffer = Utils::OpenHandle(*array_buffer); - - DCHECK(byte_offset % sizeof(ElementType) == 0); - - CHECK(length <= (std::numeric_limits::max() / sizeof(ElementType))); - CHECK(length <= static_cast(i::Smi::kMaxValue)); - size_t byte_length = length * sizeof(ElementType); - SetupArrayBufferView( - isolate, obj, buffer, byte_offset, byte_length); - - i::Handle length_object = - isolate->factory()->NewNumberFromSize(length); - obj->set_length(*length_object); - - i::Handle elements = - isolate->factory()->NewExternalArray( - static_cast(length), array_type, - static_cast(buffer->backing_store()) + byte_offset); - i::Handle map = - i::JSObject::GetElementsTransitionMap(obj, elements_kind); - i::JSObject::SetMapAndElements(obj, map, elements); - return obj; -} - - #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size) \ Local Type##Array::New(Handle array_buffer, \ - size_t byte_offset, size_t length) { \ + size_t byte_offset, size_t length) { \ i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \ LOG_API(isolate, \ - "v8::" #Type "Array::New(Handle, size_t, size_t)"); \ + "v8::" #Type "Array::New(Handle, size_t, size_t)"); \ ENTER_V8(isolate); \ if (!Utils::ApiCheck(length <= static_cast(i::Smi::kMaxValue), \ - "v8::" #Type "Array::New(Handle, size_t, size_t)", \ - "length exceeds max allowed value")) { \ - return Local(); \ + "v8::" #Type \ + "Array::New(Handle, size_t, size_t)", \ + "length exceeds max allowed value")) { \ + return Local(); \ } \ - i::Handle obj = \ - NewTypedArray( \ - isolate, array_buffer, byte_offset, length); \ + i::Handle buffer = Utils::OpenHandle(*array_buffer); \ + i::Handle obj = isolate->factory()->NewJSTypedArray( \ + v8::kExternal##Type##Array, buffer, byte_offset, length); \ return Utils::ToLocal##Type##Array(obj); \ } @@ -6162,9 +6184,8 @@ Local DataView::New(Handle array_buffer, i::Isolate* isolate = buffer->GetIsolate(); LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)"); ENTER_V8(isolate); - i::Handle obj = isolate->factory()->NewJSDataView(); - SetupArrayBufferView( - isolate, obj, buffer, byte_offset, byte_length); + i::Handle obj = + isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length); return Utils::ToLocal(obj); } @@ -6233,6 +6254,11 @@ Local v8::Symbol::GetUnscopables(Isolate* isolate) { } +Local v8::Symbol::GetToStringTag(Isolate* isolate) { + return GetWellKnownSymbol(isolate, "Symbol.toStringTag"); +} + + Local v8::Private::New(Isolate* isolate, Local name) { i::Isolate* i_isolate = reinterpret_cast(isolate); LOG_API(i_isolate, "Private::New()"); @@ -6267,7 +6293,6 @@ Local v8::Private::ForApi(Isolate* isolate, Local name) { Local v8::Number::New(Isolate* isolate, double value) { i::Isolate* internal_isolate = reinterpret_cast(isolate); - DCHECK(internal_isolate->IsInitialized()); if (std::isnan(value)) { // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. value = base::OS::nan_value(); @@ -6280,7 +6305,6 @@ Local v8::Number::New(Isolate* isolate, double value) { Local v8::Integer::New(Isolate* isolate, int32_t value) { i::Isolate* internal_isolate = reinterpret_cast(isolate); - DCHECK(internal_isolate->IsInitialized()); if (i::Smi::IsValid(value)) { return Utils::IntegerToLocal(i::Handle(i::Smi::FromInt(value), internal_isolate)); @@ -6293,7 +6317,6 @@ Local v8::Integer::New(Isolate* isolate, int32_t value) { Local v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) { i::Isolate* internal_isolate = reinterpret_cast(isolate); - DCHECK(internal_isolate->IsInitialized()); bool fits_into_int32_t = (value & (1 << 31)) == 0; if (fits_into_int32_t) { return Integer::New(isolate, static_cast(value)); @@ -6304,57 +6327,6 @@ Local v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) { } -bool V8::AddMessageListener(MessageCallback that, Handle data) { - i::Isolate* isolate = i::Isolate::Current(); - ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false); - ENTER_V8(isolate); - i::HandleScope scope(isolate); - NeanderArray listeners(isolate->factory()->message_listeners()); - NeanderObject obj(isolate, 2); - obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that))); - obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value() - : *Utils::OpenHandle(*data)); - listeners.add(obj.value()); - return true; -} - - -void V8::RemoveMessageListeners(MessageCallback that) { - i::Isolate* isolate = i::Isolate::Current(); - ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return); - ENTER_V8(isolate); - i::HandleScope scope(isolate); - NeanderArray listeners(isolate->factory()->message_listeners()); - for (int i = 0; i < listeners.length(); i++) { - if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones - - NeanderObject listener(i::JSObject::cast(listeners.get(i))); - i::Handle callback_obj(i::Foreign::cast(listener.get(0))); - if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) { - listeners.set(i, isolate->heap()->undefined_value()); - } - } -} - - -void V8::SetCaptureStackTraceForUncaughtExceptions( - bool capture, - int frame_limit, - StackTrace::StackTraceOptions options) { - i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions( - capture, - frame_limit, - options); -} - - -void V8::SetFailedAccessCheckCallbackFunction( - FailedAccessCheckCallback callback) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->SetFailedAccessCheckCallback(callback); -} - - void Isolate::CollectAllGarbage(const char* gc_reason) { reinterpret_cast(this)->heap()->CollectAllGarbage( i::Heap::kNoGCFlags, gc_reason); @@ -6484,13 +6456,6 @@ void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) { } -void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->heap()->RemoveGCPrologueCallback( - reinterpret_cast(callback)); -} - - void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) { i::Isolate* isolate = i::Isolate::Current(); isolate->heap()->AddGCEpilogueCallback( @@ -6500,62 +6465,55 @@ void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) { } -void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->heap()->RemoveGCEpilogueCallback( - reinterpret_cast(callback)); -} - - -void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback, - ObjectSpace space, - AllocationAction action) { - i::Isolate* isolate = i::Isolate::Current(); +void Isolate::AddMemoryAllocationCallback(MemoryAllocationCallback callback, + ObjectSpace space, + AllocationAction action) { + i::Isolate* isolate = reinterpret_cast(this); isolate->memory_allocator()->AddMemoryAllocationCallback( callback, space, action); } -void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) { - i::Isolate* isolate = i::Isolate::Current(); +void Isolate::RemoveMemoryAllocationCallback( + MemoryAllocationCallback callback) { + i::Isolate* isolate = reinterpret_cast(this); isolate->memory_allocator()->RemoveMemoryAllocationCallback( callback); } -void V8::TerminateExecution(Isolate* isolate) { - i::Isolate* i_isolate = reinterpret_cast(isolate); - i_isolate->stack_guard()->RequestTerminateExecution(); +void Isolate::TerminateExecution() { + i::Isolate* isolate = reinterpret_cast(this); + isolate->stack_guard()->RequestTerminateExecution(); } -bool V8::IsExecutionTerminating(Isolate* isolate) { - i::Isolate* i_isolate = isolate != NULL ? - reinterpret_cast(isolate) : i::Isolate::Current(); - return IsExecutionTerminatingCheck(i_isolate); +bool Isolate::IsExecutionTerminating() { + i::Isolate* isolate = reinterpret_cast(this); + return IsExecutionTerminatingCheck(isolate); } -void V8::CancelTerminateExecution(Isolate* isolate) { - i::Isolate* i_isolate = reinterpret_cast(isolate); - i_isolate->stack_guard()->ClearTerminateExecution(); - i_isolate->CancelTerminateExecution(); +void Isolate::CancelTerminateExecution() { + i::Isolate* isolate = reinterpret_cast(this); + isolate->stack_guard()->ClearTerminateExecution(); + isolate->CancelTerminateExecution(); } void Isolate::RequestInterrupt(InterruptCallback callback, void* data) { - i::Isolate* i_isolate = reinterpret_cast(this); - i_isolate->set_api_interrupt_callback(callback); - i_isolate->set_api_interrupt_callback_data(data); - i_isolate->stack_guard()->RequestApiInterrupt(); + i::Isolate* isolate = reinterpret_cast(this); + isolate->set_api_interrupt_callback(callback); + isolate->set_api_interrupt_callback_data(data); + isolate->stack_guard()->RequestApiInterrupt(); } void Isolate::ClearInterrupt() { - i::Isolate* i_isolate = reinterpret_cast(this); - i_isolate->stack_guard()->ClearApiInterrupt(); - i_isolate->set_api_interrupt_callback(NULL); - i_isolate->set_api_interrupt_callback_data(NULL); + i::Isolate* isolate = reinterpret_cast(this); + isolate->stack_guard()->ClearApiInterrupt(); + isolate->set_api_interrupt_callback(NULL); + isolate->set_api_interrupt_callback_data(NULL); } @@ -6581,7 +6539,7 @@ Isolate* Isolate::GetCurrent() { Isolate* Isolate::New(const Isolate::CreateParams& params) { - i::Isolate* isolate = new i::Isolate(); + i::Isolate* isolate = new i::Isolate(params.enable_serializer); Isolate* v8_isolate = reinterpret_cast(isolate); if (params.entry_hook) { isolate->set_function_entry_hook(params.entry_hook); @@ -6592,9 +6550,6 @@ Isolate* Isolate::New(const Isolate::CreateParams& params) { params.code_event_handler); } SetResourceConstraints(isolate, params.constraints); - if (params.enable_serializer) { - isolate->enable_serializer(); - } // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this. Isolate::Scope isolate_scope(v8_isolate); if (params.entry_hook || !i::Snapshot::Initialize(isolate)) { @@ -6684,14 +6639,6 @@ Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() { void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) { i::Isolate* isolate = reinterpret_cast(this); - if (!isolate->IsInitialized()) { - heap_statistics->total_heap_size_ = 0; - heap_statistics->total_heap_size_executable_ = 0; - heap_statistics->total_physical_size_ = 0; - heap_statistics->used_heap_size_ = 0; - heap_statistics->heap_size_limit_ = 0; - return; - } i::Heap* heap = isolate->heap(); heap_statistics->total_heap_size_ = heap->CommittedMemory(); heap_statistics->total_heap_size_executable_ = @@ -6702,9 +6649,17 @@ void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) { } +void Isolate::GetStackSample(const RegisterState& state, void** frames, + size_t frames_limit, SampleInfo* sample_info) { + i::Isolate* isolate = reinterpret_cast(this); + i::TickSample::GetStackSample(isolate, state, i::TickSample::kSkipCEntryFrame, + frames, frames_limit, sample_info); +} + + void Isolate::SetEventLogger(LogEventCallback that) { // Do not overwrite the event logger if we want to log explicitly. - if (i::FLAG_log_timer_events) return; + if (i::FLAG_log_internal_timer_events) return; i::Isolate* isolate = reinterpret_cast(this); isolate->set_event_logger(that); } @@ -6723,6 +6678,13 @@ void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) { } +void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) { + if (callback == NULL) return; + i::Isolate* isolate = reinterpret_cast(this); + isolate->SetPromiseRejectCallback(callback); +} + + void Isolate::RunMicrotasks() { reinterpret_cast(this)->RunMicrotasks(); } @@ -6785,7 +6747,7 @@ void Isolate::SetAddHistogramSampleFunction( } -bool v8::Isolate::IdleNotification(int idle_time_in_ms) { +bool Isolate::IdleNotification(int idle_time_in_ms) { // Returning true tells the caller that it need not // continue to call IdleNotification. i::Isolate* isolate = reinterpret_cast(this); @@ -6794,7 +6756,7 @@ bool v8::Isolate::IdleNotification(int idle_time_in_ms) { } -void v8::Isolate::LowMemoryNotification() { +void Isolate::LowMemoryNotification() { i::Isolate* isolate = reinterpret_cast(this); { i::HistogramTimerScope idle_notification_scope( @@ -6804,14 +6766,14 @@ void v8::Isolate::LowMemoryNotification() { } -int v8::Isolate::ContextDisposedNotification() { +int Isolate::ContextDisposedNotification() { i::Isolate* isolate = reinterpret_cast(this); return isolate->heap()->NotifyContextDisposed(); } -void v8::Isolate::SetJitCodeEventHandler(JitCodeEventOptions options, - JitCodeEventHandler event_handler) { +void Isolate::SetJitCodeEventHandler(JitCodeEventOptions options, + JitCodeEventHandler event_handler) { i::Isolate* isolate = reinterpret_cast(this); // Ensure that logging is initialized for our isolate. isolate->InitializeLoggingAndCounters(); @@ -6819,14 +6781,14 @@ void v8::Isolate::SetJitCodeEventHandler(JitCodeEventOptions options, } -void v8::Isolate::SetStackLimit(uintptr_t stack_limit) { +void Isolate::SetStackLimit(uintptr_t stack_limit) { i::Isolate* isolate = reinterpret_cast(this); CHECK(stack_limit); isolate->stack_guard()->SetStackLimit(stack_limit); } -void v8::Isolate::GetCodeRange(void** start, size_t* length_in_bytes) { +void Isolate::GetCodeRange(void** start, size_t* length_in_bytes) { i::Isolate* isolate = reinterpret_cast(this); if (isolate->code_range()->valid()) { *start = isolate->code_range()->start(); @@ -6838,6 +6800,115 @@ void v8::Isolate::GetCodeRange(void** start, size_t* length_in_bytes) { } +void Isolate::SetFatalErrorHandler(FatalErrorCallback that) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->set_exception_behavior(that); +} + + +void Isolate::SetAllowCodeGenerationFromStringsCallback( + AllowCodeGenerationFromStringsCallback callback) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->set_allow_code_gen_callback(callback); +} + + +bool Isolate::IsDead() { + i::Isolate* isolate = reinterpret_cast(this); + return isolate->IsDead(); +} + + +bool Isolate::AddMessageListener(MessageCallback that, Handle data) { + i::Isolate* isolate = reinterpret_cast(this); + ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false); + ENTER_V8(isolate); + i::HandleScope scope(isolate); + NeanderArray listeners(isolate->factory()->message_listeners()); + NeanderObject obj(isolate, 2); + obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that))); + obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value() + : *Utils::OpenHandle(*data)); + listeners.add(isolate, obj.value()); + return true; +} + + +void Isolate::RemoveMessageListeners(MessageCallback that) { + i::Isolate* isolate = reinterpret_cast(this); + ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return); + ENTER_V8(isolate); + i::HandleScope scope(isolate); + NeanderArray listeners(isolate->factory()->message_listeners()); + for (int i = 0; i < listeners.length(); i++) { + if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones + + NeanderObject listener(i::JSObject::cast(listeners.get(i))); + i::Handle callback_obj(i::Foreign::cast(listener.get(0))); + if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) { + listeners.set(i, isolate->heap()->undefined_value()); + } + } +} + + +void Isolate::SetFailedAccessCheckCallbackFunction( + FailedAccessCheckCallback callback) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->SetFailedAccessCheckCallback(callback); +} + + +void Isolate::SetCaptureStackTraceForUncaughtExceptions( + bool capture, int frame_limit, StackTrace::StackTraceOptions options) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->SetCaptureStackTraceForUncaughtExceptions(capture, frame_limit, + options); +} + + +void Isolate::VisitExternalResources(ExternalResourceVisitor* visitor) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->heap()->VisitExternalResources(visitor); +} + + +class VisitorAdapter : public i::ObjectVisitor { + public: + explicit VisitorAdapter(PersistentHandleVisitor* visitor) + : visitor_(visitor) {} + virtual void VisitPointers(i::Object** start, i::Object** end) { + UNREACHABLE(); + } + virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) { + Value* value = ToApi(i::Handle(p)); + visitor_->VisitPersistentHandle( + reinterpret_cast*>(&value), class_id); + } + + private: + PersistentHandleVisitor* visitor_; +}; + + +void Isolate::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) { + i::Isolate* isolate = reinterpret_cast(this); + i::DisallowHeapAllocation no_allocation; + VisitorAdapter visitor_adapter(visitor); + isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter); +} + + +void Isolate::VisitHandlesForPartialDependence( + PersistentHandleVisitor* visitor) { + i::Isolate* isolate = reinterpret_cast(this); + i::DisallowHeapAllocation no_allocation; + VisitorAdapter visitor_adapter(visitor); + isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds( + &visitor_adapter); +} + + String::Utf8Value::Utf8Value(v8::Handle obj) : str_(NULL), length_(0) { i::Isolate* isolate = i::Isolate::Current(); @@ -6845,7 +6916,7 @@ String::Utf8Value::Utf8Value(v8::Handle obj) ENTER_V8(isolate); i::HandleScope scope(isolate); TryCatch try_catch; - Handle str = obj->ToString(); + Handle str = obj->ToString(reinterpret_cast(isolate)); if (str.IsEmpty()) return; i::Handle i_str = Utils::OpenHandle(*str); length_ = v8::Utf8Length(*i_str, isolate); @@ -6866,7 +6937,7 @@ String::Value::Value(v8::Handle obj) ENTER_V8(isolate); i::HandleScope scope(isolate); TryCatch try_catch; - Handle str = obj->ToString(); + Handle str = obj->ToString(reinterpret_cast(isolate)); if (str.IsEmpty()) return; length_ = str->Length(); str_ = i::NewArray(length_ + 1); @@ -6912,6 +6983,27 @@ DEFINE_ERROR(Error) #undef DEFINE_ERROR +Local Exception::GetMessage(Handle exception) { + i::Handle obj = Utils::OpenHandle(*exception); + if (!obj->IsHeapObject()) return Local(); + i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); + ENTER_V8(isolate); + i::HandleScope scope(isolate); + return Utils::MessageToLocal( + scope.CloseAndEscape(isolate->CreateMessage(obj, NULL))); +} + + +Local Exception::GetStackTrace(Handle exception) { + i::Handle obj = Utils::OpenHandle(*exception); + if (!obj->IsJSObject()) return Local(); + i::Handle js_obj = i::Handle::cast(obj); + i::Isolate* isolate = js_obj->GetIsolate(); + ENTER_V8(isolate); + return Utils::StackTraceToLocal(isolate->GetDetailedStackTrace(js_obj)); +} + + // --- D e b u g S u p p o r t --- bool Debug::SetDebugEventListener(EventCallback that, Handle data) { @@ -6972,7 +7064,6 @@ void Debug::SendCommand(Isolate* isolate, Local Debug::Call(v8::Handle fun, v8::Handle data) { i::Isolate* isolate = i::Isolate::Current(); - if (!isolate->IsInitialized()) return Local(); ON_BAILOUT(isolate, "v8::Debug::Call()", return Local()); ENTER_V8(isolate); i::MaybeHandle maybe_result; @@ -6993,7 +7084,6 @@ Local Debug::Call(v8::Handle fun, Local Debug::GetMirror(v8::Handle obj) { i::Isolate* isolate = i::Isolate::Current(); - if (!isolate->IsInitialized()) return Local(); ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local()); ENTER_V8(isolate); v8::EscapableHandleScope scope(reinterpret_cast(isolate)); @@ -7082,6 +7172,19 @@ int CpuProfileNode::GetColumnNumber() const { } +unsigned int CpuProfileNode::GetHitLineCount() const { + const i::ProfileNode* node = reinterpret_cast(this); + return node->GetHitLineCount(); +} + + +bool CpuProfileNode::GetLineTicks(LineTick* entries, + unsigned int length) const { + const i::ProfileNode* node = reinterpret_cast(this); + return node->GetLineTicks(entries, length); +} + + const char* CpuProfileNode::GetBailoutReason() const { const i::ProfileNode* node = reinterpret_cast(this); return node->entry()->bailout_reason(); @@ -7199,13 +7302,13 @@ const CpuProfile* CpuProfiler::StopCpuProfiling(Handle title) { void CpuProfiler::SetIdle(bool is_idle) { i::Isolate* isolate = reinterpret_cast(this)->isolate(); - i::StateTag state = isolate->current_vm_state(); - DCHECK(state == i::EXTERNAL || state == i::IDLE); + v8::StateTag state = isolate->current_vm_state(); + DCHECK(state == v8::EXTERNAL || state == v8::IDLE); if (isolate->js_entry_sp() != NULL) return; if (is_idle) { - isolate->set_current_vm_state(i::IDLE); - } else if (state == i::IDLE) { - isolate->set_current_vm_state(i::EXTERNAL); + isolate->set_current_vm_state(v8::IDLE); + } else if (state == v8::IDLE) { + isolate->set_current_vm_state(v8::EXTERNAL); } } diff --git a/deps/v8/src/api.h b/deps/v8/src/api.h index 9aed5dd4e9..1d2a8c8e82 100644 --- a/deps/v8/src/api.h +++ b/deps/v8/src/api.h @@ -54,7 +54,8 @@ class NeanderArray { return obj_.value(); } - void add(v8::internal::Handle value); + void add(internal::Isolate* isolate, + v8::internal::Handle value); int length(); @@ -232,6 +233,8 @@ class Utils { static inline Local MessageToLocal( v8::internal::Handle obj); + static inline Local PromiseToLocal( + v8::internal::Handle obj); static inline Local StackTraceToLocal( v8::internal::Handle obj); static inline Local StackFrameToLocal( @@ -355,6 +358,7 @@ MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature) MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature) MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch) MAKE_TO_LOCAL(MessageToLocal, Object, Message) +MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise) MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace) MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame) MAKE_TO_LOCAL(NumberToLocal, Object, Number) diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc index 96f28f9683..eae38be6eb 100644 --- a/deps/v8/src/arm/assembler-arm.cc +++ b/deps/v8/src/arm/assembler-arm.cc @@ -109,6 +109,9 @@ void CpuFeatures::ProbeImpl(bool cross_compile) { if (cpu.architecture() >= 7) { if (FLAG_enable_armv7) supported_ |= 1u << ARMv7; + if (FLAG_enable_armv8 && cpu.architecture() >= 8) { + supported_ |= 1u << ARMv8; + } if (FLAG_enable_unaligned_accesses) supported_ |= 1u << UNALIGNED_ACCESSES; // Use movw/movt for QUALCOMM ARMv7 cores. if (FLAG_enable_movw_movt && cpu.implementer() == base::CPU::QUALCOMM) { @@ -472,7 +475,6 @@ Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) first_const_pool_32_use_ = -1; first_const_pool_64_use_ = -1; last_bound_pos_ = 0; - constant_pool_available_ = !FLAG_enable_ool_constant_pool; ClearRecordedAstId(); } @@ -1056,7 +1058,8 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const { static bool use_mov_immediate_load(const Operand& x, const Assembler* assembler) { - if (assembler != NULL && !assembler->is_constant_pool_available()) { + if (FLAG_enable_ool_constant_pool && assembler != NULL && + !assembler->is_ool_constant_pool_available()) { return true; } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && (assembler == NULL || !assembler->predictable_code_size())) { @@ -1137,7 +1140,7 @@ void Assembler::move_32_bit_immediate(Register rd, mov(rd, target, LeaveCC, cond); } } else { - DCHECK(is_constant_pool_available()); + DCHECK(!FLAG_enable_ool_constant_pool || is_ool_constant_pool_available()); ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo); if (section == ConstantPoolArray::EXTENDED_SECTION) { DCHECK(FLAG_enable_ool_constant_pool); @@ -1571,11 +1574,27 @@ void Assembler::udiv(Register dst, Register src1, Register src2, } -void Assembler::mul(Register dst, Register src1, Register src2, - SBit s, Condition cond) { +void Assembler::mul(Register dst, Register src1, Register src2, SBit s, + Condition cond) { DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); // dst goes in bits 16-19 for this instruction! - emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); + emit(cond | s | dst.code() * B16 | src2.code() * B8 | B7 | B4 | src1.code()); +} + + +void Assembler::smmla(Register dst, Register src1, Register src2, Register srcA, + Condition cond) { + DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); + emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | + srcA.code() * B12 | src2.code() * B8 | B4 | src1.code()); +} + + +void Assembler::smmul(Register dst, Register src1, Register src2, + Condition cond) { + DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); + emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | 0xf * B12 | + src2.code() * B8 | B4 | src1.code()); } @@ -2492,7 +2511,7 @@ void Assembler::vmov(const DwVfpRegister dst, int vd, d; dst.split_code(&vd, &d); emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); - } else if (FLAG_enable_vldr_imm && is_constant_pool_available()) { + } else if (FLAG_enable_vldr_imm && is_ool_constant_pool_available()) { // TODO(jfb) Temporarily turned off until we have constant blinding or // some equivalent mitigation: an attacker can otherwise control // generated data which also happens to be executable, a Very Bad @@ -2526,27 +2545,20 @@ void Assembler::vmov(const DwVfpRegister dst, uint32_t lo, hi; DoubleAsTwoUInt32(imm, &lo, &hi); - if (scratch.is(no_reg)) { - if (dst.code() < 16) { - const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); - // Move the low part of the double into the lower of the corresponsing S - // registers of D register dst. - mov(ip, Operand(lo)); - vmov(loc.low(), ip); - - // Move the high part of the double into the higher of the - // corresponsing S registers of D register dst. - mov(ip, Operand(hi)); - vmov(loc.high(), ip); + if (lo == hi) { + // Move the low and high parts of the double to a D register in one + // instruction. + mov(ip, Operand(lo)); + vmov(dst, ip, ip); + } else if (scratch.is(no_reg)) { + mov(ip, Operand(lo)); + vmov(dst, VmovIndexLo, ip); + if ((lo & 0xffff) == (hi & 0xffff)) { + movt(ip, hi >> 16); } else { - // D16-D31 does not have S registers, so move the low and high parts - // directly to the D register using vmov.32. - // Note: This may be slower, so we only do this when we have to. - mov(ip, Operand(lo)); - vmov(dst, VmovIndexLo, ip); mov(ip, Operand(hi)); - vmov(dst, VmovIndexHi, ip); } + vmov(dst, VmovIndexHi, ip); } else { // Move the low and high parts of the double to a D register in one // instruction. @@ -3075,6 +3087,76 @@ void Assembler::vsqrt(const DwVfpRegister dst, } +void Assembler::vrinta(const DwVfpRegister dst, const DwVfpRegister src) { + // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | + // 10(19-18) | RM=00(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | + // M(5) | 0(4) | Vm(3-0) + DCHECK(CpuFeatures::IsSupported(ARMv8)); + int vd, d; + dst.split_code(&vd, &d); + int vm, m; + src.split_code(&vm, &m); + emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 | + 0x5 * B9 | B8 | B6 | m * B5 | vm); +} + + +void Assembler::vrintn(const DwVfpRegister dst, const DwVfpRegister src) { + // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | + // 10(19-18) | RM=01(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | + // M(5) | 0(4) | Vm(3-0) + DCHECK(CpuFeatures::IsSupported(ARMv8)); + int vd, d; + dst.split_code(&vd, &d); + int vm, m; + src.split_code(&vm, &m); + emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 | + vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm); +} + + +void Assembler::vrintp(const DwVfpRegister dst, const DwVfpRegister src) { + // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | + // 10(19-18) | RM=10(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | + // M(5) | 0(4) | Vm(3-0) + DCHECK(CpuFeatures::IsSupported(ARMv8)); + int vd, d; + dst.split_code(&vd, &d); + int vm, m; + src.split_code(&vm, &m); + emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 | + vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm); +} + + +void Assembler::vrintm(const DwVfpRegister dst, const DwVfpRegister src) { + // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | + // 10(19-18) | RM=11(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | + // M(5) | 0(4) | Vm(3-0) + DCHECK(CpuFeatures::IsSupported(ARMv8)); + int vd, d; + dst.split_code(&vd, &d); + int vm, m; + src.split_code(&vm, &m); + emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 | + vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm); +} + + +void Assembler::vrintz(const DwVfpRegister dst, const DwVfpRegister src, + const Condition cond) { + // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) | + // Vd(15-12) | 101(11-9) | sz=1(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) + DCHECK(CpuFeatures::IsSupported(ARMv8)); + int vd, d; + dst.split_code(&vd, &d); + int vm, m; + src.split_code(&vm, &m); + emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 | + 0x5 * B9 | B8 | B7 | B6 | m * B5 | vm); +} + + // Support for NEON. void Assembler::vld1(NeonSize size, diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index e8ee605988..9087fab56a 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -975,6 +975,11 @@ class Assembler : public AssemblerBase { void mul(Register dst, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al); + void smmla(Register dst, Register src1, Register src2, Register srcA, + Condition cond = al); + + void smmul(Register dst, Register src1, Register src2, Condition cond = al); + void smlal(Register dstL, Register dstH, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al); @@ -1274,6 +1279,14 @@ class Assembler : public AssemblerBase { const DwVfpRegister src, const Condition cond = al); + // ARMv8 rounding instructions. + void vrinta(const DwVfpRegister dst, const DwVfpRegister src); + void vrintn(const DwVfpRegister dst, const DwVfpRegister src); + void vrintm(const DwVfpRegister dst, const DwVfpRegister src); + void vrintp(const DwVfpRegister dst, const DwVfpRegister src); + void vrintz(const DwVfpRegister dst, const DwVfpRegister src, + const Condition cond = al); + // Support for NEON. // All these APIs support D0 to D31 and Q0 to Q15. @@ -1488,8 +1501,6 @@ class Assembler : public AssemblerBase { // Generate the constant pool for the generated code. void PopulateConstantPool(ConstantPoolArray* constant_pool); - bool is_constant_pool_available() const { return constant_pool_available_; } - bool use_extended_constant_pool() const { return constant_pool_builder_.current_section() == ConstantPoolArray::EXTENDED_SECTION; @@ -1549,10 +1560,6 @@ class Assembler : public AssemblerBase { (pc_offset() < no_const_pool_before_); } - void set_constant_pool_available(bool available) { - constant_pool_available_ = available; - } - private: int next_buffer_check_; // pc offset of next buffer check @@ -1615,10 +1622,6 @@ class Assembler : public AssemblerBase { // The bound position, before this we cannot do instruction elimination. int last_bound_pos_; - // Indicates whether the constant pool can be accessed, which is only possible - // if the pp register points to the current code object's constant pool. - bool constant_pool_available_; - // Code emission inline void CheckBuffer(); void GrowBuffer(); @@ -1654,9 +1657,6 @@ class Assembler : public AssemblerBase { friend class RelocInfo; friend class CodePatcher; friend class BlockConstPoolScope; - friend class FrameAndConstantPoolScope; - friend class ConstantPoolUnavailableScope; - PositionsRecorder positions_recorder_; friend class PositionsRecorder; friend class EnsureSpace; diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index be0532efd9..a0e7e4a33e 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -1441,7 +1441,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ b(ne, &slow); // Null is not instance of anything. - __ cmp(scratch, Operand(isolate()->factory()->null_value())); + __ cmp(object, Operand(isolate()->factory()->null_value())); __ b(ne, &object_not_null); if (ReturnTrueFalseObject()) { __ Move(r0, factory->false_value()); @@ -1503,6 +1503,34 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) { } +void LoadIndexedStringStub::Generate(MacroAssembler* masm) { + // Return address is in lr. + Label miss; + + Register receiver = LoadDescriptor::ReceiverRegister(); + Register index = LoadDescriptor::NameRegister(); + Register scratch = r3; + Register result = r0; + DCHECK(!scratch.is(receiver) && !scratch.is(index)); + + StringCharAtGenerator char_at_generator(receiver, index, scratch, result, + &miss, // When not a string. + &miss, // When not a number. + &miss, // When index out of range. + STRING_INDEX_IS_ARRAY_INDEX, + RECEIVER_IS_STRING); + char_at_generator.GenerateFast(masm); + __ Ret(); + + StubRuntimeCallHelper call_helper; + char_at_generator.GenerateSlow(masm, call_helper); + + __ bind(&miss); + PropertyAccessCompiler::TailCallBuiltin( + masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); +} + + void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { // The displacement is the offset of the last parameter (if any) // relative to the frame pointer. @@ -2376,13 +2404,13 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { // A monomorphic miss (i.e, here the cache is not uninitialized) goes // megamorphic. - __ CompareRoot(r4, Heap::kUninitializedSymbolRootIndex); + __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex); __ b(eq, &initialize); // MegamorphicSentinel is an immortal immovable object (undefined) so no // write-barrier is needed. __ bind(&megamorphic); __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); - __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); + __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); __ jmp(&done); @@ -2698,9 +2726,9 @@ void CallICStub::Generate(MacroAssembler* masm) { __ bind(&extra_checks_or_miss); Label miss; - __ CompareRoot(r4, Heap::kMegamorphicSymbolRootIndex); + __ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex); __ b(eq, &slow_start); - __ CompareRoot(r4, Heap::kUninitializedSymbolRootIndex); + __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex); __ b(eq, &miss); if (!FLAG_trace_ic) { @@ -2710,8 +2738,19 @@ void CallICStub::Generate(MacroAssembler* masm) { __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); __ b(ne, &miss); __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); - __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); + __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); + // We have to update statistics for runtime profiling. + const int with_types_offset = + FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); + __ ldr(r4, FieldMemOperand(r2, with_types_offset)); + __ sub(r4, r4, Operand(Smi::FromInt(1))); + __ str(r4, FieldMemOperand(r2, with_types_offset)); + const int generic_offset = + FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); + __ ldr(r4, FieldMemOperand(r2, generic_offset)); + __ add(r4, r4, Operand(Smi::FromInt(1))); + __ str(r4, FieldMemOperand(r2, generic_offset)); __ jmp(&slow_start); } @@ -2759,14 +2798,16 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { // StringCharCodeAtGenerator void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { // If the receiver is a smi trigger the non-string case. - __ JumpIfSmi(object_, receiver_not_string_); + if (check_mode_ == RECEIVER_IS_UNKNOWN) { + __ JumpIfSmi(object_, receiver_not_string_); - // Fetch the instance type of the receiver into result register. - __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); - __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); - // If the receiver is not a string trigger the non-string case. - __ tst(result_, Operand(kIsNotStringMask)); - __ b(ne, receiver_not_string_); + // Fetch the instance type of the receiver into result register. + __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); + __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); + // If the receiver is not a string trigger the non-string case. + __ tst(result_, Operand(kIsNotStringMask)); + __ b(ne, receiver_not_string_); + } // If the index is non-smi trigger the non-smi case. __ JumpIfNotSmi(index_, &index_not_smi_); @@ -3137,8 +3178,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { // r2: length // r3: from index (untagged) __ SmiTag(r3, r3); - StringCharAtGenerator generator( - r0, r3, r2, r0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); + StringCharAtGenerator generator(r0, r3, r2, r0, &runtime, &runtime, &runtime, + STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); generator.GenerateFast(masm); __ Drop(3); __ Ret(); @@ -3146,6 +3187,24 @@ void SubStringStub::Generate(MacroAssembler* masm) { } +void ToNumberStub::Generate(MacroAssembler* masm) { + // The ToNumber stub takes one argument in r0. + Label check_heap_number, call_builtin; + __ JumpIfNotSmi(r0, &check_heap_number); + __ Ret(); + + __ bind(&check_heap_number); + __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); + __ CompareRoot(r1, Heap::kHeapNumberMapRootIndex); + __ b(ne, &call_builtin); + __ Ret(); + + __ bind(&call_builtin); + __ push(r0); + __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); +} + + void StringHelper::GenerateFlatOneByteStringEquals( MacroAssembler* masm, Register left, Register right, Register scratch1, Register scratch2, Register scratch3) { diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index d050399532..b577f5921f 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -604,8 +604,22 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( __ add(src_elements, elements, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4)); __ add(dst_elements, array, Operand(FixedArray::kHeaderSize)); - __ add(array, array, Operand(kHeapObjectTag)); __ add(dst_end, dst_elements, Operand(length, LSL, 1)); + + // Allocating heap numbers in the loop below can fail and cause a jump to + // gc_required. We can't leave a partly initialized FixedArray behind, + // so pessimistically fill it with holes now. + Label initialization_loop, initialization_loop_entry; + __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); + __ b(&initialization_loop_entry); + __ bind(&initialization_loop); + __ str(scratch, MemOperand(dst_elements, kPointerSize, PostIndex)); + __ bind(&initialization_loop_entry); + __ cmp(dst_elements, dst_end); + __ b(lt, &initialization_loop); + + __ add(dst_elements, array, Operand(FixedArray::kHeaderSize)); + __ add(array, array, Operand(kHeapObjectTag)); __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); // Using offsetted addresses in src_elements to fully take advantage of // post-indexing. diff --git a/deps/v8/src/arm/constants-arm.h b/deps/v8/src/arm/constants-arm.h index 375ef89774..2a293b3d13 100644 --- a/deps/v8/src/arm/constants-arm.h +++ b/deps/v8/src/arm/constants-arm.h @@ -161,26 +161,26 @@ enum MiscInstructionsBits74 { // Instruction encoding bits and masks. enum { - H = 1 << 5, // Halfword (or byte). - S6 = 1 << 6, // Signed (or unsigned). - L = 1 << 20, // Load (or store). - S = 1 << 20, // Set condition code (or leave unchanged). - W = 1 << 21, // Writeback base register (or leave unchanged). - A = 1 << 21, // Accumulate in multiply instruction (or not). - B = 1 << 22, // Unsigned byte (or word). - N = 1 << 22, // Long (or short). - U = 1 << 23, // Positive (or negative) offset/index. - P = 1 << 24, // Offset/pre-indexed addressing (or post-indexed addressing). - I = 1 << 25, // Immediate shifter operand (or not). - - B4 = 1 << 4, - B5 = 1 << 5, - B6 = 1 << 6, - B7 = 1 << 7, - B8 = 1 << 8, - B9 = 1 << 9, + H = 1 << 5, // Halfword (or byte). + S6 = 1 << 6, // Signed (or unsigned). + L = 1 << 20, // Load (or store). + S = 1 << 20, // Set condition code (or leave unchanged). + W = 1 << 21, // Writeback base register (or leave unchanged). + A = 1 << 21, // Accumulate in multiply instruction (or not). + B = 1 << 22, // Unsigned byte (or word). + N = 1 << 22, // Long (or short). + U = 1 << 23, // Positive (or negative) offset/index. + P = 1 << 24, // Offset/pre-indexed addressing (or post-indexed addressing). + I = 1 << 25, // Immediate shifter operand (or not). + B4 = 1 << 4, + B5 = 1 << 5, + B6 = 1 << 6, + B7 = 1 << 7, + B8 = 1 << 8, + B9 = 1 << 9, B12 = 1 << 12, B16 = 1 << 16, + B17 = 1 << 17, B18 = 1 << 18, B19 = 1 << 19, B20 = 1 << 20, @@ -194,16 +194,16 @@ enum { B28 = 1 << 28, // Instruction bit masks. - kCondMask = 15 << 28, - kALUMask = 0x6f << 21, - kRdMask = 15 << 12, // In str instruction. + kCondMask = 15 << 28, + kALUMask = 0x6f << 21, + kRdMask = 15 << 12, // In str instruction. kCoprocessorMask = 15 << 8, kOpCodeMask = 15 << 21, // In data-processing instructions. - kImm24Mask = (1 << 24) - 1, - kImm16Mask = (1 << 16) - 1, - kImm8Mask = (1 << 8) - 1, - kOff12Mask = (1 << 12) - 1, - kOff8Mask = (1 << 8) - 1 + kImm24Mask = (1 << 24) - 1, + kImm16Mask = (1 << 16) - 1, + kImm8Mask = (1 << 8) - 1, + kOff12Mask = (1 << 12) - 1, + kOff8Mask = (1 << 8) - 1 }; diff --git a/deps/v8/src/arm/debug-arm.cc b/deps/v8/src/arm/debug-arm.cc index 6d7d6b8ace..c9100576d2 100644 --- a/deps/v8/src/arm/debug-arm.cc +++ b/deps/v8/src/arm/debug-arm.cc @@ -178,7 +178,11 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) { // Calling convention for IC load (from ic-arm.cc). Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0); + RegList regs = receiver.bit() | name.bit(); + if (FLAG_vector_ics) { + regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit(); + } + Generate_DebugBreakCallHelper(masm, regs, 0); } diff --git a/deps/v8/src/arm/disasm-arm.cc b/deps/v8/src/arm/disasm-arm.cc index 85977b186e..dc26018974 100644 --- a/deps/v8/src/arm/disasm-arm.cc +++ b/deps/v8/src/arm/disasm-arm.cc @@ -148,7 +148,7 @@ void Decoder::Print(const char* str) { // These condition names are defined in a way to match the native disassembler // formatting. See for example the command "objdump -d ". -static const char* cond_names[kNumberOfConditions] = { +static const char* const cond_names[kNumberOfConditions] = { "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", }; @@ -1096,6 +1096,17 @@ void Decoder::DecodeType3(Instruction* instr) { break; } case db_x: { + if (instr->Bits(22, 20) == 0x5) { + if (instr->Bits(7, 4) == 0x1) { + if (instr->Bits(15, 12) == 0xF) { + Format(instr, "smmul'cond 'rn, 'rm, 'rs"); + } else { + // SMMLA (in V8 notation matching ARM ISA format) + Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd"); + } + break; + } + } if (FLAG_enable_sudiv) { if (instr->Bits(5, 4) == 0x1) { if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { @@ -1266,6 +1277,14 @@ void Decoder::DecodeTypeVFP(Instruction* instr) { } else { Unknown(instr); // Not used by V8. } + } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) { + bool dp_operation = (instr->SzValue() == 1); + // vrintz - round towards zero (truncate) + if (dp_operation) { + Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm"); + } else { + Unknown(instr); // Not used by V8. + } } else { Unknown(instr); // Not used by V8. } @@ -1616,6 +1635,50 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { Unknown(instr); } break; + case 0x1D: + if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 && + instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 && + instr->Bit(4) == 0x0) { + // VRINTA, VRINTN, VRINTP, VRINTM (floating-point) + bool dp_operation = (instr->SzValue() == 1); + int rounding_mode = instr->Bits(17, 16); + switch (rounding_mode) { + case 0x0: + if (dp_operation) { + Format(instr, "vrinta.f64.f64 'Dd, 'Dm"); + } else { + Unknown(instr); + } + break; + case 0x1: + if (dp_operation) { + Format(instr, "vrintn.f64.f64 'Dd, 'Dm"); + } else { + Unknown(instr); + } + break; + case 0x2: + if (dp_operation) { + Format(instr, "vrintp.f64.f64 'Dd, 'Dm"); + } else { + Unknown(instr); + } + break; + case 0x3: + if (dp_operation) { + Format(instr, "vrintm.f64.f64 'Dd, 'Dm"); + } else { + Unknown(instr); + } + break; + default: + UNREACHABLE(); // Case analysis is exhaustive. + break; + } + } else { + Unknown(instr); + } + break; default: Unknown(instr); break; diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index 42a605c7e9..1710b609dc 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -1102,7 +1102,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { Comment cmnt(masm_, "[ ForInStatement"); - int slot = stmt->ForInFeedbackSlot(); + FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); SetStatementPosition(stmt); Label loop, exit; @@ -1131,6 +1131,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ push(r0); __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); __ bind(&done_convert); + PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ push(r0); // Check for proxies. @@ -1155,6 +1156,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ bind(&call_runtime); __ push(r0); // Duplicate the enumerable object on the stack. __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); + PrepareForBailoutForId(stmt->EnumId(), TOS_REG); // If we got a map from the runtime call, we can do a fast // modification check. Otherwise, we got a fixed array, and we have @@ -1194,7 +1196,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ Move(r1, FeedbackVector()); __ mov(r2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); - __ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot))); + int vector_index = FeedbackVector()->GetIndex(slot); + __ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(vector_index))); __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object @@ -1364,7 +1367,13 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { Handle home_object_symbol(isolate()->heap()->home_object_symbol()); __ Move(LoadDescriptor::NameRegister(), home_object_symbol); - CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId()); + if (FLAG_vector_ics) { + __ mov(VectorLoadICDescriptor::SlotRegister(), + Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot()))); + CallLoadIC(NOT_CONTEXTUAL); + } else { + CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId()); + } __ cmp(r0, Operand(isolate()->factory()->undefined_value())); Label done; @@ -1426,7 +1435,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, __ mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name())); if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); + Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); } ContextualMode mode = (typeof_state == INSIDE_TYPEOF) @@ -1515,7 +1524,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { __ mov(LoadDescriptor::NameRegister(), Operand(var->name())); if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); + Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); } CallLoadIC(CONTEXTUAL); context()->Plug(r0); @@ -1691,6 +1700,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { FastCloneShallowObjectStub stub(isolate(), properties_count); __ CallStub(&stub); } + PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); // If result_saved is true the result is on top of the stack. If // result_saved is false the result is in r0. @@ -1719,6 +1729,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); // Fall through. case ObjectLiteral::Property::COMPUTED: + // It is safe to use [[Put]] here because the boilerplate already + // contains computed properties with an uninitialized value. if (key->value()->IsInternalizedString()) { if (property->emit_store()) { VisitForAccumulatorValue(value); @@ -1751,7 +1763,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ push(r0); VisitForStackValue(value); if (property->emit_store()) { - __ CallRuntime(Runtime::kSetPrototype, 2); + __ CallRuntime(Runtime::kInternalSetPrototype, 2); } else { __ Drop(2); } @@ -1883,22 +1895,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { - VARIABLE, - NAMED_PROPERTY, - KEYED_PROPERTY, - NAMED_SUPER_PROPERTY - }; - LhsKind assign_type = VARIABLE; Property* property = expr->target()->AsProperty(); - if (property != NULL) { - assign_type = (property->key()->IsPropertyName()) - ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY - : NAMED_PROPERTY) - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -1925,6 +1923,21 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { __ Push(result_register()); } break; + case KEYED_SUPER_PROPERTY: + VisitForStackValue(property->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(property->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(property->key()); + __ Push(result_register()); + if (expr->is_compound()) { + const Register scratch = r1; + __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); + __ Push(scratch); + __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); + __ Push(scratch); + __ Push(result_register()); + } + break; case KEYED_PROPERTY: if (expr->is_compound()) { VisitForStackValue(property->obj()); @@ -1956,6 +1969,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { EmitNamedSuperPropertyLoad(property); PrepareForBailoutForId(property->LoadId(), TOS_REG); break; + case KEYED_SUPER_PROPERTY: + EmitKeyedSuperPropertyLoad(property); + PrepareForBailoutForId(property->LoadId(), TOS_REG); + break; case KEYED_PROPERTY: EmitKeyedPropertyLoad(property); PrepareForBailoutForId(property->LoadId(), TOS_REG); @@ -2003,7 +2020,12 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { EmitNamedPropertyAssignment(expr); break; case NAMED_SUPER_PROPERTY: - EmitNamedSuperPropertyAssignment(expr); + EmitNamedSuperPropertyStore(property); + context()->Plug(r0); + break; + case KEYED_SUPER_PROPERTY: + EmitKeyedSuperPropertyStore(property); + context()->Plug(r0); break; case KEYED_PROPERTY: EmitKeyedPropertyAssignment(expr); @@ -2134,7 +2156,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ ldr(load_name, MemOperand(sp, 2 * kPointerSize)); if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(expr->KeyedLoadFeedbackSlot()))); + Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot()))); } Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); CallIC(ic, TypeFeedbackId::None()); @@ -2154,7 +2176,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(expr->DoneFeedbackSlot()))); + Operand(SmiFromSlot(expr->DoneFeedbackSlot()))); } CallLoadIC(NOT_CONTEXTUAL); // r0=result.done Handle bool_ic = ToBooleanStub::GetUninitialized(isolate()); @@ -2167,7 +2189,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(expr->ValueFeedbackSlot()))); + Operand(SmiFromSlot(expr->ValueFeedbackSlot()))); } CallLoadIC(NOT_CONTEXTUAL); // r0=result.value context()->DropAndPlug(2, r0); // drop iter and g @@ -2308,23 +2330,26 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { Label gc_required; Label allocated; - Handle map(isolate()->native_context()->iterator_result_map()); + const int instance_size = 5 * kPointerSize; + DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(), + instance_size); - __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT); + __ Allocate(instance_size, r0, r2, r3, &gc_required, TAG_OBJECT); __ jmp(&allocated); __ bind(&gc_required); - __ Push(Smi::FromInt(map->instance_size())); + __ Push(Smi::FromInt(instance_size)); __ CallRuntime(Runtime::kAllocateInNewSpace, 1); __ ldr(context_register(), MemOperand(fp, StandardFrameConstants::kContextOffset)); __ bind(&allocated); - __ mov(r1, Operand(map)); + __ ldr(r1, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); + __ ldr(r1, FieldMemOperand(r1, GlobalObject::kNativeContextOffset)); + __ ldr(r1, ContextOperand(r1, Context::ITERATOR_RESULT_MAP_INDEX)); __ pop(r2); __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); - DCHECK_EQ(map->instance_size(), 5 * kPointerSize); __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); @@ -2348,7 +2373,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { __ mov(LoadDescriptor::NameRegister(), Operand(key->value())); if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(prop->PropertyFeedbackSlot()))); + Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); CallLoadIC(NOT_CONTEXTUAL); } else { CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); @@ -2373,7 +2398,7 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(prop->PropertyFeedbackSlot()))); + Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); CallIC(ic); } else { CallIC(ic, prop->PropertyFeedbackId()); @@ -2381,6 +2406,14 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { } +void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { + // Stack: receiver, home_object, key. + SetSourcePosition(prop->position()); + + __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); +} + + void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, Token::Value op, OverwriteMode mode, @@ -2475,6 +2508,62 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, } +void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { + // Constructor is in r0. + DCHECK(lit != NULL); + __ push(r0); + + // No access check is needed here since the constructor is created by the + // class literal. + Register scratch = r1; + __ ldr(scratch, + FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset)); + __ push(scratch); + + for (int i = 0; i < lit->properties()->length(); i++) { + ObjectLiteral::Property* property = lit->properties()->at(i); + Literal* key = property->key()->AsLiteral(); + Expression* value = property->value(); + DCHECK(key != NULL); + + if (property->is_static()) { + __ ldr(scratch, MemOperand(sp, kPointerSize)); // constructor + } else { + __ ldr(scratch, MemOperand(sp, 0)); // prototype + } + __ push(scratch); + VisitForStackValue(key); + VisitForStackValue(value); + + switch (property->kind()) { + case ObjectLiteral::Property::CONSTANT: + case ObjectLiteral::Property::MATERIALIZED_LITERAL: + case ObjectLiteral::Property::COMPUTED: + case ObjectLiteral::Property::PROTOTYPE: + __ CallRuntime(Runtime::kDefineClassMethod, 3); + break; + + case ObjectLiteral::Property::GETTER: + __ CallRuntime(Runtime::kDefineClassGetter, 3); + break; + + case ObjectLiteral::Property::SETTER: + __ CallRuntime(Runtime::kDefineClassSetter, 3); + break; + + default: + UNREACHABLE(); + } + } + + // prototype + __ CallRuntime(Runtime::kToFastProperties, 1); + + // constructor + __ CallRuntime(Runtime::kToFastProperties, 1); +} + + void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op, OverwriteMode mode) { @@ -2490,16 +2579,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, void FullCodeGenerator::EmitAssignment(Expression* expr) { DCHECK(expr->IsValidReferenceExpression()); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->AsProperty(); - if (prop != NULL) { - assign_type = (prop->key()->IsPropertyName()) - ? NAMED_PROPERTY - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(prop); switch (assign_type) { case VARIABLE: { @@ -2518,6 +2599,42 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { CallStoreIC(); break; } + case NAMED_SUPER_PROPERTY: { + __ Push(r0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + // stack: value, this; r0: home_object + Register scratch = r2; + Register scratch2 = r3; + __ mov(scratch, result_register()); // home_object + __ ldr(r0, MemOperand(sp, kPointerSize)); // value + __ ldr(scratch2, MemOperand(sp, 0)); // this + __ str(scratch2, MemOperand(sp, kPointerSize)); // this + __ str(scratch, MemOperand(sp, 0)); // home_object + // stack: this, home_object; r0: value + EmitNamedSuperPropertyStore(prop); + break; + } + case KEYED_SUPER_PROPERTY: { + __ Push(r0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(prop->key()); + Register scratch = r2; + Register scratch2 = r3; + __ ldr(scratch2, MemOperand(sp, 2 * kPointerSize)); // value + // stack: value, this, home_object; r0: key, r3: value + __ ldr(scratch, MemOperand(sp, kPointerSize)); // this + __ str(scratch, MemOperand(sp, 2 * kPointerSize)); + __ ldr(scratch, MemOperand(sp, 0)); // home_object + __ str(scratch, MemOperand(sp, kPointerSize)); + __ str(r0, MemOperand(sp, 0)); + __ Move(r0, scratch2); + // stack: this, home_object, key; r0: value. + EmitKeyedSuperPropertyStore(prop); + break; + } case KEYED_PROPERTY: { __ push(r0); // Preserve value. VisitForStackValue(prop->obj()); @@ -2634,21 +2751,32 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { } -void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { +void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { // Assignment to named property of super. // r0 : value // stack : receiver ('this'), home_object - Property* prop = expr->target()->AsProperty(); DCHECK(prop != NULL); Literal* key = prop->key()->AsLiteral(); DCHECK(key != NULL); - __ Push(r0); __ Push(key->value()); + __ Push(r0); __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict : Runtime::kStoreToSuper_Sloppy), 4); - context()->Plug(r0); +} + + +void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { + // Assignment to named property of super. + // r0 : value + // stack : receiver ('this'), home_object, key + DCHECK(prop != NULL); + + __ Push(r0); + __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict + : Runtime::kStoreKeyedToSuper_Sloppy), + 4); } @@ -2686,11 +2814,19 @@ void FullCodeGenerator::VisitProperty(Property* expr) { PrepareForBailoutForId(expr->LoadId(), TOS_REG); context()->Plug(r0); } else { - VisitForStackValue(expr->obj()); - VisitForAccumulatorValue(expr->key()); - __ Move(LoadDescriptor::NameRegister(), r0); - __ pop(LoadDescriptor::ReceiverRegister()); - EmitKeyedPropertyLoad(expr); + if (!expr->IsSuperAccess()) { + VisitForStackValue(expr->obj()); + VisitForAccumulatorValue(expr->key()); + __ Move(LoadDescriptor::NameRegister(), r0); + __ pop(LoadDescriptor::ReceiverRegister()); + EmitKeyedPropertyLoad(expr); + } else { + VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(expr->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForStackValue(expr->key()); + EmitKeyedSuperPropertyLoad(expr); + } context()->Plug(r0); } } @@ -2802,6 +2938,43 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, } +void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { + Expression* callee = expr->expression(); + DCHECK(callee->IsProperty()); + Property* prop = callee->AsProperty(); + DCHECK(prop->IsSuperAccess()); + + SetSourcePosition(prop->position()); + // Load the function from the receiver. + const Register scratch = r1; + SuperReference* super_ref = prop->obj()->AsSuperReference(); + EmitLoadHomeObject(super_ref); + __ Push(r0); + VisitForAccumulatorValue(super_ref->this_var()); + __ Push(r0); + __ Push(r0); + __ ldr(scratch, MemOperand(sp, kPointerSize * 2)); + __ Push(scratch); + VisitForStackValue(prop->key()); + + // Stack here: + // - home_object + // - this (receiver) + // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. + // - home_object + // - key + __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); + + // Replace home_object with target function. + __ str(r0, MemOperand(sp, kPointerSize)); + + // Stack here: + // - target function + // - this (receiver) + EmitCall(expr, CallICState::METHOD); +} + + void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { // Load the arguments. ZoneList* args = expr->arguments(); @@ -2816,7 +2989,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { SetSourcePosition(expr->position()); Handle ic = CallIC::initialize_stub( isolate(), arg_count, call_type); - __ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot()))); + __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackSlot()))); __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Don't assign a type feedback id to the IC, since type feedback is provided // by the vector above. @@ -2830,13 +3003,16 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { - // r4: copy of the first argument or undefined if it doesn't exist. + // r5: copy of the first argument or undefined if it doesn't exist. if (arg_count > 0) { - __ ldr(r4, MemOperand(sp, arg_count * kPointerSize)); + __ ldr(r5, MemOperand(sp, arg_count * kPointerSize)); } else { - __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); + __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); } + // r4: the receiver of the enclosing function. + __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); + // r3: the receiver of the enclosing function. int receiver_offset = 2 + info_->scope()->num_parameters(); __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize)); @@ -2848,8 +3024,17 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); // Do the runtime call. + __ Push(r5); __ Push(r4, r3, r2, r1); - __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); + __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); +} + + +void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference* super_ref) { + DCHECK(super_ref != NULL); + __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); + __ Push(r0); + __ CallRuntime(Runtime::kGetPrototype, 1); } @@ -2892,6 +3077,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { // r1 (receiver). Touch up the stack with the right values. __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); __ str(r1, MemOperand(sp, arg_count * kPointerSize)); + + PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); } // Record source position for debugger. @@ -2925,6 +3112,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ Push(context_register(), r2); __ CallRuntime(Runtime::kLoadLookupSlot, 2); __ Push(r0, r1); // Function, receiver. + PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); // If fast case code has been generated, emit code to push the // function and receiver and have the slow path jump around this @@ -2948,9 +3136,12 @@ void FullCodeGenerator::VisitCall(Call* expr) { } else if (call_type == Call::PROPERTY_CALL) { Property* property = callee->AsProperty(); bool is_named_call = property->key()->IsPropertyName(); - // super.x() is handled in EmitCallWithLoadIC. - if (property->IsSuperAccess() && is_named_call) { - EmitSuperCallWithLoadIC(expr); + if (property->IsSuperAccess()) { + if (is_named_call) { + EmitSuperCallWithLoadIC(expr); + } else { + EmitKeyedSuperCallWithLoadIC(expr); + } } else { { PreservePositionScope scope(masm()->positions_recorder()); @@ -2962,6 +3153,12 @@ void FullCodeGenerator::VisitCall(Call* expr) { EmitKeyedCallWithLoadIC(expr, property->key()); } } + } else if (call_type == Call::SUPER_CALL) { + SuperReference* super_ref = callee->AsSuperReference(); + EmitLoadSuperConstructor(super_ref); + __ Push(result_register()); + VisitForStackValue(super_ref->this_var()); + EmitCall(expr, CallICState::METHOD); } else { DCHECK(call_type == Call::OTHER_CALL); // Call to an arbitrary expression not handled specially above. @@ -2990,7 +3187,12 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // Push constructor on the stack. If it's not a function it's used as // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // ignored. - VisitForStackValue(expr->expression()); + if (expr->expression()->IsSuperReference()) { + EmitLoadSuperConstructor(expr->expression()->AsSuperReference()); + __ Push(result_register()); + } else { + VisitForStackValue(expr->expression()); + } // Push the arguments ("left-to-right") on the stack. ZoneList* args = expr->arguments(); @@ -3010,12 +3212,12 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // Record call targets in unoptimized code. if (FLAG_pretenuring_call_new) { EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); - DCHECK(expr->AllocationSiteFeedbackSlot() == - expr->CallNewFeedbackSlot() + 1); + DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() == + expr->CallNewFeedbackSlot().ToInt() + 1); } __ Move(r2, FeedbackVector()); - __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); + __ mov(r3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot()))); CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); @@ -3326,6 +3528,32 @@ void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { } +void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) { + ZoneList* args = expr->arguments(); + DCHECK(args->length() == 1); + + VisitForAccumulatorValue(args->at(0)); + + Label materialize_true, materialize_false; + Label* if_true = NULL; + Label* if_false = NULL; + Label* fall_through = NULL; + context()->PrepareTest(&materialize_true, &materialize_false, &if_true, + &if_false, &fall_through); + + __ JumpIfSmi(r0, if_false); + Register map = r1; + Register type_reg = r2; + __ ldr(map, FieldMemOperand(r0, HeapObject::kMapOffset)); + __ ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); + __ sub(type_reg, type_reg, Operand(FIRST_JS_PROXY_TYPE)); + __ cmp(type_reg, Operand(LAST_JS_PROXY_TYPE - FIRST_JS_PROXY_TYPE)); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); + Split(ls, if_true, if_false, fall_through); + + context()->Plug(if_true, if_false); +} + void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { DCHECK(expr->arguments()->length() == 0); @@ -4216,7 +4444,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { __ mov(LoadDescriptor::NameRegister(), Operand(expr->name())); if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(expr->CallRuntimeFeedbackSlot()))); + Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot()))); CallLoadIC(NOT_CONTEXTUAL); } else { CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); @@ -4372,22 +4600,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { Comment cmnt(masm_, "[ CountOperation"); SetSourcePosition(expr->position()); - // Expression can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->expression()->AsProperty(); - // In case of a property we use the uninitialized expression context - // of the key to detect a named property. - if (prop != NULL) { - assign_type = - (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; - if (prop->IsSuperAccess()) { - // throw exception. - VisitSuperReference(prop->obj()->AsSuperReference()); - return; - } - } + LhsKind assign_type = GetAssignType(prop); // Evaluate expression and get value. if (assign_type == VARIABLE) { @@ -4400,18 +4614,55 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ mov(ip, Operand(Smi::FromInt(0))); __ push(ip); } - if (assign_type == NAMED_PROPERTY) { - // Put the object both on the stack and in the register. - VisitForStackValue(prop->obj()); - __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); - EmitNamedPropertyLoad(prop); - } else { - VisitForStackValue(prop->obj()); - VisitForStackValue(prop->key()); - __ ldr(LoadDescriptor::ReceiverRegister(), - MemOperand(sp, 1 * kPointerSize)); - __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0)); - EmitKeyedPropertyLoad(prop); + switch (assign_type) { + case NAMED_PROPERTY: { + // Put the object both on the stack and in the register. + VisitForStackValue(prop->obj()); + __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); + EmitNamedPropertyLoad(prop); + break; + } + + case NAMED_SUPER_PROPERTY: { + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + const Register scratch = r1; + __ ldr(scratch, MemOperand(sp, kPointerSize)); + __ Push(scratch); + __ Push(result_register()); + EmitNamedSuperPropertyLoad(prop); + break; + } + + case KEYED_SUPER_PROPERTY: { + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(prop->key()); + __ Push(result_register()); + const Register scratch = r1; + __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); + __ Push(scratch); + __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); + __ Push(scratch); + __ Push(result_register()); + EmitKeyedSuperPropertyLoad(prop); + break; + } + + case KEYED_PROPERTY: { + VisitForStackValue(prop->obj()); + VisitForStackValue(prop->key()); + __ ldr(LoadDescriptor::ReceiverRegister(), + MemOperand(sp, 1 * kPointerSize)); + __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0)); + EmitKeyedPropertyLoad(prop); + break; + } + + case VARIABLE: + UNREACHABLE(); } } @@ -4445,9 +4696,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case NAMED_PROPERTY: __ str(r0, MemOperand(sp, kPointerSize)); break; + case NAMED_SUPER_PROPERTY: + __ str(r0, MemOperand(sp, 2 * kPointerSize)); + break; case KEYED_PROPERTY: __ str(r0, MemOperand(sp, 2 * kPointerSize)); break; + case KEYED_SUPER_PROPERTY: + __ str(r0, MemOperand(sp, 3 * kPointerSize)); + break; } } } @@ -4475,9 +4732,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case NAMED_PROPERTY: __ str(r0, MemOperand(sp, kPointerSize)); break; + case NAMED_SUPER_PROPERTY: + __ str(r0, MemOperand(sp, 2 * kPointerSize)); + break; case KEYED_PROPERTY: __ str(r0, MemOperand(sp, 2 * kPointerSize)); break; + case KEYED_SUPER_PROPERTY: + __ str(r0, MemOperand(sp, 3 * kPointerSize)); + break; } } } @@ -4533,6 +4796,28 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } break; } + case NAMED_SUPER_PROPERTY: { + EmitNamedSuperPropertyStore(prop); + if (expr->is_postfix()) { + if (!context()->IsEffect()) { + context()->PlugTOS(); + } + } else { + context()->Plug(r0); + } + break; + } + case KEYED_SUPER_PROPERTY: { + EmitKeyedSuperPropertyStore(prop); + if (expr->is_postfix()) { + if (!context()->IsEffect()) { + context()->PlugTOS(); + } + } else { + context()->Plug(r0); + } + break; + } case KEYED_PROPERTY: { __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); @@ -4563,7 +4848,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { __ mov(LoadDescriptor::NameRegister(), Operand(proxy->name())); if (FLAG_vector_ics) { __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); + Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); } // Use a regular load, not a contextual load, to avoid a reference // error. diff --git a/deps/v8/src/arm/interface-descriptors-arm.cc b/deps/v8/src/arm/interface-descriptors-arm.cc index 9bbc1f58c1..6e77ee474a 100644 --- a/deps/v8/src/arm/interface-descriptors-arm.cc +++ b/deps/v8/src/arm/interface-descriptors-arm.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return r2; } const Register StoreDescriptor::ValueRegister() { return r0; } +const Register StoreTransitionDescriptor::MapRegister() { return r3; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return r3; } @@ -149,6 +152,15 @@ void TransitionElementsKindDescriptor::Initialize( } +void AllocateHeapNumberDescriptor::Initialize( + CallInterfaceDescriptorData* data) { + // register state + // cp -- context + Register registers[] = {cp}; + data->Initialize(arraysize(registers), registers, nullptr); +} + + void ArrayConstructorConstantArgCountDescriptor::Initialize( CallInterfaceDescriptorData* data) { // register state diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 13a46a2b54..46897a3726 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "src/v8.h" #include "src/arm/lithium-codegen-arm.h" @@ -316,9 +318,9 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { void LStoreNamedField::PrintDataTo(StringStream* stream) { object()->PrintTo(stream); - OStringStream os; + std::ostringstream os; os << hydrogen()->access() << " <- "; - stream->Add(os.c_str()); + stream->Add(os.str().c_str()); value()->PrintTo(stream); } @@ -697,11 +699,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, // Shift operations can only deoptimize if we do a logical shift // by 0 and the result cannot be truncated to int32. if (op == Token::SHR && constant_value == 0) { - if (FLAG_opt_safe_uint32_operations) { - does_deopt = !instr->CheckFlag(HInstruction::kUint32); - } else { - does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); - } + does_deopt = !instr->CheckFlag(HInstruction::kUint32); } LInstruction* result = diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 14740965bf..e945a13c87 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -2994,13 +2994,14 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { template void LCodeGen::EmitVectorLoadICRegisters(T* instr) { DCHECK(FLAG_vector_ics); - Register vector = ToRegister(instr->temp_vector()); - DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); - __ Move(vector, instr->hydrogen()->feedback_vector()); + Register vector_register = ToRegister(instr->temp_vector()); + DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); + Handle vector = instr->hydrogen()->feedback_vector(); + __ Move(vector_register, vector); // No need to allocate this register. DCHECK(VectorLoadICDescriptor::SlotRegister().is(r0)); - __ mov(VectorLoadICDescriptor::SlotRegister(), - Operand(Smi::FromInt(instr->hydrogen()->slot()))); + int index = vector->GetIndex(instr->hydrogen()->slot()); + __ mov(VectorLoadICDescriptor::SlotRegister(), Operand(Smi::FromInt(index))); } @@ -3015,7 +3016,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { EmitVectorLoadICRegisters(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle ic = CodeFactory::LoadIC(isolate(), mode).code(); + Handle ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3137,7 +3138,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { if (FLAG_vector_ics) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); + Handle ic = + CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -3428,7 +3430,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); + Handle ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index 0d0b0ee16e..9294a8c7c6 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -967,7 +967,7 @@ void MacroAssembler::StubPrologue() { add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); if (FLAG_enable_ool_constant_pool) { LoadConstantPoolPointerRegister(); - set_constant_pool_available(true); + set_ool_constant_pool_available(true); } } @@ -992,16 +992,16 @@ void MacroAssembler::Prologue(bool code_pre_aging) { } if (FLAG_enable_ool_constant_pool) { LoadConstantPoolPointerRegister(); - set_constant_pool_available(true); + set_ool_constant_pool_available(true); } } void MacroAssembler::EnterFrame(StackFrame::Type type, - bool load_constant_pool) { + bool load_constant_pool_pointer_reg) { // r0-r3: preserved PushFixedFrame(); - if (FLAG_enable_ool_constant_pool && load_constant_pool) { + if (FLAG_enable_ool_constant_pool && load_constant_pool_pointer_reg) { LoadConstantPoolPointerRegister(); } mov(ip, Operand(Smi::FromInt(type))); @@ -4071,21 +4071,22 @@ void MacroAssembler::TruncatingDiv(Register result, DCHECK(!dividend.is(ip)); DCHECK(!result.is(ip)); base::MagicNumbersForDivision mag = - base::SignedDivisionByConstant(static_cast(divisor)); + base::SignedDivisionByConstant(bit_cast(divisor)); mov(ip, Operand(mag.multiplier)); - smull(ip, result, dividend, ip); - bool neg = (mag.multiplier & (static_cast(1) << 31)) != 0; + bool neg = (mag.multiplier & (1U << 31)) != 0; if (divisor > 0 && neg) { - add(result, result, Operand(dividend)); - } - if (divisor < 0 && !neg && mag.multiplier > 0) { - sub(result, result, Operand(dividend)); + smmla(result, dividend, ip, dividend); + } else { + smmul(result, dividend, ip); + if (divisor < 0 && !neg && mag.multiplier > 0) { + sub(result, result, Operand(dividend)); + } } if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); add(result, result, Operand(dividend, LSR, 31)); } - -} } // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h index d2a178664e..79d26f2696 100644 --- a/deps/v8/src/arm/macro-assembler-arm.h +++ b/deps/v8/src/arm/macro-assembler-arm.h @@ -1401,7 +1401,8 @@ class MacroAssembler: public Assembler { } // Activation support. - void EnterFrame(StackFrame::Type type, bool load_constant_pool = false); + void EnterFrame(StackFrame::Type type, + bool load_constant_pool_pointer_reg = false); // Returns the pc offset at which the frame ends. int LeaveFrame(StackFrame::Type type); @@ -1530,71 +1531,6 @@ class CodePatcher { }; -class FrameAndConstantPoolScope { - public: - FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type) - : masm_(masm), - type_(type), - old_has_frame_(masm->has_frame()), - old_constant_pool_available_(masm->is_constant_pool_available()) { - // We only want to enable constant pool access for non-manual frame scopes - // to ensure the constant pool pointer is valid throughout the scope. - DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); - masm->set_has_frame(true); - masm->set_constant_pool_available(true); - masm->EnterFrame(type, !old_constant_pool_available_); - } - - ~FrameAndConstantPoolScope() { - masm_->LeaveFrame(type_); - masm_->set_has_frame(old_has_frame_); - masm_->set_constant_pool_available(old_constant_pool_available_); - } - - // Normally we generate the leave-frame code when this object goes - // out of scope. Sometimes we may need to generate the code somewhere else - // in addition. Calling this will achieve that, but the object stays in - // scope, the MacroAssembler is still marked as being in a frame scope, and - // the code will be generated again when it goes out of scope. - void GenerateLeaveFrame() { - DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); - masm_->LeaveFrame(type_); - } - - private: - MacroAssembler* masm_; - StackFrame::Type type_; - bool old_has_frame_; - bool old_constant_pool_available_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope); -}; - - -// Class for scoping the the unavailability of constant pool access. -class ConstantPoolUnavailableScope { - public: - explicit ConstantPoolUnavailableScope(MacroAssembler* masm) - : masm_(masm), - old_constant_pool_available_(masm->is_constant_pool_available()) { - if (FLAG_enable_ool_constant_pool) { - masm_->set_constant_pool_available(false); - } - } - ~ConstantPoolUnavailableScope() { - if (FLAG_enable_ool_constant_pool) { - masm_->set_constant_pool_available(old_constant_pool_available_); - } - } - - private: - MacroAssembler* masm_; - int old_constant_pool_available_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope); -}; - - // ----------------------------------------------------------------------------- // Static helper functions. diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc index 0444025a0d..972fd07a2c 100644 --- a/deps/v8/src/arm/simulator-arm.cc +++ b/deps/v8/src/arm/simulator-arm.cc @@ -2710,6 +2710,27 @@ void Simulator::DecodeType3(Instruction* instr) { break; } case db_x: { + if (instr->Bits(22, 20) == 0x5) { + if (instr->Bits(7, 4) == 0x1) { + int rm = instr->RmValue(); + int32_t rm_val = get_register(rm); + int rs = instr->RsValue(); + int32_t rs_val = get_register(rs); + if (instr->Bits(15, 12) == 0xF) { + // SMMUL (in V8 notation matching ARM ISA format) + // Format(instr, "smmul'cond 'rn, 'rm, 'rs"); + rn_val = base::bits::SignedMulHigh32(rm_val, rs_val); + } else { + // SMMLA (in V8 notation matching ARM ISA format) + // Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd"); + int rd = instr->RdValue(); + int32_t rd_val = get_register(rd); + rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val); + } + set_register(rn, rn_val); + return; + } + } if (FLAG_enable_sudiv) { if (instr->Bits(5, 4) == 0x1) { if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { @@ -2720,15 +2741,12 @@ void Simulator::DecodeType3(Instruction* instr) { int rs = instr->RsValue(); int32_t rs_val = get_register(rs); int32_t ret_val = 0; - DCHECK(rs_val != 0); // udiv if (instr->Bit(21) == 0x1) { - ret_val = static_cast(static_cast(rm_val) / - static_cast(rs_val)); - } else if ((rm_val == kMinInt) && (rs_val == -1)) { - ret_val = kMinInt; + ret_val = bit_cast(base::bits::UnsignedDiv32( + bit_cast(rm_val), bit_cast(rs_val))); } else { - ret_val = rm_val / rs_val; + ret_val = base::bits::SignedDiv32(rm_val, rs_val); } set_register(rn, ret_val); return; @@ -2939,6 +2957,12 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { } else { UNREACHABLE(); // Not used by v8. } + } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) { + // vrintz - truncate + double dm_value = get_double_from_d_register(vm); + double dd_value = trunc(dm_value); + dd_value = canonicalizeNaN(dd_value); + set_d_register_from_double(vd, dd_value); } else { UNREACHABLE(); // Not used by V8. } @@ -3589,6 +3613,50 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { UNIMPLEMENTED(); } break; + case 0x1D: + if (instr->Opc1Value() == 0x7 && instr->Opc3Value() == 0x1 && + instr->Bits(11, 9) == 0x5 && instr->Bits(19, 18) == 0x2 && + instr->Bit(8) == 0x1) { + int vm = instr->VFPMRegValue(kDoublePrecision); + int vd = instr->VFPDRegValue(kDoublePrecision); + double dm_value = get_double_from_d_register(vm); + double dd_value = 0.0; + int rounding_mode = instr->Bits(17, 16); + switch (rounding_mode) { + case 0x0: // vrinta - round with ties to away from zero + dd_value = round(dm_value); + break; + case 0x1: { // vrintn - round with ties to even + dd_value = std::floor(dm_value); + double error = dm_value - dd_value; + // Take care of correctly handling the range [-0.5, -0.0], which + // must yield -0.0. + if ((-0.5 <= dm_value) && (dm_value < 0.0)) { + dd_value = -0.0; + // If the error is greater than 0.5, or is equal to 0.5 and the + // integer result is odd, round up. + } else if ((error > 0.5) || + ((error == 0.5) && (fmod(dd_value, 2) != 0))) { + dd_value++; + } + break; + } + case 0x2: // vrintp - ceil + dd_value = std::ceil(dm_value); + break; + case 0x3: // vrintm - floor + dd_value = std::floor(dm_value); + break; + default: + UNREACHABLE(); // Case analysis is exhaustive. + break; + } + dd_value = canonicalizeNaN(dd_value); + set_d_register_from_double(vd, dd_value); + } else { + UNIMPLEMENTED(); + } + break; default: UNIMPLEMENTED(); break; diff --git a/deps/v8/src/arm64/assembler-arm64.cc b/deps/v8/src/arm64/assembler-arm64.cc index c1213e9693..076e143bc8 100644 --- a/deps/v8/src/arm64/assembler-arm64.cc +++ b/deps/v8/src/arm64/assembler-arm64.cc @@ -1936,6 +1936,12 @@ void Assembler::frintn(const FPRegister& fd, } +void Assembler::frintp(const FPRegister& fd, const FPRegister& fn) { + DCHECK(fd.SizeInBits() == fn.SizeInBits()); + FPDataProcessing1Source(fd, fn, FRINTP); +} + + void Assembler::frintz(const FPRegister& fd, const FPRegister& fn) { DCHECK(fd.SizeInBits() == fn.SizeInBits()); diff --git a/deps/v8/src/arm64/assembler-arm64.h b/deps/v8/src/arm64/assembler-arm64.h index 9b1c5e6746..53496f37ce 100644 --- a/deps/v8/src/arm64/assembler-arm64.h +++ b/deps/v8/src/arm64/assembler-arm64.h @@ -1663,6 +1663,9 @@ class Assembler : public AssemblerBase { // FP round to integer (nearest with ties to even). void frintn(const FPRegister& fd, const FPRegister& fn); + // FP round to integer (towards plus infinity). + void frintp(const FPRegister& fd, const FPRegister& fn); + // FP round to integer (towards zero.) void frintz(const FPRegister& fd, const FPRegister& fn); diff --git a/deps/v8/src/arm64/builtins-arm64.cc b/deps/v8/src/arm64/builtins-arm64.cc index e9ad8f165d..74535ba615 100644 --- a/deps/v8/src/arm64/builtins-arm64.cc +++ b/deps/v8/src/arm64/builtins-arm64.cc @@ -156,7 +156,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { __ Cbz(argc, &no_arguments); // First args = sp[(argc - 1) * 8]. __ Sub(argc, argc, 1); - __ Claim(argc, kXRegSize); + __ Drop(argc, kXRegSize); // jssp now point to args[0], load and drop args[0] + receiver. Register arg = argc; __ Ldr(arg, MemOperand(jssp, 2 * kPointerSize, PostIndex)); diff --git a/deps/v8/src/arm64/code-stubs-arm64.cc b/deps/v8/src/arm64/code-stubs-arm64.cc index 35b60f7a6f..6583775a66 100644 --- a/deps/v8/src/arm64/code-stubs-arm64.cc +++ b/deps/v8/src/arm64/code-stubs-arm64.cc @@ -1422,6 +1422,34 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) { } +void LoadIndexedStringStub::Generate(MacroAssembler* masm) { + // Return address is in lr. + Label miss; + + Register receiver = LoadDescriptor::ReceiverRegister(); + Register index = LoadDescriptor::NameRegister(); + Register result = x0; + Register scratch = x3; + DCHECK(!scratch.is(receiver) && !scratch.is(index)); + + StringCharAtGenerator char_at_generator(receiver, index, scratch, result, + &miss, // When not a string. + &miss, // When not a number. + &miss, // When index out of range. + STRING_INDEX_IS_ARRAY_INDEX, + RECEIVER_IS_STRING); + char_at_generator.GenerateFast(masm); + __ Ret(); + + StubRuntimeCallHelper call_helper; + char_at_generator.GenerateSlow(masm, call_helper); + + __ Bind(&miss); + PropertyAccessCompiler::TailCallBuiltin( + masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); +} + + void InstanceofStub::Generate(MacroAssembler* masm) { // Stack on entry: // jssp[0]: function. @@ -1569,7 +1597,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ Mov(result, res_false); // Null is not instance of anything. - __ Cmp(object_type, Operand(isolate()->factory()->null_value())); + __ Cmp(object, Operand(isolate()->factory()->null_value())); __ B(ne, &object_not_null); __ Ret(); @@ -2683,13 +2711,13 @@ static void GenerateRecordCallTarget(MacroAssembler* masm, // A monomorphic miss (i.e, here the cache is not uninitialized) goes // megamorphic. - __ JumpIfRoot(scratch1, Heap::kUninitializedSymbolRootIndex, &initialize); + __ JumpIfRoot(scratch1, Heap::kuninitialized_symbolRootIndex, &initialize); // MegamorphicSentinel is an immortal immovable object (undefined) so no // write-barrier is needed. __ Bind(&megamorphic); __ Add(scratch1, feedback_vector, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); - __ LoadRoot(scratch2, Heap::kMegamorphicSymbolRootIndex); + __ LoadRoot(scratch2, Heap::kmegamorphic_symbolRootIndex); __ Str(scratch2, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); __ B(&done); @@ -3038,8 +3066,8 @@ void CallICStub::Generate(MacroAssembler* masm) { __ bind(&extra_checks_or_miss); Label miss; - __ JumpIfRoot(x4, Heap::kMegamorphicSymbolRootIndex, &slow_start); - __ JumpIfRoot(x4, Heap::kUninitializedSymbolRootIndex, &miss); + __ JumpIfRoot(x4, Heap::kmegamorphic_symbolRootIndex, &slow_start); + __ JumpIfRoot(x4, Heap::kuninitialized_symbolRootIndex, &miss); if (!FLAG_trace_ic) { // We are going megamorphic. If the feedback is a JSFunction, it is fine @@ -3048,8 +3076,19 @@ void CallICStub::Generate(MacroAssembler* masm) { __ JumpIfNotObjectType(x4, x5, x5, JS_FUNCTION_TYPE, &miss); __ Add(x4, feedback_vector, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); - __ LoadRoot(x5, Heap::kMegamorphicSymbolRootIndex); + __ LoadRoot(x5, Heap::kmegamorphic_symbolRootIndex); __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize)); + // We have to update statistics for runtime profiling. + const int with_types_offset = + FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); + __ Ldr(x4, FieldMemOperand(feedback_vector, with_types_offset)); + __ Subs(x4, x4, Operand(Smi::FromInt(1))); + __ Str(x4, FieldMemOperand(feedback_vector, with_types_offset)); + const int generic_offset = + FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); + __ Ldr(x4, FieldMemOperand(feedback_vector, generic_offset)); + __ Adds(x4, x4, Operand(Smi::FromInt(1))); + __ Str(x4, FieldMemOperand(feedback_vector, generic_offset)); __ B(&slow_start); } @@ -3097,14 +3136,16 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { // If the receiver is a smi trigger the non-string case. - __ JumpIfSmi(object_, receiver_not_string_); + if (check_mode_ == RECEIVER_IS_UNKNOWN) { + __ JumpIfSmi(object_, receiver_not_string_); - // Fetch the instance type of the receiver into result register. - __ Ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); - __ Ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); + // Fetch the instance type of the receiver into result register. + __ Ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); + __ Ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); - // If the receiver is not a string trigger the non-string case. - __ TestAndBranchIfAnySet(result_, kIsNotStringMask, receiver_not_string_); + // If the receiver is not a string trigger the non-string case. + __ TestAndBranchIfAnySet(result_, kIsNotStringMask, receiver_not_string_); + } // If the index is non-smi trigger the non-smi case. __ JumpIfNotSmi(index_, &index_not_smi_); @@ -3782,9 +3823,9 @@ void SubStringStub::Generate(MacroAssembler* masm) { // x12: input_type // x15: from (untagged) __ SmiTag(from); - StringCharAtGenerator generator( - input_string, from, result_length, x0, - &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); + StringCharAtGenerator generator(input_string, from, result_length, x0, + &runtime, &runtime, &runtime, + STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); generator.GenerateFast(masm); __ Drop(3); __ Ret(); @@ -3792,6 +3833,22 @@ void SubStringStub::Generate(MacroAssembler* masm) { } +void ToNumberStub::Generate(MacroAssembler* masm) { + // The ToNumber stub takes one argument in x0. + Label check_heap_number, call_builtin; + __ JumpIfNotSmi(x0, &check_heap_number); + __ Ret(); + + __ bind(&check_heap_number); + __ JumpIfNotHeapNumber(x0, &call_builtin); + __ Ret(); + + __ bind(&call_builtin); + __ push(x0); + __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); +} + + void StringHelper::GenerateFlatOneByteStringEquals( MacroAssembler* masm, Register left, Register right, Register scratch1, Register scratch2, Register scratch3) { diff --git a/deps/v8/src/arm64/codegen-arm64.cc b/deps/v8/src/arm64/codegen-arm64.cc index 91eaba7957..cda6e5b6c0 100644 --- a/deps/v8/src/arm64/codegen-arm64.cc +++ b/deps/v8/src/arm64/codegen-arm64.cc @@ -290,15 +290,28 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( Register src_elements = x10; Register dst_elements = x11; Register dst_end = x12; + Register the_hole = x14; + __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex); __ Add(src_elements, elements, FixedDoubleArray::kHeaderSize - kHeapObjectTag); __ Add(dst_elements, array, FixedArray::kHeaderSize); - __ Add(array, array, kHeapObjectTag); __ Add(dst_end, dst_elements, Operand(length, LSL, kPointerSizeLog2)); - Register the_hole = x14; + // Allocating heap numbers in the loop below can fail and cause a jump to + // gc_required. We can't leave a partly initialized FixedArray behind, + // so pessimistically fill it with holes now. + Label initialization_loop, initialization_loop_entry; + __ B(&initialization_loop_entry); + __ bind(&initialization_loop); + __ Str(the_hole, MemOperand(dst_elements, kPointerSize, PostIndex)); + __ bind(&initialization_loop_entry); + __ Cmp(dst_elements, dst_end); + __ B(lt, &initialization_loop); + + __ Add(dst_elements, array, FixedArray::kHeaderSize); + __ Add(array, array, kHeapObjectTag); + Register heap_num_map = x15; - __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex); __ LoadRoot(heap_num_map, Heap::kHeapNumberMapRootIndex); Label entry; diff --git a/deps/v8/src/arm64/debug-arm64.cc b/deps/v8/src/arm64/debug-arm64.cc index f57d5b5ab2..dae5a28434 100644 --- a/deps/v8/src/arm64/debug-arm64.cc +++ b/deps/v8/src/arm64/debug-arm64.cc @@ -238,7 +238,11 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) { // Calling convention for IC load (from ic-arm.cc). Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10); + RegList regs = receiver.Bit() | name.Bit(); + if (FLAG_vector_ics) { + regs |= VectorLoadICTrampolineDescriptor::SlotRegister().Bit(); + } + Generate_DebugBreakCallHelper(masm, regs, 0, x10); } diff --git a/deps/v8/src/arm64/delayed-masm-arm64.cc b/deps/v8/src/arm64/delayed-masm-arm64.cc index c3bda915e8..b51e77ec86 100644 --- a/deps/v8/src/arm64/delayed-masm-arm64.cc +++ b/deps/v8/src/arm64/delayed-masm-arm64.cc @@ -16,8 +16,8 @@ namespace internal { void DelayedMasm::StackSlotMove(LOperand* src, LOperand* dst) { - DCHECK(src->IsStackSlot()); - DCHECK(dst->IsStackSlot()); + DCHECK((src->IsStackSlot() && dst->IsStackSlot()) || + (src->IsDoubleStackSlot() && dst->IsDoubleStackSlot())); MemOperand src_operand = cgen_->ToMemOperand(src); MemOperand dst_operand = cgen_->ToMemOperand(dst); if (pending_ == kStackSlotMove) { diff --git a/deps/v8/src/arm64/disasm-arm64.cc b/deps/v8/src/arm64/disasm-arm64.cc index ac7cb37322..36bad37705 100644 --- a/deps/v8/src/arm64/disasm-arm64.cc +++ b/deps/v8/src/arm64/disasm-arm64.cc @@ -1695,7 +1695,7 @@ int Disassembler::SubstituteBarrierField(Instruction* instr, DCHECK(format[0] == 'M'); USE(format); - static const char* options[4][4] = { + static const char* const options[4][4] = { { "sy (0b0000)", "oshld", "oshst", "osh" }, { "sy (0b0100)", "nshld", "nshst", "nsh" }, { "sy (0b1000)", "ishld", "ishst", "ish" }, diff --git a/deps/v8/src/arm64/full-codegen-arm64.cc b/deps/v8/src/arm64/full-codegen-arm64.cc index 9d544825e4..426287540e 100644 --- a/deps/v8/src/arm64/full-codegen-arm64.cc +++ b/deps/v8/src/arm64/full-codegen-arm64.cc @@ -299,24 +299,26 @@ void FullCodeGenerator::Generate() { } VisitDeclarations(scope()->declarations()); } - } - { Comment cmnt(masm_, "[ Stack check"); - PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); - Label ok; - DCHECK(jssp.Is(__ StackPointer())); - __ CompareRoot(jssp, Heap::kStackLimitRootIndex); - __ B(hs, &ok); - PredictableCodeSizeScope predictable(masm_, - Assembler::kCallSizeWithRelocation); - __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); - __ Bind(&ok); - } + { + Comment cmnt(masm_, "[ Stack check"); + PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); + Label ok; + DCHECK(jssp.Is(__ StackPointer())); + __ CompareRoot(jssp, Heap::kStackLimitRootIndex); + __ B(hs, &ok); + PredictableCodeSizeScope predictable(masm_, + Assembler::kCallSizeWithRelocation); + __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); + __ Bind(&ok); + } - { Comment cmnt(masm_, "[ Body"); - DCHECK(loop_depth() == 0); - VisitStatements(function()->body()); - DCHECK(loop_depth() == 0); + { + Comment cmnt(masm_, "[ Body"); + DCHECK(loop_depth() == 0); + VisitStatements(function()->body()); + DCHECK(loop_depth() == 0); + } } // Always emit a 'return undefined' in case control fell off the end of @@ -1097,7 +1099,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { ASM_LOCATION("FullCodeGenerator::VisitForInStatement"); Comment cmnt(masm_, "[ ForInStatement"); - int slot = stmt->ForInFeedbackSlot(); + FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); // TODO(all): This visitor probably needs better comments and a revisit. SetStatementPosition(stmt); @@ -1124,6 +1126,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ Push(x0); __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); __ Bind(&done_convert); + PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ Push(x0); // Check for proxies. @@ -1147,6 +1150,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ Bind(&call_runtime); __ Push(x0); // Duplicate the enumerable object on the stack. __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); + PrepareForBailoutForId(stmt->EnumId(), TOS_REG); // If we got a map from the runtime call, we can do a fast // modification check. Otherwise, we got a fixed array, and we have @@ -1181,7 +1185,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ LoadObject(x1, FeedbackVector()); __ Mov(x10, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); - __ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(slot))); + int vector_index = FeedbackVector()->GetIndex(slot); + __ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(vector_index))); __ Mov(x1, Smi::FromInt(1)); // Smi indicates slow check. __ Peek(x10, 0); // Get enumerated object. @@ -1350,7 +1355,13 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { Handle home_object_symbol(isolate()->heap()->home_object_symbol()); __ Mov(LoadDescriptor::NameRegister(), Operand(home_object_symbol)); - CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId()); + if (FLAG_vector_ics) { + __ Mov(VectorLoadICDescriptor::SlotRegister(), + SmiFromSlot(expr->HomeObjectFeedbackSlot())); + CallLoadIC(NOT_CONTEXTUAL); + } else { + CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId()); + } __ Mov(x10, Operand(isolate()->factory()->undefined_value())); __ cmp(x0, x10); @@ -1408,7 +1419,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, __ Mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name())); if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(proxy->VariableFeedbackSlot())); + SmiFromSlot(proxy->VariableFeedbackSlot())); } ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL @@ -1493,7 +1504,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { __ Mov(LoadDescriptor::NameRegister(), Operand(var->name())); if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(proxy->VariableFeedbackSlot())); + SmiFromSlot(proxy->VariableFeedbackSlot())); } CallLoadIC(CONTEXTUAL); context()->Plug(x0); @@ -1671,6 +1682,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { FastCloneShallowObjectStub stub(isolate(), properties_count); __ CallStub(&stub); } + PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); // If result_saved is true the result is on top of the stack. If // result_saved is false the result is in x0. @@ -1699,6 +1711,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); // Fall through. case ObjectLiteral::Property::COMPUTED: + // It is safe to use [[Put]] here because the boilerplate already + // contains computed properties with an uninitialized value. if (key->value()->IsInternalizedString()) { if (property->emit_store()) { VisitForAccumulatorValue(value); @@ -1732,7 +1746,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ Peek(x0, 0); __ Push(x0); VisitForStackValue(value); - __ CallRuntime(Runtime::kSetPrototype, 2); + __ CallRuntime(Runtime::kInternalSetPrototype, 2); } else { VisitForEffect(value); } @@ -1862,22 +1876,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { - VARIABLE, - NAMED_PROPERTY, - KEYED_PROPERTY, - NAMED_SUPER_PROPERTY - }; - LhsKind assign_type = VARIABLE; Property* property = expr->target()->AsProperty(); - if (property != NULL) { - assign_type = (property->key()->IsPropertyName()) - ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY - : NAMED_PROPERTY) - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -1903,6 +1903,20 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { __ Push(scratch, result_register()); } break; + case KEYED_SUPER_PROPERTY: + VisitForStackValue(property->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(property->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(property->key()); + __ Push(result_register()); + if (expr->is_compound()) { + const Register scratch1 = x10; + const Register scratch2 = x11; + __ Peek(scratch1, 2 * kPointerSize); + __ Peek(scratch2, kPointerSize); + __ Push(scratch1, scratch2, result_register()); + } + break; case KEYED_PROPERTY: if (expr->is_compound()) { VisitForStackValue(property->obj()); @@ -1933,6 +1947,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { EmitNamedSuperPropertyLoad(property); PrepareForBailoutForId(property->LoadId(), TOS_REG); break; + case KEYED_SUPER_PROPERTY: + EmitKeyedSuperPropertyLoad(property); + PrepareForBailoutForId(property->LoadId(), TOS_REG); + break; case KEYED_PROPERTY: EmitKeyedPropertyLoad(property); PrepareForBailoutForId(property->LoadId(), TOS_REG); @@ -1980,7 +1998,12 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { EmitNamedPropertyAssignment(expr); break; case NAMED_SUPER_PROPERTY: - EmitNamedSuperPropertyAssignment(expr); + EmitNamedSuperPropertyStore(property); + context()->Plug(x0); + break; + case KEYED_SUPER_PROPERTY: + EmitKeyedSuperPropertyStore(property); + context()->Plug(x0); break; case KEYED_PROPERTY: EmitKeyedPropertyAssignment(expr); @@ -1997,7 +2020,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { __ Mov(LoadDescriptor::NameRegister(), Operand(key->value())); if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(prop->PropertyFeedbackSlot())); + SmiFromSlot(prop->PropertyFeedbackSlot())); CallLoadIC(NOT_CONTEXTUAL); } else { CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); @@ -2019,11 +2042,11 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); - // Call keyed load IC. It has arguments key and receiver in r0 and r1. + // Call keyed load IC. It has arguments key and receiver in x0 and x1. Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(prop->PropertyFeedbackSlot())); + SmiFromSlot(prop->PropertyFeedbackSlot())); CallIC(ic); } else { CallIC(ic, prop->PropertyFeedbackId()); @@ -2031,6 +2054,14 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { } +void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { + // Stack: receiver, home_object, key. + SetSourcePosition(prop->position()); + + __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); +} + + void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, Token::Value op, OverwriteMode mode, @@ -2146,19 +2177,67 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, } +void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { + // Constructor is in x0. + DCHECK(lit != NULL); + __ push(x0); + + // No access check is needed here since the constructor is created by the + // class literal. + Register scratch = x1; + __ Ldr(scratch, + FieldMemOperand(x0, JSFunction::kPrototypeOrInitialMapOffset)); + __ Push(scratch); + + for (int i = 0; i < lit->properties()->length(); i++) { + ObjectLiteral::Property* property = lit->properties()->at(i); + Literal* key = property->key()->AsLiteral(); + Expression* value = property->value(); + DCHECK(key != NULL); + + if (property->is_static()) { + __ Peek(scratch, kPointerSize); // constructor + } else { + __ Peek(scratch, 0); // prototype + } + __ Push(scratch); + VisitForStackValue(key); + VisitForStackValue(value); + + switch (property->kind()) { + case ObjectLiteral::Property::CONSTANT: + case ObjectLiteral::Property::MATERIALIZED_LITERAL: + case ObjectLiteral::Property::COMPUTED: + case ObjectLiteral::Property::PROTOTYPE: + __ CallRuntime(Runtime::kDefineClassMethod, 3); + break; + + case ObjectLiteral::Property::GETTER: + __ CallRuntime(Runtime::kDefineClassGetter, 3); + break; + + case ObjectLiteral::Property::SETTER: + __ CallRuntime(Runtime::kDefineClassSetter, 3); + break; + + default: + UNREACHABLE(); + } + } + + // prototype + __ CallRuntime(Runtime::kToFastProperties, 1); + + // constructor + __ CallRuntime(Runtime::kToFastProperties, 1); +} + + void FullCodeGenerator::EmitAssignment(Expression* expr) { DCHECK(expr->IsValidReferenceExpression()); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->AsProperty(); - if (prop != NULL) { - assign_type = (prop->key()->IsPropertyName()) - ? NAMED_PROPERTY - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(prop); switch (assign_type) { case VARIABLE: { @@ -2179,6 +2258,42 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { CallStoreIC(); break; } + case NAMED_SUPER_PROPERTY: { + __ Push(x0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + // stack: value, this; x0: home_object + Register scratch = x10; + Register scratch2 = x11; + __ mov(scratch, result_register()); // home_object + __ Peek(x0, kPointerSize); // value + __ Peek(scratch2, 0); // this + __ Poke(scratch2, kPointerSize); // this + __ Poke(scratch, 0); // home_object + // stack: this, home_object; x0: value + EmitNamedSuperPropertyStore(prop); + break; + } + case KEYED_SUPER_PROPERTY: { + __ Push(x0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(prop->key()); + Register scratch = x10; + Register scratch2 = x11; + __ Peek(scratch2, 2 * kPointerSize); // value + // stack: value, this, home_object; x0: key, x11: value + __ Peek(scratch, kPointerSize); // this + __ Poke(scratch, 2 * kPointerSize); + __ Peek(scratch, 0); // home_object + __ Poke(scratch, kPointerSize); + __ Poke(x0, 0); + __ Move(x0, scratch2); + // stack: this, home_object, key; x0: value. + EmitKeyedSuperPropertyStore(prop); + break; + } case KEYED_PROPERTY: { __ Push(x0); // Preserve value. VisitForStackValue(prop->obj()); @@ -2297,21 +2412,32 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { } -void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { +void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { // Assignment to named property of super. // x0 : value // stack : receiver ('this'), home_object - Property* prop = expr->target()->AsProperty(); DCHECK(prop != NULL); Literal* key = prop->key()->AsLiteral(); DCHECK(key != NULL); - __ Push(x0); __ Push(key->value()); + __ Push(x0); __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict : Runtime::kStoreToSuper_Sloppy), 4); - context()->Plug(x0); +} + + +void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { + // Assignment to named property of super. + // x0 : value + // stack : receiver ('this'), home_object, key + DCHECK(prop != NULL); + + __ Push(x0); + __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict + : Runtime::kStoreKeyedToSuper_Sloppy), + 4); } @@ -2351,11 +2477,19 @@ void FullCodeGenerator::VisitProperty(Property* expr) { PrepareForBailoutForId(expr->LoadId(), TOS_REG); context()->Plug(x0); } else { - VisitForStackValue(expr->obj()); - VisitForAccumulatorValue(expr->key()); - __ Move(LoadDescriptor::NameRegister(), x0); - __ Pop(LoadDescriptor::ReceiverRegister()); - EmitKeyedPropertyLoad(expr); + if (!expr->IsSuperAccess()) { + VisitForStackValue(expr->obj()); + VisitForAccumulatorValue(expr->key()); + __ Move(LoadDescriptor::NameRegister(), x0); + __ Pop(LoadDescriptor::ReceiverRegister()); + EmitKeyedPropertyLoad(expr); + } else { + VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(expr->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForStackValue(expr->key()); + EmitKeyedSuperPropertyLoad(expr); + } context()->Plug(x0); } } @@ -2464,6 +2598,43 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, } +void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { + Expression* callee = expr->expression(); + DCHECK(callee->IsProperty()); + Property* prop = callee->AsProperty(); + DCHECK(prop->IsSuperAccess()); + + SetSourcePosition(prop->position()); + + // Load the function from the receiver. + const Register scratch = x10; + SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference(); + EmitLoadHomeObject(super_ref); + __ Push(x0); + VisitForAccumulatorValue(super_ref->this_var()); + __ Push(x0); + __ Peek(scratch, kPointerSize); + __ Push(x0, scratch); + VisitForStackValue(prop->key()); + + // Stack here: + // - home_object + // - this (receiver) + // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. + // - home_object + // - key + __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); + + // Replace home_object with target function. + __ Poke(x0, kPointerSize); + + // Stack here: + // - target function + // - this (receiver) + EmitCall(expr, CallICState::METHOD); +} + + void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { // Load the arguments. ZoneList* args = expr->arguments(); @@ -2478,7 +2649,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { Handle ic = CallIC::initialize_stub( isolate(), arg_count, call_type); - __ Mov(x3, Smi::FromInt(expr->CallFeedbackSlot())); + __ Mov(x3, SmiFromSlot(expr->CallFeedbackSlot())); __ Peek(x1, (arg_count + 1) * kXRegSize); // Don't assign a type feedback id to the IC, since type feedback is provided // by the vector above. @@ -2496,11 +2667,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { // Prepare to push a copy of the first argument or undefined if it doesn't // exist. if (arg_count > 0) { - __ Peek(x10, arg_count * kXRegSize); + __ Peek(x9, arg_count * kXRegSize); } else { - __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); + __ LoadRoot(x9, Heap::kUndefinedValueRootIndex); } + __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); // Prepare to push the receiver of the enclosing function. int receiver_offset = 2 + info_->scope()->num_parameters(); __ Ldr(x11, MemOperand(fp, receiver_offset * kPointerSize)); @@ -2511,10 +2683,18 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { __ Mov(x13, Smi::FromInt(scope()->start_position())); // Push. - __ Push(x10, x11, x12, x13); + __ Push(x9, x10, x11, x12, x13); // Do the runtime call. - __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); + __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); +} + + +void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference* super_ref) { + DCHECK(super_ref != NULL); + __ ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); + __ Push(x0); + __ CallRuntime(Runtime::kGetPrototype, 1); } @@ -2557,6 +2737,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { // The runtime call returns a pair of values in x0 (function) and // x1 (receiver). Touch up the stack with the right values. __ PokePair(x1, x0, arg_count * kPointerSize); + + PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); } // Record source position for debugger. @@ -2592,6 +2774,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ Push(context_register(), x10); __ CallRuntime(Runtime::kLoadLookupSlot, 2); __ Push(x0, x1); // Receiver, function. + PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); // If fast case code has been generated, emit code to push the // function and receiver and have the slow path jump around this @@ -2614,9 +2797,12 @@ void FullCodeGenerator::VisitCall(Call* expr) { } else if (call_type == Call::PROPERTY_CALL) { Property* property = callee->AsProperty(); bool is_named_call = property->key()->IsPropertyName(); - // super.x() is handled in EmitCallWithLoadIC. - if (property->IsSuperAccess() && is_named_call) { - EmitSuperCallWithLoadIC(expr); + if (property->IsSuperAccess()) { + if (is_named_call) { + EmitSuperCallWithLoadIC(expr); + } else { + EmitKeyedSuperCallWithLoadIC(expr); + } } else { { PreservePositionScope scope(masm()->positions_recorder()); @@ -2628,6 +2814,12 @@ void FullCodeGenerator::VisitCall(Call* expr) { EmitKeyedCallWithLoadIC(expr, property->key()); } } + } else if (call_type == Call::SUPER_CALL) { + SuperReference* super_ref = callee->AsSuperReference(); + EmitLoadSuperConstructor(super_ref); + __ Push(result_register()); + VisitForStackValue(super_ref->this_var()); + EmitCall(expr, CallICState::METHOD); } else { DCHECK(call_type == Call::OTHER_CALL); // Call to an arbitrary expression not handled specially above. @@ -2656,7 +2848,12 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // Push constructor on the stack. If it's not a function it's used as // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // ignored. - VisitForStackValue(expr->expression()); + if (expr->expression()->IsSuperReference()) { + EmitLoadSuperConstructor(expr->expression()->AsSuperReference()); + __ Push(result_register()); + } else { + VisitForStackValue(expr->expression()); + } // Push the arguments ("left-to-right") on the stack. ZoneList* args = expr->arguments(); @@ -2676,12 +2873,12 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // Record call targets in unoptimized code. if (FLAG_pretenuring_call_new) { EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); - DCHECK(expr->AllocationSiteFeedbackSlot() == - expr->CallNewFeedbackSlot() + 1); + DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() == + expr->CallNewFeedbackSlot().ToInt() + 1); } __ LoadObject(x2, FeedbackVector()); - __ Mov(x3, Smi::FromInt(expr->CallNewFeedbackSlot())); + __ Mov(x3, SmiFromSlot(expr->CallNewFeedbackSlot())); CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); @@ -3004,6 +3201,32 @@ void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { } +void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) { + ZoneList* args = expr->arguments(); + DCHECK(args->length() == 1); + + VisitForAccumulatorValue(args->at(0)); + + Label materialize_true, materialize_false; + Label* if_true = NULL; + Label* if_false = NULL; + Label* fall_through = NULL; + context()->PrepareTest(&materialize_true, &materialize_false, &if_true, + &if_false, &fall_through); + + __ JumpIfSmi(x0, if_false); + Register map = x10; + Register type_reg = x11; + __ Ldr(map, FieldMemOperand(x0, HeapObject::kMapOffset)); + __ Ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); + __ Sub(type_reg, type_reg, Operand(FIRST_JS_PROXY_TYPE)); + __ Cmp(type_reg, Operand(LAST_JS_PROXY_TYPE - FIRST_JS_PROXY_TYPE)); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); + Split(ls, if_true, if_false, fall_through); + + context()->Plug(if_true, if_false); +} + void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { DCHECK(expr->arguments()->length() == 0); @@ -3883,7 +4106,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { __ Mov(LoadDescriptor::NameRegister(), Operand(name)); if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(expr->CallRuntimeFeedbackSlot())); + SmiFromSlot(expr->CallRuntimeFeedbackSlot())); CallLoadIC(NOT_CONTEXTUAL); } else { CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); @@ -4037,22 +4260,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { Comment cmnt(masm_, "[ CountOperation"); SetSourcePosition(expr->position()); - // Expression can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->expression()->AsProperty(); - // In case of a property we use the uninitialized expression context - // of the key to detect a named property. - if (prop != NULL) { - assign_type = - (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; - if (prop->IsSuperAccess()) { - // throw exception. - VisitSuperReference(prop->obj()->AsSuperReference()); - return; - } - } + LhsKind assign_type = GetAssignType(prop); // Evaluate expression and get value. if (assign_type == VARIABLE) { @@ -4064,18 +4273,52 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix() && !context()->IsEffect()) { __ Push(xzr); } - if (assign_type == NAMED_PROPERTY) { - // Put the object both on the stack and in the register. - VisitForStackValue(prop->obj()); - __ Peek(LoadDescriptor::ReceiverRegister(), 0); - EmitNamedPropertyLoad(prop); - } else { - // KEYED_PROPERTY - VisitForStackValue(prop->obj()); - VisitForStackValue(prop->key()); - __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize); - __ Peek(LoadDescriptor::NameRegister(), 0); - EmitKeyedPropertyLoad(prop); + switch (assign_type) { + case NAMED_PROPERTY: { + // Put the object both on the stack and in the register. + VisitForStackValue(prop->obj()); + __ Peek(LoadDescriptor::ReceiverRegister(), 0); + EmitNamedPropertyLoad(prop); + break; + } + + case NAMED_SUPER_PROPERTY: { + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + const Register scratch = x10; + __ Peek(scratch, kPointerSize); + __ Push(scratch, result_register()); + EmitNamedSuperPropertyLoad(prop); + break; + } + + case KEYED_SUPER_PROPERTY: { + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(prop->key()); + __ Push(result_register()); + const Register scratch1 = x10; + const Register scratch2 = x11; + __ Peek(scratch1, 2 * kPointerSize); + __ Peek(scratch2, kPointerSize); + __ Push(scratch1, scratch2, result_register()); + EmitKeyedSuperPropertyLoad(prop); + break; + } + + case KEYED_PROPERTY: { + VisitForStackValue(prop->obj()); + VisitForStackValue(prop->key()); + __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize); + __ Peek(LoadDescriptor::NameRegister(), 0); + EmitKeyedPropertyLoad(prop); + break; + } + + case VARIABLE: + UNREACHABLE(); } } @@ -4109,9 +4352,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case NAMED_PROPERTY: __ Poke(x0, kPointerSize); break; + case NAMED_SUPER_PROPERTY: + __ Poke(x0, kPointerSize * 2); + break; case KEYED_PROPERTY: __ Poke(x0, kPointerSize * 2); break; + case KEYED_SUPER_PROPERTY: + __ Poke(x0, kPointerSize * 3); + break; } } } @@ -4139,9 +4388,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case NAMED_PROPERTY: __ Poke(x0, kXRegSize); break; + case NAMED_SUPER_PROPERTY: + __ Poke(x0, 2 * kXRegSize); + break; case KEYED_PROPERTY: __ Poke(x0, 2 * kXRegSize); break; + case KEYED_SUPER_PROPERTY: + __ Poke(x0, 3 * kXRegSize); + break; } } } @@ -4199,6 +4454,28 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } break; } + case NAMED_SUPER_PROPERTY: { + EmitNamedSuperPropertyStore(prop); + if (expr->is_postfix()) { + if (!context()->IsEffect()) { + context()->PlugTOS(); + } + } else { + context()->Plug(x0); + } + break; + } + case KEYED_SUPER_PROPERTY: { + EmitKeyedSuperPropertyStore(prop); + if (expr->is_postfix()) { + if (!context()->IsEffect()) { + context()->PlugTOS(); + } + } else { + context()->Plug(x0); + } + break; + } case KEYED_PROPERTY: { __ Pop(StoreDescriptor::NameRegister()); __ Pop(StoreDescriptor::ReceiverRegister()); @@ -4229,7 +4506,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { __ Mov(LoadDescriptor::NameRegister(), Operand(proxy->name())); if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(proxy->VariableFeedbackSlot())); + SmiFromSlot(proxy->VariableFeedbackSlot())); } // Use a regular load, not a contextual load, to avoid a reference // error. @@ -4585,7 +4862,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ Peek(load_name, 2 * kPointerSize); if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(expr->KeyedLoadFeedbackSlot())); + SmiFromSlot(expr->KeyedLoadFeedbackSlot())); } Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); CallIC(ic, TypeFeedbackId::None()); @@ -4605,7 +4882,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(expr->DoneFeedbackSlot())); + SmiFromSlot(expr->DoneFeedbackSlot())); } CallLoadIC(NOT_CONTEXTUAL); // x0=result.done // The ToBooleanStub argument (result.done) is in x0. @@ -4618,7 +4895,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" if (FLAG_vector_ics) { __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(expr->ValueFeedbackSlot())); + SmiFromSlot(expr->ValueFeedbackSlot())); } CallLoadIC(NOT_CONTEXTUAL); // x0=result.value context()->DropAndPlug(2, x0); // drop iter and g @@ -4640,7 +4917,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, // The value stays in x0, and is ultimately read by the resumed generator, as // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it - // is read to throw the value when the resumed generator is already closed. r1 + // is read to throw the value when the resumed generator is already closed. x1 // will hold the generator object until the activation has been resumed. VisitForStackValue(generator); VisitForAccumulatorValue(value); @@ -4754,16 +5031,18 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { Label gc_required; Label allocated; - Handle map(isolate()->native_context()->iterator_result_map()); + const int instance_size = 5 * kPointerSize; + DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(), + instance_size); // Allocate and populate an object with this form: { value: VAL, done: DONE } Register result = x0; - __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT); + __ Allocate(instance_size, result, x10, x11, &gc_required, TAG_OBJECT); __ B(&allocated); __ Bind(&gc_required); - __ Push(Smi::FromInt(map->instance_size())); + __ Push(Smi::FromInt(instance_size)); __ CallRuntime(Runtime::kAllocateInNewSpace, 1); __ Ldr(context_register(), MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -4774,11 +5053,13 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { Register boolean_done = x3; Register empty_fixed_array = x4; Register untagged_result = x5; - __ Mov(map_reg, Operand(map)); + __ Ldr(map_reg, GlobalObjectMemOperand()); + __ Ldr(map_reg, FieldMemOperand(map_reg, GlobalObject::kNativeContextOffset)); + __ Ldr(map_reg, + ContextMemOperand(map_reg, Context::ITERATOR_RESULT_MAP_INDEX)); __ Pop(result_value); __ Mov(boolean_done, Operand(isolate()->factory()->ToBoolean(done))); __ Mov(empty_fixed_array, Operand(isolate()->factory()->empty_fixed_array())); - DCHECK_EQ(map->instance_size(), 5 * kPointerSize); STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize == JSObject::kElementsOffset); STATIC_ASSERT(JSGeneratorObject::kResultValuePropertyOffset + kPointerSize == diff --git a/deps/v8/src/arm64/interface-descriptors-arm64.cc b/deps/v8/src/arm64/interface-descriptors-arm64.cc index 690c8c28ee..57eebcc3b5 100644 --- a/deps/v8/src/arm64/interface-descriptors-arm64.cc +++ b/deps/v8/src/arm64/interface-descriptors-arm64.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return x2; } const Register StoreDescriptor::ValueRegister() { return x0; } +const Register StoreTransitionDescriptor::MapRegister() { return x3; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return x3; } @@ -182,6 +185,14 @@ void TransitionElementsKindDescriptor::Initialize( } +void AllocateHeapNumberDescriptor::Initialize( + CallInterfaceDescriptorData* data) { + // cp: context + Register registers[] = {cp}; + data->Initialize(arraysize(registers), registers, nullptr); +} + + void ArrayConstructorConstantArgCountDescriptor::Initialize( CallInterfaceDescriptorData* data) { // cp: context diff --git a/deps/v8/src/arm64/lithium-arm64.cc b/deps/v8/src/arm64/lithium-arm64.cc index 502b046927..241bc4b20b 100644 --- a/deps/v8/src/arm64/lithium-arm64.cc +++ b/deps/v8/src/arm64/lithium-arm64.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "src/v8.h" #include "src/arm64/lithium-codegen-arm64.h" @@ -282,9 +284,9 @@ void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { void LStoreNamedField::PrintDataTo(StringStream* stream) { object()->PrintTo(stream); - OStringStream os; + std::ostringstream os; os << hydrogen()->access(); - stream->Add(os.c_str()); + stream->Add(os.str().c_str()); stream->Add(" <- "); value()->PrintTo(stream); } @@ -2234,11 +2236,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, (JSShiftAmountFromHConstant(instr->right()) == 0); bool can_deopt = false; if ((op == Token::SHR) && right_can_be_zero) { - if (FLAG_opt_safe_uint32_operations) { - can_deopt = !instr->CheckFlag(HInstruction::kUint32); - } else { - can_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); - } + can_deopt = !instr->CheckFlag(HInstruction::kUint32); } LInstruction* result; diff --git a/deps/v8/src/arm64/lithium-codegen-arm64.cc b/deps/v8/src/arm64/lithium-codegen-arm64.cc index b9b67d9bbd..a285e7bcc1 100644 --- a/deps/v8/src/arm64/lithium-codegen-arm64.cc +++ b/deps/v8/src/arm64/lithium-codegen-arm64.cc @@ -3371,13 +3371,14 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { template void LCodeGen::EmitVectorLoadICRegisters(T* instr) { DCHECK(FLAG_vector_ics); - Register vector = ToRegister(instr->temp_vector()); - DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); - __ Mov(vector, instr->hydrogen()->feedback_vector()); + Register vector_register = ToRegister(instr->temp_vector()); + DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); + Handle vector = instr->hydrogen()->feedback_vector(); + __ Mov(vector_register, vector); // No need to allocate this register. DCHECK(VectorLoadICDescriptor::SlotRegister().is(x0)); - __ Mov(VectorLoadICDescriptor::SlotRegister(), - Smi::FromInt(instr->hydrogen()->slot())); + int index = vector->GetIndex(instr->hydrogen()->slot()); + __ Mov(VectorLoadICDescriptor::SlotRegister(), Smi::FromInt(index)); } @@ -3391,7 +3392,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { EmitVectorLoadICRegisters(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle ic = CodeFactory::LoadIC(isolate(), mode).code(); + Handle ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3645,7 +3646,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); + Handle ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); DCHECK(ToRegister(instr->result()).Is(x0)); @@ -3701,7 +3702,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); + Handle ic = + CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); DCHECK(ToRegister(instr->result()).is(x0)); diff --git a/deps/v8/src/arm64/macro-assembler-arm64-inl.h b/deps/v8/src/arm64/macro-assembler-arm64-inl.h index 23767e48b3..4a4d644dae 100644 --- a/deps/v8/src/arm64/macro-assembler-arm64-inl.h +++ b/deps/v8/src/arm64/macro-assembler-arm64-inl.h @@ -825,6 +825,12 @@ void MacroAssembler::Frintn(const FPRegister& fd, const FPRegister& fn) { } +void MacroAssembler::Frintp(const FPRegister& fd, const FPRegister& fn) { + DCHECK(allow_macro_instructions_); + frintp(fd, fn); +} + + void MacroAssembler::Frintz(const FPRegister& fd, const FPRegister& fn) { DCHECK(allow_macro_instructions_); frintz(fd, fn); @@ -1120,6 +1126,14 @@ void MacroAssembler::Smulh(const Register& rd, } +void MacroAssembler::Umull(const Register& rd, const Register& rn, + const Register& rm) { + DCHECK(allow_macro_instructions_); + DCHECK(!rd.IsZero()); + umaddl(rd, rn, rm, xzr); +} + + void MacroAssembler::Stnp(const CPURegister& rt, const CPURegister& rt2, const MemOperand& dst) { diff --git a/deps/v8/src/arm64/macro-assembler-arm64.cc b/deps/v8/src/arm64/macro-assembler-arm64.cc index 3d6709777f..e0a2190f28 100644 --- a/deps/v8/src/arm64/macro-assembler-arm64.cc +++ b/deps/v8/src/arm64/macro-assembler-arm64.cc @@ -3064,6 +3064,13 @@ void MacroAssembler::Prologue(bool code_pre_aging) { } +void MacroAssembler::EnterFrame(StackFrame::Type type, + bool load_constant_pool_pointer_reg) { + // Out-of-line constant pool not implemented on arm64. + UNREACHABLE(); +} + + void MacroAssembler::EnterFrame(StackFrame::Type type) { DCHECK(jssp.Is(StackPointer())); UseScratchRegisterScope temps(this); diff --git a/deps/v8/src/arm64/macro-assembler-arm64.h b/deps/v8/src/arm64/macro-assembler-arm64.h index 7a106a18b9..cff42d7df7 100644 --- a/deps/v8/src/arm64/macro-assembler-arm64.h +++ b/deps/v8/src/arm64/macro-assembler-arm64.h @@ -422,6 +422,7 @@ class MacroAssembler : public Assembler { inline void Frinta(const FPRegister& fd, const FPRegister& fn); inline void Frintm(const FPRegister& fd, const FPRegister& fn); inline void Frintn(const FPRegister& fd, const FPRegister& fn); + inline void Frintp(const FPRegister& fd, const FPRegister& fn); inline void Frintz(const FPRegister& fd, const FPRegister& fn); inline void Fsqrt(const FPRegister& fd, const FPRegister& fn); inline void Fsub(const FPRegister& fd, @@ -489,6 +490,7 @@ class MacroAssembler : public Assembler { inline void Smulh(const Register& rd, const Register& rn, const Register& rm); + inline void Umull(const Register& rd, const Register& rn, const Register& rm); inline void Stnp(const CPURegister& rt, const CPURegister& rt2, const MemOperand& dst); @@ -1627,6 +1629,7 @@ class MacroAssembler : public Assembler { // Activation support. void EnterFrame(StackFrame::Type type); + void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg); void LeaveFrame(StackFrame::Type type); // Returns map with validated enum cache in object register. diff --git a/deps/v8/src/arm64/simulator-arm64.cc b/deps/v8/src/arm64/simulator-arm64.cc index 129252b49b..569be9cc83 100644 --- a/deps/v8/src/arm64/simulator-arm64.cc +++ b/deps/v8/src/arm64/simulator-arm64.cc @@ -2463,6 +2463,12 @@ void Simulator::VisitFPDataProcessing1Source(Instruction* instr) { set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break; case FRINTM_d: set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break; + case FRINTP_s: + set_sreg(fd, FPRoundInt(sreg(fn), FPPositiveInfinity)); + break; + case FRINTP_d: + set_dreg(fd, FPRoundInt(dreg(fn), FPPositiveInfinity)); + break; case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break; case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break; case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break; @@ -2767,6 +2773,10 @@ double Simulator::FPRoundInt(double value, FPRounding round_mode) { // We always use floor(value). break; } + case FPPositiveInfinity: { + int_result = ceil(value); + break; + } default: UNIMPLEMENTED(); } return int_result; diff --git a/deps/v8/src/array-iterator.js b/deps/v8/src/array-iterator.js index 82779bc228..864d5c1fc2 100644 --- a/deps/v8/src/array-iterator.js +++ b/deps/v8/src/array-iterator.js @@ -112,6 +112,8 @@ function SetUpArrayIterator() { %FunctionSetName(ArrayIteratorIterator, '[Symbol.iterator]'); %AddNamedProperty(ArrayIterator.prototype, symbolIterator, ArrayIteratorIterator, DONT_ENUM); + %AddNamedProperty(ArrayIterator.prototype, symbolToStringTag, + "Array Iterator", READ_ONLY | DONT_ENUM); } SetUpArrayIterator(); @@ -120,8 +122,8 @@ function ExtendArrayPrototype() { %CheckIsBootstrapping(); InstallFunctions($Array.prototype, DONT_ENUM, $Array( + // No 'values' since it breaks webcompat: http://crbug.com/409858 'entries', ArrayEntries, - 'values', ArrayValues, 'keys', ArrayKeys )); diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js index 44deff7de4..29fa8318e2 100644 --- a/deps/v8/src/array.js +++ b/deps/v8/src/array.js @@ -90,7 +90,8 @@ function UseSparseVariant(array, length, is_array, touched) { // Only use the sparse variant on arrays that are likely to be sparse and the // number of elements touched in the operation is relatively small compared to // the overall size of the array. - if (!is_array || length < 1000 || %IsObserved(array)) { + if (!is_array || length < 1000 || %IsObserved(array) || + %HasComplexElements(array)) { return false; } if (!%_IsSmi(length)) { @@ -203,7 +204,7 @@ function ConvertToLocaleString(e) { // This function implements the optimized splice implementation that can use // special array operations to handle sparse arrays in a sensible fashion. -function SmartSlice(array, start_i, del_count, len, deleted_elements) { +function SparseSlice(array, start_i, del_count, len, deleted_elements) { // Move deleted elements to a new array (the return value from splice). var indices = %GetArrayKeys(array, start_i + del_count); if (IS_NUMBER(indices)) { @@ -211,7 +212,7 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) { for (var i = start_i; i < limit; ++i) { var current = array[i]; if (!IS_UNDEFINED(current) || i in array) { - deleted_elements[i - start_i] = current; + %AddElement(deleted_elements, i - start_i, current, NONE); } } } else { @@ -222,7 +223,7 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) { if (key >= start_i) { var current = array[key]; if (!IS_UNDEFINED(current) || key in array) { - deleted_elements[key - start_i] = current; + %AddElement(deleted_elements, key - start_i, current, NONE); } } } @@ -233,7 +234,9 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) { // This function implements the optimized splice implementation that can use // special array operations to handle sparse arrays in a sensible fashion. -function SmartMove(array, start_i, del_count, len, num_additional_args) { +function SparseMove(array, start_i, del_count, len, num_additional_args) { + // Bail out if no moving is necessary. + if (num_additional_args === del_count) return; // Move data to new array. var new_array = new InternalArray(len - del_count + num_additional_args); var indices = %GetArrayKeys(array, len); @@ -281,12 +284,11 @@ function SmartMove(array, start_i, del_count, len, num_additional_args) { function SimpleSlice(array, start_i, del_count, len, deleted_elements) { for (var i = 0; i < del_count; i++) { var index = start_i + i; - // The spec could also be interpreted such that %HasOwnProperty - // would be the appropriate test. We follow KJS in consulting the - // prototype. - var current = array[index]; - if (!IS_UNDEFINED(current) || index in array) { - deleted_elements[i] = current; + if (index in array) { + var current = array[index]; + // The spec requires [[DefineOwnProperty]] here, %AddElement is close + // enough (in that it ignores the prototype). + %AddElement(deleted_elements, i, current, NONE); } } } @@ -300,12 +302,8 @@ function SimpleMove(array, start_i, del_count, len, num_additional_args) { for (var i = len - del_count; i > start_i; i--) { var from_index = i + del_count - 1; var to_index = i + num_additional_args - 1; - // The spec could also be interpreted such that - // %HasOwnProperty would be the appropriate test. We follow - // KJS in consulting the prototype. - var current = array[from_index]; - if (!IS_UNDEFINED(current) || from_index in array) { - array[to_index] = current; + if (from_index in array) { + array[to_index] = array[from_index]; } else { delete array[to_index]; } @@ -314,12 +312,8 @@ function SimpleMove(array, start_i, del_count, len, num_additional_args) { for (var i = start_i; i < len - del_count; i++) { var from_index = i + del_count; var to_index = i + num_additional_args; - // The spec could also be interpreted such that - // %HasOwnProperty would be the appropriate test. We follow - // KJS in consulting the prototype. - var current = array[from_index]; - if (!IS_UNDEFINED(current) || from_index in array) { - array[to_index] = current; + if (from_index in array) { + array[to_index] = array[from_index]; } else { delete array[to_index]; } @@ -349,7 +343,7 @@ function ArrayToString() { func = array.join; } if (!IS_SPEC_FUNCTION(func)) { - return %_CallFunction(array, ObjectToString); + return %_CallFunction(array, NoSideEffectsObjectToString); } return %_CallFunction(array, func); } @@ -378,6 +372,14 @@ function ArrayJoin(separator) { var result = %_FastOneByteArrayJoin(array, separator); if (!IS_UNDEFINED(result)) return result; + // Fast case for one-element arrays. + if (length === 1) { + var e = array[0]; + if (IS_STRING(e)) return e; + if (IS_NULL_OR_UNDEFINED(e)) return ''; + return NonStringToString(e); + } + return Join(array, length, separator, ConvertToString); } @@ -596,8 +598,8 @@ function ArrayShift() { var first = array[0]; - if (IS_ARRAY(array)) { - SmartMove(array, 0, 1, len, 0); + if (UseSparseVariant(array, len, IS_ARRAY(array), len)) { + SparseMove(array, 0, 1, len, 0); } else { SimpleMove(array, 0, 1, len, 0); } @@ -636,10 +638,10 @@ function ArrayUnshift(arg1) { // length == 1 var array = TO_OBJECT_INLINE(this); var len = TO_UINT32(array.length); var num_arguments = %_ArgumentsLength(); - var is_sealed = ObjectIsSealed(array); - if (IS_ARRAY(array) && !is_sealed && len > 0) { - SmartMove(array, 0, 0, len, num_arguments); + if (len > 0 && UseSparseVariant(array, len, IS_ARRAY(array), len) && + !ObjectIsSealed(array)) { + SparseMove(array, 0, 0, len, num_arguments); } else { SimpleMove(array, 0, 0, len, num_arguments); } @@ -685,7 +687,7 @@ function ArraySlice(start, end) { if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) { %NormalizeElements(array); %NormalizeElements(result); - SmartSlice(array, start_i, end_i - start_i, len, result); + SparseSlice(array, start_i, end_i - start_i, len, result); } else { SimpleSlice(array, start_i, end_i - start_i, len, result); } @@ -801,8 +803,8 @@ function ArraySplice(start, delete_count) { if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) { %NormalizeElements(array); %NormalizeElements(deleted_elements); - SmartSlice(array, start_i, del_count, len, deleted_elements); - SmartMove(array, start_i, del_count, len, num_elements_to_add); + SparseSlice(array, start_i, del_count, len, deleted_elements); + SparseMove(array, start_i, del_count, len, num_elements_to_add); } else { SimpleSlice(array, start_i, del_count, len, deleted_elements); SimpleMove(array, start_i, del_count, len, num_elements_to_add); @@ -1125,10 +1127,11 @@ function ArrayFilter(f, receiver) { if (!IS_SPEC_FUNCTION(f)) { throw MakeTypeError('called_non_callable', [ f ]); } + var needs_wrapper = false; if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) { - receiver = ToObject(receiver); + } else { + needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver); } var result = new $Array(); @@ -1140,7 +1143,8 @@ function ArrayFilter(f, receiver) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - if (%_CallFunction(receiver, element, i, array, f)) { + var new_receiver = needs_wrapper ? ToObject(receiver) : receiver; + if (%_CallFunction(new_receiver, element, i, array, f)) { accumulator[accumulator_length++] = element; } } @@ -1161,10 +1165,11 @@ function ArrayForEach(f, receiver) { if (!IS_SPEC_FUNCTION(f)) { throw MakeTypeError('called_non_callable', [ f ]); } + var needs_wrapper = false; if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) { - receiver = ToObject(receiver); + } else { + needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver); } var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); @@ -1173,7 +1178,8 @@ function ArrayForEach(f, receiver) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - %_CallFunction(receiver, element, i, array, f); + var new_receiver = needs_wrapper ? ToObject(receiver) : receiver; + %_CallFunction(new_receiver, element, i, array, f); } } } @@ -1192,10 +1198,11 @@ function ArraySome(f, receiver) { if (!IS_SPEC_FUNCTION(f)) { throw MakeTypeError('called_non_callable', [ f ]); } + var needs_wrapper = false; if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) { - receiver = ToObject(receiver); + } else { + needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver); } var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); @@ -1204,7 +1211,8 @@ function ArraySome(f, receiver) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - if (%_CallFunction(receiver, element, i, array, f)) return true; + var new_receiver = needs_wrapper ? ToObject(receiver) : receiver; + if (%_CallFunction(new_receiver, element, i, array, f)) return true; } } return false; @@ -1222,10 +1230,11 @@ function ArrayEvery(f, receiver) { if (!IS_SPEC_FUNCTION(f)) { throw MakeTypeError('called_non_callable', [ f ]); } + var needs_wrapper = false; if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) { - receiver = ToObject(receiver); + } else { + needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver); } var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); @@ -1234,7 +1243,8 @@ function ArrayEvery(f, receiver) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - if (!%_CallFunction(receiver, element, i, array, f)) return false; + var new_receiver = needs_wrapper ? ToObject(receiver) : receiver; + if (!%_CallFunction(new_receiver, element, i, array, f)) return false; } } return true; @@ -1251,10 +1261,11 @@ function ArrayMap(f, receiver) { if (!IS_SPEC_FUNCTION(f)) { throw MakeTypeError('called_non_callable', [ f ]); } + var needs_wrapper = false; if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) { - receiver = ToObject(receiver); + } else { + needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver); } var result = new $Array(); @@ -1265,7 +1276,8 @@ function ArrayMap(f, receiver) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - accumulator[i] = %_CallFunction(receiver, element, i, array, f); + var new_receiver = needs_wrapper ? ToObject(receiver) : receiver; + accumulator[i] = %_CallFunction(new_receiver, element, i, array, f); } } %MoveArrayContents(accumulator, result); @@ -1398,9 +1410,8 @@ function ArrayReduce(callback, current) { var i = 0; find_initial: if (%_ArgumentsLength() < 2) { for (; i < length; i++) { - current = array[i]; - if (!IS_UNDEFINED(current) || i in array) { - i++; + if (i in array) { + current = array[i++]; break find_initial; } } @@ -1435,9 +1446,8 @@ function ArrayReduceRight(callback, current) { var i = length - 1; find_initial: if (%_ArgumentsLength() < 2) { for (; i >= 0; i--) { - current = array[i]; - if (!IS_UNDEFINED(current) || i in array) { - i--; + if (i in array) { + current = array[i--]; break find_initial; } } @@ -1481,7 +1491,6 @@ function SetUpArray() { find: true, findIndex: true, keys: true, - values: true, }; %AddNamedProperty($Array.prototype, symbolUnscopables, unscopables, DONT_ENUM | READ_ONLY); diff --git a/deps/v8/src/arraybuffer.js b/deps/v8/src/arraybuffer.js index e1c887fdb8..cf00693be7 100644 --- a/deps/v8/src/arraybuffer.js +++ b/deps/v8/src/arraybuffer.js @@ -77,6 +77,9 @@ function SetUpArrayBuffer() { %AddNamedProperty( $ArrayBuffer.prototype, "constructor", $ArrayBuffer, DONT_ENUM); + %AddNamedProperty($ArrayBuffer.prototype, + symbolToStringTag, "ArrayBuffer", DONT_ENUM | READ_ONLY); + InstallGetter($ArrayBuffer.prototype, "byteLength", ArrayBufferGetByteLen); InstallFunctions($ArrayBuffer, DONT_ENUM, $Array( diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index 0d868aa641..c73b470c28 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -37,6 +37,7 @@ #include #include "src/api.h" #include "src/base/cpu.h" +#include "src/base/functional.h" #include "src/base/lazy-instance.h" #include "src/base/platform/platform.h" #include "src/builtins.h" @@ -130,7 +131,8 @@ AssemblerBase::AssemblerBase(Isolate* isolate, void* buffer, int buffer_size) emit_debug_code_(FLAG_debug_code), predictable_code_size_(false), // We may use the assembler without an isolate. - serializer_enabled_(isolate && isolate->serializer_enabled()) { + serializer_enabled_(isolate && isolate->serializer_enabled()), + ool_constant_pool_available_(false) { if (FLAG_mask_constants_with_cookie && isolate != NULL) { jit_cookie_ = isolate->random_number_generator()->NextInt(); } @@ -794,8 +796,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { } -void RelocInfo::Print(Isolate* isolate, OStream& os) { // NOLINT - os << pc_ << " " << RelocModeName(rmode_); +void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT + os << static_cast(pc_) << " " << RelocModeName(rmode_); if (IsComment(rmode_)) { os << " (" << reinterpret_cast(data_) << ")"; } else if (rmode_ == EMBEDDED_OBJECT) { @@ -803,11 +805,11 @@ void RelocInfo::Print(Isolate* isolate, OStream& os) { // NOLINT } else if (rmode_ == EXTERNAL_REFERENCE) { ExternalReferenceEncoder ref_encoder(isolate); os << " (" << ref_encoder.NameOfAddress(target_reference()) << ") (" - << target_reference() << ")"; + << static_cast(target_reference()) << ")"; } else if (IsCodeTarget(rmode_)) { Code* code = Code::GetCodeFromTargetAddress(target_address()); - os << " (" << Code::Kind2String(code->kind()) << ") (" << target_address() - << ")"; + os << " (" << Code::Kind2String(code->kind()) << ") (" + << static_cast(target_address()) << ")"; if (rmode_ == CODE_TARGET_WITH_ID) { os << " (id=" << static_cast(data_) << ")"; } @@ -1521,6 +1523,29 @@ ExternalReference ExternalReference::debug_step_in_fp_address( } +bool operator==(ExternalReference lhs, ExternalReference rhs) { + return lhs.address() == rhs.address(); +} + + +bool operator!=(ExternalReference lhs, ExternalReference rhs) { + return !(lhs == rhs); +} + + +size_t hash_value(ExternalReference reference) { + return base::hash
()(reference.address()); +} + + +std::ostream& operator<<(std::ostream& os, ExternalReference reference) { + os << static_cast(reference.address()); + const Runtime::Function* fn = Runtime::FunctionForEntry(reference.address()); + if (fn) os << "<" << fn->name << ".entry>"; + return os; +} + + void PositionsRecorder::RecordPosition(int pos) { DCHECK(pos != RelocInfo::kNoPosition); DCHECK(pos >= 0); diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 37e82ca35c..e95b7edf75 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -79,6 +79,16 @@ class AssemblerBase: public Malloced { return (enabled_cpu_features_ & (static_cast(1) << f)) != 0; } + bool is_ool_constant_pool_available() const { + if (FLAG_enable_ool_constant_pool) { + return ool_constant_pool_available_; + } else { + // Out-of-line constant pool not supported on this architecture. + UNREACHABLE(); + return false; + } + } + // Overwrite a host NaN with a quiet target NaN. Used by mksnapshot for // cross-snapshotting. static void QuietNaN(HeapObject* nan) { } @@ -98,6 +108,15 @@ class AssemblerBase: public Malloced { int buffer_size_; bool own_buffer_; + void set_ool_constant_pool_available(bool available) { + if (FLAG_enable_ool_constant_pool) { + ool_constant_pool_available_ = available; + } else { + // Out-of-line constant pool not supported on this architecture. + UNREACHABLE(); + } + } + // The program counter, which points into the buffer above and moves forward. byte* pc_; @@ -108,6 +127,14 @@ class AssemblerBase: public Malloced { bool emit_debug_code_; bool predictable_code_size_; bool serializer_enabled_; + + // Indicates whether the constant pool can be accessed, which is only possible + // if the pp register points to the current code object's constant pool. + bool ool_constant_pool_available_; + + // Constant pool. + friend class FrameAndConstantPoolScope; + friend class ConstantPoolUnavailableScope; }; @@ -216,7 +243,7 @@ class CpuFeatures : public AllStatic { // unknown pc location. Assembler::bind() is used to bind a label to the // current pc. A label can be bound only once. -class Label BASE_EMBEDDED { +class Label { public: enum Distance { kNear, kFar @@ -578,7 +605,7 @@ class RelocInfo { #ifdef ENABLE_DISASSEMBLER // Printing static const char* RelocModeName(Mode rmode); - void Print(Isolate* isolate, OStream& os); // NOLINT + void Print(Isolate* isolate, std::ostream& os); // NOLINT #endif // ENABLE_DISASSEMBLER #ifdef VERIFY_HEAP void Verify(Isolate* isolate); @@ -959,14 +986,6 @@ class ExternalReference BASE_EMBEDDED { static ExternalReference stress_deopt_count(Isolate* isolate); - bool operator==(const ExternalReference& other) const { - return address_ == other.address_; - } - - bool operator!=(const ExternalReference& other) const { - return !(*this == other); - } - private: explicit ExternalReference(void* address) : address_(address) {} @@ -987,6 +1006,13 @@ class ExternalReference BASE_EMBEDDED { void* address_; }; +bool operator==(ExternalReference, ExternalReference); +bool operator!=(ExternalReference, ExternalReference); + +size_t hash_value(ExternalReference); + +std::ostream& operator<<(std::ostream&, ExternalReference); + // ----------------------------------------------------------------------------- // Position recording support diff --git a/deps/v8/src/assert-scope.h b/deps/v8/src/assert-scope.h index 41baa65563..0f1e056fba 100644 --- a/deps/v8/src/assert-scope.h +++ b/deps/v8/src/assert-scope.h @@ -5,7 +5,7 @@ #ifndef V8_ASSERT_SCOPE_H_ #define V8_ASSERT_SCOPE_H_ -#include "include/v8stdint.h" +#include #include "src/base/macros.h" namespace v8 { diff --git a/deps/v8/src/ast-numbering.cc b/deps/v8/src/ast-numbering.cc new file mode 100644 index 0000000000..8994ac8c78 --- /dev/null +++ b/deps/v8/src/ast-numbering.cc @@ -0,0 +1,479 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/v8.h" + +#include "src/ast.h" +#include "src/ast-numbering.h" +#include "src/compiler.h" +#include "src/scopes.h" + +namespace v8 { +namespace internal { + + +class AstNumberingVisitor FINAL : public AstVisitor { + public: + explicit AstNumberingVisitor(Zone* zone) + : AstVisitor(), next_id_(BailoutId::FirstUsable().ToInt()) { + InitializeAstVisitor(zone); + } + + void Renumber(FunctionLiteral* node); + + private: +// AST node visitor interface. +#define DEFINE_VISIT(type) virtual void Visit##type(type* node) OVERRIDE; + AST_NODE_LIST(DEFINE_VISIT) +#undef DEFINE_VISIT + + void VisitStatements(ZoneList* statements) OVERRIDE; + void VisitDeclarations(ZoneList* declarations) OVERRIDE; + void VisitArguments(ZoneList* arguments); + void VisitObjectLiteralProperty(ObjectLiteralProperty* property); + + int ReserveIdRange(int n) { + int tmp = next_id_; + next_id_ += n; + return tmp; + } + + void IncrementNodeCount() { properties_.add_node_count(1); } + + int next_id_; + AstProperties properties_; + + DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); + DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor); +}; + + +void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) { + IncrementNodeCount(); + VisitVariableProxy(node->proxy()); +} + + +void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) { + IncrementNodeCount(); + VisitVariableProxy(node->proxy()); +} + + +void AstNumberingVisitor::VisitModuleUrl(ModuleUrl* node) { + IncrementNodeCount(); +} + + +void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) { + IncrementNodeCount(); +} + + +void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) { + IncrementNodeCount(); +} + + +void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) { + IncrementNodeCount(); +} + + +void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids())); +} + + +void AstNumberingVisitor::VisitNativeFunctionLiteral( + NativeFunctionLiteral* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids())); +} + + +void AstNumberingVisitor::VisitLiteral(Literal* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Literal::num_ids())); +} + + +void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids())); +} + + +void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(VariableProxy::num_ids())); +} + + +void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(ThisFunction::num_ids())); +} + + +void AstNumberingVisitor::VisitSuperReference(SuperReference* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(SuperReference::num_ids())); + Visit(node->this_var()); +} + + +void AstNumberingVisitor::VisitModuleDeclaration(ModuleDeclaration* node) { + IncrementNodeCount(); + VisitVariableProxy(node->proxy()); + Visit(node->module()); +} + + +void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) { + IncrementNodeCount(); + VisitVariableProxy(node->proxy()); + Visit(node->module()); +} + + +void AstNumberingVisitor::VisitModuleVariable(ModuleVariable* node) { + IncrementNodeCount(); + Visit(node->proxy()); +} + + +void AstNumberingVisitor::VisitModulePath(ModulePath* node) { + IncrementNodeCount(); + Visit(node->module()); +} + + +void AstNumberingVisitor::VisitModuleStatement(ModuleStatement* node) { + IncrementNodeCount(); + Visit(node->body()); +} + + +void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) { + IncrementNodeCount(); + Visit(node->expression()); +} + + +void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) { + IncrementNodeCount(); + Visit(node->expression()); +} + + +void AstNumberingVisitor::VisitYield(Yield* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Yield::num_ids())); + Visit(node->generator_object()); + Visit(node->expression()); +} + + +void AstNumberingVisitor::VisitThrow(Throw* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Throw::num_ids())); + Visit(node->exception()); +} + + +void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(UnaryOperation::num_ids())); + Visit(node->expression()); +} + + +void AstNumberingVisitor::VisitCountOperation(CountOperation* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(CountOperation::num_ids())); + Visit(node->expression()); +} + + +void AstNumberingVisitor::VisitBlock(Block* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Block::num_ids())); + if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations()); + VisitStatements(node->statements()); +} + + +void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) { + IncrementNodeCount(); + VisitVariableProxy(node->proxy()); + VisitFunctionLiteral(node->fun()); +} + + +void AstNumberingVisitor::VisitModuleLiteral(ModuleLiteral* node) { + IncrementNodeCount(); + VisitBlock(node->body()); +} + + +void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(CallRuntime::num_ids())); + VisitArguments(node->arguments()); +} + + +void AstNumberingVisitor::VisitWithStatement(WithStatement* node) { + IncrementNodeCount(); + Visit(node->expression()); + Visit(node->statement()); +} + + +void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids())); + Visit(node->body()); + Visit(node->cond()); +} + + +void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(WhileStatement::num_ids())); + Visit(node->cond()); + Visit(node->body()); +} + + +void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) { + IncrementNodeCount(); + Visit(node->try_block()); + Visit(node->catch_block()); +} + + +void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) { + IncrementNodeCount(); + Visit(node->try_block()); + Visit(node->finally_block()); +} + + +void AstNumberingVisitor::VisitProperty(Property* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Property::num_ids())); + Visit(node->key()); + Visit(node->obj()); +} + + +void AstNumberingVisitor::VisitAssignment(Assignment* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Assignment::num_ids())); + if (node->is_compound()) VisitBinaryOperation(node->binary_operation()); + Visit(node->target()); + Visit(node->value()); +} + + +void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(BinaryOperation::num_ids())); + Visit(node->left()); + Visit(node->right()); +} + + +void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(CompareOperation::num_ids())); + Visit(node->left()); + Visit(node->right()); +} + + +void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(ForInStatement::num_ids())); + Visit(node->each()); + Visit(node->enumerable()); + Visit(node->body()); +} + + +void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(ForOfStatement::num_ids())); + Visit(node->assign_iterator()); + Visit(node->next_result()); + Visit(node->result_done()); + Visit(node->assign_each()); + Visit(node->body()); +} + + +void AstNumberingVisitor::VisitConditional(Conditional* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Conditional::num_ids())); + Visit(node->condition()); + Visit(node->then_expression()); + Visit(node->else_expression()); +} + + +void AstNumberingVisitor::VisitIfStatement(IfStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(IfStatement::num_ids())); + Visit(node->condition()); + Visit(node->then_statement()); + if (node->HasElseStatement()) { + Visit(node->else_statement()); + } +} + + +void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(SwitchStatement::num_ids())); + Visit(node->tag()); + ZoneList* cases = node->cases(); + for (int i = 0; i < cases->length(); i++) { + VisitCaseClause(cases->at(i)); + } +} + + +void AstNumberingVisitor::VisitCaseClause(CaseClause* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(CaseClause::num_ids())); + if (!node->is_default()) Visit(node->label()); + VisitStatements(node->statements()); +} + + +void AstNumberingVisitor::VisitForStatement(ForStatement* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(ForStatement::num_ids())); + if (node->init() != NULL) Visit(node->init()); + if (node->cond() != NULL) Visit(node->cond()); + if (node->next() != NULL) Visit(node->next()); + Visit(node->body()); +} + + +void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(ClassLiteral::num_ids())); + if (node->extends()) Visit(node->extends()); + if (node->constructor()) Visit(node->constructor()); + for (int i = 0; i < node->properties()->length(); i++) { + VisitObjectLiteralProperty(node->properties()->at(i)); + } +} + + +void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(ObjectLiteral::num_ids())); + for (int i = 0; i < node->properties()->length(); i++) { + VisitObjectLiteralProperty(node->properties()->at(i)); + } +} + + +void AstNumberingVisitor::VisitObjectLiteralProperty( + ObjectLiteralProperty* node) { + Visit(node->key()); + Visit(node->value()); +} + + +void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(node->num_ids())); + for (int i = 0; i < node->values()->length(); i++) { + Visit(node->values()->at(i)); + } +} + + +void AstNumberingVisitor::VisitCall(Call* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(Call::num_ids())); + Visit(node->expression()); + VisitArguments(node->arguments()); +} + + +void AstNumberingVisitor::VisitCallNew(CallNew* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(CallNew::num_ids())); + Visit(node->expression()); + VisitArguments(node->arguments()); +} + + +void AstNumberingVisitor::VisitStatements(ZoneList* statements) { + if (statements == NULL) return; + for (int i = 0; i < statements->length(); i++) { + Visit(statements->at(i)); + } +} + + +void AstNumberingVisitor::VisitDeclarations( + ZoneList* declarations) { + for (int i = 0; i < declarations->length(); i++) { + Visit(declarations->at(i)); + } +} + + +void AstNumberingVisitor::VisitArguments(ZoneList* arguments) { + for (int i = 0; i < arguments->length(); i++) { + Visit(arguments->at(i)); + } +} + + +void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) { + IncrementNodeCount(); + node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids())); + // We don't recurse into the declarations or body of the function literal: + // you have to separately Renumber() each FunctionLiteral that you compile. +} + + +void AstNumberingVisitor::Renumber(FunctionLiteral* node) { + properties_.flags()->Add(*node->flags()); + properties_.increase_feedback_slots(node->slot_count()); + properties_.increase_ic_feedback_slots(node->ic_slot_count()); + + if (node->scope()->HasIllegalRedeclaration()) { + node->scope()->VisitIllegalRedeclaration(this); + return; + } + + Scope* scope = node->scope(); + VisitDeclarations(scope->declarations()); + if (scope->is_function_scope() && scope->function() != NULL) { + // Visit the name of the named function expression. + Visit(scope->function()); + } + VisitStatements(node->body()); + + node->set_ast_properties(&properties_); +} + + +bool AstNumbering::Renumber(FunctionLiteral* function, Zone* zone) { + AstNumberingVisitor visitor(zone); + visitor.Renumber(function); + return !visitor.HasStackOverflow(); +} +} +} // namespace v8::internal diff --git a/deps/v8/src/ast-numbering.h b/deps/v8/src/ast-numbering.h new file mode 100644 index 0000000000..ab97c22bdf --- /dev/null +++ b/deps/v8/src/ast-numbering.h @@ -0,0 +1,19 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_AST_NUMBERING_H_ +#define V8_AST_NUMBERING_H_ + +namespace v8 { +namespace internal { + +namespace AstNumbering { +// Assign type feedback IDs and bailout IDs to an AST node tree. +// +bool Renumber(FunctionLiteral* function, Zone* zone); +} +} +} // namespace v8::internal + +#endif // V8_AST_NUMBERING_H_ diff --git a/deps/v8/src/ast-value-factory.cc b/deps/v8/src/ast-value-factory.cc index ea8474ff52..518be23abc 100644 --- a/deps/v8/src/ast-value-factory.cc +++ b/deps/v8/src/ast-value-factory.cc @@ -117,14 +117,15 @@ bool AstRawString::IsOneByteEqualTo(const char* data) const { bool AstRawString::Compare(void* a, void* b) { - AstRawString* string1 = reinterpret_cast(a); - AstRawString* string2 = reinterpret_cast(b); - if (string1->is_one_byte_ != string2->is_one_byte_) return false; - if (string1->hash_ != string2->hash_) return false; - int length = string1->literal_bytes_.length(); - if (string2->literal_bytes_.length() != length) return false; - return memcmp(string1->literal_bytes_.start(), - string2->literal_bytes_.start(), length) == 0; + return *static_cast(a) == *static_cast(b); +} + +bool AstRawString::operator==(const AstRawString& rhs) const { + if (is_one_byte_ != rhs.is_one_byte_) return false; + if (hash_ != rhs.hash_) return false; + int len = literal_bytes_.length(); + if (rhs.literal_bytes_.length() != len) return false; + return memcmp(literal_bytes_.start(), rhs.literal_bytes_.start(), len) == 0; } @@ -158,9 +159,6 @@ bool AstValue::BooleanValue() const { return DoubleToBoolean(number_); case SMI: return smi_ != 0; - case STRING_ARRAY: - UNREACHABLE(); - break; case BOOLEAN: return bool_; case NULL_TYPE: @@ -201,22 +199,6 @@ void AstValue::Internalize(Isolate* isolate) { value_ = isolate->factory()->false_value(); } break; - case STRING_ARRAY: { - DCHECK(strings_ != NULL); - Factory* factory = isolate->factory(); - int len = strings_->length(); - Handle elements = factory->NewFixedArray(len, TENURED); - for (int i = 0; i < len; i++) { - const AstRawString* string = (*strings_)[i]; - Handle element = string->string(); - // Strings are already internalized. - DCHECK(!element.is_null()); - elements->set(i, *element); - } - value_ = - factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED); - break; - } case NULL_TYPE: value_ = isolate->factory()->null_value(); break; @@ -230,7 +212,7 @@ void AstValue::Internalize(Isolate* isolate) { } -const AstRawString* AstValueFactory::GetOneByteString( +AstRawString* AstValueFactory::GetOneByteStringInternal( Vector literal) { uint32_t hash = StringHasher::HashSequentialString( literal.start(), literal.length(), hash_seed_); @@ -238,7 +220,7 @@ const AstRawString* AstValueFactory::GetOneByteString( } -const AstRawString* AstValueFactory::GetTwoByteString( +AstRawString* AstValueFactory::GetTwoByteStringInternal( Vector literal) { uint32_t hash = StringHasher::HashSequentialString( literal.start(), literal.length(), hash_seed_); @@ -247,13 +229,24 @@ const AstRawString* AstValueFactory::GetTwoByteString( const AstRawString* AstValueFactory::GetString(Handle literal) { - DisallowHeapAllocation no_gc; - String::FlatContent content = literal->GetFlatContent(); - if (content.IsOneByte()) { - return GetOneByteString(content.ToOneByteVector()); + // For the FlatContent to stay valid, we shouldn't do any heap + // allocation. Make sure we won't try to internalize the string in GetString. + AstRawString* result = NULL; + Isolate* saved_isolate = isolate_; + isolate_ = NULL; + { + DisallowHeapAllocation no_gc; + String::FlatContent content = literal->GetFlatContent(); + if (content.IsOneByte()) { + result = GetOneByteStringInternal(content.ToOneByteVector()); + } else { + DCHECK(content.IsTwoByte()); + result = GetTwoByteStringInternal(content.ToUC16Vector()); + } } - DCHECK(content.IsTwoByte()); - return GetTwoByteString(content.ToUC16Vector()); + isolate_ = saved_isolate; + if (isolate_) result->Internalize(isolate_); + return result; } @@ -329,59 +322,45 @@ const AstValue* AstValueFactory::NewSmi(int number) { } +#define GENERATE_VALUE_GETTER(value, initializer) \ + if (!value) { \ + value = new (zone_) AstValue(initializer); \ + if (isolate_) { \ + value->Internalize(isolate_); \ + } \ + values_.Add(value); \ + } \ + return value; + + const AstValue* AstValueFactory::NewBoolean(bool b) { - AstValue* value = new (zone_) AstValue(b); - if (isolate_) { - value->Internalize(isolate_); + if (b) { + GENERATE_VALUE_GETTER(true_value_, true); + } else { + GENERATE_VALUE_GETTER(false_value_, false); } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewStringList( - ZoneList* strings) { - AstValue* value = new (zone_) AstValue(strings); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; } const AstValue* AstValueFactory::NewNull() { - AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; + GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE); } const AstValue* AstValueFactory::NewUndefined() { - AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; + GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED); } const AstValue* AstValueFactory::NewTheHole() { - AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; + GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE); } -const AstRawString* AstValueFactory::GetString( - uint32_t hash, bool is_one_byte, Vector literal_bytes) { +#undef GENERATE_VALUE_GETTER + +AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte, + Vector literal_bytes) { // literal_bytes here points to whatever the user passed, and this is OK // because we use vector_compare (which checks the contents) to compare // against the AstRawStrings which are in the string_table_. We should not diff --git a/deps/v8/src/ast-value-factory.h b/deps/v8/src/ast-value-factory.h index 2f84163ece..09a41400fb 100644 --- a/deps/v8/src/ast-value-factory.h +++ b/deps/v8/src/ast-value-factory.h @@ -88,12 +88,16 @@ class AstRawString : public AstString { return *c; } + V8_INLINE bool IsArguments(AstValueFactory* ast_value_factory) const; + // For storing AstRawStrings in a hash map. uint32_t hash() const { return hash_; } static bool Compare(void* a, void* b); + bool operator==(const AstRawString& rhs) const; + private: friend class AstValueFactory; friend class AstRawStringInternalizationKey; @@ -190,7 +194,6 @@ class AstValue : public ZoneObject { NUMBER, SMI, BOOLEAN, - STRING_ARRAY, NULL_TYPE, UNDEFINED, THE_HOLE @@ -209,10 +212,6 @@ class AstValue : public ZoneObject { explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; } - explicit AstValue(ZoneList* s) : type_(STRING_ARRAY) { - strings_ = s; - } - explicit AstValue(Type t) : type_(t) { DCHECK(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE); } @@ -234,36 +233,42 @@ class AstValue : public ZoneObject { }; -// For generating string constants. -#define STRING_CONSTANTS(F) \ - F(anonymous_function, "(anonymous function)") \ - F(arguments, "arguments") \ - F(constructor, "constructor") \ - F(done, "done") \ - F(dot, ".") \ - F(dot_for, ".for") \ - F(dot_generator, ".generator") \ - F(dot_generator_object, ".generator_object") \ - F(dot_iterator, ".iterator") \ - F(dot_module, ".module") \ - F(dot_result, ".result") \ - F(empty, "") \ - F(eval, "eval") \ - F(initialize_const_global, "initializeConstGlobal") \ - F(initialize_var_global, "initializeVarGlobal") \ - F(make_reference_error, "MakeReferenceError") \ - F(make_syntax_error, "MakeSyntaxError") \ - F(make_type_error, "MakeTypeError") \ - F(module, "module") \ - F(native, "native") \ - F(next, "next") \ - F(proto, "__proto__") \ - F(prototype, "prototype") \ - F(this, "this") \ - F(use_asm, "use asm") \ - F(use_strict, "use strict") \ +// For generating constants. +#define STRING_CONSTANTS(F) \ + F(anonymous_function, "(anonymous function)") \ + F(arguments, "arguments") \ + F(constructor, "constructor") \ + F(done, "done") \ + F(dot, ".") \ + F(dot_for, ".for") \ + F(dot_generator, ".generator") \ + F(dot_generator_object, ".generator_object") \ + F(dot_iterator, ".iterator") \ + F(dot_module, ".module") \ + F(dot_result, ".result") \ + F(empty, "") \ + F(eval, "eval") \ + F(initialize_const_global, "initializeConstGlobal") \ + F(initialize_var_global, "initializeVarGlobal") \ + F(make_reference_error, "MakeReferenceErrorEmbedded") \ + F(make_syntax_error, "MakeSyntaxErrorEmbedded") \ + F(make_type_error, "MakeTypeErrorEmbedded") \ + F(module, "module") \ + F(native, "native") \ + F(next, "next") \ + F(proto, "__proto__") \ + F(prototype, "prototype") \ + F(this, "this") \ + F(use_asm, "use asm") \ + F(use_strict, "use strict") \ F(value, "value") +#define OTHER_CONSTANTS(F) \ + F(true_value) \ + F(false_value) \ + F(null_value) \ + F(undefined_value) \ + F(the_hole_value) class AstValueFactory { public: @@ -272,18 +277,26 @@ class AstValueFactory { zone_(zone), isolate_(NULL), hash_seed_(hash_seed) { -#define F(name, str) \ - name##_string_ = NULL; +#define F(name, str) name##_string_ = NULL; STRING_CONSTANTS(F) +#undef F +#define F(name) name##_ = NULL; + OTHER_CONSTANTS(F) #undef F } - const AstRawString* GetOneByteString(Vector literal); + Zone* zone() const { return zone_; } + + const AstRawString* GetOneByteString(Vector literal) { + return GetOneByteStringInternal(literal); + } const AstRawString* GetOneByteString(const char* string) { return GetOneByteString(Vector( reinterpret_cast(string), StrLength(string))); } - const AstRawString* GetTwoByteString(Vector literal); + const AstRawString* GetTwoByteString(Vector literal) { + return GetTwoByteStringInternal(literal); + } const AstRawString* GetString(Handle literal); const AstConsString* NewConsString(const AstString* left, const AstString* right); @@ -293,15 +306,15 @@ class AstValueFactory { return isolate_ != NULL; } -#define F(name, str) \ - const AstRawString* name##_string() { \ - if (name##_string_ == NULL) { \ - const char* data = str; \ - name##_string_ = GetOneByteString( \ +#define F(name, str) \ + const AstRawString* name##_string() { \ + if (name##_string_ == NULL) { \ + const char* data = str; \ + name##_string_ = GetOneByteString( \ Vector(reinterpret_cast(data), \ - static_cast(strlen(data)))); \ - } \ - return name##_string_; \ + static_cast(strlen(data)))); \ + } \ + return name##_string_; \ } STRING_CONSTANTS(F) #undef F @@ -318,8 +331,10 @@ class AstValueFactory { const AstValue* NewTheHole(); private: - const AstRawString* GetString(uint32_t hash, bool is_one_byte, - Vector literal_bytes); + AstRawString* GetOneByteStringInternal(Vector literal); + AstRawString* GetTwoByteStringInternal(Vector literal); + AstRawString* GetString(uint32_t hash, bool is_one_byte, + Vector literal_bytes); // All strings are copied here, one after another (no NULLs inbetween). HashMap string_table_; @@ -332,14 +347,22 @@ class AstValueFactory { uint32_t hash_seed_; -#define F(name, str) \ - const AstRawString* name##_string_; +#define F(name, str) const AstRawString* name##_string_; STRING_CONSTANTS(F) #undef F + +#define F(name) AstValue* name##_; + OTHER_CONSTANTS(F) +#undef F }; + +bool AstRawString::IsArguments(AstValueFactory* ast_value_factory) const { + return ast_value_factory->arguments_string() == this; +} } } // namespace v8::internal #undef STRING_CONSTANTS +#undef OTHER_CONSTANTS #endif // V8_AST_VALUE_FACTORY_H_ diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc index a7d9bad384..26bc491557 100644 --- a/deps/v8/src/ast.cc +++ b/deps/v8/src/ast.cc @@ -59,59 +59,56 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const { } -VariableProxy::VariableProxy(Zone* zone, Variable* var, int position, - IdGen* id_gen) - : Expression(zone, position, id_gen), - name_(var->raw_name()), - var_(NULL), // Will be set by the call to BindTo. - is_this_(var->is_this()), - is_assigned_(false), - interface_(var->interface()), - variable_feedback_slot_(kInvalidFeedbackSlot) { +VariableProxy::VariableProxy(Zone* zone, Variable* var, int position) + : Expression(zone, position), + bit_field_(IsThisField::encode(var->is_this()) | + IsAssignedField::encode(false) | + IsResolvedField::encode(false)), + variable_feedback_slot_(FeedbackVectorICSlot::Invalid()), + raw_name_(var->raw_name()), + interface_(var->interface()) { BindTo(var); } VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, bool is_this, - Interface* interface, int position, IdGen* id_gen) - : Expression(zone, position, id_gen), - name_(name), - var_(NULL), - is_this_(is_this), - is_assigned_(false), - interface_(interface), - variable_feedback_slot_(kInvalidFeedbackSlot) {} + Interface* interface, int position) + : Expression(zone, position), + bit_field_(IsThisField::encode(is_this) | IsAssignedField::encode(false) | + IsResolvedField::encode(false)), + variable_feedback_slot_(FeedbackVectorICSlot::Invalid()), + raw_name_(name), + interface_(interface) {} void VariableProxy::BindTo(Variable* var) { - DCHECK(var_ == NULL); // must be bound only once - DCHECK(var != NULL); // must bind DCHECK(!FLAG_harmony_modules || interface_->IsUnified(var->interface())); - DCHECK((is_this() && var->is_this()) || name_ == var->raw_name()); + DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name()); // Ideally CONST-ness should match. However, this is very hard to achieve // because we don't know the exact semantics of conflicting (const and // non-const) multiple variable declarations, const vars introduced via // eval() etc. Const-ness and variable declarations are a complete mess // in JS. Sigh... - var_ = var; + set_var(var); + set_is_resolved(); var->set_is_used(); } Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, - Expression* value, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), - op_(op), + Expression* value, int pos) + : Expression(zone, pos), + bit_field_(IsUninitializedField::encode(false) | + KeyTypeField::encode(ELEMENT) | + StoreModeField::encode(STANDARD_STORE) | + TokenField::encode(op)), target_(target), value_(value), - binary_operation_(NULL), - assignment_id_(id_gen->GetNextId()), - is_uninitialized_(false), - store_mode_(STANDARD_STORE) {} + binary_operation_(NULL) {} Token::Value Assignment::binary_op() const { - switch (op_) { + switch (op()) { case Token::ASSIGN_BIT_OR: return Token::BIT_OR; case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; case Token::ASSIGN_BIT_AND: return Token::BIT_AND; @@ -436,7 +433,7 @@ void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { bool BinaryOperation::ResultOverwriteAllowed() const { - switch (op_) { + switch (op()) { case Token::COMMA: case Token::OR: case Token::AND: @@ -560,7 +557,7 @@ bool FunctionDeclaration::IsInlineable() const { // once we use the common type field in the AST consistently. void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { - to_boolean_types_ = oracle->ToBooleanTypes(test_id()); + set_to_boolean_types(oracle->ToBooleanTypes(test_id())); } @@ -582,6 +579,8 @@ Call::CallType Call::GetCallType(Isolate* isolate) const { } } + if (expression()->AsSuperReference() != NULL) return SUPER_CALL; + Property* property = expression()->AsProperty(); return property != NULL ? PROPERTY_CALL : OTHER_CALL; } @@ -607,9 +606,9 @@ bool Call::ComputeGlobalTarget(Handle global, void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) { - int allocation_site_feedback_slot = FLAG_pretenuring_call_new - ? AllocationSiteFeedbackSlot() - : CallNewFeedbackSlot(); + FeedbackVectorSlot allocation_site_feedback_slot = + FLAG_pretenuring_call_new ? AllocationSiteFeedbackSlot() + : CallNewFeedbackSlot(); allocation_site_ = oracle->GetCallNewAllocationSite(allocation_site_feedback_slot); is_monomorphic_ = oracle->CallNewIsMonomorphic(CallNewFeedbackSlot()); @@ -794,14 +793,14 @@ bool RegExpCapture::IsAnchoredAtEnd() { // output formats are alike. class RegExpUnparser FINAL : public RegExpVisitor { public: - RegExpUnparser(OStream& os, Zone* zone) : os_(os), zone_(zone) {} + RegExpUnparser(std::ostream& os, Zone* zone) : os_(os), zone_(zone) {} void VisitCharacterRange(CharacterRange that); #define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, \ void* data) OVERRIDE; FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE) #undef MAKE_CASE private: - OStream& os_; + std::ostream& os_; Zone* zone_; }; @@ -944,7 +943,7 @@ void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) { } -OStream& RegExpTree::Print(OStream& os, Zone* zone) { // NOLINT +std::ostream& RegExpTree::Print(std::ostream& os, Zone* zone) { // NOLINT RegExpUnparser unparser(os, zone); Accept(&unparser, NULL); return os; @@ -989,58 +988,55 @@ RegExpAlternative::RegExpAlternative(ZoneList* nodes) CaseClause::CaseClause(Zone* zone, Expression* label, - ZoneList* statements, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + ZoneList* statements, int pos) + : Expression(zone, pos), label_(label), statements_(statements), - compare_type_(Type::None(zone)), - compare_id_(id_gen->GetNextId()), - entry_id_(id_gen->GetNextId()) {} + compare_type_(Type::None(zone)) {} #define REGULAR_NODE(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ } #define REGULAR_NODE_WITH_FEEDBACK_SLOTS(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ add_slot_node(node); \ } #define DONT_OPTIMIZE_NODE(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ set_dont_crankshaft_reason(k##NodeType); \ add_flag(kDontSelfOptimize); \ } #define DONT_OPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ add_slot_node(node); \ set_dont_crankshaft_reason(k##NodeType); \ add_flag(kDontSelfOptimize); \ } #define DONT_TURBOFAN_NODE(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ + set_dont_crankshaft_reason(k##NodeType); \ + set_dont_turbofan_reason(k##NodeType); \ + add_flag(kDontSelfOptimize); \ + } +#define DONT_TURBOFAN_NODE_WITH_FEEDBACK_SLOTS(NodeType) \ + void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ + add_slot_node(node); \ set_dont_crankshaft_reason(k##NodeType); \ set_dont_turbofan_reason(k##NodeType); \ add_flag(kDontSelfOptimize); \ } #define DONT_SELFOPTIMIZE_NODE(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ add_flag(kDontSelfOptimize); \ } #define DONT_SELFOPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ add_slot_node(node); \ add_flag(kDontSelfOptimize); \ } #define DONT_CACHE_NODE(NodeType) \ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ - increase_node_count(); \ set_dont_crankshaft_reason(k##NodeType); \ add_flag(kDontSelfOptimize); \ add_flag(kDontCache); \ @@ -1091,16 +1087,18 @@ DONT_OPTIMIZE_NODE(ModuleUrl) DONT_OPTIMIZE_NODE(ModuleStatement) DONT_OPTIMIZE_NODE(WithStatement) DONT_OPTIMIZE_NODE(DebuggerStatement) -DONT_OPTIMIZE_NODE(ClassLiteral) DONT_OPTIMIZE_NODE(NativeFunctionLiteral) -DONT_OPTIMIZE_NODE(SuperReference) DONT_OPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(Yield) // TODO(turbofan): Remove the dont_turbofan_reason once this list is empty. +// This list must be kept in sync with Pipeline::GenerateCode. DONT_TURBOFAN_NODE(ForOfStatement) DONT_TURBOFAN_NODE(TryCatchStatement) DONT_TURBOFAN_NODE(TryFinallyStatement) +DONT_TURBOFAN_NODE(ClassLiteral) + +DONT_TURBOFAN_NODE_WITH_FEEDBACK_SLOTS(SuperReference) DONT_SELFOPTIMIZE_NODE(DoWhileStatement) DONT_SELFOPTIMIZE_NODE(WhileStatement) @@ -1112,7 +1110,6 @@ DONT_CACHE_NODE(ModuleLiteral) void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { - increase_node_count(); add_slot_node(node); if (node->is_jsruntime()) { // Don't try to optimize JS runtime calls because we bailout on them. @@ -1126,20 +1123,19 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { #undef DONT_CACHE_NODE -Handle Literal::ToString() { - if (value_->IsString()) return value_->AsString()->string(); - DCHECK(value_->IsNumber()); - char arr[100]; - Vector buffer(arr, arraysize(arr)); - const char* str; - if (value()->IsSmi()) { - // Optimization only, the heap number case would subsume this. - SNPrintF(buffer, "%d", Smi::cast(*value())->value()); - str = arr; - } else { - str = DoubleToCString(value()->Number(), buffer); - } - return isolate_->factory()->NewStringFromAsciiChecked(str); +uint32_t Literal::Hash() { + return raw_value()->IsString() + ? raw_value()->AsString()->hash() + : ComputeLongHash(double_to_uint64(raw_value()->AsNumber())); +} + + +// static +bool Literal::Match(void* literal1, void* literal2) { + const AstValue* x = static_cast(literal1)->raw_value(); + const AstValue* y = static_cast(literal2)->raw_value(); + return (x->IsString() && y->IsString() && *x->AsString() == *y->AsString()) || + (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); } diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index 63055ea356..749e57999c 100644 --- a/deps/v8/src/ast.h +++ b/deps/v8/src/ast.h @@ -11,7 +11,6 @@ #include "src/ast-value-factory.h" #include "src/bailout-reason.h" #include "src/factory.h" -#include "src/feedback-slots.h" #include "src/interface.h" #include "src/isolate.h" #include "src/jsregexp.h" @@ -115,7 +114,6 @@ class BreakableStatement; class Expression; class IterationStatement; class MaterializedLiteral; -class OStream; class Statement; class TargetCollector; class TypeFeedbackOracle; @@ -159,11 +157,25 @@ enum AstPropertiesFlag { }; +class FeedbackVectorRequirements { + public: + FeedbackVectorRequirements(int slots, int ic_slots) + : slots_(slots), ic_slots_(ic_slots) {} + + int slots() const { return slots_; } + int ic_slots() const { return ic_slots_; } + + private: + int slots_; + int ic_slots_; +}; + + class AstProperties FINAL BASE_EMBEDDED { public: class Flags : public EnumSet {}; -AstProperties() : node_count_(0), feedback_slots_(0) {} + AstProperties() : node_count_(0), feedback_slots_(0), ic_feedback_slots_(0) {} Flags* flags() { return &flags_; } int node_count() { return node_count_; } @@ -174,31 +186,19 @@ AstProperties() : node_count_(0), feedback_slots_(0) {} feedback_slots_ += count; } + int ic_feedback_slots() const { return ic_feedback_slots_; } + void increase_ic_feedback_slots(int count) { ic_feedback_slots_ += count; } + private: Flags flags_; int node_count_; int feedback_slots_; + int ic_feedback_slots_; }; class AstNode: public ZoneObject { public: - // For generating IDs for AstNodes. - class IdGen { - public: - explicit IdGen(int id = 0) : id_(id) {} - - int GetNextId() { return ReserveIdRange(1); } - int ReserveIdRange(int n) { - int tmp = id_; - id_ += n; - return tmp; - } - - private: - int id_; - }; - #define DECLARE_TYPE_ENUM(type) k##type, enum NodeType { AST_NODE_LIST(DECLARE_TYPE_ENUM) @@ -234,12 +234,17 @@ class AstNode: public ZoneObject { virtual IterationStatement* AsIterationStatement() { return NULL; } virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; } - protected: - // Some nodes re-use bailout IDs for type feedback. - static TypeFeedbackId reuse(BailoutId id) { - return TypeFeedbackId(id.ToInt()); + // The interface for feedback slots, with default no-op implementations for + // node types which don't actually have this. Note that this is conceptually + // not really nice, but multiple inheritance would introduce yet another + // vtable entry per node, something we don't want for space reasons. + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() { + return FeedbackVectorRequirements(0, 0); + } + virtual void SetFirstFeedbackSlot(FeedbackVectorSlot slot) { UNREACHABLE(); } + virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot) { + UNREACHABLE(); } - private: // Hidden to prevent accidental usage. It would have to load the @@ -354,9 +359,17 @@ class Expression : public AstNode { void set_bounds(Bounds bounds) { bounds_ = bounds; } // Whether the expression is parenthesized - unsigned parenthesization_level() const { return parenthesization_level_; } - bool is_parenthesized() const { return parenthesization_level_ > 0; } - void increase_parenthesization_level() { ++parenthesization_level_; } + bool is_parenthesized() const { + return IsParenthesizedField::decode(bit_field_); + } + bool is_multi_parenthesized() const { + return IsMultiParenthesizedField::decode(bit_field_); + } + void increase_parenthesization_level() { + bit_field_ = + IsMultiParenthesizedField::update(bit_field_, is_parenthesized()); + bit_field_ = IsParenthesizedField::update(bit_field_, true); + } // Type feedback information for assignments and properties. virtual bool IsMonomorphic() { @@ -367,34 +380,53 @@ class Expression : public AstNode { UNREACHABLE(); return NULL; } - virtual KeyedAccessStoreMode GetStoreMode() { + virtual KeyedAccessStoreMode GetStoreMode() const { UNREACHABLE(); return STANDARD_STORE; } + virtual IcCheckType GetKeyType() const { + UNREACHABLE(); + return ELEMENT; + } // TODO(rossberg): this should move to its own AST node eventually. virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle); - byte to_boolean_types() const { return to_boolean_types_; } + byte to_boolean_types() const { + return ToBooleanTypesField::decode(bit_field_); + } - BailoutId id() const { return id_; } - TypeFeedbackId test_id() const { return test_id_; } + void set_base_id(int id) { base_id_ = id; } + static int num_ids() { return parent_num_ids() + 2; } + BailoutId id() const { return BailoutId(local_id(0)); } + TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); } protected: - Expression(Zone* zone, int pos, IdGen* id_gen) + Expression(Zone* zone, int pos) : AstNode(pos), + base_id_(BailoutId::None().ToInt()), bounds_(Bounds::Unbounded(zone)), - parenthesization_level_(0), - id_(id_gen->GetNextId()), - test_id_(id_gen->GetNextId()) {} - void set_to_boolean_types(byte types) { to_boolean_types_ = types; } + bit_field_(0) {} + static int parent_num_ids() { return 0; } + void set_to_boolean_types(byte types) { + bit_field_ = ToBooleanTypesField::update(bit_field_, types); + } + + int base_id() const { + DCHECK(!BailoutId(base_id_).IsNone()); + return base_id_; + } private: - Bounds bounds_; - byte to_boolean_types_; - unsigned parenthesization_level_; + int local_id(int n) const { return base_id() + parent_num_ids() + n; } - const BailoutId id_; - const TypeFeedbackId test_id_; + int base_id_; + Bounds bounds_; + class ToBooleanTypesField : public BitField16 {}; + class IsParenthesizedField : public BitField16 {}; + class IsMultiParenthesizedField : public BitField16 {}; + uint16_t bit_field_; + // Ends with 16-bit field; deriving classes in turn begin with + // 16-bit fields for optimum packing efficiency. }; @@ -422,27 +454,34 @@ class BreakableStatement : public Statement { return breakable_type_ == TARGET_FOR_ANONYMOUS; } - BailoutId EntryId() const { return entry_id_; } - BailoutId ExitId() const { return exit_id_; } + void set_base_id(int id) { base_id_ = id; } + static int num_ids() { return parent_num_ids() + 2; } + BailoutId EntryId() const { return BailoutId(local_id(0)); } + BailoutId ExitId() const { return BailoutId(local_id(1)); } protected: BreakableStatement(Zone* zone, ZoneList* labels, - BreakableType breakable_type, int position, IdGen* id_gen) + BreakableType breakable_type, int position) : Statement(zone, position), labels_(labels), breakable_type_(breakable_type), - entry_id_(id_gen->GetNextId()), - exit_id_(id_gen->GetNextId()) { + base_id_(BailoutId::None().ToInt()) { DCHECK(labels == NULL || labels->length() > 0); } + static int parent_num_ids() { return 0; } + int base_id() const { + DCHECK(!BailoutId(base_id_).IsNone()); + return base_id_; + } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + ZoneList* labels_; BreakableType breakable_type_; Label break_target_; - const BailoutId entry_id_; - const BailoutId exit_id_; + int base_id_; }; @@ -457,7 +496,8 @@ class Block FINAL : public BreakableStatement { ZoneList* statements() { return &statements_; } bool is_initializer_block() const { return is_initializer_block_; } - BailoutId DeclsId() const { return decls_id_; } + static int num_ids() { return parent_num_ids() + 1; } + BailoutId DeclsId() const { return BailoutId(local_id(0)); } virtual bool IsJump() const OVERRIDE { return !statements_.is_empty() && statements_.last()->IsJump() @@ -469,17 +509,18 @@ class Block FINAL : public BreakableStatement { protected: Block(Zone* zone, ZoneList* labels, int capacity, - bool is_initializer_block, int pos, IdGen* id_gen) - : BreakableStatement(zone, labels, TARGET_FOR_NAMED_ONLY, pos, id_gen), + bool is_initializer_block, int pos) + : BreakableStatement(zone, labels, TARGET_FOR_NAMED_ONLY, pos), statements_(capacity, zone), is_initializer_block_(is_initializer_block), - decls_id_(id_gen->GetNextId()), scope_(NULL) {} + static int parent_num_ids() { return BreakableStatement::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + ZoneList statements_; bool is_initializer_block_; - const BailoutId decls_id_; Scope* scope_; }; @@ -493,21 +534,15 @@ class Declaration : public AstNode { virtual bool IsInlineable() const; protected: - Declaration(Zone* zone, - VariableProxy* proxy, - VariableMode mode, - Scope* scope, + Declaration(Zone* zone, VariableProxy* proxy, VariableMode mode, Scope* scope, int pos) - : AstNode(pos), - proxy_(proxy), - mode_(mode), - scope_(scope) { + : AstNode(pos), mode_(mode), proxy_(proxy), scope_(scope) { DCHECK(IsDeclaredVariableMode(mode)); } private: - VariableProxy* proxy_; VariableMode mode_; + VariableProxy* proxy_; // Nested scope from which the declaration originated. Scope* scope_; @@ -731,7 +766,8 @@ class IterationStatement : public BreakableStatement { Statement* body() const { return body_; } - BailoutId OsrEntryId() const { return osr_entry_id_; } + static int num_ids() { return parent_num_ids() + 1; } + BailoutId OsrEntryId() const { return BailoutId(local_id(0)); } virtual BailoutId ContinueId() const = 0; virtual BailoutId StackCheckId() const = 0; @@ -739,21 +775,17 @@ class IterationStatement : public BreakableStatement { Label* continue_target() { return &continue_target_; } protected: - IterationStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos, id_gen), - body_(NULL), - osr_entry_id_(id_gen->GetNextId()) {} - - void Initialize(Statement* body) { - body_ = body; - } + IterationStatement(Zone* zone, ZoneList* labels, int pos) + : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), + body_(NULL) {} + static int parent_num_ids() { return BreakableStatement::num_ids(); } + void Initialize(Statement* body) { body_ = body; } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Statement* body_; Label continue_target_; - - const BailoutId osr_entry_id_; }; @@ -768,23 +800,22 @@ class DoWhileStatement FINAL : public IterationStatement { Expression* cond() const { return cond_; } - virtual BailoutId ContinueId() const OVERRIDE { return continue_id_; } - virtual BailoutId StackCheckId() const OVERRIDE { return back_edge_id_; } - BailoutId BackEdgeId() const { return back_edge_id_; } + static int num_ids() { return parent_num_ids() + 2; } + virtual BailoutId ContinueId() const OVERRIDE { + return BailoutId(local_id(0)); + } + virtual BailoutId StackCheckId() const OVERRIDE { return BackEdgeId(); } + BailoutId BackEdgeId() const { return BailoutId(local_id(1)); } protected: - DoWhileStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : IterationStatement(zone, labels, pos, id_gen), - cond_(NULL), - continue_id_(id_gen->GetNextId()), - back_edge_id_(id_gen->GetNextId()) {} + DoWhileStatement(Zone* zone, ZoneList* labels, int pos) + : IterationStatement(zone, labels, pos), cond_(NULL) {} + static int parent_num_ids() { return IterationStatement::num_ids(); } private: - Expression* cond_; + int local_id(int n) const { return base_id() + parent_num_ids() + n; } - const BailoutId continue_id_; - const BailoutId back_edge_id_; + Expression* cond_; }; @@ -805,25 +836,25 @@ class WhileStatement FINAL : public IterationStatement { may_have_function_literal_ = value; } + static int num_ids() { return parent_num_ids() + 1; } virtual BailoutId ContinueId() const OVERRIDE { return EntryId(); } - virtual BailoutId StackCheckId() const OVERRIDE { return body_id_; } - BailoutId BodyId() const { return body_id_; } + virtual BailoutId StackCheckId() const OVERRIDE { return BodyId(); } + BailoutId BodyId() const { return BailoutId(local_id(0)); } protected: - WhileStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : IterationStatement(zone, labels, pos, id_gen), + WhileStatement(Zone* zone, ZoneList* labels, int pos) + : IterationStatement(zone, labels, pos), cond_(NULL), - may_have_function_literal_(true), - body_id_(id_gen->GetNextId()) {} + may_have_function_literal_(true) {} + static int parent_num_ids() { return IterationStatement::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Expression* cond_; // True if there is a function literal subexpression in the condition. bool may_have_function_literal_; - - const BailoutId body_id_; }; @@ -852,27 +883,30 @@ class ForStatement FINAL : public IterationStatement { may_have_function_literal_ = value; } - virtual BailoutId ContinueId() const OVERRIDE { return continue_id_; } - virtual BailoutId StackCheckId() const OVERRIDE { return body_id_; } - BailoutId BodyId() const { return body_id_; } + static int num_ids() { return parent_num_ids() + 2; } + virtual BailoutId ContinueId() const OVERRIDE { + return BailoutId(local_id(0)); + } + virtual BailoutId StackCheckId() const OVERRIDE { return BodyId(); } + BailoutId BodyId() const { return BailoutId(local_id(1)); } bool is_fast_smi_loop() { return loop_variable_ != NULL; } Variable* loop_variable() { return loop_variable_; } void set_loop_variable(Variable* var) { loop_variable_ = var; } protected: - ForStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : IterationStatement(zone, labels, pos, id_gen), + ForStatement(Zone* zone, ZoneList* labels, int pos) + : IterationStatement(zone, labels, pos), init_(NULL), cond_(NULL), next_(NULL), may_have_function_literal_(true), - loop_variable_(NULL), - continue_id_(id_gen->GetNextId()), - body_id_(id_gen->GetNextId()) {} + loop_variable_(NULL) {} + static int parent_num_ids() { return IterationStatement::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Statement* init_; Expression* cond_; Statement* next_; @@ -880,9 +914,6 @@ class ForStatement FINAL : public IterationStatement { // True if there is a function literal subexpression in the condition. bool may_have_function_literal_; Variable* loop_variable_; - - const BailoutId continue_id_; - const BailoutId body_id_; }; @@ -903,11 +934,8 @@ class ForEachStatement : public IterationStatement { Expression* subject() const { return subject_; } protected: - ForEachStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : IterationStatement(zone, labels, pos, id_gen), - each_(NULL), - subject_(NULL) {} + ForEachStatement(Zone* zone, ZoneList* labels, int pos) + : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {} private: Expression* each_; @@ -915,8 +943,7 @@ class ForEachStatement : public IterationStatement { }; -class ForInStatement FINAL : public ForEachStatement, - public FeedbackSlotInterface { +class ForInStatement FINAL : public ForEachStatement { public: DECLARE_NODE_TYPE(ForInStatement) @@ -925,11 +952,15 @@ class ForInStatement FINAL : public ForEachStatement, } // Type feedback information. - virtual int ComputeFeedbackSlotCount() { return 1; } - virtual void SetFirstFeedbackSlot(int slot) { for_in_feedback_slot_ = slot; } + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements(1, 0); + } + virtual void SetFirstFeedbackSlot(FeedbackVectorSlot slot) OVERRIDE { + for_in_feedback_slot_ = slot; + } - int ForInFeedbackSlot() { - DCHECK(for_in_feedback_slot_ != kInvalidFeedbackSlot); + FeedbackVectorSlot ForInFeedbackSlot() { + DCHECK(!for_in_feedback_slot_.IsInvalid()); return for_in_feedback_slot_; } @@ -937,24 +968,26 @@ class ForInStatement FINAL : public ForEachStatement, ForInType for_in_type() const { return for_in_type_; } void set_for_in_type(ForInType type) { for_in_type_ = type; } - BailoutId BodyId() const { return body_id_; } - BailoutId PrepareId() const { return prepare_id_; } + static int num_ids() { return parent_num_ids() + 4; } + BailoutId BodyId() const { return BailoutId(local_id(0)); } + BailoutId PrepareId() const { return BailoutId(local_id(1)); } + BailoutId EnumId() const { return BailoutId(local_id(2)); } + BailoutId ToObjectId() const { return BailoutId(local_id(3)); } virtual BailoutId ContinueId() const OVERRIDE { return EntryId(); } - virtual BailoutId StackCheckId() const OVERRIDE { return body_id_; } + virtual BailoutId StackCheckId() const OVERRIDE { return BodyId(); } protected: - ForInStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : ForEachStatement(zone, labels, pos, id_gen), + ForInStatement(Zone* zone, ZoneList* labels, int pos) + : ForEachStatement(zone, labels, pos), for_in_type_(SLOW_FOR_IN), - for_in_feedback_slot_(kInvalidFeedbackSlot), - body_id_(id_gen->GetNextId()), - prepare_id_(id_gen->GetNextId()) {} + for_in_feedback_slot_(FeedbackVectorSlot::Invalid()) {} + static int parent_num_ids() { return ForEachStatement::num_ids(); } + + private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } ForInType for_in_type_; - int for_in_feedback_slot_; - const BailoutId body_id_; - const BailoutId prepare_id_; + FeedbackVectorSlot for_in_feedback_slot_; }; @@ -1003,23 +1036,25 @@ class ForOfStatement FINAL : public ForEachStatement { virtual BailoutId ContinueId() const OVERRIDE { return EntryId(); } virtual BailoutId StackCheckId() const OVERRIDE { return BackEdgeId(); } - BailoutId BackEdgeId() const { return back_edge_id_; } + static int num_ids() { return parent_num_ids() + 1; } + BailoutId BackEdgeId() const { return BailoutId(local_id(0)); } protected: - ForOfStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : ForEachStatement(zone, labels, pos, id_gen), + ForOfStatement(Zone* zone, ZoneList* labels, int pos) + : ForEachStatement(zone, labels, pos), assign_iterator_(NULL), next_result_(NULL), result_done_(NULL), - assign_each_(NULL), - back_edge_id_(id_gen->GetNextId()) {} + assign_each_(NULL) {} + static int parent_num_ids() { return ForEachStatement::num_ids(); } + + private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } Expression* assign_iterator_; Expression* next_result_; Expression* result_done_; Expression* assign_each_; - const BailoutId back_edge_id_; }; @@ -1130,24 +1165,25 @@ class CaseClause FINAL : public Expression { Label* body_target() { return &body_target_; } ZoneList* statements() const { return statements_; } - BailoutId EntryId() const { return entry_id_; } + static int num_ids() { return parent_num_ids() + 2; } + BailoutId EntryId() const { return BailoutId(local_id(0)); } + TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); } - // Type feedback information. - TypeFeedbackId CompareId() { return compare_id_; } Type* compare_type() { return compare_type_; } void set_compare_type(Type* type) { compare_type_ = type; } + protected: + static int parent_num_ids() { return Expression::num_ids(); } + private: CaseClause(Zone* zone, Expression* label, ZoneList* statements, - int pos, IdGen* id_gen); + int pos); + int local_id(int n) const { return base_id() + parent_num_ids() + n; } Expression* label_; Label body_target_; ZoneList* statements_; Type* compare_type_; - - const TypeFeedbackId compare_id_; - const BailoutId entry_id_; }; @@ -1164,9 +1200,8 @@ class SwitchStatement FINAL : public BreakableStatement { ZoneList* cases() const { return cases_; } protected: - SwitchStatement(Zone* zone, ZoneList* labels, int pos, - IdGen* id_gen) - : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos, id_gen), + SwitchStatement(Zone* zone, ZoneList* labels, int pos) + : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), tag_(NULL), cases_(NULL) {} @@ -1197,28 +1232,34 @@ class IfStatement FINAL : public Statement { && HasElseStatement() && else_statement()->IsJump(); } - BailoutId IfId() const { return if_id_; } - BailoutId ThenId() const { return then_id_; } - BailoutId ElseId() const { return else_id_; } + void set_base_id(int id) { base_id_ = id; } + static int num_ids() { return parent_num_ids() + 3; } + BailoutId IfId() const { return BailoutId(local_id(0)); } + BailoutId ThenId() const { return BailoutId(local_id(1)); } + BailoutId ElseId() const { return BailoutId(local_id(2)); } protected: IfStatement(Zone* zone, Expression* condition, Statement* then_statement, - Statement* else_statement, int pos, IdGen* id_gen) + Statement* else_statement, int pos) : Statement(zone, pos), condition_(condition), then_statement_(then_statement), else_statement_(else_statement), - if_id_(id_gen->GetNextId()), - then_id_(id_gen->GetNextId()), - else_id_(id_gen->GetNextId()) {} + base_id_(BailoutId::None().ToInt()) {} + static int parent_num_ids() { return 0; } + + int base_id() const { + DCHECK(!BailoutId(base_id_).IsNone()); + return base_id_; + } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Expression* condition_; Statement* then_statement_; Statement* else_statement_; - const BailoutId if_id_; - const BailoutId then_id_; - const BailoutId else_id_; + int base_id_; }; @@ -1322,14 +1363,24 @@ class DebuggerStatement FINAL : public Statement { public: DECLARE_NODE_TYPE(DebuggerStatement) - BailoutId DebugBreakId() const { return debugger_id_; } + void set_base_id(int id) { base_id_ = id; } + static int num_ids() { return parent_num_ids() + 1; } + BailoutId DebugBreakId() const { return BailoutId(local_id(0)); } protected: - explicit DebuggerStatement(Zone* zone, int pos, IdGen* id_gen) - : Statement(zone, pos), debugger_id_(id_gen->GetNextId()) {} + explicit DebuggerStatement(Zone* zone, int pos) + : Statement(zone, pos), base_id_(BailoutId::None().ToInt()) {} + static int parent_num_ids() { return 0; } + + int base_id() const { + DCHECK(!BailoutId(base_id_).IsNone()); + return base_id_; + } private: - const BailoutId debugger_id_; + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + + int base_id_; }; @@ -1372,28 +1423,23 @@ class Literal FINAL : public Expression { // Support for using Literal as a HashMap key. NOTE: Currently, this works // only for string and number literals! - uint32_t Hash() { return ToString()->Hash(); } + uint32_t Hash(); + static bool Match(void* literal1, void* literal2); - static bool Match(void* literal1, void* literal2) { - Handle s1 = static_cast(literal1)->ToString(); - Handle s2 = static_cast(literal2)->ToString(); - return String::Equals(s1, s2); + static int num_ids() { return parent_num_ids() + 1; } + TypeFeedbackId LiteralFeedbackId() const { + return TypeFeedbackId(local_id(0)); } - TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); } - protected: - Literal(Zone* zone, const AstValue* value, int position, IdGen* id_gen) - : Expression(zone, position, id_gen), - value_(value), - isolate_(zone->isolate()) {} + Literal(Zone* zone, const AstValue* value, int position) + : Expression(zone, position), value_(value) {} + static int parent_num_ids() { return Expression::num_ids(); } private: - Handle ToString(); + int local_id(int n) const { return base_id() + parent_num_ids() + n; } const AstValue* value_; - // TODO(dcarney): remove. this is only needed for Match and Hash. - Isolate* isolate_; }; @@ -1411,8 +1457,8 @@ class MaterializedLiteral : public Expression { } protected: - MaterializedLiteral(Zone* zone, int literal_index, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + MaterializedLiteral(Zone* zone, int literal_index, int pos) + : Expression(zone, pos), literal_index_(literal_index), is_simple_(false), depth_(0) {} @@ -1477,6 +1523,8 @@ class ObjectLiteralProperty FINAL : public ZoneObject { void set_emit_store(bool emit_store); bool emit_store(); + bool is_static() const { return is_static_; } + protected: template friend class AstNodeFactory; @@ -1535,23 +1583,28 @@ class ObjectLiteral FINAL : public MaterializedLiteral { }; struct Accessors: public ZoneObject { - Accessors() : getter(NULL), setter(NULL) { } + Accessors() : getter(NULL), setter(NULL) {} Expression* getter; Expression* setter; }; + BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); } + + static int num_ids() { return parent_num_ids() + 1; } + protected: ObjectLiteral(Zone* zone, ZoneList* properties, int literal_index, - int boilerplate_properties, bool has_function, int pos, - IdGen* id_gen) - : MaterializedLiteral(zone, literal_index, pos, id_gen), + int boilerplate_properties, bool has_function, int pos) + : MaterializedLiteral(zone, literal_index, pos), properties_(properties), boilerplate_properties_(boilerplate_properties), fast_elements_(false), may_store_doubles_(false), has_function_(has_function) {} + static int parent_num_ids() { return MaterializedLiteral::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } Handle constant_properties_; ZoneList* properties_; int boilerplate_properties_; @@ -1571,9 +1624,8 @@ class RegExpLiteral FINAL : public MaterializedLiteral { protected: RegExpLiteral(Zone* zone, const AstRawString* pattern, - const AstRawString* flags, int literal_index, int pos, - IdGen* id_gen) - : MaterializedLiteral(zone, literal_index, pos, id_gen), + const AstRawString* flags, int literal_index, int pos) + : MaterializedLiteral(zone, literal_index, pos), pattern_(pattern), flags_(flags) { set_depth(1); @@ -1594,10 +1646,12 @@ class ArrayLiteral FINAL : public MaterializedLiteral { Handle constant_elements() const { return constant_elements_; } ZoneList* values() const { return values_; } + // Unlike other AST nodes, this number of bailout IDs allocated for an + // ArrayLiteral can vary, so num_ids() is not a static method. + int num_ids() const { return parent_num_ids() + values()->length(); } + // Return an AST id for an element that is used in simulate instructions. - BailoutId GetIdForElement(int i) { - return BailoutId(first_element_id_.ToInt() + i); - } + BailoutId GetIdForElement(int i) { return BailoutId(local_id(i)); } // Populate the constant elements fixed array. void BuildConstantElements(Isolate* isolate); @@ -1617,63 +1671,94 @@ class ArrayLiteral FINAL : public MaterializedLiteral { protected: ArrayLiteral(Zone* zone, ZoneList* values, int literal_index, - int pos, IdGen* id_gen) - : MaterializedLiteral(zone, literal_index, pos, id_gen), - values_(values), - first_element_id_(id_gen->ReserveIdRange(values->length())) {} + int pos) + : MaterializedLiteral(zone, literal_index, pos), values_(values) {} + static int parent_num_ids() { return MaterializedLiteral::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Handle constant_elements_; ZoneList* values_; - const BailoutId first_element_id_; }; -class VariableProxy FINAL : public Expression, public FeedbackSlotInterface { +class VariableProxy FINAL : public Expression { public: DECLARE_NODE_TYPE(VariableProxy) virtual bool IsValidReferenceExpression() const OVERRIDE { - return var_ == NULL ? true : var_->IsValidReference(); + return !is_resolved() || var()->IsValidReference(); } - bool IsArguments() const { return var_ != NULL && var_->is_arguments(); } + bool IsArguments() const { return is_resolved() && var()->is_arguments(); } + + Handle name() const { return raw_name()->string(); } + const AstRawString* raw_name() const { + return is_resolved() ? var_->raw_name() : raw_name_; + } + + Variable* var() const { + DCHECK(is_resolved()); + return var_; + } + void set_var(Variable* v) { + DCHECK(!is_resolved()); + DCHECK_NOT_NULL(v); + var_ = v; + } + + bool is_this() const { return IsThisField::decode(bit_field_); } + + bool is_assigned() const { return IsAssignedField::decode(bit_field_); } + void set_is_assigned() { + bit_field_ = IsAssignedField::update(bit_field_, true); + } + + bool is_resolved() const { return IsResolvedField::decode(bit_field_); } + void set_is_resolved() { + bit_field_ = IsResolvedField::update(bit_field_, true); + } - Handle name() const { return name_->string(); } - const AstRawString* raw_name() const { return name_; } - Variable* var() const { return var_; } - bool is_this() const { return is_this_; } Interface* interface() const { return interface_; } - bool is_assigned() const { return is_assigned_; } - void set_is_assigned() { is_assigned_ = true; } - // Bind this proxy to the variable var. Interfaces must match. void BindTo(Variable* var); - virtual int ComputeFeedbackSlotCount() { return FLAG_vector_ics ? 1 : 0; } - virtual void SetFirstFeedbackSlot(int slot) { + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements(0, FLAG_vector_ics ? 1 : 0); + } + virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot) OVERRIDE { variable_feedback_slot_ = slot; } - int VariableFeedbackSlot() { return variable_feedback_slot_; } + FeedbackVectorICSlot VariableFeedbackSlot() { + return variable_feedback_slot_; + } protected: - VariableProxy(Zone* zone, Variable* var, int position, IdGen* id_gen); + VariableProxy(Zone* zone, Variable* var, int position); VariableProxy(Zone* zone, const AstRawString* name, bool is_this, - Interface* interface, int position, IdGen* id_gen); + Interface* interface, int position); - const AstRawString* name_; - Variable* var_; // resolved variable, or NULL - bool is_this_; - bool is_assigned_; + class IsThisField : public BitField8 {}; + class IsAssignedField : public BitField8 {}; + class IsResolvedField : public BitField8 {}; + + // Start with 16-bit (or smaller) field, which should get packed together + // with Expression's trailing 16-bit field. + uint8_t bit_field_; + FeedbackVectorICSlot variable_feedback_slot_; + union { + const AstRawString* raw_name_; // if !is_resolved_ + Variable* var_; // if is_resolved_ + }; Interface* interface_; - int variable_feedback_slot_; }; -class Property FINAL : public Expression, public FeedbackSlotInterface { +class Property FINAL : public Expression { public: DECLARE_NODE_TYPE(Property) @@ -1682,9 +1767,13 @@ class Property FINAL : public Expression, public FeedbackSlotInterface { Expression* obj() const { return obj_; } Expression* key() const { return key_; } - BailoutId LoadId() const { return load_id_; } + static int num_ids() { return parent_num_ids() + 2; } + BailoutId LoadId() const { return BailoutId(local_id(0)); } + TypeFeedbackId PropertyFeedbackId() { return TypeFeedbackId(local_id(1)); } - bool IsStringAccess() const { return is_string_access_; } + bool IsStringAccess() const { + return IsStringAccessField::decode(bit_field_); + } // Type feedback information. virtual bool IsMonomorphic() OVERRIDE { @@ -1693,56 +1782,71 @@ class Property FINAL : public Expression, public FeedbackSlotInterface { virtual SmallMapList* GetReceiverTypes() OVERRIDE { return &receiver_types_; } - virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE { + virtual KeyedAccessStoreMode GetStoreMode() const OVERRIDE { return STANDARD_STORE; } - bool IsUninitialized() { return !is_for_call_ && is_uninitialized_; } - bool HasNoTypeInformation() { - return is_uninitialized_; + virtual IcCheckType GetKeyType() const OVERRIDE { + // PROPERTY key types currently aren't implemented for KeyedLoadICs. + return ELEMENT; } - void set_is_uninitialized(bool b) { is_uninitialized_ = b; } - void set_is_string_access(bool b) { is_string_access_ = b; } - void mark_for_call() { is_for_call_ = true; } - bool IsForCall() { return is_for_call_; } + bool IsUninitialized() const { + return !is_for_call() && HasNoTypeInformation(); + } + bool HasNoTypeInformation() const { + return IsUninitializedField::decode(bit_field_); + } + void set_is_uninitialized(bool b) { + bit_field_ = IsUninitializedField::update(bit_field_, b); + } + void set_is_string_access(bool b) { + bit_field_ = IsStringAccessField::update(bit_field_, b); + } + void mark_for_call() { + bit_field_ = IsForCallField::update(bit_field_, true); + } + bool is_for_call() const { return IsForCallField::decode(bit_field_); } bool IsSuperAccess() { return obj()->IsSuperReference(); } - TypeFeedbackId PropertyFeedbackId() { return reuse(id()); } - - virtual int ComputeFeedbackSlotCount() { return FLAG_vector_ics ? 1 : 0; } - virtual void SetFirstFeedbackSlot(int slot) { + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements(0, FLAG_vector_ics ? 1 : 0); + } + virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot) OVERRIDE { property_feedback_slot_ = slot; } - int PropertyFeedbackSlot() const { return property_feedback_slot_; } + FeedbackVectorICSlot PropertyFeedbackSlot() const { + return property_feedback_slot_; + } protected: - Property(Zone* zone, Expression* obj, Expression* key, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + Property(Zone* zone, Expression* obj, Expression* key, int pos) + : Expression(zone, pos), + bit_field_(IsForCallField::encode(false) | + IsUninitializedField::encode(false) | + IsStringAccessField::encode(false)), + property_feedback_slot_(FeedbackVectorICSlot::Invalid()), obj_(obj), - key_(key), - load_id_(id_gen->GetNextId()), - property_feedback_slot_(kInvalidFeedbackSlot), - is_for_call_(false), - is_uninitialized_(false), - is_string_access_(false) {} + key_(key) {} + static int parent_num_ids() { return Expression::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + + class IsForCallField : public BitField8 {}; + class IsUninitializedField : public BitField8 {}; + class IsStringAccessField : public BitField8 {}; + uint8_t bit_field_; + FeedbackVectorICSlot property_feedback_slot_; Expression* obj_; Expression* key_; - const BailoutId load_id_; - int property_feedback_slot_; - SmallMapList receiver_types_; - bool is_for_call_ : 1; - bool is_uninitialized_ : 1; - bool is_string_access_ : 1; }; -class Call FINAL : public Expression, public FeedbackSlotInterface { +class Call FINAL : public Expression { public: DECLARE_NODE_TYPE(Call) @@ -1750,15 +1854,15 @@ class Call FINAL : public Expression, public FeedbackSlotInterface { ZoneList* arguments() const { return arguments_; } // Type feedback information. - virtual int ComputeFeedbackSlotCount() { return 1; } - virtual void SetFirstFeedbackSlot(int slot) { + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements(0, 1); + } + virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot) OVERRIDE { call_feedback_slot_ = slot; } - bool HasCallFeedbackSlot() const { - return call_feedback_slot_ != kInvalidFeedbackSlot; - } - int CallFeedbackSlot() const { return call_feedback_slot_; } + bool HasCallFeedbackSlot() const { return !call_feedback_slot_.IsInvalid(); } + FeedbackVectorICSlot CallFeedbackSlot() const { return call_feedback_slot_; } virtual SmallMapList* GetReceiverTypes() OVERRIDE { if (expression()->IsProperty()) { @@ -1795,13 +1899,16 @@ class Call FINAL : public Expression, public FeedbackSlotInterface { } bool ComputeGlobalTarget(Handle global, LookupIterator* it); - BailoutId ReturnId() const { return return_id_; } + static int num_ids() { return parent_num_ids() + 2; } + BailoutId ReturnId() const { return BailoutId(local_id(0)); } + BailoutId EvalOrLookupId() const { return BailoutId(local_id(1)); } enum CallType { POSSIBLY_EVAL_CALL, GLOBAL_CALL, LOOKUP_SLOT_CALL, PROPERTY_CALL, + SUPER_CALL, OTHER_CALL }; @@ -1816,31 +1923,30 @@ class Call FINAL : public Expression, public FeedbackSlotInterface { protected: Call(Zone* zone, Expression* expression, ZoneList* arguments, - int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + int pos) + : Expression(zone, pos), + call_feedback_slot_(FeedbackVectorICSlot::Invalid()), expression_(expression), - arguments_(arguments), - call_feedback_slot_(kInvalidFeedbackSlot), - return_id_(id_gen->GetNextId()) { + arguments_(arguments) { if (expression->IsProperty()) { expression->AsProperty()->mark_for_call(); } } + static int parent_num_ids() { return Expression::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + + FeedbackVectorICSlot call_feedback_slot_; Expression* expression_; ZoneList* arguments_; - Handle target_; Handle cell_; Handle allocation_site_; - int call_feedback_slot_; - - const BailoutId return_id_; }; -class CallNew FINAL : public Expression, public FeedbackSlotInterface { +class CallNew FINAL : public Expression { public: DECLARE_NODE_TYPE(CallNew) @@ -1848,21 +1954,17 @@ class CallNew FINAL : public Expression, public FeedbackSlotInterface { ZoneList* arguments() const { return arguments_; } // Type feedback information. - virtual int ComputeFeedbackSlotCount() { - return FLAG_pretenuring_call_new ? 2 : 1; + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements(FLAG_pretenuring_call_new ? 2 : 1, 0); } - virtual void SetFirstFeedbackSlot(int slot) { + virtual void SetFirstFeedbackSlot(FeedbackVectorSlot slot) OVERRIDE { callnew_feedback_slot_ = slot; } - int CallNewFeedbackSlot() { - DCHECK(callnew_feedback_slot_ != kInvalidFeedbackSlot); - return callnew_feedback_slot_; - } - int AllocationSiteFeedbackSlot() { - DCHECK(callnew_feedback_slot_ != kInvalidFeedbackSlot); + FeedbackVectorSlot CallNewFeedbackSlot() { return callnew_feedback_slot_; } + FeedbackVectorSlot AllocationSiteFeedbackSlot() { DCHECK(FLAG_pretenuring_call_new); - return callnew_feedback_slot_ + 1; + return CallNewFeedbackSlot().next(); } void RecordTypeFeedback(TypeFeedbackOracle* oracle); @@ -1872,30 +1974,30 @@ class CallNew FINAL : public Expression, public FeedbackSlotInterface { return allocation_site_; } + static int num_ids() { return parent_num_ids() + 1; } static int feedback_slots() { return 1; } - - BailoutId ReturnId() const { return return_id_; } + BailoutId ReturnId() const { return BailoutId(local_id(0)); } protected: CallNew(Zone* zone, Expression* expression, ZoneList* arguments, - int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + int pos) + : Expression(zone, pos), expression_(expression), arguments_(arguments), is_monomorphic_(false), - callnew_feedback_slot_(kInvalidFeedbackSlot), - return_id_(id_gen->GetNextId()) {} + callnew_feedback_slot_(FeedbackVectorSlot::Invalid()) {} + + static int parent_num_ids() { return Expression::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Expression* expression_; ZoneList* arguments_; - bool is_monomorphic_; Handle target_; Handle allocation_site_; - int callnew_feedback_slot_; - - const BailoutId return_id_; + FeedbackVectorSlot callnew_feedback_slot_; }; @@ -1903,7 +2005,7 @@ class CallNew FINAL : public Expression, public FeedbackSlotInterface { // language construct. Instead it is used to call a C or JS function // with a set of arguments. This is used from the builtins that are // implemented in JavaScript (see "v8natives.js"). -class CallRuntime FINAL : public Expression, public FeedbackSlotInterface { +class CallRuntime FINAL : public Expression { public: DECLARE_NODE_TYPE(CallRuntime) @@ -1914,35 +2016,41 @@ class CallRuntime FINAL : public Expression, public FeedbackSlotInterface { bool is_jsruntime() const { return function_ == NULL; } // Type feedback information. - virtual int ComputeFeedbackSlotCount() { - return (FLAG_vector_ics && is_jsruntime()) ? 1 : 0; + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements( + 0, (FLAG_vector_ics && is_jsruntime()) ? 1 : 0); } - virtual void SetFirstFeedbackSlot(int slot) { + virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot) OVERRIDE { callruntime_feedback_slot_ = slot; } - int CallRuntimeFeedbackSlot() { - DCHECK(!is_jsruntime() || - callruntime_feedback_slot_ != kInvalidFeedbackSlot); + FeedbackVectorICSlot CallRuntimeFeedbackSlot() { return callruntime_feedback_slot_; } - TypeFeedbackId CallRuntimeFeedbackId() const { return reuse(id()); } + static int num_ids() { return parent_num_ids() + 1; } + TypeFeedbackId CallRuntimeFeedbackId() const { + return TypeFeedbackId(local_id(0)); + } protected: CallRuntime(Zone* zone, const AstRawString* name, const Runtime::Function* function, - ZoneList* arguments, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + ZoneList* arguments, int pos) + : Expression(zone, pos), raw_name_(name), function_(function), - arguments_(arguments) {} + arguments_(arguments), + callruntime_feedback_slot_(FeedbackVectorICSlot::Invalid()) {} + static int parent_num_ids() { return Expression::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + const AstRawString* raw_name_; const Runtime::Function* function_; ZoneList* arguments_; - int callruntime_feedback_slot_; + FeedbackVectorICSlot callruntime_feedback_slot_; }; @@ -1953,31 +2061,27 @@ class UnaryOperation FINAL : public Expression { Token::Value op() const { return op_; } Expression* expression() const { return expression_; } - BailoutId MaterializeTrueId() { return materialize_true_id_; } - BailoutId MaterializeFalseId() { return materialize_false_id_; } + // For unary not (Token::NOT), the AST ids where true and false will + // actually be materialized, respectively. + static int num_ids() { return parent_num_ids() + 2; } + BailoutId MaterializeTrueId() const { return BailoutId(local_id(0)); } + BailoutId MaterializeFalseId() const { return BailoutId(local_id(1)); } virtual void RecordToBooleanTypeFeedback( TypeFeedbackOracle* oracle) OVERRIDE; protected: - UnaryOperation(Zone* zone, Token::Value op, Expression* expression, int pos, - IdGen* id_gen) - : Expression(zone, pos, id_gen), - op_(op), - expression_(expression), - materialize_true_id_(id_gen->GetNextId()), - materialize_false_id_(id_gen->GetNextId()) { + UnaryOperation(Zone* zone, Token::Value op, Expression* expression, int pos) + : Expression(zone, pos), op_(op), expression_(expression) { DCHECK(Token::IsUnaryOp(op)); } + static int parent_num_ids() { return Expression::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Token::Value op_; Expression* expression_; - - // For unary not (Token::NOT), the AST ids where true and false will - // actually be materialized, respectively. - const BailoutId materialize_true_id_; - const BailoutId materialize_false_id_; }; @@ -1987,7 +2091,7 @@ class BinaryOperation FINAL : public Expression { virtual bool ResultOverwriteAllowed() const OVERRIDE; - Token::Value op() const { return op_; } + Token::Value op() const { return static_cast(op_); } Expression* left() const { return left_; } Expression* right() const { return right_; } Handle allocation_site() const { return allocation_site_; } @@ -1995,39 +2099,50 @@ class BinaryOperation FINAL : public Expression { allocation_site_ = allocation_site; } - BailoutId RightId() const { return right_id_; } + // The short-circuit logical operations need an AST ID for their + // right-hand subexpression. + static int num_ids() { return parent_num_ids() + 2; } + BailoutId RightId() const { return BailoutId(local_id(0)); } - TypeFeedbackId BinaryOperationFeedbackId() const { return reuse(id()); } - Maybe fixed_right_arg() const { return fixed_right_arg_; } - void set_fixed_right_arg(Maybe arg) { fixed_right_arg_ = arg; } + TypeFeedbackId BinaryOperationFeedbackId() const { + return TypeFeedbackId(local_id(1)); + } + Maybe fixed_right_arg() const { + return has_fixed_right_arg_ ? Maybe(fixed_right_arg_value_) + : Maybe(); + } + void set_fixed_right_arg(Maybe arg) { + has_fixed_right_arg_ = arg.has_value; + if (arg.has_value) fixed_right_arg_value_ = arg.value; + } virtual void RecordToBooleanTypeFeedback( TypeFeedbackOracle* oracle) OVERRIDE; protected: BinaryOperation(Zone* zone, Token::Value op, Expression* left, - Expression* right, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), - op_(op), + Expression* right, int pos) + : Expression(zone, pos), + op_(static_cast(op)), + has_fixed_right_arg_(false), + fixed_right_arg_value_(0), left_(left), - right_(right), - right_id_(id_gen->GetNextId()) { + right_(right) { DCHECK(Token::IsBinaryOp(op)); } + static int parent_num_ids() { return Expression::num_ids(); } private: - Token::Value op_; + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + + const byte op_; // actually Token::Value + // TODO(rossberg): the fixed arg should probably be represented as a Constant + // type for the RHS. Currenty it's actually a Maybe + bool has_fixed_right_arg_; + int fixed_right_arg_value_; Expression* left_; Expression* right_; Handle allocation_site_; - - // TODO(rossberg): the fixed arg should probably be represented as a Constant - // type for the RHS. - Maybe fixed_right_arg_; - - // The short-circuit logical operations need an AST ID for their - // right-hand subexpression. - const BailoutId right_id_; }; @@ -2035,10 +2150,10 @@ class CountOperation FINAL : public Expression { public: DECLARE_NODE_TYPE(CountOperation) - bool is_prefix() const { return is_prefix_; } - bool is_postfix() const { return !is_prefix_; } + bool is_prefix() const { return IsPrefixField::decode(bit_field_); } + bool is_postfix() const { return !is_prefix(); } - Token::Value op() const { return op_; } + Token::Value op() const { return TokenField::decode(bit_field_); } Token::Value binary_op() { return (op() == Token::INC) ? Token::ADD : Token::SUB; } @@ -2051,39 +2166,55 @@ class CountOperation FINAL : public Expression { virtual SmallMapList* GetReceiverTypes() OVERRIDE { return &receiver_types_; } - virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE { - return store_mode_; + virtual IcCheckType GetKeyType() const OVERRIDE { + return KeyTypeField::decode(bit_field_); + } + virtual KeyedAccessStoreMode GetStoreMode() const OVERRIDE { + return StoreModeField::decode(bit_field_); } Type* type() const { return type_; } - void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; } + void set_key_type(IcCheckType type) { + bit_field_ = KeyTypeField::update(bit_field_, type); + } + void set_store_mode(KeyedAccessStoreMode mode) { + bit_field_ = StoreModeField::update(bit_field_, mode); + } void set_type(Type* type) { type_ = type; } - BailoutId AssignmentId() const { return assignment_id_; } - - TypeFeedbackId CountBinOpFeedbackId() const { return count_id_; } - TypeFeedbackId CountStoreFeedbackId() const { return reuse(id()); } + static int num_ids() { return parent_num_ids() + 3; } + BailoutId AssignmentId() const { return BailoutId(local_id(0)); } + TypeFeedbackId CountBinOpFeedbackId() const { + return TypeFeedbackId(local_id(1)); + } + TypeFeedbackId CountStoreFeedbackId() const { + return TypeFeedbackId(local_id(2)); + } protected: CountOperation(Zone* zone, Token::Value op, bool is_prefix, Expression* expr, - int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), - op_(op), - is_prefix_(is_prefix), - store_mode_(STANDARD_STORE), - expression_(expr), - assignment_id_(id_gen->GetNextId()), - count_id_(id_gen->GetNextId()) {} + int pos) + : Expression(zone, pos), + bit_field_(IsPrefixField::encode(is_prefix) | + KeyTypeField::encode(ELEMENT) | + StoreModeField::encode(STANDARD_STORE) | + TokenField::encode(op)), + type_(NULL), + expression_(expr) {} + static int parent_num_ids() { return Expression::num_ids(); } private: - Token::Value op_; - bool is_prefix_ : 1; - KeyedAccessStoreMode store_mode_ : 5; // Windows treats as signed, - // must have extra bit. - Type* type_; + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + class IsPrefixField : public BitField16 {}; + class KeyTypeField : public BitField16 {}; + class StoreModeField : public BitField16 {}; + class TokenField : public BitField16 {}; + + // Starts with 16-bit field, which should get packed together with + // Expression's trailing 16-bit field. + uint16_t bit_field_; + Type* type_; Expression* expression_; - const BailoutId assignment_id_; - const TypeFeedbackId count_id_; SmallMapList receiver_types_; }; @@ -2097,7 +2228,10 @@ class CompareOperation FINAL : public Expression { Expression* right() const { return right_; } // Type feedback information. - TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); } + static int num_ids() { return parent_num_ids() + 1; } + TypeFeedbackId CompareOperationFeedbackId() const { + return TypeFeedbackId(local_id(0)); + } Type* combined_type() const { return combined_type_; } void set_combined_type(Type* type) { combined_type_ = type; } @@ -2108,16 +2242,19 @@ class CompareOperation FINAL : public Expression { protected: CompareOperation(Zone* zone, Token::Value op, Expression* left, - Expression* right, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + Expression* right, int pos) + : Expression(zone, pos), op_(op), left_(left), right_(right), combined_type_(Type::None(zone)) { DCHECK(Token::IsCompareOp(op)); } + static int parent_num_ids() { return Expression::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Token::Value op_; Expression* left_; Expression* right_; @@ -2134,25 +2271,25 @@ class Conditional FINAL : public Expression { Expression* then_expression() const { return then_expression_; } Expression* else_expression() const { return else_expression_; } - BailoutId ThenId() const { return then_id_; } - BailoutId ElseId() const { return else_id_; } + static int num_ids() { return parent_num_ids() + 2; } + BailoutId ThenId() const { return BailoutId(local_id(0)); } + BailoutId ElseId() const { return BailoutId(local_id(1)); } protected: Conditional(Zone* zone, Expression* condition, Expression* then_expression, - Expression* else_expression, int position, IdGen* id_gen) - : Expression(zone, position, id_gen), + Expression* else_expression, int position) + : Expression(zone, position), condition_(condition), then_expression_(then_expression), - else_expression_(else_expression), - then_id_(id_gen->GetNextId()), - else_id_(id_gen->GetNextId()) {} + else_expression_(else_expression) {} + static int parent_num_ids() { return Expression::num_ids(); } private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + Expression* condition_; Expression* then_expression_; Expression* else_expression_; - const BailoutId then_id_; - const BailoutId else_id_; }; @@ -2164,7 +2301,7 @@ class Assignment FINAL : public Expression { Token::Value binary_op() const; - Token::Value op() const { return op_; } + Token::Value op() const { return TokenField::decode(bit_field_); } Expression* target() const { return target_; } Expression* value() const { return value_; } BinaryOperation* binary_operation() const { return binary_operation_; } @@ -2172,33 +2309,47 @@ class Assignment FINAL : public Expression { // This check relies on the definition order of token in token.h. bool is_compound() const { return op() > Token::ASSIGN; } - BailoutId AssignmentId() const { return assignment_id_; } + static int num_ids() { return parent_num_ids() + 2; } + BailoutId AssignmentId() const { return BailoutId(local_id(0)); } // Type feedback information. - TypeFeedbackId AssignmentFeedbackId() { return reuse(id()); } + TypeFeedbackId AssignmentFeedbackId() { return TypeFeedbackId(local_id(1)); } virtual bool IsMonomorphic() OVERRIDE { return receiver_types_.length() == 1; } - bool IsUninitialized() { return is_uninitialized_; } + bool IsUninitialized() const { + return IsUninitializedField::decode(bit_field_); + } bool HasNoTypeInformation() { - return is_uninitialized_; + return IsUninitializedField::decode(bit_field_); } virtual SmallMapList* GetReceiverTypes() OVERRIDE { return &receiver_types_; } - virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE { - return store_mode_; + virtual IcCheckType GetKeyType() const OVERRIDE { + return KeyTypeField::decode(bit_field_); + } + virtual KeyedAccessStoreMode GetStoreMode() const OVERRIDE { + return StoreModeField::decode(bit_field_); + } + void set_is_uninitialized(bool b) { + bit_field_ = IsUninitializedField::update(bit_field_, b); + } + void set_key_type(IcCheckType key_type) { + bit_field_ = KeyTypeField::update(bit_field_, key_type); + } + void set_store_mode(KeyedAccessStoreMode mode) { + bit_field_ = StoreModeField::update(bit_field_, mode); } - void set_is_uninitialized(bool b) { is_uninitialized_ = b; } - void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; } protected: Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value, - int pos, IdGen* id_gen); + int pos); + static int parent_num_ids() { return Expression::num_ids(); } - template - void Init(Zone* zone, AstNodeFactory* factory) { - DCHECK(Token::IsAssignmentOp(op_)); + template + void Init(AstNodeFactory* factory) { + DCHECK(Token::IsAssignmentOp(op())); if (is_compound()) { binary_operation_ = factory->NewBinaryOperation( binary_op(), target_, value_, position() + 1); @@ -2206,20 +2357,24 @@ class Assignment FINAL : public Expression { } private: - Token::Value op_; + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + + class IsUninitializedField : public BitField16 {}; + class KeyTypeField : public BitField16 {}; + class StoreModeField : public BitField16 {}; + class TokenField : public BitField16 {}; + + // Starts with 16-bit field, which should get packed together with + // Expression's trailing 16-bit field. + uint16_t bit_field_; Expression* target_; Expression* value_; BinaryOperation* binary_operation_; - const BailoutId assignment_id_; - - bool is_uninitialized_ : 1; - KeyedAccessStoreMode store_mode_ : 5; // Windows treats as signed, - // must have extra bit. SmallMapList receiver_types_; }; -class Yield FINAL : public Expression, public FeedbackSlotInterface { +class Yield FINAL : public Expression { public: DECLARE_NODE_TYPE(Yield) @@ -2247,44 +2402,40 @@ class Yield FINAL : public Expression, public FeedbackSlotInterface { } // Type feedback information. - virtual int ComputeFeedbackSlotCount() { - return (FLAG_vector_ics && yield_kind() == kDelegating) ? 3 : 0; + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements( + 0, (FLAG_vector_ics && yield_kind() == kDelegating) ? 3 : 0); } - virtual void SetFirstFeedbackSlot(int slot) { + virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot) OVERRIDE { yield_first_feedback_slot_ = slot; } - int KeyedLoadFeedbackSlot() { - DCHECK(yield_first_feedback_slot_ != kInvalidFeedbackSlot); + FeedbackVectorICSlot KeyedLoadFeedbackSlot() { return yield_first_feedback_slot_; } - int DoneFeedbackSlot() { - DCHECK(yield_first_feedback_slot_ != kInvalidFeedbackSlot); - return yield_first_feedback_slot_ + 1; + FeedbackVectorICSlot DoneFeedbackSlot() { + return KeyedLoadFeedbackSlot().next(); } - int ValueFeedbackSlot() { - DCHECK(yield_first_feedback_slot_ != kInvalidFeedbackSlot); - return yield_first_feedback_slot_ + 2; - } + FeedbackVectorICSlot ValueFeedbackSlot() { return DoneFeedbackSlot().next(); } protected: Yield(Zone* zone, Expression* generator_object, Expression* expression, - Kind yield_kind, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), + Kind yield_kind, int pos) + : Expression(zone, pos), generator_object_(generator_object), expression_(expression), yield_kind_(yield_kind), index_(-1), - yield_first_feedback_slot_(kInvalidFeedbackSlot) {} + yield_first_feedback_slot_(FeedbackVectorICSlot::Invalid()) {} private: Expression* generator_object_; Expression* expression_; Kind yield_kind_; int index_; - int yield_first_feedback_slot_; + FeedbackVectorICSlot yield_first_feedback_slot_; }; @@ -2295,8 +2446,8 @@ class Throw FINAL : public Expression { Expression* exception() const { return exception_; } protected: - Throw(Zone* zone, Expression* exception, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), exception_(exception) {} + Throw(Zone* zone, Expression* exception, int pos) + : Expression(zone, pos), exception_(exception) {} private: Expression* exception_; @@ -2434,6 +2585,7 @@ class FunctionLiteral FINAL : public Expression { int slot_count() { return ast_properties_.feedback_slots(); } + int ic_slot_count() { return ast_properties_.ic_feedback_slots(); } bool dont_optimize() { return dont_optimize_reason_ != kNoReason; } BailoutReason dont_optimize_reason() { return dont_optimize_reason_; } void set_dont_optimize_reason(BailoutReason reason) { @@ -2449,8 +2601,8 @@ class FunctionLiteral FINAL : public Expression { ParameterFlag has_duplicate_parameters, IsFunctionFlag is_function, IsParenthesizedFlag is_parenthesized, FunctionKind kind, - int position, IdGen* id_gen) - : Expression(zone, position, id_gen), + int position) + : Expression(zone, position), raw_name_(name), scope_(scope), body_(body), @@ -2510,22 +2662,26 @@ class ClassLiteral FINAL : public Expression { Expression* extends() const { return extends_; } Expression* constructor() const { return constructor_; } ZoneList* properties() const { return properties_; } + int start_position() const { return position(); } + int end_position() const { return end_position_; } protected: ClassLiteral(Zone* zone, const AstRawString* name, Expression* extends, Expression* constructor, ZoneList* properties, - int position, IdGen* id_gen) - : Expression(zone, position, id_gen), + int start_position, int end_position) + : Expression(zone, start_position), raw_name_(name), extends_(extends), constructor_(constructor), - properties_(properties) {} + properties_(properties), + end_position_(end_position) {} private: const AstRawString* raw_name_; Expression* extends_; Expression* constructor_; ZoneList* properties_; + int end_position_; }; @@ -2538,8 +2694,8 @@ class NativeFunctionLiteral FINAL : public Expression { protected: NativeFunctionLiteral(Zone* zone, const AstRawString* name, - v8::Extension* extension, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), name_(name), extension_(extension) {} + v8::Extension* extension, int pos) + : Expression(zone, pos), name_(name), extension_(extension) {} private: const AstRawString* name_; @@ -2552,8 +2708,7 @@ class ThisFunction FINAL : public Expression { DECLARE_NODE_TYPE(ThisFunction) protected: - ThisFunction(Zone* zone, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen) {} + ThisFunction(Zone* zone, int pos) : Expression(zone, pos) {} }; @@ -2563,15 +2718,36 @@ class SuperReference FINAL : public Expression { VariableProxy* this_var() const { return this_var_; } - TypeFeedbackId HomeObjectFeedbackId() { return reuse(id()); } + static int num_ids() { return parent_num_ids() + 1; } + TypeFeedbackId HomeObjectFeedbackId() { return TypeFeedbackId(local_id(0)); } - protected: - SuperReference(Zone* zone, VariableProxy* this_var, int pos, IdGen* id_gen) - : Expression(zone, pos, id_gen), this_var_(this_var) { - DCHECK(this_var->is_this()); + // Type feedback information. + virtual FeedbackVectorRequirements ComputeFeedbackRequirements() OVERRIDE { + return FeedbackVectorRequirements(0, FLAG_vector_ics ? 1 : 0); + } + virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot) OVERRIDE { + homeobject_feedback_slot_ = slot; } + FeedbackVectorICSlot HomeObjectFeedbackSlot() { + DCHECK(!FLAG_vector_ics || !homeobject_feedback_slot_.IsInvalid()); + return homeobject_feedback_slot_; + } + + protected: + SuperReference(Zone* zone, VariableProxy* this_var, int pos) + : Expression(zone, pos), + this_var_(this_var), + homeobject_feedback_slot_(FeedbackVectorICSlot::Invalid()) { + DCHECK(this_var->is_this()); + } + static int parent_num_ids() { return Expression::num_ids(); } + + private: + int local_id(int n) const { return base_id() + parent_num_ids() + n; } + VariableProxy* this_var_; + FeedbackVectorICSlot homeobject_feedback_slot_; }; @@ -2608,7 +2784,7 @@ class RegExpTree : public ZoneObject { // expression. virtual Interval CaptureRegisters() { return Interval::Empty(); } virtual void AppendToText(RegExpText* text, Zone* zone); - OStream& Print(OStream& os, Zone* zone); // NOLINT + std::ostream& Print(std::ostream& os, Zone* zone); // NOLINT #define MAKE_ASTYPE(Name) \ virtual RegExp##Name* As##Name(); \ virtual bool Is##Name(); @@ -3025,7 +3201,6 @@ class AstConstructionVisitor BASE_EMBEDDED { AST_NODE_LIST(DEF_VISIT) #undef DEF_VISIT - void increase_node_count() { properties_.add_node_count(1); } void add_flag(AstPropertiesFlag flag) { properties_.flags()->Add(flag); } void set_dont_crankshaft_reason(BailoutReason reason) { dont_crankshaft_reason_ = reason; @@ -3034,11 +3209,17 @@ class AstConstructionVisitor BASE_EMBEDDED { dont_turbofan_reason_ = reason; } - void add_slot_node(FeedbackSlotInterface* slot_node) { - int count = slot_node->ComputeFeedbackSlotCount(); - if (count > 0) { - slot_node->SetFirstFeedbackSlot(properties_.feedback_slots()); - properties_.increase_feedback_slots(count); + void add_slot_node(AstNode* slot_node) { + FeedbackVectorRequirements reqs = slot_node->ComputeFeedbackRequirements(); + if (reqs.slots() > 0) { + slot_node->SetFirstFeedbackSlot( + FeedbackVectorSlot(properties_.feedback_slots())); + properties_.increase_feedback_slots(reqs.slots()); + } + if (reqs.ic_slots() > 0) { + slot_node->SetFirstFeedbackICSlot( + FeedbackVectorICSlot(properties_.ic_feedback_slots())); + properties_.increase_ic_feedback_slots(reqs.ic_slots()); } } @@ -3065,9 +3246,9 @@ class AstNullVisitor BASE_EMBEDDED { template class AstNodeFactory FINAL BASE_EMBEDDED { public: - AstNodeFactory(Zone* zone, AstValueFactory* ast_value_factory, - AstNode::IdGen* id_gen) - : zone_(zone), ast_value_factory_(ast_value_factory), id_gen_(id_gen) {} + explicit AstNodeFactory(AstValueFactory* ast_value_factory) + : zone_(ast_value_factory->zone()), + ast_value_factory_(ast_value_factory) {} Visitor* visitor() { return &visitor_; } @@ -3145,14 +3326,14 @@ class AstNodeFactory FINAL BASE_EMBEDDED { int capacity, bool is_initializer_block, int pos) { - Block* block = new (zone_) - Block(zone_, labels, capacity, is_initializer_block, pos, id_gen_); + Block* block = + new (zone_) Block(zone_, labels, capacity, is_initializer_block, pos); VISIT_AND_RETURN(Block, block) } #define STATEMENT_WITH_LABELS(NodeType) \ NodeType* New##NodeType(ZoneList* labels, int pos) { \ - NodeType* stmt = new (zone_) NodeType(zone_, labels, pos, id_gen_); \ + NodeType* stmt = new (zone_) NodeType(zone_, labels, pos); \ VISIT_AND_RETURN(NodeType, stmt); \ } STATEMENT_WITH_LABELS(DoWhileStatement) @@ -3166,13 +3347,11 @@ class AstNodeFactory FINAL BASE_EMBEDDED { int pos) { switch (visit_mode) { case ForEachStatement::ENUMERATE: { - ForInStatement* stmt = - new (zone_) ForInStatement(zone_, labels, pos, id_gen_); + ForInStatement* stmt = new (zone_) ForInStatement(zone_, labels, pos); VISIT_AND_RETURN(ForInStatement, stmt); } case ForEachStatement::ITERATE: { - ForOfStatement* stmt = - new (zone_) ForOfStatement(zone_, labels, pos, id_gen_); + ForOfStatement* stmt = new (zone_) ForOfStatement(zone_, labels, pos); VISIT_AND_RETURN(ForOfStatement, stmt); } } @@ -3220,8 +3399,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Statement* then_statement, Statement* else_statement, int pos) { - IfStatement* stmt = new (zone_) IfStatement( - zone_, condition, then_statement, else_statement, pos, id_gen_); + IfStatement* stmt = new (zone_) + IfStatement(zone_, condition, then_statement, else_statement, pos); VISIT_AND_RETURN(IfStatement, stmt) } @@ -3246,8 +3425,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED { } DebuggerStatement* NewDebuggerStatement(int pos) { - DebuggerStatement* stmt = - new (zone_) DebuggerStatement(zone_, pos, id_gen_); + DebuggerStatement* stmt = new (zone_) DebuggerStatement(zone_, pos); VISIT_AND_RETURN(DebuggerStatement, stmt) } @@ -3257,64 +3435,56 @@ class AstNodeFactory FINAL BASE_EMBEDDED { CaseClause* NewCaseClause( Expression* label, ZoneList* statements, int pos) { - CaseClause* clause = - new (zone_) CaseClause(zone_, label, statements, pos, id_gen_); + CaseClause* clause = new (zone_) CaseClause(zone_, label, statements, pos); VISIT_AND_RETURN(CaseClause, clause) } Literal* NewStringLiteral(const AstRawString* string, int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewString(string), pos, id_gen_); + Literal* lit = + new (zone_) Literal(zone_, ast_value_factory_->NewString(string), pos); VISIT_AND_RETURN(Literal, lit) } // A JavaScript symbol (ECMA-262 edition 6). Literal* NewSymbolLiteral(const char* name, int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewSymbol(name), pos, id_gen_); + Literal* lit = + new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos); VISIT_AND_RETURN(Literal, lit) } Literal* NewNumberLiteral(double number, int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewNumber(number), pos, id_gen_); + Literal* lit = + new (zone_) Literal(zone_, ast_value_factory_->NewNumber(number), pos); VISIT_AND_RETURN(Literal, lit) } Literal* NewSmiLiteral(int number, int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewSmi(number), pos, id_gen_); + Literal* lit = + new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos); VISIT_AND_RETURN(Literal, lit) } Literal* NewBooleanLiteral(bool b, int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewBoolean(b), pos, id_gen_); - VISIT_AND_RETURN(Literal, lit) - } - - Literal* NewStringListLiteral(ZoneList* strings, - int pos) { - Literal* lit = new (zone_) Literal( - zone_, ast_value_factory_->NewStringList(strings), pos, id_gen_); + Literal* lit = + new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos); VISIT_AND_RETURN(Literal, lit) } Literal* NewNullLiteral(int pos) { Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos, id_gen_); + new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos); VISIT_AND_RETURN(Literal, lit) } Literal* NewUndefinedLiteral(int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewUndefined(), pos, id_gen_); + Literal* lit = + new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos); VISIT_AND_RETURN(Literal, lit) } Literal* NewTheHoleLiteral(int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewTheHole(), pos, id_gen_); + Literal* lit = + new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos); VISIT_AND_RETURN(Literal, lit) } @@ -3324,9 +3494,9 @@ class AstNodeFactory FINAL BASE_EMBEDDED { int boilerplate_properties, bool has_function, int pos) { - ObjectLiteral* lit = new (zone_) - ObjectLiteral(zone_, properties, literal_index, boilerplate_properties, - has_function, pos, id_gen_); + ObjectLiteral* lit = + new (zone_) ObjectLiteral(zone_, properties, literal_index, + boilerplate_properties, has_function, pos); VISIT_AND_RETURN(ObjectLiteral, lit) } @@ -3350,8 +3520,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED { const AstRawString* flags, int literal_index, int pos) { - RegExpLiteral* lit = new (zone_) - RegExpLiteral(zone_, pattern, flags, literal_index, pos, id_gen_); + RegExpLiteral* lit = + new (zone_) RegExpLiteral(zone_, pattern, flags, literal_index, pos); VISIT_AND_RETURN(RegExpLiteral, lit); } @@ -3359,13 +3529,13 @@ class AstNodeFactory FINAL BASE_EMBEDDED { int literal_index, int pos) { ArrayLiteral* lit = - new (zone_) ArrayLiteral(zone_, values, literal_index, pos, id_gen_); + new (zone_) ArrayLiteral(zone_, values, literal_index, pos); VISIT_AND_RETURN(ArrayLiteral, lit) } VariableProxy* NewVariableProxy(Variable* var, int pos = RelocInfo::kNoPosition) { - VariableProxy* proxy = new (zone_) VariableProxy(zone_, var, pos, id_gen_); + VariableProxy* proxy = new (zone_) VariableProxy(zone_, var, pos); VISIT_AND_RETURN(VariableProxy, proxy) } @@ -3373,28 +3543,27 @@ class AstNodeFactory FINAL BASE_EMBEDDED { bool is_this, Interface* interface = Interface::NewValue(), int position = RelocInfo::kNoPosition) { - VariableProxy* proxy = new (zone_) - VariableProxy(zone_, name, is_this, interface, position, id_gen_); + VariableProxy* proxy = + new (zone_) VariableProxy(zone_, name, is_this, interface, position); VISIT_AND_RETURN(VariableProxy, proxy) } Property* NewProperty(Expression* obj, Expression* key, int pos) { - Property* prop = new (zone_) Property(zone_, obj, key, pos, id_gen_); + Property* prop = new (zone_) Property(zone_, obj, key, pos); VISIT_AND_RETURN(Property, prop) } Call* NewCall(Expression* expression, ZoneList* arguments, int pos) { - Call* call = new (zone_) Call(zone_, expression, arguments, pos, id_gen_); + Call* call = new (zone_) Call(zone_, expression, arguments, pos); VISIT_AND_RETURN(Call, call) } CallNew* NewCallNew(Expression* expression, ZoneList* arguments, int pos) { - CallNew* call = - new (zone_) CallNew(zone_, expression, arguments, pos, id_gen_); + CallNew* call = new (zone_) CallNew(zone_, expression, arguments, pos); VISIT_AND_RETURN(CallNew, call) } @@ -3403,7 +3572,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED { ZoneList* arguments, int pos) { CallRuntime* call = - new (zone_) CallRuntime(zone_, name, function, arguments, pos, id_gen_); + new (zone_) CallRuntime(zone_, name, function, arguments, pos); VISIT_AND_RETURN(CallRuntime, call) } @@ -3411,7 +3580,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Expression* expression, int pos) { UnaryOperation* node = - new (zone_) UnaryOperation(zone_, op, expression, pos, id_gen_); + new (zone_) UnaryOperation(zone_, op, expression, pos); VISIT_AND_RETURN(UnaryOperation, node) } @@ -3420,7 +3589,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Expression* right, int pos) { BinaryOperation* node = - new (zone_) BinaryOperation(zone_, op, left, right, pos, id_gen_); + new (zone_) BinaryOperation(zone_, op, left, right, pos); VISIT_AND_RETURN(BinaryOperation, node) } @@ -3429,7 +3598,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Expression* expr, int pos) { CountOperation* node = - new (zone_) CountOperation(zone_, op, is_prefix, expr, pos, id_gen_); + new (zone_) CountOperation(zone_, op, is_prefix, expr, pos); VISIT_AND_RETURN(CountOperation, node) } @@ -3438,7 +3607,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Expression* right, int pos) { CompareOperation* node = - new (zone_) CompareOperation(zone_, op, left, right, pos, id_gen_); + new (zone_) CompareOperation(zone_, op, left, right, pos); VISIT_AND_RETURN(CompareOperation, node) } @@ -3447,7 +3616,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Expression* else_expression, int position) { Conditional* cond = new (zone_) Conditional( - zone_, condition, then_expression, else_expression, position, id_gen_); + zone_, condition, then_expression, else_expression, position); VISIT_AND_RETURN(Conditional, cond) } @@ -3455,9 +3624,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Expression* target, Expression* value, int pos) { - Assignment* assign = - new (zone_) Assignment(zone_, op, target, value, pos, id_gen_); - assign->Init(zone_, this); + Assignment* assign = new (zone_) Assignment(zone_, op, target, value, pos); + assign->Init(this); VISIT_AND_RETURN(Assignment, assign) } @@ -3466,13 +3634,13 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Yield::Kind yield_kind, int pos) { if (!expression) expression = NewUndefinedLiteral(pos); - Yield* yield = new (zone_) - Yield(zone_, generator_object, expression, yield_kind, pos, id_gen_); + Yield* yield = + new (zone_) Yield(zone_, generator_object, expression, yield_kind, pos); VISIT_AND_RETURN(Yield, yield) } Throw* NewThrow(Expression* exception, int pos) { - Throw* t = new (zone_) Throw(zone_, exception, pos, id_gen_); + Throw* t = new (zone_) Throw(zone_, exception, pos); VISIT_AND_RETURN(Throw, t) } @@ -3488,8 +3656,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED { FunctionLiteral* lit = new (zone_) FunctionLiteral( zone_, name, ast_value_factory, scope, body, materialized_literal_count, expected_property_count, handler_count, parameter_count, function_type, - has_duplicate_parameters, is_function, is_parenthesized, kind, position, - id_gen_); + has_duplicate_parameters, is_function, is_parenthesized, kind, + position); // Top-level literal doesn't count for the AST's properties. if (is_function == FunctionLiteral::kIsFunction) { visitor_.VisitFunctionLiteral(lit); @@ -3500,9 +3668,10 @@ class AstNodeFactory FINAL BASE_EMBEDDED { ClassLiteral* NewClassLiteral(const AstRawString* name, Expression* extends, Expression* constructor, ZoneList* properties, - int position) { - ClassLiteral* lit = new (zone_) ClassLiteral( - zone_, name, extends, constructor, properties, position, id_gen_); + int start_position, int end_position) { + ClassLiteral* lit = + new (zone_) ClassLiteral(zone_, name, extends, constructor, properties, + start_position, end_position); VISIT_AND_RETURN(ClassLiteral, lit) } @@ -3510,18 +3679,17 @@ class AstNodeFactory FINAL BASE_EMBEDDED { v8::Extension* extension, int pos) { NativeFunctionLiteral* lit = - new (zone_) NativeFunctionLiteral(zone_, name, extension, pos, id_gen_); + new (zone_) NativeFunctionLiteral(zone_, name, extension, pos); VISIT_AND_RETURN(NativeFunctionLiteral, lit) } ThisFunction* NewThisFunction(int pos) { - ThisFunction* fun = new (zone_) ThisFunction(zone_, pos, id_gen_); + ThisFunction* fun = new (zone_) ThisFunction(zone_, pos); VISIT_AND_RETURN(ThisFunction, fun) } SuperReference* NewSuperReference(VariableProxy* this_var, int pos) { - SuperReference* super = - new (zone_) SuperReference(zone_, this_var, pos, id_gen_); + SuperReference* super = new (zone_) SuperReference(zone_, this_var, pos); VISIT_AND_RETURN(SuperReference, super); } @@ -3531,7 +3699,6 @@ class AstNodeFactory FINAL BASE_EMBEDDED { Zone* zone_; Visitor visitor_; AstValueFactory* ast_value_factory_; - AstNode::IdGen* id_gen_; }; diff --git a/deps/v8/src/base/atomicops.h b/deps/v8/src/base/atomicops.h index eba172f0be..675e43fad0 100644 --- a/deps/v8/src/base/atomicops.h +++ b/deps/v8/src/base/atomicops.h @@ -25,7 +25,7 @@ #ifndef V8_BASE_ATOMICOPS_H_ #define V8_BASE_ATOMICOPS_H_ -#include "include/v8stdint.h" +#include #include "src/base/build_config.h" #if defined(_WIN32) && defined(V8_HOST_ARCH_64_BIT) @@ -42,15 +42,17 @@ namespace base { typedef char Atomic8; typedef int32_t Atomic32; -#ifdef V8_HOST_ARCH_64_BIT +#if defined(__native_client__) +typedef int64_t Atomic64; +#elif defined(V8_HOST_ARCH_64_BIT) // We need to be able to go between Atomic64 and AtomicWord implicitly. This // means Atomic64 and AtomicWord should be the same type on 64-bit. #if defined(__ILP32__) typedef int64_t Atomic64; #else typedef intptr_t Atomic64; -#endif -#endif +#endif // defined(V8_HOST_ARCH_64_BIT) +#endif // defined(__native_client__) // Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or // Atomic64 routines below, depending on your architecture. @@ -140,6 +142,8 @@ Atomic64 Release_Load(volatile const Atomic64* ptr); #include "src/base/atomicops_internals_x86_msvc.h" #elif defined(__APPLE__) #include "src/base/atomicops_internals_mac.h" +#elif defined(__native_client__) +#include "src/base/atomicops_internals_portable.h" #elif defined(__GNUC__) && V8_HOST_ARCH_ARM64 #include "src/base/atomicops_internals_arm64_gcc.h" #elif defined(__GNUC__) && V8_HOST_ARCH_ARM diff --git a/deps/v8/src/base/atomicops_internals_mac.h b/deps/v8/src/base/atomicops_internals_mac.h index a046872e4d..84f9dbcd75 100644 --- a/deps/v8/src/base/atomicops_internals_mac.h +++ b/deps/v8/src/base/atomicops_internals_mac.h @@ -12,6 +12,20 @@ namespace v8 { namespace base { +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + +inline void MemoryBarrier() { OSMemoryBarrier(); } + +inline void AcquireMemoryBarrier() { +// On x86 processors, loads already have acquire semantics, so +// there is no need to put a full barrier here. +#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 + ATOMICOPS_COMPILER_BARRIER(); +#else + MemoryBarrier(); +#endif +} + inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { @@ -46,10 +60,6 @@ inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, return OSAtomicAdd32Barrier(increment, const_cast(ptr)); } -inline void MemoryBarrier() { - OSMemoryBarrier(); -} - inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { @@ -98,7 +108,7 @@ inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { Atomic32 value = *ptr; - MemoryBarrier(); + AcquireMemoryBarrier(); return value; } @@ -188,7 +198,7 @@ inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { Atomic64 value = *ptr; - MemoryBarrier(); + AcquireMemoryBarrier(); return value; } @@ -199,6 +209,7 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) { #endif // defined(__LP64__) +#undef ATOMICOPS_COMPILER_BARRIER } } // namespace v8::base #endif // V8_BASE_ATOMICOPS_INTERNALS_MAC_H_ diff --git a/deps/v8/src/base/atomicops_internals_portable.h b/deps/v8/src/base/atomicops_internals_portable.h new file mode 100644 index 0000000000..a3a6e74c72 --- /dev/null +++ b/deps/v8/src/base/atomicops_internals_portable.h @@ -0,0 +1,138 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is an internal atomic implementation, use atomicops.h instead. + +#ifndef V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ +#define V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ + +namespace v8 { +namespace base { + +inline void MemoryBarrier() { __sync_synchronize(); } + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return __sync_val_compare_and_swap(ptr, old_value, new_value); +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __sync_lock_test_and_set(ptr, new_value); +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return __sync_add_and_fetch(ptr, increment); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return __sync_add_and_fetch(ptr, increment); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, Atomic32 new_value) { + return __sync_val_compare_and_swap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, Atomic32 new_value) { + return __sync_val_compare_and_swap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic8* ptr, Atomic8 value) { + __sync_lock_test_and_set(ptr, value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + __sync_lock_test_and_set(ptr, value); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + __sync_lock_test_and_set(ptr, value); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + __sync_lock_test_and_set(ptr, value); +} + +inline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) { + return __sync_add_and_fetch(ptr, 0); +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return __sync_add_and_fetch(ptr, 0); +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + return __sync_add_and_fetch(ptr, 0); +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + return __sync_add_and_fetch(ptr, 0); +} + +// 64-bit versions of the operations. +// See the 32-bit versions for comments. + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return __sync_val_compare_and_swap(ptr, old_value, new_value); +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __sync_lock_test_and_set(ptr, new_value); +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return __sync_add_and_fetch(ptr, increment); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return __sync_add_and_fetch(ptr, increment); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, Atomic64 new_value) { + return __sync_val_compare_and_swap(ptr, old_value, new_value); +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, Atomic64 new_value) { + return __sync_val_compare_and_swap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + __sync_lock_test_and_set(ptr, value); +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + __sync_lock_test_and_set(ptr, value); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + __sync_lock_test_and_set(ptr, value); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return __sync_add_and_fetch(ptr, 0); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + return __sync_add_and_fetch(ptr, 0); +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + return __sync_add_and_fetch(ptr, 0); +} +} +} // namespace v8::base + +#endif // V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ diff --git a/deps/v8/src/base/base.gyp b/deps/v8/src/base/base.gyp deleted file mode 100644 index e391e2e8d1..0000000000 --- a/deps/v8/src/base/base.gyp +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2014 the V8 project authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'variables': { - 'v8_code': 1, - }, - 'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'], - 'targets': [ - { - 'target_name': 'base-unittests', - 'type': 'executable', - 'dependencies': [ - '../../testing/gtest.gyp:gtest', - '../../testing/gtest.gyp:gtest_main', - '../../tools/gyp/v8.gyp:v8_libbase', - ], - 'include_dirs': [ - '../..', - ], - 'sources': [ ### gcmole(all) ### - 'bits-unittest.cc', - 'cpu-unittest.cc', - 'division-by-constant-unittest.cc', - 'flags-unittest.cc', - 'platform/condition-variable-unittest.cc', - 'platform/mutex-unittest.cc', - 'platform/platform-unittest.cc', - 'platform/semaphore-unittest.cc', - 'platform/time-unittest.cc', - 'sys-info-unittest.cc', - 'utils/random-number-generator-unittest.cc', - ], - 'conditions': [ - ['os_posix == 1', { - # TODO(svenpanne): This is a temporary work-around to fix the warnings - # that show up because we use -std=gnu++0x instead of -std=c++11. - 'cflags!': [ - '-pedantic', - ], - }], - ], - }, - ], -} diff --git a/deps/v8/src/base/bits.cc b/deps/v8/src/base/bits.cc index 6daee532a7..74d747fc90 100644 --- a/deps/v8/src/base/bits.cc +++ b/deps/v8/src/base/bits.cc @@ -3,6 +3,9 @@ // found in the LICENSE file. #include "src/base/bits.h" + +#include + #include "src/base/logging.h" namespace v8 { @@ -20,6 +23,31 @@ uint32_t RoundUpToPowerOfTwo32(uint32_t value) { return value + 1; } + +int32_t SignedMulHigh32(int32_t lhs, int32_t rhs) { + int64_t const value = static_cast(lhs) * static_cast(rhs); + return bit_cast(bit_cast(value) >> 32u); +} + + +int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc) { + return bit_cast(bit_cast(acc) + + bit_cast(SignedMulHigh32(lhs, rhs))); +} + + +int32_t SignedDiv32(int32_t lhs, int32_t rhs) { + if (rhs == 0) return 0; + if (rhs == -1) return -lhs; + return lhs / rhs; +} + + +int32_t SignedMod32(int32_t lhs, int32_t rhs) { + if (rhs == 0 || rhs == -1) return 0; + return lhs % rhs; +} + } // namespace bits } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/bits.h b/deps/v8/src/base/bits.h index e6a733a45d..0f4d4c712b 100644 --- a/deps/v8/src/base/bits.h +++ b/deps/v8/src/base/bits.h @@ -5,7 +5,7 @@ #ifndef V8_BASE_BITS_H_ #define V8_BASE_BITS_H_ -#include "include/v8stdint.h" +#include #include "src/base/macros.h" #if V8_CC_MSVC #include @@ -19,7 +19,7 @@ namespace base { namespace bits { // CountPopulation32(value) returns the number of bits set in |value|. -inline uint32_t CountPopulation32(uint32_t value) { +inline unsigned CountPopulation32(uint32_t value) { #if V8_HAS_BUILTIN_POPCOUNT return __builtin_popcount(value); #else @@ -28,20 +28,31 @@ inline uint32_t CountPopulation32(uint32_t value) { value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f); value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff); value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff); - return value; + return static_cast(value); +#endif +} + + +// CountPopulation64(value) returns the number of bits set in |value|. +inline unsigned CountPopulation64(uint64_t value) { +#if V8_HAS_BUILTIN_POPCOUNT + return __builtin_popcountll(value); +#else + return CountPopulation32(static_cast(value)) + + CountPopulation32(static_cast(value >> 32)); #endif } // CountLeadingZeros32(value) returns the number of zero bits following the most // significant 1 bit in |value| if |value| is non-zero, otherwise it returns 32. -inline uint32_t CountLeadingZeros32(uint32_t value) { +inline unsigned CountLeadingZeros32(uint32_t value) { #if V8_HAS_BUILTIN_CLZ return value ? __builtin_clz(value) : 32; #elif V8_CC_MSVC unsigned long result; // NOLINT(runtime/int) if (!_BitScanReverse(&result, value)) return 32; - return static_cast(31 - result); + return static_cast(31 - result); #else value = value | (value >> 1); value = value | (value >> 2); @@ -53,16 +64,33 @@ inline uint32_t CountLeadingZeros32(uint32_t value) { } +// CountLeadingZeros64(value) returns the number of zero bits following the most +// significant 1 bit in |value| if |value| is non-zero, otherwise it returns 64. +inline unsigned CountLeadingZeros64(uint64_t value) { +#if V8_HAS_BUILTIN_CLZ + return value ? __builtin_clzll(value) : 64; +#else + value = value | (value >> 1); + value = value | (value >> 2); + value = value | (value >> 4); + value = value | (value >> 8); + value = value | (value >> 16); + value = value | (value >> 32); + return CountPopulation64(~value); +#endif +} + + // CountTrailingZeros32(value) returns the number of zero bits preceding the // least significant 1 bit in |value| if |value| is non-zero, otherwise it // returns 32. -inline uint32_t CountTrailingZeros32(uint32_t value) { +inline unsigned CountTrailingZeros32(uint32_t value) { #if V8_HAS_BUILTIN_CTZ return value ? __builtin_ctz(value) : 32; #elif V8_CC_MSVC unsigned long result; // NOLINT(runtime/int) if (!_BitScanForward(&result, value)) return 32; - return static_cast(result); + return static_cast(result); #else if (value == 0) return 32; unsigned count = 0; @@ -73,6 +101,22 @@ inline uint32_t CountTrailingZeros32(uint32_t value) { } +// CountTrailingZeros64(value) returns the number of zero bits preceding the +// least significant 1 bit in |value| if |value| is non-zero, otherwise it +// returns 64. +inline unsigned CountTrailingZeros64(uint64_t value) { +#if V8_HAS_BUILTIN_CTZ + return value ? __builtin_ctzll(value) : 64; +#else + if (value == 0) return 64; + unsigned count = 0; + for (value ^= value - 1; value >>= 1; ++count) + ; + return count; +#endif +} + + // Returns true iff |value| is a power of 2. inline bool IsPowerOfTwo32(uint32_t value) { return value && !(value & (value - 1)); @@ -143,6 +187,44 @@ inline bool SignedSubOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { #endif } + +// SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and +// |rhs|, extracts the most significant 32 bits of the result, and returns +// those. +int32_t SignedMulHigh32(int32_t lhs, int32_t rhs); + + +// SignedMulHighAndAdd32(lhs, rhs, acc) multiplies two signed 32-bit values +// |lhs| and |rhs|, extracts the most significant 32 bits of the result, and +// adds the accumulate value |acc|. +int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc); + + +// SignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient +// truncated to int32. If |rhs| is zero, then zero is returned. If |lhs| +// is minint and |rhs| is -1, it returns minint. +int32_t SignedDiv32(int32_t lhs, int32_t rhs); + + +// SignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder +// truncated to int32. If either |rhs| is zero or |lhs| is minint and |rhs| +// is -1, it returns zero. +int32_t SignedMod32(int32_t lhs, int32_t rhs); + + +// UnsignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient +// truncated to uint32. If |rhs| is zero, then zero is returned. +inline uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs) { + return rhs ? lhs / rhs : 0u; +} + + +// UnsignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder +// truncated to uint32. If |rhs| is zero, then zero is returned. +inline uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs) { + return rhs ? lhs % rhs : 0u; +} + } // namespace bits } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/build_config.h b/deps/v8/src/base/build_config.h index 2bf57c9633..f52877657c 100644 --- a/deps/v8/src/base/build_config.h +++ b/deps/v8/src/base/build_config.h @@ -29,6 +29,10 @@ #define V8_HOST_ARCH_64_BIT 1 #endif #endif // __native_client__ +#elif defined(__pnacl__) +// PNaCl is also ILP-32. +#define V8_HOST_ARCH_IA32 1 +#define V8_HOST_ARCH_32_BIT 1 #elif defined(_M_IX86) || defined(__i386__) #define V8_HOST_ARCH_IA32 1 #define V8_HOST_ARCH_32_BIT 1 diff --git a/deps/v8/src/base/compiler-specific.h b/deps/v8/src/base/compiler-specific.h index 475a32c2c1..9755fc13ce 100644 --- a/deps/v8/src/base/compiler-specific.h +++ b/deps/v8/src/base/compiler-specific.h @@ -7,15 +7,13 @@ #include "include/v8config.h" -// Annotate a variable indicating it's ok if the variable is not used. -// (Typically used to silence a compiler warning when the assignment -// is important for some other reason.) +// Annotate a typedef or function indicating it's ok if it's not used. // Use like: -// int x ALLOW_UNUSED = ...; +// typedef Foo Bar ALLOW_UNUSED_TYPE; #if V8_HAS_ATTRIBUTE_UNUSED -#define ALLOW_UNUSED __attribute__((unused)) +#define ALLOW_UNUSED_TYPE __attribute__((unused)) #else -#define ALLOW_UNUSED +#define ALLOW_UNUSED_TYPE #endif @@ -39,8 +37,6 @@ #define FINAL final #elif V8_HAS___FINAL #define FINAL __final -#elif V8_HAS_SEALED -#define FINAL sealed #else #define FINAL /* NOT SUPPORTED */ #endif diff --git a/deps/v8/src/base/cpu.cc b/deps/v8/src/base/cpu.cc index fbfbcf683b..5bc8b13a97 100644 --- a/deps/v8/src/base/cpu.cc +++ b/deps/v8/src/base/cpu.cc @@ -7,12 +7,18 @@ #if V8_LIBC_MSVCRT #include // __cpuid() #endif -#if V8_OS_POSIX -#include // sysconf() +#if V8_OS_LINUX +#include // AT_HWCAP +#endif +#if V8_GLIBC_PREREQ(2, 16) +#include // getauxval() #endif #if V8_OS_QNX #include // cpuinfo #endif +#if V8_OS_POSIX +#include // sysconf() +#endif #include #include @@ -29,7 +35,9 @@ namespace v8 { namespace base { -#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 +#if defined(__pnacl__) +// Portable host shouldn't do feature detection. +#elif V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 // Define __cpuid() for non-MSVC libraries. #if !V8_LIBC_MSVCRT @@ -90,11 +98,12 @@ static V8_INLINE void __cpuid(int cpu_info[4], int info_type) { #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) #define HWCAP_LPAE (1 << 20) -#define AT_HWCAP 16 - -// Read the ELF HWCAP flags by parsing /proc/self/auxv. static uint32_t ReadELFHWCaps() { uint32_t result = 0; +#if V8_GLIBC_PREREQ(2, 16) + result = static_cast(getauxval(AT_HWCAP)); +#else + // Read the ELF HWCAP flags by parsing /proc/self/auxv. FILE* fp = fopen("/proc/self/auxv", "r"); if (fp != NULL) { struct { uint32_t tag; uint32_t value; } entry; @@ -110,6 +119,7 @@ static uint32_t ReadELFHWCaps() { } fclose(fp); } +#endif return result; } @@ -119,13 +129,18 @@ static uint32_t ReadELFHWCaps() { int __detect_fp64_mode(void) { double result = 0; // Bit representation of (double)1 is 0x3FF0000000000000. - asm( - "lui $t0, 0x3FF0\n\t" - "ldc1 $f0, %0\n\t" - "mtc1 $t0, $f1\n\t" - "sdc1 $f0, %0\n\t" - : "+m" (result) - : : "t0", "$f0", "$f1", "memory"); + __asm__ volatile( + ".set push\n\t" + ".set noreorder\n\t" + ".set oddspreg\n\t" + "lui $t0, 0x3FF0\n\t" + "ldc1 $f0, %0\n\t" + "mtc1 $t0, $f1\n\t" + "sdc1 $f0, %0\n\t" + ".set pop\n\t" + : "+m"(result) + : + : "t0", "$f0", "$f1", "memory"); return !(result == 1); } @@ -133,9 +148,22 @@ int __detect_fp64_mode(void) { int __detect_mips_arch_revision(void) { // TODO(dusmil): Do the specific syscall as soon as it is implemented in mips - // kernel. Currently fail-back to the least common denominator which is - // mips32 revision 1. - return 1; + // kernel. + uint32_t result = 0; + __asm__ volatile( + "move $v0, $zero\n\t" + // Encoding for "addi $v0, $v0, 1" on non-r6, + // which is encoding for "bovc $v0, %v0, 1" on r6. + // Use machine code directly to avoid compilation errors with different + // toolchains and maintain compatibility. + ".word 0x20420001\n\t" + "sw $v0, %0\n\t" + : "=m"(result) + : + : "v0", "memory"); + // Result is 0 on r6 architectures, 1 on other architecture revisions. + // Fall-back to the least common denominator which is mips32 revision 1. + return result ? 1 : 6; } #endif @@ -290,7 +318,11 @@ CPU::CPU() : stepping_(0), has_vfp3_d32_(false), is_fp64_mode_(false) { memcpy(vendor_, "Unknown", 8); -#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 +#if V8_OS_NACL +// Portable host shouldn't do feature detection. +// TODO(jfb): Remove the hardcoded ARM simulator flags in the build, and +// hardcode them here instead. +#elif V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 int cpu_info[4]; // __cpuid with an InfoType argument of 0 returns the number of diff --git a/deps/v8/src/base/division-by-constant.cc b/deps/v8/src/base/division-by-constant.cc index 235d39fe57..5167b7a60c 100644 --- a/deps/v8/src/base/division-by-constant.cc +++ b/deps/v8/src/base/division-by-constant.cc @@ -52,7 +52,7 @@ MagicNumbersForDivision SignedDivisionByConstant(T d) { delta = ad - r2; } while (q1 < delta || (q1 == delta && r1 == 0)); T mul = q2 + 1; - return {neg ? (0 - mul) : mul, p - bits, false}; + return MagicNumbersForDivision(neg ? (0 - mul) : mul, p - bits, false); } @@ -93,7 +93,7 @@ MagicNumbersForDivision UnsignedDivisionByConstant(T d, } delta = d - 1 - r2; } while (p < bits * 2 && (q1 < delta || (q1 == delta && r1 == 0))); - return {q2 + 1, p - bits, a}; + return MagicNumbersForDivision(q2 + 1, p - bits, a); } diff --git a/deps/v8/src/base/flags.h b/deps/v8/src/base/flags.h index f3420ee536..060dba818a 100644 --- a/deps/v8/src/base/flags.h +++ b/deps/v8/src/base/flags.h @@ -26,8 +26,9 @@ class Flags FINAL { typedef S mask_type; Flags() : mask_(0) {} - Flags(flag_type flag) : mask_(flag) {} // NOLINT(runtime/explicit) - explicit Flags(mask_type mask) : mask_(mask) {} + Flags(flag_type flag) // NOLINT(runtime/explicit) + : mask_(static_cast(flag)) {} + explicit Flags(mask_type mask) : mask_(static_cast(mask)) {} Flags& operator&=(const Flags& flags) { mask_ &= flags.mask_; @@ -64,42 +65,44 @@ class Flags FINAL { }; -#define DEFINE_OPERATORS_FOR_FLAGS(Type) \ - inline Type operator&(Type::flag_type lhs, \ - Type::flag_type rhs)ALLOW_UNUSED WARN_UNUSED_RESULT; \ - inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) { \ - return Type(lhs) & rhs; \ - } \ - inline Type operator&(Type::flag_type lhs, \ - const Type& rhs)ALLOW_UNUSED WARN_UNUSED_RESULT; \ - inline Type operator&(Type::flag_type lhs, const Type& rhs) { \ - return rhs & lhs; \ - } \ - inline void operator&(Type::flag_type lhs, Type::mask_type rhs)ALLOW_UNUSED; \ - inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {} \ - inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) \ - ALLOW_UNUSED WARN_UNUSED_RESULT; \ - inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) { \ - return Type(lhs) | rhs; \ - } \ - inline Type operator|(Type::flag_type lhs, const Type& rhs) \ - ALLOW_UNUSED WARN_UNUSED_RESULT; \ - inline Type operator|(Type::flag_type lhs, const Type& rhs) { \ - return rhs | lhs; \ - } \ - inline void operator|(Type::flag_type lhs, Type::mask_type rhs) \ - ALLOW_UNUSED; \ - inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {} \ - inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) \ - ALLOW_UNUSED WARN_UNUSED_RESULT; \ - inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \ - return Type(lhs) ^ rhs; \ - } inline Type operator^(Type::flag_type lhs, const Type& rhs) \ - ALLOW_UNUSED WARN_UNUSED_RESULT; \ - inline Type operator^(Type::flag_type lhs, const Type& rhs) { \ - return rhs ^ lhs; \ - } inline void operator^(Type::flag_type lhs, Type::mask_type rhs) \ - ALLOW_UNUSED; \ +#define DEFINE_OPERATORS_FOR_FLAGS(Type) \ + inline Type operator&( \ + Type::flag_type lhs, \ + Type::flag_type rhs)ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ + inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) { \ + return Type(lhs) & rhs; \ + } \ + inline Type operator&(Type::flag_type lhs, \ + const Type& rhs)ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ + inline Type operator&(Type::flag_type lhs, const Type& rhs) { \ + return rhs & lhs; \ + } \ + inline void operator&(Type::flag_type lhs, \ + Type::mask_type rhs)ALLOW_UNUSED_TYPE; \ + inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {} \ + inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) \ + ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ + inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) { \ + return Type(lhs) | rhs; \ + } \ + inline Type operator|(Type::flag_type lhs, const Type& rhs) \ + ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ + inline Type operator|(Type::flag_type lhs, const Type& rhs) { \ + return rhs | lhs; \ + } \ + inline void operator|(Type::flag_type lhs, Type::mask_type rhs) \ + ALLOW_UNUSED_TYPE; \ + inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {} \ + inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) \ + ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ + inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \ + return Type(lhs) ^ rhs; \ + } inline Type operator^(Type::flag_type lhs, const Type& rhs) \ + ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ + inline Type operator^(Type::flag_type lhs, const Type& rhs) { \ + return rhs ^ lhs; \ + } inline void operator^(Type::flag_type lhs, Type::mask_type rhs) \ + ALLOW_UNUSED_TYPE; \ inline void operator^(Type::flag_type lhs, Type::mask_type rhs) {} } // namespace base diff --git a/deps/v8/src/base/functional.cc b/deps/v8/src/base/functional.cc new file mode 100644 index 0000000000..d212912efa --- /dev/null +++ b/deps/v8/src/base/functional.cc @@ -0,0 +1,111 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This also contains public domain code from MurmurHash. From the +// MurmurHash header: +// +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +#include "src/base/functional.h" + +#include + +#include "src/base/bits.h" + +namespace v8 { +namespace base { + +namespace { + +// Thomas Wang, Integer Hash Functions. +// https://gist.github.com/badboy/6267743 +template +V8_INLINE size_t hash_value_unsigned(T v) { + switch (sizeof(T)) { + case 4: { + // "32 bit Mix Functions" + v = ~v + (v << 15); // v = (v << 15) - v - 1; + v = v ^ (v >> 12); + v = v + (v << 2); + v = v ^ (v >> 4); + v = v * 2057; // v = (v + (v << 3)) + (v << 11); + v = v ^ (v >> 16); + return static_cast(v); + } + case 8: { + switch (sizeof(size_t)) { + case 4: { + // "64 bit to 32 bit Hash Functions" + v = ~v + (v << 18); // v = (v << 18) - v - 1; + v = v ^ (v >> 31); + v = v * 21; // v = (v + (v << 2)) + (v << 4); + v = v ^ (v >> 11); + v = v + (v << 6); + v = v ^ (v >> 22); + return static_cast(v); + } + case 8: { + // "64 bit Mix Functions" + v = ~v + (v << 21); // v = (v << 21) - v - 1; + v = v ^ (v >> 24); + v = (v + (v << 3)) + (v << 8); // v * 265 + v = v ^ (v >> 14); + v = (v + (v << 2)) + (v << 4); // v * 21 + v = v ^ (v >> 28); + v = v + (v << 31); + return static_cast(v); + } + } + } + } + UNREACHABLE(); + return static_cast(v); +} + +} // namespace + + +// This code was taken from MurmurHash. +size_t hash_combine(size_t seed, size_t value) { +#if V8_HOST_ARCH_32_BIT + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + value *= c1; + value = bits::RotateRight32(value, 15); + value *= c2; + + seed ^= value; + seed = bits::RotateRight32(seed, 13); + seed = seed * 5 + 0xe6546b64; +#else + const uint64_t m = V8_UINT64_C(0xc6a4a7935bd1e995); + const uint32_t r = 47; + + value *= m; + value ^= value >> r; + value *= m; + + seed ^= value; + seed *= m; +#endif // V8_HOST_ARCH_32_BIT + return seed; +} + + +size_t hash_value(unsigned int v) { return hash_value_unsigned(v); } + + +size_t hash_value(unsigned long v) { // NOLINT(runtime/int) + return hash_value_unsigned(v); +} + + +size_t hash_value(unsigned long long v) { // NOLINT(runtime/int) + return hash_value_unsigned(v); +} + +} // namespace base +} // namespace v8 diff --git a/deps/v8/src/base/functional.h b/deps/v8/src/base/functional.h new file mode 100644 index 0000000000..ff0d8075b9 --- /dev/null +++ b/deps/v8/src/base/functional.h @@ -0,0 +1,227 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_BASE_FUNCTIONAL_H_ +#define V8_BASE_FUNCTIONAL_H_ + +#include +#include + +#include +#include +#include +#include + +#include "src/base/macros.h" + +namespace v8 { +namespace base { + +// base::hash is an implementation of the hash function object specified by +// C++11. It was designed to be compatible with std::hash (in C++11) and +// boost:hash (which in turn is based on the hash function object specified by +// the Draft Technical Report on C++ Library Extensions (TR1)). +// +// base::hash is implemented by calling the hash_value function. The namespace +// isn't specified so that it can detect overloads via argument dependant +// lookup. So if there is a free function hash_value in the same namespace as a +// custom type, it will get called. +// +// If users are asked to implement a hash function for their own types with no +// guidance, they generally write bad hash functions. Instead, we provide a +// simple function base::hash_combine to pass hash-relevant member variables +// into, in order to define a decent hash function. base::hash_combine is +// declared as: +// +// template +// size_t hash_combine(const T& v, const Ts& ...vs); +// +// Consider the following example: +// +// namespace v8 { +// namespace bar { +// struct Point { int x; int y; }; +// size_t hash_value(Point const& p) { +// return base::hash_combine(p.x, p.y); +// } +// } +// +// namespace foo { +// void DoSomeWork(bar::Point const& p) { +// base::hash h; +// ... +// size_t hash_code = h(p); // calls bar::hash_value(Point const&) +// ... +// } +// } +// } +// +// Based on the "Hashing User-Defined Types in C++1y" proposal from Jeffrey +// Yasskin and Chandler Carruth, see +// http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2012/n3333.html. + +template +struct hash; + + +V8_INLINE size_t hash_combine() { return 0u; } +V8_INLINE size_t hash_combine(size_t seed) { return seed; } +size_t hash_combine(size_t seed, size_t value); +template +V8_INLINE size_t hash_combine(T const& v, Ts const&... vs) { + return hash_combine(hash_combine(vs...), hash()(v)); +} + + +template +V8_INLINE size_t hash_range(Iterator first, Iterator last) { + size_t seed = 0; + for (; first != last; ++first) { + seed = hash_combine(seed, *first); + } + return seed; +} + + +#define V8_BASE_HASH_VALUE_TRIVIAL(type) \ + V8_INLINE size_t hash_value(type v) { return static_cast(v); } +V8_BASE_HASH_VALUE_TRIVIAL(bool) +V8_BASE_HASH_VALUE_TRIVIAL(unsigned char) +V8_BASE_HASH_VALUE_TRIVIAL(unsigned short) // NOLINT(runtime/int) +#undef V8_BASE_HASH_VALUE_TRIVIAL + +size_t hash_value(unsigned int); +size_t hash_value(unsigned long); // NOLINT(runtime/int) +size_t hash_value(unsigned long long); // NOLINT(runtime/int) + +#define V8_BASE_HASH_VALUE_SIGNED(type) \ + V8_INLINE size_t hash_value(signed type v) { \ + return hash_value(bit_cast(v)); \ + } +V8_BASE_HASH_VALUE_SIGNED(char) +V8_BASE_HASH_VALUE_SIGNED(short) // NOLINT(runtime/int) +V8_BASE_HASH_VALUE_SIGNED(int) // NOLINT(runtime/int) +V8_BASE_HASH_VALUE_SIGNED(long) // NOLINT(runtime/int) +V8_BASE_HASH_VALUE_SIGNED(long long) // NOLINT(runtime/int) +#undef V8_BASE_HASH_VALUE_SIGNED + +V8_INLINE size_t hash_value(float v) { + // 0 and -0 both hash to zero. + return v != 0.0f ? hash_value(bit_cast(v)) : 0; +} + +V8_INLINE size_t hash_value(double v) { + // 0 and -0 both hash to zero. + return v != 0.0 ? hash_value(bit_cast(v)) : 0; +} + +template +V8_INLINE size_t hash_value(const T (&v)[N]) { + return hash_range(v, v + N); +} + +template +V8_INLINE size_t hash_value(T (&v)[N]) { + return hash_range(v, v + N); +} + +template +V8_INLINE size_t hash_value(T* const& v) { + return hash_value(bit_cast(v)); +} + +template +V8_INLINE size_t hash_value(std::pair const& v) { + return hash_combine(v.first, v.second); +} + + +template +struct hash : public std::unary_function { + V8_INLINE size_t operator()(T const& v) const { return hash_value(v); } +}; + +#define V8_BASE_HASH_SPECIALIZE(type) \ + template <> \ + struct hash : public std::unary_function { \ + V8_INLINE size_t operator()(type const v) const { \ + return ::v8::base::hash_value(v); \ + } \ + }; +V8_BASE_HASH_SPECIALIZE(bool) +V8_BASE_HASH_SPECIALIZE(signed char) +V8_BASE_HASH_SPECIALIZE(unsigned char) +V8_BASE_HASH_SPECIALIZE(short) // NOLINT(runtime/int) +V8_BASE_HASH_SPECIALIZE(unsigned short) // NOLINT(runtime/int) +V8_BASE_HASH_SPECIALIZE(int) +V8_BASE_HASH_SPECIALIZE(unsigned int) +V8_BASE_HASH_SPECIALIZE(long) // NOLINT(runtime/int) +V8_BASE_HASH_SPECIALIZE(unsigned long) // NOLINT(runtime/int) +V8_BASE_HASH_SPECIALIZE(long long) // NOLINT(runtime/int) +V8_BASE_HASH_SPECIALIZE(unsigned long long) // NOLINT(runtime/int) +V8_BASE_HASH_SPECIALIZE(float) +V8_BASE_HASH_SPECIALIZE(double) +#undef V8_BASE_HASH_SPECIALIZE + +template +struct hash : public std::unary_function { + V8_INLINE size_t operator()(T* const v) const { + return ::v8::base::hash_value(v); + } +}; + + +// base::bit_equal_to is a function object class for bitwise equality +// comparison, similar to std::equal_to, except that the comparison is performed +// on the bit representation of the operands. +// +// base::bit_hash is a function object class for bitwise hashing, similar to +// base::hash. It can be used together with base::bit_equal_to to implement a +// hash data structure based on the bitwise representation of types. + +template +struct bit_equal_to : public std::binary_function {}; + +template +struct bit_hash : public std::unary_function {}; + +#define V8_BASE_BIT_SPECIALIZE_TRIVIAL(type) \ + template <> \ + struct bit_equal_to : public std::equal_to {}; \ + template <> \ + struct bit_hash : public hash {}; +V8_BASE_BIT_SPECIALIZE_TRIVIAL(signed char) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned char) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(short) // NOLINT(runtime/int) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned short) // NOLINT(runtime/int) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(int) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned int) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(long) // NOLINT(runtime/int) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long) // NOLINT(runtime/int) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(long long) // NOLINT(runtime/int) +V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long long) // NOLINT(runtime/int) +#undef V8_BASE_BIT_SPECIALIZE_TRIVIAL + +#define V8_BASE_BIT_SPECIALIZE_BIT_CAST(type, btype) \ + template <> \ + struct bit_equal_to : public std::binary_function { \ + V8_INLINE bool operator()(type lhs, type rhs) const { \ + return bit_cast(lhs) == bit_cast(rhs); \ + } \ + }; \ + template <> \ + struct bit_hash : public std::unary_function { \ + V8_INLINE size_t operator()(type v) const { \ + hash h; \ + return h(bit_cast(v)); \ + } \ + }; +V8_BASE_BIT_SPECIALIZE_BIT_CAST(float, uint32_t) +V8_BASE_BIT_SPECIALIZE_BIT_CAST(double, uint64_t) +#undef V8_BASE_BIT_SPECIALIZE_BIT_CAST + +} // namespace base +} // namespace v8 + +#endif // V8_BASE_FUNCTIONAL_H_ diff --git a/deps/v8/src/base/logging.h b/deps/v8/src/base/logging.h index 8e24bb0864..83c1bb6013 100644 --- a/deps/v8/src/base/logging.h +++ b/deps/v8/src/base/logging.h @@ -5,9 +5,9 @@ #ifndef V8_BASE_LOGGING_H_ #define V8_BASE_LOGGING_H_ +#include #include -#include "include/v8stdint.h" #include "src/base/build_config.h" extern "C" void V8_Fatal(const char* file, int line, const char* format, ...); diff --git a/deps/v8/src/base/macros.h b/deps/v8/src/base/macros.h index cef088cb81..80a89496a5 100644 --- a/deps/v8/src/base/macros.h +++ b/deps/v8/src/base/macros.h @@ -5,9 +5,11 @@ #ifndef V8_BASE_MACROS_H_ #define V8_BASE_MACROS_H_ +#include +#include + #include -#include "include/v8stdint.h" #include "src/base/build_config.h" #include "src/base/compiler-specific.h" #include "src/base/logging.h" @@ -23,6 +25,8 @@ (reinterpret_cast(&(reinterpret_cast(4)->field)) - 4) +#if V8_OS_NACL + // ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, // but can be used on anonymous types or types defined inside // functions. It's less safe than arraysize as it accepts some @@ -63,9 +67,6 @@ ((sizeof(a) / sizeof(*(a))) / \ static_cast(!(sizeof(a) % sizeof(*(a))))) // NOLINT - -#if V8_OS_NACL - // TODO(bmeurer): For some reason, the NaCl toolchain cannot handle the correct // definition of arraysize() below, so we have to use the unsafe version for // now. @@ -130,7 +131,7 @@ struct CompileAssert {}; #define COMPILE_ASSERT(expr, msg) \ typedef CompileAssert(expr)> \ - msg[static_cast(expr) ? 1 : -1] ALLOW_UNUSED + msg[static_cast(expr) ? 1 : -1] ALLOW_UNUSED_TYPE // Implementation details of COMPILE_ASSERT: // @@ -150,23 +151,11 @@ struct CompileAssert {}; // COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is // // not a compile-time constant. // -// - By using the type CompileAssert<(bool(expr))>, we ensures that +// - By using the type CompileAssert(expr)>, we ensure that // expr is a compile-time constant. (Template arguments must be // determined at compile-time.) // -// - The outer parentheses in CompileAssert<(bool(expr))> are necessary -// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written -// -// CompileAssert -// -// instead, these compilers will refuse to compile -// -// COMPILE_ASSERT(5 > 0, some_message); -// -// (They seem to think the ">" in "5 > 0" marks the end of the -// template argument list.) -// -// - The array size is (bool(expr) ? 1 : -1), instead of simply +// - The array size is (static_cast(expr) ? 1 : -1), instead of simply // // ((expr) ? 1 : -1). // @@ -308,10 +297,10 @@ template <> class StaticAssertion { }; // actually causes each use to introduce a new defined type with a // name depending on the source line. template class StaticAssertionHelper { }; -#define STATIC_ASSERT(test) \ - typedef \ - StaticAssertionHelper((test))>)> \ - SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) ALLOW_UNUSED +#define STATIC_ASSERT(test) \ + typedef StaticAssertionHelper< \ + sizeof(StaticAssertion((test))>)> \ + SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) ALLOW_UNUSED_TYPE #endif @@ -408,4 +397,22 @@ inline T RoundUp(T x, intptr_t m) { return RoundDown(static_cast(x + m - 1), m); } + +namespace v8 { +namespace base { + +// TODO(yangguo): This is a poor man's replacement for std::is_fundamental, +// which requires C++11. Switch to std::is_fundamental once possible. +template +inline bool is_fundamental() { + return false; +} + +template <> +inline bool is_fundamental() { + return true; +} +} +} // namespace v8::base + #endif // V8_BASE_MACROS_H_ diff --git a/deps/v8/src/base/once.h b/deps/v8/src/base/once.h index a8e8437afa..6bf741d38a 100644 --- a/deps/v8/src/base/once.h +++ b/deps/v8/src/base/once.h @@ -52,6 +52,8 @@ #ifndef V8_BASE_ONCE_H_ #define V8_BASE_ONCE_H_ +#include + #include "src/base/atomicops.h" namespace v8 { diff --git a/deps/v8/src/base/platform/platform-linux.cc b/deps/v8/src/base/platform/platform-linux.cc index eff5ced3b7..b13a1e85c5 100644 --- a/deps/v8/src/base/platform/platform-linux.cc +++ b/deps/v8/src/base/platform/platform-linux.cc @@ -109,7 +109,7 @@ const char* OS::LocalTimezone(double time, TimezoneCache* cache) { if (std::isnan(time)) return ""; time_t tv = static_cast(std::floor(time/msPerSecond)); struct tm* t = localtime(&tv); - if (NULL == t) return ""; + if (!t || !t->tm_zone) return ""; return t->tm_zone; #endif } diff --git a/deps/v8/src/base/platform/platform-posix.cc b/deps/v8/src/base/platform/platform-posix.cc index 0fc04fc110..0a222a612e 100644 --- a/deps/v8/src/base/platform/platform-posix.cc +++ b/deps/v8/src/base/platform/platform-posix.cc @@ -253,14 +253,14 @@ int OS::GetCurrentProcessId() { int OS::GetCurrentThreadId() { -#if defined(ANDROID) +#if V8_OS_MACOSX + return static_cast(pthread_mach_thread_np(pthread_self())); +#elif V8_OS_LINUX return static_cast(syscall(__NR_gettid)); -#elif defined(SYS_gettid) - return static_cast(syscall(SYS_gettid)); +#elif V8_OS_ANDROID + return static_cast(gettid()); #else - // PNaCL doesn't have a way to get an integral thread ID, but it doesn't - // really matter, because we only need it in PerfJitLogger::LogRecordedBuffer. - return 0; + return static_cast(pthread_self()); #endif } diff --git a/deps/v8/src/base/platform/platform-solaris.cc b/deps/v8/src/base/platform/platform-solaris.cc index b9ef465b3e..b9a2ec8e2e 100644 --- a/deps/v8/src/base/platform/platform-solaris.cc +++ b/deps/v8/src/base/platform/platform-solaris.cc @@ -31,26 +31,6 @@ #include "src/base/platform/platform.h" -// It seems there is a bug in some Solaris distributions (experienced in -// SunOS 5.10 Generic_141445-09) which make it difficult or impossible to -// access signbit() despite the availability of other C99 math functions. -#ifndef signbit -namespace std { -// Test sign - usually defined in math.h -int signbit(double x) { - // We need to take care of the special case of both positive and negative - // versions of zero. - if (x == 0) { - return fpclass(x) & FP_NZERO; - } else { - // This won't detect negative NaN but that should be okay since we don't - // assume that behavior. - return x < 0; - } -} -} // namespace std -#endif // signbit - namespace v8 { namespace base { diff --git a/deps/v8/src/base/platform/platform-win32.cc b/deps/v8/src/base/platform/platform-win32.cc index 10f89de680..1c46cf6811 100644 --- a/deps/v8/src/base/platform/platform-win32.cc +++ b/deps/v8/src/base/platform/platform-win32.cc @@ -15,9 +15,7 @@ #endif // MINGW_HAS_SECURE_API #endif // __MINGW32__ -#ifdef _MSC_VER #include -#endif #include "src/base/win32-headers.h" @@ -28,16 +26,6 @@ #include "src/base/platform/time.h" #include "src/base/utils/random-number-generator.h" -#ifdef _MSC_VER - -// Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually -// defined in strings.h. -int strncasecmp(const char* s1, const char* s2, int n) { - return _strnicmp(s1, s2, n); -} - -#endif // _MSC_VER - // Extra functions for MinGW. Most of these are the _s functions which are in // the Microsoft Visual Studio C++ CRT. @@ -358,41 +346,26 @@ void Win32Time::SetToCurrentTime() { } +int64_t FileTimeToInt64(FILETIME ft) { + ULARGE_INTEGER result; + result.LowPart = ft.dwLowDateTime; + result.HighPart = ft.dwHighDateTime; + return static_cast(result.QuadPart); +} + + // Return the local timezone offset in milliseconds east of UTC. This // takes into account whether daylight saving is in effect at the time. // Only times in the 32-bit Unix range may be passed to this function. // Also, adding the time-zone offset to the input must not overflow. // The function EquivalentTime() in date.js guarantees this. int64_t Win32Time::LocalOffset(TimezoneCache* cache) { - cache->InitializeIfNeeded(); - - Win32Time rounded_to_second(*this); - rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * - 1000 * kTimeScaler; - // Convert to local time using POSIX localtime function. - // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime() - // very slow. Other browsers use localtime(). - - // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to - // POSIX seconds past 1/1/1970 0:00:00. - double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000; - if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) { - return 0; - } - // Because _USE_32BIT_TIME_T is defined, time_t is a 32-bit int. - time_t posix_time = static_cast(unchecked_posix_time); - - // Convert to local time, as struct with fields for day, hour, year, etc. - tm posix_local_time_struct; - if (localtime_s(&posix_local_time_struct, &posix_time)) return 0; - - if (posix_local_time_struct.tm_isdst > 0) { - return (cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * -kMsPerMinute; - } else if (posix_local_time_struct.tm_isdst == 0) { - return (cache->tzinfo_.Bias + cache->tzinfo_.StandardBias) * -kMsPerMinute; - } else { - return cache->tzinfo_.Bias * -kMsPerMinute; - } + FILETIME local; + SYSTEMTIME system_utc, system_local; + FileTimeToSystemTime(&time_.ft_, &system_utc); + SystemTimeToTzSpecificLocalTime(NULL, &system_utc, &system_local); + SystemTimeToFileTime(&system_local, &local); + return (FileTimeToInt64(local) - FileTimeToInt64(time_.ft_)) / kTimeScaler; } @@ -832,7 +805,7 @@ void OS::Abort() { void OS::DebugBreak() { -#ifdef _MSC_VER +#if V8_CC_MSVC // To avoid Visual Studio runtime support the following code can be used // instead // __asm { int 3 } @@ -1175,11 +1148,7 @@ void OS::SignalCodeMovingGC() { } double OS::nan_value() { -#ifdef _MSC_VER return std::numeric_limits::quiet_NaN(); -#else // _MSC_VER - return NAN; -#endif // _MSC_VER } diff --git a/deps/v8/src/base/platform/platform.h b/deps/v8/src/base/platform/platform.h index 9e20c084c6..0bf102723a 100644 --- a/deps/v8/src/base/platform/platform.h +++ b/deps/v8/src/base/platform/platform.h @@ -21,7 +21,7 @@ #ifndef V8_BASE_PLATFORM_PLATFORM_H_ #define V8_BASE_PLATFORM_PLATFORM_H_ -#include +#include #include #include @@ -29,48 +29,10 @@ #include "src/base/platform/mutex.h" #include "src/base/platform/semaphore.h" -#ifdef __sun -# ifndef signbit -namespace std { -int signbit(double x); -} -# endif -#endif - #if V8_OS_QNX #include "src/base/qnx-math.h" #endif -// Microsoft Visual C++ specific stuff. -#if V8_LIBC_MSVCRT - -#include "src/base/win32-headers.h" -#include "src/base/win32-math.h" - -int strncasecmp(const char* s1, const char* s2, int n); - -// Visual C++ 2013 and higher implement this function. -#if (_MSC_VER < 1800) -inline int lrint(double flt) { - int intgr; -#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87 - __asm { - fld flt - fistp intgr - }; -#else - intgr = static_cast(flt + 0.5); - if ((intgr & 1) != 0 && intgr - flt == 0.5) { - // If the number is halfway between two integers, round to the even one. - intgr--; - } -#endif - return intgr; -} -#endif // _MSC_VER < 1800 - -#endif // V8_LIBC_MSVCRT - namespace v8 { namespace base { @@ -79,7 +41,7 @@ namespace base { #ifndef V8_NO_FAST_TLS -#if defined(_MSC_VER) && (V8_HOST_ARCH_IA32) +#if V8_CC_MSVC && V8_HOST_ARCH_IA32 #define V8_FAST_TLS_SUPPORTED 1 diff --git a/deps/v8/src/base/sys-info.h b/deps/v8/src/base/sys-info.h index d1658fc09d..377deb0716 100644 --- a/deps/v8/src/base/sys-info.h +++ b/deps/v8/src/base/sys-info.h @@ -5,7 +5,7 @@ #ifndef V8_BASE_SYS_INFO_H_ #define V8_BASE_SYS_INFO_H_ -#include "include/v8stdint.h" +#include #include "src/base/compiler-specific.h" namespace v8 { diff --git a/deps/v8/src/base/utils/random-number-generator.cc b/deps/v8/src/base/utils/random-number-generator.cc index a1ec9d7184..29a48ffb05 100644 --- a/deps/v8/src/base/utils/random-number-generator.cc +++ b/deps/v8/src/base/utils/random-number-generator.cc @@ -102,6 +102,13 @@ double RandomNumberGenerator::NextDouble() { } +int64_t RandomNumberGenerator::NextInt64() { + uint64_t lo = bit_cast(Next(32)); + uint64_t hi = bit_cast(Next(32)); + return lo | (hi << 32); +} + + void RandomNumberGenerator::NextBytes(void* buffer, size_t buflen) { for (size_t n = 0; n < buflen; ++n) { static_cast(buffer)[n] = static_cast(Next(8)); diff --git a/deps/v8/src/base/utils/random-number-generator.h b/deps/v8/src/base/utils/random-number-generator.h index 479423d658..d1294f2666 100644 --- a/deps/v8/src/base/utils/random-number-generator.h +++ b/deps/v8/src/base/utils/random-number-generator.h @@ -68,6 +68,13 @@ class RandomNumberGenerator FINAL { // (exclusive), is pseudorandomly generated and returned. double NextDouble() WARN_UNUSED_RESULT; + // Returns the next pseudorandom, uniformly distributed int64 value from this + // random number generator's sequence. The general contract of |NextInt64()| + // is that one 64-bit int value is pseudorandomly generated and returned. + // All 2^64 possible integer values are produced with (approximately) equal + // probability. + int64_t NextInt64() WARN_UNUSED_RESULT; + // Fills the elements of a specified array of bytes with random numbers. void NextBytes(void* buffer, size_t buflen); diff --git a/deps/v8/src/base/win32-math.cc b/deps/v8/src/base/win32-math.cc deleted file mode 100644 index d6fc78bc82..0000000000 --- a/deps/v8/src/base/win32-math.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2011 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Extra POSIX/ANSI routines for Win32 when using Visual Studio C++. Please -// refer to The Open Group Base Specification for specification of the correct -// semantics for these functions. -// (http://www.opengroup.org/onlinepubs/000095399/) -#if defined(_MSC_VER) && (_MSC_VER < 1800) - -#include "src/base/win32-headers.h" -#include // Required for DBL_MAX and on Win32 for finite() -#include // Required for INT_MAX etc. -#include -#include "src/base/win32-math.h" - -#include "src/base/logging.h" - - -namespace std { - -// Test for a NaN (not a number) value - usually defined in math.h -int isnan(double x) { - return _isnan(x); -} - - -// Test for infinity - usually defined in math.h -int isinf(double x) { - return (_fpclass(x) & (_FPCLASS_PINF | _FPCLASS_NINF)) != 0; -} - - -// Test for finite value - usually defined in math.h -int isfinite(double x) { - return _finite(x); -} - - -// Test if x is less than y and both nominal - usually defined in math.h -int isless(double x, double y) { - return isnan(x) || isnan(y) ? 0 : x < y; -} - - -// Test if x is greater than y and both nominal - usually defined in math.h -int isgreater(double x, double y) { - return isnan(x) || isnan(y) ? 0 : x > y; -} - - -// Classify floating point number - usually defined in math.h -int fpclassify(double x) { - // Use the MS-specific _fpclass() for classification. - int flags = _fpclass(x); - - // Determine class. We cannot use a switch statement because - // the _FPCLASS_ constants are defined as flags. - if (flags & (_FPCLASS_PN | _FPCLASS_NN)) return FP_NORMAL; - if (flags & (_FPCLASS_PZ | _FPCLASS_NZ)) return FP_ZERO; - if (flags & (_FPCLASS_PD | _FPCLASS_ND)) return FP_SUBNORMAL; - if (flags & (_FPCLASS_PINF | _FPCLASS_NINF)) return FP_INFINITE; - - // All cases should be covered by the code above. - DCHECK(flags & (_FPCLASS_SNAN | _FPCLASS_QNAN)); - return FP_NAN; -} - - -// Test sign - usually defined in math.h -int signbit(double x) { - // We need to take care of the special case of both positive - // and negative versions of zero. - if (x == 0) - return _fpclass(x) & _FPCLASS_NZ; - else - return x < 0; -} - -} // namespace std - -#endif // _MSC_VER diff --git a/deps/v8/src/base/win32-math.h b/deps/v8/src/base/win32-math.h deleted file mode 100644 index e1c03506b2..0000000000 --- a/deps/v8/src/base/win32-math.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2011 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Extra POSIX/ANSI routines for Win32 when using Visual Studio C++. Please -// refer to The Open Group Base Specification for specification of the correct -// semantics for these functions. -// (http://www.opengroup.org/onlinepubs/000095399/) - -#ifndef V8_BASE_WIN32_MATH_H_ -#define V8_BASE_WIN32_MATH_H_ - -#ifndef _MSC_VER -#error Wrong environment, expected MSVC. -#endif // _MSC_VER - -// MSVC 2013+ provides implementations of all standard math functions. -#if (_MSC_VER < 1800) -enum { - FP_NAN, - FP_INFINITE, - FP_ZERO, - FP_SUBNORMAL, - FP_NORMAL -}; - - -namespace std { - -int isfinite(double x); -int isinf(double x); -int isnan(double x); -int isless(double x, double y); -int isgreater(double x, double y); -int fpclassify(double x); -int signbit(double x); - -} // namespace std - -#endif // _MSC_VER < 1800 - -#endif // V8_BASE_WIN32_MATH_H_ diff --git a/deps/v8/src/basic-block-profiler.cc b/deps/v8/src/basic-block-profiler.cc index ef68ac6228..deb1a532d0 100644 --- a/deps/v8/src/basic-block-profiler.cc +++ b/deps/v8/src/basic-block-profiler.cc @@ -4,37 +4,39 @@ #include "src/basic-block-profiler.h" +#include + namespace v8 { namespace internal { BasicBlockProfiler::Data::Data(size_t n_blocks) - : n_blocks_(n_blocks), block_ids_(n_blocks_, -1), counts_(n_blocks_, 0) {} + : n_blocks_(n_blocks), block_ids_(n_blocks_), counts_(n_blocks_, 0) {} BasicBlockProfiler::Data::~Data() {} -static void InsertIntoString(OStringStream* os, std::string* string) { - string->insert(string->begin(), os->c_str(), &os->c_str()[os->size()]); +static void InsertIntoString(std::ostringstream* os, std::string* string) { + string->insert(0, os->str()); } -void BasicBlockProfiler::Data::SetCode(OStringStream* os) { +void BasicBlockProfiler::Data::SetCode(std::ostringstream* os) { InsertIntoString(os, &code_); } -void BasicBlockProfiler::Data::SetFunctionName(OStringStream* os) { +void BasicBlockProfiler::Data::SetFunctionName(std::ostringstream* os) { InsertIntoString(os, &function_name_); } -void BasicBlockProfiler::Data::SetSchedule(OStringStream* os) { +void BasicBlockProfiler::Data::SetSchedule(std::ostringstream* os) { InsertIntoString(os, &schedule_); } -void BasicBlockProfiler::Data::SetBlockId(size_t offset, int block_id) { +void BasicBlockProfiler::Data::SetBlockId(size_t offset, size_t block_id) { DCHECK(offset < n_blocks_); block_ids_[offset] = block_id; } @@ -77,33 +79,33 @@ void BasicBlockProfiler::ResetCounts() { } -OStream& operator<<(OStream& os, const BasicBlockProfiler& p) { - os << "---- Start Profiling Data ----" << endl; +std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler& p) { + os << "---- Start Profiling Data ----" << std::endl; typedef BasicBlockProfiler::DataList::const_iterator iterator; for (iterator i = p.data_list_.begin(); i != p.data_list_.end(); ++i) { os << **i; } - os << "---- End Profiling Data ----" << endl; + os << "---- End Profiling Data ----" << std::endl; return os; } -OStream& operator<<(OStream& os, const BasicBlockProfiler::Data& d) { +std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& d) { const char* name = "unknown function"; if (!d.function_name_.empty()) { name = d.function_name_.c_str(); } if (!d.schedule_.empty()) { - os << "schedule for " << name << endl; - os << d.schedule_.c_str() << endl; + os << "schedule for " << name << std::endl; + os << d.schedule_.c_str() << std::endl; } - os << "block counts for " << name << ":" << endl; + os << "block counts for " << name << ":" << std::endl; for (size_t i = 0; i < d.n_blocks_; ++i) { - os << "block " << d.block_ids_[i] << " : " << d.counts_[i] << endl; + os << "block " << d.block_ids_[i] << " : " << d.counts_[i] << std::endl; } - os << endl; + os << std::endl; if (!d.code_.empty()) { - os << d.code_.c_str() << endl; + os << d.code_.c_str() << std::endl; } return os; } diff --git a/deps/v8/src/basic-block-profiler.h b/deps/v8/src/basic-block-profiler.h index e625cd23b5..99fa3b172d 100644 --- a/deps/v8/src/basic-block-profiler.h +++ b/deps/v8/src/basic-block-profiler.h @@ -5,7 +5,9 @@ #ifndef V8_BASIC_BLOCK_PROFILER_H_ #define V8_BASIC_BLOCK_PROFILER_H_ +#include #include +#include #include "src/v8.h" @@ -22,15 +24,16 @@ class BasicBlockProfiler { size_t n_blocks() const { return n_blocks_; } const uint32_t* counts() const { return &counts_[0]; } - void SetCode(OStringStream* os); - void SetFunctionName(OStringStream* os); - void SetSchedule(OStringStream* os); - void SetBlockId(size_t offset, int block_id); + void SetCode(std::ostringstream* os); + void SetFunctionName(std::ostringstream* os); + void SetSchedule(std::ostringstream* os); + void SetBlockId(size_t offset, size_t block_id); uint32_t* GetCounterAddress(size_t offset); private: friend class BasicBlockProfiler; - friend OStream& operator<<(OStream& os, const BasicBlockProfiler::Data& s); + friend std::ostream& operator<<(std::ostream& os, + const BasicBlockProfiler::Data& s); explicit Data(size_t n_blocks); ~Data(); @@ -38,7 +41,7 @@ class BasicBlockProfiler { void ResetCounts(); const size_t n_blocks_; - std::vector block_ids_; + std::vector block_ids_; std::vector counts_; std::string function_name_; std::string schedule_; @@ -57,15 +60,16 @@ class BasicBlockProfiler { const DataList* data_list() { return &data_list_; } private: - friend OStream& operator<<(OStream& os, const BasicBlockProfiler& s); + friend std::ostream& operator<<(std::ostream& os, + const BasicBlockProfiler& s); DataList data_list_; DISALLOW_COPY_AND_ASSIGN(BasicBlockProfiler); }; -OStream& operator<<(OStream& os, const BasicBlockProfiler& s); -OStream& operator<<(OStream& os, const BasicBlockProfiler::Data& s); +std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler& s); +std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& s); } // namespace internal } // namespace v8 diff --git a/deps/v8/src/bignum-dtoa.cc b/deps/v8/src/bignum-dtoa.cc index 53bf418f93..f9a0c95ef5 100644 --- a/deps/v8/src/bignum-dtoa.cc +++ b/deps/v8/src/bignum-dtoa.cc @@ -4,7 +4,6 @@ #include -#include "include/v8stdint.h" #include "src/base/logging.h" #include "src/utils.h" diff --git a/deps/v8/src/data-flow.cc b/deps/v8/src/bit-vector.cc similarity index 74% rename from deps/v8/src/data-flow.cc rename to deps/v8/src/bit-vector.cc index bd92ea0531..198b24273c 100644 --- a/deps/v8/src/data-flow.cc +++ b/deps/v8/src/bit-vector.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/data-flow.h" +#include "src/bit-vector.h" #include "src/base/bits.h" #include "src/scopes.h" @@ -28,12 +28,12 @@ void BitVector::Print() { void BitVector::Iterator::Advance() { current_++; - uint32_t val = current_value_; + uintptr_t val = current_value_; while (val == 0) { current_index_++; if (Done()) return; val = target_->data_[current_index_]; - current_ = current_index_ << 5; + current_ = current_index_ << kDataBitShift; } val = SkipZeroBytes(val); val = SkipZeroBits(val); @@ -44,8 +44,12 @@ void BitVector::Iterator::Advance() { int BitVector::Count() const { int count = 0; for (int i = 0; i < data_length_; i++) { - int data = data_[i]; - if (data != 0) count += base::bits::CountPopulation32(data); + uintptr_t data = data_[i]; + if (sizeof(data) == 8) { + count += base::bits::CountPopulation64(data); + } else { + count += base::bits::CountPopulation32(static_cast(data)); + } } return count; } diff --git a/deps/v8/src/data-flow.h b/deps/v8/src/bit-vector.h similarity index 79% rename from deps/v8/src/data-flow.h rename to deps/v8/src/bit-vector.h index bfd238d24e..9fc747d06f 100644 --- a/deps/v8/src/data-flow.h +++ b/deps/v8/src/bit-vector.h @@ -15,7 +15,7 @@ namespace v8 { namespace internal { -class BitVector: public ZoneObject { +class BitVector : public ZoneObject { public: // Iterator for the elements of this BitVector. class Iterator BASE_EMBEDDED { @@ -28,7 +28,7 @@ class BitVector: public ZoneObject { DCHECK(target->data_length_ > 0); Advance(); } - ~Iterator() { } + ~Iterator() {} bool Done() const { return current_index_ >= target_->data_length_; } void Advance(); @@ -39,14 +39,14 @@ class BitVector: public ZoneObject { } private: - uint32_t SkipZeroBytes(uint32_t val) { + uintptr_t SkipZeroBytes(uintptr_t val) { while ((val & 0xFF) == 0) { val >>= 8; current_ += 8; } return val; } - uint32_t SkipZeroBits(uint32_t val) { + uintptr_t SkipZeroBits(uintptr_t val) { while ((val & 0x1) == 0) { val >>= 1; current_++; @@ -56,16 +56,20 @@ class BitVector: public ZoneObject { BitVector* target_; int current_index_; - uint32_t current_value_; + uintptr_t current_value_; int current_; friend class BitVector; }; + static const int kDataBits = kPointerSize * 8; + static const int kDataBitShift = kPointerSize == 8 ? 6 : 5; + static const uintptr_t kOne = 1; // This saves some static_casts. + BitVector(int length, Zone* zone) : length_(length), data_length_(SizeFor(length)), - data_(zone->NewArray(data_length_)) { + data_(zone->NewArray(data_length_)) { DCHECK(length > 0); Clear(); } @@ -73,18 +77,11 @@ class BitVector: public ZoneObject { BitVector(const BitVector& other, Zone* zone) : length_(other.length()), data_length_(SizeFor(length_)), - data_(zone->NewArray(data_length_)) { + data_(zone->NewArray(data_length_)) { CopyFrom(other); } - static int SizeFor(int length) { - return 1 + ((length - 1) / 32); - } - - BitVector& operator=(const BitVector& rhs) { - if (this != &rhs) CopyFrom(rhs); - return *this; - } + static int SizeFor(int length) { return 1 + ((length - 1) / kDataBits); } void CopyFrom(const BitVector& other) { DCHECK(other.length() <= length()); @@ -98,18 +95,18 @@ class BitVector: public ZoneObject { bool Contains(int i) const { DCHECK(i >= 0 && i < length()); - uint32_t block = data_[i / 32]; - return (block & (1U << (i % 32))) != 0; + uintptr_t block = data_[i / kDataBits]; + return (block & (kOne << (i % kDataBits))) != 0; } void Add(int i) { DCHECK(i >= 0 && i < length()); - data_[i / 32] |= (1U << (i % 32)); + data_[i / kDataBits] |= (kOne << (i % kDataBits)); } void Remove(int i) { DCHECK(i >= 0 && i < length()); - data_[i / 32] &= ~(1U << (i % 32)); + data_[i / kDataBits] &= ~(kOne << (i % kDataBits)); } void Union(const BitVector& other) { @@ -123,7 +120,7 @@ class BitVector: public ZoneObject { DCHECK(other.length() == length()); bool changed = false; for (int i = 0; i < data_length_; i++) { - uint32_t old_data = data_[i]; + uintptr_t old_data = data_[i]; data_[i] |= other.data_[i]; if (data_[i] != old_data) changed = true; } @@ -141,7 +138,7 @@ class BitVector: public ZoneObject { DCHECK(other.length() == length()); bool changed = false; for (int i = 0; i < data_length_; i++) { - uint32_t old_data = data_[i]; + uintptr_t old_data = data_[i]; data_[i] &= other.data_[i]; if (data_[i] != old_data) changed = true; } @@ -184,9 +181,11 @@ class BitVector: public ZoneObject { #endif private: - int length_; - int data_length_; - uint32_t* data_; + const int length_; + const int data_length_; + uintptr_t* const data_; + + DISALLOW_COPY_AND_ASSIGN(BitVector); }; @@ -195,19 +194,19 @@ class GrowableBitVector BASE_EMBEDDED { class Iterator BASE_EMBEDDED { public: Iterator(const GrowableBitVector* target, Zone* zone) - : it_(target->bits_ == NULL - ? new(zone) BitVector(1, zone) - : target->bits_) { } + : it_(target->bits_ == NULL ? new (zone) BitVector(1, zone) + : target->bits_) {} bool Done() const { return it_.Done(); } void Advance() { it_.Advance(); } int Current() const { return it_.Current(); } + private: BitVector::Iterator it_; }; - GrowableBitVector() : bits_(NULL) { } + GrowableBitVector() : bits_(NULL) {} GrowableBitVector(int length, Zone* zone) - : bits_(new(zone) BitVector(length, zone)) { } + : bits_(new (zone) BitVector(length, zone)) {} bool Contains(int value) const { if (!InBitsRange(value)) return false; @@ -225,7 +224,9 @@ class GrowableBitVector BASE_EMBEDDED { } } - void Clear() { if (bits_ != NULL) bits_->Clear(); } + void Clear() { + if (bits_ != NULL) bits_->Clear(); + } private: static const int kInitialLength = 1024; @@ -238,7 +239,7 @@ class GrowableBitVector BASE_EMBEDDED { if (InBitsRange(value)) return; int new_length = bits_ == NULL ? kInitialLength : bits_->length(); while (new_length <= value) new_length *= 2; - BitVector* new_bits = new(zone) BitVector(new_length, zone); + BitVector* new_bits = new (zone) BitVector(new_length, zone); if (bits_ != NULL) new_bits->CopyFrom(*bits_); bits_ = new_bits; } diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 250562a2aa..264d1c6faf 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -57,6 +57,8 @@ Handle Bootstrapper::NativesSourceLookup(int index) { Handle source_code = isolate_->factory() ->NewExternalStringFromOneByte(resource) .ToHandleChecked(); + // Mark this external string with a special map. + source_code->set_map(isolate_->heap()->native_source_string_map()); heap->natives_source_cache()->set(index, *source_code); } Handle cached_source(heap->natives_source_cache()->get(index), @@ -126,7 +128,7 @@ char* Bootstrapper::AllocateAutoDeletedArray(int bytes) { void Bootstrapper::TearDown() { if (delete_these_non_arrays_on_tear_down_ != NULL) { int len = delete_these_non_arrays_on_tear_down_->length(); - DCHECK(len < 28); // Don't use this mechanism for unbounded allocations. + DCHECK(len < 1000); // Don't use this mechanism for unbounded allocations. for (int i = 0; i < len; i++) { delete delete_these_non_arrays_on_tear_down_->at(i); delete_these_non_arrays_on_tear_down_->at(i) = NULL; @@ -208,6 +210,16 @@ class Genesis BASE_EMBEDDED { // Used for creating a context from scratch. void InstallNativeFunctions(); void InstallExperimentalNativeFunctions(); + +#define DECLARE_FEATURE_INITIALIZATION(id, descr) \ + void InstallNativeFunctions_##id(); \ + void InitializeGlobal_##id(); + + HARMONY_INPROGRESS(DECLARE_FEATURE_INITIALIZATION) + HARMONY_STAGED(DECLARE_FEATURE_INITIALIZATION) + HARMONY_SHIPPING(DECLARE_FEATURE_INITIALIZATION) +#undef DECLARE_FEATURE_INITIALIZATION + Handle InstallInternalArray(Handle builtins, const char* name, ElementsKind elements_kind); @@ -507,7 +519,7 @@ Handle Genesis::CreateEmptyFunction(Isolate* isolate) { // prototype, otherwise the missing initial_array_prototype will cause // assertions during startup. native_context()->set_initial_array_prototype(*prototype); - Accessors::FunctionSetPrototype(object_fun, prototype); + Accessors::FunctionSetPrototype(object_fun, prototype).Assert(); } // Allocate the empty function as the prototype for function ECMAScript @@ -1328,6 +1340,11 @@ void Genesis::InitializeGlobal(Handle global_object, delegate->shared()->DontAdaptArguments(); } +#define FEATURE_INITIALIZE_GLOBAL(id, descr) InitializeGlobal_##id(); + + HARMONY_SHIPPING(FEATURE_INITIALIZE_GLOBAL) +#undef FEATURE_INITIALIZE_GLOBAL + // Initialize the embedder data slot. Handle embedder_data = factory->NewFixedArray(3); native_context()->set_embedder_data(*embedder_data); @@ -1358,16 +1375,11 @@ void Genesis::InstallTypedArray( void Genesis::InitializeExperimentalGlobal() { - // TODO(erikcorry): Move this into Genesis::InitializeGlobal once we no - // longer need to live behind a flag. - Handle builtins(native_context()->builtins()); +#define FEATURE_INITIALIZE_GLOBAL(id, descr) InitializeGlobal_##id(); - Handle flag( - FLAG_harmony_regexps ? heap()->true_value() : heap()->false_value()); - PropertyAttributes attributes = - static_cast(DONT_DELETE | READ_ONLY); - Runtime::DefineObjectProperty(builtins, factory()->harmony_regexps_string(), - flag, attributes).Assert(); + HARMONY_INPROGRESS(FEATURE_INITIALIZE_GLOBAL) + HARMONY_STAGED(FEATURE_INITIALIZE_GLOBAL) +#undef FEATURE_INITIALIZE_GLOBAL } @@ -1503,12 +1515,6 @@ static Handle ResolveBuiltinIdHolder(Handle native_context, .ToHandleChecked(); \ native_context()->set_##var(Type::cast(*var##_native)); -#define INSTALL_NATIVE_MATH(name) \ - { \ - Handle fun = \ - ResolveBuiltinIdHolder(native_context(), "Math." #name); \ - native_context()->set_math_##name##_fun(JSFunction::cast(*fun)); \ - } void Genesis::InstallNativeFunctions() { HandleScope scope(isolate()); @@ -1556,25 +1562,9 @@ void Genesis::InstallNativeFunctions() { INSTALL_NATIVE(Symbol, "symbolUnscopables", unscopables_symbol); INSTALL_NATIVE(JSFunction, "ArrayValues", array_values_iterator); - INSTALL_NATIVE_MATH(abs) - INSTALL_NATIVE_MATH(acos) - INSTALL_NATIVE_MATH(asin) - INSTALL_NATIVE_MATH(atan) - INSTALL_NATIVE_MATH(atan2) - INSTALL_NATIVE_MATH(ceil) - INSTALL_NATIVE_MATH(cos) - INSTALL_NATIVE_MATH(exp) - INSTALL_NATIVE_MATH(floor) - INSTALL_NATIVE_MATH(imul) - INSTALL_NATIVE_MATH(log) - INSTALL_NATIVE_MATH(max) - INSTALL_NATIVE_MATH(min) - INSTALL_NATIVE_MATH(pow) - INSTALL_NATIVE_MATH(random) - INSTALL_NATIVE_MATH(round) - INSTALL_NATIVE_MATH(sin) - INSTALL_NATIVE_MATH(sqrt) - INSTALL_NATIVE_MATH(tan) +#define INSTALL_NATIVE_FUNCTIONS_FOR(id, descr) InstallNativeFunctions_##id(); + HARMONY_SHIPPING(INSTALL_NATIVE_FUNCTIONS_FOR) +#undef INSTALL_NATIVE_FUNCTIONS_FOR } @@ -1585,10 +1575,65 @@ void Genesis::InstallExperimentalNativeFunctions() { INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap); INSTALL_NATIVE(JSFunction, "ProxyEnumerate", proxy_enumerate); } + +#define INSTALL_NATIVE_FUNCTIONS_FOR(id, descr) InstallNativeFunctions_##id(); + HARMONY_INPROGRESS(INSTALL_NATIVE_FUNCTIONS_FOR) + HARMONY_STAGED(INSTALL_NATIVE_FUNCTIONS_FOR) +#undef INSTALL_NATIVE_FUNCTIONS_FOR +} + + +#define EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(id) \ + void Genesis::InstallNativeFunctions_##id() {} + +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_scoping) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_modules) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_strings) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_arrays) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_classes) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_object_literals) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_regexps) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_arrow_functions) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_numeric_literals) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_tostring) + + +void Genesis::InstallNativeFunctions_harmony_proxies() { + if (FLAG_harmony_proxies) { + INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap); + INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap); + INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap); + INSTALL_NATIVE(JSFunction, "ProxyEnumerate", proxy_enumerate); + } } #undef INSTALL_NATIVE +#define EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(id) \ + void Genesis::InitializeGlobal_##id() {} + +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_scoping) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_modules) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_strings) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_arrays) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_classes) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object_literals) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_arrow_functions) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_numeric_literals) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_tostring) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_proxies) + +void Genesis::InitializeGlobal_harmony_regexps() { + Handle builtins(native_context()->builtins()); + + Handle flag(FLAG_harmony_regexps ? heap()->true_value() + : heap()->false_value()); + PropertyAttributes attributes = + static_cast(DONT_DELETE | READ_ONLY); + Runtime::DefineObjectProperty(builtins, factory()->harmony_regexps_string(), + flag, attributes).Assert(); +} + Handle Genesis::InstallInternalArray( Handle builtins, @@ -1697,7 +1742,7 @@ bool Genesis::InstallNatives() { isolate()->initial_object_prototype(), Builtins::kIllegal); Handle prototype = factory()->NewJSObject(isolate()->object_function(), TENURED); - Accessors::FunctionSetPrototype(script_fun, prototype); + Accessors::FunctionSetPrototype(script_fun, prototype).Assert(); native_context()->set_script_function(*script_fun); Handle script_map = Handle(script_fun->initial_map()); @@ -1839,7 +1884,7 @@ bool Genesis::InstallNatives() { isolate()->initial_object_prototype(), Builtins::kIllegal); Handle prototype = factory()->NewJSObject(isolate()->object_function(), TENURED); - Accessors::FunctionSetPrototype(opaque_reference_fun, prototype); + Accessors::FunctionSetPrototype(opaque_reference_fun, prototype).Assert(); native_context()->set_opaque_reference_function(*opaque_reference_fun); } @@ -1980,7 +2025,7 @@ bool Genesis::InstallNatives() { // Apply embeds an IC, so we need a type vector of size 1 in the shared // function info. Handle feedback_vector = - factory()->NewTypeFeedbackVector(1); + factory()->NewTypeFeedbackVector(0, 1); apply->shared()->set_feedback_vector(*feedback_vector); } @@ -2095,23 +2140,51 @@ bool Genesis::InstallNatives() { } -#define INSTALL_EXPERIMENTAL_NATIVE(i, flag, file) \ - if (FLAG_harmony_##flag && \ - strcmp(ExperimentalNatives::GetScriptName(i).start(), \ - "native " file) == 0) { \ - if (!CompileExperimentalBuiltin(isolate(), i)) return false; \ +#define INSTALL_EXPERIMENTAL_NATIVE(i, flag, file) \ + if (FLAG_##flag && \ + strcmp(ExperimentalNatives::GetScriptName(i).start(), "native " file) == \ + 0) { \ + if (!CompileExperimentalBuiltin(isolate(), i)) return false; \ } bool Genesis::InstallExperimentalNatives() { + static const char* harmony_arrays_natives[] = { + "native harmony-array.js", "native harmony-typedarray.js", NULL}; + static const char* harmony_proxies_natives[] = {"native proxy.js", NULL}; + static const char* harmony_strings_natives[] = {"native harmony-string.js", + NULL}; + static const char* harmony_classes_natives[] = {"native harmony-classes.js", + NULL}; + static const char* harmony_modules_natives[] = {NULL}; + static const char* harmony_scoping_natives[] = {NULL}; + static const char* harmony_object_literals_natives[] = {NULL}; + static const char* harmony_regexps_natives[] = {NULL}; + static const char* harmony_arrow_functions_natives[] = {NULL}; + static const char* harmony_numeric_literals_natives[] = {NULL}; + static const char* harmony_tostring_natives[] = {"native harmony-tostring.js", + NULL}; + for (int i = ExperimentalNatives::GetDebuggerCount(); - i < ExperimentalNatives::GetBuiltinsCount(); - i++) { - INSTALL_EXPERIMENTAL_NATIVE(i, proxies, "proxy.js") - INSTALL_EXPERIMENTAL_NATIVE(i, strings, "harmony-string.js") - INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-array.js") - INSTALL_EXPERIMENTAL_NATIVE(i, classes, "harmony-classes.js") + i < ExperimentalNatives::GetBuiltinsCount(); i++) { +#define INSTALL_EXPERIMENTAL_NATIVES(id, desc) \ + if (FLAG_##id) { \ + for (size_t j = 0; id##_natives[j] != NULL; j++) { \ + if (strcmp(ExperimentalNatives::GetScriptName(i).start(), \ + id##_natives[j]) == 0) { \ + if (!CompileExperimentalBuiltin(isolate(), i)) return false; \ + } \ + } \ } + // Iterate over flags that are not enabled by default. + HARMONY_INPROGRESS(INSTALL_EXPERIMENTAL_NATIVES); + HARMONY_STAGED(INSTALL_EXPERIMENTAL_NATIVES); +#undef INSTALL_EXPERIMENTAL_NATIVES + } + +#define USE_NATIVES_FOR_FEATURE(id, descr) USE(id##_natives); + HARMONY_SHIPPING(USE_NATIVES_FOR_FEATURE) +#undef USE_NATIVES_FOR_FEATURE InstallExperimentalNativeFunctions(); return true; @@ -2588,20 +2661,24 @@ void Genesis::MakeFunctionInstancePrototypeWritable() { class NoTrackDoubleFieldsForSerializerScope { public: explicit NoTrackDoubleFieldsForSerializerScope(Isolate* isolate) - : flag_(FLAG_track_double_fields) { + : flag_(FLAG_track_double_fields), enabled_(false) { if (isolate->serializer_enabled()) { // Disable tracking double fields because heap numbers treated as // immutable by the serializer. FLAG_track_double_fields = false; + enabled_ = true; } } ~NoTrackDoubleFieldsForSerializerScope() { - FLAG_track_double_fields = flag_; + if (enabled_) { + FLAG_track_double_fields = flag_; + } } private: bool flag_; + bool enabled_; }; diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc index c52d22852d..5eefd27fbb 100644 --- a/deps/v8/src/builtins.cc +++ b/deps/v8/src/builtins.cc @@ -182,23 +182,25 @@ static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index, } -static bool ArrayPrototypeHasNoElements(Heap* heap, - Context* native_context, - JSObject* array_proto) { +static bool ArrayPrototypeHasNoElements(Heap* heap, PrototypeIterator* iter) { DisallowHeapAllocation no_gc; - // This method depends on non writability of Object and Array prototype - // fields. - if (array_proto->elements() != heap->empty_fixed_array()) return false; - // Object.prototype - PrototypeIterator iter(heap->isolate(), array_proto); - if (iter.IsAtEnd()) { - return false; + for (; !iter->IsAtEnd(); iter->Advance()) { + if (iter->GetCurrent()->IsJSProxy()) return false; + if (JSObject::cast(iter->GetCurrent())->elements() != + heap->empty_fixed_array()) { + return false; + } } - array_proto = JSObject::cast(iter.GetCurrent()); - if (array_proto != native_context->initial_object_prototype()) return false; - if (array_proto->elements() != heap->empty_fixed_array()) return false; - iter.Advance(); - return iter.IsAtEnd(); + return true; +} + + +static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, + JSArray* receiver) { + if (!FLAG_clever_optimizations) return false; + DisallowHeapAllocation no_gc; + PrototypeIterator iter(heap->isolate(), receiver); + return ArrayPrototypeHasNoElements(heap, &iter); } @@ -213,13 +215,13 @@ static inline MaybeHandle EnsureJSArrayWithWritableFastElements( Handle array = Handle::cast(receiver); // If there may be elements accessors in the prototype chain, the fast path // cannot be used if there arguments to add to the array. - if (args != NULL && array->map()->DictionaryElementsInPrototypeChainOnly()) { + Heap* heap = isolate->heap(); + if (args != NULL && !IsJSArrayFastElementMovingAllowed(heap, *array)) { return MaybeHandle(); } if (array->map()->is_observed()) return MaybeHandle(); if (!array->map()->is_extensible()) return MaybeHandle(); Handle elms(array->elements(), isolate); - Heap* heap = isolate->heap(); Map* map = elms->map(); if (map == heap->fixed_array_map()) { if (args == NULL || array->HasFastObjectElements()) return elms; @@ -264,19 +266,6 @@ static inline MaybeHandle EnsureJSArrayWithWritableFastElements( } -static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, - JSArray* receiver) { - if (!FLAG_clever_optimizations) return false; - DisallowHeapAllocation no_gc; - Context* native_context = heap->isolate()->context()->native_context(); - JSObject* array_proto = - JSObject::cast(native_context->array_function()->prototype()); - PrototypeIterator iter(heap->isolate(), receiver); - return iter.GetCurrent() == array_proto && - ArrayPrototypeHasNoElements(heap, native_context, array_proto); -} - - MUST_USE_RESULT static Object* CallJsBuiltin( Isolate* isolate, const char* name, @@ -453,8 +442,7 @@ BUILTIN(ArrayShift) { EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); Handle elms_obj; if (!maybe_elms_obj.ToHandle(&elms_obj) || - !IsJSArrayFastElementMovingAllowed(heap, - *Handle::cast(receiver))) { + !IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(*receiver))) { return CallJsBuiltin(isolate, "ArrayShift", args); } Handle array = Handle::cast(receiver); @@ -499,11 +487,9 @@ BUILTIN(ArrayUnshift) { Heap* heap = isolate->heap(); Handle receiver = args.receiver(); MaybeHandle maybe_elms_obj = - EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); + EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); Handle elms_obj; - if (!maybe_elms_obj.ToHandle(&elms_obj) || - !IsJSArrayFastElementMovingAllowed(heap, - *Handle::cast(receiver))) { + if (!maybe_elms_obj.ToHandle(&elms_obj)) { return CallJsBuiltin(isolate, "ArrayUnshift", args); } Handle array = Handle::cast(receiver); @@ -524,9 +510,6 @@ BUILTIN(ArrayUnshift) { Handle elms = Handle::cast(elms_obj); - JSObject::EnsureCanContainElements(array, &args, 1, to_add, - DONT_ALLOW_DOUBLE_ELEMENTS); - if (new_length > elms->length()) { // New backing storage is needed. int capacity = new_length + (new_length >> 1) + 16; @@ -708,9 +691,7 @@ BUILTIN(ArraySplice) { MaybeHandle maybe_elms_obj = EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); Handle elms_obj; - if (!maybe_elms_obj.ToHandle(&elms_obj) || - !IsJSArrayFastElementMovingAllowed(heap, - *Handle::cast(receiver))) { + if (!maybe_elms_obj.ToHandle(&elms_obj)) { return CallJsBuiltin(isolate, "ArraySplice", args); } Handle array = Handle::cast(receiver); @@ -928,9 +909,10 @@ BUILTIN(ArrayConcat) { DisallowHeapAllocation no_gc; Heap* heap = isolate->heap(); Context* native_context = isolate->context()->native_context(); - JSObject* array_proto = - JSObject::cast(native_context->array_function()->prototype()); - if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) { + Object* array_proto = native_context->array_function()->prototype(); + PrototypeIterator iter(isolate, array_proto, + PrototypeIterator::START_AT_RECEIVER); + if (!ArrayPrototypeHasNoElements(heap, &iter)) { AllowHeapAllocation allow_allocation; return CallJsBuiltin(isolate, "ArrayConcatJS", args); } @@ -1279,11 +1261,6 @@ static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) { } -static void Generate_KeyedLoadIC_String(MacroAssembler* masm) { - KeyedLoadIC::GenerateString(masm); -} - - static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) { KeyedLoadIC::GeneratePreMonomorphic(masm); } @@ -1314,6 +1291,16 @@ static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) { } +static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) { + KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY); +} + + +static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) { + KeyedStoreIC::GenerateMegamorphic(masm, STRICT); +} + + static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) { KeyedStoreIC::GenerateGeneric(masm, SLOPPY); } @@ -1569,7 +1556,7 @@ void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) { PROFILE(isolate, CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name)); builtins_[i] = *code; - if (code->kind() == Code::BUILTIN) code->set_builtin_index(i); + code->set_builtin_index(i); #ifdef ENABLE_DISASSEMBLER if (FLAG_print_builtin_code) { CodeTracer::Scope trace_scope(isolate->GetCodeTracer()); diff --git a/deps/v8/src/builtins.h b/deps/v8/src/builtins.h index c1ed91df4e..13a4b8027f 100644 --- a/deps/v8/src/builtins.h +++ b/deps/v8/src/builtins.h @@ -88,19 +88,21 @@ enum BuiltinExtraArguments { V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC, \ kNoExtraICState) \ V(KeyedLoadIC_Generic, KEYED_LOAD_IC, GENERIC, kNoExtraICState) \ - V(KeyedLoadIC_String, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState) \ \ V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, StoreIC::kStrictModeState) \ \ V(KeyedStoreIC_Initialize, KEYED_STORE_IC, UNINITIALIZED, kNoExtraICState) \ V(KeyedStoreIC_PreMonomorphic, KEYED_STORE_IC, PREMONOMORPHIC, \ kNoExtraICState) \ + V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, MEGAMORPHIC, kNoExtraICState) \ V(KeyedStoreIC_Generic, KEYED_STORE_IC, GENERIC, kNoExtraICState) \ \ V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED, \ StoreIC::kStrictModeState) \ V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC, PREMONOMORPHIC, \ StoreIC::kStrictModeState) \ + V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, MEGAMORPHIC, \ + StoreIC::kStrictModeState) \ V(KeyedStoreIC_Generic_Strict, KEYED_STORE_IC, GENERIC, \ StoreIC::kStrictModeState) \ V(KeyedStoreIC_SloppyArguments, KEYED_STORE_IC, MONOMORPHIC, \ diff --git a/deps/v8/src/cached-powers.cc b/deps/v8/src/cached-powers.cc index dd9e3b4d3f..ccf8882e76 100644 --- a/deps/v8/src/cached-powers.cc +++ b/deps/v8/src/cached-powers.cc @@ -4,9 +4,9 @@ #include #include +#include #include -#include "include/v8stdint.h" #include "src/base/logging.h" #include "src/cached-powers.h" #include "src/globals.h" diff --git a/deps/v8/src/char-predicates.cc b/deps/v8/src/char-predicates.cc new file mode 100644 index 0000000000..ab551d808e --- /dev/null +++ b/deps/v8/src/char-predicates.cc @@ -0,0 +1,42 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/char-predicates.h" + +#ifdef V8_I18N_SUPPORT +#include "unicode/uchar.h" +#include "unicode/urename.h" +#endif // V8_I18N_SUPPORT + +namespace v8 { +namespace internal { + +bool SupplementaryPlanes::IsIDStart(uc32 c) { + DCHECK(c > 0xFFFF); +#ifdef V8_I18N_SUPPORT + // This only works for code points in the SMPs, since ICU does not exclude + // code points with properties 'Pattern_Syntax' or 'Pattern_White_Space'. + // Code points in the SMP do not have those properties. + return u_isIDStart(c); +#else + // This is incorrect, but if we don't have ICU, use this as fallback. + return false; +#endif // V8_I18N_SUPPORT +} + + +bool SupplementaryPlanes::IsIDPart(uc32 c) { + DCHECK(c > 0xFFFF); +#ifdef V8_I18N_SUPPORT + // This only works for code points in the SMPs, since ICU does not exclude + // code points with properties 'Pattern_Syntax' or 'Pattern_White_Space'. + // Code points in the SMP do not have those properties. + return u_isIDPart(c); +#else + // This is incorrect, but if we don't have ICU, use this as fallback. + return false; +#endif // V8_I18N_SUPPORT +} +} +} // namespace v8::internal diff --git a/deps/v8/src/char-predicates.h b/deps/v8/src/char-predicates.h index b7c5d42320..5ecb07de99 100644 --- a/deps/v8/src/char-predicates.h +++ b/deps/v8/src/char-predicates.h @@ -22,42 +22,54 @@ inline bool IsBinaryDigit(uc32 c); inline bool IsRegExpWord(uc32 c); inline bool IsRegExpNewline(uc32 c); + +struct SupplementaryPlanes { + static bool IsIDStart(uc32 c); + static bool IsIDPart(uc32 c); +}; + + +// ES6 draft section 11.6 +// This includes '_', '$' and '\', and ID_Start according to +// http://www.unicode.org/reports/tr31/, which consists of categories +// 'Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl', but excluding properties +// 'Pattern_Syntax' or 'Pattern_White_Space'. +// For code points in the SMPs, we can resort to ICU (if available). struct IdentifierStart { static inline bool Is(uc32 c) { - switch (c) { - case '$': case '_': case '\\': return true; - default: return unibrow::Letter::Is(c); - } + if (c > 0xFFFF) return SupplementaryPlanes::IsIDStart(c); + return unibrow::ID_Start::Is(c); } }; +// ES6 draft section 11.6 +// This includes \u200c and \u200d, and ID_Continue according to +// http://www.unicode.org/reports/tr31/, which consists of ID_Start, +// the categories 'Mn', 'Mc', 'Nd', 'Pc', but excluding properties +// 'Pattern_Syntax' or 'Pattern_White_Space'. +// For code points in the SMPs, we can resort to ICU (if available). struct IdentifierPart { static inline bool Is(uc32 c) { - return IdentifierStart::Is(c) - || unibrow::Number::Is(c) - || c == 0x200C // U+200C is Zero-Width Non-Joiner. - || c == 0x200D // U+200D is Zero-Width Joiner. - || unibrow::CombiningMark::Is(c) - || unibrow::ConnectorPunctuation::Is(c); + if (c > 0xFFFF) return SupplementaryPlanes::IsIDPart(c); + return unibrow::ID_Start::Is(c) || unibrow::ID_Continue::Is(c); } }; -// WhiteSpace according to ECMA-262 5.1, 7.2. +// ES6 draft section 11.2 +// This includes all code points of Unicode category 'Zs'. +// \u180e stops being one as of Unicode 6.3.0, but ES6 adheres to Unicode 5.1, +// so it is also included. +// Further included are \u0009, \u000b, \u0020, \u00a0, \u000c, and \ufeff. +// There are no category 'Zs' code points in the SMPs. struct WhiteSpace { - static inline bool Is(uc32 c) { - return c == 0x0009 || // - c == 0x000B || // - c == 0x000C || // - c == 0xFEFF || // - // \u0020 and \u00A0 are included in unibrow::WhiteSpace. - unibrow::WhiteSpace::Is(c); - } + static inline bool Is(uc32 c) { return unibrow::WhiteSpace::Is(c); } }; -// WhiteSpace and LineTerminator according to ECMA-262 5.1, 7.2 and 7.3. +// WhiteSpace and LineTerminator according to ES6 draft section 11.2 and 11.3 +// This consists of \000a, \000d, \u2028, and \u2029. struct WhiteSpaceOrLineTerminator { static inline bool Is(uc32 c) { return WhiteSpace::Is(c) || unibrow::LineTerminator::Is(c); diff --git a/deps/v8/src/code-factory.cc b/deps/v8/src/code-factory.cc index c969c8f1c1..e68d539207 100644 --- a/deps/v8/src/code-factory.cc +++ b/deps/v8/src/code-factory.cc @@ -19,13 +19,35 @@ Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode) { } +// static +Callable CodeFactory::LoadICInOptimizedCode(Isolate* isolate, + ContextualMode mode) { + if (FLAG_vector_ics) { + return Callable(LoadIC::initialize_stub_in_optimized_code( + isolate, LoadICState(mode).GetExtraICState()), + VectorLoadICDescriptor(isolate)); + } + return CodeFactory::LoadIC(isolate, mode); +} + + // static Callable CodeFactory::KeyedLoadIC(Isolate* isolate) { - return Callable(isolate->builtins()->KeyedLoadIC_Initialize(), + return Callable(KeyedLoadIC::initialize_stub(isolate), LoadDescriptor(isolate)); } +// static +Callable CodeFactory::KeyedLoadICInOptimizedCode(Isolate* isolate) { + if (FLAG_vector_ics) { + return Callable(KeyedLoadIC::initialize_stub_in_optimized_code(isolate), + VectorLoadICDescriptor(isolate)); + } + return CodeFactory::KeyedLoadIC(isolate); +} + + // static Callable CodeFactory::StoreIC(Isolate* isolate, StrictMode mode) { return Callable(StoreIC::initialize_stub(isolate, mode), @@ -81,6 +103,13 @@ Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags, } +// static +Callable CodeFactory::AllocateHeapNumber(Isolate* isolate) { + AllocateHeapNumberStub stub(isolate); + return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor()); +} + + // static Callable CodeFactory::CallFunction(Isolate* isolate, int argc, CallFunctionFlags flags) { diff --git a/deps/v8/src/code-factory.h b/deps/v8/src/code-factory.h index 3add38486f..f26bf2a28e 100644 --- a/deps/v8/src/code-factory.h +++ b/deps/v8/src/code-factory.h @@ -33,7 +33,9 @@ class CodeFactory FINAL { public: // Initial states for ICs. static Callable LoadIC(Isolate* isolate, ContextualMode mode); + static Callable LoadICInOptimizedCode(Isolate* isolate, ContextualMode mode); static Callable KeyedLoadIC(Isolate* isolate); + static Callable KeyedLoadICInOptimizedCode(Isolate* isolate); static Callable StoreIC(Isolate* isolate, StrictMode mode); static Callable KeyedStoreIC(Isolate* isolate, StrictMode mode); @@ -53,9 +55,13 @@ class CodeFactory FINAL { static Callable StringAdd(Isolate* isolate, StringAddFlags flags, PretenureFlag pretenure_flag); + static Callable AllocateHeapNumber(Isolate* isolate); + static Callable CallFunction(Isolate* isolate, int argc, CallFunctionFlags flags); }; -} -} + +} // namespace internal +} // namespace v8 + #endif // V8_CODE_FACTORY_H_ diff --git a/deps/v8/src/code-stubs-hydrogen.cc b/deps/v8/src/code-stubs-hydrogen.cc index dafef522f1..dc527d7d70 100644 --- a/deps/v8/src/code-stubs-hydrogen.cc +++ b/deps/v8/src/code-stubs-hydrogen.cc @@ -64,7 +64,8 @@ class CodeStubGraphBuilderBase : public HGraphBuilder { HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index); void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, - Representation representation); + Representation representation, + bool transition_to_field); enum ArgumentClass { NONE, @@ -232,6 +233,8 @@ Handle HydrogenCodeStub::GenerateLightweightMissCode( // Generate the code for the stub. masm.set_generating_stub(true); + // TODO(yangguo): remove this once we can serialize IC stubs. + masm.enable_serializer(); NoCurrentFrameScope scope(&masm); GenerateLightweightMiss(&masm, miss); } @@ -270,49 +273,16 @@ static Handle DoGenerateCode(Stub* stub) { } CodeStubGraphBuilder builder(isolate, stub); LChunk* chunk = OptimizeGraph(builder.CreateGraph()); - // TODO(yangguo) remove this once the code serializer handles code stubs. - if (FLAG_serialize_toplevel) chunk->info()->PrepareForSerializing(); Handle code = chunk->Codegen(); if (FLAG_profile_hydrogen_code_stub_compilation) { OFStream os(stdout); os << "[Lazy compilation of " << stub << " took " - << timer.Elapsed().InMillisecondsF() << " ms]" << endl; + << timer.Elapsed().InMillisecondsF() << " ms]" << std::endl; } return code; } -template <> -HValue* CodeStubGraphBuilder::BuildCodeStub() { - HValue* value = GetParameter(0); - - // Check if the parameter is already a SMI or heap number. - IfBuilder if_number(this); - if_number.If(value); - if_number.OrIf(value, isolate()->factory()->heap_number_map()); - if_number.Then(); - - // Return the number. - Push(value); - - if_number.Else(); - - // Convert the parameter to number using the builtin. - HValue* function = AddLoadJSBuiltin(Builtins::TO_NUMBER); - Add(value); - Push(Add(function, 1)); - - if_number.End(); - - return Pop(); -} - - -Handle ToNumberStub::GenerateCode() { - return DoGenerateCode(this); -} - - template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { info()->MarkAsSavesCallerDoubles(); @@ -415,7 +385,12 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { HInstruction* boilerplate = Add( allocation_site, static_cast(NULL), access); - int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize; + int length = casted_stub()->length(); + if (length == 0) { + // Empty objects have some slack added to them. + length = JSObject::kInitialGlobalObjectUnusedPropertiesCount; + } + int size = JSObject::kHeaderSize + length * kPointerSize; int object_size = size; if (FLAG_allocation_site_pretenuring) { size += AllocationMemento::kSize; @@ -721,7 +696,7 @@ Handle KeyedLoadSloppyArgumentsStub::GenerateCode() { void CodeStubGraphBuilderBase::BuildStoreNamedField( HValue* object, HValue* value, FieldIndex index, - Representation representation) { + Representation representation, bool transition_to_field) { DCHECK(!index.is_double() || representation.IsDouble()); int offset = index.offset(); HObjectAccess access = @@ -730,12 +705,31 @@ void CodeStubGraphBuilderBase::BuildStoreNamedField( : HObjectAccess::ForBackingStoreOffset(offset, representation); if (representation.IsDouble()) { - // Load the heap number. - object = Add( - object, static_cast(NULL), - access.WithRepresentation(Representation::Tagged())); - // Store the double value into it. - access = HObjectAccess::ForHeapNumberValue(); + HObjectAccess heap_number_access = + access.WithRepresentation(Representation::Tagged()); + if (transition_to_field) { + // The store requires a mutable HeapNumber to be allocated. + NoObservableSideEffectsScope no_side_effects(this); + HInstruction* heap_number_size = Add(HeapNumber::kSize); + + // TODO(hpayer): Allocation site pretenuring support. + HInstruction* heap_number = + Add(heap_number_size, HType::HeapObject(), NOT_TENURED, + MUTABLE_HEAP_NUMBER_TYPE); + AddStoreMapConstant(heap_number, + isolate()->factory()->mutable_heap_number_map()); + Add(heap_number, HObjectAccess::ForHeapNumberValue(), + value); + // Store the new mutable heap number into the object. + access = heap_number_access; + value = heap_number; + } else { + // Load the heap number. + object = Add(object, static_cast(NULL), + heap_number_access); + // Store the double value into it. + access = HObjectAccess::ForHeapNumberValue(); + } } else if (representation.IsHeapObject()) { BuildCheckHeapObject(value); } @@ -747,7 +741,7 @@ void CodeStubGraphBuilderBase::BuildStoreNamedField( template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(), - casted_stub()->representation()); + casted_stub()->representation(), false); return GetParameter(2); } @@ -755,6 +749,59 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { Handle StoreFieldStub::GenerateCode() { return DoGenerateCode(this); } +template <> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + HValue* object = GetParameter(StoreTransitionDescriptor::kReceiverIndex); + + switch (casted_stub()->store_mode()) { + case StoreTransitionStub::ExtendStorageAndStoreMapAndValue: { + HValue* properties = + Add(object, static_cast(NULL), + HObjectAccess::ForPropertiesPointer()); + HValue* length = AddLoadFixedArrayLength(properties); + HValue* delta = + Add(static_cast(JSObject::kFieldsAdded)); + HValue* new_capacity = AddUncasted(length, delta); + + // Grow properties array. + ElementsKind kind = FAST_ELEMENTS; + Add(new_capacity, + Add((Page::kMaxRegularHeapObjectSize - + FixedArray::kHeaderSize) >> + ElementsKindToShiftSize(kind))); + + // Reuse this code for properties backing store allocation. + HValue* new_properties = + BuildAllocateAndInitializeArray(kind, new_capacity); + + BuildCopyProperties(properties, new_properties, length, new_capacity); + + Add(object, HObjectAccess::ForPropertiesPointer(), + new_properties); + } + // Fall through. + case StoreTransitionStub::StoreMapAndValue: + // Store the new value into the "extended" object. + BuildStoreNamedField( + object, GetParameter(StoreTransitionDescriptor::kValueIndex), + casted_stub()->index(), casted_stub()->representation(), true); + // Fall through. + + case StoreTransitionStub::StoreMapOnly: + // And finally update the map. + Add(object, HObjectAccess::ForMap(), + GetParameter(StoreTransitionDescriptor::kMapIndex)); + break; + } + return GetParameter(StoreTransitionDescriptor::kValueIndex); +} + + +Handle StoreTransitionStub::GenerateCode() { + return DoGenerateCode(this); +} + + template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { HValue* string = BuildLoadNamedField(GetParameter(0), @@ -805,6 +852,22 @@ Handle TransitionElementsKindStub::GenerateCode() { return DoGenerateCode(this); } + +template <> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + HValue* result = + Add(Add(HeapNumber::kSize), HType::HeapNumber(), + NOT_TENURED, HEAP_NUMBER_TYPE); + AddStoreMapConstant(result, isolate()->factory()->heap_number_map()); + return result; +} + + +Handle AllocateHeapNumberStub::GenerateCode() { + return DoGenerateCode(this); +} + + HValue* CodeStubGraphBuilderBase::BuildArrayConstructor( ElementsKind kind, AllocationSiteOverrideMode override_mode, diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc index 5c9e1a2b86..7442f3e134 100644 --- a/deps/v8/src/code-stubs.cc +++ b/deps/v8/src/code-stubs.cc @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/code-stubs.h" + +#include #include "src/bootstrapper.h" -#include "src/code-stubs.h" #include "src/cpu-profiler.h" #include "src/factory.h" #include "src/gdb-jit.h" @@ -75,9 +76,10 @@ bool CodeStub::FindCodeInCache(Code** code_out) { void CodeStub::RecordCodeGeneration(Handle code) { IC::RegisterWeakMapDependency(code); - OStringStream os; + std::ostringstream os; os << *this; - PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, os.c_str())); + PROFILE(isolate(), + CodeCreateEvent(Logger::STUB_TAG, *code, os.str().c_str())); Counters* counters = isolate()->counters(); counters->total_stubs_code_size()->Increment(code->instruction_size()); } @@ -103,15 +105,14 @@ Handle PlatformCodeStub::GenerateCode() { // Generate the new code. MacroAssembler masm(isolate(), NULL, 256); - // TODO(yangguo) remove this once the code serializer handles code stubs. - if (FLAG_serialize_toplevel) masm.enable_serializer(); - { // Update the static counter each time a new code stub is generated. isolate()->counters()->code_stubs()->Increment(); // Generate the code for the stub. masm.set_generating_stub(true); + // TODO(yangguo): remove this once we can serialize IC stubs. + masm.enable_serializer(); NoCurrentFrameScope scope(&masm); Generate(&masm); } @@ -153,9 +154,9 @@ Handle CodeStub::GetCode() { if (FLAG_print_code_stubs) { CodeTracer::Scope trace_scope(isolate()->GetCodeTracer()); OFStream os(trace_scope.file()); - OStringStream name; + std::ostringstream name; name << *this; - new_object->Disassemble(name.c_str(), os); + new_object->Disassemble(name.str().c_str(), os); os << "\n"; } #endif @@ -198,12 +199,12 @@ const char* CodeStub::MajorName(CodeStub::Major major_key, } -void CodeStub::PrintBaseName(OStream& os) const { // NOLINT +void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT os << MajorName(MajorKey(), false); } -void CodeStub::PrintName(OStream& os) const { // NOLINT +void CodeStub::PrintName(std::ostream& os) const { // NOLINT PrintBaseName(os); PrintState(os); } @@ -222,9 +223,8 @@ void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out, CODE_STUB_LIST(DEF_CASE) #undef DEF_CASE case NUMBER_OF_IDS: - UNREACHABLE(); case NoCache: - *value_out = NULL; + UNREACHABLE(); break; } } @@ -279,7 +279,7 @@ void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) { } -void BinaryOpICStub::PrintState(OStream& os) const { // NOLINT +void BinaryOpICStub::PrintState(std::ostream& os) const { // NOLINT os << state(); } @@ -300,7 +300,7 @@ void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) { void BinaryOpICWithAllocationSiteStub::PrintState( - OStream& os) const { // NOLINT + std::ostream& os) const { // NOLINT os << state(); } @@ -315,7 +315,7 @@ void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime( } -void StringAddStub::PrintBaseName(OStream& os) const { // NOLINT +void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT os << "StringAddStub"; if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { os << "_CheckBoth"; @@ -463,17 +463,17 @@ void HydrogenCodeStub::TraceTransition(StateType from, StateType to) { OFStream os(stdout); os << "["; PrintBaseName(os); - os << ": " << from << "=>" << to << "]" << endl; + os << ": " << from << "=>" << to << "]" << std::endl; } -void CompareNilICStub::PrintBaseName(OStream& os) const { // NOLINT +void CompareNilICStub::PrintBaseName(std::ostream& os) const { // NOLINT CodeStub::PrintBaseName(os); os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)"); } -void CompareNilICStub::PrintState(OStream& os) const { // NOLINT +void CompareNilICStub::PrintState(std::ostream& os) const { // NOLINT os << state(); } @@ -481,7 +481,7 @@ void CompareNilICStub::PrintState(OStream& os) const { // NOLINT // TODO(svenpanne) Make this a real infix_ostream_iterator. class SimpleListPrinter { public: - explicit SimpleListPrinter(OStream& os) : os_(os), first_(true) {} + explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {} void Add(const char* s) { if (first_) { @@ -493,12 +493,12 @@ class SimpleListPrinter { } private: - OStream& os_; + std::ostream& os_; bool first_; }; -OStream& operator<<(OStream& os, const CompareNilICStub::State& s) { +std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) { os << "("; SimpleListPrinter p(os); if (s.IsEmpty()) p.Add("None"); @@ -539,17 +539,17 @@ Type* CompareNilICStub::GetInputType(Zone* zone, Handle map) { } -void CallIC_ArrayStub::PrintState(OStream& os) const { // NOLINT +void CallIC_ArrayStub::PrintState(std::ostream& os) const { // NOLINT os << state() << " (Array)"; } -void CallICStub::PrintState(OStream& os) const { // NOLINT +void CallICStub::PrintState(std::ostream& os) const { // NOLINT os << state(); } -void InstanceofStub::PrintName(OStream& os) const { // NOLINT +void InstanceofStub::PrintName(std::ostream& os) const { // NOLINT os << "InstanceofStub"; if (HasArgsInRegisters()) os << "_REGS"; if (HasCallSiteInlineCheck()) os << "_INLINE"; @@ -594,6 +594,9 @@ void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() { if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) { + if (FLAG_vector_ics) { + return VectorLoadICDescriptor(isolate()); + } return LoadDescriptor(isolate()); } else { DCHECK_EQ(Code::STORE_IC, kind()); @@ -614,6 +617,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor( } +CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor() { + return StoreTransitionDescriptor(isolate()); +} + + static void InitializeVectorLoadStub(Isolate* isolate, CodeStubDescriptor* descriptor, Address deoptimization_handler) { @@ -624,14 +632,13 @@ static void InitializeVectorLoadStub(Isolate* isolate, void VectorLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { InitializeVectorLoadStub(isolate(), descriptor, - FUNCTION_ADDR(VectorLoadIC_MissFromStubFailure)); + FUNCTION_ADDR(LoadIC_MissFromStubFailure)); } void VectorKeyedLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { - InitializeVectorLoadStub( - isolate(), descriptor, - FUNCTION_ADDR(VectorKeyedLoadIC_MissFromStubFailure)); + InitializeVectorLoadStub(isolate(), descriptor, + FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure)); } @@ -647,9 +654,6 @@ void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {} -void ToNumberStub::InitializeDescriptor(CodeStubDescriptor* d) {} - - void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { NumberToStringDescriptor call_descriptor(isolate()); descriptor->Initialize( @@ -690,6 +694,13 @@ void TransitionElementsKindStub::InitializeDescriptor( } +void AllocateHeapNumberStub::InitializeDescriptor( + CodeStubDescriptor* descriptor) { + descriptor->Initialize( + Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry); +} + + void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss)); descriptor->SetMissHandler( @@ -772,7 +783,7 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) { } -void ArgumentsAccessStub::PrintName(OStream& os) const { // NOLINT +void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT os << "ArgumentsAccessStub_"; switch (type()) { case READ_ELEMENT: @@ -792,18 +803,18 @@ void ArgumentsAccessStub::PrintName(OStream& os) const { // NOLINT } -void CallFunctionStub::PrintName(OStream& os) const { // NOLINT +void CallFunctionStub::PrintName(std::ostream& os) const { // NOLINT os << "CallFunctionStub_Args" << argc(); } -void CallConstructStub::PrintName(OStream& os) const { // NOLINT +void CallConstructStub::PrintName(std::ostream& os) const { // NOLINT os << "CallConstructStub"; if (RecordCallTarget()) os << "_Recording"; } -void ArrayConstructorStub::PrintName(OStream& os) const { // NOLINT +void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT os << "ArrayConstructorStub"; switch (argument_count()) { case ANY: @@ -823,8 +834,9 @@ void ArrayConstructorStub::PrintName(OStream& os) const { // NOLINT } -OStream& ArrayConstructorStubBase::BasePrintName(OStream& os, // NOLINT - const char* name) const { +std::ostream& ArrayConstructorStubBase::BasePrintName( + std::ostream& os, // NOLINT + const char* name) const { os << name << "_" << ElementsKindToString(elements_kind()); if (override_mode() == DISABLE_ALLOCATION_SITES) { os << "_DISABLE_ALLOCATION_SITES"; @@ -843,12 +855,12 @@ bool ToBooleanStub::UpdateStatus(Handle object) { } -void ToBooleanStub::PrintState(OStream& os) const { // NOLINT +void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT os << types(); } -OStream& operator<<(OStream& os, const ToBooleanStub::Types& s) { +std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) { os << "("; SimpleListPrinter p(os); if (s.IsEmpty()) p.Add("None"); diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h index b127782c6e..06eff69c8e 100644 --- a/deps/v8/src/code-stubs.h +++ b/deps/v8/src/code-stubs.h @@ -39,6 +39,7 @@ namespace internal { V(KeyedLoadICTrampoline) \ V(LoadICTrampoline) \ V(LoadIndexedInterceptor) \ + V(LoadIndexedString) \ V(MathPow) \ V(ProfileEntryHook) \ V(RecordWrite) \ @@ -49,7 +50,9 @@ namespace internal { V(StringCompare) \ V(StubFailureTrampoline) \ V(SubString) \ + V(ToNumber) \ /* HydrogenCodeStubs */ \ + V(AllocateHeapNumber) \ V(ArrayNArgumentsConstructor) \ V(ArrayNoArgumentConstructor) \ V(ArraySingleArgumentConstructor) \ @@ -75,7 +78,6 @@ namespace internal { V(StoreFastElement) \ V(StringAdd) \ V(ToBoolean) \ - V(ToNumber) \ V(TransitionElementsKind) \ V(VectorKeyedLoad) \ V(VectorLoad) \ @@ -85,6 +87,7 @@ namespace internal { V(KeyedLoadSloppyArguments) \ V(StoreField) \ V(StoreGlobal) \ + V(StoreTransition) \ V(StringLength) // List of code stubs only used on ARM 32 bits platforms. @@ -203,7 +206,7 @@ class CodeStub BASE_EMBEDDED { return Code::NORMAL; } - friend OStream& operator<<(OStream& os, const CodeStub& s) { + friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) { s.PrintName(os); return os; } @@ -221,9 +224,9 @@ class CodeStub BASE_EMBEDDED { // a fixed (non-moveable) code object. virtual bool NeedsImmovableCode() { return false; } - virtual void PrintName(OStream& os) const; // NOLINT - virtual void PrintBaseName(OStream& os) const; // NOLINT - virtual void PrintState(OStream& os) const { ; } // NOLINT + virtual void PrintName(std::ostream& os) const; // NOLINT + virtual void PrintBaseName(std::ostream& os) const; // NOLINT + virtual void PrintState(std::ostream& os) const { ; } // NOLINT // Computes the key based on major and minor. uint32_t GetKey() { @@ -335,7 +338,7 @@ class PlatformCodeStub : public CodeStub { // Retrieve the code for the stub. Generate the code if needed. virtual Handle GenerateCode() OVERRIDE; - virtual Code::Kind GetCodeKind() const { return Code::STUB; } + virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::STUB; } protected: explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {} @@ -435,7 +438,7 @@ class HydrogenCodeStub : public CodeStub { INITIALIZED }; - virtual Code::Kind GetCodeKind() const { return Code::STUB; } + virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::STUB; } template static Handle GetUninitialized(Isolate* isolate) { @@ -542,15 +545,6 @@ class NopRuntimeCallHelper : public RuntimeCallHelper { }; -class ToNumberStub: public HydrogenCodeStub { - public: - explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { } - - DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber); - DEFINE_HYDROGEN_CODE_STUB(ToNumber, HydrogenCodeStub); -}; - - class NumberToStringStub FINAL : public HydrogenCodeStub { public: explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {} @@ -705,7 +699,7 @@ class InstanceofStub: public PlatformCodeStub { return (flags() & kReturnTrueFalseObject) != 0; } - virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE; // NOLINT class FlagBits : public BitField {}; @@ -736,7 +730,7 @@ class ArrayConstructorStub: public PlatformCodeStub { void GenerateDispatchToArrayStub(MacroAssembler* masm, AllocationSiteOverrideMode mode); - virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE; // NOLINT class ArgumentCountBits : public BitField {}; @@ -822,7 +816,7 @@ class CallICStub: public PlatformCodeStub { void GenerateMiss(MacroAssembler* masm); private: - virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintState(std::ostream& os) const OVERRIDE; // NOLINT DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback); DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub); @@ -839,7 +833,7 @@ class CallIC_ArrayStub: public CallICStub { } private: - virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintState(std::ostream& os) const OVERRIDE; // NOLINT DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub); }; @@ -851,12 +845,18 @@ class FunctionPrototypeStub : public PlatformCodeStub { explicit FunctionPrototypeStub(Isolate* isolate) : PlatformCodeStub(isolate) {} - virtual Code::Kind GetCodeKind() const { return Code::HANDLER; } + virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; } // TODO(mvstanton): only the receiver register is accessed. When this is // translated to a hydrogen code stub, a new CallInterfaceDescriptor // should be created that just uses that register for more efficient code. - DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); + virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { + if (FLAG_vector_ics) { + return VectorLoadICDescriptor(isolate()); + } + return LoadDescriptor(isolate()); + } + DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub); }; @@ -867,19 +867,32 @@ class LoadIndexedInterceptorStub : public PlatformCodeStub { explicit LoadIndexedInterceptorStub(Isolate* isolate) : PlatformCodeStub(isolate) {} - virtual Code::Kind GetCodeKind() const { return Code::HANDLER; } - virtual Code::StubType GetStubType() { return Code::FAST; } + virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub); }; +class LoadIndexedStringStub : public PlatformCodeStub { + public: + explicit LoadIndexedStringStub(Isolate* isolate) + : PlatformCodeStub(isolate) {} + + virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } + + DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); + DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub); +}; + + class HandlerStub : public HydrogenCodeStub { public: - virtual Code::Kind GetCodeKind() const { return Code::HANDLER; } - virtual ExtraICState GetExtraICState() const { return kind(); } - virtual InlineCacheState GetICState() const { return MONOMORPHIC; } + virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; } + virtual ExtraICState GetExtraICState() const OVERRIDE { return kind(); } + virtual InlineCacheState GetICState() const OVERRIDE { return MONOMORPHIC; } virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE; @@ -908,7 +921,7 @@ class LoadFieldStub: public HandlerStub { protected: virtual Code::Kind kind() const { return Code::LOAD_IC; } - virtual Code::StubType GetStubType() { return Code::FAST; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } private: class LoadFieldByIndexBits : public BitField {}; @@ -923,8 +936,8 @@ class KeyedLoadSloppyArgumentsStub : public HandlerStub { : HandlerStub(isolate) {} protected: - virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; } - virtual Code::StubType GetStubType() { return Code::FAST; } + virtual Code::Kind kind() const OVERRIDE { return Code::KEYED_LOAD_IC; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } private: DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub); @@ -943,8 +956,8 @@ class LoadConstantStub : public HandlerStub { } protected: - virtual Code::Kind kind() const { return Code::LOAD_IC; } - virtual Code::StubType GetStubType() { return Code::FAST; } + virtual Code::Kind kind() const OVERRIDE { return Code::LOAD_IC; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } private: class ConstantIndexBits : public BitField {}; @@ -958,8 +971,8 @@ class StringLengthStub: public HandlerStub { explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {} protected: - virtual Code::Kind kind() const { return Code::LOAD_IC; } - virtual Code::StubType GetStubType() { return Code::FAST; } + virtual Code::Kind kind() const OVERRIDE { return Code::LOAD_IC; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub); }; @@ -987,8 +1000,8 @@ class StoreFieldStub : public HandlerStub { } protected: - virtual Code::Kind kind() const { return Code::STORE_IC; } - virtual Code::StubType GetStubType() { return Code::FAST; } + virtual Code::Kind kind() const OVERRIDE { return Code::STORE_IC; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } private: class StoreFieldByIndexBits : public BitField {}; @@ -998,6 +1011,60 @@ class StoreFieldStub : public HandlerStub { }; +class StoreTransitionStub : public HandlerStub { + public: + enum StoreMode { + StoreMapOnly, + StoreMapAndValue, + ExtendStorageAndStoreMapAndValue + }; + + explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) { + set_sub_minor_key(StoreModeBits::encode(StoreMapOnly)); + } + + StoreTransitionStub(Isolate* isolate, FieldIndex index, + Representation representation, StoreMode store_mode) + : HandlerStub(isolate) { + DCHECK(store_mode != StoreMapOnly); + int property_index_key = index.GetFieldAccessStubKey(); + uint8_t repr = PropertyDetails::EncodeRepresentation(representation); + set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) | + RepresentationBits::encode(repr) | + StoreModeBits::encode(store_mode)); + } + + FieldIndex index() const { + DCHECK(store_mode() != StoreMapOnly); + int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key()); + return FieldIndex::FromFieldAccessStubKey(property_index_key); + } + + Representation representation() { + DCHECK(store_mode() != StoreMapOnly); + uint8_t repr = RepresentationBits::decode(sub_minor_key()); + return PropertyDetails::DecodeRepresentation(repr); + } + + StoreMode store_mode() const { + return StoreModeBits::decode(sub_minor_key()); + } + + virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE; + + protected: + virtual Code::Kind kind() const OVERRIDE { return Code::STORE_IC; } + virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } + + private: + class StoreFieldByIndexBits : public BitField {}; + class RepresentationBits : public BitField {}; + class StoreModeBits : public BitField {}; + + DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub); +}; + + class StoreGlobalStub : public HandlerStub { public: StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global) @@ -1025,7 +1092,7 @@ class StoreGlobalStub : public HandlerStub { } } - virtual Code::Kind kind() const { return Code::STORE_IC; } + virtual Code::Kind kind() const OVERRIDE { return Code::STORE_IC; } bool is_constant() const { return IsConstantBits::decode(sub_minor_key()); } @@ -1123,7 +1190,7 @@ class BinaryOpICStub : public HydrogenCodeStub { return BinaryOpICState(isolate(), GetExtraICState()); } - virtual void PrintState(OStream& os) const FINAL OVERRIDE; // NOLINT + virtual void PrintState(std::ostream& os) const FINAL OVERRIDE; // NOLINT // Parameters accessed via CodeStubGraphBuilder::GetParameter() static const int kLeft = 0; @@ -1168,7 +1235,7 @@ class BinaryOpICWithAllocationSiteStub FINAL : public PlatformCodeStub { return static_cast(minor_key_); } - virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintState(std::ostream& os) const OVERRIDE; // NOLINT private: BinaryOpICState state() const { @@ -1244,7 +1311,7 @@ class StringAddStub FINAL : public HydrogenCodeStub { class StringAddFlagsBits: public BitField {}; class PretenureFlagBits: public BitField {}; - virtual void PrintBaseName(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintBaseName(std::ostream& os) const OVERRIDE; // NOLINT DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd); DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub); @@ -1263,7 +1330,7 @@ class CompareICStub : public PlatformCodeStub { void set_known_map(Handle map) { known_map_ = map; } - virtual InlineCacheState GetICState() const; + virtual InlineCacheState GetICState() const OVERRIDE; Token::Value op() const { return static_cast(Token::EQ + OpBits::decode(minor_key_)); @@ -1278,7 +1345,7 @@ class CompareICStub : public PlatformCodeStub { CompareICState::State state() const { return StateBits::decode(minor_key_); } private: - virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; } + virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::COMPARE_IC; } void GenerateSmis(MacroAssembler* masm); void GenerateNumbers(MacroAssembler* masm); @@ -1293,9 +1360,9 @@ class CompareICStub : public PlatformCodeStub { bool strict() const { return op() == Token::EQ_STRICT; } Condition GetCondition() const; - virtual void AddToSpecialCache(Handle new_object); - virtual bool FindCodeInSpecialCache(Code** code_out); - virtual bool UseSpecialCache() { + virtual void AddToSpecialCache(Handle new_object) OVERRIDE; + virtual bool FindCodeInSpecialCache(Code** code_out) OVERRIDE; + virtual bool UseSpecialCache() OVERRIDE { return state() == CompareICState::KNOWN_OBJECT; } @@ -1331,7 +1398,7 @@ class CompareNilICStub : public HydrogenCodeStub { return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode(); } - virtual InlineCacheState GetICState() const { + virtual InlineCacheState GetICState() const OVERRIDE { State state = this->state(); if (state.Contains(GENERIC)) { return MEGAMORPHIC; @@ -1342,9 +1409,13 @@ class CompareNilICStub : public HydrogenCodeStub { } } - virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; } + virtual Code::Kind GetCodeKind() const OVERRIDE { + return Code::COMPARE_NIL_IC; + } - virtual ExtraICState GetExtraICState() const { return sub_minor_key(); } + virtual ExtraICState GetExtraICState() const OVERRIDE { + return sub_minor_key(); + } void UpdateStatus(Handle object); @@ -1356,8 +1427,8 @@ class CompareNilICStub : public HydrogenCodeStub { set_sub_minor_key(TypesBits::update(sub_minor_key(), 0)); } - virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT - virtual void PrintBaseName(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintState(std::ostream& os) const OVERRIDE; // NOLINT + virtual void PrintBaseName(std::ostream& os) const OVERRIDE; // NOLINT private: CompareNilICStub(Isolate* isolate, NilValue nil, @@ -1384,7 +1455,7 @@ class CompareNilICStub : public HydrogenCodeStub { State() : EnumSet(0) { } explicit State(byte bits) : EnumSet(bits) { } }; - friend OStream& operator<<(OStream& os, const State& s); + friend std::ostream& operator<<(std::ostream& os, const State& s); State state() const { return State(TypesBits::decode(sub_minor_key())); } @@ -1398,7 +1469,7 @@ class CompareNilICStub : public HydrogenCodeStub { }; -OStream& operator<<(OStream& os, const CompareNilICStub::State& s); +std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s); class CEntryStub : public PlatformCodeStub { @@ -1425,7 +1496,7 @@ class CEntryStub : public PlatformCodeStub { int result_size() const { return ResultSizeBits::decode(minor_key_); } #endif // _WIN64 - bool NeedsImmovableCode(); + bool NeedsImmovableCode() OVERRIDE; class SaveDoublesBits : public BitField {}; class ResultSizeBits : public BitField {}; @@ -1444,9 +1515,9 @@ class JSEntryStub : public PlatformCodeStub { } private: - virtual void FinishCode(Handle code); + virtual void FinishCode(Handle code) OVERRIDE; - virtual void PrintName(OStream& os) const OVERRIDE { // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE { // NOLINT os << (type() == StackFrame::ENTRY ? "JSEntryStub" : "JSConstructEntryStub"); } @@ -1492,7 +1563,7 @@ class ArgumentsAccessStub: public PlatformCodeStub { void GenerateNewSloppyFast(MacroAssembler* masm); void GenerateNewSloppySlow(MacroAssembler* masm); - virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE; // NOLINT class TypeBits : public BitField {}; @@ -1546,7 +1617,7 @@ class CallFunctionStub: public PlatformCodeStub { bool NeedsChecks() const { return flags() != WRAP_AND_CALL; } - virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE; // NOLINT // Minor key encoding in 32 bits with Bitfield . class FlagBits : public BitField {}; @@ -1565,7 +1636,7 @@ class CallConstructStub: public PlatformCodeStub { minor_key_ = FlagBits::encode(flags); } - virtual void FinishCode(Handle code) { + virtual void FinishCode(Handle code) OVERRIDE { code->set_has_function_cache(RecordCallTarget()); } @@ -1576,7 +1647,7 @@ class CallConstructStub: public PlatformCodeStub { return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0; } - virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE; // NOLINT class FlagBits : public BitField {}; @@ -1596,6 +1667,15 @@ enum StringIndexFlags { }; +enum ReceiverCheckMode { + // We don't know anything about the receiver. + RECEIVER_IS_UNKNOWN, + + // We know the receiver is a string. + RECEIVER_IS_STRING +}; + + // Generates code implementing String.prototype.charCodeAt. // // Only supports the case when the receiver is a string and the index @@ -1608,20 +1688,19 @@ enum StringIndexFlags { // preserved, |scratch| and |result| are clobbered. class StringCharCodeAtGenerator { public: - StringCharCodeAtGenerator(Register object, - Register index, - Register result, - Label* receiver_not_string, - Label* index_not_number, + StringCharCodeAtGenerator(Register object, Register index, Register result, + Label* receiver_not_string, Label* index_not_number, Label* index_out_of_range, - StringIndexFlags index_flags) + StringIndexFlags index_flags, + ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN) : object_(object), index_(index), result_(result), receiver_not_string_(receiver_not_string), index_not_number_(index_not_number), index_out_of_range_(index_out_of_range), - index_flags_(index_flags) { + index_flags_(index_flags), + check_mode_(check_mode) { DCHECK(!result_.is(object_)); DCHECK(!result_.is(index_)); } @@ -1653,6 +1732,7 @@ class StringCharCodeAtGenerator { Label* index_out_of_range_; StringIndexFlags index_flags_; + ReceiverCheckMode check_mode_; Label call_runtime_; Label index_not_smi_; @@ -1712,21 +1792,14 @@ class StringCharFromCodeGenerator { // preserved, |scratch1|, |scratch2|, and |result| are clobbered. class StringCharAtGenerator { public: - StringCharAtGenerator(Register object, - Register index, - Register scratch, - Register result, - Label* receiver_not_string, - Label* index_not_number, - Label* index_out_of_range, - StringIndexFlags index_flags) - : char_code_at_generator_(object, - index, - scratch, - receiver_not_string, - index_not_number, - index_out_of_range, - index_flags), + StringCharAtGenerator(Register object, Register index, Register scratch, + Register result, Label* receiver_not_string, + Label* index_not_number, Label* index_out_of_range, + StringIndexFlags index_flags, + ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN) + : char_code_at_generator_(object, index, scratch, receiver_not_string, + index_not_number, index_out_of_range, + index_flags, check_mode), char_from_code_generator_(scratch, result) {} // Generates the fast case code. On the fallthrough path |result| @@ -1764,7 +1837,13 @@ class LoadDictionaryElementStub : public HydrogenCodeStub { explicit LoadDictionaryElementStub(Isolate* isolate) : HydrogenCodeStub(isolate) {} - DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); + virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { + if (FLAG_vector_ics) { + return VectorLoadICDescriptor(isolate()); + } + return LoadDescriptor(isolate()); + } + DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub); }; @@ -1773,10 +1852,16 @@ class KeyedLoadGenericStub : public HydrogenCodeStub { public: explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {} - virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; } - virtual InlineCacheState GetICState() const { return GENERIC; } + virtual Code::Kind GetCodeKind() const OVERRIDE { + return Code::KEYED_LOAD_IC; + } + virtual InlineCacheState GetICState() const OVERRIDE { return GENERIC; } + // Since KeyedLoadGeneric stub doesn't miss (simply calls runtime), it + // doesn't need to use the VectorLoadICDescriptor for the case when + // flag --vector-ics is true. DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); + DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub); }; @@ -1790,9 +1875,7 @@ class LoadICTrampolineStub : public PlatformCodeStub { virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; } - virtual InlineCacheState GetICState() const FINAL OVERRIDE { - return GENERIC; - } + virtual InlineCacheState GetICState() const FINAL OVERRIDE { return DEFAULT; } virtual ExtraICState GetExtraICState() const FINAL OVERRIDE { return static_cast(minor_key_); @@ -1838,7 +1921,13 @@ class MegamorphicLoadStub : public HydrogenCodeStub { return static_cast(sub_minor_key()); } - DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); + virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { + if (FLAG_vector_ics) { + return VectorLoadICDescriptor(isolate()); + } + return LoadDescriptor(isolate()); + } + DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub); }; @@ -1852,9 +1941,7 @@ class VectorLoadStub : public HydrogenCodeStub { virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; } - virtual InlineCacheState GetICState() const FINAL OVERRIDE { - return GENERIC; - } + virtual InlineCacheState GetICState() const FINAL OVERRIDE { return DEFAULT; } virtual ExtraICState GetExtraICState() const FINAL OVERRIDE { return static_cast(sub_minor_key()); @@ -1895,7 +1982,7 @@ class DoubleToIStub : public PlatformCodeStub { SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0); } - virtual bool SometimesSetsUpAFrame() { return false; } + virtual bool SometimesSetsUpAFrame() OVERRIDE { return false; } private: Register source() const { @@ -1948,7 +2035,13 @@ class LoadFastElementStub : public HydrogenCodeStub { class ElementsKindBits: public BitField {}; class IsJSArrayBits: public BitField {}; - DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); + virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { + if (FLAG_vector_ics) { + return VectorLoadICDescriptor(isolate()); + } + return LoadDescriptor(isolate()); + } + DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub); }; @@ -2012,6 +2105,17 @@ class TransitionElementsKindStub : public HydrogenCodeStub { }; +class AllocateHeapNumberStub FINAL : public HydrogenCodeStub { + public: + explicit AllocateHeapNumberStub(Isolate* isolate) + : HydrogenCodeStub(isolate) {} + + private: + DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber); + DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub); +}; + + class ArrayConstructorStubBase : public HydrogenCodeStub { public: ArrayConstructorStubBase(Isolate* isolate, @@ -2042,7 +2146,8 @@ class ArrayConstructorStubBase : public HydrogenCodeStub { static const int kAllocationSite = 1; protected: - OStream& BasePrintName(OStream& os, const char* name) const; // NOLINT + std::ostream& BasePrintName(std::ostream& os, + const char* name) const; // NOLINT private: // Ensure data fits within available bits. @@ -2066,7 +2171,7 @@ class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase { } private: - virtual void PrintName(OStream& os) const OVERRIDE { // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE { // NOLINT BasePrintName(os, "ArrayNoArgumentConstructorStub"); } @@ -2086,7 +2191,7 @@ class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase { } private: - virtual void PrintName(OStream& os) const { // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE { // NOLINT BasePrintName(os, "ArraySingleArgumentConstructorStub"); } @@ -2106,7 +2211,7 @@ class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase { } private: - virtual void PrintName(OStream& os) const { // NOLINT + virtual void PrintName(std::ostream& os) const OVERRIDE { // NOLINT BasePrintName(os, "ArrayNArgumentsConstructorStub"); } @@ -2250,18 +2355,22 @@ class ToBooleanStub: public HydrogenCodeStub { Types types() const { return Types(TypesBits::decode(sub_minor_key())); } ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); } - virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; } - virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT + virtual Code::Kind GetCodeKind() const OVERRIDE { + return Code::TO_BOOLEAN_IC; + } + virtual void PrintState(std::ostream& os) const OVERRIDE; // NOLINT - virtual bool SometimesSetsUpAFrame() { return false; } + virtual bool SometimesSetsUpAFrame() OVERRIDE { return false; } static Handle GetUninitialized(Isolate* isolate) { return ToBooleanStub(isolate, UNINITIALIZED).GetCode(); } - virtual ExtraICState GetExtraICState() const { return types().ToIntegral(); } + virtual ExtraICState GetExtraICState() const OVERRIDE { + return types().ToIntegral(); + } - virtual InlineCacheState GetICState() const { + virtual InlineCacheState GetICState() const OVERRIDE { if (types().IsEmpty()) { return ::v8::internal::UNINITIALIZED; } else { @@ -2283,7 +2392,7 @@ class ToBooleanStub: public HydrogenCodeStub { }; -OStream& operator<<(OStream& os, const ToBooleanStub::Types& t); +std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t); class ElementsTransitionAndStoreStub : public HydrogenCodeStub { @@ -2373,7 +2482,7 @@ class ProfileEntryHookStub : public PlatformCodeStub { explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {} // The profile entry hook function is not allowed to cause a GC. - virtual bool SometimesSetsUpAFrame() { return false; } + virtual bool SometimesSetsUpAFrame() OVERRIDE { return false; } // Generates a call to the entry hook if it's enabled. static void MaybeCallEntryHook(MacroAssembler* masm); @@ -2398,7 +2507,7 @@ class StoreBufferOverflowStub : public PlatformCodeStub { } static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); - virtual bool SometimesSetsUpAFrame() { return false; } + virtual bool SometimesSetsUpAFrame() OVERRIDE { return false; } private: bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); } @@ -2419,6 +2528,15 @@ class SubStringStub : public PlatformCodeStub { }; +class ToNumberStub FINAL : public PlatformCodeStub { + public: + explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {} + + DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber); + DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub); +}; + + class StringCompareStub : public PlatformCodeStub { public: explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {} diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc index 0998685a9f..627e8362e6 100644 --- a/deps/v8/src/codegen.cc +++ b/deps/v8/src/codegen.cc @@ -180,9 +180,7 @@ void CodeGenerator::PrintCode(Handle code, CompilationInfo* info) { Handle