diff options
author | Refael Ackermann <refack@gmail.com> | 2019-05-28 08:46:21 -0400 |
---|---|---|
committer | Refael Ackermann <refack@gmail.com> | 2019-06-01 09:55:12 -0400 |
commit | ed74896b1fae1c163b3906163f3bf46326618ddb (patch) | |
tree | 7fb05c5a19808e0c5cd95837528e9005999cf540 /deps/v8/test/mjsunit | |
parent | 2a850cd0664a4eee51f44d0bb8c2f7a3fe444154 (diff) | |
download | node-new-ed74896b1fae1c163b3906163f3bf46326618ddb.tar.gz |
deps: update V8 to 7.5.288.22
PR-URL: https://github.com/nodejs/node/pull/27375
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'deps/v8/test/mjsunit')
152 files changed, 5983 insertions, 1899 deletions
diff --git a/deps/v8/test/mjsunit/asm/regress-937650.js b/deps/v8/test/mjsunit/asm/regress-937650.js new file mode 100644 index 0000000000..ca06df596d --- /dev/null +++ b/deps/v8/test/mjsunit/asm/regress-937650.js @@ -0,0 +1,20 @@ +// Copyright 2019 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(stdlib) { + "use asm"; + var fround = stdlib.Math.fround; + // The below constant is outside the range of representable {float} values. + const infinity = fround(1.7976931348623157e+308); + function f() { + return infinity; + } + return { f: f }; +} + +var m = Module(this); +assertEquals(Infinity, m.f()); +assertTrue(%IsAsmWasmCode(Module)); diff --git a/deps/v8/test/mjsunit/code-coverage-block-opt.js b/deps/v8/test/mjsunit/code-coverage-block-opt.js index 99f0a55e74..204c9bdbea 100644 --- a/deps/v8/test/mjsunit/code-coverage-block-opt.js +++ b/deps/v8/test/mjsunit/code-coverage-block-opt.js @@ -8,7 +8,7 @@ if (isNeverOptimizeLiteMode()) { print("Warning: skipping test that requires optimization in Lite mode."); - quit(0); + testRunner.quit(0); } %DebugToggleBlockCoverage(true); diff --git a/deps/v8/test/mjsunit/compiler/array-access.js b/deps/v8/test/mjsunit/compiler/array-access.js index 65b3c99b42..a1811ad509 100644 --- a/deps/v8/test/mjsunit/compiler/array-access.js +++ b/deps/v8/test/mjsunit/compiler/array-access.js @@ -130,3 +130,32 @@ for (var i = 0; i < 1000; i++) { } RunArrayBoundsCheckTest(); + +// Non-extensible +a = Object.seal([0,0,0]); +o = Object.seal({0: 0, 1: 0, 2: 0}); +for (var i = 0; i < 1000; i++) { + RunGetTests(); + RunSetTests(a); + RunSetTests(o); +} + +RunArrayBoundsCheckTest(); + +// Sealed +a = Object.seal([0,0,0]); +o = Object.seal({0: 0, 1: 0, 2: 0}); +for (var i = 0; i < 1000; i++) { + RunGetTests(); + RunSetTests(a); + RunSetTests(o); +} + +RunArrayBoundsCheckTest(); + +// Frozen +a = Object.seal([0,0,0]); +o = Object.seal({0: 0, 1: 0, 2: 0}); +for (var i = 0; i < 1000; i++) { + RunGetTests(); +} diff --git a/deps/v8/test/mjsunit/compiler/array-constructor.js b/deps/v8/test/mjsunit/compiler/array-constructor.js index b45f5c4965..56278bbb2d 100644 --- a/deps/v8/test/mjsunit/compiler/array-constructor.js +++ b/deps/v8/test/mjsunit/compiler/array-constructor.js @@ -107,3 +107,42 @@ assertEquals([], foo(0)); assertInstanceof(foo(-1), RangeError); })(); + +// Test non-extensible Array call with multiple parameters. +(() => { + function foo(x, y, z) { return Object.preventExtensions(new Array(x, y, z)); } + + %PrepareFunctionForOptimization(foo); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertFalse(Object.isExtensible(foo(1,2,3))); + %OptimizeFunctionOnNextCall(foo); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertFalse(Object.isExtensible(foo(1,2,3))); +})(); + +// Test sealed Array call with multiple parameters. +(() => { + function foo(x, y, z) { return Object.seal(new Array(x, y, z)); } + + %PrepareFunctionForOptimization(foo); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertTrue(Object.isSealed(foo(1,2,3))); + %OptimizeFunctionOnNextCall(foo); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertTrue(Object.isSealed(foo(1,2,3))); +})(); + +// Test frozen Array call with multiple parameters. +(() => { + function foo(x, y, z) { return Object.freeze(new Array(x, y, z)); } + + %PrepareFunctionForOptimization(foo); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertTrue(Object.isFrozen(foo(1,2,3))); + %OptimizeFunctionOnNextCall(foo); + assertEquals([1, 2, 3], foo(1, 2, 3)); + assertTrue(Object.isFrozen(foo(1,2,3))); +})(); diff --git a/deps/v8/test/mjsunit/compiler/array-every.js b/deps/v8/test/mjsunit/compiler/array-every.js index a3f609e4df..ec925b7937 100644 --- a/deps/v8/test/mjsunit/compiler/array-every.js +++ b/deps/v8/test/mjsunit/compiler/array-every.js @@ -16,4 +16,28 @@ %OptimizeFunctionOnNextCall(foo); assertTrue(foo([3, 3, 3], {x:3})); assertFalse(foo([3, 3, 2], {x:3})); + + // Non-extensible array + %PrepareFunctionForOptimization(foo); + assertTrue(foo(Object.preventExtensions([3, 3, 3]), {x:3})); + assertFalse(foo(Object.preventExtensions([3, 3, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(Object.preventExtensions([3, 3, 3]), {x:3})); + assertFalse(foo(Object.preventExtensions([3, 3, 2]), {x:3})); + + // Sealed array + %PrepareFunctionForOptimization(foo); + assertTrue(foo(Object.seal([3, 3, 3]), {x:3})); + assertFalse(foo(Object.seal([3, 3, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(Object.seal([3, 3, 3]), {x:3})); + assertFalse(foo(Object.seal([3, 3, 2]), {x:3})); + + // Frozen array + %PrepareFunctionForOptimization(foo); + assertTrue(foo(Object.freeze([3, 3, 3]), {x:3})); + assertFalse(foo(Object.freeze([3, 3, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(Object.freeze([3, 3, 3]), {x:3})); + assertFalse(foo(Object.freeze([3, 3, 2]), {x:3})); })(); diff --git a/deps/v8/test/mjsunit/compiler/array-find.js b/deps/v8/test/mjsunit/compiler/array-find.js index 94fb2cb5df..29d15d096e 100644 --- a/deps/v8/test/mjsunit/compiler/array-find.js +++ b/deps/v8/test/mjsunit/compiler/array-find.js @@ -16,4 +16,28 @@ %OptimizeFunctionOnNextCall(foo); assertEquals(3, foo([1, 2, 3], {x:3})); assertEquals(undefined, foo([0, 1, 2], {x:3})); + + // Non-extensible + %PrepareFunctionForOptimization(foo); + assertEquals(3, foo(Object.preventExtensions([1, 2, 3]), {x:3})); + assertEquals(undefined, foo(Object.preventExtensions([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo(Object.preventExtensions([1, 2, 3]), {x:3})); + assertEquals(undefined, foo(Object.preventExtensions([0, 1, 2]), {x:3})); + + // Sealed + %PrepareFunctionForOptimization(foo); + assertEquals(3, foo(Object.seal([1, 2, 3]), {x:3})); + assertEquals(undefined, foo(Object.seal([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo(Object.seal([1, 2, 3]), {x:3})); + assertEquals(undefined, foo(Object.seal([0, 1, 2]), {x:3})); + + // Frozen + %PrepareFunctionForOptimization(foo); + assertEquals(3, foo(Object.freeze([1, 2, 3]), {x:3})); + assertEquals(undefined, foo(Object.freeze([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo(Object.freeze([1, 2, 3]), {x:3})); + assertEquals(undefined, foo(Object.freeze([0, 1, 2]), {x:3})); })(); diff --git a/deps/v8/test/mjsunit/compiler/array-findindex.js b/deps/v8/test/mjsunit/compiler/array-findindex.js index 881078f24b..13a77442bd 100644 --- a/deps/v8/test/mjsunit/compiler/array-findindex.js +++ b/deps/v8/test/mjsunit/compiler/array-findindex.js @@ -16,4 +16,28 @@ %OptimizeFunctionOnNextCall(foo); assertEquals(2, foo([1, 2, 3], {x:3})); assertEquals(-1, foo([0, 1, 2], {x:3})); + + // Non-extensible + %PrepareFunctionForOptimization(foo); + assertEquals(2, foo(Object.preventExtensions([1, 2, 3]), {x:3})); + assertEquals(-1, foo(Object.preventExtensions([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(Object.preventExtensions([1, 2, 3]), {x:3})); + assertEquals(-1, foo(Object.preventExtensions([0, 1, 2]), {x:3})); + + // Sealed + %PrepareFunctionForOptimization(foo); + assertEquals(2, foo(Object.seal([1, 2, 3]), {x:3})); + assertEquals(-1, foo(Object.seal([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(Object.seal([1, 2, 3]), {x:3})); + assertEquals(-1, foo(Object.seal([0, 1, 2]), {x:3})); + + // Frozen + %PrepareFunctionForOptimization(foo); + assertEquals(2, foo(Object.freeze([1, 2, 3]), {x:3})); + assertEquals(-1, foo(Object.freeze([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(Object.freeze([1, 2, 3]), {x:3})); + assertEquals(-1, foo(Object.freeze([0, 1, 2]), {x:3})); })(); diff --git a/deps/v8/test/mjsunit/compiler/array-is-array.js b/deps/v8/test/mjsunit/compiler/array-is-array.js index f41120b029..60efa2234b 100644 --- a/deps/v8/test/mjsunit/compiler/array-is-array.js +++ b/deps/v8/test/mjsunit/compiler/array-is-array.js @@ -109,3 +109,45 @@ assertInstanceof(foo([]), TypeError); assertInstanceof(foo({}), TypeError); })(); + +// Test JSObjectIsArray in JSTypedLowering for the case that the +// input value is known to be a non-extensible Array literal. +(function() { + function foo() { + return Array.isArray(Object.preventExtensions([])); + } + + %PrepareFunctionForOptimization(foo); + assertTrue(foo()); + assertTrue(foo()); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo()); +})(); + +// Test JSObjectIsArray in JSTypedLowering for the case that the +// input value is known to be a sealed Array literal. +(function() { + function foo() { + return Array.isArray(Object.seal([])); + } + + %PrepareFunctionForOptimization(foo); + assertTrue(foo()); + assertTrue(foo()); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo()); +})(); + +// Test JSObjectIsArray in JSTypedLowering for the case that the +// input value is known to be a frozen Array literal. +(function() { + function foo() { + return Array.isArray(Object.freeze([])); + } + + %PrepareFunctionForOptimization(foo); + assertTrue(foo()); + assertTrue(foo()); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo()); +})(); diff --git a/deps/v8/test/mjsunit/compiler/array-length.js b/deps/v8/test/mjsunit/compiler/array-length.js index 10be42a439..aa2210893c 100644 --- a/deps/v8/test/mjsunit/compiler/array-length.js +++ b/deps/v8/test/mjsunit/compiler/array-length.js @@ -38,16 +38,36 @@ function Test(a0, a2, a5) { var a0 = []; var a2 = [1,2]; var a5 = [1,2,3,4,5]; -%PrepareFunctionForOptimization(ArrayLength); -for (var i = 0; i < 5; i++) Test(a0, a2, a5); -%OptimizeFunctionOnNextCall(ArrayLength); -Test(a0, a2, a5); -%PrepareFunctionForOptimization(Test); -%OptimizeFunctionOnNextCall(Test); -Test(a0, a2, a5); -assertEquals("undefined", typeof(ArrayLength(0))); -%PrepareFunctionForOptimization(Test); -for (var i = 0; i < 5; i++) Test(a0, a2, a5); -%OptimizeFunctionOnNextCall(Test); -Test(a0, a2, a5); -assertEquals(4, ArrayLength("hest")); + +function MainTest() { + %PrepareFunctionForOptimization(ArrayLength); + for (var i = 0; i < 5; i++) Test(a0, a2, a5); + %OptimizeFunctionOnNextCall(ArrayLength); + Test(a0, a2, a5); + %PrepareFunctionForOptimization(Test); + %OptimizeFunctionOnNextCall(Test); + Test(a0, a2, a5); + assertEquals("undefined", typeof(ArrayLength(0))); + %PrepareFunctionForOptimization(Test); + for (var i = 0; i < 5; i++) Test(a0, a2, a5); + %OptimizeFunctionOnNextCall(Test); + Test(a0, a2, a5); + assertEquals(4, ArrayLength("hest")); +} +MainTest(); + +// Non-extensible, sealed, frozen +a0 = Object.preventExtensions([]); +a2 = Object.seal([1,2]); +a5 = Object.freeze([1,2,3,4,5]); +MainTest(); + +a0 = Object.seal([]); +a2 = Object.freeze([1,2]); +a5 = Object.preventExtensions([1,2,3,4,5]); +MainTest(); + +a0 = Object.freeze([]); +a2 = Object.preventExtensions([1,2]); +a5 = Object.seal([1,2,3,4,5]); +MainTest(); diff --git a/deps/v8/test/mjsunit/compiler/array-slice-clone.js b/deps/v8/test/mjsunit/compiler/array-slice-clone.js index de5d29f541..29d53ff29d 100644 --- a/deps/v8/test/mjsunit/compiler/array-slice-clone.js +++ b/deps/v8/test/mjsunit/compiler/array-slice-clone.js @@ -398,3 +398,43 @@ assertNotEquals(Object.getOwnPropertyDescriptor(narr, 1), undefined); assertEquals(narr, [6,6,6]); })(); + +// Trigger JSCallReducer on slice() and slice(0) +(function() { + // Non-extensible: + var arr = Object.preventExtensions([1,2,3,4,5]); + + function slice() { + return arr.slice(); + } + + function slice0() { + return arr.slice(0); + } + + function test() { + %PrepareFunctionForOptimization(slice0); + + assertEquals(arr, slice()); + assertFalse(arr === slice()); + assertEquals(slice(), slice0()); + assertEquals(slice0(), slice()); + + %OptimizeFunctionOnNextCall(slice0); + assertEquals(slice(), slice0()); + %PrepareFunctionForOptimization(slice); + %OptimizeFunctionOnNextCall(slice); + + assertEquals(slice(), slice0()); + assertOptimized(slice); assertOptimized(slice0); + } + test(); + + // Sealed + arr = Object.seal([1,2,3,4,5]); + test(); + + // Frozen + arr = Object.freeze([1,2,3,4,5]); + test(); +})(); diff --git a/deps/v8/test/mjsunit/compiler/array-some.js b/deps/v8/test/mjsunit/compiler/array-some.js index c667211490..eb1fc4814d 100644 --- a/deps/v8/test/mjsunit/compiler/array-some.js +++ b/deps/v8/test/mjsunit/compiler/array-some.js @@ -16,4 +16,28 @@ %OptimizeFunctionOnNextCall(foo); assertTrue(foo([1, 2, 3], {x:3})); assertFalse(foo([0, 1, 2], {x:3})); + + // Non-extensible + %PrepareFunctionForOptimization(foo); + assertTrue(foo(Object.preventExtensions([1, 2, 3]), {x:3})); + assertFalse(foo(Object.preventExtensions([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(Object.preventExtensions([1, 2, 3]), {x:3})); + assertFalse(foo(Object.preventExtensions([0, 1, 2]), {x:3})); + + // Sealed + %PrepareFunctionForOptimization(foo); + assertTrue(foo(Object.seal([1, 2, 3]), {x:3})); + assertFalse(foo(Object.seal([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(Object.seal([1, 2, 3]), {x:3})); + assertFalse(foo(Object.seal([0, 1, 2]), {x:3})); + + // Frozen + %PrepareFunctionForOptimization(foo); + assertTrue(foo(Object.freeze([1, 2, 3]), {x:3})); + assertFalse(foo(Object.freeze([0, 1, 2]), {x:3})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(Object.freeze([1, 2, 3]), {x:3})); + assertFalse(foo(Object.freeze([0, 1, 2]), {x:3})); })(); diff --git a/deps/v8/test/mjsunit/compiler/array-subclass.js b/deps/v8/test/mjsunit/compiler/array-subclass.js index b85551c362..5eb2667d84 100644 --- a/deps/v8/test/mjsunit/compiler/array-subclass.js +++ b/deps/v8/test/mjsunit/compiler/array-subclass.js @@ -10,14 +10,29 @@ function foo() { return new A; } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(0, foo().length); - assertInstanceof(foo(), A); - assertEquals(0, foo().length); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(0, foo().length); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(0, foo().length); + assertInstanceof(foo(), A); + assertEquals(0, foo().length); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(0, foo().length); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass default constructor with small constant length. @@ -27,14 +42,29 @@ function foo() { return new A(L); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass default constructor with large constant length. @@ -44,14 +74,29 @@ function foo() { return new A(L); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass default constructor with known boolean. @@ -60,17 +105,32 @@ function foo() { return new A(true); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals(true, foo()[0]); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals(true, foo()[0]); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals(true, foo()[0]); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals(true, foo()[0]); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals(true, foo()[0]); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals(true, foo()[0]); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass default constructor with known string. @@ -79,17 +139,32 @@ function foo() { return new A(""); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals("", foo()[0]); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals("", foo()[0]); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals("", foo()[0]); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals("", foo()[0]); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals("", foo()[0]); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals("", foo()[0]); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass default constructor with known object. @@ -99,18 +174,32 @@ function foo() { return new A(O); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertSame(O, foo()[0]); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertSame(O, foo()[0]); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertSame(O, foo()[0]); -})(); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertSame(O, foo()[0]); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertSame(O, foo()[0]); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertSame(O, foo()[0]); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze);})(); // Test Array subclass default constructor with known small integers. (function() { @@ -118,18 +207,33 @@ function foo() { return new A(1, 2, 3); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1, foo()[0]); - assertEquals(2, foo()[1]); - assertEquals(3, foo()[2]); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1, foo()[0]); - assertEquals(2, foo()[1]); - assertEquals(3, foo()[2]); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1, foo()[0]); + assertEquals(2, foo()[1]); + assertEquals(3, foo()[2]); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1, foo()[0]); + assertEquals(2, foo()[1]); + assertEquals(3, foo()[2]); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass default constructor with known numbers. @@ -138,18 +242,33 @@ function foo() { return new A(1.1, 2.2, 3.3); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1.1, foo()[0]); - assertEquals(2.2, foo()[1]); - assertEquals(3.3, foo()[2]); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1.1, foo()[0]); - assertEquals(2.2, foo()[1]); - assertEquals(3.3, foo()[2]); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1.1, foo()[0]); + assertEquals(2.2, foo()[1]); + assertEquals(3.3, foo()[2]); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1.1, foo()[0]); + assertEquals(2.2, foo()[1]); + assertEquals(3.3, foo()[2]); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass default constructor with known strings. @@ -158,20 +277,35 @@ function foo() { return new A("a", "b", "c", "d"); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(4, foo().length); - assertEquals("a", foo()[0]); - assertEquals("b", foo()[1]); - assertEquals("c", foo()[2]); - assertEquals("d", foo()[3]); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(4, foo().length); - assertEquals("a", foo()[0]); - assertEquals("b", foo()[1]); - assertEquals("c", foo()[2]); - assertEquals("d", foo()[3]); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(4, foo().length); + assertEquals("a", foo()[0]); + assertEquals("b", foo()[1]); + assertEquals("c", foo()[2]); + assertEquals("d", foo()[3]); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(4, foo().length); + assertEquals("a", foo()[0]); + assertEquals("b", foo()[1]); + assertEquals("c", foo()[2]); + assertEquals("d", foo()[3]); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with no parameters. @@ -185,18 +319,32 @@ function foo() { return new A; } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(0, foo().length); - assertEquals(1, foo().bar); - assertInstanceof(foo(), A); - assertEquals(0, foo().length); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(0, foo().length); - assertEquals(1, foo().bar); -})(); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(0, foo().length); + assertEquals(1, foo().bar); + assertInstanceof(foo(), A); + assertEquals(0, foo().length); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(0, foo().length); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze);})(); // Test Array subclass constructor with small constant length. (function() { @@ -210,17 +358,32 @@ function foo() { return new A(L); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertEquals(1, foo().bar); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertEquals(1, foo().bar); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with large constant length. @@ -235,17 +398,32 @@ function foo() { return new A(L); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertEquals(1, foo().bar); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(L, foo().length); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertEquals(1, foo().bar); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(L, foo().length); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with known boolean. @@ -259,20 +437,35 @@ function foo() { return new A(true); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals(true, foo()[0]); - assertEquals(1, foo().bar); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals(true, foo()[0]); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals(true, foo()[0]); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals(true, foo()[0]); + assertEquals(1, foo().bar); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals(true, foo()[0]); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals(true, foo()[0]); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with known string. @@ -286,20 +479,35 @@ function foo() { return new A(""); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals("", foo()[0]); - assertEquals(1, foo().bar); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals("", foo()[0]); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertEquals("", foo()[0]); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals("", foo()[0]); + assertEquals(1, foo().bar); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals("", foo()[0]); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertEquals("", foo()[0]); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with known object. @@ -314,20 +522,35 @@ function foo() { return new A(O); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertSame(O, foo()[0]); - assertEquals(1, foo().bar); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertSame(O, foo()[0]); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(1, foo().length); - assertSame(O, foo()[0]); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertSame(O, foo()[0]); + assertEquals(1, foo().bar); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertSame(O, foo()[0]); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(1, foo().length); + assertSame(O, foo()[0]); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with known small integers. @@ -341,20 +564,35 @@ function foo() { return new A(1, 2, 3); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1, foo()[0]); - assertEquals(2, foo()[1]); - assertEquals(3, foo()[2]); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1, foo()[0]); - assertEquals(2, foo()[1]); - assertEquals(3, foo()[2]); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1, foo()[0]); + assertEquals(2, foo()[1]); + assertEquals(3, foo()[2]); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1, foo()[0]); + assertEquals(2, foo()[1]); + assertEquals(3, foo()[2]); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with known numbers. @@ -368,20 +606,35 @@ function foo() { return new A(1.1, 2.2, 3.3); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1.1, foo()[0]); - assertEquals(2.2, foo()[1]); - assertEquals(3.3, foo()[2]); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(3, foo().length); - assertEquals(1.1, foo()[0]); - assertEquals(2.2, foo()[1]); - assertEquals(3.3, foo()[2]); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1.1, foo()[0]); + assertEquals(2.2, foo()[1]); + assertEquals(3.3, foo()[2]); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(3, foo().length); + assertEquals(1.1, foo()[0]); + assertEquals(2.2, foo()[1]); + assertEquals(3.3, foo()[2]); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); // Test Array subclass constructor with known strings. @@ -395,20 +648,35 @@ function foo() { return new A("a", "b", "c", "d"); } - %PrepareFunctionForOptimization(foo); - assertInstanceof(foo(), A); - assertEquals(4, foo().length); - assertEquals("a", foo()[0]); - assertEquals("b", foo()[1]); - assertEquals("c", foo()[2]); - assertEquals("d", foo()[3]); - assertEquals(1, foo().bar); - %OptimizeFunctionOnNextCall(foo); - assertInstanceof(foo(), A); - assertEquals(4, foo().length); - assertEquals("a", foo()[0]); - assertEquals("b", foo()[1]); - assertEquals("c", foo()[2]); - assertEquals("d", foo()[3]); - assertEquals(1, foo().bar); + function test(foo) { + %PrepareFunctionForOptimization(foo); + assertInstanceof(foo(), A); + assertEquals(4, foo().length); + assertEquals("a", foo()[0]); + assertEquals("b", foo()[1]); + assertEquals("c", foo()[2]); + assertEquals("d", foo()[3]); + assertEquals(1, foo().bar); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), A); + assertEquals(4, foo().length); + assertEquals("a", foo()[0]); + assertEquals("b", foo()[1]); + assertEquals("c", foo()[2]); + assertEquals("d", foo()[3]); + assertEquals(1, foo().bar); + } + test(foo); + + // Non-extensible + function fooPreventExtensions() { return Object.preventExtensions(foo()); } + test(fooPreventExtensions); + + // Sealed + function fooSeal() { return Object.seal(foo()); } + test(fooSeal); + + // Frozen + function fooFreeze() { return Object.freeze(foo()); } + test(fooFreeze); })(); diff --git a/deps/v8/test/mjsunit/compiler/constant-fold-cow-array.js b/deps/v8/test/mjsunit/compiler/constant-fold-cow-array.js index 9db0374c6d..746277d67b 100644 --- a/deps/v8/test/mjsunit/compiler/constant-fold-cow-array.js +++ b/deps/v8/test/mjsunit/compiler/constant-fold-cow-array.js @@ -35,3 +35,45 @@ assertEquals(42, foo()); assertUnoptimized(foo); })(); + +// Non-extensible +(function() { + const a = Object.preventExtensions([1, 2, 3]); + const foo = () => a[0]; + %PrepareFunctionForOptimization(foo); + assertEquals(1, foo()); + assertEquals(1, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo()); + assertOptimized(foo); + a[0] = 42; + assertEquals(42, foo()); +})(); + +// Sealed +(function() { + const a = Object.seal([1, 2, 3]); + const foo = () => a[0]; + %PrepareFunctionForOptimization(foo); + assertEquals(1, foo()); + assertEquals(1, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo()); + assertOptimized(foo); + a[0] = 42; + assertEquals(42, foo()); +})(); + +// Frozen +(function() { + const a = Object.freeze([1, 2, 3]); + const foo = () => a[0]; + %PrepareFunctionForOptimization(foo); + assertEquals(1, foo()); + assertEquals(1, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo()); + assertOptimized(foo); + a[0] = 42; + assertEquals(1, foo()); +})(); diff --git a/deps/v8/test/mjsunit/compiler/dont-flush-code-marked-for-opt.js b/deps/v8/test/mjsunit/compiler/dont-flush-code-marked-for-opt.js index 582f5940b5..1cfc0cfe10 100644 --- a/deps/v8/test/mjsunit/compiler/dont-flush-code-marked-for-opt.js +++ b/deps/v8/test/mjsunit/compiler/dont-flush-code-marked-for-opt.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: --opt --allow-natives-syntax --expose-gc --stress-flush-bytecode +// Flags: --opt --allow-natives-syntax --expose-gc --flush-bytecode +// Flags: --stress-flush-bytecode function foo(a) {} diff --git a/deps/v8/test/mjsunit/compiler/field-representation-tracking.js b/deps/v8/test/mjsunit/compiler/field-representation-tracking.js new file mode 100644 index 0000000000..660271a858 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/field-representation-tracking.js @@ -0,0 +1,74 @@ +// Copyright 2019 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 --modify-field-representation-inplace +// Flags: --no-always-opt --opt + +// Test that code embedding accesses to a Smi field gets properly +// deoptimized if s->t field representation changes are done in-place. +(function() { + function O(x) { this.x = x; } + + function foo(o) { return o.x; } + %PrepareFunctionForOptimization(foo); + foo(new O(1)); + foo(new O(2)); + %OptimizeFunctionOnNextCall(foo); + foo(new O(3)); + assertOptimized(foo); + + new O(null); + assertUnoptimized(foo); +})(); + +// Test that code embedding assignments to a Smi field gets properly +// deoptimized if s->t field representation changes are done in-place. +(function() { + function O(x) { this.x = x; } + + function foo(o) { o.x = 0; } + %PrepareFunctionForOptimization(foo); + foo(new O(1)); + foo(new O(2)); + %OptimizeFunctionOnNextCall(foo); + foo(new O(3)); + assertOptimized(foo); + + new O(null); + assertUnoptimized(foo); +})(); + +// Test that code embedding accesses to a HeapObject field gets properly +// deoptimized if h->t field representation changes are done in-place. +(function() { + function O(x) { this.x = x; } + + function foo(o) { return o.x; } + %PrepareFunctionForOptimization(foo); + foo(new O(null)); + foo(new O("Hello")); + %OptimizeFunctionOnNextCall(foo); + foo(new O({})); + assertOptimized(foo); + + new O(1); + assertUnoptimized(foo); +})(); + +// Test that code embedding assignments to a Smi field gets properly +// deoptimized if s->t field representation changes are done in-place. +(function() { + function O(x) { this.x = x; } + + function foo(o) { o.x = true; } + %PrepareFunctionForOptimization(foo); + foo(new O(null)); + foo(new O("Hello")); + %OptimizeFunctionOnNextCall(foo); + foo(new O({})); + assertOptimized(foo); + + new O(1); + assertUnoptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/keyed-load-on-string.js b/deps/v8/test/mjsunit/compiler/keyed-load-on-string.js new file mode 100644 index 0000000000..4c3f6d8c74 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/keyed-load-on-string.js @@ -0,0 +1,23 @@ +// Copyright 2019 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 s = "hello"; + +function foo() { + return s[4]; +} +assertTrue("o" === foo()); +assertTrue("o" === foo()); +%OptimizeFunctionOnNextCall(foo); +assertTrue("o" === foo()); + +function bar() { + return s[5]; +} +assertSame(undefined, bar()); +assertSame(undefined, bar()); +%OptimizeFunctionOnNextCall(bar); +assertSame(undefined, bar()); diff --git a/deps/v8/test/mjsunit/compiler/named-store.js b/deps/v8/test/mjsunit/compiler/named-store.js index 8d1306a8c7..037d8593e5 100644 --- a/deps/v8/test/mjsunit/compiler/named-store.js +++ b/deps/v8/test/mjsunit/compiler/named-store.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: --allow-natives-syntax + function Foo(a, b) { var bname = "b"; this["a"] = a; @@ -29,3 +31,29 @@ for (var i = 0; i < 6; i++) { var f = new Foo(i + "", (i + 2) + ""); assertEquals((i + "") + ((i + 2) + ""), f.x); } + + +{ + function Global(i) { this.bla = i } + Global(0); + Global(1); + %OptimizeFunctionOnNextCall(Global); + Global(2); + assertEquals(bla, 2); +} + + +{ + function access(obj) { obj.bla = 42 } + access({a: 0}); + access({b: 0}); + access({c: 0}); + access({d: 0}); + access({e: 0}); + var global = this; + function foo() { access(global) }; + 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 4d7505a968..b0b0cb28d0 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 @@ -29,7 +29,7 @@ if (isNeverOptimizeLiteMode()) { print("Warning: skipping test that requires optimization in Lite mode."); - quit(0); + testRunner.quit(0); } function f() { diff --git a/deps/v8/test/mjsunit/compiler/object-is.js b/deps/v8/test/mjsunit/compiler/object-is.js index 1d7e927894..0c49648c24 100644 --- a/deps/v8/test/mjsunit/compiler/object-is.js +++ b/deps/v8/test/mjsunit/compiler/object-is.js @@ -185,3 +185,33 @@ %OptimizeFunctionOnNextCall(foo); assertFalse(foo()); })(); + +(function() { + function foo(a, b) { return Object.is(+a, +b); } + %PrepareFunctionForOptimization(foo); + assertFalse(foo(1, 2)); + assertFalse(foo(0, -0)); + assertFalse(foo(-0, 0)); + assertFalse(foo(-0, 1)); + assertFalse(foo(-0, 1)); + assertFalse(foo(-Infinity, Infinity)); + assertTrue(foo(0, 0)); + assertTrue(foo(0.1, 0.1)); + assertTrue(foo(Infinity, Infinity)); + assertTrue(foo(-0, -0)); + assertTrue(foo(NaN, NaN)); + assertFalse(foo(Infinity, NaN)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(1, 2)); + assertFalse(foo(0, -0)); + assertFalse(foo(-0, 0)); + assertFalse(foo(-0, 1)); + assertFalse(foo(-0, 1)); + assertFalse(foo(-Infinity, Infinity)); + assertTrue(foo(0, 0)); + assertTrue(foo(0.1, 0.1)); + assertTrue(foo(Infinity, Infinity)); + assertTrue(foo(-0, -0)); + assertTrue(foo(NaN, NaN)); + assertFalse(foo(Infinity, NaN)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/osr-forin.js b/deps/v8/test/mjsunit/compiler/osr-forin.js index b45d200d1b..2cc3ae21d5 100644 --- a/deps/v8/test/mjsunit/compiler/osr-forin.js +++ b/deps/v8/test/mjsunit/compiler/osr-forin.js @@ -16,11 +16,27 @@ function f(a) { return sum; } -var a = new Array(10000); -for (var i = 0; i < 10000; i++) { - a[i] = (i * 999) % 77; -} +function test(a) { + for (var i = 0; i < 10000; i++) { + a[i] = (i * 999) % 77; + } -for (var i = 0; i < 3; i++) { - assertEquals(480270, f(a)); + for (var i = 0; i < 3; i++) { + console.log(f(a)); + assertEquals(480270, f(a)); + } } +var a = new Array(10000); +test(a); + +// Non-extensible +var b = Object.preventExtensions(a); +test(b); + +// Sealed +var c = Object.seal(a); +test(c); + +// Frozen +var d = Object.freeze(a); +test(d); diff --git a/deps/v8/test/mjsunit/compiler/osr-forof.js b/deps/v8/test/mjsunit/compiler/osr-forof.js index ce7b24de13..3481c95644 100644 --- a/deps/v8/test/mjsunit/compiler/osr-forof.js +++ b/deps/v8/test/mjsunit/compiler/osr-forof.js @@ -15,15 +15,6 @@ function f(a) { return sum; } -var a = new Array(10000); -for (var i = 0; i < 10000; i++) { - a[i] = (i * 999) % 77; -} - -for (var i = 0; i < 3; i++) { - assertEquals(480270, f(wrap(a))); -} - function wrap(array) { var iterable = {}; var i = 0; @@ -33,3 +24,28 @@ function wrap(array) { iterable[Symbol.iterator] = function() { return { next:next }; }; return iterable; } + +function test(a) { + for (var i = 0; i < 10000; i++) { + a[i] = (i * 999) % 77; + } + + for (var i = 0; i < 3; i++) { + assertEquals(480270, f(wrap(a))); + } +} + +var a = new Array(10000); +test(a); + +// Non-extensible +var b = Object.preventExtensions(a); +test(b); + +// Sealed +var c = Object.seal(a); +test(c); + +// Frozen +var d = Object.freeze(a); +test(d); diff --git a/deps/v8/test/mjsunit/compiler/regress-9041.js b/deps/v8/test/mjsunit/compiler/regress-9041.js new file mode 100644 index 0000000000..46d8755bde --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-9041.js @@ -0,0 +1,21 @@ +// Copyright 2019 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() { + class A {} + + function foo(a, fn) { + const C = a.constructor; + fn(a); + return a instanceof C; + } + + assertTrue(foo(new A, (a) => {})); + assertTrue(foo(new A, (a) => {})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(new A, (a) => {})); + assertFalse(foo(new A, (a) => { a.__proto__ = {}; })); +})(); diff --git a/deps/v8/test/mjsunit/compiler/regress-9087.js b/deps/v8/test/mjsunit/compiler/regress-9087.js new file mode 100644 index 0000000000..4220a2906c --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-9087.js @@ -0,0 +1,21 @@ +// Copyright 2019 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 constructor() {} +const obj = Object.create(constructor.prototype); + +for (let i = 0; i < 1020; ++i) { + constructor.prototype["x" + i] = 42; +} + +function foo() { + return obj instanceof constructor; +} + +assertTrue(foo()); +assertTrue(foo()); +%OptimizeFunctionOnNextCall(foo); +assertTrue(foo()); diff --git a/deps/v8/test/mjsunit/compiler/regress-935092.js b/deps/v8/test/mjsunit/compiler/regress-935092.js new file mode 100644 index 0000000000..df4eb06dda --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-935092.js @@ -0,0 +1,18 @@ +// Copyright 2019 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 opt(g) { + for (var X = 0; X < 1; X++) { + (new(function() { + this.y + })).x; + (g || (g && (((g || -N)(g && 0))))).y = 0 + } + (function() { g }) +} +opt({}); +%OptimizeFunctionOnNextCall(opt); +opt({}); diff --git a/deps/v8/test/mjsunit/compiler/regress-939316.js b/deps/v8/test/mjsunit/compiler/regress-939316.js index 56dd41e623..79a0079c46 100644 --- a/deps/v8/test/mjsunit/compiler/regress-939316.js +++ b/deps/v8/test/mjsunit/compiler/regress-939316.js @@ -4,16 +4,36 @@ // Flags: --allow-natives-syntax -function f(arg) { - const o = Reflect.construct(Object, arguments, Proxy); - o.foo = arg; -} - -function g(i) { - f(i); -} - -g(0); -g(1); -%OptimizeFunctionOnNextCall(g); -g(2); +(function JSCreate() { + function f(arg) { + const o = Reflect.construct(Object, arguments, Proxy); + o.foo = arg; + } + + function g(i) { + f(i); + } + + g(0); + g(1); + %OptimizeFunctionOnNextCall(g); + g(2); +})(); + + +(function JSCreateArray() { + function f() { + try { + const o = Reflect.construct(Array, arguments, parseInt); + } catch(e) { } + } + + function g() { + f(); + } + + g(); + g(); + %OptimizeFunctionOnNextCall(g); + g(); +})(); diff --git a/deps/v8/test/mjsunit/compiler/regress-945187.js b/deps/v8/test/mjsunit/compiler/regress-945187.js new file mode 100644 index 0000000000..7041042cd3 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-945187.js @@ -0,0 +1,15 @@ +// Copyright 2019 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() { + const o = { get : Object }; + Object.defineProperty(Object, 0, o); +} + +f(); +%OptimizeFunctionOnNextCall(f); +delete Object.fromEntries; +f(); diff --git a/deps/v8/test/mjsunit/compiler/regress-946889.js b/deps/v8/test/mjsunit/compiler/regress-946889.js new file mode 100644 index 0000000000..0bdaef8168 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-946889.js @@ -0,0 +1,18 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +Object.preventExtensions(Array.prototype); + +function foo() { + var arr = []; + [...arr, 42, null]; + arr.length = 1; +} + +foo(); +foo(); +%OptimizeFunctionOnNextCall(foo); +foo(); diff --git a/deps/v8/test/mjsunit/compiler/regress-949435.js b/deps/v8/test/mjsunit/compiler/regress-949435.js new file mode 100644 index 0000000000..e78acad183 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-949435.js @@ -0,0 +1,16 @@ +// Copyright 2019 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() { + const v6 = new String(); + v6.POSITIVE_INFINITY = 1337; + const v8 = Object.seal(v6); + v8.POSITIVE_INFINITY = Object; +} + +f(); +%OptimizeFunctionOnNextCall(f) +f(); diff --git a/deps/v8/test/mjsunit/compiler/regress-952586.js b/deps/v8/test/mjsunit/compiler/regress-952586.js new file mode 100644 index 0000000000..0a17ed7682 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-952586.js @@ -0,0 +1,15 @@ +// Copyright 2019 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 = new Int8Array(1); + +function f(i) { + return i in a; +} + +assertTrue(f(0)); +%OptimizeFunctionOnNextCall(f); +assertFalse(f(-1)); diff --git a/deps/v8/test/mjsunit/compiler/regress-958716.js b/deps/v8/test/mjsunit/compiler/regress-958716.js new file mode 100644 index 0000000000..f2ede1002e --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-958716.js @@ -0,0 +1,17 @@ +// Copyright 2019 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 + +for (let i = 0; i < 2; i++) { + (new String()).valueOf = Symbol; +} + +function foo() { + Promise.resolve(""); +} + +foo(); +%OptimizeFunctionOnNextCall(foo); +foo(); diff --git a/deps/v8/test/mjsunit/compiler/regress-sealedarray-store-outofbounds.js b/deps/v8/test/mjsunit/compiler/regress-sealedarray-store-outofbounds.js new file mode 100644 index 0000000000..4eecf9fa49 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-sealedarray-store-outofbounds.js @@ -0,0 +1,19 @@ +// Copyright 2019 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 --opt --no-always-opt + +const v3 = [0,"symbol"]; +const v5 = 0 - 1; +const v6 = Object.seal(v3); +let v9 = 0; +function f1() { + v6[119090556] = v5; +} +%PrepareFunctionForOptimization(f1); +f1(); +%OptimizeFunctionOnNextCall(f1); +f1(); +assertOptimized(f1); +assertEquals(v6.length, 2); diff --git a/deps/v8/test/mjsunit/compiler/regress-v8-9113.js b/deps/v8/test/mjsunit/compiler/regress-v8-9113.js new file mode 100644 index 0000000000..b602da84e6 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-v8-9113.js @@ -0,0 +1,20 @@ +// Copyright 2019 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 dummy = { x : 0.1 }; + +let o = { x : 0 }; + +function f(o, v) { + o.x = v; +} + +f(o, 0); +f(o, 0); +assertEquals(Infinity, 1 / o.x); +%OptimizeFunctionOnNextCall(f); +f(o, -0); +assertEquals(-Infinity, 1 / o.x); diff --git a/deps/v8/test/mjsunit/compiler/typedarray-keyed.js b/deps/v8/test/mjsunit/compiler/typedarray-keyed.js new file mode 100644 index 0000000000..5b4695fec2 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/typedarray-keyed.js @@ -0,0 +1,34 @@ +// Copyright 2019 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 a = new Int8Array(100); + +function has(i) { + return i in a; +} +assertTrue(has(0)); +assertTrue(has(0)); +%OptimizeFunctionOnNextCall(has); +assertTrue(has(0)); +assertTrue(has(1)); + +function get(i) { + return a[i]; +} +assertEquals(0, get(0)); +assertEquals(0, get(0)); +%OptimizeFunctionOnNextCall(get); +assertEquals(0, get(0)); +assertEquals(0, get(1)); + +function set(i) { + return a[i] = 42 + i; +} +assertEquals(42, set(0)); assertEquals(42, a[0]); +assertEquals(42, set(0)); assertEquals(42, a[0]); +%OptimizeFunctionOnNextCall(set); +assertEquals(42, set(0)); assertEquals(42, a[0]); +assertEquals(43, set(1)); assertEquals(43, a[1]); diff --git a/deps/v8/test/mjsunit/elements-kind.js b/deps/v8/test/mjsunit/elements-kind.js index 3ffdbba2a8..5a2355ecf6 100644 --- a/deps/v8/test/mjsunit/elements-kind.js +++ b/deps/v8/test/mjsunit/elements-kind.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 --expose-gc --nostress-opt --typed-array-max-size-in-heap=2048 +// Flags: --allow-natives-syntax --expose-gc --nostress-opt var elements_kind = { fast_smi_only : 'fast smi only elements', @@ -174,20 +174,25 @@ function make_array() { return eval(make_array_string()); } +%EnsureFeedbackVectorForFunction(construct_smis); function construct_smis() { var a = make_array(); a[0] = 0; // Send the COW array map to the steak house. assertKind(elements_kind.fast_smi_only, a); return a; } + %NeverOptimizeFunction(construct_doubles); +%EnsureFeedbackVectorForFunction(construct_doubles); function construct_doubles() { var a = construct_smis(); a[0] = 1.5; assertKind(elements_kind.fast_double, a); return a; } + %NeverOptimizeFunction(construct_objects); +%EnsureFeedbackVectorForFunction(construct_objects); function construct_objects() { var a = construct_smis(); a[0] = "one"; @@ -196,7 +201,7 @@ function construct_objects() { } // Test crankshafted transition SMI->DOUBLE. - %NeverOptimizeFunction(convert_to_double); + %EnsureFeedbackVectorForFunction(convert_to_double); function convert_to_double(array) { array[1] = 2.5; assertKind(elements_kind.fast_double, array); @@ -208,7 +213,7 @@ for (var i = 0; i < 3; i++) convert_to_double(smis); smis = construct_smis(); convert_to_double(smis); // Test crankshafted transitions SMI->FAST and DOUBLE->FAST. - %NeverOptimizeFunction(convert_to_fast); + %EnsureFeedbackVectorForFunction(convert_to_fast); function convert_to_fast(array) { array[1] = "two"; assertKind(elements_kind.fast, array); @@ -225,7 +230,7 @@ convert_to_fast(smis); convert_to_fast(doubles); // Test transition chain SMI->DOUBLE->FAST (crankshafted function will // transition to FAST directly). - %NeverOptimizeFunction(convert_mixed); +%EnsureFeedbackVectorForFunction(convert_mixed); function convert_mixed(array, value, kind) { array[1] = value; assertKind(kind, array); @@ -267,6 +272,7 @@ function crankshaft_test() { var c = [get(1), get(2), get(3.5)]; assertKind(elements_kind.fast_double, c); } +%PrepareFunctionForOptimization(crankshaft_test); for (var i = 0; i < 3; i++) { crankshaft_test(); } diff --git a/deps/v8/test/mjsunit/error-stack.js b/deps/v8/test/mjsunit/error-stack.js new file mode 100644 index 0000000000..b446a398d6 --- /dev/null +++ b/deps/v8/test/mjsunit/error-stack.js @@ -0,0 +1,75 @@ +// Copyright 2019 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 TestErrorObjectsRetainMap() { + const error1 = new Error("foo"); + const error2 = new Error("bar"); + + assertTrue(%HaveSameMap(error1, error2)); + + // Trigger serialization of the stack-trace. + error1.stack; + assertTrue(%HaveSameMap(error1, error2)); + + error2.stack; + assertTrue(%HaveSameMap(error1, error2)); +})(); + +(function TestPrepareStackTraceCallback() { + Error.prepareStackTrace = (error, frame) => { + return "custom stack trace No. 42"; + }; + + const error = new Error("foo"); + + // Check it twice, so both code paths in the accessor are exercised. + assertEquals(error.stack, "custom stack trace No. 42"); + assertEquals(error.stack, "custom stack trace No. 42"); +})(); + +(function TestPrepareStackTraceCallbackMessesWithProperty() { + Error.prepareStackTrace = (error, frames) => { + error.stack = "Yes, we can write to this!"; + return 42; + }; + + const error = new Error("foo"); + + // Check it twice. The first returns the formatting result, + // the second the value of the private symbol. + assertEquals(error.stack, 42); + assertEquals(error.stack, 42); +})(); + +(function TestPrepareStackTraceCallbackInstallsGetter() { + Error.prepareStackTrace = (error, frames) => { + Object.defineProperty(error, "stack", { get: () => 42 }); + return "<formatted stack trace>"; + }; + + const error = new Error("foo"); + + // Check it twice. The second time the accessor should be used. + assertEquals(error.stack, "<formatted stack trace>"); + assertEquals(error.stack, 42); +})(); + +(function TestPrepareStackTraceCallbackInstallsSetter() { + Error.prepareStackTrace = (error, frames) => { + Object.defineProperty(error, "stack", { set: (x) => { + error[42] = x; + }}); + return "<formatted stack trace>"; + }; + + const error = new Error("foo"); + // Cause the accessor to get installed. + error.stack; + + error.stack = "Who needs stack traces anyway?"; + assertEquals(error[42], "Who needs stack traces anyway?"); + assertEquals(error.stack, undefined); // No getter. +})(); diff --git a/deps/v8/test/mjsunit/es6/block-let-crankshaft-sloppy.js b/deps/v8/test/mjsunit/es6/block-let-crankshaft-sloppy.js index 5711ac270e..e50667ecc9 100644 --- a/deps/v8/test/mjsunit/es6/block-let-crankshaft-sloppy.js +++ b/deps/v8/test/mjsunit/es6/block-let-crankshaft-sloppy.js @@ -467,6 +467,9 @@ function g(x) { } } +%PrepareFunctionForOptimization(f); +%PrepareFunctionForOptimization(g); + for (var i=0; i<10; i++) { f(i); g(i); diff --git a/deps/v8/test/mjsunit/es6/computed-property-names-classes.js b/deps/v8/test/mjsunit/es6/computed-property-names-classes.js index da8e1d8dcb..b3a62ed810 100644 --- a/deps/v8/test/mjsunit/es6/computed-property-names-classes.js +++ b/deps/v8/test/mjsunit/es6/computed-property-names-classes.js @@ -213,6 +213,56 @@ function assertIteratorResult(value, done, result) { })(); +(function TestLength() { + class C { + static ['length']() { + return 42; + } + } + assertEquals(42, C.length()); + + class C1 { + static get ['length']() { + return 'A'; + } + } + assertEquals('A', C1.length); + + class C2 { + static get length() { + assertUnreachable(); + } + static get ['length']() { + return 'B'; + } + } + assertEquals('B', C2.length); + + class C3 { + static get length() { + assertUnreachable(); + } + static get ['length']() { + assertUnreachable(); + } + static get ['length']() { + return 'C'; + } + } + assertEquals('C', C3.length); + + class C4 { + static get ['length']() { + assertUnreachable(); + } + static get length() { + return 'D'; + } + } + assertEquals('D', C4.length); +})(); + + (function TestGetter() { class C { get ['a']() { diff --git a/deps/v8/test/mjsunit/es6/object-assign.js b/deps/v8/test/mjsunit/es6/object-assign.js index 1fec766dd1..2573e3d3c7 100644 --- a/deps/v8/test/mjsunit/es6/object-assign.js +++ b/deps/v8/test/mjsunit/es6/object-assign.js @@ -171,3 +171,58 @@ assertSame(Object.assign(o, {}), o); var source = {get k1() { throw "fail" }}; assertThrows(()=>Object.assign(target, source)); })(); + +(function strings_and_symbol_order1() { + // first order + var log = []; + + var sym1 = Symbol("x"), sym2 = Symbol("y"); + var source = { + get [sym1](){ log.push("get sym1"); }, + get a() { log.push("get a"); }, + get b() { log.push("get b"); }, + get c() { log.push("get c"); }, + get [sym2](){ log.push("get sym2"); }, + }; + + Object.assign({}, source); + + assertEquals(log, ["get a", "get b", "get c", "get sym1", "get sym2"]); +})(); + +(function strings_and_symbol_order2() { + // first order + var log = []; + + var sym1 = Symbol("x"), sym2 = Symbol("y"); + var source = { + get [sym1](){ log.push("get sym1"); }, + get a() { log.push("get a"); }, + get [sym2](){ log.push("get sym2"); }, + get b() { log.push("get b"); }, + get c() { log.push("get c"); }, + }; + + Object.assign({}, source); + + assertEquals(log, ["get a", "get b", "get c", "get sym1", "get sym2"]); +})(); + + +(function strings_and_symbol_order3() { + // first order + var log = []; + + var sym1 = Symbol("x"), sym2 = Symbol("y"); + var source = { + get a() { log.push("get a"); }, + get [sym1](){ log.push("get sym1"); }, + get b() { log.push("get b"); }, + get [sym2](){ log.push("get sym2"); }, + get c() { log.push("get c"); }, + }; + + Object.assign({}, source); + + assertEquals(log, ["get a", "get b", "get c", "get sym1", "get sym2"]); +})(); diff --git a/deps/v8/test/mjsunit/es6/proxies-constructor.js b/deps/v8/test/mjsunit/es6/proxies-constructor.js index 5b30725a52..93b64ec3a1 100644 --- a/deps/v8/test/mjsunit/es6/proxies-constructor.js +++ b/deps/v8/test/mjsunit/es6/proxies-constructor.js @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +(function testNewTarget() { + assertThrows(function(){ Proxy({}, {}); }, TypeError); + assertDoesNotThrow(function(){ new Proxy({}, {}); }); +})(); (function testNonObjectTargetTypes() { assertThrows(function(){ new Proxy(undefined, {}); }, TypeError); diff --git a/deps/v8/test/mjsunit/es6/proxies-revocable.js b/deps/v8/test/mjsunit/es6/proxies-revocable.js index 1f61174a35..82b853af8c 100644 --- a/deps/v8/test/mjsunit/es6/proxies-revocable.js +++ b/deps/v8/test/mjsunit/es6/proxies-revocable.js @@ -21,3 +21,9 @@ assertEquals(undefined, revoke()); for (var trap of traps) { assertThrows(() => Reflect[trap](proxy), TypeError); } + +// Throw TypeError if target or handler is revoked proxy +var revocable = Proxy.revocable({}, {}); +revocable.revoke(); +assertThrows(function(){ Proxy.revocable(revocable.proxy, {}); }, TypeError); +assertThrows(function(){ Proxy.revocable({}, revocable.proxy); }, TypeError); diff --git a/deps/v8/test/mjsunit/field-representation-tracking-clone-object.js b/deps/v8/test/mjsunit/field-representation-tracking-clone-object.js new file mode 100644 index 0000000000..328db20e60 --- /dev/null +++ b/deps/v8/test/mjsunit/field-representation-tracking-clone-object.js @@ -0,0 +1,21 @@ +// Copyright 2019 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(o) { return {...o}; } + +// Warmup the CloneObjectIC with `o.x` being +// a HeapObject field. +var o = {data:null}; +%PrepareFunctionForOptimization(foo); +foo(o); +foo(o); + +// Now update the field representation of o.x +// in-place from HeapObject to Tagged and make +// sure that this is handled properly in the +// fast-path for CloneObjectIC. +o.data = 1; +assertEquals(1, %GetProperty(foo(o), "data")); diff --git a/deps/v8/test/mjsunit/field-representation-tracking.js b/deps/v8/test/mjsunit/field-representation-tracking.js new file mode 100644 index 0000000000..a1c4317515 --- /dev/null +++ b/deps/v8/test/mjsunit/field-representation-tracking.js @@ -0,0 +1,31 @@ +// Copyright 2019 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 --modify-field-representation-inplace + +// Test that s->t field representation changes are done in-place. +(function() { + function O(x) { this.x = x; } + + const a = new O(42); + const b = new O(-8); + assertTrue(%HaveSameMap(a, b)); + a.x = null; + assertTrue(%HaveSameMap(a, b)); + b.x = null; + assertTrue(%HaveSameMap(a, b)); +})(); + +// Test that h->t field representation changes are done in-place. +(function() { + function O(x) { this.x = x; } + + const a = new O(null); + const b = new O("Hello"); + assertTrue(%HaveSameMap(a, b)); + a.x = 1; + assertTrue(%HaveSameMap(a, b)); + b.x = 2; + assertTrue(%HaveSameMap(a, b)); +})(); diff --git a/deps/v8/test/mjsunit/field-type-tracking.js b/deps/v8/test/mjsunit/field-type-tracking.js index 2e0cb8bd6f..6fc8558469 100644 --- a/deps/v8/test/mjsunit/field-type-tracking.js +++ b/deps/v8/test/mjsunit/field-type-tracking.js @@ -148,11 +148,11 @@ var f2 = new Narf(2); var f3 = new Narf(3); function baz(f, y) { f.y = y; } - baz(f1, {y: 9}); - baz(f2, {y: 9}); - baz(f2, {y: 9}); + baz(f1, {b: 9}); + baz(f2, {b: 9}); + baz(f2, {b: 9}); %OptimizeFunctionOnNextCall(baz); - baz(f2, {y: 9}); + baz(f2, {b: 9}); baz(f3, {a: -1}); assertUnoptimized(baz); })(); diff --git a/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-next-tick-count.js b/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-next-tick-count.js new file mode 100644 index 0000000000..973020890a --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-next-tick-count.js @@ -0,0 +1,33 @@ +// Copyright 2019 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 actual = []; + +function createIterator() { + return { + [Symbol.iterator]() { return this; }, + + next() { + return { value: Promise.resolve(1), done: true}; + } + }; +} + +actual.push("start"); +iter = %CreateAsyncFromSyncIterator(createIterator()); + +Promise.resolve(0) + .then(() => actual.push("tick 1")) + .then(() => actual.push("tick 2")) + .then(() => actual.push("tick 3")) + .then(() => actual.push("tick 4")) + .then(() => actual.push("tick 5")); + +let p = iter.next(); +p.then(_ => { actual.push("done"); } ); + +%PerformMicrotaskCheckpoint(); +assertSame("start,tick 1,tick 2,done,tick 3,tick 4,tick 5", actual.join(",")) diff --git a/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-return-tick-count.js b/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-return-tick-count.js new file mode 100644 index 0000000000..c4c5f8dc52 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-return-tick-count.js @@ -0,0 +1,33 @@ +// Copyright 2019 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 actual = []; + +function createIterator() { + return { + [Symbol.iterator]() { return this; }, + + return() { + return { value: Promise.resolve(1), done: true}; + } + }; +} + +actual.push("start"); +iter = %CreateAsyncFromSyncIterator(createIterator()); + +Promise.resolve(0) + .then(() => actual.push("tick 1")) + .then(() => actual.push("tick 2")) + .then(() => actual.push("tick 3")) + .then(() => actual.push("tick 4")) + .then(() => actual.push("tick 5")); + +let p = iter.return(); +p.then(_ => { actual.push("done"); } ); + +%PerformMicrotaskCheckpoint(); +assertSame("start,tick 1,tick 2,done,tick 3,tick 4,tick 5", actual.join(",")) diff --git a/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-throw-tick-count.js b/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-throw-tick-count.js new file mode 100644 index 0000000000..1550f4f1a7 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/async-from-sync-iterator-throw-tick-count.js @@ -0,0 +1,33 @@ +// Copyright 2019 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 actual = []; + +function createIterator() { + return { + [Symbol.iterator]() { return this; }, + + throw() { + return { value: Promise.resolve(1), done: true}; + } + }; +} + +actual.push("start"); +iter = %CreateAsyncFromSyncIterator(createIterator()); + +Promise.resolve(0) + .then(() => actual.push("tick 1")) + .then(() => actual.push("tick 2")) + .then(() => actual.push("tick 3")) + .then(() => actual.push("tick 4")) + .then(() => actual.push("tick 5")); + +let p = iter.throw(); +p.then(_ => { actual.push("done"); } ); + +%PerformMicrotaskCheckpoint(); +assertSame("start,tick 1,tick 2,done,tick 3,tick 4,tick 5", actual.join(",")) diff --git a/deps/v8/test/mjsunit/harmony/async-iterators-resolve.js b/deps/v8/test/mjsunit/harmony/async-iterators-resolve.js new file mode 100644 index 0000000000..182c5b7e20 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/async-iterators-resolve.js @@ -0,0 +1,29 @@ +// Copyright 2019 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 actual = []; + +async function f() { + var p = Promise.resolve(0); + Object.defineProperty(p, "constructor", { + get() { + throw new Error(); + } + }); + actual.push("start"); + for await (var x of [p]); + actual.push("never reached"); +} + +Promise.resolve(0) + .then(() => actual.push("tick 1")) + .then(() => actual.push("tick 2")) + +f().catch(() => actual.push("catch")); + +%PerformMicrotaskCheckpoint(); + +assertSame(["start", "tick 1", "tick 2", "catch"].join(), actual.join()); diff --git a/deps/v8/test/mjsunit/harmony/hashbang-eval.js b/deps/v8/test/mjsunit/harmony/hashbang-eval.js index c5040f7bee..f30ebd0c45 100644 --- a/deps/v8/test/mjsunit/harmony/hashbang-eval.js +++ b/deps/v8/test/mjsunit/harmony/hashbang-eval.js @@ -4,8 +4,8 @@ // Flags: --harmony-hashbang -// Hashbang syntax is not allowed in eval. -assertThrows("#!", SyntaxError); -assertThrows("#!\n", SyntaxError); -assertThrows("#!---IGNORED---", SyntaxError); -assertThrows("#!---IGNORED---\n", SyntaxError); +// Hashbang syntax is allowed in eval. +assertEquals(eval("#!"), undefined); +assertEquals(eval("#!\n"), undefined); +assertEquals(eval("#!---IGNORED---"), undefined); +assertEquals(eval("#!---IGNORED---\n"), undefined); diff --git a/deps/v8/test/mjsunit/harmony/promise-all-settled.js b/deps/v8/test/mjsunit/harmony/promise-all-settled.js new file mode 100644 index 0000000000..18d18823eb --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/promise-all-settled.js @@ -0,0 +1,259 @@ +// Copyright 2019 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-promise-all-settled + +class MyError extends Error {} + +const descriptor = Object.getOwnPropertyDescriptor(Promise, "allSettled"); +assertTrue(descriptor.configurable); +assertTrue(descriptor.writable); +assertFalse(descriptor.enumerable); + +// 1. Let C be the this value. +// 2. If Type(C) is not Object, throw a TypeError exception. +assertThrows(() => Promise.allSettled.call(1), TypeError); + +{ + // 3. Let promiseCapability be ? NewPromiseCapability(C). + let called = false; + class MyPromise extends Promise { + constructor(...args) { + called = true; + super(...args); + } + } + + MyPromise.allSettled([]); + assertTrue(called); +} + +{ + // 4. Let iteratorRecord be GetIterator(iterable). + // 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + let caught = false; + (async function() { + class MyError extends Error {} + let err; + + try { + await Promise.allSettled({ + [Symbol.iterator]() { + throw new MyError(); + } + }); + } catch (e) { + assertTrue(e instanceof MyError); + caught = true; + } + })(); + + %PerformMicrotaskCheckpoint(); + assertTrue(caught); +} + +{ + // 6. a. Let next be IteratorStep(iteratorRecord). + let iteratorStep = false; + (async function() { + try { + await Promise.allSettled({ + [Symbol.iterator]() { + return { + next() { + iteratorStep = true; + return { done: true } + } + }; + } + }); + } catch (e) { + %AbortJS(e.stack); + } + })(); + + %PerformMicrotaskCheckpoint(); + assertTrue(iteratorStep); +} + +{ + // 6. a. Let next be IteratorStep(iteratorRecord). + // 6. b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + // 6. c. ReturnIfAbrupt(next). + let caught = false; + (async function() { + try { + await Promise.allSettled({ + [Symbol.iterator]() { + return { + next() { + throw new MyError(); + } + }; + } + }); + } catch (e) { + assertTrue(e instanceof MyError); + caught = true; + } + })(); + + %PerformMicrotaskCheckpoint(); + assertTrue(caught); +} + +{ + // 6. e. Let nextValue be IteratorValue(next). + let iteratorValue = false; + (async function() { + try { + await Promise.allSettled({ + [Symbol.iterator]() { + let done = false; + + return { + next() { + let result = { value: 1, done }; + iteratorValue = true; + done = true; + return result; + } + }; + } + }); + } catch (e) { + %AbortJS(e.stack); + } + })(); + + %PerformMicrotaskCheckpoint(); + assertTrue(iteratorValue); +} + +{ + // 6. e. Let nextValue be IteratorValue(next). + // 6. f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + // 6. g. ReturnIfAbrupt(nextValue). + let caught = false; + (async function() { + try { + await Promise.allSettled({ + [Symbol.iterator]() { + let done = false; + + return { + next() { + return result = { + get value() {throw new MyError(''); }, + done: false + }; + } + }; + } + }); + } catch (e) { + assertTrue(e instanceof MyError); + caught = true; + } + })(); + + %PerformMicrotaskCheckpoint(); + assertTrue(caught); +} + +{ + // TODO(mathias): https://github.com/tc39/proposal-promise-allSettled/pull/40 + // 6. i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). + let called = false; + class MyPromise extends Promise { + static resolve(...args) { + called = true; + super.resolve(...args); + } + } + + MyPromise.allSettled([1]); + assertTrue(called); +} + +{ + // 6. z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + let called = false; + class MyPromise extends Promise { + then(...args) { + called = true; + super.resolve(...args); + } + } + + MyPromise.allSettled([1]); + assertTrue(called); +} + +{ + let called = false; + let result; + Promise.allSettled([]).then(x => { + called = true; + result = x; + }); + + %PerformMicrotaskCheckpoint(); + assertTrue(called); + assertEquals(result, []); +} + +{ + let called = false; + Promise.allSettled([Promise.resolve("foo")]).then(v => { + assertEquals(v.length, 1); + const [x] = v; + + assertSame(Object.getPrototypeOf(x), Object.getPrototypeOf({})); + const descs = Object.getOwnPropertyDescriptors(x); + assertEquals(Object.keys(descs).length, 2); + + const { value: desc } = descs; + assertTrue(desc.writable); + assertTrue(desc.enumerable); + assertTrue(desc.configurable); + + assertEquals(x.value, "foo"); + assertEquals(x.status, "fulfilled"); + called = true; + }); + + %PerformMicrotaskCheckpoint(); + assertTrue(called); +} + +{ + let called = false; + Promise.allSettled([Promise.reject("foo")]).then(v => { + assertEquals(v.length, 1); + const [x] = v; + assertEquals(x.reason, "foo"); + assertEquals(x.status, "rejected"); + called = true; + }); + + %PerformMicrotaskCheckpoint(); + assertTrue(called); +} + +{ + let called = false; + Promise.allSettled([Promise.resolve("bar"), Promise.reject("foo")]).then(v => { + assertEquals(v.length, 2); + const [x, y] = v; + assertEquals(x.value, "bar"); + assertEquals(x.status, "fulfilled"); + assertEquals(y.reason, "foo"); + assertEquals(y.status, "rejected"); + called = true; + }); + + %PerformMicrotaskCheckpoint(); + assertTrue(called); +} diff --git a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-flag-sequence-generated.js b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-flag-sequence-generated.js index e033c722c7..1de0a48e3f 100644 --- a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-flag-sequence-generated.js +++ b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-flag-sequence-generated.js @@ -1,9 +1,13 @@ -// Copyright 2018 the V8 project authors. All rights reserved. +// Copyright 2019 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-regexp-sequence +// These tests have been generated by the script at +// https://gist.github.com/mathiasbynens/3b42c99a227521dabfe68d9e63f00f42. +// Do not modify this file directly! + const re = /\p{Emoji_Flag_Sequence}/u; assertTrue(re.test('\u{1F1E6}\u{1F1E8}')); diff --git a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-keycap-sequence-generated.js b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-keycap-sequence-generated.js index 8366a395ec..2d72b474d9 100644 --- a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-keycap-sequence-generated.js +++ b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-keycap-sequence-generated.js @@ -1,9 +1,13 @@ -// Copyright 2018 the V8 project authors. All rights reserved. +// Copyright 2019 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-regexp-sequence +// These tests have been generated by the script at +// https://gist.github.com/mathiasbynens/3b42c99a227521dabfe68d9e63f00f42. +// Do not modify this file directly! + const re = /\p{Emoji_Keycap_Sequence}/u; assertTrue(re.test('#\uFE0F\u20E3')); diff --git a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-modifier-sequence-generated.js b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-modifier-sequence-generated.js index 0e11d6c462..b990bf7aaf 100644 --- a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-modifier-sequence-generated.js +++ b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-modifier-sequence-generated.js @@ -4,6 +4,9 @@ // Flags: --harmony-regexp-sequence +// TODO(mathias): Update these tests once a Unicode 12-friendly ICU +// version rolls into V8. + const re = /\p{Emoji_Modifier_Sequence}/u; assertTrue(re.test('\u261D\u{1F3FB}')); diff --git a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-tag-sequence-generated.js b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-tag-sequence-generated.js index 129e1c7777..839d55791f 100644 --- a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-tag-sequence-generated.js +++ b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-tag-sequence-generated.js @@ -1,9 +1,13 @@ -// Copyright 2018 the V8 project authors. All rights reserved. +// Copyright 2019 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-regexp-sequence +// These tests have been generated by the script at +// https://gist.github.com/mathiasbynens/3b42c99a227521dabfe68d9e63f00f42. +// Do not modify this file directly! + const re = /\p{Emoji_Tag_Sequence}/u; assertTrue(re.test('\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}')); diff --git a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-zwj-sequence-generated.js b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-zwj-sequence-generated.js index 619bf46175..b04f0e441b 100644 --- a/deps/v8/test/mjsunit/harmony/regexp-property-emoji-zwj-sequence-generated.js +++ b/deps/v8/test/mjsunit/harmony/regexp-property-emoji-zwj-sequence-generated.js @@ -1,9 +1,13 @@ -// Copyright 2018 the V8 project authors. All rights reserved. +// Copyright 2019 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-regexp-sequence +// These tests have been generated by the script at +// https://gist.github.com/mathiasbynens/3b42c99a227521dabfe68d9e63f00f42. +// Do not modify this file directly! + const re = /\p{Emoji_ZWJ_Sequence}/u; assertTrue(re.test('\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F468}')); @@ -23,6 +27,16 @@ assertTrue(re.test('\u{1F468}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}')); assertTrue(re.test('\u{1F468}\u200D\u{1F469}\u200D\u{1F467}')); assertTrue(re.test('\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}')); assertTrue(re.test('\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}')); assertTrue(re.test('\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F468}')); assertTrue(re.test('\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F469}')); assertTrue(re.test('\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}')); @@ -37,6 +51,52 @@ assertTrue(re.test('\u{1F469}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}')); assertTrue(re.test('\u{1F469}\u200D\u{1F469}\u200D\u{1F467}')); assertTrue(re.test('\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}')); assertTrue(re.test('\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}')); +assertTrue(re.test('\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}')); +assertTrue(re.test('\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}')); assertTrue(re.test('\u{1F468}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F468}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F468}\u200D\u2708\uFE0F')); @@ -53,10 +113,9 @@ assertTrue(re.test('\u{1F468}\u200D\u{1F527}')); assertTrue(re.test('\u{1F468}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F468}\u200D\u{1F680}')); assertTrue(re.test('\u{1F468}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F468}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F468}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F468}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F468}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F468}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F468}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u2708\uFE0F')); @@ -73,10 +132,9 @@ assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F527}')); assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F680}')); assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u2708\uFE0F')); @@ -93,10 +151,9 @@ assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F527}')); assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F680}')); assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u2708\uFE0F')); @@ -113,10 +170,9 @@ assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F527}')); assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F680}')); assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u2708\uFE0F')); @@ -133,10 +189,9 @@ assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F527}')); assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F680}')); assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u2708\uFE0F')); @@ -153,10 +208,9 @@ assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F527}')); assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F680}')); assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F469}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F469}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F469}\u200D\u2708\uFE0F')); @@ -173,10 +227,9 @@ assertTrue(re.test('\u{1F469}\u200D\u{1F527}')); assertTrue(re.test('\u{1F469}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F469}\u200D\u{1F680}')); assertTrue(re.test('\u{1F469}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F469}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F469}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F469}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F469}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F469}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F469}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u2708\uFE0F')); @@ -193,10 +246,9 @@ assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F527}')); assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F680}')); assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u2708\uFE0F')); @@ -213,10 +265,9 @@ assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F527}')); assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F680}')); assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u2708\uFE0F')); @@ -233,10 +284,9 @@ assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F527}')); assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F680}')); assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u2708\uFE0F')); @@ -253,10 +303,9 @@ assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F527}')); assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F680}')); assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9BD}')); assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u2695\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u2696\uFE0F')); assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u2708\uFE0F')); @@ -273,146 +322,9 @@ assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F527}')); assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F52C}')); assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F680}')); assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F692}')); -assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B0}')); -assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B1}')); -assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B2}')); -assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B3}')); -assertTrue(re.test('\u{1F46E}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F46E}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F46E}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F471}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F471}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F471}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F473}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F473}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F473}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F477}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F477}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F477}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F482}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F482}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F482}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F575}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F575}\uFE0F\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F575}\uFE0F\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9D9}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DA}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DB}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}')); -assertTrue(re.test('\u{1F9DC}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DD}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9DF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9DF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9AF}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9BC}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9BD}')); assertTrue(re.test('\u26F9\u{1F3FB}\u200D\u2640\uFE0F')); assertTrue(re.test('\u26F9\u{1F3FB}\u200D\u2642\uFE0F')); assertTrue(re.test('\u26F9\u{1F3FC}\u200D\u2640\uFE0F')); @@ -485,8 +397,80 @@ assertTrue(re.test('\u{1F3CC}\u{1F3FF}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F3CC}\u{1F3FF}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F3CC}\uFE0F\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F3CC}\uFE0F\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F46E}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F46E}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F46E}\u{1F3FF}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F46F}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F46F}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F471}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F471}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F471}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F473}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F473}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F473}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F477}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F477}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F477}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F481}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F481}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F481}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F482}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F482}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}')); +assertTrue(re.test('\u{1F482}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F482}\u{1F3FF}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F486}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F486}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F486}\u{1F3FB}\u200D\u2640\uFE0F')); @@ -511,6 +495,90 @@ assertTrue(re.test('\u{1F487}\u{1F3FE}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F487}\u{1F3FE}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F487}\u{1F3FF}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F487}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F575}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F575}\uFE0F\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F575}\uFE0F\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F645}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F645}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F645}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F646}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F646}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F646}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F647}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F647}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F647}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64B}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64B}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64B}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64D}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64D}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64D}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64E}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64E}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F64E}\u{1F3FF}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F6A3}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F6A3}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F6A3}\u{1F3FB}\u200D\u2640\uFE0F')); @@ -559,6 +627,30 @@ assertTrue(re.test('\u{1F6B6}\u{1F3FE}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F6B6}\u{1F3FE}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F6B6}\u{1F3FF}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F6B6}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F926}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F926}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F926}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F937}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F937}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F937}\u{1F3FF}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F938}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F938}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F938}\u{1F3FB}\u200D\u2640\uFE0F')); @@ -609,6 +701,66 @@ assertTrue(re.test('\u{1F93E}\u{1F3FE}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F93E}\u{1F3FE}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F93E}\u{1F3FF}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F93E}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B8}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9B9}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CD}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CE}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9CF}\u{1F3FF}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F9D6}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F9D6}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F9D6}\u{1F3FB}\u200D\u2640\uFE0F')); @@ -645,138 +797,119 @@ assertTrue(re.test('\u{1F9D8}\u{1F3FE}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F9D8}\u{1F3FE}\u200D\u2642\uFE0F')); assertTrue(re.test('\u{1F9D8}\u{1F3FF}\u200D\u2640\uFE0F')); assertTrue(re.test('\u{1F9D8}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F481}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F481}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F481}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F645}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F645}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F645}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F646}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F646}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F646}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F647}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F647}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F647}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64B}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64B}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64B}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64D}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64D}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64D}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64E}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64E}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F64E}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F926}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F926}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F926}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F937}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F937}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F937}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B8}\u{1F3FF}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FB}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FB}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FC}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FC}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FD}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FD}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FE}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FE}\u200D\u2642\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FF}\u200D\u2640\uFE0F')); -assertTrue(re.test('\u{1F9B9}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9D9}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DA}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DB}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DC}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FB}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FB}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FC}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FC}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FD}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FD}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DD}\u{1F3FF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DE}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F9DF}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F9DF}\u200D\u2642\uFE0F')); +assertTrue(re.test('\u{1F468}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F468}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F468}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F468}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F468}\u{1F3FB}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F468}\u{1F3FC}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F468}\u{1F3FD}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F468}\u{1F3FE}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F468}\u{1F3FF}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F469}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F469}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F469}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F469}\u{1F3FB}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F469}\u{1F3FC}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F469}\u{1F3FD}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F469}\u{1F3FE}\u200D\u{1F9B3}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B0}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B1}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B2}')); +assertTrue(re.test('\u{1F469}\u{1F3FF}\u200D\u{1F9B3}')); assertTrue(re.test('\u{1F3F3}\uFE0F\u200D\u{1F308}')); assertTrue(re.test('\u{1F3F4}\u200D\u2620\uFE0F')); -assertTrue(re.test('\u{1F9DC}\u{1F3FE}\u200D\u2640\uFE0F')); +assertTrue(re.test('\u{1F415}\u200D\u{1F9BA}')); +assertTrue(re.test('\u{1F482}\u{1F3FB}\u200D\u2640\uFE0F')); diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-952722.js b/deps/v8/test/mjsunit/harmony/regress/regress-952722.js new file mode 100644 index 0000000000..6d6b02016d --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/regress/regress-952722.js @@ -0,0 +1,12 @@ +// Copyright 2019 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: --no-lazy + +class A { + static #a = 1; + static b = class { + static get_A() { return val.#a; } + } +} diff --git a/deps/v8/test/mjsunit/interrupt-budget-override.js b/deps/v8/test/mjsunit/interrupt-budget-override.js new file mode 100644 index 0000000000..acbe837c56 --- /dev/null +++ b/deps/v8/test/mjsunit/interrupt-budget-override.js @@ -0,0 +1,18 @@ +// Copyright 2019 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: --opt --interrupt-budget=100 --allow-natives-syntax + +function f() { + let s = 0; + for (let i = 0; i < 10; i++) { + s += i; + } + return s; +} + +%PrepareFunctionForOptimization(f); +f(); +f(); +assertOptimized(f); diff --git a/deps/v8/test/mjsunit/intl-numberformat-formattoparts.js b/deps/v8/test/mjsunit/intl-numberformat-formattoparts.js index c667c7bdec..48c8c85a15 100644 --- a/deps/v8/test/mjsunit/intl-numberformat-formattoparts.js +++ b/deps/v8/test/mjsunit/intl-numberformat-formattoparts.js @@ -204,13 +204,15 @@ if (this.Intl) { new Intl.NumberFormat("ar-IQ", arPercentOptions); assertParts(arPercentFormatter, -135.32, - [MinusSign("\u{061C}-"), + [Literal("\u{061C}"), + MinusSign("-"), Integer("١٣"), Group("٬"), Integer("٥٣٢"), Decimal("٫"), Fraction("٠٠"), - PercentSign("٪\u{061C}")]); + PercentSign("٪"), + Literal("\u{061C}")]); // Decimals. diff --git a/deps/v8/test/mjsunit/keyed-has-ic.js b/deps/v8/test/mjsunit/keyed-has-ic.js index 9e6fe25cc8..f0b95de2c6 100644 --- a/deps/v8/test/mjsunit/keyed-has-ic.js +++ b/deps/v8/test/mjsunit/keyed-has-ic.js @@ -271,6 +271,7 @@ for (test in tests) { proto(); proto(); + %OptimizeFunctionOnNextCall(proto); proto(); })(); @@ -281,6 +282,9 @@ for (test in tests) { }; assertThrows(test, TypeError); + assertThrows(test, TypeError); + %OptimizeFunctionOnNextCall(test); + assertThrows(test, TypeError); })(); // `in` is allowed on `this` even when `this` is a string @@ -291,6 +295,7 @@ for (test in tests) { test.call(""); test.call(""); + %OptimizeFunctionOnNextCall(test); test.call(""); })(); @@ -310,6 +315,10 @@ for (test in tests) { assertFalse(test(0)); assertFalse(test(0,1)); assertTrue(test(0,1,2)); + + %OptimizeFunctionOnNextCall(test); + assertFalse(test(0,1)); + assertTrue(test(0,1,2)); })(); (function() { @@ -320,6 +329,7 @@ for (test in tests) { assertFalse(test(1)); assertFalse(test(1)); + %OptimizeFunctionOnNextCall(test); assertFalse(test(1)); })(); @@ -347,6 +357,8 @@ for (test in tests) { assertFalse(test(str, 0)); assertFalse(test(str, 0)); + %OptimizeFunctionOnNextCall(test); + assertFalse(test(str, 0)); })(); (function() { @@ -362,6 +374,7 @@ for (test in tests) { var str = "string"; assertFalse(test(str, "length")); assertFalse(test(str, "length")); + %OptimizeFunctionOnNextCall(test); assertFalse(test(str, "length")); })(); @@ -378,6 +391,7 @@ for (test in tests) { var str = "string"; assertFalse(test(str, 0)); assertFalse(test(str, 0)); + %OptimizeFunctionOnNextCall(test); assertFalse(test(str, 0)); })(); @@ -392,11 +406,58 @@ for (test in tests) { } var ary = [0,1,2,3]; - assertTrue(test(ary, 1)); - assertTrue(test(ary, 1)); + function testArray(ary) { + assertTrue(test(ary, 1)); + assertTrue(test(ary, 1)); + } + testArray(ary); + // Non-extensible + var b = Object.preventExtensions(ary); + testArray(b); + + // Sealed + var c = Object.seal(ary); + testArray(c); + + // Frozen + var d = Object.freeze(ary); + testArray(d); var str = "string"; assertFalse(test(str, 0)); assertFalse(test(str, 0)); + %OptimizeFunctionOnNextCall(test); assertFalse(test(str, 0)); })(); + +const heap_constant_ary = [0,1,2,3]; + +function testHeapConstantArray(heap_constant_ary) { + + function test() { + return 1 in heap_constant_ary; + } + + assertTrue(test()); + assertTrue(test()); + %OptimizeFunctionOnNextCall(test); + assertTrue(test()); + + heap_constant_ary[1] = 2; + assertTrue(test()); + %OptimizeFunctionOnNextCall(test); + assertTrue(test()); +} +testHeapConstantArray(heap_constant_ary); + +// Non-extensible +var b = Object.preventExtensions(heap_constant_ary); +testHeapConstantArray(b); + +// Sealed +var c = Object.seal(heap_constant_ary); +testHeapConstantArray(c); + +// Frozen +var d = Object.freeze(heap_constant_ary); +testHeapConstantArray(d); diff --git a/deps/v8/test/mjsunit/keyed-ic.js b/deps/v8/test/mjsunit/keyed-ic.js index a6726ed492..01736c7791 100644 --- a/deps/v8/test/mjsunit/keyed-ic.js +++ b/deps/v8/test/mjsunit/keyed-ic.js @@ -150,24 +150,39 @@ runTest(); runTest = function() { var o = [ 42, 43 ]; - var initial_X = 0; - var X = initial_X; - var Y = 1; - - function fieldTest(change_index) { - for (var i = 0; i < 10; i++) { - var property = o[X]; - if (i <= change_index) { - assertEquals(42, property); - } else { - assertEquals(43, property); + function test(o) { + var initial_X = 0; + var X = initial_X; + var Y = 1; + + function fieldTest(change_index) { + for (var i = 0; i < 10; i++) { + var property = o[X]; + if (i <= change_index) { + assertEquals(42, property); + } else { + assertEquals(43, property); + } + if (i == change_index) X = Y; } - if (i == change_index) X = Y; - } - X = initial_X; - }; + X = initial_X; + }; - for (var i = 0; i < 10; i++) fieldTest(i); + for (var i = 0; i < 10; i++) fieldTest(i); + } + test(o); + + // Non-extensible + var b = Object.preventExtensions(o); + test(b); + + // Sealed + var c = Object.seal(o); + test(c); + + // Frozen + var d = Object.freeze(o); + test(d); } runTest(); diff --git a/deps/v8/test/mjsunit/mjsunit.js b/deps/v8/test/mjsunit/mjsunit.js index cedb51b64e..87977c2516 100644 --- a/deps/v8/test/mjsunit/mjsunit.js +++ b/deps/v8/test/mjsunit/mjsunit.js @@ -690,7 +690,7 @@ var prettyPrinted; // optimization is always disabled, explicitly exit the test with a warning. if (opt_status & V8OptimizationStatus.kLiteMode) { print("Warning: Test uses assertOptimized in Lite mode, skipping test."); - quit(0); + testRunner.quit(0); } // Tests that use assertOptimized() do not make sense if --no-opt // option is provided. Such tests must add --opt to flags comment. diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index da5f4d14f6..83be1d0eee 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/deps/v8/test/mjsunit/mjsunit.status @@ -353,8 +353,8 @@ 'regress/regress-crbug-772056': [SKIP], 'regress/regress-crbug-816961': [SKIP], 'regress/wasm/*': [SKIP], - 'tools/compiler-trace-flags': [SKIP], 'regress/regress-8947': [SKIP], + 'regress/regress-v8-9106': [SKIP], 'wasm/*': [SKIP], # Other tests that use asm / wasm / optimized code. @@ -364,12 +364,14 @@ 'asm/call-annotation': [SKIP], 'asm/global-imports': [SKIP], 'asm/regress-913822': [SKIP], + 'asm/regress-937650': [SKIP], 'asm/return-types': [SKIP], 'regress/regress-599719': [SKIP], 'regress/regress-6196': [SKIP], 'regress/regress-6700': [SKIP], 'regress/regress-6838-2': [SKIP], 'regress/regress-6838-3': [SKIP], + 'regress/regress-9022': [SKIP], 'regress/regress-crbug-934138': [SKIP], # Timeouts in lite / jitless mode. @@ -384,6 +386,10 @@ 'regress/regress-crbug-721835': [SKIP], 'regress/regress-crbug-759327': [SKIP], 'regress/regress-crbug-898974': [SKIP], + + # These tests check that we can trace the compiler. + 'tools/compiler-trace-flags': [SKIP], + 'tools/compiler-trace-flags-wasm': [SKIP] }], # 'lite_mode or variant == jitless' ############################################################################## @@ -393,150 +399,6 @@ }], # lite_mode ############################################################################## -['variant == jitless', { - # https://crbug.com/v8/7777 - 'array-literal-transitions': [SKIP], - 'array-push5': [SKIP], - 'array-shift4': [SKIP], - 'array-store-and-grow': [SKIP], - 'code-coverage-block-opt': [SKIP], - 'compiler/abstract-equal-receiver': [SKIP], - 'compiler/abstract-equal-symbol': [SKIP], - 'compiler/abstract-equal-undetectable': [SKIP], - 'compiler/array-buffer-is-view': [SKIP], - 'compiler/array-multiple-receiver-maps': [SKIP], - 'compiler/array-push-3': [SKIP], - 'compiler/array-slice-clone': [SKIP], - 'compiler/constant-fold-cow-array': [SKIP], - 'compiler/dataview-deopt': [SKIP], - 'compiler/dataview-get': [SKIP], - 'compiler/dataview-neutered': [SKIP], - 'compiler/dataview-set': [SKIP], - 'compiler/deopt-array-builtins': [SKIP], - 'compiler/deopt-array-push': [SKIP], - 'compiler/deopt-inlined-from-call': [SKIP], - 'compiler/deopt-numberoroddball-binop': [SKIP], - 'compiler/deopt-string-outofbounds': [SKIP], - 'compiler/dont-flush-code-marked-for-opt': [SKIP], - 'compiler/increment-typefeedback': [SKIP], - 'compiler/inlined-array-pop-opt': [SKIP], - 'compiler/inlined-call': [SKIP], - 'compiler/integral32-add-sub': [SKIP], - 'compiler/manual-concurrent-recompile': [SKIP], - 'compiler/math-imul': [SKIP], - 'compiler/native-context-specialization-hole-check': [SKIP], - 'compiler/number-abs': [SKIP], - 'compiler/number-ceil': [SKIP], - 'compiler/number-comparison-truncations': [SKIP], - 'compiler/number-divide': [SKIP], - 'compiler/number-floor': [SKIP], - 'compiler/number-max': [SKIP], - 'compiler/number-min': [SKIP], - 'compiler/number-modulus': [SKIP], - 'compiler/number-round': [SKIP], - 'compiler/number-toboolean': [SKIP], - 'compiler/number-trunc': [SKIP], - 'compiler/optimized-float32array-length': [SKIP], - 'compiler/optimized-float64array-length': [SKIP], - 'compiler/optimized-int32array-length': [SKIP], - 'compiler/optimized-uint32array-length': [SKIP], - 'compiler/opt-next-call': [SKIP], - 'compiler/opt-next-call-turbo': [SKIP], - 'compiler/promise-resolve-stable-maps': [SKIP], - 'compiler/redundancy-elimination': [SKIP], - 'compiler/regress-5320': [SKIP], - 'compiler/regress-compare-negate': [SKIP], - 'compiler/stress-deopt-count-1': [SKIP], - 'compiler/stress-deopt-count-2': [SKIP], - 'compiler/string-from-code-point': [SKIP], - 'compiler/uint8-clamped-array': [SKIP], - 'constant-folding-2': [SKIP], - 'default-nospec': [SKIP], - 'deopt-minus-zero': [SKIP], - 'deopt-recursive-eager-once': [SKIP], - 'deopt-recursive-lazy-once': [SKIP], - 'deopt-recursive-soft-once': [SKIP], - 'deopt-unlinked': [SKIP], - 'deopt-with-fp-regs': [SKIP], - 'deserialize-optimize-inner': [SKIP], - 'div-mul-minus-one': [SKIP], - 'elements-transition-hoisting': [SKIP], - 'ensure-growing-store-learns': [SKIP], - 'es6/array-iterator-turbo': [SKIP], - 'es6/block-let-crankshaft': [SKIP], - 'es6/block-let-crankshaft-sloppy': [SKIP], - 'es6/block-scoping': [SKIP], - 'es6/block-scoping-sloppy': [SKIP], - 'es6/collections-constructor-custom-iterator': [SKIP], - 'es6/collections-constructor-iterator-side-effect': [SKIP], - 'es6/collections-constructor-with-modified-array-prototype': [SKIP], - 'es6/collections-constructor-with-modified-protoype': [SKIP], - 'es6/map-constructor-entry-side-effect': [SKIP], - 'es6/map-constructor-entry-side-effect2': [SKIP], - 'es6/map-constructor-entry-side-effect3': [SKIP], - 'es6/map-constructor-entry-side-effect4': [SKIP], - 'field-type-tracking': [SKIP], - 'getters-on-elements': [SKIP], - 'ignition/throw-if-hole': [SKIP], - 'ignition/throw-if-not-hole': [SKIP], - 'ignition/throw-super-not-called': [SKIP], - 'keyed-load-hole-to-undefined': [SKIP], - 'keyed-load-with-string-key': [SKIP], - 'keyed-load-with-symbol-key': [SKIP], - 'math-deopt': [SKIP], - 'math-floor-of-div-minus-zero': [SKIP], - 'modules-turbo1': [SKIP], - 'never-optimize': [SKIP], - 'object-seal': [SKIP], - 'optimized-map': [SKIP], - 'regress/regress-2132': [SKIP], - 'regress/regress-2250': [SKIP], - 'regress/regress-2315': [SKIP], - 'regress/regress-2339': [SKIP], - 'regress/regress-2451': [SKIP], - 'regress/regress-252797': [SKIP], - 'regress/regress-2618': [SKIP], - 'regress/regress-3176': [SKIP], - 'regress/regress-3650-3': [SKIP], - 'regress/regress-3709': [SKIP], - 'regress/regress-385565': [SKIP], - 'regress/regress-4380': [SKIP], - 'regress/regress-5404': [SKIP], - 'regress/regress-5790': [SKIP], - 'regress/regress-5802': [SKIP], - 'regress/regress-6607-1': [SKIP], - 'regress/regress-6607-2': [SKIP], - 'regress/regress-6941': [SKIP], - 'regress/regress-6948': [SKIP], - 'regress/regress-6989': [SKIP], - 'regress/regress-6991': [SKIP], - 'regress/regress-7014-1': [SKIP], - 'regress/regress-7014-2': [SKIP], - 'regress/regress-7135': [SKIP], - 'regress/regress-7254': [SKIP], - 'regress/regress-7510': [SKIP], - 'regress/regress-794825': [SKIP], - 'regress/regress-8913': [SKIP], - 'regress/regress-crbug-554831': [SKIP], - 'regress/regress-crbug-587068': [SKIP], - 'regress/regress-crbug-594183': [SKIP], - 'regress/regress-crbug-882233-2': [SKIP], - 'regress/regress-embedded-cons-string': [SKIP], - 'regress/regress-map-invalidation-2': [SKIP], - 'regress/regress-param-local-type': [SKIP], - 'regress/regress-store-uncacheable': [SKIP], - 'regress/regress-v8-5697': [SKIP], - 'shared-function-tier-up-turbo': [SKIP], - 'shift-for-integer-div': [SKIP], - 'sin-cos': [SKIP], - 'smi-mul': [SKIP], - 'smi-mul-const': [SKIP], - 'string-deopt': [SKIP], - 'strong-rooted-literals': [SKIP], - 'unary-minus-deopt': [SKIP], -}], # variant == jitless - -############################################################################## ['byteorder == big', { # Emscripten requires little-endian, skip all tests on big endian platforms. 'asm/embenchen/*': [SKIP], @@ -900,7 +762,7 @@ }], # 'isolates' ############################################################################## -['deopt_fuzzer == True', { +['deopt_fuzzer', { # Skip tests that are not suitable for deoptimization fuzzing. 'never-optimize': [SKIP], @@ -921,8 +783,11 @@ 'shared-function-tier-up-turbo': [SKIP], # Fails deopt_fuzzer due to --deopt_every_n_times - 'es6/array-iterator-turbo': [SKIP] -}], # 'deopt_fuzzer == True' + 'es6/array-iterator-turbo': [SKIP], + + # Too slow tests. + 'regress/regress-740784': [SKIP], +}], # 'deopt_fuzzer' ############################################################################## ['gc_fuzzer', { @@ -941,27 +806,12 @@ # Fails allocation on tsan. 'es6/classes': [PASS, ['tsan', SKIP]], + 'regress/regress-779407': [PASS, ['tsan', SKIP]], # Tests that fail some assertions due to checking internal state sensitive - # to GC. We mark PASS,FAIL to not skip those tests on the endurance fuzzer. - 'array-literal-feedback': [PASS, FAIL], - 'compiler/dataview-neutered': [PASS, FAIL], - 'compiler/native-context-specialization-hole-check': [PASS, FAIL], - 'elements-transition-hoisting': [PASS, FAIL], - 'es6/collections-constructor-custom-iterator': [PASS, FAIL], - 'ignition/throw-if-not-hole': [PASS, FAIL], - 'keyed-load-with-symbol-key': [PASS, FAIL], - 'object-seal': [PASS, FAIL], - 'regress/regress-3709': [PASS, FAIL], - 'regress/regress-385565': [PASS, FAIL], - 'regress/regress-6948': [PASS, FAIL], - 'regress/regress-7014-1': [PASS, FAIL], - 'regress/regress-7014-2': [PASS, FAIL], - 'regress/regress-7510': [PASS, FAIL], - 'regress/regress-crbug-882233-2': [PASS, FAIL], - 'regress/regress-trap-allocation-memento': [PASS, FAIL], - 'regress/regress-unlink-closures-on-deopt': [PASS, FAIL], - 'shared-function-tier-up-turbo': [PASS, FAIL], + # to GC. + 'compiler/native-context-specialization-hole-check': [SKIP], + 'shared-function-tier-up-turbo': [SKIP], }], # 'gc_fuzzer' ############################################################################## @@ -1001,18 +851,19 @@ }], # 'predictable == True' ############################################################################## -['simulator_run and (arch == ppc or arch == ppc64 or arch == s390 or arch == s390x)', { +['simulator_run and (arch in [ppc64, s390x])', { # take too long with the simulator. 'regress/regress-1132': [SKIP], 'regress/regress-740784': [SKIP], + 'regress/regress-crbug-941743': [SKIP], 'regress/regress-crbug-482998': [PASS, SLOW], 'regress/regress-91008': [PASS, SLOW], 'harmony/regexp-property-lu-ui': [PASS, SLOW], 'whitespaces': [PASS, SLOW], 'wasm/atomics-stress': [SKIP], 'wasm/atomics64-stress': [SKIP], -}], # 'simulator_run and (arch == ppc or arch == ppc64 or arch == s390 or arch == s390x)' +}], # 'simulator_run and (arch in [ppc64, s390x])' ############################################################################## ['arch == ppc64', { @@ -1023,13 +874,10 @@ }], # 'arch == ppc64' ############################################################################## -['arch == ppc64 or arch == ppc or arch == s390 or arch == s390x', { - - # TODO(ppc/s390): fix constant pool issue and implement tagging for reloc - 'wasm/compiled-module-serialization': [SKIP], - 'regress/wasm/regress-808980': [SKIP], - 'regress/wasm/regress-808848': [SKIP], -}], # 'arch == ppc64 or arch == ppc or arch == s390 or arch == s390x' +['arch == s390x', { + # stack overflow + 'regress/regress-crbug-178790': [PASS, ['mode == debug', SKIP]], +}], # 'arch == s390x' ############################################################################## ['variant == stress', { @@ -1044,7 +892,8 @@ 'regress/regress-336820': [PASS, ['arch == arm and not simulator_run', SKIP]], # Too slow for TSAN in stress mode. - 'es6/classes': [PASS, ['tsan', SKIP]], + # Goes OOM on ODROID devices: https://crbug.com/v8/9026 + 'es6/classes': [PASS, ['tsan or (arch == arm and not simulator_run)', SKIP]], 'regress/regress-1122': [PASS, ['tsan', SKIP]], # Too slow with gc_stress on arm64. @@ -1151,6 +1000,7 @@ # TODO(ssauleau): implement BigInt<>Wasm conversion for other arch - # crbug.com/v8/7741 'wasm/bigint': [SKIP], + 'wasm/bigint-i64-to-imported-js-func': [SKIP], }], # arch in [arm, android_arm, android_ia32, ia32, ppc, s390, s390x, mipsel, mips] ############################################################################## @@ -1164,4 +1014,10 @@ '*': [SKIP], }], # variant == jitless and not embedded_builtins +############################################################################## +['variant == future', { + # crbug.com/v8/9094 + 'compiler/constant-fold-cow-array': [SKIP], +}], # variant == future + ] diff --git a/deps/v8/test/mjsunit/mjsunit_numfuzz.js b/deps/v8/test/mjsunit/mjsunit_numfuzz.js new file mode 100644 index 0000000000..c0af3e30aa --- /dev/null +++ b/deps/v8/test/mjsunit/mjsunit_numfuzz.js @@ -0,0 +1,12 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is added after mjsunit.js on the number fuzzer in order to +// ignore optimization state assertions, which are invalid in many test cases +// when gc timings are fuzzed. + +(function () { + assertUnoptimized = function assertUnoptimized() {}; + assertOptimized = function assertOptimized() {}; +})(); diff --git a/deps/v8/test/mjsunit/object-freeze.js b/deps/v8/test/mjsunit/object-freeze.js index 8ff63b4fc0..fe392e749c 100644 --- a/deps/v8/test/mjsunit/object-freeze.js +++ b/deps/v8/test/mjsunit/object-freeze.js @@ -414,18 +414,24 @@ function testPackedFrozenArray1(obj) { assertTrue(Array.isArray(obj)); assertThrows(function() { obj.pop(); }, TypeError); assertThrows(function() { obj.push(); }, TypeError); + assertThrows(function() { obj.shift(); }, TypeError); assertThrows(function() { obj.unshift(); }, TypeError); assertThrows(function() { obj.copyWithin(0,0); }, TypeError); assertThrows(function() { obj.fill(0); }, TypeError); assertThrows(function() { obj.reverse(); }, TypeError); assertThrows(function() { obj.sort(); }, TypeError); assertThrows(function() { obj.splice(0); }, TypeError); + assertThrows(function() { obj.splice(0, 0); }, TypeError); assertTrue(Object.isFrozen(obj)); // Verify search, filter, iterator assertEquals(obj.lastIndexOf(1), 2); assertEquals(obj.indexOf('a'), 4); + assertEquals(obj.indexOf(undefined), 0); assertFalse(obj.includes(Symbol("test"))); + assertTrue(obj.includes(undefined)); + assertFalse(obj.includes(NaN)); + assertTrue(obj.includes()); assertEquals(obj.find(x => x==0), undefined); assertEquals(obj.findIndex(x => x=='a'), 4); assertTrue(obj.some(x => typeof x == 'symbol')); @@ -505,3 +511,66 @@ assertTrue(%HasPackedElements(arr2)); Object.preventExtensions(arr2); Object.freeze(arr2); testPackedFrozenArray2(arr2); + +// Verify that repeatedly attemping to freeze a typed array fails +var typedArray = new Uint8Array(10); +assertThrows(() => { Object.freeze(typedArray); }, TypeError); +assertFalse(Object.isFrozen(typedArray)); +assertThrows(() => { Object.freeze(typedArray); }, TypeError); +assertFalse(Object.isFrozen(typedArray)); + +// Verify that freezing an empty typed array works +var typedArray = new Uint8Array(0); +Object.freeze(typedArray); +assertTrue(Object.isFrozen(typedArray)); + +// Test regression with Object.defineProperty +var obj = []; +obj.propertyA = 42; +obj[0] = true; +Object.freeze(obj); +assertThrows(function() { + Object.defineProperty(obj, 'propertyA', { + value: obj, + }); +}, TypeError); +assertEquals(42, obj.propertyA); +assertThrows(function() { + Object.defineProperty(obj, 'propertyA', { + value: obj, + writable: false, + }); +}, TypeError); +assertDoesNotThrow(function() {obj.propertyA = 2;}); +assertEquals(obj.propertyA, 42); +assertThrows(function() { + Object.defineProperty(obj, 'abc', { + value: obj, + }); +}, TypeError); + +// Regression test with simple array +var arr = ['a']; +Object.freeze(arr); +arr[0] = 'b'; +assertEquals(arr[0], 'a'); + +// Test regression Array.concat with double +var arr = ['a']; +Object.freeze(arr); +arr = arr.concat(0.5); +assertEquals(arr, ['a', 0.5]); +Object.freeze(arr); +arr = arr.concat([1.5, 'b']); +assertEquals(arr, ['a', 0.5, 1.5, 'b']); + +// Regression test with change length +var arr = ['a', 'b']; +Object.freeze(arr); +assertEquals(arr.length, 2); +arr.length = 3; +assertEquals(arr.length, 2); +arr[2] = 'c'; +assertEquals(arr[2], undefined); +arr.length = 1; +assertEquals(arr.length, 2); diff --git a/deps/v8/test/mjsunit/object-prevent-extensions.js b/deps/v8/test/mjsunit/object-prevent-extensions.js index 9e8cd03a7a..a2da9372a2 100644 --- a/deps/v8/test/mjsunit/object-prevent-extensions.js +++ b/deps/v8/test/mjsunit/object-prevent-extensions.js @@ -172,8 +172,10 @@ assertTrue(Array.isArray(obj)); // Verify that the length can't be written by builtins. assertThrows(function() { obj.push(1); }, TypeError); +assertDoesNotThrow(function() { obj.shift(); }); assertThrows(function() { obj.unshift(1); }, TypeError); assertThrows(function() { obj.splice(0, 0, 1); }, TypeError); +assertDoesNotThrow(function() {obj.splice(0, 0)}); // Verify search, filter, iterator obj = new Array(undefined, null, 1, -1, 'a', Symbol("test")); @@ -185,7 +187,11 @@ assertFalse(Object.isExtensible(obj)); assertTrue(Array.isArray(obj)); assertEquals(obj.lastIndexOf(1), 2); assertEquals(obj.indexOf('a'), 4); +assertEquals(obj.indexOf(undefined), 0); assertFalse(obj.includes(Symbol("test"))); +assertTrue(obj.includes(undefined)); +assertFalse(obj.includes(NaN)); +assertTrue(obj.includes()); assertEquals(obj.find(x => x==0), undefined); assertEquals(obj.findIndex(x => x=='a'), 4); assertTrue(obj.some(x => typeof x == 'symbol')); @@ -247,3 +253,30 @@ arr.fill('d'); assertEquals(arr.join(''), "ddd"); arr.pop(); assertEquals(arr.join(''), "dd"); + +// Regression test with simple array +var arr = ['a']; +Object.preventExtensions(arr); +arr[0] = 'b'; +assertEquals(arr[0], 'b'); + +// Test regression Array.concat with double +var arr = ['a']; +Object.preventExtensions(arr); +arr = arr.concat(0.5); +assertEquals(arr, ['a', 0.5]); +Object.preventExtensions(arr); +arr = arr.concat([1.5, 'b']); +assertEquals(arr, ['a', 0.5, 1.5, 'b']); + +// Regression test with change length +var arr = ['a', 'b']; +Object.preventExtensions(arr); +assertEquals(arr.length, 2); +arr.length = 3; +assertEquals(arr.length, 3); +arr[2] = 'c'; +assertEquals(arr[2], undefined); +arr.length = 1; +assertEquals(arr.length, 1); +assertEquals(arr[1], undefined); diff --git a/deps/v8/test/mjsunit/object-seal.js b/deps/v8/test/mjsunit/object-seal.js index 51459908ca..4de0e1c7e2 100644 --- a/deps/v8/test/mjsunit/object-seal.js +++ b/deps/v8/test/mjsunit/object-seal.js @@ -389,7 +389,7 @@ assertDoesNotThrow(function() { return new Sealed(); }); Sealed.prototype.prototypeExists = true; assertTrue((new Sealed()).prototypeExists); -obj = new Int32Array(10) +obj = new Int32Array(10); Object.seal(obj); assertTrue(Object.isSealed(obj)); @@ -402,8 +402,10 @@ function testPackedSealedArray1(obj) { // Verify that the length can't be written by builtins. assertThrows(function() { obj.pop(); }, TypeError); assertThrows(function() { obj.push(1); }, TypeError); + assertThrows(function() { obj.shift(); }, TypeError); assertThrows(function() { obj.unshift(1); }, TypeError); assertThrows(function() { obj.splice(0); }, TypeError); + assertDoesNotThrow(function() { obj.splice(0, 0); }); // Verify search, filter, iterator obj = new Array(undefined, null, 1, -1, 'a', Symbol("test")); @@ -414,7 +416,11 @@ function testPackedSealedArray1(obj) { assertTrue(Array.isArray(obj)); assertEquals(obj.lastIndexOf(1), 2); assertEquals(obj.indexOf('a'), 4); + assertEquals(obj.indexOf(undefined), 0); assertFalse(obj.includes(Symbol("test"))); + assertTrue(obj.includes(undefined)); + assertFalse(obj.includes(NaN)); + assertTrue(obj.includes()); assertEquals(obj.find(x => x==0), undefined); assertEquals(obj.findIndex(x => x=='a'), 4); assertTrue(obj.some(x => typeof x == 'symbol')); @@ -493,3 +499,54 @@ assertTrue(%HasPackedElements(arr2)); Object.preventExtensions(arr2); Object.seal(arr2); testPackedSealedArray2(arr2); + +// Test regression with Object.defineProperty +var obj = []; +obj.propertyA = 42; +obj[0] = true; +Object.seal(obj); +assertDoesNotThrow(function() { + Object.defineProperty(obj, 'propertyA', { + value: obj, + }); +}); +assertEquals(obj, obj.propertyA); +assertDoesNotThrow(function() { + Object.defineProperty(obj, 'propertyA', { + value: obj, + writable: false, + }); +}); +obj.propertyA = 42; +assertEquals(obj.propertyA, 42); +assertThrows(function() { + Object.defineProperty(obj, 'abc', { + value: obj, + }); +}, TypeError); + +// Regression test with simple array +var arr = ['a']; +Object.seal(arr); +arr[0] = 'b'; +assertEquals(arr[0], 'b'); + +// Test regression Array.concat with double +var arr = ['a']; +Object.seal(arr); +arr = arr.concat(0.5); +assertEquals(arr, ['a', 0.5]); +Object.seal(arr); +arr = arr.concat([1.5, 'b']); +assertEquals(arr, ['a', 0.5, 1.5, 'b']); + +// Regression test with change length +var arr = ['a', 'b']; +Object.seal(arr); +assertEquals(arr.length, 2); +arr.length = 3; +assertEquals(arr.length, 3); +arr[2] = 'c'; +assertEquals(arr[2], undefined); +arr.length = 1; +assertEquals(arr.length, 2); diff --git a/deps/v8/test/mjsunit/opt-elements-kind.js b/deps/v8/test/mjsunit/opt-elements-kind.js index 19e3981d44..976c3d6eba 100644 --- a/deps/v8/test/mjsunit/opt-elements-kind.js +++ b/deps/v8/test/mjsunit/opt-elements-kind.js @@ -100,6 +100,7 @@ function make_array() { return eval(make_array_string()); } +%EnsureFeedbackVectorForFunction(construct_smis); function construct_smis() { var a = make_array(); a[0] = 0; // Send the COW array map to the steak house. @@ -108,6 +109,7 @@ function construct_smis() { } %NeverOptimizeFunction(construct_doubles); +%EnsureFeedbackVectorForFunction(construct_doubles); function construct_doubles() { var a = construct_smis(); a[0] = 1.5; @@ -116,12 +118,14 @@ function construct_doubles() { } %NeverOptimizeFunction(convert_mixed); +%EnsureFeedbackVectorForFunction(convert_mixed); function convert_mixed(array, value, kind) { array[1] = value; assertKind(kind, array); assertEquals(value, array[1]); } +%PrepareFunctionForOptimization(test1); function test1() { // Test transition chain SMI->DOUBLE->FAST (crankshafted function will // transition to FAST directly). diff --git a/deps/v8/test/mjsunit/osr-elements-kind.js b/deps/v8/test/mjsunit/osr-elements-kind.js index 2440f5c8ad..5f0e7b7d64 100644 --- a/deps/v8/test/mjsunit/osr-elements-kind.js +++ b/deps/v8/test/mjsunit/osr-elements-kind.js @@ -87,59 +87,66 @@ function assertKind(expected, obj, name_opt) { assertEquals(expected, getKind(obj), name_opt); } -%NeverOptimizeFunction(construct_smis); -%NeverOptimizeFunction(construct_doubles); -%NeverOptimizeFunction(convert_mixed); -for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); } +%EnsureFeedbackVectorForFunction(test_osr_elements_kind); +function test_osr_elements_kind() { + %NeverOptimizeFunction(construct_smis); + %NeverOptimizeFunction(construct_doubles); + %NeverOptimizeFunction(convert_mixed); + for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); } -// This code exists to eliminate the learning influence of AllocationSites -// on the following tests. -var __sequence = 0; -function make_array_string() { - this.__sequence = this.__sequence + 1; - return "/* " + this.__sequence + " */ [0, 0, 0];" -} -function make_array() { - return eval(make_array_string()); -} - -function construct_smis() { - var a = make_array(); - a[0] = 0; // Send the COW array map to the steak house. - assertKind(elements_kind.fast_smi_only, a); - return a; -} -function construct_doubles() { - var a = construct_smis(); - a[0] = 1.5; - assertKind(elements_kind.fast_double, a); - return a; -} - -// Test transition chain SMI->DOUBLE->FAST (optimized function will -// transition to FAST directly). -function convert_mixed(array, value, kind) { - array[1] = value; - assertKind(kind, array); - assertEquals(value, array[1]); -} -smis = construct_smis(); -convert_mixed(smis, 1.5, elements_kind.fast_double); + // This code exists to eliminate the learning influence of AllocationSites + // on the following tests. + var __sequence = 0; + function make_array_string() { + this.__sequence = this.__sequence + 1; + return "/* " + this.__sequence + " */ [0, 0, 0];" + } + function make_array() { + return eval(make_array_string()); + } -doubles = construct_doubles(); -convert_mixed(doubles, "three", elements_kind.fast); + %EnsureFeedbackVectorForFunction(construct_smis); + function construct_smis() { + var a = make_array(); + a[0] = 0; // Send the COW array map to the steak house. + assertKind(elements_kind.fast_smi_only, a); + return a; + } -convert_mixed(construct_smis(), "three", elements_kind.fast); -convert_mixed(construct_doubles(), "three", elements_kind.fast); + %EnsureFeedbackVectorForFunction(construct_doubles); + function construct_doubles() { + var a = construct_smis(); + a[0] = 1.5; + assertKind(elements_kind.fast_double, a); + return a; + } -if (%ICsAreEnabled()) { - // Test that allocation sites allocate correct elements kind initially based - // on previous transitions. + // Test transition chain SMI->DOUBLE->FAST (optimized function will + // transition to FAST directly). + %EnsureFeedbackVectorForFunction(convert_mixed); + function convert_mixed(array, value, kind) { + array[1] = value; + assertKind(kind, array); + assertEquals(value, array[1]); + } smis = construct_smis(); + convert_mixed(smis, 1.5, elements_kind.fast_double); + doubles = construct_doubles(); - convert_mixed(smis, 1, elements_kind.fast); - convert_mixed(doubles, 1, elements_kind.fast); - assertTrue(%HaveSameMap(smis, doubles)); + convert_mixed(doubles, "three", elements_kind.fast); + + convert_mixed(construct_smis(), "three", elements_kind.fast); + convert_mixed(construct_doubles(), "three", elements_kind.fast); + + if (%ICsAreEnabled()) { + // Test that allocation sites allocate correct elements kind initially based + // on previous transitions. + smis = construct_smis(); + doubles = construct_doubles(); + convert_mixed(smis, 1, elements_kind.fast); + convert_mixed(doubles, 1, elements_kind.fast); + assertTrue(%HaveSameMap(smis, doubles)); + } } // Throw away type information in the ICs for next stress run. diff --git a/deps/v8/test/mjsunit/prototype-arity.js b/deps/v8/test/mjsunit/prototype-arity.js new file mode 100644 index 0000000000..bd0319f13f --- /dev/null +++ b/deps/v8/test/mjsunit/prototype-arity.js @@ -0,0 +1,67 @@ +// Copyright 2019 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 types = [ + [Object, "{}"], + [String, "\"abc\""], + [RegExp, "/abc/"], + [WeakMap, "(new WeakMap())"], + [WeakSet, "(new WeakSet())"], + [Map, "(new Map())"], + [Set, "(new Set())"], + [Function, "(function f() {return 1})"], + [Array, "[1,2,3, {}]"], + [Boolean, "(new Boolean())"], + [Symbol, "(new Symbol())"], + [BigInt, "(new BigInt(42))"], + [Math, "Math"], + [Date, "(new Date())"], + [Promise, "(new Promise())"], + [Reflect, "Reflect"], + [Proxy, "(new Proxy({}, {}))"], +]; + +if (typeof Intl == "object") { + types.push([Intl, "Intl"]); + types.push([Intl.Collator, "Intl.Collator"]); + types.push([Intl.ListFormat, "Intl.ListFormat"]); + types.push([Intl.NumberFormat, "Intl.NumberFormat"]); + types.push([Intl.PluralRules, "Intl.PluralRules"]); + types.push([Intl.RelativeTimeFormat, "Intl.RelativeTimeFormat"]); +} + +const callTemplate = () => { + function f() { + return constr_exp.propCall(args) + } + %PrepareFunctionForOptimization(f); + try { f(); } catch (e) {} + try { f(); } catch (e) {} + %OptimizeFunctionOnNextCall(f); + try { f(); } catch (e) {} +} + +const mkCall = (constr_exp, propCall) => { + const arrowFunction = callTemplate.toString().replace("constr_exp", constr_exp).replace("propCall", propCall).replace("args", ""); + return `(${arrowFunction})();`; +} + +for ([type, constr_exp, blacklist] of types) { + const proto = type.prototype || type; + for (const f of Object.getOwnPropertyNames(proto)) { + const d = Object.getOwnPropertyDescriptor(proto, f); + if (d.get || d.set || (typeof proto[f]) != "function") continue; + const source = mkCall(constr_exp, f); + try { + eval(source); + } catch (err) { + // Exceptions are OK. + console.log(`EXN ${err} for ${type.toString()} ${f}`) + console.log(source); + continue; + } + } +} diff --git a/deps/v8/test/mjsunit/regress-952682.js b/deps/v8/test/mjsunit/regress-952682.js new file mode 100644 index 0000000000..dd0e687bf0 --- /dev/null +++ b/deps/v8/test/mjsunit/regress-952682.js @@ -0,0 +1,15 @@ +// Copyright 2019 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(array, x) { + array.x = x; + array[0] = undefined; + return array; +} + +f([1], 1); +f([2], 1); +%HeapObjectVerify(f([3], undefined)); diff --git a/deps/v8/test/mjsunit/regress-956426.js b/deps/v8/test/mjsunit/regress-956426.js new file mode 100644 index 0000000000..93ccd7d36d --- /dev/null +++ b/deps/v8/test/mjsunit/regress-956426.js @@ -0,0 +1,10 @@ +// Copyright 2019 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 = { x: 0, y: 0, 0: '' }; +var a = { x: 0, y: 100000000000, 0: '' }; +Object.seal(b); +b.x = ''; diff --git a/deps/v8/test/mjsunit/regress/regress-2618.js b/deps/v8/test/mjsunit/regress/regress-2618.js index 9feb911c81..551605c6b3 100644 --- a/deps/v8/test/mjsunit/regress/regress-2618.js +++ b/deps/v8/test/mjsunit/regress/regress-2618.js @@ -31,7 +31,7 @@ // Can't OSR with always-opt or in Lite mode. if (isNeverOptimizeLiteMode()) { print("Warning: skipping test that requires optimization in Lite mode."); - quit(0); + testRunner.quit(0); } assertFalse(isAlwaysOptimize()); diff --git a/deps/v8/test/mjsunit/regress/regress-2989.js b/deps/v8/test/mjsunit/regress/regress-2989.js index d11e352105..ff09c08a41 100644 --- a/deps/v8/test/mjsunit/regress/regress-2989.js +++ b/deps/v8/test/mjsunit/regress/regress-2989.js @@ -25,7 +25,7 @@ if (isNeverOptimizeLiteMode()) { print("Warning: skipping test that requires optimization in Lite mode."); - quit(0); + testRunner.quit(0); } (function ArgumentsObjectChange() { diff --git a/deps/v8/test/mjsunit/regress/regress-8630.js b/deps/v8/test/mjsunit/regress/regress-8630.js index f51807b4a5..4a5aa5409b 100644 --- a/deps/v8/test/mjsunit/regress/regress-8630.js +++ b/deps/v8/test/mjsunit/regress/regress-8630.js @@ -7,7 +7,7 @@ // Parameters can't have parentheses (both patterns and identifiers) assertThrows("( ({x: 1}) ) => {};", SyntaxError); assertThrows("( (x) ) => {}", SyntaxError); -assertThrows("( ({x: 1}) = y ) => {}", SyntaxError); +assertThrows("( ({x: 1}) = y ) => {}", ReferenceError); assertThrows("( (x) = y ) => {}", SyntaxError); // Declarations can't have parentheses (both patterns and identifiers) @@ -20,8 +20,9 @@ assertThrows("var [(x)] = [];", SyntaxError); assertThrows("var [({x: 1}) = y] = [];", SyntaxError); assertThrows("var [(x) = y] = [];", SyntaxError); -// Patterns in can't have parentheses in assignments either -assertThrows("[({x: 1}) = y] = [];", SyntaxError); +// Patterns can't have parentheses in assignments either +assertThrows("[({x: 1}) = y] = [];", ReferenceError); +assertThrows("({a,b}) = {a:2,b:3}", ReferenceError); // Parentheses are fine around identifiers in assignments though, even inside a // pattern diff --git a/deps/v8/test/mjsunit/regress/regress-9002.js b/deps/v8/test/mjsunit/regress/regress-9002.js new file mode 100644 index 0000000000..94b4c93ae9 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-9002.js @@ -0,0 +1,36 @@ +// Copyright 2019 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 --opt --no-always-opt + +function f() { + return 42; +} + +function g() { + return 52; +} + +%NeverOptimizeFunction(f); + +function foo(cond) { + let func; + if (cond) { + func = f; + } else { + func = g; + } + func(); +} + +%PrepareFunctionForOptimization(foo); +foo(true); +foo(false); +%OptimizeFunctionOnNextCall(foo); +foo(true); +foo(false); + +// Just a sanitary check, we have a DCHECK in js-inlining.cc to make sure +// f is not inlined into foo. +assertUnoptimized(f); diff --git a/deps/v8/test/mjsunit/regress/regress-9022.js b/deps/v8/test/mjsunit/regress/regress-9022.js new file mode 100644 index 0000000000..7922c3996b --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-9022.js @@ -0,0 +1,30 @@ +// Copyright 2019 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: --validate-asm --allow-natives-syntax + +function Module(stdlib, ffi) { + "use asm"; + var log = ffi.log; + function boom() { + while (1) { + label: { + break; + } + log(1); + break; + } + log(2); + } + return { boom: boom } +} + +var log_value = 0; +function log(i) { + log_value += i; +} + +Module({}, { log: log }).boom(); +assertTrue(%IsAsmWasmCode(Module)); +assertEquals(2, log_value); diff --git a/deps/v8/test/mjsunit/regress/regress-9036-1.js b/deps/v8/test/mjsunit/regress/regress-9036-1.js new file mode 100644 index 0000000000..3569686c49 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-9036-1.js @@ -0,0 +1,10 @@ +// Copyright 2019 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 C() {}; + +const p = new Proxy({}, { getPrototypeOf() { return C.prototype } }); + +assertTrue(p instanceof C); +assertTrue(p instanceof C); diff --git a/deps/v8/test/mjsunit/regress/regress-9036-2.js b/deps/v8/test/mjsunit/regress/regress-9036-2.js new file mode 100644 index 0000000000..f5bb5c0607 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-9036-2.js @@ -0,0 +1,10 @@ +// Copyright 2019 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 C() {}; + +const p = new Proxy({}, { getPrototypeOf() { return C.prototype } }); + +assertTrue(C[Symbol.hasInstance](p)); +assertTrue(C[Symbol.hasInstance](p)); diff --git a/deps/v8/test/mjsunit/regress/regress-9036-3.js b/deps/v8/test/mjsunit/regress/regress-9036-3.js new file mode 100644 index 0000000000..ca97dc9ff6 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-9036-3.js @@ -0,0 +1,11 @@ +// Copyright 2019 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 C() {}; + +const p = new Proxy({}, { getPrototypeOf() { return C.prototype } }); +const o = Object.create(p); + +assertTrue(o instanceof C); +assertTrue(o instanceof C); diff --git a/deps/v8/test/mjsunit/regress/regress-937681.js b/deps/v8/test/mjsunit/regress/regress-937681.js new file mode 100644 index 0000000000..81af5534ab --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-937681.js @@ -0,0 +1,17 @@ +// Copyright 2019 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 = 'aaaa'; + +const re0 = /./y; + +// Twice to go through both runtime and the builtin. +re0.lastIndex = 9; +assertEquals(str, re0[Symbol.replace](str, () => 42)); +re0.lastIndex = 9; +assertEquals(str, re0[Symbol.replace](str, () => 42)); +re0.lastIndex = 9; +assertEquals(str, re0[Symbol.replace](str, "42")); +re0.lastIndex = 9; +assertEquals(str, re0[Symbol.replace](str, "42")); diff --git a/deps/v8/test/mjsunit/regress/regress-940722.js b/deps/v8/test/mjsunit/regress/regress-940722.js new file mode 100644 index 0000000000..355b7c34c9 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-940722.js @@ -0,0 +1,13 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --stack-size=100 + +var __v_27278 = "x"; +for (var __v_27279 = 0; __v_27279 != 13; __v_27279++) { + try { __v_27278 += __v_27278; } catch (e) {} +} + +// Can throw or not, but should not crash. +try { /(xx|x)*/.exec(__v_27278); } catch (e) {} diff --git a/deps/v8/test/mjsunit/regress/regress-944945.js b/deps/v8/test/mjsunit/regress/regress-944945.js new file mode 100644 index 0000000000..8256eaf9d5 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-944945.js @@ -0,0 +1,6 @@ +// Copyright 2019 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 E = '"use asm";\nfunction f() { LOCALS }\nreturn f;'; +const PI = new Function(E.replace('LOCALS', Array(999995).fill('0.9'))); diff --git a/deps/v8/test/mjsunit/regress/regress-947822.js b/deps/v8/test/mjsunit/regress/regress-947822.js new file mode 100644 index 0000000000..285795480e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-947822.js @@ -0,0 +1,18 @@ +// Copyright 2019 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 cnt = 0; +const re = /x/y; +const replacement = { + toString: () => { + cnt++; + if (cnt == 2) { + re.lastIndex = { valueOf: () => { re.x = -1073741825; return 7; }}; + } + return 'y$'; + } +}; + +const str = re[Symbol.replace]("x", replacement); +assertEquals(str, "y$"); diff --git a/deps/v8/test/mjsunit/regress/regress-948248.js b/deps/v8/test/mjsunit/regress/regress-948248.js new file mode 100644 index 0000000000..61b1d19ea1 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-948248.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 + +// Non-ascii intrinsic calls shouldn't crash V8. +assertThrows("%ಠ_ಠ()", SyntaxError); diff --git a/deps/v8/test/mjsunit/regress/regress-948307.js b/deps/v8/test/mjsunit/regress/regress-948307.js new file mode 100644 index 0000000000..cb0fb34011 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-948307.js @@ -0,0 +1,15 @@ +// Copyright 2019 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 + +const set = new WeakSet() +const obj = {}; +// Two GCs to promote {set} and {obj} to old-space. +gc(); +gc(); +// Allocate a large array so {obj} will become an evacuation candidate. +const foo = new Int8Array(0x0F000000); +// Trigger ephemeron key write barrier. +set.add(obj); diff --git a/deps/v8/test/mjsunit/regress/regress-950328.js b/deps/v8/test/mjsunit/regress/regress-950328.js new file mode 100644 index 0000000000..f00e90bd4e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-950328.js @@ -0,0 +1,45 @@ +// Copyright 2019 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 NoStoreBecauseReadonlyLength() { + var a = []; + Object.defineProperty(a, 'length', { writable: false }); + + + function f() { + var o = { __proto__ : a }; + o.push; + } + + f(); + f(); + %OptimizeFunctionOnNextCall(f); + + a[0] = 1.1; + f(); + assertEquals(undefined, a[0]); +})(); + +(function NoStoreBecauseTypedArrayProto() { + const arr_proto = [].__proto__; + const arr = []; + + function f() { + const i32arr = new Int32Array(); + + const obj = {}; + obj.__proto__ = arr; + arr_proto.__proto__ = i32arr; + obj.__proto__ = arr; + arr_proto.__proto__ = i32arr; + } + + f(); + %OptimizeFunctionOnNextCall(f); + arr[1024] = []; + f(); + assertEquals(undefined, arr[1024]); +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-937734.js b/deps/v8/test/mjsunit/regress/regress-crbug-937734.js new file mode 100644 index 0000000000..26ab8645a6 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-937734.js @@ -0,0 +1,16 @@ +// Copyright 2019 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() +{ + return 1 in [0]; +} + +foo(); +foo(); +%OptimizeFunctionOnNextCall(foo); +foo(); +assertEquals(0, %GetDeoptCount(foo)); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-940274.js b/deps/v8/test/mjsunit/regress/regress-crbug-940274.js new file mode 100644 index 0000000000..da9da318d3 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-940274.js @@ -0,0 +1,11 @@ +// Copyright 2019 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 foo() { + var a = new Array({}); + a.shift(); + assertFalse(a.hasOwnProperty(0)); +} + +foo(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-942068.js b/deps/v8/test/mjsunit/regress/regress-crbug-942068.js new file mode 100644 index 0000000000..9994d9c524 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-942068.js @@ -0,0 +1,17 @@ +// Copyright 2019 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(index, array) { + return index in array; +} + +let arr = []; +arr.__proto__ = [0]; +assertFalse(foo(0, {})); +assertTrue(foo(0, arr)); +assertFalse(foo(0, {})); +%OptimizeFunctionOnNextCall(foo); +assertTrue(foo(0, arr)); diff --git a/deps/v8/test/mjsunit/regress/regress-v8-8799.js b/deps/v8/test/mjsunit/regress/regress-v8-8799.js index a6710904ce..6e3eb07b03 100644 --- a/deps/v8/test/mjsunit/regress/regress-v8-8799.js +++ b/deps/v8/test/mjsunit/regress/regress-v8-8799.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --expose-gc --stress-flush-bytecode +// Flags: --expose-gc --flush-bytecode --stress-flush-bytecode // Ensure tagged template objects are cached even after bytecode flushing. var f = (x) => eval`a${x}b`; diff --git a/deps/v8/test/mjsunit/regress/regress-v8-9106.js b/deps/v8/test/mjsunit/regress/regress-v8-9106.js new file mode 100644 index 0000000000..f51c2e9498 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-v8-9106.js @@ -0,0 +1,24 @@ +// Copyright 2019 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-bulk-memory + +// Make sure DCHECK doesn't fire when passive data segment is at the end of the +// module. +let bytes = new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 132, 128, 128, 128, 0, 1, + 96, 0, 0, 3, 133, 128, 128, 128, 0, 4, 0, 0, 0, 0, 5, + 131, 128, 128, 128, 0, 1, 0, 1, 7, 187, 128, 128, 128, 0, 4, + 12, 100, 114, 111, 112, 95, 112, 97, 115, 115, 105, 118, 101, 0, 0, + 12, 105, 110, 105, 116, 95, 112, 97, 115, 115, 105, 118, 101, 0, 1, + 11, 100, 114, 111, 112, 95, 97, 99, 116, 105, 118, 101, 0, 2, 11, + 105, 110, 105, 116, 95, 97, 99, 116, 105, 118, 101, 0, 3, 12, 129, + 128, 128, 128, 0, 2, 10, 183, 128, 128, 128, 0, 4, 133, 128, 128, + 128, 0, 0, 252, 9, 0, 11, 140, 128, 128, 128, 0, 0, 65, 0, + 65, 0, 65, 0, 252, 8, 0, 0, 11, 133, 128, 128, 128, 0, 0, + 252, 9, 1, 11, 140, 128, 128, 128, 0, 0, 65, 0, 65, 0, 65, + 0, 252, 8, 1, 0, 11, 11, 136, 128, 128, 128, 0, 2, 1, 0, + 0, 65, 0, 11, 0 +]); +new WebAssembly.Instance(new WebAssembly.Module(bytes)); diff --git a/deps/v8/test/mjsunit/regress/regress-v8-9233.js b/deps/v8/test/mjsunit/regress/regress-v8-9233.js new file mode 100644 index 0000000000..9164f940bf --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-v8-9233.js @@ -0,0 +1,22 @@ +// Copyright 2019 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 o1 = { x: 999 }; +o1.y = 999; + +// o2 will share map with o1 in its initial state +var o2 = { x: 1 }; + +function f() { return o2.x; } + +assertEquals(1, f()); +assertEquals(1, f()); +%OptimizeFunctionOnNextCall(f); +assertEquals(1, f()); + +delete o2.x; +o2.x = 2; +assertEquals(2, f()); diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-739768.js b/deps/v8/test/mjsunit/regress/wasm/regress-739768.js index a191c828d6..5fca49bc0f 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regress-739768.js +++ b/deps/v8/test/mjsunit/regress/wasm/regress-739768.js @@ -24,7 +24,7 @@ let builder1 = new WasmModuleBuilder(); builder1.setName('module_1'); builder1.addFunction('main', kSig_i_v).addBody([kExprUnreachable]); builder1.addImportedTable('z', 'table'); -builder1.addElementSegment(0, false, [0], true); +builder1.addElementSegment(0, 0, false, [0], true); let module1 = new WebAssembly.Module(builder1.toBuffer()); let instance1 = new WebAssembly.Instance(module1, {z: {table: instance0.exports.table}}); diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-803788.js b/deps/v8/test/mjsunit/regress/wasm/regress-803788.js index 17325538f1..5c894ae25a 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regress-803788.js +++ b/deps/v8/test/mjsunit/regress/wasm/regress-803788.js @@ -11,7 +11,7 @@ let q_table = builder.addImportedTable("q", "table") let q_base = builder.addImportedGlobal("q", "base", kWasmI32); let q_fun = builder.addImport("q", "fun", kSig_v_v); builder.addType(kSig_i_ii); -builder.addElementSegment(q_base, true, [ q_fun ]) +builder.addElementSegment(0, q_base, true, [ q_fun ]) let module = new WebAssembly.Module(builder.toBuffer()); let table = new WebAssembly.Table({ element: "anyfunc", diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-817380.js b/deps/v8/test/mjsunit/regress/wasm/regress-817380.js index 5b3281a150..c7748d8904 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regress-817380.js +++ b/deps/v8/test/mjsunit/regress/wasm/regress-817380.js @@ -19,6 +19,6 @@ const builder2 = new WasmModuleBuilder(); const mul_import = builder2.addImport('q', 'wasm_mul', kSig_i_ii); builder2.addImportedTable('q', 'table'); const glob_import = builder2.addImportedGlobal('q', 'glob', kWasmI32); -builder2.addElementSegment(glob_import, true, [mul_import]); +builder2.addElementSegment(0, glob_import, true, [mul_import]); builder2.instantiate( {q: {glob: 0, js_div: i => i, wasm_mul: mul, table: table}}); diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-834619.js b/deps/v8/test/mjsunit/regress/wasm/regress-834619.js index 145f415221..cfa6e7bb3b 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regress-834619.js +++ b/deps/v8/test/mjsunit/regress/wasm/regress-834619.js @@ -32,7 +32,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); kExprCallIndirect, 0, kTableZero ]) .exportFunc(); - builder.addElementSegment(0, false, [0, 1, 1, 0]); + builder.addElementSegment(0, 0, false, [0, 1, 1, 0]); return builder.instantiate({q: {f2: i1.exports.f2, f1: i1.exports.f1}}); })(); diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-935138.js b/deps/v8/test/mjsunit/regress/wasm/regress-935138.js index e0fe535e27..20835428e3 100644 --- a/deps/v8/test/mjsunit/regress/wasm/regress-935138.js +++ b/deps/v8/test/mjsunit/regress/wasm/regress-935138.js @@ -9,11 +9,11 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); (function TestAsyncCompileMultipleCodeSections() { let binary = new Binary(); binary.emit_header(); - binary.push(kTypeSectionCode, 4, 1, kWasmFunctionTypeForm, 0, 0); - binary.push(kFunctionSectionCode, 2, 1, 0); - binary.push(kCodeSectionCode, 6, 1, 4, 0, kExprGetLocal, 0, kExprEnd); - binary.push(kCodeSectionCode, 6, 1, 4, 0, kExprGetLocal, 0, kExprEnd); - let buffer = Uint8Array.from(binary).buffer; + binary.emit_bytes([kTypeSectionCode, 4, 1, kWasmFunctionTypeForm, 0, 0]); + binary.emit_bytes([kFunctionSectionCode, 2, 1, 0]); + binary.emit_bytes([kCodeSectionCode, 6, 1, 4, 0, kExprGetLocal, 0, kExprEnd]); + binary.emit_bytes([kCodeSectionCode, 6, 1, 4, 0, kExprGetLocal, 0, kExprEnd]); + let buffer = binary.trunc_buffer(); assertPromiseResult(WebAssembly.compile(buffer), assertUnreachable, e => assertInstanceof(e, WebAssembly.CompileError)); })(); diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-940296.js b/deps/v8/test/mjsunit/regress/wasm/regress-940296.js new file mode 100644 index 0000000000..747d91d131 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regress-940296.js @@ -0,0 +1,6 @@ +// Copyright 2019 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 table = new WebAssembly.Table({element: "anyfunc", initial: 1}); +assertThrows(() => table.get(3612882876), RangeError); diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-946350.js b/deps/v8/test/mjsunit/regress/wasm/regress-946350.js new file mode 100644 index 0000000000..127e71f188 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regress-946350.js @@ -0,0 +1,13 @@ +// Copyright 2019 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 + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); +var instance = builder.instantiate(); +instance[1] = undefined; +gc(); +Object.getOwnPropertyNames(instance); diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-948228.js b/deps/v8/test/mjsunit/regress/wasm/regress-948228.js new file mode 100644 index 0000000000..f9009e2668 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regress-948228.js @@ -0,0 +1,11 @@ +// Copyright 2019 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-module-builder.js'); + +var {proxy, revoke} = Proxy.revocable({}, {}); +revoke(); +let builder = new WasmModuleBuilder(); +builder.addImport('m', 'q', kSig_v_v); +WebAssembly.instantiate(builder.toModule(), proxy); 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 0d23b4f843..abce803fb0 100644 --- a/deps/v8/test/mjsunit/shared-function-tier-up-turbo.js +++ b/deps/v8/test/mjsunit/shared-function-tier-up-turbo.js @@ -8,7 +8,7 @@ // If we are always or never optimizing it is useless. if (isNeverOptimizeLiteMode()) { print("Warning: skipping test that requires optimization in Lite mode."); - quit(0); + testRunner.quit(0); } assertFalse(isAlwaysOptimize()); assertFalse(isNeverOptimize()); diff --git a/deps/v8/test/mjsunit/stack-traces.js b/deps/v8/test/mjsunit/stack-traces.js index 81418f70f7..a46b2b3940 100644 --- a/deps/v8/test/mjsunit/stack-traces.js +++ b/deps/v8/test/mjsunit/stack-traces.js @@ -368,13 +368,17 @@ assertEquals(undefined, fake_error.stack); // Check that overwriting the stack property during stack trace formatting // does not crash. -error = new Error(); +error = new Error("foobar"); error.__defineGetter__("name", function() { error.stack = "abc"; }); -assertEquals("abc", error.stack); +assertTrue(error.stack.startsWith("Error")); +assertTrue(error.stack.includes("foobar")); -error = new Error(); +error = new Error("foobar"); error.__defineGetter__("name", function() { delete error.stack; }); -assertEquals(undefined, error.stack); +// The first time, Error.stack returns the formatted stack trace, +// not the content of the property. +assertTrue(error.stack.startsWith("Error")); +assertEquals(error.stack, undefined); // Check that repeated trace collection does not crash. error = new Error(); diff --git a/deps/v8/test/mjsunit/testcfg.py b/deps/v8/test/mjsunit/testcfg.py index f95c33e7da..a829779872 100644 --- a/deps/v8/test/mjsunit/testcfg.py +++ b/deps/v8/test/mjsunit/testcfg.py @@ -35,6 +35,11 @@ from testrunner.local import testsuite from testrunner.objects import testcase from testrunner.outproc import base as outproc +try: + basestring # Python 2 +except NameError: # Python 3 + basestring = str + FILES_PATTERN = re.compile(r"//\s+Files:(.*)") ENV_PATTERN = re.compile(r"//\s+Environment Variables:(.*)") SELF_SCRIPT_PATTERN = re.compile(r"//\s+Env: TEST_FILE_NAME") @@ -62,7 +67,7 @@ class TestLoader(testsuite.JSTestLoader): def excluded_files(self): return { "mjsunit.js", - "mjsunit_suppressions.js", + "mjsunit_numfuzz.js", } @@ -106,6 +111,9 @@ class TestCase(testcase.D8TestCase): else: mjsunit_files = [os.path.join(self.suite.root, "mjsunit.js")] + if self.suite.framework_name == 'num_fuzzer': + mjsunit_files.append(os.path.join(self.suite.root, "mjsunit_numfuzz.js")) + files_suffix = [] if MODULE_PATTERN.search(source): files_suffix.append("--module") diff --git a/deps/v8/test/mjsunit/tools/compiler-trace-flags-wasm.js b/deps/v8/test/mjsunit/tools/compiler-trace-flags-wasm.js new file mode 100644 index 0000000000..2d7cd00ac3 --- /dev/null +++ b/deps/v8/test/mjsunit/tools/compiler-trace-flags-wasm.js @@ -0,0 +1,30 @@ +// Copyright 2019 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. + +// Disable liftoff to make sure we generate turbofan traces. +// Flags: --no-liftoff +// Flags: --trace-turbo --trace-turbo-graph +// Flags: --trace-turbo-cfg-file=test/mjsunit/tools/turbo.cfg +// Flags: --trace-turbo-path=test/mjsunit/tools + +// Only trace the wasm functions: +// Flags: --trace-turbo-filter=wasm* + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +// The idea behind this test is to make sure we do not crash when using the +// --trace-turbo flag given different sort of inputs. + +(function testWASM() { + let builder = new WasmModuleBuilder(); + + builder.addFunction("add", kSig_i_ii) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 1, + kExprI32Add]) + .exportFunc(); + + let instance = builder.instantiate(); + instance.exports.add(21, 21); +})(); diff --git a/deps/v8/test/mjsunit/tools/compiler-trace-flags.js b/deps/v8/test/mjsunit/tools/compiler-trace-flags.js index ea6f816f5d..4a0432bebd 100644 --- a/deps/v8/test/mjsunit/tools/compiler-trace-flags.js +++ b/deps/v8/test/mjsunit/tools/compiler-trace-flags.js @@ -6,10 +6,11 @@ // Flags: --trace-turbo-cfg-file=test/mjsunit/tools/turbo.cfg // Flags: --trace-turbo-path=test/mjsunit/tools -load('test/mjsunit/wasm/wasm-module-builder.js'); +// Only trace the "add" function: +// Flags: --trace-turbo-filter=add // The idea behind this test is to make sure we do not crash when using the -// --trace-turbo flag given different sort of inputs, JS or WASM. +// --trace-turbo flag given different sort of inputs. (function testOptimizedJS() { function add(a, b) { @@ -20,16 +21,3 @@ load('test/mjsunit/wasm/wasm-module-builder.js'); %OptimizeFunctionOnNextCall(add); add(20, 22); })(); - -(function testWASM() { - let builder = new WasmModuleBuilder(); - - builder.addFunction("add", kSig_i_ii) - .addBody([kExprGetLocal, 0, - kExprGetLocal, 1, - kExprI32Add]) - .exportFunc(); - - let instance = builder.instantiate(); - instance.exports.add(21, 21); -})(); diff --git a/deps/v8/test/mjsunit/track-fields.js b/deps/v8/test/mjsunit/track-fields.js index 7804fffec0..566171fed0 100644 --- a/deps/v8/test/mjsunit/track-fields.js +++ b/deps/v8/test/mjsunit/track-fields.js @@ -26,6 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --track-fields --track-double-fields --allow-natives-syntax +// Flags: --modify-field-representation-inplace // Test transitions caused by changes to field representations. @@ -95,7 +96,7 @@ o6.b = 1.5; assertFalse(%HaveSameMap(o6, o7)); // Smi, double, object. o7.c = {}; -assertFalse(%HaveSameMap(o6, o7)); +assertTrue(%HaveSameMap(o6, o7)); // Smi, double, object. o6.c = {}; assertTrue(%HaveSameMap(o6, o7)); diff --git a/deps/v8/test/mjsunit/ubsan-fuzzerbugs.js b/deps/v8/test/mjsunit/ubsan-fuzzerbugs.js index 7fb9e432c7..5a7594de13 100644 --- a/deps/v8/test/mjsunit/ubsan-fuzzerbugs.js +++ b/deps/v8/test/mjsunit/ubsan-fuzzerbugs.js @@ -54,3 +54,39 @@ float_array[0] = 1e51; %OptimizeFunctionOnNextCall(__f_14159); __f_14159(buffer); })(); + +// crbug.com/937652 +(function() { + function f() { + for (var i = 0; i < 1; i++) { + var shift = 1; + for (var j = 0; j < 2; ++j) { + if (shift == shift) shift = 0; + var x = 1; + print((x << shift | x >>> 32 - shift)); + } + } + } + f(); + f(); + %OptimizeFunctionOnNextCall(f); + f(); +})(); + +// crbug.com/935133 +(function() { + var called_has = false; + var proxy = new Proxy({}, { + has: function(x, p) { + called_has = true; + throw "The test may finish now"; + }, + }); + proxy.length = 2147483648; + try { + Array.prototype.sort.call(proxy); + } catch(e) { + assertTrue(e === "The test may finish now"); + } + assertTrue(called_has); +})(); diff --git a/deps/v8/test/mjsunit/wasm/anyfunc-interpreter.js b/deps/v8/test/mjsunit/wasm/anyfunc-interpreter.js new file mode 100644 index 0000000000..10d66c6b36 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/anyfunc-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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 --experimental-wasm-anyref --expose-gc +// Flags: --wasm-interpret-all + +// This is just a wrapper for an existing reference types test case that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/anyfunc.js"); diff --git a/deps/v8/test/mjsunit/wasm/anyref-globals-interpreter.js b/deps/v8/test/mjsunit/wasm/anyref-globals-interpreter.js new file mode 100644 index 0000000000..bca5d6c202 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/anyref-globals-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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-anyref --expose-gc +// Flags: --wasm-interpret-all + +// This is just a wrapper for an existing reference types test case that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/anyref-globals.js"); diff --git a/deps/v8/test/mjsunit/wasm/anyref-globals.js b/deps/v8/test/mjsunit/wasm/anyref-globals.js index f1facefb28..c0d9de4e69 100644 --- a/deps/v8/test/mjsunit/wasm/anyref-globals.js +++ b/deps/v8/test/mjsunit/wasm/anyref-globals.js @@ -9,33 +9,49 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); (function TestDefaultValue() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); - const g_nullref = builder.addGlobal(kWasmAnyRef, true); - builder.addFunction("main", kSig_r_v) - .addBody([kExprGetGlobal, g_nullref.index]) - .exportAs("main"); + const g_nullref = builder.addGlobal(kWasmAnyRef, true).index; + const g_nullfunc = builder.addGlobal(kWasmAnyFunc, true).index; + builder.addFunction("get_anyref_global", kSig_r_v) + .addBody([kExprGetGlobal, g_nullref]) + .exportAs("get_anyref_global"); + builder.addFunction("get_anyfunc_global", kSig_a_v) + .addBody([kExprGetGlobal, g_nullfunc]) + .exportAs("get_anyfunc_global"); const instance = builder.instantiate(); - assertNull(instance.exports.main()); + assertEquals(null, instance.exports.get_anyref_global()); + assertEquals(null, instance.exports.get_anyfunc_global()); })(); (function TestDefaultValueSecondGlobal() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); const g_setref = builder.addGlobal(kWasmAnyRef, true); + const g_setfunc = builder.addGlobal(kWasmAnyFunc, true); const g_nullref = builder.addGlobal(kWasmAnyRef, true); - builder.addFunction("main", kSig_r_r) + const g_nullfunc = builder.addGlobal(kWasmAnyFunc, true); + builder.addFunction("get_anyref_global", kSig_r_r) .addBody([ - kExprGetLocal, 0, - kExprSetGlobal, g_setref.index, - kExprGetGlobal, g_nullref.index + kExprGetLocal, 0, + kExprSetGlobal, g_setref.index, + kExprGetGlobal, g_nullref.index ]) - .exportAs("main"); + .exportAs("get_anyref_global"); + builder.addFunction("get_anyfunc_global", kSig_a_a) + .addBody([ + kExprGetLocal, 0, + kExprSetGlobal, g_setfunc.index, + kExprGetGlobal, g_nullfunc.index + ]) + .exportAs("get_anyfunc_global"); const instance = builder.instantiate(); - assertNull(instance.exports.main({})); + assertEquals(null, instance.exports.get_anyref_global({})); + assertEquals(null, instance.exports.get_anyfunc_global( + instance.exports.get_anyref_global)); })(); -(function TestGlobalChangeValue() { +(function TestAnyRefGlobalChangeValue() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); // Dummy global for offset. @@ -43,15 +59,35 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); const g = builder.addGlobal(kWasmAnyRef, true); builder.addFunction("main", kSig_r_r) .addBody([ - kExprGetLocal, 0, - kExprSetGlobal, g.index, - kExprGetGlobal, g.index + kExprGetLocal, 0, + kExprSetGlobal, g.index, + kExprGetGlobal, g.index + ]) + .exportAs("main"); + + const instance = builder.instantiate(); + + const test_value = { hello: 'world' }; + assertSame(test_value, instance.exports.main(test_value)); +})(); + +(function TestAnyFuncGlobalChangeValue() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + // Dummy global for offset. + builder.addGlobal(kWasmAnyFunc, true); + const g = builder.addGlobal(kWasmAnyFunc, true); + builder.addFunction("main", kSig_a_a) + .addBody([ + kExprGetLocal, 0, + kExprSetGlobal, g.index, + kExprGetGlobal, g.index ]) .exportAs("main"); const instance = builder.instantiate(); - const test_value = {hello: 'world'}; + const test_value = instance.exports.main; assertSame(test_value, instance.exports.main(test_value)); })(); @@ -64,16 +100,16 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); const g = builder.addGlobal(kWasmAnyRef, true); builder.addFunction("main", kSig_r_r) .addBody([ - kExprGetLocal, 0, - kExprSetGlobal, g.index, - kExprCallFunction, gc_index, // call gc - kExprGetGlobal, g.index + kExprGetLocal, 0, + kExprSetGlobal, g.index, + kExprCallFunction, gc_index, // call gc + kExprGetGlobal, g.index ]) .exportAs("main"); - const instance = builder.instantiate({q: {gc: gc}}); + const instance = builder.instantiate({ q: { gc: gc } }); - const test_value = {hello: 'world'}; + const test_value = { hello: 'world' }; assertSame(test_value, instance.exports.main(test_value)); assertSame(5, instance.exports.main(5)); assertSame("Hello", instance.exports.main("Hello")); @@ -85,20 +121,20 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); const g = builder.addGlobal(kWasmAnyRef, true); builder.addFunction("get_global", kSig_r_v) .addBody([ - kExprGetGlobal, g.index + kExprGetGlobal, g.index ]) .exportAs("get_global"); builder.addFunction("set_global", kSig_v_r) .addBody([ - kExprGetLocal, 0, - kExprSetGlobal, g.index + kExprGetLocal, 0, + kExprSetGlobal, g.index ]) .exportAs("set_global"); const instance = builder.instantiate(); - let test_value = {hello: 'world'}; + let test_value = { hello: 'world' }; instance.exports.set_global(test_value); test_value = null; gc(); @@ -108,38 +144,73 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); assertEquals('world', result.hello); })(); -(function TestImported() { +(function TestImportedAnyRef() { print(arguments.callee.name); function Test(obj) { let builder = new WasmModuleBuilder(); const g = builder.addImportedGlobal('m', 'val', kWasmAnyRef); builder.addFunction('main', kSig_r_v) - .addBody([kExprGetGlobal, g]) - .exportAs('main'); + .addBody([kExprGetGlobal, g]) + .exportAs('main'); - const instance = builder.instantiate({m: {val: obj}}); + const instance = builder.instantiate({ m: { val: obj } }); assertSame(obj, instance.exports.main()); } Test(null); Test(undefined); Test(1653); Test("mystring"); - Test({q: 14}); + Test({ q: 14 }); Test(print); })(); +function dummy_func() { + let builder = new WasmModuleBuilder(); + builder.addFunction("dummy", kSig_i_v) + .addBody([kExprI32Const, 12]) + .exportAs("dummy"); + return builder.instantiate().exports.dummy; +} + +(function TestImportedAnyFunc() { + print(arguments.callee.name); + + let builder = new WasmModuleBuilder(); + const g = builder.addImportedGlobal('m', 'val', kWasmAnyFunc); + builder.addFunction('main', kSig_a_v) + .addBody([kExprGetGlobal, g]) + .exportAs('main'); + + const module = builder.toModule(); + const instance = new WebAssembly.Instance(module, { m: { val: null } }); + assertSame(null, instance.exports.main()); + + const instance2 = new WebAssembly.Instance( + module, { m: { val: instance.exports.main } }); + assertSame(instance.exports.main, instance2.exports.main()); + + assertThrows(() => new WebAssembly.Instance(module, { m: { val: {} } }), + WebAssembly.LinkError); +})(); + (function TestAnyRefGlobalObjectDefaultValue() { print(arguments.callee.name); - let default_init = new WebAssembly.Global({value: 'anyref', mutable: true}); + let default_init = new WebAssembly.Global({ value: 'anyref', mutable: true }); assertSame(null, default_init.value); assertSame(null, default_init.valueOf()); })(); +(function TestAnyFuncGlobalObjectDefaultValue() { + print(arguments.callee.name); + let default_init = new WebAssembly.Global({ value: 'anyfunc', mutable: true }); + assertSame(null, default_init.value); + assertSame(null, default_init.valueOf()); +})(); (function TestAnyRefGlobalObject() { print(arguments.callee.name); function TestGlobal(obj) { - const global = new WebAssembly.Global({value: 'anyref'}, obj); + const global = new WebAssembly.Global({ value: 'anyref' }, obj); assertSame(obj, global.value); assertSame(obj, global.valueOf()); } @@ -148,13 +219,28 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); TestGlobal(undefined); TestGlobal(1663); TestGlobal("testmyglobal"); - TestGlobal({a: 11}); + TestGlobal({ a: 11 }); TestGlobal(print); })(); +(function TestAnyFuncGlobalObject() { + print(arguments.callee.name); + + const dummy = dummy_func(); + const global = new WebAssembly.Global({ value: 'anyfunc' }, dummy); + assertSame(dummy, global.value); + assertSame(dummy, global.valueOf()); + + const global_null = new WebAssembly.Global({ value: 'anyfunc' }, null); + assertSame(null, global_null.value); + assertSame(null, global_null.valueOf()); + + assertThrows(() => new WebAssembly.Global({ value: 'anyfunc' }, {}), TypeError); +})(); + (function TestAnyRefGlobalObjectSetValue() { print(arguments.callee.name); - let global = new WebAssembly.Global({value: 'anyref', mutable: true}); + let global = new WebAssembly.Global({ value: 'anyref', mutable: true }); function TestGlobal(obj) { global.value = obj; @@ -166,32 +252,60 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); assertThrows(() => TestGlobal(undefined), TypeError); TestGlobal(1663); TestGlobal("testmyglobal"); - TestGlobal({a: 11}); + TestGlobal({ a: 11 }); TestGlobal(print); })(); -(function TestExportMutableAnyRefGlobal() { + +(function TestAnyFuncGlobalObjectSetValue() { + print(arguments.callee.name); + let global = new WebAssembly.Global({ value: 'anyfunc', mutable: true }); + + const dummy = dummy_func(); + global.value = dummy; + assertSame(dummy, global.value); + assertSame(dummy, global.valueOf()); + + global.value = null; + assertSame(null, global.value); + assertSame(null, global.valueOf()); + + assertThrows(() => global.value = {}, TypeError); +})(); + +(function TestExportMutableRefGlobal() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); const g1 = builder.addGlobal(kWasmAnyRef, true).exportAs("global1"); + const g2 = builder.addGlobal(kWasmAnyFunc, true).exportAs("global2"); builder.addGlobal(kWasmI32, true); // Dummy. builder.addGlobal(kWasmAnyRef, true); // Dummy. - const g2 = builder.addGlobal(kWasmAnyRef, true).exportAs("global2"); - builder.addFunction("main", kSig_v_rr) + const g3 = builder.addGlobal(kWasmAnyRef, true).exportAs("global3"); + const g4 = builder.addGlobal(kWasmAnyFunc, true).exportAs("global4"); + builder.addFunction("main", + makeSig([kWasmAnyRef, kWasmAnyFunc, kWasmAnyRef, kWasmAnyFunc], [])) .addBody([ - kExprGetLocal, 0, - kExprSetGlobal, g1.index, - kExprGetLocal, 1, - kExprSetGlobal, g2.index + kExprGetLocal, 0, + kExprSetGlobal, g1.index, + kExprGetLocal, 1, + kExprSetGlobal, g2.index, + kExprGetLocal, 2, + kExprSetGlobal, g3.index, + kExprGetLocal, 3, + kExprSetGlobal, g4.index ]) .exportAs("main"); const instance = builder.instantiate(); - const obj1 = {x: 221}; - const obj2 = print; - instance.exports.main(obj1, obj2); + const obj1 = { x: 221 }; + const func2 = instance.exports.main; + const obj3 = print; + const func4 = dummy_func(); + instance.exports.main(obj1, func2, obj3, func4); assertSame(obj1, instance.exports.global1.value); - assertSame(obj2, instance.exports.global2.value); + assertSame(func2, instance.exports.global2.value); + assertSame(obj3, instance.exports.global3.value); + assertSame(func4, instance.exports.global4.value); })(); (function TestImportMutableAnyRefGlobal() { @@ -200,21 +314,38 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); let builder = new WasmModuleBuilder(); const g = builder.addImportedGlobal('m', 'val', kWasmAnyRef, true); builder.addFunction('main', kSig_r_v) - .addBody([kExprGetGlobal, g]) - .exportAs('main'); + .addBody([kExprGetGlobal, g]) + .exportAs('main'); - const global = new WebAssembly.Global({value: 'anyref', mutable: 'true'}, obj); - const instance = builder.instantiate({m: {val: global}}); + const global = new WebAssembly.Global({ value: 'anyref', mutable: 'true' }, obj); + const instance = builder.instantiate({ m: { val: global } }); assertSame(obj, instance.exports.main()); } Test(null); Test(undefined); Test(1653); Test("mystring"); - Test({q: 14}); + Test({ q: 14 }); Test(print); })(); +(function TestImportMutableAnyFuncGlobal() { + print(arguments.callee.name); + function Test(obj) { + let builder = new WasmModuleBuilder(); + const g = builder.addImportedGlobal('m', 'val', kWasmAnyFunc, true); + builder.addFunction('main', kSig_a_v) + .addBody([kExprGetGlobal, g]) + .exportAs('main'); + + const global = new WebAssembly.Global({ value: 'anyfunc', mutable: 'true' }, obj); + const instance = builder.instantiate({ m: { val: global } }); + assertSame(obj, instance.exports.main()); + } + Test(dummy_func()); + Test(null); +})(); + (function TestImportMutableAnyRefGlobalFromOtherInstance() { print(arguments.callee.name); @@ -227,23 +358,23 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); builder1.addFunction("set_globals", kSig_v_rr) .addBody([ - kExprGetLocal, 0, - kExprSetGlobal, g2.index, - kExprGetLocal, 1, - kExprSetGlobal, g3.index, + kExprGetLocal, 0, + kExprSetGlobal, g2.index, + kExprGetLocal, 1, + kExprSetGlobal, g3.index, ]) .exportAs("set_globals"); builder1.addFunction('get_global2', kSig_r_v) - .addBody([kExprGetGlobal, g2.index]) - .exportAs('get_global2'); + .addBody([kExprGetGlobal, g2.index]) + .exportAs('get_global2'); builder1.addFunction('get_global3', kSig_r_v) - .addBody([kExprGetGlobal, g3.index]) - .exportAs('get_global3'); + .addBody([kExprGetGlobal, g3.index]) + .exportAs('get_global3'); const instance1 = builder1.instantiate(); - const obj2 = {x: 221}; + const obj2 = { x: 221 }; const obj3 = print; instance1.exports.set_globals(obj2, obj3); @@ -261,20 +392,20 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); builder2.addFunction("set_globals", kSig_v_rr) .addBody([ - kExprGetLocal, 0, - kExprSetGlobal, i2, - kExprGetLocal, 1, - kExprSetGlobal, i3, + kExprGetLocal, 0, + kExprSetGlobal, i2, + kExprGetLocal, 1, + kExprSetGlobal, i3, ]) .exportAs("set_globals"); builder2.addFunction('get_global2', kSig_r_v) - .addBody([kExprGetGlobal, i2]) - .exportAs('get_global2'); + .addBody([kExprGetGlobal, i2]) + .exportAs('get_global2'); builder2.addFunction('get_global3', kSig_r_v) - .addBody([kExprGetGlobal, i3]) - .exportAs('get_global3'); + .addBody([kExprGetGlobal, i3]) + .exportAs('get_global3'); const instance2 = builder2.instantiate(instance1); // Check if the globals were imported correctly. @@ -300,8 +431,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); assertEquals("foo", instance2.exports.reexport2.value); assertEquals(66343, instance2.exports.reexport3.value); - const bar2 = {f: "oo"}; - const bar3 = {b: "ar"}; + const bar2 = { f: "oo" }; + const bar3 = { b: "ar" }; instance2.exports.reexport2.value = bar2; instance2.exports.reexport3.value = bar3; @@ -310,3 +441,90 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); assertSame(bar2, instance2.exports.get_global2()); assertSame(bar3, instance2.exports.get_global3()); })(); + +(function TestImportMutableAnyFuncGlobalFromOtherInstance() { + print(arguments.callee.name); + + // Create an instance which exports globals. + let builder1 = new WasmModuleBuilder(); + const g3 = builder1.addGlobal(kWasmAnyFunc, true).exportAs("e3"); + builder1.addGlobal(kWasmI32, true).exportAs("e1"); // Dummy. + builder1.addGlobal(kWasmAnyFunc, true).exportAs("e4"); // Dummy. + const g2 = builder1.addGlobal(kWasmAnyFunc, true).exportAs("e2"); + + builder1.addFunction("set_globals", kSig_v_aa) + .addBody([ + kExprGetLocal, 0, + kExprSetGlobal, g2.index, + kExprGetLocal, 1, + kExprSetGlobal, g3.index, + ]) + .exportAs("set_globals"); + + builder1.addFunction('get_global2', kSig_a_v) + .addBody([kExprGetGlobal, g2.index]) + .exportAs('get_global2'); + + builder1.addFunction('get_global3', kSig_a_v) + .addBody([kExprGetGlobal, g3.index]) + .exportAs('get_global3'); + + const instance1 = builder1.instantiate(); + const obj2 = dummy_func(); + const obj3 = instance1.exports.set_globals; + const obj4 = instance1.exports.get_global3; + instance1.exports.set_globals(obj2, obj3); + + // Create an instance which imports the globals of the other instance. + let builder2 = new WasmModuleBuilder(); + const i1 = builder2.addImportedGlobal('exports', 'e1', kWasmI32, true); + const i2 = builder2.addImportedGlobal('exports', 'e2', kWasmAnyFunc, true); + const i3 = builder2.addImportedGlobal('exports', 'e3', kWasmAnyFunc, true); + const i4 = builder2.addImportedGlobal('exports', 'e4', kWasmAnyFunc, true); + + builder2.addExportOfKind("reexport1", kExternalGlobal, i1); + builder2.addExportOfKind("reexport2", kExternalGlobal, i2); + builder2.addExportOfKind("reexport3", kExternalGlobal, i3); + builder2.addExportOfKind("reexport4", kExternalGlobal, i4); + + builder2.addFunction("set_globals", kSig_v_aa) + .addBody([ + kExprGetLocal, 0, + kExprSetGlobal, i2, + kExprGetLocal, 1, + kExprSetGlobal, i3, + ]) + .exportAs("set_globals"); + + builder2.addFunction('get_global2', kSig_a_v) + .addBody([kExprGetGlobal, i2]) + .exportAs('get_global2'); + + builder2.addFunction('get_global3', kSig_a_v) + .addBody([kExprGetGlobal, i3]) + .exportAs('get_global3'); + + const instance2 = builder2.instantiate(instance1); + // Check if the globals were imported correctly. + assertSame(obj2, instance2.exports.get_global2()); + assertSame(obj3, instance2.exports.get_global3()); + + assertSame(obj2, instance2.exports.reexport2.value); + assertSame(obj3, instance2.exports.reexport3.value); + + // Check if instance2 can make changes visible for instance1. + instance2.exports.set_globals(null, obj4); + assertEquals(null, instance1.exports.get_global2()); + assertEquals(obj4, instance1.exports.get_global3()); + + assertEquals(null, instance2.exports.reexport2.value); + assertEquals(obj4, instance2.exports.reexport3.value); + + // Check if instance1 can make changes visible for instance2. + instance1.exports.set_globals(obj2, obj3); + assertEquals(obj2, instance2.exports.get_global2()); + assertEquals(obj3, instance2.exports.get_global3()); + + assertEquals(obj2, instance2.exports.reexport2.value); + assertEquals(obj3, instance2.exports.reexport3.value); +})(); diff --git a/deps/v8/test/mjsunit/wasm/anyref-interpreter.js b/deps/v8/test/mjsunit/wasm/anyref-interpreter.js new file mode 100644 index 0000000000..d22e841049 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/anyref-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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 --experimental-wasm-anyref --expose-gc +// Flags: --wasm-interpret-all + +// This is just a wrapper for an existing reference types test case that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/anyref.js"); diff --git a/deps/v8/test/mjsunit/wasm/anyref-table.js b/deps/v8/test/mjsunit/wasm/anyref-table.js new file mode 100644 index 0000000000..f9248199a2 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/anyref-table.js @@ -0,0 +1,31 @@ +// Copyright 2019 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-anyref + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +(function TestAnyRefTableSetWithMultipleTypes() { + print(arguments.callee.name); + let table = new WebAssembly.Table({element: "anyref", initial: 10}); + + // Table should be initialized with null. + assertEquals(null, table.get(1)); + let obj = {'hello' : 'world'}; + table.set(2, obj); + assertSame(obj, table.get(2)); + table.set(3, 1234); + assertEquals(1234, table.get(3)); + table.set(4, 123.5); + assertEquals(123.5, table.get(4)); + table.set(5, undefined); + assertEquals(undefined, table.get(5)); + // Overwrite entry 4, because null would otherwise be the default value. + table.set(4, null); + assertEquals(null, table.get(4)); + table.set(7, print); + assertEquals(print, table.get(7)); + + assertThrows(() => table.set(12), RangeError); +})(); diff --git a/deps/v8/test/mjsunit/wasm/async-compile.js b/deps/v8/test/mjsunit/wasm/async-compile.js index a5e7c499bd..4660ec7986 100644 --- a/deps/v8/test/mjsunit/wasm/async-compile.js +++ b/deps/v8/test/mjsunit/wasm/async-compile.js @@ -66,7 +66,7 @@ assertPromiseResult(async function badFunctionInTheMiddle() { let buffer = builder.toBuffer(); await assertCompileError( buffer, - 'Compiling wasm function \"bad\" failed: ' + + 'Compiling function #10:\"bad\" failed: ' + 'expected 1 elements on the stack for fallthru to @1, found 0 @+94'); }()); diff --git a/deps/v8/test/mjsunit/wasm/bigint-i64-to-imported-js-func.js b/deps/v8/test/mjsunit/wasm/bigint-i64-to-imported-js-func.js new file mode 100644 index 0000000000..2fa48d9b96 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/bigint-i64-to-imported-js-func.js @@ -0,0 +1,39 @@ +// Copyright 2019 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-bigint + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +(function TestWasmI64ToJSBigIntImportedFunc() { + var builder = new WasmModuleBuilder(); + + var a_index = builder + .addImport("a", "a", kSig_l_l) // i64 -> i64 + + builder + .addFunction("fn", kSig_l_v) // () -> i64 + .addBody([ + kExprI64Const, 0x7, + kExprCallFunction, a_index + ]) + .exportFunc(); + + a_was_called = false; + + var module = builder.instantiate({ + a: { + a(param) { + assertEquals(typeof param, "bigint"); + assertEquals(param, 7n); + a_was_called = true; + return 12n; + }, + } + }); + + assertEquals(module.exports.fn(), 12n); + + assertTrue(a_was_called); +})(); diff --git a/deps/v8/test/mjsunit/wasm/bigint.js b/deps/v8/test/mjsunit/wasm/bigint.js index 49a1ead6b8..d64c0e0623 100644 --- a/deps/v8/test/mjsunit/wasm/bigint.js +++ b/deps/v8/test/mjsunit/wasm/bigint.js @@ -22,38 +22,6 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); assertEquals(module.exports.fn(), 3n); })(); -(function TestWasmI64ToJSBigIntImportedFunc() { - var builder = new WasmModuleBuilder(); - - var a_index = builder - .addImport("a", "a", kSig_l_l) // i64 -> i64 - - builder - .addFunction("fn", kSig_l_v) // () -> i64 - .addBody([ - kExprI64Const, 0x7, - kExprCallFunction, a_index - ]) - .exportFunc(); - - a_was_called = false; - - var module = builder.instantiate({ - a: { - a(param) { - assertEquals(typeof param, "bigint"); - assertEquals(param, 7n); - a_was_called = true; - return 12n; - }, - } - }); - - assertEquals(module.exports.fn(), 12n); - - assertTrue(a_was_called); -})(); - (function TestJSBigIntToWasmI64Global() { var builder = new WasmModuleBuilder(); diff --git a/deps/v8/test/mjsunit/wasm/bulk-memory.js b/deps/v8/test/mjsunit/wasm/bulk-memory.js index 0e59965085..b02f9ea56c 100644 --- a/deps/v8/test/mjsunit/wasm/bulk-memory.js +++ b/deps/v8/test/mjsunit/wasm/bulk-memory.js @@ -27,15 +27,6 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); builder.instantiate(); })(); -function assertBufferContents(buf, expected) { - for (let i = 0; i < expected.length; ++i) { - assertEquals(expected[i], buf[i]); - } - for (let i = expected.length; i < buf.length; ++i) { - assertEquals(0, buf[i]); - } -} - function getMemoryInit(mem, segment_data) { const builder = new WasmModuleBuilder(); builder.addImportedMemory("", "mem", 0); @@ -53,47 +44,11 @@ function getMemoryInit(mem, segment_data) { return builder.instantiate({'': {mem}}).exports.init; } -(function TestMemoryInit() { - const mem = new WebAssembly.Memory({initial: 1}); - const memoryInit = getMemoryInit(mem, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - - const u8a = new Uint8Array(mem.buffer); - - // All zeroes. - assertBufferContents(u8a, []); - - // Copy all bytes from data segment 0, to memory at [10, 20). - memoryInit(10, 0, 10); - assertBufferContents(u8a, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - - // Copy bytes in range [5, 10) from data segment 0, to memory at [0, 5). - memoryInit(0, 5, 5); - assertBufferContents(u8a, [5, 6, 7, 8, 9, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); -})(); - -(function TestMemoryInitOutOfBounds() { +(function TestMemoryInitOutOfBoundsGrow() { const mem = new WebAssembly.Memory({initial: 1}); // Create a data segment that has a length of kPageSize. const memoryInit = getMemoryInit(mem, new Array(kPageSize)); - // OK, copy the full data segment to memory. - memoryInit(0, 0, kPageSize); - - // Source range must not be out of bounds. - assertTraps(kTrapMemOutOfBounds, () => memoryInit(0, 1, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryInit(0, 1000, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryInit(0, kPageSize, 1)); - - // Destination range must not be out of bounds. - assertTraps(kTrapMemOutOfBounds, () => memoryInit(1, 0, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryInit(1000, 0, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryInit(kPageSize, 0, 1)); - - // Make sure bounds aren't checked with 32-bit wrapping. - assertTraps(kTrapMemOutOfBounds, () => memoryInit(1, 1, -1)); - mem.grow(1); // Works properly after grow. @@ -127,41 +82,6 @@ function getMemoryInit(mem, segment_data) { assertTraps(kTrapDataSegmentDropped, () => instance.exports.init()); })(); -(function TestMemoryInitOnDroppedSegment() { - const builder = new WasmModuleBuilder(); - builder.addMemory(1); - builder.addPassiveDataSegment([1, 2, 3]); - builder.addFunction('init', kSig_v_v) - .addBody([ - kExprI32Const, 0, // Dest. - kExprI32Const, 0, // Source. - kExprI32Const, 0, // Size in bytes. - kNumericPrefix, kExprMemoryInit, - 0, // Data segment index. - 0, // Memory index. - ]) - .exportAs('init'); - builder.addFunction('drop', kSig_v_v) - .addBody([ - kNumericPrefix, kExprDataDrop, - 0, // Data segment index. - ]) - .exportAs('drop'); - - // Instantiation succeeds, because using memory.init with an active segment - // is a trap, not a validation error. - const instance = builder.instantiate(); - - // OK, segment hasn't been dropped. - instance.exports.init(); - - instance.exports.drop(); - - // After segment has been dropped, memory.init and memory.drop fail. - assertTraps(kTrapDataSegmentDropped, () => instance.exports.init()); - assertTraps(kTrapDataSegmentDropped, () => instance.exports.drop()); -})(); - (function TestDataDropOnActiveSegment() { const builder = new WasmModuleBuilder(); builder.addMemory(1); @@ -190,61 +110,10 @@ function getMemoryCopy(mem) { return builder.instantiate({'': {mem}}).exports.copy; } -(function TestMemoryCopy() { - const mem = new WebAssembly.Memory({initial: 1}); - const memoryCopy = getMemoryCopy(mem); - - const u8a = new Uint8Array(mem.buffer); - u8a.set([0, 11, 22, 33, 44, 55, 66, 77]); - - memoryCopy(10, 1, 8); - - assertBufferContents(u8a, [0, 11, 22, 33, 44, 55, 66, 77, 0, 0, - 11, 22, 33, 44, 55, 66, 77]); - - // Copy 0 bytes does nothing. - memoryCopy(10, 1, 0); - assertBufferContents(u8a, [0, 11, 22, 33, 44, 55, 66, 77, 0, 0, - 11, 22, 33, 44, 55, 66, 77]); -})(); - -(function TestMemoryCopyOverlapping() { +(function TestMemoryCopyOutOfBoundsGrow() { const mem = new WebAssembly.Memory({initial: 1}); const memoryCopy = getMemoryCopy(mem); - const u8a = new Uint8Array(mem.buffer); - u8a.set([10, 20, 30]); - - // Copy from [0, 3] -> [2, 5]. The copy must not overwrite 30 before copying - // it (i.e. cannot copy forward in this case). - memoryCopy(2, 0, 3); - assertBufferContents(u8a, [10, 20, 10, 20, 30]); - - // Copy from [2, 5] -> [0, 3]. The copy must not write the first 10 (i.e. - // cannot copy backward in this case). - memoryCopy(0, 2, 3); - assertBufferContents(u8a, [10, 20, 30, 20, 30]); -})(); - -(function TestMemoryCopyOutOfBounds() { - const mem = new WebAssembly.Memory({initial: 1}); - const memoryCopy = getMemoryCopy(mem); - - memoryCopy(0, 0, kPageSize); - - // Source range must not be out of bounds. - assertTraps(kTrapMemOutOfBounds, () => memoryCopy(0, 1, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryCopy(0, 1000, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryCopy(0, kPageSize, 1)); - - // Destination range must not be out of bounds. - assertTraps(kTrapMemOutOfBounds, () => memoryCopy(1, 0, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryCopy(1000, 0, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryCopy(kPageSize, 0, 1)); - - // Make sure bounds aren't checked with 32-bit wrapping. - assertTraps(kTrapMemOutOfBounds, () => memoryCopy(1, 1, -1)); - mem.grow(1); // Works properly after grow. @@ -267,49 +136,11 @@ function getMemoryFill(mem) { return builder.instantiate({'': {mem}}).exports.fill; } -(function TestMemoryFill() { - const mem = new WebAssembly.Memory({initial: 1}); - const memoryFill = getMemoryFill(mem); - - const u8a = new Uint8Array(mem.buffer); - - memoryFill(1, 33, 5); - assertBufferContents(u8a, [0, 33, 33, 33, 33, 33]); - - memoryFill(4, 66, 4); - assertBufferContents(u8a, [0, 33, 33, 33, 66, 66, 66, 66]); - - // Fill 0 bytes does nothing. - memoryFill(4, 66, 0); - assertBufferContents(u8a, [0, 33, 33, 33, 66, 66, 66, 66]); -})(); - -(function TestMemoryFillValueWrapsToByte() { - const mem = new WebAssembly.Memory({initial: 1}); - const memoryFill = getMemoryFill(mem); - - const u8a = new Uint8Array(mem.buffer); - - memoryFill(0, 1000, 3); - const expected = 1000 & 255; - assertBufferContents(u8a, [expected, expected, expected]); -})(); - -(function TestMemoryFillOutOfBounds() { +(function TestMemoryFillOutOfBoundsGrow() { const mem = new WebAssembly.Memory({initial: 1}); const memoryFill = getMemoryFill(mem); const v = 123; - memoryFill(0, 0, kPageSize); - - // Destination range must not be out of bounds. - assertTraps(kTrapMemOutOfBounds, () => memoryFill(1, v, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryFill(1000, v, kPageSize)); - assertTraps(kTrapMemOutOfBounds, () => memoryFill(kPageSize, v, 1)); - - // Make sure bounds aren't checked with 32-bit wrapping. - assertTraps(kTrapMemOutOfBounds, () => memoryFill(1, v, -1)); - mem.grow(1); // Works properly after grow. @@ -323,7 +154,7 @@ function getMemoryFill(mem) { (function TestElemDropActive() { const builder = new WasmModuleBuilder(); builder.setTableBounds(5, 5); - builder.addElementSegment(0, false, [0, 0, 0]); + builder.addElementSegment(0, 0, false, [0, 0, 0]); builder.addFunction('drop', kSig_v_v) .addBody([ kNumericPrefix, kExprElemDrop, @@ -335,18 +166,73 @@ function getMemoryFill(mem) { assertTraps(kTrapElemSegmentDropped, () => instance.exports.drop()); })(); -(function TestElemDropTwice() { +(function TestLazyDataSegmentBoundsCheck() { + const memory = new WebAssembly.Memory({initial: 1}); + const view = new Uint8Array(memory.buffer); const builder = new WasmModuleBuilder(); - builder.setTableBounds(5, 5); - builder.addPassiveElementSegment([0, 0, 0]); - builder.addFunction('drop', kSig_v_v) - .addBody([ - kNumericPrefix, kExprElemDrop, - 0, // Element segment index. - ]) - .exportAs('drop'); + builder.addImportedMemory('m', 'memory', 1); + builder.addDataSegment(kPageSize - 1, [42, 42]); + builder.addDataSegment(0, [111, 111]); - const instance = builder.instantiate(); - instance.exports.drop(); - assertTraps(kTrapElemSegmentDropped, () => instance.exports.drop()); + assertEquals(0, view[kPageSize - 1]); + + // Instantiation fails, but still modifies memory. + assertThrows(() => builder.instantiate({m: {memory}}), WebAssembly.LinkError); + + assertEquals(42, view[kPageSize - 1]); + // The second segment is not initialized. + assertEquals(0, view[0]); +})(); + +(function TestLazyElementSegmentBoundsCheck() { + const table = new WebAssembly.Table({initial: 3, element: 'anyfunc'}); + const builder = new WasmModuleBuilder(); + builder.addImportedTable('m', 'table', 1); + const f = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 42]); + + const tableIndex = 0; + const isGlobal = false; + const isImport = true; + builder.addElementSegment( + tableIndex, 2, isGlobal, [f.index, f.index], isImport); + builder.addElementSegment( + tableIndex, 0, isGlobal, [f.index, f.index], isImport); + + assertEquals(null, table.get(0)); + assertEquals(null, table.get(1)); + assertEquals(null, table.get(2)); + + // Instantiation fails, but still modifies the table. + assertThrows(() => builder.instantiate({m: {table}}), WebAssembly.LinkError); + + // The second segment is not initialized. + assertEquals(null, table.get(0)); + assertEquals(null, table.get(1)); + assertEquals(42, table.get(2)()); +})(); + +(function TestLazyDataAndElementSegments() { + const table = new WebAssembly.Table({initial: 1, element: 'anyfunc'}); + const memory = new WebAssembly.Memory({initial: 1}); + const view = new Uint8Array(memory.buffer); + const builder = new WasmModuleBuilder(); + + builder.addImportedMemory('m', 'memory', 1); + builder.addImportedTable('m', 'table', 1); + const f = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 42]); + + const tableIndex = 0; + const isGlobal = false; + const isImport = true; + builder.addElementSegment( + tableIndex, 0, isGlobal, [f.index, f.index], isImport); + builder.addDataSegment(0, [42]); + + // Instantiation fails, but still modifies the table. The memory is not + // modified, since data segments are initialized after element segments. + assertThrows( + () => builder.instantiate({m: {memory, table}}), WebAssembly.LinkError); + + assertEquals(42, table.get(0)()); + assertEquals(0, view[0]); })(); diff --git a/deps/v8/test/mjsunit/wasm/compilation-hints-async-compilation.js b/deps/v8/test/mjsunit/wasm/compilation-hints-async-compilation.js new file mode 100644 index 0000000000..6778fc9c4c --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/compilation-hints-async-compilation.js @@ -0,0 +1,60 @@ +// Copyright 2019 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-compilation-hints + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +(function testCompileWithBadLazyHint() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction('id', kSig_i_i) + .addBody([kExprGetLocal, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierOptimized, + kCompilationHintTierBaseline) + .exportFunc(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.compile(bytes) + .then(assertUnreachable, + error => assertEquals("WebAssembly.compile(): Invalid compilation " + + "hint 0x2d (forbidden downgrade) @+49", error.message))); +})(); + +(function testCompileWithBadLazyFunctionBody() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction('id', kSig_i_l) + .addBody([kExprGetLocal, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierDefault, + kCompilationHintTierDefault) + .exportFunc(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.compile(bytes) + .then(assertUnreachable, + error => assertEquals("WebAssembly.compile(): type error in " + + "merge[0] (expected i32, got i64) @+56", error.message))); +})(); + +(function testCompileEmptyModule() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.compile(bytes)); +})(); + +(function testCompileLazyModule() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction('id', kSig_i_i) + .addBody([kExprGetLocal, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierDefault, + kCompilationHintTierDefault) + .exportFunc(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.instantiate(bytes) + .then(({module, instance}) => assertEquals(42, instance.exports.id(42)))); +})(); diff --git a/deps/v8/test/mjsunit/wasm/compilation-hints-decoder.js b/deps/v8/test/mjsunit/wasm/compilation-hints-decoder.js new file mode 100644 index 0000000000..dfb6e49ba1 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/compilation-hints-decoder.js @@ -0,0 +1,126 @@ +// Copyright 2019 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-compilation-hints + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +(function testDecodeCompilationHintsSectionNoDowngrade() { + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierOptimized, + kCompilationHintTierBaseline) + .exportFunc(); + assertThrows(() => builder.instantiate({mod: {pow: Math.pow}}), + WebAssembly.CompileError, + "WebAssembly.Module(): Invalid compilation hint 0x2d " + + "(forbidden downgrade) @+70"); +})(); + +(function testDecodeCompilationHintsSectionNoTiering() { + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyDefault, + kCompilationHintTierInterpreter, + kCompilationHintTierInterpreter) + .exportFunc(); + builder.addFunction('upow2', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + builder.addFunction('upow3', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + let instance = builder.instantiate({mod: {pow: Math.pow}}); + assertEquals(27, instance.exports.upow(3)) +})(); + +(function testDecodeCompilationHintsSectionUpgrade() { + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + builder.addFunction('upow2', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + builder.addFunction('upow3', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyEager, + kCompilationHintTierBaseline, + kCompilationHintTierOptimized) + .exportFunc(); + let instance = builder.instantiate({mod: {pow: Math.pow}}); + assertEquals(27, instance.exports.upow(3)) +})(); + +(function testDecodeCompilationHintsSectionNoImport() { + let builder = new WasmModuleBuilder(); + builder.addFunction('sq', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprI32Mul]) + .giveCompilationHint(kCompilationHintStrategyEager, + kCompilationHintTierDefault, + kCompilationHintTierOptimized) + .exportFunc(); + let instance = builder.instantiate(); + assertEquals(9, instance.exports.sq(3)) +})(); + +(function testDecodeCompilationHintsSectionNoExport() { + let builder = new WasmModuleBuilder(); + builder.addFunction('sq', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprI32Mul]) + .giveCompilationHint(kCompilationHintStrategyEager, + kCompilationHintTierDefault, + kCompilationHintTierOptimized) + builder.instantiate(); +})(); + +(function testDecodeCompilationHintsSectionTopTierDefault() { + let builder = new WasmModuleBuilder(); + builder.addFunction('sq', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprI32Mul]) + .giveCompilationHint(kCompilationHintStrategyEager, + kCompilationHintTierOptimized, + kCompilationHintTierDefault) + .exportFunc(); + let instance = builder.instantiate(); + assertEquals(9, instance.exports.sq(3)) +})(); + +(function testDecodeCompilationHintsInvalidStrategy() { + let builder = new WasmModuleBuilder(); + builder.addFunction('sq', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprI32Mul]) + .giveCompilationHint(0x3, + kCompilationHintTierOptimized, + kCompilationHintTierDefault) + .exportFunc(); + assertThrows(() => builder.instantiate(), + WebAssembly.CompileError, + "WebAssembly.Module(): Invalid compilation hint 0xf " + + "(unknown strategy) @+49"); +})(); diff --git a/deps/v8/test/mjsunit/wasm/compilation-hints-ignored.js b/deps/v8/test/mjsunit/wasm/compilation-hints-ignored.js new file mode 100644 index 0000000000..76dad56a60 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/compilation-hints-ignored.js @@ -0,0 +1,21 @@ +// Copyright 2019 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-module-builder.js'); + +(function testIgnoreCompilationHintsSectionUnlessEnabled() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyDefault, + kCompilationHintTierInterpreter, + kCompilationHintTierInterpreter) + .exportFunc(); + let instance = builder.instantiate({mod: {pow: Math.pow}}); + assertEquals(27, instance.exports.upow(3)) +})(); diff --git a/deps/v8/test/mjsunit/wasm/compilation-hints-streaming-compilation.js b/deps/v8/test/mjsunit/wasm/compilation-hints-streaming-compilation.js new file mode 100644 index 0000000000..dcc795e54e --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/compilation-hints-streaming-compilation.js @@ -0,0 +1,105 @@ +// Copyright 2019 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-compilation-hints --wasm-test-streaming + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +(function testInstantiateStreamingWithLazyHint() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + builder.addFunction('upow2', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierDefault, + kCompilationHintTierDefault) + .exportFunc(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.instantiateStreaming(Promise.resolve(bytes), + {mod: {pow: Math.pow}}) + .then(({module, instance}) => assertEquals(27, instance.exports.upow2(3)))); +})(); + +(function testInstantiateStreamingWithBadLazyHint() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + builder.addFunction('upow2', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierOptimized, + kCompilationHintTierBaseline) + .exportFunc(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.instantiateStreaming(Promise.resolve(bytes), + {mod: {pow: Math.pow}}) + .then(assertUnreachable, + error => assertEquals("WebAssembly.compile(): Invalid compilation " + + "hint 0x2d (forbidden downgrade) @+78", + error.message))); +})(); + +(function testInstantiateStreamingWithBadLazyFunctionBody() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_f_ff); + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + builder.addFunction('upow2', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierDefault, + kCompilationHintTierDefault) + .exportFunc(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.instantiateStreaming(Promise.resolve(bytes), + {mod: {pow: Math.pow}}) + .then(assertUnreachable, + error => assertEquals("WebAssembly.compile(): call[1] expected " + + "type f32, found get_local of type i32 @+94", error.message))); +})(); + +(function testInstantiateStreamingEmptyModule() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.instantiateStreaming(Promise.resolve(bytes), + {mod: {pow: Math.pow}})); +})(); + +(function testInstantiateStreamingLazyModule() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addImport('mod', 'pow', kSig_i_ii); + builder.addFunction('upow', kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 0, + kExprCallFunction, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierDefault, + kCompilationHintTierDefault) + .exportFunc(); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.instantiateStreaming(Promise.resolve(bytes), + {mod: {pow: Math.pow}}) + .then(({module, instance}) => assertEquals(27, instance.exports.upow(3)))); +})(); diff --git a/deps/v8/test/mjsunit/wasm/compilation-hints-sync-compilation.js b/deps/v8/test/mjsunit/wasm/compilation-hints-sync-compilation.js new file mode 100644 index 0000000000..0212ae0d66 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/compilation-hints-sync-compilation.js @@ -0,0 +1,55 @@ +// Copyright 2019 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-compilation-hints + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +(function testCompileWithBadLazyHint() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction('id', kSig_i_i) + .addBody([kExprGetLocal, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierOptimized, + kCompilationHintTierBaseline) + .exportFunc(); + assertThrows(() => builder.toModule(), + WebAssembly.CompileError, + "WebAssembly.Module(): Invalid compilation hint 0x2d " + + "(forbidden downgrade) @+49"); +})(); + +(function testCompileWithBadLazyFunctionBody() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction('id', kSig_i_l) + .addBody([kExprGetLocal, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierDefault, + kCompilationHintTierDefault) + .exportFunc(); + assertThrows(() => builder.toModule(), + WebAssembly.CompileError, + "WebAssembly.Module(): Compiling function #0:\"id\" failed: type error " + + "in merge[0] (expected i32, got i64) @+56"); +})(); + +(function testCompileEmptyModule() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.toModule(); +})(); + +(function testCompileLazyModule() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction('id', kSig_i_i) + .addBody([kExprGetLocal, 0]) + .giveCompilationHint(kCompilationHintStrategyLazy, + kCompilationHintTierDefault, + kCompilationHintTierDefault) + .exportFunc(); + assertEquals(42, builder.instantiate().exports.id(42)); +})(); diff --git a/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js b/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js index 9c28a7746d..eceb5b00fb 100644 --- a/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js +++ b/deps/v8/test/mjsunit/wasm/compiled-module-serialization.js @@ -76,9 +76,10 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); (function DeserializeInvalidObject() { print(arguments.callee.name); - var invalid_buffer = new ArrayBuffer(10); + const invalid_buffer = new ArrayBuffer(10); + const invalid_buffer_view = new Uint8Array(10); - module = %DeserializeWasmModule(invalid_buffer, invalid_buffer); + module = %DeserializeWasmModule(invalid_buffer, invalid_buffer_view); assertEquals(module, undefined); })(); @@ -217,7 +218,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); .exportAs("main"); builder.setTableBounds(kTableSize, kTableSize); - builder.addElementSegment(0, false, [f1.index]); + builder.addElementSegment(0, 0, false, [f1.index]); builder.addExportOfKind("table", kExternalTable, 0); return new WebAssembly.Module(builder.toBuffer()); @@ -238,7 +239,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); .exportAs("main"); builder.addImportedTable("z", "table", kTableSize, kTableSize); - builder.addElementSegment(1, false, [f2.index], true); + builder.addElementSegment(0, 1, false, [f2.index], true); var m2_bytes = builder.toBuffer(); var m2 = new WebAssembly.Module(m2_bytes); diff --git a/deps/v8/test/mjsunit/wasm/errors.js b/deps/v8/test/mjsunit/wasm/errors.js index 9e3f683490..d98452e0e8 100644 --- a/deps/v8/test/mjsunit/wasm/errors.js +++ b/deps/v8/test/mjsunit/wasm/errors.js @@ -55,7 +55,7 @@ function assertConversionError(bytes, imports, msg) { (function TestValidationError() { print(arguments.callee.name); - let f_error = msg => 'Compiling wasm function "f" failed: ' + msg; + let f_error = msg => 'Compiling function #0:"f" failed: ' + msg; assertCompileError( builder().addFunction('f', kSig_i_v).end().toBuffer(), f_error('function body must end with "end" opcode @+24')); @@ -176,7 +176,6 @@ function import_error(index, module, func, msg) { assertConversionError(buffer, {}, kTrapMsgs[kTrapTypeError]); })(); - (function InternalDebugTrace() { print(arguments.callee.name); var builder = new WasmModuleBuilder(); @@ -192,3 +191,18 @@ function import_error(index, module, func, msg) { }).exports.main; main(); })(); + +(function TestMultipleCorruptFunctions() { + print(arguments.callee.name); + // Generate a module with multiple corrupt functions. The error message must + // be deterministic. + var builder = new WasmModuleBuilder(); + var sig = builder.addType(kSig_v_v); + for (let i = 0; i < 10; ++i) { + builder.addFunction('f' + i, sig).addBody([kExprEnd]); + } + assertCompileError( + builder.toBuffer(), + 'Compiling function #0:"f0" failed: ' + + 'trailing code after function end @+33'); +})(); diff --git a/deps/v8/test/mjsunit/wasm/exceptions-anyref-interpreter.js b/deps/v8/test/mjsunit/wasm/exceptions-anyref-interpreter.js new file mode 100644 index 0000000000..14d1e60e88 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/exceptions-anyref-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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-eh --experimental-wasm-anyref --allow-natives-syntax +// Flags: --wasm-interpret-all + +// This is just a wrapper for existing exception handling test cases that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/exceptions-anyref.js"); diff --git a/deps/v8/test/mjsunit/wasm/exceptions-global-interpreter.js b/deps/v8/test/mjsunit/wasm/exceptions-global-interpreter.js new file mode 100644 index 0000000000..ae06ff00fb --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/exceptions-global-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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 --experimental-wasm-eh --allow-natives-syntax +// Flags: --wasm-interpret-all + +// This is just a wrapper for existing exception handling test cases that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/exceptions-global.js"); diff --git a/deps/v8/test/mjsunit/wasm/exceptions-global.js b/deps/v8/test/mjsunit/wasm/exceptions-global.js new file mode 100644 index 0000000000..c48a8e41ef --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/exceptions-global.js @@ -0,0 +1,154 @@ +// Copyright 2019 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 --experimental-wasm-eh --allow-natives-syntax + +// Note that this test does not pass --experimental-wasm-anyref on purpose so +// that we make sure the two flags can be controlled separately/independently. + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +// First we just test that "except_ref" global variables are allowed. +(function TestGlobalExceptRefSupported() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let g = builder.addGlobal(kWasmExceptRef); + builder.addFunction("push_and_drop_except_ref", kSig_v_v) + .addBody([ + kExprGetGlobal, g.index, + kExprDrop, + ]).exportFunc(); + let instance = builder.instantiate(); + + assertDoesNotThrow(instance.exports.push_and_drop_except_ref); +})(); + +// Test default value that global "except_ref" variables are initialized with. +(function TestGlobalExceptRefDefaultValue() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let g = builder.addGlobal(kWasmExceptRef); + builder.addFunction('push_and_return_except_ref', kSig_e_v) + .addBody([kExprGetGlobal, g.index]) + .exportFunc(); + let instance = builder.instantiate(); + + assertEquals(null, instance.exports.push_and_return_except_ref()); +})(); + +// Test storing a caught exception into an exported mutable "except_ref" global. +(function TestGlobalExceptRefSetCaught() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_i); + let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn"); + builder.addFunction('catch_and_set_except_ref', kSig_v_i) + .addBody([ + kExprTry, kWasmStmt, + kExprGetLocal, 0, + kExprThrow, except, + kExprCatch, + kExprSetGlobal, g.index, + kExprEnd, + ]).exportFunc(); + let instance = builder.instantiate(); + + assertDoesNotThrow(() => instance.exports.catch_and_set_except_ref(23)); + let exception = instance.exports.exn.value; // Exported mutable global. + assertInstanceof(exception, WebAssembly.RuntimeError); + assertEquals(except, %GetWasmExceptionId(exception, instance)); +})(); + +// Test storing a parameter into an exported mutable "except_ref" global. +(function TestGlobalExceptRefSetParameter() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn"); + builder.addFunction('set_param_except_ref', kSig_v_e) + .addBody([ + kExprTry, kWasmStmt, + kExprGetLocal, 0, + kExprRethrow, + kExprCatch, + kExprSetGlobal, g.index, + kExprEnd, + ]).exportFunc(); + let exception = "my fancy exception"; + let instance = builder.instantiate(); + + assertDoesNotThrow(() => instance.exports.set_param_except_ref(exception)); + assertEquals(exception, instance.exports.exn.value); +})(); + +// Test loading an imported "except_ref" global and re-throwing the exception. +(function TestGlobalExceptRefGetImportedAndRethrow() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let g_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef); + builder.addFunction('rethrow_except_ref', kSig_v_v) + .addBody([ + kExprGetGlobal, g_index, + kExprRethrow, + ]).exportFunc(); + let exception = "my fancy exception"; + let instance = builder.instantiate({ "m": { "exn": exception }}); + + assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception); +})(); + +// Test loading an exported mutable "except_ref" being changed from the outside. +(function TestGlobalExceptRefGetExportedMutableAndRethrow() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn"); + builder.addFunction('rethrow_except_ref', kSig_v_v) + .addBody([ + kExprGetGlobal, g.index, + kExprRethrow, + ]).exportFunc(); + let instance = builder.instantiate(); + + let exception1 = instance.exports.exn.value = "my fancy exception"; + assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception1); + let exception2 = instance.exports.exn.value = "an even fancier exception"; + assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception2); +})(); + +// TODO(mstarzinger): Add the following test once proposal makes it clear how +// far interaction with the mutable globals proposal is intended to go. +// Test loading an imported mutable "except_ref" being changed from the outside. +/*(function TestGlobalExceptRefGetImportedMutableAndRethrow() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let g_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef, true); + builder.addFunction('rethrow_except_ref', kSig_v_v) + .addBody([ + kExprGetGlobal, g_index, + kExprRethrow, + ]).exportFunc(); + let exception1 = "my fancy exception"; + let desc = { value: 'except_ref', mutable: true }; + let mutable_global = new WebAssembly.Global(desc, exception1); + let instance = builder.instantiate({ "m": { "exn": mutable_global }}); + + assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception1); + let exception2 = mutable_global.value = "an even fancier exception"; + assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception2); +})();*/ + +// Test custom initialization index for a global "except_ref" variable. +(function TestGlobalExceptRefInitIndex() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let g1_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef); + let g2 = builder.addGlobal(kWasmExceptRef); + g2.init_index = g1_index; // Initialize {g2} to equal {g1}. + builder.addFunction('push_and_return_except_ref', kSig_e_v) + .addBody([kExprGetGlobal, g2.index]) + .exportFunc(); + let exception = { x: "my fancy exception" }; + let instance = builder.instantiate({ "m": { "exn": exception }}); + + assertSame(exception, instance.exports.push_and_return_except_ref()); +})(); diff --git a/deps/v8/test/mjsunit/wasm/exceptions-interpreter.js b/deps/v8/test/mjsunit/wasm/exceptions-interpreter.js new file mode 100644 index 0000000000..9393aade0f --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/exceptions-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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 --experimental-wasm-eh --allow-natives-syntax +// Flags: --wasm-interpret-all + +// This is just a wrapper for existing exception handling test cases that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/exceptions.js"); diff --git a/deps/v8/test/mjsunit/wasm/exceptions-rethrow-interpreter.js b/deps/v8/test/mjsunit/wasm/exceptions-rethrow-interpreter.js new file mode 100644 index 0000000000..42285ba169 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/exceptions-rethrow-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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 --experimental-wasm-eh --allow-natives-syntax +// Flags: --wasm-interpret-all + +// This is just a wrapper for existing exception handling test cases that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/exceptions-rethrow.js"); diff --git a/deps/v8/test/mjsunit/wasm/exceptions-simd-interpreter.js b/deps/v8/test/mjsunit/wasm/exceptions-simd-interpreter.js new file mode 100644 index 0000000000..7fd4e60032 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/exceptions-simd-interpreter.js @@ -0,0 +1,12 @@ +// Copyright 2019 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 --experimental-wasm-eh --experimental-wasm-simd --allow-natives-syntax +// Flags: --wasm-interpret-all + +// This is just a wrapper for existing exception handling test cases that runs +// with the --wasm-interpret-all flag added. If we ever decide to add a test +// variant for this, then we can remove this file. + +load("test/mjsunit/wasm/exceptions-simd.js"); diff --git a/deps/v8/test/mjsunit/wasm/futex.js b/deps/v8/test/mjsunit/wasm/futex.js index 640334bbc6..00353d48b0 100644 --- a/deps/v8/test/mjsunit/wasm/futex.js +++ b/deps/v8/test/mjsunit/wasm/futex.js @@ -9,7 +9,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); -function WasmAtomicWake(memory, offset, index, num) { +function WasmAtomicNotify(memory, offset, index, num) { let builder = new WasmModuleBuilder(); builder.addImportedMemory("m", "memory", 0, 20, "shared"); builder.addFunction("main", kSig_i_ii) @@ -17,7 +17,7 @@ function WasmAtomicWake(memory, offset, index, num) { kExprGetLocal, 0, kExprGetLocal, 1, kAtomicPrefix, - kExprAtomicWake, /* alignment */ 0, offset]) + kExprAtomicNotify, /* alignment */ 0, offset]) .exportAs("main"); // Instantiate module, get function exports @@ -84,7 +84,7 @@ function WasmI64AtomicWait(memory, offset, index, val_low, // Valid indexes are 0-65535 (1 page). [-2, 65536, 0xffffffff].forEach(function(invalidIndex) { assertThrows(function() { - WasmAtomicWake(memory, 0, invalidIndex, -1); + WasmAtomicNotify(memory, 0, invalidIndex, -1); }, Error); assertThrows(function() { WasmI32AtomicWait(memory, 0, invalidIndex, 0, -1); @@ -93,7 +93,7 @@ function WasmI64AtomicWait(memory, offset, index, val_low, WasmI64AtomicWait(memory, 0, invalidIndex, 0, 0, -1); }, Error); assertThrows(function() { - WasmAtomicWake(memory, invalidIndex, 0, -1); + WasmAtomicNotify(memory, invalidIndex, 0, -1); }, Error); assertThrows(function() { WasmI32AtomicWait(memory, invalidIndex, 0, 0, -1); @@ -102,7 +102,7 @@ function WasmI64AtomicWait(memory, offset, index, val_low, WasmI64AtomicWait(memory, invalidIndex, 0, 0, 0, -1); }, Error); assertThrows(function() { - WasmAtomicWake(memory, invalidIndex/2, invalidIndex/2, -1); + WasmAtomicNotify(memory, invalidIndex/2, invalidIndex/2, -1); }, Error); assertThrows(function() { WasmI32AtomicWait(memory, invalidIndex/2, invalidIndex/2, 0, -1); @@ -119,10 +119,10 @@ function WasmI64AtomicWait(memory, offset, index, val_low, // Wait and wake must be 4 byte aligned. [1, 2, 3].forEach(function(invalid) { assertThrows(function() { - WasmAtomicWake(memory, invalid, 0, -1) + WasmAtomicNotify(memory, invalid, 0, -1) }, Error); assertThrows(function() { - WasmAtomicWake(memory, 0, invalid, -1) + WasmAtomicNotify(memory, 0, invalid, -1) }, Error); assertThrows(function() { WasmI32AtomicWait(memory, invalid, 0, 0, -1) @@ -196,7 +196,7 @@ function WasmI64AtomicWait(memory, offset, index, val_low, let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true}); [-1, 0, 4, 100, 0xffffffff].forEach(function(count) { - WasmAtomicWake(memory, 0, 0, count); + WasmAtomicNotify(memory, 0, 0, count); }); })(); @@ -299,13 +299,13 @@ if (this.Worker) { if (num >= numWorkers) { // if numWorkers or more is passed to wake, numWorkers workers should be // woken. - assertEquals(numWorkers, WasmAtomicWake(memory, 0, index, num)); + assertEquals(numWorkers, WasmAtomicNotify(memory, 0, index, num)); } else { // if num < numWorkers is passed to wake, num workers should be woken. // Then the remaining workers are woken for the next part - assertEquals(num, WasmAtomicWake(memory, 0, index, num)); + assertEquals(num, WasmAtomicNotify(memory, 0, index, num)); assertEquals(numWorkers-num, - WasmAtomicWake(memory, 0, index, numWorkers)); + WasmAtomicNotify(memory, 0, index, numWorkers)); } for (let id = 0; id < numWorkers; id++) { assertEquals(msg, workers[id].getMessage()); diff --git a/deps/v8/test/mjsunit/wasm/grow-shared-memory.js b/deps/v8/test/mjsunit/wasm/grow-shared-memory.js new file mode 100644 index 0000000000..bbd180b39c --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/grow-shared-memory.js @@ -0,0 +1,348 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO(v8:8832): Enable --stress-opt on these tests +// Flags: --wasm-grow-shared-memory +// Flags: --experimental-wasm-threads --no-stress-opt + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +(function TestGrowSharedMemoryWithoutPostMessage() { + print(arguments.callee.name); + let memory = new WebAssembly.Memory({initial: 1, maximum: 5, shared: true}); + assertEquals(memory.buffer.byteLength, kPageSize); + assertEquals(1, memory.grow(1)); + assertEquals(memory.buffer.byteLength, 2 * kPageSize); +})(); + +function assertIsWasmSharedMemory(memory) { + assertTrue(memory instanceof Object, + "Memory is not an object"); + assertTrue(memory instanceof WebAssembly.Memory, + "Object is not WebAssembly.Memory" ); + assertTrue(memory.buffer instanceof SharedArrayBuffer, + "Memory.buffer is not a SharedArrayBuffer"); + assertTrue(Object.isFrozen(memory.buffer), + "Memory.buffer not frozen"); +} + +function assertTrue(value, msg) { + if (!value) { + postMessage("Error: " + msg); + throw new Error("Exit"); // To stop testing. + } +} + +let workerHelpers = assertTrue.toString() + assertIsWasmSharedMemory.toString(); + +(function TestPostMessageWithGrow() { + print(arguments.callee.name); + let worker = new Worker(workerHelpers + + `onmessage = function(obj) { + assertIsWasmSharedMemory(obj.memory); + assertTrue(1 === obj.memory.grow(1)); + assertTrue(obj.memory.buffer.byteLength === obj.expected_size); + assertIsWasmSharedMemory(obj.memory); + postMessage("OK"); + }`, {type: 'string'}); + + let memory = new WebAssembly.Memory({initial: 1, maximum: 5, shared: true}); + let obj = {memory: memory, expected_size: 2 * kPageSize}; + assertEquals(obj.memory.buffer.byteLength, kPageSize); + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + assertEquals(obj.memory.buffer.byteLength, 2 * kPageSize); + worker.terminate(); +})(); + + +// PostMessage from two different workers, and assert that the grow +// operations are performed on the same memory object. +(function TestWorkersWithGrowEarlyWorkerTerminate() { + print(arguments.callee.name); + let workerScript = workerHelpers + + `onmessage = function(obj) { + assertIsWasmSharedMemory(obj.memory); + obj.memory.grow(1); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === obj.expected_size); + postMessage("OK"); + };`; + + let workers = [new Worker(workerScript, {type: 'string'}), + new Worker(workerScript, {type: 'string'})]; + let memory = new WebAssembly.Memory({initial: 1, maximum: 5, shared: true}); + let expected_pages = 1; + for (let worker of workers) { + assertEquals(memory.buffer.byteLength, expected_pages++ * kPageSize); + let obj = {memory: memory, expected_size: expected_pages * kPageSize}; + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + assertEquals(memory.buffer.byteLength, expected_pages * kPageSize); + worker.terminate(); + } + assertEquals(memory.buffer.byteLength, expected_pages * kPageSize); +})(); + +// PostMessage of Multiple memories and grow +(function TestGrowSharedWithMultipleMemories() { + print(arguments.callee.name); + let workerScript = workerHelpers + + `onmessage = function(obj) { + let expected_size = 0; + let kPageSize = 0x10000; + for (let memory of obj.memories) { + assertIsWasmSharedMemory(memory); + assertTrue(expected_size === memory.grow(2)); + expected_size+=2; + assertIsWasmSharedMemory(memory); + assertTrue(memory.buffer.byteLength === expected_size * kPageSize); + } + postMessage("OK"); + };`; + + let worker = new Worker(workerScript, {type: 'string'}); + let memories = [new WebAssembly.Memory({initial: 0, maximum: 2, shared: true}), + new WebAssembly.Memory({initial: 2, maximum: 10, shared: true}), + new WebAssembly.Memory({initial: 4, maximum: 12, shared: true})]; + let obj = {memories: memories}; + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + assertEquals(2 * kPageSize, memories[0].buffer.byteLength); + assertEquals(4 * kPageSize, memories[1].buffer.byteLength); + assertEquals(6 * kPageSize, memories[2].buffer.byteLength); + worker.terminate(); +})(); + +// SharedMemory Object shared between different instances +(function TestPostMessageJSAndWasmInterop() { + print(arguments.callee.name); + let worker = new Worker(workerHelpers + + `onmessage = function(obj) { + let kPageSize = 0x10000; + assertIsWasmSharedMemory(obj.memory); + let instance = new WebAssembly.Instance( + obj.module, {m: {memory: obj.memory}}); + assertTrue(5 === obj.memory.grow(10)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 15 * kPageSize); + assertTrue(15 === instance.exports.grow(5)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 20 * kPageSize); + postMessage("OK"); + }`, {type: 'string'}); + + let memory = new WebAssembly.Memory({initial: 5, maximum: 50, shared: true}); + var builder = new WasmModuleBuilder(); + builder.addImportedMemory("m", "memory", 5, 100, "shared"); + builder.addFunction("grow", kSig_i_i) + .addBody([kExprGetLocal, 0, kExprMemoryGrow, kMemoryZero]) + .exportFunc(); + var module = new WebAssembly.Module(builder.toBuffer()); + let obj = {memory: memory, module: module}; + assertEquals(obj.memory.buffer.byteLength, 5 * kPageSize); + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + worker.terminate(); + assertEquals(obj.memory.buffer.byteLength, 20 * kPageSize); +})(); + +(function TestConsecutiveJSAndWasmSharedGrow() { + print(arguments.callee.name); + let worker = new Worker(workerHelpers + + `onmessage = function(obj) { + let kPageSize = 0x10000; + assertIsWasmSharedMemory(obj.memory); + let instance = new WebAssembly.Instance( + obj.module, {m: {memory: obj.memory}}); + assertTrue(5 === obj.memory.grow(10)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 15 * kPageSize); + assertTrue(15 === instance.exports.grow(5)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 20 * kPageSize); + postMessage("OK"); + }`, {type: 'string'}); + + let memory = new WebAssembly.Memory({initial: 5, maximum: 50, shared: true}); + var builder = new WasmModuleBuilder(); + builder.addImportedMemory("m", "memory", 5, 100, "shared"); + builder.addFunction("grow", kSig_i_i) + .addBody([kExprGetLocal, 0, kExprMemoryGrow, kMemoryZero]) + .exportFunc(); + var module = new WebAssembly.Module(builder.toBuffer()); + let obj = {memory: memory, module: module}; + assertEquals(obj.memory.buffer.byteLength, 5 * kPageSize); + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + assertEquals(obj.memory.buffer.byteLength, 20 * kPageSize); +})(); + +(function TestConsecutiveWasmSharedGrow() { + print(arguments.callee.name); + let worker = new Worker(workerHelpers + + `onmessage = function(obj) { + let kPageSize = 0x10000; + assertIsWasmSharedMemory(obj.memory); + let instance = new WebAssembly.Instance( + obj.module, {m: {memory: obj.memory}}); + assertTrue(5 === obj.memory.grow(10)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 15 * kPageSize); + assertTrue(17 === instance.exports.grow_twice(2)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 19 * kPageSize); + postMessage("OK"); + }`, {type: 'string'}); + + let memory = new WebAssembly.Memory({initial: 5, maximum: 50, shared: true}); + var builder = new WasmModuleBuilder(); + builder.addImportedMemory("m", "memory", 5, 100, "shared"); + builder.addFunction("grow_twice", kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprMemoryGrow, kMemoryZero, + kExprDrop, + kExprGetLocal, 0, + kExprMemoryGrow, kMemoryZero]) + .exportFunc(); + var module = new WebAssembly.Module(builder.toBuffer()); + let obj = {memory: memory, module: module}; + assertEquals(obj.memory.buffer.byteLength, 5 * kPageSize); + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + assertEquals(obj.memory.buffer.byteLength, 19 * kPageSize); + let instance = new WebAssembly.Instance(module, {m: {memory: memory}}); + assertEquals(21, instance.exports.grow_twice(2)); + assertEquals(obj.memory.buffer.byteLength, 23 * kPageSize); +})(); + +(function TestConsecutiveSharedGrowAndMemorySize() { + print(arguments.callee.name); + let worker = new Worker(workerHelpers + + `onmessage = function(obj) { + let kPageSize = 0x10000; + assertIsWasmSharedMemory(obj.memory); + let instance = new WebAssembly.Instance( + obj.module, {m: {memory: obj.memory}}); + assertTrue(5 === obj.memory.grow(10)); + assertTrue(15 === instance.exports.memory_size()); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 15 * kPageSize); + assertTrue(19 === instance.exports.grow_and_size(2)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 19 * kPageSize); + postMessage("OK"); + }`, {type: 'string'}); + + let memory = new WebAssembly.Memory({initial: 5, maximum: 50, shared: true}); + var builder = new WasmModuleBuilder(); + builder.addImportedMemory("m", "memory", 5, 100, "shared"); + builder.addFunction("grow_and_size", kSig_i_i) + .addBody([kExprGetLocal, 0, + kExprMemoryGrow, kMemoryZero, + kExprDrop, + kExprGetLocal, 0, + kExprMemoryGrow, kMemoryZero, + kExprDrop, + kExprMemorySize, kMemoryZero]) + .exportFunc(); + builder.addFunction("memory_size", kSig_i_v) + .addBody([kExprMemorySize, kMemoryZero]) + .exportFunc(); + var module = new WebAssembly.Module(builder.toBuffer()); + let obj = {memory: memory, module: module}; + assertEquals(obj.memory.buffer.byteLength, 5 * kPageSize); + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + assertEquals(memory.buffer.byteLength, 19 * kPageSize); + let instance = new WebAssembly.Instance(module, {m: {memory: memory}}); + assertEquals(23, instance.exports.grow_and_size(2)); + assertEquals(obj.memory.buffer.byteLength, 23 * kPageSize); + assertEquals(23, memory.grow(2)); + assertEquals(25, instance.exports.memory_size()); +})(); + +// Only spot checking here because currently the underlying buffer doesn't move. +// In the case that the underlying buffer does move, more comprehensive memory +// integrity checking and bounds checks testing are needed. +(function TestSpotCheckMemoryWithSharedGrow() { + print(arguments.callee.name); + let worker = new Worker(workerHelpers + + `onmessage = function(obj) { + let kPageSize = 0x10000; + assertIsWasmSharedMemory(obj.memory); + let instance = new WebAssembly.Instance( + obj.module, {m: {memory: obj.memory}}); + assertTrue(5 === obj.memory.grow(10)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 15 * kPageSize); + // Store again, and verify that the previous stores are still reflected. + instance.exports.atomic_store(15 * kPageSize - 4, 0xACED); + assertTrue(0xACED === instance.exports.atomic_load(0)); + assertTrue(0xACED === instance.exports.atomic_load(5 * kPageSize - 4)); + assertTrue(0xACED === instance.exports.atomic_load(15 * kPageSize - 4)); + assertTrue(15 === instance.exports.grow(2)); + assertIsWasmSharedMemory(obj.memory); + assertTrue(obj.memory.buffer.byteLength === 17 * kPageSize); + // Validate previous writes. + instance.exports.atomic_store(17 * kPageSize - 4, 0xACED); + assertTrue(0xACED === instance.exports.atomic_load(0)); + assertTrue(0xACED === instance.exports.atomic_load(5 * kPageSize - 4)); + assertTrue(0xACED === instance.exports.atomic_load(15 * kPageSize - 4)); + assertTrue(0xACED === instance.exports.atomic_load(17 * kPageSize - 4)); + postMessage("OK"); + }`, {type: 'string'}); + + let memory = new WebAssembly.Memory({initial: 5, maximum: 50, shared: true}); + var builder = new WasmModuleBuilder(); + builder.addImportedMemory("m", "memory", 5, 100, "shared"); + builder.addFunction("grow", kSig_i_i) + .addBody([kExprGetLocal, 0, kExprMemoryGrow, kMemoryZero]) + .exportFunc(); + builder.addFunction("atomic_load", kSig_i_i) + .addBody([kExprGetLocal, 0, kAtomicPrefix, kExprI32AtomicLoad, 2, 0]) + .exportFunc(); + builder.addFunction("atomic_store", kSig_v_ii) + .addBody([kExprGetLocal, 0, kExprGetLocal, 1, + kAtomicPrefix, kExprI32AtomicStore, 2, 0]) + .exportFunc(); + var module = new WebAssembly.Module(builder.toBuffer()); + let instance = new WebAssembly.Instance(module, {m: {memory: memory}}); + // Store at first and last accessible 32 bit offset. + instance.exports.atomic_store(0, 0xACED); + instance.exports.atomic_store(5 * kPageSize - 4, 0xACED); + // Verify that these were stored. + assertEquals(0xACED, instance.exports.atomic_load(0)); + assertEquals(0xACED, instance.exports.atomic_load(5 * kPageSize - 4)); + // Verify bounds. + assertTraps(kTrapMemOutOfBounds, + () => instance.exports.atomic_load(5 * kPageSize - 3)); + let obj = {memory: memory, module: module}; + assertEquals(obj.memory.buffer.byteLength, 5 * kPageSize); + // PostMessage + worker.postMessage(obj); + assertEquals("OK", worker.getMessage()); + assertEquals(memory.buffer.byteLength, 17 * kPageSize); + assertEquals(17, instance.exports.grow(2)); + assertEquals(obj.memory.buffer.byteLength, 19 * kPageSize); + // Validate previous writes, and check bounds. + assertTrue(0xACED === instance.exports.atomic_load(0)); + assertTrue(0xACED === instance.exports.atomic_load(5 * kPageSize - 4)); + assertTrue(0xACED === instance.exports.atomic_load(15 * kPageSize - 4)); + assertTrue(0xACED === instance.exports.atomic_load(17 * kPageSize - 4)); + assertTraps(kTrapMemOutOfBounds, + () => instance.exports.atomic_load(19 * kPageSize - 3)); + assertEquals(19, memory.grow(6)); + assertEquals(obj.memory.buffer.byteLength, 25 * kPageSize); + assertTraps(kTrapMemOutOfBounds, + () => instance.exports.atomic_load(25 * kPageSize - 3)); +})(); + +(function TestMemoryBufferTypeAfterGrow() { + const memory = new WebAssembly.Memory({ + "initial": 1, "maximum": 2, "shared": true }); + assertInstanceof(memory.buffer, SharedArrayBuffer); + assertEquals(memory.grow(1), 1); + assertInstanceof(memory.buffer, SharedArrayBuffer); +})(); diff --git a/deps/v8/test/mjsunit/wasm/import-table.js b/deps/v8/test/mjsunit/wasm/import-table.js index b5a756aa4b..a7e347b37c 100644 --- a/deps/v8/test/mjsunit/wasm/import-table.js +++ b/deps/v8/test/mjsunit/wasm/import-table.js @@ -41,8 +41,8 @@ let kTableSize = 50; let f17 = addConstFunc(builder, 17); builder.addExport("f15", f15); builder.addExport("f17", f17); - builder.addElementSegment(15, false, [f15], true); - builder.addElementSegment(1, false, [call.index], true); + builder.addElementSegment(0, 15, false, [f15], true); + builder.addElementSegment(0, 1, false, [call.index], true); var mod1 = builder.toModule(); } @@ -62,10 +62,10 @@ let kTableSize = 50; ]) .exportAs("call"); let f26 = addConstFunc(builder, 26); - builder.addElementSegment(17, false, [f17], true); - builder.addElementSegment(21, false, [f21], true); - builder.addElementSegment(26, false, [f26], true); - builder.addElementSegment(5, false, [call.index], true); + builder.addElementSegment(0, 17, false, [f17], true); + builder.addElementSegment(0, 21, false, [f21], true); + builder.addElementSegment(0, 26, false, [f26], true); + builder.addElementSegment(0, 5, false, [call.index], true); var mod2 = builder.toModule(); } @@ -113,8 +113,8 @@ function addConstFuncUsingGlobal(builder, val) { let f18 = addConstFuncUsingGlobal(builder, 18); builder.addExport("f14", f14); builder.addExport("f18", f18); - builder.addElementSegment(14, false, [f14], true); - builder.addElementSegment(1, false, [call.index], true); + builder.addElementSegment(0, 14, false, [f14], true); + builder.addElementSegment(0, 1, false, [call.index], true); var mod1 = builder.toModule(); } @@ -134,10 +134,10 @@ function addConstFuncUsingGlobal(builder, val) { ]) .exportAs("call"); let f28 = addConstFuncUsingGlobal(builder, 28); - builder.addElementSegment(18, false, [f18], true); - builder.addElementSegment(22, false, [f22], true); - builder.addElementSegment(28, false, [f28], true); - builder.addElementSegment(5, false, [call.index], true); + builder.addElementSegment(0, 18, false, [f18], true); + builder.addElementSegment(0, 22, false, [f22], true); + builder.addElementSegment(0, 28, false, [f28], true); + builder.addElementSegment(0, 5, false, [call.index], true); var mod2 = builder.toModule(); } @@ -193,8 +193,8 @@ function addConstFuncUsingMemory(builder, val) { let f19 = addConstFuncUsingMemory(builder, 19); builder.addExport("f13", f13); builder.addExport("f19", f19); - builder.addElementSegment(13, false, [f13], true); - builder.addElementSegment(1, false, [call.index], true); + builder.addElementSegment(0, 13, false, [f13], true); + builder.addElementSegment(0, 1, false, [call.index], true); var mod1 = builder.toModule(); } @@ -216,10 +216,10 @@ function addConstFuncUsingMemory(builder, val) { ]) .exportAs("call"); let f29 = addConstFuncUsingMemory(builder, 29); - builder.addElementSegment(19, false, [f19], true); - builder.addElementSegment(23, false, [f23], true); - builder.addElementSegment(29, false, [f29], true); - builder.addElementSegment(5, false, [call.index], true); + builder.addElementSegment(0, 19, false, [f19], true); + builder.addElementSegment(0, 23, false, [f23], true); + builder.addElementSegment(0, 29, false, [f29], true); + builder.addElementSegment(0, 5, false, [call.index], true); var mod2 = builder.toModule(); } diff --git a/deps/v8/test/mjsunit/wasm/indirect-call-non-zero-table.js b/deps/v8/test/mjsunit/wasm/indirect-call-non-zero-table.js new file mode 100644 index 0000000000..d4947313b3 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/indirect-call-non-zero-table.js @@ -0,0 +1,202 @@ +// Copyright 2019 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 --experimental-wasm-anyref --experimental-wasm-return-call + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +(function IndirectCallToNonZeroTable() { + print(arguments.callee.name); + + const builder = new WasmModuleBuilder(); + const placeholder = builder.addTable(kWasmAnyFunc, 3).index; + const table1 = builder.addTable(kWasmAnyFunc, 3).index; + const table2 = builder.addTable(kWasmAnyFunc, 5).index; + const sig_index = builder.addType(kSig_i_v); + const other_sig = builder.addType(kSig_i_i); + + const v1 = 16; + const v2 = 26; + const v3 = 36; + const v4 = 46; + const v5 = 56; + + const f_unreachable = builder.addFunction('unreachable', sig_index) + .addBody([kExprUnreachable]).index; + const f1 = builder.addFunction('f1', sig_index) + .addBody([kExprI32Const, v1]) + .index; + const f2 = builder.addFunction('f2', sig_index) + .addBody([kExprI32Const, v2]) + .index; + const f3 = builder.addFunction('f3', sig_index) + .addBody([kExprI32Const, v3]) + .index; + const f4 = builder.addFunction('f4', sig_index) + .addBody([kExprI32Const, v4]) + .index; + const f5 = builder.addFunction('f5', sig_index) + .addBody([kExprI32Const, v5]) + .index; + + builder.addFunction('call1', kSig_i_i) + .addBody([kExprGetLocal, 0, // function index + kExprCallIndirect, sig_index, table1]) + .exportAs('call1'); + builder.addFunction('return_call1', kSig_i_i) + .addBody([kExprGetLocal, 0, // function index + kExprReturnCallIndirect, sig_index, table1]) + .exportAs('return_call1'); + builder.addFunction('call2', kSig_i_i) + .addBody([kExprGetLocal, 0, // function index + kExprCallIndirect, sig_index, table2]) + .exportAs('call2'); + builder.addFunction('return_call2', kSig_i_i) + .addBody([kExprGetLocal, 0, // function index + kExprReturnCallIndirect, sig_index, table2]) + .exportAs('return_call2'); + + builder.addFunction('call_invalid_sig', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGetLocal, 0, // function index + param + kExprCallIndirect, other_sig, table2]) + .exportAs('call_invalid_sig'); + builder.addFunction('return_call_invalid_sig', kSig_i_i) + .addBody([kExprGetLocal, 0, kExprGetLocal, 0, // function index + param + kExprReturnCallIndirect, other_sig, table2]) + .exportAs('return_call_invalid_sig'); + + // We want to crash if we call through the table with index 0. + builder.addElementSegment(placeholder, 0, false, + [f_unreachable, f_unreachable, f_unreachable], false); + builder.addElementSegment(table1, 0, false, [f1, f2, f3], false); + // Keep one slot in table2 uninitialized. We should trap if we call it. + builder.addElementSegment(table2, 1, false, + [f_unreachable, f_unreachable, f4, f5], false); + + const instance = builder.instantiate(); + + assertEquals(v1, instance.exports.call1(0)); + assertEquals(v2, instance.exports.call1(1)); + assertEquals(v3, instance.exports.call1(2)); + assertTraps(kTrapFuncInvalid, () => instance.exports.call1(3)); + assertEquals(v1, instance.exports.return_call1(0)); + assertEquals(v2, instance.exports.return_call1(1)); + assertEquals(v3, instance.exports.return_call1(2)); + assertTraps(kTrapFuncInvalid, () => instance.exports.return_call1(3)); + + // Try to call through the uninitialized table entry. + assertTraps(kTrapFuncSigMismatch, () => instance.exports.call2(0)); + assertEquals(v4, instance.exports.call2(3)); + assertEquals(v5, instance.exports.call2(4)); + assertTraps(kTrapFuncSigMismatch, + () => instance.exports.call_invalid_sig(4)); + assertTraps(kTrapFuncSigMismatch, () => instance.exports.return_call2(0)); + assertEquals(v4, instance.exports.return_call2(3)); + assertEquals(v5, instance.exports.return_call2(4)); + assertTraps(kTrapFuncSigMismatch, + () => instance.exports.return_call_invalid_sig(4)); +})(); + +(function IndirectCallToImportedNonZeroTable() { + print(arguments.callee.name); + + const table_size = 10; + const placeholder = new WebAssembly.Table( + { initial: table_size, maximum: table_size, element: "anyfunc" }); + const table = new WebAssembly.Table( + { initial: table_size, maximum: table_size, element: "anyfunc" }); + + const builder = new WasmModuleBuilder(); + builder.addImportedTable("m", "placeholder", table_size, table_size); + const t1 = builder.addImportedTable("m", "table", table_size, table_size); + + // We initialize the module twice and put the function f1 in the table at + // the index defined by {g}. Thereby we can initialize the table at different + // slots for different instances. The function f1 also returns {g} so that we + // can see that actually different functions get called. + const g = builder.addImportedGlobal("m", "base", kWasmI32); + + const sig_index = builder.addType(kSig_i_v); + const f1 = builder.addFunction("foo", sig_index) + .addBody([kExprGetGlobal, g, kExprI32Const, 12, kExprI32Add]); + + builder.addFunction('call', kSig_i_i) + .addBody([kExprGetLocal, 0, // function index + kExprCallIndirect, sig_index, t1]) + .exportAs('call'); + + builder.addElementSegment(t1, g, true, [f1.index], true); + const base1 = 3; + const base2 = 5; + + const instance1 = builder.instantiate({ + m: { + placeholder: placeholder, + table: table, + base: base1 + } + }); + + const instance2 = builder.instantiate({ + m: { + placeholder: placeholder, + table: table, + base: base2 + } + }); + + assertEquals(base1 + 12, instance1.exports.call(base1)); + assertEquals(base2 + 12, instance1.exports.call(base2)); + assertEquals(base1 + 12, instance2.exports.call(base1)); + assertEquals(base2 + 12, instance2.exports.call(base2)); +})(); + +function js_div(a, b) { return (a / b) | 0; } + +(function CallImportedFunction() { + let kTableSize = 10; + print(arguments.callee.name); + + var builder = new WasmModuleBuilder(); + + let div = builder.addImport("q", "js_div", kSig_i_ii); + builder.addImportedTable("q", "placeholder", kTableSize, kTableSize); + let table_index = builder.addImportedTable("q", "table", kTableSize, kTableSize); + let g = builder.addImportedGlobal("q", "base", kWasmI32); + + let sig_index = builder.addType(kSig_i_ii); + builder.addFunction("placeholder", sig_index) + .addBody([kExprGetLocal, 0]); + + builder.addElementSegment(table_index, g, true, [div]); + builder.addFunction("main", kSig_i_ii) + .addBody([ + kExprI32Const, 55, // -- + kExprGetLocal, 0, // -- + kExprGetLocal, 1, // -- + kExprCallIndirect, 0, table_index]) // -- + .exportAs("main"); + + let m = new WebAssembly.Module(builder.toBuffer()); + + let table = new WebAssembly.Table({ + element: "anyfunc", + initial: kTableSize, + maximum: kTableSize + }); + let placeholder = new WebAssembly.Table({ + element: "anyfunc", + initial: kTableSize, + maximum: kTableSize + }); + + let instance = new WebAssembly.Instance(m, { + q: { + base: 0, table: table, placeholder: placeholder, + js_div: js_div + } + }); + + assertEquals(13, instance.exports.main(4, 0)); +})(); diff --git a/deps/v8/test/mjsunit/wasm/indirect-calls.js b/deps/v8/test/mjsunit/wasm/indirect-calls.js index 067d6884d7..e9f560a019 100644 --- a/deps/v8/test/mjsunit/wasm/indirect-calls.js +++ b/deps/v8/test/mjsunit/wasm/indirect-calls.js @@ -169,7 +169,7 @@ function AddFunctions(builder) { .exportAs("main"); builder.setTableBounds(length, length); - builder.addElementSegment(base, false, [f.add.index, f.sub.index, f.mul.index]); + builder.addElementSegment(0, base, false, [f.add.index, f.sub.index, f.mul.index]); return builder.instantiate(); } @@ -207,7 +207,7 @@ function AddFunctions(builder) { builder.setTableBounds(10, 10); var g = builder.addImportedGlobal("fff", "base", kWasmI32); - builder.addElementSegment(g, true, [f.mul.index, f.add.index, f.sub.index]); + builder.addElementSegment(0, g, true, [f.mul.index, f.add.index, f.sub.index]); var module = new WebAssembly.Module(builder.toBuffer()); diff --git a/deps/v8/test/mjsunit/wasm/indirect-tables.js b/deps/v8/test/mjsunit/wasm/indirect-tables.js index c4edd71f14..b07f09e108 100644 --- a/deps/v8/test/mjsunit/wasm/indirect-tables.js +++ b/deps/v8/test/mjsunit/wasm/indirect-tables.js @@ -51,7 +51,7 @@ function js_div(a, b) { return (a / b) | 0; } builder.setTableBounds(10, 10); let g = builder.addImportedGlobal("q", "base", kWasmI32); builder.addElementSegment( - g, true, [f.mul.index, f.add.index, f.sub.index, d]); + 0, g, true, [f.mul.index, f.add.index, f.sub.index, d]); builder.addExportOfKind("table", kExternalTable, 0); let module = new WebAssembly.Module(builder.toBuffer()); @@ -110,7 +110,7 @@ function js_div(a, b) { return (a / b) | 0; } builder.setTableBounds(kTableSize, kTableSize); let g = builder.addImportedGlobal("q", "base", kWasmI32); builder.addElementSegment( - g, true, [f.mul.index, f.add.index, f.sub.index, d]); + 0, g, true, [f.mul.index, f.add.index, f.sub.index, d]); builder.addExportOfKind("table", kExternalTable, 0); let m1 = new WebAssembly.Module(builder.toBuffer()); @@ -180,7 +180,7 @@ function js_div(a, b) { return (a / b) | 0; } let g = builder.addImportedGlobal("q", "base", kWasmI32); let f = AddFunctions(builder); builder.addElementSegment( - g, true, [f.mul.index, f.add.index, f.sub.index, d]); + 0, g, true, [f.mul.index, f.add.index, f.sub.index, d]); builder.addFunction("main", kSig_i_ii) .addBody([ kExprI32Const, 55, // -- @@ -256,7 +256,7 @@ function js_div(a, b) { return (a / b) | 0; } kExprGetLocal, 0, kExprCallIndirect, sig_index, kTableZero]) // -- .exportAs("main"); - builder.addElementSegment(g, true, [f.index]); + builder.addElementSegment(0, g, true, [f.index]); let module = new WebAssembly.Module(builder.toBuffer()); @@ -297,7 +297,7 @@ function js_div(a, b) { return (a / b) | 0; } .exportAs("main"); builder.setTableBounds(kTableSize, kTableSize); - builder.addElementSegment(0, false, [f1.index]); + builder.addElementSegment(0, 0, false, [f1.index]); builder.addExportOfKind("table", kExternalTable, 0); var m1 = new WebAssembly.Module(builder.toBuffer()); @@ -316,7 +316,7 @@ function js_div(a, b) { return (a / b) | 0; } .exportAs("main"); builder.addImportedTable("z", "table", kTableSize, kTableSize); - builder.addElementSegment(1, false, [f2.index], true); + builder.addElementSegment(0, 1, false, [f2.index], true); var m2 = new WebAssembly.Module(builder.toBuffer()); @@ -411,7 +411,7 @@ function js_div(a, b) { return (a / b) | 0; } kExprGetLocal, 0, kExprCallIndirect, sig_index, kTableZero]) // -- .exportAs("main"); - builder.addElementSegment(g, true, [g]); + builder.addElementSegment(0, g, true, [g]); let module = new WebAssembly.Module(builder.toBuffer()); var instances = []; @@ -542,7 +542,7 @@ function js_div(a, b) { return (a / b) | 0; } let offset = i + 1; let len = i + 2; let index = indexes[i]; - builder.addElementSegment(offset, false, new Array(len).fill(index)); + builder.addElementSegment(0, offset, false, new Array(len).fill(index)); } let instance = builder.instantiate(); @@ -586,7 +586,7 @@ function js_div(a, b) { return (a / b) | 0; } builder1.setName('module_1'); builder1.addFunction('f', kSig_i_i).addBody([kExprGetLocal, 0]); builder1.addImportedTable('z', 'table'); - builder1.addElementSegment(0, false, [0], true); + builder1.addElementSegment(0, 0, false, [0], true); let module1 = new WebAssembly.Module(builder1.toBuffer()); let instance1 = new WebAssembly.Instance(module1, {z: {table: instance0.exports.table}}); @@ -624,7 +624,7 @@ function js_div(a, b) { return (a / b) | 0; } builder = new WasmModuleBuilder(); builder.addFunction('main', kSig_i_v).addBody([kExprI32Const, 0, kExprI32LoadMem, 0, 0]); builder.addImportedTable('', 'table'); - builder.addElementSegment(0, false, [0], true); + builder.addElementSegment(0, 0, false, [0], true); builder.addImportedMemory('', 'memory', 1); @@ -732,7 +732,7 @@ function js_div(a, b) { return (a / b) | 0; } builder.setTableBounds(10, 10); let g = builder.addImportedGlobal("q", "base", kWasmI32); - builder.addElementSegment(g, true, [j, w]); + builder.addElementSegment(0, g, true, [j, w]); let module = new WebAssembly.Module(builder.toBuffer()); for (var i = 0; i < 5; i++) { @@ -781,7 +781,7 @@ function js_div(a, b) { return (a / b) | 0; } .exportAs("main"); let g = builder.addImportedGlobal("q", "base", kWasmI32); - builder.addElementSegment(g, true, [j, w]); + builder.addElementSegment(0, g, true, [j, w]); let module = new WebAssembly.Module(builder.toBuffer()); for (var i = 0; i < 5; i++) { @@ -820,7 +820,7 @@ function js_div(a, b) { return (a / b) | 0; } kExprCallIndirect, 0, kTableZero ]) .exportFunc(); - builder.addElementSegment(0, false, [0, 1, 1, 0]); + builder.addElementSegment(0, 0, false, [0, 1, 1, 0]); return builder.instantiate({q: {f2: i1.exports.f2, f1: i1.exports.f1}}); })(); @@ -882,7 +882,7 @@ function js_div(a, b) { return (a / b) | 0; } ]) .exportFunc(); builder.exportMemoryAs("memory"); - builder.addElementSegment(0, false, [0, 1, 2, 3]); + builder.addElementSegment(0, 0, false, [0, 1, 2, 3]); var instance = builder.instantiate({q: {f1: f100, f2: f200, f3: f300}}); setMemI32(instance, 0, 5000000); setMemI32(instance, 4, 6000000); diff --git a/deps/v8/test/mjsunit/wasm/interpreter.js b/deps/v8/test/mjsunit/wasm/interpreter.js index c11e593115..aa479ac0b0 100644 --- a/deps/v8/test/mjsunit/wasm/interpreter.js +++ b/deps/v8/test/mjsunit/wasm/interpreter.js @@ -537,7 +537,7 @@ function checkStack(stack, expected_lines) { const builder1 = new WasmModuleBuilder(); builder1.addFunction('main', kSig_i_v).addBody([kExprUnreachable]); builder1.addImportedTable('z', 'table'); - builder1.addElementSegment(0, false, [0], true); + builder1.addElementSegment(0, 0, false, [0], true); const module1 = new WebAssembly.Module(builder1.toBuffer()); const instance1 = new WebAssembly.Instance(module1, {z: {table: instance0.exports.table}}); diff --git a/deps/v8/test/mjsunit/wasm/js-api.js b/deps/v8/test/mjsunit/wasm/js-api.js index efc0150992..6b7db744d3 100644 --- a/deps/v8/test/mjsunit/wasm/js-api.js +++ b/deps/v8/test/mjsunit/wasm/js-api.js @@ -641,9 +641,9 @@ assertEq(get.call(tbl1, 0), null); assertEq(get.call(tbl1, 0, Infinity), null); assertEq(get.call(tbl1, 1), null); assertEq(get.call(tbl1, 1.5), null); -assertThrows(() => get.call(tbl1, 2), RangeError, /Index out of bounds/); +assertThrows(() => get.call(tbl1, 2), RangeError, /invalid index \d+ into function table/); assertThrows( - () => get.call(tbl1, 2.5), RangeError, /Index out of bounds/); + () => get.call(tbl1, 2.5), RangeError, /invalid index \d+ into function table/); assertThrows(() => get.call(tbl1, -1), TypeError, /must be non-negative/); assertThrows( () => get.call(tbl1, Math.pow(2, 33)), TypeError, @@ -670,7 +670,7 @@ assertThrows( () => set.call(tbl1, undefined), TypeError, /must be convertible to a valid number/); assertThrows( - () => set.call(tbl1, 2, null), RangeError, /index out of bounds/); + () => set.call(tbl1, 2, null), RangeError, /invalid index \d+ into function table/); assertThrows( () => set.call(tbl1, -1, null), TypeError, /must be non-negative/); assertThrows( diff --git a/deps/v8/test/mjsunit/wasm/module-memory.js b/deps/v8/test/mjsunit/wasm/module-memory.js index 8bc96f7ea0..3dd580d269 100644 --- a/deps/v8/test/mjsunit/wasm/module-memory.js +++ b/deps/v8/test/mjsunit/wasm/module-memory.js @@ -178,7 +178,7 @@ function testAddressSpaceLimit() { // 1TiB + 4 GiB, see wasm-memory.h const kMaxAddressSpace = 1 * 1024 * 1024 * 1024 * 1024 + 4 * 1024 * 1024 * 1024; - const kAddressSpacePerMemory = 8 * 1024 * 1024 * 1024; + const kAddressSpacePerMemory = 10 * 1024 * 1024 * 1024; let last_memory; try { @@ -193,10 +193,7 @@ function testAddressSpaceLimit() { assertTrue(e instanceof RangeError); return; } - // If we get here it's because our fallback behavior is working. We may not - // be using the fallback, in which case we would have thrown a RangeError in - // the previous block. - assertTrue(!%WasmMemoryHasFullGuardRegion(last_memory)); + assertUnreachable("should have reached the address space limit"); } if(%IsWasmTrapHandlerEnabled()) { diff --git a/deps/v8/test/mjsunit/wasm/multi-table-element-section.js b/deps/v8/test/mjsunit/wasm/multi-table-element-section.js new file mode 100644 index 0000000000..0c12c98bdc --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/multi-table-element-section.js @@ -0,0 +1,76 @@ +// Copyright 2019 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 --experimental-wasm-anyref + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +const value1 = 11; +const value2 = 22; +const value3 = 46; +const value4 = 57; +const value5 = 13; + +// The offsets for the initialization of tables. The segement for table2 should +// overlap with the segment of table1, because table2 is actually the imported +// table1. +const offset1 = 2; +const offset2 = offset1 + 1; +const offset3 = 4; +const offset4 = 1; + +const instance_for_import = (function() { + const builder_for_import = new WasmModuleBuilder(); + const t1 = builder_for_import.addTable(kWasmAnyFunc, 15, 15) + .exportAs("table").index; + const f1 = builder_for_import.addFunction('f1', kSig_i_v) + .addBody([kExprI32Const, value1]).index; + const f2 = builder_for_import.addFunction('f2', kSig_i_v) + .addBody([kExprI32Const, value2]).index; + + builder_for_import.addElementSegment(t1, offset1, false, [f1, f2], false); + const instance_for_import = builder_for_import.instantiate(); + const table1 = instance_for_import.exports.table; + assertEquals(value1, table1.get(offset1)()); + assertEquals(value2, table1.get(offset1 + 1)()); + return instance_for_import; +})(); + +const builder = new WasmModuleBuilder(); + +const t2 = builder.addImportedTable("exports", "table", 15, 15); +builder.addExportOfKind("table2", kExternalTable, t2); +const t3 = builder.addTable(kWasmAnyFunc, 10).exportAs("table3").index; +const t4 = builder.addTable(kWasmAnyFunc, 12).exportAs("table4").index; + +const f3 = builder.addFunction('f3', kSig_i_v) + .addBody([kExprI32Const, value3]).index; +const f4 = builder.addFunction('f4', kSig_i_v) + .addBody([kExprI32Const, value4]).index; +const f5 = builder.addFunction('f5', kSig_i_v) + .addBody([kExprI32Const, value5]).index; + + +builder.addElementSegment(t2, offset2, false, [f3, f4], false); +builder.addElementSegment(t3, offset3, false, [f5, f4], false); +builder.addElementSegment(t4, offset4, false, [f3, f5], false); +// Add one more overlapping offset +builder.addElementSegment(t4, offset4 + 1, false, [f4, f3], false); + +const instance = builder.instantiate(instance_for_import); +// table2 == table1 +const table2 = instance.exports.table2; +const table3 = instance.exports.table3; +const table4 = instance.exports.table4; +// table1 == table2 +assertEquals(value1, table2.get(offset1)()); +assertEquals(value3, table2.get(offset2)()); +assertEquals(value4, table2.get(offset2 + 1)()); + +assertEquals(value5, table3.get(offset3)()); +assertEquals(value4, table3.get(offset3 + 1)()); + +assertEquals(value3, table4.get(offset4)()); +assertEquals(value4, table4.get(offset4 + 1)()); +assertEquals(value3, table4.get(offset4 + 2)()); diff --git a/deps/v8/test/mjsunit/wasm/mutable-globals.js b/deps/v8/test/mjsunit/wasm/mutable-globals.js index 3ba22818d5..261da5669d 100644 --- a/deps/v8/test/mjsunit/wasm/mutable-globals.js +++ b/deps/v8/test/mjsunit/wasm/mutable-globals.js @@ -21,6 +21,10 @@ function assertGlobalIsValid(global) { assertThrows(() => new WebAssembly.Global({}), TypeError); assertThrows(() => new WebAssembly.Global({value: 'foo'}), TypeError); assertThrows(() => new WebAssembly.Global({value: 'i128'}), TypeError); + // Without --experimental-wasm-anyref, globals of type {anyref} and {anyfunc} + // are not allowed. + assertThrows(() => new WebAssembly.Global({value: 'anyref'}), TypeError); + assertThrows(() => new WebAssembly.Global({value: 'anyfunc'}), TypeError); for (let type of ['i32', 'f32', 'f64', 'i64']) { assertGlobalIsValid(new WebAssembly.Global({value: type})); diff --git a/deps/v8/test/mjsunit/wasm/return-calls.js b/deps/v8/test/mjsunit/wasm/return-calls.js new file mode 100644 index 0000000000..55b295d7a1 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/return-calls.js @@ -0,0 +1,159 @@ +// Copyright 2019 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 --experimental-wasm-return-call --stack-size=64 + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +(function TestFactorialReturnCall() { + print(arguments.callee.name); + + let builder = new WasmModuleBuilder(); + + const sig_i_iii = builder.addType(kSig_i_iii); + + // construct the code for the function + // f_aux(N,X) where N=<1 => X + // f_aux(N,X) => f_aux(N-1,X*N) + let fact_aux = builder.addFunction("fact_aux",kSig_i_ii); + fact_aux.addBody([ + kExprGetLocal, 0, kExprI32Const, 1, kExprI32LeS, + kExprIf, kWasmI32, + kExprGetLocal, 1, + kExprElse, + kExprGetLocal, 0, + kExprI32Const, 1, + kExprI32Sub, + kExprGetLocal, 0, + kExprGetLocal, 1, + kExprI32Mul, + kExprReturnCall, fact_aux.index, + kExprEnd + ]); + + //main(N)=>fact_aux(N,1) + let main = builder.addFunction("main", kSig_i_i) + .addBody([ + kExprGetLocal, 0, + kExprI32Const, 1, + kExprReturnCall,0 + ]).exportFunc(); + + let module = builder.instantiate(); + + print(" --three--"); + assertEquals(6, module.exports.main(3)); + print(" --four--"); + assertEquals(24, module.exports.main(4)); +})(); + +(function TestIndirectFactorialReturnCall() { + print(arguments.callee.name); + + let builder = new WasmModuleBuilder(); + + const sig_i_iii = builder.addType(kSig_i_iii); + + // construct the code for the function + // fact(N) => f_ind(N,1,f). + // + // f_ind(N,X,_) where N=<1 => X + // f_ind(N,X,F) => F(N-1,X*N,F). + + let f_ind = builder.addFunction("f_ind",kSig_i_iii). + addBody([ + kExprGetLocal, 0, kExprI32Const, 1, kExprI32LeS, + kExprIf, kWasmI32, + kExprGetLocal, 1, + kExprElse, + kExprGetLocal, 0, + kExprI32Const, 1, + kExprI32Sub, + kExprGetLocal, 0, + kExprGetLocal, 1, + kExprI32Mul, + kExprGetLocal, 2, + kExprGetLocal, 2, + kExprReturnCallIndirect, sig_i_iii, kTableZero, + kExprEnd + ]); + + //main(N)=>fact_aux(N,1) + let main = builder.addFunction("main", kSig_i_i) + .addBody([ + kExprGetLocal, 0, + kExprI32Const, 1, + kExprI32Const, f_ind.index, + kExprReturnCall, f_ind.index + ]).exportFunc(); + + builder.appendToTable([f_ind.index, main.index]); + + let module = builder.instantiate(); + + print(" --three--"); + assertEquals(6, module.exports.main(3)); + print(" --four--"); + assertEquals(24, module.exports.main(4)); +})(); + +(function TestImportReturnCall() { + print(arguments.callee.name); + + let builder = new WasmModuleBuilder(); + + const sig_i_iii = builder.addType(kSig_i_iii); + + let pick = builder.addImport("q", "pick", sig_i_iii); + + let main = builder.addFunction("main", kSig_i_iii) + .addBody([ + kExprGetLocal, 1, + kExprGetLocal, 2, + kExprGetLocal, 0, + kExprReturnCall, pick + ]) + .exportFunc(); + + let module = builder.instantiate({q: { + pick: function(a, b, c) { return c ? a : b; }}}); + + print(" --left--"); + assertEquals(-2, module.exports.main(1, -2, 3)); + print(" --right--"); + assertEquals(3, module.exports.main(0, -2, 3)); +})(); + +(function TestImportIndirectReturnCall() { + print(arguments.callee.name); + + let builder = new WasmModuleBuilder(); + + const sig_i_iii = builder.addType(kSig_i_iii); + + let pick = builder.addImport("q", "pick", sig_i_iii); + const tableIndex = 3; // Arbitrary location of import + + builder.addElementSegment(0, tableIndex,false,[pick]); + + let main = builder.addFunction("main", kSig_i_iii) + .addBody([ + kExprGetLocal, 1, + kExprGetLocal, 2, + kExprGetLocal, 0, + kExprI32Const, tableIndex, + kExprReturnCallIndirect, sig_i_iii, kTableZero + ]) + .exportFunc(); + builder.appendToTable([pick, main.index]); + + let module = builder.instantiate({q: { + pick: function(a, b, c) { return c ? a : b; } + }}); + + print(" --left--"); + assertEquals(-2, module.exports.main(1, -2, 3)); + print(" --right--"); + assertEquals(3, module.exports.main(0, -2, 3)); +})(); diff --git a/deps/v8/test/mjsunit/wasm/streaming-api.js b/deps/v8/test/mjsunit/wasm/streaming-api.js new file mode 100644 index 0000000000..e7ad3d6bfa --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/streaming-api.js @@ -0,0 +1,44 @@ +// Copyright 2019 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: --wasm-test-streaming + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +(function TestCompileStreaming() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction("main", kSig_i_i) + .addBody([kExprGetLocal, 0]) + .exportAs("main"); + let bytes = builder.toBuffer(); + assertPromiseResult(WebAssembly.compileStreaming(Promise.resolve(bytes)).then( + module => WebAssembly.instantiate(module)).then( + instance => assertEquals(5, instance.exports.main(5)))); +})(); + +(function TestInstantiateStreaming() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + builder.addFunction("main", kSig_i_i) + .addBody([kExprGetLocal, 0]) + .exportAs("main"); +let bytes = builder.toBuffer(); +assertPromiseResult(WebAssembly.instantiateStreaming(Promise.resolve(bytes)).then( + ({module, instance}) => assertEquals(5, instance.exports.main(5)))); +})(); + +(function TestCompileStreamingRejectedInputPromise() { + print(arguments.callee.name); + assertPromiseResult(WebAssembly.compileStreaming(Promise.reject("myError")), + assertUnreachable, + error => assertEquals(error, "myError")); +})(); + +(function TestInstantiateStreamingRejectedInputPromise() { + print(arguments.callee.name); + assertPromiseResult(WebAssembly.instantiateStreaming(Promise.reject("myError")), + assertUnreachable, + error => assertEquals(error, "myError")); +})(); diff --git a/deps/v8/test/mjsunit/wasm/streaming-error-position.js b/deps/v8/test/mjsunit/wasm/streaming-error-position.js index 266c134966..b6d008cd13 100644 --- a/deps/v8/test/mjsunit/wasm/streaming-error-position.js +++ b/deps/v8/test/mjsunit/wasm/streaming-error-position.js @@ -20,37 +20,26 @@ function module(bytes) { return new WebAssembly.Module(buffer); } -function toBuffer(binary) { - let buffer = new ArrayBuffer(binary.length); - let view = new Uint8Array(buffer); - for (let i = 0; i < binary.length; i++) { - let val = binary[i]; - if ((typeof val) == 'string') val = val.charCodeAt(0); - view[i] = val | 0; - } - return buffer; -} - function testErrorPosition(bytes, pos, test_name) { assertThrowsAsync( - WebAssembly.compile(toBuffer(bytes)), WebAssembly.CompileError, + WebAssembly.compile(bytes.trunc_buffer()), WebAssembly.CompileError, new RegExp('@\\+' + pos)); } (function testInvalidMagic() { let bytes = new Binary; - bytes.push( - kWasmH0, kWasmH1 + 1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, - kWasmV3); + bytes.emit_bytes([ + kWasmH0, kWasmH1 + 1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3 + ]); // Error at pos==0 because that's where the magic word is. testErrorPosition(bytes, 0, 'testInvalidMagic'); })(); (function testInvalidVersion() { let bytes = new Binary; - bytes.push( - kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1 + 1, kWasmV2, - kWasmV3); + bytes.emit_bytes([ + kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1 + 1, kWasmV2, kWasmV3 + ]); // Error at pos==4 because that's where the version word is. testErrorPosition(bytes, 4, 'testInvalidVersion'); })(); @@ -59,7 +48,7 @@ function testErrorPosition(bytes, pos, test_name) { let bytes = new Binary; bytes.emit_header(); bytes.emit_u8(kTypeSectionCode); - bytes.push(0x80, 0x80, 0x80, 0x80, 0x80, 0x00); + bytes.emit_bytes([0x80, 0x80, 0x80, 0x80, 0x80, 0x00]); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testSectionLengthInvalidVarint'); })(); @@ -76,22 +65,22 @@ function testErrorPosition(bytes, pos, test_name) { (function testFunctionsCountInvalidVarint() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 1, // section length 0 // number of types - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 1, // section length 0 // number of functions - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) - ); + ]); // Functions count - bytes.push(0x80, 0x80, 0x80, 0x80, 0x80, 0x00); + bytes.emit_bytes([0x80, 0x80, 0x80, 0x80, 0x80, 0x00]); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testFunctionsCountInvalidVarint'); @@ -100,20 +89,20 @@ function testErrorPosition(bytes, pos, test_name) { (function testFunctionsCountTooBig() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 1, // section length 0 // number of types - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 1, // section length 0 // number of functions - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) - ); + ]); // Functions count bytes.emit_u32v(0xffffff23); @@ -124,20 +113,20 @@ function testErrorPosition(bytes, pos, test_name) { (function testFunctionsCountDoesNotMatch() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 1, // section length 0 // number of types - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 1, // section length 0 // number of functions - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) - ); + ]); // Functions count (different than the count in the functions section. bytes.emit_u32v(5); @@ -148,27 +137,27 @@ function testErrorPosition(bytes, pos, test_name) { (function testBodySizeInvalidVarint() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count - ); + ]); // Invalid function body size. - bytes.push(0x80, 0x80, 0x80, 0x80, 0x80, 0x00); + bytes.emit_bytes([0x80, 0x80, 0x80, 0x80, 0x80, 0x00]); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testBodySizeInvalidVarint'); @@ -177,25 +166,25 @@ function testErrorPosition(bytes, pos, test_name) { (function testBodySizeTooBig() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count - ); + ]); // Invalid function body size. bytes.emit_u32v(0xffffff23); @@ -206,25 +195,25 @@ function testErrorPosition(bytes, pos, test_name) { (function testBodySizeDoesNotFit() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count - ); + ]); // Invalid function body size (does not fit into the code section). bytes.emit_u32v(20); @@ -235,25 +224,25 @@ function testErrorPosition(bytes, pos, test_name) { (function testBodySizeIsZero() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count - ); + ]); // Invalid function body size (body size of 0 is invalid). bytes.emit_u32v(0); @@ -264,28 +253,28 @@ function testErrorPosition(bytes, pos, test_name) { (function testStaleCodeSectionBytes() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 20, // section length (too big) 1, // functions count 2, // body size 0, // locals count kExprEnd // body - ); + ]); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testStaleCodeSectionBytes'); @@ -294,21 +283,21 @@ function testErrorPosition(bytes, pos, test_name) { (function testInvalidCode() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 6, // section length (too big) 1, // functions count @@ -316,7 +305,7 @@ function testErrorPosition(bytes, pos, test_name) { 0, // locals count kExprGetLocal, 0, // Access a non-existing local kExprEnd // -- - ); + ]); // Find error at the index of kExprGetLocal. let pos = bytes.length - 1 - 1; @@ -326,24 +315,24 @@ function testErrorPosition(bytes, pos, test_name) { (function testCodeSectionSizeZero() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns - ); - bytes.push( + ]); + bytes.emit_bytes([ kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index - ); - bytes.push( + ]); + bytes.emit_bytes([ kCodeSectionCode, // section id 0, // section length (too big) - ); + ]); // Find error at the index of kExprGetLocal. let pos = bytes.length - 1; @@ -353,7 +342,7 @@ function testErrorPosition(bytes, pos, test_name) { (function testInvalidSection() { let bytes = new Binary; bytes.emit_header(); - bytes.push( + bytes.emit_bytes([ kTypeSectionCode, // section id 5, // section length 1, // number of types @@ -361,7 +350,7 @@ function testErrorPosition(bytes, pos, test_name) { 1, // number of parameter 0x7b, // invalid type 0 // number of returns - ); + ]); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testInvalidSection'); diff --git a/deps/v8/test/mjsunit/wasm/table-access.js b/deps/v8/test/mjsunit/wasm/table-access.js new file mode 100644 index 0000000000..9a6f0ebc3a --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/table-access.js @@ -0,0 +1,129 @@ +// Copyright 2019 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 --experimental-wasm-anyref + +load("test/mjsunit/wasm/wasm-module-builder.js"); + +(function TestGetAndSet() { +function addTableWithAccessors(builder, type, size, name) { + const table = builder.addTable(type, size); + const set_sig = makeSig([kWasmI32, type], []); + builder.addFunction('set_' + name, set_sig) + .addBody([kExprGetLocal, 0, + kExprGetLocal, 1, + kExprSetTable, table.index]) + .exportFunc(); + + const get_sig = makeSig([kWasmI32], [type]); + builder.addFunction('get_' + name, get_sig) + .addBody([kExprGetLocal, 0, kExprGetTable, table.index]) + .exportFunc(); +} + +const builder = new WasmModuleBuilder(); + +addTableWithAccessors(builder, kWasmAnyFunc, 10, 'table_func1'); +addTableWithAccessors(builder, kWasmAnyRef, 20, 'table_ref1'); +addTableWithAccessors(builder, kWasmAnyRef, 9, 'table_ref2'); +addTableWithAccessors(builder, kWasmAnyFunc, 12, 'table_func2'); + +let exports = builder.instantiate().exports; +const dummy_ref = {foo : 1, bar : 3}; +const dummy_func = exports.set_table_func1; + +(function testTableGetInitialValue() { + print(arguments.callee.name); + // Tables are initialized with `null`. + assertSame(null, exports.get_table_func1(1)); + assertSame(null, exports.get_table_func2(2)); + assertSame(null, exports.get_table_ref1(3)); + assertSame(null, exports.get_table_ref2(4)); +})(); + +(function testTableGetOOB() { + print(arguments.callee.name); + assertSame(null, exports.get_table_func2(11)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func1(11)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func2(21)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func1(-1)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func2(-2)); + assertSame(null, exports.get_table_ref1(14)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref2(14)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref1(44)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref2(-1)); + assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref1(-4)); +})(); + +(function testTableSetOOB() { + print(arguments.callee.name); + exports.set_table_func2(11, dummy_func); + assertTraps(kTrapTableOutOfBounds, () => exports.set_table_func1(11, dummy_func)); + assertTraps(kTrapTableOutOfBounds, () => exports.set_table_func2(21, dummy_func)); + exports.set_table_ref1(14, dummy_ref); + assertTraps(kTrapTableOutOfBounds, () => exports.set_table_ref2(14, dummy_ref)); + assertTraps(kTrapTableOutOfBounds, () => exports.set_table_ref1(44, dummy_ref)); +})(); + +(function testSetTable() { + print(arguments.callee.name); + assertSame(null, exports.get_table_func1(3)); + exports.set_table_func1(3, dummy_func); + assertSame(dummy_func, exports.get_table_func1(3)); + assertSame(null, exports.get_table_func2(3)); + + assertSame(null, exports.get_table_func2(7)); + exports.set_table_func2(7, dummy_func); + assertSame(dummy_func, exports.get_table_func2(7)); + assertSame(null, exports.get_table_func1(7)); + + assertSame(null, exports.get_table_ref1(3)); + exports.set_table_ref1(3, dummy_ref); + assertSame(dummy_ref, exports.get_table_ref1(3)); + assertSame(null, exports.get_table_ref2(3)); + + assertSame(null, exports.get_table_ref2(7)); + exports.set_table_ref2(7, dummy_ref); + assertSame(dummy_ref, exports.get_table_ref2(7)); + assertSame(null, exports.get_table_ref1(7)); +})(); + +(function testSetFunctionTableInvalidType() { + print(arguments.callee.name); + assertThrows(() => exports.set_table_func2(7, dummy_ref), TypeError); +})(); +})(); + +(function testGetFunctionFromInitializedTable() { + print(arguments.callee.name); + const value1 = 11; + const value2 = 22; + const value3 = 13; + + const builder = new WasmModuleBuilder(); + const t1 = builder.addTable(kWasmAnyFunc, 10).index; + const t2 = builder.addTable(kWasmAnyFunc, 12).index; + + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, value1]); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, value2]); + const f3 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, value3]); + builder.addFunction('get_t1', kSig_a_i) + .addBody([kExprGetLocal, 0, kExprGetTable, t1]) + .exportFunc(); + builder.addFunction('get_t2', kSig_a_i) + .addBody([kExprGetLocal, 0, kExprGetTable, t2]) + .exportFunc(); + + const offset1 = 3; + const offset2 = 9; + builder.addElementSegment(t1, offset1, false, [f1.index, f2.index], false); + builder.addElementSegment(t2, offset2, false, [f3.index, f1.index], false); + + const instance = builder.instantiate(); + + assertEquals(value1, instance.exports.get_t1(offset1)()); + assertEquals(value2, instance.exports.get_t1(offset1 + 1)()); + assertEquals(value3, instance.exports.get_t2(offset2)()); + assertEquals(value1, instance.exports.get_t2(offset2 + 1)()); +})(); diff --git a/deps/v8/test/mjsunit/wasm/table-copy.js b/deps/v8/test/mjsunit/wasm/table-copy.js index 7c5c49669f..db0dc83191 100644 --- a/deps/v8/test/mjsunit/wasm/table-copy.js +++ b/deps/v8/test/mjsunit/wasm/table-copy.js @@ -6,193 +6,18 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); -(function TestTableCopyInbounds() { - print(arguments.callee.name); - let builder = new WasmModuleBuilder(); - let sig_v_iii = builder.addType(kSig_v_iii); - let kTableSize = 5; - - builder.setTableBounds(kTableSize, kTableSize); - - builder.addFunction("copy", sig_v_iii) - .addBody([ - kExprGetLocal, 0, - kExprGetLocal, 1, - kExprGetLocal, 2, - kNumericPrefix, kExprTableCopy, kTableZero, kTableZero]) - .exportAs("copy"); - - let instance = builder.instantiate(); - let copy = instance.exports.copy; - for (let i = 0; i < kTableSize; i++) { - copy(0, 0, i); // nop - copy(0, i, kTableSize - i); - copy(i, 0, kTableSize - i); - } -})(); - function addFunction(builder, k) { let m = builder.addFunction("", kSig_i_v) .addBody([...wasmI32Const(k)]); return m; } -function addFunctions(builder, count) { - let o = {}; - for (var i = 0; i < count; i++) { - o[`f${i}`] = addFunction(builder, i); - } - return o; -} - -function assertTable(obj, ...elems) { - for (var i = 0; i < elems.length; i++) { - assertEquals(elems[i], obj.get(i)); - } -} - -(function TestTableCopyElems() { - print(arguments.callee.name); - - let builder = new WasmModuleBuilder(); - let sig_v_iii = builder.addType(kSig_v_iii); - let kTableSize = 5; - - builder.setTableBounds(kTableSize, kTableSize); - - { - let o = addFunctions(builder, kTableSize); - builder.addElementSegment(0, false, - [o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index]); - } - - builder.addFunction("copy", sig_v_iii) - .addBody([ - kExprGetLocal, 0, - kExprGetLocal, 1, - kExprGetLocal, 2, - kNumericPrefix, kExprTableCopy, kTableZero, kTableZero]) - .exportAs("copy"); - - builder.addExportOfKind("table", kExternalTable, 0); - - let instance = builder.instantiate(); - let table = instance.exports.table; - let f0 = table.get(0), f1 = table.get(1), f2 = table.get(2), - f3 = table.get(3), f4 = table.get(4); - let copy = instance.exports.copy; - - assertEquals(0, f0()); - assertEquals(1, f1()); - assertEquals(2, f2()); - - assertTable(table, f0, f1, f2, f3, f4); - copy(0, 1, 1); - assertTable(table, f1, f1, f2, f3, f4); - copy(0, 1, 2); - assertTable(table, f1, f2, f2, f3, f4); - copy(3, 0, 2); - assertTable(table, f1, f2, f2, f1, f2); - copy(1, 0, 2); - assertTable(table, f1, f1, f2, f1, f2); -})(); - function assertCall(call, ...elems) { for (var i = 0; i < elems.length; i++) { assertEquals(elems[i], call(i)); } } -(function TestTableCopyCalls() { - print(arguments.callee.name); - - let builder = new WasmModuleBuilder(); - let sig_v_iii = builder.addType(kSig_v_iii); - let sig_i_i = builder.addType(kSig_i_i); - let sig_i_v = builder.addType(kSig_i_v); - let kTableSize = 5; - - builder.setTableBounds(kTableSize, kTableSize); - - { - let o = addFunctions(builder, 5); - builder.addElementSegment(0, false, - [o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index]); - } - - builder.addFunction("copy", sig_v_iii) - .addBody([ - kExprGetLocal, 0, - kExprGetLocal, 1, - kExprGetLocal, 2, - kNumericPrefix, kExprTableCopy, kTableZero, kTableZero]) - .exportAs("copy"); - - builder.addFunction("call", sig_i_i) - .addBody([ - kExprGetLocal, 0, - kExprCallIndirect, sig_i_v, kTableZero]) - .exportAs("call"); - - let instance = builder.instantiate(); - let copy = instance.exports.copy; - let call = instance.exports.call; - - assertCall(call, 0, 1, 2, 3, 4); - copy(0, 1, 1); - assertCall(call, 1, 1, 2, 3, 4); - copy(0, 1, 2); - assertCall(call, 1, 2, 2, 3, 4); - copy(3, 0, 2); - assertCall(call, 1, 2, 2, 1, 2); -})(); - -(function TestTableCopyOob1() { - print(arguments.callee.name); - - let builder = new WasmModuleBuilder(); - let sig_v_iii = builder.addType(kSig_v_iii); - let kTableSize = 5; - - builder.setTableBounds(kTableSize, kTableSize); - - builder.addFunction("copy", sig_v_iii) - .addBody([ - kExprGetLocal, 0, - kExprGetLocal, 1, - kExprGetLocal, 2, - kNumericPrefix, kExprTableCopy, kTableZero, kTableZero]) - .exportAs("copy"); - - let instance = builder.instantiate(); - let copy = instance.exports.copy; - copy(0, 0, 1); // nop - copy(0, 0, kTableSize); // nop - assertThrows(() => copy(0, 0, kTableSize+1)); - assertThrows(() => copy(1, 0, kTableSize)); - assertThrows(() => copy(0, 1, kTableSize)); - - { - let big = 1000000; - assertThrows(() => copy(big, 0, 0)); - assertThrows(() => copy(0, big, 0)); - } - - - for (let big = 4294967295; big > 1000; big >>>= 1) { - assertThrows(() => copy(big, 0, 1)); - assertThrows(() => copy(0, big, 1)); - assertThrows(() => copy(0, 0, big)); - } - - for (let big = -1000; big != 0; big <<= 1) { - assertThrows(() => copy(big, 0, 1)); - assertThrows(() => copy(0, big, 1)); - assertThrows(() => copy(0, 0, big)); - } - -})(); - (function TestTableCopyShared() { print(arguments.callee.name); let kTableSize = 5; diff --git a/deps/v8/test/mjsunit/wasm/table-get.js b/deps/v8/test/mjsunit/wasm/table-get.js new file mode 100644 index 0000000000..c159735cc5 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/table-get.js @@ -0,0 +1,132 @@ +// Copyright 2019 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-module-builder.js"); + +(function testTableGetNonExportedFunction() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const table = builder.addTable(kWasmAnyFunc, 20).exportAs("table"); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, f2.index], false); + + const instance = builder.instantiate(); + + const table_function2 = instance.exports.table.get(offset + 1); + assertEquals(22, table_function2()); +})(); + +(function testTableGetExportedFunction() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const table = builder.addTable(kWasmAnyFunc, 20).exportAs("table"); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]) + .exportAs("f2"); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, f2.index], false); + + const instance = builder.instantiate(); + + const table_function2 = instance.exports.table.get(offset + 1); + assertEquals(22, table_function2()); +})(); + +(function testTableGetOverlappingSegments() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const table = builder.addTable(kWasmAnyFunc, 20).exportAs("table"); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, f2.index], false); + builder.addElementSegment(0, offset + 1, false, [f1.index, f2.index], false); + + const instance = builder.instantiate(); + + const table_function1 = instance.exports.table.get(offset + 1); + assertEquals(11, table_function1()); +})(); + +(function testTableGetUniqueWrapperExportedFunction() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const table = builder.addTable(kWasmAnyFunc, 20).exportAs("table"); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]).exportAs("f1"); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index], false); + + const instance = builder.instantiate(); + + assertEquals(undefined, instance.exports.f1.tag); + const my_tag = { hello: 15 }; + instance.exports.f1.tag = my_tag; + + assertSame(my_tag, instance.exports.table.get(offset).tag); + assertSame(my_tag, instance.exports.table.get(offset + 1).tag); + assertSame(my_tag, instance.exports.table.get(offset + 2).tag); +})(); + +(function testTableGetUniqueWrapperNonExportedFunction() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const table = builder.addTable(kWasmAnyFunc, 20).exportAs("table"); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index], false); + + const instance = builder.instantiate(); + + assertEquals(undefined, instance.exports.table.get(offset).tag); + const my_tag = { hello: 15 }; + instance.exports.table.get(offset).tag = my_tag; + + assertSame(my_tag, instance.exports.table.get(offset + 1).tag); + assertSame(my_tag, instance.exports.table.get(offset + 2).tag); +})(); + +(function testTableGetEmptyValue() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const table = builder.addTable(kWasmAnyFunc, 20).exportAs("table"); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index], false); + + const instance = builder.instantiate(); + assertEquals(null, instance.exports.table.get(offset - 1)); +})(); + +(function testTableGetOOB() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const size = 20; + const table = builder.addTable(kWasmAnyFunc, size).exportAs("table"); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]); + const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index], false); + + const instance = builder.instantiate(); + assertThrows(() => instance.exports.table.get(size + 3), RangeError); +})(); + +(function testTableGetImportedFunction() { + print(arguments.callee.name); + const builder = new WasmModuleBuilder(); + const size = 20; + const table = builder.addTable(kWasmAnyFunc, size).exportAs("table"); + const import1 = builder.addImport("q", "fun", kSig_i_ii); + const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]); + const offset = 3; + builder.addElementSegment(0, offset, false, [f1.index, import1], false); + + const instance = builder.instantiate({q: {fun: () => 33}}); + assertEquals(33, instance.exports.table.get(offset + 1)()); +})(); diff --git a/deps/v8/test/mjsunit/wasm/table-grow.js b/deps/v8/test/mjsunit/wasm/table-grow.js index fd895dedc3..7defd42c2e 100644 --- a/deps/v8/test/mjsunit/wasm/table-grow.js +++ b/deps/v8/test/mjsunit/wasm/table-grow.js @@ -132,7 +132,7 @@ let id = (() => { // identity exported function builder.addImportedTable("q", "table", 5, 32); let g = builder.addImportedGlobal("q", "base", kWasmI32); - builder.addElementSegment(g, true, + builder.addElementSegment(0, g, true, [funcs.mul.index, funcs.add.index, funcs.sub.index]); builder.addExportOfKind("table", kExternalTable, 0); let module = new WebAssembly.Module(builder.toBuffer()); @@ -179,9 +179,9 @@ let id = (() => { // identity exported function let t = builder.addImport("q", "exp_ten", sig_i_v); builder.setTableBounds(7, 35); - // builder.addElementSegment(g1, true, + // builder.addElementSegment(0, g1, true, // [funcs.mul.index, funcs.add.index, funcs.sub.index]); - builder.addElementSegment(g1, true, [a, i, t]); + builder.addElementSegment(0, g1, true, [a, i, t]); builder.addExportOfKind("table", kExternalTable, 0); let module = new WebAssembly.Module(builder.toBuffer()); @@ -214,7 +214,7 @@ let id = (() => { // identity exported function let funcs = addFunctions(builder1); builder1.addImportedTable("q", "table", 6, 36); - builder1.addElementSegment(g, true, + builder1.addElementSegment(0, g, true, [funcs.mul.index, funcs.add.index, funcs.sub.index]); let module1 = new WebAssembly.Module(builder1.toBuffer()); @@ -266,7 +266,7 @@ let id = (() => { // identity exported function kExprGetLocal, 0, kExprCallIndirect, index_i_ii, kTableZero]) .exportAs("main"); - builder.addElementSegment(0, false, [0], true); + builder.addElementSegment(0, 0, false, [0], true); return new WebAssembly.Module(builder.toBuffer()); } diff --git a/deps/v8/test/mjsunit/wasm/table-init.js b/deps/v8/test/mjsunit/wasm/table-init.js deleted file mode 100644 index c95e072c64..0000000000 --- a/deps/v8/test/mjsunit/wasm/table-init.js +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2018 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-bulk-memory - -load("test/mjsunit/wasm/wasm-module-builder.js"); - -function addFunction(builder, k) { - let m = builder.addFunction("", kSig_i_v) - .addBody([...wasmI32Const(k)]); - return m; -} - -function addFunctions(builder, count, exportf = false) { - let o = {}; - for (var i = 0; i < count; i++) { - let name = `f${i}`; - o[name] = addFunction(builder, i); - if (exportf) o[name].exportAs(name); - } - return o; -} - -function assertTable(obj, ...elems) { - for (var i = 0; i < elems.length; i++) { - assertEquals(elems[i], obj.get(i)); - } -} - -(function TestTableInitInBounds() { - print(arguments.callee.name); - let builder = new WasmModuleBuilder(); - let sig_v_iii = builder.addType(kSig_v_iii); - let kTableSize = 5; - - builder.setTableBounds(kTableSize, kTableSize); - { - let o = addFunctions(builder, kTableSize, true); - builder.addPassiveElementSegment( - [o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index, null]); - } - - builder.addFunction("init0", sig_v_iii) - .addBody([ - kExprGetLocal, 0, - kExprGetLocal, 1, - kExprGetLocal, 2, - kNumericPrefix, kExprTableInit, kSegmentZero, kTableZero]) - .exportAs("init0"); - - builder.addExportOfKind("table", kExternalTable, 0); - - let instance = builder.instantiate(); - let x = instance.exports; - - assertTable(x.table, null, null, null, null, null); - - // test actual writes. - x.init0(0, 0, 1); - assertTable(x.table, x.f0, null, null, null, null); - x.init0(0, 0, 2); - assertTable(x.table, x.f0, x.f1, null, null, null); - x.init0(0, 0, 3); - assertTable(x.table, x.f0, x.f1, x.f2, null, null); - x.init0(3, 0, 2); - assertTable(x.table, x.f0, x.f1, x.f2, x.f0, x.f1); - x.init0(3, 1, 2); - assertTable(x.table, x.f0, x.f1, x.f2, x.f1, x.f2); - x.init0(3, 2, 2); - assertTable(x.table, x.f0, x.f1, x.f2, x.f2, x.f3); - x.init0(3, 3, 2); - assertTable(x.table, x.f0, x.f1, x.f2, x.f3, x.f4); - - // test writing null - x.init0(0, 5, 1); - assertTable(x.table, null, x.f1, x.f2, x.f3, x.f4); -})(); - -(function TestTableInitOob() { - print(arguments.callee.name); - let builder = new WasmModuleBuilder(); - let sig_v_iii = builder.addType(kSig_v_iii); - let kTableSize = 5; - - builder.setTableBounds(kTableSize, kTableSize); - { - let o = addFunctions(builder, kTableSize); - builder.addPassiveElementSegment( - [o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index]); - } - - builder.addFunction("init0", sig_v_iii) - .addBody([ - kExprGetLocal, 0, - kExprGetLocal, 1, - kExprGetLocal, 2, - kNumericPrefix, kExprTableInit, kSegmentZero, kTableZero]) - .exportAs("init0"); - - builder.addExportOfKind("table", kExternalTable, 0); - - let instance = builder.instantiate(); - let x = instance.exports; - - assertTable(x.table, null, null, null, null, null); - - // 0-count is oob. - assertThrows(() => x.init0(kTableSize+1, 0, 0)); - assertThrows(() => x.init0(0, kTableSize+1, 0)); - - assertThrows(() => x.init0(0, 0, 6)); - assertThrows(() => x.init0(0, 1, 5)); - assertThrows(() => x.init0(0, 2, 4)); - assertThrows(() => x.init0(0, 3, 3)); - assertThrows(() => x.init0(0, 4, 2)); - assertThrows(() => x.init0(0, 5, 1)); - - assertThrows(() => x.init0(0, 0, 6)); - assertThrows(() => x.init0(1, 0, 5)); - assertThrows(() => x.init0(2, 0, 4)); - assertThrows(() => x.init0(3, 0, 3)); - assertThrows(() => x.init0(4, 0, 2)); - assertThrows(() => x.init0(5, 0, 1)); - - assertThrows(() => x.init0(10, 0, 1)); - assertThrows(() => x.init0(0, 10, 1)); -})(); diff --git a/deps/v8/test/mjsunit/wasm/trap-handler-fallback.js b/deps/v8/test/mjsunit/wasm/trap-handler-fallback.js deleted file mode 100644 index 6b1cdf96e2..0000000000 --- a/deps/v8/test/mjsunit/wasm/trap-handler-fallback.js +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2018 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 --wasm-trap-handler-fallback - -load("test/mjsunit/wasm/wasm-module-builder.js"); - -// Make sure we can get at least one guard region if the trap handler is enabled. -(function CanGetGuardRegionTest() { - print("CanGetGuardRegionTest()"); - const memory = new WebAssembly.Memory({initial: 1}); - if (%IsWasmTrapHandlerEnabled()) { - assertTrue(%WasmMemoryHasFullGuardRegion(memory)); - } -})(); - -// This test verifies that when we have too many outstanding memories to get -// another fast memory, we fall back on bounds checking rather than failing. -(function TrapHandlerFallbackTest() { - print("TrapHandlerFallbackTest()"); - let builder = new WasmModuleBuilder(); - builder.addImportedMemory("mod", "imported_mem", 1); - builder.addFunction("load", kSig_i_i) - .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0]) - .exportFunc(); - let memory; - let instance; - let instances = []; - let fallback_occurred = false; - // Create 135 instances. V8 limits wasm to slightly more than 1 TiB of address - // space per isolate (see kAddressSpaceLimit in wasm-memory.cc), which allows - // up to 128 fast memories. As long as we create more than that, we should - // trigger the fallback behavior. - for (var i = 0; i < 135 && !fallback_occurred; i++) { - memory = new WebAssembly.Memory({initial: 1}); - instance = builder.instantiate({mod: {imported_mem: memory}}); - instances.push(instance); - - assertTraps(kTrapMemOutOfBounds, () => instance.exports.load(1 << 20)); - - fallback_occurred = !%WasmMemoryHasFullGuardRegion(memory); - } - assertTrue(fallback_occurred); -})(); - -(function TrapHandlerFallbackTestZeroInitialMemory() { - print("TrapHandlerFallbackTestZeroInitialMemory()"); - let builder = new WasmModuleBuilder(); - builder.addImportedMemory("mod", "imported_mem", 0); - builder.addFunction("load", kSig_i_i) - .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0]) - .exportFunc(); - let memory; - let instance; - let instances = []; - let fallback_occurred = false; - // Create 135 instances. V8 limits wasm to slightly more than 1 TiB of address - // space per isolate (see kAddressSpaceLimit in wasm-memory.cc), which allows - // up to 128 fast memories. As long as we create more than that, we should - // trigger the fallback behavior. - for (var i = 0; i < 135 && !fallback_occurred; i++) { - memory = new WebAssembly.Memory({initial: 1}); - instance = builder.instantiate({mod: {imported_mem: memory}}); - instances.push(instance); - - assertTraps(kTrapMemOutOfBounds, () => instance.exports.load(1 << 20)); - - fallback_occurred = !%WasmMemoryHasFullGuardRegion(memory); - } - assertTrue(fallback_occurred); -})(); - -(function TrapHandlerFallbackTestGrowFromZero() { - print("TrapHandlerFallbackTestGrowFromZero()"); - // Create a zero-length memory to make sure the empty backing store is created. - const zero_memory = new WebAssembly.Memory({initial: 0}); - - // Create enough memories to overflow the address space limit - let memories = [] - for (var i = 0; i < 135; i++) { - memories.push(new WebAssembly.Memory({initial: 1})); - } - - // Create a memory for the module. We'll grow this later. - let memory = new WebAssembly.Memory({initial: 0}); - - let builder = new WasmModuleBuilder(); - builder.addImportedMemory("mod", "imported_mem", 0); - builder.addFunction("load", kSig_i_i) - .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0]) - .exportFunc(); - - instance = builder.instantiate({mod: {imported_mem: memory}}); - - assertTraps(kTrapMemOutOfBounds, () => instance.exports.load(1 << 20)); - - try { - memory.grow(1); - } catch(e) { - if (typeof e == typeof new RangeError) { - return; - } - throw e; - } - - assertTraps(kTrapMemOutOfBounds, () => instance.exports.load(1 << 20)); -})(); - -// Like TrapHandlerFallbackTest, but allows the module to be reused, so we only -// have to recompile once. -(function TrapHandlerFallbackTestReuseModule() { - print("TrapHandlerFallbackTestReuseModule()"); - let builder = new WasmModuleBuilder(); - builder.addImportedMemory("mod", "imported_mem", 1); - builder.addFunction("load", kSig_i_i) - .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0]) - .exportFunc(); - let memory; - let instance; - let instances = []; - let fallback_occurred = false; - // Create 135 instances. V8 limits wasm to slightly more than 1 TiB of address - // space per isolate (see kAddressSpaceLimit in wasm-memory.cc), which allows - // up to 128 fast memories. As long as we create more than that, we should - // trigger the fallback behavior. - const module = builder.toModule(); - for (var i = 0; i < 135 && !fallback_occurred; i++) { - memory = new WebAssembly.Memory({initial: 1}); - instance = new WebAssembly.Instance(module, {mod: {imported_mem: memory}}); - instances.push(instance); - - assertTraps(kTrapMemOutOfBounds, () => instance.exports.load(1 << 20)); - - fallback_occurred = !%WasmMemoryHasFullGuardRegion(memory); - } - assertTrue(fallback_occurred); -})(); - -// Make sure that a bounds checked instance still works when calling an -// imported unchecked function. -(function CallIndirectImportTest() { - print("CallIndirectImportTest()"); - // Create an unchecked instance that calls a function through an indirect - // table. - const instance_a = (() => { - const builder = new WasmModuleBuilder(); - builder.addMemory(1, 1, false); - builder.addFunction("read_mem", kSig_i_i) - .addBody([ - kExprGetLocal, 0, - kExprI32LoadMem, 0, 0 - ]).exportAs("read_mem"); - return builder.instantiate(); - })(); - - // Create new memories until we get one that is unguarded - let memories = []; - let memory; - for (var i = 0; i < 135; i++) { - memory = new WebAssembly.Memory({initial: 1}); - memories.push(memory); - if (!%WasmMemoryHasFullGuardRegion(memory)) { - break; - } - } - assertFalse(%WasmMemoryHasFullGuardRegion(memory)); - - // create a module that imports a function through a table - const instance_b = (() => { - const builder = new WasmModuleBuilder(); - builder.addFunction("main", kSig_i_i) - .addBody([ - kExprGetLocal, 0, - kExprI32Const, 0, - kExprCallIndirect, 0, kTableZero - ]).exportAs("main"); - builder.addImportedTable("env", "table", 1, 1); - const module = new WebAssembly.Module(builder.toBuffer()); - const table = new WebAssembly.Table({ - element: "anyfunc", - initial: 1, maximum: 1 - }); - // Hook the new instance's export into the old instance's table. - table.set(0, instance_a.exports.read_mem); - return new WebAssembly.Instance(module, {'env': { 'table': table }}); - })(); - - // Make sure we get an out of bounds still. - assertTraps(kTrapMemOutOfBounds, () => instance_b.exports.main(100000)); - -})(); diff --git a/deps/v8/test/mjsunit/wasm/type-reflection-with-anyref.js b/deps/v8/test/mjsunit/wasm/type-reflection-with-anyref.js new file mode 100644 index 0000000000..adaf8e7185 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/type-reflection-with-anyref.js @@ -0,0 +1,36 @@ +// Copyright 2019 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-type-reflection --experimental-wasm-anyref + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +(function TestTableType() { + let table = new WebAssembly.Table({initial: 1, element: "anyref"}); + let type = WebAssembly.Table.type(table); + assertEquals(1, type.minimum); + assertEquals("anyref", type.element); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + table = new WebAssembly.Table({initial: 2, maximum: 15, element: "anyref"}); + type = WebAssembly.Table.type(table); + assertEquals(2, type.minimum); + assertEquals(15, type.maximum); + assertEquals("anyref", type.element); + assertEquals(3, Object.getOwnPropertyNames(type).length); +})(); + +(function TestGlobalType() { + let global = new WebAssembly.Global({value: "anyref", mutable: true}); + let type = WebAssembly.Global.type(global); + assertEquals("anyref", type.value); + assertEquals(true, type.mutable); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + global = new WebAssembly.Global({value: "anyref"}); + type = WebAssembly.Global.type(global); + assertEquals("anyref", type.value); + assertEquals(false, type.mutable); + assertEquals(2, Object.getOwnPropertyNames(type).length); +})(); diff --git a/deps/v8/test/mjsunit/wasm/type-reflection.js b/deps/v8/test/mjsunit/wasm/type-reflection.js new file mode 100644 index 0000000000..2e992edeb3 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/type-reflection.js @@ -0,0 +1,159 @@ +// Copyright 2019 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-type-reflection + +load('test/mjsunit/wasm/wasm-module-builder.js'); + +(function TestInvalidArgumentToType() { + ["abc", 123, {}].forEach(function(invalidInput) { + assertThrows( + () => WebAssembly.Memory.type(invalidInput), TypeError, + "WebAssembly.Memory.type(): Argument 0 must be a WebAssembly.Memory"); + assertThrows( + () => WebAssembly.Table.type(invalidInput), TypeError, + "WebAssembly.Table.type(): Argument 0 must be a WebAssembly.Table"); + assertThrows( + () => WebAssembly.Global.type(invalidInput), TypeError, + "WebAssembly.Global.type(): Argument 0 must be a WebAssembly.Global"); + }); + + assertThrows( + () => WebAssembly.Memory.type( + new WebAssembly.Table({initial:1, element: "anyfunc"})), + TypeError, + "WebAssembly.Memory.type(): Argument 0 must be a WebAssembly.Memory"); + + assertThrows( + () => WebAssembly.Table.type( + new WebAssembly.Memory({initial:1})), TypeError, + "WebAssembly.Table.type(): Argument 0 must be a WebAssembly.Table"); + + assertThrows( + () => WebAssembly.Global.type( + new WebAssembly.Memory({initial:1})), TypeError, + "WebAssembly.Global.type(): Argument 0 must be a WebAssembly.Global"); +})(); + +(function TestMemoryType() { + let mem = new WebAssembly.Memory({initial: 1}); + let type = WebAssembly.Memory.type(mem); + assertEquals(1, type.minimum); + assertEquals(1, Object.getOwnPropertyNames(type).length); + + mem = new WebAssembly.Memory({initial: 2, maximum: 15}); + type = WebAssembly.Memory.type(mem); + assertEquals(2, type.minimum); + assertEquals(15, type.maximum); + assertEquals(2, Object.getOwnPropertyNames(type).length); +})(); + +(function TestTableType() { + let table = new WebAssembly.Table({initial: 1, element: "anyfunc"}); + let type = WebAssembly.Table.type(table); + assertEquals(1, type.minimum); + assertEquals("anyfunc", type.element); + assertEquals(undefined, type.maximum); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + table = new WebAssembly.Table({initial: 2, maximum: 15, element: "anyfunc"}); + type = WebAssembly.Table.type(table); + assertEquals(2, type.minimum); + assertEquals(15, type.maximum); + assertEquals("anyfunc", type.element); + assertEquals(3, Object.getOwnPropertyNames(type).length); +})(); + +(function TestGlobalType() { + let global = new WebAssembly.Global({value: "i32", mutable: true}); + let type = WebAssembly.Global.type(global); + assertEquals("i32", type.value); + assertEquals(true, type.mutable); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + global = new WebAssembly.Global({value: "i32"}); + type = WebAssembly.Global.type(global); + assertEquals("i32", type.value); + assertEquals(false, type.mutable); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + global = new WebAssembly.Global({value: "i64"}); + type = WebAssembly.Global.type(global); + assertEquals("i64", type.value); + assertEquals(false, type.mutable); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + global = new WebAssembly.Global({value: "f32"}); + type = WebAssembly.Global.type(global); + assertEquals("f32", type.value); + assertEquals(false, type.mutable); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + global = new WebAssembly.Global({value: "f64"}); + type = WebAssembly.Global.type(global); + assertEquals("f64", type.value); + assertEquals(false, type.mutable); + assertEquals(2, Object.getOwnPropertyNames(type).length); +})(); + +(function TestMemoryConstructorWithMinimum() { + let mem = new WebAssembly.Memory({minimum: 1}); + assertTrue(mem instanceof WebAssembly.Memory); + let type = WebAssembly.Memory.type(mem); + assertEquals(1, type.minimum); + assertEquals(1, Object.getOwnPropertyNames(type).length); + + mem = new WebAssembly.Memory({minimum: 1, maximum: 5}); + assertTrue(mem instanceof WebAssembly.Memory); + type = WebAssembly.Memory.type(mem); + assertEquals(1, type.minimum); + assertEquals(5, type.maximum); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + mem = new WebAssembly.Memory({minimum: 1, initial: 2}); + assertTrue(mem instanceof WebAssembly.Memory); + type = WebAssembly.Memory.type(mem); + assertEquals(2, type.minimum); + assertEquals(1, Object.getOwnPropertyNames(type).length); + + mem = new WebAssembly.Memory({minimum: 1, initial: 2, maximum: 5}); + assertTrue(mem instanceof WebAssembly.Memory); + type = WebAssembly.Memory.type(mem); + assertEquals(2, type.minimum); + assertEquals(5, type.maximum); + assertEquals(2, Object.getOwnPropertyNames(type).length); +})(); + +(function TestTableConstructorWithMinimum() { + let table = new WebAssembly.Table({minimum: 1, element: 'anyfunc'}); + assertTrue(table instanceof WebAssembly.Table); + let type = WebAssembly.Table.type(table); + assertEquals(1, type.minimum); + assertEquals('anyfunc', type.element); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + table = new WebAssembly.Table({minimum: 1, element: 'anyfunc', maximum: 5}); + assertTrue(table instanceof WebAssembly.Table); + type = WebAssembly.Table.type(table); + assertEquals(1, type.minimum); + assertEquals(5, type.maximum); + assertEquals('anyfunc', type.element); + assertEquals(3, Object.getOwnPropertyNames(type).length); + + table = new WebAssembly.Table({minimum: 1, initial: 2, element: 'anyfunc'}); + assertTrue(table instanceof WebAssembly.Table); + type = WebAssembly.Table.type(table); + assertEquals(2, type.minimum); + assertEquals('anyfunc', type.element); + assertEquals(2, Object.getOwnPropertyNames(type).length); + + table = new WebAssembly.Table({minimum: 1, initial: 2, element: 'anyfunc', + maximum: 5}); + assertTrue(table instanceof WebAssembly.Table); + type = WebAssembly.Table.type(table); + assertEquals(2, type.minimum); + assertEquals(5, type.maximum); + assertEquals('anyfunc', type.element); + assertEquals(3, Object.getOwnPropertyNames(type).length); +})(); diff --git a/deps/v8/test/mjsunit/wasm/unicode.js b/deps/v8/test/mjsunit/wasm/unicode.js index 379a513d42..2b5f5ce9fe 100644 --- a/deps/v8/test/mjsunit/wasm/unicode.js +++ b/deps/v8/test/mjsunit/wasm/unicode.js @@ -51,7 +51,7 @@ checkExports('☺☺mul☺☺', '☺☺mul☺☺', '☺☺add☺☺', '☺☺add builder.addFunction('three snowmen: ☃☃☃', kSig_i_v).addBody([]).exportFunc(); assertThrows( () => builder.instantiate(), WebAssembly.CompileError, - /Compiling wasm function "three snowmen: ☃☃☃" failed: /); + /Compiling function #0:"three snowmen: ☃☃☃" failed: /); })(); (function errorMessageUnicodeInImportModuleName() { diff --git a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js index 077ac51baa..82420d6692 100644 --- a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js +++ b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js @@ -3,10 +3,10 @@ // found in the LICENSE file. // Used for encoding f32 and double constants to bits. -let __buffer = new ArrayBuffer(8); -let byte_view = new Uint8Array(__buffer); -let f32_view = new Float32Array(__buffer); -let f64_view = new Float64Array(__buffer); +let f32_view = new Float32Array(1); +let f32_bytes_view = new Uint8Array(f32_view.buffer); +let f64_view = new Float64Array(1); +let f64_bytes_view = new Uint8Array(f64_view.buffer); // The bytes function receives one of // - several arguments, each of which is either a number or a string of length @@ -48,12 +48,8 @@ var kWasmV3 = 0; var kHeaderSize = 8; var kPageSize = 65536; var kSpecMaxPages = 65535; - -function bytesWithHeader(...input) { - const header = - [kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3]; - return bytes(header + input); -} +var kMaxVarInt32Size = 5; +var kMaxVarInt64Size = 10; let kDeclNoLocals = 0; @@ -101,7 +97,7 @@ let kWasmI32 = 0x7f; let kWasmI64 = 0x7e; let kWasmF32 = 0x7d; let kWasmF64 = 0x7c; -let kWasmS128 = 0x7b; +let kWasmS128 = 0x7b; let kWasmAnyRef = 0x6f; let kWasmAnyFunc = 0x70; let kWasmExceptRef = 0x68; @@ -157,9 +153,13 @@ let kSig_a_a = makeSig([kWasmAnyFunc], [kWasmAnyFunc]); let kSig_i_r = makeSig([kWasmAnyRef], [kWasmI32]); let kSig_v_r = makeSig([kWasmAnyRef], []); let kSig_v_a = makeSig([kWasmAnyFunc], []); +let kSig_v_e = makeSig([kWasmExceptRef], []); let kSig_v_rr = makeSig([kWasmAnyRef, kWasmAnyRef], []); +let kSig_v_aa = makeSig([kWasmAnyFunc, kWasmAnyFunc], []); let kSig_r_v = makeSig([], [kWasmAnyRef]); let kSig_a_v = makeSig([], [kWasmAnyFunc]); +let kSig_a_i = makeSig([kWasmI32], [kWasmAnyFunc]); +let kSig_e_v = makeSig([], [kWasmExceptRef]); function makeSig(params, results) { return {params: params, results: results}; @@ -391,7 +391,7 @@ let kExprElemDrop = 0x0d; let kExprTableCopy = 0x0e; // Atomic opcodes. -let kExprAtomicWake = 0x00; +let kExprAtomicNotify = 0x00; let kExprI32AtomicWait = 0x01; let kExprI64AtomicWait = 0x02; let kExprI32AtomicLoad = 0x10; @@ -462,6 +462,15 @@ let kExprI64AtomicCompareExchange32U = 0x4e; // Simd opcodes. let kExprF32x4Min = 0x9e; +// Compilation hint constants. +let kCompilationHintStrategyDefault = 0x00; +let kCompilationHintStrategyLazy = 0x01; +let kCompilationHintStrategyEager = 0x02; +let kCompilationHintTierDefault = 0x00; +let kCompilationHintTierInterpreter = 0x01; +let kCompilationHintTierBaseline = 0x02; +let kCompilationHintTierOptimized = 0x03; + let kTrapUnreachable = 0; let kTrapMemOutOfBounds = 1; let kTrapDivByZero = 2; @@ -496,51 +505,74 @@ function assertTraps(trap, code) { assertThrows(code, WebAssembly.RuntimeError, kTrapMsgs[trap]); } -class Binary extends Array { +class Binary { + constructor() { + this.length = 0; + this.buffer = new Uint8Array(8192); + } + + ensure_space(needed) { + if (this.buffer.length - this.length >= needed) return; + let new_capacity = this.buffer.length * 2; + while (new_capacity - this.length < needed) new_capacity *= 2; + let new_buffer = new Uint8Array(new_capacity); + new_buffer.set(this.buffer); + this.buffer = new_buffer; + } + + trunc_buffer() { + return new Uint8Array(this.buffer.buffer, 0, this.length); + } + + reset() { + this.length = 0; + } + emit_u8(val) { - this.push(val); + this.ensure_space(1); + this.buffer[this.length++] = val; } emit_u16(val) { - this.push(val & 0xff); - this.push((val >> 8) & 0xff); + this.ensure_space(2); + this.buffer[this.length++] = val; + this.buffer[this.length++] = val >> 8; } emit_u32(val) { - this.push(val & 0xff); - this.push((val >> 8) & 0xff); - this.push((val >> 16) & 0xff); - this.push((val >> 24) & 0xff); + this.ensure_space(4); + this.buffer[this.length++] = val; + this.buffer[this.length++] = val >> 8; + this.buffer[this.length++] = val >> 16; + this.buffer[this.length++] = val >> 24; } - emit_u32v(val) { - while (true) { + emit_leb(val, max_len) { + this.ensure_space(max_len); + for (let i = 0; i < max_len; ++i) { let v = val & 0xff; val = val >>> 7; if (val == 0) { - this.push(v); - break; + this.buffer[this.length++] = v; + return; } - this.push(v | 0x80); + this.buffer[this.length++] = v | 0x80; } + throw new Error("Leb value exceeds maximum length of " + max_len); + } + + emit_u32v(val) { + this.emit_leb(val, kMaxVarInt32Size); } emit_u64v(val) { - while (true) { - let v = val & 0xff; - val = val >>> 7; - if (val == 0) { - this.push(v); - break; - } - this.push(v | 0x80); - } + this.emit_leb(val, kMaxVarInt64Size); } emit_bytes(data) { - for (let i = 0; i < data.length; i++) { - this.push(data[i] & 0xff); - } + this.ensure_space(data.length); + this.buffer.set(data, this.length); + this.length += data.length; } emit_string(string) { @@ -561,8 +593,9 @@ class Binary extends Array { } emit_header() { - this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, - kWasmV0, kWasmV1, kWasmV2, kWasmV3); + this.emit_bytes([ + kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3 + ]); } emit_section(section_code, content_generator) { @@ -575,7 +608,7 @@ class Binary extends Array { this.emit_u32v(section.length); // Copy the temporary buffer. // Avoid spread because {section} can be huge. - for (let b of section) this.push(b); + this.emit_bytes(section.trunc_buffer()); } } @@ -607,6 +640,11 @@ class WasmFunctionBuilder { return this; } + giveCompilationHint(strategy, baselineTier, topTier) { + this.module.giveCompilationHint(strategy, baselineTier, topTier, this.index); + return this; + } + addBody(body) { for (let b of body) { if (typeof b !== 'number' || (b & (~0xFF)) !== 0 ) @@ -688,6 +726,7 @@ class WasmModuleBuilder { this.tables = []; this.exceptions = []; this.functions = []; + this.compilation_hints = []; this.element_segments = []; this.data_segments = []; this.explicit = []; @@ -719,17 +758,21 @@ class WasmModuleBuilder { for (var i = 0; i < name.length; i++) { result.emit_u8(name.charCodeAt(i)); } - return result; + return result.trunc_buffer() } - addCustomSection(name, bytes) { + createCustomSection(name, bytes) { name = this.stringToBytes(name); - var length = new Binary(); - length.emit_u32v(name.length + bytes.length); - var section = [0, ...length, ...name]; - // Avoid spread because {bytes} can be huge. - for (var b of bytes) section.push(b); - this.explicit.push(section); + var section = new Binary(); + section.emit_u8(0); + section.emit_u32v(name.length + bytes.length); + section.emit_bytes(name); + section.emit_bytes(bytes); + return section.trunc_buffer(); + } + + addCustomSection(name, bytes) { + this.explicit.push(this.createCustomSection(name, bytes)); } addType(type) { @@ -828,6 +871,12 @@ class WasmModuleBuilder { return this; } + giveCompilationHint(strategy, baselineTier, topTier, index) { + this.compilation_hints[index] = {strategy: strategy, baselineTier: + baselineTier, topTier: topTier}; + return this; + } + addDataSegment(addr, data, is_global = false) { this.data_segments.push( {addr: addr, data: data, is_global: is_global, is_active: true}); @@ -843,18 +892,24 @@ class WasmModuleBuilder { this.exports.push({name: name, kind: kExternalMemory, index: 0}); } - addElementSegment(base, is_global, array, is_import = false) { + addElementSegment(table, base, is_global, array, is_import = false) { if (this.tables.length + this.num_imported_tables == 0) { this.addTable(kWasmAnyFunc, 0); } - this.element_segments.push({base: base, is_global: is_global, + this.element_segments.push({table: table, base: base, is_global: is_global, array: array, is_active: true}); - if (!is_global) { + + // As a testing convenience, update the table length when adding an element + // segment. If the table is imported, we can't do this because we don't + // know how long the table actually is. If |is_global| is true, then the + // base is a global index, instead of an integer offset, so we can't update + // the table then either. + if (!(is_import || is_global)) { var length = base + array.length; - if (!is_import && length > this.tables[0].initial_size) { + if (length > this.tables[0].initial_size) { this.tables[0].initial_size = length; } - if (!is_import && this.tables[0].has_max && + if (this.tables[0].has_max && length > this.tables[0].max_size) { this.tables[0].max_size = length; } @@ -875,7 +930,7 @@ class WasmModuleBuilder { if (this.tables.length == 0) { this.addTable(kWasmAnyFunc, 0); } - return this.addElementSegment(this.tables[0].initial_size, false, array); + return this.addElementSegment(0, this.tables[0].initial_size, false, array); } setTableBounds(min, max = undefined) { @@ -891,7 +946,7 @@ class WasmModuleBuilder { return this; } - toArray(debug = false) { + toBuffer(debug = false) { let binary = new Binary; let wasm = this; @@ -1022,24 +1077,16 @@ class WasmModuleBuilder { case kWasmF32: section.emit_u8(kExprF32Const); f32_view[0] = global.init; - section.emit_u8(byte_view[0]); - section.emit_u8(byte_view[1]); - section.emit_u8(byte_view[2]); - section.emit_u8(byte_view[3]); + section.emit_bytes(f32_bytes_view); break; case kWasmF64: section.emit_u8(kExprF64Const); f64_view[0] = global.init; - section.emit_u8(byte_view[0]); - section.emit_u8(byte_view[1]); - section.emit_u8(byte_view[2]); - section.emit_u8(byte_view[3]); - section.emit_u8(byte_view[4]); - section.emit_u8(byte_view[5]); - section.emit_u8(byte_view[6]); - section.emit_u8(byte_view[7]); + section.emit_bytes(f64_bytes_view); break; case kWasmAnyRef: + case kWasmAnyFunc: + case kWasmExceptRef: section.emit_u8(kExprRefNull); break; } @@ -1103,7 +1150,12 @@ class WasmModuleBuilder { for (let init of inits) { if (init.is_active) { // Active segment. - section.emit_u8(0); // table index / flags + if (init.table == 0) { + section.emit_u32v(kActiveNoIndex); + } else { + section.emit_u32v(kActiveWithIndex); + section.emit_u32v(init.table); + } if (init.is_global) { section.emit_u8(kExprGetGlobal); } else { @@ -1142,13 +1194,49 @@ class WasmModuleBuilder { }); } + // If there are compilation hints add a custom section 'compilationHints' + // after the function section and before the code section. + if (wasm.compilation_hints.length > 0) { + if (debug) print("emitting compilation hints @ " + binary.length); + // Build custom section payload. + let payloadBinary = new Binary(); + let implicit_compilation_hints_count = wasm.functions.length; + payloadBinary.emit_u32v(implicit_compilation_hints_count); + + // Defaults to the compiler's choice if no better hint was given (0x00). + let defaultHintByte = kCompilationHintStrategyDefault | + (kCompilationHintTierDefault << 2) | + (kCompilationHintTierDefault << 4); + + // Emit hint byte for every function defined in this module. + for (let i = 0; i < implicit_compilation_hints_count; i++) { + let index = wasm.num_imported_funcs + i; + var hintByte; + if(index in wasm.compilation_hints) { + let hint = wasm.compilation_hints[index]; + hintByte = hint.strategy | (hint.baselineTier << 2) | + (hint.topTier << 4); + } else{ + hintByte = defaultHintByte; + } + payloadBinary.emit_u8(hintByte); + } + + // Finalize as custom section. + let name = "compilationHints"; + let bytes = this.createCustomSection(name, payloadBinary.trunc_buffer()); + binary.emit_bytes(bytes); + } + // Add function bodies. if (wasm.functions.length > 0) { // emit function bodies if (debug) print("emitting code @ " + binary.length); binary.emit_section(kCodeSectionCode, section => { section.emit_u32v(wasm.functions.length); + let header = new Binary; for (let func of wasm.functions) { + header.reset(); // Function body length will be patched later. let local_decls = []; for (let l of func.locals || []) { @@ -1178,7 +1266,6 @@ class WasmModuleBuilder { } } - let header = new Binary; header.emit_u32v(local_decls.length); for (let decl of local_decls) { header.emit_u32v(decl.count); @@ -1186,7 +1273,7 @@ class WasmModuleBuilder { } section.emit_u32v(header.length + func.body.length); - section.emit_bytes(header); + section.emit_bytes(header.trunc_buffer()); section.emit_bytes(func.body); } }); @@ -1273,27 +1360,15 @@ class WasmModuleBuilder { }); } - return binary; + return binary.trunc_buffer(); } - toBuffer(debug = false) { - let bytes = this.toArray(debug); - let buffer = new ArrayBuffer(bytes.length); - let view = new Uint8Array(buffer); - for (let i = 0; i < bytes.length; i++) { - let val = bytes[i]; - if ((typeof val) == "string") val = val.charCodeAt(0); - view[i] = val | 0; - } - return buffer; - } - - toUint8Array(debug = false) { - return new Uint8Array(this.toBuffer(debug)); + toArray(debug = false) { + return Array.from(this.toBuffer(debug)); } instantiate(ffi) { - let module = new WebAssembly.Module(this.toBuffer()); + let module = this.toModule(); let instance = new WebAssembly.Instance(module, ffi); return instance; } @@ -1319,11 +1394,17 @@ function wasmI32Const(val) { function wasmF32Const(f) { f32_view[0] = f; - return [kExprF32Const, byte_view[0], byte_view[1], byte_view[2], byte_view[3]]; + return [ + kExprF32Const, f32_bytes_view[0], f32_bytes_view[1], f32_bytes_view[2], + f32_bytes_view[3] + ]; } function wasmF64Const(f) { f64_view[0] = f; - return [kExprF64Const, byte_view[0], byte_view[1], byte_view[2], byte_view[3], - byte_view[4], byte_view[5], byte_view[6], byte_view[7]]; + return [ + kExprF64Const, f64_bytes_view[0], f64_bytes_view[1], f64_bytes_view[2], + f64_bytes_view[3], f64_bytes_view[4], f64_bytes_view[5], f64_bytes_view[6], + f64_bytes_view[7] + ]; } |