diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-10-18 15:03:02 -0700 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-10-18 17:01:41 -0700 |
commit | 3d1b3df9486c0e7708065257f7311902f6b7b366 (patch) | |
tree | cb051bdeaead11e06dcd97725783e0f113afb1bf /deps/v8/test/mjsunit | |
parent | e2cddbb8ccdb7b3c4a40c8acc630f68703bc77b5 (diff) | |
download | android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.tar.gz android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.tar.bz2 android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.zip |
deps: update V8 to 6.2.414.32
PR-URL: https://github.com/nodejs/node/pull/15362
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/test/mjsunit')
222 files changed, 5750 insertions, 1370 deletions
diff --git a/deps/v8/test/mjsunit/accessors-on-global-object.js b/deps/v8/test/mjsunit/accessors-on-global-object.js index dc910b7e71..4d47ce69aa 100644 --- a/deps/v8/test/mjsunit/accessors-on-global-object.js +++ b/deps/v8/test/mjsunit/accessors-on-global-object.js @@ -34,7 +34,7 @@ function getX() { return x; } for (var i = 0; i < 10; i++) { assertEquals(i < 5 ? 0 : 42, getX()); - if (i == 4) __defineGetter__("x", function() { return 42; }); + if (i == 4) this.__defineGetter__("x", function() { return 42; }); } @@ -50,8 +50,8 @@ for (var i = 0; i < 10; i++) { setY(i); assertEquals(i < 5 ? i : 2 * i, y); if (i == 4) { - __defineSetter__("y", function(value) { setter_y = 2 * value; }); - __defineGetter__("y", function() { return setter_y; }); + this.__defineSetter__("y", function(value) { setter_y = 2 * value; }); + this.__defineGetter__("y", function() { return setter_y; }); } } @@ -59,7 +59,7 @@ for (var i = 0; i < 10; i++) { // Test that replacing a getter with a normal property works as // expected. -__defineGetter__("z", function() { return 42; }); +this.__defineGetter__("z", function() { return 42; }); function getZ() { return z; } diff --git a/deps/v8/test/mjsunit/allocation-site-info.js b/deps/v8/test/mjsunit/allocation-site-info.js index 075678bdbb..7a5f2c70bf 100644 --- a/deps/v8/test/mjsunit/allocation-site-info.js +++ b/deps/v8/test/mjsunit/allocation-site-info.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: --allow-natives-syntax --expose-gc -// Flags: --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --expose-gc --opt --no-always-opt var elements_kind = { fast_smi_only : 'fast smi only elements', diff --git a/deps/v8/test/mjsunit/arguments.js b/deps/v8/test/mjsunit/arguments.js index caaac5a4d3..ad12540c6d 100644 --- a/deps/v8/test/mjsunit/arguments.js +++ b/deps/v8/test/mjsunit/arguments.js @@ -170,7 +170,7 @@ function list_args(a) { } -function f1(x, y) { +function f7(x, y) { function g(p) { x = p; } @@ -178,10 +178,10 @@ function f1(x, y) { return list_args(arguments); } -assertArrayEquals([0], f1()); -assertArrayEquals([1, void 0], f1(3)); -assertArrayEquals([2, 5, 5], f1(3, 5)); -assertArrayEquals([3, 5, 5, 7], f1(3, 5, 7)); +assertArrayEquals([0], f7()); +assertArrayEquals([1, void 0], f7(3)); +assertArrayEquals([2, 5, 5], f7(3, 5)); +assertArrayEquals([3, 5, 5, 7], f7(3, 5, 7)); // Check out of bounds behavior. function arg_get(x) { return arguments[x]; } diff --git a/deps/v8/test/mjsunit/array-constructor-feedback.js b/deps/v8/test/mjsunit/array-constructor-feedback.js index 12016b430a..c1f386d983 100644 --- a/deps/v8/test/mjsunit/array-constructor-feedback.js +++ b/deps/v8/test/mjsunit/array-constructor-feedback.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: --allow-natives-syntax --expose-gc -// Flags: --no-always-opt --opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --expose-gc --no-always-opt --opt // Test element kind of objects. diff --git a/deps/v8/test/mjsunit/array-feedback.js b/deps/v8/test/mjsunit/array-feedback.js index 223c50391f..021505d449 100644 --- a/deps/v8/test/mjsunit/array-feedback.js +++ b/deps/v8/test/mjsunit/array-feedback.js @@ -25,166 +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 --expose-gc -// Flags: --opt --no-always-opt --no-stress-fullcodegen - -var elements_kind = { - fast_smi_only : 'fast smi only elements', - fast : 'fast elements', - fast_double : 'fast double elements', - dictionary : 'dictionary elements', - external_byte : 'external byte elements', - external_unsigned_byte : 'external unsigned byte elements', - external_short : 'external short elements', - external_unsigned_short : 'external unsigned short elements', - external_int : 'external int elements', - external_unsigned_int : 'external unsigned int elements', - external_float : 'external float elements', - external_double : 'external double elements', - external_pixel : 'external pixel elements' -} - -function getKind(obj) { - if (%HasSmiElements(obj)) return elements_kind.fast_smi_only; - if (%HasObjectElements(obj)) return elements_kind.fast; - if (%HasDoubleElements(obj)) return elements_kind.fast_double; - if (%HasDictionaryElements(obj)) return elements_kind.dictionary; -} - -function isHoley(obj) { - if (%HasHoleyElements(obj)) return true; - return false; -} - -function assertKind(expected, obj, name_opt) { - assertEquals(expected, getKind(obj), name_opt); -} - -// Verify that basic elements kind feedback works for non-constructor -// array calls (as long as the call is made through an IC, and not -// a CallStub). -(function (){ - function create0() { - return Array(); - } - - // Calls through ICs need warm up through uninitialized, then - // premonomorphic first. - create0(); - a = create0(); - assertKind(elements_kind.fast_smi_only, a); - a[0] = 3.5; - b = create0(); - assertKind(elements_kind.fast_double, b); - - function create1(arg) { - return Array(arg); - } - - create1(0); - create1(0); - a = create1(0); - assertTrue(isHoley(a)); - assertKind(elements_kind.fast_smi_only, a); - a[0] = "hello"; - b = create1(10); - assertTrue(isHoley(b)); - assertKind(elements_kind.fast, b); - - a = create1(100000); - assertKind(elements_kind.fast, a); - - function create3(arg1, arg2, arg3) { - return Array(arg1, arg2, arg3); - } - - create3(1,2,3); - create3(1,2,3); - a = create3(1,2,3); - a[0] = 3.035; - assertKind(elements_kind.fast_double, a); - b = create3(1,2,3); - assertKind(elements_kind.fast_double, b); - assertFalse(isHoley(b)); -})(); - - -// Verify that keyed calls work -(function (){ - function create0(name) { - return this[name](); - } - - name = "Array"; - create0(name); - create0(name); - a = create0(name); - a[0] = 3.5; - b = create0(name); - assertKind(elements_kind.fast_double, b); -})(); - - -// Verify that feedback is turned off if the call site goes megamorphic. -(function (){ - function foo(arg) { return arg(); } - foo(Array); - foo(function() {}); - foo(Array); - - gc(); - - a = foo(Array); - a[0] = 3.5; - b = foo(Array); - // b doesn't benefit from elements kind feedback at a megamorphic site. - assertKind(elements_kind.fast_smi_only, b); -})(); - - -// Verify that crankshaft consumes type feedback. -(function (){ - function create0() { - return Array(); - } - - create0(); - create0(); - a = create0(); - a[0] = 3.5; - %OptimizeFunctionOnNextCall(create0); - create0(); - create0(); - b = create0(); - assertKind(elements_kind.fast_double, b); - assertOptimized(create0); - - function create1(arg) { - return Array(arg); - } - - create1(8); - create1(8); - a = create1(8); - a[0] = 3.5; - %OptimizeFunctionOnNextCall(create1); - b = create1(8); - assertKind(elements_kind.fast_double, b); - assertOptimized(create1); - - function createN(arg1, arg2, arg3) { - return Array(arg1, arg2, arg3); - } - - createN(1, 2, 3); - createN(1, 2, 3); - a = createN(1, 2, 3); - a[0] = 3.5; - %OptimizeFunctionOnNextCall(createN); - b = createN(1, 2, 3); - assertKind(elements_kind.fast_double, b); - assertOptimized(createN); -})(); +// Flags: --allow-natives-syntax --expose-gc --opt --no-always-opt // Verify that cross context calls work (function (){ diff --git a/deps/v8/test/mjsunit/array-literal-feedback.js b/deps/v8/test/mjsunit/array-literal-feedback.js index b03752a5f8..b20cdd8e12 100644 --- a/deps/v8/test/mjsunit/array-literal-feedback.js +++ b/deps/v8/test/mjsunit/array-literal-feedback.js @@ -25,13 +25,12 @@ // (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 --expose-gc -// Flags: --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --expose-gc --opt --no-always-opt var elements_kind = { - fast_smi_only : 'fast smi only elements', - fast : 'fast elements', - fast_double : 'fast double elements', + packed_smi : 'packed smi elements', + packed : 'packed elements', + packed_double : 'packed double elements', dictionary : 'dictionary elements', external_byte : 'external byte elements', external_unsigned_byte : 'external unsigned byte elements', @@ -45,9 +44,9 @@ var elements_kind = { } function getKind(obj) { - if (%HasSmiElements(obj)) return elements_kind.fast_smi_only; - if (%HasObjectElements(obj)) return elements_kind.fast; - if (%HasDoubleElements(obj)) return elements_kind.fast_double; + if (%HasSmiElements(obj)) return elements_kind.packed_smi; + if (%HasObjectElements(obj)) return elements_kind.packed; + if (%HasDoubleElements(obj)) return elements_kind.packed_double; if (%HasDictionaryElements(obj)) return elements_kind.dictionary; } @@ -93,7 +92,7 @@ assertOptimized(get_literal); // Test: make sure allocation site information is updated through a -// transition from SMI->DOUBLE->FAST +// transition from SMI->DOUBLE->PACKED (function() { function bar(a, b, c) { return [a, b, c]; @@ -103,5 +102,132 @@ assertOptimized(get_literal); a[0] = 3.5; a[1] = 'hi'; b = bar(1, 2, 3); - assertKind(elements_kind.fast, b); + assertKind(elements_kind.packed, b); +})(); + + +(function changeOptimizedEmptyArrayKind() { + function f() { + return new Array(); + } + var a = f(); + assertKind('packed smi elements', a); + a = f(); + assertKind('packed smi elements', a); + a = f(); + a.push(0.5); + assertKind('packed double elements', a); + %OptimizeFunctionOnNextCall(f); + a = f(); + assertKind('packed double elements', a); +})(); + +(function changeOptimizedArrayLiteralKind() { + function f() { + return [1, 2]; + } + var a = f(); + assertKind('packed smi elements', a); + + a = f(); + a.push(0.5); + assertKind('packed double elements', a); + + a = f(); + assertKind('packed double elements', a); + assertFalse(isHoley(a)); + + a = f(); + a.push(undefined); + assertKind('packed elements', a); + assertFalse(isHoley(a)); + + a = f(); + assertKind('packed elements', a); + assertFalse(isHoley(a)); + + %OptimizeFunctionOnNextCall(f); + + a = f(); + assertKind('packed elements', a); + assertFalse(isHoley(a)); + + a = f(); + assertKind('packed elements', a); + assertFalse(isHoley(a)); +})(); + +(function changeOptimizedEmptyArrayLiteralKind() { + function f() { + return []; + } + var a = f(); + assertKind('packed smi elements', a); + assertFalse(isHoley(a)); + + a = f(); + a.push(0.5); + assertKind('packed double elements', a); + assertFalse(isHoley(a)); + + a = f(); + assertKind('packed double elements', a); + assertFalse(isHoley(a)); + + %OptimizeFunctionOnNextCall(f); + + a = f(); + assertKind('packed double elements', a); + assertFalse(isHoley(a)); + + a = f(); + assertKind('packed double elements', a); + assertFalse(isHoley(a)); +})(); + +(function changeEmptyArrayLiteralKind2() { + function f() { + var literal = []; + %HeapObjectVerify(literal); + return literal; + } + var a = f(); + assertKind('packed smi elements', a); + assertFalse(isHoley(a)); + + a = f(); + a.push(0.5); + assertKind('packed double elements', a); + assertFalse(isHoley(a)); + + a = f(); + assertKind('packed double elements', a); + assertFalse(isHoley(a)); + + a = f(); + a.push(undefined); + assertKind('packed elements', a); + assertFalse(isHoley(a)); + + a = f(); + assertKind('packed elements', a); + assertFalse(isHoley(a)); + + a = f(); + a[10] = 1; + assertKind('packed elements', a); + assertTrue(isHoley(a)); + + a = f(); + assertKind('packed elements', a); + assertTrue(isHoley(a)); + + a = f(); + a[10000] = 1; + assertKind('dictionary elements', a); + assertFalse(isHoley(a)); + + a = f(); + assertKind('packed elements', a); + assertTrue(isHoley(a)); })(); diff --git a/deps/v8/test/mjsunit/array-literal-transitions.js b/deps/v8/test/mjsunit/array-literal-transitions.js index 0ea985b2fc..6366839a62 100644 --- a/deps/v8/test/mjsunit/array-literal-transitions.js +++ b/deps/v8/test/mjsunit/array-literal-transitions.js @@ -26,7 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --allow-natives-syntax --expose-gc --ignition-osr --no-always-opt -// Flags: --opt --no-stress-fullcodegen +// Flags: --opt // IC and Crankshaft support for smi-only elements in dynamic array literals. function get(foo) { return foo; } // Used to generate dynamic values. @@ -147,7 +147,7 @@ array = deopt_array_literal_all_smis(4); assertEquals(0, array[0]); assertEquals(1, array[1]); assertEquals(4, array[2]); - %OptimizeFunctionOnNextCall(deopt_array_literal_all_smis); +%OptimizeFunctionOnNextCall(deopt_array_literal_all_smis); array = deopt_array_literal_all_smis(5); array = deopt_array_literal_all_smis(6); assertOptimized(deopt_array_literal_all_smis); @@ -172,7 +172,7 @@ array = deopt_array_literal_all_doubles(0.5); assertEquals(0.5, array[0]); assertEquals(1, array[1]); assertEquals(0.5, array[2]); - %OptimizeFunctionOnNextCall(deopt_array_literal_all_doubles); +%OptimizeFunctionOnNextCall(deopt_array_literal_all_doubles); array = deopt_array_literal_all_doubles(5); array = deopt_array_literal_all_doubles(6); assertOptimized(deopt_array_literal_all_doubles); @@ -190,6 +190,7 @@ assertEquals(foo, array[2]); (function literals_after_osr() { var color = [0]; // Trigger OSR. - while (%GetOptimizationCount(literals_after_osr) == 0) {} + while ((%GetOptimizationStatus(literals_after_osr) & + V8OptimizationStatus.kTopmostFrameIsTurboFanned) !== 0) {} return [color[0]]; })(); diff --git a/deps/v8/test/mjsunit/array-push5.js b/deps/v8/test/mjsunit/array-push5.js index 772f8576ec..9961ff98c3 100644 --- a/deps/v8/test/mjsunit/array-push5.js +++ b/deps/v8/test/mjsunit/array-push5.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt var v = 0; diff --git a/deps/v8/test/mjsunit/array-shift5.js b/deps/v8/test/mjsunit/array-shift5.js index c8fb90d830..a097e2f797 100644 --- a/deps/v8/test/mjsunit/array-shift5.js +++ b/deps/v8/test/mjsunit/array-shift5.js @@ -38,6 +38,21 @@ function doShift(a) { return a.shift(); } function test() { + var a = [,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.1]; + assertEquals(undefined, doShift(a)); + assertEquals([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.1], a); + } + + test(); + test(); + %OptimizeFunctionOnNextCall(doShift); + test(); +})(); + +(function() { + function doShift(a) { return a.shift(); } + + function test() { var a = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,"16"]; assertEquals(0, doShift(a)); assertEquals([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,"16"], a); diff --git a/deps/v8/test/mjsunit/array-store-and-grow.js b/deps/v8/test/mjsunit/array-store-and-grow.js index f1b9a3b38a..ee831ad061 100644 --- a/deps/v8/test/mjsunit/array-store-and-grow.js +++ b/deps/v8/test/mjsunit/array-store-and-grow.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt // Verifies that the KeyedStoreIC correctly handles out-of-bounds stores // to an array that grow it by a single element. Test functions are diff --git a/deps/v8/test/mjsunit/asm/poppler/poppler.js b/deps/v8/test/mjsunit/asm/poppler/poppler.js index b9087f1edf..35156fbcfe 100644 --- a/deps/v8/test/mjsunit/asm/poppler/poppler.js +++ b/deps/v8/test/mjsunit/asm/poppler/poppler.js @@ -172,7 +172,7 @@ else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { } } else { - // Unreachable because SHELL is dependant on the others + // Unreachable because SHELL is dependent on the others throw 'Unknown runtime environment. Where are we?'; } @@ -595,7 +595,7 @@ var globalScope = this; // @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") // @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and // 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). -// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be omitted). Types are as in returnType, // except that 'array' is not possible (there is no way for us to know the length of the array) // @param args An array of the arguments to the function, as native JS values (as in returnType) // Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). diff --git a/deps/v8/test/mjsunit/asm/regress-674089.js b/deps/v8/test/mjsunit/asm/regress-674089.js index e87f8451f5..edba023dec 100644 --- a/deps/v8/test/mjsunit/asm/regress-674089.js +++ b/deps/v8/test/mjsunit/asm/regress-674089.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: --validate-asm --no-stress-fullcodegen --lazy-inner-functions +// Flags: --validate-asm --lazy-inner-functions function outer() { "use asm"; diff --git a/deps/v8/test/mjsunit/assert-opt-and-deopt.js b/deps/v8/test/mjsunit/assert-opt-and-deopt.js deleted file mode 100644 index c4f15cec08..0000000000 --- a/deps/v8/test/mjsunit/assert-opt-and-deopt.js +++ /dev/null @@ -1,164 +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: --allow-natives-syntax -// Flags: --noconcurrent-recompilation - -if (%IsConcurrentRecompilationSupported()) { - print("Concurrent recompilation is turned on after all. Skipping this test."); - quit(); -} - -/** - * This class shows how to use %GetOptimizationCount() and - * %GetOptimizationStatus() to infer information about opts and deopts. - * Might be nice to put this into mjsunit.js, but that doesn't depend on - * the --allow-natives-syntax flag so far. - */ -function OptTracker() { - this.opt_counts_ = {}; -} - -/** - * Always call this at the beginning of your test, once for each function - * that you later want to track de/optimizations for. It is necessary because - * tests are sometimes executed several times in a row, and you want to - * disregard counts from previous runs. - */ -OptTracker.prototype.CheckpointOptCount = function(func) { - this.opt_counts_[func] = %GetOptimizationCount(func); -}; - -OptTracker.prototype.AssertOptCount = function(func, optcount) { - if (this.DisableAsserts_(func)) { - return; - } - assertEquals(optcount, this.GetOptCount_(func)); -}; - -OptTracker.prototype.AssertDeoptCount = function(func, deopt_count) { - if (this.DisableAsserts_(func)) { - return; - } - assertEquals(deopt_count, this.GetDeoptCount_(func)); -}; - -OptTracker.prototype.AssertDeoptHappened = function(func, expect_deopt) { - if (this.DisableAsserts_(func)) { - return; - } - if (expect_deopt) { - assertTrue(this.GetDeoptCount_(func) > 0); - } else { - assertEquals(0, this.GetDeoptCount_(func)); - } -} - -OptTracker.prototype.AssertIsOptimized = function(func, expect_optimized) { - if (this.DisableAsserts_(func)) { - return; - } - var opt_status = %GetOptimizationStatus(func); - assertTrue((opt_status & V8OptimizationStatus.kIsFunction) !== 0); - assertEquals(expect_optimized, - (opt_status & V8OptimizationStatus.kOptimized) !== 0); -} - -/** - * @private - */ -OptTracker.prototype.GetOptCount_ = function(func) { - var raw_count = %GetOptimizationCount(func); - if (func in this.opt_counts_) { - var checkpointed_count = this.opt_counts_[func]; - return raw_count - checkpointed_count; - } - return raw_count; -} - -/** - * @private - */ -OptTracker.prototype.GetDeoptCount_ = function(func) { - var count = this.GetOptCount_(func); - var opt_status = %GetOptimizationStatus(func); - if ((opt_status & V8OptimizationStatus.kOptimized) !== 0) { - count -= 1; - } - return count; -} - -/** - * @private - */ -OptTracker.prototype.DisableAsserts_ = function(func) { - var opt_status = %GetOptimizationStatus(func); - return (opt_status & V8OptimizationStatus.kAlwaysOptimize) !== 0 || - (opt_status & V8OptimizationStatus.kNeverOptimize) !== 0; -} -// (End of class OptTracker.) - -// Example function used by the test below. -function f(a) { - return a+1; -} - -var tracker = new OptTracker(); -tracker.CheckpointOptCount(f); - -tracker.AssertOptCount(f, 0); -tracker.AssertIsOptimized(f, false); -tracker.AssertDeoptHappened(f, false); -tracker.AssertDeoptCount(f, 0); - -f(1); - -%OptimizeFunctionOnNextCall(f); -f(1); - -tracker.AssertOptCount(f, 1); -tracker.AssertIsOptimized(f, true); -tracker.AssertDeoptHappened(f, false); -tracker.AssertDeoptCount(f, 0); - -%DeoptimizeFunction(f); - -tracker.AssertOptCount(f, 1); -tracker.AssertIsOptimized(f, false); -tracker.AssertDeoptHappened(f, true); -tracker.AssertDeoptCount(f, 1); - -// Let's trigger optimization for another type. -for (var i = 0; i < 5; i++) f("a"); - -%OptimizeFunctionOnNextCall(f); -f("b"); - -tracker.AssertOptCount(f, 2); -tracker.AssertIsOptimized(f, true); -tracker.AssertDeoptHappened(f, true); -tracker.AssertDeoptCount(f, 1); diff --git a/deps/v8/test/mjsunit/code-coverage-ad-hoc.js b/deps/v8/test/mjsunit/code-coverage-ad-hoc.js index 93bea15fe5..75f513c099 100644 --- a/deps/v8/test/mjsunit/code-coverage-ad-hoc.js +++ b/deps/v8/test/mjsunit/code-coverage-ad-hoc.js @@ -3,26 +3,11 @@ // found in the LICENSE file. // Flags: --allow-natives-syntax --no-always-opt +// Files: test/mjsunit/code-coverage-utils.js // Test code coverage without explicitly activating it upfront. -function GetCoverage(source) { - for (var script of %DebugCollectCoverage()) { - if (script.script.source == source) return script; - } - return undefined; -} - -function TestCoverage(name, source, expectation) { - source = source.trim(); - eval(source); - var coverage = GetCoverage(source); - var result = JSON.stringify(coverage); - print(result); - assertEquals(JSON.stringify(expectation), result, name + " failed"); -} - -TestCoverage( +TestCoverageNoGC( "call simple function twice", ` function f() {} @@ -33,7 +18,7 @@ f(); {"start":0,"end":15,"count":1}] ); -TestCoverage( +TestCoverageNoGC( "call arrow function twice", ` var f = () => 1; @@ -44,7 +29,7 @@ f(); {"start":8,"end":15,"count":1}] ); -TestCoverage( +TestCoverageNoGC( "call nested function", ` function f() { @@ -60,7 +45,7 @@ f(); {"start":17,"end":32,"count":1}] ); -TestCoverage( +TestCoverageNoGC( "call recursive function", ` function fib(x) { diff --git a/deps/v8/test/mjsunit/code-coverage-block-noopt.js b/deps/v8/test/mjsunit/code-coverage-block-noopt.js new file mode 100644 index 0000000000..727acea75d --- /dev/null +++ b/deps/v8/test/mjsunit/code-coverage-block-noopt.js @@ -0,0 +1,43 @@ +// Copyright 2017 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 --no-always-opt --block-coverage +// Flags: --harmony-async-iteration --no-opt +// Files: test/mjsunit/code-coverage-utils.js + +%DebugToggleBlockCoverage(true); + +TestCoverage( +"optimized and inlined functions", +` +function g() { if (true) nop(); } // 0000 +function f() { g(); g(); } // 0050 +f(); f(); %OptimizeFunctionOnNextCall(f); // 0100 +f(); f(); f(); f(); f(); f(); // 0150 +`, +[{"start":0,"end":199,"count":1}, + {"start":0,"end":33,"count":16}, + {"start":50,"end":76,"count":8}] +); + +// In contrast to the corresponding test in -opt.js, f is not optimized here +// and therefore reports its invocation count correctly. +TestCoverage("Partial coverage collection", +` +!function() { // 0000 + function f(x) { // 0050 + if (x) { nop(); } else { nop(); } // 0100 + } // 0150 + f(true); f(true); // 0200 + %OptimizeFunctionOnNextCall(f); // 0250 + %DebugCollectCoverage(); // 0300 + f(false); // 0350 +}(); // 0400 +`, +[{"start":52,"end":153,"count":1}, + {"start":111,"end":121,"count":0}] +); + + +%DebugToggleBlockCoverage(false); diff --git a/deps/v8/test/mjsunit/code-coverage-block-opt.js b/deps/v8/test/mjsunit/code-coverage-block-opt.js new file mode 100644 index 0000000000..488af8cf96 --- /dev/null +++ b/deps/v8/test/mjsunit/code-coverage-block-opt.js @@ -0,0 +1,46 @@ +// Copyright 2017 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 --no-always-opt --block-coverage +// Flags: --harmony-async-iteration --opt +// Files: test/mjsunit/code-coverage-utils.js + +%DebugToggleBlockCoverage(true); + +TestCoverage( +"optimized and inlined functions", +` +function g() { if (true) nop(); } // 0000 +function f() { g(); g(); } // 0050 +f(); f(); %OptimizeFunctionOnNextCall(f); // 0100 +f(); f(); f(); f(); f(); f(); // 0150 +`, +[{"start":0,"end":199,"count":1}, + {"start":0,"end":33,"count":4}, // TODO(jgruber): Invocation count is off. + {"start":25,"end":32,"count":16}, + {"start":50,"end":76,"count":2}] // TODO(jgruber): Invocation count is off. +); + +// This test is tricky: it requires a non-toplevel, optimized function. +// After initial collection, counts are cleared. Further invocation_counts +// are not collected for optimized functions, and on the next coverage +// collection we and up with an uncovered function with an uncovered parent +// but with non-trivial block coverage. +TestCoverage("Partial coverage collection", +` +!function() { // 0000 + function f(x) { // 0050 + if (x) { nop(); } else { nop(); } // 0100 + } // 0150 + f(true); f(true); // 0200 + %OptimizeFunctionOnNextCall(f); // 0250 + %DebugCollectCoverage(); // 0300 + f(false); // 0350 +}(); // 0400 +`, +[{"start":52,"end":153,"count":0}, + {"start":127,"end":152,"count":1}] +); + +%DebugToggleBlockCoverage(false); diff --git a/deps/v8/test/mjsunit/code-coverage-block.js b/deps/v8/test/mjsunit/code-coverage-block.js index d55578156d..c5e7455b1c 100644 --- a/deps/v8/test/mjsunit/code-coverage-block.js +++ b/deps/v8/test/mjsunit/code-coverage-block.js @@ -2,32 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --no-always-opt --ignition --block-coverage --harmony-async-iteration -// Flags: --no-stress-fullcodegen - -// Test precise code coverage. - -function GetCoverage(source) { - for (var script of %DebugCollectCoverage()) { - if (script.script.source == source) return script; - } - return undefined; -} - -function TestCoverage(name, source, expectation) { - source = source.trim(); - eval(source); - %CollectGarbage("collect dead objects"); - var covfefe = GetCoverage(source); - var stringified_result = JSON.stringify(covfefe); - var stringified_expectation = JSON.stringify(expectation); - if (stringified_result != stringified_expectation) { - print(stringified_result.replace(/[}],[{]/g, "},\n {")); - } - assertEquals(stringified_expectation, stringified_result, name + " failed"); -} - -function nop() {} +// Flags: --allow-natives-syntax --no-always-opt --block-coverage +// Flags: --harmony-async-iteration +// Files: test/mjsunit/code-coverage-utils.js %DebugToggleBlockCoverage(true); @@ -92,7 +69,7 @@ TestCoverage( `, [{"start":0,"end":399,"count":1}, {"start":1,"end":351,"count":1}, - {"start":161,"end":351,"count":0}] + {"start":161,"end":350,"count":0}] ); TestCoverage( @@ -201,7 +178,7 @@ TestCoverage( {"start":81,"end":253,"count":10}, {"start":163,"end":253,"count":0}, {"start":460,"end":553,"count":0}, - {"start":761,"end":951,"count":0}] + {"start":761,"end":950,"count":0}] ); TestCoverage( @@ -239,7 +216,7 @@ TestCoverage( [{"start":0,"end":299,"count":1}, {"start":1,"end":201,"count":6}, // TODO(jgruber): Invocation count is off. {"start":83,"end":153,"count":4}, - {"start":153,"end":201,"count":1}] + {"start":153,"end":200,"count":1}] ); TestCoverage( @@ -301,7 +278,7 @@ TestCoverage( {"start":117,"end":303,"count":10}, {"start":213,"end":303,"count":0}, {"start":510,"end":603,"count":0}, - {"start":811,"end":1001,"count":0}] + {"start":811,"end":1000,"count":0}] ); TestCoverage( @@ -334,7 +311,7 @@ TestCoverage( {"start":105,"end":303,"count":10}, {"start":213,"end":303,"count":0}, {"start":510,"end":603,"count":0}, - {"start":811,"end":1001,"count":0}] + {"start":811,"end":1000,"count":0}] ); TestCoverage( @@ -346,9 +323,9 @@ TestCoverage( `, [{"start":0,"end":149,"count":1}, {"start":1,"end":37,"count":1}, - {"start":28,"end":37,"count":0}, + {"start":28,"end":36,"count":0}, {"start":51,"end":122,"count":1}, - {"start":81,"end":122,"count":0}] + {"start":81,"end":121,"count":0}] ); TestCoverage( @@ -374,12 +351,33 @@ TestCoverage( `, [{"start":0,"end":849,"count":1}, {"start":1,"end":801,"count":1}, - {"start":77,"end":87,"count":0}, - {"start":219,"end":232,"count":0}, - {"start":264,"end":274,"count":0}, - {"start":369,"end":380,"count":0}, - {"start":403,"end":414,"count":0}, // TODO(jgruber): Include `catch` in range. - {"start":513,"end":564,"count":0}] + {"start":67,"end":87,"count":0}, + {"start":219,"end":222,"count":0}, + {"start":254,"end":274,"count":0}, + {"start":369,"end":372,"count":0}, + {"start":390,"end":404,"count":0}, + {"start":513,"end":554,"count":0}] +); + +TestCoverage("try/catch/finally statements with early return", +` +!function() { // 0000 + try { throw 42; } catch (e) { return; } // 0050 + nop(); // 0100 +}(); // 0150 +!function() { // 0200 + try { throw 42; } catch (e) {} // 0250 + finally { return; } // 0300 + nop(); // 0350 +}(); // 0400 +`, +[{"start":0,"end":449,"count":1}, + {"start":1,"end":151,"count":1}, + {"start":67,"end":70,"count":0}, + {"start":89,"end":150,"count":0}, + {"start":201,"end":401,"count":1}, + {"start":267,"end":270,"count":0}, + {"start":319,"end":400,"count":0}] ); TestCoverage( @@ -410,17 +408,16 @@ TestCoverage( `, [{"start":0,"end":1099,"count":1}, {"start":1,"end":151,"count":1}, - {"start":67,"end":80,"count":0}, - {"start":89,"end":151,"count":0}, + {"start":67,"end":70,"count":0}, + {"start":89,"end":150,"count":0}, {"start":201,"end":351,"count":1}, - {"start":284,"end":351,"count":0}, + {"start":284,"end":350,"count":0}, {"start":401,"end":701,"count":1}, - {"start":569,"end":701,"count":0}, + {"start":569,"end":700,"count":0}, {"start":561,"end":568,"count":0}, // TODO(jgruber): Sorting. {"start":751,"end":1051,"count":1}, - {"start":817,"end":830,"count":0}, - {"start":861,"end":1051,"count":0}] - + {"start":817,"end":820,"count":0}, + {"start":861,"end":1050,"count":0}] ); TestCoverage( @@ -538,4 +535,136 @@ var FALSE = false; // 0050 {"start":775,"end":780,"count":0}] ); +TestCoverage( +"yield expressions", +` +const it = function*() { // 0000 + yield nop(); // 0050 + yield nop() ? nop() : nop() // 0100 + return nop(); // 0150 +}(); // 0200 +it.next(); it.next(); // 0250 +`, +[{"start":0,"end":299,"count":1}, + {"start":11,"end":201,"count":3}, + {"start":64,"end":116,"count":1}, + {"start":116,"end":121,"count":0}, + {"start":124,"end":129,"count":1}, + {"start":129,"end":200,"count":0}] +); + +TestCoverage( +"yield expressions (.return and .throw)", +` +const it0 = function*() { // 0000 + yield 1; yield 2; yield 3; // 0050 +}(); // 0100 +it0.next(); it0.return(); // 0150 +try { // 0200 + const it1 = function*() { // 0250 + yield 1; yield 2; yield 3; // 0300 + }(); // 0350 + it1.next(); it1.throw(); // 0400 +} catch (e) {} // 0450 +`, +[{"start":0,"end":499,"count":1}, + {"start":12,"end":101,"count":3}, + {"start":60,"end":100,"count":0}, + {"start":264,"end":353,"count":3}, + {"start":312,"end":352,"count":0}] +); + +TestCoverage("yield expressions (.return and try/catch/finally)", +` +const it = function*() { // 0000 + try { // 0050 + yield 1; yield 2; yield 3; // 0100 + } catch (e) { // 0150 + nop(); // 0200 + } finally { nop(); } // 0250 + yield 4; // 0300 +}(); // 0350 +it.next(); it.return(); // 0450 +`, +[{"start":0,"end":449,"count":1}, + {"start":11,"end":351,"count":3}, + {"start":112,"end":254,"count":0}, + {"start":254,"end":272,"count":1}, + {"start":272,"end":350,"count":0}] +); + +TestCoverage("yield expressions (.throw and try/catch/finally)", +` +const it = function*() { // 0000 + try { // 0050 + yield 1; yield 2; yield 3; // 0100 + } catch (e) { // 0150 + nop(); // 0200 + } finally { nop(); } // 0250 + yield 4; // 0300 +}(); // 0350 +it.next(); it.throw(42); // 0550 +`, +[{"start":0,"end":449,"count":1}, + {"start":11,"end":351,"count":3}, + {"start":112,"end":154,"count":0}, + {"start":154,"end":310,"count":1}, + {"start":310,"end":350,"count":0}] +); + +TestCoverage( +"yield* expressions", +` +const it = function*() { // 0000 + yield* gen(); // 0050 + yield* nop() ? gen() : gen() // 0100 + return gen(); // 0150 +}(); // 0200 +it.next(); it.next(); it.next(); // 0250 +it.next(); it.next(); it.next(); // 0300 +`, +[{"start":0,"end":349,"count":1}, + {"start":11,"end":201,"count":7}, + {"start":65,"end":117,"count":1}, + {"start":117,"end":122,"count":0}, + {"start":125,"end":130,"count":1}, + {"start":130,"end":200,"count":0}] +); + +TestCoverage( +"yield* expressions (.return and .throw)", +` +const it0 = function*() { // 0000 + yield* gen(); yield* gen(); yield 3; // 0050 +}(); // 0100 +it0.next(); it0.return(); // 0150 +try { // 0200 + const it1 = function*() { // 0250 + yield* gen(); yield* gen(); yield 3; // 0300 + }(); // 0350 + it1.next(); it1.throw(); // 0400 +} catch (e) {} // 0450 +`, +[{"start":0,"end":499,"count":1}, + {"start":12,"end":101,"count":3}, + {"start":65,"end":100,"count":0}, + {"start":264,"end":353,"count":3}, + {"start":317,"end":352,"count":0}] +); + +TestCoverage( +"await expressions", +` +async function f() { // 0000 + await 42; // 0050 + await 42; // 0100 +}; // 0150 +f(); // 0200 +%RunMicrotasks(); // 0250 +`, +[{"start":0,"end":299,"count":1}, + {"start":0,"end":151,"count":3}, + {"start":61,"end":150,"count":1}] +); + %DebugToggleBlockCoverage(false); diff --git a/deps/v8/test/mjsunit/code-coverage-precise.js b/deps/v8/test/mjsunit/code-coverage-precise.js index 2d4fa04ab9..3d5d5bac9e 100644 --- a/deps/v8/test/mjsunit/code-coverage-precise.js +++ b/deps/v8/test/mjsunit/code-coverage-precise.js @@ -2,27 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --no-always-opt +// Files: test/mjsunit/code-coverage-utils.js // Test precise code coverage. -function GetCoverage(source) { - for (var script of %DebugCollectCoverage()) { - if (script.script.source == source) return script; - } - return undefined; -} - -function TestCoverage(name, source, expectation) { - source = source.trim(); - eval(source); - %CollectGarbage("collect dead objects"); - var coverage = GetCoverage(source); - var result = JSON.stringify(coverage); - print(result); - assertEquals(JSON.stringify(expectation), result, name + " failed"); -} - // Without precise coverage enabled, we lose coverage data to the GC. TestCoverage( "call an IIFE", diff --git a/deps/v8/test/mjsunit/code-coverage-utils.js b/deps/v8/test/mjsunit/code-coverage-utils.js new file mode 100644 index 0000000000..009aa55e20 --- /dev/null +++ b/deps/v8/test/mjsunit/code-coverage-utils.js @@ -0,0 +1,49 @@ +// Copyright 2017 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 + +let TestCoverage; +let TestCoverageNoGC; + +let nop; +let gen; + +!function() { + function GetCoverage(source) { + for (var script of %DebugCollectCoverage()) { + if (script.script.source == source) return script; + } + return undefined; + }; + + function TestCoverageInternal(name, source, expectation, collect_garbage) { + source = source.trim(); + eval(source); + if (collect_garbage) %CollectGarbage("collect dead objects"); + var covfefe = GetCoverage(source); + var stringified_result = JSON.stringify(covfefe); + var stringified_expectation = JSON.stringify(expectation); + if (stringified_result != stringified_expectation) { + print(stringified_result.replace(/[}],[{]/g, "},\n {")); + } + assertEquals(stringified_expectation, stringified_result, name + " failed"); + }; + + TestCoverage = function(name, source, expectation) { + TestCoverageInternal(name, source, expectation, true); + }; + + TestCoverageNoGC = function(name, source, expectation) { + TestCoverageInternal(name, source, expectation, false); + }; + + nop = function() {}; + + gen = function*() { + yield 1; + yield 2; + yield 3; + }; +}(); diff --git a/deps/v8/test/mjsunit/compiler/alloc-object-huge.js b/deps/v8/test/mjsunit/compiler/alloc-object-huge.js index 7fd32eaa30..74b600cc7d 100644 --- a/deps/v8/test/mjsunit/compiler/alloc-object-huge.js +++ b/deps/v8/test/mjsunit/compiler/alloc-object-huge.js @@ -26,8 +26,8 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --allow-natives-syntax -// Flags: --max-inlined-source-size=999999 --max-inlined-nodes=999999 -// Flags: --max-inlined-nodes-cumulative=999999 +// Flags: --max-inlined-bytecode-size=999999 +// Flags: --max-inlined-bytecode-size-cumulative=999999 // Test that huge constructors (more than 256 this assignments) are // handled correctly. diff --git a/deps/v8/test/mjsunit/compiler/constructor-inlining-no-harmony-restrict-constructor-return.js b/deps/v8/test/mjsunit/compiler/constructor-inlining-no-harmony-restrict-constructor-return.js index 6dbaf6bf3f..50d15eb30f 100644 --- a/deps/v8/test/mjsunit/compiler/constructor-inlining-no-harmony-restrict-constructor-return.js +++ b/deps/v8/test/mjsunit/compiler/constructor-inlining-no-harmony-restrict-constructor-return.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 --no-harmony-restrict-constructor-return --max-deopt-count 200 +// Flags: --allow-natives-syntax --no-harmony-restrict-constructor-return this.FLAG_harmony_restrict_constructor_return = false; try { diff --git a/deps/v8/test/mjsunit/compiler/constructor-inlining.js b/deps/v8/test/mjsunit/compiler/constructor-inlining.js index b01885d8ba..d43545ada0 100644 --- a/deps/v8/test/mjsunit/compiler/constructor-inlining.js +++ b/deps/v8/test/mjsunit/compiler/constructor-inlining.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-restrict-constructor-return --max-deopt-count 200 +// Flags: --allow-natives-syntax --harmony-restrict-constructor-return if (this.FLAG_harmony_restrict_constructor_return === undefined) this.FLAG_harmony_restrict_constructor_return = true; diff --git a/deps/v8/test/mjsunit/compiler/deopt-eager-and-lazy.js b/deps/v8/test/mjsunit/compiler/deopt-eager-and-lazy.js new file mode 100644 index 0000000000..daea40a950 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-eager-and-lazy.js @@ -0,0 +1,27 @@ +// Copyright 2017 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() { + %DeoptimizeFunction(g); +} +%NeverOptimizeFunction(f); + +function g(o) { + f(); + return h(o); +} + +function h(o) { + return o.x; +} + +g({x : 1}); +g({x : 2}); +%OptimizeFunctionOnNextCall(g); +%OptimizeFunctionOnNextCall(h); +g({x : 3}); +g({y : 1, x : 3}); diff --git a/deps/v8/test/mjsunit/compiler/deopt-eager-var-mutation-ite.js b/deps/v8/test/mjsunit/compiler/deopt-eager-var-mutation-ite.js new file mode 100644 index 0000000000..17ce86ff4a --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-eager-var-mutation-ite.js @@ -0,0 +1,28 @@ +// Copyright 2017 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 foo = { x : 0, y : 1 } + +function f(b) { + h(b); + return foo.x; +} + +function h(b) { + g(b); + return foo.x; +} + +function g(b) { + if (b) { + foo = { x : 536 }; + } // It should trigger an eager deoptimization when b=true. +} + +f(false); f(false); +%OptimizeFunctionOnNextCall(f); +f(false); +assertEquals(f(true), 536); diff --git a/deps/v8/test/mjsunit/compiler/deopt-eager-with-freeze.js b/deps/v8/test/mjsunit/compiler/deopt-eager-with-freeze.js new file mode 100644 index 0000000000..538176d2e8 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-eager-with-freeze.js @@ -0,0 +1,20 @@ +// Copyright 2017 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 useObject(obj) { + if (!Object.isFrozen(obj)) { + var t = obj.f; + obj.f = t * 2; + } + return obj.f; +} + +var o = {f: 1, g: 2} +assertEquals(useObject(o), 2); +assertEquals(useObject(o), 4); +%OptimizeFunctionOnNextCall(useObject); +Object.freeze(o); +assertEquals(useObject(o), 4); diff --git a/deps/v8/test/mjsunit/compiler/deopt-followed-by-gc.js b/deps/v8/test/mjsunit/compiler/deopt-followed-by-gc.js new file mode 100644 index 0000000000..a5ea622dfc --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-followed-by-gc.js @@ -0,0 +1,23 @@ +// Copyright 2017 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 + +// Testing GC after setting the pc on the stack. +// There must be a safepoint for the trampoline. + +function opt_me() { + deopt(); +} + +function deopt() { + %DeoptimizeFunction(opt_me); + gc(); +} +%NeverOptimizeFunction(deopt); + +opt_me(); +opt_me(); +%OptimizeFunctionOnNextCall(opt_me); +opt_me(); diff --git a/deps/v8/test/mjsunit/compiler/deopt-inlined-from-call.js b/deps/v8/test/mjsunit/compiler/deopt-inlined-from-call.js index 28af2eebca..8fa8af5a9b 100644 --- a/deps/v8/test/mjsunit/compiler/deopt-inlined-from-call.js +++ b/deps/v8/test/mjsunit/compiler/deopt-inlined-from-call.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt var global = this; diff --git a/deps/v8/test/mjsunit/compiler/deopt-lazy-freeze.js b/deps/v8/test/mjsunit/compiler/deopt-lazy-freeze.js new file mode 100644 index 0000000000..592fca8ad2 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-lazy-freeze.js @@ -0,0 +1,28 @@ +// Copyright 2017 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 b = false; +var obj = {f: 1, g: 2}; + +function setMutability() { + if (b) Object.freeze(obj); +} +%NeverOptimizeFunction(setMutability); + +function setAndUseObject() { + setMutability(obj); + if (!Object.isFrozen(obj)) { + var t = obj.f; + obj.f = t * 2; + } + return obj.f; +} + +assertEquals(setAndUseObject(), 2); +assertEquals(setAndUseObject(), 4); +%OptimizeFunctionOnNextCall(setAndUseObject); +b = true; +assertEquals(setAndUseObject(), 4); diff --git a/deps/v8/test/mjsunit/compiler/deopt-lazy-shape-mutation.js b/deps/v8/test/mjsunit/compiler/deopt-lazy-shape-mutation.js new file mode 100644 index 0000000000..df4878e9cf --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-lazy-shape-mutation.js @@ -0,0 +1,23 @@ +// Copyright 2017 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 b = false; + +function change_o() { + if (b) o = { y : 1, x : 0}; +} +%NeverOptimizeFunction(change_o); + +var o = { x : 1 }; +function f() { + change_o(); + return o.x; +} + +f(); f(); +%OptimizeFunctionOnNextCall(f); +b = true; +f(); diff --git a/deps/v8/test/mjsunit/compiler/deopt-lazy-var-mutation.js b/deps/v8/test/mjsunit/compiler/deopt-lazy-var-mutation.js new file mode 100644 index 0000000000..93886f2ad7 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-lazy-var-mutation.js @@ -0,0 +1,26 @@ +// Copyright 2017 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 x = 1; +var y = 1; + +function g(a) { + x = a; + y = a; +} +%NeverOptimizeFunction(g); + +function foo(a) { + g(a); + return x + y; +} + +var o = 1; +assertEquals(foo(o), 2); +assertEquals(foo(o), 2); +%OptimizeFunctionOnNextCall(foo); +o = 2; +assertEquals(foo(o), 4); diff --git a/deps/v8/test/mjsunit/compiler/deopt-many-lazy.js b/deps/v8/test/mjsunit/compiler/deopt-many-lazy.js new file mode 100644 index 0000000000..e8a0b04419 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-many-lazy.js @@ -0,0 +1,33 @@ +// Copyright 2017 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 + + +// It optimizes and lazily deoptimizes 2 functions several times. + +function f() { + g(); +} + +function g() { + %DeoptimizeFunction(f); +} + +function a() { + b(); +} + +function b() { + %DeoptimizeFunction(a); +} + +f(); f(); +a(); a(); +for(var i = 0; i < 5; i++) { + %OptimizeFunctionOnNextCall(f); + %OptimizeFunctionOnNextCall(a); + f(); + a(); +} diff --git a/deps/v8/test/mjsunit/compiler/deopt-now-lazy.js b/deps/v8/test/mjsunit/compiler/deopt-now-lazy.js new file mode 100644 index 0000000000..6a86bcaf4d --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-now-lazy.js @@ -0,0 +1,12 @@ +// Copyright 2017 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() { + %DeoptimizeNow(); +} + +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/compiler/deopt-simple-eager.js b/deps/v8/test/mjsunit/compiler/deopt-simple-eager.js new file mode 100644 index 0000000000..9928647c8a --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-simple-eager.js @@ -0,0 +1,17 @@ +// Copyright 2017 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 + +// Simple eager deoptimization test. + +function f(o) { + return o.x; +} + +assertEquals(f({x : 2}), 2); +assertEquals(f({x : 2}), 2); +%OptimizeFunctionOnNextCall(f); +assertEquals(f({x : 2}), 2); +assertEquals(f({y : 1, x : 3}), 3); diff --git a/deps/v8/test/mjsunit/compiler/deopt-simple-lazy.js b/deps/v8/test/mjsunit/compiler/deopt-simple-lazy.js new file mode 100644 index 0000000000..e3721a3159 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-simple-lazy.js @@ -0,0 +1,19 @@ +// Copyright 2017 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 + +// Simple lazy deoptimization test. + +function f() { + g(); +} + +function g() { + %DeoptimizeFunction(f); +} + +f(); f(); +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/compiler/deopt-soft-simple.js b/deps/v8/test/mjsunit/compiler/deopt-soft-simple.js new file mode 100644 index 0000000000..eaa1e3c695 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-soft-simple.js @@ -0,0 +1,21 @@ +// Copyright 2017 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 change_o() { + o = { y : 0, x : 1 }; +} + +var o = { x : 1 }; + +function f() { + // It triggers a soft deoptimization. + change_o(); + return o.x; +} + +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/compiler/deopt-twice-on-call.js b/deps/v8/test/mjsunit/compiler/deopt-twice-on-call.js new file mode 100644 index 0000000000..f30b7d0aff --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-twice-on-call.js @@ -0,0 +1,22 @@ +// Copyright 2017 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() { + g(); + h(); +} + +function g() { + %DeoptimizeFunction(f); +} + +function h() { + %DeoptimizeFunction(f); +} + +f(); f(); +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/compiler/deopt-twice.js b/deps/v8/test/mjsunit/compiler/deopt-twice.js new file mode 100644 index 0000000000..1ec9c9fab8 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-twice.js @@ -0,0 +1,18 @@ +// Copyright 2017 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() { + g(); +} + +function g() { + %DeoptimizeFunction(f); + %DeoptimizeFunction(f); +} + +f(); f(); +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/compiler/deoptimize-lazy-weak.js b/deps/v8/test/mjsunit/compiler/deoptimize-lazy-weak.js new file mode 100644 index 0000000000..c774089098 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deoptimize-lazy-weak.js @@ -0,0 +1,47 @@ +// Copyright 2017 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 --allow-natives-syntax --verify-heap + +var o = { f : 0 }; + +var shouldDeopt = true; + +// This tests a scenario where a function has an embedded object reference, +// the function is lazy-deoptimized, the object is then collected, but the +// code object keeps the dangling pointer. + +function deopt() { + if (shouldDeopt) { + // Change the global object. This deoptimizes function f because + // it optimistically embedded the reference to o as a constant. + o = { f : 2 }; + // Collect the original object o; at this point, f should invalidate + // its invalid reference to the original object. + gc(); + } +} + +// Forwarding function to make sure that function f is not the topomost +// optimized frame (GC treats reference from topmost optimized code strongly). +function dummy_opt() { deopt(); } +function dummy() { dummy_opt(); } +%NeverOptimizeFunction(deopt); +%NeverOptimizeFunction(dummy); + +// When optimized, the function f embeds the constant reference +// to the original object o. +function f() { + dummy(); + return o.f; +} + +shouldDeopt = false; +f(); +f(); + +%OptimizeFunctionOnNextCall(f); +%OptimizeFunctionOnNextCall(dummy_opt); +shouldDeopt = true; +assertEquals(2, f()); diff --git a/deps/v8/test/mjsunit/compiler/escape-analysis-cycle.js b/deps/v8/test/mjsunit/compiler/escape-analysis-cycle.js new file mode 100644 index 0000000000..ee3a4a721c --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/escape-analysis-cycle.js @@ -0,0 +1,22 @@ +// Copyright 2017 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 --turbo-escape + +function g(o) { + return {a : o, b: 42, c: o}; +} + +function f() { + var o = {a: {}, b: 43}; + o.a = g(g(o)); + o.c = o.a.c; + %DeoptimizeNow(); + return o.c.a.c.a.c.a.c.b; +} + +assertEquals(42, f()); +assertEquals(42, f()); +%OptimizeFunctionOnNextCall(f); +assertEquals(42, f()); diff --git a/deps/v8/test/mjsunit/compiler/escape-analysis-type-none-in-object-state.js b/deps/v8/test/mjsunit/compiler/escape-analysis-type-none-in-object-state.js new file mode 100644 index 0000000000..aee6485eed --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/escape-analysis-type-none-in-object-state.js @@ -0,0 +1,23 @@ +// Copyright 2017 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(x) { + if (x != "x") { + var o = {a: (x + 1) * 1.5}; + %DeoptimizeNow(); + return o.a; + } +} + +f(1.5); f(2.5); f(NaN); + +function g(x) { + f(""+x); +} + +g("x"); g("x"); +%OptimizeFunctionOnNextCall(g); +g("x"); diff --git a/deps/v8/test/mjsunit/compiler/escape-analysis-typeguard.js b/deps/v8/test/mjsunit/compiler/escape-analysis-typeguard.js new file mode 100644 index 0000000000..8746a81f9e --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/escape-analysis-typeguard.js @@ -0,0 +1,23 @@ +// Copyright 2017 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 --turbo-escape + +class C { constructor(x) { this.a = x; } }; +class D { constructor(x) { this.a = x; } }; + +function foo(){ + var x = new C(7); + var y = new D(x); + var z = y.a; + %DeoptimizeNow(); + assertEquals(7, z.a); +} + +foo(); +foo(); +foo(); +foo(); +%OptimizeFunctionOnNextCall(foo) +foo(); diff --git a/deps/v8/test/mjsunit/compiler/native-context-specialization-hole-check.js b/deps/v8/test/mjsunit/compiler/native-context-specialization-hole-check.js index 18e383bfb0..1256f453eb 100644 --- a/deps/v8/test/mjsunit/compiler/native-context-specialization-hole-check.js +++ b/deps/v8/test/mjsunit/compiler/native-context-specialization-hole-check.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt function f() { Array.prototype[10] = 2; diff --git a/deps/v8/test/mjsunit/compiler/native-context-specialization-string-concat.js b/deps/v8/test/mjsunit/compiler/native-context-specialization-string-concat.js index 3b931c3a71..24fe4b1753 100644 --- a/deps/v8/test/mjsunit/compiler/native-context-specialization-string-concat.js +++ b/deps/v8/test/mjsunit/compiler/native-context-specialization-string-concat.js @@ -15,7 +15,7 @@ var d; function baz() { return 'baz'; } function test(arg) { - // All operands are constant folded by native context + // All add operations are constant folded by native context // specialization / inlining. a = '"' + foo + '-' + bar + '"'; b = '"' + foo + '-' + baz() + '"'; @@ -23,7 +23,7 @@ function test(arg) { // Reduce down to a JSAdd of folded constant + arg. c = foo + bar + arg; - // Reduces to a StringConcat with three operands. + // Reduces to two JSAdds with other arguments constant folded. d = '"' + foo + arg + bar + '"'; } diff --git a/deps/v8/test/mjsunit/compiler/osr-try-catch.js b/deps/v8/test/mjsunit/compiler/osr-try-catch.js new file mode 100644 index 0000000000..9924e88d55 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/osr-try-catch.js @@ -0,0 +1,59 @@ +// Copyright 2017 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 + +// This tests checks some possible wrong exception handling due to, +// for instance, the OSR loop peeling. If exception handlers are not updated +// correctly, when we run the second iteration of the outermost loop, which +// is the OSR optimised version, the try-catch will fail... which should not +// fail on a correct code. + +function SingleLoop() { + for (var a = 0; a < 2; a++) { + try { throw 'The exception should have been caught.'; } + catch(e) {} + for (var b = 0; b < 1; b++) { + %OptimizeOsr(); + } + } +} + + +// These function could also fail if the exception handlers are not updated at +// the right time: a JSStackCheck gets created for the print, just after the +// bytecode for the while LoopHeader. If the OSR phase did not exit properly +// the exception before visiting the bytecode for the print, it will fail +// because some IfSuccess gets created for nothing (the IfException will +// become dead code and removed). +function EmptyBody() { + try {; } catch(e) {; } + var a = 0; + while (1) { + %OptimizeOsr(); + print("foo"); + + if (a == 1) break; + a++; + } +} + +function NestedLoops() { + for (var a = 0; a < 2; a++) { + try {; } catch(e) {; } + %OptimizeOsr(); + var b = 0; + while (1) { + print("bar"); + + if (b == 1) break; + b++; + } + } +} + + +SingleLoop(); +EmptyBody(); +NestedLoops(); diff --git a/deps/v8/test/mjsunit/compiler/regress-758983.js b/deps/v8/test/mjsunit/compiler/regress-758983.js new file mode 100644 index 0000000000..45899c110b --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-758983.js @@ -0,0 +1,19 @@ +// Copyright 2017 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 holey = [ 2.2,,"x" ]; + +function f(b) { + holey[0] = 1.1; + var r = holey[0]; + r = b ? r : 0; + return r < 0; +} + +f(true); +f(true); +%OptimizeFunctionOnNextCall(f); +assertFalse(f(true)); diff --git a/deps/v8/test/mjsunit/compiler/regress-v8-6631.js b/deps/v8/test/mjsunit/compiler/regress-v8-6631.js new file mode 100644 index 0000000000..58fe360f05 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-v8-6631.js @@ -0,0 +1,22 @@ +// Copyright 2017 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 h(x) { + return (x|0) && (1>>x == {}) +} + +function g() { + return h(1) +}; + +function f() { + return g(h({})) +}; + +f(); +f(); +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/compiler/string-add-try-catch.js b/deps/v8/test/mjsunit/compiler/string-add-try-catch.js index e34332682c..d7a3d2583c 100644 --- a/deps/v8/test/mjsunit/compiler/string-add-try-catch.js +++ b/deps/v8/test/mjsunit/compiler/string-add-try-catch.js @@ -4,7 +4,7 @@ // Flags: --allow-natives-syntax -var a = "a".repeat(268435440); +var a = "a".repeat(%StringMaxLength()); (function() { function foo(a, b) { diff --git a/deps/v8/test/mjsunit/compiler/string-concat-try-catch.js b/deps/v8/test/mjsunit/compiler/string-concat-try-catch.js index dfd6edbb27..d85a891934 100644 --- a/deps/v8/test/mjsunit/compiler/string-concat-try-catch.js +++ b/deps/v8/test/mjsunit/compiler/string-concat-try-catch.js @@ -4,7 +4,7 @@ // Flags: --allow-natives-syntax -var a = "a".repeat(268435440); +var a = "a".repeat(%StringMaxLength()); (function() { function foo(a) { diff --git a/deps/v8/test/mjsunit/count-based-osr.js b/deps/v8/test/mjsunit/count-based-osr.js deleted file mode 100644 index 2df0b644f6..0000000000 --- a/deps/v8/test/mjsunit/count-based-osr.js +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 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: --allow-natives-syntax - -// Test that OSR works properly when using count-based interrupting/profiling. - -function osr_this() { - var a = 1; - while (%GetOptimizationCount(osr_this) == 2) ; - return a; -} -assertEquals(1, osr_this()); -assertEquals(1, osr_this()); diff --git a/deps/v8/test/mjsunit/cyrillic.js b/deps/v8/test/mjsunit/cyrillic.js index 9b21c4f8ec..f74743a316 100644 --- a/deps/v8/test/mjsunit/cyrillic.js +++ b/deps/v8/test/mjsunit/cyrillic.js @@ -132,7 +132,7 @@ for (var i = 0; i < 2; i++) { // Sigma is special because there are two lower case versions of the same upper -// case character. JS requires that case independece means that you should +// case character. JS requires that case independence means that you should // convert everything to upper case, so the two sigma variants are equal to each // other in a case independt comparison. for (var i = 0; i < 2; i++) { diff --git a/deps/v8/test/mjsunit/d8-worker.js b/deps/v8/test/mjsunit/d8-worker.js index 140cf3ccd8..a73d7b1706 100644 --- a/deps/v8/test/mjsunit/d8-worker.js +++ b/deps/v8/test/mjsunit/d8-worker.js @@ -121,6 +121,15 @@ if (this.Worker) { w.postMessage([], transferList); }); + // Test console.log in transfer list. + (function() { + var val = [undefined]; + Object.defineProperty(val, '0', {get: () => console.log()}); + assertThrows(function() { + w.postMessage(val, [val]); + }); + })(); + // Clone ArrayBuffer var ab1 = createArrayBuffer(16); w.postMessage(ab1); diff --git a/deps/v8/test/mjsunit/date-parse.js b/deps/v8/test/mjsunit/date-parse.js index 62dddfd1c2..59f0e367ca 100644 --- a/deps/v8/test/mjsunit/date-parse.js +++ b/deps/v8/test/mjsunit/date-parse.js @@ -207,7 +207,7 @@ var testCasesPDT = [ // Local time cases. var testCasesLocalTime = [ - // Allow timezone ommision. + // Allow timezone omission. 'Sat, 01-Jan-2000 08:00:00', 'Sat, 01 Jan 2000 08:00:00', 'Jan 01 2000 08:00:00', diff --git a/deps/v8/test/mjsunit/deopt-recursive-eager-once.js b/deps/v8/test/mjsunit/deopt-recursive-eager-once.js index 3443f52611..1b4e155091 100644 --- a/deps/v8/test/mjsunit/deopt-recursive-eager-once.js +++ b/deps/v8/test/mjsunit/deopt-recursive-eager-once.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt function foo(i, deopt = false) { if (i == 0) { @@ -15,7 +15,6 @@ function foo(i, deopt = false) { } } -assertEquals(0, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); foo(10); @@ -24,11 +23,9 @@ foo(10); foo(10); assertOptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); foo(10, true); assertUnoptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(1, %GetDeoptCount(foo)); diff --git a/deps/v8/test/mjsunit/deopt-recursive-lazy-once.js b/deps/v8/test/mjsunit/deopt-recursive-lazy-once.js index 38a5851091..f75dde7dc2 100644 --- a/deps/v8/test/mjsunit/deopt-recursive-lazy-once.js +++ b/deps/v8/test/mjsunit/deopt-recursive-lazy-once.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt function foo(i, deopt = false) { if (i == 0) { @@ -15,7 +15,6 @@ function foo(i, deopt = false) { } } -assertEquals(0, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); foo(10); @@ -24,11 +23,9 @@ foo(10); foo(10); assertOptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); foo(10, true); assertUnoptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(1, %GetDeoptCount(foo)); diff --git a/deps/v8/test/mjsunit/deopt-recursive-soft-once.js b/deps/v8/test/mjsunit/deopt-recursive-soft-once.js index d3c9b8c550..f2cadf2e54 100644 --- a/deps/v8/test/mjsunit/deopt-recursive-soft-once.js +++ b/deps/v8/test/mjsunit/deopt-recursive-soft-once.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt function foo(i, deopt = false, deoptobj = null) { @@ -16,7 +16,6 @@ function foo(i, deopt = false, deoptobj = null) { } } -assertEquals(0, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); foo(10); @@ -25,12 +24,10 @@ foo(10); foo(10); assertOptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); foo(10, true, { bar: function(){} }); assertUnoptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); // Soft deopts don't count to the deopt count. assertEquals(0, %GetDeoptCount(foo)); diff --git a/deps/v8/test/mjsunit/deopt-unlinked.js b/deps/v8/test/mjsunit/deopt-unlinked.js index 3b6d6920a8..1005737988 100644 --- a/deps/v8/test/mjsunit/deopt-unlinked.js +++ b/deps/v8/test/mjsunit/deopt-unlinked.js @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt function foo() {} -assertEquals(0, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); foo(); @@ -15,18 +14,15 @@ foo(); foo(); assertOptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(0, %GetDeoptCount(foo)); // Unlink the function. %DeoptimizeFunction(foo); assertUnoptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(1, %GetDeoptCount(foo)); foo(); assertUnoptimized(foo); -assertEquals(1, %GetOptimizationCount(foo)); assertEquals(1, %GetDeoptCount(foo)); diff --git a/deps/v8/test/mjsunit/deopt-with-fp-regs.js b/deps/v8/test/mjsunit/deopt-with-fp-regs.js index 0fff838de6..bdb08053ae 100644 --- a/deps/v8/test/mjsunit/deopt-with-fp-regs.js +++ b/deps/v8/test/mjsunit/deopt-with-fp-regs.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt deopt_trigger = 0; side_effect = 0; diff --git a/deps/v8/test/mjsunit/ensure-growing-store-learns.js b/deps/v8/test/mjsunit/ensure-growing-store-learns.js index fc7b6c2543..25fa0e6d01 100644 --- a/deps/v8/test/mjsunit/ensure-growing-store-learns.js +++ b/deps/v8/test/mjsunit/ensure-growing-store-learns.js @@ -3,7 +3,7 @@ // found in the LICENSE file. // Flags: --allow-natives-syntax --noverify-heap --noenable-slow-asserts -// Flags: --opt --no-always-opt --no-stress-fullcodegen +// Flags: --opt --no-always-opt // --noverify-heap and --noenable-slow-asserts are set because the test is too // slow with it on. diff --git a/deps/v8/test/mjsunit/es6/array-species.js b/deps/v8/test/mjsunit/es6/array-species.js index 25edf55104..5127d255bb 100644 --- a/deps/v8/test/mjsunit/es6/array-species.js +++ b/deps/v8/test/mjsunit/es6/array-species.js @@ -52,11 +52,10 @@ assertEquals(undefined, Array.prototype.map.call(new MyNonArray(), ()=>{}).length); assertEquals(undefined, Array.prototype.filter.call(new MyNonArray(), ()=>{}).length); -assertEquals(undefined, - Array.prototype.concat.call(new MyNonArray(), ()=>{}).length); -// slice and splice actually do explicitly define the length for some reason +// slice, splice, and concat actually do explicitly define the length. assertEquals(0, Array.prototype.slice.call(new MyNonArray()).length); assertEquals(0, Array.prototype.splice.call(new MyNonArray()).length); +assertEquals(1, Array.prototype.concat.call(new MyNonArray(), ()=>{}).length); // Cross-realm Arrays build same-realm arrays diff --git a/deps/v8/test/mjsunit/es6/new-target.js b/deps/v8/test/mjsunit/es6/new-target.js index 4be1254d67..14446fc40f 100644 --- a/deps/v8/test/mjsunit/es6/new-target.js +++ b/deps/v8/test/mjsunit/es6/new-target.js @@ -410,3 +410,65 @@ function get_new_target() { return new.target; } assertThrows(function() { Function("++(new.target)"); }, ReferenceError); assertThrows(function() { Function("for (new.target of {});"); }, SyntaxError); })(); + +(function TestOperatorPrecedence() { + function A() {} + function constructNewTargetDotProp() { return new new.target.Prop } + constructNewTargetDotProp.Prop = A; + assertInstanceof(new constructNewTargetDotProp, A); + + function constructNewTargetBracketProp() { return new new.target['Prop'] } + constructNewTargetBracketProp.Prop = A; + assertInstanceof(new constructNewTargetBracketProp, A); + + function refNewTargetDotProp() { return new.target.Prop; } + function B() {} + refNewTargetDotProp.Prop = B; + assertEquals(new refNewTargetDotProp, B); + + function refNewTargetBracketProp() { return new.target['Prop']; } + refNewTargetBracketProp.Prop = B; + assertEquals(new refNewTargetBracketProp, B); + + var calls = 0; + function constructNewTargetArgsDotProp(safe) { + this.Prop = ++calls; + return safe ? Object(new new.target().Prop) : this; + } + assertInstanceof(new constructNewTargetArgsDotProp, + constructNewTargetArgsDotProp); + assertEquals(3, new constructNewTargetArgsDotProp(true) | 0); + + function constructNewTargetArgsBracketProp(safe) { + this.Prop = ++calls; + return safe ? Object(new new.target()['Prop']) : this; + } + assertInstanceof(new constructNewTargetArgsBracketProp, + constructNewTargetArgsBracketProp); + assertEquals(6, new constructNewTargetArgsBracketProp(true) | 0); + + function callNewTargetArgsDotProp(safe) { + this.Prop = ++calls; + return safe ? Object(new.target().Prop) : this; + } + assertInstanceof(new callNewTargetArgsDotProp(), callNewTargetArgsDotProp); + assertEquals(new callNewTargetArgsDotProp(true) | 0, 9); + + function callNewTargetArgsBracketProp(safe) { + this.Prop = ++calls; + return safe ? Object(new.target()['Prop']) : this; + } + assertInstanceof(new callNewTargetArgsBracketProp(), + callNewTargetArgsBracketProp); + assertEquals(new callNewTargetArgsBracketProp(true) | 0, 12); + + function tagNewTarget(callSite, ...subs) { + return callSite ? subs : new.target`${new.target.name}`; + } + assertEquals(new tagNewTarget, ["tagNewTarget"]); + + function C(callSite, ...subs) { return subs; } + function tagNewTargetProp() { return new.target.Prop`${new.target.name}`; } + tagNewTargetProp.Prop = C; + assertEquals(new tagNewTargetProp, ["tagNewTargetProp"]); +})(); diff --git a/deps/v8/test/mjsunit/es6/proxies-construct.js b/deps/v8/test/mjsunit/es6/proxies-construct.js index 344c50a7e4..5d78e5b3e1 100644 --- a/deps/v8/test/mjsunit/es6/proxies-construct.js +++ b/deps/v8/test/mjsunit/es6/proxies-construct.js @@ -94,6 +94,20 @@ assertEquals('b1', instance2.arg2); })(); +(function testConstructTrapNonConstructor() { + function target() { + }; + var p = new Proxy(target, { + construct: function() { + return 0; + } + }); + + assertThrows(function() { + new p(); + }, TypeError); +})(); + (function testConstructCrossRealm() { var realm1 = Realm.create(); var handler = { diff --git a/deps/v8/test/mjsunit/es6/proxies-get.js b/deps/v8/test/mjsunit/es6/proxies-get.js index b1b92dbb06..4f7b2d0be4 100644 --- a/deps/v8/test/mjsunit/es6/proxies-get.js +++ b/deps/v8/test/mjsunit/es6/proxies-get.js @@ -35,6 +35,12 @@ assertThrows("proxy.property", Error); })(); +(function testThrowOnTrapNotCallable() { + var handler = new Proxy({}, {get: 'not_callable' }); + var proxy = new Proxy({}, handler); + assertThrows("proxy.property", Error); +})(); + (function testFallback() { var target = {property:"value"}; var proxy = new Proxy(target, {}); @@ -125,3 +131,83 @@ "[[Get]](iterator, next)" ], log); })(); + +(function testGetterWithSideEffect() { + var obj = { + key: 0 + } + assertEquals(obj.key, 0); + var p = new Proxy(obj, {}); + var q = new Proxy(p, { + get(target, name) { + if (name != 'key') return Reflect.get(target, name); + target.key++; + return target.key; + } + }); + + assertEquals(0, p.key); + // Assert the trap is not called twice. + assertEquals(1, q.key); +})(); + +(function testReceiverWithTrap() { + var obj = {}; + var p = new Proxy(obj, { + get(target, name, receiver) { + if (name != 'key') return Reflect.get(target, name); + + assertSame(target, obj); + assertSame(receiver, p); + return 42; + } + }); + assertEquals(42, p.key); +})(); + +(function testReceiverWithoutTrap() { + var obj = { + get prop() { + assertSame(this, p); + return 42; + } + }; + var p = new Proxy(obj, {}); + assertEquals(42, p.prop); +})(); + +(function testGetPropertyDetailsBailout() { + var obj = { + } + var p = new Proxy(obj, { + getOwnPropertyDescriptor() { + throw new Error('Error from proxy getOwnPropertyDescriptor trap'); + } + }); + var q = new Proxy(p, { + get(target, name) { + return 42; + } + }); + assertThrows(function(){ q.prop }, Error, + 'Error from proxy getOwnPropertyDescriptor trap'); +})(); + + +(function testGetPropertyDetailsBailout2() { + var obj = {}; + Object.defineProperty(obj, 'prop', { + value: 53, + configurable: false + }); + var p = new Proxy(obj, {}); + var q = new Proxy(p, { + get(target, name) { + return 42; + } + }); + assertThrows(function(){ q.prop }, TypeError, + "'get' on proxy: property 'prop' is a read-only and non-configurable data" + + " property on the proxy target but the proxy did not return its actual" + + " value (expected '53' but got '42')"); +})(); diff --git a/deps/v8/test/mjsunit/es6/proxies-has.js b/deps/v8/test/mjsunit/es6/proxies-has.js index 7294196a11..f5b11cfc57 100644 --- a/deps/v8/test/mjsunit/es6/proxies-has.js +++ b/deps/v8/test/mjsunit/es6/proxies-has.js @@ -5,12 +5,13 @@ var target = { "target_one": 1 }; +target[0] = 42; target.__proto__ = { "target_two": 2 }; var handler = { has: function(target, name) { - return name == "present"; + return name == "present" || name == '0'; } } @@ -20,6 +21,25 @@ var proxy = new Proxy(target, handler); assertTrue("present" in proxy); assertFalse("nonpresent" in proxy); +// Test element cases. +assertTrue(0 in proxy); +assertFalse(1 in proxy); +assertTrue('0' in proxy); +assertFalse('1' in proxy); + +var symbol0 = { + [Symbol.toPrimitive](hint) { + return 0; + } +}; +var symbol1 = { + [Symbol.toPrimitive](hint) { + return 1; + } +}; +assertTrue(symbol0 in proxy); +assertFalse(symbol1 in proxy); + // Test interesting algorithm steps: // Step 7: Fall through to target if trap is undefined. @@ -59,3 +79,48 @@ assertFalse("in_your_dreams" in proxy); var object = Object.create(proxy); object.hasOwnProperty(0); })(); + +(function FalseTargetPropExists() { + var target2 = { + attr: 1 + }; + var p = new Proxy(target2, { + has: function(t, prop) { + return false; + } + }); + + assertFalse("attr" in p); +})(); + +(function TargetHasAccessorProperty() { + var target = {}; + Object.defineProperty(target, 'prop', { + get: function() { + assertSame(this, target); + return 42; + }, + configurable: true + }) + var proxy = new Proxy(target, { + has: function(t, prop) { + return false; + }, + }); + assertFalse('prop' in proxy); +})(); + +(function TargetHasNonConfigurableProperty() { + var target = {}; + Object.defineProperty(target, 'prop', { + value: 42, + configurable: false, + writable: true + }) + var proxy = new Proxy(target, { + has: function(t, prop) { + return false; + }, + }); + assertThrows(function() { 'prop' in proxy; }, TypeError); +})(); diff --git a/deps/v8/test/mjsunit/es6/reflect-define-property.js b/deps/v8/test/mjsunit/es6/reflect-define-property.js index 8eb3f6580e..6ead02ba74 100644 --- a/deps/v8/test/mjsunit/es6/reflect-define-property.js +++ b/deps/v8/test/mjsunit/es6/reflect-define-property.js @@ -920,7 +920,7 @@ for (var i = 0; i < 1000; i++) { assertEquals(999, o[999]); -// Regression test: Bizzare behavior on non-strict arguments object. +// Regression test: Bizarre behavior on non-strict arguments object. // TODO(yangguo): Tests disabled, needs investigation! /* (function test(arg0) { diff --git a/deps/v8/test/mjsunit/es6/templates.js b/deps/v8/test/mjsunit/es6/templates.js index efe314ed95..a5157b85f9 100644 --- a/deps/v8/test/mjsunit/es6/templates.js +++ b/deps/v8/test/mjsunit/es6/templates.js @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Flags: --no-harmony-template-escapes + var num = 5; var str = "str"; function fn() { return "result"; } diff --git a/deps/v8/test/mjsunit/es6/typedarray-slice.js b/deps/v8/test/mjsunit/es6/typedarray-slice.js index 4fa3b9f21f..2f40fe5425 100644 --- a/deps/v8/test/mjsunit/es6/typedarray-slice.js +++ b/deps/v8/test/mjsunit/es6/typedarray-slice.js @@ -124,7 +124,7 @@ function testCustomSubclass(superClass, speciesClass) { // Custom constructor with shared buffer. exampleArray = new Array(64).fill(0).map((v,i) => i); let filledBuffer = new Uint8Array(exampleArray).buffer; - // Create a view for the begining of the buffer. + // Create a view for the beginning of the buffer. let customArray2 = new superClass(filledBuffer, 0, 3); customArray2.constructor = { [Symbol.species]: function(length) { diff --git a/deps/v8/test/mjsunit/es6/typedarray.js b/deps/v8/test/mjsunit/es6/typedarray.js index dcfc9caa30..2f4c1b639d 100644 --- a/deps/v8/test/mjsunit/es6/typedarray.js +++ b/deps/v8/test/mjsunit/es6/typedarray.js @@ -534,6 +534,7 @@ function TestTypedArraySet() { var a51 = new Int8Array(b, 0, 2) var a52 = new Int8Array(b, 1, 2) var a53 = new Int8Array(b, 2, 2) + var a54 = new Int8Array(b, 0, 0) a5.set([0x5050, 0x0a0a]) assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) @@ -565,6 +566,10 @@ function TestTypedArraySet() { a5.set(a53) assertArrayPrefix([0x000a, 0x000b], a5) + a50.set([0x50, 0x51, 0x0a, 0x0b]) + a5.set(a54, 0) + assertArrayPrefix([0x50, 0x51, 0x0a, 0x0b], a50) + // Mixed types of same size. var a61 = new Float32Array([1.2, 12.3]) var a62 = new Int32Array(2) diff --git a/deps/v8/test/mjsunit/es8/async-await-basic.js b/deps/v8/test/mjsunit/es8/async-await-basic.js index ba11798aac..6e9ee02ffe 100644 --- a/deps/v8/test/mjsunit/es8/async-await-basic.js +++ b/deps/v8/test/mjsunit/es8/async-await-basic.js @@ -562,3 +562,42 @@ assertDoesNotThrow(gaga); %RunMicrotasks(); assertEquals(["a", "b", "c"], log); } + +{ + function f1() { + var x; + with ({get await() { return [42] }}) { + x = await + [0]; + }; + return x; + } + + assertEquals(42, f1()); + async function f2() { + var x; + with ({get await() { return [42] }}) { + x = await + [0]; + }; + return x; + } + + var ans; + f2().then(x => ans = x).catch(e => ans = e); + %RunMicrotasks(); + assertEquals([0], ans); +} + +{ + function f1() { + var x, y; + with ({get await() { return [42] }}) { + x = await + y = 1 + }; + return y; + } + + assertEquals(1, f1()); +} diff --git a/deps/v8/test/mjsunit/field-type-tracking.js b/deps/v8/test/mjsunit/field-type-tracking.js index 4afc7456e2..2e0cb8bd6f 100644 --- a/deps/v8/test/mjsunit/field-type-tracking.js +++ b/deps/v8/test/mjsunit/field-type-tracking.js @@ -3,7 +3,7 @@ // found in the LICENSE file. // Flags: --allow-natives-syntax --nostress-opt --track-field-types -// Flags: --opt --no-always-opt --no-stress-fullcodegen +// Flags: --opt --no-always-opt (function() { var o = { text: "Hello World!" }; diff --git a/deps/v8/test/mjsunit/getters-on-elements.js b/deps/v8/test/mjsunit/getters-on-elements.js index d40c56f4e0..d8cda83ad1 100644 --- a/deps/v8/test/mjsunit/getters-on-elements.js +++ b/deps/v8/test/mjsunit/getters-on-elements.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 --noalways-opt --opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --noalways-opt --opt // It's nice to run this in other browsers too. var standalone = false; diff --git a/deps/v8/test/mjsunit/harmony/async-generators-resume-return.js b/deps/v8/test/mjsunit/harmony/async-generators-resume-return.js new file mode 100644 index 0000000000..7a7efe7801 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/async-generators-resume-return.js @@ -0,0 +1,150 @@ +// Copyright 2017 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-async-iteration --allow-natives-syntax + +// .return() from state suspendedStart with undefined +testAsync(test => { + test.plan(3); + + async function* gen() { + test.unreachable(); + } + + let didResolvePromise = false; + let g = gen(); + g.return(undefined).then( + (iterResult) => { + test.equals(true, didResolvePromise); + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + + g.next().then( + (iterResult) => { + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + + // Race: generator request's promise should resolve after this Promise. + Promise.resolve("already-resolved").then( + _ => { didResolvePromise = true }, + test.unexpectedRejection()); + +}, "AsyncGenerator.return(undefined) / suspendStart"); + +// .return() from state suspendedStart with thenable +testAsync(test => { + test.plan(3); + + async function* gen() { + test.unreachable(); + } + + let didResolvePromise = false; + let g = gen(); + + let resolve; + let awaitedThenable = { then(resolveFn) { resolve = resolveFn; } }; + + g.return(awaitedThenable).then( + (iterResult) => { + test.equals(true, didResolvePromise); + test.equals({ value: "resolvedPromise", done: true }, iterResult); + }, + test.unexpectedRejection()); + + g.next().then( + (iterResult) => { + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + + test.drainMicrotasks(); + resolve("resolvedPromise"); + + // Race: generator request's promise should resolve after this Promise. + Promise.resolve("already-resolved").then( + _ => { didResolvePromise = true }, + test.unexpectedRejection()); + +}, "AsyncGenerator.return(thenable) / suspendStart"); + +// .return() from state suspendedYield with undefined +testAsync(test => { + test.plan(4); + + async function* gen() { + yield; + test.unreachable(); + } + + let didResolvePromise = false; + let g = gen(); + g.next().then( + (iterResult) => { + test.equals({ value: undefined, done: false }, iterResult); + }, + test.unexpectedRejection()); + g.return(undefined).then( + (iterResult) => { + test.equals(true, didResolvePromise); + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + g.next().then( + (iterResult) => { + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + + // Race: generator request's promise should resolve after this Promise. + Promise.resolve("already-resolved").then( + _ => { didResolvePromise = true }, + test.unexpectedRejection()); + +}, "AsyncGenerator.return(undefined) / suspendedYield"); + +// .return() from state suspendedYield with thenable +testAsync(test => { + test.plan(4); + + async function* gen() { + yield; + test.unreachable(); + } + + let didResolvePromise = false; + let g = gen(); + + let resolve; + let awaitedThenable = { then(resolveFn) { resolve = resolveFn; } }; + + g.next().then( + (iterResult) => { + test.equals({ value: undefined, done: false }, iterResult); + }, + test.unexpectedRejection()); + g.return(awaitedThenable).then( + (iterResult) => { + test.equals(true, didResolvePromise); + test.equals({ value: "resolvedPromise", done: true }, iterResult); + }, + test.unexpectedRejection()); + + g.next().then( + (iterResult) => { + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + + test.drainMicrotasks(); + resolve("resolvedPromise"); + + // Race: generator request's promise should resolve after this Promise. + Promise.resolve("already-resolved").then( + _ => { didResolvePromise = true }, + test.unexpectedRejection()); + +}, "AsyncGenerator.return(thenable) / suspendYield"); diff --git a/deps/v8/test/mjsunit/harmony/async-generators-return.js b/deps/v8/test/mjsunit/harmony/async-generators-return.js new file mode 100644 index 0000000000..b0c7febf8c --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/async-generators-return.js @@ -0,0 +1,119 @@ +// Copyright 2017 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-async-iteration --allow-natives-syntax + +testAsync(test => { + test.plan(2); + + async function* gen() { + return; + test.unreachable(); + } + + let didResolvePromise = false; + gen().next().then( + (iterResult) => { + test.equals(false, didResolvePromise); + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + + // Race: generator request's promise should resolve before this Promise. + Promise.resolve("already-resolved").then( + _ => { didResolvePromise = true }, + test.unexpectedRejection()); + +}, "return-race-no-operand"); + +testAsync(test => { + test.plan(2); + + async function* gen() { + return undefined; + test.unreachable(); + } + + let didResolvePromise = false; + gen().next().then( + (iterResult) => { + test.equals(true, didResolvePromise); + test.equals({ value: undefined, done: true }, iterResult); + }, + test.unexpectedRejection()); + + // Race: generator request's promise should resolve after this Promise. + Promise.resolve("already-resolved").then( + _ => { didResolvePromise = true }, + test.unexpectedRejection()); + +}, "return-race-with-operand"); + +// Return a thenable which is never settled +testAsync(test => { + test.plan(0); + + let promise = { then() { } }; + + async function* gen() { + return promise; + test.unreachable(); + } + + gen().next().then( + (iterResult) => test.unreachable(), + test.unexpectedRejection()); +}, "return-await-thenable-pending"); + +// Return a thenable which is fulfilled later +testAsync(test => { + test.plan(2); + + let resolve; + let awaitedThenable = { then(resolveFn) { resolve = resolveFn; } }; + let finallyEvaluated = false; + + async function* gen() { + try { + return awaitedThenable; + } finally { + finallyEvaluated = true; + } + } + + gen().next().then( + (iterResult) => { + test.equals({ value: "resolvedPromise", done: true }, iterResult); + test.equals(true, finallyEvaluated); + }, + test.unexpectedRejection()); + + test.drainMicrotasks(); + resolve("resolvedPromise"); +}, "yield-await-thenable-resolved"); + +// Return a thenable which is rejected later +testAsync(test => { + test.plan(2); + + let reject; + let awaitedThenable = { then(resolveFn, rejectFn) { reject = rejectFn; } }; + async function* gen() { + try { + yield awaitedThenable; + } catch (e) { + test.equals("rejection", e); + return e; + } + } + + gen().next().then( + (iterResult) => { + test.equals({ value: "rejection", done: true }, iterResult); + }, + test.unexpectedRejection()); + + test.drainMicrotasks(); + reject("rejection"); +}, "yield-await-thenable-rejected"); diff --git a/deps/v8/test/mjsunit/harmony/async-generators-yield.js b/deps/v8/test/mjsunit/harmony/async-generators-yield.js new file mode 100644 index 0000000000..c999c7006f --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/async-generators-yield.js @@ -0,0 +1,68 @@ +// Copyright 2017 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-async-iteration --allow-natives-syntax + +// Yield a thenable which is never settled +testAsync(test => { + test.plan(0); + + let awaitedThenable = { then() { } }; + + async function* gen() { + yield awaitedThenable; + test.unreachable(); + } + + gen().next().then( + (iterResult) => test.unreachable(), + test.unexpectedRejection()); +}, "yield-await-thenable-pending"); + +// Yield a thenable which is fulfilled later +testAsync(test => { + test.plan(1); + + let resolve; + let awaitedThenable = { then(resolveFn) { resolve = resolveFn; } }; + + async function* gen() { + let input = yield awaitedThenable; + test.equals("resolvedPromise", input); + } + + gen().next().then( + (iterResult) => { + test.equals({ value: "resolvedPromise", done: false }, iterResult); + }, + test.unexpectedRejection()); + + test.drainMicrotasks(); + resolve("resolvedPromise"); +}, "yield-await-thenable-resolved"); + +// Yield a thenable which is rejected later +testAsync(test => { + test.plan(2); + + let reject; + let awaitedThenable = { then(resolveFn, rejectFn) { reject = rejectFn; } }; + async function* gen() { + try { + yield awaitedThenable; + } catch (e) { + test.equals("rejection", e); + return e; + } + } + + gen().next().then( + (iterResult) => { + test.equals({ value: "rejection", done: true }, iterResult); + }, + test.unexpectedRejection()); + + test.drainMicrotasks(); + reject("rejection"); +}, "yield-await-thenable-rejected"); diff --git a/deps/v8/test/mjsunit/harmony/do-expressions-arrow-param-scope.js b/deps/v8/test/mjsunit/harmony/do-expressions-arrow-param-scope.js new file mode 100644 index 0000000000..f5d5097995 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/do-expressions-arrow-param-scope.js @@ -0,0 +1,95 @@ +// Copyright 2017 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-do-expressions + +(function testBasic() { + let f = (x = eval("var z = 42; z"), y = do { 43 }) => x + y; + assertEquals(85, f()); +})(); + +(function testReturnParam() { + let f = (x = eval("var z = 42; z"), y = do { x }) => x + y; + assertEquals(84, f()); +})(); + +(function testCaptureParam() { + let f = (x = eval("var z = 42; z"), y = do { () => x }) => x + y(); + assertEquals(84, f()); +})(); + +(function testScoped() { + let f = (x = eval("var z = 42; z"), y = do { let z; x }) => x + y; + assertEquals(84, f()); +})(); + +(function testCaptureScoped() { + let f = (x = eval("var z = 42; z"), y = do { let z; () => x }) => x + y(); + assertEquals(84, f()); +})(); + +(function testCaptureOuter() { + let z = 44; + let f = (x = eval("var z = 42; z"), y = do { () => z }) => x + y(); + assertEquals(86, f()) +})(); + +(function testCaptureOuterScoped() { + let z = 44; + let f = (x = eval("var z = 42; z"), y = do { let q; () => z }) => x + y(); + assertEquals(86, f()) +})(); + +(function testWith() { + let f = (x = eval("var z = 42; z"), + y = do { + with ({foo: "bar"}) { + () => x } + }) => x + y(); + assertEquals(84, f()) +})(); + +(function testTry() { + let f = (x = eval("var z = 42; z"), + y = do { + try { () => x } + catch (e) { } + }) => x + y(); + assertEquals(84, f()) +})(); + +(function testCatch() { + let f = (x = eval("var z = 42; z"), + y = do { + try { throw 42 } + catch (e) { () => x } + }) => x + y(); + assertEquals(84, f()) +})(); + +(function testFinally() { + let z = 44; + let q; + let f = (x = eval("var z = 42; z"), + y = do { + try { } + catch (e) { } + finally { q = () => z } + q; + }) => x + y(); + assertEquals(86, f()) +})(); + +(function testFinallyThrow() { + let z = 44; + let q; + let f = (x = eval("var z = 42; z"), + y = do { + try { throw 42; } + catch (e) { } + finally { q = () => z } + q; + }) => x + y(); + assertEquals(86, f()) +})(); diff --git a/deps/v8/test/mjsunit/harmony/do-expressions.js b/deps/v8/test/mjsunit/harmony/do-expressions.js index c238bc6330..f66c71eb83 100644 --- a/deps/v8/test/mjsunit/harmony/do-expressions.js +++ b/deps/v8/test/mjsunit/harmony/do-expressions.js @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-do-expressions --allow-natives-syntax --no-always-opt -// Flags: --opt --no-stress-fullcodegen +// Flags: --harmony-do-expressions --allow-natives-syntax --no-always-opt --opt function returnValue(v) { return v; } function MyError() {} diff --git a/deps/v8/test/mjsunit/harmony/intl-pluralrules-select.js b/deps/v8/test/mjsunit/harmony/intl-pluralrules-select.js new file mode 100644 index 0000000000..cced9b1335 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/intl-pluralrules-select.js @@ -0,0 +1,52 @@ +// Copyright 2017 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-plural-rules + +if (this.Intl) { + var pr; + var suffixes; + function format(n) { + return "" + n + suffixes[pr.select(n)]; + } + + // These English examples illustrate the purpose of the PluralRules class. + pr = new Intl.PluralRules("en-US"); + suffixes = { + one: " day", + other: " days", + }; + assertEquals("0 days", format(0)); + assertEquals("0.5 days", format(0.5)); + assertEquals("1 day", format(1)); + assertEquals("1.5 days", format(1.5)); + assertEquals("2 days", format(2)); + + pr = new Intl.PluralRules("en-US", {type: "ordinal"}); + suffixes = { + one: "st", + two: "nd", + few: "rd", + other: "th", + }; + assertEquals("0th", format(0)); + assertEquals("1st", format(1)); + assertEquals("2nd", format(2)); + assertEquals("3rd", format(3)); + assertEquals("4th", format(4)); + assertEquals("11th", format(11)); + assertEquals("21st", format(21)); + assertEquals("103rd", format(103)); + + // Arabic can cause every possible return value from select() + pr = new Intl.PluralRules("ar"); + suffixes = null; + assertEquals("zero", pr.select(0)); + assertEquals("one", pr.select(1)); + assertEquals("two", pr.select(2)); + assertEquals("few", pr.select(3)); + assertEquals("many", pr.select(11)); + assertEquals("other", pr.select(100)); + assertEquals("other", pr.select(1.5)); +} diff --git a/deps/v8/test/mjsunit/harmony/modules-import-16.js b/deps/v8/test/mjsunit/harmony/modules-import-16.js new file mode 100644 index 0000000000..94510d48fc --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-16.js @@ -0,0 +1,36 @@ +// Copyright 2017 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 --harmony-dynamic-import + +var ran = false; +var x; + +var body = "import('modules-skip-1.js').then(ns => { x = ns.life();" + + " ran = true;} ).catch(err => %AbortJS(err))" +var func = new Function(body); +func(); + +%RunMicrotasks(); +assertEquals(42, x); +assertTrue(ran); + +var ran = false; +var body = "import('modules-skip-1.js').then(ns => { x = ns.life();" + + " ran = true;} ).catch(err => %AbortJS(err))" +eval("var func = new Function(body); func();"); + +%RunMicrotasks(); +assertEquals(42, x); +assertTrue(ran); + +var ran = false; +var body = "eval(import('modules-skip-1.js').then(ns => { x = ns.life();" + + " ran = true;} ).catch(err => %AbortJS(err)))" +var func = new Function(body); +func(); + +%RunMicrotasks(); +assertEquals(42, x); +assertTrue(ran); diff --git a/deps/v8/test/mjsunit/harmony/private-symbols.js b/deps/v8/test/mjsunit/harmony/private-symbols.js index 4006359746..627a43a70b 100644 --- a/deps/v8/test/mjsunit/harmony/private-symbols.js +++ b/deps/v8/test/mjsunit/harmony/private-symbols.js @@ -28,7 +28,8 @@ for (var key in object2) assertUnreachable(); // Private symbols must never leak to proxy traps. -var proxy = new Proxy({}, new Proxy({}, {get() {return () => {throw 666}}})); +var proxy = new Proxy({}, new Proxy({}, {get() {return () => { + throw new Error()}}})); var object = {__proto__: proxy}; // [[Set]] diff --git a/deps/v8/test/mjsunit/harmony/promise-prototype-finally.js b/deps/v8/test/mjsunit/harmony/promise-prototype-finally.js index eefce4b6ba..d80065f10d 100644 --- a/deps/v8/test/mjsunit/harmony/promise-prototype-finally.js +++ b/deps/v8/test/mjsunit/harmony/promise-prototype-finally.js @@ -4,320 +4,241 @@ // Flags: --harmony-promise-finally --allow-natives-syntax -var asyncAssertsExpected = 0; +assertThrows(() => Promise.prototype.finally.call(5), TypeError); -function assertUnreachable() { - %AbortJS("Unreachable: failure"); -} +testAsync(assert => { + assert.plan(1); -function assertAsyncRan() { - ++asyncAssertsExpected; -} + Promise.resolve(3).finally().then(x => { + assert.equals(3, x); + }, assert.unreachable); +}, "resolve/finally/then"); -function assertAsync(b, s) { - if (b) { - print(s, "succeeded"); - } else { - %AbortJS(s + " FAILED!"); - } - --asyncAssertsExpected; -} - -function assertEqualsAsync(b, s) { - if (b === s) { - print(b, "===", s, "succeeded"); - } else { - %AbortJS(b + "===" + s + " FAILED!"); - } - --asyncAssertsExpected; -} - -function assertAsyncDone(iteration) { - var iteration = iteration || 0; - %EnqueueMicrotask(function() { - if (asyncAssertsExpected === 0) - assertAsync(true, "all"); - else if ( - iteration > 10 // Shouldn't take more. - ) - assertAsync(false, "all... " + asyncAssertsExpected); - else - assertAsyncDone(iteration + 1); +testAsync(assert => { + assert.plan(1); + + Promise.reject(3).finally().then(assert.unreachable, x => { + assert.equals(3, x); }); -} - -(function() { - assertThrows( - function() { - Promise.prototype.finally.call(5); - }, - TypeError - ); -})(); - -// resolve/finally/then -(function() { - Promise.resolve(3).finally().then( - x => { - assertEqualsAsync(3, x); - }, - assertUnreachable - ); - assertAsyncRan(); -})(); - -// reject/finally/then -(function() { - Promise.reject(3).finally().then(assertUnreachable, x => { - assertEqualsAsync(3, x); +}, "reject/finally/then"); + +testAsync(assert => { + assert.plan(1); + + Promise.resolve(3).finally(2).then(x => { + assert.equals(3, x); + }, assert.unreachable); +}, "resolve/finally-return-notcallable/then"); + +testAsync(assert => { + assert.plan(1); + + Promise.reject(3).finally(2).then(assert.unreachable, e => { + assert.equals(3, e); }); - assertAsyncRan(); -})(); - -// resolve/finally-return-notcallable/then -(function() { - Promise.resolve(3).finally(2).then( - x => { - assertEqualsAsync(3, x); - }, - assertUnreachable - ); - assertAsyncRan(); -})(); - -// reject/finally-return-notcallable/then -(function() { - Promise.reject(3).finally(2).then( - assertUnreachable, e => { - assertEqualsAsync(3, e); - }); - assertAsyncRan(); -})(); +}, "reject/finally-return-notcallable/then"); + +testAsync(assert => { + assert.plan(1); -// reject/finally/catch -(function() { Promise.reject(3).finally().catch(reason => { - assertEqualsAsync(3, reason); + assert.equals(3, reason); }); - assertAsyncRan(); -})(); +}, "reject/finally/catch"); -// reject/finally/then/catch -(function() { - Promise.reject(3).finally().then(assertUnreachable).catch(reason => { - assertEqualsAsync(3, reason); +testAsync(assert => { + assert.plan(1); + + Promise.reject(3).finally().then(assert.unreachable).catch(reason => { + assert.equals(3, reason); }); - assertAsyncRan(); -})(); +}, "reject/finally/then/catch"); + +testAsync(assert => { + assert.plan(2); -// resolve/then/finally/then -(function() { Promise.resolve(3) .then(x => { - assertEqualsAsync(3, x); + assert.equals(3, x); return x; }) .finally() - .then( - x => { - assertEqualsAsync(3, x); - }, - assertUnreachable - ); - assertAsyncRan(); - assertAsyncRan(); -})(); - -// reject/catch/finally/then -(function() { + .then(x => { + assert.equals(3, x); + }, assert.unreachable); +}, "resolve/then/finally/then"); + +testAsync(assert => { + assert.plan(2); + Promise.reject(3) .catch(x => { - assertEqualsAsync(3, x); + assert.equals(3, x); return x; }) .finally() - .then( - x => { - assertEqualsAsync(3, x); - }, - assertUnreachable - ); - assertAsyncRan(); - assertAsyncRan(); -})(); - -// resolve/finally-throw/then -(function() { + .then(x => { + assert.equals(3, x); + }, assert.unreachable); +}, "reject/catch/finally/then"); + +testAsync(assert => { + assert.plan(2); + Promise.resolve(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + print("in finally"); + assert.equals(0, arguments.length); throw 1; }) - .then(assertUnreachable, function onRejected(reason) { - assertEqualsAsync(1, reason); + .then(assert.unreachable, function onRejected(reason) { + assert.equals(1, reason); }); - assertAsyncRan(); - assertAsyncRan(); -})(); +}, "resolve/finally-throw/then"); + +testAsync(assert => { + assert.plan(2); -// reject/finally-throw/then -(function() { Promise.reject(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); throw 1; }) - .then(assertUnreachable, function onRejected(reason) { - assertEqualsAsync(1, reason); + .then(assert.unreachable, function onRejected(reason) { + assert.equals(1, reason); }); - assertAsyncRan(); - assertAsyncRan(); -})(); +}, "reject/finally-throw/then"); + +testAsync(assert => { + assert.plan(2); -// resolve/finally-return/then -(function() { Promise.resolve(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return 4; }) - .then( - x => { - assertEqualsAsync(x, 3); - }, - assertUnreachable - ); - assertAsyncRan(); - assertAsyncRan(); -})(); + .then(x => { + assert.equals(x, 3); + }, assert.unreachable); +}, "resolve/finally-return/then"); // reject/finally-return/then -(function() { +testAsync(assert => { + assert.plan(2); + Promise.reject(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return 4; }) - .then(assertUnreachable, x => { - assertEqualsAsync(x, 3); + .then(assert.unreachable, x => { + assert.equals(x, 3); }); - assertAsyncRan(); - assertAsyncRan(); -})(); +}); // reject/catch-throw/finally-throw/then -(function() { +testAsync(assert => { + assert.plan(3); + Promise.reject(3) .catch(e => { - assertEqualsAsync(3, e); + assert.equals(3, e); throw e; }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); throw 4; }) - .then(assertUnreachable, function onRejected(e) { - assertEqualsAsync(4, e); + .then(assert.unreachable, function onRejected(e) { + assert.equals(4, e); }); - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); +}); + +testAsync(assert => { + assert.plan(3); -// resolve/then-throw/finally-throw/then -(function() { Promise.resolve(3) .then(e => { - assertEqualsAsync(3, e); + assert.equals(3, e); throw e; }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); throw 4; }) - .then(assertUnreachable, function onRejected(e) { - assertEqualsAsync(4, e); + .then(assert.unreachable, function onRejected(e) { + assert.equals(4, e); }); - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); +}, "resolve/then-throw/finally-throw/then"); + +testAsync(assert => { + assert.plan(2); -// resolve/finally-return-rejected-promise/then -(function() { Promise.resolve(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return Promise.reject(4); }) - .then(assertUnreachable, e => { - assertEqualsAsync(4, e); + .then(assert.unreachable, e => { + assert.equals(4, e); }); - assertAsyncRan(); - assertAsyncRan(); -})(); +}, "resolve/finally-return-rejected-promise/then"); + +testAsync(assert => { + assert.plan(2); -// reject/finally-return-rejected-promise/then -(function() { Promise.reject(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return Promise.reject(4); }) - .then(assertUnreachable, e => { - assertEqualsAsync(4, e); + .then(assert.unreachable, e => { + assert.equals(4, e); }); - assertAsyncRan(); - assertAsyncRan(); -})(); +}, "reject/finally-return-rejected-promise/then"); + +testAsync(assert => { + assert.plan(2); -// resolve/finally-return-resolved-promise/then -(function() { Promise.resolve(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return Promise.resolve(4); }) - .then( - x => { - assertEqualsAsync(3, x); - }, - assertUnreachable - ); - assertAsyncRan(); - assertAsyncRan(); -})(); - -// reject/finally-return-resolved-promise/then -(function() { + .then(x => { + assert.equals(3, x); + }, assert.unreachable); +}, "resolve/finally-return-resolved-promise/then"); + +testAsync(assert => { + assert.plan(2); + Promise.reject(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return Promise.resolve(4); }) - .then(assertUnreachable, e => { - assertEqualsAsync(3, e); + .then(assert.unreachable, e => { + assert.equals(3, e); }); - assertAsyncRan(); - assertAsyncRan(); -})(); +}, "reject/finally-return-resolved-promise/then"); + +testAsync(assert => { + assert.plan(2); -// reject/finally-return-resolved-promise/then -(function() { Promise.reject(3) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return Promise.resolve(4); }) - .then(assertUnreachable, e => { - assertEqualsAsync(3, e); + .then(assert.unreachable, e => { + assert.equals(3, e); }); - assertAsyncRan(); - assertAsyncRan(); -})(); +}, "reject/finally-return-resolved-promise/then"); + +testAsync(assert => { + assert.plan(2); -// resolve/finally-thenable-resolve/then -(function() { var thenable = { then: function(onResolve, onReject) { onResolve(5); @@ -326,22 +247,17 @@ function assertAsyncDone(iteration) { Promise.resolve(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return thenable; }) - .then( - x => { - assertEqualsAsync(5, x); - }, - assertUnreachable - ); + .then(x => { + assert.equals(5, x); + }, assert.unreachable); +}, "resolve/finally-thenable-resolve/then"); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(2); -// reject/finally-thenable-resolve/then -(function() { var thenable = { then: function(onResolve, onReject) { onResolve(1); @@ -350,19 +266,17 @@ function assertAsyncDone(iteration) { Promise.reject(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return thenable; }) - .then(assertUnreachable, e => { - assertEqualsAsync(5, e); + .then(assert.unreachable, e => { + assert.equals(5, e); }); +}, "reject/finally-thenable-resolve/then"); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(2); -// reject/finally-thenable-reject/then -(function() { var thenable = { then: function(onResolve, onReject) { onReject(1); @@ -371,19 +285,17 @@ function assertAsyncDone(iteration) { Promise.reject(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return thenable; }) - .then(assertUnreachable, e => { - assertEqualsAsync(1, e); + .then(assert.unreachable, e => { + assert.equals(1, e); }); +}, "reject/finally-thenable-reject/then"); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(2); -// resolve/finally-thenable-reject/then -(function() { var thenable = { then: function(onResolve, onReject) { onReject(1); @@ -392,159 +304,133 @@ function assertAsyncDone(iteration) { Promise.resolve(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return thenable; }) - .then(assertUnreachable, e => { - assertEqualsAsync(1, e); + .then(assert.unreachable, e => { + assert.equals(1, e); }); +}, "resolve/finally-thenable-reject/then"); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(3); -// resolve/finally/finally/then -(function() { Promise.resolve(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); - }) - .then( - x => { - assertEqualsAsync(5, x); - }, - assertUnreachable - ); - - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); - -// resolve/finally-throw/finally/then -(function() { + assert.equals(0, arguments.length); + }) + .then(x => { + assert.equals(5, x); + }, assert.unreachable); +}, "resolve/finally/finally/then"); + +testAsync(assert => { + assert.plan(3); + Promise.resolve(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); throw 1; }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) - .then(assertUnreachable, e => { - assertEqualsAsync(1, e); + .then(assert.unreachable, e => { + assert.equals(1, e); }); +}, "resolve/finally-throw/finally/then"); - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(3); -// resolve/finally-return-rejected-promise/finally/then -(function() { Promise.resolve(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return Promise.reject(1); }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) - .then(assertUnreachable, e => { - assertEqualsAsync(1, e); + .then(assert.unreachable, e => { + assert.equals(1, e); }); +}, "resolve/finally-return-rejected-promise/finally/then"); - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(3); -// reject/finally/finally/then -(function() { Promise.reject(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) - .then(assertUnreachable, e => { - assertEqualsAsync(5, e); + .then(assert.unreachable, e => { + assert.equals(5, e); }); +}, "reject/finally/finally/then"); - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(3); -// reject/finally-throw/finally/then -(function() { Promise.reject(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); throw 1; }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) - .then(assertUnreachable, e => { - assertEqualsAsync(1, e); + .then(assert.unreachable, e => { + assert.equals(1, e); }); +}, "reject/finally-throw/finally/then"); - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(3); -// reject/finally-return-rejected-promise/finally/then -(function() { Promise.reject(5) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return Promise.reject(1); }) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) - .then(assertUnreachable, e => { - assertEqualsAsync(1, e); + .then(assert.unreachable, e => { + assert.equals(1, e); }); +}, "reject/finally-return-rejected-promise/finally/then"); - assertAsyncRan(); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(2); -// resolve/finally-deferred-resolve/then -(function() { var resolve, reject; var deferred = new Promise((x, y) => { resolve = x; reject = y; }); + Promise.resolve(1) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return deferred; }) - .then( - x => { - assertEqualsAsync(1, x); - }, - assertUnreachable - ); - - assertAsyncRan(); - assertAsyncRan(); + .then(x => { + assert.equals(1, x); + }, assert.unreachable); resolve(5); -})(); +}, "resolve/finally-deferred-resolve/then"); + +// +testAsync(assert => { + assert.plan(2); -// resolve/finally-deferred-reject/then -(function() { var resolve, reject; var deferred = new Promise((x, y) => { resolve = x; @@ -552,46 +438,38 @@ function assertAsyncDone(iteration) { }); Promise.resolve(1) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); return deferred; }) - .then(assertUnreachable, e => { - assertEqualsAsync(5, e); + .then(assert.unreachable, e => { + assert.equals(5, e); }); - assertAsyncRan(); - assertAsyncRan(); - reject(5); -})(); +}, "resolve/finally-deferred-reject/then"); + +testAsync(assert => { + assert.plan(2); -// all/finally/then -(function() { var resolve, reject; var deferred = new Promise((x, y) => { resolve = x; reject = y; }); - Promise.all([deferred]) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) - .then( - ([x]) => { - assertEqualsAsync(1, x); - }, - assertUnreachable - ); - - assertAsyncRan(); - assertAsyncRan(); + .then(([x]) => { + assert.equals(1, x); + }, assert.unreachable); resolve(1); -})(); +}, "all/finally/then"); + +testAsync(assert => { + assert.plan(2); -// race/finally/then -(function() { var resolve, reject; var d1 = new Promise((x, y) => { resolve = x; @@ -601,61 +479,48 @@ function assertAsyncDone(iteration) { resolve = x; reject = y; }); - Promise.race([d1, d2]) .finally(function onFinally() { - assertEqualsAsync(0, arguments.length); + assert.equals(0, arguments.length); }) - .then( - x => { - assertEqualsAsync(1, x); - }, - assertUnreachable - ); - - assertAsyncRan(); - assertAsyncRan(); + .then(x => { + assert.equals(1, x); + }, assert.unreachable); resolve(1); -})(); +}, "race/finally/then"); + +testAsync(assert => { + assert.plan(2); -// resolve/finally-customthen/then -(function() { class MyPromise extends Promise { - then(onFulfilled, onRejected) { - assertEqualsAsync(5, onFulfilled); - assertEqualsAsync(5, onRejected); - return super.then(onFulfilled, onRejected); - } + then(onFulfilled, onRejected) { + assert.equals(5, onFulfilled); + assert.equals(5, onRejected); + return super.then(onFulfilled, onRejected); + } } MyPromise.resolve(3).finally(5); +}, "resolve/finally-customthen/then"); - assertAsyncRan(); - assertAsyncRan(); -})(); +testAsync(assert => { + assert.plan(2); -// reject/finally-customthen/then -(function() { class MyPromise extends Promise { - then(onFulfilled, onRejected) { - assertEqualsAsync(5, onFulfilled); - assertEqualsAsync(5, onRejected); - return super.then(onFulfilled, onRejected); - } + then(onFulfilled, onRejected) { + assert.equals(5, onFulfilled); + assert.equals(5, onRejected); + return super.then(onFulfilled, onRejected); + } } MyPromise.reject(3).finally(5); +}, "reject/finally-customthen/then"); - assertAsyncRan(); - assertAsyncRan(); -})(); - -var descriptor = Object.getOwnPropertyDescriptor(Promise.prototype, 'finally'); +var descriptor = Object.getOwnPropertyDescriptor(Promise.prototype, "finally"); assertTrue(descriptor.writable); assertTrue(descriptor.configurable); assertFalse(descriptor.enumerable); assertEquals("finally", Promise.prototype.finally.name); assertEquals(1, Promise.prototype.finally.length); - -assertAsyncDone(); diff --git a/deps/v8/test/mjsunit/harmony/regexp-dotall-disabled.js b/deps/v8/test/mjsunit/harmony/regexp-dotall-disabled.js deleted file mode 100644 index 825d3842dc..0000000000 --- a/deps/v8/test/mjsunit/harmony/regexp-dotall-disabled.js +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This tests that RegExp dotall features are not enabled when -// --harmony-regexp-dotall is not passed. - -// Flags: --no-harmony-regexp-dotall - -// Construction does not throw. -{ - assertThrows("/./s", SyntaxError); - assertThrows(() => RegExp(".", "s"), SyntaxError); - assertThrows(() => new RegExp(".", "s"), SyntaxError); - assertThrows(() => new RegExp(".", "wtf"), SyntaxError); -} - -// The flags accessors. -{ - let re = /./gimyu; - assertEquals("gimuy", re.flags); - assertTrue(re.global); - assertTrue(re.ignoreCase); - assertTrue(re.multiline); - assertTrue(re.sticky); - assertTrue(re.unicode); - - assertEquals(re.dotAll, undefined); - assertFalse("dotAll" in re); - - let callCount = 0; - re.__defineGetter__("dotAll", () => { callCount++; return undefined; }); - assertEquals("gimuy", re.flags); - assertEquals(callCount, 0); -} - -// Default '.' behavior. -{ - let re = /^.$/; - assertTrue(re.test("a")); - assertTrue(re.test("3")); - assertTrue(re.test("π")); - assertTrue(re.test("\u2027")); - assertTrue(re.test("\u0085")); - assertTrue(re.test("\v")); - assertTrue(re.test("\f")); - assertTrue(re.test("\u180E")); - assertFalse(re.test("\u{10300}")); // Supplementary plane. - assertFalse(re.test("\n")); - assertFalse(re.test("\r")); - assertFalse(re.test("\u2028")); - assertFalse(re.test("\u2029")); -} - -// Default '.' behavior (unicode). -{ - let re = /^.$/u; - assertTrue(re.test("a")); - assertTrue(re.test("3")); - assertTrue(re.test("π")); - assertTrue(re.test("\u2027")); - assertTrue(re.test("\u0085")); - assertTrue(re.test("\v")); - assertTrue(re.test("\f")); - assertTrue(re.test("\u180E")); - assertTrue(re.test("\u{10300}")); // Supplementary plane. - assertFalse(re.test("\n")); - assertFalse(re.test("\r")); - assertFalse(re.test("\u2028")); - assertFalse(re.test("\u2029")); -} diff --git a/deps/v8/test/mjsunit/harmony/regexp-dotall.js b/deps/v8/test/mjsunit/harmony/regexp-dotall.js index eed5d26f05..d7b45b69f4 100644 --- a/deps/v8/test/mjsunit/harmony/regexp-dotall.js +++ b/deps/v8/test/mjsunit/harmony/regexp-dotall.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-regexp-dotall - function toSlowMode(re) { re.exec = (str) => RegExp.prototype.exec.call(re, str); return re; diff --git a/deps/v8/test/mjsunit/harmony/regexp-property-char-class.js b/deps/v8/test/mjsunit/harmony/regexp-property-char-class.js index c70e82676e..1de8acb5f2 100644 --- a/deps/v8/test/mjsunit/harmony/regexp-property-char-class.js +++ b/deps/v8/test/mjsunit/harmony/regexp-property-char-class.js @@ -9,9 +9,10 @@ assertThrows("/[\\p{garbage}]/u"); assertThrows("/[\\p{}]/u"); assertThrows("/[\\p{]/u"); assertThrows("/[\\p}]/u"); +assertThrows("/^[\\p{Lu}-\\p{Ll}]+$/u"); assertTrue(/^[\p{Lu}\p{Ll}]+$/u.test("ABCabc")); -assertTrue(/^[\p{Lu}-\p{Ll}]+$/u.test("ABC-abc")); +assertTrue(/^[\p{Lu}-]+$/u.test("ABC-")); assertFalse(/^[\P{Lu}\p{Ll}]+$/u.test("ABCabc")); assertTrue(/^[\P{Lu}\p{Ll}]+$/u.test("abc")); assertTrue(/^[\P{Lu}]+$/u.test("abc123")); diff --git a/deps/v8/test/mjsunit/hash-code.js b/deps/v8/test/mjsunit/hash-code.js new file mode 100644 index 0000000000..1a0057ff38 --- /dev/null +++ b/deps/v8/test/mjsunit/hash-code.js @@ -0,0 +1,25 @@ +// Copyright 2017 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 x = { a: 1 } + var set = new Set(); + set.add(x); + + x.b = 1; + x.c = 2; + x.d = 3; + x.e = 4; + x.f = 5; + x.g = 6; + + assertTrue(set.has(x)); +} + +f(); +f(); +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/ignition/ignition-statistics-extension.js b/deps/v8/test/mjsunit/ignition/ignition-statistics-extension.js index 18097aac5c..e10ecc3d30 100644 --- a/deps/v8/test/mjsunit/ignition/ignition-statistics-extension.js +++ b/deps/v8/test/mjsunit/ignition/ignition-statistics-extension.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: --no-stress-fullcodegen --trace-ignition-dispatches +// Flags: --trace-ignition-dispatches assertEquals(typeof getIgnitionDispatchCounters, "function"); diff --git a/deps/v8/test/mjsunit/ignition/osr-from-bytecode.js b/deps/v8/test/mjsunit/ignition/osr-from-bytecode.js index e281eca33f..a0c80f8e3b 100644 --- a/deps/v8/test/mjsunit/ignition/osr-from-bytecode.js +++ b/deps/v8/test/mjsunit/ignition/osr-from-bytecode.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 --no-stress-fullcodegen --ignition-osr +// Flags: --allow-natives-syntax --ignition-osr function f() { for (var i = 0; i < 10; i++) { diff --git a/deps/v8/test/mjsunit/ignition/print-ast.js b/deps/v8/test/mjsunit/ignition/print-ast.js new file mode 100644 index 0000000000..4a77e9a557 --- /dev/null +++ b/deps/v8/test/mjsunit/ignition/print-ast.js @@ -0,0 +1,13 @@ +// Copyright 2017 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: --print-ast + +// Ensures that the --print-ast flag doesn't crash. +function foo(a) { + var b = 2; + return function bar() { return a + b; }; +} + +foo()(); diff --git a/deps/v8/test/mjsunit/ignition/regress-599001-verifyheap.js b/deps/v8/test/mjsunit/ignition/regress-599001-verifyheap.js index 6ec9464e17..5aa2efdb36 100644 --- a/deps/v8/test/mjsunit/ignition/regress-599001-verifyheap.js +++ b/deps/v8/test/mjsunit/ignition/regress-599001-verifyheap.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: --no-stress-fullcodegen --verify-heap --expose-gc +// Flags: --verify-heap --expose-gc // Tests that verify heap works for BytecodeArrays in the large object space. diff --git a/deps/v8/test/mjsunit/ignition/regress-616064.js b/deps/v8/test/mjsunit/ignition/regress-616064.js index 27c3becf76..805de41ac5 100644 --- a/deps/v8/test/mjsunit/ignition/regress-616064.js +++ b/deps/v8/test/mjsunit/ignition/regress-616064.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: --no-stress-fullcodegen - function foo() { if (this.Worker) { function __f_0() { this.s = a; } diff --git a/deps/v8/test/mjsunit/ignition/throw-if-hole.js b/deps/v8/test/mjsunit/ignition/throw-if-hole.js index ac155e0c9c..ea3f6df605 100644 --- a/deps/v8/test/mjsunit/ignition/throw-if-hole.js +++ b/deps/v8/test/mjsunit/ignition/throw-if-hole.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: --opt --allow-natives-syntax --no-always-opt --no-stress-fullcodegen +// Flags: --opt --allow-natives-syntax --no-always-opt function f(b) { if (b == 1) { diff --git a/deps/v8/test/mjsunit/keyed-load-hole-to-undefined.js b/deps/v8/test/mjsunit/keyed-load-hole-to-undefined.js index 251bde27b2..ffac5488c0 100644 --- a/deps/v8/test/mjsunit/keyed-load-hole-to-undefined.js +++ b/deps/v8/test/mjsunit/keyed-load-hole-to-undefined.js @@ -2,8 +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 -// Flags: --no-stress-opt --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --no-stress-opt --opt --no-always-opt // --nostress-opt is specified because the test corrupts the "pristine" // array prototype chain by storing an element, and this is tracked diff --git a/deps/v8/test/mjsunit/keyed-load-with-symbol-key.js b/deps/v8/test/mjsunit/keyed-load-with-symbol-key.js index 301d4e4855..d0be0a0545 100644 --- a/deps/v8/test/mjsunit/keyed-load-with-symbol-key.js +++ b/deps/v8/test/mjsunit/keyed-load-with-symbol-key.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt var s = Symbol("foo"); diff --git a/deps/v8/test/mjsunit/large-object-literal.js b/deps/v8/test/mjsunit/large-object-literal.js index e44c05794a..8bf4debbb7 100644 --- a/deps/v8/test/mjsunit/large-object-literal.js +++ b/deps/v8/test/mjsunit/large-object-literal.js @@ -78,7 +78,7 @@ for (var i = 0; i < sizes.length; i++) { } -// Larg Object dictionary mode literal. +// Large Object dictionary mode literal. function TestSlowLiteralOptimized() { diff --git a/deps/v8/test/mjsunit/messages.js b/deps/v8/test/mjsunit/messages.js index 3281fc897d..a57e1fcf1c 100644 --- a/deps/v8/test/mjsunit/messages.js +++ b/deps/v8/test/mjsunit/messages.js @@ -73,6 +73,10 @@ test(function() { Array.prototype.shift.call(null); }, "Array.prototype.shift called on null or undefined", TypeError); +test(function() { + String.prototype.includes.call(null); +}, "String.prototype.includes called on null or undefined", TypeError); + // kCannotFreezeArrayBufferView test(function() { Object.freeze(new Uint16Array(1)); @@ -122,6 +126,11 @@ test(function() { }, "First argument to String.prototype.startsWith " + "must not be a regular expression", TypeError); +test(function() { + "a".includes(/a/); +}, "First argument to String.prototype.includes " + + "must not be a regular expression", TypeError); + // kFlagsGetterNonObject test(function() { Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get.call(1); @@ -426,12 +435,12 @@ test(function() { // kNumberFormatRange test(function() { - Number(1).toFixed(100); -}, "toFixed() digits argument must be between 0 and 20", RangeError); + Number(1).toFixed(101); +}, "toFixed() digits argument must be between 0 and 100", RangeError); test(function() { - Number(1).toExponential(100); -}, "toExponential() argument must be between 0 and 20", RangeError); + Number(1).toExponential(101); +}, "toExponential() argument must be between 0 and 100", RangeError); // kStackOverflow test(function() { @@ -441,8 +450,8 @@ test(function() { // kToPrecisionFormatRange test(function() { - Number(1).toPrecision(100); -}, "toPrecision() argument must be between 1 and 21", RangeError); + Number(1).toPrecision(101); +}, "toPrecision() argument must be between 1 and 100", RangeError); // kToPrecisionFormatRange test(function() { diff --git a/deps/v8/test/mjsunit/migrations.js b/deps/v8/test/mjsunit/migrations.js index 2bd70fb771..1828a612dc 100644 --- a/deps/v8/test/mjsunit/migrations.js +++ b/deps/v8/test/mjsunit/migrations.js @@ -278,7 +278,7 @@ var migrations = [ migr: function(o, i) { Object.seal(o); }, }, { // Must be the last in the sequence, because after the global object freeze - // the other modifications does not make sence. + // the other modifications does not make sense. name: "freeze", migr: function(o, i) { Object.freeze(o); }, }, diff --git a/deps/v8/test/mjsunit/mjsunit.js b/deps/v8/test/mjsunit/mjsunit.js index 90551f6e6f..77f8b7605b 100644 --- a/deps/v8/test/mjsunit/mjsunit.js +++ b/deps/v8/test/mjsunit/mjsunit.js @@ -80,7 +80,7 @@ var assertArrayEquals; var assertPropertiesEqual; // Assert that the string conversion of the found value is equal to -// the expected string. Only kept for backwards compatability, please +// the expected string. Only kept for backwards compatibility, please // check the real structure of the found value. var assertToStringEquals; @@ -146,7 +146,12 @@ var V8OptimizationStatus = { kMaybeDeopted: 1 << 3, kOptimized: 1 << 4, kTurboFanned: 1 << 5, - kInterpreted: 1 << 6 + kInterpreted: 1 << 6, + kMarkedForOptimization: 1 << 7, + kMarkedForConcurrentOptimization: 1 << 8, + kOptimizingConcurrently: 1 << 9, + kIsExecuting: 1 << 10, + kTopmostFrameIsTurboFanned: 1 << 11, }; // Returns true if --no-opt mode is on. @@ -167,6 +172,9 @@ var isCrankshafted; // Returns true if given function is compiled by TurboFan. var isTurboFanned; +// Used for async tests. See definition below for more documentation. +var testAsync; + // Monkey-patchable all-purpose failure handler. var failWithMessage; @@ -270,8 +278,7 @@ var failWithMessage; throw new MjsUnitAssertionError(message); } - - function fail(expectedText, found, name_opt) { + function formatFailureText(expectedText, found, name_opt) { var message = "Fail" + "ure"; if (name_opt) { // Fix this when we ditch the old test runner. @@ -284,7 +291,11 @@ var failWithMessage; } else { message += ":\nexpected:\n" + expectedText + "\nfound:\n" + foundText; } - return failWithMessage(message); + return message; + } + + function fail(expectedText, found, name_opt) { + return failWithMessage(formatFailureText(expectedText, found, name_opt)); } @@ -486,9 +497,9 @@ var failWithMessage; assertDoesNotThrow = function assertDoesNotThrow(code, name_opt) { try { if (typeof code === 'function') { - code(); + return code(); } else { - eval(code); + return eval(code); } } catch (e) { failWithMessage("threw an exception: " + (e.message || e)); @@ -706,4 +717,110 @@ var failWithMessage; return error.stack; } + /** + * This is to be used through the testAsync helper function defined + * below. + * + * This requires the --allow-natives-syntax flag to allow calling + * runtime functions. + * + * There must be at least one assertion in an async test. A test + * with no assertions will fail. + * + * @example + * testAsync(assert => { + * assert.plan(1) // There should be one assertion in this test. + * Promise.resolve(1) + * .then(val => assert.equals(1, val), + * assert.unreachable); + * }) + */ + class AsyncAssertion { + constructor(test, name) { + this.expectedAsserts_ = -1; + this.actualAsserts_ = 0; + this.test_ = test; + this.name_ = name || ''; + } + + /** + * Sets the number of expected asserts in the test. The test fails + * if the number of asserts computed after running the test is not + * equal to this specified value. + * @param {number} expectedAsserts + */ + plan(expectedAsserts) { + this.expectedAsserts_ = expectedAsserts; + } + + fail(expectedText, found) { + let message = formatFailureText(expectedText, found); + message += "\nin test:" + this.name_ + message += "\n" + Function.prototype.toString.apply(this.test_); + eval("%AbortJS(message)"); + } + + equals(expected, found, name_opt) { + this.actualAsserts_++; + if (!deepEquals(expected, found)) { + this.fail(PrettyPrint(expected), found, name_opt); + } + } + + unreachable() { + let message = "Failure: unreachable in test: " + this.name_; + message += "\n" + Function.prototype.toString.apply(this.test_); + eval("%AbortJS(message)"); + } + + unexpectedRejection(details) { + return (error) => { + let message = + "Failure: unexpected Promise rejection in test: " + this.name_; + if (details) message += "\n @" + details; + if (error instanceof Error) { + message += "\n" + String(error.stack); + } else { + message += "\n" + String(error); + } + message += "\n\n" + Function.prototype.toString.apply(this.test_); + eval("%AbortJS(message)"); + }; + } + + drainMicrotasks() { + eval("%RunMicrotasks()"); + } + + done_() { + if (this.expectedAsserts_ === -1) { + let message = "Please call t.plan(count) to initialize test harness " + + "with correct assert count (Note: count > 0)"; + eval("%AbortJS(message)"); + } + + if (this.expectedAsserts_ !== this.actualAsserts_) { + let message = "Expected asserts: " + this.expectedAsserts_; + message += ", Actual asserts: " + this.actualAsserts_; + message += "\nin test: " + this.name_; + message += "\n" + Function.prototype.toString.apply(this.test_); + eval("%AbortJS(message)"); + } + } + } + + /** This is used to test async functions and promises. + * @param {testCallback} test - test function + * @param {string} [name] - optional name of the test + * + * + * @callback testCallback + * @param {AsyncAssertion} assert + */ + testAsync = function(test, name) { + let assert = new AsyncAssertion(test, name); + test(assert); + eval("%RunMicrotasks()"); + assert.done_(); + } })(); diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index d9ee246026..4f49fdd595 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/deps/v8/test/mjsunit/mjsunit.status @@ -91,6 +91,10 @@ 'regress/regress-crbug-482998': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]], 'regress/regress-740784': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]], + # This test allocates a 2G block of memory and if there are multiple + # variants this can lead to OOM. + 'regress/regress-crbug-514081': [PASS, NO_VARIANTS], + ############################################################################## # Skip long running tests that time out in debug mode. 'generated-transition-stub': [PASS, ['mode == debug', SKIP]], @@ -178,8 +182,8 @@ # BUG(v8:6306). 'wasm/huge-memory': [SKIP], - # BUG(v8:6577). - 'wasm/exceptions': [SKIP], + # Allocates a huge string and then flattens it, very slow in debug mode. + 'regress/regress-752764': [PASS, ['mode == debug', SLOW]], }], # ALWAYS ['novfp3 == True', { @@ -248,6 +252,9 @@ # BUG(v8:4779): Crashes flakily with stress mode on arm64. 'array-splice': [PASS, SLOW, ['arch == arm64', FAST_VARIANTS]], + + # BUG(chromium:751825): Crashes flakily. + 'wasm/js-api': [SKIP], }], # 'gc_stress == True' ############################################################################## @@ -421,6 +428,7 @@ 'regress/regress-91008': [PASS, SLOW], 'regress/regress-json-stringify-gc': [PASS, SLOW], 'string-indexof-2': [PASS, SLOW], + 'wasm/atomics': [PASS, SLOW], }], # 'arch == arm or arch == android_arm' ############################################################################## @@ -546,7 +554,6 @@ ['deopt_fuzzer == True', { # Skip tests that are not suitable for deoptimization fuzzing. - 'assert-opt-and-deopt': [SKIP], 'never-optimize': [SKIP], 'regress/regress-2185-2': [SKIP], 'readonly': [SKIP], @@ -578,6 +585,7 @@ # take too long with the simulator. 'regress/regress-1132': [SKIP], + 'regress/regress-740784': [PASS, SLOW], }], # 'arch == ppc and simulator_run' ############################################################################## @@ -589,9 +597,11 @@ }], # 'arch == ppc64' ############################################################################## -['variant == fullcode', { - 'es6/array-iterator-turbo': [SKIP], -}], # variant == nocranshaft +['arch == ppc64 or arch == ppc or arch == s390 or arch == s390x', { + + # TODO(ppc/s390): implement atomic operations + 'wasm/atomics': [SKIP], +}], # 'arch == ppc64 or arch == ppc or arch == s390 or arch == s390x' ############################################################################## ['variant == stress', { @@ -646,13 +656,4 @@ 'mjsunit-assertion-error' : [SKIP], }], # no_harness -############################################################################## -# This test allocates a 2G block of memory and if there are multiple -# varients this leads kills by the OOM killer, crashes or messages -# indicating the OS cannot allocate memory, exclude for Node.js runs -# re-evalute when we move up to v8 5.1 -[ALWAYS, { -'regress/regress-crbug-514081': [PASS, NO_VARIANTS], -}], # ALWAYS - ] diff --git a/deps/v8/test/mjsunit/modules-init4.js b/deps/v8/test/mjsunit/modules-init4.js new file mode 100644 index 0000000000..6b9e47726c --- /dev/null +++ b/deps/v8/test/mjsunit/modules-init4.js @@ -0,0 +1,8 @@ +// Copyright 2017 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 "./modules-skip-init4a.js" +export {foo, ns} from "./modules-skip-init4b.js" diff --git a/deps/v8/test/mjsunit/modules-skip-init4a.js b/deps/v8/test/mjsunit/modules-skip-init4a.js new file mode 100644 index 0000000000..66f4e8276b --- /dev/null +++ b/deps/v8/test/mjsunit/modules-skip-init4a.js @@ -0,0 +1,8 @@ +// Copyright 2017 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. + +import {foo, ns} from "./modules-init4.js" +assertEquals(foo(), 42) +assertEquals(ns.foo(), 42) +assertSame(foo, ns.foo) diff --git a/deps/v8/test/mjsunit/modules-skip-init4b.js b/deps/v8/test/mjsunit/modules-skip-init4b.js new file mode 100644 index 0000000000..502c93b8f4 --- /dev/null +++ b/deps/v8/test/mjsunit/modules-skip-init4b.js @@ -0,0 +1,7 @@ +// Copyright 2017 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. + +import * as ns from "./modules-skip-init4b.js" +export function foo() { return 42 } +export {ns} diff --git a/deps/v8/test/mjsunit/never-baseline.js b/deps/v8/test/mjsunit/never-baseline.js deleted file mode 100644 index 8be55d24a4..0000000000 --- a/deps/v8/test/mjsunit/never-baseline.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 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 --no-stress-fullcodegen - -function f(a, b) { - %DeoptimizeNow(); - return a + b; -} - -// Go through enough optimization and deoptimization cycles in order for the -// function {f} to be marked as optimization disabled. -for (var i = 0; i < 16; ++i) { - %OptimizeFunctionOnNextCall(f); - f(1, 2); -} - -// Make the runtime profiler perceive {f} as hot again and then verify that we -// didn't trigger an unintentional baseline compilation. -for (var i = 0; i < 100000; ++i) { - f(1, 2); -} -assertTrue(isInterpreted(f)); diff --git a/deps/v8/test/mjsunit/object-define-property.js b/deps/v8/test/mjsunit/object-define-property.js index 1aac489839..cc9c0b79a6 100644 --- a/deps/v8/test/mjsunit/object-define-property.js +++ b/deps/v8/test/mjsunit/object-define-property.js @@ -1014,7 +1014,7 @@ for (var i = 0; i < 1000; i++) { assertEquals(999, o[999]); -// Regression test: Bizzare behavior on non-strict arguments object. +// Regression test: Bizarre behavior on non-strict arguments object. // TODO(yangguo): Tests disabled, needs investigation! /* (function test(arg0) { diff --git a/deps/v8/test/mjsunit/object-seal.js b/deps/v8/test/mjsunit/object-seal.js index 1a3a555535..f685b41927 100644 --- a/deps/v8/test/mjsunit/object-seal.js +++ b/deps/v8/test/mjsunit/object-seal.js @@ -28,7 +28,7 @@ // Tests the Object.seal and Object.isSealed methods - ES 19.1.2.17 and // ES 19.1.2.13 -// Flags: --allow-natives-syntax --opt --noalways-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --noalways-opt // Test that we return obj if non-object is passed as argument var non_objects = new Array(undefined, null, 1, -1, 0, 42.43, Symbol("test")); diff --git a/deps/v8/test/mjsunit/optimized-foreach.js b/deps/v8/test/mjsunit/optimized-foreach.js index a6e4341420..f3513f3838 100644 --- a/deps/v8/test/mjsunit/optimized-foreach.js +++ b/deps/v8/test/mjsunit/optimized-foreach.js @@ -4,7 +4,7 @@ // Flags: --allow-natives-syntax --expose-gc --turbo-inline-array-builtins -var a = [0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,0,0]; +var a = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,0,0]; var b = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; @@ -217,15 +217,47 @@ var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; lazyDeopt(); })(); +// Call to a.forEach is done inside a try-catch block and the callback function +// being called throws into a deoptimized caller function. +(function TestThrowIntoDeoptimizedOuter() { + var a = [1,2,3,4]; + var lazyDeopt = function(deopt) { + var sum = function(v,i,o) { + result += v; + if (i == 1 && deopt) { + %DeoptimizeFunction(lazyDeopt); + throw "some exception"; + } + }; + %NeverOptimizeFunction(sum); + var result = 0; + try { + a.forEach(sum); + } catch (e) { + assertEquals("some exception", e) + result += 100; + } + return result; + } + assertEquals(10, lazyDeopt(false)); + assertEquals(10, lazyDeopt(false)); + assertEquals(103, lazyDeopt(true)); + assertEquals(103, lazyDeopt(true)); + %OptimizeFunctionOnNextCall(lazyDeopt); + assertEquals(10, lazyDeopt(false)); + assertEquals(103, lazyDeopt(true)); +})(); + (function() { var re = /Array\.forEach/; - var lazyDeopt = function(deopt) { + var lazyDeopt = function foobar(deopt) { var b = [1,2,3]; var result = 0; var sum = function(v,i,o) { result += v; if (i == 1) { var e = new Error(); + print(e.stack); assertTrue(re.exec(e.stack) !== null); } }; diff --git a/deps/v8/test/mjsunit/optimized-map.js b/deps/v8/test/mjsunit/optimized-map.js index c53d77b61b..55a87bb5df 100644 --- a/deps/v8/test/mjsunit/optimized-map.js +++ b/deps/v8/test/mjsunit/optimized-map.js @@ -3,9 +3,9 @@ // found in the LICENSE file. // Flags: --allow-natives-syntax --expose-gc --turbo-inline-array-builtins -// Flags: --opt --no-always-opt --no-stress-fullcodegen +// Flags: --opt --no-always-opt -var a = [0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,0,0]; +var a = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,0,0]; var b = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; @@ -227,6 +227,37 @@ var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; lazyDeopt(); })(); +// Call to a.map is done inside a try-catch block and the callback function +// being called throws into a deoptimized caller function. +(function TestThrowIntoDeoptimizedOuter() { + var a = [1,2,3,4]; + var lazyDeopt = function(deopt) { + var callback = function(v,i,o) { + if (i == 1 && deopt) { + %DeoptimizeFunction(lazyDeopt); + throw "some exception"; + } + return 2 * v; + }; + %NeverOptimizeFunction(callback); + var result = 0; + try { + result = a.map(callback); + } catch (e) { + assertEquals("some exception", e) + result = "nope"; + } + return result; + } + assertEquals([2,4,6,8], lazyDeopt(false)); + assertEquals([2,4,6,8], lazyDeopt(false)); + assertEquals("nope", lazyDeopt(true)); + assertEquals("nope", lazyDeopt(true)); + %OptimizeFunctionOnNextCall(lazyDeopt); + assertEquals([2,4,6,8], lazyDeopt(false)); + assertEquals("nope", lazyDeopt(true)); +})(); + (function() { var re = /Array\.map/; var lazyDeopt = function(deopt) { @@ -336,13 +367,10 @@ var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; if (i < 5) { // First transition the output array to PACKED_DOUBLE_ELEMENTS. return v + 0.5; - } else if (i < 10) { + } else { // Then return smi values and make sure they can live in the double // array. return v; - } else { - // Later, to PACKED_ELEMENTS. - return v + 'hello'; } } return c.map(callback); @@ -351,11 +379,42 @@ var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; to_double(); %OptimizeFunctionOnNextCall(to_double); var output = to_double(); + assertTrue(%HasDoubleElements(output)); + assertEquals(1.5, output[0]); + assertEquals(6, output[5]); assertEquals(975, result); - assertEquals("11hello", output[10]); assertOptimized(to_double); })(); +(function() { + var result = 0; + var to_fast = function() { + var callback = function(v,i,o) { + result += v; + if (i < 5) { + // First transition the output array to PACKED_DOUBLE_ELEMENTS. + return v + 0.5; + } else if (i < 10) { + // Then return smi values and make sure they can live in the double + // array. + return v; + } else { + // Later, to PACKED_ELEMENTS. + return v + 'hello'; + } + } + return c.map(callback); + } + to_fast(); + to_fast(); + %OptimizeFunctionOnNextCall(to_fast); + var output = to_fast(); + %HasObjectElements(output); + assertEquals(975, result); + assertEquals("11hello", output[10]); + assertOptimized(to_fast); +})(); + // Messing with the Array species constructor causes deoptimization. (function() { var result = 0; diff --git a/deps/v8/test/mjsunit/parse-tasks.js b/deps/v8/test/mjsunit/parse-tasks.js deleted file mode 100644 index 11b48ebe0e..0000000000 --- a/deps/v8/test/mjsunit/parse-tasks.js +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 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: --compiler-dispatcher --use-parse-tasks --use-external-strings - -(function(a) { - assertEquals(a, "IIFE"); -})("IIFE"); - -(function(a, ...rest) { - assertEquals(a, 1); - assertEquals(rest.length, 2); - assertEquals(rest[0], 2); - assertEquals(rest[1], 3); -})(1,2,3); - -var outer_var = 42; - -function lazy_outer() { - return 42; -} - -var eager_outer = (function() { return 42; }); - -(function() { - assertEquals(outer_var, 42); - assertEquals(lazy_outer(), 42); - assertEquals(eager_outer(), 42); -})(); - -var gen = (function*() { - yield 1; - yield 2; -})(); - -assertEquals(gen.next().value, 1); -assertEquals(gen.next().value, 2); - -var result = (function recursive(a=0) { - if (a == 1) { - return 42; - } - return recursive(1); -})(); - -assertEquals(result, 42); - -var a = 42; -var b; -var c = (a, b = (function z(){ return a+1; })()); -assertEquals(b, 43); -assertEquals(c, 43); -var c = (a, b = (function z(){ return a+1; })()) => { return b; }; -assertEquals(c(314), 315); diff --git a/deps/v8/test/mjsunit/regress/regress-1708.js b/deps/v8/test/mjsunit/regress/regress-1708.js index ed2ddb1458..a2937750d7 100644 --- a/deps/v8/test/mjsunit/regress/regress-1708.js +++ b/deps/v8/test/mjsunit/regress/regress-1708.js @@ -57,7 +57,7 @@ assertEquals(50, array.length); // At this point "array" should have been trimmed from the left with - // marking bits being correctly transfered to the new object start. + // marking bits being correctly transferred to the new object start. // Scavenging operations cause concurrent sweeping to advance and verify // that marking bit patterns are still sane. for (var i = 0; i < 200; i++) { diff --git a/deps/v8/test/mjsunit/regress/regress-2595.js b/deps/v8/test/mjsunit/regress/regress-2595.js index 5bb5f6d16a..c7e95711a8 100644 --- a/deps/v8/test/mjsunit/regress/regress-2595.js +++ b/deps/v8/test/mjsunit/regress/regress-2595.js @@ -39,7 +39,7 @@ function F(x) { } // First make CALL IC in F go MEGAMORPHIC and ensure that we put the stub -// that calls p.f (guarded by a negative dictionary lookup on the reciever) +// that calls p.f (guarded by a negative dictionary lookup on the receiver) // into the stub cache assertEquals("p", F(o)); assertEquals("p", F(o)); diff --git a/deps/v8/test/mjsunit/regress/regress-2618.js b/deps/v8/test/mjsunit/regress/regress-2618.js index 10ed81f0be..437401e487 100644 --- a/deps/v8/test/mjsunit/regress/regress-2618.js +++ b/deps/v8/test/mjsunit/regress/regress-2618.js @@ -26,17 +26,26 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --use-osr --allow-natives-syntax --ignition-osr --opt +// Flags: --no-always-opt + +// Can't OSR with always-opt. +assertFalse(isAlwaysOptimize()); function f() { do { do { for (var i = 0; i < 10; i++) %OptimizeOsr(); + // Note: this check can't be wrapped in a function, because + // calling that function causes a deopt from lack of call + // feedback. + var opt_status = %GetOptimizationStatus(f); + assertTrue( + (opt_status & V8OptimizationStatus.kTopmostFrameIsTurboFanned) !== 0); } while (false); } while (false); } f(); -assertTrue(%GetOptimizationCount(f) > 0); function g() { for (var i = 0; i < 1; i++) { } @@ -56,6 +65,9 @@ function g() { do { do { for (var i = 0; i < 10; i++) %OptimizeOsr(); + var opt_status = %GetOptimizationStatus(g); + assertTrue((opt_status + & V8OptimizationStatus.kTopmostFrameIsTurboFanned) !== 0); } while (false); } while (false); } while (false); @@ -67,4 +79,3 @@ function g() { } g(); -assertTrue(%GetOptimizationCount(g) > 0); diff --git a/deps/v8/test/mjsunit/regress/regress-336820.js b/deps/v8/test/mjsunit/regress/regress-336820.js index f305626596..56d88747fb 100644 --- a/deps/v8/test/mjsunit/regress/regress-336820.js +++ b/deps/v8/test/mjsunit/regress/regress-336820.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: --max-old-space-size=400 +// Flags: --max-old-space-size=1600 assertThrows((function() { s = "Hello World!\n"; diff --git a/deps/v8/test/mjsunit/regress/regress-347914.js b/deps/v8/test/mjsunit/regress/regress-347914.js index 0137397cf2..170a4f8b52 100644 --- a/deps/v8/test/mjsunit/regress/regress-347914.js +++ b/deps/v8/test/mjsunit/regress/regress-347914.js @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --debug-code --gc-interval=201 --verify-heap --max-inlined-source-size=999999 --max-inlined-nodes=999999 --max-inlined-nodes-cumulative=999999 +// Flags: --allow-natives-syntax --debug-code --gc-interval=201 --verify-heap +// Flags: --max-inlined-bytecode-size=999999 --max-inlined-bytecode-size-cumulative=999999 // Flags: --opt --no-always-opt // Begin stripped down and modified version of mjsunit.js for easy minimization in CF. diff --git a/deps/v8/test/mjsunit/regress/regress-3650-3.js b/deps/v8/test/mjsunit/regress/regress-3650-3.js index 83a030c806..6195b12441 100644 --- a/deps/v8/test/mjsunit/regress/regress-3650-3.js +++ b/deps/v8/test/mjsunit/regress/regress-3650-3.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 --opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt function foo(a) { for (var d in a) { diff --git a/deps/v8/test/mjsunit/regress/regress-3709.js b/deps/v8/test/mjsunit/regress/regress-3709.js index 9ce484973e..ecb906a908 100644 --- a/deps/v8/test/mjsunit/regress/regress-3709.js +++ b/deps/v8/test/mjsunit/regress/regress-3709.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt function getobj() { return { bar : function() { return 0}}; diff --git a/deps/v8/test/mjsunit/regress/regress-3718.js b/deps/v8/test/mjsunit/regress/regress-3718.js index 26d96d448d..ec180bc3ef 100644 --- a/deps/v8/test/mjsunit/regress/regress-3718.js +++ b/deps/v8/test/mjsunit/regress/regress-3718.js @@ -18,4 +18,5 @@ assertEquals("String", getTypeName("")); assertEquals("Boolean", getTypeName(false)); assertEquals("Object", getTypeName({})); assertEquals("Array", getTypeName([])); +assertEquals("Proxy", getTypeName(new Proxy({},{}))); assertEquals("Custom", getTypeName(new (function Custom(){})())); diff --git a/deps/v8/test/mjsunit/regress/regress-385565.js b/deps/v8/test/mjsunit/regress/regress-385565.js index 9004dde90a..541e461d96 100644 --- a/deps/v8/test/mjsunit/regress/regress-385565.js +++ b/deps/v8/test/mjsunit/regress/regress-385565.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 --opt --no-always-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --no-always-opt var calls = 0; diff --git a/deps/v8/test/mjsunit/regress/regress-394.js b/deps/v8/test/mjsunit/regress/regress-394.js index 7b98205b3d..1537483918 100644 --- a/deps/v8/test/mjsunit/regress/regress-394.js +++ b/deps/v8/test/mjsunit/regress/regress-394.js @@ -37,8 +37,8 @@ function getx(){ setx() setx() -__defineSetter__('x',function(){}); -__defineGetter__('x',function(){return 2;}); +this.__defineSetter__('x',function(){}); +this.__defineGetter__('x',function(){return 2;}); setx() assertEquals(2, x); diff --git a/deps/v8/test/mjsunit/regress/regress-5252.js b/deps/v8/test/mjsunit/regress/regress-5252.js index 91cb53cd13..41f3feeec2 100644 --- a/deps/v8/test/mjsunit/regress/regress-5252.js +++ b/deps/v8/test/mjsunit/regress/regress-5252.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 --no-stress-fullcodegen --ignition-osr +// Flags: --allow-natives-syntax --ignition-osr (function TestNonLoopyLoop() { function f() { diff --git a/deps/v8/test/mjsunit/regress/regress-5262.js b/deps/v8/test/mjsunit/regress/regress-5262.js index 186ed054e3..06932a2f0f 100644 --- a/deps/v8/test/mjsunit/regress/regress-5262.js +++ b/deps/v8/test/mjsunit/regress/regress-5262.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: --no-stress-fullcodegen --ignition-osr --allow-natives-syntax +// Flags: --ignition-osr --allow-natives-syntax function g() { return 23 } function h() { return 42 } diff --git a/deps/v8/test/mjsunit/regress/regress-5404.js b/deps/v8/test/mjsunit/regress/regress-5404.js index 72c5d30fe3..eddd1837a8 100644 --- a/deps/v8/test/mjsunit/regress/regress-5404.js +++ b/deps/v8/test/mjsunit/regress/regress-5404.js @@ -13,9 +13,9 @@ foo("a"); %OptimizeFunctionOnNextCall(foo); foo("a"); -var a = "a".repeat(268435440); -assertThrows(function() { foo(a); }); +var a = "a".repeat(%StringMaxLength()); +assertThrows(function() { foo(a); }, RangeError); %OptimizeFunctionOnNextCall(foo); -assertThrows(function() { foo(a); }); +assertThrows(function() { foo(a); }, RangeError); assertOptimized(foo); diff --git a/deps/v8/test/mjsunit/regress/regress-605470.js b/deps/v8/test/mjsunit/regress/regress-605470.js index 58e87fc27f..8c9de85957 100644 --- a/deps/v8/test/mjsunit/regress/regress-605470.js +++ b/deps/v8/test/mjsunit/regress/regress-605470.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: --no-stress-fullcodegen - function function_with_m_args(m) { var source = '(function f() { return; })('; for (var arg = 0; arg < m ; arg++) { diff --git a/deps/v8/test/mjsunit/regress/regress-618657.js b/deps/v8/test/mjsunit/regress/regress-618657.js index 9bb98d6e63..e1e89d5b8f 100644 --- a/deps/v8/test/mjsunit/regress/regress-618657.js +++ b/deps/v8/test/mjsunit/regress/regress-618657.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: --no-stress-fullcodegen - function* foo() { yield 42 } function* goo() { yield 42 } var f = foo(); diff --git a/deps/v8/test/mjsunit/regress/regress-6288.js b/deps/v8/test/mjsunit/regress/regress-6288.js index eb8e735920..337af54c1a 100644 --- a/deps/v8/test/mjsunit/regress/regress-6288.js +++ b/deps/v8/test/mjsunit/regress/regress-6288.js @@ -4,7 +4,7 @@ // Environment Variables: LC_ALL=pt-BR.UTF8 -// The data files packaged with d8 currently have Brazillian Portugese +// The data files packaged with d8 currently have Brazillian Portuguese // DateTimeFormat but not Collation if (this.Intl) { diff --git a/deps/v8/test/mjsunit/regress/regress-632289.js b/deps/v8/test/mjsunit/regress/regress-632289.js index 3c982d24b7..e216035ab9 100644 --- a/deps/v8/test/mjsunit/regress/regress-632289.js +++ b/deps/v8/test/mjsunit/regress/regress-632289.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: --no-stress-fullcodegen --always-opt --allow-natives-syntax +// Flags: --always-opt --allow-natives-syntax try { } catch(e) {; } diff --git a/deps/v8/test/mjsunit/regress/regress-639270.js b/deps/v8/test/mjsunit/regress/regress-639270.js index 9a01b8dfeb..731175dcfc 100644 --- a/deps/v8/test/mjsunit/regress/regress-639270.js +++ b/deps/v8/test/mjsunit/regress/regress-639270.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 --es-staging --no-stress-fullcodegen +// Flags: --allow-natives-syntax --es-staging "use strict"; diff --git a/deps/v8/test/mjsunit/regress/regress-653407.js b/deps/v8/test/mjsunit/regress/regress-653407.js index cca332c22b..66d537ee55 100644 --- a/deps/v8/test/mjsunit/regress/regress-653407.js +++ b/deps/v8/test/mjsunit/regress/regress-653407.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 --no-stress-fullcodegen +// Flags: --allow-natives-syntax // This is to test if 'this' gets correctly initialized when inlining // constructors in turbofan. diff --git a/deps/v8/test/mjsunit/regress/regress-655573.js b/deps/v8/test/mjsunit/regress/regress-655573.js index 31f8ffe32d..967ab31f01 100644 --- a/deps/v8/test/mjsunit/regress/regress-655573.js +++ b/deps/v8/test/mjsunit/regress/regress-655573.js @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Flags: --no-always-opt --no-stress-opt + // Generate a function with a very large closure. source = "(function() {\n" for (var i = 0; i < 65000; i++) { diff --git a/deps/v8/test/mjsunit/regress/regress-6677.js b/deps/v8/test/mjsunit/regress/regress-6677.js new file mode 100644 index 0000000000..2898c8f6a6 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-6677.js @@ -0,0 +1,27 @@ +// Copyright 2017 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. + +// Assignment to const variable inside with-statement should fail. +const x = 0; +assertThrows(() => { with ({}) { x = 1; } }, TypeError); +assertEquals(0, x); + +assertThrows(() => { with ({}) { eval("x = 1"); } }, TypeError); +assertEquals(0, x); + +// Assignment to name of named function expression inside with-statement +// should not throw (but also not succeed). +assertEquals('function', function f() { + with ({}) { f = 1 } + return typeof f; +}()); + +// But we should throw an exception if the assignment is itself in strict +// code. +assertEquals('function', function f() { + with ({}) { + assertThrows(function() { "use strict"; f = 1 }, TypeError); + } + return typeof f; +}()); diff --git a/deps/v8/test/mjsunit/regress/regress-6681.js b/deps/v8/test/mjsunit/regress/regress-6681.js new file mode 100644 index 0000000000..d35ae41ffb --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-6681.js @@ -0,0 +1,10 @@ +// Copyright 2017 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 * as ns from "./regress-6681.js"; +export var foo; + +assertEquals(false, Reflect.defineProperty(ns, 'foo', {value: 123})); diff --git a/deps/v8/test/mjsunit/regress/regress-6700.js b/deps/v8/test/mjsunit/regress/regress-6700.js new file mode 100644 index 0000000000..342cac485e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-6700.js @@ -0,0 +1,90 @@ +// Copyright 2017 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 TestLeftRight() { + function Module(stdlib, foreign, heap) { + "use asm"; + var HEAP32 = new stdlib.Int32Array(heap); + function f(i) { + i = i | 0; + return HEAP32[i << 2 >> 2] | 0; + } + return { f:f } + } + var buffer = new ArrayBuffer(1024); + var module = new Module(this, {}, buffer); + assertTrue(%IsAsmWasmCode(Module)); + new Int32Array(buffer)[42] = 23; + assertEquals(23, module.f(42)); +})(); + +(function TestRightRight() { + function Module(stdlib, foreign, heap) { + "use asm"; + var HEAP32 = new stdlib.Int32Array(heap); + function f(i) { + i = i | 0; + return HEAP32[i >> 2 >> 2] | 0; + } + return { f:f } + } + var buffer = new ArrayBuffer(1024); + var module = new Module(this, {}, buffer) + assertTrue(%IsAsmWasmCode(Module)); + new Int32Array(buffer)[42 >> 4] = 23; + assertEquals(23, module.f(42)); +})(); + +(function TestRightLeft() { + function Module(stdlib, foreign, heap) { + "use asm"; + var HEAP32 = new stdlib.Int32Array(heap); + function f(i) { + i = i | 0; + return HEAP32[i >> 2 << 2] | 0; + } + return { f:f } + } + var buffer = new ArrayBuffer(1024); + var module = new Module(this, {}, buffer) + assertFalse(%IsAsmWasmCode(Module)); + new Int32Array(buffer)[42 & 0xfc] = 23; + assertEquals(23, module.f(42)); +})(); + +(function TestRightButNotImmediate() { + function Module(stdlib, foreign, heap) { + "use asm"; + var HEAP32 = new stdlib.Int32Array(heap); + function f(i) { + i = i | 0; + return HEAP32[i >> 2 + 1] | 0; + } + return { f:f } + } + var buffer = new ArrayBuffer(1024); + var module = new Module(this, {}, buffer) + assertFalse(%IsAsmWasmCode(Module)); + new Int32Array(buffer)[42 >> 3] = 23; + assertEquals(23, module.f(42)); +})(); + +(function TestLeftOnly() { + function Module(stdlib, foreign, heap) { + "use asm"; + var HEAP32 = new stdlib.Int32Array(heap); + function f(i) { + i = i | 0; + return HEAP32[i << 2] | 0; + } + return { f:f } + } + var buffer = new ArrayBuffer(1024); + var module = new Module(this, {}, buffer) + assertFalse(%IsAsmWasmCode(Module)); + new Int32Array(buffer)[42 << 2] = 23; + assertEquals(23, module.f(42)); +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-6707.js b/deps/v8/test/mjsunit/regress/regress-6707.js new file mode 100644 index 0000000000..1a8984a7c9 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-6707.js @@ -0,0 +1,13 @@ +// Copyright 2017 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 a = [0, 1]; +a.constructor = { + [Symbol.species]: function(len) { + var arr = {length: 0}; + Object.defineProperty(arr, "length", {writable: false}); + return arr; + } +} +assertThrows(() => { Array.prototype.concat.call(a) }, TypeError); diff --git a/deps/v8/test/mjsunit/regress/regress-6708.js b/deps/v8/test/mjsunit/regress/regress-6708.js new file mode 100644 index 0000000000..06b6835795 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-6708.js @@ -0,0 +1,12 @@ +// Copyright 2017 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 a = [0, 1]; +a.constructor = { + [Symbol.species]: function(len) { + var arr = Array(20); + return arr; + } +}; +assertEquals([0, 1], Array.prototype.concat.call(a)); diff --git a/deps/v8/test/mjsunit/regress/regress-6733.js b/deps/v8/test/mjsunit/regress/regress-6733.js new file mode 100644 index 0000000000..76a6911df1 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-6733.js @@ -0,0 +1,22 @@ +// Copyright 2017 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. + +let x; +Realm.eval(Realm.current(), "let y"); +assertFalse(delete x); +assertFalse(delete y); +assertFalse(eval("delete x")); +assertFalse(eval("delete y")); + +(function() { + let z; + assertFalse(delete x); + assertFalse(delete y); + assertFalse(delete z); + assertFalse(eval("delete x")); + assertFalse(eval("delete y")); + assertFalse(eval("delete z")); +})(); + +assertFalse(eval("let z; delete z")); diff --git a/deps/v8/test/mjsunit/regress/regress-677685.js b/deps/v8/test/mjsunit/regress/regress-677685.js index bb7754c1af..59076a92bd 100644 --- a/deps/v8/test/mjsunit/regress/regress-677685.js +++ b/deps/v8/test/mjsunit/regress/regress-677685.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: --no-stress-fullcodegen --stack-size=100 +// Flags: --stack-size=100 function Module(stdlib) { "use asm"; diff --git a/deps/v8/test/mjsunit/regress/regress-678917.js b/deps/v8/test/mjsunit/regress/regress-678917.js index cb88ead5ba..0e302e58d2 100644 --- a/deps/v8/test/mjsunit/regress/regress-678917.js +++ b/deps/v8/test/mjsunit/regress/regress-678917.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: --max-old-space-size=400 +// Flags: --max-old-space-size=1600 s1 = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; s1 += s1; diff --git a/deps/v8/test/mjsunit/regress/regress-718891.js b/deps/v8/test/mjsunit/regress/regress-718891.js index 60ce380e01..209568dca3 100644 --- a/deps/v8/test/mjsunit/regress/regress-718891.js +++ b/deps/v8/test/mjsunit/regress/regress-718891.js @@ -20,7 +20,7 @@ function TestDontSelfHealWithDeoptedCode(run_unoptimized, ClosureFactory) { unoptimized_closure(); } - // Run and optimize the code (do this in a seperate function + // Run and optimize the code (do this in a separate function // so that the closure doesn't leak in a dead register). (() => { var optimized_closure = ClosureFactory(); diff --git a/deps/v8/test/mjsunit/regress/regress-746909.js b/deps/v8/test/mjsunit/regress/regress-746909.js new file mode 100644 index 0000000000..e3bd224908 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-746909.js @@ -0,0 +1,8 @@ +// Copyright 2017 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-dynamic-import + +eval(`import('modules-skip-2.js');`); +eval(`eval(import('modules-skip-2.js'));`); diff --git a/deps/v8/test/mjsunit/regress/regress-748069.js b/deps/v8/test/mjsunit/regress/regress-748069.js new file mode 100644 index 0000000000..e652cca672 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-748069.js @@ -0,0 +1,12 @@ +// Copyright 2017 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. + +try { + var a = 'a'.repeat(1 << 28); +} catch (e) { + // If the allocation fails, we don't care, because we can't cause the + // overflow. +} +// Cause an overflow in worst-case calculation for string replacement. +JSON.stringify(a); diff --git a/deps/v8/test/mjsunit/regress/regress-751789.js b/deps/v8/test/mjsunit/regress/regress-751789.js new file mode 100644 index 0000000000..049acd71a8 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-751789.js @@ -0,0 +1,5 @@ +// Copyright 2017 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. + +assertThrows(() => eval('async A=>{s.await i}')); diff --git a/deps/v8/test/mjsunit/regress/regress-752764.js b/deps/v8/test/mjsunit/regress/regress-752764.js new file mode 100644 index 0000000000..4963089d0c --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-752764.js @@ -0,0 +1,8 @@ +// Copyright 2017 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 + +a = "a".repeat(%StringMaxLength() - 3); +assertThrows(() => new RegExp("a" + a), SyntaxError); diff --git a/deps/v8/test/mjsunit/regress/regress-756608.js b/deps/v8/test/mjsunit/regress/regress-756608.js new file mode 100644 index 0000000000..50377bec28 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-756608.js @@ -0,0 +1,7 @@ +// Copyright 2017 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. + +assertThrows(function() { + 'foo' in new Proxy({}, {has: 0}); +}, TypeError); diff --git a/deps/v8/test/mjsunit/regress/regress-758763.js b/deps/v8/test/mjsunit/regress/regress-758763.js new file mode 100644 index 0000000000..87839c2096 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-758763.js @@ -0,0 +1,7 @@ +// Copyright 2017 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. + +const re = /./g; +function toSlowMode() { re.slow = true; } +re[Symbol.split]("abc", { valueOf: toSlowMode }); diff --git a/deps/v8/test/mjsunit/regress/regress-761831.js b/deps/v8/test/mjsunit/regress/regress-761831.js new file mode 100644 index 0000000000..80ae256351 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-761831.js @@ -0,0 +1,13 @@ +// Copyright 2017 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 OrigReproCase() { + assertThrows('var f = ([x=[a=undefined]=[]]) => {}; f();', TypeError); +} +OrigReproCase(); + +function SimpleReproCase() { + assertThrows('var f = ([x=[]=[]]) => {}; f()', TypeError); +} +SimpleReproCase(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-632800.js b/deps/v8/test/mjsunit/regress/regress-crbug-632800.js index 68158ef591..9848a83882 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-632800.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-632800.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: --no-stress-fullcodegen --ignition-osr +// Flags: --ignition-osr function osr() { for (var i = 0; i < 50000; ++i) Math.random(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-635923.js b/deps/v8/test/mjsunit/regress/regress-crbug-635923.js index 41a7be06e9..5101b7973e 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-635923.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-635923.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 --no-stress-fullcodegen --turbo-filter=f +// Flags: --allow-natives-syntax --turbo-filter=f function f(x) { return x + 23 } function g(x) { return f(x) + 42 } diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-638551.js b/deps/v8/test/mjsunit/regress/regress-crbug-638551.js index 1f24140fa4..f812359d8d 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-638551.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-638551.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 --expose-gc --no-stress-fullcodegen --no-lazy +// Flags: --allow-natives-syntax --expose-gc --no-lazy function f() { for (var i = 0; i < 10; i++) if (i == 5) %OptimizeOsr(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-644111.js b/deps/v8/test/mjsunit/regress/regress-crbug-644111.js index 63c6b4417f..285e3d1ab3 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-644111.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-644111.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: --no-stress-fullcodegen --validate-asm --always-opt +// Flags: --validate-asm --always-opt function Module() { "use asm"; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-645103.js b/deps/v8/test/mjsunit/regress/regress-crbug-645103.js index 0fb3ab1acd..b81b9f2b04 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-645103.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-645103.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 --no-stress-fullcodegen +// Flags: --allow-natives-syntax class Base {} class Subclass extends Base { diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-645888.js b/deps/v8/test/mjsunit/regress/regress-crbug-645888.js index 8a9bfb3cf6..06879723ea 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-645888.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-645888.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 --no-stress-fullcodegen +// Flags: --allow-natives-syntax function f() { for (var i = 0; i < 3; ++i) { diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-647217.js b/deps/v8/test/mjsunit/regress/regress-crbug-647217.js index 92909682d6..e3968a19d6 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-647217.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-647217.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 --stack-size=100 --no-stress-fullcodegen +// Flags: --allow-natives-syntax --stack-size=100 var source = "return 1" + new Array(2048).join(' + a') + ""; eval("function g(a) {" + source + "}"); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-651403.js b/deps/v8/test/mjsunit/regress/regress-crbug-651403.js index d10d8051bb..c180e23752 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-651403.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-651403.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: --no-stress-fullcodegen --always-opt +// Flags: --always-opt function f () { var x = ""; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-658691.js b/deps/v8/test/mjsunit/regress/regress-crbug-658691.js index 1af2ed83eb..4f226e78bb 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-658691.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-658691.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 --no-stress-fullcodegen +// Flags: --allow-natives-syntax // The {f} function is compiled using TurboFan. // 1) The call to {Reflect.set} has no arguments adaptation. diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-668795.js b/deps/v8/test/mjsunit/regress/regress-crbug-668795.js index fc94097a43..b85d222080 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-668795.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-668795.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 --no-stress-fullcodegen +// Flags: --allow-natives-syntax function g() { return g.arguments; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-702798.js b/deps/v8/test/mjsunit/regress/regress-crbug-702798.js index 05a49f7135..861271a28e 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-702798.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-702798.js @@ -3,6 +3,6 @@ // found in the LICENSE file. // Access any property that's also available on the global of the other realm. -__defineGetter__("Object", ()=>0); +this.__defineGetter__("Object", ()=>0); __proto__ = Realm.global(Realm.create()); Object; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-722783.js b/deps/v8/test/mjsunit/regress/regress-crbug-722783.js new file mode 100644 index 0000000000..32ffd4e33c --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-722783.js @@ -0,0 +1,21 @@ +// Copyright 2017 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 set_x(v) { + x = v; +} + +var o = {}; +set_x(o); +set_x(o); +assertEquals(o, x); +Object.defineProperty(this, "x", { value:5, writable:false, configurable:true }); +assertEquals(5, x); +set_x(o); +set_x(o); +assertEquals(5, x); +Object.defineProperty(this, "x", { value:42, writable:true, configurable:true }); +assertEquals(42, x); +set_x(o); +assertEquals(o, x); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-740398.js b/deps/v8/test/mjsunit/regress/regress-crbug-740398.js index 26b8d9be3b..3624107052 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-740398.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-740398.js @@ -2,12 +2,10 @@ // 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 longString = (function() { - var str = ""; - for (var i = 0; i < 24; i++) { - str += "abcdefgh12345678" + str; - } - return str; + return "a".repeat(%StringMaxLength()); })(); assertThrows(() => { return { get[longString]() { } } }, RangeError); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-740591.js b/deps/v8/test/mjsunit/regress/regress-crbug-740591.js index e0a904f00e..c3f516199b 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-740591.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-740591.js @@ -35,3 +35,35 @@ assertEquals(a, b); } })(); + +(function testClassLiteral() { + for (let { a, b = class c { static f() { return a, b } } } of [{}]) { + assertSame(b, (function() { return b.f() })()); + } +})(); + +// Methods in class literals remain inside the +// class scope after scope reparenting. +(function testClassLiteralMethod() { + for (let { a, b = class c { m() { return c } } } of [{}]) { + assertSame(b, (function() { return (new b).m() })()); + } +})(); + +// Function literals in computed class names remain inside the +// class scope after scope reparenting. +(function testClassLiteralComputedName() { + let d; + for (let { a, b = class c { [d = function() { return c }]() { } } } of [{}]) { + assertSame(b, (function() { return b, d() })()); + } +})(); + +// Function literals in class extends expressions names remain inside the +// class scope after scope reparenting. +(function testClassLiteralComputedName() { + let d; + for (let { a, b = class c extends (d = function() { return c }, Object) { } } of [{}]) { + assertSame(b, (function() { return b, d() })()); + } +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-743154.js b/deps/v8/test/mjsunit/regress/regress-crbug-743154.js new file mode 100644 index 0000000000..a5bb2aa0ae --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-743154.js @@ -0,0 +1,22 @@ +// Copyright 2017 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. + + + +Object.prototype[1] = 1.5; + +var v = { length: 12, [1073741824]: 0 }; + +assertEquals(['1073741824', 'length'], Object.keys(v)); +assertEquals(undefined, v[0]); +assertEquals(1.5, v[1]); +assertEquals(0, v[1073741824]); + +// Properly handle out of range HeapNumber keys on 32bit platforms. +Array.prototype.sort.call(v); + +assertEquals(['0', '1073741824', 'length'], Object.keys(v)); +assertEquals(1.5, v[0]); +assertEquals(1.5, v[1]); +assertEquals(0, v[1073741824]); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-746835.js b/deps/v8/test/mjsunit/regress/regress-crbug-746835.js new file mode 100644 index 0000000000..ab5e3549d4 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-746835.js @@ -0,0 +1,112 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This example crashes if the AllocationSites have not been properly added to +// the allocation_sites_list. + +// Flags: --expose-gc + +function __getProperties() { + return []; + let properties = []; + for (let name of Object.getOwnPropertyNames()) {; + } + return properties; +} + +function __getRandomProperty() { + let properties = __getProperties(); + if (!properties.length) + return undefined; + return properties[seed % properties.length]; +} +var kWasmH0 = 0; +var kWasmH1 = 0x61; +var kWasmH2 = 0x73; +var kWasmH3 = 0x6d; +var kWasmV0 = 0x1; +var kWasmV1 = 0; +var kWasmV2 = 0; +var kWasmV3 = 0; +class Binary extends Array { + emit_header() { + this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, + kWasmV0, kWasmV1, kWasmV2, kWasmV3); + } +} +class WasmModuleBuilder { + constructor() { + this.exports = []; + } + addImportedMemory() {} + setFunctionTableLength() {} + toArray() { + let binary = new Binary; + let wasm = this; + binary.emit_header(); + "emitting imports @ " + binary.length; + section => {}; + var mem_export = (wasm.memory !== undefined && wasm.memory.exp); + var exports_count = wasm.exports.length + (mem_export ? 1 : 0); + return binary; + } + toBuffer() { + let bytes = this.toArray(); + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; i++) { + let val = bytes[i]; + view[i] = val | 0; + } + return buffer; + } + instantiate(ffi) { + let module = new WebAssembly.Module(this.toBuffer()); + let instance = new WebAssembly.Instance(module); + } +} + +var v_40 = 0; +var v_43 = NaN; + +try { + v_23 = new WasmModuleBuilder(); +} catch (e) { + print("Caught: " + e); +} + +try { + v_31 = [0xff]; + v_29 = [v_31]; +} catch (e) { + print("Caught: " + e); +} + +try { + v_25 = ["main"]; + gc(); +} catch (e) { + print("Caught: " + e); +} +for (var v_28 of [[2]]) { + try { + gc(); + } catch (e) { + print("Caught: " + e); + } +} +try { + module = v_23.instantiate(); +} catch (e) { + print("Caught: " + e); +} +try { + v_41 = []; +} catch (e) {; +} +for (var v_43 = 0; v_43 < 100000; v_43++) try { + v_41[v_43] = []; +} catch (e) { + "Caught: " + e; +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-747062.js b/deps/v8/test/mjsunit/regress/regress-crbug-747062.js new file mode 100644 index 0000000000..4fe99d39c1 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-747062.js @@ -0,0 +1,37 @@ +// Copyright 2017 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 TestNonCallableForEach() { + function foo() { [].forEach(undefined) } + assertThrows(foo, TypeError); + assertThrows(foo, TypeError); + %OptimizeFunctionOnNextCall(foo); + assertThrows(foo, TypeError); +})(); + +(function TestNonCallableForEachCaught() { + function foo() { try { [].forEach(undefined) } catch(e) { return e } } + assertInstanceof(foo(), TypeError); + assertInstanceof(foo(), TypeError); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), TypeError); +})(); + +(function TestNonCallableMap() { + function foo() { [].map(undefined); } + assertThrows(foo, TypeError); + assertThrows(foo, TypeError); + %OptimizeFunctionOnNextCall(foo); + assertThrows(foo, TypeError); +})(); + +(function TestNonCallableMapCaught() { + function foo() { try { [].map(undefined) } catch(e) { return e } } + assertInstanceof(foo(), TypeError); + assertInstanceof(foo(), TypeError); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), TypeError); +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-751109.js b/deps/v8/test/mjsunit/regress/regress-crbug-751109.js new file mode 100644 index 0000000000..035e64697d --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-751109.js @@ -0,0 +1,7 @@ +// Copyright 2017 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: --verify-heap + +(new constructor)[0] = null; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-751715.js b/deps/v8/test/mjsunit/regress/regress-crbug-751715.js new file mode 100644 index 0000000000..68241ebb18 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-751715.js @@ -0,0 +1,16 @@ +// Copyright 2017 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 + +class Base {} +class Derived extends Base { + constructor() { super(); } +} +var proxy = new Proxy(Base, { get() {} }); +assertDoesNotThrow(() => Reflect.construct(Derived, [])); +assertThrows(() => Reflect.construct(Derived, [], proxy), TypeError); +assertThrows(() => Reflect.construct(Derived, [], proxy), TypeError); +%OptimizeFunctionOnNextCall(Derived); +assertThrows(() => Reflect.construct(Derived, [], proxy), TypeError); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-752481.js b/deps/v8/test/mjsunit/regress/regress-crbug-752481.js new file mode 100644 index 0000000000..d0cc6a32a2 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-752481.js @@ -0,0 +1,32 @@ +// Copyright 2017 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 + +const A = class A {} + +function test(foo) { + assertThrows(foo); + assertThrows(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(foo); +} + +// Test combinations of rest parameters and primitive new.targets +test((...args) => Reflect.construct(A, args, 0)); +test((...args) => Reflect.construct(A, args, true)); +test((...args) => Reflect.construct(A, args, false)); +test((...args) => Reflect.construct(A, args, "")); +test((...args) => Reflect.construct(A, args, null)); +test((...args) => Reflect.construct(A, args, undefined)); +test((...args) => Reflect.construct(A, args, Symbol.species)); + +// Test combinations of arguments object and primitive new.targets. +test(function() { Reflect.construct(A, arguments, 0); }); +test(function() { Reflect.construct(A, arguments, true); }); +test(function() { Reflect.construct(A, arguments, false); }); +test(function() { Reflect.construct(A, arguments, ""); }); +test(function() { Reflect.construct(A, arguments, null); }); +test(function() { Reflect.construct(A, arguments, undefined); }); +test(function() { Reflect.construct(A, arguments, Symbol.species); }); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-752712.js b/deps/v8/test/mjsunit/regress/regress-crbug-752712.js new file mode 100644 index 0000000000..12d833ca5f --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-752712.js @@ -0,0 +1,24 @@ +// Copyright 2017 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 + +// Proxy get trap doesn't fail when the value returned by it +// is a number. + +var number = 1; + +(function testFailingInvariant() { + var obj = {}; + var handler = { + get: function() {} + }; + var proxy = new Proxy(obj, handler); + Object.defineProperty(handler, 'get', { + get: function() { + return number; + } + }); + assertThrows(function(){ proxy.property; }, TypeError); +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-752826.js b/deps/v8/test/mjsunit/regress/regress-crbug-752826.js new file mode 100644 index 0000000000..d0e124ed2b --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-752826.js @@ -0,0 +1,22 @@ +// Copyright 2017 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 h(a) { + return a[1]; +} +assertEquals(0, h(new Int8Array(10))); +assertEquals(0, h(new Int8Array(10))); + +function g() { + return h(arguments); +} +function f() { + return g(23, 42); +} +assertEquals(42, f()); +assertEquals(42, f()); +%OptimizeFunctionOnNextCall(f); +assertEquals(42, f()); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-752846.js b/deps/v8/test/mjsunit/regress/regress-crbug-752846.js new file mode 100644 index 0000000000..c2095dc57f --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-752846.js @@ -0,0 +1,21 @@ +// Copyright 2017 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 + +// Check that the receiver of Runtime_GetPropertyWithReceiver can be +// a plain JS value. + +var values = [ + 10, + false, + "test" +]; + +for (let val of values) { + var proto = Object.getPrototypeOf(val); + + var proxy = new Proxy({}, {}); + Object.setPrototypeOf(proto, proxy); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-754175.js b/deps/v8/test/mjsunit/regress/regress-crbug-754175.js new file mode 100644 index 0000000000..5490ba35b9 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-754175.js @@ -0,0 +1,19 @@ +// Copyright 2017 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: --mock-arraybuffer-allocator + +function Module(stdlib, foreign, buffer) { + "use asm"; + var heap = new stdlib.Int8Array(buffer); + function foo() { return heap[23] | 0 } + return { foo:foo }; +} +function instantiate() { + // On 32-bit architectures buffer allocation will throw. + var buffer = new ArrayBuffer(0x100000000); + // On 64-bit architectures instantiation will throw. + var module = Module(this, {}, buffer); +} +assertThrows(instantiate, RangeError); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-754177.js b/deps/v8/test/mjsunit/regress/regress-crbug-754177.js new file mode 100644 index 0000000000..1c105a3bf2 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-754177.js @@ -0,0 +1,12 @@ +// Copyright 2017 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 + +// Do not crash on non-JSFunction input. +%NeverOptimizeFunction(undefined); +%NeverOptimizeFunction(true); +%NeverOptimizeFunction(1); +%NeverOptimizeFunction({}); +assertThrows("%NeverOptimizeFunction()", SyntaxError); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-755044.js b/deps/v8/test/mjsunit/regress/regress-crbug-755044.js new file mode 100644 index 0000000000..45f0e84661 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-755044.js @@ -0,0 +1,15 @@ +// Copyright 2017 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 foo(f){ + f.caller; +} +function bar(f) { + new foo(f); +} +bar(function() {}); +%OptimizeFunctionOnNextCall(bar); +bar(function() {}); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-756332.js b/deps/v8/test/mjsunit/regress/regress-crbug-756332.js new file mode 100644 index 0000000000..10bccbc8f9 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-756332.js @@ -0,0 +1,13 @@ +// Copyright 2017 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. + +{ + let z = ({x: {y} = {y: 42}} = {}) => y; + assertEquals(42, z()); +} + +{ + let z = ({x: [y] = [42]} = {}) => y; + assertEquals(42, z()); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-757199.js b/deps/v8/test/mjsunit/regress/regress-crbug-757199.js new file mode 100644 index 0000000000..d2e9502b39 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-757199.js @@ -0,0 +1,31 @@ +/// Copyright 2017 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 obj1 = {}; +var obj2 = {}; + +function h() {} + +h.prototype = obj2; + +function g(v) { + v.constructor; +} +function f() { + g(obj1); +} + +obj1.x = 0; +f(); + +obj1.__defineGetter__("x", function() {}); + +g(obj2); + +obj2.y = 0; + +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-758773.js b/deps/v8/test/mjsunit/regress/regress-crbug-758773.js new file mode 100644 index 0000000000..1dbcdd1397 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-758773.js @@ -0,0 +1,6 @@ +// Copyright 2017 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. + +(0).__defineGetter__(0, function() { }); +Number.prototype[0] = "string"; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-759327.js b/deps/v8/test/mjsunit/regress/regress-crbug-759327.js new file mode 100644 index 0000000000..9b422176b8 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-759327.js @@ -0,0 +1,23 @@ +// Copyright 2017 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 Module(stdlib, env, heap) { + "use asm"; + var MEM = new stdlib.Int32Array(heap); + function f() { + MEM[0] = 0; + } + return { f: f }; +} +function instantiate() { + var buffer = new ArrayBuffer(0); + Module(this, {}, buffer).f(); + try {} finally {} + gc(); + Module(this, {}, buffer).f(); +} +instantiate(); +assertTrue(%IsAsmWasmCode(Module)); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-762472.js b/deps/v8/test/mjsunit/regress/regress-crbug-762472.js new file mode 100644 index 0000000000..e8d28426b3 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-762472.js @@ -0,0 +1,26 @@ +// Copyright 2017 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 Module() { + "use asm"; + function f() {} + return { f:f } +} + +function InstantiateNearStackLimit() { + try { + var fuse = InstantiateNearStackLimit(); + if (fuse == 0) Module(); + return fuse - 1; + } catch(e) { + return init_fuse; + } +} + +var init_fuse = 0; +for (init_fuse = 0; init_fuse < 10; init_fuse++) { + InstantiateNearStackLimit(); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-762874-1.js b/deps/v8/test/mjsunit/regress/regress-crbug-762874-1.js index b82a786159..ab1b7c1578 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-762874-1.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-762874-1.js @@ -4,7 +4,7 @@ // Flags: --allow-natives-syntax -const maxLength = 268435440; +const maxLength = %StringMaxLength(); const s = 'A'.repeat(maxLength); function foo(s) { diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-762874-2.js b/deps/v8/test/mjsunit/regress/regress-crbug-762874-2.js index 9a2a3f18eb..6d301b5ae3 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-762874-2.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-762874-2.js @@ -4,7 +4,7 @@ // Flags: --allow-natives-syntax -const maxLength = 268435440; +const maxLength = %StringMaxLength(); const s = 'A'.repeat(maxLength); function foo(s) { diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-763683.js b/deps/v8/test/mjsunit/regress/regress-crbug-763683.js new file mode 100644 index 0000000000..92ba46ce9a --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-763683.js @@ -0,0 +1,22 @@ +// Copyright 2017 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. + +assertThrows(function test() { + var proxy = new Proxy({}, {}); + var key_or_proxy = 0; + + function failing_get() { + return proxy[key_or_proxy]; + } + + failing_get(); + + key_or_proxy = new Proxy({ + toString() { + throw new TypeError('error'); + } + }, {}); + + failing_get(); +}, TypeError); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-768158.js b/deps/v8/test/mjsunit/regress/regress-crbug-768158.js new file mode 100644 index 0000000000..f33f0efae0 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-768158.js @@ -0,0 +1,23 @@ +// Copyright 2017 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: --always-opt + +(function testOriginalRepro() { + var result; + var dict = { toString() { result = v;} }; + for (var v of ['fontsize', 'sup']) { + String.prototype[v].call(dict); + assertEquals(v, result); + } +})(); + +(function testSimpler() { + var result; + function setResult() { result = v; } + for (var v of ['hello', 'world']) { + setResult(); + assertEquals(v, result); + } +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-771428.js b/deps/v8/test/mjsunit/regress/regress-crbug-771428.js new file mode 100644 index 0000000000..3bebfa102c --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-771428.js @@ -0,0 +1,24 @@ +// Copyright 2017 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 Module() { + "use asm"; + function f(i) { + i = i | 0; + switch (i | 0) { + case 2: + // Exceeds value range. + i = 0x1ffffffff; + break; + } + return i | 0; + } + return f; +} +var f = Module(); +assertEquals(0, f(0)); +assertEquals(1, f(1)); +assertEquals(-1, f(2)); +assertFalse(%IsAsmWasmCode(Module)); diff --git a/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js b/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js index 8e7b0396e8..03fe321690 100644 --- a/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js +++ b/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js @@ -31,7 +31,7 @@ // internally calls RegExpImpl::IrregexpExecOnce more than once without // ensuring that the regexp is compiled. // This can create a crash if the code was exchanged with the sweep -// generation (for code flushing support) in GC durring the matching. +// generation (for code flushing support) in GC during the matching. var re = new RegExp('(s)', "g"); diff --git a/deps/v8/test/mjsunit/regress/regress-v8-6706.js b/deps/v8/test/mjsunit/regress/regress-v8-6706.js new file mode 100644 index 0000000000..36ce229fd8 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-v8-6706.js @@ -0,0 +1,37 @@ +// Copyright 2017 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. + +const str = "a-b-c"; + +function test(re) { + assertArrayEquals(["a", "b", "c"], re[Symbol.split](str)); +} + +!function() { + const re = /-/y; + re.lastIndex = 1; + test(re); +}(); + +!function() { + const re = /-/y; + re.lastIndex = 3; + test(re); +}(); + +!function() { + const re = /-/y; + re.lastIndex = -1; + test(re); +}(); + +!function() { + const re = /-/y; + test(re); +}(); + +!function() { + const re = /-/g; + test(re); +}(); diff --git a/deps/v8/test/mjsunit/regress/regress-v8-6712.js b/deps/v8/test/mjsunit/regress/regress-v8-6712.js new file mode 100644 index 0000000000..0c5d5442fa --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-v8-6712.js @@ -0,0 +1,16 @@ +// Copyright 2017 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 log = []; + +function f() {} +Object.defineProperty(Function.prototype, "name", { + get() { log.push("getter"); return "ok"; } +}); +delete f.name; +var b = f.bind(); +assertEquals("bound ok", b.name); +assertEquals("bound ok", b.name); +assertEquals("bound ok", b.name); +assertEquals(["getter"], log); diff --git a/deps/v8/test/mjsunit/regress/wasm/regression-648079.js b/deps/v8/test/mjsunit/regress/wasm/regression-648079.js index e9d14175e4..2fa6b4db7a 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regression-648079.js +++ b/deps/v8/test/mjsunit/regress/wasm/regression-648079.js @@ -7,6 +7,11 @@ load("test/mjsunit/wasm/wasm-constants.js"); load("test/mjsunit/wasm/wasm-module-builder.js"); +// Non-standard opcodes. +let kWasmS128 = 0x7b; +let kSig_s_v = makeSig([], [kWasmS128]); +let kExprS128LoadMem = 0xc0; + (function() { "use asm"; var builder = new WasmModuleBuilder(); diff --git a/deps/v8/test/mjsunit/regress/wasm/regression-702460.js b/deps/v8/test/mjsunit/regress/wasm/regression-702460.js index 25ed5b5061..2d63440255 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regression-702460.js +++ b/deps/v8/test/mjsunit/regress/wasm/regression-702460.js @@ -5,6 +5,11 @@ load("test/mjsunit/wasm/wasm-constants.js"); load("test/mjsunit/wasm/wasm-module-builder.js"); +// Non-standard opcodes. +let kWasmS128 = 0x7b; +let kSig_s_v = makeSig([], [kWasmS128]); +let kExprS128LoadMem = 0xc0; + (function() { "use asm"; var builder = new WasmModuleBuilder(); diff --git a/deps/v8/test/mjsunit/regress/wasm/regression-739768.js b/deps/v8/test/mjsunit/regress/wasm/regression-739768.js index 72843b909d..bcf3ceeca2 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regression-739768.js +++ b/deps/v8/test/mjsunit/regress/wasm/regression-739768.js @@ -16,7 +16,7 @@ builder0.addFunction('main', kSig_i_i) kExprCallIndirect, sig_index, kTableZero ]) // -- .exportAs('main'); -builder0.setFunctionTableLength(3); +builder0.setFunctionTableBounds(3, 3); builder0.addExportOfKind('table', kExternalTable); let module0 = new WebAssembly.Module(builder0.toBuffer()); let instance0 = new WebAssembly.Instance(module0); diff --git a/deps/v8/test/mjsunit/regress/wasm/regression-753496.js b/deps/v8/test/mjsunit/regress/wasm/regression-753496.js new file mode 100644 index 0000000000..a056a9fd8e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regression-753496.js @@ -0,0 +1,17 @@ +// Copyright 2017 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 Module(stdlib, foreign, heap) { + "use asm"; + var MEM64 = new stdlib.Float64Array(heap); + function foo(i) { + i = i | 0; + MEM64[032 ] = +(i >>> 7 ) / 2.; + return +MEM64[0]; + } + return { foo: foo }; +} + +var foo = Module(this, {}, new ArrayBuffer( "" ? this : this)).foo; +assertEquals(NaN, foo(1)); diff --git a/deps/v8/test/mjsunit/regress/wasm/regression-757217.js b/deps/v8/test/mjsunit/regress/wasm/regression-757217.js new file mode 100644 index 0000000000..218b090c45 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regression-757217.js @@ -0,0 +1,20 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +load('test/mjsunit/wasm/wasm-constants.js'); +load('test/mjsunit/wasm/wasm-module-builder.js'); + +let builder = new WasmModuleBuilder(); +builder.addImport('','f', kSig_v_v); +builder.addExport('a', 0); +builder.addExport('b', 0); +var bytes = builder.toBuffer(); + +var m = new WebAssembly.Module(bytes); +assertTrue(m instanceof WebAssembly.Module); + +assertPromiseResult( + WebAssembly.compile(bytes) + .then(async_result => assertTrue(async_result instanceof WebAssembly.Module), + assertUnreachable)); diff --git a/deps/v8/test/mjsunit/shared-function-tier-up-turbo.js b/deps/v8/test/mjsunit/shared-function-tier-up-turbo.js index a9e3938dd3..f8e9117785 100644 --- a/deps/v8/test/mjsunit/shared-function-tier-up-turbo.js +++ b/deps/v8/test/mjsunit/shared-function-tier-up-turbo.js @@ -3,7 +3,7 @@ // found in the LICENSE file. // // Flags: --mark-shared-functions-for-tier-up --allow-natives-syntax -// Flags: --no-stress-fullcodegen --opt --no-always-opt --turbo-filter=* +// Flags: --opt --no-always-opt --turbo-filter=* // If we are always or never optimizing it is useless. assertFalse(isAlwaysOptimize()); diff --git a/deps/v8/test/mjsunit/skipping-inner-functions-bailout.js b/deps/v8/test/mjsunit/skipping-inner-functions-bailout.js new file mode 100644 index 0000000000..f09f1d9bb7 --- /dev/null +++ b/deps/v8/test/mjsunit/skipping-inner-functions-bailout.js @@ -0,0 +1,78 @@ +// Copyright 2017 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: --preparser-scope-analysis + +// Tests for cases where PreParser must bail out of creating data for skipping +// inner functions, since it cannot replicate the Scope structure created by +// Parser. + +function TestBailoutBecauseOfSloppyEvalInArrowParams() { + let bailout = (a = function() {}, b = eval('')) => 0 + bailout(); + + function not_skippable() {} +} +TestBailoutBecauseOfSloppyEvalInArrowParams(); + +function TestBailoutBecauseOfSloppyEvalInArrowParams2() { + let bailout = (a = function() {}, b = eval('')) => {} + bailout(); + + function not_skippable() {} +} +TestBailoutBecauseOfSloppyEvalInArrowParams2(); + +function TestBailoutBecauseOfSloppyEvalInParams() { + function bailout(a = function() {}, b = eval('')) { + function not_skippable() {} + } + bailout(); + + function not_skippable_either() {} +} +TestBailoutBecauseOfSloppyEvalInParams(); + + // Test bailing out from 2 places. +function TestMultiBailout1() { + function bailout(a = function() {}, b = eval('')) { + function not_skippable() {} + } + bailout(); + + function bailout_too(a = function() {}, b = eval('')) { + function not_skippable_either() {} + } + bailout_too(); +} +TestMultiBailout1(); + +function TestMultiBailout2() { + function f(a = function() {}, b = eval('')) { + function not_skippable() {} + } + f(); + + function not_skippable_either() { + function bailout_too(a = function() {}, b = eval('')) { + function inner_not_skippable() {} + } + bailout_too(); + } + not_skippable_either(); +} +TestMultiBailout2(); + +function TestMultiBailout3() { + function bailout(a = function() {}, b = eval('')) { + function bailout_too(a = function() {}, b = eval('')) { + function not_skippable() {} + } + bailout_too(); + } + bailout(); + + function not_skippable_either() {} +} +TestMultiBailout3(); diff --git a/deps/v8/test/mjsunit/skipping-inner-functions.js b/deps/v8/test/mjsunit/skipping-inner-functions.js index 4ca293625a..51c9fd5534 100644 --- a/deps/v8/test/mjsunit/skipping-inner-functions.js +++ b/deps/v8/test/mjsunit/skipping-inner-functions.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: --experimental-preparser-scope-analysis +// Flags: --preparser-scope-analysis --enable-slow-asserts (function TestBasicSkipping() { var result = 0; @@ -82,7 +82,7 @@ })(); // Skippable top level functions. -let result = 0; +var result = 0; function lazy_top_level(ctxt_alloc_param) { let ctxt_alloc_var = 24; function skip_me() { @@ -203,3 +203,95 @@ let f1 = (ctxt_alloc_param) => { } f1(9)(); assertEquals(19, result); + +function TestStrictEvalInParams() { + "use strict"; + var result = 0; + + function lazy(a = function() { return 2; }, b = eval('3')) { + function skip_me() { + result = a() + b; + } + return skip_me; + } + lazy()(); + assertEquals(5, result); + + function not_skippable_either() {} +} + +TestStrictEvalInParams(); + +function TestSloppyEvalInFunctionWithComplexParams() { + var result = 0; + + function lazy1(ctxt_alloc_param = 2) { + var ctxt_alloc_var = 3; + function skip_me() { + result = ctxt_alloc_param + ctxt_alloc_var; + } + eval(''); + return skip_me; + } + lazy1()(); + assertEquals(5, result); + + function lazy2(ctxt_alloc_param = 4) { + var ctxt_alloc_var = 5; + function skip_me() { + eval('result = ctxt_alloc_param + ctxt_alloc_var;'); + } + return skip_me; + } + lazy2()(); + assertEquals(9, result); +} + +TestSloppyEvalInFunctionWithComplexParams(); + +function TestSkippableFunctionInForOfHeader() { + var c; + function inner() { + for (let [a, b = c = function() { return a; }] of [[10]]) { + } + } + inner(); + var result = c(); + assertEquals(10, result); +} + +TestSkippableFunctionInForOfHeader(); + +function TestSkippableFunctionInForOfBody() { + var c; + function inner() { + for (let [a, b] of [[10, 11]]) { + c = function f() { + return a + b; + } + } + } + inner(); + var result = c(); + assertEquals(21, result); +} + +TestSkippableFunctionInForOfBody(); + + +function TestSkippableFunctionInForOfHeaderAndBody() { + var c1; + var c2; + function inner() { + for (let [a, b = c1 = function() { return a; }] of [[10]]) { + c2 = function f() { + return a + 1; + } + } + } + inner(); + var result = c1() + c2(); + assertEquals(21, result); +} + +TestSkippableFunctionInForOfHeaderAndBody(); diff --git a/deps/v8/test/mjsunit/smi-mul-const.js b/deps/v8/test/mjsunit/smi-mul-const.js index 64cc2e5f27..e5255014dc 100644 --- a/deps/v8/test/mjsunit/smi-mul-const.js +++ b/deps/v8/test/mjsunit/smi-mul-const.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 --opt --noalways-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --noalways-opt function check(func, input, expected) { func(-1); diff --git a/deps/v8/test/mjsunit/smi-mul.js b/deps/v8/test/mjsunit/smi-mul.js index ca1bf06b69..12d206abec 100644 --- a/deps/v8/test/mjsunit/smi-mul.js +++ b/deps/v8/test/mjsunit/smi-mul.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 --opt --noalways-opt --no-stress-fullcodegen +// Flags: --allow-natives-syntax --opt --noalways-opt function mul(a, b) { return a * b; diff --git a/deps/v8/test/mjsunit/stack-traces-custom.js b/deps/v8/test/mjsunit/stack-traces-custom.js index 75fad636e0..0cb53faaec 100644 --- a/deps/v8/test/mjsunit/stack-traces-custom.js +++ b/deps/v8/test/mjsunit/stack-traces-custom.js @@ -24,3 +24,28 @@ try { assertEquals("k", frames[4].getMethodName()); assertEquals(null, frames[5].getMethodName()); } + +function testMethodName(f, frameNumber, expectedName) { + try { + Error.prepareStackTrace = function(e, frames) { return frames; } + f(); + assertUnreachable(); + } catch (e) { + const frame = e.stack[frameNumber]; + assertEquals(expectedName, frame.getMethodName()); + } finally { + Error.prepareStackTrace = undefined; + } +} + +const thrower = { valueOf: () => { throw new Error(); }}; + +{ + const str = ""; + testMethodName(() => { str.indexOf(str, thrower); }, 1, "indexOf"); +} + +{ + const nr = 42; + testMethodName(() => { nr.toString(thrower); }, 1, "toString"); +} diff --git a/deps/v8/test/mjsunit/string-oom-array-join.js b/deps/v8/test/mjsunit/string-oom-array-join.js index 73758ce96b..2ed51900de 100644 --- a/deps/v8/test/mjsunit/string-oom-array-join.js +++ b/deps/v8/test/mjsunit/string-oom-array-join.js @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var a = "a"; -for (var i = 0; i < 23; i++) a += a; +// Flags: --allow-natives-syntax + +var a = "a".repeat(%StringMaxLength() / 10); var b = []; -for (var i = 0; i < (1<<5); i++) b.push(a); +for (var i = 0; i < 11; i++) b.push(a); function join() { b.join(); diff --git a/deps/v8/test/mjsunit/string-oom-replace-global-regexp-with-string.js b/deps/v8/test/mjsunit/string-oom-replace-global-regexp-with-string.js index 2de01109eb..5053d81e8c 100644 --- a/deps/v8/test/mjsunit/string-oom-replace-global-regexp-with-string.js +++ b/deps/v8/test/mjsunit/string-oom-replace-global-regexp-with-string.js @@ -2,12 +2,10 @@ // 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 a = 'a'; -for (var i = 0; i < 5; i++) a += a; -var b = 'b'; -for (var i = 0; i < 23; i++) b += b; +var a = 'a'.repeat(32); +var b = 'b'.repeat(%StringMaxLength() / 32 + 1); function replace1() { a.replace(/./g, b); @@ -16,8 +14,7 @@ function replace1() { assertThrows(replace1, RangeError); -var a = 'a'; -for (var i = 0; i < 16; i++) a += a; +var a = 'a'.repeat(Math.sqrt(%StringMaxLength()) + 1); function replace2() { a.replace(/a/g, a); diff --git a/deps/v8/test/mjsunit/string-oom-replace-regexp-global-with-function.js b/deps/v8/test/mjsunit/string-oom-replace-regexp-global-with-function.js index 5555a5f1e9..567920b411 100644 --- a/deps/v8/test/mjsunit/string-oom-replace-regexp-global-with-function.js +++ b/deps/v8/test/mjsunit/string-oom-replace-regexp-global-with-function.js @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var a = "a"; -for (var i = 0; i < 5; i++) a += a; -var b = "b"; -for (var i = 0; i < 23; i++) b += b; +// Flags: --allow-natives-syntax + +var a = 'a'.repeat(32); +var b = 'b'.repeat(%StringMaxLength() / 32 + 1); function replace() { a.replace(/a/g, function() { return b }); diff --git a/deps/v8/test/mjsunit/type-profile/collect-type-profile.js b/deps/v8/test/mjsunit/type-profile/collect-type-profile.js index deff079cdb..d21d11d9d2 100644 --- a/deps/v8/test/mjsunit/type-profile/collect-type-profile.js +++ b/deps/v8/test/mjsunit/type-profile/collect-type-profile.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: --type-profile --no-stress-fullcodegen --allow-natives-syntax +// Flags: --type-profile --allow-natives-syntax function check_collect_types(name, expected) { const type_profile = %TypeProfile(name); @@ -36,7 +36,7 @@ testFunction(123, true); testFunction('hello'); testFunction(123); -expected = `{\"519\":[\"Object\",\"number\",\"string\",\"number\"],\"526\":[\"undefined\",\"boolean\",\"undefined\",\"undefined\"],\"715\":[\"Object\",\"number\",\"string\",\"number\"]}`; +expected = `{\"495\":[\"Object\",\"number\",\"string\",\"number\"],\"502\":[\"undefined\",\"boolean\",\"undefined\",\"undefined\"],\"691\":[\"Object\",\"number\",\"string\",\"number\"]}`; check_collect_types(testFunction, expected); testFunction(undefined); @@ -45,7 +45,7 @@ testFunction({x: 12}, true); testFunction({x: 12}); testFunction(new MyClass()); -expected = `{\"519\":[\"Object\",\"number\",\"string\",\"number\",\"undefined\",\"string\",\"Object\",\"Object\",\"MyClass\"],\"526\":[\"undefined\",\"boolean\",\"undefined\",\"undefined\",\"undefined\",\"boolean\",\"boolean\",\"undefined\",\"undefined\"],\"715\":[\"Object\",\"number\",\"string\",\"number\",\"undefined\",\"string\",\"Object\",\"Object\",\"MyClass\"]}`; +expected = `{\"495\":[\"Object\",\"number\",\"string\",\"number\",\"undefined\",\"string\",\"Object\",\"Object\",\"MyClass\"],\"502\":[\"undefined\",\"boolean\",\"undefined\",\"undefined\",\"undefined\",\"boolean\",\"boolean\",\"undefined\",\"undefined\"],\"691\":[\"Object\",\"number\",\"string\",\"number\",\"undefined\",\"string\",\"Object\",\"Object\",\"MyClass\"]}`; check_collect_types(testFunction, expected); @@ -53,7 +53,7 @@ function testReturnOfNonVariable() { return 32; } testReturnOfNonVariable(); -expected = `{\"1748\":[\"number\"]}`; +expected = `{\"1724\":[\"number\"]}`; check_collect_types(testReturnOfNonVariable, expected); // Return statement is reached but its expression is never really returned. @@ -65,7 +65,7 @@ function try_finally() { } } try_finally(); -expected = `{\"2050\":[\"string\"]}`; +expected = `{\"2026\":[\"string\"]}`; check_collect_types(try_finally, expected); // Fall-off return. @@ -73,7 +73,7 @@ function fall_off() { //nothing } fall_off(); -expected = `{\"2204\":[\"undefined\"]}`; +expected = `{\"2180\":[\"undefined\"]}`; check_collect_types(fall_off, expected); // Do not collect types when the function is never run. @@ -86,5 +86,5 @@ function several_params(a, b, c, d) { //nothing } several_params(2, 'foo', {}, new MyClass()); -expected = `{\"2472\":[\"number\"],\"2475\":[\"string\"],\"2478\":[\"Object\"],\"2481\":[\"MyClass\"],\"2498\":[\"undefined\"]}`; +expected = `{\"2448\":[\"number\"],\"2451\":[\"string\"],\"2454\":[\"Object\"],\"2457\":[\"MyClass\"],\"2474\":[\"undefined\"]}`; check_collect_types(several_params, expected); diff --git a/deps/v8/test/mjsunit/unicode-test.js b/deps/v8/test/mjsunit/unicode-test.js index 1d64420c30..509eb89566 100644 --- a/deps/v8/test/mjsunit/unicode-test.js +++ b/deps/v8/test/mjsunit/unicode-test.js @@ -4110,7 +4110,7 @@ var source = " if no space is available. Additionally, on failure, errno is\n" + " set to ENOMEM on ANSI C systems.\n" + "\n" + -" If n is zero, malloc returns a minumum-sized chunk. (The minimum\n" + +" If n is zero, malloc returns a minimum-sized chunk. (The minimum\n" + " size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit\n" + " systems.) On most systems, size_t is an unsigned type, so calls\n" + " with negative arguments are interpreted as requests for huge amounts\n" + @@ -5364,7 +5364,7 @@ var source = " and consolidated sets of chunks, which is what these bins hold, so\n" + " they can be found quickly. All procedures maintain the invariant\n" + " that no consolidated chunk physically borders another one, so each\n" + -" chunk in a list is known to be preceeded and followed by either\n" + +" chunk in a list is known to be preceded and followed by either\n" + " inuse chunks or the ends of memory.\n" + "\n" + " Chunks in bins are kept in size order, with ties going to the\n" + @@ -9097,7 +9097,7 @@ assertEquals(25640, hebrew.length, "hebrew utf8 in source"); assertEquals(31082, japanese.length, "japanese utf8 in source"); assertEquals(12291, korean.length, "korean utf8 in source"); assertEquals(13851, persian.length, "persian utf8 in source"); -assertEquals(177470, source.length, "source utf8 in source"); +assertEquals(177469, source.length, "source utf8 in source"); assertEquals(18315, thai.length, "thai utf8 in source"); munged_sizes = new Array(17197, 2511, 2645, 3820, 3086, 2609, diff --git a/deps/v8/test/mjsunit/wasm/OWNERS b/deps/v8/test/mjsunit/wasm/OWNERS index 59b1e7dc7a..5bd472f49d 100644 --- a/deps/v8/test/mjsunit/wasm/OWNERS +++ b/deps/v8/test/mjsunit/wasm/OWNERS @@ -1,6 +1,7 @@ ahaas@chromium.org bradnelson@chromium.org clemensh@chromium.org +eholk@chromium.org mtrofin@chromium.org rossberg@chromium.org titzer@chromium.org diff --git a/deps/v8/test/mjsunit/wasm/async-compile.js b/deps/v8/test/mjsunit/wasm/async-compile.js index 854e8bb6c1..fe7b1aa886 100644 --- a/deps/v8/test/mjsunit/wasm/async-compile.js +++ b/deps/v8/test/mjsunit/wasm/async-compile.js @@ -56,7 +56,7 @@ assertPromiseResult(async function basicCompile() { assertPromiseResult(async function badFunctionInTheMiddle() { // We had an error where an exception was generated by a background task and // later thrown in a foreground task. The handle to the exception died - // inbetween, since the HandleScope was left. + // between, since the HandleScope was left. // This test reproduced that error. let builder = new WasmModuleBuilder(); let sig = builder.addType(kSig_i_v); diff --git a/deps/v8/test/mjsunit/wasm/atomics.js b/deps/v8/test/mjsunit/wasm/atomics.js new file mode 100644 index 0000000000..089accb45b --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/atomics.js @@ -0,0 +1,257 @@ +// Copyright 2017 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: --experimental-wasm-threads + +load("test/mjsunit/wasm/wasm-constants.js"); +load("test/mjsunit/wasm/wasm-module-builder.js"); + +const kMemtypeSize32 = 4; +const kMemtypeSize16 = 2; +const kMemtypeSize8 = 1; + +function Add(a, b) { return a + b; } +function Sub(a, b) { return a - b; } +function And(a, b) { return a & b; } +function Or(a, b) { return a | b; } +function Xor(a, b) { return a ^ b; } +function Exchange(a, b) { return b; } + +let maxSize = 10; +let memory = new WebAssembly.Memory({initial: 1, maximum: maxSize, shared: true}); + +function GetAtomicBinOpFunction(wasmExpression) { + let builder = new WasmModuleBuilder(); + builder.addImportedMemory("m", "imported_mem"); + builder.addFunction("main", kSig_i_ii) + .addBody([ + kExprGetLocal, 0, + kExprGetLocal, 1, + kAtomicPrefix, + wasmExpression]) + .exportAs("main"); + + // Instantiate module, get function exports + let module = new WebAssembly.Module(builder.toBuffer()); + let instance = (new WebAssembly.Instance(module, + {m: {imported_mem: memory}})); + return instance.exports.main; +} + +function GetAtomicCmpExchangeFunction(wasmExpression) { + let builder = new WasmModuleBuilder(); + builder.addImportedMemory("m", "imported_mem"); + builder.addFunction("main", kSig_i_iii) + .addBody([ + kExprGetLocal, 0, + kExprGetLocal, 1, + kExprGetLocal, 2, + kAtomicPrefix, + wasmExpression]) + .exportAs("main"); + + // Instantiate module, get function exports + let module = new WebAssembly.Module(builder.toBuffer()); + let instance = (new WebAssembly.Instance(module, + {m: {imported_mem: memory}})); + return instance.exports.main; +} + + +function VerifyBoundsCheck(func, memtype_size) { + const kPageSize = 65536; + // Test out of bounds at boundary + for (let i = memory.buffer.byteLength - memtype_size + 1; + i < memory.buffer.byteLength + memtype_size + 4; i++) { + assertTraps(kTrapMemOutOfBounds, () => func(i, 5, 10)); + } + // Test out of bounds at maximum + 1 + assertTraps(kTrapMemOutOfBounds, () => func((maxSize + 1) * kPageSize, 5, 1)); +} + +function Test32Op(operation, func) { + let i32 = new Uint32Array(memory.buffer); + for (let i = 0; i < i32.length; i++) { + let expected = 0x9cedf00d; + let value = 0x11111111; + i32[i] = expected; + assertEquals(expected, func(i * kMemtypeSize32, value) >>> 0); + assertEquals(operation(expected, value) >>> 0, i32[i]); + } + VerifyBoundsCheck(func, kMemtypeSize32); +} + +function Test16Op(operation, func) { + let i16 = new Uint16Array(memory.buffer); + for (let i = 0; i < i16.length; i++) { + let expected = 0xd00d; + let value = 0x1111; + i16[i] = expected; + assertEquals(expected, func(i * kMemtypeSize16, value)); + assertEquals(operation(expected, value), i16[i]); + } + VerifyBoundsCheck(func, kMemtypeSize16); +} + +function Test8Op(operation, func) { + let i8 = new Uint8Array(memory.buffer); + for (let i = 0; i < i8.length; i++) { + let expected = 0xbe; + let value = 0x12; + i8[i] = expected; + assertEquals(expected, func(i * kMemtypeSize8, value)); + assertEquals(operation(expected, value), i8[i]); + } + VerifyBoundsCheck(func, kMemtypeSize8, 10); +} + +(function TestAtomicAdd() { + print("TestAtomicAdd"); + let wasmAdd = GetAtomicBinOpFunction(kExprI32AtomicAdd); + Test32Op(Add, wasmAdd); +})(); + +(function TestAtomicAdd16U() { + print("TestAtomicAdd16U"); + let wasmAdd = GetAtomicBinOpFunction(kExprI32AtomicAdd16U); + Test16Op(Add, wasmAdd); +})(); + +(function TestAtomicAdd8U() { + print("TestAtomicAdd8U"); + let wasmAdd = GetAtomicBinOpFunction(kExprI32AtomicAdd8U); + Test8Op(Add, wasmAdd); +})(); + +(function TestAtomicSub() { + print("TestAtomicSub"); + let wasmSub = GetAtomicBinOpFunction(kExprI32AtomicSub); + Test32Op(Sub, wasmSub); +})(); + +(function TestAtomicSub16U() { + print("TestAtomicSub16U"); + let wasmSub = GetAtomicBinOpFunction(kExprI32AtomicSub16U); + Test16Op(Sub, wasmSub); +})(); + +(function TestAtomicSub8U() { + print("TestAtomicSub8U"); + let wasmSub = GetAtomicBinOpFunction(kExprI32AtomicSub8U); + Test8Op(Sub, wasmSub); +})(); + +(function TestAtomicAnd() { + print("TestAtomicAnd"); + let wasmAnd = GetAtomicBinOpFunction(kExprI32AtomicAnd); + Test32Op(And, wasmAnd); +})(); + +(function TestAtomicAnd16U() { + print("TestAtomicAnd16U"); + let wasmAnd = GetAtomicBinOpFunction(kExprI32AtomicAnd16U); + Test16Op(And, wasmAnd); +})(); + +(function TestAtomicAnd8U() { + print("TestAtomicAnd8U"); + let wasmAnd = GetAtomicBinOpFunction(kExprI32AtomicAnd8U); + Test8Op(And, wasmAnd); +})(); + +(function TestAtomicOr() { + print("TestAtomicOr"); + let wasmOr = GetAtomicBinOpFunction(kExprI32AtomicOr); + Test32Op(Or, wasmOr); +})(); + +(function TestAtomicOr16U() { + print("TestAtomicOr16U"); + let wasmOr = GetAtomicBinOpFunction(kExprI32AtomicOr16U); + Test16Op(Or, wasmOr); +})(); + +(function TestAtomicOr8U() { + print("TestAtomicOr8U"); + let wasmOr = GetAtomicBinOpFunction(kExprI32AtomicOr8U); + Test8Op(Or, wasmOr); +})(); + +(function TestAtomicXor() { + print("TestAtomicXor"); + let wasmXor = GetAtomicBinOpFunction(kExprI32AtomicXor); + Test32Op(Xor, wasmXor); +})(); + +(function TestAtomicXor16U() { + print("TestAtomicXor16U"); + let wasmXor = GetAtomicBinOpFunction(kExprI32AtomicXor16U); + Test16Op(Xor, wasmXor); +})(); + +(function TestAtomicXor8U() { + print("TestAtomicXor8U"); + let wasmXor = GetAtomicBinOpFunction(kExprI32AtomicXor8U); + Test8Op(Xor, wasmXor); +})(); + +(function TestAtomicExchange() { + print("TestAtomicExchange"); + let wasmExchange = GetAtomicBinOpFunction(kExprI32AtomicExchange); + Test32Op(Exchange, wasmExchange); +})(); + +(function TestAtomicExchange16U() { + print("TestAtomicExchange16U"); + let wasmExchange = GetAtomicBinOpFunction(kExprI32AtomicExchange16U); + Test16Op(Exchange, wasmExchange); +})(); + +(function TestAtomicExchange8U() { + print("TestAtomicExchange8U"); + let wasmExchange = GetAtomicBinOpFunction(kExprI32AtomicExchange8U); + Test8Op(Exchange, wasmExchange); +})(); + +function TestCmpExchange(func, buffer, params, size) { + for (let i = 0; i < buffer.length; i++) { + for (let j = 0; j < params.length; j++) { + for (let k = 0; k < params.length; k++) { + buffer[i] = params[j]; + let loaded = func(i * size, params[k], params[j]) >>> 0; + let expected = (params[k] == loaded) ? params[j] : loaded; + assertEquals(loaded, params[j]); + assertEquals(expected, buffer[i]); + } + } + } + VerifyBoundsCheck(func, size); +} + +(function TestAtomicCompareExchange() { + print("TestAtomicCompareExchange"); + let wasmCmpExchange = + GetAtomicCmpExchangeFunction(kExprI32AtomicCompareExchange); + let i32 = new Uint32Array(memory.buffer); + let params = [0x00000001, 0x00000555, 0x00099999, 0xffffffff]; + TestCmpExchange(wasmCmpExchange, i32, params, kMemtypeSize32); +})(); + +(function TestAtomicCompareExchange16U() { + print("TestAtomicCompareExchange16U"); + let wasmCmpExchange = + GetAtomicCmpExchangeFunction(kExprI32AtomicCompareExchange16U); + let i16 = new Uint16Array(memory.buffer); + let params = [0x0001, 0x0555, 0x9999]; + TestCmpExchange(wasmCmpExchange, i16, params, kMemtypeSize16); +})(); + +(function TestAtomicCompareExchange8U() { + print("TestAtomicCompareExchange8U"); + let wasmCmpExchange = + GetAtomicCmpExchangeFunction(kExprI32AtomicCompareExchange8U); + let i8 = new Uint8Array(memory.buffer); + let params = [0x01, 0x0d, 0xf9]; + TestCmpExchange(wasmCmpExchange, i8, params, kMemtypeSize8); +})(); diff --git a/deps/v8/test/mjsunit/wasm/compiled-module-management.js b/deps/v8/test/mjsunit/wasm/compiled-module-management.js index 80a19c3b6c..f2777d1b03 100644 --- a/deps/v8/test/mjsunit/wasm/compiled-module-management.js +++ b/deps/v8/test/mjsunit/wasm/compiled-module-management.js @@ -68,4 +68,6 @@ gc(); })(); gc(); +// the first GC will clear the module, the second the instance. +gc(); %ValidateWasmOrphanedInstance(instance4); diff --git a/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js b/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js index 80840e3535..0ec3296b03 100644 --- a/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js +++ b/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js @@ -189,7 +189,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); kExprCallIndirect, sig_index1, kTableZero]) // -- .exportAs("main"); - builder.setFunctionTableLength(kTableSize); + builder.setFunctionTableBounds(kTableSize, kTableSize); builder.addFunctionTableInit(0, false, [f1.index]); builder.addExportOfKind("table", kExternalTable, 0); diff --git a/deps/v8/test/mjsunit/wasm/errors.js b/deps/v8/test/mjsunit/wasm/errors.js index 5910bc3449..89066d671a 100644 --- a/deps/v8/test/mjsunit/wasm/errors.js +++ b/deps/v8/test/mjsunit/wasm/errors.js @@ -27,18 +27,8 @@ function instance(bytes, imports = {}) { // instantiate should succeed but run should fail. function instantiateAndFailAtRuntime(bytes, imports = {}) { - var instance = undefined; - try { - instance = new WebAssembly.Instance(module(bytes), imports); - } catch(e) { - // If we fail at startup. - if (e instanceof WebAssembly.RuntimeError) { - throw e; - } - // Swallow other instantiation errors because we expect instantiation - // to succeed but runtime to fail. - return; - } + var instance = + assertDoesNotThrow(new WebAssembly.Instance(module(bytes), imports)); instance.exports.run(); } @@ -46,59 +36,65 @@ function builder() { return new WasmModuleBuilder; } -function assertCompileError(bytes) { - assertThrows(() => module(bytes), WebAssembly.CompileError); +function assertCompileError(bytes, msg) { + assertThrows(() => module(bytes), WebAssembly.CompileError, msg); } // default imports to {} so we get LinkError by default, thus allowing us to // distinguish the TypeError we want to catch -function assertTypeError(bytes, imports = {}) { - assertThrows(() => instance(bytes, imports), TypeError); +function assertTypeError(bytes, imports = {}, msg) { + assertThrows(() => instance(bytes, imports), TypeError, msg); } -function assertLinkError(bytes, imports) { - assertThrows(() => instance(bytes, imports), WebAssembly.LinkError); +function assertLinkError(bytes, imports, msg) { + assertThrows(() => instance(bytes, imports), WebAssembly.LinkError, msg); } -function assertRuntimeError(bytes, imports) { - assertThrows(() => instantiateAndFailAtRuntime(bytes, imports), - WebAssembly.RuntimeError); +function assertRuntimeError(bytes, imports, msg) { + assertThrows( + () => instantiateAndFailAtRuntime(bytes, imports), + WebAssembly.RuntimeError, msg); } -function assertConversionError(bytes, imports) { - assertThrows(() => instantiateAndFailAtRuntime(bytes, imports), TypeError); +function assertConversionError(bytes, imports, msg) { + assertThrows( + () => instantiateAndFailAtRuntime(bytes, imports), TypeError, msg); } (function TestDecodingError() { - assertCompileError(""); - assertCompileError("X"); - assertCompileError("\0x00asm"); + assertCompileError("", /is empty/); + assertCompileError("X", /expected 4 bytes, fell off end @\+0/); + assertCompileError( + "\0x00asm", /expected magic word 00 61 73 6d, found 00 78 30 30 @\+0/); })(); (function TestValidationError() { - assertCompileError(builder().addFunction("f", kSig_i_v).end().toBuffer()); + assertCompileError( + builder().addFunction("f", kSig_i_v).end().toBuffer(), + /function body must end with "end" opcode @/); assertCompileError(builder().addFunction("f", kSig_i_v).addBody([ kExprReturn - ]).end().toBuffer()); + ]).end().toBuffer(), /return found empty stack @/); assertCompileError(builder().addFunction("f", kSig_v_v).addBody([ kExprGetLocal, 0 - ]).end().toBuffer()); - assertCompileError(builder().addStart(0).toBuffer()); + ]).end().toBuffer(), /invalid local index: 0 @/); + assertCompileError( + builder().addStart(0).toBuffer(), /function index 0 out of bounds/); })(); (function TestTypeError() { let b; b = builder(); b.addImport("foo", "bar", kSig_v_v); - assertTypeError(b.toBuffer(), {}); + assertTypeError(b.toBuffer(), {}, /module is not an object or function/); b = builder(); b.addImportedGlobal("foo", "bar", kWasmI32); - assertTypeError(b.toBuffer(), {}); + assertTypeError(b.toBuffer(), {}, /module is not an object or function/); b = builder(); b.addImportedMemory("foo", "bar"); - assertTypeError(b.toBuffer(), {}); + assertTypeError(b.toBuffer(), {}, /module is not an object or function/); })(); (function TestLinkingError() { @@ -106,53 +102,60 @@ function assertConversionError(bytes, imports) { b = builder(); b.addImport("foo", "bar", kSig_v_v); - assertLinkError(b.toBuffer(), {foo: {}}); + assertLinkError( + b.toBuffer(), {foo: {}}, /function import requires a callable/); b = builder(); b.addImport("foo", "bar", kSig_v_v); - assertLinkError(b.toBuffer(), {foo: {bar: 9}}); + assertLinkError( + b.toBuffer(), {foo: {bar: 9}}, /function import requires a callable/); b = builder(); b.addImportedGlobal("foo", "bar", kWasmI32); - assertLinkError(b.toBuffer(), {foo: {}}); + assertLinkError(b.toBuffer(), {foo: {}}, /global import must be a number/); b = builder(); b.addImportedGlobal("foo", "bar", kWasmI32); - assertLinkError(b.toBuffer(), {foo: {bar: ""}}); + assertLinkError( + b.toBuffer(), {foo: {bar: ""}}, /global import must be a number/); b = builder(); b.addImportedGlobal("foo", "bar", kWasmI32); - assertLinkError(b.toBuffer(), {foo: {bar: () => 9}}); + assertLinkError( + b.toBuffer(), {foo: {bar: () => 9}}, /global import must be a number/); b = builder(); b.addImportedMemory("foo", "bar"); - assertLinkError(b.toBuffer(), {foo: {}}); + assertLinkError( + b.toBuffer(), {foo: {}}, + /memory import must be a WebAssembly\.Memory object/); b = builder(); b.addImportedMemory("foo", "bar", 1); - assertLinkError(b.toBuffer(), - {foo: {bar: () => new WebAssembly.Memory({initial: 0})}}); + assertLinkError( + b.toBuffer(), {foo: {bar: () => new WebAssembly.Memory({initial: 0})}}, + /memory import must be a WebAssembly\.Memory object/); b = builder(); b.addFunction("startup", kSig_v_v).addBody([ kExprUnreachable, ]).end().addStart(0); - assertRuntimeError(b.toBuffer()); + assertRuntimeError(b.toBuffer(), {}, "unreachable"); })(); (function TestTrapError() { assertRuntimeError(builder().addFunction("run", kSig_v_v).addBody([ kExprUnreachable - ]).exportFunc().end().toBuffer()); + ]).exportFunc().end().toBuffer(), {}, "unreachable"); assertRuntimeError(builder().addFunction("run", kSig_v_v).addBody([ kExprI32Const, 1, kExprI32Const, 0, kExprI32DivS, kExprDrop - ]).exportFunc().end().toBuffer()); + ]).exportFunc().end().toBuffer(), {}, "divide by zero"); - assertRuntimeError(builder().addFunction("run", kSig_v_v).addBody([ - ]).exportFunc().end(). - addFunction("start", kSig_v_v).addBody([ - kExprUnreachable - ]).end().addStart(1).toBuffer()); + assertRuntimeError(builder(). + addFunction("run", kSig_v_v).addBody([]).exportFunc().end(). + addFunction("start", kSig_v_v).addBody([kExprUnreachable]).end(). + addStart(1).toBuffer(), + {}, "unreachable"); })(); (function TestConversionError() { @@ -160,10 +163,10 @@ function assertConversionError(bytes, imports) { b.addImport("foo", "bar", kSig_v_l); assertConversionError(b.addFunction("run", kSig_v_v).addBody([ kExprI64Const, 0, kExprCallFunction, 0 - ]).exportFunc().end().toBuffer(), {foo:{bar: (l)=>{}}}); + ]).exportFunc().end().toBuffer(), {foo:{bar: (l)=>{}}}, "invalid type"); b = builder() assertConversionError(builder().addFunction("run", kSig_l_v).addBody([ kExprI64Const, 0 - ]).exportFunc().end().toBuffer()); + ]).exportFunc().end().toBuffer(), {}, "invalid type"); })(); diff --git a/deps/v8/test/mjsunit/wasm/exceptions.js b/deps/v8/test/mjsunit/wasm/exceptions.js index dc5d1e5f32..8fcfd15ff4 100644 --- a/deps/v8/test/mjsunit/wasm/exceptions.js +++ b/deps/v8/test/mjsunit/wasm/exceptions.js @@ -7,6 +7,73 @@ load("test/mjsunit/wasm/wasm-constants.js"); load("test/mjsunit/wasm/wasm-module-builder.js"); +// The following method doesn't attempt to catch an raised exception. +var test_throw = (function () { + var builder = new WasmModuleBuilder(); + + builder.addException(kSig_v_v); + + builder.addFunction("throw_if_param_not_zero", kSig_i_i) + .addBody([ + kExprGetLocal, 0, + kExprI32Const, 0, + kExprI32Ne, + kExprIf, kWasmStmt, + kExprThrow, 0, + kExprEnd, + kExprI32Const, 1 + ]).exportFunc(); + + return builder.instantiate(); +})(); + +// Check the test_throw exists. +assertFalse(test_throw === undefined); +assertFalse(test_throw === null); +assertFalse(test_throw === 0); +assertEquals("object", typeof test_throw.exports); +assertEquals("function", typeof test_throw.exports.throw_if_param_not_zero); + +// Test expected behavior of throws +assertEquals(1, test_throw.exports.throw_if_param_not_zero(0)); +assertWasmThrows([], function() { test_throw.exports.throw_if_param_not_zero(10) }); +assertWasmThrows([], function() { test_throw.exports.throw_if_param_not_zero(-1) }); + +// Now that we know throwing works, we test catching the exceptions we raise. +var test_catch = (function () { + var builder = new WasmModuleBuilder(); + + builder.addException(kSig_v_v); + builder.addFunction("simple_throw_catch_to_0_1", kSig_i_i) + .addBody([ + kExprTry, kWasmI32, + kExprGetLocal, 0, + kExprI32Eqz, + kExprIf, kWasmStmt, + kExprThrow, 0, + kExprEnd, + kExprI32Const, 1, + kExprCatch, 0, + kExprI32Const, 0, + kExprEnd + ]).exportFunc(); + + return builder.instantiate(); +})(); + +// Check the test_catch exists. +assertFalse(test_catch === undefined); +assertFalse(test_catch === null); +assertFalse(test_catch === 0); +assertEquals("object", typeof test_catch.exports); +assertEquals("function", typeof test_catch.exports.simple_throw_catch_to_0_1); + +// Test expected behavior of simple catch. +assertEquals(0, test_catch.exports.simple_throw_catch_to_0_1(0)); +assertEquals(1, test_catch.exports.simple_throw_catch_to_0_1(1)); + +/* TODO(kschimpf) Convert these tests to work for the proposed exceptions. + // The following methods do not attempt to catch the exception they raise. var test_throw = (function () { var builder = new WasmModuleBuilder(); @@ -229,16 +296,16 @@ var test_catch = (function () { kExprI32Eq, kExprIf, kWasmStmt, kExprGetLocal, 2, - kExprI32Const, /*64=*/ 192, 0, + kExprI32Const, / *64=* / 192, 0, kExprI32Ior, kExprThrow, kExprUnreachable, kExprEnd, - kExprI32Const, /*128=*/ 128, 1, + kExprI32Const, / *128=* / 128, 1, kExprI32Ior, kExprCatch, 1, kExprGetLocal, 1, - kExprI32Const, /*256=*/ 128, 2, + kExprI32Const, / *256=* / 128, 2, kExprI32Ior, kExprEnd, ]) @@ -252,7 +319,7 @@ var test_catch = (function () { kExprTry, kWasmI32, kExprGetLocal, 0, kExprCallFunction, kWasmThrowFunction, - kExprI32Const, /*-1=*/ 127, + kExprI32Const, / *-1=* / 127, kExprCatch, 1, kExprGetLocal, 1, kExprEnd @@ -287,7 +354,7 @@ var test_catch = (function () { kExprGetLocal, 0, kExprI32Const, 0, kExprCallFunction, kFromIndirectCalleeHelper, - kExprI32Const, /*-1=*/ 127, + kExprI32Const, / *-1=* / 127, kExprCatch, 1, kExprGetLocal, 1, kExprEnd @@ -301,7 +368,7 @@ var test_catch = (function () { kExprTry, kWasmI32, kExprGetLocal, 0, kExprCallFunction, kJSThrowI, - kExprI32Const, /*-1=*/ 127, + kExprI32Const, / *-1=* / 127, kExprCatch, 1, kExprGetLocal, 1, kExprEnd, @@ -381,3 +448,4 @@ assertEquals(-10, test_catch.exports.from_js(-10)); assertThrowsEquals(test_catch.exports.string_from_js, "use wasm;"); assertThrowsEquals(test_catch.exports.large_from_js, 1e+28); assertThrowsEquals(test_catch.exports.undefined_from_js, undefined); +*/ diff --git a/deps/v8/test/mjsunit/wasm/export-global.js b/deps/v8/test/mjsunit/wasm/export-global.js index 470851d87c..43c788c02e 100644 --- a/deps/v8/test/mjsunit/wasm/export-global.js +++ b/deps/v8/test/mjsunit/wasm/export-global.js @@ -56,3 +56,20 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); () => builder.instantiate(), WebAssembly.CompileError, /Duplicate export name 'foo' for global 0 and function 0/); })(); + +(function veryLongExportName() { + // Regression test for crbug.com/740023. + var export_name = 'abc'; + while (export_name.length < 8192) { + export_name = export_name.concat(export_name); + } + var builder = new WasmModuleBuilder(); + var global = builder.addGlobal(kWasmI64, false); + global.exportAs(export_name); + global.exportAs(export_name); + var error_msg = + 'Duplicate export name \'(abc){10,20}ab?c?\.\.\.\' for global 0 and global 0'; + assertThrows( + () => builder.instantiate(), WebAssembly.CompileError, + new RegExp(error_msg)); +})(); diff --git a/deps/v8/test/mjsunit/wasm/grow-memory-in-branch.js b/deps/v8/test/mjsunit/wasm/grow-memory-in-branch.js new file mode 100644 index 0000000000..f0e526fcc9 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/grow-memory-in-branch.js @@ -0,0 +1,292 @@ +// Copyright 2017 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-wasm --stress-compaction + +load('test/mjsunit/wasm/wasm-constants.js'); +load('test/mjsunit/wasm/wasm-module-builder.js'); + +var initialMemoryPages = 1; +var maximumMemoryPages = 5; + +function generateBuilder() { + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + builder.addFunction('load', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0]) + .exportFunc(); + builder.addFunction('store', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, kExprGetLocal, 1, + kExprI32StoreMem, 0, 0, kExprGetLocal, 1 + ]) + .exportFunc(); + return builder; +} + +// This test verifies that the effects of growing memory in an if branch +// affect the result of current_memory when the branch is merged. +(function TestGrowMemoryInIfBranchNoElse() { + print('TestGrowMemoryInIfBranchNoElse ...'); + let deltaPages = 4; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_i) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprI32Const, deltaPages, // put deltaPages on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprEnd, + kExprMemorySize, kMemoryZero // get the memory size + ]) + .exportFunc(); + var instance = builder.instantiate(); + // Avoid the if branch (not growing memory). + assertEquals(initialMemoryPages, instance.exports.main(0)); + // Enter the if branch (growing memory). + assertEquals(initialMemoryPages + deltaPages, instance.exports.main(1)); +})(); + +// This test verifies that the effects of growing memory in an if branch are +// retained when the branch is merged even when an else branch exists. +(function TestGrowMemoryInIfBranchWithElse() { + print('TestGrowMemoryInIfBranchWithElse ...'); + let index = 0; + let oldValue = 21; + let newValue = 42; + let deltaPages = 4; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_i) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprI32Const, deltaPages, // put deltaPages on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprElse, + kExprI32Const, index, // put index on stack + kExprI32Const, newValue, // put the value on stack + kExprI32StoreMem, 0, 0, // store + kExprEnd, + kExprMemorySize, kMemoryZero // get the memory size + ]) + .exportFunc(); + var instance = builder.instantiate(); + // Initialize the memory location with oldValue. + instance.exports.store(index, oldValue); + assertEquals(oldValue, instance.exports.load(index)); + // Verify that the else branch (not growing) is reachable. + assertEquals(initialMemoryPages, instance.exports.main(0)); + assertEquals(newValue, instance.exports.load(index)); + // Enter the if branch (growing memory). + assertEquals(initialMemoryPages + deltaPages, instance.exports.main(1)); +})(); + +// This test verifies that the effects of growing memory in an else branch +// affect the result of current_memory when the branch is merged. +(function TestGrowMemoryInElseBranch() { + print('TestGrowMemoryInElseBranch ...'); + let index = 0; + let oldValue = 21; + let newValue = 42; + let deltaPages = 4; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_i) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprI32Const, index, // put index on stack + kExprI32Const, newValue, // put the value on stack + kExprI32StoreMem, 0, 0, // store + kExprElse, + kExprI32Const, deltaPages, // put deltaPages on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprEnd, + kExprMemorySize, kMemoryZero // get the memory size + ]) + .exportFunc(); + var instance = builder.instantiate(); + // Initialize the memory location with oldValue. + instance.exports.store(index, oldValue); + assertEquals(oldValue, instance.exports.load(index)); + // Verify that the if branch (not growing) is reachable. + assertEquals(initialMemoryPages, instance.exports.main(1)); + assertEquals(newValue, instance.exports.load(index)); + // Enter the else branch (growing memory). + assertEquals(initialMemoryPages + deltaPages, instance.exports.main(0)); +})(); + +// This test verifies that the effects of growing memory in an if/else +// branch affect the result of current_memory when the branches are merged. +(function TestGrowMemoryInBothIfAndElse() { + print('TestGrowMemoryInBothIfAndElse ...'); + let deltaPagesIf = 1; + let deltaPagesElse = 2; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_i) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprI32Const, deltaPagesIf, // put deltaPagesIf on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprElse, + kExprI32Const, deltaPagesElse, // put deltaPagesElse on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprEnd, + kExprMemorySize, kMemoryZero // get the memory size + ]) + .exportFunc(); + var instance = builder.instantiate(); + // Enter the if branch (growing memory by 1 page). + assertEquals(initialMemoryPages + deltaPagesIf, instance.exports.main(1)); + // Create a new instance for the testing the else branch. + var instance = builder.instantiate(); + // Enter the else branch (growing memory by 2 pages). + assertEquals(initialMemoryPages + deltaPagesElse, instance.exports.main(0)); +})(); + +// This test verifies that the effects of growing memory in an if branch are +// retained when the branch is merged. +(function TestGrowMemoryAndStoreInIfBranchNoElse() { + print('TestGrowMemoryAndStoreInIfBranchNoElse ...'); + let index = 2 * kPageSize - 4; + let value = 42; + let deltaPages = 1; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprI32Const, deltaPages, // put deltaPages on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprGetLocal, 1, // get index parameter + kExprI32Const, value, // put the value on stack + kExprI32StoreMem, 0, 0, // store + kExprEnd, + kExprGetLocal, 1, // get index parameter + kExprI32LoadMem, 0, 0 // load from grown memory + ]) + .exportFunc(); + var instance = builder.instantiate(); + + // Avoid the if branch (not growing memory). This should trap when executing + // the kExprI32LoadMem instruction at the end of main. + assertTraps(kTrapMemOutOfBounds, () => instance.exports.main(0, index)); + // Enter the if branch (growing memory). + assertEquals(value, instance.exports.main(1, index)); +})(); + +// This test verifies that the effects of growing memory in an if branch are +// retained when the branch is merged even when an else branch exists. +(function TestGrowMemoryAndStoreInIfBranchWithElse() { + print('TestGrowMemoryAndStoreInIfBranchWithElse ...'); + let index = 2 * kPageSize - 4; + let value = 42; + let deltaPages = 1; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprI32Const, deltaPages, // put deltaPages on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprGetLocal, 1, // get index parameter + kExprI32Const, value, // put the value on stack + kExprI32StoreMem, 0, 0, // store + kExprElse, + kExprGetLocal, 1, // get index parameter + kExprI32Const, value, // put the value on stack + kExprI32StoreMem, 0, 0, // store + kExprEnd, + kExprGetLocal, 1, // get index parameter + kExprI32LoadMem, 0, 0 // load from grown memory + ]) + .exportFunc(); + var instance = builder.instantiate(); + // Avoid the if branch (not growing memory). This should trap when executing + // the kExprI32StoreMem instruction in the if branch. + assertTraps(kTrapMemOutOfBounds, () => instance.exports.main(0, index)); + // Enter the if branch (growing memory). + assertEquals(value, instance.exports.main(1, index)); +})(); + +// This test verifies that the effects of growing memory in an else branch are +// retained when the branch is merged. +(function TestGrowMemoryAndStoreInElseBranch() { + print('TestGrowMemoryAndStoreInElseBranch ...'); + let index = 2 * kPageSize - 4; + let value = 42; + let deltaPages = 1; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprGetLocal, 1, // get index parameter + kExprI32Const, value, // put the value on stack + kExprI32StoreMem, 0, 0, // store + kExprElse, + kExprI32Const, deltaPages, // put deltaPages on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprGetLocal, 1, // get index parameter + kExprI32Const, value, // put the value on stack + kExprI32StoreMem, 0, 0, // store + kExprEnd, + kExprGetLocal, 1, // get index parameter + kExprI32LoadMem, 0, 0 // load from grown memory + ]) + .exportFunc(); + var instance = builder.instantiate(); + // Avoid the else branch (not growing memory). This should trap when executing + // the kExprI32StoreMem instruction in the else branch. + assertTraps(kTrapMemOutOfBounds, () => instance.exports.main(1, index)); + // Enter the else branch (growing memory). + assertEquals(value, instance.exports.main(0, index)); +})(); + +// This test verifies that the effects of growing memory in an if/else branch +// are retained when the branch is merged. +(function TestGrowMemoryAndStoreInBothIfAndElse() { + print('TestGrowMemoryAndStoreInBothIfAndElse ...'); + let index = 0; + let valueIf = 21; + let valueElse = 42; + let deltaPagesIf = 1; + let deltaPagesElse = 2; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, // get condition parameter + kExprIf, kWasmStmt, // if it's 1 then enter if + kExprI32Const, deltaPagesIf, // put deltaPagesIf on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprGetLocal, 1, // get index parameter + kExprI32Const, valueIf, // put valueIf on stack + kExprI32StoreMem, 0, 0, // store + kExprElse, + kExprI32Const, deltaPagesElse, // put deltaPagesElse on stack + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprGetLocal, 1, // get index parameter + kExprI32Const, valueElse, // put valueElse on stack + kExprI32StoreMem, 0, 0, // store + kExprEnd, + kExprGetLocal, 1, // get index parameter + kExprI32LoadMem, 0, 0 // load from grown memory + ]) + .exportFunc(); + var instance = builder.instantiate(); + // Enter the if branch (growing memory by 1 page). + assertEquals(valueIf, instance.exports.main(1, index)); + // Enter the else branch (growing memory by 2 pages). + assertEquals(valueElse, instance.exports.main(0, index)); +})(); diff --git a/deps/v8/test/mjsunit/wasm/grow-memory-in-call.js b/deps/v8/test/mjsunit/wasm/grow-memory-in-call.js new file mode 100644 index 0000000000..750e76905a --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/grow-memory-in-call.js @@ -0,0 +1,437 @@ +// Copyright 2017 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-wasm --stress-compaction + +load('test/mjsunit/wasm/wasm-constants.js'); +load('test/mjsunit/wasm/wasm-module-builder.js'); + +var initialMemoryPages = 1; +var maximumMemoryPages = 5; + +// Grow memory in directly called functions. +print('=== grow_memory in direct calls ==='); + +// This test verifies that the current_memory instruction returns the correct +// value after returning from a function (direct call) that grew memory. +(function TestGrowMemoryInFunction() { + print('TestGrowMemoryInFunction ...'); + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + builder.addFunction('main', kSig_i_i) + .addBody([ + kExprGetLocal, 0, // get number of new pages + kExprCallFunction, kGrowFunction, // call the grow function + kExprDrop, // drop the result of grow + kExprMemorySize, kMemoryZero // get the memory size + ]) + .exportFunc(); + var instance = builder.instantiate(); + // The caller should be aware that the memory was grown by the callee. + var deltaPages = 1; + assertEquals( + initialMemoryPages + deltaPages, instance.exports.main(deltaPages)); +})(); + +// This test verifies that accessing a memory page that has been created inside +// a function (direct call) does not trap in the caller. +(function TestGrowMemoryAndAccessInFunction() { + print('TestGrowMemoryAndAccessInFunction ...'); + let index = 2 * kPageSize - 4; + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + builder.addFunction('load', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0]) + .exportFunc(); + builder.addFunction('main', kSig_v_iii) + .addBody([ + kExprGetLocal, 0, // get number of new pages + kExprCallFunction, kGrowFunction, // call the grow function + kExprDrop, // drop the result of grow + kExprGetLocal, 1, // get index + kExprGetLocal, 2, // get value + kExprI32StoreMem, 0, 0 // store + ]) + .exportFunc(); + var instance = builder.instantiate(); + assertTraps(kTrapMemOutOfBounds, () => instance.exports.load(index)); + var deltaPages = 1; + instance.exports.main(deltaPages, index, 1234); + // The caller should be able to access memory that was grown by the callee. + assertEquals(1234, instance.exports.load(index)); +})(); + +// This test verifies that when a function (direct call) grows and store +// something in the grown memory, the caller always reads from the grown +// memory. This checks that the memory start address gets updated in the caller. +(function TestGrowMemoryAndStoreInFunction() { + print('TestGrowMemoryAndStoreInFunction ...'); + let index = 0; + let oldValue = 21; + let newValue = 42; + let deltaPages = 1; + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_v_v) + .addBody([ + kExprI32Const, deltaPages, // always grow memory by deltaPages + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprI32Const, index, // put index on stack + kExprI32Const, newValue, // put new value on stack + kExprI32StoreMem, 0, 0 // store + ]) + .exportFunc() + .index; + builder.addFunction('main', kSig_i_i) + .addBody([ + kExprI32Const, index, // put index on stack + kExprI32Const, oldValue, // put old value on stack + kExprI32StoreMem, 0, 0, // store + kExprCallFunction, kGrowFunction, // call grow_and_store + kExprI32Const, index, // put index on stack + kExprI32LoadMem, 0, 0 // load from grown memory + ]) + .exportFunc(); + var instance = builder.instantiate(); + // The caller should always read from grown memory. + assertEquals(newValue, instance.exports.main()); +})(); + +// This test verifies that the effects of growing memory in an directly +// called function inside a loop affect the result of current_memory when +// the loop is over. +(function TestGrowMemoryInFunctionInsideLoop() { + print('TestGrowMemoryInFunctionInsideLoop ...'); + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + builder.addFunction('main', kSig_i_ii) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprGetLocal, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + // Grow memory. + kExprGetLocal, 1, // get number of new pages + kExprCallFunction, kGrowFunction, // call the grow function + kExprDrop, // drop the result of grow + // Decrease loop variable. + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 0, // decrease <param0> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Return the memory size. + kExprMemorySize, kMemoryZero // put memory size on stack + // clang-format on + ]) + .exportFunc(); + // The caller should be aware that the memory was grown by the callee. + let instance = builder.instantiate(); + let iterations = 4; + let deltaPages = 1; + assertEquals( + initialMemoryPages + iterations * deltaPages, + instance.exports.main(iterations, deltaPages)); +})(); + +// This test verifies that the effects of writing to memory grown in an +// directly called function inside a loop are retained when the loop is over. +(function TestGrowMemoryAndStoreInFunctionInsideLoop() { + print('TestGrowMemoryAndStoreInFunctionInsideLoop ...'); + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + builder.addFunction('store', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, kExprGetLocal, 1, kExprI32StoreMem, 0, 0, + kExprGetLocal, 1 + ]) + .exportFunc(); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + // parameters: iterations, deltaPages, index + builder.addFunction('main', kSig_i_iii) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprGetLocal, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + // Grow memory. + kExprGetLocal, 1, // get number of new pages + kExprCallFunction, kGrowFunction, // call the grow function + kExprDrop, // drop the result of grow + // Increase counter in memory. + kExprGetLocal, 2, // put index (for store) + kExprGetLocal, 2, // put index (for load) + kExprI32LoadMem, 0, 0, // load from grown memory + kExprI32Const, 1, // - + kExprI32Add, // increase counter + kExprI32StoreMem, 0, 0, // store counter in memory + // Decrease loop variable. + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 0, // decrease <param0> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Return the value + kExprGetLocal, 2, // - + kExprI32LoadMem, 0, 0 // load from grown memory + // clang-format on + ]) + .exportFunc(); + // The caller should always read the correct memory + let instance = builder.instantiate(); + let iterations = 4; + let deltaPages = 1; + let index = 0; + let initialValue = 1; + let expectedValue = initialValue + iterations; + instance.exports.store(index, initialValue); + assertEquals( + expectedValue, instance.exports.main(iterations, deltaPages, index)); +})(); + +// Grow memory in indirectly called functions. +print('\n=== grow_memory in indirect calls ==='); + +// This test verifies that the current_memory instruction returns the correct +// value after returning from a function (indirect call) that grew memory. +(function TestGrowMemoryInIndirectCall() { + print('TestGrowMemoryInIndirectCall ...'); + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + builder.addFunction('main', kSig_i_ii) + .addBody([ + kExprGetLocal, 1, // get number of new pages + kExprGetLocal, 0, // get index of the function + kExprCallIndirect, 0, kTableZero, // call the function + kExprDrop, // drop the result of grow + kExprMemorySize, kMemoryZero // get the memory size + ]) + .exportFunc(); + builder.appendToTable([kGrowFunction]); + var instance = builder.instantiate(); + // The caller should be aware that the memory was grown by the callee. + var deltaPages = 1; + assertEquals( + initialMemoryPages + deltaPages, + instance.exports.main(kGrowFunction, deltaPages)); +})(); + +// This test verifies that accessing a memory page that has been created inside +// a function (indirect call) does not trap in the caller. +(function TestGrowMemoryAndAccessInIndirectCall() { + print('TestGrowMemoryAndAccessInIndirectCall ...'); + let index = 2 * kPageSize - 4; + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + builder.addFunction('load', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0]) + .exportFunc(); + let sig = makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], []); + builder.addFunction('main', sig) + .addBody([ + kExprGetLocal, 1, // get number of new pages + kExprGetLocal, 0, // get index of the function + kExprCallIndirect, 0, kTableZero, // call the function + kExprDrop, // drop the result of grow + kExprGetLocal, 2, // get index + kExprGetLocal, 3, // get value + kExprI32StoreMem, 0, 0 // store + ]) + .exportFunc(); + builder.appendToTable([kGrowFunction]); + var instance = builder.instantiate(); + assertTraps(kTrapMemOutOfBounds, () => instance.exports.load(index)); + let deltaPages = 1; + let value = 1234; + instance.exports.main(kGrowFunction, deltaPages, index, value); + // The caller should be able to access memory that was grown by the callee. + assertEquals(value, instance.exports.load(index)); +})(); + +// This test verifies that when a function (indirect call) grows and store +// something in the grown memory, the caller always reads from the grown +// memory. This checks that the memory start address gets updated in the caller. +(function TestGrowMemoryAndStoreInIndirectCall() { + print('TestGrowMemoryAndStoreInIndirectCall ...'); + let index = 0; + let oldValue = 21; + let newValue = 42; + let deltaPages = 1; + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_v_v) + .addBody([ + kExprI32Const, deltaPages, // always grow memory by deltaPages + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprI32Const, index, // put index on stack + kExprI32Const, newValue, // put new value on stack + kExprI32StoreMem, 0, 0 // store + ]) + .exportFunc() + .index; + builder.addFunction('main', kSig_i_i) + .addBody([ + kExprI32Const, index, // put index on stack + kExprI32Const, oldValue, // put old value on stack + kExprI32StoreMem, 0, 0, // store + kExprGetLocal, 0, // get index of the function + kExprCallIndirect, 0, kTableZero, // call the function + kExprI32Const, index, // put index on stack + kExprI32LoadMem, 0, 0 // load from grown memory + ]) + .exportFunc(); + builder.appendToTable([kGrowFunction]); + var instance = builder.instantiate(); + // The caller should always read from grown memory. + assertEquals(42, instance.exports.main(kGrowFunction)); +})(); + +// This test verifies that the effects of growing memory in an indirectly +// called function inside a loop affect the result of current_memory when +// the loop is over. +(function TestGrowMemoryInIndirectCallInsideLoop() { + print('TestGrowMemoryInIndirectCallInsideLoop ...'); + let builder = new WasmModuleBuilder(); + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + builder.addFunction('main', kSig_i_iii) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprGetLocal, 1, // - + kExprIf, kWasmStmt, // if <param1> != 0 + // Grow memory. + kExprGetLocal, 2, // get number of new pages + kExprGetLocal, 0, // get index of the function + kExprCallIndirect, 0, kTableZero, // call the function + kExprDrop, // drop the result of grow + // Decrease loop variable. + kExprGetLocal, 1, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 1, // decrease <param1> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Return the memory size. + kExprMemorySize, kMemoryZero // put memory size on stack + // clang-format on + ]) + .exportFunc(); + builder.appendToTable([kGrowFunction]); + // The caller should be aware that the memory was grown by the callee. + let instance = builder.instantiate(); + let deltaPages = 1; + let iterations = 4; + assertEquals( + initialMemoryPages + iterations * deltaPages, + instance.exports.main(kGrowFunction, iterations, deltaPages)); +})(); + +// This test verifies that the effects of writing to memory grown in an +// indirectly called function inside a loop are retained when the loop is over. +(function TestGrowMemoryAndStoreInIndirectCallInsideLoop() { + print('TestGrowMemoryAndStoreInIndirectCallInsideLoop ...'); + let builder = new WasmModuleBuilder(); + let deltaPages = 1; + builder.addMemory(initialMemoryPages, maximumMemoryPages, true); + let kGrowFunction = + builder.addFunction('grow', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc() + .index; + builder.addFunction('store', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, kExprGetLocal, 1, kExprI32StoreMem, 0, 0, + kExprGetLocal, 1 + ]) + .exportFunc(); + builder + .addFunction( + // parameters: function_index, iterations, deltaPages, index + 'main', makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], [kWasmI32])) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprGetLocal, 1, // - + kExprIf, kWasmStmt, // if <param1> != 0 + // Grow memory. + kExprGetLocal, 2, // get number of new pages + kExprGetLocal, 0, // get index of the function + kExprCallIndirect, 0, kTableZero, // call the function + kExprDrop, // drop the result of grow + // Increase counter in memory. + kExprGetLocal, 3, // put index (for store) + kExprGetLocal, 3, // put index (for load) + kExprI32LoadMem, 0, 0, // load from grown memory + kExprI32Const, 1, // - + kExprI32Add, // increase counter + kExprI32StoreMem, 0, 0, // store counter in memory + // Decrease loop variable. + kExprGetLocal, 1, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 1, // decrease <param1> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Return the value + kExprGetLocal, 3, // - + kExprI32LoadMem, 0, 0 // load from grown memory + // clang-format on + ]) + .exportFunc(); + builder.appendToTable([kGrowFunction]); + // The caller should be aware that the memory was grown by the callee. + let instance = builder.instantiate(); + let iterations = 4; + let index = 0; + let initialValue = 1; + let expectedValue = initialValue + iterations; + instance.exports.store(index, initialValue); + assertEquals( + expectedValue, + instance.exports.main(kGrowFunction, iterations, deltaPages, index)); +})(); diff --git a/deps/v8/test/mjsunit/wasm/grow-memory-in-loop.js b/deps/v8/test/mjsunit/wasm/grow-memory-in-loop.js new file mode 100644 index 0000000000..8bb1018825 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/grow-memory-in-loop.js @@ -0,0 +1,253 @@ +// Copyright 2017 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-wasm --stress-compaction + +load('test/mjsunit/wasm/wasm-constants.js'); +load('test/mjsunit/wasm/wasm-module-builder.js'); + +let initialPages = 1; +let maximumPages = 6; + +function generateBuilder() { + let builder = new WasmModuleBuilder(); + builder.addMemory(initialPages, maximumPages, true); + builder.addFunction('store', kSig_i_ii) + .addBody([ + kExprGetLocal, 0, kExprGetLocal, 1, kExprI32StoreMem, 0, 0, + kExprGetLocal, 1 + ]) + .exportFunc(); + return builder; +} + +// This test verifies that the effects of growing memory inside a loop +// affect the result of current_memory when the loop is over. +(function TestGrowMemoryInsideLoop() { + print('TestGrowMemoryInsideLoop ...'); + let deltaPages = 1; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_i) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprGetLocal, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + // Grow memory. + kExprI32Const, deltaPages, // - + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + // Decrease loop variable. + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 0, // decrease <param0> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Return the memory size. + kExprMemorySize, kMemoryZero // put memory size on stack + // clang-format on + ]) + .exportFunc(); + { + // Avoid the loop branch (not growing memory). + let instance = builder.instantiate(); + let iterations = 0; + let expectedPages = initialPages + iterations * deltaPages; + assertTrue(expectedPages <= maximumPages); + assertEquals(expectedPages, instance.exports.main(iterations)); + } + { + // Enter the loop branch (growing memory). + let instance = builder.instantiate(); + let iterations = 2; + let expectedPages = initialPages + iterations * deltaPages; + assertTrue(expectedPages <= maximumPages); + assertEquals(expectedPages, instance.exports.main(iterations)); + } +})(); + +// This test verifies that a loop does not affect the result of current_memory +// when the memory is grown both inside and outside the loop. +(function TestGrowMemoryInsideAndOutsideLoop() { + print('TestGrowMemoryInsideAndOutsideLoop ...'); + let deltaPagesIn = 1; + let deltaPagesOut = 2; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_i) + .addBody([ + // clang-format off + // Grow memory. + kExprI32Const, deltaPagesOut, // - + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + kExprLoop, kWasmStmt, // while + kExprGetLocal, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + // Grow memory. + kExprI32Const, deltaPagesIn, // - + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + // Decrease loop variable. + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 0, // decrease <param0> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Return memory size. + kExprMemorySize, kMemoryZero // put memory size on stack + // clang-format on + ]) + .exportFunc(); + { + // Avoid the loop branch (grow memory by deltaPagesOut). + let instance = builder.instantiate(); + let iterations = 0; + let expectedPages = initialPages + deltaPagesOut; + assertTrue(expectedPages <= maximumPages); + assertEquals(expectedPages, instance.exports.main(iterations)); + } + { + // Avoid the loop branch (grow memory by deltaPagesOut + // + iterations * deltaPagesIn). + let instance = builder.instantiate(); + let iterations = 3; + let expectedPages = + initialPages + deltaPagesOut + (iterations * deltaPagesIn); + assertTrue(expectedPages <= maximumPages); + assertEquals(expectedPages, instance.exports.main(iterations)); + } +})(); + +// This test verifies that the effects of writing to memory grown inside a loop +// are retained when the loop is over. +(function TestGrowMemoryAndStoreInsideLoop() { + print('TestGrowMemoryAndStoreInsideLoop ...'); + let deltaPages = 1; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_ii) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprGetLocal, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + // Grow memory. + kExprI32Const, deltaPages, // - + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + // Increase counter in memory. + kExprGetLocal, 1, // put index (for store) + kExprGetLocal, 1, // put index (for load) + kExprI32LoadMem, 0, 0, // load from grown memory + kExprI32Const, 1, // - + kExprI32Add, // increase counter + kExprI32StoreMem, 0, 0, // store counter in memory + // Decrease loop variable. + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 0, // decrease <param0> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Increase counter in memory. + kExprGetLocal, 1, // - + kExprI32LoadMem, 0, 0 // load from grown memory + // clang-format on + ]) + .exportFunc(); + + let index = 0; + let initialValue = 1; + { + // Avoid the loop (not growing memory). + let instance = builder.instantiate(); + let iterations = 0; + let expectedValue = initialValue + iterations; + instance.exports.store(index, initialValue); + assertEquals(expectedValue, instance.exports.main(iterations, index)); + } + { + // Enter the loop (growing memory + increasing counter in grown memory). + let instance = builder.instantiate(); + let iterations = 2; + let expectedValue = initialValue + iterations; + instance.exports.store(index, initialValue); + assertEquals(expectedValue, instance.exports.main(iterations, index)); + } +})(); + +// This test verifies that a loop does not affect the memory when the +// memory is grown both inside and outside the loop. +(function TestGrowMemoryAndStoreInsideAndOutsideLoop() { + print('TestGrowMemoryAndStoreInsideAndOutsideLoop ...'); + let deltaPagesIn = 1; + let deltaPagesOut = 2; + let builder = generateBuilder(); + builder.addFunction('main', kSig_i_ii) + .addBody([ + // clang-format off + // Grow memory. + kExprI32Const, deltaPagesOut, // - + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + // Increase counter in memory. + kExprGetLocal, 1, // put index (for store) + kExprGetLocal, 1, // put index (for load) + kExprI32LoadMem, 0, 0, // load from grown memory + kExprI32Const, 1, // - + kExprI32Add, // increase value on stack + kExprI32StoreMem, 0, 0, // store new value + // Start loop. + kExprLoop, kWasmStmt, // while + kExprGetLocal, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + // Grow memory. + kExprI32Const, deltaPagesIn, // - + kExprGrowMemory, kMemoryZero, // grow memory + kExprDrop, // drop the result of grow + // Increase counter in memory. + kExprGetLocal, 1, // put index (for store) + kExprGetLocal, 1, // put index (for load) + kExprI32LoadMem, 0, 0, // load from grown memory + kExprI32Const, 1, // - + kExprI32Add, // increase value on stack + kExprI32StoreMem, 0, 0, // store new value + // Decrease loop variable. + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 0, // decrease <param0> + kExprBr, 1, // continue + kExprEnd, // end if + kExprEnd, // end loop + // Return counter from memory. + kExprGetLocal, 1, // put index on stack + kExprI32LoadMem, 0, 0 // load from grown memory + // clang-format on + ]) + .exportFunc(); + + let index = 0; + let initialValue = 1; + { + // Avoid the loop (grow memory and increment counter only outside the loop). + let instance = builder.instantiate(); + let iterations = 0; + let expectedValue = initialValue + 1; + instance.exports.store(index, initialValue); + assertEquals(expectedValue, instance.exports.main(iterations, index)); + } + { + // Enter the loop (grow memory and increment counter outside/inside loop). + let instance = builder.instantiate(); + let iterations = 3; + let expectedValue = initialValue + iterations + 1; + instance.exports.store(index, initialValue); + assertEquals(expectedValue, instance.exports.main(iterations, index)); + } +})(); diff --git a/deps/v8/test/mjsunit/wasm/grow-memory.js b/deps/v8/test/mjsunit/wasm/grow-memory.js index a428896847..fc82dc6004 100644 --- a/deps/v8/test/mjsunit/wasm/grow-memory.js +++ b/deps/v8/test/mjsunit/wasm/grow-memory.js @@ -7,8 +7,6 @@ load("test/mjsunit/wasm/wasm-constants.js"); load("test/mjsunit/wasm/wasm-module-builder.js"); -var kPageSize = 0x10000; -var kV8MaxPages = 32767; function genGrowMemoryBuilder() { var builder = new WasmModuleBuilder(); @@ -479,9 +477,8 @@ testGrowMemoryDeclaredMaxTraps(); function testGrowMemoryDeclaredSpecMaxTraps() { // The spec maximum is higher than the internal V8 maximum. This test only // checks that grow_memory does not grow past the internally defined maximum - // to reflect the currentl implementation. + // to reflect the current implementation. var builder = genGrowMemoryBuilder(); - var kSpecMaxPages = 65535; builder.addMemory(1, kSpecMaxPages, false); var module = builder.instantiate(); function poke(value) { return module.exports.store(offset, value); } diff --git a/deps/v8/test/mjsunit/wasm/import-memory.js b/deps/v8/test/mjsunit/wasm/import-memory.js index b5dd620546..1f0d847131 100644 --- a/deps/v8/test/mjsunit/wasm/import-memory.js +++ b/deps/v8/test/mjsunit/wasm/import-memory.js @@ -149,7 +149,6 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); (function TestGrowMemoryZeroInitialMemory() { print("ZeroInitialMemory"); - let kV8MaxPages = 32767; let memory = new WebAssembly.Memory({initial: 0}); assertEquals(0, memory.buffer.byteLength); let i32 = new Int32Array(memory.buffer); @@ -326,9 +325,6 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); })(); (function TestExportImportedMemoryGrowMultipleInstances() { - // TODO(gdeepti):Exported memory objects currently do not take max_size - // into account so this can grow past the maximum specified in the exported - // memory object. Assert that growing past maximum for exported objects fails. print("TestExportImportedMemoryGrowMultipleInstances"); var instance; { @@ -364,6 +360,40 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); assertEquals(current_mem_size, instances[i].exports.grow(1)); verify_mem_size(++current_mem_size); } + for (var i = 0; i < 10; i++) { + assertEquals(-1, instances[i].exports.grow(1)); + verify_mem_size(current_mem_size); + } +})(); + +(function TestExportImportedMemoryGrowPastV8Maximum() { + // The spec maximum is higher than the internal V8 maximum. This test only + // checks that grow_memory does not grow past the internally defined maximum + // to reflect the current implementation even when the memory is exported. + print("TestExportImportedMemoryGrowPastV8Maximum"); + var instance_1, instance_2; + { + let builder = new WasmModuleBuilder(); + builder.addMemory(1, kSpecMaxPages, true); + builder.exportMemoryAs("exported_mem"); + builder.addFunction("grow", kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc(); + instance_1 = builder.instantiate(); + } + { + let builder = new WasmModuleBuilder(); + builder.addImportedMemory("doo", "imported_mem"); + builder.addFunction("grow", kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGrowMemory, kMemoryZero]) + .exportFunc(); + instance_2 = builder.instantiate({ + doo: {imported_mem: instance_1.exports.exported_mem}}); + } + assertEquals(1, instance_1.exports.grow(20)); + assertEquals(21, instance_2.exports.grow(20)); + assertEquals(-1, instance_1.exports.grow(kV8MaxPages - 40)); + assertEquals(-1, instance_2.exports.grow(kV8MaxPages - 40)); })(); (function TestExportGrow() { diff --git a/deps/v8/test/mjsunit/wasm/indirect-calls.js b/deps/v8/test/mjsunit/wasm/indirect-calls.js index 4c906a0110..bcb7acd2ba 100644 --- a/deps/v8/test/mjsunit/wasm/indirect-calls.js +++ b/deps/v8/test/mjsunit/wasm/indirect-calls.js @@ -147,7 +147,7 @@ assertTraps(kTrapFuncInvalid, "module.exports.main(12, 3)"); kExprCallIndirect, 0, kTableZero]) // -- .exportAs("main"); - builder.setFunctionTableLength(length); + builder.setFunctionTableBounds(length, length); builder.addFunctionTableInit(base, false, [f.add.index, f.sub.index, f.mul.index]); return builder.instantiate(); @@ -184,7 +184,7 @@ assertTraps(kTrapFuncInvalid, "module.exports.main(12, 3)"); kExprCallIndirect, 0, kTableZero]) // -- .exportAs("main"); - builder.setFunctionTableLength(10); + builder.setFunctionTableBounds(10, 10); var g = builder.addImportedGlobal("fff", "base", kWasmI32); builder.addFunctionTableInit(g, true, [f.mul.index, f.add.index, f.sub.index]); diff --git a/deps/v8/test/mjsunit/wasm/indirect-tables.js b/deps/v8/test/mjsunit/wasm/indirect-tables.js index e3e6e00773..f158718f8d 100644 --- a/deps/v8/test/mjsunit/wasm/indirect-tables.js +++ b/deps/v8/test/mjsunit/wasm/indirect-tables.js @@ -49,7 +49,7 @@ function js_div(a, b) { return (a / b) | 0; } f.add.exportAs("blarg"); - builder.setFunctionTableLength(10); + builder.setFunctionTableBounds(10, 10); let g = builder.addImportedGlobal("q", "base", kWasmI32); builder.addFunctionTableInit(g, true, [f.mul.index, f.add.index, f.sub.index, @@ -109,7 +109,7 @@ function js_div(a, b) { return (a / b) | 0; } let d = builder.addImport("q", "js_div", kSig_i_ii); let f = AddFunctions(builder); - builder.setFunctionTableLength(kTableSize); + builder.setFunctionTableBounds(kTableSize, kTableSize); let g = builder.addImportedGlobal("q", "base", kWasmI32); builder.addFunctionTableInit(g, true, [f.mul.index, f.add.index, f.sub.index, @@ -141,7 +141,7 @@ function js_div(a, b) { return (a / b) | 0; } let main = i2.exports.main; for (var j = 0; j < i; j++) { - assertThrows(() => main(0, j)); + assertTraps(kTrapFuncSigMismatch, () => main(0, j)); assertSame(null, table.get(j)); } @@ -207,7 +207,7 @@ function js_div(a, b) { return (a / b) | 0; } let main = i2.exports.main; for (var j = 0; j < i; j++) { - assertThrows(() => main(0, j)); + assertTraps(kTrapFuncSigMismatch, () => main(0, j)); assertSame(null, table.get(j)); } @@ -300,7 +300,7 @@ function js_div(a, b) { return (a / b) | 0; } kExprCallIndirect, sig_index1, kTableZero]) // -- .exportAs("main"); - builder.setFunctionTableLength(kTableSize); + builder.setFunctionTableBounds(kTableSize, kTableSize); builder.addFunctionTableInit(0, false, [f1.index]); builder.addExportOfKind("table", kExternalTable, 0); @@ -335,11 +335,10 @@ function js_div(a, b) { return (a / b) | 0; } assertEquals(22, i1.exports.main(1)); assertEquals(22, i2.exports.main(1)); - assertThrows(() => i1.exports.main(2)); - assertThrows(() => i2.exports.main(2)); - assertThrows(() => i1.exports.main(3)); - assertThrows(() => i2.exports.main(3)); - + assertTraps(kTrapFuncSigMismatch, () => i1.exports.main(2)); + assertTraps(kTrapFuncSigMismatch, () => i2.exports.main(2)); + assertTraps(kTrapFuncInvalid, () => i1.exports.main(3)); + assertTraps(kTrapFuncInvalid, () => i2.exports.main(3)); })(); (function MismatchedTableSize() { @@ -350,7 +349,7 @@ function js_div(a, b) { return (a / b) | 0; } for (var impsize = 1; impsize < 4; impsize++) { print(" expsize = " + expsize + ", impsize = " + impsize); var builder = new WasmModuleBuilder(); - builder.setFunctionTableLength(expsize); + builder.setFunctionTableBounds(expsize, expsize); builder.addExportOfKind("expfoo", kExternalTable, 0); let m1 = new WebAssembly.Module(builder.toBuffer()); @@ -388,14 +387,14 @@ function js_div(a, b) { return (a / b) | 0; } assertEquals(i, table.length); for (var j = 0; j < i; j++) table.set(j, null); for (var j = 0; j < i; j++) assertEquals(null, table.get(j)); - assertThrows(() => table.set(i, null)); - assertThrows(() => table.get(i)); + assertThrows(() => table.set(i, null), RangeError); + assertThrows(() => table.get(i), RangeError); assertEquals(i, table.grow(5)); } assertEquals(30, table.length); - assertThrows(() => table.grow(1)); - assertThrows(() => table.set(kMaxSize, null)); - assertThrows(() => table.get(kMaxSize)); + assertThrows(() => table.grow(1), RangeError); + assertThrows(() => table.set(kMaxSize, null), RangeError); + assertThrows(() => table.get(kMaxSize), RangeError); })(); (function CumulativeGrowTest() { @@ -456,7 +455,7 @@ function js_div(a, b) { return (a / b) | 0; } assertEquals("function", typeof func); assertSame(new_func, table.get(j)); } - assertThrows(() => table.grow(11)); + assertThrows(() => table.grow(11), RangeError); })(); @@ -467,15 +466,15 @@ function js_div(a, b) { return (a / b) | 0; } // initial size is too large assertThrows(() => builder.instantiate({t: {t: new WebAssembly.Table( - {element: "anyfunc", initial: 3, maximum: 3})}})); + {element: "anyfunc", initial: 3, maximum: 3})}}), WebAssembly.LinkError); // maximum size is too large assertThrows(() => builder.instantiate({t: {t: new WebAssembly.Table( - {element: "anyfunc", initial: 1, maximum: 4})}})); + {element: "anyfunc", initial: 1, maximum: 4})}}), WebAssembly.LinkError); // no maximum assertThrows(() => builder.instantiate({t: {t: new WebAssembly.Table( - {element: "anyfunc", initial: 1})}})); + {element: "anyfunc", initial: 1})}}), WebAssembly.LinkError); })(); (function TableImportLargerThanCompiled() { @@ -489,7 +488,7 @@ function js_div(a, b) { return (a / b) | 0; } let instance = new WebAssembly.Instance(module, {x: {base: 1, table: table}}); for (var i = 0; i < kInitSize; ++i) table.set(i, null); for (var i = 0; i < kInitSize; ++i) assertEquals(null, table.get(i)); - assertThrows(() => table.set(kInitSize, null)); + assertThrows(() => table.set(kInitSize, null), RangeError); })(); (function ModulesShareTableAndGrow() { @@ -515,13 +514,13 @@ function js_div(a, b) { return (a / b) | 0; } for (var i = 0; i < kInitSize; ++i) table.set(i, null); for (var i = 0; i < kInitSize; ++i) assertEquals(null, table.get(i)); - assertThrows(() => table.set(kInitSize, null)); + assertThrows(() => table.set(kInitSize, null), RangeError); assertEquals(kInitSize, table.grow(5)); for (var i = 0; i < 2*kInitSize; ++i) table.set(i, null); for (var i = 0; i < 2*kInitSize; ++i) assertEquals(null, table.get(i)); - assertThrows(() => table.set(2*kInitSize, null)); + assertThrows(() => table.set(2*kInitSize, null), RangeError); // Try to grow past imported maximum - assertThrows(() => table.grow(21)); + assertThrows(() => table.grow(21), RangeError); })(); (function MultipleElementSegments() { @@ -539,7 +538,7 @@ function js_div(a, b) { return (a / b) | 0; } for (let num_segments = 1; num_segments < 4; ++num_segments) { var builder = new WasmModuleBuilder(); - builder.setFunctionTableLength(kTableSize); + builder.setFunctionTableBounds(kTableSize, kTableSize); builder.addExportOfKind("table", kExternalTable, 0); let f = AddFunctions(builder); let indexes = [f.mul.index, f.add.index, f.sub.index]; @@ -581,7 +580,7 @@ function js_div(a, b) { return (a / b) | 0; } kExprCallIndirect, sig_index, kTableZero ]) .exportAs('main'); - builder0.setFunctionTableLength(3); + builder0.setFunctionTableBounds(3, 3); builder0.addExportOfKind('table', kExternalTable); let module0 = new WebAssembly.Module(builder0.toBuffer()); let instance0 = new WebAssembly.Instance(module0); diff --git a/deps/v8/test/mjsunit/wasm/interpreter-mixed.js b/deps/v8/test/mjsunit/wasm/interpreter-mixed.js index e0249ce799..08cfc8c96d 100644 --- a/deps/v8/test/mjsunit/wasm/interpreter-mixed.js +++ b/deps/v8/test/mjsunit/wasm/interpreter-mixed.js @@ -12,6 +12,20 @@ load('test/mjsunit/wasm/wasm-module-builder.js'); // compiled code. // ============================================================================= +// The stack trace contains file path, replace it by "file". +let stripPath = s => s.replace(/[^ (]*interpreter-mixed\.js/g, 'file'); + +function checkStack(stack, expected_lines) { + print('stack: ' + stack); + let lines = stack.split('\n'); + assertEquals(expected_lines.length, lines.length); + for (let i = 0; i < lines.length; ++i) { + let test = + typeof expected_lines[i] == 'string' ? assertEquals : assertMatches; + test(expected_lines[i], lines[i], 'line ' + i); + } +} + (function testGrowMemoryBetweenInterpretedAndCompiled() { // grow_memory can be called from interpreted or compiled code, and changes // should be reflected in either execution. @@ -76,3 +90,106 @@ load('test/mjsunit/wasm/wasm-module-builder.js'); // Overall, we executed 9 functions in the interpreter. assertEquals(initial_interpreted + 9, %WasmNumInterpretedCalls(instance)); })(); + +function createTwoInstancesCallingEachOther(inner_throws = false) { + let builder1 = new WasmModuleBuilder(); + + let id_imp = builder1.addImport('q', 'id', kSig_i_i); + let plus_one = builder1.addFunction('plus_one', kSig_i_i) + .addBody([ + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Add, // - + kExprCallFunction, id_imp + ]) + .exportFunc(); + function imp(i) { + if (inner_throws) throw new Error('i=' + i); + return i; + } + let instance1 = builder1.instantiate({q: {id: imp}}); + + let builder2 = new WasmModuleBuilder(); + + let plus_one_imp = builder2.addImport('q', 'plus_one', kSig_i_i); + let plus_two = builder2.addFunction('plus_two', kSig_i_i) + .addBody([ + // Call import, add one more. + kExprGetLocal, 0, // - + kExprCallFunction, plus_one_imp, // - + kExprI32Const, 1, // - + kExprI32Add + ]) + .exportFunc(); + + let instance2 = + builder2.instantiate({q: {plus_one: instance1.exports.plus_one}}); + return [instance1, instance2]; +} + +function redirectToInterpreter( + instance1, instance2, redirect_plus_one, redirect_plus_two) { + // Redirect functions to the interpreter. + if (redirect_plus_one) { + %RedirectToWasmInterpreter(instance1, + parseInt(instance1.exports.plus_one.name)); + } + if (redirect_plus_two) { + %RedirectToWasmInterpreter(instance2, + parseInt(instance2.exports.plus_two.name)); + } +} + +(function testImportFromOtherInstance() { + print("testImportFromOtherInstance"); + // Three runs: Break in instance 1, break in instance 2, or both. + for (let run = 0; run < 3; ++run) { + print(" - run " + run); + let [instance1, instance2] = createTwoInstancesCallingEachOther(); + + let interpreted_before_1 = %WasmNumInterpretedCalls(instance1); + let interpreted_before_2 = %WasmNumInterpretedCalls(instance2); + // Call plus_two, which calls plus_one. + assertEquals(9, instance2.exports.plus_two(7)); + + // Nothing interpreted: + assertEquals(interpreted_before_1, %WasmNumInterpretedCalls(instance1)); + assertEquals(interpreted_before_2, %WasmNumInterpretedCalls(instance2)); + + // Now redirect functions to the interpreter. + redirectToInterpreter(instance1, instance2, run != 1, run != 0); + + // Call plus_two, which calls plus_one. + assertEquals(9, instance2.exports.plus_two(7)); + + // TODO(6668): Fix patching of instances which imported others' code. + //assertEquals(interpreted_before_1 + (run == 1 ? 0 : 1), + // %WasmNumInterpretedCalls(instance1)); + assertEquals(interpreted_before_2 + (run == 0 ? 0 : 1), + %WasmNumInterpretedCalls(instance2)); + } +})(); + +(function testStackTraceThroughCWasmEntry() { + print("testStackTraceThroughCWasmEntry"); + for (let run = 0; run < 3; ++run) { + print(" - run " + run); + let [instance1, instance2] = createTwoInstancesCallingEachOther(true); + redirectToInterpreter(instance1, instance2, run != 1, run != 0); + + try { + // Call plus_two, which calls plus_one. + instance2.exports.plus_two(7); + assertUnreachable('should trap because of unreachable instruction'); + } catch (e) { + checkStack(stripPath(e.stack), [ + 'Error: i=8', // - + /^ at imp \(file:\d+:29\)$/, // - + ' at plus_one (wasm-function[1]:6)', // - + ' at plus_two (wasm-function[1]:3)', // - + /^ at testStackTraceThroughCWasmEntry \(file:\d+:25\)$/, // - + /^ at file:\d+:3$/ + ]); + } + } +})(); diff --git a/deps/v8/test/mjsunit/wasm/js-api.js b/deps/v8/test/mjsunit/wasm/js-api.js index 8053d2934e..352f7caefa 100644 --- a/deps/v8/test/mjsunit/wasm/js-api.js +++ b/deps/v8/test/mjsunit/wasm/js-api.js @@ -265,7 +265,7 @@ let exportingModuleBinary2 = (() => { builder.addFunction('foo', kSig_v_v).addBody([]).exportAs('a'); builder.addMemory(1, 1, false); builder.exportMemoryAs('b'); - builder.setFunctionTableLength(1); + builder.setFunctionTableBounds(1, 1); builder.addExportOfKind('c', kExternalTable, 0); var o = builder.addGlobal(kWasmI32, false).exportAs('x'); return new Int8Array(builder.toBuffer()); @@ -307,12 +307,6 @@ assertEq(arr.length, 0); assertErrorMessage( () => moduleCustomSections(1), TypeError, 'first argument must be a WebAssembly.Module'); -assertErrorMessage( - () => moduleCustomSections(emptyModule), TypeError, - 'second argument must be a String'); -assertErrorMessage( - () => moduleCustomSections(emptyModule, 3), TypeError, - 'second argument must be a String'); let customSectionModuleBinary2 = (() => { let builder = new WasmModuleBuilder(); @@ -334,6 +328,15 @@ assertArrayBuffer(arr[1], [91, 92, 93]); var arr = moduleCustomSections(new Module(customSectionModuleBinary2), 'bar'); assertEq(arr instanceof Array, true); assertEq(arr.length, 0); +var o = {toString() { return "foo" }} +var arr = moduleCustomSections(new Module(customSectionModuleBinary2), o); +assertEq(arr instanceof Array, true); +assertEq(arr.length, 2); +assertArrayBuffer(arr[0], [66, 77]); +assertArrayBuffer(arr[1], [91, 92, 93]); +var o = {toString() { throw "boo!" }} +assertThrows( + () => moduleCustomSections(new Module(customSectionModuleBinary2), o)); // 'WebAssembly.Instance' data property let instanceDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Instance'); @@ -389,12 +392,12 @@ assertEq(typeof exportingInstance, 'object'); assertEq(String(exportingInstance), '[object WebAssembly.Instance]'); assertEq(Object.getPrototypeOf(exportingInstance), instanceProto); -// 'WebAssembly.Instance' 'exports' data property +// 'WebAssembly.Instance' 'exports' getter property let instanceExportsDesc = - Object.getOwnPropertyDescriptor(exportingInstance, 'exports'); -assertEq(typeof instanceExportsDesc.value, 'object'); -assertTrue(instanceExportsDesc.writable); -assertTrue(instanceExportsDesc.enumerable); + Object.getOwnPropertyDescriptor(instanceProto, 'exports'); +assertEq(typeof instanceExportsDesc.get, 'function'); +assertEq(instanceExportsDesc.set, undefined); +assertFalse(instanceExportsDesc.enumerable); assertTrue(instanceExportsDesc.configurable); exportsObj = exportingInstance.exports; @@ -517,6 +520,13 @@ assertEq(buf.byteLength, 2 * kPageSize); assertErrorMessage(() => mem.grow(1), Error, /failed to grow memory/); assertEq(buf, mem.buffer); +let empty_mem = new Memory({initial: 0, maximum: 5}); +let empty_buf = empty_mem.buffer; +assertEq(empty_buf.byteLength, 0); +assertEq(empty_mem.grow(0), 0); +assertEq(empty_mem.buffer.byteLength, 0); +assertTrue(empty_buf !== empty_mem.buffer); + // 'WebAssembly.Table' data property let tableDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Table'); assertEq(typeof tableDesc.value, 'function'); diff --git a/deps/v8/test/mjsunit/wasm/jsapi-harness.js b/deps/v8/test/mjsunit/wasm/jsapi-harness.js index 3506b592a4..d827b67570 100644 --- a/deps/v8/test/mjsunit/wasm/jsapi-harness.js +++ b/deps/v8/test/mjsunit/wasm/jsapi-harness.js @@ -8,16 +8,9 @@ // Flags: --expose-wasm --allow-natives-syntax const known_failures = { - "'WebAssembly.Module.customSections' method": - 'https://bugs.chromium.org/p/v8/issues/detail?id=5815', - "'WebAssembly.Table.prototype.get' method": - 'https://bugs.chromium.org/p/v8/issues/detail?id=5507', - "'WebAssembly.Table.prototype.set' method": - 'https://bugs.chromium.org/p/v8/issues/detail?id=5507', - "'WebAssembly.Instance.prototype.exports' accessor property": - 'https://bugs.chromium.org/p/v8/issues/detail?id=5507', - "'WebAssembly.Memory.prototype.grow' method": - 'https://bugs.chromium.org/p/v8/issues/detail?id=6546' + // Enter failing tests like follows: + // "'WebAssembly.Instance.prototype.exports' accessor property": + // 'https://bugs.chromium.org/p/v8/issues/detail?id=5507', }; let failures = []; @@ -62,11 +55,37 @@ function promise_test(func, description) { }); } -let assert_equals = assertEquals; -let assert_not_equals = assertNotEquals; let assert_true = assertEquals.bind(null, true); let assert_false = assertEquals.bind(null, false); +function same_value(x, y) { + if (y !== y) { + // NaN case + return x!==x; + } + if (x === 0 && y === 0) { + // Distinguish +0 and -0 + return 1/x === 1/y; + } + return x === y; +} + +let assert_equals = function(expected, found, description) { + if (typeof found != typeof expected) { + assert_true(false, "assert_equals", description, + "expected (" + typeof expected + ") ${expected} but got (" + + typeof found + ") ${found}", {expected:expected, found:found}); + } + assert_true(same_value(found, expected), "assert_equals", description, + "expected ${expected} but got ${found}", + {expected:expected, found:found}); +} + +let assert_not_equals = function(expected, found, description) { + assert_true(!same_value(found, expected), "assert_not_equals", description, + "got disallowed value ${found}", {found:found}); +} + function assert_unreached(description) { throw new Error(`unreachable:\n${description}`); } diff --git a/deps/v8/test/mjsunit/wasm/many-parameters.js b/deps/v8/test/mjsunit/wasm/many-parameters.js new file mode 100644 index 0000000000..03d7e09ef3 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/many-parameters.js @@ -0,0 +1,55 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +load('test/mjsunit/wasm/wasm-constants.js'); +load('test/mjsunit/wasm/wasm-module-builder.js'); + +let types = [kWasmI32, kWasmF32, kWasmF64]; +let type_names = ["i32", "f32", "f64"]; +let type_const = [wasmI32Const, wasmF32Const, wasmF64Const]; + +function f(values, shift, num_const_params, ...args) { + assertEquals( + values.length + num_const_params, args.length, 'number of arguments'); + args.forEach((arg_val, idx) => { + const expected = + idx < values.length ? values[(idx + shift) % values.length] : idx; + assertEquals(expected, arg_val, 'arg #' + idx + ', shifted by ' + shift); + }); +} + +types.forEach((type, type_idx) => { + for (let num_params = 3; num_params < 32; num_params += 4) { + print( + 'Testing ' + num_params + ' parameters of type ' + + type_names[type_idx] + '...'); + for (let num_const_params = 0; num_const_params <= 3; ++num_const_params) { + for (let shift = 2; shift <= 5; shift += 3) { + let builder = new WasmModuleBuilder(); + + let params_outer = new Array(num_params).fill(type); + sig_outer = makeSig(params_outer, []); + let params_inner = new Array(num_params + num_const_params).fill(type); + sig_inner = makeSig(params_inner, []); + + let body = []; + for (let i = 0; i < num_params; ++i) + body.push(kExprGetLocal, (i + shift) % num_params); + for (let i = 0; i < num_const_params; ++i) + body.push(...type_const[type_idx](num_params + i)); + body.push(kExprCallFunction, 0); + + builder.addImport('', 'f', sig_inner); + builder.addFunction(undefined, sig_outer) + .addBody(body) + .exportAs('main'); + let values = new Array(num_params).fill(0).map((_, i) => 123 - 3 * i); + + instance = builder.instantiate( + {'': {'f': f.bind(null, values, shift, num_const_params)}}); + instance.exports.main(...values); + } + } + } +}); diff --git a/deps/v8/test/mjsunit/wasm/memory.js b/deps/v8/test/mjsunit/wasm/memory.js index 1fbe0581b1..fbf4b18a27 100644 --- a/deps/v8/test/mjsunit/wasm/memory.js +++ b/deps/v8/test/mjsunit/wasm/memory.js @@ -4,6 +4,8 @@ // Flags: --expose-wasm +load("test/mjsunit/wasm/wasm-constants.js"); + // Basic tests. var outOfUint32RangeValue = 1e12; @@ -93,7 +95,6 @@ function assertMemoryIsValid(memory) { })(); (function TestMemoryGrow() { - var kPageSize = 65536; let memory = new WebAssembly.Memory({initial: 1, maximum:30}); assertEquals(1, memory.grow(9)); assertTrue(memory.buffer instanceof ArrayBuffer); diff --git a/deps/v8/test/mjsunit/wasm/table-grow.js b/deps/v8/test/mjsunit/wasm/table-grow.js new file mode 100644 index 0000000000..ab998e91b0 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/table-grow.js @@ -0,0 +1,302 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +load("test/mjsunit/wasm/wasm-constants.js"); +load("test/mjsunit/wasm/wasm-module-builder.js"); + +let kMaxTableSize = 10000000; + +function addFunctions(builder) { + let sig_index = builder.addType(kSig_i_ii); + let mul = builder.addFunction("mul", sig_index) + .addBody([ + kExprGetLocal, 0, // -- + kExprGetLocal, 1, // -- + kExprI32Mul // -- + ]); + let add = builder.addFunction("add", sig_index) + .addBody([ + kExprGetLocal, 0, // -- + kExprGetLocal, 1, // -- + kExprI32Add // -- + ]); + let sub = builder.addFunction("sub", sig_index) + .addBody([ + kExprGetLocal, 0, // -- + kExprGetLocal, 1, // -- + kExprI32Sub // -- + ]); + return {mul: mul, add: add, sub: sub}; +} + +function testBounds(func, table) { + for (let i = 0; i < table.length; i++) { + assertEquals(0, func(i)); + } + let l = table.length; + let oob = [l, l + 1, l + 2, l * 2, l * 3, l + 10000]; + for (let i of oob) { + assertThrows(() => func(i)); + } +} + +function addMain(builder) { + builder.addImportedTable("imp", "table", 0, kMaxTableSize); + builder.addFunction("main", kSig_i_i) + .addBody([ + kExprI32Const, 0, + kExprGetLocal, 0, + kExprCallIndirect, 0, kTableZero]) + .exportAs("main"); +} + +let id = (() => { // identity exported function + let builder = new WasmModuleBuilder(); + builder.addFunction("id", kSig_i_i) + .addBody([kExprGetLocal, 0]) + .exportAs("id"); + let module = new WebAssembly.Module(builder.toBuffer()); + return (new WebAssembly.Instance(builder.toModule())).exports.id; +})(); + +(function TableGrowBoundsCheck() { + print("TableGrowBoundsCheck"); + let builder = new WasmModuleBuilder(); + addMain(builder); + let module = WebAssembly.Module(builder.toBuffer()); + let table = new WebAssembly.Table({element: "anyfunc", + initial: 1, maximum:kMaxTableSize}); + function fillTable() { + for (let i = 0; i < table.length; i++) table.set(i, id); + return table; + } + fillTable(); + let instance1 = new WebAssembly.Instance(module, {imp: {table:table}}); + testBounds(instance1.exports.main, table); + + for (let i = 0; i < 4; i++) { + table.grow(1); + fillTable(table); + testBounds(instance1.exports.main, table); + } + let instance2 = new WebAssembly.Instance(module, {imp: {table:table}}); + testBounds(instance2.exports.main, table); + + for (let i = 0; i < 4; i++) { + table.grow(1); + fillTable(table); + testBounds(instance1.exports.main, table); + testBounds(instance2.exports.main, table); + } +})(); + +(function TableGrowBoundsZeroInitial() { + print("TableGrowBoundsZeroInitial"); + let builder = new WasmModuleBuilder(); + addMain(builder); + let module = WebAssembly.Module(builder.toBuffer()); + var table = new WebAssembly.Table({element: "anyfunc", + initial: 0, maximum:kMaxTableSize}); + function growTableByOne() { + table.grow(1); + table.set(table.length - 1, id); + } + let instance1 = new WebAssembly.Instance(module, {imp: {table:table}}); + testBounds(instance1.exports.main, table); + + for (let i = 0; i < 4; i++) { + growTableByOne(); + testBounds(instance1.exports.main, table); + } + let instance2 = new WebAssembly.Instance(module, {imp: {table:table}}); + testBounds(instance2.exports.main, table); + + for (let i = 0; i < 4; i++) { + growTableByOne(); + testBounds(instance1.exports.main, table); + testBounds(instance2.exports.main, table); + } +})(); + +(function InstancesShareTableAndGrowTest() { + print("InstancesShareTableAndGrowTest"); + let builder = new WasmModuleBuilder(); + let funcs = addFunctions(builder); + builder.addFunction("main", kSig_i_ii) + .addBody([ + kExprI32Const, 15, // -- + kExprGetLocal, 0, // -- + kExprGetLocal, 1, // -- + kExprCallIndirect, 0, kTableZero]) // -- + .exportAs("main"); + + builder.addImportedTable("q", "table", 5, 32); + let g = builder.addImportedGlobal("q", "base", kWasmI32); + builder.addFunctionTableInit(g, true, + [funcs.mul.index, funcs.add.index, funcs.sub.index]); + builder.addExportOfKind("table", kExternalTable, 0); + let module = new WebAssembly.Module(builder.toBuffer()); + let t1 = new WebAssembly.Table({element: "anyfunc", + initial: 5, maximum: 30}); + + for (let i = 0; i < 5; i++) { + print("base = " + i); + let instance = new WebAssembly.Instance(module, {q: {base: i, table: t1}}); + main = instance.exports.main; + assertEquals(i * 5 + 5, t1.length); + + // mul + assertEquals(15, main(1, i)); + assertEquals(30, main(2, i)); + // add + assertEquals(20, main(5, i+1)); + assertEquals(25, main(10, i+1)); + //sub + assertEquals(10, main(5, i+2)); + assertEquals(5, main(10, i+2)); + + assertThrows(() => t1.set(t1.length, id), RangeError); + assertThrows(() => t1.set(t1.length + 5, id), RangeError); + assertEquals(i * 5 + 5, t1.grow(5)); + } + + t1.set(t1.length - 1, id); + assertThrows(() => t1.set(t1.length, id), RangeError); + assertThrows(() => t1.grow(2), RangeError); +})(); + +(function ModulesShareTableAndGrowTest() { + print("ModulesShareTableAndGrowTest"); + let builder = new WasmModuleBuilder(); + let sig_i_ii = builder.addType(kSig_i_ii); + let sig_i_i = builder.addType(kSig_i_i); + let sig_i_v = builder.addType(kSig_i_v); + + let g1 = builder.addImportedGlobal("q", "base", kWasmI32); + + let a = builder.addImport("q", "exp_add", sig_i_ii); + let i = builder.addImport("q", "exp_inc", sig_i_i); + let t = builder.addImport("q", "exp_ten", sig_i_v); + + builder.setFunctionTableBounds(7, 35); + // builder.addFunctionTableInit(g1, true, + // [funcs.mul.index, funcs.add.index, funcs.sub.index]); + builder.addFunctionTableInit(g1, true, [a, i, t]); + + builder.addExportOfKind("table", kExternalTable, 0); + let module = new WebAssembly.Module(builder.toBuffer()); + + function exp_add(a, b) { return a + b; } + function exp_inc(a) { return a + 1 | 0; } + function exp_ten() { return 10; } + + let instance = new WebAssembly.Instance(module, {q: {base: 0, + exp_add: exp_add, exp_inc: exp_inc, exp_ten: exp_ten}}); + + let table = instance.exports.table; + exp_a = table.get(0); + exp_i = table.get(1); + exp_t = table.get(2); + + assertEquals(exp_a(1, 4), 5); + assertEquals(exp_i(8), 9); + assertEquals(exp_t(0), 10); + + let builder1 = new WasmModuleBuilder(); + let g = builder1.addImportedGlobal("q", "base", kWasmI32); + let funcs = addFunctions(builder1); + + builder1.addImportedTable("q", "table", 6, 36); + builder1.addFunctionTableInit(g, true, + [funcs.mul.index, funcs.add.index, funcs.sub.index]); + let module1 = new WebAssembly.Module(builder1.toBuffer()); + + function verifyTableFuncs(base) { + assertEquals(exp_a(1, 4), 5); + assertEquals(exp_i(8), 9); + assertEquals(exp_t(0), 10); + + mul = table.get(base); + add = table.get(base + 1); + sub = table.get(base + 2); + + assertEquals(20, mul(10, 2)); + assertEquals(12, add(10, 2)); + assertEquals(8, sub(10, 2)); + } + + for (let i = 3; i < 10; i++) { + let instance1 = new WebAssembly.Instance(module1, {q: {base: i, table: table}}); + verifyTableFuncs(i); + assertEquals(table.length, table.grow(3)); + verifyTableFuncs(i); + + assertThrows(() => table.set(table.length, id), RangeError); + assertThrows(() => table.set(table.length + 5, id), RangeError); + } +})(); + +(function ModulesInstancesSharedTableBoundsCheck() { + print("ModulesInstancesSharedTableBoundsCheck"); + let table = new WebAssembly.Table({element: "anyfunc", + initial: 1, maximum: kMaxTableSize}); + + function CallModuleBuilder() { + var builder = new WasmModuleBuilder(); + builder.addType(kSig_i_v); + builder.addType(kSig_v_v); + let index_i_ii = builder.addType(kSig_i_ii); + let index_i_i = builder.addType(kSig_i_i); + builder.addImportedTable("x", "table", 1, kMaxTableSize); + builder.addFunction("add", index_i_ii) + .addBody([ + kExprGetLocal, 0, + kExprGetLocal, 1, + kExprI32Add]); + builder.addFunction("main", index_i_i) + .addBody([ + kExprI32Const, 5, + kExprI32Const, 5, + kExprGetLocal, 0, + kExprCallIndirect, index_i_ii, kTableZero]) + .exportAs("main"); + builder.addFunctionTableInit(0, false, [0], true); + return new WebAssembly.Module(builder.toBuffer()); + } + + var instances = [], modules = []; + modules[0] = CallModuleBuilder(); + modules[1] = CallModuleBuilder(); + + // Modules[0] shared by instances[0..2], modules[1] shared by instances[3, 4] + instances[0] = new WebAssembly.Instance(modules[0], {x: {table:table}}); + instances[1] = new WebAssembly.Instance(modules[0], {x: {table:table}}); + instances[2] = new WebAssembly.Instance(modules[0], {x: {table:table}}); + instances[3] = new WebAssembly.Instance(modules[1], {x: {table:table}}); + instances[4] = new WebAssembly.Instance(modules[1], {x: {table:table}}); + + function VerifyTableBoundsCheck(size) { + print("Verifying bounds for size = " + size); + assertEquals(size, table.length); + for (let i = 0; i < 5; i++) { + // Sanity check for indirect call + assertEquals(10, instances[i].exports.main(0)); + // Bounds check at different out of bounds indices + assertInvalidFunction = function(s) { + assertThrows( + () => instances[i].exports.main(s), WebAssembly.RuntimeError, + /invalid function/); + } + assertInvalidFunction(size); + assertInvalidFunction(size + 1); + assertInvalidFunction(size + 1000); + assertInvalidFunction(2 * size); + } + } + + for (let i = 0; i < 4; i++) { + VerifyTableBoundsCheck(99900 * i + 1); + table.grow(99900); + } +})(); diff --git a/deps/v8/test/mjsunit/wasm/table.js b/deps/v8/test/mjsunit/wasm/table.js index c63eb5a2b2..4724561670 100644 --- a/deps/v8/test/mjsunit/wasm/table.js +++ b/deps/v8/test/mjsunit/wasm/table.js @@ -272,4 +272,8 @@ function assertTableIsValid(table, length) { {element: "anyfunc", initial: 0, maximum: kV8MaxWasmTableSize}); table.grow(kV8MaxWasmTableSize); assertThrows(() => table.grow(1), RangeError); + + table = new WebAssembly.Table({element: "anyfunc", initial: 0}); + table.grow({valueOf: () => {table.grow(2); return 1;}}); + assertEquals(3, table.length); })(); diff --git a/deps/v8/test/mjsunit/wasm/test-wasm-module-builder.js b/deps/v8/test/mjsunit/wasm/test-wasm-module-builder.js index 0fa55fadf6..abe003e3e7 100644 --- a/deps/v8/test/mjsunit/wasm/test-wasm-module-builder.js +++ b/deps/v8/test/mjsunit/wasm/test-wasm-module-builder.js @@ -14,6 +14,7 @@ function instantiate(buffer, ffi) { } (function BasicTest() { + print("BasicTest"); let builder = new WasmModuleBuilder(); builder.addMemory(1, 2, false); builder.addFunction("foo", kSig_i_v) @@ -26,6 +27,7 @@ function instantiate(buffer, ffi) { })(); (function ImportTest() { + print("ImportTest"); let builder = new WasmModuleBuilder(); var index = builder.addImport("", "print", makeSig_v_x(kWasmI32)); builder.addFunction("foo", kSig_v_v) @@ -39,6 +41,7 @@ function instantiate(buffer, ffi) { })(); (function LocalsTest() { + print("LocalsTest"); let builder = new WasmModuleBuilder(); builder.addFunction(undefined, kSig_i_i) .addLocals({i32_count: 1}) @@ -52,6 +55,7 @@ function instantiate(buffer, ffi) { })(); (function LocalsTest2() { + print("LocalsTest2"); // TODO(titzer): i64 only works on 64-bit platforms. var types = [ {locals: {i32_count: 1}, type: kWasmI32}, @@ -75,6 +79,7 @@ function instantiate(buffer, ffi) { })(); (function CallTest() { + print("CallTest"); let builder = new WasmModuleBuilder(); builder.addFunction("add", kSig_i_ii) .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]); @@ -88,6 +93,7 @@ function instantiate(buffer, ffi) { })(); (function IndirectCallTest() { + print("IndirectCallTest"); let builder = new WasmModuleBuilder(); builder.addFunction("add", kSig_i_ii) .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]); @@ -104,6 +110,7 @@ function instantiate(buffer, ffi) { })(); (function DataSegmentTest() { + print("DataSegmentTest"); let builder = new WasmModuleBuilder(); builder.addMemory(1, 1, false); builder.addFunction("load", kSig_i_i) @@ -118,6 +125,7 @@ function instantiate(buffer, ffi) { (function BasicTestWithUint8Array() { + print("BasicTestWithUint8Array"); let builder = new WasmModuleBuilder(); builder.addMemory(1, 2, false); builder.addFunction("foo", kSig_i_v) @@ -144,6 +152,7 @@ function instantiate(buffer, ffi) { })(); (function ImportTestTwoLevel() { + print("ImportTestTwoLevel"); let builder = new WasmModuleBuilder(); var index = builder.addImport("mod", "print", makeSig_v_x(kWasmI32)); builder.addFunction("foo", kSig_v_v) diff --git a/deps/v8/test/mjsunit/wasm/trap-location.js b/deps/v8/test/mjsunit/wasm/trap-location.js index 890672357c..390ad74d8d 100644 --- a/deps/v8/test/mjsunit/wasm/trap-location.js +++ b/deps/v8/test/mjsunit/wasm/trap-location.js @@ -12,10 +12,28 @@ Error.prepareStackTrace = function(error, frames) { return frames; }; -var builder = new WasmModuleBuilder(); +function testTrapLocations(instance, expected_stack_length) { + function testWasmTrap(value, reason, position) { + try { + instance.exports.main(value); + fail('expected wasm exception'); + } catch (e) { + assertEquals(kTrapMsgs[reason], e.message, 'trap reason'); + assertEquals(expected_stack_length, e.stack.length, 'number of frames'); + assertEquals(0, e.stack[0].getLineNumber(), 'wasmFunctionIndex'); + assertEquals(position, e.stack[0].getPosition(), 'position'); + } + } -builder.addMemory(0, 1, false); + // The actual tests: + testWasmTrap(0, kTrapDivByZero, 14); + testWasmTrap(1, kTrapMemOutOfBounds, 15); + testWasmTrap(2, kTrapUnreachable, 28); + testWasmTrap(3, kTrapFuncInvalid, 32); +} +var builder = new WasmModuleBuilder(); +builder.addMemory(0, 1, false); var sig_index = builder.addType(kSig_i_v) // Build a function to resemble this code: @@ -60,22 +78,12 @@ builder.addFunction("main", kSig_i_i) .exportAs("main"); builder.appendToTable([0]); -var module = builder.instantiate(); +let buffer = builder.toBuffer(); -function testWasmTrap(value, reason, position) { - try { - module.exports.main(value); - fail("expected wasm exception"); - } catch (e) { - assertEquals(kTrapMsgs[reason], e.message, "trap reason"); - assertEquals(3, e.stack.length, "number of frames"); - assertEquals(0, e.stack[0].getLineNumber(), "wasmFunctionIndex"); - assertEquals(position, e.stack[0].getPosition(), "position"); - } -} +// Test async compilation and instantiation. +assertPromiseResult(WebAssembly.instantiate(buffer), pair => { + testTrapLocations(pair.instance, 6); +}); -// The actual tests: -testWasmTrap(0, kTrapDivByZero, 14); -testWasmTrap(1, kTrapMemOutOfBounds, 15); -testWasmTrap(2, kTrapUnreachable, 28); -testWasmTrap(3, kTrapFuncInvalid, 32); +// Test sync compilation and instantiation. +testTrapLocations(builder.instantiate(), 4); diff --git a/deps/v8/test/mjsunit/wasm/wasm-constants.js b/deps/v8/test/mjsunit/wasm/wasm-constants.js index bfadbef7dd..c556b109a1 100644 --- a/deps/v8/test/mjsunit/wasm/wasm-constants.js +++ b/deps/v8/test/mjsunit/wasm/wasm-constants.js @@ -15,6 +15,9 @@ function bytes() { return buffer; } +// V8 internal constants +var kV8MaxPages = 32767; + // Header declaration constants var kWasmH0 = 0; var kWasmH1 = 0x61; @@ -28,6 +31,7 @@ var kWasmV3 = 0; var kHeaderSize = 8; var kPageSize = 65536; +var kSpecMaxPages = 65535; function bytesWithHeader() { var buffer = new ArrayBuffer(kHeaderSize + arguments.length); @@ -52,18 +56,19 @@ let kDeclNoLocals = 0; // Section declaration constants let kUnknownSectionCode = 0; -let kTypeSectionCode = 1; // Function signature declarations -let kImportSectionCode = 2; // Import declarations -let kFunctionSectionCode = 3; // Function declarations -let kTableSectionCode = 4; // Indirect function table and other tables -let kMemorySectionCode = 5; // Memory attributes -let kGlobalSectionCode = 6; // Global declarations -let kExportSectionCode = 7; // Exports -let kStartSectionCode = 8; // Start function declaration -let kElementSectionCode = 9; // Elements section -let kCodeSectionCode = 10; // Function code -let kDataSectionCode = 11; // Data segments -let kNameSectionCode = 12; // Name section (encoded as string) +let kTypeSectionCode = 1; // Function signature declarations +let kImportSectionCode = 2; // Import declarations +let kFunctionSectionCode = 3; // Function declarations +let kTableSectionCode = 4; // Indirect function table and other tables +let kMemorySectionCode = 5; // Memory attributes +let kGlobalSectionCode = 6; // Global declarations +let kExportSectionCode = 7; // Exports +let kStartSectionCode = 8; // Start function declaration +let kElementSectionCode = 9; // Elements section +let kCodeSectionCode = 10; // Function code +let kDataSectionCode = 11; // Data segments +let kNameSectionCode = 12; // Name section (encoded as string) +let kExceptionSectionCode = 13; // Exception section (must appear before code section) // Name section types let kModuleNameCode = 0; @@ -87,7 +92,6 @@ let kWasmI32 = 0x7f; let kWasmI64 = 0x7e; let kWasmF32 = 0x7d; let kWasmF64 = 0x7c; -let kWasmS128 = 0x7b; let kExternalFunction = 0; let kExternalTable = 1; @@ -118,7 +122,6 @@ let kSig_v_l = makeSig([kWasmI64], []); let kSig_v_d = makeSig([kWasmF64], []); let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []); let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []); -let kSig_s_v = makeSig([], [kWasmS128]); function makeSig(params, results) { return {params: params, results: results}; @@ -320,7 +323,31 @@ let kExprI32ReinterpretF32 = 0xbc; let kExprI64ReinterpretF64 = 0xbd; let kExprF32ReinterpretI32 = 0xbe; let kExprF64ReinterpretI64 = 0xbf; -let kExprS128LoadMem = 0xc0; + +// Prefix opcodes +let kAtomicPrefix = 0xfe; + +let kExprI32AtomicAdd = 0x1e; +let kExprI32AtomicAdd8U = 0x20; +let kExprI32AtomicAdd16U = 0x21; +let kExprI32AtomicSub = 0x25; +let kExprI32AtomicSub8U = 0x27; +let kExprI32AtomicSub16U = 0x28; +let kExprI32AtomicAnd = 0x2c; +let kExprI32AtomicAnd8U = 0x2e; +let kExprI32AtomicAnd16U = 0x2f; +let kExprI32AtomicOr = 0x33; +let kExprI32AtomicOr8U = 0x35; +let kExprI32AtomicOr16U = 0x36; +let kExprI32AtomicXor = 0x3a; +let kExprI32AtomicXor8U = 0x3c; +let kExprI32AtomicXor16U = 0x3d; +let kExprI32AtomicExchange = 0x41; +let kExprI32AtomicExchange8U = 0x43; +let kExprI32AtomicExchange16U = 0x44; +let kExprI32AtomicCompareExchange = 0x48 +let kExprI32AtomicCompareExchange8U = 0x4a +let kExprI32AtomicCompareExchange16U = 0x4b let kTrapUnreachable = 0; let kTrapMemOutOfBounds = 1; @@ -360,8 +387,7 @@ function assertTraps(trap, code) { throw new MjsUnitAssertionError('Did not trap, expected: ' + kTrapMsgs[trap]); } -function assertWasmThrows(value, code) { - assertEquals('number', typeof value); +function assertWasmThrows(values, code) { try { if (typeof code === 'function') { code(); @@ -369,10 +395,31 @@ function assertWasmThrows(value, code) { eval(code); } } catch (e) { - assertEquals('number', typeof e); - assertEquals(value, e); + assertTrue(e instanceof WebAssembly.RuntimeError); + assertNotEquals(e['WasmExceptionTag'], undefined); + assertTrue(Number.isInteger(e['WasmExceptionTag'])); + // TODO(kschimpf): Extract values from the exception. + let e_values = []; + assertEquals(values, e_values); // Success. return; } - throw new MjsUnitAssertionError('Did not throw, expected: ' + value); + throw new MjsUnitAssertionError('Did not throw, expected: ' + values); +} + +function wasmI32Const(val) { + let bytes = [kExprI32Const]; + for (let i = 0; i < 4; ++i) { + bytes.push(0x80 | ((val >> (7 * i)) & 0x7f)); + } + bytes.push((val >> (7 * 4)) & 0x7f); + return bytes; +} + +function wasmF32Const(f) { + return [kExprF32Const].concat(Array.from(new Uint8Array((new Float32Array([f])).buffer))); +} + +function wasmF64Const(f) { + return [kExprF64Const].concat(Array.from(new Uint8Array((new Float64Array([f])).buffer))); } diff --git a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js index a26384e545..78e3d6bde8 100644 --- a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js +++ b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js @@ -74,7 +74,7 @@ class Binary extends Array { // Emit section length. this.emit_u32v(section.length); // Copy the temporary buffer. - this.push(...section); + for (var i = 0; i < section.length; i++) this.push(section[i]); } } @@ -107,8 +107,8 @@ class WasmFunctionBuilder { addBody(body) { for (let b of body) { - if (typeof b != 'number') - throw new Error('invalid body (entries have to be numbers): ' + body); + if (typeof b !== 'number' || (b & (~0xFF)) !== 0 ) + throw new Error('invalid body (entries must be 8 bit numbers): ' + body); } this.body = body.slice(); // Automatically add the end for the function block to the body. @@ -153,9 +153,11 @@ class WasmModuleBuilder { this.imports = []; this.exports = []; this.globals = []; + this.exceptions = []; this.functions = []; this.function_table = []; - this.function_table_length = 0; + this.function_table_length_min = 0; + this.function_table_length_max = 0; this.function_table_inits = []; this.segments = []; this.explicit = []; @@ -196,8 +198,9 @@ class WasmModuleBuilder { } addType(type) { - // TODO: canonicalize types? this.types.push(type); + var pl = type.params.length; // should have params + var rl = type.results.length; // should have results return this.types.length - 1; } @@ -208,6 +211,13 @@ class WasmModuleBuilder { return glob; } + addException(type) { + if (type.results.length != 0) + throw new Error('Invalid exception signature: ' + type); + this.exceptions.push(type); + return this.exceptions.length - 1; + } + addFunction(name, type) { let type_index = (typeof type) == "number" ? type : this.addType(type); let func = new WasmFunctionBuilder(this, name, type_index); @@ -267,8 +277,11 @@ class WasmModuleBuilder { array: array}); if (!is_global) { var length = base + array.length; - if (length > this.function_table_length && !is_import) { - this.function_table_length = length; + if (length > this.function_table_length_min && !is_import) { + this.function_table_length_min = length; + } + if (length > this.function_table_length_max && !is_import) { + this.function_table_length_max = length; } } return this; @@ -282,8 +295,9 @@ class WasmModuleBuilder { return this.addFunctionTableInit(this.function_table.length, false, array); } - setFunctionTableLength(length) { - this.function_table_length = length; + setFunctionTableBounds(min, max) { + this.function_table_length_min = min; + this.function_table_length_max = max; return this; } @@ -362,14 +376,16 @@ class WasmModuleBuilder { } // Add function_table. - if (wasm.function_table_length > 0) { + if (wasm.function_table_length_min > 0) { if (debug) print("emitting table @ " + binary.length); binary.emit_section(kTableSectionCode, section => { section.emit_u8(1); // one table entry section.emit_u8(kWasmAnyFunctionTypeForm); - section.emit_u8(1); - section.emit_u32v(wasm.function_table_length); - section.emit_u32v(wasm.function_table_length); + // TODO(gdeepti): Cleanup to use optional max flag, + // fix up tests to set correct initial/maximum values + section.emit_u32v(1); + section.emit_u32v(wasm.function_table_length_min); + section.emit_u32v(wasm.function_table_length_max); }); } @@ -378,9 +394,10 @@ class WasmModuleBuilder { if (debug) print("emitting memory @ " + binary.length); binary.emit_section(kMemorySectionCode, section => { section.emit_u8(1); // one memory entry - section.emit_u32v(kResizableMaximumFlag); + const has_max = wasm.memory.max !== undefined; + section.emit_u32v(has_max ? kResizableMaximumFlag : 0); section.emit_u32v(wasm.memory.min); - section.emit_u32v(wasm.memory.max); + if (has_max) section.emit_u32v(wasm.memory.max); }); } @@ -486,6 +503,20 @@ class WasmModuleBuilder { }); } + // Add exceptions. + if (wasm.exceptions.length > 0) { + if (debug) print("emitting exceptions @ " + binary.length); + binary.emit_section(kExceptionSectionCode, section => { + section.emit_u32v(wasm.exceptions.length); + for (let type of wasm.exceptions) { + section.emit_u32v(type.params.length); + for (let param of type.params) { + section.enit_u8(param); + } + } + }); + } + // Add function bodies. if (wasm.functions.length > 0) { // emit function bodies |