summaryrefslogtreecommitdiff
path: root/deps/v8/test
diff options
context:
space:
mode:
authorChris Dickinson <christopher.s.dickinson@gmail.com>2015-05-05 13:48:55 -0700
committerRod Vagg <rod@vagg.org>2015-08-04 11:56:09 -0700
commitd58e780504bdba6c5897c48428fd984c5b5f96fe (patch)
tree033f1568ae3f9f077aceb843b42eb1ed1739ce0f /deps/v8/test
parent21d31c08e7d0b6865e52452750b20b05e6dca443 (diff)
downloadnode-new-d58e780504bdba6c5897c48428fd984c5b5f96fe.tar.gz
deps: update v8 to 4.3.61.21
* @indutny's SealHandleScope patch (484bebc38319fc7c622478037922ad73b2edcbf9) has been cherry picked onto the top of V8 to make it compile. * There's some test breakage in contextify. * This was merged at the request of the TC. PR-URL: https://github.com/iojs/io.js/pull/1632
Diffstat (limited to 'deps/v8/test')
-rw-r--r--deps/v8/test/cctest/cctest.gyp6
-rw-r--r--deps/v8/test/cctest/cctest.h3
-rw-r--r--deps/v8/test/cctest/cctest.status73
-rw-r--r--deps/v8/test/cctest/compiler/call-tester.h15
-rw-r--r--deps/v8/test/cctest/compiler/function-tester.h22
-rw-r--r--deps/v8/test/cctest/compiler/simplified-graph-builder.cc2
-rw-r--r--deps/v8/test/cctest/compiler/test-codegen-deopt.cc28
-rw-r--r--deps/v8/test/cctest/compiler/test-control-reducer.cc53
-rw-r--r--deps/v8/test/cctest/compiler/test-instruction.cc55
-rw-r--r--deps/v8/test/cctest/compiler/test-js-typed-lowering.cc85
-rw-r--r--deps/v8/test/cctest/compiler/test-jump-threading.cc16
-rw-r--r--deps/v8/test/cctest/compiler/test-linkage.cc23
-rw-r--r--deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc11
-rw-r--r--deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc1
-rw-r--r--deps/v8/test/cctest/compiler/test-node-algorithm.cc40
-rw-r--r--deps/v8/test/cctest/compiler/test-node.cc627
-rw-r--r--deps/v8/test/cctest/compiler/test-osr.cc111
-rw-r--r--deps/v8/test/cctest/compiler/test-pipeline.cc8
-rw-r--r--deps/v8/test/cctest/compiler/test-run-inlining.cc99
-rw-r--r--deps/v8/test/cctest/compiler/test-run-intrinsics.cc279
-rw-r--r--deps/v8/test/cctest/compiler/test-run-jsexceptions.cc139
-rw-r--r--deps/v8/test/cctest/compiler/test-run-jsops.cc2
-rw-r--r--deps/v8/test/cctest/compiler/test-run-machops.cc104
-rw-r--r--deps/v8/test/cctest/compiler/test-run-stubs.cc106
-rw-r--r--deps/v8/test/cctest/compiler/test-run-variables.cc1
-rw-r--r--deps/v8/test/cctest/compiler/test-simplified-lowering.cc107
-rw-r--r--deps/v8/test/cctest/test-accessors.cc83
-rw-r--r--deps/v8/test/cctest/test-alloc.cc4
-rw-r--r--deps/v8/test/cctest/test-api-interceptors.cc239
-rw-r--r--deps/v8/test/cctest/test-api.cc1068
-rw-r--r--deps/v8/test/cctest/test-array-list.cc41
-rw-r--r--deps/v8/test/cctest/test-assembler-arm64.cc170
-rw-r--r--deps/v8/test/cctest/test-assembler-ia32.cc1
-rw-r--r--deps/v8/test/cctest/test-assembler-mips64.cc4
-rw-r--r--deps/v8/test/cctest/test-assembler-x64.cc1
-rw-r--r--deps/v8/test/cctest/test-assembler-x87.cc1
-rw-r--r--deps/v8/test/cctest/test-compiler.cc2
-rw-r--r--deps/v8/test/cctest/test-constantpool.cc3
-rw-r--r--deps/v8/test/cctest/test-conversions.cc55
-rw-r--r--deps/v8/test/cctest/test-cpu-profiler.cc519
-rw-r--r--deps/v8/test/cctest/test-date.cc1
-rw-r--r--deps/v8/test/cctest/test-debug.cc61
-rw-r--r--deps/v8/test/cctest/test-decls.cc117
-rw-r--r--deps/v8/test/cctest/test-disasm-arm.cc1
-rw-r--r--deps/v8/test/cctest/test-disasm-ia32.cc14
-rw-r--r--deps/v8/test/cctest/test-disasm-mips.cc1
-rw-r--r--deps/v8/test/cctest/test-disasm-mips64.cc1
-rw-r--r--deps/v8/test/cctest/test-disasm-ppc.cc1
-rw-r--r--deps/v8/test/cctest/test-disasm-x64.cc21
-rw-r--r--deps/v8/test/cctest/test-disasm-x87.cc1
-rw-r--r--deps/v8/test/cctest/test-feedback-vector.cc59
-rw-r--r--deps/v8/test/cctest/test-func-name-inference.cc8
-rw-r--r--deps/v8/test/cctest/test-heap-profiler.cc224
-rw-r--r--deps/v8/test/cctest/test-heap.cc344
-rw-r--r--deps/v8/test/cctest/test-javascript-arm64.cc1
-rw-r--r--deps/v8/test/cctest/test-js-arm64-variables.cc1
-rw-r--r--deps/v8/test/cctest/test-lockers.cc1
-rw-r--r--deps/v8/test/cctest/test-log.cc2
-rw-r--r--deps/v8/test/cctest/test-macro-assembler-ia32.cc1
-rw-r--r--deps/v8/test/cctest/test-macro-assembler-x64.cc35
-rw-r--r--deps/v8/test/cctest/test-macro-assembler-x87.cc1
-rw-r--r--deps/v8/test/cctest/test-mark-compact.cc11
-rw-r--r--deps/v8/test/cctest/test-mementos.cc17
-rw-r--r--deps/v8/test/cctest/test-migrations.cc232
-rw-r--r--deps/v8/test/cctest/test-parsing.cc536
-rw-r--r--deps/v8/test/cctest/test-serialize.cc975
-rw-r--r--deps/v8/test/cctest/test-spaces.cc30
-rw-r--r--deps/v8/test/cctest/test-strings.cc2
-rw-r--r--deps/v8/test/cctest/test-thread-termination.cc65
-rw-r--r--deps/v8/test/cctest/test-transitions.cc197
-rw-r--r--deps/v8/test/cctest/test-typedarrays.cc81
-rw-r--r--deps/v8/test/cctest/test-unboxed-doubles.cc470
-rw-r--r--deps/v8/test/cctest/test-weakmaps.cc7
-rw-r--r--deps/v8/test/cctest/test-weaksets.cc7
-rw-r--r--deps/v8/test/cctest/test-weaktypedarrays.cc61
-rw-r--r--deps/v8/test/js-perf-test/JSTests.json2
-rw-r--r--deps/v8/test/message/class-constructor-accessor.js (renamed from deps/v8/test/mjsunit/harmony/disable-harmony-string.js)9
-rw-r--r--deps/v8/test/message/class-constructor-accessor.out7
-rw-r--r--deps/v8/test/message/class-constructor-generator.js10
-rw-r--r--deps/v8/test/message/class-constructor-generator.out7
-rw-r--r--deps/v8/test/message/export-duplicate-as.js9
-rw-r--r--deps/v8/test/message/export-duplicate-as.out7
-rw-r--r--deps/v8/test/message/export-duplicate-default.js8
-rw-r--r--deps/v8/test/message/export-duplicate-default.out7
-rw-r--r--deps/v8/test/message/export-duplicate.js9
-rw-r--r--deps/v8/test/message/export-duplicate.out7
-rw-r--r--deps/v8/test/message/import-as-eval.js7
-rw-r--r--deps/v8/test/message/import-as-eval.out7
-rw-r--r--deps/v8/test/message/import-as-redeclaration.js8
-rw-r--r--deps/v8/test/message/import-as-redeclaration.out7
-rw-r--r--deps/v8/test/message/import-as-reserved-word.js7
-rw-r--r--deps/v8/test/message/import-as-reserved-word.out7
-rw-r--r--deps/v8/test/message/import-eval.js7
-rw-r--r--deps/v8/test/message/import-eval.out7
-rw-r--r--deps/v8/test/message/import-redeclaration.js8
-rw-r--r--deps/v8/test/message/import-redeclaration.out7
-rw-r--r--deps/v8/test/message/import-reserved-word.js7
-rw-r--r--deps/v8/test/message/import-reserved-word.out7
-rw-r--r--deps/v8/test/message/testcfg.py3
-rw-r--r--deps/v8/test/message/unterminated-arg-list.js7
-rw-r--r--deps/v8/test/message/unterminated-arg-list.out8
-rw-r--r--deps/v8/test/mjsunit/asm/construct-double.js33
-rw-r--r--deps/v8/test/mjsunit/asm/double-hi.js40
-rw-r--r--deps/v8/test/mjsunit/asm/double-lo.js40
-rw-r--r--deps/v8/test/mjsunit/asm/if-cloning.js34
-rw-r--r--deps/v8/test/mjsunit/asm/math-clz32.js31
-rw-r--r--deps/v8/test/mjsunit/bugs/harmony/debug-blockscopes.js2
-rw-r--r--deps/v8/test/mjsunit/compiler/deopt-tonumber-binop.js40
-rw-r--r--deps/v8/test/mjsunit/compiler/eager-deopt-simple.js18
-rw-r--r--deps/v8/test/mjsunit/compiler/osr-forin-nested.js35
-rw-r--r--deps/v8/test/mjsunit/compiler/osr-infinite.js78
-rw-r--r--deps/v8/test/mjsunit/compiler/osr-labeled.js47
-rw-r--r--deps/v8/test/mjsunit/compiler/osr-literals-adapted.js56
-rw-r--r--deps/v8/test/mjsunit/compiler/osr-literals.js56
-rw-r--r--deps/v8/test/mjsunit/compiler/regress-463056.js9
-rw-r--r--deps/v8/test/mjsunit/compiler/regress-468727.js16
-rw-r--r--deps/v8/test/mjsunit/compiler/regress-469089.js16
-rw-r--r--deps/v8/test/mjsunit/compiler/truncating-store-deopt.js28
-rw-r--r--deps/v8/test/mjsunit/compiler/try-deopt.js56
-rw-r--r--deps/v8/test/mjsunit/constant-folding-2.js2
-rw-r--r--deps/v8/test/mjsunit/debug-allscopes-on-debugger.js58
-rw-r--r--deps/v8/test/mjsunit/debug-liveedit-check-stack.js6
-rw-r--r--deps/v8/test/mjsunit/debug-references.js5
-rw-r--r--deps/v8/test/mjsunit/debug-scopes.js24
-rw-r--r--deps/v8/test/mjsunit/debug-set-variable-value.js15
-rw-r--r--deps/v8/test/mjsunit/debug-sourceinfo.js618
-rw-r--r--deps/v8/test/mjsunit/debug-step-turbofan.js2
-rw-r--r--deps/v8/test/mjsunit/debug-stepframe-clearing.js97
-rw-r--r--deps/v8/test/mjsunit/debug-stepin-foreach.js8
-rw-r--r--deps/v8/test/mjsunit/es6/block-conflicts.js (renamed from deps/v8/test/mjsunit/harmony/block-conflicts.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/block-const-assign.js160
-rw-r--r--deps/v8/test/mjsunit/es6/block-early-errors.js (renamed from deps/v8/test/mjsunit/harmony/block-early-errors.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/block-for.js (renamed from deps/v8/test/mjsunit/harmony/block-for.js)5
-rw-r--r--deps/v8/test/mjsunit/es6/block-leave.js (renamed from deps/v8/test/mjsunit/harmony/block-leave.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/block-let-crankshaft.js (renamed from deps/v8/test/mjsunit/harmony/block-let-crankshaft.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/block-let-declaration.js (renamed from deps/v8/test/mjsunit/harmony/block-let-declaration.js)26
-rw-r--r--deps/v8/test/mjsunit/es6/block-let-semantics.js (renamed from deps/v8/test/mjsunit/harmony/block-let-semantics.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/block-non-strict-errors.js (renamed from deps/v8/test/mjsunit/harmony/block-non-strict-errors.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/block-scoping.js (renamed from deps/v8/test/mjsunit/harmony/block-scoping.js)8
-rw-r--r--deps/v8/test/mjsunit/es6/collections.js122
-rw-r--r--deps/v8/test/mjsunit/es6/debug-blockscopes.js (renamed from deps/v8/test/mjsunit/harmony/debug-blockscopes.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/debug-evaluate-blockscopes.js (renamed from deps/v8/test/mjsunit/harmony/debug-evaluate-blockscopes.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/debug-function-scopes.js (renamed from deps/v8/test/mjsunit/harmony/debug-function-scopes.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js32
-rw-r--r--deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js29
-rw-r--r--deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js30
-rw-r--r--deps/v8/test/mjsunit/es6/debug-stepin-promises.js65
-rw-r--r--deps/v8/test/mjsunit/es6/empty-for.js (renamed from deps/v8/test/mjsunit/harmony/empty-for.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/function-length-configurable.js119
-rw-r--r--deps/v8/test/mjsunit/es6/function-name-configurable.js115
-rw-r--r--deps/v8/test/mjsunit/es6/generators-debug-liveedit.js4
-rw-r--r--deps/v8/test/mjsunit/es6/generators-objects.js2
-rw-r--r--deps/v8/test/mjsunit/es6/indexed-integer-exotics.js63
-rw-r--r--deps/v8/test/mjsunit/es6/iteration-semantics.js32
-rw-r--r--deps/v8/test/mjsunit/es6/iteration-syntax.js2
-rw-r--r--deps/v8/test/mjsunit/es6/map-minus-zero.js51
-rw-r--r--deps/v8/test/mjsunit/es6/promises.js200
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-2243.js (renamed from deps/v8/test/mjsunit/harmony/regress/regress-2243.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-2322.js (renamed from deps/v8/test/mjsunit/harmony/regress/regress-2322.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-2506.js (renamed from deps/v8/test/mjsunit/regress/regress-2506.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-2858.js (renamed from deps/v8/test/mjsunit/harmony/regress/regress-2858.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-3426.js (renamed from deps/v8/test/mjsunit/harmony/regress/regress-3426.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-347906.js (renamed from deps/v8/test/mjsunit/regress/regress-347906.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-3683.js (renamed from deps/v8/test/mjsunit/harmony/regress/regress-3683.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-3741.js (renamed from deps/v8/test/mjsunit/harmony/regress/regress-3741.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-3938.js8
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-411237.js (renamed from deps/v8/test/mjsunit/regress/regress-411237.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-468661.js75
-rw-r--r--deps/v8/test/mjsunit/es6/regress/regress-474783.js24
-rw-r--r--deps/v8/test/mjsunit/es6/set-minus-zero.js51
-rw-r--r--deps/v8/test/mjsunit/es6/string-codepointat.js (renamed from deps/v8/test/mjsunit/harmony/string-codepointat.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/string-endswith.js (renamed from deps/v8/test/mjsunit/harmony/string-endswith.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/string-fromcodepoint.js (renamed from deps/v8/test/mjsunit/harmony/string-fromcodepoint.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/string-includes.js (renamed from deps/v8/test/mjsunit/harmony/string-includes.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/string-raw.js (renamed from deps/v8/test/mjsunit/harmony/string-raw.js)38
-rw-r--r--deps/v8/test/mjsunit/es6/string-repeat.js (renamed from deps/v8/test/mjsunit/harmony/string-repeat.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/string-startswith.js (renamed from deps/v8/test/mjsunit/harmony/string-startswith.js)2
-rw-r--r--deps/v8/test/mjsunit/es6/symbols.js5
-rw-r--r--deps/v8/test/mjsunit/es6/templates.js (renamed from deps/v8/test/mjsunit/harmony/templates.js)165
-rw-r--r--deps/v8/test/mjsunit/es7/object-observe.js67
-rw-r--r--deps/v8/test/mjsunit/function-length-accessor.js2
-rw-r--r--deps/v8/test/mjsunit/function-prototype.js3
-rw-r--r--deps/v8/test/mjsunit/harmony/block-const-assign.js137
-rw-r--r--deps/v8/test/mjsunit/harmony/computed-property-names-classes.js131
-rw-r--r--deps/v8/test/mjsunit/harmony/computed-property-names.js23
-rw-r--r--deps/v8/test/mjsunit/harmony/module-linking.js2
-rw-r--r--deps/v8/test/mjsunit/harmony/module-resolution.js2
-rw-r--r--deps/v8/test/mjsunit/harmony/private.js5
-rw-r--r--deps/v8/test/mjsunit/harmony/reflect-apply.js212
-rw-r--r--deps/v8/test/mjsunit/harmony/reflect-construct.js277
-rw-r--r--deps/v8/test/mjsunit/harmony/regress/regress-3501.js (renamed from deps/v8/test/mjsunit/regress/regress-3501.js)0
-rw-r--r--deps/v8/test/mjsunit/harmony/regress/regress-crbug-448730.js (renamed from deps/v8/test/mjsunit/regress/regress-crbug-448730.js)0
-rw-r--r--deps/v8/test/mjsunit/harmony/regress/regress-crbug-451770.js (renamed from deps/v8/test/mjsunit/regress/regress-crbug-451770.js)0
-rw-r--r--deps/v8/test/mjsunit/harmony/regress/regress-crbug-461520.js18
-rw-r--r--deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671-null.js16
-rw-r--r--deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671.js16
-rw-r--r--deps/v8/test/mjsunit/harmony/rest-params.js34
-rw-r--r--deps/v8/test/mjsunit/harmony/typedarrays.js4
-rw-r--r--deps/v8/test/mjsunit/json2.js5
-rw-r--r--deps/v8/test/mjsunit/mjsunit.status48
-rw-r--r--deps/v8/test/mjsunit/regexp-stack-overflow.js18
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1530.js8
-rw-r--r--deps/v8/test/mjsunit/regress/regress-270142.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-330046.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-3960.js36
-rw-r--r--deps/v8/test/mjsunit/regress/regress-3969.js36
-rw-r--r--deps/v8/test/mjsunit/regress/regress-3976.js80
-rw-r--r--deps/v8/test/mjsunit/regress/regress-3985.js45
-rw-r--r--deps/v8/test/mjsunit/regress/regress-4023.js67
-rw-r--r--deps/v8/test/mjsunit/regress/regress-4027.js60
-rw-r--r--deps/v8/test/mjsunit/regress/regress-430201b.js (renamed from deps/v8/test/preparser/strict-const.js)22
-rw-r--r--deps/v8/test/mjsunit/regress/regress-460937.js19
-rw-r--r--deps/v8/test/mjsunit/regress/regress-463028.js18
-rw-r--r--deps/v8/test/mjsunit/regress/regress-469605.js43
-rw-r--r--deps/v8/test/mjsunit/regress/regress-470804.js53
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-385002.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-401915.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-465564.js7
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-467047.js17
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-467531.js25
-rw-r--r--deps/v8/test/mjsunit/regress/regress-filter-contexts.js14
-rw-r--r--deps/v8/test/mjsunit/regress/regress-function-length-strict.js2
-rw-r--r--deps/v8/test/mjsunit/regress/string-compare-memcmp.js2
-rw-r--r--deps/v8/test/mjsunit/stack-traces.js34
-rw-r--r--deps/v8/test/mjsunit/strict-mode.js16
-rw-r--r--deps/v8/test/mjsunit/string-concat.js14
-rw-r--r--deps/v8/test/mjsunit/string-index.js16
-rw-r--r--deps/v8/test/mjsunit/strong/arrays.js12
-rw-r--r--deps/v8/test/mjsunit/strong/classes.js47
-rw-r--r--deps/v8/test/mjsunit/strong/declaration-after-use.js258
-rw-r--r--deps/v8/test/mjsunit/strong/functions.js68
-rw-r--r--deps/v8/test/mozilla/mozilla.status13
-rw-r--r--deps/v8/test/preparser/strict-function-statement.pyt109
-rw-r--r--deps/v8/test/test262-es6/test262-es6.status324
-rw-r--r--deps/v8/test/test262-es6/testcfg.py3
-rw-r--r--deps/v8/test/test262/test262.status127
-rw-r--r--deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc15
-rw-r--r--deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc137
-rw-r--r--deps/v8/test/unittests/compiler/change-lowering-unittest.cc456
-rw-r--r--deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc64
-rw-r--r--deps/v8/test/unittests/compiler/common-operator-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/control-equivalence-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc80
-rw-r--r--deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc44
-rw-r--r--deps/v8/test/unittests/compiler/instruction-selector-unittest.cc49
-rw-r--r--deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc121
-rw-r--r--deps/v8/test/unittests/compiler/instruction-sequence-unittest.h52
-rw-r--r--deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc125
-rw-r--r--deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc148
-rw-r--r--deps/v8/test/unittests/compiler/js-operator-unittest.cc83
-rw-r--r--deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc70
-rw-r--r--deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc373
-rw-r--r--deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc149
-rw-r--r--deps/v8/test/unittests/compiler/machine-operator-unittest.cc44
-rw-r--r--deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc15
-rw-r--r--deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc36
-rw-r--r--deps/v8/test/unittests/compiler/move-optimizer-unittest.cc53
-rw-r--r--deps/v8/test/unittests/compiler/node-properties-unittest.cc72
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.cc39
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.h16
-rw-r--r--deps/v8/test/unittests/compiler/node-unittest.cc6
-rw-r--r--deps/v8/test/unittests/compiler/opcodes-unittest.cc25
-rw-r--r--deps/v8/test/unittests/compiler/ppc/OWNERS3
-rw-r--r--deps/v8/test/unittests/compiler/register-allocator-unittest.cc106
-rw-r--r--deps/v8/test/unittests/compiler/schedule-unittest.cc33
-rw-r--r--deps/v8/test/unittests/compiler/scheduler-unittest.cc303
-rw-r--r--deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc33
-rw-r--r--deps/v8/test/unittests/compiler/simplified-operator-unittest.cc1
-rw-r--r--deps/v8/test/unittests/compiler/state-values-utils-unittest.cc149
-rw-r--r--deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc34
-rw-r--r--deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc52
-rw-r--r--deps/v8/test/unittests/unittests.gyp2
-rw-r--r--deps/v8/test/webkit/fast/js/kde/prototype_length-expected.txt2
-rw-r--r--deps/v8/test/webkit/fast/js/kde/prototype_length.js2
-rw-r--r--deps/v8/test/webkit/webkit.status6
275 files changed, 12207 insertions, 4349 deletions
diff --git a/deps/v8/test/cctest/cctest.gyp b/deps/v8/test/cctest/cctest.gyp
index 1b851e44cf..60536a4420 100644
--- a/deps/v8/test/cctest/cctest.gyp
+++ b/deps/v8/test/cctest/cctest.gyp
@@ -86,6 +86,7 @@
'compiler/test-run-machops.cc',
'compiler/test-run-properties.cc',
'compiler/test-run-stackcheck.cc',
+ 'compiler/test-run-stubs.cc',
'compiler/test-run-variables.cc',
'compiler/test-simplified-lowering.cc',
'cctest.cc',
@@ -99,6 +100,7 @@
'test-api.cc',
'test-api.h',
'test-api-interceptors.cc',
+ 'test-array-list.cc',
'test-ast.cc',
'test-atomicops.cc',
'test-bignum.cc',
@@ -156,6 +158,7 @@
'test-thread-termination.cc',
'test-threads.cc',
'test-transitions.cc',
+ 'test-typedarrays.cc',
'test-types.cc',
'test-unbound-queue.cc',
'test-unboxed-doubles.cc',
@@ -270,6 +273,9 @@
},
},
}],
+ ['OS=="aix"', {
+ 'ldflags': [ '-Wl,-bbigtoc' ],
+ }],
['component=="shared_library"', {
# cctest can't be built against a shared library, so we need to
# depend on the underlying static target in that case.
diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h
index e111438cdf..08877c8268 100644
--- a/deps/v8/test/cctest/cctest.h
+++ b/deps/v8/test/cctest/cctest.h
@@ -558,6 +558,9 @@ static inline void SimulateIncrementalMarking(i::Heap* heap) {
CHECK(marking->IsMarking());
while (!marking->IsComplete()) {
marking->Step(i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
+ if (marking->IsReadyToOverApproximateWeakClosure()) {
+ marking->MarkObjectGroups();
+ }
}
CHECK(marking->IsComplete());
}
diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status
index c58b1f0204..d7f72495ae 100644
--- a/deps/v8/test/cctest/cctest.status
+++ b/deps/v8/test/cctest/cctest.status
@@ -64,9 +64,6 @@
# are actually 13 * 38 * 5 * 128 = 316160 individual tests hidden here.
'test-parsing/ParserSync': [PASS, NO_VARIANTS],
- # Modules are busted
- 'test-parsing/ExportsMaybeAssigned': [SKIP],
-
# This tests only the type system, so there is no point in running several
# variants.
'test-hydrogen-types/*': [PASS, NO_VARIANTS],
@@ -75,13 +72,25 @@
# The cpu profiler tests are notoriously flaky.
# BUG(2999). (test/cpu-profiler/CollectCpuProfile)
# BUG(3287). (test-cpu-profiler/SampleWhenFrameIsNotSetup)
- 'test-cpu-profiler/*': [PASS, FLAKY],
- 'test-cpu-profiler/*': [SKIP],
+ 'test-cpu-profiler/CollectCpuProfile': [SKIP],
+ 'test-cpu-profiler/CollectCpuProfileSamples': [SKIP],
+ 'test-cpu-profiler/FunctionApplySample': [SKIP],
+ 'test-cpu-profiler/FunctionCallSample': [SKIP],
+ 'test-cpu-profiler/SampleWhenFrameIsNotSetup': [SKIP],
+ 'test-cpu-profiler/HotDeoptNoFrameEntry': [SKIP],
+ 'test-cpu-profiler/BoundFunctionCall': [SKIP],
+ 'test-cpu-profiler/CpuProfileDeepStack': [SKIP],
+ 'test-cpu-profiler/JsNativeJsSample': [SKIP],
+ 'test-cpu-profiler/JsNativeJsRuntimeJsSample': [SKIP],
+ 'test-cpu-profiler/JsNative1JsNative2JsSample': [SKIP],
# BUG(3525). Test crashes flakily.
'test-debug/RecursiveBreakpoints': [PASS, FLAKY],
'test-debug/RecursiveBreakpointsGlobal': [PASS, FLAKY],
+ # Fails sometimes.
+ 'test-debug/ProcessDebugMessagesThreaded': [PASS, FLAKY],
+
##############################################################################
# TurboFan compiler failures.
@@ -94,14 +103,15 @@
# BUG(3742).
'test-mark-compact/MarkCompactCollector': [PASS, ['arch==arm', NO_VARIANTS]],
- # TODO(jarin/mstarzinger): Investigate debugger issues with TurboFan.
- 'test-debug/DebugStepNatives': [PASS, NO_VARIANTS],
- 'test-debug/DebugStepFunctionApply': [PASS, NO_VARIANTS],
- 'test-debug/DebugStepFunctionCall': [PASS, NO_VARIANTS],
+ # TODO(jarin): Cannot lazy-deoptimize from conversions before comparisons.
+ 'test-js-typed-lowering/OrderCompareEffects': [SKIP],
# TODO(jochen): Reenable after we removed the CHECK() from the marking queue.
'test-mark-compact/MarkingDeque': [SKIP],
+ 'test-heap/TestInternalWeakLists': [PASS, ['arch==arm', NO_VARIANTS]],
+ 'test-heap/TestInternalWeakListsTraverseWithGC': [PASS, ['arch==arm', NO_VARIANTS]],
+
############################################################################
# Slow tests.
'test-api/Threading1': [PASS, ['mode == debug', SLOW]],
@@ -114,15 +124,14 @@
##############################################################################
['arch == arm64', {
+ 'test-cpu-profiler/CollectDeoptEvents': [PASS, FAIL],
+
'test-api/Bug618': [PASS],
# BUG(v8:3385).
'test-serialize/DeserializeFromSecondSerialization': [PASS, FAIL],
'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [PASS, FAIL],
- # BUG(v8:2999).
- 'test-cpu-profiler/CollectCpuProfile': [PASS, FAIL],
-
# BUG(v8:3154).
'test-heap/ReleaseOverReservedPages': [PASS, FAIL],
@@ -180,18 +189,12 @@
##############################################################################
['system == windows', {
- # BUG(2999).
- 'test-cpu-profiler/CollectCpuProfile': [PASS, FAIL],
-
# BUG(3005).
'test-alloc/CodeRange': [PASS, FAIL],
# BUG(3331). Fails on windows.
'test-heap/NoWeakHashTableLeakWithIncrementalMarking': [SKIP],
- # BUG(v8:3433). Crashes on windows.
- 'test-cpu-profiler/FunctionApplySample': [SKIP],
-
}], # 'system == windows'
##############################################################################
@@ -206,6 +209,8 @@
##############################################################################
['arch == arm', {
+ 'test-cpu-profiler/CollectDeoptEvents': [PASS, FAIL],
+
# BUG(355): Test crashes on ARM.
'test-log/ProfLazyMode': [SKIP],
@@ -229,20 +234,13 @@
##############################################################################
['arch == mipsel or arch == mips', {
-
- # BUG(2657): Test sometimes times out on MIPS simulator.
- 'test-thread-termination/TerminateMultipleV8ThreadsDefaultIsolate': [PASS, TIMEOUT],
+ 'test-cpu-profiler/CollectDeoptEvents': [PASS, FAIL],
# BUG(1075): Unresolved crashes on MIPS also.
'test-serialize/Deserialize': [SKIP],
'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [SKIP],
'test-serialize/DeserializeAndRunScript2': [SKIP],
'test-serialize/DeserializeFromSecondSerialization': [SKIP],
-
- # Test requires turbofan:
- 'test-simplified-lowering/LowerStringOps_to_call_and_compare': [SKIP],
- 'codegen-tester/CompareWrapper': [SKIP],
- 'codegen-tester/ParametersEqual': [SKIP],
}], # 'arch == mipsel or arch == mips'
##############################################################################
@@ -260,9 +258,7 @@
##############################################################################
['arch == mips64el', {
-
- # BUG(2657): Test sometimes times out on MIPS simulator.
- 'test-thread-termination/TerminateMultipleV8ThreadsDefaultIsolate': [PASS, TIMEOUT],
+ 'test-cpu-profiler/CollectDeoptEvents': [PASS, FAIL],
# BUG(v8:3154).
'test-heap/ReleaseOverReservedPages': [PASS, FAIL],
@@ -272,11 +268,6 @@
'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [SKIP],
'test-serialize/DeserializeAndRunScript2': [SKIP],
'test-serialize/DeserializeFromSecondSerialization': [SKIP],
-
- # Test requires turbofan:
- 'test-simplified-lowering/LowerStringOps_to_call_and_compare': [SKIP],
- 'codegen-tester/CompareWrapper': [SKIP],
- 'codegen-tester/ParametersEqual': [SKIP],
}], # 'arch == mips64el'
##############################################################################
@@ -286,6 +277,7 @@
'codegen-tester/CompareWrapper': [SKIP],
'codegen-tester/ParametersEqual': [SKIP],
'test-simplified-lowering/LowerStringOps_to_call_and_compare': [SKIP],
+ 'test-serialize/SerializeInternalReference': [FAIL],
}], # 'arch == x87'
##############################################################################
@@ -402,8 +394,13 @@
}], # 'arch == nacl_ia32 or arch == nacl_x64'
-['arch == ppc64', {
- #issue 2857
- 'test-log/EquivalenceOfLoggingAndTraversal' : [SKIP],
-}], # 'arch == ppc64'
+##############################################################################
+['arch == ppc and simulator_run == True or arch == ppc64 and simulator_run == True', {
+
+ # Pass but take too long with the simulator.
+ 'test-api/Threading1': [PASS, SLOW],
+ 'test-api/Threading2': [PASS, SLOW],
+ 'test-api/ExternalArrays': [PASS, SLOW],
+
+}], # 'arch == ppc64 and simulator_run == True'
]
diff --git a/deps/v8/test/cctest/compiler/call-tester.h b/deps/v8/test/cctest/compiler/call-tester.h
index ffafaf0803..30bbe1e8aa 100644
--- a/deps/v8/test/cctest/compiler/call-tester.h
+++ b/deps/v8/test/cctest/compiler/call-tester.h
@@ -128,6 +128,20 @@ struct ParameterTraits<T*> {
static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
};
+// Additional template specialization required for mips64 to sign-extend
+// parameters defined by calling convention.
+template <>
+struct ParameterTraits<int32_t> {
+ static int64_t Cast(int32_t r) { return static_cast<int64_t>(r); }
+};
+
+template <>
+struct ParameterTraits<uint32_t> {
+ static int64_t Cast(uint32_t r) {
+ return static_cast<int64_t>(static_cast<int32_t>(r));
+ }
+};
+
class CallHelper {
public:
explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
@@ -214,6 +228,7 @@ class CallHelper {
return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
}
+
template <typename R, typename F>
R DoCall(F* f) {
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
diff --git a/deps/v8/test/cctest/compiler/function-tester.h b/deps/v8/test/cctest/compiler/function-tester.h
index 440043cb94..20efd1e304 100644
--- a/deps/v8/test/cctest/compiler/function-tester.h
+++ b/deps/v8/test/cctest/compiler/function-tester.h
@@ -34,6 +34,7 @@ class FunctionTester : public InitializedHandleScope {
flags_(flags) {
Compile(function);
const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
+ CompilationInfo::kBuiltinInliningEnabled |
CompilationInfo::kInliningEnabled |
CompilationInfo::kTypingEnabled;
CHECK_EQ(0u, flags_ & ~supported_flags);
@@ -60,7 +61,6 @@ class FunctionTester : public InitializedHandleScope {
CHECK(isolate->has_pending_exception());
CHECK(try_catch.HasCaught());
CHECK(no_result.is_null());
- // TODO(mstarzinger): Temporary workaround for issue chromium:362388.
isolate->OptionalRescheduleException(true);
}
@@ -71,10 +71,8 @@ class FunctionTester : public InitializedHandleScope {
CHECK(isolate->has_pending_exception());
CHECK(try_catch.HasCaught());
CHECK(no_result.is_null());
- // TODO(mstarzinger): Calling OptionalRescheduleException is a dirty hack,
- // it's the only way to make Message() not to assert because an external
- // exception has been caught by the try_catch.
isolate->OptionalRescheduleException(true);
+ CHECK(!try_catch.Message().IsEmpty());
return try_catch.Message();
}
@@ -152,9 +150,11 @@ class FunctionTester : public InitializedHandleScope {
Handle<JSFunction> Compile(Handle<JSFunction> function) {
// TODO(titzer): make this method private.
#if V8_TURBOFAN_TARGET
- CompilationInfoWithZone info(function);
+ Zone zone;
+ ParseInfo parse_info(&zone, function);
+ CompilationInfo info(&parse_info);
- CHECK(Parser::ParseStatic(&info));
+ CHECK(Parser::ParseStatic(info.parse_info()));
info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
if (flags_ & CompilationInfo::kContextSpecializing) {
info.MarkAsContextSpecializing();
@@ -165,7 +165,7 @@ class FunctionTester : public InitializedHandleScope {
if (flags_ & CompilationInfo::kTypingEnabled) {
info.MarkAsTypingEnabled();
}
- CHECK(Compiler::Analyze(&info));
+ CHECK(Compiler::Analyze(info.parse_info()));
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Pipeline pipeline(&info);
@@ -208,12 +208,14 @@ class FunctionTester : public InitializedHandleScope {
// and replace the JSFunction's code with the result.
Handle<JSFunction> CompileGraph(Graph* graph) {
CHECK(Pipeline::SupportedTarget());
- CompilationInfoWithZone info(function);
+ Zone zone;
+ ParseInfo parse_info(&zone, function);
+ CompilationInfo info(&parse_info);
- CHECK(Parser::ParseStatic(&info));
+ CHECK(Parser::ParseStatic(info.parse_info()));
info.SetOptimizing(BailoutId::None(),
Handle<Code>(function->shared()->code()));
- CHECK(Compiler::Analyze(&info));
+ CHECK(Compiler::Analyze(info.parse_info()));
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
diff --git a/deps/v8/test/cctest/compiler/simplified-graph-builder.cc b/deps/v8/test/cctest/compiler/simplified-graph-builder.cc
index e65ba2e0df..6afdc0a211 100644
--- a/deps/v8/test/cctest/compiler/simplified-graph-builder.cc
+++ b/deps/v8/test/cctest/compiler/simplified-graph-builder.cc
@@ -48,7 +48,7 @@ Node* SimplifiedGraphBuilder::MakeNode(const Operator* op,
DCHECK(op->ValueInputCount() == value_input_count);
DCHECK(!OperatorProperties::HasContextInput(op));
- DCHECK(!OperatorProperties::HasFrameStateInput(op));
+ DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
bool has_control = op->ControlInputCount() == 1;
bool has_effect = op->EffectInputCount() == 1;
diff --git a/deps/v8/test/cctest/compiler/test-codegen-deopt.cc b/deps/v8/test/cctest/compiler/test-codegen-deopt.cc
index a90e4025dc..0b59308216 100644
--- a/deps/v8/test/cctest/compiler/test-codegen-deopt.cc
+++ b/deps/v8/test/cctest/compiler/test-codegen-deopt.cc
@@ -44,11 +44,14 @@ class DeoptCodegenTester {
explicit DeoptCodegenTester(HandleAndZoneScope* scope, const char* src)
: scope_(scope),
function(NewFunction(src)),
- info(function, scope->main_zone()),
- bailout_id(-1) {
- CHECK(Parser::ParseStatic(&info));
+ parse_info(scope->main_zone(), function),
+ info(&parse_info),
+ bailout_id(-1),
+ tagged_type(1, kMachAnyTagged, zone()),
+ empty_types(zone()) {
+ CHECK(Parser::ParseStatic(&parse_info));
info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
- CHECK(Compiler::Analyze(&info));
+ CHECK(Compiler::Analyze(&parse_info));
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
DCHECK(info.shared_info()->has_deoptimization_support());
@@ -76,11 +79,14 @@ class DeoptCodegenTester {
HandleAndZoneScope* scope_;
Handle<JSFunction> function;
+ ParseInfo parse_info;
CompilationInfo info;
BailoutId bailout_id;
Handle<Code> result_code;
TestInstrSeq* code;
Graph* graph;
+ ZoneVector<MachineType> tagged_type;
+ ZoneVector<MachineType> empty_types;
};
@@ -118,9 +124,10 @@ class TrivialDeoptCodegenTester : public DeoptCodegenTester {
m.NewNode(common.HeapConstant(caller_context_constant));
bailout_id = GetCallBailoutId();
- Node* parameters = m.NewNode(common.StateValues(1), m.UndefinedConstant());
- Node* locals = m.NewNode(common.StateValues(0));
- Node* stack = m.NewNode(common.StateValues(0));
+ Node* parameters =
+ m.NewNode(common.TypedStateValues(&tagged_type), m.UndefinedConstant());
+ Node* locals = m.NewNode(common.TypedStateValues(&empty_types));
+ Node* stack = m.NewNode(common.TypedStateValues(&empty_types));
Node* state_node = m.NewNode(
common.FrameState(JS_FRAME, bailout_id,
@@ -233,9 +240,10 @@ class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
Node* context_node = m.NewNode(common.HeapConstant(context_constant));
bailout_id = GetCallBailoutId();
- Node* parameters = m.NewNode(common.StateValues(1), m.UndefinedConstant());
- Node* locals = m.NewNode(common.StateValues(0));
- Node* stack = m.NewNode(common.StateValues(0));
+ Node* parameters =
+ m.NewNode(common.TypedStateValues(&tagged_type), m.UndefinedConstant());
+ Node* locals = m.NewNode(common.TypedStateValues(&empty_types));
+ Node* stack = m.NewNode(common.TypedStateValues(&empty_types));
Node* state_node = m.NewNode(
common.FrameState(JS_FRAME, bailout_id,
diff --git a/deps/v8/test/cctest/compiler/test-control-reducer.cc b/deps/v8/test/cctest/compiler/test-control-reducer.cc
index 827dcfdaa8..c2b225ab00 100644
--- a/deps/v8/test/cctest/compiler/test-control-reducer.cc
+++ b/deps/v8/test/cctest/compiler/test-control-reducer.cc
@@ -8,7 +8,7 @@
#include "src/base/bits.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/control-reducer.h"
-#include "src/compiler/graph-inl.h"
+#include "src/compiler/graph.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
@@ -694,9 +694,9 @@ TEST(CMergeReduce_none1) {
TEST(CMergeReduce_none2) {
ControlReducerTester R;
- Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
- Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
- Node* merge = R.graph.NewNode(R.common.Merge(2), t, f);
+ Node* t1 = R.graph.NewNode(R.common.IfTrue(), R.start);
+ Node* t2 = R.graph.NewNode(R.common.IfTrue(), R.start);
+ Node* merge = R.graph.NewNode(R.common.Merge(2), t1, t2);
R.ReduceMerge(merge, merge);
}
@@ -744,7 +744,7 @@ TEST(CMergeReduce_dead_rm1b) {
ControlReducerTester R;
Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
- Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
+ Node* f = R.graph.NewNode(R.common.IfTrue(), R.start);
for (int i = 0; i < 2; i++) {
Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
for (int j = i + 1; j < 3; j++) {
@@ -1118,7 +1118,7 @@ TEST(CChainedDiamondsReduce_x_false) {
Diamond d2(R, R.zero);
d2.chain(d1);
- R.ReduceMergeIterative(d1.merge, d2.merge);
+ R.ReduceMergeIterative(R.start, d2.merge);
}
@@ -1128,8 +1128,7 @@ TEST(CChainedDiamondsReduce_false_x) {
Diamond d2(R, R.p0);
d2.chain(d1);
- R.ReduceMergeIterative(d2.merge, d2.merge);
- CheckInputs(d2.branch, R.p0, R.start);
+ R.ReduceMergeIterative(R.start, d2.merge);
}
@@ -1190,6 +1189,28 @@ TEST(CNestedDiamonds_xyz) {
}
+TEST(CUnusedDiamond1) {
+ ControlReducerTester R;
+ // if (p0) { } else { }
+ Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start);
+ Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch);
+ Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch);
+ Node* merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
+ R.ReduceMergeIterative(R.start, merge);
+}
+
+
+TEST(CUnusedDiamond2) {
+ ControlReducerTester R;
+ // if (p0) { } else { }
+ Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start);
+ Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch);
+ Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch);
+ Node* merge = R.graph.NewNode(R.common.Merge(2), if_false, if_true);
+ R.ReduceMergeIterative(R.start, merge);
+}
+
+
TEST(CDeadLoop1) {
ControlReducerTester R;
@@ -1329,9 +1350,7 @@ TEST(Return_nested_diamonds1) {
CheckInputs(ret, d1.phi, R.start, d1.merge);
CheckInputs(d1.phi, R.one, R.zero, d1.merge);
- CheckInputs(d1.merge, d2.merge, d3.merge);
- CheckLiveDiamond(d2);
- CheckLiveDiamond(d3);
+ CheckInputs(d1.merge, d1.if_true, d1.if_false);
}
@@ -1348,11 +1367,7 @@ TEST(Return_nested_diamonds_true1) {
R.ReduceGraph(); // d1 gets folded true.
- CheckInputs(ret, R.one, R.start, d2.merge);
- CheckInputs(d2.branch, R.p0, R.start);
- CheckDeadDiamond(d1);
- CheckLiveDiamond(d2);
- CheckDeadDiamond(d3);
+ CheckInputs(ret, R.one, R.start, R.start);
}
@@ -1369,11 +1384,7 @@ TEST(Return_nested_diamonds_false1) {
R.ReduceGraph(); // d1 gets folded false.
- CheckInputs(ret, R.zero, R.start, d3.merge);
- CheckInputs(d3.branch, R.p0, R.start);
- CheckDeadDiamond(d1);
- CheckDeadDiamond(d2);
- CheckLiveDiamond(d3);
+ CheckInputs(ret, R.zero, R.start, R.start);
}
diff --git a/deps/v8/test/cctest/compiler/test-instruction.cc b/deps/v8/test/cctest/compiler/test-instruction.cc
index 85cc870e9d..22d46e7e39 100644
--- a/deps/v8/test/cctest/compiler/test-instruction.cc
+++ b/deps/v8/test/cctest/compiler/test-instruction.cc
@@ -27,20 +27,14 @@ typedef v8::internal::compiler::InstructionSequence TestInstrSeq;
class InstructionTester : public HandleAndZoneScope {
public: // We're all friends here.
InstructionTester()
- : isolate(main_isolate()),
- graph(zone()),
+ : graph(zone()),
schedule(zone()),
- fake_stub(main_isolate()),
- info(&fake_stub, main_isolate()),
common(zone()),
machine(zone()),
code(NULL) {}
- Isolate* isolate;
Graph graph;
Schedule schedule;
- FakeStubForTesting fake_stub;
- CompilationInfoWithZone info;
CommonOperatorBuilder common;
MachineOperatorBuilder machine;
TestInstrSeq* code;
@@ -93,8 +87,12 @@ class InstructionTester : public HandleAndZoneScope {
return UnallocatedOperand(UnallocatedOperand::ANY, vreg).Copy(zone());
}
+ RpoNumber RpoFor(BasicBlock* block) {
+ return RpoNumber::FromInt(block->rpo_number());
+ }
+
InstructionBlock* BlockAt(BasicBlock* block) {
- return code->InstructionBlockAt(block->GetRpoNumber());
+ return code->InstructionBlockAt(RpoFor(block));
}
BasicBlock* GetBasicBlock(int instruction_index) {
const InstructionBlock* block =
@@ -131,7 +129,6 @@ TEST(InstructionBasic) {
for (auto block : *blocks) {
CHECK_EQ(block->rpo_number(), R.BlockAt(block)->rpo_number().ToInt());
- CHECK_EQ(block->id().ToInt(), R.BlockAt(block)->id().ToInt());
CHECK(!block->loop_end());
}
}
@@ -151,23 +148,23 @@ TEST(InstructionGetBasicBlock) {
R.allocCode();
- R.code->StartBlock(b0->GetRpoNumber());
+ R.code->StartBlock(R.RpoFor(b0));
int i0 = R.NewInstr();
int i1 = R.NewInstr();
- R.code->EndBlock(b0->GetRpoNumber());
- R.code->StartBlock(b1->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
+ R.code->StartBlock(R.RpoFor(b1));
int i2 = R.NewInstr();
int i3 = R.NewInstr();
int i4 = R.NewInstr();
int i5 = R.NewInstr();
- R.code->EndBlock(b1->GetRpoNumber());
- R.code->StartBlock(b2->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b1));
+ R.code->StartBlock(R.RpoFor(b2));
int i6 = R.NewInstr();
int i7 = R.NewInstr();
int i8 = R.NewInstr();
- R.code->EndBlock(b2->GetRpoNumber());
- R.code->StartBlock(b3->GetRpoNumber());
- R.code->EndBlock(b3->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b2));
+ R.code->StartBlock(R.RpoFor(b3));
+ R.code->EndBlock(R.RpoFor(b3));
CHECK_EQ(b0, R.GetBasicBlock(i0));
CHECK_EQ(b0, R.GetBasicBlock(i1));
@@ -203,11 +200,11 @@ TEST(InstructionIsGapAt) {
R.allocCode();
TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0->GetRpoNumber());
+ TestInstr* g = TestInstr::New(R.zone(), 103);
+ R.code->StartBlock(R.RpoFor(b0));
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
- R.code->EndBlock(b0->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
CHECK(R.code->instructions().size() == 4);
for (size_t i = 0; i < R.code->instructions().size(); ++i) {
@@ -226,18 +223,18 @@ TEST(InstructionIsGapAt2) {
R.allocCode();
TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0->GetRpoNumber());
+ TestInstr* g = TestInstr::New(R.zone(), 103);
+ R.code->StartBlock(R.RpoFor(b0));
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
- R.code->EndBlock(b0->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
TestInstr* i1 = TestInstr::New(R.zone(), 102);
- TestInstr* g1 = TestInstr::New(R.zone(), 104)->MarkAsControl();
- R.code->StartBlock(b1->GetRpoNumber());
+ TestInstr* g1 = TestInstr::New(R.zone(), 104);
+ R.code->StartBlock(R.RpoFor(b1));
R.code->AddInstruction(i1);
R.code->AddInstruction(g1);
- R.code->EndBlock(b1->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b1));
CHECK(R.code->instructions().size() == 8);
for (size_t i = 0; i < R.code->instructions().size(); ++i) {
@@ -254,11 +251,11 @@ TEST(InstructionAddGapMove) {
R.allocCode();
TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0->GetRpoNumber());
+ TestInstr* g = TestInstr::New(R.zone(), 103);
+ R.code->StartBlock(R.RpoFor(b0));
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
- R.code->EndBlock(b0->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
CHECK(R.code->instructions().size() == 4);
for (size_t i = 0; i < R.code->instructions().size(); ++i) {
diff --git a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc
index f4531d3e83..cc4b2bdef2 100644
--- a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc
+++ b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/compiler/graph-inl.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/machine-operator.h"
@@ -68,7 +67,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
Node* stack = graph.NewNode(common.StateValues(0));
Node* state_node =
- graph.NewNode(common.FrameState(JS_FRAME, BailoutId(0),
+ graph.NewNode(common.FrameState(JS_FRAME, BailoutId::None(),
OutputFrameStateCombine::Ignore()),
parameters, locals, stack, context, UndefinedConstant());
@@ -114,9 +113,13 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
Node* Binop(const Operator* op, Node* left, Node* right) {
// JS binops also require context, effect, and control
- if (OperatorProperties::HasFrameStateInput(op)) {
+ if (OperatorProperties::GetFrameStateInputCount(op) == 1) {
return graph.NewNode(op, left, right, context(),
EmptyFrameState(context()), start(), control());
+ } else if (OperatorProperties::GetFrameStateInputCount(op) == 2) {
+ return graph.NewNode(op, left, right, context(),
+ EmptyFrameState(context()),
+ EmptyFrameState(context()), start(), control());
} else {
return graph.NewNode(op, left, right, context(), start(), control());
}
@@ -124,7 +127,8 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
Node* Unop(const Operator* op, Node* input) {
// JS unops also require context, effect, and control
- if (OperatorProperties::HasFrameStateInput(op)) {
+ if (OperatorProperties::GetFrameStateInputCount(op) > 0) {
+ DCHECK(OperatorProperties::GetFrameStateInputCount(op) == 1);
return graph.NewNode(op, input, context(), EmptyFrameState(context()),
start(), control());
} else {
@@ -134,7 +138,10 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
Node* UseForEffect(Node* node) {
// TODO(titzer): use EffectPhi after fixing EffectCount
- if (OperatorProperties::HasFrameStateInput(javascript.ToNumber())) {
+ if (OperatorProperties::GetFrameStateInputCount(javascript.ToNumber()) >
+ 0) {
+ DCHECK(OperatorProperties::GetFrameStateInputCount(
+ javascript.ToNumber()) == 1);
return graph.NewNode(javascript.ToNumber(), node, context(),
EmptyFrameState(context()), node, control());
} else {
@@ -500,42 +507,6 @@ TEST(JSToNumberOfNumberOrOtherPrimitive) {
}
-TEST(JSToBoolean) {
- JSTypedLoweringTester R;
- const Operator* op = R.javascript.ToBoolean();
-
- { // ToBoolean(undefined)
- Node* r = R.ReduceUnop(op, Type::Undefined());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(null)
- Node* r = R.ReduceUnop(op, Type::Null());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(boolean)
- Node* r = R.ReduceUnop(op, Type::Boolean());
- CHECK_EQ(IrOpcode::kParameter, r->opcode());
- }
-
- { // ToBoolean(object)
- Node* r = R.ReduceUnop(op, Type::DetectableObject());
- R.CheckTrue(r);
- }
-
- { // ToBoolean(undetectable)
- Node* r = R.ReduceUnop(op, Type::Undetectable());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(object)
- Node* r = R.ReduceUnop(op, Type::Object());
- CHECK_EQ(IrOpcode::kAnyToBoolean, r->opcode());
- }
-}
-
-
TEST(JSToString1) {
JSTypedLoweringTester R;
@@ -717,24 +688,6 @@ TEST(MixedComparison1) {
}
-TEST(UnaryNot) {
- JSTypedLoweringTester R;
- const Operator* opnot = R.javascript.UnaryNot();
-
- for (size_t i = 0; i < arraysize(kJSTypes); i++) {
- Node* orig = R.Unop(opnot, R.Parameter(kJSTypes[i]));
- Node* r = R.reduce(orig);
-
- if (r == orig && orig->opcode() == IrOpcode::kJSToBoolean) {
- // The original node was turned into a ToBoolean.
- CHECK_EQ(IrOpcode::kJSToBoolean, r->opcode());
- } else if (r->opcode() != IrOpcode::kHeapConstant) {
- CHECK_EQ(IrOpcode::kBooleanNot, r->opcode());
- }
- }
-}
-
-
TEST(RemoveToNumberEffects) {
FLAG_turbo_deoptimization = true;
@@ -749,8 +702,9 @@ TEST(RemoveToNumberEffects) {
switch (i) {
case 0:
- // TODO(jarin) Replace with a query of FLAG_turbo_deoptimization.
- if (OperatorProperties::HasFrameStateInput(R.javascript.ToNumber())) {
+ if (FLAG_turbo_deoptimization) {
+ DCHECK(OperatorProperties::GetFrameStateInputCount(
+ R.javascript.ToNumber()) == 1);
effect_use = R.graph.NewNode(R.javascript.ToNumber(), p0, R.context(),
frame_state, ton, R.start());
} else {
@@ -759,8 +713,9 @@ TEST(RemoveToNumberEffects) {
}
break;
case 1:
- // TODO(jarin) Replace with a query of FLAG_turbo_deoptimization.
- if (OperatorProperties::HasFrameStateInput(R.javascript.ToNumber())) {
+ if (FLAG_turbo_deoptimization) {
+ DCHECK(OperatorProperties::GetFrameStateInputCount(
+ R.javascript.ToNumber()) == 1);
effect_use =
R.graph.NewNode(R.javascript.ToNumber(), ton, R.context(),
frame_state, ton, R.start());
@@ -773,11 +728,11 @@ TEST(RemoveToNumberEffects) {
effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start());
case 3:
effect_use = R.graph.NewNode(R.javascript.Add(), ton, ton, R.context(),
- frame_state, ton, R.start());
+ frame_state, frame_state, ton, R.start());
break;
case 4:
effect_use = R.graph.NewNode(R.javascript.Add(), p0, p0, R.context(),
- frame_state, ton, R.start());
+ frame_state, frame_state, ton, R.start());
break;
case 5:
effect_use = R.graph.NewNode(R.common.Return(), p0, ton, R.start());
diff --git a/deps/v8/test/cctest/compiler/test-jump-threading.cc b/deps/v8/test/cctest/compiler/test-jump-threading.cc
index d9de18efad..b2d3008aa9 100644
--- a/deps/v8/test/cctest/compiler/test-jump-threading.cc
+++ b/deps/v8/test/cctest/compiler/test-jump-threading.cc
@@ -13,8 +13,6 @@ namespace v8 {
namespace internal {
namespace compiler {
-typedef BasicBlock::RpoNumber RpoNumber;
-
class TestCode : public HandleAndZoneScope {
public:
TestCode()
@@ -32,8 +30,8 @@ class TestCode : public HandleAndZoneScope {
int Jump(int target) {
Start();
InstructionOperand ops[] = {UseRpo(target)};
- sequence_.AddInstruction(Instruction::New(main_zone(), kArchJmp, 0, NULL, 1,
- ops, 0, NULL)->MarkAsControl());
+ sequence_.AddInstruction(
+ Instruction::New(main_zone(), kArchJmp, 0, NULL, 1, ops, 0, NULL));
int pos = static_cast<int>(sequence_.instructions().size() - 1);
End();
return pos;
@@ -47,8 +45,8 @@ class TestCode : public HandleAndZoneScope {
InstructionOperand ops[] = {UseRpo(ttarget), UseRpo(ftarget)};
InstructionCode code = 119 | FlagsModeField::encode(kFlags_branch) |
FlagsConditionField::encode(kEqual);
- sequence_.AddInstruction(Instruction::New(main_zone(), code, 0, NULL, 2,
- ops, 0, NULL)->MarkAsControl());
+ sequence_.AddInstruction(
+ Instruction::New(main_zone(), code, 0, NULL, 2, ops, 0, NULL));
int pos = static_cast<int>(sequence_.instructions().size() - 1);
End();
return pos;
@@ -87,9 +85,9 @@ class TestCode : public HandleAndZoneScope {
}
void Start(bool deferred = false) {
if (current_ == NULL) {
- current_ = new (main_zone()) InstructionBlock(
- main_zone(), BasicBlock::Id::FromInt(rpo_number_.ToInt()),
- rpo_number_, RpoNumber::Invalid(), RpoNumber::Invalid(), deferred);
+ current_ = new (main_zone())
+ InstructionBlock(main_zone(), rpo_number_, RpoNumber::Invalid(),
+ RpoNumber::Invalid(), deferred);
blocks_.push_back(current_);
sequence_.StartBlock(rpo_number_);
}
diff --git a/deps/v8/test/cctest/compiler/test-linkage.cc b/deps/v8/test/cctest/compiler/test-linkage.cc
index 13695b2e0b..212ff3a8f2 100644
--- a/deps/v8/test/cctest/compiler/test-linkage.cc
+++ b/deps/v8/test/cctest/compiler/test-linkage.cc
@@ -6,6 +6,7 @@
#include "src/code-stubs.h"
#include "src/compiler.h"
+#include "src/parser.h"
#include "src/zone.h"
#include "src/compiler/common-operator.h"
@@ -33,7 +34,7 @@ static Handle<JSFunction> Compile(const char* source) {
->NewStringFromUtf8(CStrVector(source))
.ToHandleChecked();
Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript(
- source_code, Handle<String>(), 0, 0, false, false,
+ source_code, Handle<String>(), 0, 0, false, false, Handle<Object>(),
Handle<Context>(isolate->native_context()), NULL, NULL,
v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE, false);
return isolate->factory()->NewFunctionFromSharedFunctionInfo(
@@ -42,25 +43,25 @@ static Handle<JSFunction> Compile(const char* source) {
TEST(TestLinkageCreate) {
- InitializedHandleScope handles;
+ HandleAndZoneScope handles;
Handle<JSFunction> function = Compile("a + b");
- CompilationInfoWithZone info(function);
+ ParseInfo parse_info(handles.main_zone(), function);
+ CompilationInfo info(&parse_info);
CallDescriptor* descriptor = Linkage::ComputeIncoming(info.zone(), &info);
CHECK(descriptor);
}
TEST(TestLinkageJSFunctionIncoming) {
- InitializedHandleScope handles;
-
const char* sources[] = {"(function() { })", "(function(a) { })",
"(function(a,b) { })", "(function(a,b,c) { })"};
for (int i = 0; i < 3; i++) {
- i::HandleScope handles(CcTest::i_isolate());
+ HandleAndZoneScope handles;
Handle<JSFunction> function = v8::Utils::OpenHandle(
*v8::Handle<v8::Function>::Cast(CompileRun(sources[i])));
- CompilationInfoWithZone info(function);
+ ParseInfo parse_info(handles.main_zone(), function);
+ CompilationInfo info(&parse_info);
CallDescriptor* descriptor = Linkage::ComputeIncoming(info.zone(), &info);
CHECK(descriptor);
@@ -74,9 +75,10 @@ TEST(TestLinkageJSFunctionIncoming) {
TEST(TestLinkageCodeStubIncoming) {
Isolate* isolate = CcTest::InitIsolateOnce();
+ Zone zone;
ToNumberStub stub(isolate);
- CompilationInfoWithZone info(&stub, isolate);
- CallDescriptor* descriptor = Linkage::ComputeIncoming(info.zone(), &info);
+ CompilationInfo info(&stub, isolate, &zone);
+ CallDescriptor* descriptor = Linkage::ComputeIncoming(&zone, &info);
CHECK(descriptor);
CHECK_EQ(1, static_cast<int>(descriptor->JSParameterCount()));
CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
@@ -88,7 +90,8 @@ TEST(TestLinkageCodeStubIncoming) {
TEST(TestLinkageJSCall) {
HandleAndZoneScope handles;
Handle<JSFunction> function = Compile("a + c");
- CompilationInfoWithZone info(function);
+ ParseInfo parse_info(handles.main_zone(), function);
+ CompilationInfo info(&parse_info);
for (int i = 0; i < 32; i++) {
CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(
diff --git a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc
index 7513307bab..5f9820c72a 100644
--- a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc
+++ b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc
@@ -29,14 +29,15 @@ struct TestHelper : public HandleAndZoneScope {
void CheckLoopAssignedCount(int expected, const char* var_name) {
// TODO(titzer): don't scope analyze every single time.
- CompilationInfo info(function, main_zone());
+ ParseInfo parse_info(main_zone(), function);
+ CompilationInfo info(&parse_info);
- CHECK(Parser::ParseStatic(&info));
- CHECK(Rewriter::Rewrite(&info));
- CHECK(Scope::Analyze(&info));
+ CHECK(Parser::ParseStatic(&parse_info));
+ CHECK(Rewriter::Rewrite(&parse_info));
+ CHECK(Scope::Analyze(&parse_info));
Scope* scope = info.function()->scope();
- AstValueFactory* factory = info.ast_value_factory();
+ AstValueFactory* factory = parse_info.ast_value_factory();
CHECK(scope);
if (result == NULL) {
diff --git a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc
index 7ee5751875..beedc459e7 100644
--- a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc
+++ b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc
@@ -6,7 +6,6 @@
#include "src/base/utils/random-number-generator.h"
#include "src/codegen.h"
-#include "src/compiler/graph-inl.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/operator-properties.h"
diff --git a/deps/v8/test/cctest/compiler/test-node-algorithm.cc b/deps/v8/test/cctest/compiler/test-node-algorithm.cc
index 842d18272e..0cb77011aa 100644
--- a/deps/v8/test/cctest/compiler/test-node-algorithm.cc
+++ b/deps/v8/test/cctest/compiler/test-node-algorithm.cc
@@ -9,7 +9,6 @@
#include "graph-tester.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
-#include "src/compiler/graph-inl.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
@@ -20,45 +19,6 @@ using namespace v8::internal::compiler;
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 1, 0, 0);
-class PreNodeVisitor : public NullNodeVisitor {
- public:
- void Pre(Node* node) {
- printf("NODE ID: %d\n", node->id());
- nodes_.push_back(node);
- }
- std::vector<Node*> nodes_;
-};
-
-
-class PostNodeVisitor : public NullNodeVisitor {
- public:
- void Post(Node* node) {
- printf("NODE ID: %d\n", node->id());
- nodes_.push_back(node);
- }
- std::vector<Node*> nodes_;
-};
-
-
-TEST(TestInputNodePreOrderVisitSimple) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, n2);
- Node* n4 = graph.NewNode(&dummy_operator, n2, n3);
- Node* n5 = graph.NewNode(&dummy_operator, n4, n2);
- graph.SetEnd(n5);
-
- PreNodeVisitor node_visitor;
- graph.VisitNodeInputsFromEnd(&node_visitor);
- CHECK_EQ(5, static_cast<int>(node_visitor.nodes_.size()));
- CHECK(n5->id() == node_visitor.nodes_[0]->id());
- CHECK(n4->id() == node_visitor.nodes_[1]->id());
- CHECK(n2->id() == node_visitor.nodes_[2]->id());
- CHECK(graph.start()->id() == node_visitor.nodes_[3]->id());
- CHECK(n3->id() == node_visitor.nodes_[4]->id());
-}
-
-
TEST(TestPrintNodeGraphToNodeGraphviz) {
GraphWithStartNodeTester graph;
Node* n2 = graph.NewNode(&dummy_operator, graph.start());
diff --git a/deps/v8/test/cctest/compiler/test-node.cc b/deps/v8/test/cctest/compiler/test-node.cc
index 2c51e26f86..5bb21f585d 100644
--- a/deps/v8/test/cctest/compiler/test-node.cc
+++ b/deps/v8/test/cctest/compiler/test-node.cc
@@ -13,32 +13,143 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
+#define NONE reinterpret_cast<Node*>(1)
+
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 1, 0, 0);
+#define CHECK_USES(node, ...) \
+ do { \
+ Node* __array[] = {__VA_ARGS__}; \
+ int __size = \
+ __array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
+ CheckUseChain(node, __array, __size); \
+ } while (false)
+
+
+typedef std::multiset<Node*, std::less<Node*>> NodeMSet;
+
+static void CheckUseChain(Node* node, Node** uses, int use_count) {
+ // Check ownership.
+ if (use_count == 1) CHECK(node->OwnedBy(uses[0]));
+ if (use_count > 1) {
+ for (int i = 0; i < use_count; i++) {
+ CHECK(!node->OwnedBy(uses[i]));
+ }
+ }
+
+ // Check the self-reported use count.
+ CHECK_EQ(use_count, node->UseCount());
+
+ // Build the expectation set.
+ NodeMSet expect_set;
+ for (int i = 0; i < use_count; i++) {
+ expect_set.insert(uses[i]);
+ }
+
+ {
+ // Check that iterating over the uses gives the right counts.
+ NodeMSet use_set;
+ for (auto use : node->uses()) {
+ use_set.insert(use);
+ }
+ CHECK(expect_set == use_set);
+ }
+
+ {
+ // Check that iterating over the use edges gives the right counts,
+ // input indices, from(), and to() pointers.
+ NodeMSet use_set;
+ for (auto edge : node->use_edges()) {
+ CHECK_EQ(node, edge.to());
+ CHECK_EQ(node, edge.from()->InputAt(edge.index()));
+ use_set.insert(edge.from());
+ }
+ CHECK(expect_set == use_set);
+ }
+
+ {
+ // Check the use nodes actually have the node as inputs.
+ for (Node* use : node->uses()) {
+ size_t count = 0;
+ for (Node* input : use->inputs()) {
+ if (input == node) count++;
+ }
+ CHECK_EQ(count, expect_set.count(use));
+ }
+ }
+}
+
+
+#define CHECK_INPUTS(node, ...) \
+ do { \
+ Node* __array[] = {__VA_ARGS__}; \
+ int __size = \
+ __array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
+ CheckInputs(node, __array, __size); \
+ } while (false)
+
+
+static void CheckInputs(Node* node, Node** inputs, int input_count) {
+ CHECK_EQ(input_count, node->InputCount());
+ // Check InputAt().
+ for (int i = 0; i < static_cast<int>(input_count); i++) {
+ CHECK_EQ(inputs[i], node->InputAt(i));
+ }
+
+ // Check input iterator.
+ int index = 0;
+ for (Node* input : node->inputs()) {
+ CHECK_EQ(inputs[index], input);
+ index++;
+ }
+
+ // Check use lists of inputs.
+ for (int i = 0; i < static_cast<int>(input_count); i++) {
+ Node* input = inputs[i];
+ if (!input) continue; // skip null inputs
+ bool found = false;
+ // Check regular use list.
+ for (Node* use : input->uses()) {
+ if (use == node) {
+ found = true;
+ break;
+ }
+ }
+ CHECK(found);
+ int count = 0;
+ // Check use edge list.
+ for (auto edge : input->use_edges()) {
+ if (edge.from() == node && edge.to() == input && edge.index() == i) {
+ count++;
+ }
+ }
+ CHECK_EQ(1, count);
+ }
+}
+
+
TEST(NodeUseIteratorReplaceUses) {
GraphTester graph;
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator);
- auto i1(n0->uses().begin());
- CHECK_EQ(n1, *i1);
- ++i1;
- CHECK_EQ(n2, *i1);
+
+ CHECK_USES(n0, n1, n2);
+
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0);
+
n0->ReplaceUses(n3);
- auto i2(n3->uses().begin());
- CHECK_EQ(n1, *i2);
- ++i2;
- CHECK_EQ(n2, *i2);
- auto i3(n1->inputs().begin());
- CHECK_EQ(n3, *i3);
- ++i3;
- CHECK(n1->inputs().end() == i3);
- auto i4(n2->inputs().begin());
- CHECK_EQ(n3, *i4);
- ++i4;
- CHECK(n2->inputs().end() == i4);
+
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
+ CHECK_USES(n3, n1, n2);
+
+ CHECK_INPUTS(n1, n3);
+ CHECK_INPUTS(n2, n3);
}
@@ -46,21 +157,22 @@ TEST(NodeUseIteratorReplaceUsesSelf) {
GraphTester graph;
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
+
+ CHECK_USES(n0, n1);
+ CHECK_USES(n1, NONE);
n1->ReplaceInput(0, n1); // Create self-reference.
- auto i1(n1->uses().begin());
- CHECK_EQ(n1, *i1);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, n1);
- n1->ReplaceUses(n3);
+ Node* n2 = graph.NewNode(&dummy_operator);
- CHECK(n1->uses().begin() == n1->uses().end());
+ n1->ReplaceUses(n2);
- auto i2(n3->uses().begin());
- CHECK_EQ(n1, *i2);
- ++i2;
- CHECK(n1->uses().end() == i2);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, n1);
}
@@ -70,48 +182,22 @@ TEST(ReplaceInput) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator);
Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
- auto i1(n3->inputs().begin());
- CHECK(n0 == *i1);
- CHECK_EQ(n0, n3->InputAt(0));
- ++i1;
- CHECK_EQ(n1, *i1);
- CHECK_EQ(n1, n3->InputAt(1));
- ++i1;
- CHECK_EQ(n2, *i1);
- CHECK_EQ(n2, n3->InputAt(2));
- ++i1;
- CHECK(i1 == n3->inputs().end());
-
- auto i2(n1->uses().begin());
- CHECK_EQ(n3, *i2);
- ++i2;
- CHECK(i2 == n1->uses().end());
-
Node* n4 = graph.NewNode(&dummy_operator);
- auto i3(n4->uses().begin());
- CHECK(i3 == n4->uses().end());
+
+ CHECK_USES(n0, n3);
+ CHECK_USES(n1, n3);
+ CHECK_USES(n2, n3);
+ CHECK_USES(n3, NONE);
+ CHECK_USES(n4, NONE);
+
+ CHECK_INPUTS(n3, n0, n1, n2);
n3->ReplaceInput(1, n4);
- auto i4(n1->uses().begin());
- CHECK(i4 == n1->uses().end());
-
- auto i5(n4->uses().begin());
- CHECK_EQ(n3, *i5);
- ++i5;
- CHECK(i5 == n4->uses().end());
-
- auto i6(n3->inputs().begin());
- CHECK(n0 == *i6);
- CHECK_EQ(n0, n3->InputAt(0));
- ++i6;
- CHECK_EQ(n4, *i6);
- CHECK_EQ(n4, n3->InputAt(1));
- ++i6;
- CHECK_EQ(n2, *i6);
- CHECK_EQ(n2, n3->InputAt(2));
- ++i6;
- CHECK(i6 == n3->inputs().end());
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n4, n3);
+
+ CHECK_INPUTS(n3, n0, n4, n2);
}
@@ -169,16 +255,19 @@ TEST(Uses) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(1, n0->UseCount());
- printf("A: %d vs %d\n", n0->UseAt(0)->id(), n1->id());
- CHECK(n0->UseAt(0) == n1);
+
+ CHECK_USES(n0, n1);
+ CHECK_USES(n1, NONE);
+
Node* n2 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(2, n0->UseCount());
- printf("B: %d vs %d\n", n0->UseAt(1)->id(), n2->id());
- CHECK(n0->UseAt(1) == n2);
+
+ CHECK_USES(n0, n1, n2);
+ CHECK_USES(n2, NONE);
+
Node* n3 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(3, n0->UseCount());
- CHECK(n0->UseAt(2) == n3);
+
+ CHECK_USES(n0, n1, n2, n3);
+ CHECK_USES(n3, NONE);
}
@@ -189,39 +278,23 @@ TEST(Inputs) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
- CHECK_EQ(3, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
+
+ CHECK_INPUTS(n3, n0, n1, n2);
+
Node* n4 = graph.NewNode(&dummy_operator, n0, n1, n2);
n3->AppendInput(graph.zone(), n4);
- CHECK_EQ(4, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- CHECK(n3->InputAt(3) == n4);
- Node* n5 = graph.NewNode(&dummy_operator, n4);
+
+ CHECK_INPUTS(n3, n0, n1, n2, n4);
+ CHECK_USES(n4, n3);
+
n3->AppendInput(graph.zone(), n4);
- CHECK_EQ(5, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- CHECK(n3->InputAt(3) == n4);
- CHECK(n3->InputAt(4) == n4);
-
- // Make sure uses have been hooked op correctly.
- Node::Uses uses(n4->uses());
- auto current = uses.begin();
- CHECK(current != uses.end());
- CHECK(*current == n3);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n5);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n3);
- ++current;
- CHECK(current == uses.end());
+
+ CHECK_INPUTS(n3, n0, n1, n2, n4, n4);
+ CHECK_USES(n4, n3, n3);
+
+ Node* n5 = graph.NewNode(&dummy_operator, n4);
+
+ CHECK_USES(n4, n3, n3, n5);
}
@@ -232,17 +305,25 @@ TEST(RemoveInput) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n1, n2);
+
n1->RemoveInput(0);
- CHECK_EQ(0, n1->InputCount());
- CHECK_EQ(1, n0->UseCount());
+ CHECK_INPUTS(n1, NONE);
+ CHECK_USES(n0, n2);
n2->RemoveInput(0);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
+ CHECK_INPUTS(n2, n1);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, n2);
n2->RemoveInput(0);
- CHECK_EQ(0, n2->InputCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
@@ -253,33 +334,17 @@ TEST(AppendInputsAndIterator) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- Node::InputEdges inputs(n2->input_edges());
- Node::InputEdges::iterator current = inputs.begin();
- CHECK(current != inputs.end());
- CHECK((*current).to() == n0);
- ++current;
- CHECK(current != inputs.end());
- CHECK((*current).to() == n1);
- ++current;
- CHECK(current == inputs.end());
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n1, n2);
Node* n3 = graph.NewNode(&dummy_operator);
+
n2->AppendInput(graph.zone(), n3);
- inputs = n2->input_edges();
- current = inputs.begin();
- CHECK(current != inputs.end());
- CHECK((*current).to() == n0);
- CHECK_EQ(0, (*current).index());
- ++current;
- CHECK(current != inputs.end());
- CHECK((*current).to() == n1);
- CHECK_EQ(1, (*current).index());
- ++current;
- CHECK(current != inputs.end());
- CHECK((*current).to() == n3);
- CHECK_EQ(2, (*current).index());
- ++current;
- CHECK(current == inputs.end());
+
+ CHECK_INPUTS(n2, n0, n1, n3);
+ CHECK_USES(n3, n2);
}
@@ -289,15 +354,23 @@ TEST(NullInputsSimple) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- CHECK_EQ(2, n2->InputCount());
-
- CHECK(n0 == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK_EQ(2, n0->UseCount());
- n2->ReplaceInput(0, NULL);
- CHECK(NULL == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
+
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n1, n2);
+
+ n2->ReplaceInput(0, nullptr);
+
+ CHECK_INPUTS(n2, NULL, n1);
+
+ CHECK_USES(n0, n1);
+
+ n2->ReplaceInput(1, nullptr);
+
+ CHECK_INPUTS(n2, NULL, NULL);
+
+ CHECK_USES(n1, NONE);
}
@@ -310,17 +383,16 @@ TEST(NullInputsAppended) {
Node* n3 = graph.NewNode(&dummy_operator, n0);
n3->AppendInput(graph.zone(), n1);
n3->AppendInput(graph.zone(), n2);
- CHECK_EQ(3, n3->InputCount());
- CHECK(n0 == n3->InputAt(0));
- CHECK(n1 == n3->InputAt(1));
- CHECK(n2 == n3->InputAt(2));
- CHECK_EQ(1, n1->UseCount());
+ CHECK_INPUTS(n3, n0, n1, n2);
+ CHECK_USES(n0, n1, n2, n3);
+ CHECK_USES(n1, n3);
+ CHECK_USES(n2, n3);
+
n3->ReplaceInput(1, NULL);
- CHECK(n0 == n3->InputAt(0));
- CHECK(NULL == n3->InputAt(1));
- CHECK(n2 == n3->InputAt(2));
- CHECK_EQ(0, n1->UseCount());
+ CHECK_USES(n1, NONE);
+
+ CHECK_INPUTS(n3, n0, NULL, n2);
}
@@ -331,26 +403,23 @@ TEST(ReplaceUsesFromAppendedInputs) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator);
+
+ CHECK_INPUTS(n2, n0);
+
n2->AppendInput(graph.zone(), n1);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n1, n2);
+
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(0, n3->UseCount());
- CHECK_EQ(3, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n1, n0);
+ CHECK_USES(n1, n2);
+ CHECK_USES(n0, n2, n1, n2);
+
n0->ReplaceUses(n3);
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(3, n3->UseCount());
-
- Node::Uses uses(n3->uses());
- auto current = uses.begin();
- CHECK(current != uses.end());
- CHECK(*current == n1);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n2);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n2);
- ++current;
- CHECK(current == uses.end());
+
+ CHECK_USES(n0, NONE);
+ CHECK_INPUTS(n2, n3, n1, n3);
+ CHECK_USES(n3, n2, n1, n2);
}
@@ -378,17 +447,16 @@ TEST(TrimInputCountInline) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
n1->TrimInputCount(1);
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, n1->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
+ CHECK_INPUTS(n1, n0);
+ CHECK_USES(n0, n1);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
n1->TrimInputCount(0);
- CHECK_EQ(0, n1->InputCount());
- CHECK_EQ(0, n0->UseCount());
+ CHECK_INPUTS(n1, NONE);
+ CHECK_USES(n0, NONE);
}
{
@@ -396,10 +464,9 @@ TEST(TrimInputCountInline) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, n2);
}
{
@@ -407,10 +474,9 @@ TEST(TrimInputCountInline) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, NONE);
}
{
@@ -418,28 +484,25 @@ TEST(TrimInputCountInline) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
}
}
@@ -451,10 +514,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator);
n1->AppendInput(graph.zone(), n0);
+ CHECK_INPUTS(n1, n0);
+ CHECK_USES(n0, n1);
+
n1->TrimInputCount(1);
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, n1->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
+ CHECK_INPUTS(n1, n0);
+ CHECK_USES(n0, n1);
}
{
@@ -473,14 +538,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(n1, n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, n2);
+ CHECK_USES(n2, NONE);
}
{
@@ -489,13 +552,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
@@ -504,12 +566,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
@@ -517,12 +579,11 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n0);
+ CHECK_USES(n0, n2, n2);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
}
{
@@ -530,12 +591,11 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n0);
+ CHECK_USES(n0, n2, n2);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
}
}
@@ -548,14 +608,12 @@ TEST(TrimInputCountOutOfLine2) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(n1, n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, n2);
+ CHECK_USES(n2, NONE);
}
{
@@ -563,13 +621,12 @@ TEST(TrimInputCountOutOfLine2) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
@@ -577,24 +634,24 @@ TEST(TrimInputCountOutOfLine2) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n0);
+ CHECK_USES(n0, n2, n2);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n2, NONE);
}
{
@@ -611,7 +668,7 @@ TEST(TrimInputCountOutOfLine2) {
}
-TEST(RemoveAllInputs) {
+TEST(NullAllInputs) {
GraphTester graph;
for (int i = 0; i < 2; i++) {
@@ -620,27 +677,27 @@ TEST(RemoveAllInputs) {
Node* n2;
if (i == 0) {
n2 = graph.NewNode(&dummy_operator, n0, n1);
+ CHECK_INPUTS(n2, n0, n1);
} else {
n2 = graph.NewNode(&dummy_operator, n0);
+ CHECK_INPUTS(n2, n0);
n2->AppendInput(graph.zone(), n1); // with out-of-line input.
+ CHECK_INPUTS(n2, n0, n1);
}
- n0->RemoveAllInputs();
- CHECK_EQ(0, n0->InputCount());
+ n0->NullAllInputs();
+ CHECK_INPUTS(n0, NONE);
- CHECK_EQ(2, n0->UseCount());
- n1->RemoveAllInputs();
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK(!n1->InputAt(0));
+ CHECK_USES(n0, n1, n2);
+ n1->NullAllInputs();
+ CHECK_INPUTS(n1, NULL);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
- CHECK_EQ(1, n1->UseCount());
- n2->RemoveAllInputs();
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK(!n2->InputAt(0));
- CHECK(!n2->InputAt(1));
+ n2->NullAllInputs();
+ CHECK_INPUTS(n1, NULL);
+ CHECK_INPUTS(n2, NULL, NULL);
+ CHECK_USES(n0, NONE);
}
{
@@ -648,11 +705,53 @@ TEST(RemoveAllInputs) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
n1->ReplaceInput(0, n1); // self-reference.
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- n1->RemoveAllInputs();
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK(!n1->InputAt(0));
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n1);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, n1);
+ n1->NullAllInputs();
+
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, NULL);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ }
+}
+
+
+TEST(AppendAndTrim) {
+ GraphTester graph;
+
+ Node* nodes[] = {
+ graph.NewNode(&dummy_operator), graph.NewNode(&dummy_operator),
+ graph.NewNode(&dummy_operator), graph.NewNode(&dummy_operator),
+ graph.NewNode(&dummy_operator)};
+
+ int max = static_cast<int>(arraysize(nodes));
+
+ Node* last = graph.NewNode(&dummy_operator);
+
+ for (int i = 0; i < max; i++) {
+ last->AppendInput(graph.zone(), nodes[i]);
+ CheckInputs(last, nodes, i + 1);
+
+ for (int j = 0; j < max; j++) {
+ if (j <= i) CHECK_USES(nodes[j], last);
+ if (j > i) CHECK_USES(nodes[j], NONE);
+ }
+
+ CHECK_USES(last, NONE);
+ }
+
+ for (int i = max; i >= 0; i--) {
+ last->TrimInputCount(i);
+ CheckInputs(last, nodes, i);
+
+ for (int j = 0; j < i; j++) {
+ if (j < i) CHECK_USES(nodes[j], last);
+ if (j >= i) CHECK_USES(nodes[j], NONE);
+ }
+
+ CHECK_USES(last, NONE);
}
}
diff --git a/deps/v8/test/cctest/compiler/test-osr.cc b/deps/v8/test/cctest/compiler/test-osr.cc
index e3963901a5..d2171188f8 100644
--- a/deps/v8/test/cctest/compiler/test-osr.cc
+++ b/deps/v8/test/cctest/compiler/test-osr.cc
@@ -36,6 +36,8 @@ static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL,
static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure,
"Int32LessThan", 2, 0, 0, 1, 0, 0);
+static Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0,
+ 0, 1, 0, 0);
static const int kMaxOsrValues = 10;
@@ -122,7 +124,12 @@ class OsrDeconstructorTester : public HandleAndZoneScope {
CHECK(!nodes.IsLive(osr_normal_entry));
CHECK(!nodes.IsLive(osr_loop_entry));
// No dangling nodes should be left over.
- CHECK_EQ(0u, nodes.gray.size());
+ for (Node* const node : nodes.live) {
+ for (Node* const use : node->uses()) {
+ CHECK(std::find(nodes.live.begin(), nodes.live.end(), use) !=
+ nodes.live.end());
+ }
+ }
}
};
@@ -484,3 +491,105 @@ TEST(Deconstruct_osr_nested2) {
CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi,
T.jsgraph.ZeroConstant(), new_outer_loop);
}
+
+
+Node* MakeCounter(JSGraph* jsgraph, Node* start, Node* loop) {
+ int count = loop->InputCount();
+ NodeVector tmp_inputs(jsgraph->graph()->zone());
+ for (int i = 0; i < count; i++) {
+ tmp_inputs.push_back(start);
+ }
+ tmp_inputs.push_back(loop);
+
+ Node* phi = jsgraph->graph()->NewNode(
+ jsgraph->common()->Phi(kMachInt32, count), count + 1, &tmp_inputs[0]);
+ Node* inc = jsgraph->graph()->NewNode(&kIntAdd, phi, jsgraph->OneConstant());
+
+ for (int i = 1; i < count; i++) {
+ phi->ReplaceInput(i, inc);
+ }
+ return phi;
+}
+
+
+TEST(Deconstruct_osr_nested3) {
+ OsrDeconstructorTester T(1);
+
+ // outermost loop.
+ While loop0(T, T.p0, false, 1);
+ Node* loop0_cntr = MakeCounter(&T.jsgraph, T.p0, loop0.loop);
+ loop0.branch->ReplaceInput(0, loop0_cntr);
+
+ // middle loop.
+ Node* loop1 = T.graph.NewNode(T.common.Loop(2), loop0.if_true, T.self);
+ loop1->ReplaceInput(0, loop0.if_true);
+ Node* loop1_phi =
+ T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), loop0_cntr, loop0_cntr);
+
+ // innermost (OSR) loop.
+ While loop2(T, T.p0, true, 1);
+ loop2.loop->ReplaceInput(0, loop1);
+
+ Node* loop2_cntr = MakeCounter(&T.jsgraph, loop1_phi, loop2.loop);
+ loop2_cntr->ReplaceInput(1, T.osr_values[0]);
+ Node* osr_phi = loop2_cntr;
+ Node* loop2_inc = loop2_cntr->InputAt(2);
+ loop2.branch->ReplaceInput(0, loop2_cntr);
+
+ loop1_phi->ReplaceInput(1, loop2_cntr);
+ loop0_cntr->ReplaceInput(1, loop2_cntr);
+
+ // Branch to either the outer or middle loop.
+ Node* branch = T.graph.NewNode(T.common.Branch(), loop2_cntr, loop2.exit);
+ Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch);
+ Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch);
+
+ loop0.loop->ReplaceInput(1, if_true);
+ loop1->ReplaceInput(1, if_false);
+
+ Node* ret =
+ T.graph.NewNode(T.common.Return(), loop0_cntr, T.start, loop0.exit);
+ Node* end = T.graph.NewNode(T.common.End(), ret);
+ T.graph.SetEnd(end);
+
+ T.DeconstructOsr();
+
+ // Check structure of deconstructed graph.
+ // Check loop2 (OSR loop) is directly connected to start.
+ CheckInputs(loop2.loop, T.start, loop2.if_true);
+ CheckInputs(osr_phi, T.osr_values[0], loop2_inc, loop2.loop);
+ CheckInputs(loop2.branch, osr_phi, loop2.loop);
+ CheckInputs(loop2.if_true, loop2.branch);
+ CheckInputs(loop2.exit, loop2.branch);
+ CheckInputs(branch, osr_phi, loop2.exit);
+ CheckInputs(if_true, branch);
+ CheckInputs(if_false, branch);
+
+ // Check structure of new_loop1.
+ Node* new_loop1_loop = FindSuccessor(if_false, IrOpcode::kLoop);
+ // TODO(titzer): check the internal copy of loop2.
+ USE(new_loop1_loop);
+
+ // Check structure of new_loop0.
+ Node* new_loop0_loop_entry = FindSuccessor(if_true, IrOpcode::kMerge);
+ Node* new_loop0_loop = FindSuccessor(new_loop0_loop_entry, IrOpcode::kLoop);
+ // TODO(titzer): check the internal copies of loop1 and loop2.
+
+ Node* new_loop0_branch = FindSuccessor(new_loop0_loop, IrOpcode::kBranch);
+ Node* new_loop0_if_true = FindSuccessor(new_loop0_branch, IrOpcode::kIfTrue);
+ Node* new_loop0_exit = FindSuccessor(new_loop0_branch, IrOpcode::kIfFalse);
+
+ USE(new_loop0_if_true);
+
+ Node* new_ret = T.graph.end()->InputAt(0);
+ CHECK_EQ(IrOpcode::kReturn, new_ret->opcode());
+
+ Node* new_loop0_phi = new_ret->InputAt(0);
+ CHECK_EQ(IrOpcode::kPhi, new_loop0_phi->opcode());
+ CHECK_EQ(new_loop0_loop, NodeProperties::GetControlInput(new_loop0_phi));
+ CHECK_EQ(new_loop0_phi, FindSuccessor(new_loop0_loop, IrOpcode::kPhi));
+
+ // Check that the return returns the phi from the OSR loop and control
+ // depends on the copy of the outer loop0.
+ CheckInputs(new_ret, new_loop0_phi, T.graph.start(), new_loop0_exit);
+}
diff --git a/deps/v8/test/cctest/compiler/test-pipeline.cc b/deps/v8/test/cctest/compiler/test-pipeline.cc
index 98b0baeefd..b67af6ecf7 100644
--- a/deps/v8/test/cctest/compiler/test-pipeline.cc
+++ b/deps/v8/test/cctest/compiler/test-pipeline.cc
@@ -17,13 +17,13 @@ using namespace v8::internal;
using namespace v8::internal::compiler;
TEST(PipelineAdd) {
- InitializedHandleScope handles;
+ HandleAndZoneScope handles;
const char* source = "(function(a,b) { return a + b; })";
Handle<JSFunction> function = v8::Utils::OpenHandle(
*v8::Handle<v8::Function>::Cast(CompileRun(source)));
- CompilationInfoWithZone info(function);
-
- CHECK(Compiler::ParseAndAnalyze(&info));
+ ParseInfo parse_info(handles.main_zone(), function);
+ CHECK(Compiler::ParseAndAnalyze(&parse_info));
+ CompilationInfo info(&parse_info);
Pipeline pipeline(&info);
#if V8_TURBOFAN_TARGET
diff --git a/deps/v8/test/cctest/compiler/test-run-inlining.cc b/deps/v8/test/cctest/compiler/test-run-inlining.cc
index 19b96bad50..a6d76e4d57 100644
--- a/deps/v8/test/cctest/compiler/test-run-inlining.cc
+++ b/deps/v8/test/cctest/compiler/test-run-inlining.cc
@@ -11,9 +11,11 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
+namespace {
+
// Helper to determine inline count via JavaScriptFrame::GetInlineCount.
// Note that a count of 1 indicates that no inlining has occured.
-static void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
+void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
StackTraceFrameIterator it(CcTest::i_isolate());
int frames_seen = 0;
JavaScriptFrame* topmost = it.frame();
@@ -30,7 +32,7 @@ static void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
-static void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
+void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::FunctionTemplate> t =
v8::FunctionTemplate::New(isolate, AssertInlineCount);
@@ -38,9 +40,15 @@ static void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
}
-static uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
- CompilationInfo::kContextSpecializing |
- CompilationInfo::kTypingEnabled;
+const uint32_t kBuiltinInlineFlags = CompilationInfo::kBuiltinInliningEnabled |
+ CompilationInfo::kContextSpecializing |
+ CompilationInfo::kTypingEnabled;
+
+const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
+ CompilationInfo::kContextSpecializing |
+ CompilationInfo::kTypingEnabled;
+
+} // namespace
TEST(SimpleInlining) {
@@ -320,6 +328,53 @@ TEST(InlineLoopGuardedTwice) {
}
+TEST(InlineLoopUnguardedEmpty) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T(
+ "(function () {"
+ " function foo(s) { AssertInlineCount(2); while (s); return s; };"
+ " function bar(s, t) { return foo(s); };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
+}
+
+
+TEST(InlineLoopUnguardedOnce) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T(
+ "(function () {"
+ " function foo(s) { AssertInlineCount(2); while (s) {"
+ " s = s - 1; }; return s; };"
+ " function bar(s, t) { return foo(s); };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
+}
+
+
+TEST(InlineLoopUnguardedTwice) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T(
+ "(function () {"
+ " function foo(s) { AssertInlineCount(2); while (s > 0) {"
+ " s = s - 1; }; return s; };"
+ " function bar(s,t) { return foo(foo(s,t),t); };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
+}
+
+
TEST(InlineStrictIntoNonStrict) {
FLAG_turbo_deoptimization = true;
FunctionTester T(
@@ -437,4 +492,38 @@ TEST(InlineWithArguments) {
T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
}
+
+TEST(InlineBuiltin) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T(
+ "(function () {"
+ " function foo(s,t,u) { AssertInlineCount(2); return true; }"
+ " function bar() { return foo(); };"
+ " %SetInlineBuiltinFlag(foo);"
+ " return bar;"
+ "})();",
+ kBuiltinInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.true_value());
+}
+
+
+TEST(InlineNestedBuiltin) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T(
+ "(function () {"
+ " function foo(s,t,u) { AssertInlineCount(3); return true; }"
+ " function baz(s,t,u) { return foo(s,t,u); }"
+ " function bar() { return baz(); };"
+ " %SetInlineBuiltinFlag(foo);"
+ " %SetInlineBuiltinFlag(baz);"
+ " return bar;"
+ "})();",
+ kBuiltinInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.true_value());
+}
+
#endif // V8_TURBOFAN_TARGET
diff --git a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc
index bd4038ed91..7fc5cc9758 100644
--- a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc
+++ b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc
@@ -10,29 +10,98 @@ using namespace v8::internal;
using namespace v8::internal::compiler;
uint32_t flags = CompilationInfo::kInliningEnabled;
-TEST(IsSmi) {
+
+TEST(CallFunction) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsSmi(a); })", flags);
+ FunctionTester T("(function(a,b) { return %_CallFunction(a, 1, 2, 3, b); })",
+ flags);
+ CompileRun("function f(a,b,c) { return a + b + c + this.d; }");
- T.CheckTrue(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckFalse(T.Val(-0.0));
- T.CheckTrue(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
+ T.CheckCall(T.Val(129), T.NewObject("({d:123})"), T.NewObject("f"));
+ T.CheckCall(T.Val("6x"), T.NewObject("({d:'x'})"), T.NewObject("f"));
+}
+
+
+TEST(ClassOf) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T("(function(a) { return %_ClassOf(a); })", flags);
+
+ T.CheckCall(T.Val("Function"), T.NewObject("(function() {})"));
+ T.CheckCall(T.Val("Array"), T.NewObject("([1])"));
+ T.CheckCall(T.Val("Object"), T.NewObject("({})"));
+ T.CheckCall(T.Val("RegExp"), T.NewObject("(/x/)"));
+ T.CheckCall(T.null(), T.undefined());
+ T.CheckCall(T.null(), T.null());
+ T.CheckCall(T.null(), T.Val("x"));
+ T.CheckCall(T.null(), T.Val(1));
+}
+
+
+TEST(HeapObjectGetMap) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T("(function(a) { return %_HeapObjectGetMap(a); })", flags);
+
+ Factory* factory = T.main_isolate()->factory();
+ T.CheckCall(factory->null_map(), T.null());
+ T.CheckCall(factory->undefined_map(), T.undefined());
+ T.CheckCall(factory->heap_number_map(), T.Val(3.1415));
+ T.CheckCall(factory->symbol_map(), factory->NewSymbol());
+}
+
+
+#define COUNTER_NAME "hurz"
+
+static int* LookupCounter(const char* name) {
+ static int counter = 1234;
+ return strcmp(name, COUNTER_NAME) == 0 ? &counter : nullptr;
+}
+
+
+TEST(IncrementStatsCounter) {
+ FLAG_turbo_deoptimization = true;
+ FLAG_native_code_counters = true;
+ reinterpret_cast<v8::Isolate*>(CcTest::InitIsolateOnce())
+ ->SetCounterFunction(LookupCounter);
+ FunctionTester T(
+ "(function() { %_IncrementStatsCounter('" COUNTER_NAME "'); })", flags);
+ StatsCounter counter(T.main_isolate(), COUNTER_NAME);
+ if (!counter.Enabled()) return;
+
+ int old_value = *counter.GetInternalPointer();
+ T.CheckCall(T.undefined());
+ CHECK_EQ(old_value + 1, *counter.GetInternalPointer());
+}
+
+#undef COUNTER_NAME
+
+
+TEST(IsArray) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T("(function(a) { return %_IsArray(a); })", flags);
+
+ T.CheckFalse(T.NewObject("(function() {})"));
+ T.CheckTrue(T.NewObject("([1])"));
+ T.CheckFalse(T.NewObject("({})"));
+ T.CheckFalse(T.NewObject("(/x/)"));
T.CheckFalse(T.undefined());
+ T.CheckFalse(T.null());
+ T.CheckFalse(T.Val("x"));
+ T.CheckFalse(T.Val(1));
}
-TEST(IsNonNegativeSmi) {
+TEST(IsFunction) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsNonNegativeSmi(a); })", flags);
+ FunctionTester T("(function(a) { return %_IsFunction(a); })", flags);
- T.CheckTrue(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckFalse(T.Val(-0.0));
- T.CheckFalse(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
+ T.CheckTrue(T.NewObject("(function() {})"));
+ T.CheckFalse(T.NewObject("([1])"));
+ T.CheckFalse(T.NewObject("({})"));
+ T.CheckFalse(T.NewObject("(/x/)"));
T.CheckFalse(T.undefined());
+ T.CheckFalse(T.null());
+ T.CheckFalse(T.Val("x"));
+ T.CheckFalse(T.Val(1));
}
@@ -49,18 +118,16 @@ TEST(IsMinusZero) {
}
-TEST(IsArray) {
+TEST(IsNonNegativeSmi) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsArray(a); })", flags);
+ FunctionTester T("(function(a) { return %_IsNonNegativeSmi(a); })", flags);
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckTrue(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckFalse(T.NewObject("(/x/)"));
+ T.CheckTrue(T.Val(1));
+ T.CheckFalse(T.Val(1.1));
+ T.CheckFalse(T.Val(-0.0));
+ T.CheckFalse(T.Val(-2));
+ T.CheckFalse(T.Val(-2.3));
T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
}
@@ -79,14 +146,14 @@ TEST(IsObject) {
}
-TEST(IsFunction) {
+TEST(IsRegExp) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsFunction(a); })", flags);
+ FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
- T.CheckTrue(T.NewObject("(function() {})"));
+ T.CheckFalse(T.NewObject("(function() {})"));
T.CheckFalse(T.NewObject("([1])"));
T.CheckFalse(T.NewObject("({})"));
- T.CheckFalse(T.NewObject("(/x/)"));
+ T.CheckTrue(T.NewObject("(/x/)"));
T.CheckFalse(T.undefined());
T.CheckFalse(T.null());
T.CheckFalse(T.Val("x"));
@@ -94,33 +161,30 @@ TEST(IsFunction) {
}
-TEST(IsRegExp) {
+TEST(IsSmi) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
+ FunctionTester T("(function(a) { return %_IsSmi(a); })", flags);
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckFalse(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(/x/)"));
+ T.CheckTrue(T.Val(1));
+ T.CheckFalse(T.Val(1.1));
+ T.CheckFalse(T.Val(-0.0));
+ T.CheckTrue(T.Val(-2));
+ T.CheckFalse(T.Val(-2.3));
T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
}
-TEST(ClassOf) {
+TEST(MapGetInstanceType) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_ClassOf(a); })", flags);
-
- T.CheckCall(T.Val("Function"), T.NewObject("(function() {})"));
- T.CheckCall(T.Val("Array"), T.NewObject("([1])"));
- T.CheckCall(T.Val("Object"), T.NewObject("({})"));
- T.CheckCall(T.Val("RegExp"), T.NewObject("(/x/)"));
- T.CheckCall(T.null(), T.undefined());
- T.CheckCall(T.null(), T.null());
- T.CheckCall(T.null(), T.Val("x"));
- T.CheckCall(T.null(), T.Val(1));
+ FunctionTester T(
+ "(function(a) { return %_MapGetInstanceType(%_HeapObjectGetMap(a)); })",
+ flags);
+
+ Factory* factory = T.main_isolate()->factory();
+ T.CheckCall(T.Val(ODDBALL_TYPE), T.null());
+ T.CheckCall(T.Val(ODDBALL_TYPE), T.undefined());
+ T.CheckCall(T.Val(HEAP_NUMBER_TYPE), T.Val(3.1415));
+ T.CheckCall(T.Val(SYMBOL_TYPE), factory->NewSymbol());
}
@@ -138,14 +202,48 @@ TEST(ObjectEquals) {
}
-TEST(ValueOf) {
+TEST(OneByteSeqStringGetChar) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_ValueOf(a); })", flags);
+ FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })",
+ flags);
- T.CheckCall(T.Val("a"), T.Val("a"));
- T.CheckCall(T.Val("b"), T.NewObject("(new String('b'))"));
- T.CheckCall(T.Val(123), T.Val(123));
- T.CheckCall(T.Val(456), T.NewObject("(new Number(456))"));
+ Handle<SeqOneByteString> string =
+ T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
+ string->SeqOneByteStringSet(0, 'b');
+ string->SeqOneByteStringSet(1, 'a');
+ string->SeqOneByteStringSet(2, 'r');
+ T.CheckCall(T.Val('b'), string, T.Val(0.0));
+ T.CheckCall(T.Val('a'), string, T.Val(1));
+ T.CheckCall(T.Val('r'), string, T.Val(2));
+}
+
+
+TEST(OneByteSeqStringSetChar) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T("(function(a,b) { %_OneByteSeqStringSetChar(a,88,b); })",
+ flags);
+
+ Handle<SeqOneByteString> string =
+ T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
+ string->SeqOneByteStringSet(0, 'b');
+ string->SeqOneByteStringSet(1, 'a');
+ string->SeqOneByteStringSet(2, 'r');
+ T.Call(T.Val(1), string);
+ CHECK_EQ('b', string->SeqOneByteStringGet(0));
+ CHECK_EQ('X', string->SeqOneByteStringGet(1));
+ CHECK_EQ('r', string->SeqOneByteStringGet(2));
+}
+
+
+TEST(NewConsString) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T(
+ "(function() { "
+ " return %_NewConsString(14, true, 'abcdefghi', 'jklmn');"
+ " })",
+ flags);
+
+ T.CheckCall(T.Val("abcdefghijklmn"));
}
@@ -159,13 +257,13 @@ TEST(SetValueOf) {
}
-TEST(StringCharFromCode) {
+TEST(StringAdd) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_StringCharFromCode(a); })", flags);
+ FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
- T.CheckCall(T.Val("a"), T.Val(97));
- T.CheckCall(T.Val("\xE2\x9D\x8A"), T.Val(0x274A));
- T.CheckCall(T.Val(""), T.undefined());
+ T.CheckCall(T.Val("aaabbb"), T.Val("aaa"), T.Val("bbb"));
+ T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(""));
+ T.CheckCall(T.Val("bbb"), T.Val(""), T.Val("bbb"));
}
@@ -190,17 +288,27 @@ TEST(StringCharCodeAt) {
}
-TEST(StringAdd) {
+TEST(StringCharFromCode) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
+ FunctionTester T("(function(a) { return %_StringCharFromCode(a); })", flags);
- T.CheckCall(T.Val("aaabbb"), T.Val("aaa"), T.Val("bbb"));
- T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(""));
- T.CheckCall(T.Val("bbb"), T.Val(""), T.Val("bbb"));
+ T.CheckCall(T.Val("a"), T.Val(97));
+ T.CheckCall(T.Val("\xE2\x9D\x8A"), T.Val(0x274A));
+ T.CheckCall(T.Val(""), T.undefined());
+}
+
+
+TEST(StringCompare) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T("(function(a,b) { return %_StringCompare(a,b); })", flags);
+
+ T.CheckCall(T.Val(-1), T.Val("aaa"), T.Val("bbb"));
+ T.CheckCall(T.Val(0.0), T.Val("bbb"), T.Val("bbb"));
+ T.CheckCall(T.Val(+1), T.Val("ccc"), T.Val("bbb"));
}
-TEST(StringSubString) {
+TEST(SubString) {
FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_SubString(a,b,b+3); })", flags);
@@ -210,22 +318,45 @@ TEST(StringSubString) {
}
-TEST(StringCompare) {
+TEST(TwoByteSeqStringGetChar) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a,b) { return %_StringCompare(a,b); })", flags);
+ FunctionTester T("(function(a,b) { return %_TwoByteSeqStringGetChar(a,b); })",
+ flags);
- T.CheckCall(T.Val(-1), T.Val("aaa"), T.Val("bbb"));
- T.CheckCall(T.Val(0.0), T.Val("bbb"), T.Val("bbb"));
- T.CheckCall(T.Val(+1), T.Val("ccc"), T.Val("bbb"));
+ Handle<SeqTwoByteString> string =
+ T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
+ string->SeqTwoByteStringSet(0, 'b');
+ string->SeqTwoByteStringSet(1, 'a');
+ string->SeqTwoByteStringSet(2, 'r');
+ T.CheckCall(T.Val('b'), string, T.Val(0.0));
+ T.CheckCall(T.Val('a'), string, T.Val(1));
+ T.CheckCall(T.Val('r'), string, T.Val(2));
}
-TEST(CallFunction) {
+TEST(TwoByteSeqStringSetChar) {
FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a,b) { return %_CallFunction(a, 1, 2, 3, b); })",
+ FunctionTester T("(function(a,b) { %_TwoByteSeqStringSetChar(a,88,b); })",
flags);
- CompileRun("function f(a,b,c) { return a + b + c + this.d; }");
- T.CheckCall(T.Val(129), T.NewObject("({d:123})"), T.NewObject("f"));
- T.CheckCall(T.Val("6x"), T.NewObject("({d:'x'})"), T.NewObject("f"));
+ Handle<SeqTwoByteString> string =
+ T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
+ string->SeqTwoByteStringSet(0, 'b');
+ string->SeqTwoByteStringSet(1, 'a');
+ string->SeqTwoByteStringSet(2, 'r');
+ T.Call(T.Val(1), string);
+ CHECK_EQ('b', string->SeqTwoByteStringGet(0));
+ CHECK_EQ('X', string->SeqTwoByteStringGet(1));
+ CHECK_EQ('r', string->SeqTwoByteStringGet(2));
+}
+
+
+TEST(ValueOf) {
+ FLAG_turbo_deoptimization = true;
+ FunctionTester T("(function(a) { return %_ValueOf(a); })", flags);
+
+ T.CheckCall(T.Val("a"), T.Val("a"));
+ T.CheckCall(T.Val("b"), T.NewObject("(new String('b'))"));
+ T.CheckCall(T.Val(123), T.Val(123));
+ T.CheckCall(T.Val(456), T.NewObject("(new Number(456))"));
}
diff --git a/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc b/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc
index 74990daac9..f06dc5f315 100644
--- a/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc
+++ b/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc
@@ -18,7 +18,8 @@ TEST(Throw) {
}
-TEST(ThrowSourcePosition) {
+TEST(ThrowMessagePosition) {
+ i::FLAG_turbo_exceptions = true;
static const char* src =
"(function(a, b) { \n"
" if (a == 1) throw 1; \n"
@@ -30,22 +31,57 @@ TEST(ThrowSourcePosition) {
v8::Handle<v8::Message> message;
message = T.CheckThrowsReturnMessage(T.Val(1), T.undefined());
- CHECK(!message.IsEmpty());
CHECK_EQ(2, message->GetLineNumber());
CHECK_EQ(40, message->GetStartPosition());
message = T.CheckThrowsReturnMessage(T.Val(2), T.undefined());
- CHECK(!message.IsEmpty());
CHECK_EQ(3, message->GetLineNumber());
CHECK_EQ(67, message->GetStartPosition());
message = T.CheckThrowsReturnMessage(T.Val(3), T.undefined());
- CHECK(!message.IsEmpty());
CHECK_EQ(4, message->GetLineNumber());
CHECK_EQ(95, message->GetStartPosition());
}
+TEST(ThrowMessageDirectly) {
+ i::FLAG_turbo_exceptions = true;
+ static const char* src =
+ "(function(a, b) {"
+ " if (a) { throw b; } else { throw new Error(b); }"
+ "})";
+ FunctionTester T(src);
+ v8::Handle<v8::Message> message;
+
+ message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
+ CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?")));
+
+ message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
+ CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!")));
+}
+
+
+TEST(ThrowMessageIndirectly) {
+ i::FLAG_turbo_exceptions = true;
+ static const char* src =
+ "(function(a, b) {"
+ " try {"
+ " if (a) { throw b; } else { throw new Error(b); }"
+ " } finally {"
+ " try { throw 'clobber'; } catch (e) { 'unclobber'; }"
+ " }"
+ "})";
+ FunctionTester T(src);
+ v8::Handle<v8::Message> message;
+
+ message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
+ CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?")));
+
+ message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
+ CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!")));
+}
+
+
// TODO(mstarzinger): Increase test coverage by having similar tests within the
// mjsunit suite to also test integration with other components (e.g. OSR).
@@ -118,6 +154,28 @@ TEST(CatchBreak) {
}
+TEST(CatchCall) {
+ i::FLAG_turbo_exceptions = true;
+ const char* src =
+ "(function(fun) {"
+ " var r = '-';"
+ " try {"
+ " r += 'A-';"
+ " return r + 'B-' + fun();"
+ " } catch (e) {"
+ " r += e;"
+ " }"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ CompileRun("function thrower() { throw 'T-'; }");
+ T.CheckCall(T.Val("-A-T-"), T.NewFunction("thrower"));
+ CompileRun("function returner() { return 'R-'; }");
+ T.CheckCall(T.Val("-A-B-R-"), T.NewFunction("returner"));
+}
+
+
TEST(Finally) {
i::FLAG_turbo_exceptions = true;
const char* src =
@@ -158,3 +216,76 @@ TEST(FinallyBreak) {
T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value());
T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value());
}
+
+
+TEST(DeoptTry) {
+ i::FLAG_turbo_exceptions = true;
+ i::FLAG_turbo_deoptimization = true;
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " %DeoptimizeFunction(f);"
+ " throw a;"
+ " } catch (e) {"
+ " return e + 1;"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val(2), T.Val(1));
+}
+
+
+TEST(DeoptCatch) {
+ i::FLAG_turbo_exceptions = true;
+ i::FLAG_turbo_deoptimization = true;
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " throw a;"
+ " } catch (e) {"
+ " %DeoptimizeFunction(f);"
+ " return e + 1;"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val(2), T.Val(1));
+}
+
+
+TEST(DeoptFinallyReturn) {
+ i::FLAG_turbo_exceptions = true;
+ i::FLAG_turbo_deoptimization = true;
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " throw a;"
+ " } finally {"
+ " %DeoptimizeFunction(f);"
+ " return a + 1;"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val(2), T.Val(1));
+}
+
+
+TEST(DeoptFinallyReThrow) {
+ i::FLAG_turbo_exceptions = true;
+ i::FLAG_turbo_deoptimization = true;
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " throw a;"
+ " } finally {"
+ " %DeoptimizeFunction(f);"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+#if 0 // TODO(mstarzinger): Enable once we can.
+ T.CheckThrows(T.NewObject("new Error"), T.Val(1));
+#endif
+}
diff --git a/deps/v8/test/cctest/compiler/test-run-jsops.cc b/deps/v8/test/cctest/compiler/test-run-jsops.cc
index bb7c239a59..032db82db3 100644
--- a/deps/v8/test/cctest/compiler/test-run-jsops.cc
+++ b/deps/v8/test/cctest/compiler/test-run-jsops.cc
@@ -451,7 +451,6 @@ TEST(LookupStore) {
TEST(BlockLoadStore) {
- FLAG_harmony_scoping = true;
FunctionTester T("(function(a) { 'use strict'; { let x = a+a; return x; }})");
T.CheckCall(T.Val(46), T.Val(23));
@@ -460,7 +459,6 @@ TEST(BlockLoadStore) {
TEST(BlockLoadStoreNested) {
- FLAG_harmony_scoping = true;
const char* src =
"(function(a,b) {"
"'use strict';"
diff --git a/deps/v8/test/cctest/compiler/test-run-machops.cc b/deps/v8/test/cctest/compiler/test-run-machops.cc
index 5a55ce6e23..102e6d8ad4 100644
--- a/deps/v8/test/cctest/compiler/test-run-machops.cc
+++ b/deps/v8/test/cctest/compiler/test-run-machops.cc
@@ -4436,6 +4436,26 @@ TEST(RunInt32SubWithOverflowInBranchP) {
}
+TEST(RunWord64EqualInBranchP) {
+ int64_t input;
+ MLabel blocka, blockb;
+ RawMachineAssemblerTester<int64_t> m;
+ if (!m.machine()->Is64()) return;
+ Node* value = m.LoadFromPointer(&input, kMachInt64);
+ m.Branch(m.Word64Equal(value, m.Int64Constant(0)), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(2));
+ input = V8_INT64_C(0);
+ CHECK_EQ(1, m.Call());
+ input = V8_INT64_C(1);
+ CHECK_EQ(2, m.Call());
+ input = V8_INT64_C(0x100000000);
+ CHECK_EQ(2, m.Call());
+}
+
+
TEST(RunChangeInt32ToInt64P) {
if (kPointerSize < 8) return;
int64_t actual = -1;
@@ -4627,6 +4647,72 @@ TEST(RunFloat32Constant) {
}
+TEST(RunFloat64ExtractLowWord32) {
+ uint64_t input = 0;
+ RawMachineAssemblerTester<int32_t> m;
+ m.Return(m.Float64ExtractLowWord32(m.LoadFromPointer(&input, kMachFloat64)));
+ FOR_FLOAT64_INPUTS(i) {
+ input = bit_cast<uint64_t>(*i);
+ int32_t expected = bit_cast<int32_t>(static_cast<uint32_t>(input));
+ CHECK_EQ(expected, m.Call());
+ }
+}
+
+
+TEST(RunFloat64ExtractHighWord32) {
+ uint64_t input = 0;
+ RawMachineAssemblerTester<int32_t> m;
+ m.Return(m.Float64ExtractHighWord32(m.LoadFromPointer(&input, kMachFloat64)));
+ FOR_FLOAT64_INPUTS(i) {
+ input = bit_cast<uint64_t>(*i);
+ int32_t expected = bit_cast<int32_t>(static_cast<uint32_t>(input >> 32));
+ CHECK_EQ(expected, m.Call());
+ }
+}
+
+
+TEST(RunFloat64InsertLowWord32) {
+ uint64_t input = 0;
+ uint64_t result = 0;
+ RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ m.StoreToPointer(
+ &result, kMachFloat64,
+ m.Float64InsertLowWord32(m.LoadFromPointer(&input, kMachFloat64),
+ m.Parameter(0)));
+ m.Return(m.Int32Constant(0));
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ input = bit_cast<uint64_t>(*i);
+ uint64_t expected = (input & ~(V8_UINT64_C(0xFFFFFFFF))) |
+ (static_cast<uint64_t>(bit_cast<uint32_t>(*j)));
+ CHECK_EQ(0, m.Call(*j));
+ CHECK_EQ(expected, result);
+ }
+ }
+}
+
+
+TEST(RunFloat64InsertHighWord32) {
+ uint64_t input = 0;
+ uint64_t result = 0;
+ RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ m.StoreToPointer(
+ &result, kMachFloat64,
+ m.Float64InsertHighWord32(m.LoadFromPointer(&input, kMachFloat64),
+ m.Parameter(0)));
+ m.Return(m.Int32Constant(0));
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ input = bit_cast<uint64_t>(*i);
+ uint64_t expected = (input & ~(V8_UINT64_C(0xFFFFFFFF) << 32)) |
+ (static_cast<uint64_t>(bit_cast<uint32_t>(*j)) << 32);
+ CHECK_EQ(0, m.Call(*j));
+ CHECK_EQ(expected, result);
+ }
+ }
+}
+
+
static double two_30 = 1 << 30; // 2^30 is a smi boundary.
static double two_52 = two_30 * (1 << 22); // 2^52 is a precision boundary.
static double kValues[] = {0.1,
@@ -4725,13 +4811,13 @@ static double kValues[] = {0.1,
-two_52 + 1 - 0.7};
-TEST(RunFloat64Floor) {
+TEST(RunFloat64RoundDown1) {
double input = -1.0;
double result = 0.0;
RawMachineAssemblerTester<int32_t> m;
- if (!m.machine()->HasFloat64Floor()) return;
+ if (!m.machine()->HasFloat64RoundDown()) return;
m.StoreToPointer(&result, kMachFloat64,
- m.Float64Floor(m.LoadFromPointer(&input, kMachFloat64)));
+ m.Float64RoundDown(m.LoadFromPointer(&input, kMachFloat64)));
m.Return(m.Int32Constant(0));
for (size_t i = 0; i < arraysize(kValues); ++i) {
input = kValues[i];
@@ -4742,13 +4828,16 @@ TEST(RunFloat64Floor) {
}
-TEST(RunFloat64Ceil) {
+TEST(RunFloat64RoundDown2) {
double input = -1.0;
double result = 0.0;
RawMachineAssemblerTester<int32_t> m;
- if (!m.machine()->HasFloat64Ceil()) return;
+ if (!m.machine()->HasFloat64RoundDown()) return;
m.StoreToPointer(&result, kMachFloat64,
- m.Float64Ceil(m.LoadFromPointer(&input, kMachFloat64)));
+ m.Float64Sub(m.Float64Constant(-0.0),
+ m.Float64RoundDown(m.Float64Sub(
+ m.Float64Constant(-0.0),
+ m.LoadFromPointer(&input, kMachFloat64)))));
m.Return(m.Int32Constant(0));
for (size_t i = 0; i < arraysize(kValues); ++i) {
input = kValues[i];
@@ -4763,7 +4852,7 @@ TEST(RunFloat64RoundTruncate) {
double input = -1.0;
double result = 0.0;
RawMachineAssemblerTester<int32_t> m;
- if (!m.machine()->HasFloat64Ceil()) return;
+ if (!m.machine()->HasFloat64RoundTruncate()) return;
m.StoreToPointer(
&result, kMachFloat64,
m.Float64RoundTruncate(m.LoadFromPointer(&input, kMachFloat64)));
@@ -4793,4 +4882,5 @@ TEST(RunFloat64RoundTiesAway) {
CHECK_EQ(expected, result);
}
}
+
#endif // V8_TURBOFAN_TARGET
diff --git a/deps/v8/test/cctest/compiler/test-run-stubs.cc b/deps/v8/test/cctest/compiler/test-run-stubs.cc
new file mode 100644
index 0000000000..daf9a461b1
--- /dev/null
+++ b/deps/v8/test/cctest/compiler/test-run-stubs.cc
@@ -0,0 +1,106 @@
+// Copyright 2015 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/bootstrapper.h"
+#include "src/code-stubs.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/pipeline.h"
+#include "src/parser.h"
+#include "test/cctest/compiler/function-tester.h"
+
+#if V8_TURBOFAN_TARGET
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+
+static Handle<JSFunction> GetFunction(Isolate* isolate, const char* name) {
+ v8::ExtensionConfiguration no_extensions;
+ Handle<Context> ctx = isolate->bootstrapper()->CreateEnvironment(
+ MaybeHandle<JSGlobalProxy>(), v8::Handle<v8::ObjectTemplate>(),
+ &no_extensions);
+ Handle<JSBuiltinsObject> builtins = handle(ctx->builtins());
+ MaybeHandle<Object> fun = Object::GetProperty(isolate, builtins, name);
+ Handle<JSFunction> function = Handle<JSFunction>::cast(fun.ToHandleChecked());
+ // Just to make sure nobody calls this...
+ function->set_code(isolate->builtins()->builtin(Builtins::kIllegal));
+ return function;
+}
+
+
+class StringLengthStubTF : public CodeStub {
+ public:
+ explicit StringLengthStubTF(Isolate* isolate) : CodeStub(isolate) {}
+
+ StringLengthStubTF(uint32_t key, Isolate* isolate) : CodeStub(key, isolate) {}
+
+ CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
+ return LoadDescriptor(isolate());
+ };
+
+ Handle<Code> GenerateCode() OVERRIDE {
+ Zone zone;
+ // Build a "hybrid" CompilationInfo for a JSFunction/CodeStub pair.
+ ParseInfo parse_info(&zone, GetFunction(isolate(), "STRING_LENGTH_STUB"));
+ CompilationInfo info(&parse_info);
+ info.SetStub(this);
+ // Run a "mini pipeline", extracted from compiler.cc.
+ CHECK(Parser::ParseStatic(info.parse_info()));
+ CHECK(Compiler::Analyze(info.parse_info()));
+ return Pipeline(&info).GenerateCode();
+ }
+
+ Major MajorKey() const OVERRIDE { return StringLength; };
+ Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; }
+ InlineCacheState GetICState() const OVERRIDE { return MONOMORPHIC; }
+ ExtraICState GetExtraICState() const OVERRIDE { return Code::LOAD_IC; }
+ Code::StubType GetStubType() const OVERRIDE { return Code::FAST; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StringLengthStubTF);
+};
+
+
+TEST(RunStringLengthStubTF) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ // Create code and an accompanying descriptor.
+ StringLengthStubTF stub(isolate);
+ Handle<Code> code = stub.GenerateCode();
+ CompilationInfo info(&stub, isolate, zone);
+ CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info);
+
+ // Create a function to call the code using the descriptor.
+ Graph graph(zone);
+ CommonOperatorBuilder common(zone);
+ // FunctionTester (ab)uses a 2-argument function
+ Node* start = graph.NewNode(common.Start(2));
+ // Parameter 0 is the receiver
+ Node* receiverParam = graph.NewNode(common.Parameter(1), start);
+ Node* nameParam = graph.NewNode(common.Parameter(2), start);
+ Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code);
+ Node* theCode = graph.NewNode(common.HeapConstant(u));
+ Node* dummyContext = graph.NewNode(common.NumberConstant(0.0));
+ Node* call = graph.NewNode(common.Call(descriptor), theCode, receiverParam,
+ nameParam, dummyContext, start, start);
+ Node* ret = graph.NewNode(common.Return(), call, call, start);
+ Node* end = graph.NewNode(common.End(), ret);
+ graph.SetStart(start);
+ graph.SetEnd(end);
+ FunctionTester ft(&graph);
+
+ // Actuall call through to the stub, verifying its result.
+ const char* testString = "Und das Lamm schrie HURZ!";
+ Handle<JSReceiver> receiverArg =
+ Object::ToObject(isolate, ft.Val(testString)).ToHandleChecked();
+ Handle<String> nameArg = ft.Val("length");
+ Handle<Object> result = ft.Call(receiverArg, nameArg).ToHandleChecked();
+ CHECK_EQ(static_cast<int>(strlen(testString)), Smi::cast(*result)->value());
+}
+
+#endif // V8_TURBOFAN_TARGET
diff --git a/deps/v8/test/cctest/compiler/test-run-variables.cc b/deps/v8/test/cctest/compiler/test-run-variables.cc
index bf86e0d42c..4e5fd181f4 100644
--- a/deps/v8/test/cctest/compiler/test-run-variables.cc
+++ b/deps/v8/test/cctest/compiler/test-run-variables.cc
@@ -49,7 +49,6 @@ static const char* bind_tests[] = {
static void RunVariableTests(const char* source, const char* tests[]) {
- FLAG_harmony_scoping = true;
EmbeddedVector<char, 512> buffer;
for (int i = 0; tests[i] != NULL; i += 3) {
diff --git a/deps/v8/test/cctest/compiler/test-simplified-lowering.cc b/deps/v8/test/cctest/compiler/test-simplified-lowering.cc
index 6e2480e51e..634483bf24 100644
--- a/deps/v8/test/cctest/compiler/test-simplified-lowering.cc
+++ b/deps/v8/test/cctest/compiler/test-simplified-lowering.cc
@@ -790,25 +790,6 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
};
-#if V8_TURBOFAN_TARGET
-
-TEST(LowerAnyToBoolean_tagged_tagged) {
- // AnyToBoolean(x: kRepTagged) used as kRepTagged
- TestingGraph t(Type::Any());
- Node* x = t.p0;
- Node* cnv = t.graph()->NewNode(t.simplified()->AnyToBoolean(), x);
- Node* use = t.Use(cnv, kRepTagged);
- t.Return(use);
- t.Lower();
- CHECK_EQ(IrOpcode::kCall, cnv->opcode());
- CHECK_EQ(IrOpcode::kHeapConstant, cnv->InputAt(0)->opcode());
- CHECK_EQ(x, cnv->InputAt(1));
- CHECK_EQ(t.jsgraph.NoContextConstant(), cnv->InputAt(2));
-}
-
-#endif
-
-
TEST(LowerBooleanNot_bit_bit) {
// BooleanNot(x: kRepBit) used as kRepBit
TestingGraph t(Type::Boolean());
@@ -1441,27 +1422,43 @@ TEST(LowerLoadField_to_load) {
TEST(LowerStoreField_to_store) {
- TestingGraph t(Type::Any(), Type::Signed32());
+ {
+ TestingGraph t(Type::Any(), Type::Signed32());
- for (size_t i = 0; i < arraysize(kMachineReps); i++) {
- FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Handle<Name>::null(), Type::Any(), kMachineReps[i]};
+ for (size_t i = 0; i < arraysize(kMachineReps); i++) {
+ FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Handle<Name>::null(), Type::Any(), kMachineReps[i]};
- Node* val = t.ExampleWithOutput(kMachineReps[i]);
+ Node* val = t.ExampleWithOutput(kMachineReps[i]);
+ Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
+ val, t.start, t.start);
+ t.Effect(store);
+ t.Lower();
+ CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(val, store->InputAt(2));
+ CheckFieldAccessArithmetic(access, store);
+
+ StoreRepresentation rep = OpParameter<StoreRepresentation>(store);
+ if (kMachineReps[i] & kRepTagged) {
+ CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+ }
+ CHECK_EQ(kMachineReps[i], rep.machine_type());
+ }
+ }
+ {
+ TestingGraph t(Type::Any(),
+ Type::Intersect(Type::SignedSmall(), Type::TaggedSigned()));
+ FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Handle<Name>::null(), Type::Any(), kMachAnyTagged};
Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
- val, t.start, t.start);
+ t.p1, t.start, t.start);
t.Effect(store);
t.Lower();
CHECK_EQ(IrOpcode::kStore, store->opcode());
- CHECK_EQ(val, store->InputAt(2));
- CheckFieldAccessArithmetic(access, store);
-
+ CHECK_EQ(t.p1, store->InputAt(2));
StoreRepresentation rep = OpParameter<StoreRepresentation>(store);
- if (kMachineReps[i] & kRepTagged) {
- CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
- }
- CHECK_EQ(kMachineReps[i], rep.machine_type());
+ CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
}
}
@@ -1489,26 +1486,42 @@ TEST(LowerLoadElement_to_load) {
TEST(LowerStoreElement_to_store) {
- TestingGraph t(Type::Any(), Type::Signed32());
+ {
+ TestingGraph t(Type::Any(), Type::Signed32());
- for (size_t i = 0; i < arraysize(kMachineReps); i++) {
- ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Type::Any(), kMachineReps[i]};
+ for (size_t i = 0; i < arraysize(kMachineReps); i++) {
+ ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Type::Any(), kMachineReps[i]};
+
+ Node* val = t.ExampleWithOutput(kMachineReps[i]);
+ Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access),
+ t.p0, t.p1, val, t.start, t.start);
+ t.Effect(store);
+ t.Lower();
+ CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(val, store->InputAt(2));
+ CheckElementAccessArithmetic(access, store);
- Node* val = t.ExampleWithOutput(kMachineReps[i]);
+ StoreRepresentation rep = OpParameter<StoreRepresentation>(store);
+ if (kMachineReps[i] & kRepTagged) {
+ CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+ }
+ CHECK_EQ(kMachineReps[i], rep.machine_type());
+ }
+ }
+ {
+ TestingGraph t(Type::Any(), Type::Signed32(),
+ Type::Intersect(Type::SignedSmall(), Type::TaggedSigned()));
+ ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Type::Any(), kMachAnyTagged};
Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
- t.p1, val, t.start, t.start);
+ t.p1, t.p2, t.start, t.start);
t.Effect(store);
t.Lower();
CHECK_EQ(IrOpcode::kStore, store->opcode());
- CHECK_EQ(val, store->InputAt(2));
- CheckElementAccessArithmetic(access, store);
-
+ CHECK_EQ(t.p2, store->InputAt(2));
StoreRepresentation rep = OpParameter<StoreRepresentation>(store);
- if (kMachineReps[i] & kRepTagged) {
- CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
- }
- CHECK_EQ(kMachineReps[i], rep.machine_type());
+ CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
}
}
@@ -1938,10 +1951,10 @@ TEST(NumberModulus_TruncatingToUint32) {
Node* k = t.jsgraph.Constant(constants[i]);
Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod);
- Node* ret = t.Return(trunc);
+ t.Return(trunc);
t.Lower();
- CHECK_EQ(IrOpcode::kUint32Mod, ret->InputAt(0)->opcode());
+ CHECK_EQ(IrOpcode::kUint32Mod, t.ret->InputAt(0)->InputAt(0)->opcode());
}
}
diff --git a/deps/v8/test/cctest/test-accessors.cc b/deps/v8/test/cctest/test-accessors.cc
index bbb74c0a71..be69111364 100644
--- a/deps/v8/test/cctest/test-accessors.cc
+++ b/deps/v8/test/cctest/test-accessors.cc
@@ -605,3 +605,86 @@ THREADED_TEST(Regress433458) {
"Object.defineProperty(obj, 'prop', { writable: false });"
"Object.defineProperty(obj, 'prop', { writable: true });");
}
+
+
+static bool security_check_value = false;
+
+
+static bool SecurityTestCallback(Local<v8::Object> global, Local<Value> name,
+ v8::AccessType type, Local<Value> data) {
+ return security_check_value;
+}
+
+
+TEST(PrototypeGetterAccessCheck) {
+ i::FLAG_allow_natives_syntax = true;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ auto fun_templ = v8::FunctionTemplate::New(isolate);
+ auto getter_templ = v8::FunctionTemplate::New(isolate, handle_property);
+ getter_templ->SetAcceptAnyReceiver(false);
+ fun_templ->InstanceTemplate()->SetAccessorProperty(v8_str("foo"),
+ getter_templ);
+ auto obj_templ = v8::ObjectTemplate::New(isolate);
+ obj_templ->SetAccessCheckCallbacks(SecurityTestCallback, nullptr);
+ env->Global()->Set(v8_str("Fun"), fun_templ->GetFunction());
+ env->Global()->Set(v8_str("obj"), obj_templ->NewInstance());
+ env->Global()->Set(v8_str("obj2"), obj_templ->NewInstance());
+
+ security_check_value = true;
+ CompileRun("var proto = new Fun();");
+ CompileRun("obj.__proto__ = proto;");
+ ExpectInt32("proto.foo", 907);
+
+ // Test direct.
+ security_check_value = true;
+ ExpectInt32("obj.foo", 907);
+ security_check_value = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ CompileRun("obj.foo");
+ CHECK(try_catch.HasCaught());
+ }
+
+ // Test through call.
+ security_check_value = true;
+ ExpectInt32("proto.__lookupGetter__('foo').call(obj)", 907);
+ security_check_value = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ CompileRun("proto.__lookupGetter__('foo').call(obj)");
+ CHECK(try_catch.HasCaught());
+ }
+
+ // Test ics.
+ CompileRun(
+ "function f() {"
+ " var x;"
+ " for (var i = 0; i < 4; i++) {"
+ " x = obj.foo;"
+ " }"
+ " return x;"
+ "}");
+
+ security_check_value = true;
+ ExpectInt32("f()", 907);
+ security_check_value = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ CompileRun("f();");
+ CHECK(try_catch.HasCaught());
+ }
+
+ // Test crankshaft.
+ CompileRun("%OptimizeFunctionOnNextCall(f);");
+
+ security_check_value = true;
+ ExpectInt32("f()", 907);
+ security_check_value = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ CompileRun("f();");
+ CHECK(try_catch.HasCaught());
+ }
+}
diff --git a/deps/v8/test/cctest/test-alloc.cc b/deps/v8/test/cctest/test-alloc.cc
index 79ba4a486e..0ec9934644 100644
--- a/deps/v8/test/cctest/test-alloc.cc
+++ b/deps/v8/test/cctest/test-alloc.cc
@@ -63,7 +63,7 @@ static AllocationResult AllocateAfterFailures() {
heap->AllocateFixedArray(10000, TENURED).ToObjectChecked();
// Large object space.
- static const int kLargeObjectSpaceFillerLength = 300000;
+ static const int kLargeObjectSpaceFillerLength = 3 * (Page::kPageSize / 10);
static const int kLargeObjectSpaceFillerSize = FixedArray::SizeFor(
kLargeObjectSpaceFillerLength);
DCHECK(kLargeObjectSpaceFillerSize > heap->old_pointer_space()->AreaSize());
@@ -210,7 +210,7 @@ TEST(CodeRange) {
// Geometrically distributed sizes, greater than
// Page::kMaxRegularHeapObjectSize (which is greater than code page area).
// TODO(gc): instead of using 3 use some contant based on code_range_size
- // kMaxHeapObjectSize.
+ // kMaxRegularHeapObjectSize.
size_t requested =
(Page::kMaxRegularHeapObjectSize << (Pseudorandom() % 3)) +
Pseudorandom() % 5000 + 1;
diff --git a/deps/v8/test/cctest/test-api-interceptors.cc b/deps/v8/test/cctest/test-api-interceptors.cc
index a2acb24d76..e3bee15318 100644
--- a/deps/v8/test/cctest/test-api-interceptors.cc
+++ b/deps/v8/test/cctest/test-api-interceptors.cc
@@ -15,7 +15,6 @@
#include "src/objects.h"
#include "src/parser.h"
#include "src/smart-pointers.h"
-#include "src/snapshot.h"
#include "src/unicode-inl.h"
#include "src/utils.h"
#include "src/vm-state.h"
@@ -2934,16 +2933,8 @@ struct AccessCheckData {
};
-bool SimpleNamedAccessChecker(Local<v8::Object> global, Local<Value> name,
- v8::AccessType type, Local<Value> data) {
- auto access_check_data = GetWrappedObject<AccessCheckData>(data);
- access_check_data->count++;
- return access_check_data->result;
-}
-
-
-bool SimpleIndexedAccessChecker(Local<v8::Object> global, uint32_t index,
- v8::AccessType type, Local<Value> data) {
+bool SimpleAccessChecker(Local<v8::Object> global, Local<Value> name,
+ v8::AccessType type, Local<Value> data) {
auto access_check_data = GetWrappedObject<AccessCheckData>(data);
access_check_data->count++;
return access_check_data->result;
@@ -3015,7 +3006,7 @@ THREADED_TEST(NamedAllCanReadInterceptor) {
auto checked = v8::ObjectTemplate::New(isolate);
checked->SetAccessCheckCallbacks(
- SimpleNamedAccessChecker, nullptr,
+ SimpleAccessChecker, nullptr,
BuildWrappedObject<AccessCheckData>(isolate, &access_check_data), false);
context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance());
@@ -3032,15 +3023,27 @@ THREADED_TEST(NamedAllCanReadInterceptor) {
access_check_data.result = true;
ExpectInt32("checked.whatever", 17);
- CHECK_EQ(1, access_check_data.count);
+ CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')")
+ ->IsUndefined());
+ CHECK_EQ(2, access_check_data.count);
access_check_data.result = false;
ExpectInt32("checked.whatever", intercept_data_0.value);
- CHECK_EQ(2, access_check_data.count);
+ {
+ v8::TryCatch try_catch(isolate);
+ CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')");
+ CHECK(try_catch.HasCaught());
+ }
+ CHECK_EQ(4, access_check_data.count);
intercept_data_1.should_intercept = true;
ExpectInt32("checked.whatever", intercept_data_1.value);
- CHECK_EQ(3, access_check_data.count);
+ {
+ v8::TryCatch try_catch(isolate);
+ CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')");
+ CHECK(try_catch.HasCaught());
+ }
+ CHECK_EQ(6, access_check_data.count);
}
@@ -3081,7 +3084,7 @@ THREADED_TEST(IndexedAllCanReadInterceptor) {
auto checked = v8::ObjectTemplate::New(isolate);
checked->SetAccessCheckCallbacks(
- nullptr, SimpleIndexedAccessChecker,
+ SimpleAccessChecker, nullptr,
BuildWrappedObject<AccessCheckData>(isolate, &access_check_data), false);
context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance());
@@ -3098,13 +3101,211 @@ THREADED_TEST(IndexedAllCanReadInterceptor) {
access_check_data.result = true;
ExpectInt32("checked[15]", 17);
- CHECK_EQ(1, access_check_data.count);
+ CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')")
+ ->IsUndefined());
+ CHECK_EQ(3, access_check_data.count);
access_check_data.result = false;
ExpectInt32("checked[15]", intercept_data_0.value);
- CHECK_EQ(2, access_check_data.count);
+ // Note: this should throw but without a LookupIterator it's complicated.
+ CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')")
+ ->IsUndefined());
+ CHECK_EQ(6, access_check_data.count);
intercept_data_1.should_intercept = true;
ExpectInt32("checked[15]", intercept_data_1.value);
- CHECK_EQ(3, access_check_data.count);
+ // Note: this should throw but without a LookupIterator it's complicated.
+ CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')")
+ ->IsUndefined());
+ CHECK_EQ(9, access_check_data.count);
+}
+
+
+THREADED_TEST(NonMaskingInterceptorOwnProperty) {
+ auto isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext context;
+
+ ShouldInterceptData intercept_data;
+ intercept_data.value = 239;
+ intercept_data.should_intercept = true;
+
+ auto interceptor_templ = v8::ObjectTemplate::New(isolate);
+ v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
+ conf.flags = v8::PropertyHandlerFlags::kNonMasking;
+ conf.data = BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data);
+ interceptor_templ->SetHandler(conf);
+
+ auto interceptor = interceptor_templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), interceptor);
+
+ ExpectInt32("obj.whatever", 239);
+
+ CompileRun("obj.whatever = 4;");
+ ExpectInt32("obj.whatever", 4);
+
+ CompileRun("delete obj.whatever;");
+ ExpectInt32("obj.whatever", 239);
+}
+
+
+THREADED_TEST(NonMaskingInterceptorPrototypeProperty) {
+ auto isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext context;
+
+ ShouldInterceptData intercept_data;
+ intercept_data.value = 239;
+ intercept_data.should_intercept = true;
+
+ auto interceptor_templ = v8::ObjectTemplate::New(isolate);
+ v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
+ conf.flags = v8::PropertyHandlerFlags::kNonMasking;
+ conf.data = BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data);
+ interceptor_templ->SetHandler(conf);
+
+ auto interceptor = interceptor_templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), interceptor);
+
+ ExpectInt32("obj.whatever", 239);
+
+ CompileRun("obj.__proto__ = {'whatever': 4};");
+ ExpectInt32("obj.whatever", 4);
+
+ CompileRun("delete obj.__proto__.whatever;");
+ ExpectInt32("obj.whatever", 239);
+}
+
+
+THREADED_TEST(NonMaskingInterceptorPrototypePropertyIC) {
+ auto isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext context;
+
+ ShouldInterceptData intercept_data;
+ intercept_data.value = 239;
+ intercept_data.should_intercept = true;
+
+ auto interceptor_templ = v8::ObjectTemplate::New(isolate);
+ v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
+ conf.flags = v8::PropertyHandlerFlags::kNonMasking;
+ conf.data = BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data);
+ interceptor_templ->SetHandler(conf);
+
+ auto interceptor = interceptor_templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), interceptor);
+
+ CompileRun(
+ "outer = {};"
+ "outer.__proto__ = obj;"
+ "function f(obj) {"
+ " var x;"
+ " for (var i = 0; i < 4; i++) {"
+ " x = obj.whatever;"
+ " }"
+ " return x;"
+ "}");
+
+ // Receiver == holder.
+ CompileRun("obj.__proto__ = null;");
+ ExpectInt32("f(obj)", 239);
+ ExpectInt32("f(outer)", 239);
+
+ // Receiver != holder.
+ CompileRun("Object.setPrototypeOf(obj, {});");
+ ExpectInt32("f(obj)", 239);
+ ExpectInt32("f(outer)", 239);
+
+ // Masked value on prototype.
+ CompileRun("obj.__proto__.whatever = 4;");
+ CompileRun("obj.__proto__.__proto__ = { 'whatever' : 5 };");
+ ExpectInt32("f(obj)", 4);
+ ExpectInt32("f(outer)", 4);
+
+ // Masked value on prototype prototype.
+ CompileRun("delete obj.__proto__.whatever;");
+ ExpectInt32("f(obj)", 5);
+ ExpectInt32("f(outer)", 5);
+
+ // Reset.
+ CompileRun("delete obj.__proto__.__proto__.whatever;");
+ ExpectInt32("f(obj)", 239);
+ ExpectInt32("f(outer)", 239);
+
+ // Masked value on self.
+ CompileRun("obj.whatever = 4;");
+ ExpectInt32("f(obj)", 4);
+ ExpectInt32("f(outer)", 4);
+
+ // Reset.
+ CompileRun("delete obj.whatever;");
+ ExpectInt32("f(obj)", 239);
+ ExpectInt32("f(outer)", 239);
+
+ CompileRun("outer.whatever = 4;");
+ ExpectInt32("f(obj)", 239);
+ ExpectInt32("f(outer)", 4);
+}
+
+
+namespace {
+
+void DatabaseGetter(Local<Name> name,
+ const v8::PropertyCallbackInfo<Value>& info) {
+ ApiTestFuzzer::Fuzz();
+ auto context = info.GetIsolate()->GetCurrentContext();
+ Local<v8::Object> db = info.Holder()
+ ->GetRealNamedProperty(context, v8_str("db"))
+ .ToLocalChecked()
+ .As<v8::Object>();
+ if (!db->Has(context, name).FromJust()) return;
+ info.GetReturnValue().Set(db->Get(context, name).ToLocalChecked());
+}
+
+
+void DatabaseSetter(Local<Name> name, Local<Value> value,
+ const v8::PropertyCallbackInfo<Value>& info) {
+ ApiTestFuzzer::Fuzz();
+ auto context = info.GetIsolate()->GetCurrentContext();
+ if (name->Equals(v8_str("db"))) return;
+ Local<v8::Object> db = info.Holder()
+ ->GetRealNamedProperty(context, v8_str("db"))
+ .ToLocalChecked()
+ .As<v8::Object>();
+ db->Set(context, name, value).FromJust();
+ info.GetReturnValue().Set(value);
+}
+}
+
+
+THREADED_TEST(NonMaskingInterceptorGlobalEvalRegression) {
+ auto isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext context;
+
+ auto interceptor_templ = v8::ObjectTemplate::New(isolate);
+ v8::NamedPropertyHandlerConfiguration conf(DatabaseGetter, DatabaseSetter);
+ conf.flags = v8::PropertyHandlerFlags::kNonMasking;
+ interceptor_templ->SetHandler(conf);
+
+ context->Global()->Set(v8_str("intercepted_1"),
+ interceptor_templ->NewInstance());
+ context->Global()->Set(v8_str("intercepted_2"),
+ interceptor_templ->NewInstance());
+
+ // Init dbs.
+ CompileRun(
+ "intercepted_1.db = {};"
+ "intercepted_2.db = {};");
+
+ ExpectInt32(
+ "var obj = intercepted_1;"
+ "obj.x = 4;"
+ "eval('obj.x');"
+ "eval('obj.x');"
+ "eval('obj.x');"
+ "obj = intercepted_2;"
+ "obj.x = 9;"
+ "eval('obj.x');",
+ 9);
}
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index afb70ffeee..8432cbfba1 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -45,7 +45,6 @@
#include "src/objects.h"
#include "src/parser.h"
#include "src/smart-pointers.h"
-#include "src/snapshot.h"
#include "src/unicode-inl.h"
#include "src/utils.h"
#include "src/vm-state.h"
@@ -61,12 +60,15 @@ using ::v8::FunctionTemplate;
using ::v8::Handle;
using ::v8::HandleScope;
using ::v8::Local;
-using ::v8::Name;
+using ::v8::Maybe;
using ::v8::Message;
using ::v8::MessageCallback;
+using ::v8::Name;
+using ::v8::None;
using ::v8::Object;
using ::v8::ObjectTemplate;
using ::v8::Persistent;
+using ::v8::PropertyAttribute;
using ::v8::Script;
using ::v8::StackTrace;
using ::v8::String;
@@ -691,28 +693,23 @@ class RandomLengthOneByteResource
THREADED_TEST(NewExternalForVeryLongString) {
+ auto isolate = CcTest::isolate();
{
- LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::HandleScope scope(isolate);
v8::TryCatch try_catch;
RandomLengthOneByteResource r(1 << 30);
- v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
+ v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
CHECK(str.IsEmpty());
- CHECK(try_catch.HasCaught());
- String::Utf8Value exception_value(try_catch.Exception());
- CHECK_EQ(0, strcmp("RangeError: Invalid string length", *exception_value));
+ CHECK(!try_catch.HasCaught());
}
{
- LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::HandleScope scope(isolate);
v8::TryCatch try_catch;
RandomLengthResource r(1 << 30);
- v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
+ v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
CHECK(str.IsEmpty());
- CHECK(try_catch.HasCaught());
- String::Utf8Value exception_value(try_catch.Exception());
- CHECK_EQ(0, strcmp("RangeError: Invalid string length", *exception_value));
+ CHECK(!try_catch.HasCaught());
}
}
@@ -733,8 +730,8 @@ THREADED_TEST(ScavengeExternalString) {
CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
CHECK_EQ(0, dispose_count);
}
- CcTest::heap()->CollectGarbage(
- in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
+ CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE
+ : i::OLD_DATA_SPACE);
CHECK_EQ(1, dispose_count);
}
@@ -756,8 +753,8 @@ THREADED_TEST(ScavengeExternalOneByteString) {
CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
CHECK_EQ(0, dispose_count);
}
- CcTest::heap()->CollectGarbage(
- in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
+ CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE
+ : i::OLD_DATA_SPACE);
CHECK_EQ(1, dispose_count);
}
@@ -2124,7 +2121,7 @@ THREADED_TEST(InternalFieldsAlignedPointers) {
void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
CheckAlignedPointerInInternalField(obj, huge);
- v8::UniquePersistent<v8::Object> persistent(isolate, obj);
+ v8::Global<v8::Object> persistent(isolate, obj);
CHECK_EQ(1, Object::InternalFieldCount(persistent));
CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
}
@@ -3035,20 +3032,20 @@ THREADED_TEST(ResettingGlobalHandleToEmpty) {
template <class T>
-static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
+static v8::Global<T> PassUnique(v8::Global<T> unique) {
return unique.Pass();
}
template <class T>
-static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
- const v8::Persistent<T>& global) {
- v8::UniquePersistent<String> unique(isolate, global);
+static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
+ const v8::Persistent<T>& global) {
+ v8::Global<String> unique(isolate, global);
return unique.Pass();
}
-THREADED_TEST(UniquePersistent) {
+THREADED_TEST(Global) {
v8::Isolate* isolate = CcTest::isolate();
v8::Persistent<String> global;
{
@@ -3059,11 +3056,11 @@ THREADED_TEST(UniquePersistent) {
reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
int initial_handle_count = global_handles->global_handles_count();
{
- v8::UniquePersistent<String> unique(isolate, global);
+ v8::Global<String> unique(isolate, global);
CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
// Test assignment via Pass
{
- v8::UniquePersistent<String> copy = unique.Pass();
+ v8::Global<String> copy = unique.Pass();
CHECK(unique.IsEmpty());
CHECK(copy == global);
CHECK_EQ(initial_handle_count + 1,
@@ -3072,7 +3069,7 @@ THREADED_TEST(UniquePersistent) {
}
// Test ctor via Pass
{
- v8::UniquePersistent<String> copy(unique.Pass());
+ v8::Global<String> copy(unique.Pass());
CHECK(unique.IsEmpty());
CHECK(copy == global);
CHECK_EQ(initial_handle_count + 1,
@@ -3081,7 +3078,7 @@ THREADED_TEST(UniquePersistent) {
}
// Test pass through function call
{
- v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
+ v8::Global<String> copy = PassUnique(unique.Pass());
CHECK(unique.IsEmpty());
CHECK(copy == global);
CHECK_EQ(initial_handle_count + 1,
@@ -3092,7 +3089,7 @@ THREADED_TEST(UniquePersistent) {
}
// Test pass from function call
{
- v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
+ v8::Global<String> unique = ReturnUnique(isolate, global);
CHECK(unique == global);
CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
}
@@ -3101,6 +3098,123 @@ THREADED_TEST(UniquePersistent) {
}
+namespace {
+
+class TwoPassCallbackData;
+void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
+void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
+
+
+class TwoPassCallbackData {
+ public:
+ TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
+ : first_pass_called_(false),
+ second_pass_called_(false),
+ trigger_gc_(false),
+ instance_counter_(instance_counter) {
+ HandleScope scope(isolate);
+ i::ScopedVector<char> buffer(40);
+ i::SNPrintF(buffer, "%p", static_cast<void*>(this));
+ auto string =
+ v8::String::NewFromUtf8(isolate, buffer.start(),
+ v8::NewStringType::kNormal).ToLocalChecked();
+ cell_.Reset(isolate, string);
+ (*instance_counter_)++;
+ }
+
+ ~TwoPassCallbackData() {
+ CHECK(first_pass_called_);
+ CHECK(second_pass_called_);
+ CHECK(cell_.IsEmpty());
+ (*instance_counter_)--;
+ }
+
+ void FirstPass() {
+ CHECK(!first_pass_called_);
+ CHECK(!second_pass_called_);
+ CHECK(!cell_.IsEmpty());
+ cell_.Reset();
+ first_pass_called_ = true;
+ }
+
+ void SecondPass() {
+ CHECK(first_pass_called_);
+ CHECK(!second_pass_called_);
+ CHECK(cell_.IsEmpty());
+ second_pass_called_ = true;
+ delete this;
+ }
+
+ void SetWeak() {
+ cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
+ }
+
+ void MarkTriggerGc() { trigger_gc_ = true; }
+ bool trigger_gc() { return trigger_gc_; }
+
+ int* instance_counter() { return instance_counter_; }
+
+ private:
+ bool first_pass_called_;
+ bool second_pass_called_;
+ bool trigger_gc_;
+ v8::Global<v8::String> cell_;
+ int* instance_counter_;
+};
+
+
+void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
+ ApiTestFuzzer::Fuzz();
+ bool trigger_gc = data.GetParameter()->trigger_gc();
+ int* instance_counter = data.GetParameter()->instance_counter();
+ data.GetParameter()->SecondPass();
+ if (!trigger_gc) return;
+ auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
+ data_2->SetWeak();
+ CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+}
+
+
+void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
+ data.GetParameter()->FirstPass();
+ data.SetSecondPassCallback(SecondPassCallback);
+}
+
+} // namespace
+
+
+TEST(TwoPassPhantomCallbacks) {
+ auto isolate = CcTest::isolate();
+ const size_t kLength = 20;
+ int instance_counter = 0;
+ for (size_t i = 0; i < kLength; ++i) {
+ auto data = new TwoPassCallbackData(isolate, &instance_counter);
+ data->SetWeak();
+ }
+ CHECK_EQ(static_cast<int>(kLength), instance_counter);
+ CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CHECK_EQ(0, instance_counter);
+}
+
+
+TEST(TwoPassPhantomCallbacksNestedGc) {
+ auto isolate = CcTest::isolate();
+ const size_t kLength = 20;
+ TwoPassCallbackData* array[kLength];
+ int instance_counter = 0;
+ for (size_t i = 0; i < kLength; ++i) {
+ array[i] = new TwoPassCallbackData(isolate, &instance_counter);
+ array[i]->SetWeak();
+ }
+ array[5]->MarkTriggerGc();
+ array[10]->MarkTriggerGc();
+ array[15]->MarkTriggerGc();
+ CHECK_EQ(static_cast<int>(kLength), instance_counter);
+ CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CHECK_EQ(0, instance_counter);
+}
+
+
template <typename K, typename V>
class WeakStdMapTraits : public v8::StdMapTraits<K, V> {
public:
@@ -3126,8 +3240,7 @@ class WeakStdMapTraits : public v8::StdMapTraits<K, V> {
return data.GetParameter()->key;
}
static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
- static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<V> value,
- K key) {}
+ static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {}
};
@@ -3153,7 +3266,7 @@ static void TestPersistentValueMap() {
typename Map::PersistentValueReference ref = map.GetReference(7);
CHECK(expected->Equals(ref.NewLocal(isolate)));
}
- v8::UniquePersistent<v8::Object> removed = map.Remove(7);
+ v8::Global<v8::Object> removed = map.Remove(7);
CHECK_EQ(0, static_cast<int>(map.Size()));
CHECK(expected == removed);
removed = map.Remove(7);
@@ -3165,8 +3278,7 @@ static void TestPersistentValueMap() {
{
typename Map::PersistentValueReference ref;
Local<v8::Object> expected2 = v8::Object::New(isolate);
- removed = map.Set(8, v8::UniquePersistent<v8::Object>(isolate, expected2),
- &ref);
+ removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
CHECK_EQ(1, static_cast<int>(map.Size()));
CHECK(expected == removed);
CHECK(expected2->Equals(ref.NewLocal(isolate)));
@@ -3197,6 +3309,126 @@ TEST(PersistentValueMap) {
}
+namespace {
+
+void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
+
+
+Local<v8::Object> NewObjectForIntKey(
+ v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
+ int key) {
+ auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
+ auto obj = local->NewInstance();
+ obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
+ return obj;
+}
+
+
+template <typename K, typename V>
+class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
+ public:
+ typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
+ static const v8::PersistentContainerCallbackType kCallbackType =
+ v8::kWeakWithInternalFields;
+ struct WeakCallbackDataType {
+ MapType* map;
+ K key;
+ };
+ static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
+ Local<V> value) {
+ WeakCallbackDataType* data = new WeakCallbackDataType;
+ data->map = map;
+ data->key = key;
+ return data;
+ }
+ static MapType* MapFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+ return data.GetParameter()->map;
+ }
+ static K KeyFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+ return data.GetParameter()->key;
+ }
+ static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
+ static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
+ CHECK_EQ(IntKeyToVoidPointer(key),
+ v8::Object::GetAlignedPointerFromInternalField(value, 0));
+ }
+ static void DisposeWeak(
+ v8::Isolate* isolate,
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& info, K key) {
+ CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
+ DisposeCallbackData(info.GetParameter());
+ }
+};
+
+} // namespace
+
+
+TEST(GlobalValueMap) {
+ typedef v8::GlobalValueMap<int, v8::Object,
+ PhantomStdMapTraits<int, v8::Object>> Map;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::Global<ObjectTemplate> templ;
+ {
+ HandleScope scope(isolate);
+ auto t = ObjectTemplate::New(isolate);
+ t->SetInternalFieldCount(1);
+ templ.Reset(isolate, t);
+ }
+ Map map(isolate);
+ v8::internal::GlobalHandles* global_handles =
+ reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
+ int initial_handle_count = global_handles->global_handles_count();
+ CHECK_EQ(0, static_cast<int>(map.Size()));
+ {
+ HandleScope scope(isolate);
+ Local<v8::Object> obj = map.Get(7);
+ CHECK(obj.IsEmpty());
+ Local<v8::Object> expected = v8::Object::New(isolate);
+ map.Set(7, expected);
+ CHECK_EQ(1, static_cast<int>(map.Size()));
+ obj = map.Get(7);
+ CHECK(expected->Equals(obj));
+ {
+ Map::PersistentValueReference ref = map.GetReference(7);
+ CHECK(expected->Equals(ref.NewLocal(isolate)));
+ }
+ v8::Global<v8::Object> removed = map.Remove(7);
+ CHECK_EQ(0, static_cast<int>(map.Size()));
+ CHECK(expected == removed);
+ removed = map.Remove(7);
+ CHECK(removed.IsEmpty());
+ map.Set(8, expected);
+ CHECK_EQ(1, static_cast<int>(map.Size()));
+ map.Set(8, expected);
+ CHECK_EQ(1, static_cast<int>(map.Size()));
+ {
+ Map::PersistentValueReference ref;
+ Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
+ removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
+ CHECK_EQ(1, static_cast<int>(map.Size()));
+ CHECK(expected == removed);
+ CHECK(expected2->Equals(ref.NewLocal(isolate)));
+ }
+ }
+ CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
+ CcTest::i_isolate()->heap()->CollectAllGarbage(
+ i::Heap::kAbortIncrementalMarkingMask);
+ CHECK_EQ(0, static_cast<int>(map.Size()));
+ CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
+ {
+ HandleScope scope(isolate);
+ Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
+ map.Set(9, value);
+ map.Clear();
+ }
+ CHECK_EQ(0, static_cast<int>(map.Size()));
+ CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
+}
+
+
TEST(PersistentValueVector) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
@@ -3209,7 +3441,7 @@ TEST(PersistentValueVector) {
Local<v8::Object> obj1 = v8::Object::New(isolate);
Local<v8::Object> obj2 = v8::Object::New(isolate);
- v8::UniquePersistent<v8::Object> obj3(isolate, v8::Object::New(isolate));
+ v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
CHECK(vector.IsEmpty());
CHECK_EQ(0, static_cast<int>(vector.Size()));
@@ -3891,6 +4123,7 @@ static void check_message_3(v8::Handle<v8::Message> message,
CHECK(message->GetScriptOrigin().ResourceIsSharedCrossOrigin()->Value());
CHECK(message->GetScriptOrigin().ResourceIsEmbedderDebugScript()->Value());
CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
+ CHECK_EQ(7.40, message->GetScriptOrigin().SourceMapUrl()->NumberValue());
message_received = true;
}
@@ -3902,10 +4135,10 @@ TEST(MessageHandler3) {
CHECK(!message_received);
v8::V8::AddMessageListener(check_message_3);
LocalContext context;
- v8::ScriptOrigin origin =
- v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
- v8::Integer::New(isolate, 2), v8::True(isolate),
- Handle<v8::Integer>(), v8::True(isolate));
+ v8::ScriptOrigin origin = v8::ScriptOrigin(
+ v8_str("6.75"), v8::Integer::New(isolate, 1),
+ v8::Integer::New(isolate, 2), v8::True(isolate), Handle<v8::Integer>(),
+ v8::True(isolate), v8_str("7.40"));
v8::Handle<v8::Script> script =
Script::Compile(v8_str("throw 'error'"), &origin);
script->Run();
@@ -6266,12 +6499,13 @@ THREADED_TEST(ErrorWithMissingScriptInfo) {
struct FlagAndPersistent {
bool flag;
- v8::Persistent<v8::Object> handle;
+ v8::Global<v8::Object> handle;
};
-static void SetFlag(const v8::PhantomCallbackData<FlagAndPersistent>& data) {
+static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
data.GetParameter()->flag = true;
+ data.GetParameter()->handle.Reset();
}
@@ -6309,8 +6543,10 @@ static void IndependentWeakHandle(bool global_gc, bool interlinked) {
object_a.flag = false;
object_b.flag = false;
- object_a.handle.SetPhantom(&object_a, &SetFlag);
- object_b.handle.SetPhantom(&object_b, &SetFlag);
+ object_a.handle.SetWeak(&object_a, &SetFlag,
+ v8::WeakCallbackType::kParameter);
+ object_b.handle.SetWeak(&object_b, &SetFlag,
+ v8::WeakCallbackType::kParameter);
CHECK(!object_b.handle.IsIndependent());
object_a.handle.MarkIndependent();
object_b.handle.MarkIndependent();
@@ -6365,7 +6601,7 @@ class Trivial2 {
void CheckInternalFields(
- const v8::PhantomCallbackData<v8::Persistent<v8::Object>>& data) {
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
v8::Persistent<v8::Object>* handle = data.GetParameter();
handle->Reset();
Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField1());
@@ -6405,8 +6641,8 @@ void InternalFieldCallback(bool global_gc) {
reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
CHECK_EQ(103, t2->x());
- handle.SetPhantom<v8::Persistent<v8::Object>>(&handle, CheckInternalFields,
- 0, 1);
+ handle.SetWeak<v8::Persistent<v8::Object>>(
+ &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
if (!global_gc) {
handle.MarkIndependent();
}
@@ -7673,30 +7909,9 @@ TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
// For use within the TestSecurityHandler() test.
static bool g_security_callback_result = false;
-static bool NamedSecurityTestCallback(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
+static bool SecurityTestCallback(Local<v8::Object> global, Local<Value> name,
+ v8::AccessType type, Local<Value> data) {
printf("a\n");
- // Always allow read access.
- if (type == v8::ACCESS_GET)
- return true;
-
- // Sometimes allow other access.
- return g_security_callback_result;
-}
-
-
-static bool IndexedSecurityTestCallback(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- printf("b\n");
- // Always allow read access.
- if (type == v8::ACCESS_GET)
- return true;
-
- // Sometimes allow other access.
return g_security_callback_result;
}
@@ -7707,8 +7922,7 @@ TEST(SecurityHandler) {
v8::HandleScope scope0(isolate);
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
- IndexedSecurityTestCallback);
+ global_template->SetAccessCheckCallbacks(SecurityTestCallback, NULL);
// Create an environment
v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
context0->Enter();
@@ -7735,6 +7949,7 @@ TEST(SecurityHandler) {
v8::Handle<Script> script1 =
v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
script1->Run();
+ g_security_callback_result = true;
// This read will pass the security check.
v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
CHECK_EQ(111, foo1->Int32Value());
@@ -7743,7 +7958,7 @@ TEST(SecurityHandler) {
CHECK_EQ(999, z1->Int32Value());
// Create another environment, should pass security checks.
- { g_security_callback_result = true; // allow security handler to pass.
+ {
v8::HandleScope scope2(isolate);
LocalContext context2;
v8::Handle<v8::Object> global2 = context2->Global();
@@ -7866,26 +8081,13 @@ THREADED_TEST(SecurityChecksForPrototypeChain) {
}
-static bool named_security_check_with_gc_called;
+static bool security_check_with_gc_called;
-static bool NamedSecurityCallbackWithGC(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
+static bool SecurityTestCallbackWithGC(Local<v8::Object> global,
+ Local<v8::Value> name,
+ v8::AccessType type, Local<Value> data) {
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- named_security_check_with_gc_called = true;
- return true;
-}
-
-
-static bool indexed_security_check_with_gc_called;
-
-static bool IndexedSecurityTestCallbackWithGC(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- indexed_security_check_with_gc_called = true;
+ security_check_with_gc_called = true;
return true;
}
@@ -7895,29 +8097,20 @@ TEST(SecurityTestGCAllowed) {
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate);
- object_template->SetAccessCheckCallbacks(NamedSecurityCallbackWithGC,
- IndexedSecurityTestCallbackWithGC);
+ object_template->SetAccessCheckCallbacks(SecurityTestCallbackWithGC, NULL);
v8::Handle<Context> context = Context::New(isolate);
v8::Context::Scope context_scope(context);
context->Global()->Set(v8_str("obj"), object_template->NewInstance());
- named_security_check_with_gc_called = false;
- CompileRun("obj.foo = new String(1001);");
- CHECK(named_security_check_with_gc_called);
-
- indexed_security_check_with_gc_called = false;
+ security_check_with_gc_called = false;
CompileRun("obj[0] = new String(1002);");
- CHECK(indexed_security_check_with_gc_called);
-
- named_security_check_with_gc_called = false;
- CHECK(CompileRun("obj.foo")->ToString(isolate)->Equals(v8_str("1001")));
- CHECK(named_security_check_with_gc_called);
+ CHECK(security_check_with_gc_called);
- indexed_security_check_with_gc_called = false;
+ security_check_with_gc_called = false;
CHECK(CompileRun("obj[0]")->ToString(isolate)->Equals(v8_str("1002")));
- CHECK(indexed_security_check_with_gc_called);
+ CHECK(security_check_with_gc_called);
}
@@ -8275,22 +8468,11 @@ TEST(DetachedAccesses) {
}
-static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
-static bool NamedAccessBlocker(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
+static bool allowed_access = false;
+static bool AccessBlocker(Local<v8::Object> global, Local<Value> name,
+ v8::AccessType type, Local<Value> data) {
return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
- allowed_access_type[type];
-}
-
-
-static bool IndexedAccessBlocker(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
- allowed_access_type[type];
+ allowed_access;
}
@@ -8338,8 +8520,7 @@ TEST(AccessControl) {
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
- IndexedAccessBlocker);
+ global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
// Add an accessor accessible by cross-domain JS code.
global_template->SetAccessor(
@@ -8413,15 +8594,10 @@ TEST(AccessControl) {
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
- // Enable ACCESS_HAS
- allowed_access_type[v8::ACCESS_HAS] = true;
- CHECK(CompileRun("other[239]").IsEmpty());
- // ... and now we can get the descriptor...
- CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239').value")
- .IsEmpty());
- // ... and enumerate the property.
+ allowed_access = true;
+ // Now we can enumerate the property.
ExpectTrue("propertyIsEnumerable.call(other, '239')");
- allowed_access_type[v8::ACCESS_HAS] = false;
+ allowed_access = false;
// Access a property with JS accessor.
CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
@@ -8430,9 +8606,7 @@ TEST(AccessControl) {
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
.IsEmpty());
- // Enable both ACCESS_HAS and ACCESS_GET.
- allowed_access_type[v8::ACCESS_HAS] = true;
- allowed_access_type[v8::ACCESS_GET] = true;
+ allowed_access = true;
ExpectString("other.js_accessor_p", "getter");
ExpectObject(
@@ -8442,8 +8616,7 @@ TEST(AccessControl) {
ExpectUndefined(
"Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
- allowed_access_type[v8::ACCESS_HAS] = false;
- allowed_access_type[v8::ACCESS_GET] = false;
+ allowed_access = false;
// Access an element with JS accessor.
CHECK(CompileRun("other[42] = 2").IsEmpty());
@@ -8451,17 +8624,14 @@ TEST(AccessControl) {
CHECK(CompileRun("other[42]").IsEmpty());
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
- // Enable both ACCESS_HAS and ACCESS_GET.
- allowed_access_type[v8::ACCESS_HAS] = true;
- allowed_access_type[v8::ACCESS_GET] = true;
+ allowed_access = true;
ExpectString("other[42]", "el_getter");
ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
- allowed_access_type[v8::ACCESS_HAS] = false;
- allowed_access_type[v8::ACCESS_GET] = false;
+ allowed_access = false;
v8::Handle<Value> value;
@@ -8514,8 +8684,7 @@ TEST(AccessControlES5) {
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
- IndexedAccessBlocker);
+ global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
// Add accessible accessor.
global_template->SetAccessor(
@@ -8578,14 +8747,9 @@ TEST(AccessControlES5) {
}
-static bool BlockEverythingNamed(Local<v8::Object> object, Local<Value> name,
- v8::AccessType type, Local<Value> data) {
- return false;
-}
-
-
-static bool BlockEverythingIndexed(Local<v8::Object> object, uint32_t key,
- v8::AccessType type, Local<Value> data) {
+static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name,
+ v8::AccessType type, Local<Value> data) {
+ i::PrintF("Access blocked.\n");
return false;
}
@@ -8597,8 +8761,7 @@ THREADED_TEST(AccessControlGetOwnPropertyNames) {
v8::ObjectTemplate::New(isolate);
obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
- obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
- BlockEverythingIndexed);
+ obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
// Create an environment
v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
@@ -8641,8 +8804,7 @@ TEST(SuperAccessControl) {
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::ObjectTemplate> obj_template =
v8::ObjectTemplate::New(isolate);
- obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
- BlockEverythingIndexed);
+ obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
LocalContext env;
env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
@@ -8690,6 +8852,32 @@ TEST(SuperAccessControl) {
}
+TEST(Regress470113) {
+ i::FLAG_harmony_classes = true;
+ i::FLAG_harmony_object_literals = true;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> obj_template =
+ v8::ObjectTemplate::New(isolate);
+ obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+ LocalContext env;
+ env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
+
+ {
+ v8::TryCatch try_catch;
+ CompileRun(
+ "'use strict';\n"
+ "class C extends Object {\n"
+ " m() { super.powned = 'Powned!'; }\n"
+ "}\n"
+ "let c = new C();\n"
+ "c.m.call(prohibited)");
+
+ CHECK(try_catch.HasCaught());
+ }
+}
+
+
static void ConstTenGetter(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(v8_num(10));
@@ -8749,31 +8937,18 @@ THREADED_TEST(CrossDomainAccessors) {
}
-static int named_access_count = 0;
-static int indexed_access_count = 0;
+static int access_count = 0;
-static bool NamedAccessCounter(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- named_access_count++;
- return true;
-}
-
-
-static bool IndexedAccessCounter(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- indexed_access_count++;
+static bool AccessCounter(Local<v8::Object> global, Local<Value> name,
+ v8::AccessType type, Local<Value> data) {
+ access_count++;
return true;
}
// This one is too easily disturbed by other tests.
TEST(AccessControlIC) {
- named_access_count = 0;
- indexed_access_count = 0;
+ access_count = 0;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);
@@ -8786,8 +8961,7 @@ TEST(AccessControlIC) {
// called for cross-domain access.
v8::Handle<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate);
- object_template->SetAccessCheckCallbacks(NamedAccessCounter,
- IndexedAccessCounter);
+ object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
Local<v8::Object> object = object_template->NewInstance();
v8::HandleScope scope1(isolate);
@@ -8811,7 +8985,7 @@ TEST(AccessControlIC) {
value = CompileRun("testProp(obj)");
CHECK(value->IsNumber());
CHECK_EQ(1, value->Int32Value());
- CHECK_EQ(21, named_access_count);
+ CHECK_EQ(21, access_count);
// Check that the named access-control function is called every time.
CompileRun("var p = 'prop';"
@@ -8825,16 +8999,18 @@ TEST(AccessControlIC) {
value = CompileRun("testKeyed(obj)");
CHECK(value->IsNumber());
CHECK_EQ(1, value->Int32Value());
- CHECK_EQ(42, named_access_count);
+ CHECK_EQ(42, access_count);
// Force the inline caches into generic state and try again.
CompileRun("testKeyed({ a: 0 })");
CompileRun("testKeyed({ b: 0 })");
value = CompileRun("testKeyed(obj)");
CHECK(value->IsNumber());
CHECK_EQ(1, value->Int32Value());
- CHECK_EQ(63, named_access_count);
+ CHECK_EQ(63, access_count);
// Check that the indexed access-control function is called every time.
+ access_count = 0;
+
CompileRun("function testIndexed(obj) {"
" for (var i = 0; i < 10; i++) obj[0] = 1;"
" for (var j = 0; j < 10; j++) obj[0];"
@@ -8843,15 +9019,16 @@ TEST(AccessControlIC) {
value = CompileRun("testIndexed(obj)");
CHECK(value->IsNumber());
CHECK_EQ(1, value->Int32Value());
- CHECK_EQ(21, indexed_access_count);
+ CHECK_EQ(21, access_count);
// Force the inline caches into generic state.
CompileRun("testIndexed(new Array(1))");
// Test that the indexed access check is called.
value = CompileRun("testIndexed(obj)");
CHECK(value->IsNumber());
CHECK_EQ(1, value->Int32Value());
- CHECK_EQ(42, indexed_access_count);
+ CHECK_EQ(42, access_count);
+ access_count = 0;
// Check that the named access check is called when invoking
// functions on an object that requires access checks.
CompileRun("obj.f = function() {}");
@@ -8859,7 +9036,8 @@ TEST(AccessControlIC) {
" for (var i = 0; i < 10; i++) obj.f();"
"}");
CompileRun("testCallNormal(obj)");
- CHECK_EQ(74, named_access_count);
+ printf("%i\n", access_count);
+ CHECK_EQ(11, access_count);
// Force obj into slow case.
value = CompileRun("delete obj.prop");
@@ -8870,89 +9048,14 @@ TEST(AccessControlIC) {
value = CompileRun("testProp(obj);");
CHECK(value->IsNumber());
CHECK_EQ(1, value->Int32Value());
- CHECK_EQ(96, named_access_count);
+ CHECK_EQ(33, access_count);
// Force the call inline cache into dictionary probing mode.
CompileRun("o.f = function() {}; testCallNormal(o)");
// Test that the named access check is still called for each
// invocation of the function.
value = CompileRun("testCallNormal(obj)");
- CHECK_EQ(106, named_access_count);
-
- context1->Exit();
- context0->Exit();
-}
-
-
-static bool NamedAccessFlatten(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- char buf[100];
- int len;
-
- CHECK(name->IsString());
-
- memset(buf, 0x1, sizeof(buf));
- len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
- CHECK_EQ(4, len);
-
- uint16_t buf2[100];
-
- memset(buf, 0x1, sizeof(buf));
- len = name.As<String>()->Write(buf2);
- CHECK_EQ(4, len);
-
- return true;
-}
-
-
-static bool IndexedAccessFlatten(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- return true;
-}
-
-
-// Regression test. In access checks, operations that may cause
-// garbage collection are not allowed. It used to be the case that
-// using the Write operation on a string could cause a garbage
-// collection due to flattening of the string. This is no longer the
-// case.
-THREADED_TEST(AccessControlFlatten) {
- named_access_count = 0;
- indexed_access_count = 0;
-
- v8::Isolate* isolate = CcTest::isolate();
- v8::HandleScope handle_scope(isolate);
-
- // Create an environment.
- v8::Local<Context> context0 = Context::New(isolate);
- context0->Enter();
-
- // Create an object that requires access-check functions to be
- // called for cross-domain access.
- v8::Handle<v8::ObjectTemplate> object_template =
- v8::ObjectTemplate::New(isolate);
- object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
- IndexedAccessFlatten);
- Local<v8::Object> object = object_template->NewInstance();
-
- v8::HandleScope scope1(isolate);
-
- // Create another environment.
- v8::Local<Context> context1 = Context::New(isolate);
- context1->Enter();
-
- // Make easy access to the object from the other environment.
- v8::Handle<v8::Object> global1 = context1->Global();
- global1->Set(v8_str("obj"), object);
-
- v8::Handle<Value> value;
-
- value = v8_compile("var p = 'as' + 'df';")->Run();
- value = v8_compile("obj[p];")->Run();
+ CHECK_EQ(43, access_count);
context1->Exit();
context0->Exit();
@@ -10869,16 +10972,29 @@ THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
try_catch.Reset();
CHECK(result.IsEmpty());
+ Maybe<PropertyAttribute> attr =
+ instance->GetRealNamedPropertyAttributes(v8_str("f"));
+ CHECK(!try_catch.HasCaught());
+ CHECK(Just(None) == attr);
+
result = another->GetRealNamedProperty(v8_str("f"));
CHECK(try_catch.HasCaught());
try_catch.Reset();
CHECK(result.IsEmpty());
+ attr = another->GetRealNamedPropertyAttributes(v8_str("f"));
+ CHECK(!try_catch.HasCaught());
+ CHECK(Just(None) == attr);
+
result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
CHECK(try_catch.HasCaught());
try_catch.Reset();
CHECK(result.IsEmpty());
+ attr = another->GetRealNamedPropertyAttributesInPrototypeChain(v8_str("f"));
+ CHECK(!try_catch.HasCaught());
+ CHECK(Just(None) == attr);
+
result = another->Get(v8_str("f"));
CHECK(try_catch.HasCaught());
try_catch.Reset();
@@ -10889,6 +11005,10 @@ THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
try_catch.Reset();
CHECK(result.IsEmpty());
+ attr = with_js_getter->GetRealNamedPropertyAttributes(v8_str("f"));
+ CHECK(!try_catch.HasCaught());
+ CHECK(Just(None) == attr);
+
result = with_js_getter->Get(v8_str("f"));
CHECK(try_catch.HasCaught());
try_catch.Reset();
@@ -12676,61 +12796,13 @@ THREADED_TEST(PropertyEnumeration2) {
}
}
-static bool NamedSetAccessBlocker(Local<v8::Object> obj,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- return type != v8::ACCESS_SET;
-}
-
-
-static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- return type != v8::ACCESS_SET;
-}
-
-
-THREADED_TEST(DisableAccessChecksWhileConfiguring) {
- LocalContext context;
- v8::Isolate* isolate = context->GetIsolate();
- v8::HandleScope scope(isolate);
- Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
- templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
- IndexedSetAccessBlocker);
- templ->Set(v8_str("x"), v8::True(isolate));
- Local<v8::Object> instance = templ->NewInstance();
- context->Global()->Set(v8_str("obj"), instance);
- Local<Value> value = CompileRun("obj.x");
- CHECK(value->BooleanValue());
-}
-
-
-static bool NamedGetAccessBlocker(Local<v8::Object> obj,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- return false;
-}
-
-
-static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- return false;
-}
-
-
THREADED_TEST(AccessChecksReenabledCorrectly) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
- templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
- IndexedGetAccessBlocker);
+ templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
templ->Set(v8_str("a"), v8_str("a"));
// Add more than 8 (see kMaxFastProperties) properties
// so that the constructor will force copying map.
@@ -12762,27 +12834,6 @@ THREADED_TEST(AccessChecksReenabledCorrectly) {
}
-// This tests that access check information remains on the global
-// object template when creating contexts.
-THREADED_TEST(AccessControlRepeatedContextCreation) {
- v8::Isolate* isolate = CcTest::isolate();
- v8::HandleScope handle_scope(isolate);
- v8::Handle<v8::ObjectTemplate> global_template =
- v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
- IndexedSetAccessBlocker);
- i::Handle<i::ObjectTemplateInfo> internal_template =
- v8::Utils::OpenHandle(*global_template);
- CHECK(!internal_template->constructor()->IsUndefined());
- i::Handle<i::FunctionTemplateInfo> constructor(
- i::FunctionTemplateInfo::cast(internal_template->constructor()));
- CHECK(!constructor->access_check_info()->IsUndefined());
- v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
- CHECK(!context0.IsEmpty());
- CHECK(!constructor->access_check_info()->IsUndefined());
-}
-
-
THREADED_TEST(TurnOnAccessCheck) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);
@@ -12791,10 +12842,8 @@ THREADED_TEST(TurnOnAccessCheck) {
// default.
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
- IndexedGetAccessBlocker,
- v8::Handle<v8::Value>(),
- false);
+ global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
+ v8::Handle<v8::Value>(), false);
v8::Local<Context> context = Context::New(isolate, NULL, global_template);
Context::Scope context_scope(context);
@@ -12850,109 +12899,6 @@ THREADED_TEST(TurnOnAccessCheck) {
}
-static const char* kPropertyA = "a";
-static const char* kPropertyH = "h";
-
-static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- if (!name->IsString()) return false;
- i::Handle<i::String> name_handle =
- v8::Utils::OpenHandle(String::Cast(*name));
- return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
- && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
-}
-
-
-THREADED_TEST(TurnOnAccessCheckAndRecompile) {
- v8::Isolate* isolate = CcTest::isolate();
- v8::HandleScope handle_scope(isolate);
-
- // Create an environment with access check to the global object disabled by
- // default. When the registered access checker will block access to properties
- // a and h.
- v8::Handle<v8::ObjectTemplate> global_template =
- v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
- IndexedGetAccessBlocker,
- v8::Handle<v8::Value>(),
- false);
- v8::Local<Context> context = Context::New(isolate, NULL, global_template);
- Context::Scope context_scope(context);
-
- // Set up a property and a number of functions.
- context->Global()->Set(v8_str("a"), v8_num(1));
- static const char* source = "function f1() {return a;}"
- "function f2() {return a;}"
- "function g1() {return h();}"
- "function g2() {return h();}"
- "function h() {return 1;}";
-
- CompileRun(source);
- Local<Function> f1;
- Local<Function> f2;
- Local<Function> g1;
- Local<Function> g2;
- Local<Function> h;
- f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
- f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
- g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
- g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
- h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
-
- // Get the global object.
- v8::Handle<v8::Object> global = context->Global();
-
- // Call f1 one time and f2 a number of times. This will ensure that f1 still
- // uses the runtime system to retreive property a whereas f2 uses global load
- // inline cache.
- CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
- for (int i = 0; i < 4; i++) {
- CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
- }
-
- // Same for g1 and g2.
- CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
- for (int i = 0; i < 4; i++) {
- CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
- }
-
- // Detach the global and turn on access check now blocking access to property
- // a and function h.
- Local<Object> hidden_global = Local<Object>::Cast(
- context->Global()->GetPrototype());
- context->DetachGlobal();
- hidden_global->TurnOnAccessCheck();
-
- // Failing access check results in exception.
- CHECK(f1->Call(global, 0, NULL).IsEmpty());
- CHECK(f2->Call(global, 0, NULL).IsEmpty());
- CHECK(g1->Call(global, 0, NULL).IsEmpty());
- CHECK(g2->Call(global, 0, NULL).IsEmpty());
-
- // No failing access check when just returning a constant.
- CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
-
- // Now compile the source again. And get the newly compiled functions, except
- // for h for which access is blocked.
- CompileRun(source);
- f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
- f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
- g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
- g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
- CHECK(hidden_global->Get(v8_str("h")).IsEmpty());
-
- // Failing access check results in exception.
- v8::Local<v8::Value> result = f1->Call(global, 0, NULL);
- CHECK(result.IsEmpty());
- CHECK(f1->Call(global, 0, NULL).IsEmpty());
- CHECK(f2->Call(global, 0, NULL).IsEmpty());
- CHECK(g1->Call(global, 0, NULL).IsEmpty());
- CHECK(g2->Call(global, 0, NULL).IsEmpty());
-}
-
-
// Tests that ScriptData can be serialized and deserialized.
TEST(PreCompileSerialization) {
v8::V8::Initialize();
@@ -15223,6 +15169,54 @@ TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
}
+static void StackTraceFunctionNameListener(v8::Handle<v8::Message> message,
+ v8::Handle<Value>) {
+ v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+ CHECK_EQ(5, stack_trace->GetFrameCount());
+ checkStackFrame("origin", "foo:0", 4, 7, false, false,
+ stack_trace->GetFrame(0));
+ checkStackFrame("origin", "foo:1", 5, 27, false, false,
+ stack_trace->GetFrame(1));
+ checkStackFrame("origin", "foo", 5, 27, false, false,
+ stack_trace->GetFrame(2));
+ checkStackFrame("origin", "foo", 5, 27, false, false,
+ stack_trace->GetFrame(3));
+ checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
+}
+
+
+TEST(GetStackTraceContainsFunctionsWithFunctionName) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ CompileRunWithOrigin(
+ "function gen(name, counter) {\n"
+ " var f = function foo() {\n"
+ " if (counter === 0)\n"
+ " throw 1;\n"
+ " gen(name, counter - 1)();\n"
+ " };\n"
+ " if (counter == 3) {\n"
+ " Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
+ " } else {\n"
+ " Object.defineProperty(f, 'name', {writable:true});\n"
+ " if (counter == 2)\n"
+ " f.name = 42;\n"
+ " else\n"
+ " f.name = name + ':' + counter;\n"
+ " }\n"
+ " return f;\n"
+ "};",
+ "origin");
+
+ v8::V8::AddMessageListener(StackTraceFunctionNameListener);
+ v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+ CompileRunWithOrigin("gen('foo', 3)();", "origin");
+ v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+ v8::V8::RemoveMessageListeners(StackTraceFunctionNameListener);
+}
+
+
static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data) {
// Use the frame where JavaScript is called from.
@@ -15991,30 +15985,10 @@ static void CreateGarbageInOldSpace() {
}
-// Test that idle notification can be handled and eventually returns true.
-TEST(IdleNotification) {
- const intptr_t MB = 1024 * 1024;
- const int IdlePauseInMs = 1000;
- LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
- intptr_t initial_size = CcTest::heap()->SizeOfObjects();
- CreateGarbageInOldSpace();
- intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
- CHECK_GT(size_with_garbage, initial_size + MB);
- bool finished = false;
- for (int i = 0; i < 200 && !finished; i++) {
- finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
- }
- intptr_t final_size = CcTest::heap()->SizeOfObjects();
- CHECK(finished);
- CHECK_LT(final_size, initial_size + 1);
-}
-
-
// Test that idle notification can be handled and eventually collects garbage.
-TEST(IdleNotificationWithSmallHint) {
+TEST(TestIdleNotification) {
const intptr_t MB = 1024 * 1024;
- const int IdlePauseInMs = 900;
+ const double IdlePauseInSeconds = 1.0;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
intptr_t initial_size = CcTest::heap()->SizeOfObjects();
@@ -16023,27 +15997,10 @@ TEST(IdleNotificationWithSmallHint) {
CHECK_GT(size_with_garbage, initial_size + MB);
bool finished = false;
for (int i = 0; i < 200 && !finished; i++) {
- finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
- }
- intptr_t final_size = CcTest::heap()->SizeOfObjects();
- CHECK(finished);
- CHECK_LT(final_size, initial_size + 1);
-}
-
-
-// Test that idle notification can be handled and eventually collects garbage.
-TEST(IdleNotificationWithLargeHint) {
- const intptr_t MB = 1024 * 1024;
- const int IdlePauseInMs = 900;
- LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
- intptr_t initial_size = CcTest::heap()->SizeOfObjects();
- CreateGarbageInOldSpace();
- intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
- CHECK_GT(size_with_garbage, initial_size + MB);
- bool finished = false;
- for (int i = 0; i < 200 && !finished; i++) {
- finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
+ finished = env->GetIsolate()->IdleNotificationDeadline(
+ (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
+ static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
+ IdlePauseInSeconds);
}
intptr_t final_size = CcTest::heap()->SizeOfObjects();
CHECK(finished);
@@ -16188,7 +16145,7 @@ TEST(ExternalizeOldSpaceTwoByteCons) {
CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
CcTest::heap()->CollectAllAvailableGarbage();
CHECK(CcTest::heap()->old_pointer_space()->Contains(
- *v8::Utils::OpenHandle(*cons)));
+ *v8::Utils::OpenHandle(*cons)));
TestResource* resource = new TestResource(
AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
@@ -16211,7 +16168,7 @@ TEST(ExternalizeOldSpaceOneByteCons) {
CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
CcTest::heap()->CollectAllAvailableGarbage();
CHECK(CcTest::heap()->old_pointer_space()->Contains(
- *v8::Utils::OpenHandle(*cons)));
+ *v8::Utils::OpenHandle(*cons)));
TestOneByteResource* resource =
new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
@@ -16501,6 +16458,7 @@ THREADED_TEST(SpaghettiStackReThrow) {
TEST(Regress528) {
v8::V8::Initialize();
v8::Isolate* isolate = CcTest::isolate();
+ i::FLAG_retain_maps_for_n_gc = 0;
v8::HandleScope scope(isolate);
v8::Local<Context> other_context;
int gc_count;
@@ -16593,7 +16551,8 @@ THREADED_TEST(ScriptOrigin) {
v8::String::NewFromUtf8(env->GetIsolate(), "test"),
v8::Integer::New(env->GetIsolate(), 1),
v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
- v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()));
+ v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()),
+ v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"));
v8::Handle<v8::String> script = v8::String::NewFromUtf8(
env->GetIsolate(), "function f() {}\n\nfunction g() {}");
v8::Script::Compile(script, &origin)->Run();
@@ -16608,6 +16567,10 @@ THREADED_TEST(ScriptOrigin) {
CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value());
CHECK(script_origin_f.ResourceIsSharedCrossOrigin()->Value());
CHECK(script_origin_f.ResourceIsEmbedderDebugScript()->Value());
+ printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
+
+ CHECK_EQ(0, strcmp("http://sourceMapUrl",
+ *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
CHECK_EQ(0, strcmp("test",
@@ -16615,6 +16578,8 @@ THREADED_TEST(ScriptOrigin) {
CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value());
CHECK(script_origin_g.ResourceIsSharedCrossOrigin()->Value());
CHECK(script_origin_g.ResourceIsEmbedderDebugScript()->Value());
+ CHECK_EQ(0, strcmp("http://sourceMapUrl",
+ *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
}
@@ -17457,10 +17422,8 @@ TEST(GCInFailedAccessCheckCallback) {
// check callbacks that will block access.
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
- IndexedGetAccessBlocker,
- v8::Handle<v8::Value>(),
- false);
+ global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
+ v8::Handle<v8::Value>(), false);
// Create a context and set an x property on it's global object.
LocalContext context0(NULL, global_template);
@@ -18230,18 +18193,22 @@ THREADED_TEST(CreationContext) {
instance2 = func2->NewInstance();
}
- CHECK(object1->CreationContext() == context1);
- CheckContextId(object1, 1);
- CHECK(func1->CreationContext() == context1);
- CheckContextId(func1, 1);
- CHECK(instance1->CreationContext() == context1);
- CheckContextId(instance1, 1);
- CHECK(object2->CreationContext() == context2);
- CheckContextId(object2, 2);
- CHECK(func2->CreationContext() == context2);
- CheckContextId(func2, 2);
- CHECK(instance2->CreationContext() == context2);
- CheckContextId(instance2, 2);
+ {
+ Handle<Context> other_context = Context::New(isolate);
+ Context::Scope scope(other_context);
+ CHECK(object1->CreationContext() == context1);
+ CheckContextId(object1, 1);
+ CHECK(func1->CreationContext() == context1);
+ CheckContextId(func1, 1);
+ CHECK(instance1->CreationContext() == context1);
+ CheckContextId(instance1, 1);
+ CHECK(object2->CreationContext() == context2);
+ CheckContextId(object2, 2);
+ CHECK(func2->CreationContext() == context2);
+ CheckContextId(func2, 2);
+ CHECK(instance2->CreationContext() == context2);
+ CheckContextId(instance2, 2);
+ }
{
Context::Scope scope(context1);
@@ -18288,6 +18255,8 @@ THREADED_TEST(CreationContextOfJsFunction) {
function = CompileRun("function foo() {}; foo").As<Object>();
}
+ Handle<Context> other_context = Context::New(CcTest::isolate());
+ Context::Scope scope(other_context);
CHECK(function->CreationContext() == context);
CheckContextId(function, 1);
}
@@ -18596,33 +18565,13 @@ THREADED_TEST(Regress1516) {
}
-static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- // Only block read access to __proto__.
- if (type == v8::ACCESS_GET && name->IsString() &&
- name.As<v8::String>()->Length() == 9 &&
- name.As<v8::String>()->Utf8Length() == 9) {
- char buffer[10];
- CHECK_EQ(10, name.As<v8::String>()->WriteUtf8(buffer));
- return strncmp(buffer, "__proto__", 9) != 0;
- }
-
- return true;
-}
-
-
THREADED_TEST(Regress93759) {
v8::Isolate* isolate = CcTest::isolate();
HandleScope scope(isolate);
// Template for object with security check.
Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
- // We don't do indexing, so any callback can be used for that.
- no_proto_template->SetAccessCheckCallbacks(
- BlockProtoNamedSecurityTestCallback,
- IndexedSecurityTestCallback);
+ no_proto_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
// Templates for objects with hidden prototypes and possibly security check.
Local<FunctionTemplate> hidden_proto_template =
@@ -18632,8 +18581,7 @@ THREADED_TEST(Regress93759) {
Local<FunctionTemplate> protected_hidden_proto_template =
v8::FunctionTemplate::New(isolate);
protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
- BlockProtoNamedSecurityTestCallback,
- IndexedSecurityTestCallback);
+ AccessAlwaysBlocked, NULL);
protected_hidden_proto_template->SetHiddenPrototype(true);
// Context for "foreign" objects used in test.
@@ -18644,12 +18592,10 @@ THREADED_TEST(Regress93759) {
Local<Object> simple_object = Object::New(isolate);
// Object with explicit security check.
- Local<Object> protected_object =
- no_proto_template->NewInstance();
+ Local<Object> protected_object = no_proto_template->NewInstance();
// JSGlobalProxy object, always have security check.
- Local<Object> proxy_object =
- context->Global();
+ Local<Object> proxy_object = context->Global();
// Global object, the prototype of proxy_object. No security checks.
Local<Object> global_object = proxy_object->GetPrototype()->ToObject(isolate);
@@ -19815,24 +19761,6 @@ THREADED_TEST(SemaphoreInterruption) {
#endif // V8_OS_POSIX
-static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- i::PrintF("Named access blocked.\n");
- return false;
-}
-
-
-static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- i::PrintF("Indexed access blocked.\n");
- return false;
-}
-
-
void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(false);
}
@@ -19847,8 +19775,7 @@ TEST(JSONStringifyAccessCheck) {
// check callbacks that will block access.
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
- IndexAccessAlwaysBlocked);
+ global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
// Create a context and set an x property on it's global object.
LocalContext context0(NULL, global_template);
@@ -19946,8 +19873,7 @@ TEST(AccessCheckThrows) {
// check callbacks that will block access.
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
- IndexAccessAlwaysBlocked);
+ global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
// Create a context and set an x property on it's global object.
LocalContext context0(NULL, global_template);
@@ -20100,6 +20026,7 @@ class RequestInterruptTestWithFunctionCall
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("ShouldContinue"), func);
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("while (ShouldContinue()) { }");
}
};
@@ -20115,6 +20042,7 @@ class RequestInterruptTestWithMethodCall
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
}
};
@@ -20130,6 +20058,7 @@ class RequestInterruptTestWithAccessor
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
}
};
@@ -20147,6 +20076,7 @@ class RequestInterruptTestWithNativeAccessor
v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
}
@@ -20176,6 +20106,7 @@ class RequestInterruptTestWithMethodCallAndInterceptor
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
}
@@ -20200,6 +20131,7 @@ class RequestInterruptTestWithMathAbs
v8::External::New(isolate_, this)));
i::FLAG_allow_natives_syntax = true;
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("function loopish(o) {"
" var pre = 10;"
" while (o.abs(1) > 0) {"
@@ -20283,6 +20215,7 @@ class RequestMultipleInterrupts : public RequestInterruptTestBase {
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("ShouldContinue"), func);
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("while (ShouldContinue()) { }");
}
@@ -21002,42 +20935,42 @@ TEST(Regress354123) {
v8::HandleScope scope(isolate);
v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
- templ->SetAccessCheckCallbacks(NamedAccessCounter, IndexedAccessCounter);
+ templ->SetAccessCheckCallbacks(AccessCounter, NULL);
current->Global()->Set(v8_str("friend"), templ->NewInstance());
// Test access using __proto__ from the prototype chain.
- named_access_count = 0;
+ access_count = 0;
CompileRun("friend.__proto__ = {};");
- CHECK_EQ(2, named_access_count);
+ CHECK_EQ(2, access_count);
CompileRun("friend.__proto__;");
- CHECK_EQ(4, named_access_count);
+ CHECK_EQ(4, access_count);
// Test access using __proto__ as a hijacked function (A).
- named_access_count = 0;
+ access_count = 0;
CompileRun("var p = Object.prototype;"
"var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
"f.call(friend, {});");
- CHECK_EQ(1, named_access_count);
+ CHECK_EQ(1, access_count);
CompileRun("var p = Object.prototype;"
"var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
"f.call(friend);");
- CHECK_EQ(2, named_access_count);
+ CHECK_EQ(2, access_count);
// Test access using __proto__ as a hijacked function (B).
- named_access_count = 0;
+ access_count = 0;
CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
"f.call(friend, {});");
- CHECK_EQ(1, named_access_count);
+ CHECK_EQ(1, access_count);
CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
"f.call(friend);");
- CHECK_EQ(2, named_access_count);
+ CHECK_EQ(2, access_count);
// Test access using Object.setPrototypeOf reflective method.
- named_access_count = 0;
+ access_count = 0;
CompileRun("Object.setPrototypeOf(friend, {});");
- CHECK_EQ(1, named_access_count);
+ CHECK_EQ(1, access_count);
CompileRun("Object.getPrototypeOf(friend);");
- CHECK_EQ(2, named_access_count);
+ CHECK_EQ(2, access_count);
}
@@ -21192,8 +21125,7 @@ TEST(Regress411877) {
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate);
- object_template->SetAccessCheckCallbacks(NamedAccessCounter,
- IndexedAccessCounter);
+ object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
v8::Handle<Context> context = Context::New(isolate);
v8::Context::Scope context_scope(context);
@@ -21208,8 +21140,7 @@ TEST(GetHiddenPropertyTableAfterAccessCheck) {
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate);
- object_template->SetAccessCheckCallbacks(NamedAccessCounter,
- IndexedAccessCounter);
+ object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
v8::Handle<Context> context = Context::New(isolate);
v8::Context::Scope context_scope(context);
@@ -21227,8 +21158,7 @@ TEST(Regress411793) {
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate);
- object_template->SetAccessCheckCallbacks(NamedAccessCounter,
- IndexedAccessCounter);
+ object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
v8::Handle<Context> context = Context::New(isolate);
v8::Context::Scope context_scope(context);
@@ -21806,6 +21736,7 @@ TEST(TurboAsmDisablesNeuter) {
"Module(this, {}, buffer).load();"
"buffer";
+ i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
CHECK_EQ(should_be_neuterable, result->IsNeuterable());
@@ -21820,6 +21751,7 @@ TEST(TurboAsmDisablesNeuter) {
"Module(this, {}, buffer).store();"
"buffer";
+ i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
result = CompileRun(store).As<v8::ArrayBuffer>();
CHECK_EQ(should_be_neuterable, result->IsNeuterable());
}
@@ -21833,8 +21765,7 @@ TEST(GetPrototypeAccessControl) {
v8::Handle<v8::ObjectTemplate> obj_template =
v8::ObjectTemplate::New(isolate);
- obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
- BlockEverythingIndexed);
+ obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
@@ -21917,7 +21848,6 @@ TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
TEST(NewStringRangeError) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);
- LocalContext env;
const int length = i::String::kMaxLength + 1;
const int buffer_size = length * sizeof(uint16_t);
void* buffer = malloc(buffer_size);
@@ -21928,21 +21858,21 @@ TEST(NewStringRangeError) {
char* data = reinterpret_cast<char*>(buffer);
CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString,
length).IsEmpty());
- CHECK(try_catch.HasCaught());
+ CHECK(!try_catch.HasCaught());
}
{
v8::TryCatch try_catch;
uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString,
length).IsEmpty());
- CHECK(try_catch.HasCaught());
+ CHECK(!try_catch.HasCaught());
}
{
v8::TryCatch try_catch;
uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString,
length).IsEmpty());
- CHECK(try_catch.HasCaught());
+ CHECK(!try_catch.HasCaught());
}
free(buffer);
}
diff --git a/deps/v8/test/cctest/test-array-list.cc b/deps/v8/test/cctest/test-array-list.cc
new file mode 100644
index 0000000000..2852043b2f
--- /dev/null
+++ b/deps/v8/test/cctest/test-array-list.cc
@@ -0,0 +1,41 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "src/v8.h"
+
+#include "src/factory.h"
+#include "test/cctest/cctest.h"
+
+namespace {
+
+using namespace v8::internal;
+
+
+TEST(ArrayList) {
+ LocalContext context;
+ Isolate* isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+ Handle<ArrayList> array(
+ ArrayList::cast(isolate->heap()->empty_fixed_array()));
+ CHECK_EQ(0, array->Length());
+ array = ArrayList::Add(array, handle(Smi::FromInt(100), isolate));
+ CHECK_EQ(1, array->Length());
+ CHECK_EQ(100, Smi::cast(array->Get(0))->value());
+ array = ArrayList::Add(array, handle(Smi::FromInt(200), isolate),
+ handle(Smi::FromInt(300), isolate));
+ CHECK_EQ(3, array->Length());
+ CHECK_EQ(100, Smi::cast(array->Get(0))->value());
+ CHECK_EQ(200, Smi::cast(array->Get(1))->value());
+ CHECK_EQ(300, Smi::cast(array->Get(2))->value());
+ array->Set(2, Smi::FromInt(400));
+ CHECK_EQ(400, Smi::cast(array->Get(2))->value());
+ array->Clear(2, isolate->heap()->undefined_value());
+ array->SetLength(2);
+ CHECK_EQ(2, array->Length());
+ CHECK_EQ(100, Smi::cast(array->Get(0))->value());
+ CHECK_EQ(200, Smi::cast(array->Get(1))->value());
+}
+}
diff --git a/deps/v8/test/cctest/test-assembler-arm64.cc b/deps/v8/test/cctest/test-assembler-arm64.cc
index df8477ba9f..e54c4894b7 100644
--- a/deps/v8/test/cctest/test-assembler-arm64.cc
+++ b/deps/v8/test/cctest/test-assembler-arm64.cc
@@ -11223,3 +11223,173 @@ TEST(pool_size) {
TEARDOWN();
}
+
+
+TEST(jump_tables_forward) {
+ // Test jump tables with forward jumps.
+ const int kNumCases = 512;
+
+ INIT_V8();
+ SETUP_SIZE(kNumCases * 5 * kInstructionSize + 8192);
+ START();
+
+ int32_t values[kNumCases];
+ isolate->random_number_generator()->NextBytes(values, sizeof(values));
+ int32_t results[kNumCases];
+ memset(results, 0, sizeof(results));
+ uintptr_t results_ptr = reinterpret_cast<uintptr_t>(results);
+
+ Label loop;
+ Label labels[kNumCases];
+ Label done;
+
+ const Register& index = x0;
+ STATIC_ASSERT(sizeof(results[0]) == 4);
+ const Register& value = w1;
+ const Register& target = x2;
+
+ __ Mov(index, 0);
+ __ Mov(target, results_ptr);
+ __ Bind(&loop);
+
+ {
+ Assembler::BlockPoolsScope block_pools(&masm);
+ Label base;
+
+ __ Adr(x10, &base);
+ __ Ldr(x11, MemOperand(x10, index, LSL, kPointerSizeLog2));
+ __ Br(x11);
+ __ Bind(&base);
+ for (int i = 0; i < kNumCases; ++i) {
+ __ dcptr(&labels[i]);
+ }
+ }
+
+ for (int i = 0; i < kNumCases; ++i) {
+ __ Bind(&labels[i]);
+ __ Mov(value, values[i]);
+ __ B(&done);
+ }
+
+ __ Bind(&done);
+ __ Str(value, MemOperand(target, 4, PostIndex));
+ __ Add(index, index, 1);
+ __ Cmp(index, kNumCases);
+ __ B(ne, &loop);
+
+ END();
+
+ RUN();
+
+ for (int i = 0; i < kNumCases; ++i) {
+ CHECK_EQ(values[i], results[i]);
+ }
+
+ TEARDOWN();
+}
+
+
+TEST(jump_tables_backward) {
+ // Test jump tables with backward jumps.
+ const int kNumCases = 512;
+
+ INIT_V8();
+ SETUP_SIZE(kNumCases * 5 * kInstructionSize + 8192);
+ START();
+
+ int32_t values[kNumCases];
+ isolate->random_number_generator()->NextBytes(values, sizeof(values));
+ int32_t results[kNumCases];
+ memset(results, 0, sizeof(results));
+ uintptr_t results_ptr = reinterpret_cast<uintptr_t>(results);
+
+ Label loop;
+ Label labels[kNumCases];
+ Label done;
+
+ const Register& index = x0;
+ STATIC_ASSERT(sizeof(results[0]) == 4);
+ const Register& value = w1;
+ const Register& target = x2;
+
+ __ Mov(index, 0);
+ __ Mov(target, results_ptr);
+ __ B(&loop);
+
+ for (int i = 0; i < kNumCases; ++i) {
+ __ Bind(&labels[i]);
+ __ Mov(value, values[i]);
+ __ B(&done);
+ }
+
+ __ Bind(&loop);
+ {
+ Assembler::BlockPoolsScope block_pools(&masm);
+ Label base;
+
+ __ Adr(x10, &base);
+ __ Ldr(x11, MemOperand(x10, index, LSL, kPointerSizeLog2));
+ __ Br(x11);
+ __ Bind(&base);
+ for (int i = 0; i < kNumCases; ++i) {
+ __ dcptr(&labels[i]);
+ }
+ }
+
+ __ Bind(&done);
+ __ Str(value, MemOperand(target, 4, PostIndex));
+ __ Add(index, index, 1);
+ __ Cmp(index, kNumCases);
+ __ B(ne, &loop);
+
+ END();
+
+ RUN();
+
+ for (int i = 0; i < kNumCases; ++i) {
+ CHECK_EQ(values[i], results[i]);
+ }
+
+ TEARDOWN();
+}
+
+
+TEST(internal_reference_linked) {
+ // Test internal reference when they are linked in a label chain.
+
+ INIT_V8();
+ SETUP();
+ START();
+
+ Label done;
+
+ __ Mov(x0, 0);
+ __ Cbnz(x0, &done);
+
+ {
+ Assembler::BlockPoolsScope block_pools(&masm);
+ Label base;
+
+ __ Adr(x10, &base);
+ __ Ldr(x11, MemOperand(x10));
+ __ Br(x11);
+ __ Bind(&base);
+ __ dcptr(&done);
+ }
+
+ // Dead code, just to extend the label chain.
+ __ B(&done);
+ __ dcptr(&done);
+ __ Tbz(x0, 1, &done);
+
+ __ Bind(&done);
+ __ Mov(x0, 1);
+
+ END();
+
+ RUN();
+
+ CHECK_EQUAL_64(0x1, x0);
+
+ TEARDOWN();
+}
diff --git a/deps/v8/test/cctest/test-assembler-ia32.cc b/deps/v8/test/cctest/test-assembler-ia32.cc
index 46592a05d1..5a7ad0294a 100644
--- a/deps/v8/test/cctest/test-assembler-ia32.cc
+++ b/deps/v8/test/cctest/test-assembler-ia32.cc
@@ -34,7 +34,6 @@
#include "src/factory.h"
#include "src/macro-assembler.h"
#include "src/ostreams.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-assembler-mips64.cc b/deps/v8/test/cctest/test-assembler-mips64.cc
index d4cabbcf72..e55fb24282 100644
--- a/deps/v8/test/cctest/test-assembler-mips64.cc
+++ b/deps/v8/test/cctest/test-assembler-mips64.cc
@@ -1585,7 +1585,7 @@ TEST(jump_tables3) {
__ bind(&done);
__ ld(ra, MemOperand(sp));
- __ addiu(sp, sp, 8);
+ __ daddiu(sp, sp, 8);
__ jr(ra);
__ nop();
@@ -1594,7 +1594,7 @@ TEST(jump_tables3) {
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
-// code->Print(std::cout);
+ code->Print(std::cout);
#endif
F1 f = FUNCTION_CAST<F1>(code->entry());
for (int i = 0; i < kNumCases; ++i) {
diff --git a/deps/v8/test/cctest/test-assembler-x64.cc b/deps/v8/test/cctest/test-assembler-x64.cc
index f5d59ded9b..ca88309bb6 100644
--- a/deps/v8/test/cctest/test-assembler-x64.cc
+++ b/deps/v8/test/cctest/test-assembler-x64.cc
@@ -34,7 +34,6 @@
#include "src/factory.h"
#include "src/macro-assembler.h"
#include "src/ostreams.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-assembler-x87.cc b/deps/v8/test/cctest/test-assembler-x87.cc
index c07be845b9..f83bbbd0d8 100644
--- a/deps/v8/test/cctest/test-assembler-x87.cc
+++ b/deps/v8/test/cctest/test-assembler-x87.cc
@@ -34,7 +34,6 @@
#include "src/factory.h"
#include "src/macro-assembler.h"
#include "src/ostreams.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc
index faf533239e..ed8b1c6d99 100644
--- a/deps/v8/test/cctest/test-compiler.cc
+++ b/deps/v8/test/cctest/test-compiler.cc
@@ -60,7 +60,7 @@ static Handle<JSFunction> Compile(const char* source) {
Handle<String> source_code = isolate->factory()->NewStringFromUtf8(
CStrVector(source)).ToHandleChecked();
Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript(
- source_code, Handle<String>(), 0, 0, false, false,
+ source_code, Handle<String>(), 0, 0, false, false, Handle<Object>(),
Handle<Context>(isolate->native_context()), NULL, NULL,
v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE, false);
return isolate->factory()->NewFunctionFromSharedFunctionInfo(
diff --git a/deps/v8/test/cctest/test-constantpool.cc b/deps/v8/test/cctest/test-constantpool.cc
index 453657609e..8b9b2cf73a 100644
--- a/deps/v8/test/cctest/test-constantpool.cc
+++ b/deps/v8/test/cctest/test-constantpool.cc
@@ -284,8 +284,9 @@ TEST(ConstantPoolCompacting) {
Page* first_page = heap->old_data_space()->anchor()->next_page();
{
HandleScope scope(isolate);
+ int dummy_array_size = Page::kMaxRegularHeapObjectSize - 92 * KB;
Handle<HeapObject> temp =
- factory->NewFixedDoubleArray(900 * KB / kDoubleSize, TENURED);
+ factory->NewFixedDoubleArray(dummy_array_size / kDoubleSize, TENURED);
CHECK(heap->InOldDataSpace(temp->address()));
Handle<HeapObject> heap_ptr =
factory->NewHeapNumber(5.0, IMMUTABLE, TENURED);
diff --git a/deps/v8/test/cctest/test-conversions.cc b/deps/v8/test/cctest/test-conversions.cc
index b7881edcf6..789425119d 100644
--- a/deps/v8/test/cctest/test-conversions.cc
+++ b/deps/v8/test/cctest/test-conversions.cc
@@ -362,3 +362,58 @@ TEST(BitField64) {
CHECK(x == MiddleBits::encode(3));
CHECK_EQ(3, MiddleBits::decode(x));
}
+
+
+static void CheckNonArrayIndex(bool expected, const char* chars) {
+ auto isolate = CcTest::i_isolate();
+ auto string = isolate->factory()->NewStringFromAsciiChecked(chars);
+ CHECK_EQ(expected, IsNonArrayIndexInteger(*string));
+}
+
+
+TEST(NonArrayIndexParsing) {
+ auto isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+ CheckNonArrayIndex(false, "");
+ CheckNonArrayIndex(false, "-");
+ CheckNonArrayIndex(false, "0");
+ CheckNonArrayIndex(false, "01");
+ CheckNonArrayIndex(false, "-01");
+ CheckNonArrayIndex(false, "4294967295");
+ CheckNonArrayIndex(false, "429496.7295");
+ CheckNonArrayIndex(false, "43s3");
+ CheckNonArrayIndex(true, "-0");
+ CheckNonArrayIndex(true, "-1");
+ CheckNonArrayIndex(true, "4294967296");
+ CheckNonArrayIndex(true, "-4294967296");
+ CheckNonArrayIndex(
+ true,
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296");
+ CheckNonArrayIndex(
+ true,
+ "-429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296"
+ "429496729642949672964294967296429496729642949672964294967296");
+}
diff --git a/deps/v8/test/cctest/test-cpu-profiler.cc b/deps/v8/test/cctest/test-cpu-profiler.cc
index e2b6db0b96..a8cbdd505c 100644
--- a/deps/v8/test/cctest/test-cpu-profiler.cc
+++ b/deps/v8/test/cctest/test-cpu-profiler.cc
@@ -56,6 +56,16 @@ static v8::Local<v8::Function> GetFunction(v8::Context* env, const char* name) {
}
+static int offset(const char* src, const char* substring) {
+ return static_cast<int>(strstr(src, substring) - src);
+}
+
+
+static const char* reason(const i::Deoptimizer::DeoptReason reason) {
+ return i::Deoptimizer::GetDeoptReason(reason);
+}
+
+
TEST(StartStop) {
i::Isolate* isolate = CcTest::i_isolate();
CpuProfilesCollection profiles(isolate->heap());
@@ -433,8 +443,7 @@ static v8::CpuProfile* RunProfiler(
static bool ContainsString(v8::Handle<v8::String> string,
const Vector<v8::Handle<v8::String> >& vector) {
for (int i = 0; i < vector.length(); i++) {
- if (string->Equals(vector[i]))
- return true;
+ if (string->Equals(vector[i])) return true;
}
return false;
}
@@ -445,18 +454,31 @@ static void CheckChildrenNames(const v8::CpuProfileNode* node,
int count = node->GetChildrenCount();
for (int i = 0; i < count; i++) {
v8::Handle<v8::String> name = node->GetChild(i)->GetFunctionName();
- CHECK(ContainsString(name, names));
+ if (!ContainsString(name, names)) {
+ char buffer[100];
+ i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
+ "Unexpected child '%s' found in '%s'",
+ *v8::String::Utf8Value(name),
+ *v8::String::Utf8Value(node->GetFunctionName()));
+ FATAL(buffer);
+ }
// Check that there are no duplicates.
for (int j = 0; j < count; j++) {
if (j == i) continue;
- CHECK(!name->Equals(node->GetChild(j)->GetFunctionName()));
+ if (name->Equals(node->GetChild(j)->GetFunctionName())) {
+ char buffer[100];
+ i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
+ "Second child with the same name '%s' found in '%s'",
+ *v8::String::Utf8Value(name),
+ *v8::String::Utf8Value(node->GetFunctionName()));
+ FATAL(buffer);
+ }
}
}
}
-static const v8::CpuProfileNode* FindChild(v8::Isolate* isolate,
- const v8::CpuProfileNode* node,
+static const v8::CpuProfileNode* FindChild(const v8::CpuProfileNode* node,
const char* name) {
int count = node->GetChildrenCount();
v8::Handle<v8::String> nameHandle = v8_str(name);
@@ -468,10 +490,9 @@ static const v8::CpuProfileNode* FindChild(v8::Isolate* isolate,
}
-static const v8::CpuProfileNode* GetChild(v8::Isolate* isolate,
- const v8::CpuProfileNode* node,
+static const v8::CpuProfileNode* GetChild(const v8::CpuProfileNode* node,
const char* name) {
- const v8::CpuProfileNode* result = FindChild(isolate, node, name);
+ const v8::CpuProfileNode* result = FindChild(node, name);
if (!result) {
char buffer[100];
i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
@@ -482,26 +503,24 @@ static const v8::CpuProfileNode* GetChild(v8::Isolate* isolate,
}
-static void CheckSimpleBranch(v8::Isolate* isolate,
- const v8::CpuProfileNode* node,
+static void CheckSimpleBranch(const v8::CpuProfileNode* node,
const char* names[], int length) {
for (int i = 0; i < length; i++) {
const char* name = names[i];
- node = GetChild(isolate, node, name);
+ node = GetChild(node, name);
int expectedChildrenCount = (i == length - 1) ? 0 : 1;
CHECK_EQ(expectedChildrenCount, node->GetChildrenCount());
}
}
-static const v8::CpuProfileNode* GetSimpleBranch(v8::Isolate* isolate,
- const v8::CpuProfileNode* node,
- const char* names[],
- int length) {
+static const ProfileNode* GetSimpleBranch(v8::CpuProfile* profile,
+ const char* names[], int length) {
+ const v8::CpuProfileNode* node = profile->GetTopDownRoot();
for (int i = 0; i < length; i++) {
- node = GetChild(isolate, node, names[i]);
+ node = GetChild(node, names[i]);
}
- return node;
+ return reinterpret_cast<const ProfileNode*>(node);
}
@@ -577,23 +596,18 @@ TEST(CollectCpuProfile) {
names[2] = v8_str("start");
CheckChildrenNames(root, names);
- const v8::CpuProfileNode* startNode =
- GetChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
CHECK_EQ(1, startNode->GetChildrenCount());
- const v8::CpuProfileNode* fooNode =
- GetChild(env->GetIsolate(), startNode, "foo");
+ const v8::CpuProfileNode* fooNode = GetChild(startNode, "foo");
CHECK_EQ(3, fooNode->GetChildrenCount());
const char* barBranch[] = { "bar", "delay", "loop" };
- CheckSimpleBranch(env->GetIsolate(), fooNode, barBranch,
- arraysize(barBranch));
+ CheckSimpleBranch(fooNode, barBranch, arraysize(barBranch));
const char* bazBranch[] = { "baz", "delay", "loop" };
- CheckSimpleBranch(env->GetIsolate(), fooNode, bazBranch,
- arraysize(bazBranch));
+ CheckSimpleBranch(fooNode, bazBranch, arraysize(bazBranch));
const char* delayBranch[] = { "delay", "loop" };
- CheckSimpleBranch(env->GetIsolate(), fooNode, delayBranch,
- arraysize(delayBranch));
+ CheckSimpleBranch(fooNode, delayBranch, arraysize(delayBranch));
profile->Delete();
}
@@ -650,11 +664,10 @@ TEST(HotDeoptNoFrameEntry) {
names[2] = v8_str("start");
CheckChildrenNames(root, names);
- const v8::CpuProfileNode* startNode =
- GetChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
CHECK_EQ(1, startNode->GetChildrenCount());
- GetChild(env->GetIsolate(), startNode, "foo");
+ GetChild(startNode, "foo");
profile->Delete();
}
@@ -736,17 +749,15 @@ TEST(SampleWhenFrameIsNotSetup) {
names[2] = v8_str("start");
CheckChildrenNames(root, names);
- const v8::CpuProfileNode* startNode =
- FindChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = FindChild(root, "start");
// On slow machines there may be no meaningfull samples at all, skip the
// check there.
if (startNode && startNode->GetChildrenCount() > 0) {
CHECK_EQ(1, startNode->GetChildrenCount());
- const v8::CpuProfileNode* delayNode =
- GetChild(env->GetIsolate(), startNode, "delay");
+ const v8::CpuProfileNode* delayNode = GetChild(startNode, "delay");
if (delayNode->GetChildrenCount() > 0) {
CHECK_EQ(1, delayNode->GetChildrenCount());
- GetChild(env->GetIsolate(), delayNode, "loop");
+ GetChild(delayNode, "loop");
}
}
@@ -842,10 +853,9 @@ TEST(NativeAccessorUninitializedIC) {
RunProfiler(env.local(), function, args, arraysize(args), 180);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- const v8::CpuProfileNode* startNode =
- GetChild(isolate, root, "start");
- GetChild(isolate, startNode, "get foo");
- GetChild(isolate, startNode, "set foo");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ GetChild(startNode, "get foo");
+ GetChild(startNode, "set foo");
profile->Delete();
}
@@ -894,10 +904,9 @@ TEST(NativeAccessorMonomorphicIC) {
RunProfiler(env.local(), function, args, arraysize(args), 200);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- const v8::CpuProfileNode* startNode =
- GetChild(isolate, root, "start");
- GetChild(isolate, startNode, "get foo");
- GetChild(isolate, startNode, "set foo");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ GetChild(startNode, "get foo");
+ GetChild(startNode, "set foo");
profile->Delete();
}
@@ -944,9 +953,8 @@ TEST(NativeMethodUninitializedIC) {
RunProfiler(env.local(), function, args, arraysize(args), 100);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- const v8::CpuProfileNode* startNode =
- GetChild(isolate, root, "start");
- GetChild(isolate, startNode, "fooMethod");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ GetChild(startNode, "fooMethod");
profile->Delete();
}
@@ -997,10 +1005,9 @@ TEST(NativeMethodMonomorphicIC) {
RunProfiler(env.local(), function, args, arraysize(args), 100);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- GetChild(isolate, root, "start");
- const v8::CpuProfileNode* startNode =
- GetChild(isolate, root, "start");
- GetChild(isolate, startNode, "fooMethod");
+ GetChild(root, "start");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ GetChild(startNode, "fooMethod");
profile->Delete();
}
@@ -1034,9 +1041,8 @@ TEST(BoundFunctionCall) {
// Don't allow |foo| node to be at the top level.
CheckChildrenNames(root, names);
- const v8::CpuProfileNode* startNode =
- GetChild(env->GetIsolate(), root, "start");
- GetChild(env->GetIsolate(), startNode, "foo");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ GetChild(startNode, "foo");
profile->Delete();
}
@@ -1086,10 +1092,10 @@ TEST(TickLines) {
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
profiles->StartProfiling("", false);
ProfileGenerator generator(profiles);
- ProfilerEventsProcessor* processor = new ProfilerEventsProcessor(
- &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100));
+ SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
+ &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
processor->Start();
- CpuProfiler profiler(isolate, profiles, &generator, processor);
+ CpuProfiler profiler(isolate, profiles, &generator, processor.get());
// Enqueue code creation events.
i::Handle<i::String> str = factory->NewStringFromAsciiChecked(func_name);
@@ -1099,7 +1105,7 @@ TEST(TickLines) {
*str, line, column);
// Enqueue a tick event to enable code events processing.
- EnqueueTickSampleEvent(processor, code_address);
+ EnqueueTickSampleEvent(processor.get(), code_address);
processor->StopSynchronously();
@@ -1197,8 +1203,7 @@ TEST(FunctionCallSample) {
// won't be |start| node in the profiles.
bool is_gc_stress_testing =
(i::FLAG_gc_interval != -1) || i::FLAG_stress_compaction;
- const v8::CpuProfileNode* startNode =
- FindChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = FindChild(root, "start");
CHECK(is_gc_stress_testing || startNode);
if (startNode) {
ScopedVector<v8::Handle<v8::String> > names(2);
@@ -1207,8 +1212,8 @@ TEST(FunctionCallSample) {
CheckChildrenNames(startNode, names);
}
- const v8::CpuProfileNode* unresolvedNode = FindChild(
- env->GetIsolate(), root, i::ProfileGenerator::kUnresolvedFunctionName);
+ const v8::CpuProfileNode* unresolvedNode =
+ FindChild(root, i::ProfileGenerator::kUnresolvedFunctionName);
if (unresolvedNode) {
ScopedVector<v8::Handle<v8::String> > names(1);
names[0] = v8_str("call");
@@ -1270,8 +1275,7 @@ TEST(FunctionApplySample) {
CheckChildrenNames(root, names);
}
- const v8::CpuProfileNode* startNode =
- FindChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = FindChild(root, "start");
if (startNode) {
{
ScopedVector<v8::Handle<v8::String> > names(2);
@@ -1280,8 +1284,7 @@ TEST(FunctionApplySample) {
CheckChildrenNames(startNode, names);
}
- const v8::CpuProfileNode* testNode =
- FindChild(env->GetIsolate(), startNode, "test");
+ const v8::CpuProfileNode* testNode = FindChild(startNode, "test");
if (testNode) {
ScopedVector<v8::Handle<v8::String> > names(3);
names[0] = v8_str("bar");
@@ -1293,12 +1296,11 @@ TEST(FunctionApplySample) {
}
if (const v8::CpuProfileNode* unresolvedNode =
- FindChild(env->GetIsolate(), startNode,
- ProfileGenerator::kUnresolvedFunctionName)) {
+ FindChild(startNode, ProfileGenerator::kUnresolvedFunctionName)) {
ScopedVector<v8::Handle<v8::String> > names(1);
names[0] = v8_str("apply");
CheckChildrenNames(unresolvedNode, names);
- GetChild(env->GetIsolate(), unresolvedNode, "apply");
+ GetChild(unresolvedNode, "apply");
}
}
@@ -1354,10 +1356,9 @@ TEST(CpuProfileDeepStack) {
CheckChildrenNames(root, names);
}
- const v8::CpuProfileNode* node =
- GetChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* node = GetChild(root, "start");
for (int i = 0; i < 250; ++i) {
- node = GetChild(env->GetIsolate(), node, "foo");
+ node = GetChild(node, "foo");
}
// TODO(alph):
// In theory there must be one more 'foo' and a 'startProfiling' nodes,
@@ -1419,18 +1420,16 @@ TEST(JsNativeJsSample) {
CheckChildrenNames(root, names);
}
- const v8::CpuProfileNode* startNode =
- GetChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
CHECK_EQ(1, startNode->GetChildrenCount());
const v8::CpuProfileNode* nativeFunctionNode =
- GetChild(env->GetIsolate(), startNode, "CallJsFunction");
+ GetChild(startNode, "CallJsFunction");
CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
- const v8::CpuProfileNode* barNode =
- GetChild(env->GetIsolate(), nativeFunctionNode, "bar");
+ const v8::CpuProfileNode* barNode = GetChild(nativeFunctionNode, "bar");
CHECK_EQ(1, barNode->GetChildrenCount());
- GetChild(env->GetIsolate(), barNode, "foo");
+ GetChild(barNode, "foo");
profile->Delete();
}
@@ -1481,22 +1480,20 @@ TEST(JsNativeJsRuntimeJsSample) {
names[2] = v8_str("start");
CheckChildrenNames(root, names);
- const v8::CpuProfileNode* startNode =
- GetChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
CHECK_EQ(1, startNode->GetChildrenCount());
const v8::CpuProfileNode* nativeFunctionNode =
- GetChild(env->GetIsolate(), startNode, "CallJsFunction");
+ GetChild(startNode, "CallJsFunction");
CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
- const v8::CpuProfileNode* barNode =
- GetChild(env->GetIsolate(), nativeFunctionNode, "bar");
+ const v8::CpuProfileNode* barNode = GetChild(nativeFunctionNode, "bar");
// The child is in fact a bound foo.
// A bound function has a wrapper that may make calls to
// other functions e.g. "get length".
CHECK_LE(1, barNode->GetChildrenCount());
CHECK_GE(2, barNode->GetChildrenCount());
- GetChild(env->GetIsolate(), barNode, "foo");
+ GetChild(barNode, "foo");
profile->Delete();
}
@@ -1560,22 +1557,19 @@ TEST(JsNative1JsNative2JsSample) {
names[2] = v8_str("start");
CheckChildrenNames(root, names);
- const v8::CpuProfileNode* startNode =
- GetChild(env->GetIsolate(), root, "start");
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
CHECK_EQ(1, startNode->GetChildrenCount());
const v8::CpuProfileNode* nativeNode1 =
- GetChild(env->GetIsolate(), startNode, "CallJsFunction1");
+ GetChild(startNode, "CallJsFunction1");
CHECK_EQ(1, nativeNode1->GetChildrenCount());
- const v8::CpuProfileNode* barNode =
- GetChild(env->GetIsolate(), nativeNode1, "bar");
+ const v8::CpuProfileNode* barNode = GetChild(nativeNode1, "bar");
CHECK_EQ(1, barNode->GetChildrenCount());
- const v8::CpuProfileNode* nativeNode2 =
- GetChild(env->GetIsolate(), barNode, "CallJsFunction2");
+ const v8::CpuProfileNode* nativeNode2 = GetChild(barNode, "CallJsFunction2");
CHECK_EQ(1, nativeNode2->GetChildrenCount());
- GetChild(env->GetIsolate(), nativeNode2, "foo");
+ GetChild(nativeNode2, "foo");
profile->Delete();
}
@@ -1620,12 +1614,12 @@ TEST(IdleTime) {
CheckChildrenNames(root, names);
const v8::CpuProfileNode* programNode =
- GetChild(env->GetIsolate(), root, ProfileGenerator::kProgramEntryName);
+ GetChild(root, ProfileGenerator::kProgramEntryName);
CHECK_EQ(0, programNode->GetChildrenCount());
CHECK_GE(programNode->GetHitCount(), 3u);
const v8::CpuProfileNode* idleNode =
- GetChild(env->GetIsolate(), root, ProfileGenerator::kIdleEntryName);
+ GetChild(root, ProfileGenerator::kIdleEntryName);
CHECK_EQ(0, idleNode->GetChildrenCount());
CHECK_GE(idleNode->GetHitCount(), 3u);
@@ -1672,16 +1666,16 @@ TEST(FunctionDetails) {
// 0 foo 18 #4 TryCatchStatement script_a:2
// 1 bar 18 #5 no reason script_a:3
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- const v8::CpuProfileNode* script = GetChild(env->GetIsolate(), root, "");
+ const v8::CpuProfileNode* script = GetChild(root, "");
CheckFunctionDetails(env->GetIsolate(), script, "", "script_b",
script_b->GetUnboundScript()->GetId(), 1, 1);
- const v8::CpuProfileNode* baz = GetChild(env->GetIsolate(), script, "baz");
+ const v8::CpuProfileNode* baz = GetChild(script, "baz");
CheckFunctionDetails(env->GetIsolate(), baz, "baz", "script_b",
script_b->GetUnboundScript()->GetId(), 3, 16);
- const v8::CpuProfileNode* foo = GetChild(env->GetIsolate(), baz, "foo");
+ const v8::CpuProfileNode* foo = GetChild(baz, "foo");
CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a",
script_a->GetUnboundScript()->GetId(), 2, 1);
- const v8::CpuProfileNode* bar = GetChild(env->GetIsolate(), foo, "bar");
+ const v8::CpuProfileNode* bar = GetChild(foo, "bar");
CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a",
script_a->GetUnboundScript()->GetId(), 3, 14);
}
@@ -1720,39 +1714,17 @@ TEST(DontStopOnFinishedProfileDelete) {
}
-static const char* collect_deopt_events_test_source =
- "function opt_function(left, right, depth) {\n"
- " if (depth) return opt_function(left, right, depth - 1);\n"
- "\n"
- " var k = left / 10;\n"
- " var r = 10 / right;\n"
- " return k + r;"
- "}\n"
- "\n"
- "function test(left, right) {\n"
- " return opt_function(left, right, 1);\n"
- "}\n"
- "\n"
- "startProfiling();\n"
- "\n"
- "test(10, 10);\n"
- "\n"
- "%OptimizeFunctionOnNextCall(opt_function)\n"
- "\n"
- "test(10, 10);\n"
- "\n"
- "test(undefined, 10);\n"
- "\n"
- "%OptimizeFunctionOnNextCall(opt_function)\n"
- "\n"
- "test(10, 10);\n"
- "\n"
- "test(10, 0);\n"
- "\n"
- "stopProfiling();\n"
- "\n";
+const char* GetBranchDeoptReason(i::CpuProfile* iprofile, const char* branch[],
+ int length) {
+ v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
+ const ProfileNode* iopt_function = NULL;
+ iopt_function = GetSimpleBranch(profile, branch, length);
+ CHECK_EQ(1, iopt_function->deopt_infos().size());
+ return iopt_function->deopt_infos()[0].deopt_reason;
+}
+// deopt at top function
TEST(CollectDeoptEvents) {
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
i::FLAG_allow_natives_syntax = true;
@@ -1763,21 +1735,90 @@ TEST(CollectDeoptEvents) {
v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
- v8::Script::Compile(v8_str(collect_deopt_events_test_source))->Run();
+ const char opt_source[] =
+ "function opt_function%d(value, depth) {\n"
+ " if (depth) return opt_function%d(value, depth - 1);\n"
+ "\n"
+ " return 10 / value;\n"
+ "}\n"
+ "\n";
+
+ for (int i = 0; i < 3; ++i) {
+ i::EmbeddedVector<char, sizeof(opt_source) + 100> buffer;
+ i::SNPrintF(buffer, opt_source, i, i);
+ v8::Script::Compile(v8_str(buffer.start()))->Run();
+ }
+
+ const char* source =
+ "startProfiling();\n"
+ "\n"
+ "opt_function0(1, 1);\n"
+ "\n"
+ "%OptimizeFunctionOnNextCall(opt_function0)\n"
+ "\n"
+ "opt_function0(1, 1);\n"
+ "\n"
+ "opt_function0(undefined, 1);\n"
+ "\n"
+ "opt_function1(1, 1);\n"
+ "\n"
+ "%OptimizeFunctionOnNextCall(opt_function1)\n"
+ "\n"
+ "opt_function1(1, 1);\n"
+ "\n"
+ "opt_function1(NaN, 1);\n"
+ "\n"
+ "opt_function2(1, 1);\n"
+ "\n"
+ "%OptimizeFunctionOnNextCall(opt_function2)\n"
+ "\n"
+ "opt_function2(1, 1);\n"
+ "\n"
+ "opt_function2(0, 1);\n"
+ "\n"
+ "stopProfiling();\n"
+ "\n";
+
+ v8::Script::Compile(v8_str(source))->Run();
i::CpuProfile* iprofile = iprofiler->GetProfile(0);
iprofile->Print();
- v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
- const char* branch[] = {"", "test", "opt_function", "opt_function"};
- const v8::CpuProfileNode* opt_function = GetSimpleBranch(
- env->GetIsolate(), profile->GetTopDownRoot(), branch, arraysize(branch));
- CHECK(opt_function);
- const i::ProfileNode* iopt_function =
- reinterpret_cast<const i::ProfileNode*>(opt_function);
- CHECK_EQ(2, iopt_function->deopt_infos().length());
- CHECK_EQ(i::Deoptimizer::GetDeoptReason(i::Deoptimizer::kNotAHeapNumber),
- iopt_function->deopt_infos()[0].deopt_reason);
- CHECK_EQ(i::Deoptimizer::GetDeoptReason(i::Deoptimizer::kDivisionByZero),
- iopt_function->deopt_infos()[1].deopt_reason);
+ /* The expected profile
+ [Top down]:
+ 0 (root) 0 #1
+ 23 32 #2
+ 1 opt_function2 31 #7
+ 1 opt_function2 31 #8
+ ;;; deopted at script_id: 31 position: 106 with reason
+ 'division by zero'.
+ 2 opt_function0 29 #3
+ 4 opt_function0 29 #4
+ ;;; deopted at script_id: 29 position: 108 with reason 'not a
+ heap number'.
+ 0 opt_function1 30 #5
+ 1 opt_function1 30 #6
+ ;;; deopted at script_id: 30 position: 108 with reason 'lost
+ precision or NaN'.
+ */
+
+ {
+ const char* branch[] = {"", "opt_function0", "opt_function0"};
+ CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber),
+ GetBranchDeoptReason(iprofile, branch, arraysize(branch)));
+ }
+ {
+ const char* branch[] = {"", "opt_function1", "opt_function1"};
+ const char* deopt_reason =
+ GetBranchDeoptReason(iprofile, branch, arraysize(branch));
+ if (deopt_reason != reason(i::Deoptimizer::kNaN) &&
+ deopt_reason != reason(i::Deoptimizer::kLostPrecisionOrNaN)) {
+ FATAL(deopt_reason);
+ }
+ }
+ {
+ const char* branch[] = {"", "opt_function2", "opt_function2"};
+ CHECK_EQ(reason(i::Deoptimizer::kDivisionByZero),
+ GetBranchDeoptReason(iprofile, branch, arraysize(branch)));
+ }
iprofiler->DeleteProfile(iprofile);
}
@@ -1796,3 +1837,197 @@ TEST(SourceLocation) {
v8::Script::Compile(v8_str(source))->Run();
}
+
+
+static const char* inlined_source =
+ "function opt_function(left, right) { var k = left / 10; var r = 10 / "
+ "right; return k + r; }\n";
+// 0.........1.........2.........3.........4....*....5.........6......*..7
+
+
+// deopt at the first level inlined function
+TEST(DeoptAtFirstLevelInlinedSource) {
+ if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
+ i::FLAG_allow_natives_syntax = true;
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+ v8::Context::Scope context_scope(env);
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
+ i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
+
+ // 0.........1.........2.........3.........4.........5.........6.........7
+ const char* source =
+ "function test(left, right) { return opt_function(left, right); }\n"
+ "\n"
+ "startProfiling();\n"
+ "\n"
+ "test(10, 10);\n"
+ "\n"
+ "%OptimizeFunctionOnNextCall(test)\n"
+ "\n"
+ "test(10, 10);\n"
+ "\n"
+ "test(undefined, 10);\n"
+ "\n"
+ "stopProfiling();\n"
+ "\n";
+
+ v8::Handle<v8::Script> inlined_script = v8_compile(inlined_source);
+ inlined_script->Run();
+ int inlined_script_id = inlined_script->GetUnboundScript()->GetId();
+
+ v8::Handle<v8::Script> script = v8_compile(source);
+ script->Run();
+ int script_id = script->GetUnboundScript()->GetId();
+
+ i::CpuProfile* iprofile = iprofiler->GetProfile(0);
+ iprofile->Print();
+ /* The expected profile output
+ [Top down]:
+ 0 (root) 0 #1
+ 10 30 #2
+ 1 test 30 #3
+ ;;; deopted at script_id: 29 position: 45 with reason 'not a
+ heap number'.
+ ;;; Inline point: script_id 30 position: 36.
+ 4 opt_function 29 #4
+ */
+ v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
+
+ const char* branch[] = {"", "test"};
+ const ProfileNode* itest_node =
+ GetSimpleBranch(profile, branch, arraysize(branch));
+ const std::vector<i::DeoptInfo>& deopt_infos = itest_node->deopt_infos();
+ CHECK_EQ(1, deopt_infos.size());
+
+ const i::DeoptInfo& info = deopt_infos[0];
+ CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber), info.deopt_reason);
+ CHECK_EQ(2, info.stack.size());
+ CHECK_EQ(inlined_script_id, info.stack[0].script_id);
+ CHECK_EQ(offset(inlined_source, "left /"), info.stack[0].position);
+ CHECK_EQ(script_id, info.stack[1].script_id);
+ CHECK_EQ(offset(source, "opt_function(left,"), info.stack[1].position);
+
+ iprofiler->DeleteProfile(iprofile);
+}
+
+
+// deopt at the second level inlined function
+TEST(DeoptAtSecondLevelInlinedSource) {
+ if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
+ i::FLAG_allow_natives_syntax = true;
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+ v8::Context::Scope context_scope(env);
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
+ i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
+
+ // 0.........1.........2.........3.........4.........5.........6.........7
+ const char* source =
+ "function test2(left, right) { return opt_function(left, right); }\n"
+ "function test1(left, right) { return test2(left, right); }\n"
+ "\n"
+ "startProfiling();\n"
+ "\n"
+ "test1(10, 10);\n"
+ "\n"
+ "%OptimizeFunctionOnNextCall(test1)\n"
+ "\n"
+ "test1(10, 10);\n"
+ "\n"
+ "test1(undefined, 10);\n"
+ "\n"
+ "stopProfiling();\n"
+ "\n";
+
+ v8::Handle<v8::Script> inlined_script = v8_compile(inlined_source);
+ inlined_script->Run();
+ int inlined_script_id = inlined_script->GetUnboundScript()->GetId();
+
+ v8::Handle<v8::Script> script = v8_compile(source);
+ script->Run();
+ int script_id = script->GetUnboundScript()->GetId();
+
+ i::CpuProfile* iprofile = iprofiler->GetProfile(0);
+ iprofile->Print();
+ /* The expected profile output
+ [Top down]:
+ 0 (root) 0 #1
+ 11 30 #2
+ 1 test1 30 #3
+ ;;; deopted at script_id: 29 position: 45 with reason 'not a
+ heap number'.
+ ;;; Inline point: script_id 30 position: 37.
+ ;;; Inline point: script_id 30 position: 103.
+ 1 test2 30 #4
+ 3 opt_function 29 #5
+ */
+
+ v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
+
+ const char* branch[] = {"", "test1"};
+ const ProfileNode* itest_node =
+ GetSimpleBranch(profile, branch, arraysize(branch));
+ const std::vector<i::DeoptInfo>& deopt_infos = itest_node->deopt_infos();
+ CHECK_EQ(1, deopt_infos.size());
+
+ const i::DeoptInfo info = deopt_infos[0];
+ CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber), info.deopt_reason);
+ CHECK_EQ(3, info.stack.size());
+ CHECK_EQ(inlined_script_id, info.stack[0].script_id);
+ CHECK_EQ(offset(inlined_source, "left /"), info.stack[0].position);
+ CHECK_EQ(script_id, info.stack[1].script_id);
+ CHECK_EQ(offset(source, "opt_function(left,"), info.stack[1].position);
+ CHECK_EQ(offset(source, "test2(left, right);"), info.stack[2].position);
+
+ iprofiler->DeleteProfile(iprofile);
+}
+
+
+// deopt in untracked function
+TEST(DeoptUntrackedFunction) {
+ if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
+ i::FLAG_allow_natives_syntax = true;
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+ v8::Context::Scope context_scope(env);
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
+ i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
+
+ // 0.........1.........2.........3.........4.........5.........6.........7
+ const char* source =
+ "function test(left, right) { return opt_function(left, right); }\n"
+ "\n"
+ "test(10, 10);\n"
+ "\n"
+ "%OptimizeFunctionOnNextCall(test)\n"
+ "\n"
+ "test(10, 10);\n"
+ "\n"
+ "startProfiling();\n" // profiler started after compilation.
+ "\n"
+ "test(undefined, 10);\n"
+ "\n"
+ "stopProfiling();\n"
+ "\n";
+
+ v8::Handle<v8::Script> inlined_script = v8_compile(inlined_source);
+ inlined_script->Run();
+
+ v8::Handle<v8::Script> script = v8_compile(source);
+ script->Run();
+
+ i::CpuProfile* iprofile = iprofiler->GetProfile(0);
+ iprofile->Print();
+ v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
+
+ const char* branch[] = {"", "test"};
+ const ProfileNode* itest_node =
+ GetSimpleBranch(profile, branch, arraysize(branch));
+ CHECK_EQ(0, itest_node->deopt_infos().size());
+
+ iprofiler->DeleteProfile(iprofile);
+}
diff --git a/deps/v8/test/cctest/test-date.cc b/deps/v8/test/cctest/test-date.cc
index 2f722c2baf..2bcc625a95 100644
--- a/deps/v8/test/cctest/test-date.cc
+++ b/deps/v8/test/cctest/test-date.cc
@@ -28,7 +28,6 @@
#include "src/v8.h"
#include "src/global-handles.h"
-#include "src/snapshot.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
index a4a993ad30..5929379663 100644
--- a/deps/v8/test/cctest/test-debug.cc
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -416,7 +416,7 @@ void CheckDebuggerUnloaded(bool check_functions) {
if (RelocInfo::IsCodeTarget(rmode)) {
CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
} else if (RelocInfo::IsJSReturn(rmode)) {
- CHECK(!Debug::IsDebugBreakAtReturn(it.rinfo()));
+ CHECK(!it.rinfo()->IsPatchedReturnSequence());
}
}
}
@@ -437,47 +437,36 @@ static void CheckDebuggerUnloaded(bool check_functions = false) {
}
-// Inherit from BreakLocationIterator to get access to protected parts for
-// testing.
-class TestBreakLocationIterator: public v8::internal::BreakLocationIterator {
- public:
- explicit TestBreakLocationIterator(Handle<v8::internal::DebugInfo> debug_info)
- : BreakLocationIterator(debug_info, v8::internal::SOURCE_BREAK_LOCATIONS) {}
- v8::internal::RelocIterator* it() { return reloc_iterator_; }
- v8::internal::RelocIterator* it_original() {
- return reloc_iterator_original_;
- }
-};
-
-
// Compile a function, set a break point and check that the call at the break
// location in the code is the expected debug_break function.
void CheckDebugBreakFunction(DebugLocalContext* env,
const char* source, const char* name,
int position, v8::internal::RelocInfo::Mode mode,
Code* debug_break) {
- v8::internal::Debug* debug = CcTest::i_isolate()->debug();
+ i::Debug* debug = CcTest::i_isolate()->debug();
// Create function and set the break point.
- Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle(
- *CompileFunction(env, source, name));
+ Handle<i::JSFunction> fun =
+ v8::Utils::OpenHandle(*CompileFunction(env, source, name));
int bp = SetBreakPoint(fun, position);
// Check that the debug break function is as expected.
- Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
+ Handle<i::SharedFunctionInfo> shared(fun->shared());
CHECK(Debug::HasDebugInfo(shared));
- TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
- it1.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
- v8::internal::RelocInfo::Mode actual_mode = it1.it()->rinfo()->rmode();
- if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
- actual_mode = v8::internal::RelocInfo::CODE_TARGET;
+ i::BreakLocation location = i::BreakLocation::FromPosition(
+ Debug::GetDebugInfo(shared), i::SOURCE_BREAK_LOCATIONS, position,
+ i::STATEMENT_ALIGNED);
+ i::RelocInfo::Mode actual_mode = location.rmode();
+ if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
+ actual_mode = i::RelocInfo::CODE_TARGET;
}
CHECK_EQ(mode, actual_mode);
- if (mode != v8::internal::RelocInfo::JS_RETURN) {
- CHECK_EQ(debug_break,
- Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address()));
+ if (mode != i::RelocInfo::JS_RETURN) {
+ CHECK_EQ(debug_break, *location.CodeTarget());
} else {
- CHECK(Debug::IsDebugBreakAtReturn(it1.it()->rinfo()));
+ i::RelocInfo rinfo = location.rinfo();
+ CHECK(i::RelocInfo::IsJSReturn(rinfo.rmode()));
+ CHECK(rinfo.IsPatchedReturnSequence());
}
// Clear the break point and check that the debug break function is no longer
@@ -485,15 +474,17 @@ void CheckDebugBreakFunction(DebugLocalContext* env,
ClearBreakPoint(bp);
CHECK(!debug->HasDebugInfo(shared));
CHECK(debug->EnsureDebugInfo(shared, fun));
- TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
- it2.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
- actual_mode = it2.it()->rinfo()->rmode();
- if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
- actual_mode = v8::internal::RelocInfo::CODE_TARGET;
+ location = i::BreakLocation::FromPosition(Debug::GetDebugInfo(shared),
+ i::SOURCE_BREAK_LOCATIONS, position,
+ i::STATEMENT_ALIGNED);
+ actual_mode = location.rmode();
+ if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
+ actual_mode = i::RelocInfo::CODE_TARGET;
}
CHECK_EQ(mode, actual_mode);
- if (mode == v8::internal::RelocInfo::JS_RETURN) {
- CHECK(!Debug::IsDebugBreakAtReturn(it2.it()->rinfo()));
+ if (mode == i::RelocInfo::JS_RETURN) {
+ i::RelocInfo rinfo = location.rinfo();
+ CHECK(!rinfo.IsPatchedReturnSequence());
}
}
@@ -6706,6 +6697,7 @@ TEST(ProcessDebugMessagesThreaded) {
v8::FunctionTemplate::New(isolate, StartSendingCommands);
env->Global()->Set(v8_str("start"), start->GetFunction());
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("start(); while (true) { }");
CHECK_EQ(20, counting_message_handler_counter);
@@ -7655,7 +7647,6 @@ static void DebugHarmonyScopingListener(
TEST(DebugBreakInLexicalScopes) {
- i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true;
DebugLocalContext env;
diff --git a/deps/v8/test/cctest/test-decls.cc b/deps/v8/test/cctest/test-decls.cc
index 5d487bb7da..f3dc777102 100644
--- a/deps/v8/test/cctest/test-decls.cc
+++ b/deps/v8/test/cctest/test-decls.cc
@@ -637,7 +637,6 @@ TEST(CrossScriptReferences) {
TEST(CrossScriptReferences_Simple) {
- i::FLAG_harmony_scoping = true;
i::FLAG_use_strict = true;
v8::Isolate* isolate = CcTest::isolate();
@@ -652,7 +651,6 @@ TEST(CrossScriptReferences_Simple) {
TEST(CrossScriptReferences_Simple2) {
- i::FLAG_harmony_scoping = true;
i::FLAG_use_strict = true;
v8::Isolate* isolate = CcTest::isolate();
@@ -675,8 +673,6 @@ TEST(CrossScriptReferences_Simple2) {
TEST(CrossScriptReferencesHarmony) {
- i::FLAG_harmony_scoping = true;
-
v8::Isolate* isolate = CcTest::isolate();
HandleScope scope(isolate);
@@ -818,9 +814,27 @@ TEST(CrossScriptReferencesHarmony) {
}
+TEST(CrossScriptReferencesHarmonyRegress) {
+ v8::Isolate* isolate = CcTest::isolate();
+ HandleScope scope(isolate);
+ SimpleContext context;
+ context.Check(
+ "'use strict';"
+ "function i1() { "
+ " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
+ "}"
+ "i1();"
+ "i1();",
+ EXPECT_RESULT, Number::New(isolate, 10));
+ context.Check(
+ "'use strict';"
+ "let x2 = 2; i1();",
+ EXPECT_RESULT, Number::New(isolate, 12));
+}
+
+
TEST(GlobalLexicalOSR) {
i::FLAG_use_strict = true;
- i::FLAG_harmony_scoping = true;
v8::Isolate* isolate = CcTest::isolate();
HandleScope scope(isolate);
@@ -844,7 +858,6 @@ TEST(GlobalLexicalOSR) {
TEST(CrossScriptConflicts) {
i::FLAG_use_strict = true;
- i::FLAG_harmony_scoping = true;
HandleScope scope(CcTest::isolate());
@@ -880,8 +893,6 @@ TEST(CrossScriptConflicts) {
TEST(CrossScriptDynamicLookup) {
- i::FLAG_harmony_scoping = true;
-
HandleScope handle_scope(CcTest::isolate());
{
@@ -913,8 +924,6 @@ TEST(CrossScriptDynamicLookup) {
TEST(CrossScriptGlobal) {
- i::FLAG_harmony_scoping = true;
-
HandleScope handle_scope(CcTest::isolate());
{
SimpleContext context;
@@ -957,8 +966,6 @@ TEST(CrossScriptGlobal) {
TEST(CrossScriptStaticLookupUndeclared) {
- i::FLAG_harmony_scoping = true;
-
HandleScope handle_scope(CcTest::isolate());
{
@@ -991,7 +998,6 @@ TEST(CrossScriptStaticLookupUndeclared) {
TEST(CrossScriptLoadICs) {
- i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true;
HandleScope handle_scope(CcTest::isolate());
@@ -1047,7 +1053,6 @@ TEST(CrossScriptLoadICs) {
TEST(CrossScriptStoreICs) {
- i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true;
HandleScope handle_scope(CcTest::isolate());
@@ -1125,7 +1130,6 @@ TEST(CrossScriptStoreICs) {
TEST(CrossScriptAssignmentToConst) {
- i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true;
HandleScope handle_scope(CcTest::isolate());
@@ -1148,7 +1152,6 @@ TEST(CrossScriptAssignmentToConst) {
TEST(Regress425510) {
- i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true;
HandleScope handle_scope(CcTest::isolate());
@@ -1163,3 +1166,85 @@ TEST(Regress425510) {
}
}
}
+
+
+TEST(Regress3941) {
+ i::FLAG_allow_natives_syntax = true;
+
+ HandleScope handle_scope(CcTest::isolate());
+
+ {
+ SimpleContext context;
+ context.Check("function f() { x = 1; }", EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
+ }
+
+
+ {
+ // Train ICs.
+ SimpleContext context;
+ context.Check("function f() { x = 1; }", EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ for (int i = 0; i < 4; i++) {
+ context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
+ }
+ context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
+ }
+
+
+ {
+ // Optimize.
+ SimpleContext context;
+ context.Check("function f() { x = 1; }", EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ for (int i = 0; i < 4; i++) {
+ context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
+ }
+ context.Check("%OptimizeFunctionOnNextCall(f); f(); x", EXPECT_RESULT,
+ Number::New(CcTest::isolate(), 1));
+
+ context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
+ }
+}
+
+
+TEST(Regress3941_Reads) {
+ i::FLAG_allow_natives_syntax = true;
+
+ HandleScope handle_scope(CcTest::isolate());
+
+ {
+ SimpleContext context;
+ context.Check("function f() { return x; }", EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
+ }
+
+
+ {
+ // Train ICs.
+ SimpleContext context;
+ context.Check("function f() { return x; }", EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ for (int i = 0; i < 4; i++) {
+ context.Check("f()", EXPECT_EXCEPTION);
+ }
+ context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
+ }
+
+
+ {
+ // Optimize.
+ SimpleContext context;
+ context.Check("function f() { return x; }", EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ for (int i = 0; i < 4; i++) {
+ context.Check("f()", EXPECT_EXCEPTION);
+ }
+ context.Check("%OptimizeFunctionOnNextCall(f);", EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+
+ context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
+ }
+}
diff --git a/deps/v8/test/cctest/test-disasm-arm.cc b/deps/v8/test/cctest/test-disasm-arm.cc
index 095c63679c..502b641df6 100644
--- a/deps/v8/test/cctest/test-disasm-arm.cc
+++ b/deps/v8/test/cctest/test-disasm-arm.cc
@@ -34,7 +34,6 @@
#include "src/disasm.h"
#include "src/disassembler.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-disasm-ia32.cc b/deps/v8/test/cctest/test-disasm-ia32.cc
index a2eaa15ed3..ca4a4f2868 100644
--- a/deps/v8/test/cctest/test-disasm-ia32.cc
+++ b/deps/v8/test/cctest/test-disasm-ia32.cc
@@ -34,7 +34,6 @@
#include "src/disassembler.h"
#include "src/ic/ic.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
@@ -442,6 +441,10 @@ TEST(DisasmIa320) {
__ subsd(xmm1, Operand(ebx, ecx, times_4, 10000));
__ divsd(xmm1, xmm0);
__ divsd(xmm1, Operand(ebx, ecx, times_4, 10000));
+ __ minsd(xmm1, xmm0);
+ __ minsd(xmm1, Operand(ebx, ecx, times_4, 10000));
+ __ maxsd(xmm1, xmm0);
+ __ maxsd(xmm1, Operand(ebx, ecx, times_4, 10000));
__ ucomisd(xmm0, xmm1);
__ cmpltsd(xmm0, xmm1);
@@ -451,6 +454,11 @@ TEST(DisasmIa320) {
__ psrlq(xmm0, 17);
__ psrlq(xmm0, xmm1);
__ por(xmm0, xmm1);
+
+ __ pcmpeqd(xmm1, xmm0);
+
+ __ punpckldq(xmm1, xmm6);
+ __ punpckhdq(xmm7, xmm5);
}
// cmov.
@@ -494,6 +502,10 @@ TEST(DisasmIa320) {
__ vsubsd(xmm0, xmm1, Operand(ebx, ecx, times_4, 10000));
__ vdivsd(xmm0, xmm1, xmm2);
__ vdivsd(xmm0, xmm1, Operand(ebx, ecx, times_4, 10000));
+ __ vminsd(xmm0, xmm1, xmm2);
+ __ vminsd(xmm0, xmm1, Operand(ebx, ecx, times_4, 10000));
+ __ vmaxsd(xmm0, xmm1, xmm2);
+ __ vmaxsd(xmm0, xmm1, Operand(ebx, ecx, times_4, 10000));
}
}
diff --git a/deps/v8/test/cctest/test-disasm-mips.cc b/deps/v8/test/cctest/test-disasm-mips.cc
index 131f41384c..ca928a61eb 100644
--- a/deps/v8/test/cctest/test-disasm-mips.cc
+++ b/deps/v8/test/cctest/test-disasm-mips.cc
@@ -34,7 +34,6 @@
#include "src/disasm.h"
#include "src/disassembler.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-disasm-mips64.cc b/deps/v8/test/cctest/test-disasm-mips64.cc
index d682d33480..a2a93c611a 100644
--- a/deps/v8/test/cctest/test-disasm-mips64.cc
+++ b/deps/v8/test/cctest/test-disasm-mips64.cc
@@ -34,7 +34,6 @@
#include "src/disasm.h"
#include "src/disassembler.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-disasm-ppc.cc b/deps/v8/test/cctest/test-disasm-ppc.cc
index 87b9ade055..ed409f2f9d 100644
--- a/deps/v8/test/cctest/test-disasm-ppc.cc
+++ b/deps/v8/test/cctest/test-disasm-ppc.cc
@@ -34,7 +34,6 @@
#include "src/disasm.h"
#include "src/disassembler.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-disasm-x64.cc b/deps/v8/test/cctest/test-disasm-x64.cc
index 6cd58ec209..cdedc8be55 100644
--- a/deps/v8/test/cctest/test-disasm-x64.cc
+++ b/deps/v8/test/cctest/test-disasm-x64.cc
@@ -34,7 +34,6 @@
#include "src/disassembler.h"
#include "src/ic/ic.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
@@ -89,6 +88,9 @@ TEST(DisasmX64) {
__ addq(rdi, Operand(rbp, rcx, times_4, -3999));
__ addq(Operand(rbp, rcx, times_4, 12), Immediate(12));
+ __ bsrl(rax, r15);
+ __ bsrl(r9, Operand(rcx, times_8, 91919));
+
__ nop();
__ addq(rbx, Immediate(12));
__ nop();
@@ -436,6 +438,10 @@ TEST(DisasmX64) {
__ subsd(xmm1, Operand(rbx, rcx, times_4, 10000));
__ divsd(xmm1, xmm0);
__ divsd(xmm1, Operand(rbx, rcx, times_4, 10000));
+ __ minsd(xmm1, xmm0);
+ __ minsd(xmm1, Operand(rbx, rcx, times_4, 10000));
+ __ maxsd(xmm1, xmm0);
+ __ maxsd(xmm1, Operand(rbx, rcx, times_4, 10000));
__ ucomisd(xmm0, xmm1);
__ andpd(xmm0, xmm1);
@@ -446,6 +452,9 @@ TEST(DisasmX64) {
__ psrlq(xmm0, 6);
__ pcmpeqd(xmm1, xmm0);
+
+ __ punpckldq(xmm1, xmm11);
+ __ punpckhdq(xmm8, xmm15);
}
// cmov.
@@ -472,6 +481,10 @@ TEST(DisasmX64) {
if (CpuFeatures::IsSupported(SSE4_1)) {
CpuFeatureScope scope(&assm, SSE4_1);
__ extractps(rax, xmm1, 0);
+ __ pextrd(rbx, xmm15, 0);
+ __ pextrd(r12, xmm0, 1);
+ __ pinsrd(xmm9, r9, 0);
+ __ pinsrd(xmm5, rax, 1);
}
}
@@ -486,7 +499,11 @@ TEST(DisasmX64) {
__ vsubsd(xmm0, xmm1, xmm2);
__ vsubsd(xmm0, xmm1, Operand(rbx, rcx, times_4, 10000));
__ vdivsd(xmm0, xmm1, xmm2);
- __ vdivsd(xmm0, xmm1, Operand(rbx, rcx, times_4, 10000));
+ __ vdivsd(xmm0, xmm1, Operand(rbx, rcx, times_2, 10000));
+ __ vminsd(xmm8, xmm1, xmm2);
+ __ vminsd(xmm9, xmm1, Operand(rbx, rcx, times_8, 10000));
+ __ vmaxsd(xmm8, xmm1, xmm2);
+ __ vmaxsd(xmm9, xmm1, Operand(rbx, rcx, times_1, 10000));
}
}
diff --git a/deps/v8/test/cctest/test-disasm-x87.cc b/deps/v8/test/cctest/test-disasm-x87.cc
index e9b0dc5474..a3433b290b 100644
--- a/deps/v8/test/cctest/test-disasm-x87.cc
+++ b/deps/v8/test/cctest/test-disasm-x87.cc
@@ -34,7 +34,6 @@
#include "src/disassembler.h"
#include "src/ic/ic.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-feedback-vector.cc b/deps/v8/test/cctest/test-feedback-vector.cc
index 89c475eab5..f53dfde10e 100644
--- a/deps/v8/test/cctest/test-feedback-vector.cc
+++ b/deps/v8/test/cctest/test-feedback-vector.cc
@@ -22,10 +22,11 @@ TEST(VectorStructure) {
v8::HandleScope scope(context->GetIsolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
+ Zone* zone = isolate->runtime_zone();
// Empty vectors are the empty fixed array.
FeedbackVectorSpec empty;
- Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(empty);
+ Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&empty);
CHECK(Handle<FixedArray>::cast(vector)
.is_identical_to(factory->empty_fixed_array()));
// Which can nonetheless be queried.
@@ -34,24 +35,21 @@ TEST(VectorStructure) {
CHECK_EQ(0, vector->Slots());
CHECK_EQ(0, vector->ICSlots());
- FeedbackVectorSpec one_slot(1, 0);
- vector = factory->NewTypeFeedbackVector(one_slot);
+ FeedbackVectorSpec one_slot(1);
+ vector = factory->NewTypeFeedbackVector(&one_slot);
CHECK_EQ(1, vector->Slots());
CHECK_EQ(0, vector->ICSlots());
- FeedbackVectorSpec one_icslot(0, 1);
- if (FLAG_vector_ics) {
- one_icslot.SetKind(0, Code::CALL_IC);
- }
- vector = factory->NewTypeFeedbackVector(one_icslot);
+ FeedbackVectorSpec one_icslot(0, Code::CALL_IC);
+ vector = factory->NewTypeFeedbackVector(&one_icslot);
CHECK_EQ(0, vector->Slots());
CHECK_EQ(1, vector->ICSlots());
- FeedbackVectorSpec spec(3, 5);
+ ZoneFeedbackVectorSpec spec(zone, 3, 5);
if (FLAG_vector_ics) {
for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC);
}
- vector = factory->NewTypeFeedbackVector(spec);
+ vector = factory->NewTypeFeedbackVector(&spec);
CHECK_EQ(3, vector->Slots());
CHECK_EQ(5, vector->ICSlots());
@@ -71,8 +69,8 @@ TEST(VectorStructure) {
CHECK_EQ(index,
TypeFeedbackVector::kReservedIndexCount + metadata_length + 3);
CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index));
-
- CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 + 5,
+ CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 +
+ 5 * TypeFeedbackVector::elements_per_ic_slot(),
vector->length());
}
@@ -88,8 +86,9 @@ TEST(VectorICMetadata) {
}
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
+ Zone* zone = isolate->runtime_zone();
- FeedbackVectorSpec spec(10, 3 * 10);
+ ZoneFeedbackVectorSpec spec(zone, 10, 3 * 10);
// Set metadata.
for (int i = 0; i < 30; i++) {
Code::Kind kind;
@@ -103,7 +102,7 @@ TEST(VectorICMetadata) {
spec.SetKind(i, kind);
}
- Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(spec);
+ Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&spec);
CHECK_EQ(10, vector->Slots());
CHECK_EQ(3 * 10, vector->ICSlots());
@@ -136,8 +135,8 @@ TEST(VectorSlotClearing) {
// We only test clearing FeedbackVectorSlots, not FeedbackVectorICSlots.
// The reason is that FeedbackVectorICSlots need a full code environment
// to fully test (See VectorICProfilerStatistics test below).
- FeedbackVectorSpec spec(5, 0);
- Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(spec);
+ FeedbackVectorSpec spec(5);
+ Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&spec);
// Fill with information
vector->Set(FeedbackVectorSlot(0), Smi::FromInt(1));
@@ -307,6 +306,34 @@ TEST(VectorLoadICStates) {
}
+TEST(VectorLoadICSlotSharing) {
+ if (i::FLAG_always_opt || !i::FLAG_vector_ics) return;
+ CcTest::InitializeVM();
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+ Isolate* isolate = CcTest::i_isolate();
+
+ // Function f has 3 LoadICs, one for each o, but the ICs share the same
+ // feedback vector IC slot.
+ CompileRun(
+ "var o = 10;"
+ "function f() {"
+ " var x = o + 10;"
+ " return o + x + o;"
+ "}"
+ "f();");
+ Handle<JSFunction> f = v8::Utils::OpenHandle(
+ *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
+ // There should be one IC slot.
+ Handle<TypeFeedbackVector> feedback_vector =
+ Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
+ CHECK_EQ(1, feedback_vector->ICSlots());
+ FeedbackVectorICSlot slot(0);
+ LoadICNexus nexus(feedback_vector, slot);
+ CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
+}
+
+
TEST(VectorLoadICOnSmi) {
if (i::FLAG_always_opt || !i::FLAG_vector_ics) return;
CcTest::InitializeVM();
diff --git a/deps/v8/test/cctest/test-func-name-inference.cc b/deps/v8/test/cctest/test-func-name-inference.cc
index 24f9c73532..ae8e77d745 100644
--- a/deps/v8/test/cctest/test-func-name-inference.cc
+++ b/deps/v8/test/cctest/test-func-name-inference.cc
@@ -81,11 +81,9 @@ static void CheckFunctionName(v8::Handle<v8::Script> script,
// Obtain SharedFunctionInfo for the function.
isolate->debug()->PrepareForBreakPoints();
- Object* shared_func_info_ptr =
- isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos);
- CHECK(shared_func_info_ptr != CcTest::heap()->undefined_value());
- Handle<SharedFunctionInfo> shared_func_info(
- SharedFunctionInfo::cast(shared_func_info_ptr));
+ Handle<SharedFunctionInfo> shared_func_info =
+ Handle<SharedFunctionInfo>::cast(
+ isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos));
// Verify inferred function name.
SmartArrayPointer<char> inferred_name =
diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc
index 5c9d2e69f0..d00532f48d 100644
--- a/deps/v8/test/cctest/test-heap-profiler.cc
+++ b/deps/v8/test/cctest/test-heap-profiler.cc
@@ -36,7 +36,6 @@
#include "src/debug.h"
#include "src/hashmap.h"
#include "src/heap-profiler.h"
-#include "src/snapshot.h"
#include "src/utils-inl.h"
#include "test/cctest/cctest.h"
@@ -183,8 +182,7 @@ TEST(HeapSnapshot) {
"var a2 = new A2();\n"
"var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
"var c2 = new C2(a2);");
- const v8::HeapSnapshot* snapshot_env2 =
- heap_profiler->TakeHeapSnapshot(v8_str("env2"));
+ const v8::HeapSnapshot* snapshot_env2 = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot_env2));
const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
@@ -217,8 +215,7 @@ TEST(HeapSnapshotObjectSizes) {
"x = new X(new X(), new X());\n"
"dummy = new X();\n"
"(function() { x.a.a = x.b; })();");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("sizes"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* x =
@@ -246,8 +243,7 @@ TEST(BoundFunctionInSnapshot) {
"function myFunction(a, b) { this.a = a; this.b = b; }\n"
"function AAAAA() {}\n"
"boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("sizes"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* f =
@@ -286,8 +282,7 @@ TEST(HeapSnapshotEntryChildren) {
CompileRun(
"function A() { }\n"
"a = new A;");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("children"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) {
@@ -314,8 +309,7 @@ TEST(HeapSnapshotCodeObjects) {
"function compiled(x) { return x + 1; }\n"
"var anonymous = (function() { return function() { return 0; } })();\n"
"compiled(1)");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("code"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
@@ -387,8 +381,7 @@ TEST(HeapSnapshotHeapNumbers) {
CompileRun(
"a = 1; // a is Smi\n"
"b = 2.5; // b is HeapNumber");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("numbers"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK(!GetProperty(global, v8::HeapGraphEdge::kProperty, "a"));
@@ -413,8 +406,7 @@ TEST(HeapSnapshotSlicedString) {
"123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789.\";"
"child_string = parent_string.slice(100);");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("strings"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* parent_string =
@@ -451,8 +443,7 @@ TEST(HeapSnapshotConsString) {
global->SetInternalField(0, v8::ToApiHandle<v8::String>(cons_string));
v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("cons_strings"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
@@ -479,8 +470,7 @@ TEST(HeapSnapshotSymbol) {
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("a = Symbol('mySymbol');\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("Symbol"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* a =
@@ -504,8 +494,7 @@ TEST(HeapSnapshotWeakCollection) {
"k = {}; v = {}; s = 'str';\n"
"ws = new WeakSet(); ws.add(k); ws.add(v); ws[s] = s;\n"
"wm = new WeakMap(); wm.set(k, v); wm[s] = s;\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("WeakCollections"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* k =
@@ -578,8 +567,7 @@ TEST(HeapSnapshotCollection) {
"k = {}; v = {}; s = 'str';\n"
"set = new Set(); set.add(k); set.add(v); set[s] = s;\n"
"map = new Map(); map.set(k, v); map[s] = s;\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("Collections"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* k =
@@ -656,8 +644,7 @@ TEST(HeapSnapshotInternalReferences) {
global->SetInternalField(0, v8_num(17));
global->SetInternalField(1, obj);
v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("internals"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
// The first reference will not present, because it's a Smi.
@@ -677,8 +664,7 @@ TEST(HeapSnapshotAddressReuse) {
"var a = [];\n"
"for (var i = 0; i < 10000; ++i)\n"
" a[i] = new A();\n");
- const v8::HeapSnapshot* snapshot1 =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot1"));
+ const v8::HeapSnapshot* snapshot1 = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot1));
v8::SnapshotObjectId maxId1 = snapshot1->GetMaxSnapshotJSObjectId();
@@ -687,8 +673,7 @@ TEST(HeapSnapshotAddressReuse) {
" a[i] = new A();\n");
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- const v8::HeapSnapshot* snapshot2 =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot2"));
+ const v8::HeapSnapshot* snapshot2 = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot2));
const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
@@ -721,8 +706,7 @@ TEST(HeapEntryIdsAndArrayShift) {
"var a = new Array();\n"
"for (var i = 0; i < 10; ++i)\n"
" a.push(new AnObject());\n");
- const v8::HeapSnapshot* snapshot1 =
- heap_profiler->TakeHeapSnapshot(v8_str("s1"));
+ const v8::HeapSnapshot* snapshot1 = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot1));
CompileRun(
@@ -731,8 +715,7 @@ TEST(HeapEntryIdsAndArrayShift) {
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- const v8::HeapSnapshot* snapshot2 =
- heap_profiler->TakeHeapSnapshot(v8_str("s2"));
+ const v8::HeapSnapshot* snapshot2 = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot2));
const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
@@ -768,16 +751,12 @@ TEST(HeapEntryIdsAndGC) {
"function B(x) { this.x = x; }\n"
"var a = new A();\n"
"var b = new B(a);");
- v8::Local<v8::String> s1_str = v8_str("s1");
- v8::Local<v8::String> s2_str = v8_str("s2");
- const v8::HeapSnapshot* snapshot1 =
- heap_profiler->TakeHeapSnapshot(s1_str);
+ const v8::HeapSnapshot* snapshot1 = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot1));
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- const v8::HeapSnapshot* snapshot2 =
- heap_profiler->TakeHeapSnapshot(s2_str);
+ const v8::HeapSnapshot* snapshot2 = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot2));
CHECK_GT(snapshot1->GetMaxSnapshotJSObjectId(), 7000u);
@@ -827,8 +806,7 @@ TEST(HeapSnapshotRootPreservedAfterSorting) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("s"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* root1 = snapshot->GetRoot();
const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
@@ -896,8 +874,7 @@ TEST(HeapSnapshotJSONSerialization) {
"function B(x) { this.x = x; }\n"
"var a = new A(" STRING_LITERAL_FOR_TEST ");\n"
"var b = new B(a);");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("json"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
TestJSONStream stream;
@@ -996,8 +973,7 @@ TEST(HeapSnapshotJSONSerializationAborting) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("abort"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
TestJSONStream stream(5);
snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
@@ -1067,9 +1043,12 @@ static TestStatsStream GetHeapStatsUpdate(
v8::HeapProfiler* heap_profiler,
v8::SnapshotObjectId* object_id = NULL) {
TestStatsStream stream;
- v8::SnapshotObjectId last_seen_id = heap_profiler->GetHeapStats(&stream);
+ int64_t timestamp = -1;
+ v8::SnapshotObjectId last_seen_id =
+ heap_profiler->GetHeapStats(&stream, &timestamp);
if (object_id)
*object_id = last_seen_id;
+ CHECK_NE(-1, timestamp);
CHECK_EQ(1, stream.eos_signaled());
return stream;
}
@@ -1279,8 +1258,7 @@ TEST(HeapSnapshotGetNodeById) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("id"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* root = snapshot->GetRoot();
CheckChildrenIds(snapshot, root, 0, 3);
@@ -1294,8 +1272,7 @@ TEST(HeapSnapshotGetSnapshotObjectId) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("globalObject = {};\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("get_snapshot_object_id"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* global_object =
@@ -1318,8 +1295,7 @@ TEST(HeapSnapshotUnknownSnapshotObjectId) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("globalObject = {};\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("unknown_object_id"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* node =
snapshot->GetNodeById(v8::HeapProfiler::kUnknownObjectId);
@@ -1357,16 +1333,13 @@ TEST(TakeHeapSnapshotAborting) {
const int snapshots_count = heap_profiler->GetSnapshotCount();
TestActivityControl aborting_control(1);
const v8::HeapSnapshot* no_snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("abort"),
- &aborting_control);
+ heap_profiler->TakeHeapSnapshot(&aborting_control);
CHECK(!no_snapshot);
CHECK_EQ(snapshots_count, heap_profiler->GetSnapshotCount());
CHECK_GT(aborting_control.total(), aborting_control.done());
TestActivityControl control(-1); // Don't abort.
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("full"),
- &control);
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(&control);
CHECK(ValidateSnapshot(snapshot));
CHECK(snapshot);
@@ -1477,8 +1450,7 @@ TEST(HeapSnapshotRetainedObjectInfo) {
v8::Persistent<v8::String> p_CCC(isolate, v8_str("CCC"));
p_CCC.SetWrapperClassId(2);
CHECK_EQ(0, TestRetainedObjectInfo::instances.length());
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("retained"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
CHECK_EQ(3, TestRetainedObjectInfo::instances.length());
@@ -1570,8 +1542,7 @@ TEST(HeapSnapshotImplicitReferences) {
GraphWithImplicitRefs graph(&env);
v8::V8::AddGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue);
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("implicit_refs"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot);
@@ -1604,28 +1575,25 @@ TEST(DeleteAllHeapSnapshots) {
CHECK_EQ(0, heap_profiler->GetSnapshotCount());
heap_profiler->DeleteAllHeapSnapshots();
CHECK_EQ(0, heap_profiler->GetSnapshotCount());
- CHECK(heap_profiler->TakeHeapSnapshot(v8_str("1")));
+ CHECK(heap_profiler->TakeHeapSnapshot());
CHECK_EQ(1, heap_profiler->GetSnapshotCount());
heap_profiler->DeleteAllHeapSnapshots();
CHECK_EQ(0, heap_profiler->GetSnapshotCount());
- CHECK(heap_profiler->TakeHeapSnapshot(v8_str("1")));
- CHECK(heap_profiler->TakeHeapSnapshot(v8_str("2")));
+ CHECK(heap_profiler->TakeHeapSnapshot());
+ CHECK(heap_profiler->TakeHeapSnapshot());
CHECK_EQ(2, heap_profiler->GetSnapshotCount());
heap_profiler->DeleteAllHeapSnapshots();
CHECK_EQ(0, heap_profiler->GetSnapshotCount());
}
-static const v8::HeapSnapshot* FindHeapSnapshot(v8::HeapProfiler* profiler,
- unsigned uid) {
+static bool FindHeapSnapshot(v8::HeapProfiler* profiler,
+ const v8::HeapSnapshot* snapshot) {
int length = profiler->GetSnapshotCount();
for (int i = 0; i < length; i++) {
- const v8::HeapSnapshot* snapshot = profiler->GetHeapSnapshot(i);
- if (snapshot->GetUid() == uid) {
- return snapshot;
- }
+ if (snapshot == profiler->GetHeapSnapshot(i)) return true;
}
- return NULL;
+ return false;
}
@@ -1635,38 +1603,31 @@ TEST(DeleteHeapSnapshot) {
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CHECK_EQ(0, heap_profiler->GetSnapshotCount());
- const v8::HeapSnapshot* s1 =
- heap_profiler->TakeHeapSnapshot(v8_str("1"));
+ const v8::HeapSnapshot* s1 = heap_profiler->TakeHeapSnapshot();
CHECK(s1);
CHECK_EQ(1, heap_profiler->GetSnapshotCount());
- unsigned uid1 = s1->GetUid();
- CHECK_EQ(s1, FindHeapSnapshot(heap_profiler, uid1));
+ CHECK(FindHeapSnapshot(heap_profiler, s1));
const_cast<v8::HeapSnapshot*>(s1)->Delete();
CHECK_EQ(0, heap_profiler->GetSnapshotCount());
- CHECK(!FindHeapSnapshot(heap_profiler, uid1));
+ CHECK(!FindHeapSnapshot(heap_profiler, s1));
- const v8::HeapSnapshot* s2 =
- heap_profiler->TakeHeapSnapshot(v8_str("2"));
+ const v8::HeapSnapshot* s2 = heap_profiler->TakeHeapSnapshot();
CHECK(s2);
CHECK_EQ(1, heap_profiler->GetSnapshotCount());
- unsigned uid2 = s2->GetUid();
- CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
- CHECK_EQ(s2, FindHeapSnapshot(heap_profiler, uid2));
- const v8::HeapSnapshot* s3 =
- heap_profiler->TakeHeapSnapshot(v8_str("3"));
+ CHECK(FindHeapSnapshot(heap_profiler, s2));
+ const v8::HeapSnapshot* s3 = heap_profiler->TakeHeapSnapshot();
CHECK(s3);
CHECK_EQ(2, heap_profiler->GetSnapshotCount());
- unsigned uid3 = s3->GetUid();
- CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
- CHECK_EQ(s3, FindHeapSnapshot(heap_profiler, uid3));
+ CHECK_NE(s2, s3);
+ CHECK(FindHeapSnapshot(heap_profiler, s3));
const_cast<v8::HeapSnapshot*>(s2)->Delete();
CHECK_EQ(1, heap_profiler->GetSnapshotCount());
- CHECK(!FindHeapSnapshot(heap_profiler, uid2));
- CHECK_EQ(s3, FindHeapSnapshot(heap_profiler, uid3));
+ CHECK(!FindHeapSnapshot(heap_profiler, s2));
+ CHECK(FindHeapSnapshot(heap_profiler, s3));
const_cast<v8::HeapSnapshot*>(s3)->Delete();
CHECK_EQ(0, heap_profiler->GetSnapshotCount());
- CHECK(!FindHeapSnapshot(heap_profiler, uid3));
+ CHECK(!FindHeapSnapshot(heap_profiler, s3));
}
@@ -1687,9 +1648,7 @@ TEST(GlobalObjectName) {
NameResolver name_resolver;
const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("document"),
- NULL,
- &name_resolver);
+ heap_profiler->TakeHeapSnapshot(NULL, &name_resolver);
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK(global);
@@ -1705,8 +1664,7 @@ TEST(GlobalObjectFields) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("obj = {};");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* builtins =
@@ -1728,10 +1686,9 @@ TEST(NoHandleLeaks) {
CompileRun("document = { URL:\"abcdefgh\" };");
- v8::Handle<v8::String> name(v8_str("leakz"));
i::Isolate* isolate = CcTest::i_isolate();
int count_before = i::HandleScope::NumberOfHandles(isolate);
- heap_profiler->TakeHeapSnapshot(name);
+ heap_profiler->TakeHeapSnapshot();
int count_after = i::HandleScope::NumberOfHandles(isolate);
CHECK_EQ(count_before, count_after);
}
@@ -1741,8 +1698,7 @@ TEST(NodesIteration) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("iteration"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK(global);
@@ -1763,8 +1719,7 @@ TEST(GetHeapValueForNode) {
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("a = { s_prop: \'value\', n_prop: \'value2\' };");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("value"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK(heap_profiler->FindObjectById(global->GetId())->IsObject());
@@ -1798,8 +1753,7 @@ TEST(GetHeapValueForDeletedObject) {
// property of the "a" object. Also, the "p" object can't be an empty one
// because the empty object is static and isn't actually deleted.
CompileRun("a = { p: { r: {} } };");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* obj = GetProperty(
@@ -1889,8 +1843,7 @@ TEST(FastCaseAccessors) {
"obj1.__defineSetter__('propWithSetter', function Z(value) {\n"
" return this.value_ = value;\n"
"});\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("fastCaseAccessors"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
@@ -1935,8 +1888,7 @@ TEST(FastCaseRedefinedAccessors) {
v8::Utils::OpenHandle(*js_global->Get(v8_str("obj1")).As<v8::Object>());
USE(js_obj1);
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("fastCaseAccessors"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK(global);
@@ -1964,8 +1916,7 @@ TEST(SlowCaseAccessors) {
"obj1.__defineSetter__('propWithSetter', function Z(value) {\n"
" return this.value_ = value;\n"
"});\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("slowCaseAccessors"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
@@ -1994,8 +1945,7 @@ TEST(HiddenPropertiesFastCase) {
CompileRun(
"function C(x) { this.a = this; this.b = x; }\n"
"c = new C(2012);\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("HiddenPropertiesFastCase1"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* c =
@@ -2010,8 +1960,7 @@ TEST(HiddenPropertiesFastCase) {
CHECK(!cHandle.IsEmpty() && cHandle->IsObject());
cHandle->ToObject(isolate)->SetHiddenValue(v8_str("key"), v8_str("val"));
- snapshot = heap_profiler->TakeHeapSnapshot(
- v8_str("HiddenPropertiesFastCase2"));
+ snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
global = GetGlobalObject(snapshot);
c = GetProperty(global, v8::HeapGraphEdge::kProperty, "c");
@@ -2028,8 +1977,7 @@ TEST(AccessorInfo) {
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("function foo(x) { }\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("AccessorInfoTest"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* foo =
@@ -2074,8 +2022,7 @@ bool HasWeakEdge(const v8::HeapGraphNode* node) {
bool HasWeakGlobalHandle() {
v8::Isolate* isolate = CcTest::isolate();
v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("weaks"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* gc_roots = GetNode(
snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "(GC roots)");
@@ -2115,8 +2062,7 @@ TEST(SfiAndJsFunctionWeakRefs) {
CompileRun(
"fun = (function (x) { return function () { return x + 1; } })(1);");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("fun"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK(global);
@@ -2136,8 +2082,7 @@ TEST(NoDebugObjectInSnapshot) {
CHECK(CcTest::i_isolate()->debug()->Load());
CompileRun("foo = {};");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* root = snapshot->GetRoot();
int globals_count = 0;
@@ -2161,8 +2106,7 @@ TEST(AllStrongGcRootsHaveNames) {
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("foo = {};");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* gc_roots = GetNode(
snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "(GC roots)");
@@ -2184,8 +2128,7 @@ TEST(NoRefsToNonEssentialEntries) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("global_object = {};\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* global_object =
@@ -2205,8 +2148,7 @@ TEST(MapHasDescriptorsAndTransitions) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("obj = { a: 10 };\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* global_object =
@@ -2244,8 +2186,7 @@ TEST(ManyLocalsInSharedContext) {
"result.push('return f_' + (n - 1) + ';');"
"result.push('})()');"
"var ok = eval(result.join('\\n'));");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
@@ -2279,8 +2220,7 @@ TEST(AllocationSitesAreVisible) {
CompileRun(
"fun = function () { var a = [3, 2, 1]; return a; }\n"
"fun();");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
@@ -2292,11 +2232,11 @@ TEST(AllocationSitesAreVisible) {
GetProperty(fun_code, v8::HeapGraphEdge::kInternal, "literals");
CHECK(literals);
CHECK_EQ(v8::HeapGraphNode::kArray, literals->GetType());
- CHECK_EQ(2, literals->GetChildrenCount());
+ CHECK_EQ(1, literals->GetChildrenCount());
- // The second value in the literals array should be the boilerplate,
+ // The first value in the literals array should be the boilerplate,
// after an AllocationSite.
- const v8::HeapGraphEdge* prop = literals->GetChild(1);
+ const v8::HeapGraphEdge* prop = literals->GetChild(0);
const v8::HeapGraphNode* allocation_site = prop->GetToNode();
v8::String::Utf8Value name(allocation_site->GetName());
CHECK_EQ(0, strcmp("system / AllocationSite", *name));
@@ -2333,8 +2273,7 @@ TEST(JSFunctionHasCodeLink) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("function foo(x, y) { return x + y; }\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* foo_func =
@@ -2375,8 +2314,7 @@ TEST(CheckCodeNames) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("var a = 1.1;");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("CheckCodeNames"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const char* stub_path[] = {
@@ -2634,8 +2572,7 @@ TEST(ArrayBufferAndArrayBufferView) {
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("arr1 = new Uint32Array(100);\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* arr1_obj =
@@ -2693,8 +2630,7 @@ TEST(ArrayBufferSharedBackingStore) {
v8::Handle<v8::Value> result = CompileRun("ab2.byteLength");
CHECK_EQ(1024, result->Int32Value());
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* ab1_node =
@@ -2728,8 +2664,7 @@ TEST(BoxObject) {
global->Set(0, v8::ToApiHandle<v8::Object>(box));
v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
const v8::HeapGraphNode* box_node =
@@ -2756,8 +2691,7 @@ TEST(WeakContainers) {
"foo(obj);\n"
"%OptimizeFunctionOnNextCall(foo);\n"
"foo(obj);\n");
- const v8::HeapSnapshot* snapshot =
- heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* obj =
diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc
index ae3c1d365c..9867f933b1 100644
--- a/deps/v8/test/cctest/test-heap.cc
+++ b/deps/v8/test/cctest/test-heap.cc
@@ -36,10 +36,10 @@
#include "src/global-handles.h"
#include "src/ic/ic.h"
#include "src/macro-assembler.h"
-#include "src/snapshot.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
+using v8::Just;
static void CheckMap(Map* map, int type, int instance_size) {
CHECK(map->IsHeapObject());
@@ -191,9 +191,7 @@ TEST(HeapObjects) {
Handle<String> object_string = Handle<String>::cast(factory->Object_string());
Handle<GlobalObject> global(CcTest::i_isolate()->context()->global_object());
- v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, object_string);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(global, object_string));
// Check ToString for oddballs
CheckOddball(isolate, heap->true_value(), "true");
@@ -260,9 +258,7 @@ TEST(GarbageCollection) {
heap->CollectGarbage(NEW_SPACE);
// Function should be alive.
- v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, name);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(global, name));
// Check function is retained.
Handle<Object> func_value =
Object::GetProperty(global, name).ToHandleChecked();
@@ -280,9 +276,7 @@ TEST(GarbageCollection) {
// After gc, it should survive.
heap->CollectGarbage(NEW_SPACE);
- maybe = JSReceiver::HasOwnProperty(global, obj_name);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(global, obj_name));
Handle<Object> obj =
Object::GetProperty(global, obj_name).ToHandleChecked();
CHECK(obj->IsJSObject());
@@ -639,85 +633,55 @@ TEST(ObjectProperties) {
Handle<Smi> two(Smi::FromInt(2), isolate);
// check for empty
- v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(!maybe.value);
+ CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
// add first
JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
// delete first
JSReceiver::DeleteProperty(obj, first, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(!maybe.value);
+ CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
// add first and then second
JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
- maybe = JSReceiver::HasOwnProperty(obj, second);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second));
// delete first and then second
JSReceiver::DeleteProperty(obj, first, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, second);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second));
JSReceiver::DeleteProperty(obj, second, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(!maybe.value);
- maybe = JSReceiver::HasOwnProperty(obj, second);
- CHECK(maybe.has_value);
- CHECK(!maybe.value);
+ CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
+ CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, second));
// add first and then second
JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
- maybe = JSReceiver::HasOwnProperty(obj, second);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second));
// delete second and then first
JSReceiver::DeleteProperty(obj, second, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
JSReceiver::DeleteProperty(obj, first, SLOPPY).Check();
- maybe = JSReceiver::HasOwnProperty(obj, first);
- CHECK(maybe.has_value);
- CHECK(!maybe.value);
- maybe = JSReceiver::HasOwnProperty(obj, second);
- CHECK(maybe.has_value);
- CHECK(!maybe.value);
+ CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
+ CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, second));
// check string and internalized string match
const char* string1 = "fisk";
Handle<String> s1 = factory->NewStringFromAsciiChecked(string1);
JSReceiver::SetProperty(obj, s1, one, SLOPPY).Check();
Handle<String> s1_string = factory->InternalizeUtf8String(string1);
- maybe = JSReceiver::HasOwnProperty(obj, s1_string);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, s1_string));
// check internalized string and string match
const char* string2 = "fugl";
Handle<String> s2_string = factory->InternalizeUtf8String(string2);
JSReceiver::SetProperty(obj, s2_string, one, SLOPPY).Check();
Handle<String> s2 = factory->NewStringFromAsciiChecked(string2);
- maybe = JSReceiver::HasOwnProperty(obj, s2);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, s2));
}
@@ -1502,6 +1466,7 @@ TEST(TestInternalWeakLists) {
// Some flags turn Scavenge collections into Mark-sweep collections
// and hence are incompatible with this test case.
if (FLAG_gc_global || FLAG_stress_compaction) return;
+ FLAG_retain_maps_for_n_gc = 0;
static const int kNumTestContexts = 10;
@@ -2176,6 +2141,12 @@ TEST(InstanceOfStubWriteBarrier) {
}
+static int NumberOfProtoTransitions(Map* map) {
+ return TransitionArray::NumberOfPrototypeTransitions(
+ TransitionArray::GetPrototypeTransitions(map));
+}
+
+
TEST(PrototypeTransitionClearing) {
if (FLAG_never_compact) return;
CcTest::InitializeVM();
@@ -2188,7 +2159,7 @@ TEST(PrototypeTransitionClearing) {
v8::Utils::OpenHandle(
*v8::Handle<v8::Object>::Cast(
CcTest::global()->Get(v8_str("base"))));
- int initialTransitions = baseObject->map()->NumberOfProtoTransitions();
+ int initialTransitions = NumberOfProtoTransitions(baseObject->map());
CompileRun(
"var live = [];"
@@ -2201,16 +2172,17 @@ TEST(PrototypeTransitionClearing) {
// Verify that only dead prototype transitions are cleared.
CHECK_EQ(initialTransitions + 10,
- baseObject->map()->NumberOfProtoTransitions());
+ NumberOfProtoTransitions(baseObject->map()));
CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
const int transitions = 10 - 3;
CHECK_EQ(initialTransitions + transitions,
- baseObject->map()->NumberOfProtoTransitions());
+ NumberOfProtoTransitions(baseObject->map()));
// Verify that prototype transitions array was compacted.
- FixedArray* trans = baseObject->map()->GetPrototypeTransitions();
+ FixedArray* trans =
+ TransitionArray::GetPrototypeTransitions(baseObject->map());
for (int i = initialTransitions; i < initialTransitions + transitions; i++) {
- int j = Map::kProtoTransitionHeaderSize + i;
+ int j = TransitionArray::kProtoTransitionHeaderSize + i;
CHECK(trans->get(j)->IsMap());
}
@@ -2228,7 +2200,7 @@ TEST(PrototypeTransitionClearing) {
i::FLAG_always_compact = true;
Handle<Map> map(baseObject->map());
CHECK(!space->LastPage()->Contains(
- map->GetPrototypeTransitions()->address()));
+ TransitionArray::GetPrototypeTransitions(*map)->address()));
CHECK(space->LastPage()->Contains(prototype->address()));
}
@@ -2267,9 +2239,12 @@ TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
marking->Start();
// The following two calls will increment CcTest::heap()->global_ic_age().
- const int kLongIdlePauseInMs = 1000;
+ const double kLongIdlePauseInSeconds = 1.0;
CcTest::isolate()->ContextDisposedNotification();
- CcTest::isolate()->IdleNotification(kLongIdlePauseInMs);
+ CcTest::isolate()->IdleNotificationDeadline(
+ (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
+ static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
+ kLongIdlePauseInSeconds);
while (!marking->IsStopped() && !marking->IsComplete()) {
marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
@@ -2323,9 +2298,12 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
// The following two calls will increment CcTest::heap()->global_ic_age().
// Since incremental marking is off, IdleNotification will do full GC.
- const int kLongIdlePauseInMs = 1000;
+ const double kLongIdlePauseInSeconds = 1.0;
CcTest::isolate()->ContextDisposedNotification();
- CcTest::isolate()->IdleNotification(kLongIdlePauseInMs);
+ CcTest::isolate()->IdleNotificationDeadline(
+ (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
+ static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
+ kLongIdlePauseInSeconds);
CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
CHECK_EQ(0, f->shared()->opt_count());
@@ -2368,9 +2346,14 @@ TEST(IdleNotificationFinishMarking) {
CHECK(!marking->IsIdleMarkingDelayCounterLimitReached());
}
+ marking->SetWeakClosureWasOverApproximatedForTesting(true);
+
// The next idle notification has to finish incremental marking.
- const int kLongIdleTime = 1000000;
- CcTest::isolate()->IdleNotification(kLongIdleTime);
+ const double kLongIdleTime = 1000.0;
+ CcTest::isolate()->IdleNotificationDeadline(
+ (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
+ static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
+ kLongIdleTime);
CHECK_EQ(CcTest::heap()->gc_count(), 1);
}
@@ -2550,8 +2533,8 @@ TEST(OptimizedPretenuringMixedInObjectProperties) {
} else {
CHECK_EQ(2.2, inner_object->RawFastDoublePropertyAt(idx1));
}
- CHECK(CcTest::heap()->InOldPointerSpace(
- inner_object->RawFastPropertyAt(idx2)));
+ CHECK(
+ CcTest::heap()->InOldPointerSpace(inner_object->RawFastPropertyAt(idx2)));
}
@@ -2911,7 +2894,7 @@ TEST(OptimizedAllocationArrayLiterals) {
static int CountMapTransitions(Map* map) {
- return map->transitions()->number_of_transitions();
+ return TransitionArray::NumberOfTransitions(map->raw_transitions());
}
@@ -2921,6 +2904,7 @@ TEST(Regress1465) {
i::FLAG_stress_compaction = false;
i::FLAG_allow_natives_syntax = true;
i::FLAG_trace_incremental_marking = true;
+ i::FLAG_retain_maps_for_n_gc = 0;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
static const int transitions_count = 256;
@@ -2983,6 +2967,7 @@ static void AddPropertyTo(
Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
i::FLAG_gc_interval = gc_count;
i::FLAG_gc_global = true;
+ i::FLAG_retain_maps_for_n_gc = 0;
CcTest::heap()->set_allocation_timeout(gc_count);
JSReceiver::SetProperty(object, prop_name, twenty_three, SLOPPY).Check();
}
@@ -3090,7 +3075,7 @@ TEST(TransitionArraySimpleToFull) {
CompileRun("o = new F;"
"root = new F");
root = GetByName("root");
- DCHECK(root->map()->transitions()->IsSimpleTransition());
+ DCHECK(TransitionArray::IsSimpleTransition(root->map()->raw_transitions()));
AddPropertyTo(2, root, "happy");
// Count number of live transitions after marking. Note that one transition
@@ -4090,7 +4075,8 @@ TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) {
if (marking->IsStopped()) marking->Start();
// This big step should be sufficient to mark the whole array.
marking->Step(100 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
- DCHECK(marking->IsComplete());
+ DCHECK(marking->IsComplete() ||
+ marking->IsReadyToOverApproximateWeakClosure());
}
@@ -4181,7 +4167,7 @@ TEST(EnsureAllocationSiteDependentCodesProcessed) {
// Now make sure that a gc should get rid of the function, even though we
// still have the allocation site alive.
for (int i = 0; i < 4; i++) {
- heap->CollectAllGarbage(Heap::kNoGCFlags);
+ heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
}
// The site still exists because of our global handle, but the code is no
@@ -4283,6 +4269,7 @@ TEST(NoWeakHashTableLeakWithIncrementalMarking) {
i::FLAG_weak_embedded_objects_in_optimized_code = true;
i::FLAG_allow_natives_syntax = true;
i::FLAG_compilation_cache = false;
+ i::FLAG_retain_maps_for_n_gc = 0;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
v8::internal::Heap* heap = CcTest::heap();
@@ -4608,17 +4595,33 @@ Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) {
}
-void CheckIC(Code* code, Code::Kind kind, InlineCacheState state) {
- Code* ic = FindFirstIC(code, kind);
- CHECK(ic->is_inline_cache_stub());
- CHECK(ic->ic_state() == state);
+void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared,
+ int ic_slot, InlineCacheState state) {
+ if (FLAG_vector_ics &&
+ (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
+ kind == Code::CALL_IC)) {
+ TypeFeedbackVector* vector = shared->feedback_vector();
+ FeedbackVectorICSlot slot(ic_slot);
+ if (kind == Code::LOAD_IC) {
+ LoadICNexus nexus(vector, slot);
+ CHECK_EQ(nexus.StateFromFeedback(), state);
+ } else if (kind == Code::KEYED_LOAD_IC) {
+ KeyedLoadICNexus nexus(vector, slot);
+ CHECK_EQ(nexus.StateFromFeedback(), state);
+ } else if (kind == Code::CALL_IC) {
+ CallICNexus nexus(vector, slot);
+ CHECK_EQ(nexus.StateFromFeedback(), state);
+ }
+ } else {
+ Code* ic = FindFirstIC(code, kind);
+ CHECK(ic->is_inline_cache_stub());
+ CHECK(ic->ic_state() == state);
+ }
}
TEST(MonomorphicStaysMonomorphicAfterGC) {
if (FLAG_always_opt) return;
- // TODO(mvstanton): vector ics need weak support!
- if (FLAG_vector_ics) return;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
@@ -4641,19 +4644,17 @@ TEST(MonomorphicStaysMonomorphicAfterGC) {
CompileRun("(testIC())");
}
heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CheckIC(loadIC->code(), Code::LOAD_IC, MONOMORPHIC);
+ CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
{
v8::HandleScope scope(CcTest::isolate());
CompileRun("(testIC())");
}
- CheckIC(loadIC->code(), Code::LOAD_IC, MONOMORPHIC);
+ CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
}
TEST(PolymorphicStaysPolymorphicAfterGC) {
if (FLAG_always_opt) return;
- // TODO(mvstanton): vector ics need weak support!
- if (FLAG_vector_ics) return;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
@@ -4679,12 +4680,12 @@ TEST(PolymorphicStaysPolymorphicAfterGC) {
CompileRun("(testIC())");
}
heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CheckIC(loadIC->code(), Code::LOAD_IC, POLYMORPHIC);
+ CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
{
v8::HandleScope scope(CcTest::isolate());
CompileRun("(testIC())");
}
- CheckIC(loadIC->code(), Code::LOAD_IC, POLYMORPHIC);
+ CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
}
@@ -4878,7 +4879,7 @@ TEST(ArrayShiftSweeping) {
UNINITIALIZED_TEST(PromotionQueue) {
i::FLAG_expose_gc = true;
- i::FLAG_max_semi_space_size = 2;
+ i::FLAG_max_semi_space_size = 2 * (Page::kPageSize / MB);
v8::Isolate* isolate = v8::Isolate::New();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
{
@@ -5073,16 +5074,109 @@ TEST(Regress442710) {
TEST(NumberStringCacheSize) {
- if (!Snapshot::HaveASnapshotToStartFrom()) return;
// Test that the number-string cache has not been resized in the snapshot.
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
+ if (!isolate->snapshot_available()) return;
Heap* heap = isolate->heap();
CHECK_EQ(TestHeap::kInitialNumberStringCacheSize * 2,
heap->number_string_cache()->length());
}
+TEST(Regress3877) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ Heap* heap = isolate->heap();
+ Factory* factory = isolate->factory();
+ HandleScope scope(isolate);
+ CompileRun("function cls() { this.x = 10; }");
+ Handle<WeakCell> weak_prototype;
+ {
+ HandleScope inner_scope(isolate);
+ v8::Local<v8::Value> result = CompileRun("cls.prototype");
+ Handle<JSObject> proto =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(result));
+ weak_prototype = inner_scope.CloseAndEscape(factory->NewWeakCell(proto));
+ }
+ CHECK(!weak_prototype->cleared());
+ CompileRun(
+ "var a = { };"
+ "a.x = new cls();"
+ "cls.prototype = null;");
+ for (int i = 0; i < 4; i++) {
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
+ }
+ // The map of a.x keeps prototype alive
+ CHECK(!weak_prototype->cleared());
+ // Change the map of a.x and make the previous map garbage collectable.
+ CompileRun("a.x.__proto__ = {};");
+ for (int i = 0; i < 4; i++) {
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
+ }
+ CHECK(weak_prototype->cleared());
+}
+
+
+Handle<WeakCell> AddRetainedMap(Isolate* isolate, Heap* heap) {
+ HandleScope inner_scope(isolate);
+ Handle<Map> map = Map::Create(isolate, 1);
+ v8::Local<v8::Value> result =
+ CompileRun("(function () { return {x : 10}; })();");
+ Handle<JSObject> proto =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(result));
+ map->set_prototype(*proto);
+ heap->AddRetainedMap(map);
+ return inner_scope.CloseAndEscape(Map::WeakCellForMap(map));
+}
+
+
+void CheckMapRetainingFor(int n) {
+ FLAG_retain_maps_for_n_gc = n;
+ Isolate* isolate = CcTest::i_isolate();
+ Heap* heap = isolate->heap();
+ Handle<WeakCell> weak_cell = AddRetainedMap(isolate, heap);
+ CHECK(!weak_cell->cleared());
+ for (int i = 0; i < n; i++) {
+ heap->CollectGarbage(OLD_POINTER_SPACE);
+ }
+ CHECK(!weak_cell->cleared());
+ heap->CollectGarbage(OLD_POINTER_SPACE);
+ CHECK(weak_cell->cleared());
+}
+
+
+TEST(MapRetaining) {
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ CheckMapRetainingFor(FLAG_retain_maps_for_n_gc);
+ CheckMapRetainingFor(0);
+ CheckMapRetainingFor(1);
+ CheckMapRetainingFor(7);
+}
+
+
+TEST(RegressArrayListGC) {
+ FLAG_retain_maps_for_n_gc = 1;
+ FLAG_incremental_marking = 0;
+ FLAG_gc_global = true;
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ Isolate* isolate = CcTest::i_isolate();
+ Heap* heap = isolate->heap();
+ AddRetainedMap(isolate, heap);
+ Handle<Map> map = Map::Create(isolate, 1);
+ heap->CollectGarbage(OLD_POINTER_SPACE);
+ // Force GC in old space on next addition of retained map.
+ Map::WeakCellForMap(map);
+ SimulateFullSpace(CcTest::heap()->new_space());
+ for (int i = 0; i < 10; i++) {
+ heap->AddRetainedMap(map);
+ }
+ heap->CollectGarbage(OLD_POINTER_SPACE);
+}
+
+
#ifdef DEBUG
TEST(PathTracer) {
CcTest::InitializeVM();
@@ -5095,23 +5189,63 @@ TEST(PathTracer) {
#endif // DEBUG
-TEST(FirstPageFitsStartup) {
- // Test that the first page sizes provided by the default snapshot are large
- // enough to fit everything right after startup and creating one context.
- // If this test fails, we are allocating too much aside from deserialization.
- if (!Snapshot::HaveASnapshotToStartFrom()) return;
- if (Snapshot::EmbedsScript()) return;
- CcTest::InitializeVM();
- LocalContext env;
- PagedSpaces spaces(CcTest::heap());
- for (PagedSpace* s = spaces.next(); s != NULL; s = spaces.next()) {
- uint32_t default_size = s->AreaSize();
- uint32_t reduced_size = Snapshot::SizeOfFirstPage(s->identity());
- if (reduced_size == default_size) continue;
- int counter = 0;
- Page* page = NULL;
- for (PageIterator it(s); it.has_next(); page = it.next()) counter++;
- CHECK_LE(counter, 1);
- CHECK(static_cast<uint32_t>(page->area_size()) == reduced_size);
+TEST(WritableVsImmortalRoots) {
+ for (int i = 0; i < Heap::kStrongRootListLength; ++i) {
+ Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
+ bool writable = Heap::RootCanBeWrittenAfterInitialization(root_index);
+ bool immortal = Heap::RootIsImmortalImmovable(root_index);
+ // A root value can be writable, immortal, or neither, but not both.
+ CHECK(!immortal || !writable);
}
}
+
+
+static void TestRightTrimFixedTypedArray(v8::ExternalArrayType type,
+ int initial_length,
+ int elements_to_trim) {
+ v8::HandleScope scope(CcTest::isolate());
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+
+ Handle<FixedTypedArrayBase> array =
+ factory->NewFixedTypedArray(initial_length, type);
+ int old_size = array->size();
+ heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, elements_to_trim);
+
+ // Check that free space filler is at the right place and did not smash the
+ // array header.
+ CHECK(array->IsFixedArrayBase());
+ CHECK_EQ(initial_length - elements_to_trim, array->length());
+ int new_size = array->size();
+ if (new_size != old_size) {
+ // Free space filler should be created in this case.
+ Address next_obj_address = array->address() + array->size();
+ CHECK(HeapObject::FromAddress(next_obj_address)->IsFiller());
+ }
+ heap->CollectAllAvailableGarbage();
+}
+
+
+TEST(Regress472513) {
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+
+ // The combination of type/initial_length/elements_to_trim triggered
+ // typed array header smashing with free space filler (crbug/472513).
+
+ // 64-bit cases.
+ TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 32, 6);
+ TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 32 - 7, 6);
+ TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 16, 6);
+ TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 16 - 3, 6);
+ TestRightTrimFixedTypedArray(v8::kExternalUint32Array, 8, 6);
+ TestRightTrimFixedTypedArray(v8::kExternalUint32Array, 8 - 1, 6);
+
+ // 32-bit cases.
+ TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 16, 3);
+ TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 16 - 3, 3);
+ TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 8, 3);
+ TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 8 - 1, 3);
+ TestRightTrimFixedTypedArray(v8::kExternalUint32Array, 4, 3);
+}
diff --git a/deps/v8/test/cctest/test-javascript-arm64.cc b/deps/v8/test/cctest/test-javascript-arm64.cc
index 5e4503478d..cbbbf3c22a 100644
--- a/deps/v8/test/cctest/test-javascript-arm64.cc
+++ b/deps/v8/test/cctest/test-javascript-arm64.cc
@@ -35,7 +35,6 @@
#include "src/execution.h"
#include "src/isolate.h"
#include "src/parser.h"
-#include "src/snapshot.h"
#include "src/unicode-inl.h"
#include "src/utils.h"
#include "test/cctest/cctest.h"
diff --git a/deps/v8/test/cctest/test-js-arm64-variables.cc b/deps/v8/test/cctest/test-js-arm64-variables.cc
index 7f2771094c..98d3365b87 100644
--- a/deps/v8/test/cctest/test-js-arm64-variables.cc
+++ b/deps/v8/test/cctest/test-js-arm64-variables.cc
@@ -37,7 +37,6 @@
#include "src/execution.h"
#include "src/isolate.h"
#include "src/parser.h"
-#include "src/snapshot.h"
#include "src/unicode-inl.h"
#include "src/utils.h"
#include "test/cctest/cctest.h"
diff --git a/deps/v8/test/cctest/test-lockers.cc b/deps/v8/test/cctest/test-lockers.cc
index c909a02125..b571564601 100644
--- a/deps/v8/test/cctest/test-lockers.cc
+++ b/deps/v8/test/cctest/test-lockers.cc
@@ -36,7 +36,6 @@
#include "src/isolate.h"
#include "src/parser.h"
#include "src/smart-pointers.h"
-#include "src/snapshot.h"
#include "src/unicode-inl.h"
#include "src/utils.h"
#include "test/cctest/cctest.h"
diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc
index 4b676d2e05..2386cec55b 100644
--- a/deps/v8/test/cctest/test-log.cc
+++ b/deps/v8/test/cctest/test-log.cc
@@ -39,7 +39,7 @@
#include "src/cpu-profiler.h"
#include "src/log.h"
#include "src/log-utils.h"
-#include "src/natives.h"
+#include "src/snapshot/natives.h"
#include "src/utils.h"
#include "src/v8threads.h"
#include "src/version.h"
diff --git a/deps/v8/test/cctest/test-macro-assembler-ia32.cc b/deps/v8/test/cctest/test-macro-assembler-ia32.cc
index b2b8c946c3..3834b18798 100644
--- a/deps/v8/test/cctest/test-macro-assembler-ia32.cc
+++ b/deps/v8/test/cctest/test-macro-assembler-ia32.cc
@@ -33,7 +33,6 @@
#include "src/base/platform/platform.h"
#include "src/factory.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-macro-assembler-x64.cc b/deps/v8/test/cctest/test-macro-assembler-x64.cc
index 7f20a8dd4b..4ff8cba68b 100644
--- a/deps/v8/test/cctest/test-macro-assembler-x64.cc
+++ b/deps/v8/test/cctest/test-macro-assembler-x64.cc
@@ -32,7 +32,6 @@
#include "src/base/platform/platform.h"
#include "src/factory.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
#include "test/cctest/cctest.h"
namespace i = v8::internal;
@@ -98,21 +97,13 @@ typedef int (*F0)();
static void EntryCode(MacroAssembler* masm) {
// Smi constant register is callee save.
- __ pushq(i::kSmiConstantRegister);
__ pushq(i::kRootRegister);
- __ InitializeSmiConstantRegister();
__ InitializeRootRegister();
}
static void ExitCode(MacroAssembler* masm) {
- // Return -1 if kSmiConstantRegister was clobbered during the test.
- __ Move(rdx, Smi::FromInt(1));
- __ cmpq(rdx, i::kSmiConstantRegister);
- __ movq(rdx, Immediate(-1));
- __ cmovq(not_equal, rax, rdx);
__ popq(i::kRootRegister);
- __ popq(i::kSmiConstantRegister);
}
@@ -556,32 +547,6 @@ TEST(SmiCheck) {
cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi.
__ j(cond, &exit);
- // CheckIsMinSmi
-
- __ incq(rax);
- __ movq(rcx, Immediate(Smi::kMaxValue));
- __ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckIsMinSmi(rcx);
- __ j(cond, &exit);
-
- __ incq(rax);
- __ movq(rcx, Immediate(0));
- __ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckIsMinSmi(rcx);
- __ j(cond, &exit);
-
- __ incq(rax);
- __ movq(rcx, Immediate(Smi::kMinValue));
- __ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckIsMinSmi(rcx);
- __ j(NegateCondition(cond), &exit);
-
- __ incq(rax);
- __ movq(rcx, Immediate(Smi::kMinValue + 1));
- __ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckIsMinSmi(rcx);
- __ j(cond, &exit);
-
// CheckBothSmi
__ incq(rax);
diff --git a/deps/v8/test/cctest/test-macro-assembler-x87.cc b/deps/v8/test/cctest/test-macro-assembler-x87.cc
index 0b057d818f..3cee27add0 100644
--- a/deps/v8/test/cctest/test-macro-assembler-x87.cc
+++ b/deps/v8/test/cctest/test-macro-assembler-x87.cc
@@ -33,7 +33,6 @@
#include "src/base/platform/platform.h"
#include "src/factory.h"
#include "src/macro-assembler.h"
-#include "src/serialize.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-mark-compact.cc b/deps/v8/test/cctest/test-mark-compact.cc
index 64d995d95a..cfc971770d 100644
--- a/deps/v8/test/cctest/test-mark-compact.cc
+++ b/deps/v8/test/cctest/test-mark-compact.cc
@@ -41,10 +41,10 @@
#include "src/full-codegen.h"
#include "src/global-handles.h"
-#include "src/snapshot.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
+using v8::Just;
TEST(MarkingDeque) {
@@ -127,6 +127,7 @@ TEST(NoPromotion) {
TEST(MarkCompactCollector) {
FLAG_incremental_marking = false;
+ FLAG_retain_maps_for_n_gc = 0;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
TestHeap* heap = CcTest::test_heap();
@@ -167,9 +168,7 @@ TEST(MarkCompactCollector) {
{ HandleScope scope(isolate);
Handle<String> func_name = factory->InternalizeUtf8String("theFunction");
- v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, func_name);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(global, func_name));
Handle<Object> func_value =
Object::GetProperty(global, func_name).ToHandleChecked();
CHECK(func_value->IsJSFunction());
@@ -187,9 +186,7 @@ TEST(MarkCompactCollector) {
{ HandleScope scope(isolate);
Handle<String> obj_name = factory->InternalizeUtf8String("theObject");
- v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, obj_name);
- CHECK(maybe.has_value);
- CHECK(maybe.value);
+ CHECK(Just(true) == JSReceiver::HasOwnProperty(global, obj_name));
Handle<Object> object =
Object::GetProperty(global, obj_name).ToHandleChecked();
CHECK(object->IsJSObject());
diff --git a/deps/v8/test/cctest/test-mementos.cc b/deps/v8/test/cctest/test-mementos.cc
index 4c85151b88..391c934475 100644
--- a/deps/v8/test/cctest/test-mementos.cc
+++ b/deps/v8/test/cctest/test-mementos.cc
@@ -58,9 +58,26 @@ TEST(Regress340063) {
if (!i::FLAG_allocation_site_pretenuring) return;
v8::HandleScope scope(CcTest::isolate());
+ SetUpNewSpaceWithPoisonedMementoAtTop();
+
+ // Call GC to see if we can handle a poisonous memento right after the
+ // current new space top pointer.
+ CcTest::i_isolate()->heap()->CollectAllGarbage(
+ Heap::kAbortIncrementalMarkingMask);
+}
+
+
+TEST(Regress470390) {
+ CcTest::InitializeVM();
+ if (!i::FLAG_allocation_site_pretenuring) return;
+ v8::HandleScope scope(CcTest::isolate());
SetUpNewSpaceWithPoisonedMementoAtTop();
+ // Set the new space limit to be equal to the top.
+ Address top = CcTest::i_isolate()->heap()->new_space()->top();
+ *(CcTest::i_isolate()->heap()->new_space()->allocation_limit_address()) = top;
+
// Call GC to see if we can handle a poisonous memento right after the
// current new space top pointer.
CcTest::i_isolate()->heap()->CollectAllGarbage(
diff --git a/deps/v8/test/cctest/test-migrations.cc b/deps/v8/test/cctest/test-migrations.cc
index 2f7ff8703c..3be173453a 100644
--- a/deps/v8/test/cctest/test-migrations.cc
+++ b/deps/v8/test/cctest/test-migrations.cc
@@ -145,6 +145,7 @@ class Expectations {
os << ": " << representations_[i].Mnemonic();
os << ", attrs: " << attributes_[i] << ")\n";
}
+ os << "\n";
}
Handle<HeapType> GetFieldType(int index) {
@@ -232,12 +233,14 @@ class Expectations {
representations_[descriptor])) {
return false;
}
- Object* expected_value = *values_[descriptor];
Object* value = descriptors->GetValue(descriptor);
+ Object* expected_value = *values_[descriptor];
switch (type) {
case DATA:
- case ACCESSOR:
- return HeapType::cast(expected_value)->Equals(HeapType::cast(value));
+ case ACCESSOR: {
+ HeapType* type = descriptors->GetFieldType(descriptor);
+ return HeapType::cast(expected_value)->Equals(type);
+ }
case DATA_CONSTANT:
return value == expected_value;
@@ -263,6 +266,9 @@ class Expectations {
for (int i = 0; i < expected_nof; i++) {
if (!Check(descriptors, i)) {
Print();
+#ifdef OBJECT_PRINT
+ descriptors->Print();
+#endif
Check(descriptors, i);
return false;
}
@@ -336,9 +342,10 @@ class Expectations {
SetDataField(property_index, attributes, representation, heap_type);
Handle<String> name = MakeName("prop", property_index);
- int t = map->SearchTransition(kData, *name, attributes);
- CHECK_NE(TransitionArray::kNotFound, t);
- return handle(map->GetTransition(t));
+ Map* target =
+ TransitionArray::SearchTransition(*map, kData, *name, attributes);
+ CHECK(target != NULL);
+ return handle(target);
}
Handle<Map> AddAccessorConstant(Handle<Map> map,
@@ -517,21 +524,51 @@ TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
// A set of tests for representation generalization case.
//
-static void TestGeneralizeRepresentation(Representation from_representation,
- Handle<HeapType> from_type,
- Representation to_representation,
- Handle<HeapType> to_type,
- Representation expected_representation,
- Handle<HeapType> expected_type) {
+// This test ensures that representation/field type generalization at
+// |property_index| is done correctly independently of the fact that the |map|
+// is detached from transition tree or not.
+//
+// {} - p0 - p1 - p2: |detach_point_map|
+// |
+// X - detached at |detach_property_at_index|
+// |
+// + - p3 - p4: |map|
+//
+// Detaching does not happen if |detach_property_at_index| is -1.
+//
+static void TestGeneralizeRepresentation(
+ int detach_property_at_index, int property_index,
+ Representation from_representation, Handle<HeapType> from_type,
+ Representation to_representation, Handle<HeapType> to_type,
+ Representation expected_representation, Handle<HeapType> expected_type,
+ bool expected_deprecation, bool expected_field_type_dependency) {
Isolate* isolate = CcTest::i_isolate();
+ Handle<HeapType> any_type = HeapType::Any(isolate);
+
+ CHECK(detach_property_at_index >= -1 &&
+ detach_property_at_index < kPropCount);
+ CHECK(property_index < kPropCount);
+ CHECK_NE(detach_property_at_index, property_index);
+
+ const bool is_detached_map = detach_property_at_index >= 0;
Expectations expectations(isolate);
// Create a map, add required properties to it and initialize expectations.
Handle<Map> initial_map = Map::Create(isolate, 0);
Handle<Map> map = initial_map;
+ Handle<Map> detach_point_map;
for (int i = 0; i < kPropCount; i++) {
- map = expectations.AddDataField(map, NONE, from_representation, from_type);
+ if (i == property_index) {
+ map =
+ expectations.AddDataField(map, NONE, from_representation, from_type);
+ } else {
+ map =
+ expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
+ if (i == detach_property_at_index) {
+ detach_point_map = map;
+ }
+ }
}
CHECK(!map->is_deprecated());
CHECK(map->is_stable());
@@ -540,97 +577,121 @@ static void TestGeneralizeRepresentation(Representation from_representation,
Zone zone;
FakeStubForTesting stub(isolate);
+ if (is_detached_map) {
+ detach_point_map = Map::ReconfigureProperty(
+ detach_point_map, detach_property_at_index, kData, NONE,
+ Representation::Tagged(), any_type, FORCE_FIELD);
+ expectations.SetDataField(detach_property_at_index,
+ Representation::Tagged(), any_type);
+ CHECK(map->is_deprecated());
+ CHECK(expectations.Check(*detach_point_map,
+ detach_point_map->NumberOfOwnDescriptors()));
+ }
+
// Create new maps by generalizing representation of propX field.
- Handle<Map> maps[kPropCount];
- for (int i = 0; i < kPropCount; i++) {
- Handle<Map> field_owner(map->FindFieldOwner(i), isolate);
- CompilationInfo info(&stub, isolate, &zone);
- CHECK(!info.HasAbortedDueToDependencyChange());
+ Handle<Map> field_owner(map->FindFieldOwner(property_index), isolate);
+ CompilationInfo info(&stub, isolate, &zone);
+ CHECK(!info.HasAbortedDueToDependencyChange());
+
+ Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
+ &info);
- Map::AddDependentCompilationInfo(field_owner,
- DependentCode::kFieldTypeGroup, &info);
+ Handle<Map> new_map =
+ Map::ReconfigureProperty(map, property_index, kData, NONE,
+ to_representation, to_type, FORCE_FIELD);
- Handle<Map> new_map = Map::ReconfigureProperty(
- map, i, kData, NONE, to_representation, to_type, FORCE_FIELD);
- maps[i] = new_map;
+ expectations.SetDataField(property_index, expected_representation,
+ expected_type);
- expectations.SetDataField(i, expected_representation, expected_type);
+ CHECK(!new_map->is_deprecated());
+ CHECK(expectations.Check(*new_map));
+ if (is_detached_map) {
CHECK(map->is_deprecated());
- CHECK(!info.HasAbortedDueToDependencyChange());
- info.RollbackDependencies(); // Properly cleanup compilation info.
+ CHECK_NE(*map, *new_map);
+ CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(),
+ info.HasAbortedDueToDependencyChange());
+ } else if (expected_deprecation) {
+ CHECK(map->is_deprecated());
+ CHECK(field_owner->is_deprecated());
CHECK_NE(*map, *new_map);
- CHECK(i == 0 || maps[i - 1]->is_deprecated());
+ CHECK(!info.HasAbortedDueToDependencyChange());
- CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
- CHECK(expectations.Check(*new_map));
+ } else {
+ CHECK(!field_owner->is_deprecated());
+ CHECK_EQ(*map, *new_map);
+
+ CHECK_EQ(expected_field_type_dependency,
+ info.HasAbortedDueToDependencyChange());
}
- Handle<Map> active_map = maps[kPropCount - 1];
- CHECK(!active_map->is_deprecated());
+ info.RollbackDependencies(); // Properly cleanup compilation info.
// Update all deprecated maps and check that they are now the same.
Handle<Map> updated_map = Map::Update(map);
- CHECK_EQ(*active_map, *updated_map);
- for (int i = 0; i < kPropCount; i++) {
- updated_map = Map::Update(maps[i]);
- CHECK_EQ(*active_map, *updated_map);
- }
+ CHECK_EQ(*new_map, *updated_map);
}
-static void TestGeneralizeRepresentationTrivial(
+static void TestGeneralizeRepresentation(
Representation from_representation, Handle<HeapType> from_type,
Representation to_representation, Handle<HeapType> to_type,
Representation expected_representation, Handle<HeapType> expected_type,
- bool expected_field_type_dependency = true) {
- Isolate* isolate = CcTest::i_isolate();
-
- Expectations expectations(isolate);
-
- // Create a map, add required properties to it and initialize expectations.
- Handle<Map> initial_map = Map::Create(isolate, 0);
- Handle<Map> map = initial_map;
- for (int i = 0; i < kPropCount; i++) {
- map = expectations.AddDataField(map, NONE, from_representation, from_type);
+ bool expected_deprecation, bool expected_field_type_dependency) {
+ // Check the cases when the map being reconfigured is a part of the
+ // transition tree.
+ STATIC_ASSERT(kPropCount > 4);
+ int indices[] = {0, 2, kPropCount - 1};
+ for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
+ TestGeneralizeRepresentation(
+ -1, indices[i], from_representation, from_type, to_representation,
+ to_type, expected_representation, expected_type, expected_deprecation,
+ expected_field_type_dependency);
+ }
+
+ if (!from_representation.IsNone()) {
+ // Check the cases when the map being reconfigured is NOT a part of the
+ // transition tree. "None -> anything" representation changes make sense
+ // only for "attached" maps.
+ int indices[] = {0, kPropCount - 1};
+ for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
+ TestGeneralizeRepresentation(
+ indices[i], 2, from_representation, from_type, to_representation,
+ to_type, expected_representation, expected_type, expected_deprecation,
+ expected_field_type_dependency);
+ }
}
- CHECK(!map->is_deprecated());
- CHECK(map->is_stable());
- CHECK(expectations.Check(*map));
-
- Zone zone;
- FakeStubForTesting stub(isolate);
-
- // Create new maps by generalizing representation of propX field.
- for (int i = 0; i < kPropCount; i++) {
- Handle<Map> field_owner(map->FindFieldOwner(i), isolate);
- CompilationInfo info(&stub, isolate, &zone);
- CHECK(!info.HasAbortedDueToDependencyChange());
-
- Map::AddDependentCompilationInfo(field_owner,
- DependentCode::kFieldTypeGroup, &info);
+}
- Handle<Map> new_map = Map::ReconfigureProperty(
- map, i, kData, NONE, to_representation, to_type, FORCE_FIELD);
- expectations.SetDataField(i, expected_representation, expected_type);
+static void TestGeneralizeRepresentation(Representation from_representation,
+ Handle<HeapType> from_type,
+ Representation to_representation,
+ Handle<HeapType> to_type,
+ Representation expected_representation,
+ Handle<HeapType> expected_type) {
+ const bool expected_deprecation = true;
+ const bool expected_field_type_dependency = false;
- CHECK_EQ(*map, *new_map);
- CHECK_EQ(expected_field_type_dependency,
- info.HasAbortedDueToDependencyChange());
+ TestGeneralizeRepresentation(
+ from_representation, from_type, to_representation, to_type,
+ expected_representation, expected_type, expected_deprecation,
+ expected_field_type_dependency);
+}
- info.RollbackDependencies(); // Properly cleanup compilation info.
- CHECK_EQ(*map, *new_map);
- CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
- CHECK(expectations.Check(*new_map));
- }
+static void TestGeneralizeRepresentationTrivial(
+ Representation from_representation, Handle<HeapType> from_type,
+ Representation to_representation, Handle<HeapType> to_type,
+ Representation expected_representation, Handle<HeapType> expected_type,
+ bool expected_field_type_dependency = true) {
+ const bool expected_deprecation = false;
- Handle<Map> updated_map = Map::Update(map);
- CHECK_EQ(*map, *updated_map);
+ TestGeneralizeRepresentation(
+ from_representation, from_type, to_representation, to_type,
+ expected_representation, expected_type, expected_deprecation,
+ expected_field_type_dependency);
}
@@ -828,7 +889,6 @@ TEST(GeneralizeRepresentationWithAccessorProperties) {
CHECK(i == 0 || maps[i - 1]->is_deprecated());
CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
CHECK(expectations.Check(*new_map));
}
@@ -925,7 +985,6 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
CHECK_NE(*map, *new_map);
CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
CHECK(expectations.Check(*new_map));
// Update deprecated |map|, it should become |new_map|.
@@ -1016,7 +1075,6 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
info.RollbackDependencies(); // Properly cleanup compilation info.
CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
CHECK(expectations.Check(*new_map));
Handle<Map> updated_map = Map::Update(map);
@@ -1121,7 +1179,6 @@ struct CheckDeprecated {
CHECK_NE(*map, *new_map);
CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
CHECK(expectations.Check(*new_map));
// Update deprecated |map|, it should become |new_map|.
@@ -1140,7 +1197,6 @@ struct CheckSameMap {
CHECK_EQ(*map, *new_map);
CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
CHECK(expectations.Check(*new_map));
// Update deprecated |map|, it should become |new_map|.
@@ -1163,7 +1219,6 @@ struct CheckCopyGeneralizeAllRepresentations {
}
CHECK(!new_map->is_deprecated());
- CHECK(!new_map->is_dictionary_map());
CHECK(expectations.Check(*new_map));
}
};
@@ -1423,9 +1478,10 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
}
Handle<String> name = MakeName("prop", i);
- int t = map2->SearchTransition(kData, *name, NONE);
- CHECK_NE(TransitionArray::kNotFound, t);
- map2 = handle(map2->GetTransition(t));
+ Map* target =
+ TransitionArray::SearchTransition(*map2, kData, *name, NONE);
+ CHECK(target != NULL);
+ map2 = handle(target);
}
map2 = Map::ReconfigureProperty(map2, kSplitProp, kData, NONE,
@@ -1445,12 +1501,12 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
// Fill in transition tree of |map2| so that it can't have more transitions.
for (int i = 0; i < TransitionArray::kMaxNumberOfTransitions; i++) {
- CHECK(map2->CanHaveMoreTransitions());
+ CHECK(TransitionArray::CanHaveMoreTransitions(map2));
Handle<String> name = MakeName("foo", i);
Map::CopyWithField(map2, name, any_type, NONE, Representation::Smi(),
INSERT_TRANSITION).ToHandleChecked();
}
- CHECK(!map2->CanHaveMoreTransitions());
+ CHECK(!TransitionArray::CanHaveMoreTransitions(map2));
// Try to update |map|, since there is no place for propX transition at |map2|
// |map| should become "copy-generalized".
diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc
index 1a17475ada..5b19746f93 100644
--- a/deps/v8/test/cctest/test-parsing.cc
+++ b/deps/v8/test/cctest/test-parsing.cc
@@ -72,7 +72,6 @@ TEST(ScanKeywords) {
i::Utf8ToUtf16CharacterStream stream(keyword, length);
i::Scanner scanner(&unicode_cache);
// The scanner should parse Harmony keywords for this test.
- scanner.SetHarmonyScoping(true);
scanner.SetHarmonyModules(true);
scanner.SetHarmonyClasses(true);
scanner.Initialize(&stream);
@@ -1045,15 +1044,14 @@ TEST(ScopeUsesArgumentsSuperThis) {
factory->NewStringFromUtf8(i::CStrVector(program.start()))
.ToHandleChecked();
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(), isolate->unicode_cache());
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
parser.set_allow_harmony_arrow_functions(true);
parser.set_allow_harmony_classes(true);
parser.set_allow_harmony_object_literals(true);
- parser.set_allow_harmony_scoping(true);
parser.set_allow_harmony_sloppy(true);
- info.MarkAsGlobal();
+ info.set_global();
CHECK(parser.Parse(&info));
CHECK(i::Rewriter::Rewrite(&info));
CHECK(i::Scope::Analyze(&info));
@@ -1086,8 +1084,6 @@ TEST(ScopeUsesArgumentsSuperThis) {
TEST(ScopePositions) {
- v8::internal::FLAG_harmony_scoping = true;
-
// Test the parser for correctly setting the start and end positions
// of a scope. We check the scope positions of exactly one scope
// nested in the global scope of a program. 'inner source' is the
@@ -1297,14 +1293,13 @@ TEST(ScopePositions) {
i::CStrVector(program.start())).ToHandleChecked();
CHECK_EQ(source->length(), kProgramSize);
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(), isolate->unicode_cache());
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
parser.set_allow_lazy(true);
- parser.set_allow_harmony_scoping(true);
parser.set_allow_harmony_arrow_functions(true);
- info.MarkAsGlobal();
- info.SetLanguageMode(source_data[i].language_mode);
+ info.set_global();
+ info.set_language_mode(source_data[i].language_mode);
parser.Parse(&info);
CHECK(info.function() != NULL);
@@ -1377,14 +1372,12 @@ i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
enum ParserFlag {
kAllowLazy,
kAllowNatives,
- kAllowHarmonyScoping,
kAllowHarmonyModules,
kAllowHarmonyNumericLiterals,
kAllowHarmonyArrowFunctions,
kAllowHarmonyClasses,
kAllowHarmonyObjectLiterals,
kAllowHarmonyRestParameters,
- kAllowHarmonyTemplates,
kAllowHarmonySloppy,
kAllowHarmonyUnicode,
kAllowHarmonyComputedPropertyNames,
@@ -1403,7 +1396,6 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
i::EnumSet<ParserFlag> flags) {
parser->set_allow_lazy(flags.Contains(kAllowLazy));
parser->set_allow_natives(flags.Contains(kAllowNatives));
- parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));
parser->set_allow_harmony_modules(flags.Contains(kAllowHarmonyModules));
parser->set_allow_harmony_numeric_literals(
flags.Contains(kAllowHarmonyNumericLiterals));
@@ -1412,7 +1404,6 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
parser->set_allow_harmony_arrow_functions(
flags.Contains(kAllowHarmonyArrowFunctions));
parser->set_allow_harmony_classes(flags.Contains(kAllowHarmonyClasses));
- parser->set_allow_harmony_templates(flags.Contains(kAllowHarmonyTemplates));
parser->set_allow_harmony_rest_params(
flags.Contains(kAllowHarmonyRestParameters));
parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy));
@@ -1456,11 +1447,11 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
i::FunctionLiteral* function;
{
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(), isolate->unicode_cache());
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
SetParserFlags(&parser, flags);
- info.MarkAsGlobal();
+ info.set_global();
parser.Parse(&info);
function = info.function();
if (function) {
@@ -1973,8 +1964,8 @@ TEST(NoErrorsFutureStrictReservedWords) {
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
- static const ParserFlag classes_flags[] = {
- kAllowHarmonyArrowFunctions, kAllowHarmonyClasses, kAllowHarmonyScoping};
+ static const ParserFlag classes_flags[] = {kAllowHarmonyArrowFunctions,
+ kAllowHarmonyClasses};
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
classes_flags, arraysize(classes_flags));
}
@@ -2544,10 +2535,13 @@ TEST(DontRegressPreParserDataSizes) {
i::Handle<i::String> source =
factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
i::ScriptData* sd = NULL;
- info.SetCachedData(&sd, v8::ScriptCompiler::kProduceParserCache);
- i::Parser::ParseStatic(&info, true);
+ info.set_cached_data(&sd);
+ info.set_compile_options(v8::ScriptCompiler::kProduceParserCache);
+ info.set_allow_lazy_parsing();
+ i::Parser::ParseStatic(&info);
i::ParseData* pd = i::ParseData::FromCachedData(sd);
if (pd->FunctionCount() != test_cases[i].functions) {
@@ -2961,6 +2955,36 @@ TEST(StrictDelete) {
}
+TEST(NoErrorsDeclsInCase) {
+ const char* context_data[][2] = {
+ {"'use strict'; switch(x) { case 1:", "}"},
+ {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
+ {"'use strict'; switch(x) { case 1: case 2:", "}"},
+ {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
+ {"'use strict'; switch(x) { default:", "}"},
+ {"function foo() {'use strict'; switch(x) { default:", "}}"},
+ {"'use strict'; switch(x) { case 1: default:", "}"},
+ {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
+ { nullptr, nullptr }
+ };
+
+ const char* statement_data[] = {
+ "function f() { }",
+ "class C { }",
+ "class C extends Q {}",
+ "function f() { } class C {}",
+ "function f() { }; class C {}",
+ "class C {}; function f() {}",
+ nullptr
+ };
+
+ static const ParserFlag always_flags[] = {kAllowHarmonyClasses};
+
+ RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
+ always_flags, arraysize(always_flags));
+}
+
+
TEST(InvalidLeftHandSide) {
const char* assignment_context_data[][2] = {
{"", " = 1;"},
@@ -3246,70 +3270,6 @@ TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
}
-TEST(ExportsMaybeAssigned) {
- i::FLAG_use_strict = true;
- i::FLAG_harmony_scoping = true;
- i::FLAG_harmony_modules = true;
-
- i::Isolate* isolate = CcTest::i_isolate();
- i::Factory* factory = isolate->factory();
- i::HandleScope scope(isolate);
- LocalContext env;
-
- const char* src =
- "module A {"
- " export var x = 1;"
- " export function f() { return x };"
- " export const y = 2;"
- " module B {}"
- " export module C {}"
- "};"
- "A.f";
-
- i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
- i::SNPrintF(program, "%s", src);
- i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
- source->PrintOn(stdout);
- printf("\n");
- i::Zone zone;
- v8::Local<v8::Value> v = CompileRun(src);
- i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
- i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
- i::Context* context = f->context();
- i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
- avf.Internalize(isolate);
-
- i::Scope* script_scope =
- new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
- script_scope->Initialize();
- i::Scope* s =
- i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
- DCHECK(s != script_scope);
- const i::AstRawString* name_x = avf.GetOneByteString("x");
- const i::AstRawString* name_f = avf.GetOneByteString("f");
- const i::AstRawString* name_y = avf.GetOneByteString("y");
- const i::AstRawString* name_B = avf.GetOneByteString("B");
- const i::AstRawString* name_C = avf.GetOneByteString("C");
-
- // Get result from h's function context (that is f's context)
- i::Variable* var_x = s->Lookup(name_x);
- CHECK(var_x != NULL);
- CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
- i::Variable* var_f = s->Lookup(name_f);
- CHECK(var_f != NULL);
- CHECK(var_f->maybe_assigned() == i::kMaybeAssigned);
- i::Variable* var_y = s->Lookup(name_y);
- CHECK(var_y != NULL);
- CHECK(var_y->maybe_assigned() == i::kNotAssigned);
- i::Variable* var_B = s->Lookup(name_B);
- CHECK(var_B != NULL);
- CHECK(var_B->maybe_assigned() == i::kNotAssigned);
- i::Variable* var_C = s->Lookup(name_C);
- CHECK(var_C != NULL);
- CHECK(var_C->maybe_assigned() == i::kNotAssigned);
-}
-
-
TEST(InnerAssignment) {
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
@@ -3431,11 +3391,9 @@ TEST(InnerAssignment) {
printf("\n");
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(),
- isolate->unicode_cache());
- parser.set_allow_harmony_scoping(true);
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
CHECK(parser.Parse(&info));
CHECK(i::Compiler::Analyze(&info));
CHECK(info.function() != NULL);
@@ -3583,7 +3541,7 @@ TEST(ErrorsArrowFunctions) {
};
// The test is quite slow, so run it with a reduced set of flags.
- static const ParserFlag flags[] = {kAllowLazy, kAllowHarmonyScoping};
+ static const ParserFlag flags[] = {kAllowLazy};
static const ParserFlag always_flags[] = { kAllowHarmonyArrowFunctions };
RunParserSyncTest(context_data, statement_data, kError, flags,
arraysize(flags), always_flags, arraysize(always_flags));
@@ -4111,8 +4069,7 @@ TEST(ClassDeclarationNoErrors) {
"class name extends class base {} {}",
NULL};
- static const ParserFlag always_flags[] = {
- kAllowHarmonyClasses, kAllowHarmonyScoping};
+ static const ParserFlag always_flags[] = {kAllowHarmonyClasses};
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
}
@@ -4631,9 +4588,7 @@ TEST(ConstParsingInForIn) {
"for(const x in [1,2,3]) {}",
"for(const x of [1,2,3]) {}",
NULL};
- static const ParserFlag always_flags[] = {kAllowHarmonyScoping};
- RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
- arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
}
@@ -4653,9 +4608,7 @@ TEST(ConstParsingInForInError) {
"for(const x = 1, y = 2 of []) {}",
"for(const x,y of []) {}",
NULL};
- static const ParserFlag always_flags[] = {kAllowHarmonyScoping};
- RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
- arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
}
@@ -4749,9 +4702,7 @@ TEST(ScanTemplateLiterals) {
"`foo${\r a}`",
"`foo${'a' in a}`",
NULL};
- static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
- RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
- arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
}
@@ -4786,9 +4737,7 @@ TEST(ScanTaggedTemplateLiterals) {
"tag`foo${\r a}`",
"tag`foo${'a' in a}`",
NULL};
- static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
- RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
- arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
}
@@ -4815,9 +4764,7 @@ TEST(TemplateMaterializedLiterals) {
NULL
};
- static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
- RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
- arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
}
@@ -4851,9 +4798,7 @@ TEST(ScanUnterminatedTemplateLiterals) {
"`foo${fn(}`",
"`foo${1 if}`",
NULL};
- static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
- RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
- arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
}
@@ -4873,9 +4818,7 @@ TEST(TemplateLiteralsIllegalTokens) {
"`hello${1}\\x\n${2}`",
NULL};
- static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
- RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
- arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
}
@@ -5010,8 +4953,7 @@ TEST(LexicalScopingSloppyMode) {
"(class C {})",
"(class C extends D {})",
NULL};
- static const ParserFlag always_true_flags[] = {
- kAllowHarmonyScoping, kAllowHarmonyClasses};
+ static const ParserFlag always_true_flags[] = {kAllowHarmonyClasses};
static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy};
RunParserSyncTest(context_data, bad_data, kError, NULL, 0,
always_true_flags, arraysize(always_true_flags),
@@ -5108,6 +5050,7 @@ TEST(BasicImportExportParsing) {
"export { yield } from 'm.js'",
"export { static } from 'm.js'",
"export { let } from 'm.js'",
+ "var a; export { a as b, a as c };",
"import 'somemodule.js';",
"import { } from 'm.js';",
@@ -5135,23 +5078,18 @@ TEST(BasicImportExportParsing) {
128 * 1024);
for (unsigned i = 0; i < arraysize(kSources); ++i) {
- int kProgramByteSize = i::StrLength(kSources[i]);
- i::ScopedVector<char> program(kProgramByteSize + 1);
- i::SNPrintF(program, "%s", kSources[i]);
i::Handle<i::String> source =
- factory->NewStringFromUtf8(i::CStrVector(program.start()))
- .ToHandleChecked();
+ factory->NewStringFromAsciiChecked(kSources[i]);
// Show that parsing as a module works
{
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(), isolate->unicode_cache());
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
parser.set_allow_harmony_classes(true);
parser.set_allow_harmony_modules(true);
- parser.set_allow_harmony_scoping(true);
- info.MarkAsModule();
+ info.set_module();
if (!parser.Parse(&info)) {
i::Handle<i::JSObject> exception_handle(
i::JSObject::cast(isolate->pending_exception()));
@@ -5173,13 +5111,12 @@ TEST(BasicImportExportParsing) {
// And that parsing a script does not.
{
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(), isolate->unicode_cache());
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
parser.set_allow_harmony_classes(true);
parser.set_allow_harmony_modules(true);
- parser.set_allow_harmony_scoping(true);
- info.MarkAsGlobal();
+ info.set_global();
CHECK(!parser.Parse(&info));
}
}
@@ -5211,6 +5148,10 @@ TEST(ImportExportParsingErrors) {
"export { arguments }",
"export { arguments as foo }",
"var a; export { a, a };",
+ "var a, b; export { a as b, b };",
+ "var a, b; export { a as c, b as c };",
+ "export default function f(){}; export default class C {};",
+ "export default function f(){}; var a; export { a as default };",
"import from;",
"import from 'm.js';",
@@ -5256,26 +5197,81 @@ TEST(ImportExportParsingErrors) {
128 * 1024);
for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
- int kProgramByteSize = i::StrLength(kErrorSources[i]);
- i::ScopedVector<char> program(kProgramByteSize + 1);
- i::SNPrintF(program, "%s", kErrorSources[i]);
i::Handle<i::String> source =
- factory->NewStringFromUtf8(i::CStrVector(program.start()))
- .ToHandleChecked();
+ factory->NewStringFromAsciiChecked(kErrorSources[i]);
i::Handle<i::Script> script = factory->NewScript(source);
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(), isolate->unicode_cache());
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
parser.set_allow_harmony_classes(true);
parser.set_allow_harmony_modules(true);
- parser.set_allow_harmony_scoping(true);
- info.MarkAsModule();
+ info.set_module();
CHECK(!parser.Parse(&info));
}
}
+TEST(ModuleParsingInternals) {
+ i::FLAG_harmony_modules = true;
+
+ i::Isolate* isolate = CcTest::i_isolate();
+ i::Factory* factory = isolate->factory();
+ v8::HandleScope handles(CcTest::isolate());
+ v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
+ v8::Context::Scope context_scope(context);
+ isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
+ 128 * 1024);
+
+ static const char kSource[] =
+ "let x = 5;"
+ "export { x as y };"
+ "import { q as z } from 'm.js';"
+ "import n from 'n.js'";
+ i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
+ i::Handle<i::Script> script = factory->NewScript(source);
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
+ i::Parser parser(&info);
+ parser.set_allow_harmony_modules(true);
+ info.set_module();
+ CHECK(parser.Parse(&info));
+ CHECK(i::Compiler::Analyze(&info));
+
+ i::FunctionLiteral* func = info.function();
+ i::Scope* module_scope = func->scope();
+ i::Scope* outer_scope = module_scope->outer_scope();
+ CHECK(outer_scope->is_script_scope());
+ CHECK_NULL(outer_scope->outer_scope());
+ CHECK_EQ(1, outer_scope->num_modules());
+ CHECK(module_scope->is_module_scope());
+ CHECK_NOT_NULL(module_scope->module_var());
+ CHECK_EQ(i::INTERNAL, module_scope->module_var()->mode());
+
+ i::ModuleDescriptor* descriptor = module_scope->module();
+ CHECK_NOT_NULL(descriptor);
+ CHECK_EQ(1, descriptor->Length());
+ const i::AstRawString* export_name = avf.GetOneByteString("y");
+ const i::AstRawString* local_name =
+ descriptor->LookupLocalExport(export_name, &zone);
+ CHECK_NOT_NULL(local_name);
+ CHECK(local_name->IsOneByteEqualTo("x"));
+ i::ZoneList<i::Declaration*>* declarations = module_scope->declarations();
+ CHECK_EQ(3, declarations->length());
+ CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
+ i::ImportDeclaration* import_decl =
+ declarations->at(1)->AsImportDeclaration();
+ CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
+ CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
+ CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
+ import_decl = declarations->at(2)->AsImportDeclaration();
+ CHECK(import_decl->import_name()->IsOneByteEqualTo("default"));
+ CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n"));
+ CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js"));
+}
+
+
TEST(DuplicateProtoError) {
const char* context_data[][2] = {
{"({", "});"},
@@ -5339,8 +5335,8 @@ TEST(DeclarationsError) {
"class C {}",
NULL};
- static const ParserFlag always_flags[] = {
- kAllowHarmonyClasses, kAllowHarmonyScoping, kAllowStrongMode};
+ static const ParserFlag always_flags[] = {kAllowHarmonyClasses,
+ kAllowStrongMode};
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
}
@@ -5358,11 +5354,11 @@ void TestLanguageMode(const char* source,
i::Handle<i::Script> script =
factory->NewScript(factory->NewStringFromAsciiChecked(source));
- i::CompilationInfoWithZone info(script);
- i::Parser parser(&info, isolate->stack_guard()->real_climit(),
- isolate->heap()->HashSeed(), isolate->unicode_cache());
+ i::Zone zone;
+ i::ParseInfo info(&zone, script);
+ i::Parser parser(&info);
parser.set_allow_strong_mode(true);
- info.MarkAsGlobal();
+ info.set_global();
parser.Parse(&info);
CHECK(info.function() != NULL);
CHECK_EQ(expected_language_mode, info.function()->language_mode());
@@ -5425,8 +5421,7 @@ TEST(PropertyNameEvalArguments) {
NULL};
static const ParserFlag always_flags[] = {
- kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, kAllowHarmonyScoping,
- kAllowStrongMode};
+ kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, kAllowStrongMode};
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
}
@@ -5498,8 +5493,7 @@ TEST(VarForbiddenInStrongMode) {
"const x = 0;",
NULL};
- static const ParserFlag always_flags[] = {kAllowStrongMode,
- kAllowHarmonyScoping};
+ static const ParserFlag always_flags[] = {kAllowStrongMode};
RunParserSyncTest(strong_context_data, var_declarations, kError, NULL, 0,
always_flags, arraysize(always_flags));
RunParserSyncTest(strong_context_data, let_declarations, kSuccess, NULL, 0,
@@ -5539,7 +5533,7 @@ TEST(StrongEmptySubStatements) {
NULL};
static const ParserFlag always_flags[] = {
- kAllowStrongMode, kAllowHarmonyScoping
+ kAllowStrongMode,
};
RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags));
@@ -5561,7 +5555,7 @@ TEST(StrongForIn) {
NULL};
static const ParserFlag always_flags[] = {
- kAllowStrongMode, kAllowHarmonyScoping
+ kAllowStrongMode,
};
RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags));
@@ -5570,3 +5564,227 @@ TEST(StrongForIn) {
RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
}
+
+
+TEST(StrongSuperCalls) {
+ const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
+ const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
+ const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
+
+ const char* data[] = {
+ "class C extends Object { constructor() {} }",
+ "class C extends Object { constructor() { (super()); } }",
+ "class C extends Object { constructor() { (() => super())(); } }",
+ "class C extends Object { constructor() { { super(); } } }",
+ "class C extends Object { constructor() { if (1) super(); } }",
+ "class C extends Object { constructor() { super(), super(); } }",
+ "class C extends Object { constructor() { super(); super(); } }",
+ "class C extends Object { constructor() { super(); (super()); } }",
+ "class C extends Object { constructor() { super(); { super() } } }",
+ NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals,
+ kAllowHarmonyArrowFunctions
+ };
+ RunParserSyncTest(sloppy_context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
+TEST(StrongConstructorReturns) {
+ const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
+ const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
+ const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
+
+ const char* data[] = {
+ "class C extends Object { constructor() { super(); return {}; } }",
+ "class C extends Object { constructor() { super(); { return {}; } } }",
+ "class C extends Object { constructor() { super(); if (1) return {}; } }",
+ "class C extends Object { constructor() { return; super(); } }",
+ "class C extends Object { constructor() { { return; } super(); } }",
+ "class C extends Object { constructor() { if (0) return; super(); } }",
+ NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals
+ };
+ RunParserSyncTest(sloppy_context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
+TEST(ArrowFunctionASIErrors) {
+ const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
+ {NULL, NULL}};
+
+ const char* data[] = {
+ "(a\n=> a)(1)",
+ "(a/*\n*/=> a)(1)",
+ "((a)\n=> a)(1)",
+ "((a)/*\n*/=> a)(1)",
+ "((a, b)\n=> a + b)(1, 2)",
+ "((a, b)/*\n*/=> a + b)(1, 2)",
+ NULL};
+ static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions};
+ RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
+TEST(StrongModeFreeVariablesDeclaredByPreviousScript) {
+ i::FLAG_strong_mode = true;
+ v8::V8::Initialize();
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
+ v8::TryCatch try_catch;
+
+ // Introduce a bunch of variables, in all language modes.
+ const char* script1 =
+ "var my_var1 = 0; \n"
+ "function my_func1() { } \n"
+ "const my_const1 = 0; \n";
+ CompileRun(v8_str(script1));
+ CHECK(!try_catch.HasCaught());
+
+ const char* script2 =
+ "\"use strict\"; \n"
+ "let my_var2 = 0; \n"
+ "function my_func2() { } \n"
+ "const my_const2 = 0 \n";
+ CompileRun(v8_str(script2));
+ CHECK(!try_catch.HasCaught());
+
+ const char* script3 =
+ "\"use strong\"; \n"
+ "let my_var3 = 0; \n"
+ "function my_func3() { } \n"
+ "const my_const3 = 0; \n";
+ CompileRun(v8_str(script3));
+ CHECK(!try_catch.HasCaught());
+
+ // Sloppy eval introduces variables in the surrounding scope.
+ const char* script4 =
+ "eval('var my_var4 = 0;') \n"
+ "eval('function my_func4() { }') \n"
+ "eval('const my_const4 = 0;') \n";
+ CompileRun(v8_str(script4));
+ CHECK(!try_catch.HasCaught());
+
+ // Test that referencing these variables work.
+ const char* script5 =
+ "\"use strong\"; \n"
+ "my_var1; \n"
+ "my_func1; \n"
+ "my_const1; \n"
+ "my_var2; \n"
+ "my_func2; \n"
+ "my_const2; \n"
+ "my_var3; \n"
+ "my_func3; \n"
+ "my_const3; \n"
+ "my_var4; \n"
+ "my_func4; \n"
+ "my_const4; \n";
+ CompileRun(v8_str(script5));
+ CHECK(!try_catch.HasCaught());
+}
+
+
+TEST(StrongModeFreeVariablesDeclaredByLanguage) {
+ i::FLAG_strong_mode = true;
+ v8::V8::Initialize();
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
+ v8::TryCatch try_catch;
+
+ const char* script1 =
+ "\"use strong\"; \n"
+ "Math; \n"
+ "RegExp; \n";
+ CompileRun(v8_str(script1));
+ CHECK(!try_catch.HasCaught());
+}
+
+
+TEST(StrongModeFreeVariablesDeclaredInGlobalPrototype) {
+ i::FLAG_strong_mode = true;
+ v8::V8::Initialize();
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
+ v8::TryCatch try_catch;
+
+ const char* script1 = "this.__proto__.my_var = 0;\n";
+ CompileRun(v8_str(script1));
+ CHECK(!try_catch.HasCaught());
+
+ const char* script2 =
+ "\"use strong\"; \n"
+ "my_var; \n";
+ CompileRun(v8_str(script2));
+ CHECK(!try_catch.HasCaught());
+}
+
+
+TEST(StrongModeFreeVariablesNotDeclared) {
+ i::FLAG_strong_mode = true;
+ v8::V8::Initialize();
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
+ v8::TryCatch try_catch;
+
+ // Test that referencing unintroduced variables in sloppy mode is ok.
+ const char* script1 =
+ "if (false) { \n"
+ " not_there1; \n"
+ "} \n";
+ CompileRun(v8_str(script1));
+ CHECK(!try_catch.HasCaught());
+
+ // But not in strong mode.
+ {
+ const char* script2 =
+ "\"use strong\"; \n"
+ "if (false) { \n"
+ " not_there2; \n"
+ "} \n";
+ v8::TryCatch try_catch2;
+ v8::Script::Compile(v8_str(script2));
+ CHECK(try_catch2.HasCaught());
+ v8::String::Utf8Value exception(try_catch2.Exception());
+ CHECK_EQ(0,
+ strcmp(
+ "ReferenceError: In strong mode, using an undeclared global "
+ "variable 'not_there2' is not allowed",
+ *exception));
+ }
+
+ // Check that the variable reference is detected inside a strong function too,
+ // even if the script scope is not strong.
+ {
+ const char* script3 =
+ "(function not_lazy() { \n"
+ " \"use strong\"; \n"
+ " if (false) { \n"
+ " not_there3; \n"
+ " } \n"
+ "})(); \n";
+ v8::TryCatch try_catch2;
+ v8::Script::Compile(v8_str(script3));
+ CHECK(try_catch2.HasCaught());
+ v8::String::Utf8Value exception(try_catch2.Exception());
+ CHECK_EQ(0,
+ strcmp(
+ "ReferenceError: In strong mode, using an undeclared global "
+ "variable 'not_there3' is not allowed",
+ *exception));
+ }
+}
diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc
index 55eac60f37..80aa77bacf 100644
--- a/deps/v8/test/cctest/test-serialize.cc
+++ b/deps/v8/test/cctest/test-serialize.cc
@@ -35,83 +35,41 @@
#include "src/compilation-cache.h"
#include "src/debug.h"
#include "src/heap/spaces.h"
-#include "src/natives.h"
#include "src/objects.h"
+#include "src/parser.h"
#include "src/runtime/runtime.h"
#include "src/scopeinfo.h"
-#include "src/serialize.h"
-#include "src/snapshot.h"
+#include "src/snapshot/natives.h"
+#include "src/snapshot/serialize.h"
+#include "src/snapshot/snapshot.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
-template <class T>
-static Address AddressOf(T id) {
- return ExternalReference(id, CcTest::i_isolate()).address();
+bool DefaultSnapshotAvailable() {
+ return i::Snapshot::DefaultSnapshotBlob() != NULL;
}
-template <class T>
-static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
- return encoder.Encode(AddressOf(id));
+void DisableTurbofan() {
+ const char* flag = "--turbo-filter=\"\"";
+ FlagList::SetFlagsFromString(flag, StrLength(flag));
}
-static uint32_t make_code(TypeCode type, int id) {
- return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
-}
-
-
-TEST(ExternalReferenceEncoder) {
- Isolate* isolate = CcTest::i_isolate();
- v8::V8::Initialize();
-
- ExternalReferenceEncoder encoder(isolate);
- CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
- Encode(encoder, Builtins::kArrayCode));
- CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
- Encode(encoder, Runtime::kAbort));
- ExternalReference stack_limit_address =
- ExternalReference::address_of_stack_limit(isolate);
- CHECK_EQ(make_code(UNCLASSIFIED, 2),
- encoder.Encode(stack_limit_address.address()));
- ExternalReference real_stack_limit_address =
- ExternalReference::address_of_real_stack_limit(isolate);
- CHECK_EQ(make_code(UNCLASSIFIED, 3),
- encoder.Encode(real_stack_limit_address.address()));
- CHECK_EQ(make_code(UNCLASSIFIED, 8),
- encoder.Encode(ExternalReference::debug_break(isolate).address()));
- CHECK_EQ(
- make_code(UNCLASSIFIED, 4),
- encoder.Encode(ExternalReference::new_space_start(isolate).address()));
- CHECK_EQ(
- make_code(UNCLASSIFIED, 1),
- encoder.Encode(ExternalReference::roots_array_start(isolate).address()));
- CHECK_EQ(make_code(UNCLASSIFIED, 33),
- encoder.Encode(ExternalReference::cpu_features().address()));
-}
-
-
-TEST(ExternalReferenceDecoder) {
- Isolate* isolate = CcTest::i_isolate();
- v8::V8::Initialize();
-
- ExternalReferenceDecoder decoder(isolate);
- CHECK_EQ(AddressOf(Builtins::kArrayCode),
- decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
- CHECK_EQ(AddressOf(Runtime::kAbort),
- decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
- Runtime::kAbort)));
- CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(),
- decoder.Decode(make_code(UNCLASSIFIED, 2)));
- CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(),
- decoder.Decode(make_code(UNCLASSIFIED, 3)));
- CHECK_EQ(ExternalReference::debug_break(isolate).address(),
- decoder.Decode(make_code(UNCLASSIFIED, 8)));
- CHECK_EQ(ExternalReference::new_space_start(isolate).address(),
- decoder.Decode(make_code(UNCLASSIFIED, 4)));
-}
+// TestIsolate is used for testing isolate serialization.
+class TestIsolate : public Isolate {
+ public:
+ static v8::Isolate* NewInitialized(bool enable_serializer) {
+ i::Isolate* isolate = new TestIsolate(enable_serializer);
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
+ v8::Isolate::Scope isolate_scope(v8_isolate);
+ isolate->Init(NULL);
+ return v8_isolate;
+ }
+ explicit TestIsolate(bool enable_serializer) : Isolate(enable_serializer) {}
+};
void WritePayload(const Vector<const byte>& payload, const char* file_name) {
@@ -175,24 +133,20 @@ Vector<const uint8_t> ConstructSource(Vector<const uint8_t> head,
// Test that the whole heap can be serialized.
UNINITIALIZED_TEST(Serialize) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate::CreateParams params;
- params.enable_serializer = true;
- v8::Isolate* isolate = v8::Isolate::New(params);
- Serialize(isolate);
- }
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* isolate = TestIsolate::NewInitialized(true);
+ Serialize(isolate);
}
// Test that heap serialization is non-destructive.
UNINITIALIZED_TEST(SerializeTwice) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate::CreateParams params;
- params.enable_serializer = true;
- v8::Isolate* isolate = v8::Isolate::New(params);
- Serialize(isolate);
- Serialize(isolate);
- }
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* isolate = TestIsolate::NewInitialized(true);
+ Serialize(isolate);
+ Serialize(isolate);
}
@@ -207,7 +161,7 @@ v8::Isolate* InitializeFromFile(const char* snapshot_file) {
{
SnapshotData snapshot_data(Vector<const byte>(str, len));
Deserializer deserializer(&snapshot_data);
- Isolate* isolate = Isolate::NewForTesting();
+ Isolate* isolate = new TestIsolate(false);
v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
v8::Isolate::Scope isolate_scope(v8_isolate);
isolate->Init(&deserializer);
@@ -241,466 +195,538 @@ UNINITIALIZED_DEPENDENT_TEST(Deserialize, Serialize) {
// The serialize-deserialize tests only work if the VM is built without
// serialization. That doesn't matter. We don't need to be able to
// serialize a snapshot in a VM that is booted from a snapshot.
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate* isolate = Deserialize();
- {
- v8::HandleScope handle_scope(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* isolate = Deserialize();
+ {
+ v8::HandleScope handle_scope(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
- v8::Local<v8::Context> env = v8::Context::New(isolate);
- env->Enter();
+ v8::Local<v8::Context> env = v8::Context::New(isolate);
+ env->Enter();
- SanityCheck(isolate);
- }
- isolate->Dispose();
+ SanityCheck(isolate);
}
+ isolate->Dispose();
}
UNINITIALIZED_DEPENDENT_TEST(DeserializeFromSecondSerialization,
SerializeTwice) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate* isolate = Deserialize();
- {
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* isolate = Deserialize();
+ {
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> env = v8::Context::New(isolate);
- env->Enter();
+ v8::Local<v8::Context> env = v8::Context::New(isolate);
+ env->Enter();
- SanityCheck(isolate);
- }
- isolate->Dispose();
+ SanityCheck(isolate);
}
+ isolate->Dispose();
}
UNINITIALIZED_DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate* isolate = Deserialize();
- {
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* isolate = Deserialize();
+ {
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> env = v8::Context::New(isolate);
- env->Enter();
+ v8::Local<v8::Context> env = v8::Context::New(isolate);
+ env->Enter();
- const char* c_source = "\"1234\".length";
- v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
- v8::Local<v8::Script> script = v8::Script::Compile(source);
- CHECK_EQ(4, script->Run()->Int32Value());
- }
- isolate->Dispose();
+ const char* c_source = "\"1234\".length";
+ v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
+ v8::Local<v8::Script> script = v8::Script::Compile(source);
+ CHECK_EQ(4, script->Run()->Int32Value());
}
+ isolate->Dispose();
}
UNINITIALIZED_DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
SerializeTwice) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate* isolate = Deserialize();
- {
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* isolate = Deserialize();
+ {
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> env = v8::Context::New(isolate);
- env->Enter();
+ v8::Local<v8::Context> env = v8::Context::New(isolate);
+ env->Enter();
- const char* c_source = "\"1234\".length";
- v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
- v8::Local<v8::Script> script = v8::Script::Compile(source);
- CHECK_EQ(4, script->Run()->Int32Value());
- }
- isolate->Dispose();
+ const char* c_source = "\"1234\".length";
+ v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
+ v8::Local<v8::Script> script = v8::Script::Compile(source);
+ CHECK_EQ(4, script->Run()->Int32Value());
}
+ isolate->Dispose();
}
UNINITIALIZED_TEST(PartialSerialization) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate::CreateParams params;
- params.enable_serializer = true;
- v8::Isolate* v8_isolate = v8::Isolate::New(params);
- Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
- v8_isolate->Enter();
- {
- Heap* heap = isolate->heap();
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
+ Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
+ v8_isolate->Enter();
+ {
+ Heap* heap = isolate->heap();
- v8::Persistent<v8::Context> env;
- {
- HandleScope scope(isolate);
- env.Reset(v8_isolate, v8::Context::New(v8_isolate));
- }
- DCHECK(!env.IsEmpty());
- {
- v8::HandleScope handle_scope(v8_isolate);
- v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
- }
- // Make sure all builtin scripts are cached.
- {
- HandleScope scope(isolate);
- for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
- isolate->bootstrapper()->NativesSourceLookup(i);
- }
- }
- heap->CollectAllGarbage(Heap::kNoGCFlags);
- heap->CollectAllGarbage(Heap::kNoGCFlags);
-
- Object* raw_foo;
- {
- v8::HandleScope handle_scope(v8_isolate);
- v8::Local<v8::String> foo = v8::String::NewFromUtf8(v8_isolate, "foo");
- DCHECK(!foo.IsEmpty());
- raw_foo = *(v8::Utils::OpenHandle(*foo));
+ v8::Persistent<v8::Context> env;
+ {
+ HandleScope scope(isolate);
+ env.Reset(v8_isolate, v8::Context::New(v8_isolate));
+ }
+ DCHECK(!env.IsEmpty());
+ {
+ v8::HandleScope handle_scope(v8_isolate);
+ v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
+ }
+ // Make sure all builtin scripts are cached.
+ {
+ HandleScope scope(isolate);
+ for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
+ isolate->bootstrapper()->NativesSourceLookup(i);
}
+ }
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
- int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
- Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
- SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+ Object* raw_foo;
+ {
+ v8::HandleScope handle_scope(v8_isolate);
+ v8::Local<v8::String> foo = v8::String::NewFromUtf8(v8_isolate, "foo");
+ DCHECK(!foo.IsEmpty());
+ raw_foo = *(v8::Utils::OpenHandle(*foo));
+ }
- {
- v8::HandleScope handle_scope(v8_isolate);
- v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
- }
- env.Reset();
+ int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
+ Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
+ SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
- SnapshotByteSink startup_sink;
- StartupSerializer startup_serializer(isolate, &startup_sink);
- startup_serializer.SerializeStrongReferences();
+ {
+ v8::HandleScope handle_scope(v8_isolate);
+ v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
+ }
+ env.Reset();
- SnapshotByteSink partial_sink;
- PartialSerializer partial_serializer(isolate, &startup_serializer,
- &partial_sink);
- partial_serializer.Serialize(&raw_foo);
+ SnapshotByteSink startup_sink;
+ StartupSerializer startup_serializer(isolate, &startup_sink);
+ startup_serializer.SerializeStrongReferences();
- startup_serializer.SerializeWeakReferences();
+ SnapshotByteSink partial_sink;
+ PartialSerializer partial_serializer(isolate, &startup_serializer,
+ &partial_sink);
+ partial_serializer.Serialize(&raw_foo);
- SnapshotData startup_snapshot(startup_serializer);
- SnapshotData partial_snapshot(partial_serializer);
+ startup_serializer.SerializeWeakReferences();
- WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file);
- WritePayload(startup_snapshot.RawData(), startup_name.start());
+ SnapshotData startup_snapshot(startup_serializer);
+ SnapshotData partial_snapshot(partial_serializer);
- startup_name.Dispose();
- }
- v8_isolate->Exit();
- v8_isolate->Dispose();
+ WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file);
+ WritePayload(startup_snapshot.RawData(), startup_name.start());
+
+ startup_name.Dispose();
}
+ v8_isolate->Exit();
+ v8_isolate->Dispose();
}
UNINITIALIZED_DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
- Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
- SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
+ Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
+ SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+
+ v8::Isolate* v8_isolate = InitializeFromFile(startup_name.start());
+ CHECK(v8_isolate);
+ startup_name.Dispose();
+ {
+ v8::Isolate::Scope isolate_scope(v8_isolate);
- v8::Isolate* v8_isolate = InitializeFromFile(startup_name.start());
- CHECK(v8_isolate);
- startup_name.Dispose();
+ const char* file_name = FLAG_testing_serialization_file;
+
+ int snapshot_size = 0;
+ byte* snapshot = ReadBytes(file_name, &snapshot_size);
+
+ Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
+ HandleScope handle_scope(isolate);
+ Handle<Object> root;
+ Handle<FixedArray> outdated_contexts;
+ // Intentionally empty handle. The deserializer should not come across
+ // any references to the global proxy in this test.
+ Handle<JSGlobalProxy> global_proxy = Handle<JSGlobalProxy>::null();
{
- v8::Isolate::Scope isolate_scope(v8_isolate);
-
- const char* file_name = FLAG_testing_serialization_file;
-
- int snapshot_size = 0;
- byte* snapshot = ReadBytes(file_name, &snapshot_size);
-
- Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
- HandleScope handle_scope(isolate);
- Handle<Object> root;
- Handle<FixedArray> outdated_contexts;
- // Intentionally empty handle. The deserializer should not come across
- // any references to the global proxy in this test.
- Handle<JSGlobalProxy> global_proxy = Handle<JSGlobalProxy>::null();
- {
- SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
- Deserializer deserializer(&snapshot_data);
- root = deserializer.DeserializePartial(isolate, global_proxy,
- &outdated_contexts)
- .ToHandleChecked();
- CHECK_EQ(0, outdated_contexts->length());
- CHECK(root->IsString());
- }
+ SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
+ Deserializer deserializer(&snapshot_data);
+ root =
+ deserializer.DeserializePartial(isolate, global_proxy,
+ &outdated_contexts).ToHandleChecked();
+ CHECK_EQ(0, outdated_contexts->length());
+ CHECK(root->IsString());
+ }
- Handle<Object> root2;
- {
- SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
- Deserializer deserializer(&snapshot_data);
- root2 = deserializer.DeserializePartial(isolate, global_proxy,
- &outdated_contexts)
- .ToHandleChecked();
- CHECK(root2->IsString());
- CHECK(root.is_identical_to(root2));
- }
+ Handle<Object> root2;
+ {
+ SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
+ Deserializer deserializer(&snapshot_data);
+ root2 =
+ deserializer.DeserializePartial(isolate, global_proxy,
+ &outdated_contexts).ToHandleChecked();
+ CHECK(root2->IsString());
+ CHECK(root.is_identical_to(root2));
}
- v8_isolate->Dispose();
+
+ DeleteArray(snapshot);
}
+ v8_isolate->Dispose();
}
UNINITIALIZED_TEST(ContextSerialization) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate::CreateParams params;
- params.enable_serializer = true;
- v8::Isolate* v8_isolate = v8::Isolate::New(params);
- Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
- Heap* heap = isolate->heap();
- {
- v8::Isolate::Scope isolate_scope(v8_isolate);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
+ Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
+ Heap* heap = isolate->heap();
+ {
+ v8::Isolate::Scope isolate_scope(v8_isolate);
- v8::Persistent<v8::Context> env;
- {
- HandleScope scope(isolate);
- env.Reset(v8_isolate, v8::Context::New(v8_isolate));
- }
- DCHECK(!env.IsEmpty());
- {
- v8::HandleScope handle_scope(v8_isolate);
- v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
- }
- // Make sure all builtin scripts are cached.
- {
- HandleScope scope(isolate);
- for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
- isolate->bootstrapper()->NativesSourceLookup(i);
- }
+ v8::Persistent<v8::Context> env;
+ {
+ HandleScope scope(isolate);
+ env.Reset(v8_isolate, v8::Context::New(v8_isolate));
+ }
+ DCHECK(!env.IsEmpty());
+ {
+ v8::HandleScope handle_scope(v8_isolate);
+ v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
+ }
+ // Make sure all builtin scripts are cached.
+ {
+ HandleScope scope(isolate);
+ for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
+ isolate->bootstrapper()->NativesSourceLookup(i);
}
- // If we don't do this then we end up with a stray root pointing at the
- // context even after we have disposed of env.
- heap->CollectAllGarbage(Heap::kNoGCFlags);
+ }
+ // If we don't do this then we end up with a stray root pointing at the
+ // context even after we have disposed of env.
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
- int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
- Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
- SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+ int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
+ Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
+ SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
- {
- v8::HandleScope handle_scope(v8_isolate);
- v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
- }
+ {
+ v8::HandleScope handle_scope(v8_isolate);
+ v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
+ }
- i::Object* raw_context = *v8::Utils::OpenPersistent(env);
+ i::Object* raw_context = *v8::Utils::OpenPersistent(env);
- env.Reset();
+ env.Reset();
- SnapshotByteSink startup_sink;
- StartupSerializer startup_serializer(isolate, &startup_sink);
- startup_serializer.SerializeStrongReferences();
+ SnapshotByteSink startup_sink;
+ StartupSerializer startup_serializer(isolate, &startup_sink);
+ startup_serializer.SerializeStrongReferences();
- SnapshotByteSink partial_sink;
- PartialSerializer partial_serializer(isolate, &startup_serializer,
- &partial_sink);
- partial_serializer.Serialize(&raw_context);
- startup_serializer.SerializeWeakReferences();
+ SnapshotByteSink partial_sink;
+ PartialSerializer partial_serializer(isolate, &startup_serializer,
+ &partial_sink);
+ partial_serializer.Serialize(&raw_context);
+ startup_serializer.SerializeWeakReferences();
- SnapshotData startup_snapshot(startup_serializer);
- SnapshotData partial_snapshot(partial_serializer);
+ SnapshotData startup_snapshot(startup_serializer);
+ SnapshotData partial_snapshot(partial_serializer);
- WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file);
- WritePayload(startup_snapshot.RawData(), startup_name.start());
+ WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file);
+ WritePayload(startup_snapshot.RawData(), startup_name.start());
- startup_name.Dispose();
- }
- v8_isolate->Dispose();
+ startup_name.Dispose();
}
+ v8_isolate->Dispose();
}
UNINITIALIZED_DEPENDENT_TEST(ContextDeserialization, ContextSerialization) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
- Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
- SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
+ Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
+ SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+
+ v8::Isolate* v8_isolate = InitializeFromFile(startup_name.start());
+ CHECK(v8_isolate);
+ startup_name.Dispose();
+ {
+ v8::Isolate::Scope isolate_scope(v8_isolate);
- v8::Isolate* v8_isolate = InitializeFromFile(startup_name.start());
- CHECK(v8_isolate);
- startup_name.Dispose();
+ const char* file_name = FLAG_testing_serialization_file;
+
+ int snapshot_size = 0;
+ byte* snapshot = ReadBytes(file_name, &snapshot_size);
+
+ Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
+ HandleScope handle_scope(isolate);
+ Handle<Object> root;
+ Handle<FixedArray> outdated_contexts;
+ Handle<JSGlobalProxy> global_proxy =
+ isolate->factory()->NewUninitializedJSGlobalProxy();
{
- v8::Isolate::Scope isolate_scope(v8_isolate);
-
- const char* file_name = FLAG_testing_serialization_file;
-
- int snapshot_size = 0;
- byte* snapshot = ReadBytes(file_name, &snapshot_size);
-
- Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
- HandleScope handle_scope(isolate);
- Handle<Object> root;
- Handle<FixedArray> outdated_contexts;
- Handle<JSGlobalProxy> global_proxy =
- isolate->factory()->NewUninitializedJSGlobalProxy();
- {
- SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
- Deserializer deserializer(&snapshot_data);
- root = deserializer.DeserializePartial(isolate, global_proxy,
- &outdated_contexts)
- .ToHandleChecked();
- CHECK(root->IsContext());
- CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
- CHECK_EQ(1, outdated_contexts->length());
- }
+ SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
+ Deserializer deserializer(&snapshot_data);
+ root =
+ deserializer.DeserializePartial(isolate, global_proxy,
+ &outdated_contexts).ToHandleChecked();
+ CHECK(root->IsContext());
+ CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
+ CHECK_EQ(1, outdated_contexts->length());
+ }
- Handle<Object> root2;
- {
- SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
- Deserializer deserializer(&snapshot_data);
- root2 = deserializer.DeserializePartial(isolate, global_proxy,
- &outdated_contexts)
- .ToHandleChecked();
- CHECK(root2->IsContext());
- CHECK(!root.is_identical_to(root2));
- }
+ Handle<Object> root2;
+ {
+ SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
+ Deserializer deserializer(&snapshot_data);
+ root2 =
+ deserializer.DeserializePartial(isolate, global_proxy,
+ &outdated_contexts).ToHandleChecked();
+ CHECK(root2->IsContext());
+ CHECK(!root.is_identical_to(root2));
}
- v8_isolate->Dispose();
+ DeleteArray(snapshot);
}
+ v8_isolate->Dispose();
}
UNINITIALIZED_TEST(CustomContextSerialization) {
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- v8::Isolate::CreateParams params;
- params.enable_serializer = true;
- v8::Isolate* v8_isolate = v8::Isolate::New(params);
- Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
- {
- v8::Isolate::Scope isolate_scope(v8_isolate);
+ DisableTurbofan();
+ if (DefaultSnapshotAvailable()) return;
+ v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
+ Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
+ {
+ v8::Isolate::Scope isolate_scope(v8_isolate);
- v8::Persistent<v8::Context> env;
- {
- HandleScope scope(isolate);
- env.Reset(v8_isolate, v8::Context::New(v8_isolate));
- }
- DCHECK(!env.IsEmpty());
- {
- v8::HandleScope handle_scope(v8_isolate);
- v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
- // After execution, e's function context refers to the global object.
- CompileRun(
- "var e;"
- "(function() {"
- " e = function(s) { return eval (s); }"
- "})();"
- "var o = this;"
- "var r = Math.random() + Math.cos(0);"
- "var f = (function(a, b) { return a + b; }).bind(1, 2, 3);"
- "var s = parseInt('12345');");
-
- Vector<const uint8_t> source = ConstructSource(
- STATIC_CHAR_VECTOR("function g() { return [,"),
- STATIC_CHAR_VECTOR("1,"),
- STATIC_CHAR_VECTOR("];} a = g(); b = g(); b.push(1);"), 100000);
- v8::Handle<v8::String> source_str = v8::String::NewFromOneByte(
- v8_isolate, source.start(), v8::String::kNormalString,
- source.length());
- CompileRun(source_str);
- source.Dispose();
- }
- // Make sure all builtin scripts are cached.
- {
- HandleScope scope(isolate);
- for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
- isolate->bootstrapper()->NativesSourceLookup(i);
- }
+ v8::Persistent<v8::Context> env;
+ {
+ HandleScope scope(isolate);
+ env.Reset(v8_isolate, v8::Context::New(v8_isolate));
+ }
+ DCHECK(!env.IsEmpty());
+ {
+ v8::HandleScope handle_scope(v8_isolate);
+ v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
+ // After execution, e's function context refers to the global object.
+ CompileRun(
+ "var e;"
+ "(function() {"
+ " e = function(s) { return eval (s); }"
+ "})();"
+ "var o = this;"
+ "var r = Math.random() + Math.cos(0);"
+ "var f = (function(a, b) { return a + b; }).bind(1, 2, 3);"
+ "var s = parseInt('12345');");
+
+ Vector<const uint8_t> source = ConstructSource(
+ STATIC_CHAR_VECTOR("function g() { return [,"),
+ STATIC_CHAR_VECTOR("1,"),
+ STATIC_CHAR_VECTOR("];} a = g(); b = g(); b.push(1);"), 100000);
+ v8::Handle<v8::String> source_str = v8::String::NewFromOneByte(
+ v8_isolate, source.start(), v8::String::kNormalString,
+ source.length());
+ CompileRun(source_str);
+ source.Dispose();
+ }
+ // Make sure all builtin scripts are cached.
+ {
+ HandleScope scope(isolate);
+ for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
+ isolate->bootstrapper()->NativesSourceLookup(i);
}
- // If we don't do this then we end up with a stray root pointing at the
- // context even after we have disposed of env.
- isolate->heap()->CollectAllAvailableGarbage("snapshotting");
+ }
+ // If we don't do this then we end up with a stray root pointing at the
+ // context even after we have disposed of env.
+ isolate->heap()->CollectAllAvailableGarbage("snapshotting");
- int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
- Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
- SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+ int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
+ Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
+ SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
- {
- v8::HandleScope handle_scope(v8_isolate);
- v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
- }
+ {
+ v8::HandleScope handle_scope(v8_isolate);
+ v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
+ }
- i::Object* raw_context = *v8::Utils::OpenPersistent(env);
+ i::Object* raw_context = *v8::Utils::OpenPersistent(env);
- env.Reset();
+ env.Reset();
- SnapshotByteSink startup_sink;
- StartupSerializer startup_serializer(isolate, &startup_sink);
- startup_serializer.SerializeStrongReferences();
+ SnapshotByteSink startup_sink;
+ StartupSerializer startup_serializer(isolate, &startup_sink);
+ startup_serializer.SerializeStrongReferences();
- SnapshotByteSink partial_sink;
- PartialSerializer partial_serializer(isolate, &startup_serializer,
- &partial_sink);
- partial_serializer.Serialize(&raw_context);
- startup_serializer.SerializeWeakReferences();
+ SnapshotByteSink partial_sink;
+ PartialSerializer partial_serializer(isolate, &startup_serializer,
+ &partial_sink);
+ partial_serializer.Serialize(&raw_context);
+ startup_serializer.SerializeWeakReferences();
- SnapshotData startup_snapshot(startup_serializer);
- SnapshotData partial_snapshot(partial_serializer);
+ SnapshotData startup_snapshot(startup_serializer);
+ SnapshotData partial_snapshot(partial_serializer);
- WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file);
- WritePayload(startup_snapshot.RawData(), startup_name.start());
+ WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file);
+ WritePayload(startup_snapshot.RawData(), startup_name.start());
- startup_name.Dispose();
- }
- v8_isolate->Dispose();
+ startup_name.Dispose();
}
+ v8_isolate->Dispose();
}
UNINITIALIZED_DEPENDENT_TEST(CustomContextDeserialization,
CustomContextSerialization) {
+ DisableTurbofan();
FLAG_crankshaft = false;
- if (!Snapshot::HaveASnapshotToStartFrom()) {
- int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
- Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
- SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+ if (DefaultSnapshotAvailable()) return;
+ int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
+ Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
+ SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
+
+ v8::Isolate* v8_isolate = InitializeFromFile(startup_name.start());
+ CHECK(v8_isolate);
+ startup_name.Dispose();
+ {
+ v8::Isolate::Scope isolate_scope(v8_isolate);
- v8::Isolate* v8_isolate = InitializeFromFile(startup_name.start());
- CHECK(v8_isolate);
- startup_name.Dispose();
+ const char* file_name = FLAG_testing_serialization_file;
+
+ int snapshot_size = 0;
+ byte* snapshot = ReadBytes(file_name, &snapshot_size);
+
+ Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
+ HandleScope handle_scope(isolate);
+ Handle<Object> root;
+ Handle<FixedArray> outdated_contexts;
+ Handle<JSGlobalProxy> global_proxy =
+ isolate->factory()->NewUninitializedJSGlobalProxy();
{
- v8::Isolate::Scope isolate_scope(v8_isolate);
-
- const char* file_name = FLAG_testing_serialization_file;
-
- int snapshot_size = 0;
- byte* snapshot = ReadBytes(file_name, &snapshot_size);
-
- Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
- HandleScope handle_scope(isolate);
- Handle<Object> root;
- Handle<FixedArray> outdated_contexts;
- Handle<JSGlobalProxy> global_proxy =
- isolate->factory()->NewUninitializedJSGlobalProxy();
- {
- SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
- Deserializer deserializer(&snapshot_data);
- root = deserializer.DeserializePartial(isolate, global_proxy,
- &outdated_contexts)
- .ToHandleChecked();
- CHECK_EQ(2, outdated_contexts->length());
- CHECK(root->IsContext());
- Handle<Context> context = Handle<Context>::cast(root);
- CHECK(context->global_proxy() == *global_proxy);
- Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o");
- Handle<JSObject> global_object(context->global_object(), isolate);
- Handle<Object> property = JSObject::GetDataProperty(global_object, o);
- CHECK(property.is_identical_to(global_proxy));
-
- v8::Handle<v8::Context> v8_context = v8::Utils::ToLocal(context);
- v8::Context::Scope context_scope(v8_context);
- double r = CompileRun("r")->ToNumber(v8_isolate)->Value();
- CHECK(r >= 1 && r <= 2);
- int f = CompileRun("f()")->ToNumber(v8_isolate)->Int32Value();
- CHECK_EQ(5, f);
- f = CompileRun("e('f()')")->ToNumber(v8_isolate)->Int32Value();
- CHECK_EQ(5, f);
- v8::Handle<v8::String> s = CompileRun("s")->ToString(v8_isolate);
- CHECK(s->Equals(v8_str("12345")));
- int a = CompileRun("a.length")->ToNumber(v8_isolate)->Int32Value();
- CHECK_EQ(100001, a);
- int b = CompileRun("b.length")->ToNumber(v8_isolate)->Int32Value();
- CHECK_EQ(100002, b);
- }
+ SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
+ Deserializer deserializer(&snapshot_data);
+ root =
+ deserializer.DeserializePartial(isolate, global_proxy,
+ &outdated_contexts).ToHandleChecked();
+ CHECK_EQ(2, outdated_contexts->length());
+ CHECK(root->IsContext());
+ Handle<Context> context = Handle<Context>::cast(root);
+ CHECK(context->global_proxy() == *global_proxy);
+ Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o");
+ Handle<JSObject> global_object(context->global_object(), isolate);
+ Handle<Object> property = JSObject::GetDataProperty(global_object, o);
+ CHECK(property.is_identical_to(global_proxy));
+
+ v8::Handle<v8::Context> v8_context = v8::Utils::ToLocal(context);
+ v8::Context::Scope context_scope(v8_context);
+ double r = CompileRun("r")->ToNumber(v8_isolate)->Value();
+ CHECK(r >= 1 && r <= 2);
+ int f = CompileRun("f()")->ToNumber(v8_isolate)->Int32Value();
+ CHECK_EQ(5, f);
+ f = CompileRun("e('f()')")->ToNumber(v8_isolate)->Int32Value();
+ CHECK_EQ(5, f);
+ v8::Handle<v8::String> s = CompileRun("s")->ToString(v8_isolate);
+ CHECK(s->Equals(v8_str("12345")));
+ int a = CompileRun("a.length")->ToNumber(v8_isolate)->Int32Value();
+ CHECK_EQ(100001, a);
+ int b = CompileRun("b.length")->ToNumber(v8_isolate)->Int32Value();
+ CHECK_EQ(100002, b);
}
- v8_isolate->Dispose();
+ DeleteArray(snapshot);
+ }
+ v8_isolate->Dispose();
+}
+
+
+TEST(PerIsolateSnapshotBlobs) {
+ DisableTurbofan();
+ const char* source1 = "function f() { return 42; }";
+ const char* source2 =
+ "function f() { return g() * 2; }"
+ "function g() { return 43; }"
+ "/./.test('a')";
+
+ v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
+ v8::StartupData data2 = v8::V8::CreateSnapshotDataBlob(source2);
+
+ v8::Isolate::CreateParams params1;
+ params1.snapshot_blob = &data1;
+ v8::Isolate* isolate1 = v8::Isolate::New(params1);
+ {
+ v8::Isolate::Scope i_scope(isolate1);
+ v8::HandleScope h_scope(isolate1);
+ v8::Local<v8::Context> context = v8::Context::New(isolate1);
+ delete[] data1.data; // We can dispose of the snapshot blob now.
+ v8::Context::Scope c_scope(context);
+ CHECK_EQ(42, CompileRun("f()")->ToInt32(isolate1)->Int32Value());
+ CHECK(CompileRun("this.g")->IsUndefined());
+ }
+ isolate1->Dispose();
+
+ v8::Isolate::CreateParams params2;
+ params2.snapshot_blob = &data2;
+ v8::Isolate* isolate2 = v8::Isolate::New(params2);
+ {
+ v8::Isolate::Scope i_scope(isolate2);
+ v8::HandleScope h_scope(isolate2);
+ v8::Local<v8::Context> context = v8::Context::New(isolate2);
+ delete[] data2.data; // We can dispose of the snapshot blob now.
+ v8::Context::Scope c_scope(context);
+ CHECK_EQ(86, CompileRun("f()")->ToInt32(isolate2)->Int32Value());
+ CHECK_EQ(43, CompileRun("g()")->ToInt32(isolate2)->Int32Value());
+ }
+ isolate2->Dispose();
+}
+
+
+TEST(PerIsolateSnapshotBlobsWithLocker) {
+ DisableTurbofan();
+ v8::Isolate* isolate0 = v8::Isolate::New();
+ {
+ v8::Locker locker(isolate0);
+ v8::Isolate::Scope i_scope(isolate0);
+ v8::HandleScope h_scope(isolate0);
+ v8::Local<v8::Context> context = v8::Context::New(isolate0);
+ v8::Context::Scope c_scope(context);
+ CHECK_EQ(1, CompileRun("Math.cos(0)")->ToInt32(isolate0)->Int32Value());
}
+ isolate0->Dispose();
+
+ const char* source1 = "function f() { return 42; }";
+
+ v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
+
+ v8::Isolate::CreateParams params1;
+ params1.snapshot_blob = &data1;
+ v8::Isolate* isolate1 = v8::Isolate::New(params1);
+ {
+ v8::Locker locker(isolate1);
+ v8::Isolate::Scope i_scope(isolate1);
+ v8::HandleScope h_scope(isolate1);
+ v8::Local<v8::Context> context = v8::Context::New(isolate1);
+ delete[] data1.data; // We can dispose of the snapshot blob now.
+ v8::Context::Scope c_scope(context);
+ CHECK_EQ(42, CompileRun("f()")->ToInt32(isolate1)->Int32Value());
+ }
+ isolate1->Dispose();
}
@@ -735,10 +761,10 @@ int CountBuiltins() {
static Handle<SharedFunctionInfo> CompileScript(
Isolate* isolate, Handle<String> source, Handle<String> name,
ScriptData** cached_data, v8::ScriptCompiler::CompileOptions options) {
- return Compiler::CompileScript(source, name, 0, 0, false, false,
- Handle<Context>(isolate->native_context()),
- NULL, cached_data, options, NOT_NATIVES_CODE,
- false);
+ return Compiler::CompileScript(
+ source, name, 0, 0, false, false, Handle<Object>(),
+ Handle<Context>(isolate->native_context()), NULL, cached_data, options,
+ NOT_NATIVES_CODE, false);
}
@@ -1346,7 +1372,9 @@ TEST(SerializeToplevelFlagChange) {
v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
v8::Isolate* isolate2 = v8::Isolate::New();
+
FLAG_allow_natives_syntax = true; // Flag change should trigger cache reject.
+ FlagList::EnforceFlagImplications();
{
v8::Isolate::Scope iscope(isolate2);
v8::HandleScope scope(isolate2);
@@ -1393,7 +1421,6 @@ TEST(SerializeToplevelBitFlip) {
TEST(SerializeWithHarmonyScoping) {
FLAG_serialize_toplevel = true;
- FLAG_harmony_scoping = true;
const char* source1 = "'use strict'; let x = 'X'";
const char* source2 = "'use strict'; let y = 'Y'";
@@ -1454,3 +1481,71 @@ TEST(SerializeWithHarmonyScoping) {
}
isolate2->Dispose();
}
+
+
+TEST(SerializeInternalReference) {
+#ifdef V8_TARGET_ARCH_ARM64
+ return;
+#endif // V8_TARGET_ARCH_ARM64
+ // Disable experimental natives that are loaded after deserialization.
+ FLAG_turbo_deoptimization = false;
+ FLAG_context_specialization = false;
+ FLAG_always_opt = true;
+ const char* flag = "--turbo-filter=foo";
+ FlagList::SetFlagsFromString(flag, StrLength(flag));
+
+ const char* source =
+ "var foo = (function(stdlib, foreign, heap) {"
+ " function foo(i) {"
+ " i = i|0;"
+ " var j = 0;"
+ " switch (i) {"
+ " case 0:"
+ " case 1: j = 1; break;"
+ " case 2:"
+ " case 3: j = 2; break;"
+ " case 4:"
+ " case 5: j = foo(3) + 1; break;"
+ " default: j = 0; break;"
+ " }"
+ " return j + 10;"
+ " }"
+ " return { foo: foo };"
+ "})(this, {}, undefined).foo;"
+ "foo(1);";
+
+ v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
+ CHECK(data.data);
+
+ v8::Isolate::CreateParams params;
+ params.snapshot_blob = &data;
+ v8::Isolate* isolate = v8::Isolate::New(params);
+ {
+ v8::Isolate::Scope i_scope(isolate);
+ v8::HandleScope h_scope(isolate);
+ v8::Local<v8::Context> context = v8::Context::New(isolate);
+ delete[] data.data; // We can dispose of the snapshot blob now.
+ v8::Context::Scope c_scope(context);
+ v8::Handle<v8::Function> foo =
+ v8::Handle<v8::Function>::Cast(CompileRun("foo"));
+
+ // There are at least 6 internal references.
+ int mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
+ RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
+ RelocIterator it(v8::Utils::OpenHandle(*foo)->code(), mask);
+ for (int i = 0; i < 6; ++i) {
+ CHECK(!it.done());
+ it.next();
+ }
+
+ CHECK(v8::Utils::OpenHandle(*foo)->code()->is_turbofanned());
+ CHECK_EQ(11, CompileRun("foo(0)")->ToInt32(isolate)->Int32Value());
+ CHECK_EQ(11, CompileRun("foo(1)")->ToInt32(isolate)->Int32Value());
+ CHECK_EQ(12, CompileRun("foo(2)")->ToInt32(isolate)->Int32Value());
+ CHECK_EQ(12, CompileRun("foo(3)")->ToInt32(isolate)->Int32Value());
+ CHECK_EQ(23, CompileRun("foo(4)")->ToInt32(isolate)->Int32Value());
+ CHECK_EQ(23, CompileRun("foo(5)")->ToInt32(isolate)->Int32Value());
+ CHECK_EQ(10, CompileRun("foo(6)")->ToInt32(isolate)->Int32Value());
+ }
+ isolate->Dispose();
+}
diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc
index 331ea02510..92305f9f1e 100644
--- a/deps/v8/test/cctest/test-spaces.cc
+++ b/deps/v8/test/cctest/test-spaces.cc
@@ -28,7 +28,7 @@
#include <stdlib.h>
#include "src/base/platform/platform.h"
-#include "src/snapshot.h"
+#include "src/snapshot/snapshot.h"
#include "src/v8.h"
#include "test/cctest/cctest.h"
@@ -207,12 +207,13 @@ static void VerifyMemoryChunk(Isolate* isolate,
TEST(Regress3540) {
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
+ const int pageSize = Page::kPageSize;
MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
CHECK(
memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize()));
TestMemoryAllocatorScope test_allocator_scope(isolate, memory_allocator);
CodeRange* code_range = new CodeRange(isolate);
- const size_t code_range_size = 4 * MB;
+ const size_t code_range_size = 4 * pageSize;
if (!code_range->SetUp(
code_range_size +
RoundUp(v8::base::OS::CommitPageSize() * kReservedCodeRangePages,
@@ -222,13 +223,13 @@ TEST(Regress3540) {
}
Address address;
size_t size;
- address = code_range->AllocateRawMemory(code_range_size - 2 * MB,
- code_range_size - 2 * MB, &size);
+ address = code_range->AllocateRawMemory(
+ code_range_size - 2 * pageSize, code_range_size - 2 * pageSize, &size);
CHECK(address != NULL);
Address null_address;
size_t null_size;
null_address = code_range->AllocateRawMemory(
- code_range_size - MB, code_range_size - MB, &null_size);
+ code_range_size - pageSize, code_range_size - pageSize, &null_size);
CHECK(null_address == NULL);
code_range->FreeRawMemory(address, size);
delete code_range;
@@ -307,9 +308,7 @@ TEST(MemoryAllocator) {
heap->MaxExecutableSize()));
int total_pages = 0;
- OldSpace faked_space(heap,
- heap->MaxReserved(),
- OLD_POINTER_SPACE,
+ OldSpace faked_space(heap, heap->MaxReserved(), OLD_POINTER_SPACE,
NOT_EXECUTABLE);
Page* first_page = memory_allocator->AllocatePage(
faked_space.AreaSize(), &faked_space, NOT_EXECUTABLE);
@@ -379,10 +378,8 @@ TEST(OldSpace) {
heap->MaxExecutableSize()));
TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
- OldSpace* s = new OldSpace(heap,
- heap->MaxOldGenerationSize(),
- OLD_POINTER_SPACE,
- NOT_EXECUTABLE);
+ OldSpace* s = new OldSpace(heap, heap->MaxOldGenerationSize(),
+ OLD_POINTER_SPACE, NOT_EXECUTABLE);
CHECK(s != NULL);
CHECK(s->SetUp());
@@ -422,7 +419,9 @@ TEST(LargeObjectSpace) {
{ AllocationResult allocation = lo->AllocateRaw(lo_size, NOT_EXECUTABLE);
if (allocation.IsRetry()) break;
}
- CHECK(lo->Available() < available);
+ // The available value is conservative such that it may report
+ // zero prior to heap exhaustion.
+ CHECK(lo->Available() < available || available == 0);
}
CHECK(!lo->IsEmpty());
@@ -434,9 +433,10 @@ TEST(LargeObjectSpace) {
TEST(SizeOfFirstPageIsLargeEnough) {
if (i::FLAG_always_opt) return;
// Bootstrapping without a snapshot causes more allocations.
- if (!i::Snapshot::HaveASnapshotToStartFrom()) return;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
+ if (!isolate->snapshot_available()) return;
+ if (Snapshot::EmbedsScript(isolate)) return;
// Freshly initialized VM gets by with one page per space.
for (int i = FIRST_PAGED_SPACE; i <= LAST_PAGED_SPACE; i++) {
@@ -460,7 +460,7 @@ TEST(SizeOfFirstPageIsLargeEnough) {
UNINITIALIZED_TEST(NewSpaceGrowsToTargetCapacity) {
- FLAG_target_semi_space_size = 2;
+ FLAG_target_semi_space_size = 2 * (Page::kPageSize / MB);
if (FLAG_optimize_for_size) return;
v8::Isolate* isolate = v8::Isolate::New();
diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc
index 9a4e96ffd5..8d5129cd05 100644
--- a/deps/v8/test/cctest/test-strings.cc
+++ b/deps/v8/test/cctest/test-strings.cc
@@ -1209,7 +1209,7 @@ UNINITIALIZED_TEST(OneByteArrayJoin) {
v8::Isolate::CreateParams create_params;
// Set heap limits.
create_params.constraints.set_max_semi_space_size(1);
- create_params.constraints.set_max_old_space_size(5);
+ create_params.constraints.set_max_old_space_size(6);
v8::Isolate* isolate = v8::Isolate::New(create_params);
isolate->Enter();
diff --git a/deps/v8/test/cctest/test-thread-termination.cc b/deps/v8/test/cctest/test-thread-termination.cc
index d31b4131df..0d20e0f043 100644
--- a/deps/v8/test/cctest/test-thread-termination.cc
+++ b/deps/v8/test/cctest/test-thread-termination.cc
@@ -192,6 +192,7 @@ TEST(TerminateOnlyV8ThreadFromOtherThread) {
// Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::String::NewFromUtf8(
CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }");
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
v8::Script::Compile(source)->Run();
thread.Join();
@@ -228,6 +229,7 @@ void LoopGetProperty(const v8::FunctionCallbackInfo<v8::Value>& args) {
" }"
" fail();"
" } catch(e) {"
+ " (function() {})();" // trigger stack check.
" fail();"
" }"
"}"
@@ -375,6 +377,7 @@ void MicrotaskLoopForever(const v8::FunctionCallbackInfo<v8::Value>& info) {
// Enqueue another should-not-run task to ensure we clean out the queue
// when we terminate.
isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskShouldNotRun));
+ i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("terminate(); while (true) { }");
CHECK(v8::V8::IsExecutionTerminating());
}
@@ -474,3 +477,65 @@ TEST(ErrorObjectAfterTermination) {
// TODO(yangguo): crbug/403509. Check for empty handle instead.
CHECK(error->IsUndefined());
}
+
+
+void InnerTryCallTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
+ v8::Handle<v8::Object> global = CcTest::global();
+ v8::Handle<v8::Function> loop =
+ v8::Handle<v8::Function>::Cast(global->Get(v8_str("loop")));
+ i::MaybeHandle<i::Object> result =
+ i::Execution::TryCall(v8::Utils::OpenHandle((*loop)),
+ v8::Utils::OpenHandle((*global)), 0, NULL, NULL);
+ CHECK(result.is_null());
+ // TryCall ignores terminate execution, but rerequests the interrupt.
+ CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
+ CHECK(CompileRun("1 + 1;").IsEmpty());
+}
+
+
+TEST(TerminationInInnerTryCall) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::ObjectTemplate> global_template = CreateGlobalTemplate(
+ CcTest::isolate(), TerminateCurrentThread, DoLoopNoCall);
+ global_template->Set(
+ v8_str("inner_try_call_terminate"),
+ v8::FunctionTemplate::New(isolate, InnerTryCallTerminate));
+ v8::Handle<v8::Context> context =
+ v8::Context::New(CcTest::isolate(), NULL, global_template);
+ v8::Context::Scope context_scope(context);
+ {
+ v8::TryCatch try_catch;
+ CompileRun("inner_try_call_terminate()");
+ CHECK(try_catch.HasTerminated());
+ }
+ CHECK_EQ(4, CompileRun("2 + 2")->ToInt32()->Int32Value());
+ CHECK(!v8::V8::IsExecutionTerminating());
+}
+
+
+TEST(TerminateAndTryCall) {
+ i::FLAG_allow_natives_syntax = true;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(
+ isolate, TerminateCurrentThread, DoLoopCancelTerminate);
+ v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL, global);
+ v8::Context::Scope context_scope(context);
+ CHECK(!v8::V8::IsExecutionTerminating(isolate));
+ v8::TryCatch try_catch;
+ CHECK(!v8::V8::IsExecutionTerminating(isolate));
+ // Terminate execution has been triggered inside TryCall, but re-requested
+ // to trigger later.
+ CHECK(CompileRun("terminate(); reference_error();").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ CHECK(!v8::V8::IsExecutionTerminating(isolate));
+ CHECK(CcTest::global()->Get(v8_str("terminate"))->IsFunction());
+ // The first stack check after terminate has been re-requested fails.
+ CHECK(CompileRun("1 + 1").IsEmpty());
+ CHECK(!v8::V8::IsExecutionTerminating(isolate));
+ // V8 then recovers.
+ CHECK_EQ(4, CompileRun("2 + 2")->ToInt32()->Int32Value());
+ CHECK(!v8::V8::IsExecutionTerminating(isolate));
+}
diff --git a/deps/v8/test/cctest/test-transitions.cc b/deps/v8/test/cctest/test-transitions.cc
index 59c9f74c96..800c2a0e44 100644
--- a/deps/v8/test/cctest/test-transitions.cc
+++ b/deps/v8/test/cctest/test-transitions.cc
@@ -20,16 +20,6 @@ using namespace v8::internal;
// Helper functions.
//
-static void ConnectTransition(Handle<Map> parent,
- Handle<TransitionArray> transitions,
- Handle<Map> child) {
- if (!parent->HasTransitionArray() || *transitions != parent->transitions()) {
- parent->set_transitions(*transitions);
- }
- child->SetBackPointer(*parent);
-}
-
-
static void CheckPropertyDetailsFieldsConsistency(PropertyType type,
PropertyKind kind,
PropertyLocation location) {
@@ -69,34 +59,32 @@ TEST(TransitionArray_SimpleFieldTransitions) {
attributes, Representation::Tagged(),
OMIT_TRANSITION).ToHandleChecked();
- CHECK(!map0->HasTransitionArray());
- Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0);
- CHECK(transitions->IsFullTransitionArray());
-
- int transition;
- transitions =
- transitions->Insert(map0, name1, map1, SIMPLE_PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map1);
- CHECK(transitions->IsSimpleTransition());
- transition = transitions->Search(kData, *name1, attributes);
- CHECK_EQ(TransitionArray::kSimpleTransitionIndex, transition);
- CHECK_EQ(*name1, transitions->GetKey(transition));
- CHECK_EQ(*map1, transitions->GetTarget(transition));
-
- transitions =
- transitions->Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map2);
- CHECK(transitions->IsFullTransitionArray());
-
- transition = transitions->Search(kData, *name1, attributes);
- CHECK_EQ(*name1, transitions->GetKey(transition));
- CHECK_EQ(*map1, transitions->GetTarget(transition));
-
- transition = transitions->Search(kData, *name2, attributes);
- CHECK_EQ(*name2, transitions->GetKey(transition));
- CHECK_EQ(*map2, transitions->GetTarget(transition));
-
- DCHECK(transitions->IsSortedNoDuplicates());
+ CHECK(map0->raw_transitions()->IsSmi());
+
+ TransitionArray::Insert(map0, name1, map1, SIMPLE_PROPERTY_TRANSITION);
+ CHECK(TransitionArray::IsSimpleTransition(map0->raw_transitions()));
+ CHECK_EQ(*map1,
+ TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
+ CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
+ CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
+ CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
+
+ TransitionArray::Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION);
+ CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
+
+ CHECK_EQ(*map1,
+ TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
+ CHECK_EQ(*map2,
+ TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
+ CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
+ for (int i = 0; i < 2; i++) {
+ Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
+ Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
+ CHECK((key == *name1 && target == *map1) ||
+ (key == *name2 && target == *map2));
+ }
+
+ DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
}
@@ -120,31 +108,32 @@ TEST(TransitionArray_FullFieldTransitions) {
attributes, Representation::Tagged(),
OMIT_TRANSITION).ToHandleChecked();
- CHECK(!map0->HasTransitionArray());
- Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0);
- CHECK(transitions->IsFullTransitionArray());
-
- int transition;
- transitions = transitions->Insert(map0, name1, map1, PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map1);
- CHECK(transitions->IsFullTransitionArray());
- transition = transitions->Search(kData, *name1, attributes);
- CHECK_EQ(*name1, transitions->GetKey(transition));
- CHECK_EQ(*map1, transitions->GetTarget(transition));
-
- transitions = transitions->Insert(map0, name2, map2, PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map2);
- CHECK(transitions->IsFullTransitionArray());
-
- transition = transitions->Search(kData, *name1, attributes);
- CHECK_EQ(*name1, transitions->GetKey(transition));
- CHECK_EQ(*map1, transitions->GetTarget(transition));
-
- transition = transitions->Search(kData, *name2, attributes);
- CHECK_EQ(*name2, transitions->GetKey(transition));
- CHECK_EQ(*map2, transitions->GetTarget(transition));
+ CHECK(map0->raw_transitions()->IsSmi());
+
+ TransitionArray::Insert(map0, name1, map1, PROPERTY_TRANSITION);
+ CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
+ CHECK_EQ(*map1,
+ TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
+ CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
+ CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
+ CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
+
+ TransitionArray::Insert(map0, name2, map2, PROPERTY_TRANSITION);
+ CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
+
+ CHECK_EQ(*map1,
+ TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
+ CHECK_EQ(*map2,
+ TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
+ CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
+ for (int i = 0; i < 2; i++) {
+ Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
+ Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
+ CHECK((key == *name1 && target == *map1) ||
+ (key == *name2 && target == *map2));
+ }
- DCHECK(transitions->IsSortedNoDuplicates());
+ DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
}
@@ -160,9 +149,7 @@ TEST(TransitionArray_DifferentFieldNames) {
PropertyAttributes attributes = NONE;
Handle<Map> map0 = Map::Create(isolate, 0);
- CHECK(!map0->HasTransitionArray());
- Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0);
- CHECK(transitions->IsFullTransitionArray());
+ CHECK(map0->raw_transitions()->IsSmi());
for (int i = 0; i < PROPS_COUNT; i++) {
EmbeddedVector<char, 64> buffer;
@@ -175,17 +162,25 @@ TEST(TransitionArray_DifferentFieldNames) {
names[i] = name;
maps[i] = map;
- transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map);
+ TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
for (int i = 0; i < PROPS_COUNT; i++) {
- int transition = transitions->Search(kData, *names[i], attributes);
- CHECK_EQ(*names[i], transitions->GetKey(transition));
- CHECK_EQ(*maps[i], transitions->GetTarget(transition));
+ CHECK_EQ(*maps[i], TransitionArray::SearchTransition(
+ *map0, kData, *names[i], attributes));
+ }
+ for (int i = 0; i < PROPS_COUNT; i++) {
+ Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
+ Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
+ for (int j = 0; j < PROPS_COUNT; j++) {
+ if (*names[i] == key) {
+ CHECK_EQ(*maps[i], target);
+ break;
+ }
+ }
}
- DCHECK(transitions->IsSortedNoDuplicates());
+ DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
}
@@ -196,9 +191,7 @@ TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) {
Factory* factory = isolate->factory();
Handle<Map> map0 = Map::Create(isolate, 0);
- CHECK(!map0->HasTransitionArray());
- Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0);
- CHECK(transitions->IsFullTransitionArray());
+ CHECK(map0->raw_transitions()->IsSmi());
const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
STATIC_ASSERT(ATTRS_COUNT == 8);
@@ -215,20 +208,20 @@ TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) {
OMIT_TRANSITION).ToHandleChecked();
attr_maps[i] = map;
- transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map);
+ TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
// Ensure that transitions for |name| field are valid.
for (int i = 0; i < ATTRS_COUNT; i++) {
PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
-
- int transition = transitions->Search(kData, *name, attributes);
- CHECK_EQ(*name, transitions->GetKey(transition));
- CHECK_EQ(*attr_maps[i], transitions->GetTarget(transition));
+ CHECK_EQ(*attr_maps[i], TransitionArray::SearchTransition(
+ *map0, kData, *name, attributes));
+ // All transitions use the same key, so this check doesn't need to
+ // care about ordering.
+ CHECK_EQ(*name, TransitionArray::GetKey(map0->raw_transitions(), i));
}
- DCHECK(transitions->IsSortedNoDuplicates());
+ DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
}
@@ -243,9 +236,7 @@ TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
Handle<Map> maps[PROPS_COUNT];
Handle<Map> map0 = Map::Create(isolate, 0);
- CHECK(!map0->HasTransitionArray());
- Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0);
- CHECK(transitions->IsFullTransitionArray());
+ CHECK(map0->raw_transitions()->IsSmi());
// Some number of fields.
for (int i = 0; i < PROPS_COUNT; i++) {
@@ -259,8 +250,7 @@ TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
names[i] = name;
maps[i] = map;
- transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map);
+ TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
@@ -278,25 +268,36 @@ TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
OMIT_TRANSITION).ToHandleChecked();
attr_maps[i] = map;
- transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION);
- ConnectTransition(map0, transitions, map);
+ TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
// Ensure that transitions for |name| field are valid.
for (int i = 0; i < ATTRS_COUNT; i++) {
- PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
-
- int transition = transitions->Search(kData, *name, attributes);
- CHECK_EQ(*name, transitions->GetKey(transition));
- CHECK_EQ(*attr_maps[i], transitions->GetTarget(transition));
+ PropertyAttributes attr = static_cast<PropertyAttributes>(i);
+ CHECK_EQ(*attr_maps[i],
+ TransitionArray::SearchTransition(*map0, kData, *name, attr));
}
// Ensure that info about the other fields still valid.
- for (int i = 0; i < PROPS_COUNT; i++) {
- int transition = transitions->Search(kData, *names[i], NONE);
- CHECK_EQ(*names[i], transitions->GetKey(transition));
- CHECK_EQ(*maps[i], transitions->GetTarget(transition));
+ CHECK_EQ(PROPS_COUNT + ATTRS_COUNT,
+ TransitionArray::NumberOfTransitions(map0->raw_transitions()));
+ for (int i = 0; i < PROPS_COUNT + ATTRS_COUNT; i++) {
+ Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
+ Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
+ if (key == *name) {
+ // Attributes transition.
+ PropertyAttributes attributes =
+ target->GetLastDescriptorDetails().attributes();
+ CHECK_EQ(*attr_maps[static_cast<int>(attributes)], target);
+ } else {
+ for (int j = 0; j < PROPS_COUNT; j++) {
+ if (*names[j] == key) {
+ CHECK_EQ(*maps[j], target);
+ break;
+ }
+ }
+ }
}
- DCHECK(transitions->IsSortedNoDuplicates());
+ DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
}
diff --git a/deps/v8/test/cctest/test-typedarrays.cc b/deps/v8/test/cctest/test-typedarrays.cc
new file mode 100644
index 0000000000..d031048cae
--- /dev/null
+++ b/deps/v8/test/cctest/test-typedarrays.cc
@@ -0,0 +1,81 @@
+// Copyright 2015 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 <stdlib.h>
+
+#include "src/v8.h"
+#include "test/cctest/cctest.h"
+
+#include "src/api.h"
+#include "src/heap/heap.h"
+#include "src/objects.h"
+#include "src/v8.h"
+
+using namespace v8::internal;
+
+void TestArrayBufferViewContents(LocalContext& env, bool should_use_buffer) {
+ v8::Local<v8::Object> obj_a =
+ v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
+ CHECK(obj_a->IsArrayBufferView());
+ v8::Local<v8::ArrayBufferView> array_buffer_view =
+ v8::Local<v8::ArrayBufferView>::Cast(obj_a);
+ CHECK_EQ(array_buffer_view->HasBuffer(), should_use_buffer);
+ unsigned char contents[4] = {23, 23, 23, 23};
+ CHECK_EQ(sizeof(contents),
+ array_buffer_view->CopyContents(contents, sizeof(contents)));
+ CHECK_EQ(array_buffer_view->HasBuffer(), should_use_buffer);
+ for (size_t i = 0; i < sizeof(contents); ++i) {
+ CHECK_EQ(i, contents[i]);
+ }
+}
+
+
+TEST(CopyContentsTypedArray) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ CompileRun(
+ "var a = new Uint8Array(4);"
+ "a[0] = 0;"
+ "a[1] = 1;"
+ "a[2] = 2;"
+ "a[3] = 3;");
+ TestArrayBufferViewContents(env, false);
+}
+
+
+TEST(CopyContentsArray) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ CompileRun("var a = new Uint8Array([0, 1, 2, 3]);");
+ TestArrayBufferViewContents(env, true);
+}
+
+
+TEST(CopyContentsView) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ CompileRun(
+ "var b = new ArrayBuffer(6);"
+ "var c = new Uint8Array(b);"
+ "c[0] = -1;"
+ "c[1] = -1;"
+ "c[2] = 0;"
+ "c[3] = 1;"
+ "c[4] = 2;"
+ "c[5] = 3;"
+ "var a = new DataView(b, 2);");
+ TestArrayBufferViewContents(env, true);
+}
+
+
+TEST(AllocateNotExternal) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ void* memory = V8::ArrayBufferAllocator()->Allocate(1024);
+ v8::Local<v8::ArrayBuffer> buffer =
+ v8::ArrayBuffer::New(env->GetIsolate(), memory, 1024,
+ v8::ArrayBufferCreationMode::kInternalized);
+ CHECK(!buffer->IsExternal());
+ CHECK_EQ(memory, buffer->GetContents().Data());
+}
diff --git a/deps/v8/test/cctest/test-unboxed-doubles.cc b/deps/v8/test/cctest/test-unboxed-doubles.cc
index fdcac3af35..05c13e5776 100644
--- a/deps/v8/test/cctest/test-unboxed-doubles.cc
+++ b/deps/v8/test/cctest/test-unboxed-doubles.cc
@@ -18,7 +18,7 @@
using namespace v8::base;
using namespace v8::internal;
-#if (V8_DOUBLE_FIELDS_UNBOXING)
+#if V8_DOUBLE_FIELDS_UNBOXING
//
@@ -30,7 +30,7 @@ static void InitializeVerifiedMapDescriptors(
Map* map, DescriptorArray* descriptors,
LayoutDescriptor* layout_descriptor) {
map->InitializeDescriptors(descriptors, layout_descriptor);
- CHECK(layout_descriptor->IsConsistentWithMap(map));
+ CHECK(layout_descriptor->IsConsistentWithMap(map, true));
}
@@ -48,6 +48,12 @@ static Handle<String> MakeName(const char* str, int suffix) {
}
+Handle<JSObject> GetObject(const char* name) {
+ return v8::Utils::OpenHandle(
+ *v8::Handle<v8::Object>::Cast(CcTest::global()->Get(v8_str(name))));
+}
+
+
static double GetDoubleFieldValue(JSObject* obj, FieldIndex field_index) {
if (obj->IsUnboxedDoubleField(field_index)) {
return obj->RawFastDoublePropertyAt(field_index);
@@ -224,7 +230,7 @@ TEST(LayoutDescriptorBasicSlow) {
}
CHECK(layout_desc->IsSlowLayout());
CHECK(!layout_desc->IsFastPointerLayout());
- CHECK(layout_descriptor->IsConsistentWithMap(*map));
+ CHECK(layout_descriptor->IsConsistentWithMap(*map, true));
}
}
@@ -638,7 +644,7 @@ static Handle<LayoutDescriptor> TestLayoutDescriptorAppend(
map->InitializeDescriptors(*descriptors, *layout_descriptor);
}
Handle<LayoutDescriptor> layout_descriptor(map->layout_descriptor(), isolate);
- CHECK(layout_descriptor->IsConsistentWithMap(*map));
+ CHECK(layout_descriptor->IsConsistentWithMap(*map, true));
return layout_descriptor;
}
@@ -907,42 +913,126 @@ TEST(Regress436816) {
}
+TEST(DescriptorArrayTrimming) {
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ Isolate* isolate = CcTest::i_isolate();
+
+ const int kFieldCount = 128;
+ const int kSplitFieldIndex = 32;
+ const int kTrimmedLayoutDescriptorLength = 64;
+
+ Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<Map> map = Map::Create(isolate, kFieldCount);
+ for (int i = 0; i < kSplitFieldIndex; i++) {
+ map = Map::CopyWithField(map, MakeName("prop", i), any_type, NONE,
+ Representation::Smi(),
+ INSERT_TRANSITION).ToHandleChecked();
+ }
+ map = Map::CopyWithField(map, MakeName("dbl", kSplitFieldIndex), any_type,
+ NONE, Representation::Double(),
+ INSERT_TRANSITION).ToHandleChecked();
+ CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true));
+ CHECK(map->layout_descriptor()->IsSlowLayout());
+ CHECK(map->owns_descriptors());
+ CHECK_EQ(2, map->layout_descriptor()->length());
+
+ {
+ // Add transitions to double fields.
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<Map> tmp_map = map;
+ for (int i = kSplitFieldIndex + 1; i < kFieldCount; i++) {
+ tmp_map = Map::CopyWithField(tmp_map, MakeName("dbl", i), any_type, NONE,
+ Representation::Double(),
+ INSERT_TRANSITION).ToHandleChecked();
+ CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true));
+ }
+ // Check that descriptors are shared.
+ CHECK(tmp_map->owns_descriptors());
+ CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors());
+ CHECK_EQ(map->layout_descriptor(), tmp_map->layout_descriptor());
+ }
+ CHECK(map->layout_descriptor()->IsSlowLayout());
+ CHECK_EQ(4, map->layout_descriptor()->length());
+
+ // The unused tail of the layout descriptor is now "durty" because of sharing.
+ CHECK(map->layout_descriptor()->IsConsistentWithMap(*map));
+ for (int i = kSplitFieldIndex + 1; i < kTrimmedLayoutDescriptorLength; i++) {
+ CHECK(!map->layout_descriptor()->IsTagged(i));
+ }
+ CHECK_LT(map->NumberOfOwnDescriptors(),
+ map->instance_descriptors()->number_of_descriptors());
+
+ // Call GC that should trim both |map|'s descriptor array and layout
+ // descriptor.
+ CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
+
+ // The unused tail of the layout descriptor is now "clean" again.
+ CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true));
+ CHECK(map->owns_descriptors());
+ CHECK_EQ(map->NumberOfOwnDescriptors(),
+ map->instance_descriptors()->number_of_descriptors());
+ CHECK(map->layout_descriptor()->IsSlowLayout());
+ CHECK_EQ(2, map->layout_descriptor()->length());
+
+ {
+ // Add transitions to tagged fields.
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<Map> tmp_map = map;
+ for (int i = kSplitFieldIndex + 1; i < kFieldCount - 1; i++) {
+ tmp_map = Map::CopyWithField(tmp_map, MakeName("tagged", i), any_type,
+ NONE, Representation::Tagged(),
+ INSERT_TRANSITION).ToHandleChecked();
+ CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true));
+ }
+ tmp_map = Map::CopyWithField(tmp_map, MakeString("dbl"), any_type, NONE,
+ Representation::Double(),
+ INSERT_TRANSITION).ToHandleChecked();
+ CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true));
+ // Check that descriptors are shared.
+ CHECK(tmp_map->owns_descriptors());
+ CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors());
+ }
+ CHECK(map->layout_descriptor()->IsSlowLayout());
+}
+
+
TEST(DoScavenge) {
CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
- v8::HandleScope scope(CcTest::isolate());
- CompileRun(
- "function A() {"
- " this.x = 42.5;"
- " this.o = {};"
- "};"
- "var o = new A();");
+ // The plan: create |obj| with double field in new space, do scanvenge so
+ // that |obj| is moved to old space, construct a double value that looks like
+ // a pointer to "from space" pointer. Do scavenge one more time and ensure
+ // that it didn't crash or corrupt the double value stored in the object.
- Handle<String> obj_name = factory->InternalizeUtf8String("o");
+ Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<Map> map = Map::Create(isolate, 10);
+ map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
+ Representation::Double(),
+ INSERT_TRANSITION).ToHandleChecked();
- Handle<Object> obj_value =
- Object::GetProperty(isolate->global_object(), obj_name).ToHandleChecked();
- CHECK(obj_value->IsJSObject());
- Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
+ // Create object in new space.
+ Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED, false);
+
+ Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
+ obj->WriteToField(0, *heap_number);
{
// Ensure the object is properly set up.
- Map* map = obj->map();
- DescriptorArray* descriptors = map->instance_descriptors();
- CHECK(map->NumberOfOwnDescriptors() == 2);
- CHECK(descriptors->GetDetails(0).representation().IsDouble());
- CHECK(descriptors->GetDetails(1).representation().IsHeapObject());
- FieldIndex field_index = FieldIndex::ForDescriptor(map, 0);
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, 0);
CHECK(field_index.is_inobject() && field_index.is_double());
CHECK_EQ(FLAG_unbox_double_fields, map->IsUnboxedDoubleField(field_index));
CHECK_EQ(42.5, GetDoubleFieldValue(*obj, field_index));
}
CHECK(isolate->heap()->new_space()->Contains(*obj));
- // Trigger GCs so that the newly allocated object moves to old gen.
- CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
+ // Do scavenge so that |obj| is moved to survivor space.
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE);
// Create temp object in the new space.
Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED);
@@ -957,9 +1047,9 @@ TEST(DoScavenge) {
Handle<HeapNumber> boom_number = factory->NewHeapNumber(boom_value, MUTABLE);
obj->FastPropertyAtPut(field_index, *boom_number);
- // Now the object moves to old gen and it has a double field that looks like
+ // Now |obj| moves to old gen and it has a double field that looks like
// a pointer to a from semi-space.
- CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE, "boom");
CHECK(isolate->heap()->old_pointer_space()->Contains(*obj));
@@ -967,6 +1057,96 @@ TEST(DoScavenge) {
}
+TEST(DoScavengeWithIncrementalWriteBarrier) {
+ if (FLAG_never_compact || !FLAG_incremental_marking) return;
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ Heap* heap = CcTest::heap();
+ PagedSpace* old_pointer_space = heap->old_pointer_space();
+
+ // The plan: create |obj_value| in old space and ensure that it is allocated
+ // on evacuation candidate page, create |obj| with double and tagged fields
+ // in new space and write |obj_value| to tagged field of |obj|, do two
+ // scavenges to promote |obj| to old space, a GC in old space and ensure that
+ // the tagged value was properly updated after candidates evacuation.
+
+ Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<Map> map = Map::Create(isolate, 10);
+ map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
+ Representation::Double(),
+ INSERT_TRANSITION).ToHandleChecked();
+ map = Map::CopyWithField(map, MakeName("prop", 1), any_type, NONE,
+ Representation::Tagged(),
+ INSERT_TRANSITION).ToHandleChecked();
+
+ // Create |obj_value| in old space.
+ Handle<HeapObject> obj_value;
+ Page* ec_page;
+ {
+ AlwaysAllocateScope always_allocate(isolate);
+ // Make sure |obj_value| is placed on an old-space evacuation candidate.
+ SimulateFullSpace(old_pointer_space);
+ obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
+ ec_page = Page::FromAddress(obj_value->address());
+ }
+
+ // Create object in new space.
+ Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED, false);
+
+ Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
+ obj->WriteToField(0, *heap_number);
+ obj->WriteToField(1, *obj_value);
+
+ {
+ // Ensure the object is properly set up.
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, 0);
+ CHECK(field_index.is_inobject() && field_index.is_double());
+ CHECK_EQ(FLAG_unbox_double_fields, map->IsUnboxedDoubleField(field_index));
+ CHECK_EQ(42.5, GetDoubleFieldValue(*obj, field_index));
+
+ field_index = FieldIndex::ForDescriptor(*map, 1);
+ CHECK(field_index.is_inobject() && !field_index.is_double());
+ CHECK(!map->IsUnboxedDoubleField(field_index));
+ }
+ CHECK(isolate->heap()->new_space()->Contains(*obj));
+
+ // Heap is ready, force |ec_page| to become an evacuation candidate and
+ // simulate incremental marking.
+ FLAG_stress_compaction = true;
+ FLAG_manual_evacuation_candidates_selection = true;
+ ec_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
+ SimulateIncrementalMarking(heap);
+ // Disable stress compaction mode in order to let GC do scavenge.
+ FLAG_stress_compaction = false;
+
+ // Check that everything is ready for triggering incremental write barrier
+ // during scavenge (i.e. that |obj| is black and incremental marking is
+ // in compacting mode and |obj_value|'s page is an evacuation candidate).
+ IncrementalMarking* marking = heap->incremental_marking();
+ CHECK(marking->IsCompacting());
+ CHECK(Marking::IsBlack(Marking::MarkBitFrom(*obj)));
+ CHECK(MarkCompactCollector::IsOnEvacuationCandidate(*obj_value));
+
+ // Trigger GCs so that |obj| moves to old gen.
+ heap->CollectGarbage(i::NEW_SPACE); // in survivor space now
+ heap->CollectGarbage(i::NEW_SPACE); // in old gen now
+
+ CHECK(isolate->heap()->old_pointer_space()->Contains(*obj));
+ CHECK(isolate->heap()->old_pointer_space()->Contains(*obj_value));
+ CHECK(MarkCompactCollector::IsOnEvacuationCandidate(*obj_value));
+
+ heap->CollectGarbage(i::OLD_POINTER_SPACE, "boom");
+
+ // |obj_value| must be evacuated.
+ CHECK(!MarkCompactCollector::IsOnEvacuationCandidate(*obj_value));
+
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, 1);
+ CHECK_EQ(*obj_value, obj->RawFastPropertyAt(field_index));
+}
+
+
static void TestLayoutDescriptorHelper(Isolate* isolate,
int inobject_properties,
Handle<DescriptorArray> descriptors,
@@ -1131,7 +1311,7 @@ TEST(LayoutDescriptorSharing) {
}
Handle<LayoutDescriptor> split_layout_descriptor(
split_map->layout_descriptor(), isolate);
- CHECK(split_layout_descriptor->IsConsistentWithMap(*split_map));
+ CHECK(split_layout_descriptor->IsConsistentWithMap(*split_map, true));
CHECK(split_layout_descriptor->IsSlowLayout());
CHECK(split_map->owns_descriptors());
@@ -1144,7 +1324,7 @@ TEST(LayoutDescriptorSharing) {
// Layout descriptors should be shared with |split_map|.
CHECK(map1->owns_descriptors());
CHECK_EQ(*split_layout_descriptor, map1->layout_descriptor());
- CHECK(map1->layout_descriptor()->IsConsistentWithMap(*map1));
+ CHECK(map1->layout_descriptor()->IsConsistentWithMap(*map1, true));
Handle<Map> map2 = Map::CopyWithField(split_map, MakeString("bar"), any_type,
NONE, Representation::Tagged(),
@@ -1153,7 +1333,7 @@ TEST(LayoutDescriptorSharing) {
// Layout descriptors should not be shared with |split_map|.
CHECK(map2->owns_descriptors());
CHECK_NE(*split_layout_descriptor, map2->layout_descriptor());
- CHECK(map2->layout_descriptor()->IsConsistentWithMap(*map2));
+ CHECK(map2->layout_descriptor()->IsConsistentWithMap(*map2, true));
}
@@ -1163,28 +1343,23 @@ TEST(StoreBufferScanOnScavenge) {
Factory* factory = isolate->factory();
v8::HandleScope scope(CcTest::isolate());
- CompileRun(
- "function A() {"
- " this.x = 42.5;"
- " this.o = {};"
- "};"
- "var o = new A();");
+ Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<Map> map = Map::Create(isolate, 10);
+ map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
+ Representation::Double(),
+ INSERT_TRANSITION).ToHandleChecked();
- Handle<String> obj_name = factory->InternalizeUtf8String("o");
+ // Create object in new space.
+ Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED, false);
- Handle<Object> obj_value =
- Object::GetProperty(isolate->global_object(), obj_name).ToHandleChecked();
- CHECK(obj_value->IsJSObject());
- Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
+ Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
+ obj->WriteToField(0, *heap_number);
{
// Ensure the object is properly set up.
- Map* map = obj->map();
DescriptorArray* descriptors = map->instance_descriptors();
- CHECK(map->NumberOfOwnDescriptors() == 2);
CHECK(descriptors->GetDetails(0).representation().IsDouble());
- CHECK(descriptors->GetDetails(1).representation().IsHeapObject());
- FieldIndex field_index = FieldIndex::ForDescriptor(map, 0);
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, 0);
CHECK(field_index.is_inobject() && field_index.is_double());
CHECK_EQ(FLAG_unbox_double_fields, map->IsUnboxedDoubleField(field_index));
CHECK_EQ(42.5, GetDoubleFieldValue(*obj, field_index));
@@ -1305,4 +1480,211 @@ TEST(WriteBarriersInCopyJSObject) {
CHECK_EQ(boom_value, clone->RawFastDoublePropertyAt(index));
}
+
+static void TestWriteBarrier(Handle<Map> map, Handle<Map> new_map,
+ int tagged_descriptor, int double_descriptor,
+ bool check_tagged_value = true) {
+ FLAG_stress_compaction = true;
+ FLAG_manual_evacuation_candidates_selection = true;
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ Heap* heap = CcTest::heap();
+ PagedSpace* old_pointer_space = heap->old_pointer_space();
+
+ // The plan: create |obj| by |map| in old space, create |obj_value| in
+ // new space and ensure that write barrier is triggered when |obj_value| is
+ // written to property |tagged_descriptor| of |obj|.
+ // Then migrate object to |new_map| and set proper value for property
+ // |double_descriptor|. Call GC and ensure that it did not crash during
+ // store buffer entries updating.
+
+ Handle<JSObject> obj;
+ Handle<HeapObject> obj_value;
+ {
+ AlwaysAllocateScope always_allocate(isolate);
+ obj = factory->NewJSObjectFromMap(map, TENURED, false);
+ CHECK(old_pointer_space->Contains(*obj));
+
+ obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS);
+ }
+
+ CHECK(heap->InNewSpace(*obj_value));
+
+ {
+ FieldIndex index = FieldIndex::ForDescriptor(*map, tagged_descriptor);
+ const int n = 153;
+ for (int i = 0; i < n; i++) {
+ obj->FastPropertyAtPut(index, *obj_value);
+ }
+ }
+
+ // Migrate |obj| to |new_map| which should shift fields and put the
+ // |boom_value| to the slot that was earlier recorded by write barrier.
+ JSObject::MigrateToMap(obj, new_map);
+
+ Address fake_object = reinterpret_cast<Address>(*obj_value) + kPointerSize;
+ double boom_value = bit_cast<double>(fake_object);
+
+ FieldIndex double_field_index =
+ FieldIndex::ForDescriptor(*new_map, double_descriptor);
+ CHECK(obj->IsUnboxedDoubleField(double_field_index));
+ obj->RawFastDoublePropertyAtPut(double_field_index, boom_value);
+
+ // Trigger GC to evacuate all candidates.
+ CcTest::heap()->CollectGarbage(NEW_SPACE, "boom");
+
+ if (check_tagged_value) {
+ FieldIndex tagged_field_index =
+ FieldIndex::ForDescriptor(*new_map, tagged_descriptor);
+ CHECK_EQ(*obj_value, obj->RawFastPropertyAt(tagged_field_index));
+ }
+ CHECK_EQ(boom_value, obj->RawFastDoublePropertyAt(double_field_index));
+}
+
+
+static void TestIncrementalWriteBarrier(Handle<Map> map, Handle<Map> new_map,
+ int tagged_descriptor,
+ int double_descriptor,
+ bool check_tagged_value = true) {
+ if (FLAG_never_compact || !FLAG_incremental_marking) return;
+ FLAG_stress_compaction = true;
+ FLAG_manual_evacuation_candidates_selection = true;
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ Heap* heap = CcTest::heap();
+ PagedSpace* old_pointer_space = heap->old_pointer_space();
+
+ // The plan: create |obj| by |map| in old space, create |obj_value| in
+ // old space and ensure it end up in evacuation candidate page. Start
+ // incremental marking and ensure that incremental write barrier is triggered
+ // when |obj_value| is written to property |tagged_descriptor| of |obj|.
+ // Then migrate object to |new_map| and set proper value for property
+ // |double_descriptor|. Call GC and ensure that it did not crash during
+ // slots buffer entries updating.
+
+ Handle<JSObject> obj;
+ Handle<HeapObject> obj_value;
+ Page* ec_page;
+ {
+ AlwaysAllocateScope always_allocate(isolate);
+ obj = factory->NewJSObjectFromMap(map, TENURED, false);
+ CHECK(old_pointer_space->Contains(*obj));
+
+ // Make sure |obj_value| is placed on an old-space evacuation candidate.
+ SimulateFullSpace(old_pointer_space);
+ obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
+ ec_page = Page::FromAddress(obj_value->address());
+ CHECK_NE(ec_page, Page::FromAddress(obj->address()));
+ }
+
+ // Heap is ready, force |ec_page| to become an evacuation candidate and
+ // simulate incremental marking.
+ ec_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
+ SimulateIncrementalMarking(heap);
+
+ // Check that everything is ready for triggering incremental write barrier
+ // (i.e. that both |obj| and |obj_value| are black and the marking phase is
+ // still active and |obj_value|'s page is indeed an evacuation candidate).
+ IncrementalMarking* marking = heap->incremental_marking();
+ CHECK(marking->IsMarking());
+ CHECK(Marking::IsBlack(Marking::MarkBitFrom(*obj)));
+ CHECK(Marking::IsBlack(Marking::MarkBitFrom(*obj_value)));
+ CHECK(MarkCompactCollector::IsOnEvacuationCandidate(*obj_value));
+
+ // Trigger incremental write barrier, which should add a slot to |ec_page|'s
+ // slots buffer.
+ {
+ int slots_buffer_len = SlotsBuffer::SizeOfChain(ec_page->slots_buffer());
+ FieldIndex index = FieldIndex::ForDescriptor(*map, tagged_descriptor);
+ const int n = SlotsBuffer::kNumberOfElements + 10;
+ for (int i = 0; i < n; i++) {
+ obj->FastPropertyAtPut(index, *obj_value);
+ }
+ // Ensure that the slot was actually added to the |ec_page|'s slots buffer.
+ CHECK_EQ(slots_buffer_len + n,
+ SlotsBuffer::SizeOfChain(ec_page->slots_buffer()));
+ }
+
+ // Migrate |obj| to |new_map| which should shift fields and put the
+ // |boom_value| to the slot that was earlier recorded by incremental write
+ // barrier.
+ JSObject::MigrateToMap(obj, new_map);
+
+ double boom_value = bit_cast<double>(UINT64_C(0xbaad0176a37c28e1));
+
+ FieldIndex double_field_index =
+ FieldIndex::ForDescriptor(*new_map, double_descriptor);
+ CHECK(obj->IsUnboxedDoubleField(double_field_index));
+ obj->RawFastDoublePropertyAtPut(double_field_index, boom_value);
+
+ // Trigger GC to evacuate all candidates.
+ CcTest::heap()->CollectGarbage(OLD_POINTER_SPACE, "boom");
+
+ // Ensure that the values are still there and correct.
+ CHECK(!MarkCompactCollector::IsOnEvacuationCandidate(*obj_value));
+
+ if (check_tagged_value) {
+ FieldIndex tagged_field_index =
+ FieldIndex::ForDescriptor(*new_map, tagged_descriptor);
+ CHECK_EQ(*obj_value, obj->RawFastPropertyAt(tagged_field_index));
+ }
+ CHECK_EQ(boom_value, obj->RawFastDoublePropertyAt(double_field_index));
+}
+
+
+enum WriteBarrierKind { OLD_TO_OLD_WRITE_BARRIER, OLD_TO_NEW_WRITE_BARRIER };
+static void TestWriteBarrierObjectShiftFieldsRight(
+ WriteBarrierKind write_barrier_kind) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<HeapType> any_type = HeapType::Any(isolate);
+
+ CompileRun("function func() { return 1; }");
+
+ Handle<JSObject> func = GetObject("func");
+
+ Handle<Map> map = Map::Create(isolate, 10);
+ map = Map::CopyWithConstant(map, MakeName("prop", 0), func, NONE,
+ INSERT_TRANSITION).ToHandleChecked();
+ map = Map::CopyWithField(map, MakeName("prop", 1), any_type, NONE,
+ Representation::Double(),
+ INSERT_TRANSITION).ToHandleChecked();
+ map = Map::CopyWithField(map, MakeName("prop", 2), any_type, NONE,
+ Representation::Tagged(),
+ INSERT_TRANSITION).ToHandleChecked();
+
+ // Shift fields right by turning constant property to a field.
+ Handle<Map> new_map = Map::ReconfigureProperty(
+ map, 0, kData, NONE, Representation::Tagged(), any_type, FORCE_FIELD);
+
+ if (write_barrier_kind == OLD_TO_NEW_WRITE_BARRIER) {
+ TestWriteBarrier(map, new_map, 2, 1);
+ } else {
+ CHECK_EQ(OLD_TO_OLD_WRITE_BARRIER, write_barrier_kind);
+ TestIncrementalWriteBarrier(map, new_map, 2, 1);
+ }
+}
+
+
+// TODO(ishell): enable when this issue is fixed.
+DISABLED_TEST(WriteBarrierObjectShiftFieldsRight) {
+ TestWriteBarrierObjectShiftFieldsRight(OLD_TO_NEW_WRITE_BARRIER);
+}
+
+
+TEST(IncrementalWriteBarrierObjectShiftFieldsRight) {
+ TestWriteBarrierObjectShiftFieldsRight(OLD_TO_OLD_WRITE_BARRIER);
+}
+
+
+// TODO(ishell): add respective tests for property kind reconfiguring from
+// accessor field to double, once accessor fields are supported by
+// Map::ReconfigureProperty().
+
+
+// TODO(ishell): add respective tests for fast property removal case once
+// Map::ReconfigureProperty() supports that.
+
#endif
diff --git a/deps/v8/test/cctest/test-weakmaps.cc b/deps/v8/test/cctest/test-weakmaps.cc
index 04f41b9aee..dfe3f453c5 100644
--- a/deps/v8/test/cctest/test-weakmaps.cc
+++ b/deps/v8/test/cctest/test-weakmaps.cc
@@ -30,7 +30,6 @@
#include "src/v8.h"
#include "src/global-handles.h"
-#include "src/snapshot.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
@@ -184,7 +183,8 @@ TEST(Regress2060a) {
// Start second old-space page so that values land on evacuation candidate.
Page* first_page = heap->old_pointer_space()->anchor()->next_page();
- factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
+ int dummy_array_size = Page::kMaxRegularHeapObjectSize - 92 * KB;
+ factory->NewFixedArray(dummy_array_size / kPointerSize, TENURED);
// Fill up weak map with values on an evacuation candidate.
{
@@ -222,7 +222,8 @@ TEST(Regress2060b) {
// Start second old-space page so that keys land on evacuation candidate.
Page* first_page = heap->old_pointer_space()->anchor()->next_page();
- factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
+ int dummy_array_size = Page::kMaxRegularHeapObjectSize - 92 * KB;
+ factory->NewFixedArray(dummy_array_size / kPointerSize, TENURED);
// Fill up weak map with keys on an evacuation candidate.
Handle<JSObject> keys[32];
diff --git a/deps/v8/test/cctest/test-weaksets.cc b/deps/v8/test/cctest/test-weaksets.cc
index f08a99bcbf..1ab9f10989 100644
--- a/deps/v8/test/cctest/test-weaksets.cc
+++ b/deps/v8/test/cctest/test-weaksets.cc
@@ -30,7 +30,6 @@
#include "src/v8.h"
#include "src/global-handles.h"
-#include "src/snapshot.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
@@ -184,7 +183,8 @@ TEST(WeakSet_Regress2060a) {
// Start second old-space page so that values land on evacuation candidate.
Page* first_page = heap->old_pointer_space()->anchor()->next_page();
- factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
+ int dummy_array_size = Page::kMaxRegularHeapObjectSize - 92 * KB;
+ factory->NewFixedArray(dummy_array_size / kPointerSize, TENURED);
// Fill up weak set with values on an evacuation candidate.
{
@@ -222,7 +222,8 @@ TEST(WeakSet_Regress2060b) {
// Start second old-space page so that keys land on evacuation candidate.
Page* first_page = heap->old_pointer_space()->anchor()->next_page();
- factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
+ int dummy_array_size = Page::kMaxRegularHeapObjectSize - 92 * KB;
+ factory->NewFixedArray(dummy_array_size / kPointerSize, TENURED);
// Fill up weak set with keys on an evacuation candidate.
Handle<JSObject> keys[32];
diff --git a/deps/v8/test/cctest/test-weaktypedarrays.cc b/deps/v8/test/cctest/test-weaktypedarrays.cc
index d40b7e95a9..c1f59de45a 100644
--- a/deps/v8/test/cctest/test-weaktypedarrays.cc
+++ b/deps/v8/test/cctest/test-weaktypedarrays.cc
@@ -62,7 +62,20 @@ static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) {
}
-static int CountViews(JSArrayBuffer* array_buffer) {
+static int CountViewsInNewSpaceList(Heap* heap, JSArrayBuffer* array_buffer) {
+ int count = 0;
+ for (Object* o = heap->new_array_buffer_views_list(); !o->IsUndefined();) {
+ JSArrayBufferView* view = JSArrayBufferView::cast(o);
+ if (array_buffer == view->buffer()) {
+ count++;
+ }
+ o = view->weak_next();
+ }
+ return count;
+}
+
+
+static int CountViews(Heap* heap, JSArrayBuffer* array_buffer) {
int count = 0;
for (Object* o = array_buffer->weak_first_view();
!o->IsUndefined();
@@ -70,17 +83,27 @@ static int CountViews(JSArrayBuffer* array_buffer) {
count++;
}
- return count;
+ return count + CountViewsInNewSpaceList(heap, array_buffer);
}
-static bool HasViewInWeakList(JSArrayBuffer* array_buffer,
+
+static bool HasViewInNewSpaceList(Heap* heap, JSArrayBufferView* ta) {
+ for (Object* o = heap->new_array_buffer_views_list(); !o->IsUndefined();
+ o = JSArrayBufferView::cast(o)->weak_next()) {
+ if (ta == o) return true;
+ }
+ return false;
+}
+
+
+static bool HasViewInWeakList(Heap* heap, JSArrayBuffer* array_buffer,
JSArrayBufferView* ta) {
for (Object* o = array_buffer->weak_first_view();
!o->IsUndefined();
o = JSArrayBufferView::cast(o)->weak_next()) {
if (ta == o) return true;
}
- return false;
+ return HasViewInNewSpaceList(heap, ta);
}
@@ -200,18 +223,18 @@ void TestViewFromApi() {
Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1);
Handle<JSArrayBufferView> ita2 = v8::Utils::OpenHandle(*ta2);
- CHECK_EQ(2, CountViews(*iab));
- CHECK(HasViewInWeakList(*iab, *ita1));
- CHECK(HasViewInWeakList(*iab, *ita2));
+ CHECK_EQ(2, CountViews(isolate->heap(), *iab));
+ CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita1));
+ CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita2));
}
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(1, CountViews(*iab));
+ CHECK_EQ(1, CountViews(isolate->heap(), *iab));
Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1);
- CHECK(HasViewInWeakList(*iab, *ita1));
+ CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita1));
}
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(0, CountViews(*iab));
+ CHECK_EQ(0, CountViews(isolate->heap(), *iab));
}
@@ -299,10 +322,13 @@ static void TestTypedArrayFromScript(const char* constructor) {
v8::Handle<TypedArray>::Cast(CompileRun("ta3"));
CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
- CHECK_EQ(3, CountViews(*iab));
- CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta1)));
- CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta2)));
- CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta3)));
+ CHECK_EQ(3, CountViews(isolate->heap(), *iab));
+ CHECK(HasViewInWeakList(isolate->heap(), *iab,
+ *v8::Utils::OpenHandle(*ta1)));
+ CHECK(HasViewInWeakList(isolate->heap(), *iab,
+ *v8::Utils::OpenHandle(*ta2)));
+ CHECK(HasViewInWeakList(isolate->heap(), *iab,
+ *v8::Utils::OpenHandle(*ta3)));
}
i::SNPrintF(source, "ta%d = null;", i);
@@ -316,13 +342,14 @@ static void TestTypedArrayFromScript(const char* constructor) {
v8::Handle<v8::ArrayBuffer> ab =
v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab"));
Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
- CHECK_EQ(2, CountViews(*iab));
+ CHECK_EQ(2, CountViews(isolate->heap(), *iab));
for (int j = 1; j <= 3; j++) {
if (j == i) continue;
i::SNPrintF(source, "ta%d", j);
v8::Handle<TypedArray> ta =
v8::Handle<TypedArray>::Cast(CompileRun(source.start()));
- CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta)));
+ CHECK(HasViewInWeakList(isolate->heap(), *iab,
+ *v8::Utils::OpenHandle(*ta)));
}
}
@@ -336,7 +363,7 @@ static void TestTypedArrayFromScript(const char* constructor) {
v8::Handle<v8::ArrayBuffer> ab =
v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab"));
Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
- CHECK_EQ(0, CountViews(*iab));
+ CHECK_EQ(0, CountViews(isolate->heap(), *iab));
}
}
}
diff --git a/deps/v8/test/js-perf-test/JSTests.json b/deps/v8/test/js-perf-test/JSTests.json
index 0a99ad4d6a..a703642390 100644
--- a/deps/v8/test/js-perf-test/JSTests.json
+++ b/deps/v8/test/js-perf-test/JSTests.json
@@ -60,7 +60,6 @@
"path": ["Strings"],
"main": "run.js",
"resources": ["harmony-string.js"],
- "flags": ["--harmony-strings"],
"results_regexp": "^%s\\-Strings\\(Score\\): (.+)$",
"tests": [
{"name": "StringFunctions"}
@@ -71,7 +70,6 @@
"path": ["Templates"],
"main": "run.js",
"resources": ["templates.js"],
- "flags": ["--harmony-templates"],
"run_count": 5,
"units": "score",
"results_regexp": "^%s\\-Templates\\(Score\\): (.+)$",
diff --git a/deps/v8/test/mjsunit/harmony/disable-harmony-string.js b/deps/v8/test/message/class-constructor-accessor.js
index 0b88ae0be9..edc3c13169 100644
--- a/deps/v8/test/mjsunit/harmony/disable-harmony-string.js
+++ b/deps/v8/test/message/class-constructor-accessor.js
@@ -1,7 +1,10 @@
// 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.
+//
+// Flags: --harmony-classes
+'use strict';
-// Flags: --noharmony-strings
-
-assertEquals(undefined, String.prototype.includes);
+class C {
+ get constructor() {}
+}
diff --git a/deps/v8/test/message/class-constructor-accessor.out b/deps/v8/test/message/class-constructor-accessor.out
new file mode 100644
index 0000000000..8776f54db1
--- /dev/null
+++ b/deps/v8/test/message/class-constructor-accessor.out
@@ -0,0 +1,7 @@
+# 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.
+*%(basename)s:9: SyntaxError: Class constructor may not be an accessor
+ get constructor() {}
+ ^^^^^^^^^^^
+SyntaxError: Class constructor may not be an accessor
diff --git a/deps/v8/test/message/class-constructor-generator.js b/deps/v8/test/message/class-constructor-generator.js
new file mode 100644
index 0000000000..5d370f865e
--- /dev/null
+++ b/deps/v8/test/message/class-constructor-generator.js
@@ -0,0 +1,10 @@
+// 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.
+//
+// Flags: --harmony-classes
+'use strict';
+
+class C {
+ *constructor() {}
+}
diff --git a/deps/v8/test/message/class-constructor-generator.out b/deps/v8/test/message/class-constructor-generator.out
new file mode 100644
index 0000000000..5075e511cc
--- /dev/null
+++ b/deps/v8/test/message/class-constructor-generator.out
@@ -0,0 +1,7 @@
+# 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.
+*%(basename)s:9: SyntaxError: Class constructor may not be a generator
+ *constructor() {}
+ ^^^^^^^^^^^
+SyntaxError: Class constructor may not be a generator
diff --git a/deps/v8/test/message/export-duplicate-as.js b/deps/v8/test/message/export-duplicate-as.js
new file mode 100644
index 0000000000..49b52d4b17
--- /dev/null
+++ b/deps/v8/test/message/export-duplicate-as.js
@@ -0,0 +1,9 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+var a, b;
+export { a as c };
+export { a, b as c };
diff --git a/deps/v8/test/message/export-duplicate-as.out b/deps/v8/test/message/export-duplicate-as.out
new file mode 100644
index 0000000000..1726d9491a
--- /dev/null
+++ b/deps/v8/test/message/export-duplicate-as.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:9: SyntaxError: Duplicate export of 'c'
+export { a, b as c };
+ ^
+SyntaxError: Duplicate export of 'c'
diff --git a/deps/v8/test/message/export-duplicate-default.js b/deps/v8/test/message/export-duplicate-default.js
new file mode 100644
index 0000000000..72a54a45f4
--- /dev/null
+++ b/deps/v8/test/message/export-duplicate-default.js
@@ -0,0 +1,8 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+export default function f() {};
+export default class C {};
diff --git a/deps/v8/test/message/export-duplicate-default.out b/deps/v8/test/message/export-duplicate-default.out
new file mode 100644
index 0000000000..4c6b97a7a1
--- /dev/null
+++ b/deps/v8/test/message/export-duplicate-default.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:8: SyntaxError: Duplicate export of 'default'
+export default class C {};
+ ^^^^^^^
+SyntaxError: Duplicate export of 'default'
diff --git a/deps/v8/test/message/export-duplicate.js b/deps/v8/test/message/export-duplicate.js
new file mode 100644
index 0000000000..f45aefe13f
--- /dev/null
+++ b/deps/v8/test/message/export-duplicate.js
@@ -0,0 +1,9 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+var a, b;
+export { a };
+export { a, b };
diff --git a/deps/v8/test/message/export-duplicate.out b/deps/v8/test/message/export-duplicate.out
new file mode 100644
index 0000000000..e88779f580
--- /dev/null
+++ b/deps/v8/test/message/export-duplicate.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:9: SyntaxError: Duplicate export of 'a'
+export { a, b };
+ ^
+SyntaxError: Duplicate export of 'a'
diff --git a/deps/v8/test/message/import-as-eval.js b/deps/v8/test/message/import-as-eval.js
new file mode 100644
index 0000000000..66adc32cbe
--- /dev/null
+++ b/deps/v8/test/message/import-as-eval.js
@@ -0,0 +1,7 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+import { foo as eval } from "mod";
diff --git a/deps/v8/test/message/import-as-eval.out b/deps/v8/test/message/import-as-eval.out
new file mode 100644
index 0000000000..622f7fe9e1
--- /dev/null
+++ b/deps/v8/test/message/import-as-eval.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:7: SyntaxError: Unexpected eval or arguments in strict mode
+import { foo as eval } from "mod";
+ ^^^^
+SyntaxError: Unexpected eval or arguments in strict mode
diff --git a/deps/v8/test/message/import-as-redeclaration.js b/deps/v8/test/message/import-as-redeclaration.js
new file mode 100644
index 0000000000..43bf278d1b
--- /dev/null
+++ b/deps/v8/test/message/import-as-redeclaration.js
@@ -0,0 +1,8 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+let foo = 42;
+import { bar as foo } from "mod";
diff --git a/deps/v8/test/message/import-as-redeclaration.out b/deps/v8/test/message/import-as-redeclaration.out
new file mode 100644
index 0000000000..51c4c032dc
--- /dev/null
+++ b/deps/v8/test/message/import-as-redeclaration.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:8: SyntaxError: Identifier 'foo' has already been declared
+import { bar as foo } from "mod";
+ ^^^
+SyntaxError: Identifier 'foo' has already been declared
diff --git a/deps/v8/test/message/import-as-reserved-word.js b/deps/v8/test/message/import-as-reserved-word.js
new file mode 100644
index 0000000000..562699d45f
--- /dev/null
+++ b/deps/v8/test/message/import-as-reserved-word.js
@@ -0,0 +1,7 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+import { foo as import } from "mod";
diff --git a/deps/v8/test/message/import-as-reserved-word.out b/deps/v8/test/message/import-as-reserved-word.out
new file mode 100644
index 0000000000..1ee8d41c1a
--- /dev/null
+++ b/deps/v8/test/message/import-as-reserved-word.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:7: SyntaxError: Unexpected reserved word
+import { foo as import } from "mod";
+ ^^^^^^
+SyntaxError: Unexpected reserved word
diff --git a/deps/v8/test/message/import-eval.js b/deps/v8/test/message/import-eval.js
new file mode 100644
index 0000000000..8ab35baef6
--- /dev/null
+++ b/deps/v8/test/message/import-eval.js
@@ -0,0 +1,7 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+import { eval } from "mod";
diff --git a/deps/v8/test/message/import-eval.out b/deps/v8/test/message/import-eval.out
new file mode 100644
index 0000000000..148662a28c
--- /dev/null
+++ b/deps/v8/test/message/import-eval.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:7: SyntaxError: Unexpected eval or arguments in strict mode
+import { eval } from "mod";
+ ^^^^
+SyntaxError: Unexpected eval or arguments in strict mode
diff --git a/deps/v8/test/message/import-redeclaration.js b/deps/v8/test/message/import-redeclaration.js
new file mode 100644
index 0000000000..27b0cdccef
--- /dev/null
+++ b/deps/v8/test/message/import-redeclaration.js
@@ -0,0 +1,8 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+let foo = 42;
+import { foo } from "mod";
diff --git a/deps/v8/test/message/import-redeclaration.out b/deps/v8/test/message/import-redeclaration.out
new file mode 100644
index 0000000000..641948810f
--- /dev/null
+++ b/deps/v8/test/message/import-redeclaration.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:8: SyntaxError: Identifier 'foo' has already been declared
+import { foo } from "mod";
+ ^^^
+SyntaxError: Identifier 'foo' has already been declared
diff --git a/deps/v8/test/message/import-reserved-word.js b/deps/v8/test/message/import-reserved-word.js
new file mode 100644
index 0000000000..1fd7ba291e
--- /dev/null
+++ b/deps/v8/test/message/import-reserved-word.js
@@ -0,0 +1,7 @@
+// Copyright 2015 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.
+//
+// MODULE
+
+import { import } from "mod";
diff --git a/deps/v8/test/message/import-reserved-word.out b/deps/v8/test/message/import-reserved-word.out
new file mode 100644
index 0000000000..5b990e9e59
--- /dev/null
+++ b/deps/v8/test/message/import-reserved-word.out
@@ -0,0 +1,7 @@
+# Copyright 2015 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.
+*%(basename)s:7: SyntaxError: Unexpected reserved word
+import { import } from "mod";
+ ^^^^^^
+SyntaxError: Unexpected reserved word
diff --git a/deps/v8/test/message/testcfg.py b/deps/v8/test/message/testcfg.py
index 5d6ab84663..cfe22f15d7 100644
--- a/deps/v8/test/message/testcfg.py
+++ b/deps/v8/test/message/testcfg.py
@@ -36,6 +36,7 @@ from testrunner.objects import testcase
FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
INVALID_FLAGS = ["--enable-slow-asserts"]
+MODULE_PATTERN = re.compile(r"^// MODULE$", flags=re.MULTILINE)
class MessageTestSuite(testsuite.TestSuite):
@@ -63,6 +64,8 @@ class MessageTestSuite(testsuite.TestSuite):
for match in flags_match:
result += match.strip().split()
result += context.mode_flags
+ if MODULE_PATTERN.search(source):
+ result.append("--module")
result = [x for x in result if x not in INVALID_FLAGS]
result.append(os.path.join(self.root, testcase.path + ".js"))
return testcase.flags + result
diff --git a/deps/v8/test/message/unterminated-arg-list.js b/deps/v8/test/message/unterminated-arg-list.js
new file mode 100644
index 0000000000..b0fd1dd893
--- /dev/null
+++ b/deps/v8/test/message/unterminated-arg-list.js
@@ -0,0 +1,7 @@
+// Copyright 2015 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.
+
+$(document).ready(function() {
+$("html").load( "https://localhost" );
+}
diff --git a/deps/v8/test/message/unterminated-arg-list.out b/deps/v8/test/message/unterminated-arg-list.out
new file mode 100644
index 0000000000..5be2b3d90c
--- /dev/null
+++ b/deps/v8/test/message/unterminated-arg-list.out
@@ -0,0 +1,8 @@
+# Copyright 2015 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.
+
+*%(basename)s:7: SyntaxError: missing ) after argument list
+}
+^
+SyntaxError: missing ) after argument list
diff --git a/deps/v8/test/mjsunit/asm/construct-double.js b/deps/v8/test/mjsunit/asm/construct-double.js
new file mode 100644
index 0000000000..8bb5000082
--- /dev/null
+++ b/deps/v8/test/mjsunit/asm/construct-double.js
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+var stdlib = this;
+var foreign = {};
+var heap = new ArrayBuffer(64 * 1024);
+
+
+var m = (function(stdlib, foreign, heap) {
+ "use asm";
+ function cd1(i, j) {
+ i = i|0;
+ j = j|0;
+ return +%_ConstructDouble(i, j);
+ }
+ function cd2(i) {
+ i = i|0;
+ return +%_ConstructDouble(0, i);
+ }
+ return { cd1: cd1, cd2: cd2 };
+})(stdlib, foreign, heap);
+
+assertEquals(0.0, m.cd1(0, 0));
+assertEquals(%ConstructDouble(0, 1), m.cd2(1));
+for (var i = -2147483648; i < 2147483648; i += 3999773) {
+ assertEquals(%ConstructDouble(0, i), m.cd2(i));
+ for (var j = -2147483648; j < 2147483648; j += 3999773) {
+ assertEquals(%ConstructDouble(i, j), m.cd1(i, j));
+ }
+}
diff --git a/deps/v8/test/mjsunit/asm/double-hi.js b/deps/v8/test/mjsunit/asm/double-hi.js
new file mode 100644
index 0000000000..5a5f942f7b
--- /dev/null
+++ b/deps/v8/test/mjsunit/asm/double-hi.js
@@ -0,0 +1,40 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+var stdlib = this;
+var foreign = {};
+var heap = new ArrayBuffer(64 * 1024);
+
+
+var m = (function(stdlib, foreign, heap) {
+ "use asm";
+ function hi1(i) {
+ i = +i;
+ return %_DoubleHi(i)|0;
+ }
+ function hi2(i, j) {
+ i = +i;
+ j = +j;
+ return %_DoubleHi(i)+%_DoubleHi(j)|0;
+ }
+ return { hi1: hi1, hi2: hi2 };
+})(stdlib, foreign, heap);
+
+assertEquals(0, m.hi1(0.0));
+assertEquals(-2147483648, m.hi1(-0.0));
+assertEquals(2146435072, m.hi1(Infinity));
+assertEquals(-1048576, m.hi1(-Infinity));
+assertEquals(0, m.hi2(0.0, 0.0));
+assertEquals(-2147483648, m.hi2(0.0, -0.0));
+assertEquals(-2147483648, m.hi2(-0.0, 0.0));
+assertEquals(0, m.hi2(-0.0, -0.0));
+for (var i = -2147483648; i < 2147483648; i += 3999773) {
+ assertEquals(%_DoubleHi(i), m.hi1(i));
+ assertEquals(i, m.hi1(%ConstructDouble(i, 0)));
+ assertEquals(i, m.hi1(%ConstructDouble(i, i)));
+ assertEquals(i+i|0, m.hi2(%ConstructDouble(i, 0), %ConstructDouble(i, 0)));
+ assertEquals(i+i|0, m.hi2(%ConstructDouble(i, i), %ConstructDouble(i, i)));
+}
diff --git a/deps/v8/test/mjsunit/asm/double-lo.js b/deps/v8/test/mjsunit/asm/double-lo.js
new file mode 100644
index 0000000000..39d5b5268f
--- /dev/null
+++ b/deps/v8/test/mjsunit/asm/double-lo.js
@@ -0,0 +1,40 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+var stdlib = this;
+var foreign = {};
+var heap = new ArrayBuffer(64 * 1024);
+
+
+var m = (function(stdlib, foreign, heap) {
+ "use asm";
+ function lo1(i) {
+ i = +i;
+ return %_DoubleLo(i)|0;
+ }
+ function lo2(i, j) {
+ i = +i;
+ j = +j;
+ return %_DoubleLo(i)+%_DoubleLo(j)|0;
+ }
+ return { lo1: lo1, lo2: lo2 };
+})(stdlib, foreign, heap);
+
+assertEquals(0, m.lo1(0.0));
+assertEquals(0, m.lo1(-0.0));
+assertEquals(0, m.lo1(Infinity));
+assertEquals(0, m.lo1(-Infinity));
+assertEquals(0, m.lo2(0.0, 0.0));
+assertEquals(0, m.lo2(0.0, -0.0));
+assertEquals(0, m.lo2(-0.0, 0.0));
+assertEquals(0, m.lo2(-0.0, -0.0));
+for (var i = -2147483648; i < 2147483648; i += 3999773) {
+ assertEquals(%_DoubleLo(i), m.lo1(i));
+ assertEquals(i, m.lo1(%ConstructDouble(0, i)));
+ assertEquals(i, m.lo1(%ConstructDouble(i, i)));
+ assertEquals(i+i|0, m.lo2(%ConstructDouble(0, i), %ConstructDouble(0, i)));
+ assertEquals(i+i|0, m.lo2(%ConstructDouble(i, i), %ConstructDouble(i, i)));
+}
diff --git a/deps/v8/test/mjsunit/asm/if-cloning.js b/deps/v8/test/mjsunit/asm/if-cloning.js
new file mode 100644
index 0000000000..99d4edc67a
--- /dev/null
+++ b/deps/v8/test/mjsunit/asm/if-cloning.js
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+var if0 = (function Module() {
+ "use asm";
+ function if0(i, j) {
+ i = i|0;
+ j = j|0;
+ if (i == 0 ? j == 0 : 0) return 1;
+ return 0;
+ }
+ return {if0: if0};
+})().if0;
+assertEquals(1, if0(0, 0));
+assertEquals(0, if0(11, 0));
+assertEquals(0, if0(0, -1));
+assertEquals(0, if0(-1024, 1));
+
+
+var if1 = (function Module() {
+ "use asm";
+ function if1(i, j) {
+ i = i|0;
+ j = j|0;
+ if (i == 0 ? j == 0 : 1) return 0;
+ return 1;
+ }
+ return {if1: if1};
+})().if1;
+assertEquals(0, if1(0, 0));
+assertEquals(0, if1(11, 0));
+assertEquals(1, if1(0, -1));
+assertEquals(0, if1(-1024, 9));
diff --git a/deps/v8/test/mjsunit/asm/math-clz32.js b/deps/v8/test/mjsunit/asm/math-clz32.js
new file mode 100644
index 0000000000..004aa65b46
--- /dev/null
+++ b/deps/v8/test/mjsunit/asm/math-clz32.js
@@ -0,0 +1,31 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+var stdlib = { Math: Math };
+
+var f = (function Module(stdlib) {
+ "use asm";
+
+ var clz32 = stdlib.Math.clz32;
+
+ function f(a) {
+ a = a >>> 0;
+ return clz32(a)|0;
+ }
+
+ return f;
+})(stdlib);
+
+assertEquals(32, f(0));
+assertEquals(32, f(NaN));
+assertEquals(32, f(undefined));
+for (var i = 0; i < 32; ++i) {
+ assertEquals(i, f((-1) >>> i));
+}
+for (var i = -2147483648; i < 2147483648; i += 3999773) {
+ assertEquals(%MathClz32(i), f(i));
+ assertEquals(%_MathClz32(i), f(i));
+}
diff --git a/deps/v8/test/mjsunit/bugs/harmony/debug-blockscopes.js b/deps/v8/test/mjsunit/bugs/harmony/debug-blockscopes.js
index 9ef8efbc0c..52c94e7548 100644
--- a/deps/v8/test/mjsunit/bugs/harmony/debug-blockscopes.js
+++ b/deps/v8/test/mjsunit/bugs/harmony/debug-blockscopes.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --expose-debug-as debug --harmony-scoping
+// Flags: --expose-debug-as debug
// The functions used for testing backtraces. They are at the top to make the
// testing of source line/column easier.
diff --git a/deps/v8/test/mjsunit/compiler/deopt-tonumber-binop.js b/deps/v8/test/mjsunit/compiler/deopt-tonumber-binop.js
new file mode 100644
index 0000000000..c93ef9dfd5
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/deopt-tonumber-binop.js
@@ -0,0 +1,40 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+//
+var f = (function() {
+ "use asm";
+ function f(x, y) {
+ return x - y;
+ }
+ return f;
+})();
+
+var counter = 0;
+
+var deopt = { toString : function() {
+ %DeoptimizeFunction(f);
+ counter++;
+ return "2";
+} };
+
+var o = { toString : function() {
+ counter++;
+ return "1";
+} };
+
+counter = 0;
+assertEquals(1, f(deopt, o));
+assertEquals(2, counter);
+
+%OptimizeFunctionOnNextCall(f);
+counter = 0;
+assertEquals(-1, f(o, deopt));
+assertEquals(2, counter);
+
+%OptimizeFunctionOnNextCall(f);
+counter = 0;
+assertEquals(0, f(deopt, deopt));
+assertEquals(2, counter);
diff --git a/deps/v8/test/mjsunit/compiler/eager-deopt-simple.js b/deps/v8/test/mjsunit/compiler/eager-deopt-simple.js
new file mode 100644
index 0000000000..067400cfc6
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/eager-deopt-simple.js
@@ -0,0 +1,18 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+function g(a, b, c) {
+ return a + b + c;
+}
+
+function f() {
+ return g(1, (%_DeoptimizeNow(), 2), 3);
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+assertEquals(6, f());
diff --git a/deps/v8/test/mjsunit/compiler/osr-forin-nested.js b/deps/v8/test/mjsunit/compiler/osr-forin-nested.js
new file mode 100644
index 0000000000..ad55b30bd8
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/osr-forin-nested.js
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+// Flags: --turbo-osr --allow-natives-syntax
+
+function test(e, f, v) {
+ assertEquals(e, f(v));
+ assertEquals(e, f(v));
+ assertEquals(e, f(v));
+}
+
+function foo(t) {
+ for (var x in t) {
+ for (var i = 0; i < 2; i++) {
+ %OptimizeOsr();
+ }
+ }
+ return 5;
+}
+
+test(5, foo, {x:20});
+
+function bar(t) {
+ var sum = 0;
+ for (var x in t) {
+ for (var i = 0; i < 2; i++) {
+ %OptimizeOsr();
+ sum += t[x];
+ }
+ }
+ return sum;
+}
+
+test(62, bar, {x:20,y:11});
diff --git a/deps/v8/test/mjsunit/compiler/osr-infinite.js b/deps/v8/test/mjsunit/compiler/osr-infinite.js
new file mode 100644
index 0000000000..aa74c877d5
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/osr-infinite.js
@@ -0,0 +1,78 @@
+// Copyright 2015 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.
+
+// Flags: --use-osr --allow-natives-syntax --turbo-osr
+
+var global_counter = 0;
+
+function thrower() {
+ var x = global_counter++;
+ if (x == 5) %OptimizeOsr(thrower.caller);
+ if (x == 10) throw "terminate";
+}
+
+%NeverOptimizeFunction(thrower); // Don't want to inline the thrower.
+%NeverOptimizeFunction(test); // Don't want to inline the func into test.
+
+function test(func) {
+ for (var i = 0; i < 3; i++) {
+ global_counter = 0;
+ assertThrows(func);
+ }
+}
+
+function n1() {
+ while (true) thrower();
+}
+
+function n2() {
+ while (true) while (true) thrower();
+}
+
+function n3() {
+ while (true) while (true) while (true) thrower();
+}
+
+function n4() {
+ while (true) while (true) while (true) while (true) thrower();
+}
+
+function b1(a) {
+ while (true) {
+ thrower();
+ if (a) break
+ }
+}
+
+
+function b2(a) {
+ while (true) {
+ while (true) {
+ thrower();
+ if (a) break
+ }
+ }
+}
+
+
+function b3(a) {
+ while (true) {
+ while (true) {
+ while (true) {
+ thrower();
+ if (a) break
+ }
+ if (a) break
+ }
+ }
+}
+
+
+test(n1);
+test(n2);
+test(n3);
+test(n4);
+test(b1);
+test(b2);
+test(b3);
diff --git a/deps/v8/test/mjsunit/compiler/osr-labeled.js b/deps/v8/test/mjsunit/compiler/osr-labeled.js
new file mode 100644
index 0000000000..1a9709285e
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/osr-labeled.js
@@ -0,0 +1,47 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax --use-osr --turbo-osr
+
+function foo() {
+ var sum = 0;
+ A: for (var i = 0; i < 5; i++) {
+ B: for (var j = 0; j < 5; j++) {
+ C: for (var k = 0; k < 10; k++) {
+ if (k === 5) %OptimizeOsr();
+ if (k === 6) break B;
+ sum++;
+ }
+ }
+ }
+ return sum;
+}
+
+assertEquals(30, foo());
+assertEquals(30, foo());
+
+function bar(a) {
+ var sum = 0;
+ A: for (var i = 0; i < 5; i++) {
+ B: for (var j = 0; j < 5; j++) {
+ C: for (var k = 0; k < 10; k++) {
+ sum++;
+ %OptimizeOsr();
+ if (a === 1) break A;
+ if (a === 2) break B;
+ if (a === 3) break C;
+ }
+ }
+ }
+ return sum;
+}
+
+assertEquals(1, bar(1));
+assertEquals(1, bar(1));
+
+assertEquals(5, bar(2));
+assertEquals(5, bar(2));
+
+assertEquals(25, bar(3));
+assertEquals(25, bar(3));
diff --git a/deps/v8/test/mjsunit/compiler/osr-literals-adapted.js b/deps/v8/test/mjsunit/compiler/osr-literals-adapted.js
new file mode 100644
index 0000000000..950d8b0762
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/osr-literals-adapted.js
@@ -0,0 +1,56 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax --use-osr --turbo-osr
+
+function mod() {
+ function f0() {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f1(a) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f2(a,b) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f3(a,b,c) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f4(a,b,c,d) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function bar() {
+ assertEquals(3, f0().blah);
+ assertEquals(3, f1().blah);
+ assertEquals(3, f2().blah);
+ assertEquals(3, f3().blah);
+ assertEquals(3, f4().blah);
+ }
+ bar();
+}
+
+
+mod();
+mod();
+mod();
diff --git a/deps/v8/test/mjsunit/compiler/osr-literals.js b/deps/v8/test/mjsunit/compiler/osr-literals.js
new file mode 100644
index 0000000000..d9f68a0b37
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/osr-literals.js
@@ -0,0 +1,56 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax --use-osr --turbo-osr
+
+function mod() {
+ function f0() {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f1(a) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f2(a,b) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f3(a,b,c) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function f4(a,b,c,d) {
+ for (var i = 0; i < 3; i = i + 1 | 0) {
+ %OptimizeOsr();
+ }
+ return {blah: i};
+ }
+
+ function bar() {
+ assertEquals(3, f0().blah);
+ assertEquals(3, f1(1).blah);
+ assertEquals(3, f2(1,2).blah);
+ assertEquals(3, f3(1,2,3).blah);
+ assertEquals(3, f4(1,2,3,4).blah);
+ }
+ bar();
+}
+
+
+mod();
+mod();
+mod();
diff --git a/deps/v8/test/mjsunit/compiler/regress-463056.js b/deps/v8/test/mjsunit/compiler/regress-463056.js
new file mode 100644
index 0000000000..fb871618e4
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/regress-463056.js
@@ -0,0 +1,9 @@
+// Copyright 2015 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.
+
+function f() {
+ return ((0%0)&1) + (1>>>(0%0));
+}
+
+f();
diff --git a/deps/v8/test/mjsunit/compiler/regress-468727.js b/deps/v8/test/mjsunit/compiler/regress-468727.js
new file mode 100644
index 0000000000..a69efe5a56
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/regress-468727.js
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+// Flags: --noanalyze-environment-liveness
+
+function f() {
+ var __v_7 = -126 - __v_3;
+ var __v_17 = ((__v_15 & __v_14) != 4) | 16;
+ if (__v_17) {
+ var __v_11 = 1 << __v_7;
+ }
+ __v_12 >>= __v_3;
+}
+
+assertThrows(f);
diff --git a/deps/v8/test/mjsunit/compiler/regress-469089.js b/deps/v8/test/mjsunit/compiler/regress-469089.js
new file mode 100644
index 0000000000..6aff2b7203
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/regress-469089.js
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+// Flags: --expose-gc
+
+(function() {
+ var __v_6 = false;
+ function f(val, idx) {
+ if (idx === 1) {
+ gc();
+ __v_6 = (val === 0);
+ }
+ }
+ f(.1, 1);
+})();
diff --git a/deps/v8/test/mjsunit/compiler/truncating-store-deopt.js b/deps/v8/test/mjsunit/compiler/truncating-store-deopt.js
new file mode 100644
index 0000000000..a640caf583
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/truncating-store-deopt.js
@@ -0,0 +1,28 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+function g(a, b, c) {
+ return a + b + c;
+}
+
+var asm = (function Module(global, env, buffer) {
+ "use asm";
+
+ var i32 = new global.Int32Array(buffer);
+
+ // This is not valid asm.js, but we should still generate correct code.
+ function store(x) {
+ return g(1, i32[0] = x, 2);
+ }
+
+ return { store: store };
+})({
+ "Int32Array": Int32Array
+}, {}, new ArrayBuffer(64 * 1024));
+
+var o = { toString : function() { %DeoptimizeFunction(asm.store); return "1"; } }
+
+asm.store(o);
diff --git a/deps/v8/test/mjsunit/compiler/try-deopt.js b/deps/v8/test/mjsunit/compiler/try-deopt.js
new file mode 100644
index 0000000000..dc44e7326f
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/try-deopt.js
@@ -0,0 +1,56 @@
+// Copyright 2015 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.
+
+// TODO(mstarzinger): Add FLAG_turbo_exceptions once we want ClusterFuzz.
+// Flags: --allow-natives-syntax --turbo-deoptimization
+
+function DeoptFromTry(x) {
+ try {
+ %DeoptimizeFunction(DeoptFromTry);
+ throw x;
+ } catch (e) {
+ return e + 1;
+ }
+ return x + 2;
+}
+%OptimizeFunctionOnNextCall(DeoptFromTry);
+assertEquals(24, DeoptFromTry(23));
+
+
+function DeoptFromCatch(x) {
+ try {
+ throw x;
+ } catch (e) {
+ %DeoptimizeFunction(DeoptFromCatch);
+ return e + 1;
+ }
+ return x + 2;
+}
+%OptimizeFunctionOnNextCall(DeoptFromCatch);
+assertEquals(24, DeoptFromCatch(23));
+
+
+function DeoptFromFinally_Return(x) {
+ try {
+ throw x;
+ } finally {
+ %DeoptimizeFunction(DeoptFromFinally_Return);
+ return x + 1;
+ }
+ return x + 2;
+}
+%OptimizeFunctionOnNextCall(DeoptFromFinally_Return);
+assertEquals(24, DeoptFromFinally_Return(23));
+
+
+function DeoptFromFinally_ReThrow(x) {
+ try {
+ throw x;
+ } finally {
+ %DeoptimizeFunction(DeoptFromFinally_ReThrow);
+ }
+ return x + 2;
+}
+%OptimizeFunctionOnNextCall(DeoptFromFinally_ReThrow);
+assertThrows("DeoptFromFinally_ReThrow(new Error)", Error);
diff --git a/deps/v8/test/mjsunit/constant-folding-2.js b/deps/v8/test/mjsunit/constant-folding-2.js
index 73cf040f5a..3f82c2fa43 100644
--- a/deps/v8/test/mjsunit/constant-folding-2.js
+++ b/deps/v8/test/mjsunit/constant-folding-2.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --nodead-code-elimination --fold-constants --allow-natives-syntax
+// Flags: --nodead-code-elimination --fold-constants --allow-natives-syntax --nostress-opt
function test(f) {
f();
diff --git a/deps/v8/test/mjsunit/debug-allscopes-on-debugger.js b/deps/v8/test/mjsunit/debug-allscopes-on-debugger.js
new file mode 100644
index 0000000000..f0613b2926
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-allscopes-on-debugger.js
@@ -0,0 +1,58 @@
+// Copyright 2015 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.
+
+// Flags: --expose-debug-as debug
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
+ // Count number of expected breakpoints in this source file.
+ if (!break_count) {
+ var source_text = exec_state.frame(0).func().script().source();
+ expected_breaks = source_text.match(/\/\/\s*Break\s+\d+\./g).length;
+ print("Expected breaks: " + expected_breaks);
+ }
+ var frameMirror = exec_state.frame(0);
+
+ frameMirror.allScopes();
+ var source = frameMirror.sourceLineText();
+ print("paused at: " + source);
+ assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
+ "Unexpected pause at: " + source + "\n" +
+ "Expected: // Break " + break_count + ".");
+ ++break_count;
+
+ if (break_count !== expected_breaks) {
+ exec_state.prepareStep(Debug.StepAction.StepIn, 1);
+ print("Next step prepared");
+ }
+ }
+ } catch(e) {
+ exception = e;
+ print(e, e.stack);
+ }
+};
+
+Debug.setListener(listener);
+
+var sum = 0;
+(function (){
+ 'use strict';
+
+ debugger; // Break 0.
+ var i = 0; // Break 1.
+ i++; // Break 2.
+ i++; // Break 3.
+ return i; // Break 4.
+}()); // Break 5.
+
+assertNull(exception); // Break 6.
+assertEquals(expected_breaks, break_count);
+
+Debug.setListener(null);
diff --git a/deps/v8/test/mjsunit/debug-liveedit-check-stack.js b/deps/v8/test/mjsunit/debug-liveedit-check-stack.js
index 6948a70d6b..d843ca6a60 100644
--- a/deps/v8/test/mjsunit/debug-liveedit-check-stack.js
+++ b/deps/v8/test/mjsunit/debug-liveedit-check-stack.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --expose-debug-as debug
+// Flags: --expose-debug-as debug --allow-natives-syntax
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
@@ -87,13 +87,13 @@ function WrapInCatcher(f, holder) {
function WrapInNativeCall(f) {
return function() {
- return Debug.ExecuteInDebugContext(f, true);
+ return %Call(undefined, f);
};
}
function WrapInDebuggerCall(f) {
return function() {
- return Debug.ExecuteInDebugContext(f, false);
+ return %ExecuteInDebugContext(f);
};
}
diff --git a/deps/v8/test/mjsunit/debug-references.js b/deps/v8/test/mjsunit/debug-references.js
index bb339768b8..cb9f3701e2 100644
--- a/deps/v8/test/mjsunit/debug-references.js
+++ b/deps/v8/test/mjsunit/debug-references.js
@@ -26,6 +26,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug --turbo-deoptimization
+// Flags: --stack-trace-on-illegal
+
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
@@ -98,7 +100,8 @@ function listener(event, exec_state, event_data, data) {
listenerComplete = true;
}
} catch (e) {
- exception = e
+ exception = e;
+ print(e + "\n" + e.stack);
};
};
diff --git a/deps/v8/test/mjsunit/debug-scopes.js b/deps/v8/test/mjsunit/debug-scopes.js
index 7c08120e2a..78a70af26a 100644
--- a/deps/v8/test/mjsunit/debug-scopes.js
+++ b/deps/v8/test/mjsunit/debug-scopes.js
@@ -1049,6 +1049,30 @@ catch_block_7();
EndTest();
+BeginTest("Classes and methods 1");
+
+listener_delegate = function(exec_state) {
+ "use strict"
+ CheckScopeChain([debug.ScopeType.Local,
+ debug.ScopeType.Block,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({C1: class { m() { debugger; }} }, 1, exec_state);
+};
+
+(function() {
+ "use strict";
+ class C1 {
+ m() {
+ debugger;
+ }
+ }
+ new C1().m();
+})();
+
+EndTest();
+
+
assertEquals(begin_test_count, break_count,
'one or more tests did not enter the debugger');
assertEquals(begin_test_count, end_test_count,
diff --git a/deps/v8/test/mjsunit/debug-set-variable-value.js b/deps/v8/test/mjsunit/debug-set-variable-value.js
index 4667a71d6b..65434289d0 100644
--- a/deps/v8/test/mjsunit/debug-set-variable-value.js
+++ b/deps/v8/test/mjsunit/debug-set-variable-value.js
@@ -29,6 +29,7 @@
// Get the Debug object exposed from the debug context global object.
var Debug = debug.Debug;
+var DebugCommandProcessor = debug.DebugCommandProcessor;
// Accepts a function/closure 'fun' that must have a debugger statement inside.
// A variable 'variable_name' must be initialized before debugger statement
@@ -291,18 +292,18 @@ RunPauseTest(0, 5, 'p', 2012, 2012, (function Factory() {
// Test value description protocol JSON
-assertEquals(true, Debug.TestApi.CommandProcessorResolveValue({value: true}));
+assertEquals(true, DebugCommandProcessor.resolveValue_({value: true}));
-assertSame(null, Debug.TestApi.CommandProcessorResolveValue({type: "null"}));
+assertSame(null, DebugCommandProcessor.resolveValue_({type: "null"}));
assertSame(undefined,
- Debug.TestApi.CommandProcessorResolveValue({type: "undefined"}));
+ DebugCommandProcessor.resolveValue_({type: "undefined"}));
-assertSame("123", Debug.TestApi.CommandProcessorResolveValue(
+assertSame("123", DebugCommandProcessor.resolveValue_(
{type: "string", stringDescription: "123"}));
-assertSame(123, Debug.TestApi.CommandProcessorResolveValue(
+assertSame(123, DebugCommandProcessor.resolveValue_(
{type: "number", stringDescription: "123"}));
-assertSame(Number, Debug.TestApi.CommandProcessorResolveValue(
+assertSame(Number, DebugCommandProcessor.resolveValue_(
{handle: Debug.MakeMirror(Number).handle()}));
-assertSame(RunClosureTest, Debug.TestApi.CommandProcessorResolveValue(
+assertSame(RunClosureTest, DebugCommandProcessor.resolveValue_(
{handle: Debug.MakeMirror(RunClosureTest).handle()}));
diff --git a/deps/v8/test/mjsunit/debug-sourceinfo.js b/deps/v8/test/mjsunit/debug-sourceinfo.js
index ddf80dc51c..1dbe1b7a0a 100644
--- a/deps/v8/test/mjsunit/debug-sourceinfo.js
+++ b/deps/v8/test/mjsunit/debug-sourceinfo.js
@@ -1,352 +1,266 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --expose-debug-as debug
-// For this test to work this file MUST have CR LF line endings.
-function a() { b(); };
-function b() {
- c(true);
-};
- function c(x) {
- if (x) {
- return 1;
- } else {
- return 1;
- }
- };
-function d(x) {
- x = 1 ;
- x = 2 ;
- x = 3 ;
- x = 4 ;
- x = 5 ;
- x = 6 ;
- x = 7 ;
- x = 8 ;
- x = 9 ;
- x = 10;
- x = 11;
- x = 12;
- x = 13;
- x = 14;
- x = 15;
-}
-
-// Get the Debug object exposed from the debug context global object.
-Debug = debug.Debug
-
-// This is the number of comment lines above the first test function.
-var comment_lines = 29;
-
-// This is the last position in the entire file (note: this equals
-// file size of <debug-sourceinfo.js> - 1, since starting at 0).
-var last_position = 14312;
-// This is the last line of entire file (note: starting at 0).
-var last_line = 351;
-// This is the last column of last line (note: starting at 0 and +2, due
-// to trailing <CR><LF>).
-var last_column = 2;
-
-// This magic number is the length or the first line comment (actually number
-// of characters before 'function a(...'.
-var comment_line_length = 1726;
-var start_a = 10 + comment_line_length;
-var start_b = 37 + comment_line_length;
-var start_c = 71 + comment_line_length;
-var start_d = 163 + comment_line_length;
-
-// The position of the first line of d(), i.e. "x = 1 ;".
-var start_code_d = start_d + 7;
-// The line # of the first line of d() (note: starting at 0).
-var start_line_d = 41;
-var line_length_d = 11;
-var num_lines_d = 15;
-
-assertEquals(start_a, Debug.sourcePosition(a));
-assertEquals(start_b, Debug.sourcePosition(b));
-assertEquals(start_c, Debug.sourcePosition(c));
-assertEquals(start_d, Debug.sourcePosition(d));
-
-var script = Debug.findScript(a);
-assertTrue(script.data === Debug.findScript(b).data);
-assertTrue(script.data === Debug.findScript(c).data);
-assertTrue(script.data === Debug.findScript(d).data);
-assertTrue(script.source === Debug.findScript(b).source);
-assertTrue(script.source === Debug.findScript(c).source);
-assertTrue(script.source === Debug.findScript(d).source);
-
-// Test that when running through source positions the position, line and
-// column progresses as expected.
-var position;
-var line;
-var column;
-for (var p = 0; p < 100; p++) {
- var location = script.locationFromPosition(p);
- if (p > 0) {
- assertEquals(position + 1, location.position);
- if (line == location.line) {
- assertEquals(column + 1, location.column);
- } else {
- assertEquals(line + 1, location.line);
- assertEquals(0, location.column);
- }
- } else {
- assertEquals(0, location.position);
- assertEquals(0, location.line);
- assertEquals(0, location.column);
- }
-
- // Remember the location.
- position = location.position;
- line = location.line;
- column = location.column;
-}
-
-// Every line of d() is the same length. Verify we can loop through all
-// positions and find the right line # for each.
-var p = start_code_d;
-for (line = 0; line < num_lines_d; line++) {
- for (column = 0; column < line_length_d; column++) {
- var location = script.locationFromPosition(p);
- assertEquals(p, location.position);
- assertEquals(start_line_d + line, location.line);
- assertEquals(column, location.column);
- p++;
- }
-}
-
-// Test first position.
-assertEquals(0, script.locationFromPosition(0).position);
-assertEquals(0, script.locationFromPosition(0).line);
-assertEquals(0, script.locationFromPosition(0).column);
-
-// Test second position.
-assertEquals(1, script.locationFromPosition(1).position);
-assertEquals(0, script.locationFromPosition(1).line);
-assertEquals(1, script.locationFromPosition(1).column);
-
-// Test first position in function a().
-assertEquals(start_a, script.locationFromPosition(start_a).position);
-assertEquals(0, script.locationFromPosition(start_a).line - comment_lines);
-assertEquals(10, script.locationFromPosition(start_a).column);
-
-// Test first position in function b().
-assertEquals(start_b, script.locationFromPosition(start_b).position);
-assertEquals(1, script.locationFromPosition(start_b).line - comment_lines);
-assertEquals(13, script.locationFromPosition(start_b).column);
-
-// Test first position in function c().
-assertEquals(start_c, script.locationFromPosition(start_c).position);
-assertEquals(4, script.locationFromPosition(start_c).line - comment_lines);
-assertEquals(12, script.locationFromPosition(start_c).column);
-
-// Test first position in function d().
-assertEquals(start_d, script.locationFromPosition(start_d).position);
-assertEquals(11, script.locationFromPosition(start_d).line - comment_lines);
-assertEquals(10, script.locationFromPosition(start_d).column);
-
-// Test first line.
-assertEquals(0, script.locationFromLine().position);
-assertEquals(0, script.locationFromLine().line);
-assertEquals(0, script.locationFromLine().column);
-assertEquals(0, script.locationFromLine(0).position);
-assertEquals(0, script.locationFromLine(0).line);
-assertEquals(0, script.locationFromLine(0).column);
-
-// Test first line column 1.
-assertEquals(1, script.locationFromLine(0, 1).position);
-assertEquals(0, script.locationFromLine(0, 1).line);
-assertEquals(1, script.locationFromLine(0, 1).column);
-
-// Test first line offset 1.
-assertEquals(1, script.locationFromLine(0, 0, 1).position);
-assertEquals(0, script.locationFromLine(0, 0, 1).line);
-assertEquals(1, script.locationFromLine(0, 0, 1).column);
-
-// Test offset function a().
-assertEquals(start_a, script.locationFromLine(void 0, void 0, start_a).position);
-assertEquals(0, script.locationFromLine(void 0, void 0, start_a).line - comment_lines);
-assertEquals(10, script.locationFromLine(void 0, void 0, start_a).column);
-assertEquals(start_a, script.locationFromLine(0, void 0, start_a).position);
-assertEquals(0, script.locationFromLine(0, void 0, start_a).line - comment_lines);
-assertEquals(10, script.locationFromLine(0, void 0, start_a).column);
-assertEquals(start_a, script.locationFromLine(0, 0, start_a).position);
-assertEquals(0, script.locationFromLine(0, 0, start_a).line - comment_lines);
-assertEquals(10, script.locationFromLine(0, 0, start_a).column);
-
-// Test second line offset function a().
-assertEquals(start_a + 14, script.locationFromLine(1, 0, start_a).position);
-assertEquals(1, script.locationFromLine(1, 0, start_a).line - comment_lines);
-assertEquals(0, script.locationFromLine(1, 0, start_a).column);
-
-// Test second line column 2 offset function a().
-assertEquals(start_a + 14 + 2, script.locationFromLine(1, 2, start_a).position);
-assertEquals(1, script.locationFromLine(1, 2, start_a).line - comment_lines);
-assertEquals(2, script.locationFromLine(1, 2, start_a).column);
-
-// Test offset function b().
-assertEquals(start_b, script.locationFromLine(0, 0, start_b).position);
-assertEquals(1, script.locationFromLine(0, 0, start_b).line - comment_lines);
-assertEquals(13, script.locationFromLine(0, 0, start_b).column);
-
-// Test second line offset function b().
-assertEquals(start_b + 6, script.locationFromLine(1, 0, start_b).position);
-assertEquals(2, script.locationFromLine(1, 0, start_b).line - comment_lines);
-assertEquals(0, script.locationFromLine(1, 0, start_b).column);
-
-// Test second line column 11 offset function b().
-assertEquals(start_b + 6 + 11, script.locationFromLine(1, 11, start_b).position);
-assertEquals(2, script.locationFromLine(1, 11, start_b).line - comment_lines);
-assertEquals(11, script.locationFromLine(1, 11, start_b).column);
-
-// Test second line column 12 offset function b. Second line in b is 11 long
-// using column 12 wraps to next line.
-assertEquals(start_b + 6 + 12, script.locationFromLine(1, 12, start_b).position);
-assertEquals(3, script.locationFromLine(1, 12, start_b).line - comment_lines);
-assertEquals(0, script.locationFromLine(1, 12, start_b).column);
-
-// Test the Debug.findSourcePosition which wraps SourceManager.
-assertEquals(0 + start_a, Debug.findFunctionSourceLocation(a, 0, 0).position);
-assertEquals(0 + start_b, Debug.findFunctionSourceLocation(b, 0, 0).position);
-assertEquals(6 + start_b, Debug.findFunctionSourceLocation(b, 1, 0).position);
-assertEquals(8 + start_b, Debug.findFunctionSourceLocation(b, 1, 2).position);
-assertEquals(18 + start_b, Debug.findFunctionSourceLocation(b, 2, 0).position);
-assertEquals(0 + start_c, Debug.findFunctionSourceLocation(c, 0, 0).position);
-assertEquals(7 + start_c, Debug.findFunctionSourceLocation(c, 1, 0).position);
-assertEquals(21 + start_c, Debug.findFunctionSourceLocation(c, 2, 0).position);
-assertEquals(38 + start_c, Debug.findFunctionSourceLocation(c, 3, 0).position);
-assertEquals(52 + start_c, Debug.findFunctionSourceLocation(c, 4, 0).position);
-assertEquals(69 + start_c, Debug.findFunctionSourceLocation(c, 5, 0).position);
-assertEquals(76 + start_c, Debug.findFunctionSourceLocation(c, 6, 0).position);
-assertEquals(0 + start_d, Debug.findFunctionSourceLocation(d, 0, 0).position);
-assertEquals(7 + start_d, Debug.findFunctionSourceLocation(d, 1, 0).position);
-for (i = 1; i <= num_lines_d; i++) {
- assertEquals(7 + (i * line_length_d) + start_d, Debug.findFunctionSourceLocation(d, (i + 1), 0).position);
-}
-assertEquals(175 + start_d, Debug.findFunctionSourceLocation(d, 17, 0).position);
-
-// Make sure invalid inputs work properly.
-assertEquals(0, script.locationFromPosition(-1).line);
-assertEquals(null, script.locationFromPosition(last_position + 1));
-
-// Test last position.
-assertEquals(last_position, script.locationFromPosition(last_position).position);
-assertEquals(last_line, script.locationFromPosition(last_position).line);
-assertEquals(last_column, script.locationFromPosition(last_position).column);
-
-// Test source line and restriction. All the following tests start from line 1
-// column 2 in function b, which is the call to c.
-// c(true);
-// ^
-
-var location;
-
-location = script.locationFromLine(1, 0, start_b);
-assertEquals(' c(true);', location.sourceText());
-
-result = ['c', ' c', ' c(', ' c(', ' c(t']
-for (var i = 1; i <= 5; i++) {
- location = script.locationFromLine(1, 2, start_b);
- location.restrict(i);
- assertEquals(result[i - 1], location.sourceText());
-}
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(1, 0);
-assertEquals('c', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(2, 0);
-assertEquals('c(', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(2, 1);
-assertEquals(' c', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(2, 2);
-assertEquals(' c', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(2, 3);
-assertEquals(' c', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(3, 1);
-assertEquals(' c(', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(5, 0);
-assertEquals('c(tru', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(5, 2);
-assertEquals(' c(t', location.sourceText());
-
-location = script.locationFromLine(1, 2, start_b);
-location.restrict(5, 4);
-assertEquals(' c(t', location.sourceText());
-
-// All the following tests start from line 1 column 10 in function b, which is
-// the final character.
-// c(true);
-// ^
-
-location = script.locationFromLine(1, 10, start_b);
-location.restrict(5, 0);
-assertEquals('rue);', location.sourceText());
-
-location = script.locationFromLine(1, 10, start_b);
-location.restrict(7, 0);
-assertEquals('(true);', location.sourceText());
-
-// All the following tests start from line 1 column 0 in function b, which is
-// the first character.
-// c(true);
-//^
-
-location = script.locationFromLine(1, 0, start_b);
-location.restrict(5, 0);
-assertEquals(' c(t', location.sourceText());
-
-location = script.locationFromLine(1, 0, start_b);
-location.restrict(5, 4);
-assertEquals(' c(t', location.sourceText());
-
-location = script.locationFromLine(1, 0, start_b);
-location.restrict(7, 0);
-assertEquals(' c(tru', location.sourceText());
-
-location = script.locationFromLine(1, 0, start_b);
-location.restrict(7, 6);
-assertEquals(' c(tru', location.sourceText());
-
-// Test that script.sourceLine(line) works.
-for (line = 0; line < num_lines_d; line++) {
- var line_content_regexp = new RegExp(" x = " + (line + 1));
- assertTrue(line_content_regexp.test(script.sourceLine(start_line_d + line)));
-}
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --expose-debug-as debug
+function a() { b(); };
+function b() {
+ c(true);
+};
+ function c(x) {
+ if (x) {
+ return 1;
+ } else {
+ return 1;
+ }
+ };
+function d(x) {
+ x = 1 ;
+ x = 2 ;
+ x = 3 ;
+ x = 4 ;
+ x = 5 ;
+ x = 6 ;
+ x = 7 ;
+ x = 8 ;
+ x = 9 ;
+ x = 10;
+ x = 11;
+ x = 12;
+ x = 13;
+ x = 14;
+ x = 15;
+}
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// This is the number of comment lines above the first test function.
+var comment_lines = 28;
+
+// This is the last position in the entire file (note: this equals
+// file size of <debug-sourceinfo.js> - 1, since starting at 0).
+var last_position = 11337;
+// This is the last line of entire file (note: starting at 0).
+var last_line = 265;
+// This is the last column of last line (note: starting at 0 and +1, due
+// to trailing <LF>).
+var last_column = 1;
+
+// This magic number is the length or the first line comment (actually number
+// of characters before 'function a(...'.
+var comment_line_length = 1633;
+var start_a = 9 + comment_line_length;
+var start_b = 35 + comment_line_length;
+var start_c = 66 + comment_line_length;
+var start_d = 151 + comment_line_length;
+
+// The position of the first line of d(), i.e. "x = 1 ;".
+var start_code_d = start_d + 6;
+// The line # of the first line of d() (note: starting at 0).
+var start_line_d = 40;
+var line_length_d = 10;
+var num_lines_d = 15;
+
+assertEquals(start_a, Debug.sourcePosition(a));
+assertEquals(start_b, Debug.sourcePosition(b));
+assertEquals(start_c, Debug.sourcePosition(c));
+assertEquals(start_d, Debug.sourcePosition(d));
+
+var script = Debug.findScript(a);
+assertTrue(script.data === Debug.findScript(b).data);
+assertTrue(script.data === Debug.findScript(c).data);
+assertTrue(script.data === Debug.findScript(d).data);
+assertTrue(script.source === Debug.findScript(b).source);
+assertTrue(script.source === Debug.findScript(c).source);
+assertTrue(script.source === Debug.findScript(d).source);
+
+// Test that when running through source positions the position, line and
+// column progresses as expected.
+var position;
+var line;
+var column;
+for (var p = 0; p < 100; p++) {
+ var location = script.locationFromPosition(p);
+ if (p > 0) {
+ assertEquals(position + 1, location.position);
+ if (line == location.line) {
+ assertEquals(column + 1, location.column);
+ } else {
+ assertEquals(line + 1, location.line);
+ assertEquals(0, location.column);
+ }
+ } else {
+ assertEquals(0, location.position);
+ assertEquals(0, location.line);
+ assertEquals(0, location.column);
+ }
+
+ // Remember the location.
+ position = location.position;
+ line = location.line;
+ column = location.column;
+}
+
+// Every line of d() is the same length. Verify we can loop through all
+// positions and find the right line # for each.
+var p = start_code_d;
+for (line = 0; line < num_lines_d; line++) {
+ for (column = 0; column < line_length_d; column++) {
+ var location = script.locationFromPosition(p);
+ assertEquals(p, location.position);
+ assertEquals(start_line_d + line, location.line);
+ assertEquals(column, location.column);
+ p++;
+ }
+}
+
+// Test first position.
+assertEquals(0, script.locationFromPosition(0).position);
+assertEquals(0, script.locationFromPosition(0).line);
+assertEquals(0, script.locationFromPosition(0).column);
+
+// Test second position.
+assertEquals(1, script.locationFromPosition(1).position);
+assertEquals(0, script.locationFromPosition(1).line);
+assertEquals(1, script.locationFromPosition(1).column);
+
+// Test first position in function a().
+assertEquals(start_a, script.locationFromPosition(start_a).position);
+assertEquals(0, script.locationFromPosition(start_a).line - comment_lines);
+assertEquals(10, script.locationFromPosition(start_a).column);
+
+// Test first position in function b().
+assertEquals(start_b, script.locationFromPosition(start_b).position);
+assertEquals(1, script.locationFromPosition(start_b).line - comment_lines);
+assertEquals(13, script.locationFromPosition(start_b).column);
+
+// Test first position in function c().
+assertEquals(start_c, script.locationFromPosition(start_c).position);
+assertEquals(4, script.locationFromPosition(start_c).line - comment_lines);
+assertEquals(12, script.locationFromPosition(start_c).column);
+
+// Test first position in function d().
+assertEquals(start_d, script.locationFromPosition(start_d).position);
+assertEquals(11, script.locationFromPosition(start_d).line - comment_lines);
+assertEquals(10, script.locationFromPosition(start_d).column);
+
+// Test first line.
+assertEquals(0, script.locationFromLine().position);
+assertEquals(0, script.locationFromLine().line);
+assertEquals(0, script.locationFromLine().column);
+assertEquals(0, script.locationFromLine(0).position);
+assertEquals(0, script.locationFromLine(0).line);
+assertEquals(0, script.locationFromLine(0).column);
+
+// Test first line column 1.
+assertEquals(1, script.locationFromLine(0, 1).position);
+assertEquals(0, script.locationFromLine(0, 1).line);
+assertEquals(1, script.locationFromLine(0, 1).column);
+
+// Test first line offset 1.
+assertEquals(1, script.locationFromLine(0, 0, 1).position);
+assertEquals(0, script.locationFromLine(0, 0, 1).line);
+assertEquals(1, script.locationFromLine(0, 0, 1).column);
+
+// Test offset function a().
+assertEquals(start_a, script.locationFromLine(void 0, void 0, start_a).position);
+assertEquals(0, script.locationFromLine(void 0, void 0, start_a).line - comment_lines);
+assertEquals(10, script.locationFromLine(void 0, void 0, start_a).column);
+assertEquals(start_a, script.locationFromLine(0, void 0, start_a).position);
+assertEquals(0, script.locationFromLine(0, void 0, start_a).line - comment_lines);
+assertEquals(10, script.locationFromLine(0, void 0, start_a).column);
+assertEquals(start_a, script.locationFromLine(0, 0, start_a).position);
+assertEquals(0, script.locationFromLine(0, 0, start_a).line - comment_lines);
+assertEquals(10, script.locationFromLine(0, 0, start_a).column);
+
+// Test second line offset function a().
+assertEquals(start_a + 13, script.locationFromLine(1, 0, start_a).position);
+assertEquals(1, script.locationFromLine(1, 0, start_a).line - comment_lines);
+assertEquals(0, script.locationFromLine(1, 0, start_a).column);
+
+// Test second line column 2 offset function a().
+assertEquals(start_a + 13 + 1, script.locationFromLine(1, 1, start_a).position);
+assertEquals(1, script.locationFromLine(1, 2, start_a).line - comment_lines);
+assertEquals(2, script.locationFromLine(1, 2, start_a).column);
+
+// Test offset function b().
+assertEquals(start_b, script.locationFromLine(0, 0, start_b).position);
+assertEquals(1, script.locationFromLine(0, 0, start_b).line - comment_lines);
+assertEquals(13, script.locationFromLine(0, 0, start_b).column);
+
+// Test second line offset function b().
+assertEquals(start_b + 5, script.locationFromLine(1, 0, start_b).position);
+assertEquals(2, script.locationFromLine(1, 0, start_b).line - comment_lines);
+assertEquals(0, script.locationFromLine(1, 0, start_b).column);
+
+// Test second line column 10 offset function b().
+assertEquals(start_b + 5 + 10, script.locationFromLine(1, 10, start_b).position);
+assertEquals(2, script.locationFromLine(1, 10, start_b).line - comment_lines);
+assertEquals(10, script.locationFromLine(1, 10, start_b).column);
+
+// Test second line column 11 offset function b. Second line in b is 10 long
+// using column 11 wraps to next line.
+assertEquals(start_b + 5 + 11, script.locationFromLine(1, 11, start_b).position);
+assertEquals(3, script.locationFromLine(1, 11, start_b).line - comment_lines);
+assertEquals(0, script.locationFromLine(1, 11, start_b).column);
+
+// Test the Debug.findSourcePosition which wraps SourceManager.
+assertEquals(0 + start_a, Debug.findFunctionSourceLocation(a, 0, 0).position);
+assertEquals(0 + start_b, Debug.findFunctionSourceLocation(b, 0, 0).position);
+assertEquals(5 + start_b, Debug.findFunctionSourceLocation(b, 1, 0).position);
+assertEquals(7 + start_b, Debug.findFunctionSourceLocation(b, 1, 2).position);
+assertEquals(16 + start_b, Debug.findFunctionSourceLocation(b, 2, 0).position);
+assertEquals(0 + start_c, Debug.findFunctionSourceLocation(c, 0, 0).position);
+assertEquals(6 + start_c, Debug.findFunctionSourceLocation(c, 1, 0).position);
+assertEquals(19 + start_c, Debug.findFunctionSourceLocation(c, 2, 0).position);
+assertEquals(35 + start_c, Debug.findFunctionSourceLocation(c, 3, 0).position);
+assertEquals(48 + start_c, Debug.findFunctionSourceLocation(c, 4, 0).position);
+assertEquals(64 + start_c, Debug.findFunctionSourceLocation(c, 5, 0).position);
+assertEquals(70 + start_c, Debug.findFunctionSourceLocation(c, 6, 0).position);
+assertEquals(0 + start_d, Debug.findFunctionSourceLocation(d, 0, 0).position);
+assertEquals(6 + start_d, Debug.findFunctionSourceLocation(d, 1, 0).position);
+for (i = 1; i <= num_lines_d; i++) {
+ assertEquals(6 + (i * line_length_d) + start_d, Debug.findFunctionSourceLocation(d, (i + 1), 0).position);
+}
+assertEquals(158 + start_d, Debug.findFunctionSourceLocation(d, 17, 0).position);
+
+// Make sure invalid inputs work properly.
+assertEquals(0, script.locationFromPosition(-1).line);
+assertEquals(null, script.locationFromPosition(last_position + 1));
+
+// Test last position.
+assertEquals(last_position, script.locationFromPosition(last_position).position);
+assertEquals(last_line, script.locationFromPosition(last_position).line);
+assertEquals(last_column, script.locationFromPosition(last_position).column);
+
+// Test that script.sourceLine(line) works.
+var location;
+
+for (line = 0; line < num_lines_d; line++) {
+ var line_content_regexp = new RegExp(" x = " + (line + 1));
+ assertTrue(line_content_regexp.test(script.sourceLine(start_line_d + line)));
+}
diff --git a/deps/v8/test/mjsunit/debug-step-turbofan.js b/deps/v8/test/mjsunit/debug-step-turbofan.js
index c8c346b2c7..1710942e9a 100644
--- a/deps/v8/test/mjsunit/debug-step-turbofan.js
+++ b/deps/v8/test/mjsunit/debug-step-turbofan.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --turbo-filter=g --allow-natives-syntax
+// Flags: --expose-debug-as debug --turbo-filter=g --allow-natives-syntax
// Test that Debug::PrepareForBreakPoints can deal with turbofan code (g)
// on the stack. Without deoptimization support, we will not be able to
diff --git a/deps/v8/test/mjsunit/debug-stepframe-clearing.js b/deps/v8/test/mjsunit/debug-stepframe-clearing.js
new file mode 100644
index 0000000000..c440e78dd2
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-stepframe-clearing.js
@@ -0,0 +1,97 @@
+// Copyright 2015 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.
+
+// Flags: --expose-debug-as debug
+
+// This test ensures that IC learning doesn't interfere with stepping into
+// property accessor. f1()'s ICs are allowed to learn to a monomorphic state,
+// and the breakpoints flooding get() are allowed to expire, then we ensure
+// that we can step into get() again later (when k == 1).
+function f1() {
+ for (var k = 0; k < 2; k++) { // Break 1
+ var v10 = 0; // Line 2
+ for (var i = 0; i < 10; i++) { // Line 3
+ var v12 = o.slappy; // Line 4
+ var v13 = 3 // Line 5
+ } // Line 6
+ print("break here"); // Break 3
+ } // Line 8
+ print("exiting f1"); // Line 9 (dummy break)
+}
+
+function get() {
+ var g0 = 0; // Break 2
+ var g1 = 1;
+ return 3;
+}
+
+
+var o = {};
+Object.defineProperty(o, "slappy", { get : get });
+
+Debug = debug.Debug;
+var break_count = 0
+var exception = null;
+var bp_f1_line7;
+var bp_f1_line9;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ var line = exec_state.frame(0).sourceLineText();
+ print(line);
+ var match = line.match(/\/\/ Break (\d+)$/);
+ assertEquals(2, match.length);
+ var match_value = parseInt(match[1]);
+
+ if (break_count >= 0 && break_count < 2) {
+ // 0, 1: Keep stepping through frames.
+ assertEquals(break_count, match_value);
+ exec_state.prepareStep(Debug.StepAction.StepFrame, 1);
+ } else if (break_count === 2) {
+ // 2: let the code run to a breakpoint we set. The load should
+ // go monomorphic.
+ assertEquals(break_count, match_value);
+ } else if (break_count === 3) {
+ // 3: back to frame stepping. Does the monomorphic slappy accessor
+ // call still have the ability to break like before?
+ assertEquals(break_count, match_value);
+ Debug.clearBreakPoint(bp_f1_line7);
+ exec_state.prepareStep(Debug.StepAction.StepFrame, 1);
+ } else {
+ assertEquals(4, break_count);
+ assertEquals(2, match_value);
+ // Apparently we can still stop in the accessor even though we cleared
+ // breakpoints earlier and there was a monomorphic step.
+ // Allow running to completion now.
+ Debug.clearBreakPoint(bp_f1_line9);
+ }
+
+ break_count++;
+ } catch (e) {
+ print(e + e.stack);
+ exception = e;
+ }
+}
+
+for (var j = 1; j < 3; j++) {
+ break_count = 0;
+ Debug.setListener(listener);
+
+ // Breakpoints are added here rather than in the listener because their
+ // addition causes a full (clearing) gc that clears type feedback when we
+ // want to let it build up. Also, bp_f1_line9 is set simply because if we
+ // handled then deleted bp_f1_line7, then the debugger clears DebugInfo from
+ // f1 while we are still using it, again, resetting type feedback which is
+ // undesirable.
+ bp_f1_line7 = Debug.setBreakPoint(f1, 7);
+ bp_f1_line9 = Debug.setBreakPoint(f1, 9);
+
+ debugger; // Break 0
+ f1();
+ Debug.setListener(null);
+ assertTrue(break_count === 5);
+}
+
+assertNull(exception);
diff --git a/deps/v8/test/mjsunit/debug-stepin-foreach.js b/deps/v8/test/mjsunit/debug-stepin-foreach.js
index fa728e019c..c2702f794a 100644
--- a/deps/v8/test/mjsunit/debug-stepin-foreach.js
+++ b/deps/v8/test/mjsunit/debug-stepin-foreach.js
@@ -37,15 +37,17 @@ function listener(event, exec_state, event_data, data) {
};
Debug.setListener(listener);
+var bound_callback = callback.bind(null);
debugger; // Break 0.
[1,2].forEach(callback); // Break 1.
+[3,4].forEach(bound_callback); // Break 6.
function callback(x) {
- return x; // Break 2. // Break 4.
-} // Break 3. // Break 5.
+ return x; // Break 2. // Break 4. // Break 7. // Break 9.
+} // Break 3. // Break 5. // Break 8. // Break 10.
-assertNull(exception); // Break 6.
+assertNull(exception); // Break 11.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);
diff --git a/deps/v8/test/mjsunit/harmony/block-conflicts.js b/deps/v8/test/mjsunit/es6/block-conflicts.js
index d19a34a2c3..fdd581dd70 100644
--- a/deps/v8/test/mjsunit/harmony/block-conflicts.js
+++ b/deps/v8/test/mjsunit/es6/block-conflicts.js
@@ -1,8 +1,6 @@
// 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.
-//
-// Flags: --harmony-scoping
// Test for conflicting variable bindings.
diff --git a/deps/v8/test/mjsunit/es6/block-const-assign.js b/deps/v8/test/mjsunit/es6/block-const-assign.js
new file mode 100644
index 0000000000..f78faa689d
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/block-const-assign.js
@@ -0,0 +1,160 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-computed-property-names
+
+// Test that we throw early syntax errors in harmony mode
+// when using an immutable binding in an assigment or with
+// prefix/postfix decrement/increment operators.
+
+"use strict";
+
+const decls = [
+ // Const declaration.
+ function(use) { return "const c = 1; " + use + ";" }, TypeError,
+ function(use) { return "const x = 0, c = 1; " + use + ";" }, TypeError,
+ function(use) { return "const c = 1, x = (" + use + ");" }, TypeError,
+ function(use) { return use + "; const c = 1;" }, ReferenceError,
+ function(use) { return use + "; const x = 0, c = 1;" }, ReferenceError,
+ function(use) { return "const x = (" + use + "), c = 1;" }, ReferenceError,
+ function(use) { return "const c = (" + use + ");" }, ReferenceError,
+
+ // Function expression.
+ function(use) { return "(function c() { " + use + "; })();"; }, TypeError,
+ // TODO(rossberg): Once we have default parameters, test using 'c' there.
+
+ // Class expression.
+ function(use) {
+ return "new class c { constructor() { " + use + " } };";
+ }, TypeError,
+ function(use) {
+ return "(new class c { m() { " + use + " } }).m();";
+ }, TypeError,
+ function(use) {
+ return "(new class c { get a() { " + use + " } }).a;";
+ }, TypeError,
+ function(use) {
+ return "(new class c { set a(x) { " + use + " } }).a = 0;";
+ }, TypeError,
+ function(use) {
+ return "(class c { static m() { " + use + " } }).s();";
+ }, TypeError,
+ function(use) {
+ return "(class c extends (" + use + ") {});";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { [" + use + "]() {} });";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { get [" + use + "]() {} });";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { set [" + use + "](x) {} });";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { static [" + use + "]() {} });";
+ }, ReferenceError,
+
+ // For loop.
+ function(use) {
+ return "for (const c = 0; " + use + ";) {}"
+ }, TypeError,
+ function(use) {
+ return "for (const x = 0, c = 0; " + use + ";) {}"
+ }, TypeError,
+ function(use) {
+ return "for (const c = 0; ; " + use + ") {}"
+ }, TypeError,
+ function(use) {
+ return "for (const x = 0, c = 0; ; " + use + ") {}"
+ }, TypeError,
+ function(use) {
+ return "for (const c = 0; ;) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const x = 0, c = 0; ;) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const c in {a: 1}) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const c of [1]) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const x = (" + use + "), c = 0; ;) {}"
+ }, ReferenceError,
+ function(use) {
+ return "for (const c = (" + use + "); ;) {}"
+ }, ReferenceError,
+]
+
+let uses = [
+ 'c = 1',
+ 'c += 1',
+ '++c',
+ 'c--',
+];
+
+let declcontexts = [
+ function(decl) { return decl; },
+ function(decl) { return "eval(\'" + decl + "\')"; },
+ function(decl) { return "{ " + decl + " }"; },
+ function(decl) { return "(function() { " + decl + " })()"; },
+];
+
+let usecontexts = [
+ function(use) { return use; },
+ function(use) { return "eval(\"" + use + "\")"; },
+ function(use) { return "(function() { " + use + " })()"; },
+ function(use) { return "(function() { eval(\"" + use + "\"); })()"; },
+ function(use) { return "eval(\"(function() { " + use + "; })\")()"; },
+];
+
+function Test(program, error) {
+ program = "'use strict'; " + program;
+ try {
+ print(program, " // throw " + error.name);
+ eval(program);
+ } catch (e) {
+ assertInstanceof(e, error);
+ if (e === TypeError) {
+ assertTrue(e.toString().indexOf("Assignment to constant variable") >= 0);
+ }
+ return;
+ }
+ assertUnreachable();
+}
+
+for (var d = 0; d < decls.length; d += 2) {
+ for (var u = 0; u < uses.length; ++u) {
+ for (var o = 0; o < declcontexts.length; ++o) {
+ for (var i = 0; i < usecontexts.length; ++i) {
+ Test(declcontexts[o](decls[d](usecontexts[i](uses[u]))), decls[d + 1]);
+ }
+ }
+ }
+}
diff --git a/deps/v8/test/mjsunit/harmony/block-early-errors.js b/deps/v8/test/mjsunit/es6/block-early-errors.js
index 8ed5ea84ec..bf24942bb1 100644
--- a/deps/v8/test/mjsunit/harmony/block-early-errors.js
+++ b/deps/v8/test/mjsunit/es6/block-early-errors.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
function CheckException(e) {
var string = e.toString();
assertInstanceof(e, SyntaxError);
diff --git a/deps/v8/test/mjsunit/harmony/block-for.js b/deps/v8/test/mjsunit/es6/block-for.js
index 110f1ccf45..b91af0116c 100644
--- a/deps/v8/test/mjsunit/harmony/block-for.js
+++ b/deps/v8/test/mjsunit/es6/block-for.js
@@ -24,9 +24,6 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-scoping
-
"use strict";
function props(x) {
@@ -147,7 +144,7 @@ function closure_in_for_cond() {
assertEquals(k, a[k]());
}
}
-closure_in_for_next();
+closure_in_for_cond();
function closure_in_for_next() {
diff --git a/deps/v8/test/mjsunit/harmony/block-leave.js b/deps/v8/test/mjsunit/es6/block-leave.js
index 87d35b396d..338631b76e 100644
--- a/deps/v8/test/mjsunit/harmony/block-leave.js
+++ b/deps/v8/test/mjsunit/es6/block-leave.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
"use strict";
// We want to test the context chain shape. In each of the tests cases
diff --git a/deps/v8/test/mjsunit/harmony/block-let-crankshaft.js b/deps/v8/test/mjsunit/es6/block-let-crankshaft.js
index e8e00b200e..9cfdf847fc 100644
--- a/deps/v8/test/mjsunit/harmony/block-let-crankshaft.js
+++ b/deps/v8/test/mjsunit/es6/block-let-crankshaft.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping --allow-natives-syntax
+// Flags: --allow-natives-syntax
"use strict";
diff --git a/deps/v8/test/mjsunit/harmony/block-let-declaration.js b/deps/v8/test/mjsunit/es6/block-let-declaration.js
index 44a0049a44..5fbb12824b 100644
--- a/deps/v8/test/mjsunit/harmony/block-let-declaration.js
+++ b/deps/v8/test/mjsunit/es6/block-let-declaration.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
// Test let declarations in various settings.
"use strict";
@@ -70,8 +68,8 @@ TestLocalThrows("do let x; while (false)", SyntaxError);
TestLocalThrows("while (false) let x;", SyntaxError);
TestLocalThrows("label: let x;", SyntaxError);
TestLocalThrows("for (;false;) let x;", SyntaxError);
-TestLocalThrows("switch (true) { case true: let x; }", SyntaxError);
-TestLocalThrows("switch (true) { default: let x; }", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: let x; }");
+TestLocalDoesNotThrow("switch (true) { default: let x; }");
// Test const declarations with initialisers in statement positions.
TestLocalThrows("if (true) const x = 1;", SyntaxError);
@@ -80,8 +78,8 @@ TestLocalThrows("do const x = 1; while (false)", SyntaxError);
TestLocalThrows("while (false) const x = 1;", SyntaxError);
TestLocalThrows("label: const x = 1;", SyntaxError);
TestLocalThrows("for (;false;) const x = 1;", SyntaxError);
-TestLocalThrows("switch (true) { case true: const x = 1; }", SyntaxError);
-TestLocalThrows("switch (true) { default: const x = 1; }", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: const x = 1; }");
+TestLocalDoesNotThrow("switch (true) { default: const x = 1; }");
// Test const declarations without initialisers.
TestLocalThrows("const x;", SyntaxError);
@@ -149,11 +147,11 @@ function f() {
f();
// Test function declarations in statement position in strict mode.
-TestLocalThrows("function f() { if (true) function g() {}", SyntaxError);
-TestLocalThrows("function f() { if (true) {} else function g() {}", SyntaxError);
-TestLocalThrows("function f() { do function g() {} while (false)", SyntaxError);
-TestLocalThrows("function f() { while (false) function g() {}", SyntaxError);
-TestLocalThrows("function f() { label: function g() {}", SyntaxError);
-TestLocalThrows("function f() { for (;false;) function g() {}", SyntaxError);
-TestLocalThrows("function f() { switch (true) { case true: function g() {} }", SyntaxError);
-TestLocalThrows("function f() { switch (true) { default: function g() {} }", SyntaxError);
+TestLocalThrows("function f() { if (true) function g() {} }", SyntaxError);
+TestLocalThrows("function f() { if (true) {} else function g() {} }", SyntaxError);
+TestLocalThrows("function f() { do function g() {} while (false) }", SyntaxError);
+TestLocalThrows("function f() { while (false) function g() {} }", SyntaxError);
+TestLocalThrows("function f() { label: function g() {} }", SyntaxError);
+TestLocalThrows("function f() { for (;false;) function g() {} }", SyntaxError);
+TestLocalDoesNotThrow("function f() { switch (true) { case true: function g() {} } }");
+TestLocalDoesNotThrow("function f() { switch (true) { default: function g() {} } }");
diff --git a/deps/v8/test/mjsunit/harmony/block-let-semantics.js b/deps/v8/test/mjsunit/es6/block-let-semantics.js
index a37b795b0a..b0a826a007 100644
--- a/deps/v8/test/mjsunit/harmony/block-let-semantics.js
+++ b/deps/v8/test/mjsunit/es6/block-let-semantics.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
"use strict";
// Test temporal dead zone semantics of let bound variables in
diff --git a/deps/v8/test/mjsunit/harmony/block-non-strict-errors.js b/deps/v8/test/mjsunit/es6/block-non-strict-errors.js
index 11fa5c6a52..48cac21141 100644
--- a/deps/v8/test/mjsunit/harmony/block-non-strict-errors.js
+++ b/deps/v8/test/mjsunit/es6/block-non-strict-errors.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-scoping --harmony-classes
+// Flags: --harmony-classes
function CheckError(source) {
var exception = null;
diff --git a/deps/v8/test/mjsunit/harmony/block-scoping.js b/deps/v8/test/mjsunit/es6/block-scoping.js
index 001d9fbfd5..5f481b8bf2 100644
--- a/deps/v8/test/mjsunit/harmony/block-scoping.js
+++ b/deps/v8/test/mjsunit/es6/block-scoping.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --allow-natives-syntax --harmony-scoping
+// Flags: --allow-natives-syntax
// Test functionality of block scopes.
"use strict";
@@ -101,7 +101,8 @@ function f4(one) {
assertEquals(4, eval('z'));
assertEquals(5, eval('u'));
assertEquals(6, eval('v'));
- };
+ }
+ f();
}
}
f4(1);
@@ -122,7 +123,8 @@ function f5(one) {
assertEquals(4, z);
assertEquals(5, u);
assertEquals(6, v);
- };
+ }
+ f();
}
}
f5(1);
diff --git a/deps/v8/test/mjsunit/es6/collections.js b/deps/v8/test/mjsunit/es6/collections.js
index 92cd087839..888b6863c1 100644
--- a/deps/v8/test/mjsunit/es6/collections.js
+++ b/deps/v8/test/mjsunit/es6/collections.js
@@ -51,6 +51,21 @@ function TestValidMapCalls(m) {
assertDoesNotThrow(function () { m.set(new Object) });
assertDoesNotThrow(function () { m.has(new Object) });
assertDoesNotThrow(function () { m.delete(new Object) });
+ assertDoesNotThrow(function () { m.get(undefined) });
+ assertDoesNotThrow(function () { m.get(null) });
+ assertDoesNotThrow(function () { m.get(0) });
+ assertDoesNotThrow(function () { m.get('a-key') });
+ assertDoesNotThrow(function () { m.get(Symbol()) });
+ assertDoesNotThrow(function () { m.has(undefined) });
+ assertDoesNotThrow(function () { m.has(null) });
+ assertDoesNotThrow(function () { m.has(0) });
+ assertDoesNotThrow(function () { m.has('a-key') });
+ assertDoesNotThrow(function () { m.has(Symbol()) });
+ assertDoesNotThrow(function () { m.delete(undefined) });
+ assertDoesNotThrow(function () { m.delete(null) });
+ assertDoesNotThrow(function () { m.delete(0) });
+ assertDoesNotThrow(function () { m.delete('a-key') });
+ assertDoesNotThrow(function () { m.delete(Symbol()) });
}
TestValidMapCalls(new Map);
TestValidMapCalls(new WeakMap);
@@ -58,14 +73,11 @@ TestValidMapCalls(new WeakMap);
// Test invalid getter and setter calls for WeakMap only
function TestInvalidCalls(m) {
- assertThrows(function () { m.get(undefined) }, TypeError);
assertThrows(function () { m.set(undefined, 0) }, TypeError);
- assertThrows(function () { m.get(null) }, TypeError);
assertThrows(function () { m.set(null, 0) }, TypeError);
- assertThrows(function () { m.get(0) }, TypeError);
assertThrows(function () { m.set(0, 0) }, TypeError);
- assertThrows(function () { m.get('a-key') }, TypeError);
assertThrows(function () { m.set('a-key', 0) }, TypeError);
+ assertThrows(function () { m.set(Symbol(), 0) }, TypeError);
}
TestInvalidCalls(new WeakMap);
@@ -73,57 +85,79 @@ TestInvalidCalls(new WeakMap);
// Test expected behavior for Sets and WeakSets
function TestSet(set, key) {
assertFalse(set.has(key));
- assertSame(set, set.add(key));
- assertTrue(set.has(key));
- assertTrue(set.delete(key));
+ assertFalse(set.delete(key));
+ if (typeof key === 'object' && !(set instanceof WeakSet)) {
+ assertSame(set, set.add(key));
+ assertTrue(set.has(key));
+ assertTrue(set.delete(key));
+ }
assertFalse(set.has(key));
assertFalse(set.delete(key));
assertFalse(set.has(key));
}
function TestSetBehavior(set) {
+ // Fill
for (var i = 0; i < 20; i++) {
TestSet(set, new Object);
TestSet(set, i);
TestSet(set, i / 100);
TestSet(set, 'key-' + i);
+ TestSet(set, Symbol(i));
}
- var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ];
+
+ var keys = [
+ -0, +0, 1, 1/3, 10, +Infinity, -Infinity, NaN, true, false, null, undefined,
+ 'x', Symbol(), {}, function(){}
+ ];
for (var i = 0; i < keys.length; i++) {
TestSet(set, keys[i]);
}
}
TestSetBehavior(new Set);
-TestSet(new WeakSet, new Object);
+TestSetBehavior(new WeakSet);
// Test expected mapping behavior for Maps and WeakMaps
function TestMapping(map, key, value) {
- assertSame(map, map.set(key, value));
- assertSame(value, map.get(key));
+ assertFalse(map.has(key));
+ assertSame(undefined, map.get(key));
+ assertFalse(map.delete(key));
+ if (typeof key === 'object' && !(map instanceof WeakMap)) {
+ assertSame(map, map.set(key, value));
+ assertSame(value, map.get(key));
+ assertTrue(map.has(key));
+ assertTrue(map.delete(key));
+ }
+ assertFalse(map.has(key));
+ assertSame(undefined, map.get(key));
+ assertFalse(map.delete(key));
+ assertFalse(map.has(key));
+ assertSame(undefined, map.get(key));
}
-function TestMapBehavior1(m) {
+function TestMapBehavior(m) {
+ // Fill
TestMapping(m, new Object, 23);
TestMapping(m, new Object, 'the-value');
TestMapping(m, new Object, new Object);
-}
-TestMapBehavior1(new Map);
-TestMapBehavior1(new WeakMap);
-
-
-// Test expected mapping behavior for Maps only
-function TestMapBehavior2(m) {
for (var i = 0; i < 20; i++) {
TestMapping(m, i, new Object);
TestMapping(m, i / 10, new Object);
TestMapping(m, 'key-' + i, new Object);
+ TestMapping(m, Symbol(i), new Object);
}
- // -0 is handled in TestMinusZeroMap
- var keys = [ 0, +Infinity, -Infinity, true, false, null, undefined ];
+
+ var keys = [
+ -0, +0, 1, 1/3, 10, +Infinity, -Infinity, NaN, true, false, null, undefined,
+ 'x', Symbol(), {}, function(){}
+ ];
for (var i = 0; i < keys.length; i++) {
+ TestMapping(m, keys[i], 23);
+ TestMapping(m, keys[i], 'the-value');
TestMapping(m, keys[i], new Object);
}
}
-TestMapBehavior2(new Map);
+TestMapBehavior(new Map);
+TestMapBehavior(new WeakMap);
// Test expected querying behavior of Maps and WeakMaps
@@ -132,8 +166,6 @@ function TestQuery(m) {
var values = [ 'x', 0, +Infinity, -Infinity, true, false, null, undefined ];
for (var i = 0; i < values.length; i++) {
TestMapping(m, key, values[i]);
- assertTrue(m.has(key));
- assertFalse(m.has(new Object));
}
}
TestQuery(new Map);
@@ -144,7 +176,6 @@ TestQuery(new WeakMap);
function TestDelete(m) {
var key = new Object;
TestMapping(m, key, 'to-be-deleted');
- assertTrue(m.delete(key));
assertFalse(m.delete(key));
assertFalse(m.delete(new Object));
assertSame(m.get(key), undefined);
@@ -1190,8 +1221,9 @@ function TestSetConstructorIterableValue(ctor) {
// Strict mode is required to prevent implicit wrapping in the getter.
Object.defineProperty(Number.prototype, Symbol.iterator, {
get: function() {
- assertEquals('object', typeof this);
+ assertEquals('number', typeof this);
return function() {
+ assertEquals('number', typeof this);
return oneAndTwo.keys();
};
},
@@ -1380,8 +1412,9 @@ function TestMapConstructorIterableValue(ctor) {
// Strict mode is required to prevent implicit wrapping in the getter.
Object.defineProperty(Number.prototype, Symbol.iterator, {
get: function() {
- assertEquals('object', typeof this);
+ assertEquals('number', typeof this);
return function() {
+ assertEquals('number', typeof this);
return oneAndTwo.entries();
};
},
@@ -1406,3 +1439,38 @@ TestCollectionToString(Map);
TestCollectionToString(Set);
TestCollectionToString(WeakMap);
TestCollectionToString(WeakSet);
+
+
+function TestConstructorOrderOfAdderIterator(ctor, adderName) {
+ var iterable = new Map();
+ iterable.set({}, {});
+ iterable.set({}, {});
+ var iterableFunction = iterable[Symbol.iterator];
+ Object.defineProperty(iterable, Symbol.iterator, {
+ get: function() {
+ log += 'iterator';
+ return iterableFunction;
+ }
+ });
+
+ var log = '';
+ var adderFunction = ctor.prototype[adderName];
+
+ Object.defineProperty(ctor.prototype, adderName, {
+ get: function() {
+ log += adderName;
+ return adderFunction;
+ }
+ });
+
+ new ctor(iterable);
+ assertEquals(adderName + 'iterator', log);
+
+ Object.defineProperty(ctor.prototype, adderName, {
+ value: adderFunction
+ });
+}
+TestConstructorOrderOfAdderIterator(Map, 'set');
+TestConstructorOrderOfAdderIterator(Set, 'add');
+TestConstructorOrderOfAdderIterator(WeakMap, 'set');
+TestConstructorOrderOfAdderIterator(WeakSet, 'add');
diff --git a/deps/v8/test/mjsunit/harmony/debug-blockscopes.js b/deps/v8/test/mjsunit/es6/debug-blockscopes.js
index 8180377e6d..9f5d13e900 100644
--- a/deps/v8/test/mjsunit/harmony/debug-blockscopes.js
+++ b/deps/v8/test/mjsunit/es6/debug-blockscopes.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --expose-debug-as debug --harmony-scoping
+// Flags: --expose-debug-as debug
// The functions used for testing backtraces. They are at the top to make the
// testing of source line/column easier.
diff --git a/deps/v8/test/mjsunit/harmony/debug-evaluate-blockscopes.js b/deps/v8/test/mjsunit/es6/debug-evaluate-blockscopes.js
index d133cc07ce..e24ca78315 100644
--- a/deps/v8/test/mjsunit/harmony/debug-evaluate-blockscopes.js
+++ b/deps/v8/test/mjsunit/es6/debug-evaluate-blockscopes.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --expose-debug-as debug --harmony-scoping
+// Flags: --expose-debug-as debug
// Test debug evaluation for functions without local context, but with
// nested catch contexts.
diff --git a/deps/v8/test/mjsunit/harmony/debug-function-scopes.js b/deps/v8/test/mjsunit/es6/debug-function-scopes.js
index 1b380c2b84..699bd5343d 100644
--- a/deps/v8/test/mjsunit/harmony/debug-function-scopes.js
+++ b/deps/v8/test/mjsunit/es6/debug-function-scopes.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --expose-debug-as debug --harmony-scoping
+// Flags: --expose-debug-as debug
"use strict";
let top_level_let = 255;
diff --git a/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js
new file mode 100644
index 0000000000..918ae2a2e8
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js
@@ -0,0 +1,32 @@
+// 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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// Test debug events when we listen to all exceptions and
+// there is a catch handler for the exception thrown in a Promise.
+// We expect a normal Exception debug event to be triggered.
+
+Debug = debug.Debug;
+
+var events = [];
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status());
+}
+
+Debug.setListener(listener);
+
+var p = new Promise(function(resolve, reject) {
+ do {
+ try {
+ throw new Error("reject");
+ } finally {
+ break; // No rethrow.
+ }
+ } while (false);
+ resolve();
+});
+
+assertEquals([0 /* create */, 1 /* resolve */], events);
diff --git a/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js
new file mode 100644
index 0000000000..298201f103
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js
@@ -0,0 +1,29 @@
+// 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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// Test debug events when we listen to all exceptions and
+// there is a catch handler for the exception thrown in a Promise.
+// We expect a normal Exception debug event to be triggered.
+
+Debug = debug.Debug;
+
+var events = [];
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status());
+}
+
+Debug.setListener(listener);
+
+var p = new Promise(function (resolve, reject) {
+ try {
+ throw new Error("reject");
+ } catch (e) {
+ }
+ resolve();
+});
+
+assertEquals([0 /* create */, 1 /* resolve */], events);
diff --git a/deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js b/deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js
new file mode 100644
index 0000000000..b1e2ff98e1
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js
@@ -0,0 +1,30 @@
+// 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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// Test debug events when we listen to all exceptions and
+// there is a catch handler for the exception thrown in a Promise.
+// We expect a normal Exception debug event to be triggered.
+
+Debug = debug.Debug;
+
+var events = [];
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status());
+}
+
+Debug.setListener(listener);
+
+var p = new Promise(function(resolve, reject) {
+ try {
+ throw new Error("reject");
+ } finally {
+ // Implicit rethrow.
+ }
+ resolve();
+});
+
+assertEquals([0 /* create */, -1 /* rethrown */], events);
diff --git a/deps/v8/test/mjsunit/es6/debug-stepin-promises.js b/deps/v8/test/mjsunit/es6/debug-stepin-promises.js
new file mode 100644
index 0000000000..8548a2badd
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/debug-stepin-promises.js
@@ -0,0 +1,65 @@
+// Copyright 2015 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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --noalways-opt
+// Tests stepping into through Promises.
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+var expected_breaks = -1;
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
+ if (!break_count) {
+ // Count number of expected breakpoints in this source file.
+ var source_text = exec_state.frame(0).func().script().source();
+ expected_breaks = source_text.match(/\/\/\s*Break\s+\d+\./g).length;
+ print("Expected breaks: " + expected_breaks);
+ }
+ var source = exec_state.frame(0).sourceLineText();
+ print("paused at: " + source);
+ assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
+ "Unexpected pause at: " + source + "\n" +
+ "Expected: // Break " + break_count + ".");
+ ++break_count;
+ if (break_count !== expected_breaks) {
+ exec_state.prepareStep(Debug.StepAction.StepIn, 1);
+ }
+ }
+ } catch(e) {
+ exception = e;
+ print(e, e.stack);
+ }
+};
+
+Debug.setListener(listener);
+
+Promise.resolve(42)
+ .then(
+ function f0() {
+ debugger; // Break 0.
+ } // Break 1.
+ )
+ .then(callback)
+ .then(callback.bind(null))
+ .then(Object)
+ .then(callback.bind(null).bind(null))
+ .then(finalize)
+ .catch(function(err) {
+ %AbortJS("FAIL: " + err);
+ });
+
+function callback(x) {
+ return x; // Break 2. // Break 4. // Break 6.
+} // Break 3. // Break 5. // Break 7.
+
+function finalize() {
+ assertNull(exception); // Break 8.
+ assertEquals(expected_breaks, break_count);
+
+ Debug.setListener(null);
+}
diff --git a/deps/v8/test/mjsunit/harmony/empty-for.js b/deps/v8/test/mjsunit/es6/empty-for.js
index 02211260ff..dad892d328 100644
--- a/deps/v8/test/mjsunit/harmony/empty-for.js
+++ b/deps/v8/test/mjsunit/es6/empty-for.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
"use strict";
function for_const() {
diff --git a/deps/v8/test/mjsunit/es6/function-length-configurable.js b/deps/v8/test/mjsunit/es6/function-length-configurable.js
new file mode 100644
index 0000000000..e5b51aba20
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/function-length-configurable.js
@@ -0,0 +1,119 @@
+// Copyright 2015 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.
+
+function getStrictF() {
+ 'use strict';
+ return function f(x) {};
+}
+
+
+function getSloppyF() {
+ return function f(x) {};
+}
+
+
+function getStrictGenerator() {
+ 'use strict';
+ return function* f(x) {};
+}
+
+
+function getSloppyGenerator() {
+ return function* f(x) {};
+}
+
+
+function test(testFunction) {
+ testFunction(getStrictF());
+ testFunction(getSloppyF());
+ testFunction(getStrictGenerator());
+ testFunction(getSloppyGenerator());
+}
+
+
+function testDescriptor(f) {
+ var descr = Object.getOwnPropertyDescriptor(f, 'length');
+ assertTrue(descr.configurable);
+ assertFalse(descr.enumerable);
+ assertEquals(1, descr.value);
+ assertFalse(descr.writable);
+}
+test(testDescriptor);
+
+
+function testSet(f) {
+ f.length = 2;
+ assertEquals(1, f.length);
+}
+test(testSet);
+
+
+function testSetStrict(f) {
+ 'use strict';
+ assertThrows(function() {
+ f.length = 2;
+ }, TypeError);
+}
+test(testSetStrict);
+
+
+function testReconfigureAsDataProperty(f) {
+ Object.defineProperty(f, 'length', {
+ value: 2,
+ });
+ assertEquals(2, f.length);
+ Object.defineProperty(f, 'length', {
+ writable: true
+ });
+ f.length = 3;
+ assertEquals(3, f.length);
+
+ f.length = 42;
+ assertEquals(42, f.length);
+}
+test(testReconfigureAsDataProperty);
+
+
+function testReconfigureAsAccessorProperty(f) {
+ var length = 2;
+ Object.defineProperty(f, 'length', {
+ get: function() { return length; },
+ set: function(v) { length = v; }
+ });
+ assertEquals(2, f.length);
+ f.length = 3;
+ assertEquals(3, f.length);
+}
+test(testReconfigureAsAccessorProperty);
+
+
+(function testSetOnInstance() {
+ // This needs to come before testDelete below
+ assertTrue(Function.prototype.hasOwnProperty('length'));
+
+ function f() {}
+ delete f.length;
+ assertEquals(0, f.length);
+
+ f.length = 42;
+ assertEquals(0, f.length); // non writable prototype property.
+ assertFalse(f.hasOwnProperty('length'));
+
+ Object.defineProperty(Function.prototype, 'length', {writable: true});
+
+ f.length = 123;
+ assertTrue(f.hasOwnProperty('length'));
+ assertEquals(123, f.length);
+})();
+
+
+(function testDelete() {
+ function f(x) {}
+ assertTrue(delete f.length);
+ assertFalse(f.hasOwnProperty('length'));
+ assertEquals(0, f.length);
+
+ assertTrue(delete Function.prototype.length);
+ assertEquals(undefined, f.length);
+})();
diff --git a/deps/v8/test/mjsunit/es6/function-name-configurable.js b/deps/v8/test/mjsunit/es6/function-name-configurable.js
new file mode 100644
index 0000000000..f0ff406da8
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/function-name-configurable.js
@@ -0,0 +1,115 @@
+// Copyright 2015 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.
+
+function getStrictF() {
+ 'use strict';
+ return function f() {};
+}
+
+
+function getSloppyF() {
+ return function f() {};
+}
+
+
+function test(testFunction) {
+ testFunction(getStrictF());
+ testFunction(getSloppyF());
+}
+
+
+function testDescriptor(f) {
+ var descr = Object.getOwnPropertyDescriptor(f, 'name');
+ assertTrue(descr.configurable);
+ assertFalse(descr.enumerable);
+ assertEquals('f', descr.value);
+ assertFalse(descr.writable);
+}
+test(testDescriptor);
+
+
+function testSet(f) {
+ f.name = 'g';
+ assertEquals('f', f.name);
+}
+test(testSet);
+
+
+function testSetStrict(f) {
+ 'use strict';
+ assertThrows(function() {
+ f.name = 'g';
+ }, TypeError);
+}
+test(testSetStrict);
+
+
+function testReconfigureAsDataProperty(f) {
+ Object.defineProperty(f, 'name', {
+ value: 'g',
+ });
+ assertEquals('g', f.name);
+ Object.defineProperty(f, 'name', {
+ writable: true
+ });
+ f.name = 'h';
+ assertEquals('h', f.name);
+
+ f.name = 42;
+ assertEquals(42, f.name);
+}
+test(testReconfigureAsDataProperty);
+
+
+function testReconfigureAsAccessorProperty(f) {
+ var name = 'g';
+ Object.defineProperty(f, 'name', {
+ get: function() { return name; },
+ set: function(v) { name = v; }
+ });
+ assertEquals('g', f.name);
+ f.name = 'h';
+ assertEquals('h', f.name);
+}
+test(testReconfigureAsAccessorProperty);
+
+
+function testFunctionToString(f) {
+ Object.defineProperty(f, 'name', {
+ value: {toString: function() { assertUnreachable(); }},
+ });
+ assertEquals('function f() {}', f.toString());
+}
+test(testFunctionToString);
+
+
+(function testSetOnInstance() {
+ // This needs to come before testDelete below
+ assertTrue(Function.prototype.hasOwnProperty('name'));
+
+ function f() {}
+ delete f.name;
+ assertEquals('Empty', f.name);
+
+ f.name = 42;
+ assertEquals('Empty', f.name); // non writable prototype property.
+ assertFalse(f.hasOwnProperty('name'));
+
+ Object.defineProperty(Function.prototype, 'name', {writable: true});
+
+ f.name = 123;
+ assertTrue(f.hasOwnProperty('name'));
+ assertEquals(123, f.name);
+})();
+
+
+(function testDelete() {
+ function f() {}
+ assertTrue(delete f.name);
+ assertFalse(f.hasOwnProperty('name'));
+ assertEquals('Empty', f.name);
+
+ assertTrue(delete Function.prototype.name);
+ assertEquals(undefined, f.name);
+})();
diff --git a/deps/v8/test/mjsunit/es6/generators-debug-liveedit.js b/deps/v8/test/mjsunit/es6/generators-debug-liveedit.js
index 6f0c443afc..987a42c41c 100644
--- a/deps/v8/test/mjsunit/es6/generators-debug-liveedit.js
+++ b/deps/v8/test/mjsunit/es6/generators-debug-liveedit.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --expose-debug-as debug
+// Flags: --expose-debug-as debug --allow-natives-syntax
var Debug = debug.Debug;
var LiveEdit = Debug.LiveEdit;
@@ -54,7 +54,7 @@ function patch(fun, from, to) {
print("Change log: " + JSON.stringify(log) + "\n");
}
}
- Debug.ExecuteInDebugContext(debug, false);
+ %ExecuteInDebugContext(debug);
}
// Try to edit a MakeGenerator while it's running, then again while it's
diff --git a/deps/v8/test/mjsunit/es6/generators-objects.js b/deps/v8/test/mjsunit/es6/generators-objects.js
index 8039ca8bb1..5112443ea0 100644
--- a/deps/v8/test/mjsunit/es6/generators-objects.js
+++ b/deps/v8/test/mjsunit/es6/generators-objects.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping --allow-natives-syntax --harmony-tostring
+// Flags: --allow-natives-syntax --harmony-tostring
// Test instantations of generators.
diff --git a/deps/v8/test/mjsunit/es6/indexed-integer-exotics.js b/deps/v8/test/mjsunit/es6/indexed-integer-exotics.js
new file mode 100644
index 0000000000..7aefd78c4f
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/indexed-integer-exotics.js
@@ -0,0 +1,63 @@
+// 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.
+
+// Flags: --allow-natives-syntax
+
+Object.prototype["10"] = "unreachable";
+Object.prototype["7"] = "unreachable";
+Object.prototype["-1"] = "unreachable";
+Object.prototype["-0"] = "unreachable";
+Object.prototype["4294967296"] = "unreachable";
+
+var array = new Int32Array(10);
+
+function check() {
+ for (var i = 0; i < 4; i++) {
+ assertEquals(undefined, array["-1"]);
+ assertEquals(undefined, array["-0"]);
+ assertEquals(undefined, array["10"]);
+ assertEquals(undefined, array["4294967296"]);
+ }
+ assertEquals("unreachable", array.__proto__["-1"]);
+ assertEquals("unreachable", array.__proto__["-0"]);
+ assertEquals("unreachable", array.__proto__["10"]);
+ assertEquals("unreachable", array.__proto__["4294967296"]);
+}
+
+check();
+
+array["-1"] = "unreachable";
+array["-0"] = "unreachable";
+array["10"] = "unreachable";
+array["4294967296"] = "unreachable";
+
+check();
+
+delete array["-0"];
+delete array["-1"];
+delete array["10"];
+delete array["4294967296"];
+
+assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-1"));
+assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-0"));
+assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "10"));
+assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "4294967296"));
+assertEquals(10, Object.keys(array).length);
+
+check();
+
+function f() { return array["-1"]; }
+
+for (var i = 0; i < 3; i++) {
+ assertEquals(undefined, f());
+}
+%OptimizeFunctionOnNextCall(f);
+assertEquals(undefined, f());
+
+Object.defineProperty(new Int32Array(), "-1", {'value': 1});
+Object.defineProperty(new Int32Array(), "-0", {'value': 1});
+Object.defineProperty(new Int32Array(), "-10", {'value': 1});
+Object.defineProperty(new Int32Array(), "4294967296", {'value': 1});
+
+check();
diff --git a/deps/v8/test/mjsunit/es6/iteration-semantics.js b/deps/v8/test/mjsunit/es6/iteration-semantics.js
index 544c94d915..f29e6e011b 100644
--- a/deps/v8/test/mjsunit/es6/iteration-semantics.js
+++ b/deps/v8/test/mjsunit/es6/iteration-semantics.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping --harmony-proxies
+// Flags: --harmony-proxies
// Test for-of semantics.
@@ -200,9 +200,11 @@ assertEquals([undefined, 1, 2, 3],
// Done.
{ value: 4, done: 42 }])));
// Results that are not objects.
-assertEquals([undefined, undefined, undefined],
- fold(append, [],
- results([10, "foo", /qux/, { value: 37, done: true }])));
+assertThrows(function() {
+ assertEquals([undefined, undefined, undefined],
+ fold(append, [],
+ results([10, "foo", /qux/, { value: 37, done: true }])));
+}, TypeError);
// Getters (shudder).
assertEquals([1, 2],
fold(append, [],
@@ -334,3 +336,25 @@ function poison_proxy_after(iterable, n) {
}));
}
assertEquals(45, fold(sum, 0, poison_proxy_after(integers_until(10), 10)));
+
+
+function test_iterator_result_object_non_object(value, descr) {
+ var arr = [];
+ var ex;
+ var message = 'Iterator result ' + (descr || value) + ' is not an object';
+ try {
+ fold(append, arr,
+ results([{value: 1}, {}, value, {value: 2}, {done: true}]));
+ } catch (e) {
+ ex = e;
+ }
+ assertInstanceof(ex, TypeError);
+ assertEquals(message, ex.message);
+ assertArrayEquals([1, undefined], arr);
+}
+test_iterator_result_object_non_object(null);
+test_iterator_result_object_non_object(undefined);
+test_iterator_result_object_non_object(42);
+test_iterator_result_object_non_object('abc');
+test_iterator_result_object_non_object(false);
+test_iterator_result_object_non_object(Symbol('x'), 'Symbol(x)');
diff --git a/deps/v8/test/mjsunit/es6/iteration-syntax.js b/deps/v8/test/mjsunit/es6/iteration-syntax.js
index 4be94c5db4..c6a7d477bc 100644
--- a/deps/v8/test/mjsunit/es6/iteration-syntax.js
+++ b/deps/v8/test/mjsunit/es6/iteration-syntax.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
// Test for-of syntax.
"use strict";
diff --git a/deps/v8/test/mjsunit/es6/map-minus-zero.js b/deps/v8/test/mjsunit/es6/map-minus-zero.js
new file mode 100644
index 0000000000..f9f397ec5c
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/map-minus-zero.js
@@ -0,0 +1,51 @@
+// 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.
+
+'use strict';
+
+var map = new Map();
+
+var objectKey = {};
+var stringKey = 'keykeykey';
+var numberKey = 42.24;
+var booleanKey = true;
+var undefinedKey = undefined;
+var nullKey = null;
+var nanKey = NaN;
+var zeroKey = 0;
+var minusZeroKey = -0;
+
+assertEquals(map.size, 0);
+
+map.set(objectKey, 'aaa');
+map.set(stringKey, 'bbb');
+map.set(numberKey, 'ccc');
+map.set(booleanKey, 'ddd');
+map.set(undefinedKey, 'eee');
+map.set(nullKey, 'fff');
+map.set(nanKey, 'ggg');
+map.set(zeroKey, 'hhh');
+
+assertEquals(8, map.size);
+
+assertEquals('aaa', map.get(objectKey));
+assertEquals('bbb', map.get(stringKey));
+assertEquals('ccc', map.get(numberKey));
+assertEquals('ddd', map.get(booleanKey));
+assertEquals('eee', map.get(undefinedKey));
+assertEquals('fff', map.get(nullKey));
+assertEquals('ggg', map.get(nanKey));
+assertEquals('hhh', map.get(zeroKey));
+
+assertEquals(undefined, map.get({}));
+assertEquals('bbb', map.get('keykeykey'));
+assertEquals('ccc', map.get(42.24));
+assertEquals('ddd', map.get(true));
+assertEquals('eee', map.get(undefined));
+assertEquals('fff', map.get(null));
+assertEquals('ggg', map.get(NaN));
+assertEquals('hhh', map.get(0));
+assertEquals('hhh', map.get(-0));
+assertEquals('hhh', map.get(1 / Infinity));
+assertEquals('hhh', map.get(-1 / Infinity));
diff --git a/deps/v8/test/mjsunit/es6/promises.js b/deps/v8/test/mjsunit/es6/promises.js
index 04059aa720..63b6d2f94a 100644
--- a/deps/v8/test/mjsunit/es6/promises.js
+++ b/deps/v8/test/mjsunit/es6/promises.js
@@ -32,6 +32,8 @@ var call = Function.prototype.call.call.bind(Function.prototype.call)
var observe = Object.observe;
var getOwnPropertyNames = Object.getOwnPropertyNames;
var defineProperty = Object.defineProperty;
+var numberPrototype = Number.prototype;
+var symbolIterator = Symbol.iterator;
(function() {
@@ -637,14 +639,6 @@ function assertAsyncDone(iteration) {
})();
(function() {
- Promise.all({}).chain(
- assertUnreachable,
- function(r) { assertAsync(r instanceof TypeError, "all/no-array") }
- )
- assertAsyncRan()
-})();
-
-(function() {
Promise.all([]).chain(
function(x) { assertAsync(x.length === 0, "all/resolve/empty") },
assertUnreachable
@@ -653,6 +647,45 @@ function assertAsyncDone(iteration) {
})();
(function() {
+ function testPromiseAllNonIterable(value) {
+ Promise.all(value).chain(
+ assertUnreachable,
+ function(r) {
+ assertAsync(r instanceof TypeError, 'all/non iterable');
+ });
+ assertAsyncRan();
+ }
+ testPromiseAllNonIterable(null);
+ testPromiseAllNonIterable(undefined);
+ testPromiseAllNonIterable({});
+ testPromiseAllNonIterable(42);
+})();
+
+(function() {
+ var deferred = Promise.defer();
+ var p = deferred.promise;
+ function* f() {
+ yield 1;
+ yield p;
+ yield 3;
+ }
+ Promise.all(f()).chain(
+ function(x) {
+ assertAsync(x.length === 3, "all/resolve/iterable");
+ assertAsync(x[0] === 1, "all/resolve/iterable/0");
+ assertAsync(x[1] === 2, "all/resolve/iterable/1");
+ assertAsync(x[2] === 3, "all/resolve/iterable/2");
+ },
+ assertUnreachable);
+ deferred.resolve(2);
+ assertAsyncRan();
+ assertAsyncRan();
+ assertAsyncRan();
+ assertAsyncRan();
+})();
+
+
+(function() {
var deferred1 = Promise.defer()
var p1 = deferred1.promise
var deferred2 = Promise.defer()
@@ -706,6 +739,52 @@ function assertAsyncDone(iteration) {
assertAsyncRan()
})();
+
+(function() {
+ 'use strict';
+ var getCalls = 0;
+ var funcCalls = 0;
+ var nextCalls = 0;
+ defineProperty(numberPrototype, symbolIterator, {
+ get: function() {
+ assertEquals('number', typeof this);
+ getCalls++;
+ return function() {
+ assertEquals('number', typeof this);
+ funcCalls++;
+ var n = this;
+ var i = 0
+ return {
+ next() {
+ nextCalls++;
+ return {value: i++, done: i > n};
+ }
+ };
+ };
+ },
+ configurable: true
+ });
+
+ Promise.all(3).chain(
+ function(x) {
+ assertAsync(x.length === 3, "all/iterable/number/length");
+ assertAsync(x[0] === 0, "all/iterable/number/0");
+ assertAsync(x[1] === 1, "all/iterable/number/1");
+ assertAsync(x[2] === 2, "all/iterable/number/2");
+ },
+ assertUnreachable);
+ delete numberPrototype[symbolIterator];
+
+ assertEquals(getCalls, 1);
+ assertEquals(funcCalls, 1);
+ assertEquals(nextCalls, 3 + 1); // + 1 for {done: true}
+ assertAsyncRan();
+ assertAsyncRan();
+ assertAsyncRan();
+ assertAsyncRan();
+})();
+
+
(function() {
Promise.race([]).chain(
assertUnreachable,
@@ -736,14 +815,6 @@ function assertAsyncDone(iteration) {
})();
(function() {
- Promise.race({}).chain(
- assertUnreachable,
- function(r) { assertAsync(r instanceof TypeError, "one/no-array") }
- )
- assertAsyncRan()
-})();
-
-(function() {
var deferred1 = Promise.defer()
var p1 = deferred1.promise
var deferred2 = Promise.defer()
@@ -804,6 +875,103 @@ function assertAsyncDone(iteration) {
assertAsyncRan()
})();
+
+(function() {
+ function testPromiseRaceNonIterable(value) {
+ Promise.race(value).chain(
+ assertUnreachable,
+ function(r) {
+ assertAsync(r instanceof TypeError, 'race/non iterable');
+ });
+ assertAsyncRan();
+ }
+ testPromiseRaceNonIterable(null);
+ testPromiseRaceNonIterable(undefined);
+ testPromiseRaceNonIterable({});
+ testPromiseRaceNonIterable(42);
+})();
+
+
+(function() {
+ var deferred1 = Promise.defer()
+ var p1 = deferred1.promise
+ var deferred2 = Promise.defer()
+ var p2 = deferred2.promise
+ var deferred3 = Promise.defer()
+ var p3 = deferred3.promise
+ function* f() {
+ yield p1;
+ yield p2;
+ yield p3;
+ }
+ Promise.race(f()).chain(
+ function(x) { assertAsync(x === 3, "race/iterable/resolve/reject") },
+ assertUnreachable
+ )
+ deferred3.resolve(3)
+ deferred1.reject(1)
+ assertAsyncRan()
+})();
+
+(function() {
+ var deferred1 = Promise.defer()
+ var p1 = deferred1.promise
+ var deferred2 = Promise.defer()
+ var p2 = deferred2.promise
+ var deferred3 = Promise.defer()
+ var p3 = deferred3.promise
+ function* f() {
+ yield p1;
+ yield p2;
+ yield p3;
+ }
+ Promise.race(f()).chain(
+ assertUnreachable,
+ function(x) { assertAsync(x === 3, "race/iterable/reject/resolve") }
+ )
+ deferred3.reject(3)
+ deferred1.resolve(1)
+ assertAsyncRan()
+})();
+
+(function() {
+ 'use strict';
+ var getCalls = 0;
+ var funcCalls = 0;
+ var nextCalls = 0;
+ defineProperty(numberPrototype, symbolIterator, {
+ get: function() {
+ assertEquals('number', typeof this);
+ getCalls++;
+ return function() {
+ assertEquals('number', typeof this);
+ funcCalls++;
+ var n = this;
+ var i = 0
+ return {
+ next() {
+ nextCalls++;
+ return {value: i++, done: i > n};
+ }
+ };
+ };
+ },
+ configurable: true
+ });
+
+ Promise.race(3).chain(
+ function(x) {
+ assertAsync(x === 0, "race/iterable/number");
+ },
+ assertUnreachable);
+ delete numberPrototype[symbolIterator];
+
+ assertEquals(getCalls, 1);
+ assertEquals(funcCalls, 1);
+ assertEquals(nextCalls, 3 + 1); // + 1 for {done: true}
+ assertAsyncRan();
+})();
+
(function() {
var log
function MyPromise(resolver) {
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-2243.js b/deps/v8/test/mjsunit/es6/regress/regress-2243.js
index e2411d241b..d5377cfd54 100644
--- a/deps/v8/test/mjsunit/harmony/regress/regress-2243.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-2243.js
@@ -25,7 +25,5 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
assertThrows("'use strict'; (function f() { f = 123; })()", TypeError);
assertThrows("(function f() { 'use strict'; f = 123; })()", TypeError);
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-2322.js b/deps/v8/test/mjsunit/es6/regress/regress-2322.js
index 1195bab67c..6eca046397 100644
--- a/deps/v8/test/mjsunit/harmony/regress/regress-2322.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-2322.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-scoping
-
"use strict";
assertThrows("'use strict'; for (let x in x);", ReferenceError);
diff --git a/deps/v8/test/mjsunit/regress/regress-2506.js b/deps/v8/test/mjsunit/es6/regress/regress-2506.js
index 0eb2770e59..b5cc91dbd7 100644
--- a/deps/v8/test/mjsunit/regress/regress-2506.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-2506.js
@@ -1,8 +1,6 @@
// 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.
-//
-// Flags: --harmony-scoping
'use strict';
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-2858.js b/deps/v8/test/mjsunit/es6/regress/regress-2858.js
index 4ce9478497..3b54b17da0 100644
--- a/deps/v8/test/mjsunit/harmony/regress/regress-2858.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-2858.js
@@ -1,8 +1,6 @@
// 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.
-//
-// Flags: --harmony-scoping
"use strict";
function f() {
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-3426.js b/deps/v8/test/mjsunit/es6/regress/regress-3426.js
index c3b11a1792..fd4903b1f8 100644
--- a/deps/v8/test/mjsunit/harmony/regress/regress-3426.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-3426.js
@@ -2,6 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-scoping
-
assertThrows("(function() { 'use strict'; { let f; var f; } })", SyntaxError);
diff --git a/deps/v8/test/mjsunit/regress/regress-347906.js b/deps/v8/test/mjsunit/es6/regress/regress-347906.js
index c751618928..daa62f5df7 100644
--- a/deps/v8/test/mjsunit/regress/regress-347906.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-347906.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony
+// Flags: --allow-natives-syntax
function foo() {
return Math.clz32(12.34);
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-3683.js b/deps/v8/test/mjsunit/es6/regress/regress-3683.js
index a00d82bd1f..2c18632719 100644
--- a/deps/v8/test/mjsunit/harmony/regress/regress-3683.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-3683.js
@@ -1,8 +1,6 @@
// 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.
-//
-// Flags: --harmony-scoping
"use strict";
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-3741.js b/deps/v8/test/mjsunit/es6/regress/regress-3741.js
index 8a9dd9e09c..0c5074a0f8 100644
--- a/deps/v8/test/mjsunit/harmony/regress/regress-3741.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-3741.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Flags: --harmony-scoping --allow-natives-syntax
+// Flags: --allow-natives-syntax
'use strict';
function f24(deopt) {
let x = 1;
diff --git a/deps/v8/test/mjsunit/es6/regress/regress-3938.js b/deps/v8/test/mjsunit/es6/regress/regress-3938.js
new file mode 100644
index 0000000000..bd7d1befa1
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/regress/regress-3938.js
@@ -0,0 +1,8 @@
+// Copyright 2015 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.
+
+'use strict';
+
+assertThrows(function() { for (const i = 0; ; i++) {} }, TypeError);
+assertThrows("'use strict'; for (const i = 0; ; i++) {}", TypeError);
diff --git a/deps/v8/test/mjsunit/regress/regress-411237.js b/deps/v8/test/mjsunit/es6/regress/regress-411237.js
index 8b75ba3015..ece6481737 100644
--- a/deps/v8/test/mjsunit/regress/regress-411237.js
+++ b/deps/v8/test/mjsunit/es6/regress/regress-411237.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony
+// Flags: --allow-natives-syntax
try {
%OptimizeFunctionOnNextCall(print);
diff --git a/deps/v8/test/mjsunit/es6/regress/regress-468661.js b/deps/v8/test/mjsunit/es6/regress/regress-468661.js
new file mode 100644
index 0000000000..656190da0b
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/regress/regress-468661.js
@@ -0,0 +1,75 @@
+// Copyright 2015 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.
+
+// Flags: --expose-debug-as debug
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+
+var expected_values =
+ [ReferenceError, ReferenceError, 0, 0, 0, 0, 0, 1, ReferenceError, ReferenceError];
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
+ // Count number of expected breakpoints in this source file.
+ if (!break_count) {
+ var source_text = exec_state.frame(0).func().script().source();
+ expected_breaks = source_text.match(/\/\/\s*Break\s+\d+\./g).length;
+ print("Expected breaks: " + expected_breaks);
+ }
+ var frameMirror = exec_state.frame(0);
+
+ var v = null;;
+ try {
+ v = frameMirror.evaluate('i').value();
+ } catch(e) {
+ v = e;
+ }
+ frameMirror.allScopes();
+ var source = frameMirror.sourceLineText();
+ print("paused at: " + source);
+ assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
+ "Unexpected pause at: " + source + "\n" +
+ "Expected: // Break " + break_count + ".");
+ if (expected_values[break_count] === ReferenceError) {
+ assertTrue(v instanceof ReferenceError);
+ } else {
+ assertSame(expected_values[break_count], v);
+ }
+ ++break_count;
+
+ if (break_count !== expected_breaks) {
+ exec_state.prepareStep(Debug.StepAction.StepIn, 1);
+ print("Next step prepared");
+ }
+ }
+ } catch(e) {
+ exception = e;
+ print(e, e.stack);
+ }
+};
+
+Debug.setListener(listener);
+
+var sum = 0;
+(function (){
+ 'use strict';
+
+ debugger; // Break 0.
+
+ for (let i=0; // Break 1.
+ i < 1; // Break 2. // Break 3. // Break 6. // Break 7.
+ i++) {
+ let key = i; // Break 4.
+ sum += key; // Break 5.
+ }
+}()); // Break 8.
+
+assertNull(exception); // Break 9.
+assertEquals(expected_breaks, break_count);
+
+Debug.setListener(null);
diff --git a/deps/v8/test/mjsunit/es6/regress/regress-474783.js b/deps/v8/test/mjsunit/es6/regress/regress-474783.js
new file mode 100644
index 0000000000..e258dcb49f
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/regress/regress-474783.js
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+
+"use strict";
+class Base {
+}
+class Subclass extends Base {
+ constructor(a,b,c) {
+ arguments[1];
+ }
+}
+assertThrows(function() { Subclass(); }, TypeError);
+assertThrows(function() { Subclass(1); }, TypeError);
+assertThrows(function() { Subclass(1, 2); }, TypeError);
+assertThrows(function() { Subclass(1, 2, 3); }, TypeError);
+assertThrows(function() { Subclass(1, 2, 3, 4); }, TypeError);
+
+assertThrows(function() { Subclass.call(); }, TypeError);
+assertThrows(function() { Subclass.call({}); }, TypeError);
+assertThrows(function() { Subclass.call({}, 1); }, TypeError);
+assertThrows(function() { Subclass.call({}, 1, 2); }, TypeError);
+assertThrows(function() { Subclass.call({}, 1, 2, 3, 4); }, TypeError);
diff --git a/deps/v8/test/mjsunit/es6/set-minus-zero.js b/deps/v8/test/mjsunit/es6/set-minus-zero.js
new file mode 100644
index 0000000000..792332c648
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/set-minus-zero.js
@@ -0,0 +1,51 @@
+// Copyright 2015 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.
+
+'use strict';
+
+var set = new Set();
+
+var objectKey = {};
+var stringKey = 'keykeykey';
+var numberKey = 42.24;
+var booleanKey = true;
+var undefinedKey = undefined;
+var nullKey = null;
+var nanKey = NaN;
+var zeroKey = 0;
+var minusZeroKey = -0;
+
+assertEquals(set.size, 0);
+
+set.add(objectKey);
+set.add(stringKey);
+set.add(numberKey);
+set.add(booleanKey);
+set.add(undefinedKey);
+set.add(nullKey);
+set.add(nanKey);
+set.add(zeroKey);
+
+assertEquals(8, set.size);
+
+assertTrue(set.has(objectKey));
+assertTrue(set.has(stringKey));
+assertTrue(set.has(numberKey));
+assertTrue(set.has(booleanKey));
+assertTrue(set.has(undefinedKey));
+assertTrue(set.has(nullKey));
+assertTrue(set.has(nanKey));
+assertTrue(set.has(zeroKey));
+
+assertFalse(set.has({}));
+assertTrue(set.has('keykeykey'));
+assertTrue(set.has(42.24));
+assertTrue(set.has(true));
+assertTrue(set.has(undefined));
+assertTrue(set.has(null));
+assertTrue(set.has(NaN));
+assertTrue(set.has(0));
+assertTrue(set.has(-0));
+assertTrue(set.has(1 / Infinity));
+assertTrue(set.has(-1 / Infinity));
diff --git a/deps/v8/test/mjsunit/harmony/string-codepointat.js b/deps/v8/test/mjsunit/es6/string-codepointat.js
index 411b0f23c7..976d5be6af 100644
--- a/deps/v8/test/mjsunit/harmony/string-codepointat.js
+++ b/deps/v8/test/mjsunit/es6/string-codepointat.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-strings
-
// Tests taken from:
// https://github.com/mathiasbynens/String.prototype.codePointAt
diff --git a/deps/v8/test/mjsunit/harmony/string-endswith.js b/deps/v8/test/mjsunit/es6/string-endswith.js
index cc76b5fe4e..cbf2ed8766 100644
--- a/deps/v8/test/mjsunit/harmony/string-endswith.js
+++ b/deps/v8/test/mjsunit/es6/string-endswith.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-strings
-
assertEquals(1, String.prototype.endsWith.length);
var testString = "Hello World";
diff --git a/deps/v8/test/mjsunit/harmony/string-fromcodepoint.js b/deps/v8/test/mjsunit/es6/string-fromcodepoint.js
index 97ecf0eec5..c4634ace44 100644
--- a/deps/v8/test/mjsunit/harmony/string-fromcodepoint.js
+++ b/deps/v8/test/mjsunit/es6/string-fromcodepoint.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-strings
-
// Tests taken from:
// https://github.com/mathiasbynens/String.fromCodePoint
diff --git a/deps/v8/test/mjsunit/harmony/string-includes.js b/deps/v8/test/mjsunit/es6/string-includes.js
index 33ed8ea44c..61bf779483 100644
--- a/deps/v8/test/mjsunit/harmony/string-includes.js
+++ b/deps/v8/test/mjsunit/es6/string-includes.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-strings
-
assertEquals(1, String.prototype.includes.length);
var reString = "asdf[a-z]+(asdf)?";
diff --git a/deps/v8/test/mjsunit/harmony/string-raw.js b/deps/v8/test/mjsunit/es6/string-raw.js
index 28e2af9164..2c6bb2ff30 100644
--- a/deps/v8/test/mjsunit/harmony/string-raw.js
+++ b/deps/v8/test/mjsunit/es6/string-raw.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-templates
-
(function testStringRawArity() {
assertEquals(1, String.raw.length);
})();
@@ -256,3 +254,39 @@
assertEquals("12345", String.raw(callSiteObj, arg(2), arg(4), arg(6)));
assertEquals(["length", "raw1", "arg2", "raw3", "arg4", "raw5"], order);
})();
+
+
+(function testStringRawToStringSubstitutionsOrder() {
+ var subs = [];
+ var log = [];
+ function stringify(toString) {
+ var valueOf = "_" + toString + "_";
+ return {
+ toString: function() { return toString; },
+ valueOf: function() { return valueOf; }
+ };
+ }
+ function getter(name, value) {
+ return {
+ get: function() {
+ log.push("get" + name);
+ return value;
+ },
+ set: function(v) {
+ log.push("set" + name);
+ }
+ };
+ }
+ Object.defineProperties(subs, {
+ 0: getter(0, stringify("a")),
+ 1: getter(1, stringify("b")),
+ 2: getter(2, stringify("c"))
+ });
+
+ assertEquals("-a-b-c-", String.raw`-${subs[0]}-${subs[1]}-${subs[2]}-`);
+ assertArrayEquals(["get0", "get1", "get2"], log);
+
+ log.length = 0;
+ assertEquals("-a-", String.raw`-${subs[0]}-`);
+ assertArrayEquals(["get0"], log);
+})();
diff --git a/deps/v8/test/mjsunit/harmony/string-repeat.js b/deps/v8/test/mjsunit/es6/string-repeat.js
index 0af74483a0..15caea14f3 100644
--- a/deps/v8/test/mjsunit/harmony/string-repeat.js
+++ b/deps/v8/test/mjsunit/es6/string-repeat.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-strings
-
assertEquals("000", String.prototype.repeat.call(0, 3));
assertEquals("-1-1-1", String.prototype.repeat.call(-1, 3));
assertEquals("2.12.12.1", String.prototype.repeat.call(2.1, 3));
diff --git a/deps/v8/test/mjsunit/harmony/string-startswith.js b/deps/v8/test/mjsunit/es6/string-startswith.js
index d72f2946f5..887db994a0 100644
--- a/deps/v8/test/mjsunit/harmony/string-startswith.js
+++ b/deps/v8/test/mjsunit/es6/string-startswith.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-strings
-
assertEquals(1, String.prototype.startsWith.length);
var testString = "Hello World";
diff --git a/deps/v8/test/mjsunit/es6/symbols.js b/deps/v8/test/mjsunit/es6/symbols.js
index b9811f509e..46c3daba8a 100644
--- a/deps/v8/test/mjsunit/es6/symbols.js
+++ b/deps/v8/test/mjsunit/es6/symbols.js
@@ -245,25 +245,20 @@ TestCall()
function TestCollections() {
var set = new Set
var map = new Map
- var weakmap = new WeakMap
for (var i in symbols) {
set.add(symbols[i])
map.set(symbols[i], i)
- weakmap.set(symbols[i], i)
}
assertEquals(symbols.length, set.size)
assertEquals(symbols.length, map.size)
for (var i in symbols) {
assertTrue(set.has(symbols[i]))
assertTrue(map.has(symbols[i]))
- assertTrue(weakmap.has(symbols[i]))
assertEquals(i, map.get(symbols[i]))
- assertEquals(i, weakmap.get(symbols[i]))
}
for (var i in symbols) {
assertTrue(set.delete(symbols[i]))
assertTrue(map.delete(symbols[i]))
- assertTrue(weakmap.delete(symbols[i]))
}
assertEquals(0, set.size)
assertEquals(0, map.size)
diff --git a/deps/v8/test/mjsunit/harmony/templates.js b/deps/v8/test/mjsunit/es6/templates.js
index a884f58fb6..15296e8722 100644
--- a/deps/v8/test/mjsunit/harmony/templates.js
+++ b/deps/v8/test/mjsunit/es6/templates.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-templates --harmony-unicode
+// Flags: --harmony-unicode
var num = 5;
var str = "str";
@@ -423,10 +423,12 @@ var obj = {
Object.defineProperty(Array.prototype, 0, {
set: function() {
assertUnreachable();
- }
+ },
+ configurable: true
});
function tag(){}
tag`a${1}b`;
+ delete Array.prototype[0];
})();
@@ -518,3 +520,162 @@ var obj = {
assertThrows("`${(function() { \"use strict\"; return \"\\07\"; })()}`",
SyntaxError);
})();
+
+
+var global = this;
+(function testCallNew() {
+ "use strict";
+ var called = false;
+ var calledWith;
+ global.log = function(x) { called = true; calledWith = x; }
+
+ assertInstanceof(new Function`log("test")`, Object);
+ assertTrue(called);
+ assertSame("test", calledWith);
+ delete global.log;
+})();
+
+
+(function testCallNew2() {
+ "use strict";
+ var log = [];
+ function tag(x) {
+ log.push(x);
+ if (!(this instanceof tag)) {
+ return tag;
+ }
+ this.x = x === void 0 ? null : x;
+ return this;
+ }
+ // No arguments passed to constructor
+ var instance = new tag`x``y``z`;
+ assertInstanceof(instance, tag);
+ assertSame(tag.prototype, Object.getPrototypeOf(instance));
+ assertEquals({ x: null }, instance);
+ assertEquals([["x"], ["y"], ["z"], undefined], log);
+
+ // Arguments passed to constructor
+ log.length = 0;
+ instance = new tag`x2` `y2` `z2` (`test`);
+ assertInstanceof(instance, tag);
+ assertSame(tag.prototype, Object.getPrototypeOf(instance));
+ assertEquals({ x: "test" }, instance);
+ assertEquals([["x2"], ["y2"], ["z2"], "test"], log);
+})();
+
+
+(function testCallResultOfTagFn() {
+ "use strict";
+ var i = 0;
+ var raw = [];
+ function tag(cs) {
+ var args = Array.prototype.slice.call(arguments);
+ var text = String.raw.apply(null, args);
+ if (i++ < 2) {
+ raw.push("tag;" + text);
+ return tag;
+ }
+
+ raw.push("raw;" + text);
+ return text;
+ }
+ assertEquals("test3", tag`test1``test2``test3`);
+ assertEquals([
+ "tag;test1",
+ "tag;test2",
+ "raw;test3"
+ ], raw);
+})();
+
+
+(function testToStringSubstitutions() {
+ var a = {
+ toString: function() { return "a"; },
+ valueOf: function() { return "-a-"; }
+ };
+ var b = {
+ toString: function() { return "b"; },
+ valueOf: function() { return "-b-"; }
+ };
+ assertEquals("a", `${a}`);
+ assertEquals("ab", `${a}${b}`);
+ assertEquals("-a--b-", `${a + b}`);
+ assertEquals("-a-", `${a + ""}`);
+ assertEquals("1a", `1${a}`);
+ assertEquals("1a2", `1${a}2`);
+ assertEquals("1a2b", `1${a}2${b}`);
+ assertEquals("1a2b3", `1${a}2${b}3`);
+})();
+
+
+(function testToStringSubstitutionsOrder() {
+ var subs = [];
+ var log = [];
+ function getter(name, value) {
+ return {
+ get: function() {
+ log.push("get" + name);
+ return value;
+ },
+ set: function(v) {
+ log.push("set" + name);
+ }
+ };
+ }
+ Object.defineProperties(subs, {
+ 0: getter(0, "a"),
+ 1: getter(1, "b"),
+ 2: getter(2, "c")
+ });
+
+ assertEquals("-a-b-c-", `-${subs[0]}-${subs[1]}-${subs[2]}-`);
+ assertArrayEquals(["get0", "get1", "get2"], log);
+})();
+
+
+(function testTaggedToStringSubstitutionsOrder() {
+ var subs = [];
+ var log = [];
+ var tagged = [];
+ function getter(name, value) {
+ return {
+ get: function() {
+ log.push("get" + name);
+ return value;
+ },
+ set: function(v) {
+ log.push("set" + name);
+ }
+ };
+ }
+ Object.defineProperties(subs, {
+ 0: getter(0, 1),
+ 1: getter(1, 2),
+ 2: getter(2, 3)
+ });
+
+ function tag(cs) {
+ var n_substitutions = arguments.length - 1;
+ var n_cooked = cs.length;
+ var e = cs[0];
+ var i = 0;
+ assertEquals(n_cooked, n_substitutions + 1);
+ while (i < n_substitutions) {
+ var sub = arguments[i++ + 1];
+ var tail = cs[i];
+ tagged.push(sub);
+ e = e.concat(sub, tail);
+ }
+ return e;
+ }
+
+ assertEquals("-1-2-3-", tag`-${subs[0]}-${subs[1]}-${subs[2]}-`);
+ assertArrayEquals(["get0", "get1", "get2"], log);
+ assertArrayEquals([1, 2, 3], tagged);
+
+ tagged.length = 0;
+ log.length = 0;
+ assertEquals("-1-", tag`-${subs[0]}-`);
+ assertArrayEquals(["get0"], log);
+ assertArrayEquals([1], tagged);
+})();
diff --git a/deps/v8/test/mjsunit/es7/object-observe.js b/deps/v8/test/mjsunit/es7/object-observe.js
index 5af205eadf..b2853c4048 100644
--- a/deps/v8/test/mjsunit/es7/object-observe.js
+++ b/deps/v8/test/mjsunit/es7/object-observe.js
@@ -1142,7 +1142,9 @@ var properties = ["a", "1", 1, "length", "setPrototype", "name", "caller"];
function blacklisted(obj, prop) {
return (obj instanceof Int32Array && prop == 1) ||
(obj instanceof Int32Array && prop === "length") ||
- (obj instanceof ArrayBuffer && prop == 1)
+ (obj instanceof ArrayBuffer && prop == 1) ||
+ (obj instanceof Function && prop === "name") || // Has its own test.
+ (obj instanceof Function && prop === "length"); // Has its own test.
}
for (var i in objects) for (var j in properties) {
@@ -1798,3 +1800,66 @@ for (var b1 = 0; b1 < 2; ++b1)
for (var n = 0; n < 3; ++n)
for (var i in mutationByIncr)
TestFastElementsLength(mutationByIncr[i], b1 != 0, b2 != 0, 7*n, 7*n+1);
+
+
+(function TestFunctionName() {
+ reset();
+
+ function fun() {}
+ Object.observe(fun, observer.callback);
+ fun.name = 'x'; // No change. Not writable.
+ Object.defineProperty(fun, 'name', {value: 'a'});
+ Object.defineProperty(fun, 'name', {writable: true});
+ fun.name = 'b';
+ delete fun.name;
+ fun.name = 'x'; // No change. Function.prototype.name is non writable
+ Object.defineProperty(Function.prototype, 'name', {writable: true});
+ fun.name = 'c';
+ fun.name = 'c'; // Same, no update.
+ Object.deliverChangeRecords(observer.callback);
+ observer.assertCallbackRecords([
+ { object: fun, type: 'update', name: 'name', oldValue: 'fun' },
+ { object: fun, type: 'reconfigure', name: 'name'},
+ { object: fun, type: 'update', name: 'name', oldValue: 'a' },
+ { object: fun, type: 'delete', name: 'name', oldValue: 'b' },
+ { object: fun, type: 'add', name: 'name' },
+ ]);
+})();
+
+
+(function TestFunctionLength() {
+ reset();
+
+ function fun(x) {}
+ Object.observe(fun, observer.callback);
+ fun.length = 'x'; // No change. Not writable.
+ Object.defineProperty(fun, 'length', {value: 'a'});
+ Object.defineProperty(fun, 'length', {writable: true});
+ fun.length = 'b';
+ delete fun.length;
+ fun.length = 'x'; // No change. Function.prototype.length is non writable
+ Object.defineProperty(Function.prototype, 'length', {writable: true});
+ fun.length = 'c';
+ fun.length = 'c'; // Same, no update.
+ Object.deliverChangeRecords(observer.callback);
+ observer.assertCallbackRecords([
+ { object: fun, type: 'update', name: 'length', oldValue: 1 },
+ { object: fun, type: 'reconfigure', name: 'length'},
+ { object: fun, type: 'update', name: 'length', oldValue: 'a' },
+ { object: fun, type: 'delete', name: 'length', oldValue: 'b' },
+ { object: fun, type: 'add', name: 'length' },
+ ]);
+})();
+
+
+(function TestObserveInvalidAcceptMessage() {
+ var ex;
+ try {
+ Object.observe({}, function(){}, "not an object");
+ } catch (e) {
+ ex = e;
+ }
+ assertInstanceof(ex, TypeError);
+ assertEquals("Third argument to Object.observe must be an array of strings.",
+ ex.message);
+})()
diff --git a/deps/v8/test/mjsunit/function-length-accessor.js b/deps/v8/test/mjsunit/function-length-accessor.js
index 97c9f65822..386ac99643 100644
--- a/deps/v8/test/mjsunit/function-length-accessor.js
+++ b/deps/v8/test/mjsunit/function-length-accessor.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-scoping --lazy
+// Flags: --lazy
function foo(a, b, c, d) {
"use strict"
diff --git a/deps/v8/test/mjsunit/function-prototype.js b/deps/v8/test/mjsunit/function-prototype.js
index 7eac6df121..76ab53cf07 100644
--- a/deps/v8/test/mjsunit/function-prototype.js
+++ b/deps/v8/test/mjsunit/function-prototype.js
@@ -34,6 +34,9 @@ function TestNonObjectPrototype(value) {
var f = new F();
assertEquals(value, F.prototype);
assertEquals(Object.prototype, f.__proto__);
+ // Test that map transitions don't break anything.
+ F.property = "value";
+ assertEquals(value, F.prototype);
}
var values = [123, "asdf", true];
diff --git a/deps/v8/test/mjsunit/harmony/block-const-assign.js b/deps/v8/test/mjsunit/harmony/block-const-assign.js
deleted file mode 100644
index c21a0a3480..0000000000
--- a/deps/v8/test/mjsunit/harmony/block-const-assign.js
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-scoping
-
-// Test that we throw early syntax errors in harmony mode
-// when using an immutable binding in an assigment or with
-// prefix/postfix decrement/increment operators.
-
-"use strict";
-
-// Function local const.
-function constDecl0(use) {
- return "(function() { const constvar = 1; " + use + "; })();";
-}
-
-
-function constDecl1(use) {
- return "(function() { " + use + "; const constvar = 1; })();";
-}
-
-
-// Function local const, assign from eval.
-function constDecl2(use) {
- use = "eval('(function() { " + use + " })')()";
- return "(function() { const constvar = 1; " + use + "; })();";
-}
-
-
-function constDecl3(use) {
- use = "eval('(function() { " + use + " })')()";
- return "(function() { " + use + "; const constvar = 1; })();";
-}
-
-
-// Block local const.
-function constDecl4(use) {
- return "(function() { { const constvar = 1; " + use + "; } })();";
-}
-
-
-function constDecl5(use) {
- return "(function() { { " + use + "; const constvar = 1; } })();";
-}
-
-
-// Block local const, assign from eval.
-function constDecl6(use) {
- use = "eval('(function() {" + use + "})')()";
- return "(function() { { const constvar = 1; " + use + "; } })();";
-}
-
-
-function constDecl7(use) {
- use = "eval('(function() {" + use + "})')()";
- return "(function() { { " + use + "; const constvar = 1; } })();";
-}
-
-
-// Function expression name.
-function constDecl8(use) {
- return "(function constvar() { " + use + "; })();";
-}
-
-
-// Function expression name, assign from eval.
-function constDecl9(use) {
- use = "eval('(function(){" + use + "})')()";
- return "(function constvar() { " + use + "; })();";
-}
-
-let decls = [ constDecl0,
- constDecl1,
- constDecl2,
- constDecl3,
- constDecl4,
- constDecl5,
- constDecl6,
- constDecl7,
- constDecl8,
- constDecl9
- ];
-let declsForTDZ = new Set([constDecl1, constDecl3, constDecl5, constDecl7]);
-let uses = [ 'constvar = 1;',
- 'constvar += 1;',
- '++constvar;',
- 'constvar++;'
- ];
-
-function Test(d,u) {
- 'use strict';
- try {
- print(d(u));
- eval(d(u));
- } catch (e) {
- if (declsForTDZ.has(d) && u !== uses[0]) {
- // In these cases, read of a const variable occurs
- // before a write to it, so TDZ kicks in before const check.
- assertInstanceof(e, ReferenceError);
- return;
- }
- assertInstanceof(e, TypeError);
- assertTrue(e.toString().indexOf("Assignment to constant variable") >= 0);
- return;
- }
- assertUnreachable();
-}
-
-for (var d = 0; d < decls.length; ++d) {
- for (var u = 0; u < uses.length; ++u) {
- Test(decls[d], uses[u]);
- }
-}
diff --git a/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js b/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js
index 4e50f8a461..ab5d39e867 100644
--- a/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js
+++ b/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js
@@ -312,41 +312,74 @@ function assertIteratorResult(value, done, result) {
(function TestPrototype() {
- // Normally a static prototype property is not allowed.
- class C {
- static ['prototype']() {
- return 1;
+ assertThrows(function() {
+ class C {
+ static ['prototype']() {
+ return 1;
+ }
}
- }
- assertEquals(1, C.prototype());
+ }, TypeError);
- class C2 {
- static get ['prototype']() {
- return 2;
+ assertThrows(function() {
+ class C2 {
+ static get ['prototype']() {
+ return 2;
+ }
}
- }
- assertEquals(2, C2.prototype);
+ }, TypeError);
- var calls = 0;
- class C3 {
- static set ['prototype'](x) {
- assertEquals(3, x);
- calls++;
+ assertThrows(function() {
+ class C3 {
+ static set ['prototype'](x) {
+ assertEquals(3, x);
+ }
}
- }
- C3.prototype = 3;
- assertEquals(1, calls);
+ }, TypeError);
+
+ assertThrows(function() {
+ class C4 {
+ static *['prototype']() {
+ yield 1;
+ yield 2;
+ }
+ }
+ }, TypeError);
+})();
- class C4 {
- static *['prototype']() {
- yield 1;
- yield 2;
+
+(function TestPrototypeConcat() {
+ assertThrows(function() {
+ class C {
+ static ['pro' + 'tot' + 'ype']() {
+ return 1;
+ }
}
- }
- var iter = C4.prototype();
- assertIteratorResult(1, false, iter.next());
- assertIteratorResult(2, false, iter.next());
- assertIteratorResult(undefined, true, iter.next());
+ }, TypeError);
+
+ assertThrows(function() {
+ class C2 {
+ static get ['pro' + 'tot' + 'ype']() {
+ return 2;
+ }
+ }
+ }, TypeError);
+
+ assertThrows(function() {
+ class C3 {
+ static set ['pro' + 'tot' + 'ype'](x) {
+ assertEquals(3, x);
+ }
+ }
+ }, TypeError);
+
+ assertThrows(function() {
+ class C4 {
+ static *['pro' + 'tot' + 'ype']() {
+ yield 1;
+ yield 2;
+ }
+ }
+ }, TypeError);
})();
@@ -388,3 +421,45 @@ function assertIteratorResult(value, done, result) {
assertIteratorResult(2, false, iter.next());
assertIteratorResult(undefined, true, iter.next());
})();
+
+
+(function TestExceptionInName() {
+ function MyError() {};
+ function throwMyError() {
+ throw new MyError();
+ }
+ assertThrows(function() {
+ class C {
+ [throwMyError()]() {}
+ }
+ }, MyError);
+ assertThrows(function() {
+ class C {
+ get [throwMyError()]() { return 42; }
+ }
+ }, MyError);
+ assertThrows(function() {
+ class C {
+ set [throwMyError()](_) { }
+ }
+ }, MyError);
+})();
+
+
+(function TestTdzName() {
+ assertThrows(function() {
+ class C {
+ [C]() {}
+ }
+ }, ReferenceError);
+ assertThrows(function() {
+ class C {
+ get [C]() { return 42; }
+ }
+ }, ReferenceError);
+ assertThrows(function() {
+ class C {
+ set [C](_) { }
+ }
+ }, ReferenceError);
+})();
diff --git a/deps/v8/test/mjsunit/harmony/computed-property-names.js b/deps/v8/test/mjsunit/harmony/computed-property-names.js
index 69360771c1..36e1411169 100644
--- a/deps/v8/test/mjsunit/harmony/computed-property-names.js
+++ b/deps/v8/test/mjsunit/harmony/computed-property-names.js
@@ -277,3 +277,26 @@ function ID(x) {
assertEquals('X', object.x);
assertEquals(proto, Object.getPrototypeOf(object));
})();
+
+
+(function TestExceptionInName() {
+ function MyError() {};
+ function throwMyError() {
+ throw new MyError();
+ }
+ assertThrows(function() {
+ var o = {
+ [throwMyError()]: 42
+ };
+ }, MyError);
+ assertThrows(function() {
+ var o = {
+ get [throwMyError()]() { return 42; }
+ };
+ }, MyError);
+ assertThrows(function() {
+ var o = {
+ set [throwMyError()](_) { }
+ };
+ }, MyError);
+})();
diff --git a/deps/v8/test/mjsunit/harmony/module-linking.js b/deps/v8/test/mjsunit/harmony/module-linking.js
index 3a5bc89793..faaf7f2e49 100644
--- a/deps/v8/test/mjsunit/harmony/module-linking.js
+++ b/deps/v8/test/mjsunit/harmony/module-linking.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-modules --harmony-scoping
+// Flags: --harmony-modules
// Test basic module linking and initialization.
diff --git a/deps/v8/test/mjsunit/harmony/module-resolution.js b/deps/v8/test/mjsunit/harmony/module-resolution.js
index 1a95347d14..7f1e431313 100644
--- a/deps/v8/test/mjsunit/harmony/module-resolution.js
+++ b/deps/v8/test/mjsunit/harmony/module-resolution.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-modules --harmony-scoping
+// Flags: --harmony-modules
// Test basic module interface inference.
diff --git a/deps/v8/test/mjsunit/harmony/private.js b/deps/v8/test/mjsunit/harmony/private.js
index 218094c3d5..c08daf1050 100644
--- a/deps/v8/test/mjsunit/harmony/private.js
+++ b/deps/v8/test/mjsunit/harmony/private.js
@@ -196,25 +196,20 @@ TestSet()
function TestCollections() {
var set = new Set
var map = new Map
- var weakmap = new WeakMap
for (var i in symbols) {
set.add(symbols[i])
map.set(symbols[i], i)
- weakmap.set(symbols[i], i)
}
assertEquals(symbols.length, set.size)
assertEquals(symbols.length, map.size)
for (var i in symbols) {
assertTrue(set.has(symbols[i]))
assertTrue(map.has(symbols[i]))
- assertTrue(weakmap.has(symbols[i]))
assertEquals(i, map.get(symbols[i]))
- assertEquals(i, weakmap.get(symbols[i]))
}
for (var i in symbols) {
assertTrue(set.delete(symbols[i]))
assertTrue(map.delete(symbols[i]))
- assertTrue(weakmap.delete(symbols[i]))
}
assertEquals(0, set.size)
assertEquals(0, map.size)
diff --git a/deps/v8/test/mjsunit/harmony/reflect-apply.js b/deps/v8/test/mjsunit/harmony/reflect-apply.js
new file mode 100644
index 0000000000..2cfb98282b
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/reflect-apply.js
@@ -0,0 +1,212 @@
+// 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.
+
+// Flags: --harmony-reflect
+
+
+(function testReflectApplyArity() {
+ assertEquals(3, Reflect.apply.length);
+})();
+
+
+(function testReflectApplyNonConstructor() {
+ assertThrows(function() {
+ new Reflect.apply(function(){}, null, []);
+ }, TypeError);
+})();
+
+
+(function testAppliedReceiverSloppy() {
+ function returnThis() { return this; }
+ var receiver = {};
+
+ assertSame(this, Reflect.apply(returnThis, void 0, []));
+ assertSame(this, Reflect.apply(returnThis, null, []));
+ assertSame(this, Reflect.apply(returnThis, this, []));
+ assertSame(receiver, Reflect.apply(returnThis, receiver, []));
+
+ // Wrap JS values
+ assertSame(String.prototype,
+ Object.getPrototypeOf(Reflect.apply(returnThis, "str", [])));
+ assertSame(Number.prototype,
+ Object.getPrototypeOf(Reflect.apply(returnThis, 123, [])));
+ assertSame(Boolean.prototype,
+ Object.getPrototypeOf(Reflect.apply(returnThis, true, [])));
+ assertSame(Symbol.prototype,
+ Object.getPrototypeOf(
+ Reflect.apply(returnThis, Symbol("test"), [])));
+})();
+
+
+(function testAppliedReceiverStrict() {
+ function returnThis() { 'use strict'; return this; }
+ var receiver = {};
+
+ assertSame(void 0, Reflect.apply(returnThis, void 0, []));
+ assertSame(this, Reflect.apply(returnThis, this, []));
+ assertSame(receiver, Reflect.apply(returnThis, receiver, []));
+
+ // Don't wrap value types
+ var regexp = /123/;
+ var symbol = Symbol("test");
+ assertSame("str", Reflect.apply(returnThis, "str", []));
+ assertSame(123, Reflect.apply(returnThis, 123, []));
+ assertSame(true, Reflect.apply(returnThis, true, []));
+ assertSame(regexp, Reflect.apply(returnThis, regexp, []));
+ assertSame(symbol, Reflect.apply(returnThis, symbol, []));
+})();
+
+
+(function testAppliedArgumentsLength() {
+ function returnLengthStrict() { 'use strict'; return arguments.length; }
+ function returnLengthSloppy() { return arguments.length; }
+
+ assertEquals(0, Reflect.apply(returnLengthStrict, this, []));
+ assertEquals(0, Reflect.apply(returnLengthSloppy, this, []));
+ assertEquals(0, Reflect.apply(returnLengthStrict, this, {}));
+ assertEquals(0, Reflect.apply(returnLengthSloppy, this, {}));
+
+ for (var i = 0; i < 256; ++i) {
+ assertEquals(i, Reflect.apply(returnLengthStrict, this, new Array(i)));
+ assertEquals(i, Reflect.apply(returnLengthSloppy, this, new Array(i)));
+ assertEquals(i, Reflect.apply(returnLengthStrict, this, { length: i }));
+ assertEquals(i, Reflect.apply(returnLengthSloppy, this, { length: i }));
+ }
+})();
+
+
+(function testAppliedArgumentsLengthThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = {};
+ Object.defineProperty(argsList, "length", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.apply(noopStrict, this, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.apply(noopSloppy, this, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedArgumentsElementThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = { length: 1 };
+ Object.defineProperty(argsList, "0", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.apply(noopStrict, this, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.apply(noopSloppy, this, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedNonFunctionStrict() {
+ 'use strict';
+ assertThrows(function() { Reflect.apply(void 0); }, TypeError);
+ assertThrows(function() { Reflect.apply(null); }, TypeError);
+ assertThrows(function() { Reflect.apply(123); }, TypeError);
+ assertThrows(function() { Reflect.apply("str"); }, TypeError);
+ assertThrows(function() { Reflect.apply(Symbol("x")); }, TypeError);
+ assertThrows(function() { Reflect.apply(/123/); }, TypeError);
+ assertThrows(function() { Reflect.apply(NaN); }, TypeError);
+ assertThrows(function() { Reflect.apply({}); }, TypeError);
+ assertThrows(function() { Reflect.apply([]); }, TypeError);
+})();
+
+
+(function testAppliedNonFunctionSloppy() {
+ assertThrows(function() { Reflect.apply(void 0); }, TypeError);
+ assertThrows(function() { Reflect.apply(null); }, TypeError);
+ assertThrows(function() { Reflect.apply(123); }, TypeError);
+ assertThrows(function() { Reflect.apply("str"); }, TypeError);
+ assertThrows(function() { Reflect.apply(Symbol("x")); }, TypeError);
+ assertThrows(function() { Reflect.apply(/123/); }, TypeError);
+ assertThrows(function() { Reflect.apply(NaN); }, TypeError);
+ assertThrows(function() { Reflect.apply({}); }, TypeError);
+ assertThrows(function() { Reflect.apply([]); }, TypeError);
+})();
+
+
+(function testAppliedArgumentsNonList() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() {}
+ var R = void 0;
+ assertThrows(function() { Reflect.apply(noopStrict, R, null); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, null); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopStrict, R, 1); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, 1); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopStrict, R, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopStrict, R, true); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, true); }, TypeError);
+ var sym = Symbol("x");
+ assertThrows(function() { Reflect.apply(noopStrict, R, sym); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, sym); }, TypeError);
+})();
+
+
+(function testAppliedArgumentValue() {
+ function returnFirstStrict(a) { 'use strict'; return a; }
+ function returnFirstSloppy(a) { return a; }
+ function returnLastStrict(a) {
+ 'use strict'; return arguments[arguments.length - 1]; }
+ function returnLastSloppy(a) { return arguments[arguments.length - 1]; }
+ function returnSumStrict() {
+ 'use strict';
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ return sum;
+ }
+ function returnSumSloppy() {
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ return sum;
+ }
+
+ assertEquals("OK!", Reflect.apply(returnFirstStrict, this, ["OK!"]));
+ assertEquals("OK!", Reflect.apply(returnFirstSloppy, this, ["OK!"]));
+ assertEquals("OK!", Reflect.apply(returnFirstStrict, this,
+ { 0: "OK!", length: 1 }));
+ assertEquals("OK!", Reflect.apply(returnFirstSloppy, this,
+ { 0: "OK!", length: 1 }));
+ assertEquals("OK!", Reflect.apply(returnLastStrict, this,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]));
+ assertEquals("OK!", Reflect.apply(returnLastSloppy, this,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]));
+ assertEquals("OK!", Reflect.apply(returnLastStrict, this,
+ { 9: "OK!", length: 10 }));
+ assertEquals("OK!", Reflect.apply(returnLastSloppy, this,
+ { 9: "OK!", length: 10 }));
+ assertEquals("TEST", Reflect.apply(returnSumStrict, this,
+ ["T", "E", "S", "T"]));
+ assertEquals("TEST!!", Reflect.apply(returnSumStrict, this,
+ ["T", "E", "S", "T", "!", "!"]));
+ assertEquals(10, Reflect.apply(returnSumStrict, this,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }));
+ assertEquals("TEST", Reflect.apply(returnSumSloppy, this,
+ ["T", "E", "S", "T"]));
+ assertEquals("TEST!!", Reflect.apply(returnSumSloppy, this,
+ ["T", "E", "S", "T", "!", "!"]));
+ assertEquals(10, Reflect.apply(returnSumSloppy, this,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }));
+})();
diff --git a/deps/v8/test/mjsunit/harmony/reflect-construct.js b/deps/v8/test/mjsunit/harmony/reflect-construct.js
new file mode 100644
index 0000000000..2211e3f783
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/reflect-construct.js
@@ -0,0 +1,277 @@
+// 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.
+
+// Flags: --harmony-reflect
+
+
+(function testReflectConstructArity() {
+ assertEquals(2, Reflect.construct.length);
+})();
+
+
+(function testReflectConstructNonConstructor() {
+ assertThrows(function() {
+ new Reflect.construct(function(){}, []);
+ }, TypeError);
+})();
+
+
+(function testReflectConstructBasic() {
+ function Constructor() { "use strict"; }
+ assertInstanceof(Reflect.construct(Constructor, []), Constructor);
+})();
+
+
+(function testReflectConstructBasicSloppy() {
+ function Constructor() {}
+ assertInstanceof(Reflect.construct(Constructor, []), Constructor);
+})();
+
+
+(function testReflectConstructReturnSomethingElseStrict() {
+ var R = {};
+ function Constructor() { "use strict"; return R; }
+ assertSame(R, Reflect.construct(Constructor, []));
+})();
+
+
+(function testReflectConstructReturnSomethingElseSloppy() {
+ var R = {};
+ function Constructor() { return R; }
+ assertSame(R, Reflect.construct(Constructor, []));
+})();
+
+
+(function testReflectConstructNewTargetStrict() {
+ "use strict";
+ function Constructor() { this[9] = 1; }
+ var O = Reflect.construct(Constructor, [], Array);
+ assertEquals(1, O[9]);
+ // Ordinary object with Array.prototype --- no exotic Array magic
+ assertFalse(Array.isArray(O));
+ assertEquals(0, O.length);
+ assertSame(Array.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testReflectConstructNewTargetSloppy() {
+ function Constructor() { this[9] = 1; }
+ var O = Reflect.construct(Constructor, [], Array);
+ assertEquals(1, O[9]);
+ // Ordinary object with Array.prototype --- no exotic Array magic
+ assertFalse(Array.isArray(O));
+ assertEquals(0, O.length);
+ assertSame(Array.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testReflectConstructNewTargetStrict2() {
+ "use strict";
+ function Constructor() { this[9] = 1; }
+ Constructor.prototype.add = function(x) {
+ this[this.length] = x; return this;
+ }
+ var O = Reflect.construct(Array, [1, 2, 3], Constructor);
+ // Exotic Array object with Constructor.prototype
+ assertTrue(Array.isArray(O));
+ assertSame(Constructor.prototype, Object.getPrototypeOf(O));
+ assertFalse(O instanceof Array);
+ assertEquals(3, O.length);
+ assertEquals(undefined, O[9]);
+ assertSame(O, O.add(4));
+ assertEquals(4, O.length);
+ assertEquals(4, O[3]);
+})();
+
+
+(function testReflectConstructNewTargetSloppy2() {
+ function Constructor() { this[9] = 1; }
+ Constructor.prototype.add = function(x) {
+ this[this.length] = x; return this;
+ }
+ var O = Reflect.construct(Array, [1, 2, 3], Constructor);
+ // Exotic Array object with Constructor.prototype
+ assertTrue(Array.isArray(O));
+ assertSame(Constructor.prototype, Object.getPrototypeOf(O));
+ assertFalse(O instanceof Array);
+ assertEquals(3, O.length);
+ assertEquals(undefined, O[9]);
+ assertSame(O, O.add(4));
+ assertEquals(4, O.length);
+ assertEquals(4, O[3]);
+})();
+
+
+(function testReflectConstructNewTargetStrict3() {
+ "use strict";
+ function A() {}
+ function B() {}
+ var O = Reflect.construct(A, [], B);
+ // TODO(caitp): bug: newTarget prototype is not used if it is not
+ // explicitly set.
+ //assertSame(B.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testReflectConstructNewTargetSloppy3() {
+ function A() {}
+ function B() {}
+ var O = Reflect.construct(A, [], B);
+ // TODO(caitp): bug: newTarget prototype is not used if it is not
+ // explicitly set.
+ //assertSame(B.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testAppliedArgumentsLength() {
+ function lengthStrict() { 'use strict'; this.a = arguments.length; }
+ function lengthSloppy() { this.a = arguments.length; }
+
+ assertEquals(0, Reflect.construct(lengthStrict, []).a);
+ assertEquals(0, Reflect.construct(lengthSloppy, []).a);
+ assertEquals(0, Reflect.construct(lengthStrict, {}).a);
+ assertEquals(0, Reflect.construct(lengthSloppy, {}).a);
+
+ for (var i = 0; i < 256; ++i) {
+ assertEquals(i, Reflect.construct(lengthStrict, new Array(i)).a);
+ assertEquals(i, Reflect.construct(lengthSloppy, new Array(i)).a);
+ assertEquals(i, Reflect.construct(lengthStrict, { length: i }).a);
+ assertEquals(i, Reflect.construct(lengthSloppy, { length: i }).a);
+ }
+})();
+
+
+(function testAppliedArgumentsLengthThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = {};
+ Object.defineProperty(argsList, "length", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.construct(noopStrict, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.construct(noopSloppy, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedArgumentsElementThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = { length: 1 };
+ Object.defineProperty(argsList, "0", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.construct(noopStrict, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.construct(noopSloppy, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedNonFunctionStrict() {
+ 'use strict';
+ assertThrows(function() { Reflect.construct(void 0, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(null, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(123, []); }, TypeError);
+ assertThrows(function() { Reflect.construct("str", []); }, TypeError);
+ assertThrows(function() { Reflect.construct(Symbol("x"), []); }, TypeError);
+ assertThrows(function() { Reflect.construct(/123/, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(NaN, []); }, TypeError);
+ assertThrows(function() { Reflect.construct({}, []); }, TypeError);
+ assertThrows(function() { Reflect.construct([], []); }, TypeError);
+})();
+
+
+(function testAppliedNonFunctionSloppy() {
+ assertThrows(function() { Reflect.construct(void 0, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(null, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(123, []); }, TypeError);
+ assertThrows(function() { Reflect.construct("str", []); }, TypeError);
+ assertThrows(function() { Reflect.construct(Symbol("x"), []); }, TypeError);
+ assertThrows(function() { Reflect.construct(/123/, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(NaN, []); }, TypeError);
+ assertThrows(function() { Reflect.construct({}, []); }, TypeError);
+ assertThrows(function() { Reflect.construct([], []); }, TypeError);
+})();
+
+
+(function testAppliedArgumentsNonList() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() {}
+ assertThrows(function() { Reflect.construct(noopStrict, null); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, null); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopStrict, 1); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, 1); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopStrict, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopStrict, true); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, true); }, TypeError);
+ var sym = Symbol("x");
+ assertThrows(function() { Reflect.construct(noopStrict, sym); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, sym); }, TypeError);
+})();
+
+
+(function testAppliedArgumentValue() {
+ function firstStrict(a) { 'use strict'; this.a = a; }
+ function firstSloppy(a) { this.a = a; }
+ function lastStrict(a) {
+ 'use strict'; this.a = arguments[arguments.length - 1]; }
+ function lastSloppy(a) { this.a = arguments[arguments.length - 1]; }
+ function sumStrict() {
+ 'use strict';
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ this.a = sum;
+ }
+ function sumSloppy() {
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ this.a = sum;
+ }
+
+ assertEquals("OK!", Reflect.construct(firstStrict, ["OK!"]).a);
+ assertEquals("OK!", Reflect.construct(firstSloppy, ["OK!"]).a);
+ assertEquals("OK!", Reflect.construct(firstStrict,
+ { 0: "OK!", length: 1 }).a);
+ assertEquals("OK!", Reflect.construct(firstSloppy,
+ { 0: "OK!", length: 1 }).a);
+ assertEquals("OK!", Reflect.construct(lastStrict,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]).a);
+ assertEquals("OK!", Reflect.construct(lastSloppy,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]).a);
+ assertEquals("OK!", Reflect.construct(lastStrict,
+ { 9: "OK!", length: 10 }).a);
+ assertEquals("OK!", Reflect.construct(lastSloppy,
+ { 9: "OK!", length: 10 }).a);
+ assertEquals("TEST", Reflect.construct(sumStrict,
+ ["T", "E", "S", "T"]).a);
+ assertEquals("TEST!!", Reflect.construct(sumStrict,
+ ["T", "E", "S", "T", "!", "!"]).a);
+ assertEquals(10, Reflect.construct(sumStrict,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }).a);
+ assertEquals("TEST", Reflect.construct(sumSloppy,
+ ["T", "E", "S", "T"]).a);
+ assertEquals("TEST!!", Reflect.construct(sumSloppy,
+ ["T", "E", "S", "T", "!", "!"]).a);
+ assertEquals(10, Reflect.construct(sumSloppy,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }).a);
+})();
diff --git a/deps/v8/test/mjsunit/regress/regress-3501.js b/deps/v8/test/mjsunit/harmony/regress/regress-3501.js
index 4b449e458f..4b449e458f 100644
--- a/deps/v8/test/mjsunit/regress/regress-3501.js
+++ b/deps/v8/test/mjsunit/harmony/regress/regress-3501.js
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-448730.js b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-448730.js
index 31d276aa83..31d276aa83 100644
--- a/deps/v8/test/mjsunit/regress/regress-crbug-448730.js
+++ b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-448730.js
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-451770.js b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-451770.js
index 942814a316..942814a316 100644
--- a/deps/v8/test/mjsunit/regress/regress-crbug-451770.js
+++ b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-451770.js
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-crbug-461520.js b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-461520.js
new file mode 100644
index 0000000000..c30260db72
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-461520.js
@@ -0,0 +1,18 @@
+// Copyright 2015 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.
+
+// Flags: --harmony-proxies
+
+var fuse = 1;
+var handler = {
+ get: function() { return function() {} },
+ getPropertyDescriptor: function() {
+ if (fuse-- == 0) throw "please die";
+ return {value: function() {}, configurable: true};
+ }
+};
+
+var p = Proxy.create(handler);
+var o = Object.create(p);
+with (o) { f() }
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671-null.js b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671-null.js
new file mode 100644
index 0000000000..d24599c385
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671-null.js
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+// Flags: --harmony-arrow-functions
+
+// This used to trigger a segfault because of NULL being accessed.
+function f() {
+ var a = [10];
+ try {
+ f();
+ } catch(e) {
+ a.map((v) => v + 1);
+ }
+}
+f();
diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671.js b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671.js
new file mode 100644
index 0000000000..24f4d05475
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-465671.js
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+// Flags: --harmony-arrow-functions
+
+// This used to trigger crash because of an unhandled stack overflow.
+function f() {
+ var a = [10];
+ try {
+ f();
+ } catch(e) {
+ a.map(v => v + 1);
+ }
+}
+f();
diff --git a/deps/v8/test/mjsunit/harmony/rest-params.js b/deps/v8/test/mjsunit/harmony/rest-params.js
index 5bb258ee68..341cb33087 100644
--- a/deps/v8/test/mjsunit/harmony/rest-params.js
+++ b/deps/v8/test/mjsunit/harmony/rest-params.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-rest-parameters
+// Flags: --harmony-rest-parameters --harmony-classes
(function testRestIndex() {
assertEquals(5, (function(...args) { return args.length; })(1,2,3,4,5));
@@ -180,3 +180,35 @@ var O = {
assertEquals([], ((...args) => args)());
assertEquals([1,2,3], ((...args) => args)(1,2,3));
})();*/
+
+
+(function testRestParamsWithNewTarget() {
+ "use strict";
+ class Base {
+ constructor(...a) {
+ this.base = a;
+ assertEquals(arguments.length, a.length);
+ var args = [];
+ for (var i = 0; i < arguments.length; ++i) {
+ args.push(arguments[i]);
+ }
+ assertEquals(args, a);
+ }
+ }
+ class Child extends Base {
+ constructor(...b) {
+ super(1, 2, 3);
+ this.child = b;
+ assertEquals(arguments.length, b.length);
+ var args = [];
+ for (var i = 0; i < arguments.length; ++i) {
+ args.push(arguments[i]);
+ }
+ assertEquals(args, b);
+ }
+ }
+
+ var c = new Child(1, 2, 3);
+ assertEquals([1, 2, 3], c.child);
+ assertEquals([1, 2, 3], c.base);
+})();
diff --git a/deps/v8/test/mjsunit/harmony/typedarrays.js b/deps/v8/test/mjsunit/harmony/typedarrays.js
index a4d6e7927a..0cdb7ed396 100644
--- a/deps/v8/test/mjsunit/harmony/typedarrays.js
+++ b/deps/v8/test/mjsunit/harmony/typedarrays.js
@@ -530,7 +530,7 @@ function TestTypedArraysWithIllegalIndices() {
* assertEquals(undefined, a[-Infinity]);
*/
a[1.5] = 10;
- assertEquals(undefined, a[1.5]);
+ assertEquals(10, a[1.5]);
var nan = Math.sqrt(-1);
a[nan] = 5;
assertEquals(5, a[nan]);
@@ -579,7 +579,7 @@ function TestTypedArraysWithIllegalIndicesStrict() {
* assertEquals(undefined, a[-Infinity]);
*/
a[1.5] = 10;
- assertEquals(undefined, a[1.5]);
+ assertEquals(10, a[1.5]);
var nan = Math.sqrt(-1);
a[nan] = 5;
assertEquals(5, a[nan]);
diff --git a/deps/v8/test/mjsunit/json2.js b/deps/v8/test/mjsunit/json2.js
index f048f05290..f68c76c92a 100644
--- a/deps/v8/test/mjsunit/json2.js
+++ b/deps/v8/test/mjsunit/json2.js
@@ -183,3 +183,8 @@ try {
externalizeString(str, true);
} catch (e) { }
TestStringify("\"external\"", str, null, 0);
+
+var o = {};
+o.somespecialproperty = 10;
+o["\x19"] = 10;
+assertThrows("JSON.parse('{\"somespecialproperty\":100, \"\x19\":10}')");
diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status
index dc96a1de35..4b3ae5dd7c 100644
--- a/deps/v8/test/mjsunit/mjsunit.status
+++ b/deps/v8/test/mjsunit/mjsunit.status
@@ -68,6 +68,7 @@
'compare-known-objects-slow': [PASS, NO_VARIANTS],
'elements-kind': [PASS, NO_VARIANTS],
'opt-elements-kind': [PASS, NO_VARIANTS],
+ 'smi-representation': [PASS, NO_VARIANTS],
# Some tests are just too slow to run for now.
'big-object-literal': [PASS, NO_VARIANTS],
@@ -95,25 +96,11 @@
'debug-evaluate-locals': [PASS, NO_VARIANTS],
'debug-liveedit-check-stack': [PASS, NO_VARIANTS], # only in no-snap mode.
'debug-liveedit-double-call': [PASS, NO_VARIANTS],
- 'debug-step-stub-callfunction': [PASS, NO_VARIANTS],
'debug-set-variable-value': [PASS, NO_VARIANTS],
- 'debug-stepin-accessor': [PASS, NO_VARIANTS],
- 'debug-stepin-builtin': [PASS, NO_VARIANTS],
- 'debug-stepin-constructor': [PASS, NO_VARIANTS],
- 'debug-stepin-function-call': [PASS, NO_VARIANTS],
- 'debug-stepnext-do-while': [PASS, NO_VARIANTS],
'debug-stepout-scope-part1': [PASS, NO_VARIANTS],
'debug-stepout-scope-part2': [PASS, NO_VARIANTS],
'debug-stepout-scope-part3': [PASS, NO_VARIANTS],
- 'es6/debug-stepin-microtasks': [PASS, NO_VARIANTS],
- 'es6/debug-stepnext-for': [PASS, NO_VARIANTS],
- 'harmony/debug-evaluate-blockscopes': [PASS, NO_VARIANTS],
-
- # TODO(jarin): Some tests don't like --turbo-deoptimzation very much.
- 'asm/embenchen/lua_binarytrees': [SKIP],
- 'es6/symbols': [PASS, NO_VARIANTS],
- 'regress/regress-354433': [PASS, NO_VARIANTS], # only on ARM simulator.
- 'regress/regress-crbug-259300': [PASS, NO_VARIANTS],
+ 'es6/debug-evaluate-blockscopes': [PASS, NO_VARIANTS],
##############################################################################
# Too slow in debug mode with --stress-opt mode.
@@ -123,6 +110,11 @@
'regress/regress-create-exception': [PASS, ['mode == debug', SKIP]],
##############################################################################
+ # Too slow in debug mode for validation of elements.
+ 'regress/regress-430201': [PASS, ['mode == debug', SKIP]],
+ 'regress/regress-430201b': [PASS, ['mode == debug', SKIP]],
+
+ ##############################################################################
# Too slow in debug mode for GC stress mode.
'regress/regress-crbug-217858': [PASS, ['mode == debug', SKIP]],
@@ -139,6 +131,7 @@
# Very slow on ARM and MIPS, contains no architecture dependent code.
'unicode-case-overoptimization': [PASS, NO_VARIANTS, ['arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', TIMEOUT]],
+ 'regress/regress-3976': [PASS, NO_VARIANTS, ['arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]],
##############################################################################
# This test expects to reach a certain recursion depth, which may not work
@@ -185,6 +178,10 @@
# nosse2. Also for arm novfp3.
'regress/regress-2989': [FAIL, NO_VARIANTS, ['system == linux and arch == x87 or arch == arm and simulator == True', PASS]],
+ # BUG(v8:3985). Wrong materialization of arguments object after throwing
+ # an exception.
+ 'regress/regress-3985': [PASS, FAIL],
+
# Skip endain dependent test for mips due to different typed views of the same
# array buffer.
'nans': [PASS, ],
@@ -194,6 +191,9 @@
# Too slow for slow variants.
'asm/embenchen/*': [PASS, SLOW, FAST_VARIANTS],
+
+ # BUG(v8:3838).
+ 'regress/regress-3116': [PASS, ['isolates', FLAKY]],
}], # ALWAYS
##############################################################################
@@ -210,7 +210,7 @@
'fast-prototype': [SKIP],
'field-type-tracking': [SKIP],
'getters-on-elements': [SKIP],
- 'harmony/block-let-crankshaft': [SKIP],
+ 'es6/block-let-crankshaft': [SKIP],
'opt-elements-kind': [SKIP],
'osr-elements-kind': [SKIP],
'regress/regress-crbug-137689': [SKIP],
@@ -244,8 +244,10 @@
# Issue 3723.
'regress/regress-3717': [SKIP],
- # Issue 3776.
- 'debug-stepframe': [SKIP],
+ # Issue 3924.
+ 'mjsunit/debug-clearbreakpointgroup': [SKIP],
+ # Issue 3969.
+ 'mjsunit/debug-references': [SKIP],
}], # 'gc_stress == True'
##############################################################################
@@ -585,7 +587,17 @@
'readonly': [SKIP],
'array-feedback': [SKIP],
+ # Deopting uses just enough memory to make this one OOM.
+ 'regress/regress-3976': [SKIP],
+
# Deopt every n garbage collections collides with deopt every n times.
'regress/regress-2653': [SKIP],
}], # 'deopt_fuzzer == True'
+
+##############################################################################
+['arch == ppc and simulator_run == True or arch == ppc64 and simulator_run == True', {
+
+ # take too long with the simulator.
+ 'regress/regress-1132': [SKIP],
+}], # 'arch == ppc and simulator_run == True'
]
diff --git a/deps/v8/test/mjsunit/regexp-stack-overflow.js b/deps/v8/test/mjsunit/regexp-stack-overflow.js
new file mode 100644
index 0000000000..63f6971ace
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-stack-overflow.js
@@ -0,0 +1,18 @@
+// Copyright 2015 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.
+
+// Flags: --stack-size=100
+
+var re = /\w/;
+re.test("a"); // Trigger regexp compile.
+
+function rec() {
+ try {
+ return rec();
+ } catch (e) {
+ return re.test("b");
+ }
+}
+
+assertTrue(rec());
diff --git a/deps/v8/test/mjsunit/regress/regress-1530.js b/deps/v8/test/mjsunit/regress/regress-1530.js
index 20d1f265c0..fa86f62ce5 100644
--- a/deps/v8/test/mjsunit/regress/regress-1530.js
+++ b/deps/v8/test/mjsunit/regress/regress-1530.js
@@ -80,8 +80,10 @@ assertFalse(Object.getOwnPropertyDescriptor(f, 'prototype').writable);
assertThrows("'use strict'; f.prototype = {}");
assertThrows("Object.defineProperty(f, 'prototype', { value: {} })");
-// Verify that non-writability of other properties is respected.
-assertThrows("Object.defineProperty(f, 'name', { value: {} })");
-assertThrows("Object.defineProperty(f, 'length', { value: {} })");
+// Verify that non-configurability of other properties is respected, but
+// non-writability is ignored by Object.defineProperty().
+// name and length are configurable in ES6
+Object.defineProperty(f, 'name', { value: {} });
+Object.defineProperty(f, 'length', { value: {} });
assertThrows("Object.defineProperty(f, 'caller', { value: {} })");
assertThrows("Object.defineProperty(f, 'arguments', { value: {} })");
diff --git a/deps/v8/test/mjsunit/regress/regress-270142.js b/deps/v8/test/mjsunit/regress/regress-270142.js
index 6e0865c4f8..63f4d1414e 100644
--- a/deps/v8/test/mjsunit/regress/regress-270142.js
+++ b/deps/v8/test/mjsunit/regress/regress-270142.js
@@ -39,7 +39,7 @@ function g(x) {
function checkNameDescriptor(f) {
var descriptor = Object.getOwnPropertyDescriptor(f, "name");
- assertFalse(descriptor.configurable);
+ assertTrue(descriptor.configurable);
assertFalse(descriptor.enumerable);
assertFalse(descriptor.writable);
}
diff --git a/deps/v8/test/mjsunit/regress/regress-330046.js b/deps/v8/test/mjsunit/regress/regress-330046.js
index d94b804ac0..eb0d3f38a2 100644
--- a/deps/v8/test/mjsunit/regress/regress-330046.js
+++ b/deps/v8/test/mjsunit/regress/regress-330046.js
@@ -58,4 +58,4 @@ f(10, o3);
// The old code is already deoptimized, but f still points to it.
// Disassembling it will crash.
-%DebugDisassembleFunction(f);
+%DisassembleFunction(f);
diff --git a/deps/v8/test/mjsunit/regress/regress-3960.js b/deps/v8/test/mjsunit/regress/regress-3960.js
new file mode 100644
index 0000000000..4aaab0b067
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-3960.js
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+// Test that setting break point is works correctly when the debugger is
+// activated late, which leads to duplicate shared function infos.
+
+(function() {
+ var Debug = %GetDebugContext().Debug;
+
+ function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ assertTrue(/foo/.test(exec_state.frame(0).sourceLineText()));
+ break_count++;
+ } catch (e) {
+ exception = e;
+ }
+ }
+
+ for (var i = 0; i < 3; i++) {
+ var foo = function() { a = 1; }
+ var exception = null;
+ var break_count = 0;
+ Debug.setListener(listener);
+ if (i < 2) Debug.setBreakPoint(foo, 0, 0);
+ assertTrue(/\[B\d\]a = 1/.test(Debug.showBreakPoints(foo)));
+ foo();
+ assertEquals(1, break_count);
+ assertNull(exception);
+ }
+
+ Debug.setListener(null);
+})();
diff --git a/deps/v8/test/mjsunit/regress/regress-3969.js b/deps/v8/test/mjsunit/regress/regress-3969.js
new file mode 100644
index 0000000000..4659e1caf8
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-3969.js
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+function Inner() {
+ this.property = "OK";
+ this.o2 = 1;
+}
+
+function Outer(inner) {
+ this.inner = inner;
+}
+
+var inner = new Inner();
+var outer = new Outer(inner);
+
+Outer.prototype.boom = function() {
+ return this.inner.property;
+}
+
+assertEquals("OK", outer.boom());
+assertEquals("OK", outer.boom());
+%OptimizeFunctionOnNextCall(Outer.prototype.boom);
+assertEquals("OK", outer.boom());
+
+inner = undefined;
+%SetAllocationTimeout(0 /*interval*/, 2 /*timeout*/);
+// Call something that will do GC while holding a handle to outer's map.
+// The key is that this lets inner's map die while keeping outer's map alive.
+delete outer.inner;
+
+outer = new Outer({field: 1.51, property: "OK"});
+
+assertEquals("OK", outer.boom());
diff --git a/deps/v8/test/mjsunit/regress/regress-3976.js b/deps/v8/test/mjsunit/regress/regress-3976.js
new file mode 100644
index 0000000000..c151f689f4
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-3976.js
@@ -0,0 +1,80 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --max-old-space-size=60
+
+table = [];
+
+for (var i = 0; i < 32; i++) {
+ table[i] = String.fromCharCode(i + 0x410);
+}
+
+
+var random = (function() {
+ var seed = 10;
+ return function() {
+ seed = (seed * 1009) % 8831;
+ return seed;
+ };
+})();
+
+
+function key(length) {
+ var s = "";
+ for (var i = 0; i < length; i++) {
+ s += table[random() % 32];
+ }
+ return '"' + s + '"';
+}
+
+
+function value() {
+ return '[{' + '"field1" : ' + random() + ', "field2" : ' + random() + '}]';
+}
+
+
+function generate(n) {
+ var s = '{';
+ for (var i = 0; i < n; i++) {
+ if (i > 0) s += ', ';
+ s += key(random() % 10 + 7);
+ s += ':';
+ s += value();
+ }
+ s += '}';
+ return s;
+}
+
+
+print("generating");
+
+var str = generate(50000);
+
+print("parsing " + str.length);
+JSON.parse(str);
+
+print("done");
diff --git a/deps/v8/test/mjsunit/regress/regress-3985.js b/deps/v8/test/mjsunit/regress/regress-3985.js
new file mode 100644
index 0000000000..6dbc4bdadd
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-3985.js
@@ -0,0 +1,45 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+var shouldThrow = false;
+
+function h() {
+ try { // Prevent inlining in Crankshaft.
+ } catch(e) { }
+ var res = g.arguments[0].x;
+ if (shouldThrow) {
+ throw res;
+ }
+ return res;
+}
+
+function g(o) { h(); }
+
+function f1() {
+ var o = { x : 1 };
+ g(o);
+ return o.x;
+}
+
+function f2() {
+ var o = { x : 2 };
+ g(o);
+ return o.x;
+}
+
+f1();
+f2();
+f1();
+f2();
+%OptimizeFunctionOnNextCall(f1);
+%OptimizeFunctionOnNextCall(f2);
+shouldThrow = true;
+try { f1(); } catch(e) {
+ assertEquals(e, 1);
+}
+try { f2(); } catch(e) {
+ assertEquals(e, 2);
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-4023.js b/deps/v8/test/mjsunit/regress/regress-4023.js
new file mode 100644
index 0000000000..902741f6f5
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-4023.js
@@ -0,0 +1,67 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax --expose-gc --block-concurrent-recompilation
+
+function Inner() {
+ this.property = "OK";
+ this.prop2 = 1;
+}
+
+function Outer() {
+ this.o = "u";
+}
+function KeepMapAlive(o) {
+ return o.o;
+}
+function SetInner(o, i) {
+ o.inner_field = i;
+}
+function Crash(o) {
+ return o.inner_field.property;
+}
+
+var inner = new Inner();
+var outer = new Outer();
+
+// Collect type feedback.
+SetInner(new Outer(), inner);
+SetInner(outer, inner);
+
+// This function's only purpose is to stash away a Handle that keeps
+// outer's map alive during the gc() call below. We store this handle
+// on the compiler thread :-)
+KeepMapAlive(outer);
+KeepMapAlive(outer);
+%OptimizeFunctionOnNextCall(KeepMapAlive, "concurrent");
+KeepMapAlive(outer);
+
+// So far, all is well. Collect type feedback and optimize.
+print(Crash(outer));
+print(Crash(outer));
+%OptimizeFunctionOnNextCall(Crash);
+print(Crash(outer));
+
+// Null out references and perform GC. This will keep outer's map alive
+// (due to the handle created above), but will let inner's map die. Hence,
+// inner_field's field type stored in outer's map will get cleared.
+inner = undefined;
+outer = undefined;
+gc();
+
+// We could unblock the compiler thread now. But why bother?
+
+// Now optimize SetInner while inner_field's type is still cleared!
+// This will generate optimized code that stores arbitrary objects
+// into inner_field without checking their type against the field type.
+%OptimizeFunctionOnNextCall(SetInner);
+
+// Use the optimized code to store an arbitrary object into
+// o2's inner_field, without triggering any dependent code deopts...
+var o2 = new Outer();
+SetInner(o2, { invalid: 1.51, property: "OK" });
+// ...and then use the existing code expecting an Inner-class object to
+// read invalid data (in this case, a raw double).
+// We crash trying to convert the raw double into a printable string.
+print(Crash(o2));
diff --git a/deps/v8/test/mjsunit/regress/regress-4027.js b/deps/v8/test/mjsunit/regress/regress-4027.js
new file mode 100644
index 0000000000..3a5d11b8e5
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-4027.js
@@ -0,0 +1,60 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax --expose-gc
+
+function Inner() {
+ this.inner_name = "inner";
+}
+
+function Boom() {
+ this.boom = "boom";
+}
+
+function Outer() {
+ this.outer_name = "outer";
+}
+
+function SetInner(inner, value) {
+ inner.prop = value;
+}
+
+function SetOuter(outer, value) {
+ outer.inner = value;
+}
+
+var inner1 = new Inner();
+var inner2 = new Inner();
+
+SetInner(inner1, 10);
+SetInner(inner2, 10);
+
+var outer1 = new Outer();
+var outer2 = new Outer();
+var outer3 = new Outer();
+
+SetOuter(outer1, inner1);
+SetOuter(outer1, inner1);
+SetOuter(outer1, inner1);
+
+SetOuter(outer2, inner2);
+SetOuter(outer2, inner2);
+SetOuter(outer2, inner2);
+
+SetOuter(outer3, inner2);
+SetOuter(outer3, inner2);
+SetOuter(outer3, inner2);
+
+
+SetInner(inner2, 6.5);
+
+outer1 = null;
+inner1 = null;
+
+gc();
+
+var boom = new Boom();
+SetOuter(outer2, boom);
+
+gc();
diff --git a/deps/v8/test/preparser/strict-const.js b/deps/v8/test/mjsunit/regress/regress-430201b.js
index 97b908128e..056504d1d7 100644
--- a/deps/v8/test/preparser/strict-const.js
+++ b/deps/v8/test/mjsunit/regress/regress-430201b.js
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -24,8 +24,20 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Flags: --noharmony-scoping
-"use strict";
-const x = 42;
+// Flags: --allow-natives-syntax --expose-gc
+
+(function() {
+ var array_1 = [];
+
+ %SetFlags("--stress-compaction");
+ for (var a = 0; a < 10000; a++) { array_1[a * 100] = 0; }
+
+ gc();
+ gc();
+
+ var array_2 = [];
+ for (var i = 0; i < 321361; i++) {
+ array_2[i] = String.fromCharCode(i)[0];
+ }
+})();
diff --git a/deps/v8/test/mjsunit/regress/regress-460937.js b/deps/v8/test/mjsunit/regress/regress-460937.js
new file mode 100644
index 0000000000..cd57f93328
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-460937.js
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+function f() {
+ var a = new Array(100000);
+ var i = 0;
+ while (!%HasFastDoubleElements(a)) {
+ a[i] = i;
+ i += 0.1;
+ }
+ a[1] = 1.5;
+}
+
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/deps/v8/test/mjsunit/regress/regress-463028.js b/deps/v8/test/mjsunit/regress/regress-463028.js
new file mode 100644
index 0000000000..1454ef1aea
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-463028.js
@@ -0,0 +1,18 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+var o = {}
+Object.defineProperty(o, "z", {
+ set: function() {
+ %DeoptimizeFunction(f);
+ },
+});
+
+function f(o) {
+ return 19 + (void(o.z = 12));
+}
+
+f(o);
diff --git a/deps/v8/test/mjsunit/regress/regress-469605.js b/deps/v8/test/mjsunit/regress/regress-469605.js
new file mode 100644
index 0000000000..65725117bd
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-469605.js
@@ -0,0 +1,43 @@
+// Copyright 2015 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.
+
+function counter() {
+ var i = 100;
+ return function() {
+ if (i-- > 0) return i;
+ throw "done";
+ }
+}
+
+var c1 = counter();
+var c2 = counter();
+
+var f = (function() {
+ "use asm";
+ return function f(i) {
+ i = i|0;
+ do {
+ if (i > 0) c1();
+ else c2();
+ } while (true);
+ }
+})();
+
+assertThrows(function() { f(0); });
+assertThrows(function() { f(1); });
+
+var c3 = counter();
+
+var g = (function() {
+ "use asm";
+ return function g(i) {
+ i = i + 1;
+ do {
+ i = c3(i);
+ } while (true);
+ }
+})();
+
+assertThrows(function() { g(0); });
+assertThrows(function() { g(1); });
diff --git a/deps/v8/test/mjsunit/regress/regress-470804.js b/deps/v8/test/mjsunit/regress/regress-470804.js
new file mode 100644
index 0000000000..cebb91f7e0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-470804.js
@@ -0,0 +1,53 @@
+// Copyright 2015 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.
+//
+// Flags: --expose-gc
+
+function f() {
+ this.foo00 = 0;
+ this.foo01 = 0;
+ this.foo02 = 0;
+ this.foo03 = 0;
+ this.foo04 = 0;
+ this.foo05 = 0;
+ this.foo06 = 0;
+ this.foo07 = 0;
+ this.foo08 = 0;
+ this.foo09 = 0;
+ this.foo0a = 0;
+ this.foo0b = 0;
+ this.foo0c = 0;
+ this.foo0d = 0;
+ this.foo0e = 0;
+ this.foo0f = 0;
+ this.foo10 = 0;
+ this.foo11 = 0;
+ this.foo12 = 0;
+ this.foo13 = 0;
+ this.foo14 = 0;
+ this.foo15 = 0;
+ this.foo16 = 0;
+ this.foo17 = 0;
+ this.foo18 = 0;
+ this.foo19 = 0;
+ this.foo1a = 0;
+ this.foo1b = 0;
+ this.foo1c = 0;
+ this.foo1d = 0;
+ this.foo1e = 0;
+ this.foo1f = 0;
+ this.d = 1.3;
+ gc();
+ this.boom = 230;
+ this.boom = 1.4;
+}
+
+function g() {
+ return new f();
+}
+g();
+g();
+var o = g();
+assertEquals(0, o.foo00);
+assertEquals(1.4, o.boom);
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-385002.js b/deps/v8/test/mjsunit/regress/regress-crbug-385002.js
index 34713e27d4..e9023e1d6d 100644
--- a/deps/v8/test/mjsunit/regress/regress-crbug-385002.js
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-385002.js
@@ -4,7 +4,7 @@
// Flags: --stack-size=200 --allow-natives-syntax
-%Break(); // Schedule an interrupt that does not go away.
+%ScheduleBreak(); // Schedule an interrupt that does not go away.
function f() { f(); }
assertThrows(f, RangeError);
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-401915.js b/deps/v8/test/mjsunit/regress/regress-crbug-401915.js
index 96dce04868..67ea19158e 100644
--- a/deps/v8/test/mjsunit/regress/regress-crbug-401915.js
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-401915.js
@@ -10,7 +10,7 @@ Debug.setBreakOnException();
try {
try {
- %DebugPushPromise(new Promise(function() {}));
+ %DebugPushPromise(new Promise(function() {}), function() {});
} catch (e) {
}
throw new Error();
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-465564.js b/deps/v8/test/mjsunit/regress/regress-crbug-465564.js
new file mode 100644
index 0000000000..ea0c8dcf66
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-465564.js
@@ -0,0 +1,7 @@
+// 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.
+
+// Flags: --allow-natives-syntax --cache=code
+
+assertEquals(-1, %StringCompare("a", "b"));
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-467047.js b/deps/v8/test/mjsunit/regress/regress-crbug-467047.js
new file mode 100644
index 0000000000..373e984a2c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-467047.js
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+// Flags: --stack-size=100
+
+function captureMatch(re) {
+ var local_variable = 0;
+ "abcd".replace(re, function() { });
+ assertEquals("abcd", RegExp.input);
+ assertEquals("a", RegExp.leftContext);
+ assertEquals("bc", RegExp.lastMatch);
+ assertEquals("d", RegExp.rightContext);
+ assertEquals("foo", captureMatch(/^bar/));
+}
+
+assertThrows(function() { captureMatch(/(bc)/) }, RangeError);
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-467531.js b/deps/v8/test/mjsunit/regress/regress-crbug-467531.js
new file mode 100644
index 0000000000..73256c7acc
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-467531.js
@@ -0,0 +1,25 @@
+// Copyright 2015 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.
+
+// Flags: --turbo-filter=* --always-opt
+
+assertThrows(function() {
+ "use strict";
+ try {
+ x = ref_error;
+ let x = 0;
+ } catch (e) {
+ throw e;
+ }
+}, ReferenceError);
+
+assertThrows(function() {
+ "use strict";
+ try {
+ x = ref_error;
+ let x = 0;
+ } finally {
+ // re-throw
+ }
+}, ReferenceError);
diff --git a/deps/v8/test/mjsunit/regress/regress-filter-contexts.js b/deps/v8/test/mjsunit/regress/regress-filter-contexts.js
new file mode 100644
index 0000000000..d2abe00325
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-filter-contexts.js
@@ -0,0 +1,14 @@
+// Copyright 2015 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.
+
+// Flags: --allow-natives-syntax
+
+function f() { return f.x; }
+f.__proto__ = null;
+f.prototype = "";
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/deps/v8/test/mjsunit/regress/regress-function-length-strict.js b/deps/v8/test/mjsunit/regress/regress-function-length-strict.js
index 700f34a67a..77cca24054 100644
--- a/deps/v8/test/mjsunit/regress/regress-function-length-strict.js
+++ b/deps/v8/test/mjsunit/regress/regress-function-length-strict.js
@@ -37,5 +37,5 @@ var desc = Object.getOwnPropertyDescriptor(foo, 'length');
assertEquals(3, desc.value);
assertFalse(desc.writable);
assertFalse(desc.enumerable);
-assertFalse(desc.configurable);
+assertTrue(desc.configurable);
assertThrows(function() { foo.length = 2; }, TypeError);
diff --git a/deps/v8/test/mjsunit/regress/string-compare-memcmp.js b/deps/v8/test/mjsunit/regress/string-compare-memcmp.js
index 45f47343ee..ae4b33ace9 100644
--- a/deps/v8/test/mjsunit/regress/string-compare-memcmp.js
+++ b/deps/v8/test/mjsunit/regress/string-compare-memcmp.js
@@ -4,4 +4,4 @@
// Flags: --allow-natives-syntax
-assertEquals(-1, %StringCompare("abc\u0102", "abc\u0201"));
+assertEquals(-1, %StringCompareRT("abc\u0102", "abc\u0201"));
diff --git a/deps/v8/test/mjsunit/stack-traces.js b/deps/v8/test/mjsunit/stack-traces.js
index f80a627b24..b256033b53 100644
--- a/deps/v8/test/mjsunit/stack-traces.js
+++ b/deps/v8/test/mjsunit/stack-traces.js
@@ -94,6 +94,37 @@ function testAnonymousMethod() {
(function () { FAIL }).call([1, 2, 3]);
}
+function testFunctionName() {
+ function gen(name, counter) {
+ var f = function foo() {
+ if (counter === 0) {
+ FAIL;
+ }
+ gen(name, counter - 1)();
+ }
+ if (counter === 4) {
+ Object.defineProperty(f, 'name', {get: function(){ throw 239; }});
+ } else if (counter == 3) {
+ Object.defineProperty(f, 'name', {value: 'boo' + '_' + counter});
+ } else {
+ Object.defineProperty(f, 'name', {writable: true});
+ if (counter === 2)
+ f.name = 42;
+ else
+ f.name = name + '_' + counter;
+ }
+ return f;
+ }
+ gen('foo', 4)();
+}
+
+function testFunctionInferredName() {
+ var f = function() {
+ FAIL;
+ }
+ f();
+}
+
function CustomError(message, stripPoint) {
this.message = message;
Error.captureStackTrace(this, stripPoint);
@@ -261,6 +292,9 @@ testTrace("testValue", testValue, ["at Number.causeError"]);
testTrace("testConstructor", testConstructor, ["new Plonk"]);
testTrace("testRenamedMethod", testRenamedMethod, ["Wookie.a$b$c$d [as d]"]);
testTrace("testAnonymousMethod", testAnonymousMethod, ["Array.<anonymous>"]);
+testTrace("testFunctionName", testFunctionName,
+ [" at foo_0 ", " at foo_1", " at foo ", " at boo_3 ", " at foo "]);
+testTrace("testFunctionInferredName", testFunctionInferredName, [" at f "]);
testTrace("testDefaultCustomError", testDefaultCustomError,
["hep-hey", "new CustomError"],
["collectStackTrace"]);
diff --git a/deps/v8/test/mjsunit/strict-mode.js b/deps/v8/test/mjsunit/strict-mode.js
index d0839ba0fb..c97429f7b7 100644
--- a/deps/v8/test/mjsunit/strict-mode.js
+++ b/deps/v8/test/mjsunit/strict-mode.js
@@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --turbo-deoptimization --noharmony-scoping
-// Flags: --noharmony-classes --noharmony-object-literals
+// Flags: --turbo-deoptimization
function CheckStrictMode(code, exception) {
assertDoesNotThrow(code);
@@ -287,19 +286,6 @@ CheckStrictMode("function strict() { print(--arguments); }", SyntaxError);
CheckStrictMode("function strict() { var x = --eval; }", SyntaxError);
CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError);
-// Use of const in strict mode is disallowed in anticipation of ES Harmony.
-CheckStrictMode("const x = 0;", SyntaxError);
-CheckStrictMode("for (const x = 0; false;) {}", SyntaxError);
-CheckStrictMode("function strict() { const x = 0; }", SyntaxError);
-
-// Strict mode only allows functions in StatementList
-CheckStrictMode("if (true) { function invalid() {} }", SyntaxError);
-CheckStrictMode("for (;false;) { function invalid() {} }", SyntaxError);
-CheckStrictMode("{ function invalid() {} }", SyntaxError);
-CheckStrictMode("try { function invalid() {} } catch(e) {}", SyntaxError);
-CheckStrictMode("try { } catch(e) { function invalid() {} }", SyntaxError);
-CheckStrictMode("function outer() {{ function invalid() {} }}", SyntaxError);
-
// Delete of an unqualified identifier
CheckStrictMode("delete unqualified;", SyntaxError);
CheckStrictMode("function strict() { delete unqualified; }", SyntaxError);
diff --git a/deps/v8/test/mjsunit/string-concat.js b/deps/v8/test/mjsunit/string-concat.js
new file mode 100644
index 0000000000..c669b3bd4b
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-concat.js
@@ -0,0 +1,14 @@
+// Copyright 2015 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.
+
+function Stringified(toString) {
+ var valueOf = "-" + toString + "-";
+ return {
+ toString: function() { return toString; },
+ valueOf: function() { return valueOf; }
+ };
+}
+
+assertEquals("a.b.", "a.".concat(Stringified("b.")));
+assertEquals("a.b.c.", "a.".concat(Stringified("b."), Stringified("c.")));
diff --git a/deps/v8/test/mjsunit/string-index.js b/deps/v8/test/mjsunit/string-index.js
index 315708ca5f..1c0e3d915d 100644
--- a/deps/v8/test/mjsunit/string-index.js
+++ b/deps/v8/test/mjsunit/string-index.js
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Flags: --allow-natives-syntax
+
/**
* @fileoverview Test indexing on strings with [].
*/
@@ -250,6 +252,20 @@ for (var i = 0; i < 100; ++i) {
assertEquals(expected, actual);
}
+// Test out of range with a heap number case.
+var num = Math.floor(4) * 0.5;
+// TODO(mvstanton): figure out a reliable way to get a heap number every time.
+// assertFalse(!%_IsSmi(num));
+var keys = [0, num];
+var str = 'ab', arr = ['a', undefined];
+for (var i = 0; i < 100; ++i) {
+ var index = Math.floor(i / 50);
+ var key = keys[index];
+ var expected = arr[index];
+ var actual = str[key];
+ assertEquals(expected, actual);
+}
+
// Test two byte string.
var str = '\u0427', arr = ['\u0427'];
for (var i = 0; i < 50; ++i) {
diff --git a/deps/v8/test/mjsunit/strong/arrays.js b/deps/v8/test/mjsunit/strong/arrays.js
new file mode 100644
index 0000000000..b9e4fad357
--- /dev/null
+++ b/deps/v8/test/mjsunit/strong/arrays.js
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+// Flags: --strong-mode
+
+(function NoEllisions() {
+ assertThrows("'use strong'; [,]", SyntaxError);
+ assertThrows("'use strong'; [,3]", SyntaxError);
+ assertThrows("'use strong'; [3,,4]", SyntaxError);
+ assertTrue(eval("'use strong'; [3,] !== [3,4,]"));
+})();
diff --git a/deps/v8/test/mjsunit/strong/classes.js b/deps/v8/test/mjsunit/strong/classes.js
index 3c7caf5f84..e33742af3f 100644
--- a/deps/v8/test/mjsunit/strong/classes.js
+++ b/deps/v8/test/mjsunit/strong/classes.js
@@ -3,15 +3,58 @@
// found in the LICENSE file.
// Flags: --strong-mode
+// Flags: --harmony-classes --harmony-arrow-functions
'use strong';
class C {}
+function assertTypeError(script) { assertThrows(script, TypeError) }
+function assertSyntaxError(script) { assertThrows(script, SyntaxError) }
+function assertReferenceError(script) { assertThrows(script, ReferenceError) }
+
(function ImmutableClassBindings() {
class D {}
- assertThrows(function(){ eval("C = 0") }, TypeError);
- assertThrows(function(){ eval("D = 0") }, TypeError);
+ assertTypeError(function(){ eval("C = 0") });
+ assertTypeError(function(){ eval("D = 0") });
assertEquals('function', typeof C);
assertEquals('function', typeof D);
})();
+
+function constructor(body) {
+ return "'use strong'; " +
+ "(class extends Object { constructor() { " + body + " } })";
+}
+
+(function NoMissingSuper() {
+ assertReferenceError(constructor(""));
+ assertReferenceError(constructor("1"));
+})();
+
+(function NoNestedSuper() {
+ assertSyntaxError(constructor("(super());"));
+ assertSyntaxError(constructor("(() => super())();"));
+ assertSyntaxError(constructor("{ super(); }"));
+ assertSyntaxError(constructor("if (1) super();"));
+})();
+
+(function NoDuplicateSuper() {
+ assertSyntaxError(constructor("super(), super();"));
+ assertSyntaxError(constructor("super(); super();"));
+ assertSyntaxError(constructor("super(); (super());"));
+ assertSyntaxError(constructor("super(); { super() }"));
+ assertSyntaxError(constructor("super(); (() => super())();"));
+})();
+
+(function NoReturnValue() {
+ assertSyntaxError(constructor("return {};"));
+ assertSyntaxError(constructor("return undefined;"));
+ assertSyntaxError(constructor("{ return {}; }"));
+ assertSyntaxError(constructor("if (1) return {};"));
+})();
+
+(function NoReturnBeforeSuper() {
+ assertSyntaxError(constructor("return; super();"));
+ assertSyntaxError(constructor("if (0) return; super();"));
+ assertSyntaxError(constructor("{ return; } super();"));
+})();
diff --git a/deps/v8/test/mjsunit/strong/declaration-after-use.js b/deps/v8/test/mjsunit/strong/declaration-after-use.js
new file mode 100644
index 0000000000..aa5ff67283
--- /dev/null
+++ b/deps/v8/test/mjsunit/strong/declaration-after-use.js
@@ -0,0 +1,258 @@
+// Copyright 2015 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.
+
+// Flags: --strong-mode --harmony_rest_parameters --harmony_arrow_functions --harmony_classes --harmony_computed-property_names
+
+// Note that it's essential for these tests that the reference is inside dead
+// code (because we already produce ReferenceErrors for run-time unresolved
+// variables and don't want to confuse those with strong mode errors). But the
+// errors should *not* be inside lazy, unexecuted functions, since lazy parsing
+// doesn't produce strong mode scoping errors).
+
+// In addition, assertThrows will call eval and that changes variable binding
+// types (see e.g., UNBOUND_EVAL_SHADOWED). We can avoid unwanted side effects
+// by wrapping the code to be tested inside an outer function.
+function assertThrowsHelper(code) {
+ "use strict";
+ let prologue = "(function outer() { if (false) { ";
+ let epilogue = " } })();";
+
+ assertThrows("'use strong'; " + prologue + code + epilogue, ReferenceError);
+
+ // Make sure the error happens only in strong mode (note that we need strict
+ // mode here because of let).
+ assertDoesNotThrow("'use strict'; " + prologue + code + epilogue);
+}
+
+(function DeclarationAfterUse() {
+ // Note that these tests only test cases where the declaration is found but is
+ // after the use. In particular, we cannot yet detect cases where the use can
+ // possibly bind to a global variable.
+ assertThrowsHelper("x; let x = 0;");
+ assertThrowsHelper("function f() { x; let x = 0; }");
+ assertThrowsHelper("function f() { x; } let x = 0;");
+
+ // These tests needs to be done a bit more manually, since var is not allowed
+ // in strong mode:
+ assertThrows(
+ `(function outer() {
+ function f() { 'use strong'; if (false) { x; } } var x = 0; f();
+ })()`,
+ ReferenceError);
+ assertDoesNotThrow(
+ "(function outer() {\n" +
+ " function f() { if (false) { x; } } var x = 0; f(); \n" +
+ "})()");
+
+ assertThrows(
+ "(function outer() {\n" +
+ " function f() { 'use strong'; if (false) { x; } } var x; f(); \n" +
+ "})()",
+ ReferenceError);
+ assertDoesNotThrow(
+ "(function outer() {\n" +
+ " function f() { if (false) { x; } } var x; f(); \n" +
+ "})()");
+
+ // Errors are also detected when the declaration and the use are in the same
+ // eval scope.
+ assertThrows("'use strong'; eval('if (false) { x; let x = 0;}')",
+ ReferenceError);
+ assertDoesNotThrow("'use strict'; eval('if (false) { x; let x = 0; }')");
+
+ // Use occurring in the initializer of the declaration:
+ assertThrowsHelper("let x = x + 1;");
+ assertThrowsHelper("let x = x;");
+ assertThrowsHelper("let x = y, y = 4;");
+ assertThrowsHelper("let x = function() { x; }");
+ assertThrowsHelper("let x = a => { x; }");
+ assertThrowsHelper("function f(x) { return x; }; let x = f(x);");
+ assertThrowsHelper("const x = x;");
+ assertThrowsHelper("const x = function() { x; }");
+ assertThrowsHelper("const x = a => { x; }");
+ assertThrowsHelper("function f(x) {return x}; const x = f(x);");
+
+ assertThrowsHelper("for (let x = x; ; ) { }");
+ assertThrowsHelper("for (const x = x; ; ) { }");
+ assertThrowsHelper("for (let x = y, y; ; ) { }");
+ assertThrowsHelper("for (const x = y, y = 0; ; ) { }");
+
+ // Computed property names
+ assertThrowsHelper("let o = { 'a': 'b', [o.a]: 'c'};");
+})();
+
+
+(function DeclarationAfterUseInClasses() {
+ assertThrowsHelper("class C extends C { }");
+ assertThrowsHelper("let C = class C2 extends C { }");
+ assertThrowsHelper("let C = class C2 extends C2 { }");
+
+ assertThrowsHelper("let C = class C2 { constructor() { C; } }");
+ assertThrowsHelper("let C = class C2 { method() { C; } }");
+ assertThrowsHelper("let C = class C2 { *generator_method() { C; } }");
+
+ assertThrowsHelper(
+ `let C = class C2 {
+ static a() { return 'A'; }
+ [C.a()]() { return 'B'; }
+ };`);
+
+ assertThrowsHelper(
+ `let C = class C2 {
+ static a() { return 'A'; }
+ [C2.a()]() { return 'B'; }
+ };`);
+
+ assertThrowsHelper(
+ `let C = class C2 {
+ [(function() { C; return 'A';})()]() { return 'B'; }
+ };`);
+
+ // The reference to C or C2 is inside a function, but not a method.
+ assertThrowsHelper(
+ `let C = class C2 {
+ [(function() { C2; return 'A';})()]() { return 'B'; }
+ };`);
+
+ assertThrowsHelper(
+ `let C = class C2 {
+ [(function() { C; return 'A';})()]() { return 'B'; }
+ };`);
+
+ // The reference to C or C2 is inside a method, but it's not a method of the
+ // relevant class (C2).
+ assertThrowsHelper(
+ `let C = class C2 {
+ [(new (class D { m() { C2; return 'A'; } })).m()]() {
+ return 'B';
+ }
+ }`);
+
+ assertThrowsHelper(
+ `let C = class C2 {
+ [(new (class D { m() { C; return 'A'; } })).m()]() {
+ return 'B';
+ }
+ }`);
+
+ assertThrowsHelper(
+ `let C = class C2 {
+ [({m() { C2; return 'A'; }}).m()]() { return 'B'; }
+ }`);
+
+ assertThrowsHelper(
+ `let C = class C2 {
+ [({m() { C; return 'A'; }}).m()]() { return 'B'; }
+ }`);
+
+ assertThrowsHelper(
+ `class COuter {
+ m() {
+ class CInner {
+ [({ m() { CInner; return 'A'; } }).m()]() {
+ return 'B';
+ }
+ }
+ }
+ }`);
+})();
+
+
+(function UsesWhichAreFine() {
+ "use strong";
+
+ let var1 = 0;
+ var1;
+
+ let var2a = 0, var2b = var2a + 1, var2c = 2 + var2b;
+
+ for (let var3 = 0; var3 < 1; var3++) {
+ var3;
+ }
+
+ for (let var4a = 0, var4b = var4a; var4a + var4b < 4; var4a++, var4b++) {
+ var4a;
+ var4b;
+ }
+
+ let var5 = 5;
+ for (; var5 < 10; ++var5) { }
+
+ let arr = [1, 2];
+ for (let i of arr) {
+ i;
+ }
+
+ let var6 = [1, 2];
+ // The second var6 resolves to outside (not to the first var6).
+ for (let var6 of var6) { var6; }
+
+ try {
+ throw "error";
+ } catch (e) {
+ e;
+ }
+
+ function func1() { func1; this; }
+ func1();
+ func1;
+
+ function * func2() { func2; this; }
+ func2();
+ func2;
+
+ function func4(p, ...rest) { p; rest; this; func2; }
+ func4();
+
+ let func5 = (p1, p2) => { p1; p2; };
+ func5();
+
+ let func5b = p1 => p1;
+ func5b();
+
+ function func6() {
+ var1, var2a, var2b, var2c;
+ }
+
+ (function eval1() {
+ let var7 = 0; // Declaration position will be something large.
+ // But use position will be something small, however, this is not an error,
+ // since the use is inside an eval scope.
+ eval("var7;");
+ })();
+
+
+ class C1 { constructor() { C1; } }; new C1();
+ let C2 = class C3 { constructor() { C3; } }; new C2();
+
+ class C4 { method() { C4; } *generator_method() { C4; } }; new C4();
+ let C5 = class C6 { method() { C6; } *generator_method() { C6; } }; new C5();
+
+ class C7 { static method() { C7; } }; new C7();
+ let C8 = class C9 { static method() { C9; } }; new C8();
+
+ class C10 { get x() { C10; } }; new C10();
+ let C11 = class C12 { get x() { C12; } }; new C11();
+
+ // Regression test for unnamed classes.
+ let C13 = class { m() { var1; } };
+
+ class COuter {
+ m() {
+ class CInner {
+ // Here we can refer to COuter but not to CInner (see corresponding
+ // assertion test):
+ [({ m() { COuter; return 'A'; } }).m()]() { return 'B'; }
+ // And here we can refer to both:
+ n() { COuter; CInner; }
+ }
+ return new CInner();
+ }
+ }
+ (new COuter()).m().n();
+
+ // Making sure the check which is supposed to prevent "object literal inside
+ // computed property name references the class name" is not too generic:
+ class C14 { m() { let obj = { n() { C14 } }; obj.n(); } }; (new C14()).m();
+})();
diff --git a/deps/v8/test/mjsunit/strong/functions.js b/deps/v8/test/mjsunit/strong/functions.js
index 4869ac6dfa..6956462e5d 100644
--- a/deps/v8/test/mjsunit/strong/functions.js
+++ b/deps/v8/test/mjsunit/strong/functions.js
@@ -6,28 +6,82 @@
'use strong';
+function f() {}
+function* g() {}
+
(function NoArguments() {
assertThrows("'use strong'; arguments", SyntaxError);
assertThrows("'use strong'; function f() { arguments }", SyntaxError);
+ assertThrows("'use strong'; function* g() { arguments }", SyntaxError);
assertThrows("'use strong'; let f = function() { arguments }", SyntaxError);
+ assertThrows("'use strong'; let g = function*() { arguments }", SyntaxError);
assertThrows("'use strong'; let f = () => arguments", SyntaxError);
// The following are strict mode errors already.
assertThrows("'use strong'; let arguments", SyntaxError);
assertThrows("'use strong'; function f(arguments) {}", SyntaxError);
+ assertThrows("'use strong'; function* g(arguments) {}", SyntaxError);
assertThrows("'use strong'; let f = (arguments) => {}", SyntaxError);
})();
-function g() {}
+(function NoArgumentsProperty() {
+ assertFalse(f.hasOwnProperty("arguments"));
+ assertFalse(g.hasOwnProperty("arguments"));
+ assertThrows(function(){ f.arguments = 0 }, TypeError);
+ assertThrows(function(){ g.arguments = 0 }, TypeError);
+})();
+
+(function NoCaller() {
+ assertFalse(f.hasOwnProperty("caller"));
+ assertFalse(g.hasOwnProperty("caller"));
+ assertThrows(function(){ f.caller = 0 }, TypeError);
+ assertThrows(function(){ g.caller = 0 }, TypeError);
+})();
+
+(function NoCallee() {
+ assertFalse("callee" in f);
+ assertFalse("callee" in g);
+ assertThrows(function(){ f.callee = 0 }, TypeError);
+ assertThrows(function(){ g.callee = 0 }, TypeError);
+})();
-(function LexicalFunctionBindings(global) {
+(function LexicalBindings(global) {
+ assertEquals('function', typeof f);
assertEquals('function', typeof g);
+ assertEquals(undefined, global.f);
assertEquals(undefined, global.g);
})(this);
-(function ImmutableFunctionBindings() {
- function f() {}
- assertThrows(function(){ eval("g = 0") }, TypeError);
- assertThrows(function(){ eval("f = 0") }, TypeError);
- assertEquals('function', typeof g);
+(function ImmutableBindings() {
+ function f2() {}
+ function* g2() {}
+ assertThrows(function(){ f = 0 }, TypeError);
+ assertThrows(function(){ g = 0 }, TypeError);
+ assertThrows(function(){ f2 = 0 }, TypeError);
+ assertThrows(function(){ g2 = 0 }, TypeError);
assertEquals('function', typeof f);
+ assertEquals('function', typeof g);
+ assertEquals('function', typeof f2);
+ assertEquals('function', typeof g2);
+})();
+
+(function NonExtensible() {
+ assertThrows(function(){ f.a = 0 }, TypeError);
+ assertThrows(function(){ g.a = 0 }, TypeError);
+ assertThrows(function(){ Object.defineProperty(f, "a", {value: 0}) }, TypeError);
+ assertThrows(function(){ Object.defineProperty(g, "a", {value: 0}) }, TypeError);
+ assertThrows(function(){ Object.setPrototypeOf(f, {}) }, TypeError);
+ assertThrows(function(){ Object.setPrototypeOf(g, {}) }, TypeError);
+})();
+
+(function NoPrototype() {
+ assertFalse("prototype" in f);
+ assertFalse(g.hasOwnProperty("prototype"));
+ assertThrows(function(){ f.prototype = 0 }, TypeError);
+ assertThrows(function(){ g.prototype = 0 }, TypeError);
+ assertThrows(function(){ f.prototype.a = 0 }, TypeError);
+})();
+
+(function NonConstructor() {
+ assertThrows(function(){ new f }, TypeError);
+ assertThrows(function(){ new g }, TypeError);
})();
diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status
index 0d6baf0e22..a1254dbd09 100644
--- a/deps/v8/test/mozilla/mozilla.status
+++ b/deps/v8/test/mozilla/mozilla.status
@@ -61,6 +61,19 @@
# TODO(turbofan): Large switch statements crash.
'js1_5/Regress/regress-398085-01': [PASS, NO_VARIANTS],
+ ############################ INVALID TESTS #############################
+
+ # Function length properties are configurable in ES6
+ 'ecma/Array/15.4.4.3-1': [FAIL],
+ 'ecma/Array/15.4.4.4-1': [FAIL],
+ 'ecma/Array/15.4.4.4-2': [FAIL],
+ 'ecma/String/15.5.4.10-1': [FAIL],
+ 'ecma/String/15.5.4.11-1': [FAIL],
+ 'ecma/String/15.5.4.7-2': [FAIL],
+ 'ecma/String/15.5.4.8-1': [FAIL],
+ 'ecma/String/15.5.4.9-1': [FAIL],
+
+
##################### SKIPPED TESTS #####################
# This test checks that we behave properly in an out-of-memory
diff --git a/deps/v8/test/preparser/strict-function-statement.pyt b/deps/v8/test/preparser/strict-function-statement.pyt
deleted file mode 100644
index cc3d7bb582..0000000000
--- a/deps/v8/test/preparser/strict-function-statement.pyt
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright 2011 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials provided
-# with the distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# In strict mode, function declarations may only appear as source elements.
-
-# A template that performs the same strict-mode test in different
-# scopes (global scope, function scope, and nested function scope).
-def StrictTest(name, source, legacy):
- if legacy:
- extra_flags = [
- "--noharmony-scoping",
- "--noharmony-classes",
- "--noharmony-object-literals"]
- else:
- extra_flags = []
- Test(name, '"use strict";\n' + source, "strict_function",
- extra_flags)
- Test(name + '-infunc',
- 'function foo() {\n "use strict";\n' + source +'\n}\n',
- "strict_function",
- extra_flags)
- Test(name + '-infunc2',
- 'function foo() {\n "use strict";\n function bar() {\n' +
- source +'\n }\n}\n',
- "strict_function",
- extra_flags)
-
-# Not testing with-scope, since with is not allowed in strict mode at all.
-
-StrictTest("block", """
- { function foo() { } }
-""", True)
-
-StrictTest("try-w-catch", """
- try { function foo() { } } catch (e) { }
-""", True)
-
-StrictTest("try-w-finally", """
- try { function foo() { } } finally { }
-""", True)
-
-StrictTest("catch", """
- try { } catch (e) { function foo() { } }
-""", True)
-
-StrictTest("finally", """
- try { } finally { function foo() { } }
-""", True)
-
-StrictTest("for", """
- for (;;) { function foo() { } }
-""", True)
-
-StrictTest("while", """
- while (true) { function foo() { } }
-""", True)
-
-StrictTest("do", """
- do { function foo() { } } while (true);
-""", True)
-
-StrictTest("then", """
- if (true) { function foo() { } }
-""", True)
-
-
-StrictTest("then-w-else", """
- if (true) { function foo() { } } else { }
-""", True)
-
-
-StrictTest("else", """
- if (true) { } else { function foo() { } }
-""", True)
-
-StrictTest("switch-case", """
- switch (true) { case true: function foo() { } }
-""", False)
-
-StrictTest("labeled", """
- label: function foo() { }
-""", False)
-
-
-
diff --git a/deps/v8/test/test262-es6/test262-es6.status b/deps/v8/test/test262-es6/test262-es6.status
index fd93f295fa..c004242ce3 100644
--- a/deps/v8/test/test262-es6/test262-es6.status
+++ b/deps/v8/test/test262-es6/test262-es6.status
@@ -30,119 +30,119 @@
############################### BUGS ###################################
# BUG(v8:3455)
- '11.2.3_b': [FAIL],
- '12.2.3_b': [FAIL],
+ 'intl402/ch11/11.2/11.2.3_b': [FAIL],
+ 'intl402/ch12/12.2/12.2.3_b': [FAIL],
# Unicode canonicalization is not available with i18n turned off.
- '15.5.4.9_CE': [['no_i18n', SKIP]],
+ 'ch15/15.5/15.5.4/15.5.4.9/15.5.4.9_CE': [['no_i18n', SKIP]],
###################### NEEDS INVESTIGATION #######################
# Possibly same cause as S8.5_A2.1, below: floating-point tests.
- 'S15.8.2.16_A7': [PASS, FAIL_OK],
- 'S15.8.2.18_A7': [PASS, FAIL_OK],
- 'S15.8.2.7_A7': [PASS, FAIL_OK],
+ 'ch15/15.8/15.8.2/15.8.2.16/S15.8.2.16_A7': [PASS, FAIL_OK],
+ 'ch15/15.8/15.8.2/15.8.2.18/S15.8.2.18_A7': [PASS, FAIL_OK],
+ 'ch15/15.8/15.8.2/15.8.2.7/S15.8.2.7_A7': [PASS, FAIL_OK],
# This is an incompatibility between ES5 and V8 on enumerating
# shadowed elements in a for..in loop.
# https://code.google.com/p/v8/issues/detail?id=705
- '12.6.4-2': [PASS, FAIL_OK],
+ 'ch12/12.6/12.6.4/12.6.4-2': [PASS, FAIL_OK],
###################### MISSING ES6 FEATURES #######################
# Array.fill (currently requires --harmony-arrays)
- 'S22.1.3.6_T1': [FAIL],
+ 'es6/ch22/22.1/22.1.3/S22.1.3.6_T1': [FAIL],
# Array.find (currently requires --harmony-arrays)
- 'S22.1.2.3_T1': [FAIL],
- 'S22.1.2.3_T2': [FAIL],
- 'Array.prototype.find_empty-array-undefined': [FAIL],
- 'Array.prototype.find_length-property': [FAIL],
- 'Array.prototype.find_modify-after-start': [FAIL],
- 'Array.prototype.find_non-returning-predicate': [FAIL],
- 'Array.prototype.find_predicate-arguments': [FAIL],
- 'Array.prototype.find_push-after-start': [FAIL],
- 'Array.prototype.find_remove-after-start': [FAIL],
- 'Array.prototype.find_return-found-value': [FAIL],
- 'Array.prototype.find_skip-empty': [FAIL],
- 'Array.prototype.find_this-defined': [FAIL],
- 'Array.prototype.find_this-is-object': [FAIL],
- 'Array.prototype.find_this-undefined': [FAIL],
+ 'es6/ch22/22.1/22.1.2/S22.1.2.3_T1': [FAIL],
+ 'es6/ch22/22.1/22.1.2/S22.1.2.3_T2': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_empty-array-undefined': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_length-property': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_modify-after-start': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_non-returning-predicate': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_predicate-arguments': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_push-after-start': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_remove-after-start': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_return-found-value': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_skip-empty': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_this-defined': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_this-is-object': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_this-undefined': [FAIL],
# Array.from
- 'S22.1.2.1_T1': [FAIL],
- 'S22.1.2.1_T2': [FAIL],
+ 'es6/ch22/22.1/22.1.2/S22.1.2.1_T1': [FAIL],
+ 'es6/ch22/22.1/22.1.2/S22.1.2.1_T2': [FAIL],
# Direct proxies
- 'Array.prototype.find_callable-predicate': [FAIL],
+ 'es6/Array.prototype.find/Array.prototype.find_callable-predicate': [FAIL],
######################## OBSOLETED BY ES6 ###########################
# ES6 allows duplicate properties
- '11.1.5-4-4-a-1-s': [FAIL],
- '11.1.5_4-4-b-1': [FAIL],
- '11.1.5_4-4-b-2': [FAIL],
- '11.1.5_4-4-c-1': [FAIL],
- '11.1.5_4-4-c-2': [FAIL],
- '11.1.5_4-4-d-1': [FAIL],
- '11.1.5_4-4-d-2': [FAIL],
- '11.1.5_4-4-d-3': [FAIL],
- '11.1.5_4-4-d-4': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5-4-4-a-1-s': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-b-1': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-b-2': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-c-1': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-c-2': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-d-1': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-d-2': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-d-3': [FAIL],
+ 'ch11/11.1/11.1.5/11.1.5_4-4-d-4': [FAIL],
# ES6 does ToObject for Object.prototype.getOwnPropertyNames
- '15.2.3.4-1': [FAIL],
- '15.2.3.4-1-4': [FAIL],
- '15.2.3.4-1-5': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-4': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-5': [FAIL],
# ES6 allows block-local functions.
- 'Sbp_A1_T1': [FAIL],
- 'Sbp_A2_T1': [FAIL],
- 'Sbp_A2_T2': [FAIL],
- 'Sbp_A3_T1': [FAIL],
- 'Sbp_A3_T2': [FAIL],
- 'Sbp_A4_T1': [FAIL],
- 'Sbp_A4_T2': [FAIL],
- 'Sbp_A5_T1': [PASS], # Test is broken (strict reference to unbound variable)
- 'Sbp_A5_T2': [FAIL],
+ 'bestPractice/Sbp_A1_T1': [FAIL],
+ 'bestPractice/Sbp_A2_T1': [FAIL],
+ 'bestPractice/Sbp_A2_T2': [FAIL],
+ 'bestPractice/Sbp_A3_T1': [FAIL],
+ 'bestPractice/Sbp_A3_T2': [FAIL],
+ 'bestPractice/Sbp_A4_T1': [FAIL],
+ 'bestPractice/Sbp_A4_T2': [FAIL],
+ 'bestPractice/Sbp_A5_T1': [PASS], # Test is broken (strict reference to unbound variable)
+ 'bestPractice/Sbp_A5_T2': [FAIL],
######################## NEEDS INVESTIGATION ###########################
# These test failures are specific to the intl402 suite and need investigation
# to be either marked as bugs with issues filed for them or as deliberate
# incompatibilities if the test cases turn out to be broken or ambiguous.
- '6.2.3': [FAIL],
- '9.2.1_2': [FAIL],
- '9.2.6_2': [FAIL],
- '10.1.1_a': [FAIL],
- '10.1.1_19_c': [PASS, FAIL, NO_VARIANTS],
- '10.1.2.1_4': [FAIL],
- '10.2.3_b': [PASS, FAIL],
- '10.3_a': [FAIL],
- '11.1.1_17': [PASS, FAIL],
- '11.1.1_19': [PASS, FAIL],
- '11.1.1_20_c': [FAIL],
- '11.1.1_a': [FAIL],
- '11.1.2.1_4': [FAIL],
- '11.3.2_FN_2': [PASS, FAIL],
- '11.3.2_TRF': [PASS, FAIL],
- '11.3_a': [FAIL],
- '12.1.1_a': [FAIL],
- '12.1.2.1_4': [FAIL],
- '12.3.2_FDT_7_a_iv': [FAIL],
- '12.3.3': [FAIL],
- '12.3_a': [FAIL],
- '15.5.4.9_3': [PASS, FAIL],
+ 'intl402/ch06/6.2/6.2.3': [FAIL],
+ 'intl402/ch09/9.2/9.2.1_2': [FAIL],
+ 'intl402/ch09/9.2/9.2.6_2': [FAIL],
+ 'intl402/ch10/10.1/10.1.1_a': [FAIL],
+ 'intl402/ch10/10.1/10.1.1_19_c': [PASS, FAIL, NO_VARIANTS],
+ 'intl402/ch10/10.1/10.1.2.1_4': [FAIL],
+ 'intl402/ch10/10.2/10.2.3_b': [PASS, FAIL],
+ 'intl402/ch10/10.3/10.3_a': [FAIL],
+ 'intl402/ch11/11.1/11.1.1_17': [PASS, FAIL],
+ 'intl402/ch11/11.1/11.1.1_19': [PASS, FAIL],
+ 'intl402/ch11/11.1/11.1.1_20_c': [FAIL],
+ 'intl402/ch11/11.1/11.1.1_a': [FAIL],
+ 'intl402/ch11/11.1/11.1.2.1_4': [FAIL],
+ 'intl402/ch11/11.3/11.3.2_FN_2': [PASS, FAIL],
+ 'intl402/ch11/11.3/11.3.2_TRF': [PASS, FAIL],
+ 'intl402/ch11/11.3/11.3_a': [FAIL],
+ 'intl402/ch12/12.1/12.1.1_a': [FAIL],
+ 'intl402/ch12/12.1/12.1.2.1_4': [FAIL],
+ 'intl402/ch12/12.3/12.3.2_FDT_7_a_iv': [FAIL],
+ 'intl402/ch12/12.3/12.3.3': [FAIL],
+ 'intl402/ch12/12.3/12.3_a': [FAIL],
+ 'intl402/ch15/15.5/15.5.4/15.5.4.915.5.4.9_3': [PASS, FAIL],
##################### DELIBERATE INCOMPATIBILITIES #####################
- 'S15.8.2.8_A6': [PASS, FAIL_OK], # Math.exp (less precise with --fast-math)
+ 'ch15/15.8/15.8.2/15.8.2.8/S15.8.2.8_A6': [PASS, FAIL_OK], # Math.exp (less precise with --fast-math)
# Linux for ia32 (and therefore simulators) default to extended 80 bit
# floating point formats, so these tests checking 64-bit FP precision fail.
# The other platforms/arch's pass these tests.
# We follow the other major JS engines by keeping this default.
- 'S8.5_A2.1': [PASS, FAIL_OK],
- 'S8.5_A2.2': [PASS, FAIL_OK],
+ 'ch08/8.5/S8.5_A2.1': [PASS, FAIL_OK],
+ 'ch08/8.5/S8.5_A2.2': [PASS, FAIL_OK],
############################ INVALID TESTS #############################
@@ -150,55 +150,181 @@
# tests in PST/PDT between first Sunday in March and first Sunday in April.
# The DST switch was moved in 2007 whereas Test262 bases the reference value
# on 2000. Test262 Bug: https://bugs.ecmascript.org/show_bug.cgi?id=293
- 'S15.9.3.1_A5_T1': [PASS, FAIL_OK],
- 'S15.9.3.1_A5_T2': [PASS, FAIL_OK],
- 'S15.9.3.1_A5_T3': [PASS, FAIL_OK],
- 'S15.9.3.1_A5_T4': [PASS, FAIL_OK],
- 'S15.9.3.1_A5_T5': [PASS, FAIL_OK],
- 'S15.9.3.1_A5_T6': [PASS, FAIL_OK],
+ 'ch15/15.9/15.9.3/S15.9.3.1_A5_T1': [PASS, FAIL_OK],
+ 'ch15/15.9/15.9.3/S15.9.3.1_A5_T2': [PASS, FAIL_OK],
+ 'ch15/15.9/15.9.3/S15.9.3.1_A5_T3': [PASS, FAIL_OK],
+ 'ch15/15.9/15.9.3/S15.9.3.1_A5_T4': [PASS, FAIL_OK],
+ 'ch15/15.9/15.9.3/S15.9.3.1_A5_T5': [PASS, FAIL_OK],
+ 'ch15/15.9/15.9.3/S15.9.3.1_A5_T6': [PASS, FAIL_OK],
# Test makes unjustified assumptions about the number of calls to SortCompare.
# Test262 Bug: https://bugs.ecmascript.org/show_bug.cgi?id=596
- 'bug_596_1': [PASS, FAIL_OK],
+ 'es6/bug_596_1': [PASS, FAIL_OK],
# Tests do not return boolean.
- '15.2.3.14-1-1': [PASS, FAIL_OK],
- '15.2.3.14-1-2': [PASS, FAIL_OK],
- '15.2.3.14-1-3': [PASS, FAIL_OK],
+ 'ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-1': [PASS, FAIL_OK],
+ 'ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-2': [PASS, FAIL_OK],
+ 'ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-3': [PASS, FAIL_OK],
# String.prototype.contains renamed to 'S.p.includes'
- 'String.prototype.contains_FailBadLocation' : [FAIL_OK],
- 'String.prototype.contains_FailLocation' : [FAIL_OK],
- 'String.prototype.contains_FailMissingLetter' : [FAIL_OK],
- 'String.prototype.contains_lengthProp' : [FAIL_OK],
- 'String.prototype.contains_Success' : [FAIL_OK],
- 'String.prototype.contains_SuccessNoLocation' : [FAIL_OK],
-
+ 'es6/String.prototype.contains/String.prototype.contains_FailBadLocation' : [FAIL_OK],
+ 'es6/String.prototype.contains/String.prototype.contains_FailLocation' : [FAIL_OK],
+ 'es6/String.prototype.contains/String.prototype.contains_FailMissingLetter' : [FAIL_OK],
+ 'es6/String.prototype.contains/String.prototype.contains_lengthProp' : [FAIL_OK],
+ 'es6/String.prototype.contains/String.prototype.contains_Success' : [FAIL_OK],
+ 'es6/String.prototype.contains/String.prototype.contains_SuccessNoLocation' : [FAIL_OK],
+
+ # Function length properties are configurable in ES6
+ 'ch11/11.4/11.4.1/11.4.1-5-a-28-s': [FAIL],
+ 'ch13/13.2/13.2-15-1': [FAIL],
+ 'ch15/15.1/15.1.2/15.1.2.1/S15.1.2.1_A4.2': [FAIL],
+ 'ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A9.2': [FAIL],
+ 'ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A7.2': [FAIL],
+ 'ch15/15.1/15.1.2/15.1.2.4/S15.1.2.4_A2.2': [FAIL],
+ 'ch15/15.1/15.1.2/15.1.2.5/S15.1.2.5_A2.2': [FAIL],
+ 'ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A5.2': [FAIL],
+ 'ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A5.2': [FAIL],
+ 'ch15/15.1/15.1.3/15.1.3.3/S15.1.3.3_A5.2': [FAIL],
+ 'ch15/15.1/15.1.3/15.1.3.4/S15.1.3.4_A5.2': [FAIL],
+ 'ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A9': [FAIL],
+ 'ch15/15.10/15.10.6/15.10.6.3/S15.10.6.3_A9': [FAIL],
+ 'ch15/15.10/15.10.6/15.10.6.4/S15.10.6.4_A9': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-186': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-187': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-191': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-194': [FAIL],
+ 'ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-201': [FAIL],
+ 'ch15/15.2/15.2.4/15.2.4.2/S15.2.4.2_A9': [FAIL],
+ 'ch15/15.2/15.2.4/15.2.4.3/S15.2.4.3_A9': [FAIL],
+ 'ch15/15.2/15.2.4/15.2.4.4/S15.2.4.4_A9': [FAIL],
+ 'ch15/15.2/15.2.4/15.2.4.5/S15.2.4.5_A9': [FAIL],
+ 'ch15/15.2/15.2.4/15.2.4.6/S15.2.4.6_A9': [FAIL],
+ 'ch15/15.2/15.2.4/15.2.4.7/S15.2.4.7_A9': [FAIL],
+ 'ch15/15.3/15.3.3/15.3.3.2/15.3.3.2-1': [FAIL],
+ 'ch15/15.3/15.3.4/15.3.4.2/S15.3.4.2_A9': [FAIL],
+ 'ch15/15.3/15.3.4/15.3.4.3/S15.3.4.3_A9': [FAIL],
+ 'ch15/15.3/15.3.4/15.3.4.4/S15.3.4.4_A9': [FAIL],
+ 'ch15/15.3/15.3.5/S15.3.5.1_A2_T1': [FAIL],
+ 'ch15/15.3/15.3.5/S15.3.5.1_A2_T2': [FAIL],
+ 'ch15/15.3/15.3.5/S15.3.5.1_A2_T3': [FAIL],
+ 'ch15/15.4/15.4.3/S15.4.3_A2.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A5.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A7.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A5.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A5.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.2/S15.4.4.2_A4.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.3/S15.4.4.3_A4.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.4/S15.4.4.4_A4.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A6.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A5.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A6.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A5.2': [FAIL],
+ 'ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A5.2': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.10/S15.5.4.10_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.11/S15.5.4.11_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.12/S15.5.4.12_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.13/S15.5.4.13_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.14/S15.5.4.14_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.15/S15.5.4.15_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.16/S15.5.4.16_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.17/S15.5.4.17_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.18/S15.5.4.18_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.19/S15.5.4.19_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.4/S15.5.4.4_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.5/S15.5.4.5_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.6/S15.5.4.6_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.7/S15.5.4.7_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.8/S15.5.4.8_A9': [FAIL],
+ 'ch15/15.5/15.5.4/15.5.4.9/S15.5.4.9_A9': [FAIL],
+ 'ch15/15.9/15.9.4/15.9.4.2/S15.9.4.2_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.4/15.9.4.3/S15.9.4.3_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.1/S15.9.5.1_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.10/S15.9.5.10_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.11/S15.9.5.11_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.12/S15.9.5.12_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.13/S15.9.5.13_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.14/S15.9.5.14_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.15/S15.9.5.15_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.16/S15.9.5.16_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.17/S15.9.5.17_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.18/S15.9.5.18_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.19/S15.9.5.19_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.2/S15.9.5.2_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.20/S15.9.5.20_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.21/S15.9.5.21_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.22/S15.9.5.22_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.23/S15.9.5.23_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.24/S15.9.5.24_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.25/S15.9.5.25_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.26/S15.9.5.26_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.27/S15.9.5.27_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.28/S15.9.5.28_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.29/S15.9.5.29_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.3/S15.9.5.3_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.30/S15.9.5.30_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.31/S15.9.5.31_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.32/S15.9.5.32_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.33/S15.9.5.33_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.34/S15.9.5.34_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.35/S15.9.5.35_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.36/S15.9.5.36_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.37/S15.9.5.37_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.38/S15.9.5.38_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.39/S15.9.5.39_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.4/S15.9.5.4_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.40/S15.9.5.40_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.41/S15.9.5.41_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.42/S15.9.5.42_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.5/S15.9.5.5_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.6/S15.9.5.6_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.7/S15.9.5.7_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.8/S15.9.5.8_A3_T2': [FAIL],
+ 'ch15/15.9/15.9.5/15.9.5.9/S15.9.5.9_A3_T2': [FAIL],
+ 'intl402/ch10/10.1/10.1_L15': [FAIL],
+ 'intl402/ch10/10.2/10.2.2_L15': [FAIL],
+ 'intl402/ch10/10.3/10.3.2_1_a_L15': [FAIL],
+ 'intl402/ch10/10.3/10.3.2_L15': [FAIL],
+ 'intl402/ch10/10.3/10.3.3_L15': [FAIL],
+ 'intl402/ch11/11.1/11.1_L15': [FAIL],
+ 'intl402/ch11/11.2/11.2.2_L15': [FAIL],
+ 'intl402/ch11/11.3/11.3.2_1_a_L15': [FAIL],
+ 'intl402/ch11/11.3/11.3.2_L15': [FAIL],
+ 'intl402/ch11/11.3/11.3.3_L15': [FAIL],
+ 'intl402/ch12/12.1/12.1_L15': [FAIL],
+ 'intl402/ch12/12.2/12.2.2_L15': [FAIL],
+ 'intl402/ch12/12.3/12.3.2_1_a_L15': [FAIL],
+ 'intl402/ch12/12.3/12.3.2_L15': [FAIL],
+ 'intl402/ch12/12.3/12.3.3_L15': [FAIL],
+ 'intl402/ch13/13.1/13.1.1_L15': [FAIL],
+ 'intl402/ch13/13.2/13.2.1_L15': [FAIL],
+ 'intl402/ch13/13.3/13.3.1_L15': [FAIL],
+ 'intl402/ch13/13.3/13.3.2_L15': [FAIL],
+ 'intl402/ch13/13.3/13.3.3_L15': [FAIL],
############################ SKIPPED TESTS #############################
# These tests take a looong time to run in debug mode.
- 'S15.1.3.1_A2.5_T1': [PASS, ['mode == debug', SKIP]],
- 'S15.1.3.2_A2.5_T1': [PASS, ['mode == debug', SKIP]],
+ 'ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A2.5_T1': [PASS, ['mode == debug', SKIP]],
+ 'ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A2.5_T1': [PASS, ['mode == debug', SKIP]],
}], # ALWAYS
['system == macos', {
- '11.3.2_TRP': [FAIL],
- '9.2.5_11_g_ii_2': [FAIL],
+ 'intl402/ch11/11.3/11.3.2_TRP': [FAIL],
+ 'intl402/ch09/9.2/9.2.5_11_g_ii_2': [FAIL],
}], # system == macos
['arch == arm or arch == mipsel or arch == mips or arch == arm64 or arch == mips64el', {
# TODO(mstarzinger): Causes stack overflow on simulators due to eager
# compilation of parenthesized function literals. Needs investigation.
- 'S13.2.1_A1_T1': [SKIP],
+ 'ch13/13.2/S13.2.1_A1_T1': [SKIP],
# BUG(3251225): Tests that timeout with --nocrankshaft.
- 'S15.1.3.1_A2.4_T1': [SKIP],
- 'S15.1.3.1_A2.5_T1': [SKIP],
- 'S15.1.3.2_A2.4_T1': [SKIP],
- 'S15.1.3.2_A2.5_T1': [SKIP],
- 'S15.1.3.3_A2.3_T1': [SKIP],
- 'S15.1.3.4_A2.3_T1': [SKIP],
+ 'ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A2.4_T1': [SKIP],
+ 'ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A2.5_T1': [SKIP],
+ 'ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A2.4_T1': [SKIP],
+ 'ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A2.5_T1': [SKIP],
+ 'ch15/15.1/15.1.3/15.1.3.3/S15.1.3.3_A2.3_T1': [SKIP],
+ 'ch15/15.1/15.1.3/15.1.3.4/S15.1.3.4_A2.3_T1': [SKIP],
}], # 'arch == arm or arch == mipsel or arch == mips or arch == arm64'
]
diff --git a/deps/v8/test/test262-es6/testcfg.py b/deps/v8/test/test262-es6/testcfg.py
index 0a894104a2..cb44da073a 100644
--- a/deps/v8/test/test262-es6/testcfg.py
+++ b/deps/v8/test/test262-es6/testcfg.py
@@ -57,9 +57,6 @@ class Test262TestSuite(testsuite.TestSuite):
self.harness += [os.path.join(self.root, "harness-adapt.js")]
self.ParseTestRecord = None
- def CommonTestName(self, testcase):
- return testcase.path.split(os.path.sep)[-1]
-
def ListTests(self, context):
tests = []
for dirname, dirs, files in os.walk(self.testroot):
diff --git a/deps/v8/test/test262/test262.status b/deps/v8/test/test262/test262.status
index d1800c5fc5..8e7496bc25 100644
--- a/deps/v8/test/test262/test262.status
+++ b/deps/v8/test/test262/test262.status
@@ -62,6 +62,133 @@
'11.1.5_4-4-d-3': [FAIL],
'11.1.5_4-4-d-4': [FAIL],
+ # Function length properties are configurable in ES6
+ '10.1_L15': [FAIL],
+ '10.2.2_L15': [FAIL],
+ '10.3.2_1_a_L15': [FAIL],
+ '10.3.2_L15': [FAIL],
+ '10.3.3_L15': [FAIL],
+ '11.1_L15': [FAIL],
+ '11.2.2_L15': [FAIL],
+ '11.3.2_1_a_L15': [FAIL],
+ '11.3.2_L15': [FAIL],
+ '11.3.3_L15': [FAIL],
+ '11.4.1-5-a-28-s': [FAIL],
+ '12.1_L15': [FAIL],
+ '12.2.2_L15': [FAIL],
+ '12.3.2_1_a_L15': [FAIL],
+ '12.3.2_L15': [FAIL],
+ '12.3.3_L15': [FAIL],
+ '13.1.1_L15': [FAIL],
+ '13.2-15-1': [FAIL],
+ '13.2.1_L15': [FAIL],
+ '13.3.1_L15': [FAIL],
+ '13.3.2_L15': [FAIL],
+ '13.3.3_L15': [FAIL],
+ '15.2.3.3-4-186': [FAIL],
+ '15.2.3.3-4-187': [FAIL],
+ '15.2.3.3-4-191': [FAIL],
+ '15.2.3.3-4-194': [FAIL],
+ '15.2.3.3-4-201': [FAIL],
+ '15.3.3.2-1': [FAIL],
+ 'S15.1.2.1_A4.2': [FAIL],
+ 'S15.1.2.2_A9.2': [FAIL],
+ 'S15.1.2.3_A7.2': [FAIL],
+ 'S15.1.2.4_A2.2': [FAIL],
+ 'S15.1.2.5_A2.2': [FAIL],
+ 'S15.1.3.1_A5.2': [FAIL],
+ 'S15.1.3.2_A5.2': [FAIL],
+ 'S15.1.3.3_A5.2': [FAIL],
+ 'S15.1.3.4_A5.2': [FAIL],
+ 'S15.10.6.2_A9': [FAIL],
+ 'S15.10.6.3_A9': [FAIL],
+ 'S15.10.6.4_A9': [FAIL],
+ 'S15.2.4.2_A9': [FAIL],
+ 'S15.2.4.3_A9': [FAIL],
+ 'S15.2.4.4_A9': [FAIL],
+ 'S15.2.4.5_A9': [FAIL],
+ 'S15.2.4.6_A9': [FAIL],
+ 'S15.2.4.7_A9': [FAIL],
+ 'S15.3.4.2_A9': [FAIL],
+ 'S15.3.4.3_A9': [FAIL],
+ 'S15.3.4.4_A9': [FAIL],
+ 'S15.3.5.1_A2_T1': [FAIL],
+ 'S15.3.5.1_A2_T2': [FAIL],
+ 'S15.3.5.1_A2_T3': [FAIL],
+ 'S15.4.3_A2.2': [FAIL],
+ 'S15.4.4.10_A5.2': [FAIL],
+ 'S15.4.4.11_A7.2': [FAIL],
+ 'S15.4.4.12_A5.2': [FAIL],
+ 'S15.4.4.13_A5.2': [FAIL],
+ 'S15.4.4.2_A4.2': [FAIL],
+ 'S15.4.4.3_A4.2': [FAIL],
+ 'S15.4.4.4_A4.2': [FAIL],
+ 'S15.4.4.5_A6.2': [FAIL],
+ 'S15.4.4.6_A5.2': [FAIL],
+ 'S15.4.4.7_A6.2': [FAIL],
+ 'S15.4.4.8_A5.2': [FAIL],
+ 'S15.4.4.9_A5.2': [FAIL],
+ 'S15.5.4.10_A9': [FAIL],
+ 'S15.5.4.11_A9': [FAIL],
+ 'S15.5.4.12_A9': [FAIL],
+ 'S15.5.4.13_A9': [FAIL],
+ 'S15.5.4.14_A9': [FAIL],
+ 'S15.5.4.15_A9': [FAIL],
+ 'S15.5.4.16_A9': [FAIL],
+ 'S15.5.4.17_A9': [FAIL],
+ 'S15.5.4.18_A9': [FAIL],
+ 'S15.5.4.19_A9': [FAIL],
+ 'S15.5.4.4_A9': [FAIL],
+ 'S15.5.4.5_A9': [FAIL],
+ 'S15.5.4.6_A9': [FAIL],
+ 'S15.5.4.7_A9': [FAIL],
+ 'S15.5.4.8_A9': [FAIL],
+ 'S15.5.4.9_A9': [FAIL],
+ 'S15.9.4.2_A3_T2': [FAIL],
+ 'S15.9.4.3_A3_T2': [FAIL],
+ 'S15.9.5.10_A3_T2': [FAIL],
+ 'S15.9.5.11_A3_T2': [FAIL],
+ 'S15.9.5.12_A3_T2': [FAIL],
+ 'S15.9.5.13_A3_T2': [FAIL],
+ 'S15.9.5.14_A3_T2': [FAIL],
+ 'S15.9.5.15_A3_T2': [FAIL],
+ 'S15.9.5.16_A3_T2': [FAIL],
+ 'S15.9.5.17_A3_T2': [FAIL],
+ 'S15.9.5.18_A3_T2': [FAIL],
+ 'S15.9.5.19_A3_T2': [FAIL],
+ 'S15.9.5.1_A3_T2': [FAIL],
+ 'S15.9.5.20_A3_T2': [FAIL],
+ 'S15.9.5.21_A3_T2': [FAIL],
+ 'S15.9.5.22_A3_T2': [FAIL],
+ 'S15.9.5.23_A3_T2': [FAIL],
+ 'S15.9.5.24_A3_T2': [FAIL],
+ 'S15.9.5.25_A3_T2': [FAIL],
+ 'S15.9.5.26_A3_T2': [FAIL],
+ 'S15.9.5.27_A3_T2': [FAIL],
+ 'S15.9.5.28_A3_T2': [FAIL],
+ 'S15.9.5.29_A3_T2': [FAIL],
+ 'S15.9.5.2_A3_T2': [FAIL],
+ 'S15.9.5.30_A3_T2': [FAIL],
+ 'S15.9.5.31_A3_T2': [FAIL],
+ 'S15.9.5.32_A3_T2': [FAIL],
+ 'S15.9.5.33_A3_T2': [FAIL],
+ 'S15.9.5.34_A3_T2': [FAIL],
+ 'S15.9.5.35_A3_T2': [FAIL],
+ 'S15.9.5.36_A3_T2': [FAIL],
+ 'S15.9.5.37_A3_T2': [FAIL],
+ 'S15.9.5.38_A3_T2': [FAIL],
+ 'S15.9.5.39_A3_T2': [FAIL],
+ 'S15.9.5.3_A3_T2': [FAIL],
+ 'S15.9.5.40_A3_T2': [FAIL],
+ 'S15.9.5.41_A3_T2': [FAIL],
+ 'S15.9.5.42_A3_T2': [FAIL],
+ 'S15.9.5.4_A3_T2': [FAIL],
+ 'S15.9.5.5_A3_T2': [FAIL],
+ 'S15.9.5.6_A3_T2': [FAIL],
+ 'S15.9.5.7_A3_T2': [FAIL],
+ 'S15.9.5.8_A3_T2': [FAIL],
+ 'S15.9.5.9_A3_T2': [FAIL],
+
######################## NEEDS INVESTIGATION ###########################
# These test failures are specific to the intl402 suite and need investigation
diff --git a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 1fa0b10842..85e52488b4 100644
--- a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -2426,6 +2426,21 @@ TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
}
}
+
+TEST_F(InstructionSelectorTest, Word32Clz) {
+ StreamBuilder m(this, kMachUint32, kMachUint32);
+ Node* const p0 = m.Parameter(0);
+ Node* const n = m.Word32Clz(p0);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmClz, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
index 571dbecd14..02c8d2e06d 100644
--- a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
@@ -472,6 +472,36 @@ TEST_P(InstructionSelectorAddSubTest, ShiftByImmediateOnRight) {
}
+TEST_P(InstructionSelectorAddSubTest, ExtendByte) {
+ const AddSub dpi = GetParam();
+ const MachineType type = dpi.mi.machine_type;
+ StreamBuilder m(this, type, type, type);
+ m.Return((m.*dpi.mi.constructor)(
+ m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xff))));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+}
+
+
+TEST_P(InstructionSelectorAddSubTest, ExtendHalfword) {
+ const AddSub dpi = GetParam();
+ const MachineType type = dpi.mi.machine_type;
+ StreamBuilder m(this, type, type, type);
+ m.Return((m.*dpi.mi.constructor)(
+ m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xffff))));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+}
+
+
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
::testing::ValuesIn(kAddSubInstructions));
@@ -616,6 +646,58 @@ TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
}
+TEST_F(InstructionSelectorTest, AddExtendByteOnLeft) {
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ {
+ StreamBuilder m(this, kMachInt64, kMachInt32, kMachInt64);
+ m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, AddExtendHalfwordOnLeft) {
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ {
+ StreamBuilder m(this, kMachInt64, kMachInt32, kMachInt64);
+ m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+}
+
+
// -----------------------------------------------------------------------------
// Data processing controlled branches.
@@ -896,26 +978,6 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
}
-
- TRACED_FORRANGE(int, bit, 0, 63) {
- uint64_t mask = 1L << bit;
- StreamBuilder m(this, kMachInt64, kMachInt64);
- MLabel a, b;
- m.Branch(
- m.Word64BinaryNot(m.Word64And(m.Parameter(0), m.Int64Constant(mask))),
- &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
- Stream s = m.Build();
- ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
- EXPECT_EQ(kEqual, s[0]->flags_condition());
- EXPECT_EQ(4U, s[0]->InputCount());
- EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
- EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
- }
}
@@ -937,26 +999,6 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
}
-
- TRACED_FORRANGE(int, bit, 0, 63) {
- uint64_t mask = 1L << bit;
- StreamBuilder m(this, kMachInt64, kMachInt64);
- MLabel a, b;
- m.Branch(
- m.Word64BinaryNot(m.Word64And(m.Int64Constant(mask), m.Parameter(0))),
- &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
- Stream s = m.Build();
- ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
- EXPECT_EQ(kEqual, s[0]->flags_condition());
- EXPECT_EQ(4U, s[0]->InputCount());
- EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
- EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
- }
}
@@ -2200,6 +2242,21 @@ TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
}
}
+
+TEST_F(InstructionSelectorTest, Word32Clz) {
+ StreamBuilder m(this, kMachUint32, kMachUint32);
+ Node* const p0 = m.Parameter(0);
+ Node* const n = m.Word32Clz(p0);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Clz32, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/change-lowering-unittest.cc b/deps/v8/test/unittests/compiler/change-lowering-unittest.cc
index 5b31f5e04c..5cfb8fdc41 100644
--- a/deps/v8/test/unittests/compiler/change-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/change-lowering-unittest.cc
@@ -23,45 +23,15 @@ namespace v8 {
namespace internal {
namespace compiler {
-class ChangeLoweringTest : public GraphTest {
+class ChangeLoweringTest : public TypedGraphTest {
public:
ChangeLoweringTest() : simplified_(zone()) {}
- ~ChangeLoweringTest() OVERRIDE {}
virtual MachineType WordRepresentation() const = 0;
protected:
- int HeapNumberValueOffset() const {
- STATIC_ASSERT(HeapNumber::kValueOffset % kApiPointerSize == 0);
- return (HeapNumber::kValueOffset / kApiPointerSize) * PointerSize() -
- kHeapObjectTag;
- }
bool Is32() const { return WordRepresentation() == kRepWord32; }
- int PointerSize() const {
- switch (WordRepresentation()) {
- case kRepWord32:
- return 4;
- case kRepWord64:
- return 8;
- default:
- break;
- }
- UNREACHABLE();
- return 0;
- }
- int SmiMaxValue() const { return -(SmiMinValue() + 1); }
- int SmiMinValue() const {
- return static_cast<int>(0xffffffffu << (SmiValueSize() - 1));
- }
- int SmiShiftAmount() const { return kSmiTagSize + SmiShiftSize(); }
- int SmiShiftSize() const {
- return Is32() ? SmiTagging<4>::SmiShiftSize()
- : SmiTagging<8>::SmiShiftSize();
- }
- int SmiValueSize() const {
- return Is32() ? SmiTagging<4>::SmiValueSize()
- : SmiTagging<8>::SmiValueSize();
- }
+ bool Is64() const { return WordRepresentation() == kRepWord64; }
Reduction Reduce(Node* node) {
MachineOperatorBuilder machine(zone(), WordRepresentation());
@@ -80,15 +50,33 @@ class ChangeLoweringTest : public GraphTest {
IsNumberConstant(BitEq(0.0)), effect_matcher,
control_matcher);
}
+ Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) {
+ return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher),
+ IsSmiShiftBitsConstant())
+ : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
+ }
+ Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) {
+ return Is64() ? IsTruncateInt64ToInt32(
+ IsWord64Sar(value_matcher, IsSmiShiftBitsConstant()))
+ : IsWord32Sar(value_matcher, IsSmiShiftBitsConstant());
+ }
+ Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) {
+ return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher),
+ IsSmiShiftBitsConstant())
+ : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
+ }
Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher) {
return IsLoad(kMachFloat64, value_matcher,
- IsIntPtrConstant(HeapNumberValueOffset()), graph()->start(),
- control_matcher);
+ IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
+ graph()->start(), control_matcher);
}
Matcher<Node*> IsIntPtrConstant(int value) {
return Is32() ? IsInt32Constant(value) : IsInt64Constant(value);
}
+ Matcher<Node*> IsSmiShiftBitsConstant() {
+ return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize);
+ }
Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
@@ -115,51 +103,95 @@ class ChangeLoweringCommonTest
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeBitToBool(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
- EXPECT_THAT(reduction.replacement(),
- IsSelect(static_cast<MachineType>(kTypeBool | kRepTagged), val,
- IsTrueConstant(), IsFalseConstant()));
+ Node* value = Parameter(Type::Boolean());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeBitToBool(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsSelect(kMachAnyTagged, value, IsTrueConstant(),
+ IsFalseConstant()));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrueConstant()));
+ Node* value = Parameter(Type::Number());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsWordEqual(value, IsTrueConstant()));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeFloat64ToTagged(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* finish = reduction.replacement();
+ Node* value = Parameter(Type::Number());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeFloat64ToTagged(), value));
+ ASSERT_TRUE(r.Changed());
Capture<Node*> heap_number;
EXPECT_THAT(
- finish,
+ r.replacement(),
IsFinish(
AllOf(CaptureEq(&heap_number),
- IsAllocateHeapNumber(IsValueEffect(val), graph()->start())),
+ IsAllocateHeapNumber(IsValueEffect(value), graph()->start())),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
- IsIntPtrConstant(HeapNumberValueOffset()), val,
- CaptureEq(&heap_number), graph()->start())));
+ IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
+ value, CaptureEq(&heap_number), graph()->start())));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) {
+ Node* value = Parameter(Type::SignedSmall());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeInt32ToTagged(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
}
-TARGET_TEST_P(ChangeLoweringCommonTest, StringAdd) {
- Node* node =
- graph()->NewNode(simplified()->StringAdd(), Parameter(0), Parameter(1));
- Reduction reduction = Reduce(node);
- EXPECT_FALSE(reduction.Changed());
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeUint32ToTaggedWithUnsignedSmall) {
+ Node* value = Parameter(Type::UnsignedSmall());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsChangeUint32ToSmi(value));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedSigned) {
+ Node* value = Parameter(Type::TaggedSigned());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedPointer) {
+ Node* value = Parameter(Type::TaggedPointer());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsChangeFloat64ToInt32(
+ IsLoadHeapNumber(value, graph()->start())));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedSigned) {
+ Node* value = Parameter(Type::TaggedSigned());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedPointer) {
+ Node* value = Parameter(Type::TaggedPointer());
+ Reduction r =
+ Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsChangeFloat64ToUint32(
+ IsLoadHeapNumber(value, graph()->start())));
}
@@ -179,26 +211,24 @@ class ChangeLowering32Test : public ChangeLoweringTest {
TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
- NodeProperties::SetBounds(val, Bounds(Type::None(), Type::Signed32()));
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Integral32());
+ Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> add, branch, heap_number, if_true;
EXPECT_THAT(
- phi,
+ r.replacement(),
IsPhi(kMachAnyTagged,
IsFinish(AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_true))),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
- IsIntPtrConstant(HeapNumberValueOffset()),
- IsChangeInt32ToFloat64(val),
+ IsIntPtrConstant(HeapNumber::kValueOffset -
+ kHeapObjectTag),
+ IsChangeInt32ToFloat64(value),
CaptureEq(&heap_number), CaptureEq(&if_true))),
- IsProjection(
- 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))),
+ IsProjection(0, AllOf(CaptureEq(&add),
+ IsInt32AddWithOverflow(value, value))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(CaptureEq(&branch),
IsBranch(IsProjection(1, CaptureEq(&add)),
@@ -206,43 +236,27 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
}
-TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTaggedSmall) {
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
- NodeProperties::SetBounds(val, Bounds(Type::None(), Type::Signed31()));
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* change = reduction.replacement();
- Capture<Node*> add, branch, heap_number, if_true;
- EXPECT_THAT(change, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())));
-}
-
-
TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Number());
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
- phi,
- IsPhi(
- kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)),
- IsChangeInt32ToFloat64(
- IsWord32Sar(val, IsInt32Constant(SmiShiftAmount()))),
- IsMerge(
- AllOf(CaptureEq(&if_true),
- IsIfTrue(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
- graph()->start())))),
- IsIfFalse(CaptureEq(&branch)))));
+ r.replacement(),
+ IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)),
+ IsChangeInt32ToFloat64(IsWord32Sar(
+ value, IsInt32Constant(kSmiTagSize + kSmiShiftSize))),
+ IsMerge(AllOf(CaptureEq(&if_true),
+ IsIfTrue(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord32And(
+ value, IsInt32Constant(kSmiTagMask)),
+ graph()->start())))),
+ IsIfFalse(CaptureEq(&branch)))));
}
@@ -250,23 +264,22 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Signed32());
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
- phi,
- IsPhi(kMachInt32,
- IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
- IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
- graph()->start()))))));
+ r.replacement(),
+ IsPhi(
+ kMachInt32,
+ IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
+ IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
+ graph()->start()))))));
}
@@ -274,23 +287,22 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Unsigned32());
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
- phi,
- IsPhi(kMachUint32,
- IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
- IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
- graph()->start()))))));
+ r.replacement(),
+ IsPhi(
+ kMachUint32,
+ IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
+ IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
+ graph()->start()))))));
}
@@ -298,30 +310,30 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Number());
+ Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, heap_number, if_false;
EXPECT_THAT(
- phi,
+ r.replacement(),
IsPhi(
- kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())),
+ kMachAnyTagged,
+ IsWord32Shl(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
IsFinish(AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_false))),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
- IsInt32Constant(HeapNumberValueOffset()),
- IsChangeUint32ToFloat64(val),
+ IsInt32Constant(HeapNumber::kValueOffset -
+ kHeapObjectTag),
+ IsChangeUint32ToFloat64(value),
CaptureEq(&heap_number), CaptureEq(&if_false))),
- IsMerge(
- IsIfTrue(AllOf(CaptureEq(&branch),
- IsBranch(IsUint32LessThanOrEqual(
- val, IsInt32Constant(SmiMaxValue())),
- graph()->start()))),
- AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
+ IsMerge(IsIfTrue(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsUint32LessThanOrEqual(
+ value, IsInt32Constant(Smi::kMaxValue)),
+ graph()->start()))),
+ AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
}
@@ -337,14 +349,11 @@ class ChangeLowering64Test : public ChangeLoweringTest {
TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- EXPECT_THAT(reduction.replacement(),
- IsWord64Shl(IsChangeInt32ToInt64(val),
- IsInt64Constant(SmiShiftAmount())));
+ Node* value = Parameter(Type::Signed32());
+ Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
}
@@ -352,26 +361,23 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Number());
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
- phi,
- IsPhi(
- kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)),
- IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(
- IsWord64Sar(val, IsInt64Constant(SmiShiftAmount())))),
- IsMerge(
- AllOf(CaptureEq(&if_true),
- IsIfTrue(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
- graph()->start())))),
- IsIfFalse(CaptureEq(&branch)))));
+ r.replacement(),
+ IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)),
+ IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(IsWord64Sar(
+ value, IsInt64Constant(kSmiTagSize + kSmiShiftSize)))),
+ IsMerge(AllOf(CaptureEq(&if_true),
+ IsIfTrue(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord64And(
+ value, IsInt64Constant(kSmiTagMask)),
+ graph()->start())))),
+ IsIfFalse(CaptureEq(&branch)))));
}
@@ -379,24 +385,23 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Signed32());
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
- phi,
- IsPhi(kMachInt32,
- IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
- IsTruncateInt64ToInt32(
- IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
- graph()->start()))))));
+ r.replacement(),
+ IsPhi(
+ kMachInt32,
+ IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
+ IsTruncateInt64ToInt32(
+ IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
+ graph()->start()))))));
}
@@ -404,24 +409,23 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Unsigned32());
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
- phi,
- IsPhi(kMachUint32,
- IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
- IsTruncateInt64ToInt32(
- IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
- graph()->start()))))));
+ r.replacement(),
+ IsPhi(
+ kMachUint32,
+ IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
+ IsTruncateInt64ToInt32(
+ IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
+ graph()->start()))))));
}
@@ -429,31 +433,31 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
- Node* val = Parameter(0);
- Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
- Reduction reduction = Reduce(node);
- ASSERT_TRUE(reduction.Changed());
-
- Node* phi = reduction.replacement();
+ Node* value = Parameter(Type::Number());
+ Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
+ Reduction r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
Capture<Node*> branch, heap_number, if_false;
EXPECT_THAT(
- phi,
+ r.replacement(),
IsPhi(
- kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val),
- IsInt64Constant(SmiShiftAmount())),
+ kMachAnyTagged,
+ IsWord64Shl(IsChangeUint32ToUint64(value),
+ IsInt64Constant(kSmiTagSize + kSmiShiftSize)),
IsFinish(AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_false))),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
- IsInt64Constant(HeapNumberValueOffset()),
- IsChangeUint32ToFloat64(val),
+ IsInt64Constant(HeapNumber::kValueOffset -
+ kHeapObjectTag),
+ IsChangeUint32ToFloat64(value),
CaptureEq(&heap_number), CaptureEq(&if_false))),
- IsMerge(
- IsIfTrue(AllOf(CaptureEq(&branch),
- IsBranch(IsUint32LessThanOrEqual(
- val, IsInt32Constant(SmiMaxValue())),
- graph()->start()))),
- AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
+ IsMerge(IsIfTrue(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsUint32LessThanOrEqual(
+ value, IsInt32Constant(Smi::kMaxValue)),
+ graph()->start()))),
+ AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
}
} // namespace compiler
diff --git a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
index 1f6044b97c..3b60e5b9bd 100644
--- a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
@@ -4,9 +4,13 @@
#include "src/compiler/common-operator.h"
#include "src/compiler/common-operator-reducer.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/machine-operator.h"
#include "src/compiler/machine-type.h"
#include "src/compiler/operator.h"
#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
namespace v8 {
namespace internal {
@@ -15,14 +19,23 @@ namespace compiler {
class CommonOperatorReducerTest : public GraphTest {
public:
explicit CommonOperatorReducerTest(int num_parameters = 1)
- : GraphTest(num_parameters) {}
+ : GraphTest(num_parameters), machine_(zone()) {}
~CommonOperatorReducerTest() OVERRIDE {}
protected:
- Reduction Reduce(Node* node) {
- CommonOperatorReducer reducer;
+ Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
+ MachineOperatorBuilder::kNoFlags) {
+ JSOperatorBuilder javascript(zone());
+ MachineOperatorBuilder machine(zone(), kMachPtr, flags);
+ JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
+ CommonOperatorReducer reducer(&jsgraph);
return reducer.Reduce(node);
}
+
+ MachineOperatorBuilder* machine() { return &machine_; }
+
+ private:
+ MachineOperatorBuilder machine_;
};
@@ -78,9 +91,14 @@ TEST_F(CommonOperatorReducerTest, RedundantPhi) {
int const value_input_count = input_count - 1;
TRACED_FOREACH(MachineType, type, kMachineTypes) {
for (int i = 0; i < value_input_count; ++i) {
+ inputs[i] = graph()->start();
+ }
+ Node* merge = graph()->NewNode(common()->Merge(value_input_count),
+ value_input_count, inputs);
+ for (int i = 0; i < value_input_count; ++i) {
inputs[i] = input;
}
- inputs[value_input_count] = graph()->start();
+ inputs[value_input_count] = merge;
Reduction r = Reduce(graph()->NewNode(
common()->Phi(type, value_input_count), input_count, inputs));
ASSERT_TRUE(r.Changed());
@@ -90,6 +108,27 @@ TEST_F(CommonOperatorReducerTest, RedundantPhi) {
}
+TEST_F(CommonOperatorReducerTest, PhiToFloat64MaxOrFloat64Min) {
+ Node* p0 = Parameter(0);
+ Node* p1 = Parameter(1);
+ Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1);
+ Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Reduction r1 =
+ Reduce(graph()->NewNode(common()->Phi(kMachFloat64, 2), p1, p0, merge),
+ MachineOperatorBuilder::kFloat64Max);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_THAT(r1.replacement(), IsFloat64Max(p1, p0));
+ Reduction r2 =
+ Reduce(graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge),
+ MachineOperatorBuilder::kFloat64Min);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_THAT(r2.replacement(), IsFloat64Min(p0, p1));
+}
+
+
// -----------------------------------------------------------------------------
// Select
@@ -106,6 +145,23 @@ TEST_F(CommonOperatorReducerTest, RedundantSelect) {
}
}
+
+TEST_F(CommonOperatorReducerTest, SelectToFloat64MaxOrFloat64Min) {
+ Node* p0 = Parameter(0);
+ Node* p1 = Parameter(1);
+ Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1);
+ Reduction r1 =
+ Reduce(graph()->NewNode(common()->Select(kMachFloat64), check, p1, p0),
+ MachineOperatorBuilder::kFloat64Max);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_THAT(r1.replacement(), IsFloat64Max(p1, p0));
+ Reduction r2 =
+ Reduce(graph()->NewNode(common()->Select(kMachFloat64), check, p0, p1),
+ MachineOperatorBuilder::kFloat64Min);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_THAT(r2.replacement(), IsFloat64Min(p0, p1));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/common-operator-unittest.cc b/deps/v8/test/unittests/compiler/common-operator-unittest.cc
index 6e60cfd12a..c0d25ea741 100644
--- a/deps/v8/test/unittests/compiler/common-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/common-operator-unittest.cc
@@ -53,6 +53,8 @@ const SharedOperator kSharedOperators[] = {
SHARED(End, Operator::kKontrol, 0, 0, 1, 0, 0, 0),
SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
+ SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
+ SHARED(IfException, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(Throw, Operator::kFoldable, 1, 1, 1, 0, 0, 1),
SHARED(Return, Operator::kNoThrow, 1, 1, 1, 0, 0, 1)
#undef SHARED
diff --git a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
index 17716ab1a9..515bd061ef 100644
--- a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
+++ b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
@@ -17,7 +17,7 @@ namespace compiler {
do { \
Node* __n[] = {__VA_ARGS__}; \
ASSERT_TRUE(IsEquivalenceClass(arraysize(__n), __n)); \
- } while (false);
+ } while (false)
class ControlEquivalenceTest : public GraphTest {
public:
diff --git a/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc b/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc
index c083d4bab5..f300d07767 100644
--- a/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc
@@ -21,25 +21,32 @@ namespace compiler {
class ControlFlowOptimizerTest : public GraphTest {
public:
explicit ControlFlowOptimizerTest(int num_parameters = 3)
- : GraphTest(num_parameters), machine_(zone()) {}
+ : GraphTest(num_parameters),
+ machine_(zone()),
+ javascript_(zone()),
+ jsgraph_(isolate(), graph(), common(), javascript(), machine()) {}
~ControlFlowOptimizerTest() OVERRIDE {}
protected:
void Optimize() {
- JSOperatorBuilder javascript(zone());
- JSGraph jsgraph(isolate(), graph(), common(), &javascript, machine());
- ControlFlowOptimizer optimizer(&jsgraph, zone());
+ ControlFlowOptimizer optimizer(jsgraph(), zone());
optimizer.Optimize();
}
+ Node* EmptyFrameState() { return jsgraph()->EmptyFrameState(); }
+
+ JSGraph* jsgraph() { return &jsgraph_; }
+ JSOperatorBuilder* javascript() { return &javascript_; }
MachineOperatorBuilder* machine() { return &machine_; }
private:
MachineOperatorBuilder machine_;
+ JSOperatorBuilder javascript_;
+ JSGraph jsgraph_;
};
-TEST_F(ControlFlowOptimizerTest, Switch) {
+TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
Node* index = Parameter(0);
Node* branch0 = graph()->NewNode(
common()->Branch(),
@@ -65,6 +72,69 @@ TEST_F(ControlFlowOptimizerTest, Switch) {
IsSwitch(index, start()))))));
}
+
+TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
+ Node* input = Parameter(0);
+ Node* context = Parameter(1);
+ Node* index = FLAG_turbo_deoptimization
+ ? graph()->NewNode(javascript()->ToNumber(), input, context,
+ EmptyFrameState(), start(), start())
+ : graph()->NewNode(javascript()->ToNumber(), input, context,
+ start(), start());
+ Node* if_success = graph()->NewNode(common()->IfSuccess(), index);
+ Node* branch0 = graph()->NewNode(
+ common()->Branch(),
+ graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
+ if_success);
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* branch1 = graph()->NewNode(
+ common()->Branch(),
+ graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(1)),
+ if_false0);
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* merge =
+ graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
+ graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+ Optimize();
+ Capture<Node*> switch_capture;
+ EXPECT_THAT(
+ end(),
+ IsEnd(IsMerge(IsIfValue(0, CaptureEq(&switch_capture)),
+ IsIfValue(1, CaptureEq(&switch_capture)),
+ IsIfDefault(AllOf(CaptureEq(&switch_capture),
+ IsSwitch(index, IsIfSuccess(index)))))));
+}
+
+
+TEST_F(ControlFlowOptimizerTest, CloneBranch) {
+ Node* cond0 = Parameter(0);
+ Node* cond1 = Parameter(1);
+ Node* cond2 = Parameter(2);
+ Node* branch0 = graph()->NewNode(common()->Branch(), cond0, start());
+ Node* control1 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* control2 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* merge0 = graph()->NewNode(common()->Merge(2), control1, control2);
+ Node* phi0 =
+ graph()->NewNode(common()->Phi(kRepBit, 2), cond1, cond2, merge0);
+ Node* branch = graph()->NewNode(common()->Branch(), phi0, merge0);
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+ Optimize();
+ Capture<Node*> branch1_capture, branch2_capture;
+ EXPECT_THAT(
+ end(),
+ IsEnd(IsMerge(IsMerge(IsIfTrue(CaptureEq(&branch1_capture)),
+ IsIfTrue(CaptureEq(&branch2_capture))),
+ IsMerge(IsIfFalse(AllOf(CaptureEq(&branch1_capture),
+ IsBranch(cond1, control1))),
+ IsIfFalse(AllOf(CaptureEq(&branch2_capture),
+ IsBranch(cond2, control2)))))));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc b/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
index afa1e94245..9138ab2ca6 100644
--- a/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
+++ b/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
@@ -11,9 +11,9 @@ namespace compiler {
namespace {
// Immediates (random subset).
-static const int32_t kImmediates[] = {
- kMinInt, -42, -1, 0, 1, 2, 3, 4, 5,
- 6, 7, 8, 16, 42, 0xff, 0xffff, 0x0f0f0f0f, kMaxInt};
+const int32_t kImmediates[] = {kMinInt, -42, -1, 0, 1, 2,
+ 3, 4, 5, 6, 7, 8,
+ 16, 42, 0xff, 0xffff, 0x0f0f0f0f, kMaxInt};
} // namespace
@@ -666,6 +666,44 @@ TEST_F(InstructionSelectorTest, Float64BinopArithmetic) {
}
}
+
+// -----------------------------------------------------------------------------
+// Miscellaneous.
+
+
+TEST_F(InstructionSelectorTest, Uint32LessThanWithLoadAndLoadStackPointer) {
+ StreamBuilder m(this, kMachBool);
+ Node* const sl = m.Load(
+ kMachPtr,
+ m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate())));
+ Node* const sp = m.LoadStackPointer();
+ Node* const n = m.Uint32LessThan(sl, sp);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kIA32StackCheck, s[0]->arch_opcode());
+ ASSERT_EQ(0U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+ EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition());
+}
+
+
+TEST_F(InstructionSelectorTest, Word32Clz) {
+ StreamBuilder m(this, kMachUint32, kMachUint32);
+ Node* const p0 = m.Parameter(0);
+ Node* const n = m.Word32Clz(p0);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kIA32Lzcnt, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
index d3e00c642c..e52580dc64 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
@@ -4,7 +4,8 @@
#include "test/unittests/compiler/instruction-selector-unittest.h"
-#include "src/compiler/graph-inl.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/schedule.h"
#include "src/flags.h"
#include "test/unittests/compiler/compiler-test-utils.h"
@@ -346,9 +347,13 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
Node* receiver = m.Parameter(1);
Node* context = m.Parameter(2);
- Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(1));
- Node* locals = m.NewNode(m.common()->StateValues(0));
- Node* stack = m.NewNode(m.common()->StateValues(0));
+ ZoneVector<MachineType> int32_type(1, kMachInt32, zone());
+ ZoneVector<MachineType> empty_types(zone());
+
+ Node* parameters =
+ m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(1));
+ Node* locals = m.NewNode(m.common()->TypedStateValues(&empty_types));
+ Node* stack = m.NewNode(m.common()->TypedStateValues(&empty_types));
Node* context_dummy = m.Int32Constant(0);
Node* state_node = m.NewNode(
@@ -386,10 +391,17 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
Node* receiver = m.Parameter(1);
Node* context = m.Int32Constant(1); // Context is ignored.
+ ZoneVector<MachineType> int32_type(1, kMachInt32, zone());
+ ZoneVector<MachineType> float64_type(1, kMachFloat64, zone());
+ ZoneVector<MachineType> tagged_type(1, kMachAnyTagged, zone());
+
// Build frame state for the state before the call.
- Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
- Node* locals = m.NewNode(m.common()->StateValues(1), m.Float64Constant(0.5));
- Node* stack = m.NewNode(m.common()->StateValues(1), m.UndefinedConstant());
+ Node* parameters =
+ m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43));
+ Node* locals = m.NewNode(m.common()->TypedStateValues(&float64_type),
+ m.Float64Constant(0.5));
+ Node* stack = m.NewNode(m.common()->TypedStateValues(&tagged_type),
+ m.UndefinedConstant());
Node* context_sentinel = m.Int32Constant(0);
Node* frame_state_before = m.NewNode(
@@ -472,10 +484,17 @@ TARGET_TEST_F(InstructionSelectorTest,
Node* receiver = m.Parameter(1);
Node* context = m.Int32Constant(66);
+ ZoneVector<MachineType> int32_type(1, kMachInt32, zone());
+ ZoneVector<MachineType> int32x2_type(2, kMachInt32, zone());
+ ZoneVector<MachineType> float64_type(1, kMachFloat64, zone());
+
// Build frame state for the state before the call.
- Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(63));
- Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(64));
- Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(65));
+ Node* parameters =
+ m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(63));
+ Node* locals =
+ m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64));
+ Node* stack =
+ m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65));
Node* frame_state_parent =
m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_parent,
OutputFrameStateCombine::Ignore()),
@@ -483,11 +502,11 @@ TARGET_TEST_F(InstructionSelectorTest,
Node* context2 = m.Int32Constant(46);
Node* parameters2 =
- m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
- Node* locals2 =
- m.NewNode(m.common()->StateValues(1), m.Float64Constant(0.25));
- Node* stack2 = m.NewNode(m.common()->StateValues(2), m.Int32Constant(44),
- m.Int32Constant(45));
+ m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43));
+ Node* locals2 = m.NewNode(m.common()->TypedStateValues(&float64_type),
+ m.Float64Constant(0.25));
+ Node* stack2 = m.NewNode(m.common()->TypedStateValues(&int32x2_type),
+ m.Int32Constant(44), m.Int32Constant(45));
Node* frame_state_before =
m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before,
OutputFrameStateCombine::Push()),
diff --git a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc
index 001fb11d13..c2e626fd59 100644
--- a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc
+++ b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc
@@ -40,7 +40,6 @@ InstructionSequenceTest::InstructionSequenceTest()
num_general_registers_(kDefaultNRegs),
num_double_registers_(kDefaultNRegs),
instruction_blocks_(zone()),
- current_instruction_index_(-1),
current_block_(nullptr),
block_returns_(false) {
InitializeRegisterNames();
@@ -100,8 +99,8 @@ void InstructionSequenceTest::StartBlock() {
}
-int InstructionSequenceTest::EndBlock(BlockCompletion completion) {
- int instruction_index = kMinInt;
+Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) {
+ Instruction* result = nullptr;
if (block_returns_) {
CHECK(completion.type_ == kBlockEnd || completion.type_ == kFallThrough);
completion.type_ = kBlockEnd;
@@ -110,22 +109,22 @@ int InstructionSequenceTest::EndBlock(BlockCompletion completion) {
case kBlockEnd:
break;
case kFallThrough:
- instruction_index = EmitFallThrough();
+ result = EmitFallThrough();
break;
case kJump:
CHECK(!block_returns_);
- instruction_index = EmitJump();
+ result = EmitJump();
break;
case kBranch:
CHECK(!block_returns_);
- instruction_index = EmitBranch(completion.op_);
+ result = EmitBranch(completion.op_);
break;
}
completions_.push_back(completion);
CHECK(current_block_ != nullptr);
sequence()->EndBlock(current_block_->rpo_number());
current_block_ = nullptr;
- return instruction_index;
+ return result;
}
@@ -139,15 +138,15 @@ InstructionSequenceTest::VReg InstructionSequenceTest::Define(
TestOperand output_op) {
VReg vreg = NewReg();
InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)};
- Emit(vreg.value_, kArchNop, 1, outputs);
+ Emit(kArchNop, 1, outputs);
return vreg;
}
-int InstructionSequenceTest::Return(TestOperand input_op_0) {
+Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) {
block_returns_ = true;
InstructionOperand inputs[1]{ConvertInputOp(input_op_0)};
- return Emit(NewIndex(), kArchRet, 0, nullptr, 1, inputs);
+ return Emit(kArchRet, 0, nullptr, 1, inputs);
}
@@ -192,12 +191,12 @@ InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant(
VReg vreg = NewReg();
sequence()->AddConstant(vreg.value_, Constant(imm));
InstructionOperand outputs[1]{ConstantOperand(vreg.value_)};
- Emit(vreg.value_, kArchNop, 1, outputs);
+ Emit(kArchNop, 1, outputs);
return vreg;
}
-int InstructionSequenceTest::EmitNop() { return Emit(NewIndex(), kArchNop); }
+Instruction* InstructionSequenceTest::EmitNop() { return Emit(kArchNop); }
static size_t CountInputs(size_t size,
@@ -210,16 +209,17 @@ static size_t CountInputs(size_t size,
}
-int InstructionSequenceTest::EmitI(size_t input_size, TestOperand* inputs) {
+Instruction* InstructionSequenceTest::EmitI(size_t input_size,
+ TestOperand* inputs) {
InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
- return Emit(NewIndex(), kArchNop, 0, nullptr, input_size, mapped_inputs);
+ return Emit(kArchNop, 0, nullptr, input_size, mapped_inputs);
}
-int InstructionSequenceTest::EmitI(TestOperand input_op_0,
- TestOperand input_op_1,
- TestOperand input_op_2,
- TestOperand input_op_3) {
+Instruction* InstructionSequenceTest::EmitI(TestOperand input_op_0,
+ TestOperand input_op_1,
+ TestOperand input_op_2,
+ TestOperand input_op_3) {
TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
return EmitI(CountInputs(arraysize(inputs), inputs), inputs);
}
@@ -230,7 +230,7 @@ InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
VReg output_vreg = NewReg();
InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
- Emit(output_vreg.value_, kArchNop, 1, outputs, input_size, mapped_inputs);
+ Emit(kArchNop, 1, outputs, input_size, mapped_inputs);
return output_vreg;
}
@@ -243,14 +243,36 @@ InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
}
+InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
+ TestOperand output_op_0, TestOperand output_op_1, size_t input_size,
+ TestOperand* inputs) {
+ VRegPair output_vregs = std::make_pair(NewReg(), NewReg());
+ InstructionOperand outputs[2]{
+ ConvertOutputOp(output_vregs.first, output_op_0),
+ ConvertOutputOp(output_vregs.second, output_op_1)};
+ InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
+ Emit(kArchNop, 2, outputs, input_size, mapped_inputs);
+ return output_vregs;
+}
+
+
+InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
+ TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0,
+ TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) {
+ TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
+ return EmitOOI(output_op_0, output_op_1,
+ CountInputs(arraysize(inputs), inputs), inputs);
+}
+
+
InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
TestOperand output_op, size_t input_size, TestOperand* inputs) {
VReg output_vreg = NewReg();
InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy());
InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
- Emit(output_vreg.value_, kArchCallCodeObject, 1, outputs, input_size,
- mapped_inputs, 0, nullptr, true);
+ Emit(kArchCallCodeObject, 1, outputs, input_size, mapped_inputs, 0, nullptr,
+ true);
return output_vreg;
}
@@ -263,36 +285,26 @@ InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
}
-const Instruction* InstructionSequenceTest::GetInstruction(
- int instruction_index) {
- auto it = instructions_.find(instruction_index);
- CHECK(it != instructions_.end());
- return it->second;
-}
-
-
-int InstructionSequenceTest::EmitBranch(TestOperand input_op) {
+Instruction* InstructionSequenceTest::EmitBranch(TestOperand input_op) {
InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()),
ConvertInputOp(Imm()), ConvertInputOp(Imm())};
InstructionCode opcode = kArchJmp | FlagsModeField::encode(kFlags_branch) |
FlagsConditionField::encode(kEqual);
- auto instruction =
- NewInstruction(opcode, 0, nullptr, 4, inputs)->MarkAsControl();
- return AddInstruction(NewIndex(), instruction);
+ auto instruction = NewInstruction(opcode, 0, nullptr, 4, inputs);
+ return AddInstruction(instruction);
}
-int InstructionSequenceTest::EmitFallThrough() {
- auto instruction = NewInstruction(kArchNop, 0, nullptr)->MarkAsControl();
- return AddInstruction(NewIndex(), instruction);
+Instruction* InstructionSequenceTest::EmitFallThrough() {
+ auto instruction = NewInstruction(kArchNop, 0, nullptr);
+ return AddInstruction(instruction);
}
-int InstructionSequenceTest::EmitJump() {
+Instruction* InstructionSequenceTest::EmitJump() {
InstructionOperand inputs[1]{ConvertInputOp(Imm())};
- auto instruction =
- NewInstruction(kArchJmp, 0, nullptr, 1, inputs)->MarkAsControl();
- return AddInstruction(NewIndex(), instruction);
+ auto instruction = NewInstruction(kArchJmp, 0, nullptr, 1, inputs);
+ return AddInstruction(instruction);
}
@@ -359,6 +371,9 @@ InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
case kRegister:
return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER,
UnallocatedOperand::USED_AT_START);
+ case kSlot:
+ return Unallocated(op, UnallocatedOperand::MUST_HAVE_SLOT,
+ UnallocatedOperand::USED_AT_START);
case kFixedRegister:
CHECK(0 <= op.value_ && op.value_ < num_general_registers_);
return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_);
@@ -396,15 +411,14 @@ InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg,
InstructionBlock* InstructionSequenceTest::NewBlock() {
CHECK(current_block_ == nullptr);
- auto block_id = BasicBlock::Id::FromSize(instruction_blocks_.size());
- Rpo rpo = Rpo::FromInt(block_id.ToInt());
+ Rpo rpo = Rpo::FromInt(static_cast<int>(instruction_blocks_.size()));
Rpo loop_header = Rpo::Invalid();
Rpo loop_end = Rpo::Invalid();
if (!loop_blocks_.empty()) {
auto& loop_data = loop_blocks_.back();
// This is a loop header.
if (!loop_data.loop_header_.IsValid()) {
- loop_end = Rpo::FromInt(block_id.ToInt() + loop_data.expected_blocks_);
+ loop_end = Rpo::FromInt(rpo.ToInt() + loop_data.expected_blocks_);
loop_data.expected_blocks_--;
loop_data.loop_header_ = rpo;
} else {
@@ -416,8 +430,8 @@ InstructionBlock* InstructionSequenceTest::NewBlock() {
}
}
// Construct instruction block.
- auto instruction_block = new (zone())
- InstructionBlock(zone(), block_id, rpo, loop_header, loop_end, false);
+ auto instruction_block =
+ new (zone()) InstructionBlock(zone(), rpo, loop_header, loop_end, false);
instruction_blocks_.push_back(instruction_block);
current_block_ = instruction_block;
sequence()->StartBlock(rpo);
@@ -458,23 +472,20 @@ void InstructionSequenceTest::WireBlock(size_t block_offset, int jump_offset) {
}
-int InstructionSequenceTest::Emit(int instruction_index, InstructionCode code,
- size_t outputs_size,
- InstructionOperand* outputs,
- size_t inputs_size,
- InstructionOperand* inputs, size_t temps_size,
- InstructionOperand* temps, bool is_call) {
+Instruction* InstructionSequenceTest::Emit(
+ InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
+ size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
+ InstructionOperand* temps, bool is_call) {
auto instruction = NewInstruction(code, outputs_size, outputs, inputs_size,
inputs, temps_size, temps);
if (is_call) instruction->MarkAsCall();
- return AddInstruction(instruction_index, instruction);
+ return AddInstruction(instruction);
}
-int InstructionSequenceTest::AddInstruction(int instruction_index,
- Instruction* instruction) {
+Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) {
sequence()->AddInstruction(instruction);
- return instruction_index;
+ return instruction;
}
} // namespace compiler
diff --git a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.h b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.h
index 613e25883e..2d75da7e47 100644
--- a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.h
+++ b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.h
@@ -18,7 +18,7 @@ class InstructionSequenceTest : public TestWithIsolateAndZone {
static const int kDefaultNRegs = 4;
static const int kNoValue = kMinInt;
- typedef BasicBlock::RpoNumber Rpo;
+ typedef RpoNumber Rpo;
struct VReg {
VReg() : value_(kNoValue) {}
@@ -27,6 +27,8 @@ class InstructionSequenceTest : public TestWithIsolateAndZone {
int value_;
};
+ typedef std::pair<VReg, VReg> VRegPair;
+
enum TestOperandType {
kInvalid,
kSameAsFirst,
@@ -125,14 +127,14 @@ class InstructionSequenceTest : public TestWithIsolateAndZone {
void StartLoop(int loop_blocks);
void EndLoop();
void StartBlock();
- int EndBlock(BlockCompletion completion = FallThrough());
+ Instruction* EndBlock(BlockCompletion completion = FallThrough());
TestOperand Imm(int32_t imm = 0);
VReg Define(TestOperand output_op);
VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); }
- int Return(TestOperand input_op_0);
- int Return(VReg vreg) { return Return(Reg(vreg, 0)); }
+ Instruction* Return(TestOperand input_op_0);
+ Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); }
PhiInstruction* Phi(VReg incoming_vreg_0 = VReg(),
VReg incoming_vreg_1 = VReg(),
@@ -142,27 +144,30 @@ class InstructionSequenceTest : public TestWithIsolateAndZone {
void SetInput(PhiInstruction* phi, size_t input, VReg vreg);
VReg DefineConstant(int32_t imm = 0);
- int EmitNop();
- int EmitI(size_t input_size, TestOperand* inputs);
- int EmitI(TestOperand input_op_0 = TestOperand(),
- TestOperand input_op_1 = TestOperand(),
- TestOperand input_op_2 = TestOperand(),
- TestOperand input_op_3 = TestOperand());
+ Instruction* EmitNop();
+ Instruction* EmitI(size_t input_size, TestOperand* inputs);
+ Instruction* EmitI(TestOperand input_op_0 = TestOperand(),
+ TestOperand input_op_1 = TestOperand(),
+ TestOperand input_op_2 = TestOperand(),
+ TestOperand input_op_3 = TestOperand());
VReg EmitOI(TestOperand output_op, size_t input_size, TestOperand* inputs);
VReg EmitOI(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
TestOperand input_op_1 = TestOperand(),
TestOperand input_op_2 = TestOperand(),
TestOperand input_op_3 = TestOperand());
+ VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
+ size_t input_size, TestOperand* inputs);
+ VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
+ TestOperand input_op_0 = TestOperand(),
+ TestOperand input_op_1 = TestOperand(),
+ TestOperand input_op_2 = TestOperand(),
+ TestOperand input_op_3 = TestOperand());
VReg EmitCall(TestOperand output_op, size_t input_size, TestOperand* inputs);
VReg EmitCall(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
TestOperand input_op_1 = TestOperand(),
TestOperand input_op_2 = TestOperand(),
TestOperand input_op_3 = TestOperand());
- // Get defining instruction vreg or value returned at instruction creation
- // time when there is no return value.
- const Instruction* GetInstruction(int instruction_index);
-
InstructionBlock* current_block() const { return current_block_; }
int num_general_registers() const { return num_general_registers_; }
int num_double_registers() const { return num_double_registers_; }
@@ -172,13 +177,12 @@ class InstructionSequenceTest : public TestWithIsolateAndZone {
private:
VReg NewReg() { return VReg(sequence()->NextVirtualRegister()); }
- int NewIndex() { return current_instruction_index_--; }
static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); }
- int EmitBranch(TestOperand input_op);
- int EmitFallThrough();
- int EmitJump();
+ Instruction* EmitBranch(TestOperand input_op);
+ Instruction* EmitFallThrough();
+ Instruction* EmitJump();
Instruction* NewInstruction(InstructionCode code, size_t outputs_size,
InstructionOperand* outputs,
size_t inputs_size = 0,
@@ -202,12 +206,13 @@ class InstructionSequenceTest : public TestWithIsolateAndZone {
InstructionBlock* NewBlock();
void WireBlock(size_t block_offset, int jump_offset);
- int Emit(int instruction_index, InstructionCode code, size_t outputs_size = 0,
- InstructionOperand* outputs = nullptr, size_t inputs_size = 0,
- InstructionOperand* inputs = nullptr, size_t temps_size = 0,
- InstructionOperand* temps = nullptr, bool is_call = false);
+ Instruction* Emit(InstructionCode code, size_t outputs_size = 0,
+ InstructionOperand* outputs = nullptr,
+ size_t inputs_size = 0,
+ InstructionOperand* inputs = nullptr, size_t temps_size = 0,
+ InstructionOperand* temps = nullptr, bool is_call = false);
- int AddInstruction(int instruction_index, Instruction* instruction);
+ Instruction* AddInstruction(Instruction* instruction);
struct LoopData {
Rpo loop_header_;
@@ -226,7 +231,6 @@ class InstructionSequenceTest : public TestWithIsolateAndZone {
// Block building state.
InstructionBlocks instruction_blocks_;
Instructions instructions_;
- int current_instruction_index_;
Completions completions_;
LoopBlocks loop_blocks_;
InstructionBlock* current_block_;
diff --git a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
index b5c688e147..5c508a5d4b 100644
--- a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -62,58 +62,6 @@ Type* const kNumberTypes[] = {
// -----------------------------------------------------------------------------
-// Math.abs
-
-
-TEST_F(JSBuiltinReducerTest, MathAbs) {
- Handle<JSFunction> f = MathFunction("abs");
-
- TRACED_FOREACH(Type*, t0, kNumberTypes) {
- Node* p0 = Parameter(t0, 0);
- Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
- Node* call =
- graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
- fun, UndefinedConstant(), p0);
- Reduction r = Reduce(call);
-
- if (t0->Is(Type::Unsigned32())) {
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), p0);
- } else {
- Capture<Node*> branch;
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsSelect(kMachNone,
- IsNumberLessThan(IsNumberConstant(BitEq(0.0)), p0), p0,
- IsNumberSubtract(IsNumberConstant(BitEq(0.0)), p0)));
- }
- }
-}
-
-
-// -----------------------------------------------------------------------------
-// Math.sqrt
-
-
-TEST_F(JSBuiltinReducerTest, MathSqrt) {
- Handle<JSFunction> f = MathFunction("sqrt");
-
- TRACED_FOREACH(Type*, t0, kNumberTypes) {
- Node* p0 = Parameter(t0, 0);
- Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
- Node* call =
- graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
- fun, UndefinedConstant(), p0);
- Reduction r = Reduce(call);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsFloat64Sqrt(p0));
- }
-}
-
-
-// -----------------------------------------------------------------------------
// Math.max
@@ -223,79 +171,6 @@ TEST_F(JSBuiltinReducerTest, MathFround) {
}
}
-
-// -----------------------------------------------------------------------------
-// Math.floor
-
-
-TEST_F(JSBuiltinReducerTest, MathFloorAvailable) {
- Handle<JSFunction> f = MathFunction("floor");
-
- TRACED_FOREACH(Type*, t0, kNumberTypes) {
- Node* p0 = Parameter(t0, 0);
- Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
- Node* call =
- graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
- fun, UndefinedConstant(), p0);
- Reduction r = Reduce(call, MachineOperatorBuilder::Flag::kFloat64Floor);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsFloat64Floor(p0));
- }
-}
-
-
-TEST_F(JSBuiltinReducerTest, MathFloorUnavailable) {
- Handle<JSFunction> f = MathFunction("floor");
-
- TRACED_FOREACH(Type*, t0, kNumberTypes) {
- Node* p0 = Parameter(t0, 0);
- Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
- Node* call =
- graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
- fun, UndefinedConstant(), p0);
- Reduction r = Reduce(call, MachineOperatorBuilder::Flag::kNoFlags);
-
- ASSERT_FALSE(r.Changed());
- }
-}
-
-
-// -----------------------------------------------------------------------------
-// Math.ceil
-
-
-TEST_F(JSBuiltinReducerTest, MathCeilAvailable) {
- Handle<JSFunction> f = MathFunction("ceil");
-
- TRACED_FOREACH(Type*, t0, kNumberTypes) {
- Node* p0 = Parameter(t0, 0);
- Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
- Node* call =
- graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
- fun, UndefinedConstant(), p0);
- Reduction r = Reduce(call, MachineOperatorBuilder::Flag::kFloat64Ceil);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsFloat64Ceil(p0));
- }
-}
-
-
-TEST_F(JSBuiltinReducerTest, MathCeilUnavailable) {
- Handle<JSFunction> f = MathFunction("ceil");
-
- TRACED_FOREACH(Type*, t0, kNumberTypes) {
- Node* p0 = Parameter(t0, 0);
- Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
- Node* call =
- graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
- fun, UndefinedConstant(), p0);
- Reduction r = Reduce(call, MachineOperatorBuilder::Flag::kNoFlags);
-
- ASSERT_FALSE(r.Changed());
- }
-}
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
index 20d5c069fe..8adbc54ac2 100644
--- a/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
@@ -27,8 +27,9 @@ class JSIntrinsicLoweringTest : public GraphTest {
~JSIntrinsicLoweringTest() OVERRIDE {}
protected:
- Reduction Reduce(Node* node) {
- MachineOperatorBuilder machine(zone());
+ Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
+ MachineOperatorBuilder::kNoFlags) {
+ MachineOperatorBuilder machine(zone(), kMachPtr, flags);
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
JSIntrinsicLowering reducer(&jsgraph);
return reducer.Reduce(node);
@@ -42,6 +43,61 @@ class JSIntrinsicLoweringTest : public GraphTest {
// -----------------------------------------------------------------------------
+// %_ConstructDouble
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineOptimizedConstructDouble) {
+ Node* const input0 = Parameter(0);
+ Node* const input1 = Parameter(1);
+ Node* const context = Parameter(2);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(graph()->NewNode(
+ javascript()->CallRuntime(Runtime::kInlineConstructDouble, 2), input0,
+ input1, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64InsertHighWord32(
+ IsFloat64InsertLowWord32(
+ IsNumberConstant(BitEq(0.0)), input1),
+ input0));
+}
+
+
+// -----------------------------------------------------------------------------
+// %_DoubleLo
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleLo) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(
+ graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleLo, 1),
+ input, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64ExtractLowWord32(input));
+}
+
+
+// -----------------------------------------------------------------------------
+// %_DoubleHi
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleHi) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(
+ graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleHi, 1),
+ input, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64ExtractHighWord32(input));
+}
+
+
+// -----------------------------------------------------------------------------
// %_IsSmi
@@ -169,6 +225,94 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsRegExp) {
// -----------------------------------------------------------------------------
+// %_JSValueGetValue
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineJSValueGetValue) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(graph()->NewNode(
+ javascript()->CallRuntime(Runtime::kInlineJSValueGetValue, 1), input,
+ context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsLoadField(AccessBuilder::ForValue(), input, effect, control));
+}
+
+
+// -----------------------------------------------------------------------------
+// %_MathFloor
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineMathFloor) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(
+ graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineMathFloor, 1),
+ input, context, effect, control),
+ MachineOperatorBuilder::kFloat64RoundDown);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64RoundDown(input));
+}
+
+
+// -----------------------------------------------------------------------------
+// %_MathSqrt
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineMathSqrt) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(
+ graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineMathSqrt, 1),
+ input, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Sqrt(input));
+}
+
+
+// -----------------------------------------------------------------------------
+// %_StringGetLength
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineStringGetLength) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(graph()->NewNode(
+ javascript()->CallRuntime(Runtime::kInlineStringGetLength, 1), input,
+ context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
+ input, effect, control));
+}
+
+
+// -----------------------------------------------------------------------------
+// %_MathClz32
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineMathClz32) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(
+ graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineMathClz32, 1),
+ input, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsWord32Clz(input));
+}
+
+
+// -----------------------------------------------------------------------------
// %_ValueOf
diff --git a/deps/v8/test/unittests/compiler/js-operator-unittest.cc b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
index 8f4622ae67..7ecaed016d 100644
--- a/deps/v8/test/unittests/compiler/js-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
@@ -28,6 +28,7 @@ struct SharedOperator {
int control_input_count;
int value_output_count;
int effect_output_count;
+ int control_output_count;
};
@@ -39,48 +40,48 @@ std::ostream& operator<<(std::ostream& os, const SharedOperator& sop) {
const SharedOperator kSharedOperators[] = {
#define SHARED(Name, properties, value_input_count, frame_state_input_count, \
effect_input_count, control_input_count, value_output_count, \
- effect_output_count) \
+ effect_output_count, control_output_count) \
{ \
&JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties, \
value_input_count, frame_state_input_count, effect_input_count, \
- control_input_count, value_output_count, effect_output_count \
+ control_input_count, value_output_count, effect_output_count, \
+ control_output_count \
}
- SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(StrictEqual, Operator::kPure, 2, 0, 0, 0, 1, 0),
- SHARED(StrictNotEqual, Operator::kPure, 2, 0, 0, 0, 1, 0),
- SHARED(LessThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(GreaterThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(BitwiseOr, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(BitwiseXor, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(BitwiseAnd, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(ShiftLeft, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(ShiftRight, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(ShiftRightLogical, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(Add, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(Subtract, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(Multiply, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(Divide, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(Modulus, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(UnaryNot, Operator::kPure, 1, 0, 0, 0, 1, 0),
- SHARED(ToBoolean, Operator::kPure, 1, 0, 0, 0, 1, 0),
- SHARED(ToNumber, Operator::kNoProperties, 1, 1, 1, 1, 1, 1),
- SHARED(ToString, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
- SHARED(ToName, Operator::kNoProperties, 1, 1, 1, 1, 1, 1),
- SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1),
- SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
- SHARED(Create, Operator::kEliminatable, 0, 0, 1, 1, 1, 1),
- SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0),
- SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(Debugger, Operator::kNoProperties, 0, 0, 1, 1, 0, 1),
- SHARED(CreateFunctionContext, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
- SHARED(CreateWithContext, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
- SHARED(CreateBlockContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1),
- SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1),
- SHARED(CreateScriptContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1)
+ SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(StrictEqual, Operator::kPure, 2, 0, 0, 0, 1, 0, 0),
+ SHARED(StrictNotEqual, Operator::kPure, 2, 0, 0, 0, 1, 0, 0),
+ SHARED(LessThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(GreaterThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(BitwiseOr, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(BitwiseXor, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(BitwiseAnd, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(ShiftLeft, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(ShiftRight, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(ShiftRightLogical, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(Add, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(Subtract, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(UnaryNot, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
+ SHARED(ToBoolean, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
+ SHARED(ToNumber, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
+ SHARED(ToString, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
+ SHARED(ToName, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
+ SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
+ SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
+ SHARED(Create, Operator::kEliminatable, 0, 0, 1, 0, 1, 1, 0),
+ SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
+ SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(CreateFunctionContext, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
+ SHARED(CreateWithContext, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(CreateBlockContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
+ SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
+ SHARED(CreateScriptContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2)
#undef SHARED
};
@@ -122,7 +123,7 @@ TEST_P(JSSharedOperatorTest, NumberOfInputsAndOutputs) {
EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
- EXPECT_EQ(0, op->ControlOutputCount());
+ EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
}
@@ -169,7 +170,7 @@ TEST_P(JSStorePropertyOperatorTest, NumberOfInputsAndOutputs) {
const Operator* op = javascript.StoreProperty(mode);
// TODO(jarin): Get rid of this hack.
- const int frame_state_input_count = FLAG_turbo_deoptimization ? 1 : 0;
+ const int frame_state_input_count = FLAG_turbo_deoptimization ? 2 : 0;
EXPECT_EQ(3, op->ValueInputCount());
EXPECT_EQ(1, OperatorProperties::GetContextInputCount(op));
EXPECT_EQ(frame_state_input_count,
@@ -181,7 +182,7 @@ TEST_P(JSStorePropertyOperatorTest, NumberOfInputsAndOutputs) {
EXPECT_EQ(0, op->ValueOutputCount());
EXPECT_EQ(1, op->EffectOutputCount());
- EXPECT_EQ(0, op->ControlOutputCount());
+ EXPECT_EQ(2, op->ControlOutputCount());
}
diff --git a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
index d61a1817b2..d347c4139b 100644
--- a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -8,6 +8,7 @@
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties.h"
+#include "src/compiler/operator-properties.h"
#include "test/unittests/compiler/compiler-test-utils.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
@@ -119,6 +120,16 @@ TEST_F(JSTypedLoweringTest, JSUnaryNotWithBoolean) {
}
+TEST_F(JSTypedLoweringTest, JSUnaryNotWithOrderedNumber) {
+ Node* input = Parameter(Type::OrderedNumber(), 0);
+ Node* context = Parameter(Type::Any(), 1);
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->UnaryNot(), input, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberEqual(input, IsNumberConstant(0)));
+}
+
+
TEST_F(JSTypedLoweringTest, JSUnaryNotWithFalsish) {
Node* input = Parameter(
Type::Union(
@@ -173,13 +184,25 @@ TEST_F(JSTypedLoweringTest, JSUnaryNotWithNonZeroPlainNumber) {
}
+TEST_F(JSTypedLoweringTest, JSUnaryNotWithString) {
+ Node* input = Parameter(Type::String(), 0);
+ Node* context = Parameter(Type::Any(), 1);
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->UnaryNot(), input, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsNumberEqual(IsLoadField(AccessBuilder::ForStringLength(), input,
+ graph()->start(), graph()->start()),
+ IsNumberConstant(0.0)));
+}
+
+
TEST_F(JSTypedLoweringTest, JSUnaryNotWithAny) {
Node* input = Parameter(Type::Any(), 0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->UnaryNot(), input, context));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsBooleanNot(IsAnyToBoolean(input)));
+ ASSERT_FALSE(r.Changed());
}
@@ -349,13 +372,37 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
}
+TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
+ Node* input = Parameter(Type::OrderedNumber(), 0);
+ Node* context = Parameter(Type::Any(), 1);
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->ToBoolean(), input, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0))));
+}
+
+
+TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
+ Node* input = Parameter(Type::String(), 0);
+ Node* context = Parameter(Type::Any(), 1);
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->ToBoolean(), input, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsNumberLessThan(IsNumberConstant(0.0),
+ IsLoadField(AccessBuilder::ForStringLength(), input,
+ graph()->start(), graph()->start())));
+}
+
+
TEST_F(JSTypedLoweringTest, JSToBooleanWithAny) {
Node* input = Parameter(Type::Any(), 0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(), input, context));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsAnyToBoolean(input));
+ ASSERT_FALSE(r.Changed());
}
@@ -681,8 +728,9 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
Node* control = graph()->start();
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
base, key, value, context);
- if (FLAG_turbo_deoptimization) {
- node->AppendInput(zone(), UndefinedConstant());
+ for (int i = 0;
+ i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
+ node->AppendInput(zone(), EmptyFrameState());
}
node->AppendInput(zone(), effect);
node->AppendInput(zone(), control);
@@ -726,8 +774,9 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
Node* control = graph()->start();
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
base, key, value, context);
- if (FLAG_turbo_deoptimization) {
- node->AppendInput(zone(), UndefinedConstant());
+ for (int i = 0;
+ i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
+ node->AppendInput(zone(), EmptyFrameState());
}
node->AppendInput(zone(), effect);
node->AppendInput(zone(), control);
@@ -784,8 +833,9 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) {
Node* control = graph()->start();
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
base, key, value, context);
- if (FLAG_turbo_deoptimization) {
- node->AppendInput(zone(), UndefinedConstant());
+ for (int i = 0;
+ i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
+ node->AppendInput(zone(), EmptyFrameState());
}
node->AppendInput(zone(), effect);
node->AppendInput(zone(), control);
diff --git a/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
new file mode 100644
index 0000000000..f7d0db354d
--- /dev/null
+++ b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
@@ -0,0 +1,373 @@
+// 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.
+
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/liveness-analyzer.h"
+#include "src/compiler/node-matchers.h"
+#include "src/compiler/state-values-utils.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+
+using testing::MakeMatcher;
+using testing::MatcherInterface;
+using testing::MatchResultListener;
+using testing::StringMatchResultListener;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class LivenessAnalysisTest : public GraphTest {
+ public:
+ explicit LivenessAnalysisTest(int locals_count = 4)
+ : locals_count_(locals_count),
+ machine_(zone(), kRepWord32),
+ javascript_(zone()),
+ jsgraph_(isolate(), graph(), common(), &javascript_, &machine_),
+ analyzer_(locals_count, zone()),
+ empty_values_(graph()->NewNode(common()->StateValues(0), 0, nullptr)),
+ next_checkpoint_id_(0),
+ current_block_(nullptr) {}
+
+
+ protected:
+ JSGraph* jsgraph() { return &jsgraph_; }
+
+ LivenessAnalyzer* analyzer() { return &analyzer_; }
+ void Run() {
+ StateValuesCache cache(jsgraph());
+ NonLiveFrameStateSlotReplacer replacer(&cache,
+ jsgraph()->UndefinedConstant(),
+ analyzer()->local_count(), zone());
+ analyzer()->Run(&replacer);
+ }
+
+ Node* Checkpoint() {
+ int ast_num = next_checkpoint_id_++;
+ int first_const = intconst_from_bailout_id(ast_num, locals_count_);
+
+ const Operator* locals_op = common()->StateValues(locals_count_);
+
+ ZoneVector<Node*> local_inputs(locals_count_, nullptr, zone());
+ for (int i = 0; i < locals_count_; i++) {
+ local_inputs[i] = jsgraph()->Int32Constant(i + first_const);
+ }
+ Node* locals =
+ graph()->NewNode(locals_op, locals_count_, &local_inputs.front());
+
+ const Operator* op = common()->FrameState(
+ JS_FRAME, BailoutId(ast_num), OutputFrameStateCombine::Ignore());
+ Node* result = graph()->NewNode(op, empty_values_, locals, empty_values_,
+ jsgraph()->UndefinedConstant(),
+ jsgraph()->UndefinedConstant());
+
+ current_block_->Checkpoint(result);
+ return result;
+ }
+
+ void Bind(int var) { current_block()->Bind(var); }
+ void Lookup(int var) { current_block()->Lookup(var); }
+
+ class CheckpointMatcher : public MatcherInterface<Node*> {
+ public:
+ explicit CheckpointMatcher(const char* liveness, Node* empty_values,
+ int locals_count, Node* replacement)
+ : liveness_(liveness),
+ empty_values_(empty_values),
+ locals_count_(locals_count),
+ replacement_(replacement) {}
+
+ void DescribeTo(std::ostream* os) const OVERRIDE {
+ *os << "is a frame state with '" << liveness_
+ << "' liveness, empty "
+ "parameters and empty expression stack";
+ }
+
+ bool MatchAndExplain(Node* frame_state,
+ MatchResultListener* listener) const OVERRIDE {
+ if (frame_state == NULL) {
+ *listener << "which is NULL";
+ return false;
+ }
+ DCHECK(frame_state->opcode() == IrOpcode::kFrameState);
+
+ FrameStateCallInfo state_info =
+ OpParameter<FrameStateCallInfo>(frame_state);
+ int ast_num = state_info.bailout_id().ToInt();
+ int first_const = intconst_from_bailout_id(ast_num, locals_count_);
+
+ if (empty_values_ != frame_state->InputAt(0)) {
+ *listener << "whose parameters are " << frame_state->InputAt(0)
+ << " but should have been " << empty_values_ << " (empty)";
+ return false;
+ }
+ if (empty_values_ != frame_state->InputAt(2)) {
+ *listener << "whose expression stack is " << frame_state->InputAt(2)
+ << " but should have been " << empty_values_ << " (empty)";
+ return false;
+ }
+ StateValuesAccess locals(frame_state->InputAt(1));
+ if (locals_count_ != static_cast<int>(locals.size())) {
+ *listener << "whose number of locals is " << locals.size()
+ << " but should have been " << locals_count_;
+ return false;
+ }
+ int i = 0;
+ for (StateValuesAccess::TypedNode value : locals) {
+ if (liveness_[i] == 'L') {
+ StringMatchResultListener value_listener;
+ if (value.node == replacement_) {
+ *listener << "whose local #" << i << " was " << value.node->opcode()
+ << " but should have been 'undefined'";
+ return false;
+ } else if (!IsInt32Constant(first_const + i)
+ .MatchAndExplain(value.node, &value_listener)) {
+ *listener << "whose local #" << i << " does not match";
+ if (value_listener.str() != "") {
+ *listener << ", " << value_listener.str();
+ }
+ return false;
+ }
+ } else if (liveness_[i] == '.') {
+ if (value.node != replacement_) {
+ *listener << "whose local #" << i << " is " << value.node
+ << " but should have been " << replacement_
+ << " (undefined)";
+ return false;
+ }
+ } else {
+ UNREACHABLE();
+ }
+ i++;
+ }
+ return true;
+ }
+
+ private:
+ const char* liveness_;
+ Node* empty_values_;
+ int locals_count_;
+ Node* replacement_;
+ };
+
+ Matcher<Node*> IsCheckpointModuloLiveness(const char* liveness) {
+ return MakeMatcher(new CheckpointMatcher(liveness, empty_values_,
+ locals_count_,
+ jsgraph()->UndefinedConstant()));
+ }
+
+ LivenessAnalyzerBlock* current_block() { return current_block_; }
+ void set_current_block(LivenessAnalyzerBlock* block) {
+ current_block_ = block;
+ }
+
+ private:
+ static int intconst_from_bailout_id(int ast_num, int locals_count) {
+ return (locals_count + 1) * ast_num + 1;
+ }
+
+ int locals_count_;
+ MachineOperatorBuilder machine_;
+ JSOperatorBuilder javascript_;
+ JSGraph jsgraph_;
+ LivenessAnalyzer analyzer_;
+ Node* empty_values_;
+ int next_checkpoint_id_;
+ LivenessAnalyzerBlock* current_block_;
+};
+
+
+TEST_F(LivenessAnalysisTest, EmptyBlock) {
+ set_current_block(analyzer()->NewBlock());
+
+ Node* c1 = Checkpoint();
+
+ Run();
+
+ // Nothing is live.
+ EXPECT_THAT(c1, IsCheckpointModuloLiveness("...."));
+}
+
+
+TEST_F(LivenessAnalysisTest, SimpleLookup) {
+ set_current_block(analyzer()->NewBlock());
+
+ Node* c1 = Checkpoint();
+ Lookup(1);
+ Node* c2 = Checkpoint();
+
+ Run();
+
+ EXPECT_THAT(c1, IsCheckpointModuloLiveness(".L.."));
+ EXPECT_THAT(c2, IsCheckpointModuloLiveness("...."));
+}
+
+
+TEST_F(LivenessAnalysisTest, DiamondLookups) {
+ // Start block.
+ LivenessAnalyzerBlock* start = analyzer()->NewBlock();
+ set_current_block(start);
+ Node* c1_start = Checkpoint();
+
+ // First branch.
+ LivenessAnalyzerBlock* b1 = analyzer()->NewBlock(start);
+ set_current_block(b1);
+
+ Node* c1_b1 = Checkpoint();
+ Lookup(1);
+ Node* c2_b1 = Checkpoint();
+ Lookup(3);
+ Node* c3_b1 = Checkpoint();
+
+ // Second branch.
+ LivenessAnalyzerBlock* b2 = analyzer()->NewBlock(start);
+ set_current_block(b2);
+
+ Node* c1_b2 = Checkpoint();
+ Lookup(3);
+ Node* c2_b2 = Checkpoint();
+ Lookup(2);
+ Node* c3_b2 = Checkpoint();
+
+ // Merge block.
+ LivenessAnalyzerBlock* m = analyzer()->NewBlock(b1);
+ m->AddPredecessor(b2);
+ set_current_block(m);
+ Node* c1_m = Checkpoint();
+ Lookup(0);
+ Node* c2_m = Checkpoint();
+
+ Run();
+
+ EXPECT_THAT(c1_start, IsCheckpointModuloLiveness("LLLL"));
+
+ EXPECT_THAT(c1_b1, IsCheckpointModuloLiveness("LL.L"));
+ EXPECT_THAT(c2_b1, IsCheckpointModuloLiveness("L..L"));
+ EXPECT_THAT(c3_b1, IsCheckpointModuloLiveness("L..."));
+
+ EXPECT_THAT(c1_b2, IsCheckpointModuloLiveness("L.LL"));
+ EXPECT_THAT(c2_b2, IsCheckpointModuloLiveness("L.L."));
+ EXPECT_THAT(c3_b2, IsCheckpointModuloLiveness("L..."));
+
+ EXPECT_THAT(c1_m, IsCheckpointModuloLiveness("L..."));
+ EXPECT_THAT(c2_m, IsCheckpointModuloLiveness("...."));
+}
+
+
+TEST_F(LivenessAnalysisTest, DiamondLookupsAndBinds) {
+ // Start block.
+ LivenessAnalyzerBlock* start = analyzer()->NewBlock();
+ set_current_block(start);
+ Node* c1_start = Checkpoint();
+ Bind(0);
+ Node* c2_start = Checkpoint();
+
+ // First branch.
+ LivenessAnalyzerBlock* b1 = analyzer()->NewBlock(start);
+ set_current_block(b1);
+
+ Node* c1_b1 = Checkpoint();
+ Bind(2);
+ Bind(1);
+ Node* c2_b1 = Checkpoint();
+ Bind(3);
+ Node* c3_b1 = Checkpoint();
+
+ // Second branch.
+ LivenessAnalyzerBlock* b2 = analyzer()->NewBlock(start);
+ set_current_block(b2);
+
+ Node* c1_b2 = Checkpoint();
+ Lookup(2);
+ Node* c2_b2 = Checkpoint();
+ Bind(2);
+ Bind(3);
+ Node* c3_b2 = Checkpoint();
+
+ // Merge block.
+ LivenessAnalyzerBlock* m = analyzer()->NewBlock(b1);
+ m->AddPredecessor(b2);
+ set_current_block(m);
+ Node* c1_m = Checkpoint();
+ Lookup(0);
+ Lookup(1);
+ Lookup(2);
+ Lookup(3);
+ Node* c2_m = Checkpoint();
+
+ Run();
+
+ EXPECT_THAT(c1_start, IsCheckpointModuloLiveness(".LL."));
+ EXPECT_THAT(c2_start, IsCheckpointModuloLiveness("LLL."));
+
+ EXPECT_THAT(c1_b1, IsCheckpointModuloLiveness("L..."));
+ EXPECT_THAT(c2_b1, IsCheckpointModuloLiveness("LLL."));
+ EXPECT_THAT(c3_b1, IsCheckpointModuloLiveness("LLLL"));
+
+ EXPECT_THAT(c1_b2, IsCheckpointModuloLiveness("LLL."));
+ EXPECT_THAT(c2_b2, IsCheckpointModuloLiveness("LL.."));
+ EXPECT_THAT(c3_b2, IsCheckpointModuloLiveness("LLLL"));
+
+ EXPECT_THAT(c1_m, IsCheckpointModuloLiveness("LLLL"));
+ EXPECT_THAT(c2_m, IsCheckpointModuloLiveness("...."));
+}
+
+
+TEST_F(LivenessAnalysisTest, SimpleLoop) {
+ // Start block.
+ LivenessAnalyzerBlock* start = analyzer()->NewBlock();
+ set_current_block(start);
+ Node* c1_start = Checkpoint();
+ Bind(0);
+ Bind(1);
+ Bind(2);
+ Bind(3);
+ Node* c2_start = Checkpoint();
+
+ // Loop header block.
+ LivenessAnalyzerBlock* header = analyzer()->NewBlock(start);
+ set_current_block(header);
+ Node* c1_header = Checkpoint();
+ Lookup(0);
+ Bind(2);
+ Node* c2_header = Checkpoint();
+
+ // Inside-loop block.
+ LivenessAnalyzerBlock* in_loop = analyzer()->NewBlock(header);
+ set_current_block(in_loop);
+ Node* c1_in_loop = Checkpoint();
+ Bind(0);
+ Lookup(3);
+ Node* c2_in_loop = Checkpoint();
+
+ // Add back edge.
+ header->AddPredecessor(in_loop);
+
+ // After-loop block.
+ LivenessAnalyzerBlock* end = analyzer()->NewBlock(header);
+ set_current_block(end);
+ Node* c1_end = Checkpoint();
+ Lookup(1);
+ Lookup(2);
+ Node* c2_end = Checkpoint();
+
+ Run();
+
+ EXPECT_THAT(c1_start, IsCheckpointModuloLiveness("...."));
+ EXPECT_THAT(c2_start, IsCheckpointModuloLiveness("LL.L"));
+
+ EXPECT_THAT(c1_header, IsCheckpointModuloLiveness("LL.L"));
+ EXPECT_THAT(c2_header, IsCheckpointModuloLiveness(".LLL"));
+
+ EXPECT_THAT(c1_in_loop, IsCheckpointModuloLiveness(".L.L"));
+ EXPECT_THAT(c2_in_loop, IsCheckpointModuloLiveness("LL.L"));
+
+ EXPECT_THAT(c1_end, IsCheckpointModuloLiveness(".LL."));
+ EXPECT_THAT(c2_end, IsCheckpointModuloLiveness("...."));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
index f63e70da5a..11c679cb29 100644
--- a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
@@ -233,6 +233,27 @@ const uint32_t kUint32Values[] = {
0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
+
+struct ComparisonBinaryOperator {
+ const Operator* (MachineOperatorBuilder::*constructor)();
+ const char* constructor_name;
+};
+
+
+std::ostream& operator<<(std::ostream& os,
+ ComparisonBinaryOperator const& cbop) {
+ return os << cbop.constructor_name;
+}
+
+
+const ComparisonBinaryOperator kComparisonBinaryOperators[] = {
+#define OPCODE(Opcode) \
+ { &MachineOperatorBuilder::Opcode, #Opcode } \
+ ,
+ MACHINE_COMPARE_BINOP_LIST(OPCODE)
+#undef OPCODE
+};
+
} // namespace
@@ -595,6 +616,33 @@ TEST_F(MachineOperatorReducerTest, Word32AndWithInt32AddAndConstant) {
}
+TEST_F(MachineOperatorReducerTest, Word32AndWithInt32MulAndConstant) {
+ Node* const p0 = Parameter(0);
+
+ TRACED_FORRANGE(int32_t, l, 1, 31) {
+ TRACED_FOREACH(int32_t, k, kInt32Values) {
+ if ((k << l) == 0) continue;
+
+ // (x * (K << L)) & (-1 << L) => x * (K << L)
+ Reduction const r1 = Reduce(graph()->NewNode(
+ machine()->Word32And(),
+ graph()->NewNode(machine()->Int32Mul(), p0, Int32Constant(k << l)),
+ Int32Constant(-1 << l)));
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_THAT(r1.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
+
+ // ((K << L) * x) & (-1 << L) => x * (K << L)
+ Reduction const r2 = Reduce(graph()->NewNode(
+ machine()->Word32And(),
+ graph()->NewNode(machine()->Int32Mul(), Int32Constant(k << l), p0),
+ Int32Constant(-1 << l)));
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_THAT(r2.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
+ }
+ }
+}
+
+
TEST_F(MachineOperatorReducerTest,
Word32AndWithInt32AddAndInt32MulAndConstant) {
Node* const p0 = Parameter(0);
@@ -632,6 +680,27 @@ TEST_F(MachineOperatorReducerTest,
}
+TEST_F(MachineOperatorReducerTest, Word32AndWithComparisonAndConstantOne) {
+ Node* const p0 = Parameter(0);
+ Node* const p1 = Parameter(1);
+ TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
+ Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
+
+ // cmp & 1 => cmp
+ Reduction const r1 =
+ Reduce(graph()->NewNode(machine()->Word32And(), cmp, Int32Constant(1)));
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(cmp, r1.replacement());
+
+ // 1 & cmp => cmp
+ Reduction const r2 =
+ Reduce(graph()->NewNode(machine()->Word32And(), Int32Constant(1), cmp));
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(cmp, r2.replacement());
+ }
+}
+
+
// -----------------------------------------------------------------------------
// Word32Xor
@@ -773,6 +842,24 @@ TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
// Word32Sar
+TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndComparison) {
+ Node* const p0 = Parameter(0);
+ Node* const p1 = Parameter(1);
+
+ TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
+ Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
+
+ // cmp << 31 >> 31 => 0 - cmp
+ Reduction const r = Reduce(graph()->NewNode(
+ machine()->Word32Sar(),
+ graph()->NewNode(machine()->Word32Shl(), cmp, Int32Constant(31)),
+ Int32Constant(31)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), cmp));
+ }
+}
+
+
TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
Node* const p0 = Parameter(0);
Node* const p1 = Parameter(1);
@@ -1190,6 +1277,28 @@ TEST_F(MachineOperatorReducerTest, Uint32ModWithParameters) {
// -----------------------------------------------------------------------------
+// Int32Add
+
+
+TEST_F(MachineOperatorReducerTest, Int32AddWithInt32SubWithConstantZero) {
+ Node* const p0 = Parameter(0);
+ Node* const p1 = Parameter(1);
+
+ Reduction const r1 = Reduce(graph()->NewNode(
+ machine()->Int32Add(),
+ graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p0), p1));
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_THAT(r1.replacement(), IsInt32Sub(p1, p0));
+
+ Reduction const r2 = Reduce(graph()->NewNode(
+ machine()->Int32Add(), p0,
+ graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p1)));
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_THAT(r2.replacement(), IsInt32Sub(p0, p1));
+}
+
+
+// -----------------------------------------------------------------------------
// Int32AddWithOverflow
@@ -1327,6 +1436,46 @@ TEST_F(MachineOperatorReducerTest, Float64MulWithMinusOne) {
// -----------------------------------------------------------------------------
+// Float64InsertLowWord32
+
+
+TEST_F(MachineOperatorReducerTest, Float64InsertLowWord32WithConstant) {
+ TRACED_FOREACH(double, x, kFloat64Values) {
+ TRACED_FOREACH(uint32_t, y, kUint32Values) {
+ Reduction const r =
+ Reduce(graph()->NewNode(machine()->Float64InsertLowWord32(),
+ Float64Constant(x), Uint32Constant(y)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsFloat64Constant(BitEq(bit_cast<double>(
+ (bit_cast<uint64_t>(x) & V8_UINT64_C(0xFFFFFFFF00000000)) | y))));
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// Float64InsertHighWord32
+
+
+TEST_F(MachineOperatorReducerTest, Float64InsertHighWord32WithConstant) {
+ TRACED_FOREACH(double, x, kFloat64Values) {
+ TRACED_FOREACH(uint32_t, y, kUint32Values) {
+ Reduction const r =
+ Reduce(graph()->NewNode(machine()->Float64InsertHighWord32(),
+ Float64Constant(x), Uint32Constant(y)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFloat64Constant(BitEq(bit_cast<double>(
+ (bit_cast<uint64_t>(x) & V8_UINT64_C(0xFFFFFFFF)) |
+ (static_cast<uint64_t>(y) << 32)))));
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------
// Store
diff --git a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
index 6e0df2ab44..71b3c0edd9 100644
--- a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
@@ -180,24 +180,24 @@ const PureOperator kPureOperators[] = {
PURE(Word32And, 2, 0, 1), PURE(Word32Or, 2, 0, 1), PURE(Word32Xor, 2, 0, 1),
PURE(Word32Shl, 2, 0, 1), PURE(Word32Shr, 2, 0, 1),
PURE(Word32Sar, 2, 0, 1), PURE(Word32Ror, 2, 0, 1),
- PURE(Word32Equal, 2, 0, 1), PURE(Word64And, 2, 0, 1),
- PURE(Word64Or, 2, 0, 1), PURE(Word64Xor, 2, 0, 1), PURE(Word64Shl, 2, 0, 1),
- PURE(Word64Shr, 2, 0, 1), PURE(Word64Sar, 2, 0, 1),
- PURE(Word64Ror, 2, 0, 1), PURE(Word64Equal, 2, 0, 1),
- PURE(Int32Add, 2, 0, 1), PURE(Int32AddWithOverflow, 2, 0, 2),
- PURE(Int32Sub, 2, 0, 1), PURE(Int32SubWithOverflow, 2, 0, 2),
- PURE(Int32Mul, 2, 0, 1), PURE(Int32MulHigh, 2, 0, 1),
- PURE(Int32Div, 2, 1, 1), PURE(Uint32Div, 2, 1, 1), PURE(Int32Mod, 2, 1, 1),
- PURE(Uint32Mod, 2, 1, 1), PURE(Int32LessThan, 2, 0, 1),
- PURE(Int32LessThanOrEqual, 2, 0, 1), PURE(Uint32LessThan, 2, 0, 1),
- PURE(Uint32LessThanOrEqual, 2, 0, 1), PURE(Int64Add, 2, 0, 1),
- PURE(Int64Sub, 2, 0, 1), PURE(Int64Mul, 2, 0, 1), PURE(Int64Div, 2, 0, 1),
- PURE(Uint64Div, 2, 0, 1), PURE(Int64Mod, 2, 0, 1), PURE(Uint64Mod, 2, 0, 1),
- PURE(Int64LessThan, 2, 0, 1), PURE(Int64LessThanOrEqual, 2, 0, 1),
- PURE(Uint64LessThan, 2, 0, 1), PURE(ChangeFloat32ToFloat64, 1, 0, 1),
- PURE(ChangeFloat64ToInt32, 1, 0, 1), PURE(ChangeFloat64ToUint32, 1, 0, 1),
- PURE(ChangeInt32ToInt64, 1, 0, 1), PURE(ChangeUint32ToFloat64, 1, 0, 1),
- PURE(ChangeUint32ToUint64, 1, 0, 1),
+ PURE(Word32Equal, 2, 0, 1), PURE(Word32Clz, 1, 0, 1),
+ PURE(Word64And, 2, 0, 1), PURE(Word64Or, 2, 0, 1), PURE(Word64Xor, 2, 0, 1),
+ PURE(Word64Shl, 2, 0, 1), PURE(Word64Shr, 2, 0, 1),
+ PURE(Word64Sar, 2, 0, 1), PURE(Word64Ror, 2, 0, 1),
+ PURE(Word64Equal, 2, 0, 1), PURE(Int32Add, 2, 0, 1),
+ PURE(Int32AddWithOverflow, 2, 0, 2), PURE(Int32Sub, 2, 0, 1),
+ PURE(Int32SubWithOverflow, 2, 0, 2), PURE(Int32Mul, 2, 0, 1),
+ PURE(Int32MulHigh, 2, 0, 1), PURE(Int32Div, 2, 1, 1),
+ PURE(Uint32Div, 2, 1, 1), PURE(Int32Mod, 2, 1, 1), PURE(Uint32Mod, 2, 1, 1),
+ PURE(Int32LessThan, 2, 0, 1), PURE(Int32LessThanOrEqual, 2, 0, 1),
+ PURE(Uint32LessThan, 2, 0, 1), PURE(Uint32LessThanOrEqual, 2, 0, 1),
+ PURE(Int64Add, 2, 0, 1), PURE(Int64Sub, 2, 0, 1), PURE(Int64Mul, 2, 0, 1),
+ PURE(Int64Div, 2, 0, 1), PURE(Uint64Div, 2, 0, 1), PURE(Int64Mod, 2, 0, 1),
+ PURE(Uint64Mod, 2, 0, 1), PURE(Int64LessThan, 2, 0, 1),
+ PURE(Int64LessThanOrEqual, 2, 0, 1), PURE(Uint64LessThan, 2, 0, 1),
+ PURE(ChangeFloat32ToFloat64, 1, 0, 1), PURE(ChangeFloat64ToInt32, 1, 0, 1),
+ PURE(ChangeFloat64ToUint32, 1, 0, 1), PURE(ChangeInt32ToInt64, 1, 0, 1),
+ PURE(ChangeUint32ToFloat64, 1, 0, 1), PURE(ChangeUint32ToUint64, 1, 0, 1),
PURE(TruncateFloat64ToFloat32, 1, 0, 1),
PURE(TruncateFloat64ToInt32, 1, 0, 1), PURE(TruncateInt64ToInt32, 1, 0, 1),
PURE(Float64Add, 2, 0, 1), PURE(Float64Sub, 2, 0, 1),
@@ -205,8 +205,12 @@ const PureOperator kPureOperators[] = {
PURE(Float64Mod, 2, 0, 1), PURE(Float64Sqrt, 1, 0, 1),
PURE(Float64Equal, 2, 0, 1), PURE(Float64LessThan, 2, 0, 1),
PURE(Float64LessThanOrEqual, 2, 0, 1), PURE(LoadStackPointer, 0, 0, 1),
- PURE(Float64Floor, 1, 0, 1), PURE(Float64Ceil, 1, 0, 1),
- PURE(Float64RoundTruncate, 1, 0, 1), PURE(Float64RoundTiesAway, 1, 0, 1)
+ PURE(Float64RoundDown, 1, 0, 1), PURE(Float64RoundTruncate, 1, 0, 1),
+ PURE(Float64RoundTiesAway, 1, 0, 1), PURE(Float64ExtractLowWord32, 1, 0, 1),
+ PURE(Float64ExtractHighWord32, 1, 0, 1),
+ PURE(Float64InsertLowWord32, 2, 0, 1),
+ PURE(Float64InsertHighWord32, 2, 0, 1), PURE(Float64Max, 2, 0, 1),
+ PURE(Float64Min, 2, 0, 1)
#undef PURE
};
diff --git a/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc b/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
index efe26d22b4..bafa89d581 100644
--- a/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
+++ b/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
@@ -800,6 +800,21 @@ TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
}
}
+
+TEST_F(InstructionSelectorTest, Word32Clz) {
+ StreamBuilder m(this, kMachUint32, kMachUint32);
+ Node* const p0 = m.Parameter(0);
+ Node* const n = m.Word32Clz(p0);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kMipsClz, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc b/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
index 41453337f2..0953de8c40 100644
--- a/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
@@ -166,29 +166,28 @@ const IntCmp kCmpInstructions[] = {
{{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMips64Cmp,
kMachInt64},
1U},
- {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp32,
- kMachInt32},
+ {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp, kMachInt32},
1U},
- {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp32,
+ {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp,
kMachInt32},
1U},
- {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp32,
+ {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp,
kMachInt32},
1U},
{{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
- kMips64Cmp32, kMachInt32},
+ kMips64Cmp, kMachInt32},
1U},
- {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp32,
+ {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp,
kMachInt32},
1U},
{{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
- kMips64Cmp32, kMachInt32},
+ kMips64Cmp, kMachInt32},
1U},
- {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp32,
+ {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp,
kMachUint32},
1U},
{{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
- kMips64Cmp32, kMachUint32},
+ kMips64Cmp, kMachUint32},
1U}};
@@ -753,7 +752,7 @@ TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
@@ -765,7 +764,7 @@ TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
@@ -802,6 +801,21 @@ TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
}
}
+
+TEST_F(InstructionSelectorTest, Word32Clz) {
+ StreamBuilder m(this, kMachUint32, kMachUint32);
+ Node* const p0 = m.Parameter(0);
+ Node* const n = m.Word32Clz(p0);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kMips64Clz, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/move-optimizer-unittest.cc b/deps/v8/test/unittests/compiler/move-optimizer-unittest.cc
index b8375fab10..da887fe88a 100644
--- a/deps/v8/test/unittests/compiler/move-optimizer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/move-optimizer-unittest.cc
@@ -124,6 +124,59 @@ TEST_F(MoveOptimizerTest, SplitsConstants) {
CHECK(Contains(move, Reg(0), Slot(2)));
}
+
+TEST_F(MoveOptimizerTest, SimpleMerge) {
+ StartBlock();
+ EndBlock(Branch(Imm(), 1, 2));
+
+ StartBlock();
+ EndBlock(Jump(2));
+ AddMove(LastGap(), Reg(0), Reg(1));
+
+ StartBlock();
+ EndBlock(Jump(1));
+ AddMove(LastGap(), Reg(0), Reg(1));
+
+ StartBlock();
+ EndBlock(Last());
+
+ Optimize();
+
+ auto move = LastGap()->parallel_moves()[0];
+ CHECK_EQ(1, NonRedundantSize(move));
+ CHECK(Contains(move, Reg(0), Reg(1)));
+}
+
+
+TEST_F(MoveOptimizerTest, SimpleMergeCycle) {
+ StartBlock();
+ EndBlock(Branch(Imm(), 1, 2));
+
+ StartBlock();
+ EndBlock(Jump(2));
+ auto gap_0 = LastGap();
+ AddMove(gap_0, Reg(0), Reg(1));
+ AddMove(LastGap(), Reg(1), Reg(0));
+
+ StartBlock();
+ EndBlock(Jump(1));
+ auto gap_1 = LastGap();
+ AddMove(gap_1, Reg(0), Reg(1));
+ AddMove(gap_1, Reg(1), Reg(0));
+
+ StartBlock();
+ EndBlock(Last());
+
+ Optimize();
+
+ CHECK(gap_0->IsRedundant());
+ CHECK(gap_1->IsRedundant());
+ auto move = LastGap()->parallel_moves()[0];
+ CHECK_EQ(2, NonRedundantSize(move));
+ CHECK(Contains(move, Reg(0), Reg(1)));
+ CHECK(Contains(move, Reg(1), Reg(0)));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/node-properties-unittest.cc b/deps/v8/test/unittests/compiler/node-properties-unittest.cc
index bb471bd01e..2bec4faf4d 100644
--- a/deps/v8/test/unittests/compiler/node-properties-unittest.cc
+++ b/deps/v8/test/unittests/compiler/node-properties-unittest.cc
@@ -8,7 +8,9 @@
#include "testing/gmock/include/gmock/gmock.h"
using testing::AnyOf;
+using testing::ElementsAre;
using testing::IsNull;
+using testing::UnorderedElementsAre;
namespace v8 {
namespace internal {
@@ -17,6 +19,64 @@ namespace compiler {
typedef TestWithZone NodePropertiesTest;
+namespace {
+
+const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
+ "MockOperator", 0, 0, 0, 1, 0, 0);
+const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties,
+ "MockOpEffect", 0, 1, 0, 1, 1, 0);
+const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties,
+ "MockOpControl", 0, 0, 1, 1, 0, 1);
+const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties,
+ "MockCallOperator", 0, 0, 0, 0, 0, 2);
+
+} // namespace
+
+
+TEST_F(NodePropertiesTest, ReplaceWithValue_ValueUse) {
+ CommonOperatorBuilder common(zone());
+ Node* node = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
+ Node* use_value = Node::New(zone(), 0, common.Return(), 1, &node, false);
+ Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
+ NodeProperties::ReplaceWithValue(node, replacement);
+ EXPECT_EQ(replacement, use_value->InputAt(0));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(1, replacement->UseCount());
+ EXPECT_THAT(replacement->uses(), ElementsAre(use_value));
+}
+
+
+TEST_F(NodePropertiesTest, ReplaceWithValue_EffectUse) {
+ CommonOperatorBuilder common(zone());
+ Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false);
+ Node* node = Node::New(zone(), 0, &kMockOpEffect, 1, &start, false);
+ Node* use_effect = Node::New(zone(), 0, common.EffectPhi(1), 1, &node, false);
+ Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
+ NodeProperties::ReplaceWithValue(node, replacement);
+ EXPECT_EQ(start, use_effect->InputAt(0));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(2, start->UseCount());
+ EXPECT_EQ(0, replacement->UseCount());
+ EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node));
+}
+
+
+TEST_F(NodePropertiesTest, ReplaceWithValue_ControlUse) {
+ CommonOperatorBuilder common(zone());
+ Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false);
+ Node* node = Node::New(zone(), 0, &kMockOpControl, 1, &start, false);
+ Node* success = Node::New(zone(), 0, common.IfSuccess(), 1, &node, false);
+ Node* use_control = Node::New(zone(), 0, common.Merge(1), 1, &success, false);
+ Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
+ NodeProperties::ReplaceWithValue(node, replacement);
+ EXPECT_EQ(start, use_control->InputAt(0));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(2, start->UseCount());
+ EXPECT_EQ(0, replacement->UseCount());
+ EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
+}
+
+
TEST_F(NodePropertiesTest, FindProjection) {
CommonOperatorBuilder common(zone());
Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false);
@@ -41,6 +101,18 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Branch) {
}
+TEST_F(NodePropertiesTest, CollectControlProjections_Call) {
+ Node* result[2];
+ CommonOperatorBuilder common(zone());
+ Node* call = Node::New(zone(), 1, &kMockCallOperator, 0, nullptr, false);
+ Node* if_ex = Node::New(zone(), 2, common.IfException(), 1, &call, false);
+ Node* if_ok = Node::New(zone(), 3, common.IfSuccess(), 1, &call, false);
+ NodeProperties::CollectControlProjections(call, result, arraysize(result));
+ EXPECT_EQ(if_ok, result[0]);
+ EXPECT_EQ(if_ex, result[1]);
+}
+
+
TEST_F(NodePropertiesTest, CollectControlProjections_Switch) {
Node* result[3];
CommonOperatorBuilder common(zone());
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.cc b/deps/v8/test/unittests/compiler/node-test-utils.cc
index eccc96227e..5890b49b02 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.cc
+++ b/deps/v8/test/unittests/compiler/node-test-utils.cc
@@ -543,11 +543,23 @@ class IsEffectSetMatcher FINAL : public NodeMatcher {
}
bool MatchAndExplain(Node* node, MatchResultListener* listener) const FINAL {
- return (NodeMatcher::MatchAndExplain(node, listener) &&
- PrintMatchAndExplain(NodeProperties::GetEffectInput(node, 0),
- "effect0", effect0_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetEffectInput(node, 1),
- "effect1", effect1_matcher_, listener));
+ if (!NodeMatcher::MatchAndExplain(node, listener)) return false;
+
+ Node* effect0 = NodeProperties::GetEffectInput(node, 0);
+ Node* effect1 = NodeProperties::GetEffectInput(node, 1);
+
+ {
+ // Try matching in the reverse order first.
+ StringMatchResultListener value_listener;
+ if (effect0_matcher_.MatchAndExplain(effect1, &value_listener) &&
+ effect1_matcher_.MatchAndExplain(effect0, &value_listener)) {
+ return true;
+ }
+ }
+
+ return PrintMatchAndExplain(effect0, "effect0", effect0_matcher_,
+ listener) &&
+ PrintMatchAndExplain(effect1, "effect1", effect1_matcher_, listener);
}
private:
@@ -1303,6 +1315,12 @@ Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher) {
}
+Matcher<Node*> IsIfSuccess(const Matcher<Node*>& control_matcher) {
+ return MakeMatcher(
+ new IsControl1Matcher(IrOpcode::kIfSuccess, control_matcher));
+}
+
+
Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher) {
return MakeMatcher(new IsSwitchMatcher(value_matcher, control_matcher));
@@ -1584,7 +1602,11 @@ IS_BINOP_MATCHER(Int32MulHigh)
IS_BINOP_MATCHER(Int32LessThan)
IS_BINOP_MATCHER(Uint32LessThan)
IS_BINOP_MATCHER(Uint32LessThanOrEqual)
+IS_BINOP_MATCHER(Float64Max)
+IS_BINOP_MATCHER(Float64Min)
IS_BINOP_MATCHER(Float64Sub)
+IS_BINOP_MATCHER(Float64InsertLowWord32)
+IS_BINOP_MATCHER(Float64InsertHighWord32)
#undef IS_BINOP_MATCHER
@@ -1592,7 +1614,6 @@ IS_BINOP_MATCHER(Float64Sub)
Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher) { \
return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \
}
-IS_UNOP_MATCHER(AnyToBoolean)
IS_UNOP_MATCHER(BooleanNot)
IS_UNOP_MATCHER(ChangeFloat64ToInt32)
IS_UNOP_MATCHER(ChangeFloat64ToUint32)
@@ -1604,14 +1625,16 @@ IS_UNOP_MATCHER(TruncateFloat64ToFloat32)
IS_UNOP_MATCHER(TruncateFloat64ToInt32)
IS_UNOP_MATCHER(TruncateInt64ToInt32)
IS_UNOP_MATCHER(Float64Sqrt)
-IS_UNOP_MATCHER(Float64Floor)
-IS_UNOP_MATCHER(Float64Ceil)
+IS_UNOP_MATCHER(Float64RoundDown)
IS_UNOP_MATCHER(Float64RoundTruncate)
IS_UNOP_MATCHER(Float64RoundTiesAway)
+IS_UNOP_MATCHER(Float64ExtractLowWord32)
+IS_UNOP_MATCHER(Float64ExtractHighWord32)
IS_UNOP_MATCHER(NumberToInt32)
IS_UNOP_MATCHER(NumberToUint32)
IS_UNOP_MATCHER(ObjectIsSmi)
IS_UNOP_MATCHER(ObjectIsNonNegativeSmi)
+IS_UNOP_MATCHER(Word32Clz)
#undef IS_UNOP_MATCHER
} // namespace compiler
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.h b/deps/v8/test/unittests/compiler/node-test-utils.h
index 03011972b7..7c306a2c9d 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.h
+++ b/deps/v8/test/unittests/compiler/node-test-utils.h
@@ -47,6 +47,7 @@ Matcher<Node*> IsLoop(const Matcher<Node*>& control0_matcher,
const Matcher<Node*>& control2_matcher);
Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher);
Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsIfSuccess(const Matcher<Node*>& control_matcher);
Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsIfValue(const Matcher<int32_t>& value_matcher,
@@ -100,7 +101,6 @@ Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
-Matcher<Node*> IsAnyToBoolean(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsBooleanNot(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberEqual(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
@@ -169,6 +169,7 @@ Matcher<Node*> IsWord32Ror(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsWord32Equal(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsWord32Clz(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsWord64And(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsWord64Shl(const Matcher<Node*>& lhs_matcher,
@@ -202,13 +203,22 @@ Matcher<Node*> IsChangeUint32ToUint64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateFloat64ToFloat32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateFloat64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64Max(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsFloat64Min(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Sqrt(const Matcher<Node*>& input_matcher);
-Matcher<Node*> IsFloat64Floor(const Matcher<Node*>& input_matcher);
-Matcher<Node*> IsFloat64Ceil(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64RoundDown(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat64RoundTruncate(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat64RoundTiesAway(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64ExtractLowWord32(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64ExtractHighWord32(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64InsertLowWord32(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsFloat64InsertHighWord32(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher,
const Matcher<Node*>& context_matcher,
const Matcher<Node*>& effect_matcher,
diff --git a/deps/v8/test/unittests/compiler/node-unittest.cc b/deps/v8/test/unittests/compiler/node-unittest.cc
index f56d7d6f8c..1a6c1bdf37 100644
--- a/deps/v8/test/unittests/compiler/node-unittest.cc
+++ b/deps/v8/test/unittests/compiler/node-unittest.cc
@@ -48,15 +48,15 @@ TEST_F(NodeTest, NewWithInputs) {
EXPECT_EQ(0, n0->InputCount());
Node* n1 = Node::New(zone(), 1, &kOp1, 1, &n0, false);
EXPECT_EQ(1, n0->UseCount());
- EXPECT_EQ(n1, n0->UseAt(0));
+ EXPECT_THAT(n0->uses(), UnorderedElementsAre(n1));
EXPECT_EQ(0, n1->UseCount());
EXPECT_EQ(1, n1->InputCount());
EXPECT_EQ(n0, n1->InputAt(0));
Node* n0_n1[] = {n0, n1};
Node* n2 = Node::New(zone(), 2, &kOp2, 2, n0_n1, false);
EXPECT_EQ(2, n0->UseCount());
- EXPECT_EQ(n1, n0->UseAt(0));
- EXPECT_EQ(n2, n0->UseAt(1));
+ EXPECT_THAT(n0->uses(), UnorderedElementsAre(n1, n2));
+ EXPECT_THAT(n1->uses(), UnorderedElementsAre(n2));
EXPECT_EQ(2, n2->InputCount());
EXPECT_EQ(n0, n2->InputAt(0));
EXPECT_EQ(n1, n2->InputAt(1));
diff --git a/deps/v8/test/unittests/compiler/opcodes-unittest.cc b/deps/v8/test/unittests/compiler/opcodes-unittest.cc
index ca79e8ac8b..3bb65c2e13 100644
--- a/deps/v8/test/unittests/compiler/opcodes-unittest.cc
+++ b/deps/v8/test/unittests/compiler/opcodes-unittest.cc
@@ -64,6 +64,21 @@ bool IsConstantOpcode(IrOpcode::Value opcode) {
}
+bool IsComparisonOpcode(IrOpcode::Value opcode) {
+ switch (opcode) {
+#define OPCODE(Opcode) \
+ case IrOpcode::k##Opcode: \
+ return true;
+ JS_COMPARE_BINOP_LIST(OPCODE)
+ SIMPLIFIED_COMPARE_BINOP_LIST(OPCODE)
+ MACHINE_COMPARE_BINOP_LIST(OPCODE)
+#undef OPCODE
+ default:
+ return false;
+ }
+}
+
+
const IrOpcode::Value kInvalidOpcode = static_cast<IrOpcode::Value>(123456789);
} // namespace
@@ -109,6 +124,16 @@ TEST(IrOpcodeTest, IsConstantOpcode) {
}
+TEST(IrOpcodeTest, IsComparisonOpcode) {
+ EXPECT_FALSE(IrOpcode::IsComparisonOpcode(kInvalidOpcode));
+#define OPCODE(Opcode) \
+ EXPECT_EQ(IsComparisonOpcode(IrOpcode::k##Opcode), \
+ IrOpcode::IsComparisonOpcode(IrOpcode::k##Opcode));
+ ALL_OP_LIST(OPCODE)
+#undef OPCODE
+}
+
+
TEST(IrOpcodeTest, Mnemonic) {
EXPECT_STREQ("UnknownOpcode", IrOpcode::Mnemonic(kInvalidOpcode));
#define OPCODE(Opcode) \
diff --git a/deps/v8/test/unittests/compiler/ppc/OWNERS b/deps/v8/test/unittests/compiler/ppc/OWNERS
new file mode 100644
index 0000000000..beecb3d0b1
--- /dev/null
+++ b/deps/v8/test/unittests/compiler/ppc/OWNERS
@@ -0,0 +1,3 @@
+joransiu@ca.ibm.com
+mbrandy@us.ibm.com
+michael_dawson@ca.ibm.com
diff --git a/deps/v8/test/unittests/compiler/register-allocator-unittest.cc b/deps/v8/test/unittests/compiler/register-allocator-unittest.cc
index c82cc3733e..873b4ecd2a 100644
--- a/deps/v8/test/unittests/compiler/register-allocator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/register-allocator-unittest.cc
@@ -301,6 +301,31 @@ TEST_F(RegisterAllocatorTest, SplitBeforeInstruction) {
}
+TEST_F(RegisterAllocatorTest, SplitBeforeInstruction2) {
+ const int kNumRegs = 6;
+ SetNumRegs(kNumRegs, kNumRegs);
+
+ StartBlock();
+
+ // Stack parameters/spilled values.
+ auto p_0 = Define(Slot(-1));
+ auto p_1 = Define(Slot(-2));
+
+ // Fill registers.
+ VReg values[kNumRegs];
+ for (size_t i = 0; i < arraysize(values); ++i) {
+ values[i] = Define(Reg(static_cast<int>(i)));
+ }
+
+ // values[0] and [1] will be split in the second half of this instruction.
+ EmitOOI(Reg(0), Reg(1), Reg(p_0, 0), Reg(p_1, 1));
+ EmitI(Reg(values[0]), Reg(values[1]));
+ EndBlock(Last());
+
+ Allocate();
+}
+
+
TEST_F(RegisterAllocatorTest, NestedDiamondPhiMerge) {
// Outer diamond.
StartBlock();
@@ -466,6 +491,87 @@ TEST_F(RegisterAllocatorTest, RegressionLoadConstantBeforeSpill) {
Allocate();
}
+
+namespace {
+
+enum class ParameterType { kFixedSlot, kSlot, kRegister, kFixedRegister };
+
+const ParameterType kParameterTypes[] = {
+ ParameterType::kFixedSlot, ParameterType::kSlot, ParameterType::kRegister,
+ ParameterType::kFixedRegister};
+
+class SlotConstraintTest : public RegisterAllocatorTest,
+ public ::testing::WithParamInterface<
+ ::testing::tuple<ParameterType, int>> {
+ public:
+ static const int kMaxVariant = 5;
+
+ protected:
+ ParameterType parameter_type() const {
+ return ::testing::get<0>(B::GetParam());
+ }
+ int variant() const { return ::testing::get<1>(B::GetParam()); }
+
+ private:
+ typedef ::testing::WithParamInterface<::testing::tuple<ParameterType, int>> B;
+};
+}
+
+
+#if GTEST_HAS_COMBINE
+
+TEST_P(SlotConstraintTest, SlotConstraint) {
+ StartBlock();
+ VReg p_0;
+ switch (parameter_type()) {
+ case ParameterType::kFixedSlot:
+ p_0 = Parameter(Slot(-1));
+ break;
+ case ParameterType::kSlot:
+ p_0 = Parameter(Slot(-1));
+ break;
+ case ParameterType::kRegister:
+ p_0 = Parameter(Reg());
+ break;
+ case ParameterType::kFixedRegister:
+ p_0 = Parameter(Reg(1));
+ break;
+ }
+ switch (variant()) {
+ case 0:
+ EmitI(Slot(p_0), Reg(p_0));
+ break;
+ case 1:
+ EmitI(Slot(p_0));
+ break;
+ case 2:
+ EmitI(Reg(p_0));
+ EmitI(Slot(p_0));
+ break;
+ case 3:
+ EmitI(Slot(p_0));
+ EmitI(Reg(p_0));
+ break;
+ case 4:
+ EmitI(Slot(p_0, -1), Slot(p_0), Reg(p_0), Reg(p_0, 1));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ EndBlock(Last());
+
+ Allocate();
+}
+
+
+INSTANTIATE_TEST_CASE_P(
+ RegisterAllocatorTest, SlotConstraintTest,
+ ::testing::Combine(::testing::ValuesIn(kParameterTypes),
+ ::testing::Range(0, SlotConstraintTest::kMaxVariant)));
+
+#endif // GTEST_HAS_COMBINE
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/schedule-unittest.cc b/deps/v8/test/unittests/compiler/schedule-unittest.cc
index 70fd4d50ad..bc825353c4 100644
--- a/deps/v8/test/unittests/compiler/schedule-unittest.cc
+++ b/deps/v8/test/unittests/compiler/schedule-unittest.cc
@@ -73,8 +73,10 @@ typedef TestWithZone ScheduleTest;
namespace {
+const Operator kCallOperator(IrOpcode::kCall, Operator::kNoProperties,
+ "MockCall", 0, 0, 0, 0, 0, 0);
const Operator kBranchOperator(IrOpcode::kBranch, Operator::kNoProperties,
- "Branch", 0, 0, 0, 0, 0, 0);
+ "MockBranch", 0, 0, 0, 0, 0, 0);
const Operator kDummyOperator(IrOpcode::kParameter, Operator::kNoProperties,
"Dummy", 0, 0, 0, 0, 0, 0);
@@ -135,6 +137,35 @@ TEST_F(ScheduleTest, AddGoto) {
}
+TEST_F(ScheduleTest, AddCall) {
+ Schedule schedule(zone());
+ BasicBlock* start = schedule.start();
+
+ Node* call = Node::New(zone(), 0, &kCallOperator, 0, nullptr, false);
+ BasicBlock* sblock = schedule.NewBasicBlock();
+ BasicBlock* eblock = schedule.NewBasicBlock();
+ schedule.AddCall(start, call, sblock, eblock);
+
+ EXPECT_EQ(start, schedule.block(call));
+
+ EXPECT_EQ(0u, start->PredecessorCount());
+ EXPECT_EQ(2u, start->SuccessorCount());
+ EXPECT_EQ(sblock, start->SuccessorAt(0));
+ EXPECT_EQ(eblock, start->SuccessorAt(1));
+ EXPECT_THAT(start->successors(), ElementsAre(sblock, eblock));
+
+ EXPECT_EQ(1u, sblock->PredecessorCount());
+ EXPECT_EQ(0u, sblock->SuccessorCount());
+ EXPECT_EQ(start, sblock->PredecessorAt(0));
+ EXPECT_THAT(sblock->predecessors(), ElementsAre(start));
+
+ EXPECT_EQ(1u, eblock->PredecessorCount());
+ EXPECT_EQ(0u, eblock->SuccessorCount());
+ EXPECT_EQ(start, eblock->PredecessorAt(0));
+ EXPECT_THAT(eblock->predecessors(), ElementsAre(start));
+}
+
+
TEST_F(ScheduleTest, AddBranch) {
Schedule schedule(zone());
BasicBlock* start = schedule.start();
diff --git a/deps/v8/test/unittests/compiler/scheduler-unittest.cc b/deps/v8/test/unittests/compiler/scheduler-unittest.cc
index 860d5cd325..eeb5bbc4d6 100644
--- a/deps/v8/test/unittests/compiler/scheduler-unittest.cc
+++ b/deps/v8/test/unittests/compiler/scheduler-unittest.cc
@@ -16,6 +16,9 @@
#include "src/compiler/verifier.h"
#include "test/unittests/compiler/compiler-test-utils.h"
#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::AnyOf;
namespace v8 {
namespace internal {
@@ -26,31 +29,31 @@ class SchedulerTest : public TestWithZone {
SchedulerTest()
: graph_(zone()), common_(zone()), simplified_(zone()), js_(zone()) {}
- static Schedule* ComputeAndVerifySchedule(int expected, Graph* graph) {
+ Schedule* ComputeAndVerifySchedule(size_t expected) {
if (FLAG_trace_turbo) {
OFStream os(stdout);
- os << AsDOT(*graph);
+ os << AsDOT(*graph());
}
- Schedule* schedule = Scheduler::ComputeSchedule(graph->zone(), graph,
- Scheduler::kSplitNodes);
+ Schedule* schedule =
+ Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kSplitNodes);
if (FLAG_trace_turbo_scheduler) {
OFStream os(stdout);
os << *schedule << std::endl;
}
ScheduleVerifier::Run(schedule);
- CHECK_EQ(expected, GetScheduledNodeCount(schedule));
+ EXPECT_EQ(expected, GetScheduledNodeCount(schedule));
return schedule;
}
- static int GetScheduledNodeCount(const Schedule* schedule) {
+ size_t GetScheduledNodeCount(const Schedule* schedule) {
size_t node_count = 0;
for (auto block : *schedule->rpo_order()) {
node_count += block->NodeCount();
if (block->control() != BasicBlock::kNone) ++node_count;
}
- return static_cast<int>(node_count);
+ return node_count;
}
Graph* graph() { return &graph_; }
@@ -71,8 +74,8 @@ class SchedulerRPOTest : public SchedulerTest {
SchedulerRPOTest() {}
// TODO(titzer): pull RPO tests out to their own file.
- static void CheckRPONumbers(BasicBlockVector* order, size_t expected,
- bool loops_allowed) {
+ void CheckRPONumbers(BasicBlockVector* order, size_t expected,
+ bool loops_allowed) {
CHECK(expected == order->size());
for (int i = 0; i < static_cast<int>(order->size()); i++) {
CHECK(order->at(i)->rpo_number() == i);
@@ -83,8 +86,7 @@ class SchedulerRPOTest : public SchedulerTest {
}
}
- static void CheckLoop(BasicBlockVector* order, BasicBlock** blocks,
- int body_size) {
+ void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, int body_size) {
BasicBlock* header = blocks[0];
BasicBlock* end = header->loop_end();
CHECK(end);
@@ -110,11 +112,9 @@ class SchedulerRPOTest : public SchedulerTest {
BasicBlock* header() { return nodes[0]; }
BasicBlock* last() { return nodes[count - 1]; }
~TestLoop() { delete[] nodes; }
-
- void Check(BasicBlockVector* order) { CheckLoop(order, nodes, count); }
};
- static TestLoop* CreateLoop(Schedule* schedule, int count) {
+ TestLoop* CreateLoop(Schedule* schedule, int count) {
TestLoop* loop = new TestLoop();
loop->count = count;
loop->nodes = new BasicBlock* [count];
@@ -130,75 +130,27 @@ class SchedulerRPOTest : public SchedulerTest {
};
-class SchedulerTestWithIsolate : public SchedulerTest, public TestWithIsolate {
- public:
- SchedulerTestWithIsolate() {}
-
- Unique<HeapObject> GetUniqueUndefined() {
- Handle<HeapObject> object =
- Handle<HeapObject>(isolate()->heap()->undefined_value(), isolate());
- return Unique<HeapObject>::CreateUninitialized(object);
- }
-};
-
namespace {
+const Operator kHeapConstant(IrOpcode::kHeapConstant, Operator::kPure,
+ "HeapConstant", 0, 0, 0, 1, 0, 0);
const Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0,
0, 1, 0, 0);
+const Operator kMockCall(IrOpcode::kCall, Operator::kNoProperties, "MockCall",
+ 0, 0, 1, 1, 0, 2);
} // namespace
-TEST_F(SchedulerTest, BuildScheduleEmpty) {
- graph()->SetStart(graph()->NewNode(common()->Start(0)));
- graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start()));
- USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
-}
-
-
-TEST_F(SchedulerTest, BuildScheduleOneParameter) {
- graph()->SetStart(graph()->NewNode(common()->Start(0)));
-
- Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start());
- Node* ret = graph()->NewNode(common()->Return(), p1, graph()->start(),
- graph()->start());
-
- graph()->SetEnd(graph()->NewNode(common()->End(), ret));
-
- USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
-}
-
-
-TEST_F(SchedulerTest, BuildScheduleIfSplit) {
- graph()->SetStart(graph()->NewNode(common()->Start(3)));
-
- Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start());
- Node* p2 = graph()->NewNode(common()->Parameter(1), graph()->start());
- Node* p3 = graph()->NewNode(common()->Parameter(2), graph()->start());
- Node* p4 = graph()->NewNode(common()->Parameter(3), graph()->start());
- Node* p5 = graph()->NewNode(common()->Parameter(4), graph()->start());
- Node* cmp = graph()->NewNode(js()->LessThanOrEqual(), p1, p2, p3,
- graph()->start(), graph()->start());
- Node* branch = graph()->NewNode(common()->Branch(), cmp, graph()->start());
- Node* true_branch = graph()->NewNode(common()->IfTrue(), branch);
- Node* false_branch = graph()->NewNode(common()->IfFalse(), branch);
-
- Node* ret1 =
- graph()->NewNode(common()->Return(), p4, graph()->start(), true_branch);
- Node* ret2 =
- graph()->NewNode(common()->Return(), p5, graph()->start(), false_branch);
- Node* merge = graph()->NewNode(common()->Merge(2), ret1, ret2);
- graph()->SetEnd(graph()->NewNode(common()->End(), merge));
-
- ComputeAndVerifySchedule(13, graph());
-}
+// -----------------------------------------------------------------------------
+// Special reverse-post-order block ordering.
TEST_F(SchedulerRPOTest, Degenerate1) {
Schedule schedule(zone());
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, 1, false);
- CHECK_EQ(schedule.start(), order->at(0));
+ EXPECT_EQ(schedule.start(), order->at(0));
}
@@ -208,8 +160,8 @@ TEST_F(SchedulerRPOTest, Degenerate2) {
schedule.AddGoto(schedule.start(), schedule.end());
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, 2, false);
- CHECK_EQ(schedule.start(), order->at(0));
- CHECK_EQ(schedule.end(), order->at(1));
+ EXPECT_EQ(schedule.start(), order->at(0));
+ EXPECT_EQ(schedule.end(), order->at(1));
}
@@ -230,7 +182,7 @@ TEST_F(SchedulerRPOTest, Line) {
for (size_t i = 0; i < schedule.BasicBlockCount(); i++) {
BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i));
if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) {
- CHECK(block->rpo_number() + 1 == block->SuccessorAt(0)->rpo_number());
+ EXPECT_EQ(block->rpo_number() + 1, block->SuccessorAt(0)->rpo_number());
}
}
}
@@ -265,7 +217,7 @@ TEST_F(SchedulerRPOTest, EndLoop) {
schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, 3, true);
- loop1->Check(order);
+ CheckLoop(order, loop1->nodes, loop1->count);
}
@@ -276,7 +228,7 @@ TEST_F(SchedulerRPOTest, EndLoopNested) {
schedule.AddSuccessorForTesting(loop1->last(), schedule.start());
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, 3, true);
- loop1->Check(order);
+ CheckLoop(order, loop1->nodes, loop1->count);
}
@@ -296,10 +248,10 @@ TEST_F(SchedulerRPOTest, Diamond) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, 4, false);
- CHECK_EQ(0, A->rpo_number());
- CHECK((B->rpo_number() == 1 && C->rpo_number() == 2) ||
- (B->rpo_number() == 2 && C->rpo_number() == 1));
- CHECK_EQ(3, D->rpo_number());
+ EXPECT_EQ(0, A->rpo_number());
+ EXPECT_THAT(B->rpo_number(), AnyOf(1, 2));
+ EXPECT_THAT(C->rpo_number(), AnyOf(1, 2));
+ EXPECT_EQ(3, D->rpo_number());
}
@@ -464,11 +416,9 @@ TEST_F(SchedulerRPOTest, LoopFollow1) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
-
- loop1->Check(order);
- loop2->Check(order);
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
}
@@ -489,10 +439,9 @@ TEST_F(SchedulerRPOTest, LoopFollow2) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
- loop1->Check(order);
- loop2->Check(order);
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
}
@@ -510,10 +459,9 @@ TEST_F(SchedulerRPOTest, LoopFollowN) {
schedule.AddSuccessorForTesting(loop2->nodes[exit], E);
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
- loop1->Check(order);
- loop2->Check(order);
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
}
}
}
@@ -539,10 +487,9 @@ TEST_F(SchedulerRPOTest, NestedLoopFollow1) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
- loop1->Check(order);
- loop2->Check(order);
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
CheckLoop(order, loop3, 4);
@@ -566,7 +513,7 @@ TEST_F(SchedulerRPOTest, LoopBackedges1) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
+ CheckLoop(order, loop1->nodes, loop1->count);
}
}
}
@@ -591,7 +538,7 @@ TEST_F(SchedulerRPOTest, LoopOutedges1) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
+ CheckLoop(order, loop1->nodes, loop1->count);
}
}
}
@@ -616,7 +563,7 @@ TEST_F(SchedulerRPOTest, LoopOutedges2) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
+ CheckLoop(order, loop1->nodes, loop1->count);
}
}
@@ -640,10 +587,10 @@ TEST_F(SchedulerRPOTest, LoopOutloops1) {
BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
+ CheckLoop(order, loop1->nodes, loop1->count);
for (int j = 0; j < size; j++) {
- loopN[j]->Check(order);
+ CheckLoop(order, loopN[j]->nodes, loopN[j]->count);
delete loopN[j];
}
delete[] loopN;
@@ -676,7 +623,58 @@ TEST_F(SchedulerRPOTest, LoopMultibackedge) {
}
-TEST_F(SchedulerTestWithIsolate, BuildScheduleIfSplitWithEffects) {
+// -----------------------------------------------------------------------------
+// Graph end-to-end scheduling.
+
+
+TEST_F(SchedulerTest, BuildScheduleEmpty) {
+ graph()->SetStart(graph()->NewNode(common()->Start(0)));
+ graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start()));
+ USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
+}
+
+
+TEST_F(SchedulerTest, BuildScheduleOneParameter) {
+ graph()->SetStart(graph()->NewNode(common()->Start(0)));
+
+ Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start());
+ Node* ret = graph()->NewNode(common()->Return(), p1, graph()->start(),
+ graph()->start());
+
+ graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+ USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
+}
+
+
+TEST_F(SchedulerTest, BuildScheduleIfSplit) {
+ graph()->SetStart(graph()->NewNode(common()->Start(3)));
+
+ Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start());
+ Node* p2 = graph()->NewNode(common()->Parameter(1), graph()->start());
+ Node* p3 = graph()->NewNode(common()->Parameter(2), graph()->start());
+ Node* p4 = graph()->NewNode(common()->Parameter(3), graph()->start());
+ Node* p5 = graph()->NewNode(common()->Parameter(4), graph()->start());
+ Node* cmp = graph()->NewNode(js()->LessThanOrEqual(), p1, p2, p3,
+ graph()->start(), graph()->start());
+ Node* branch = graph()->NewNode(common()->Branch(), cmp, graph()->start());
+ Node* true_branch = graph()->NewNode(common()->IfTrue(), branch);
+ Node* false_branch = graph()->NewNode(common()->IfFalse(), branch);
+
+ Node* ret1 =
+ graph()->NewNode(common()->Return(), p4, graph()->start(), true_branch);
+ Node* ret2 =
+ graph()->NewNode(common()->Return(), p5, graph()->start(), false_branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), ret1, ret2);
+ graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+
+ ComputeAndVerifySchedule(13);
+}
+
+
+TEST_F(SchedulerTest, BuildScheduleIfSplitWithEffects) {
+ FLAG_turbo_deoptimization = false;
+
const Operator* op;
// Manually transcripted code for:
@@ -720,7 +718,7 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleIfSplitWithEffects) {
Node* n3 = graph()->NewNode(op, n0);
USE(n3);
n11->ReplaceInput(1, n3);
- op = common()->HeapConstant(GetUniqueUndefined());
+ op = &kHeapConstant;
Node* n7 = graph()->NewNode(op);
USE(n7);
n11->ReplaceInput(2, n7);
@@ -808,11 +806,13 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleIfSplitWithEffects) {
graph()->SetStart(n0);
graph()->SetEnd(n23);
- ComputeAndVerifySchedule(20, graph());
+ ComputeAndVerifySchedule(20);
}
-TEST_F(SchedulerTestWithIsolate, BuildScheduleSimpleLoop) {
+TEST_F(SchedulerTest, BuildScheduleSimpleLoop) {
+ FLAG_turbo_deoptimization = false;
+
const Operator* op;
// Manually transcripted code for:
@@ -846,7 +846,7 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleSimpleLoop) {
Node* n16 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n16);
n16->ReplaceInput(0, n8);
- op = common()->HeapConstant(GetUniqueUndefined());
+ op = &kHeapConstant;
Node* n5 = graph()->NewNode(op);
USE(n5);
n16->ReplaceInput(1, n5);
@@ -911,11 +911,13 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleSimpleLoop) {
graph()->SetStart(n0);
graph()->SetEnd(n20);
- ComputeAndVerifySchedule(19, graph());
+ ComputeAndVerifySchedule(19);
}
-TEST_F(SchedulerTestWithIsolate, BuildScheduleComplexLoops) {
+TEST_F(SchedulerTest, BuildScheduleComplexLoops) {
+ FLAG_turbo_deoptimization = false;
+
const Operator* op;
// Manually transcripted code for:
@@ -961,7 +963,7 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleComplexLoops) {
Node* n18 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n18);
n18->ReplaceInput(0, n9);
- op = common()->HeapConstant(GetUniqueUndefined());
+ op = &kHeapConstant;
Node* n6 = graph()->NewNode(op);
USE(n6);
n18->ReplaceInput(1, n6);
@@ -1149,11 +1151,13 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleComplexLoops) {
graph()->SetStart(n0);
graph()->SetEnd(n46);
- ComputeAndVerifySchedule(46, graph());
+ ComputeAndVerifySchedule(46);
}
-TEST_F(SchedulerTestWithIsolate, BuildScheduleBreakAndContinue) {
+TEST_F(SchedulerTest, BuildScheduleBreakAndContinue) {
+ FLAG_turbo_deoptimization = false;
+
const Operator* op;
// Manually transcripted code for:
@@ -1201,7 +1205,7 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleBreakAndContinue) {
Node* n20 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n20);
n20->ReplaceInput(0, n10);
- op = common()->HeapConstant(GetUniqueUndefined());
+ op = &kHeapConstant;
Node* n6 = graph()->NewNode(op);
USE(n6);
n20->ReplaceInput(1, n6);
@@ -1469,11 +1473,13 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleBreakAndContinue) {
graph()->SetStart(n0);
graph()->SetEnd(n58);
- ComputeAndVerifySchedule(62, graph());
+ ComputeAndVerifySchedule(62);
}
-TEST_F(SchedulerTestWithIsolate, BuildScheduleSimpleLoopWithCodeMotion) {
+TEST_F(SchedulerTest, BuildScheduleSimpleLoopWithCodeMotion) {
+ FLAG_turbo_deoptimization = false;
+
const Operator* op;
// Manually transcripted code for:
@@ -1533,7 +1539,7 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleSimpleLoopWithCodeMotion) {
USE(n14);
n14->ReplaceInput(0, n9);
n14->ReplaceInput(1, n10);
- op = common()->HeapConstant(GetUniqueUndefined());
+ op = &kHeapConstant;
Node* n6 = graph()->NewNode(op);
USE(n6);
n14->ReplaceInput(2, n6);
@@ -1583,10 +1589,7 @@ TEST_F(SchedulerTestWithIsolate, BuildScheduleSimpleLoopWithCodeMotion) {
graph()->SetStart(n0);
graph()->SetEnd(n22);
- Schedule* schedule = ComputeAndVerifySchedule(19, graph());
- // Make sure the integer-only add gets hoisted to a different block that the
- // JSAdd.
- CHECK(schedule->block(n19) != schedule->block(n20));
+ ComputeAndVerifySchedule(19);
}
@@ -1617,7 +1620,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond1) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(13, graph());
+ ComputeAndVerifySchedule(13);
}
@@ -1635,7 +1638,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond2) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(24, graph());
+ ComputeAndVerifySchedule(24);
}
@@ -1654,7 +1657,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond3) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(33, graph());
+ ComputeAndVerifySchedule(33);
}
@@ -1691,7 +1694,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamonds) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(23, graph());
+ ComputeAndVerifySchedule(23);
}
@@ -1735,7 +1738,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithChain) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(36, graph());
+ ComputeAndVerifySchedule(36);
}
@@ -1769,7 +1772,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithLoop) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(20, graph());
+ ComputeAndVerifySchedule(20);
}
@@ -1802,7 +1805,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond1) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(20, graph());
+ ComputeAndVerifySchedule(20);
}
@@ -1836,7 +1839,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond2) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(20, graph());
+ ComputeAndVerifySchedule(20);
}
@@ -1882,7 +1885,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond3) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(28, graph());
+ ComputeAndVerifySchedule(28);
}
@@ -1916,7 +1919,7 @@ TARGET_TEST_F(SchedulerTest, PhisPushedDownToDifferentBranches) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(24, graph());
+ ComputeAndVerifySchedule(24);
}
@@ -1937,10 +1940,10 @@ TARGET_TEST_F(SchedulerTest, BranchHintTrue) {
graph()->SetEnd(end);
- Schedule* schedule = ComputeAndVerifySchedule(13, graph());
+ Schedule* schedule = ComputeAndVerifySchedule(13);
// Make sure the false block is marked as deferred.
- CHECK(!schedule->block(t)->deferred());
- CHECK(schedule->block(f)->deferred());
+ EXPECT_FALSE(schedule->block(t)->deferred());
+ EXPECT_TRUE(schedule->block(f)->deferred());
}
@@ -1961,10 +1964,38 @@ TARGET_TEST_F(SchedulerTest, BranchHintFalse) {
graph()->SetEnd(end);
- Schedule* schedule = ComputeAndVerifySchedule(13, graph());
+ Schedule* schedule = ComputeAndVerifySchedule(13);
// Make sure the true block is marked as deferred.
- CHECK(schedule->block(t)->deferred());
- CHECK(!schedule->block(f)->deferred());
+ EXPECT_TRUE(schedule->block(t)->deferred());
+ EXPECT_FALSE(schedule->block(f)->deferred());
+}
+
+
+TARGET_TEST_F(SchedulerTest, CallException) {
+ Node* start = graph()->NewNode(common()->Start(1));
+ graph()->SetStart(start);
+
+ Node* p0 = graph()->NewNode(common()->Parameter(0), start);
+ Node* c1 = graph()->NewNode(&kMockCall, start);
+ Node* ok1 = graph()->NewNode(common()->IfSuccess(), c1);
+ Node* ex1 = graph()->NewNode(common()->IfException(), c1);
+ Node* c2 = graph()->NewNode(&kMockCall, ok1);
+ Node* ok2 = graph()->NewNode(common()->IfSuccess(), c2);
+ Node* ex2 = graph()->NewNode(common()->IfException(), c2);
+ Node* hdl = graph()->NewNode(common()->Merge(2), ex1, ex2);
+ Node* m = graph()->NewNode(common()->Merge(2), ok2, hdl);
+ Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), c2, p0, m);
+ Node* ret = graph()->NewNode(common()->Return(), phi, start, m);
+ Node* end = graph()->NewNode(common()->End(), ret);
+
+ graph()->SetEnd(end);
+
+ Schedule* schedule = ComputeAndVerifySchedule(17);
+ // Make sure the exception blocks as well as the handler are deferred.
+ EXPECT_TRUE(schedule->block(ex1)->deferred());
+ EXPECT_TRUE(schedule->block(ex2)->deferred());
+ EXPECT_TRUE(schedule->block(hdl)->deferred());
+ EXPECT_FALSE(schedule->block(m)->deferred());
}
@@ -1987,7 +2018,7 @@ TARGET_TEST_F(SchedulerTest, Switch) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(16, graph());
+ ComputeAndVerifySchedule(16);
}
@@ -2010,7 +2041,7 @@ TARGET_TEST_F(SchedulerTest, FloatingSwitch) {
graph()->SetEnd(end);
- ComputeAndVerifySchedule(16, graph());
+ ComputeAndVerifySchedule(16);
}
} // namespace compiler
diff --git a/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
index 38924123df..f8f9561af8 100644
--- a/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
@@ -119,39 +119,6 @@ const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
// -----------------------------------------------------------------------------
-// AnyToBoolean
-
-
-TEST_F(SimplifiedOperatorReducerTest, AnyToBooleanWithBoolean) {
- Node* p = Parameter(Type::Boolean());
- Reduction r = Reduce(graph()->NewNode(simplified()->AnyToBoolean(), p));
- ASSERT_TRUE(r.Changed());
- EXPECT_EQ(p, r.replacement());
-}
-
-
-TEST_F(SimplifiedOperatorReducerTest, AnyToBooleanWithOrderedNumber) {
- Node* p = Parameter(Type::OrderedNumber());
- Reduction r = Reduce(graph()->NewNode(simplified()->AnyToBoolean(), p));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsBooleanNot(IsNumberEqual(p, IsNumberConstant(0))));
-}
-
-
-TEST_F(SimplifiedOperatorReducerTest, AnyToBooleanWithString) {
- Node* p = Parameter(Type::String());
- Reduction r = Reduce(graph()->NewNode(simplified()->AnyToBoolean(), p));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsBooleanNot(
- IsNumberEqual(IsLoadField(AccessBuilder::ForStringLength(), p,
- graph()->start(), graph()->start()),
- IsNumberConstant(0))));
-}
-
-
-// -----------------------------------------------------------------------------
// BooleanNot
diff --git a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
index 680793023f..a5dad5a415 100644
--- a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
@@ -38,7 +38,6 @@ const PureOperator kPureOperators[] = {
&SimplifiedOperatorBuilder::Name, IrOpcode::k##Name, \
Operator::kPure | properties, input_count \
}
- PURE(AnyToBoolean, Operator::kNoProperties, 1),
PURE(BooleanNot, Operator::kNoProperties, 1),
PURE(BooleanToNumber, Operator::kNoProperties, 1),
PURE(NumberEqual, Operator::kCommutative, 2),
diff --git a/deps/v8/test/unittests/compiler/state-values-utils-unittest.cc b/deps/v8/test/unittests/compiler/state-values-utils-unittest.cc
new file mode 100644
index 0000000000..e6f4701598
--- /dev/null
+++ b/deps/v8/test/unittests/compiler/state-values-utils-unittest.cc
@@ -0,0 +1,149 @@
+// 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.
+
+#include "src/compiler/state-values-utils.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class StateValuesIteratorTest : public GraphTest {
+ public:
+ StateValuesIteratorTest() : GraphTest(3) {}
+
+ Node* StateValuesFromVector(NodeVector* nodes) {
+ int count = static_cast<int>(nodes->size());
+ return graph()->NewNode(common()->StateValues(count), count,
+ count == 0 ? nullptr : &(nodes->front()));
+ }
+};
+
+
+TEST_F(StateValuesIteratorTest, SimpleIteration) {
+ NodeVector inputs(zone());
+ const int count = 10;
+ for (int i = 0; i < count; i++) {
+ inputs.push_back(Int32Constant(i));
+ }
+ Node* state_values = StateValuesFromVector(&inputs);
+ int i = 0;
+ for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
+ EXPECT_THAT(node.node, IsInt32Constant(i));
+ i++;
+ }
+ EXPECT_EQ(count, i);
+}
+
+
+TEST_F(StateValuesIteratorTest, EmptyIteration) {
+ NodeVector inputs(zone());
+ Node* state_values = StateValuesFromVector(&inputs);
+ for (auto node : StateValuesAccess(state_values)) {
+ USE(node);
+ FAIL();
+ }
+}
+
+
+TEST_F(StateValuesIteratorTest, NestedIteration) {
+ NodeVector inputs(zone());
+ int count = 0;
+ for (int i = 0; i < 8; i++) {
+ if (i == 2) {
+ // Single nested in index 2.
+ NodeVector nested_inputs(zone());
+ for (int j = 0; j < 8; j++) {
+ nested_inputs.push_back(Int32Constant(count++));
+ }
+ inputs.push_back(StateValuesFromVector(&nested_inputs));
+ } else if (i == 5) {
+ // Double nested at index 5.
+ NodeVector nested_inputs(zone());
+ for (int j = 0; j < 8; j++) {
+ if (j == 7) {
+ NodeVector doubly_nested_inputs(zone());
+ for (int k = 0; k < 2; k++) {
+ doubly_nested_inputs.push_back(Int32Constant(count++));
+ }
+ nested_inputs.push_back(StateValuesFromVector(&doubly_nested_inputs));
+ } else {
+ nested_inputs.push_back(Int32Constant(count++));
+ }
+ }
+ inputs.push_back(StateValuesFromVector(&nested_inputs));
+ } else {
+ inputs.push_back(Int32Constant(count++));
+ }
+ }
+ Node* state_values = StateValuesFromVector(&inputs);
+ int i = 0;
+ for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
+ EXPECT_THAT(node.node, IsInt32Constant(i));
+ i++;
+ }
+ EXPECT_EQ(count, i);
+}
+
+
+TEST_F(StateValuesIteratorTest, TreeFromVector) {
+ int sizes[] = {0, 1, 2, 100, 5000, 30000};
+ TRACED_FOREACH(int, count, sizes) {
+ JSOperatorBuilder javascript(zone());
+ MachineOperatorBuilder machine(zone());
+ JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
+
+ // Generate the input vector.
+ NodeVector inputs(zone());
+ for (int i = 0; i < count; i++) {
+ inputs.push_back(Int32Constant(i));
+ }
+
+ // Build the tree.
+ StateValuesCache builder(&jsgraph);
+ Node* values_node = builder.GetNodeForValues(
+ inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size());
+
+ // Check the tree contents with vector.
+ int i = 0;
+ for (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) {
+ EXPECT_THAT(node.node, IsInt32Constant(i));
+ i++;
+ }
+ EXPECT_EQ(inputs.size(), static_cast<size_t>(i));
+ }
+}
+
+
+TEST_F(StateValuesIteratorTest, BuildTreeIdentical) {
+ int sizes[] = {0, 1, 2, 100, 5000, 30000};
+ TRACED_FOREACH(int, count, sizes) {
+ JSOperatorBuilder javascript(zone());
+ MachineOperatorBuilder machine(zone());
+ JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
+
+ // Generate the input vector.
+ NodeVector inputs(zone());
+ for (int i = 0; i < count; i++) {
+ inputs.push_back(Int32Constant(i));
+ }
+
+ // Build two trees from the same data.
+ StateValuesCache builder(&jsgraph);
+ Node* node1 = builder.GetNodeForValues(
+ inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size());
+ Node* node2 = builder.GetNodeForValues(
+ inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size());
+
+ // The trees should be equal since the data was the same.
+ EXPECT_EQ(node1, node2);
+ }
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc b/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
index 1f374c0f85..a83deafe7d 100644
--- a/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
@@ -1030,6 +1030,25 @@ TEST_F(InstructionSelectorTest, Float64BinopArithmetic) {
// Miscellaneous.
+TEST_F(InstructionSelectorTest, Uint64LessThanWithLoadAndLoadStackPointer) {
+ StreamBuilder m(this, kMachBool);
+ Node* const sl = m.Load(
+ kMachPtr,
+ m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate())));
+ Node* const sp = m.LoadStackPointer();
+ Node* const n = m.Uint64LessThan(sl, sp);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64StackCheck, s[0]->arch_opcode());
+ ASSERT_EQ(0U, s[0]->InputCount());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+ EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition());
+}
+
+
TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
TRACED_FORRANGE(int64_t, x, 32, 63) {
StreamBuilder m(this, kMachInt64, kMachInt32);
@@ -1127,6 +1146,21 @@ TEST_F(InstructionSelectorTest, Word32AndWith0xffff) {
}
}
+
+TEST_F(InstructionSelectorTest, Word32Clz) {
+ StreamBuilder m(this, kMachUint32, kMachUint32);
+ Node* const p0 = m.Parameter(0);
+ Node* const n = m.Word32Clz(p0);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Lzcnt32, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc
index 2076e604fa..ed33259775 100644
--- a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc
+++ b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc
@@ -168,7 +168,7 @@ TEST_F(GCIdleTimeHandlerTest, DoScavengeHighScavengeSpeed) {
TEST_F(GCIdleTimeHandlerTest, ShouldDoMarkCompact) {
- size_t idle_time_in_ms = 16;
+ size_t idle_time_in_ms = GCIdleTimeHandler::kMaxScheduledIdleTime;
EXPECT_TRUE(GCIdleTimeHandler::ShouldDoMarkCompact(idle_time_in_ms, 0, 0));
}
@@ -440,5 +440,55 @@ TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeDoNothingButStartIdleRound) {
EXPECT_EQ(DO_NOTHING, action.type);
}
+
+TEST_F(GCIdleTimeHandlerTest, KeepDoingDoNothingWithZeroIdleTime) {
+ GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
+ for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound;
+ i++) {
+ GCIdleTimeAction action = handler()->Compute(0, heap_state);
+ EXPECT_EQ(DO_NOTHING, action.type);
+ }
+ // Should still return DO_NOTHING if we have been given 0 deadline yet.
+ GCIdleTimeAction action = handler()->Compute(0, heap_state);
+ EXPECT_EQ(DO_NOTHING, action.type);
+}
+
+
+TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) {
+ GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
+
+ // Simulate sweeping being in-progress but not complete.
+ heap_state.incremental_marking_stopped = true;
+ heap_state.can_start_incremental_marking = false;
+ heap_state.sweeping_in_progress = true;
+ double idle_time_ms = 10.0;
+ for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound;
+ i++) {
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_NOTHING, action.type);
+ }
+ // We should return DONE after not making progress for some time.
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DONE, action.type);
+}
+
+
+TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
+ GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
+
+ // Simulate incremental marking stopped and not eligible to start.
+ heap_state.incremental_marking_stopped = true;
+ heap_state.can_start_incremental_marking = false;
+ double idle_time_ms = 10.0;
+ for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound;
+ i++) {
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_NOTHING, action.type);
+ }
+ // We should return DONE after not making progress for some time.
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DONE, action.type);
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/unittests.gyp b/deps/v8/test/unittests/unittests.gyp
index a12d5e7f4b..2ed05b8adc 100644
--- a/deps/v8/test/unittests/unittests.gyp
+++ b/deps/v8/test/unittests/unittests.gyp
@@ -57,6 +57,7 @@
'compiler/js-intrinsic-lowering-unittest.cc',
'compiler/js-operator-unittest.cc',
'compiler/js-typed-lowering-unittest.cc',
+ 'compiler/liveness-analyzer-unittest.cc',
'compiler/load-elimination-unittest.cc',
'compiler/loop-peeling-unittest.cc',
'compiler/machine-operator-reducer-unittest.cc',
@@ -74,6 +75,7 @@
'compiler/scheduler-unittest.cc',
'compiler/simplified-operator-reducer-unittest.cc',
'compiler/simplified-operator-unittest.cc',
+ 'compiler/state-values-utils-unittest.cc',
'compiler/typer-unittest.cc',
'compiler/value-numbering-reducer-unittest.cc',
'compiler/zone-pool-unittest.cc',
diff --git a/deps/v8/test/webkit/fast/js/kde/prototype_length-expected.txt b/deps/v8/test/webkit/fast/js/kde/prototype_length-expected.txt
index 7c4c2e25d8..5cf2bd5db8 100644
--- a/deps/v8/test/webkit/fast/js/kde/prototype_length-expected.txt
+++ b/deps/v8/test/webkit/fast/js/kde/prototype_length-expected.txt
@@ -39,7 +39,7 @@ PASS Array.prototype.length is 6
PASS Function.prototype.length is 0
PASS String.prototype.length is 0
PASS delete Array.prototype.length is false
-PASS delete Function.prototype.length is false
+PASS delete Function.prototype.length is true
PASS delete String.prototype.length is false
PASS foundArrayPrototypeLength is false
PASS foundFunctionPrototypeLength is false
diff --git a/deps/v8/test/webkit/fast/js/kde/prototype_length.js b/deps/v8/test/webkit/fast/js/kde/prototype_length.js
index 4eb888c3da..48357005d1 100644
--- a/deps/v8/test/webkit/fast/js/kde/prototype_length.js
+++ b/deps/v8/test/webkit/fast/js/kde/prototype_length.js
@@ -43,7 +43,7 @@ shouldBe("String.prototype.length","0");
// check DontDelete
shouldBe("delete Array.prototype.length","false");
-shouldBe("delete Function.prototype.length","false");
+shouldBe("delete Function.prototype.length","true");
shouldBe("delete String.prototype.length","false");
// check DontEnum
diff --git a/deps/v8/test/webkit/webkit.status b/deps/v8/test/webkit/webkit.status
index fb8d77d8d2..d8c6864105 100644
--- a/deps/v8/test/webkit/webkit.status
+++ b/deps/v8/test/webkit/webkit.status
@@ -56,10 +56,10 @@
['arch == arm64 and simulator_run == True', {
'dfg-int-overflow-in-loop': [SKIP],
}], # 'arch == arm64 and simulator_run == True'
-['dcheck_always_on == True and arch == arm64', {
- # Doesn't work with gcc 4.6 on arm64 for some reason.
+['dcheck_always_on == True and (arch == arm or arch == arm64)', {
+ # Doesn't work with gcc 4.6 on arm or arm64 for some reason.
'reentrant-caching': [SKIP],
-}], # 'dcheck_always_on == True and arch == arm64'
+}], # 'dcheck_always_on == True and (arch == arm or arch == arm64)'
##############################################################################