diff --git a/implementation-contributed/v8/intl/intl.status b/implementation-contributed/v8/intl/intl.status index 1082049dc1..d70056f049 100644 --- a/implementation-contributed/v8/intl/intl.status +++ b/implementation-contributed/v8/intl/intl.status @@ -48,11 +48,5 @@ # Unable to change locale on Android: 'relative-time-format/default-locale-fr-CA': [FAIL], 'relative-time-format/default-locale-pt-BR': [FAIL], - - # https://bugs.chromium.org/p/v8/issues/detail?id=8432 - 'regress-8432': [FAIL], - - # https://crbug.com/v8/8414 - 'regress-8414': [FAIL], }], # 'system == android' ] diff --git a/implementation-contributed/v8/intl/regress-8432.js b/implementation-contributed/v8/intl/regress-8432.js index 5bf9fb6cd8..13083e3c82 100644 --- a/implementation-contributed/v8/intl/regress-8432.js +++ b/implementation-contributed/v8/intl/regress-8432.js @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Somehow only ar-SA fail on Android in regress-8413*.js -// Split it into this test just for ar-SA -// This is likely to be an ICU data trimming issue only apply to Android. +// Somehow only ar-SA fails on Android in regress-8413*.js. +// Split it into this test just for ar-SA. +// This is likely to be caused by an Android-specific ICU data trimming. let locales = [ "ar-SA" ]; // "Table 5: Components of date and time formats" as in diff --git a/implementation-contributed/v8/mjsunit/apply.js b/implementation-contributed/v8/mjsunit/apply.js index 07639c940e..115d2467d8 100644 --- a/implementation-contributed/v8/mjsunit/apply.js +++ b/implementation-contributed/v8/mjsunit/apply.js @@ -122,7 +122,10 @@ for (var j = 1; j < 0x400000; j <<= 1) { a[j - 1] = 42; assertEquals(42 + j, al.apply(345, a)); } catch (e) { - assertTrue(e.toString().indexOf("Maximum call stack size exceeded") != -1); + assertTrue( + e.toString().indexOf('Maximum call stack size exceeded') != -1 || + e.toString().indexOf( + 'Too many arguments in function call (only 65534 allowed)') != -1); for (; j < 0x400000; j <<= 1) { var caught = false; try { @@ -133,7 +136,10 @@ for (var j = 1; j < 0x400000; j <<= 1) { assertUnreachable("Apply of array with length " + a.length + " should have thrown"); } catch (e) { - assertTrue(e.toString().indexOf("Maximum call stack size exceeded") != -1); + assertTrue( + e.toString().indexOf('Maximum call stack size exceeded') != -1 || + e.toString().indexOf( + 'Too many arguments in function call (only 65534 allowed)') != -1); caught = true; } assertTrue(caught, "exception not caught"); diff --git a/implementation-contributed/v8/mjsunit/compiler/number-modulus.js b/implementation-contributed/v8/mjsunit/compiler/number-modulus.js index 5f695d1ee5..0925aa0da3 100644 --- a/implementation-contributed/v8/mjsunit/compiler/number-modulus.js +++ b/implementation-contributed/v8/mjsunit/compiler/number-modulus.js @@ -4,178 +4,6 @@ // Flags: --allow-natives-syntax --opt --noalways-opt -// Test that NumberModulus with Number feedback works if only in the -// end SimplifiedLowering figures out that the inputs to this operation -// are actually Unsigned32. -(function() { - // We need a separately polluted % with NumberOrOddball feedback. - function bar(x) { return x % 2; } - bar(undefined); // The % feedback is now NumberOrOddball. - - // Now just use the gadget above in a way that only after RETYPE - // in SimplifiedLowering we find out that the `x` is actually in - // Unsigned32 range (based on taking the SignedSmall feedback on - // the + operator). - function foo(x) { - x = (x >>> 0) + 1; - return bar(x) | 0; - } - - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - assertOptimized(foo); -})(); - -// Test that NumberModulus with Number feedback works if only in the -// end SimplifiedLowering figures out that the inputs to this operation -// are actually Signed32. -(function() { - // We need a separately polluted % with NumberOrOddball feedback. - function bar(x) { return x % 2; } - bar(undefined); // The % feedback is now NumberOrOddball. - - // Now just use the gadget above in a way that only after RETYPE - // in SimplifiedLowering we find out that the `x` is actually in - // Signed32 range (based on taking the SignedSmall feedback on - // the + operator). - function foo(x) { - x = (x | 0) + 1; - return bar(x) | 0; - } - - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - assertOptimized(foo); -})(); - -// Test that SpeculativeNumberModulus with Number feedback works if -// only in the end SimplifiedLowering figures out that the inputs to -// this operation are actually Unsigned32. -(function() { - // We need to use an object literal here to make sure that the - // SpeculativeNumberModulus is not turned into a NumberModulus - // early during JSTypedLowering. - function bar(x) { return {x}.x % 2; } - bar(undefined); // The % feedback is now NumberOrOddball. - - // Now just use the gadget above in a way that only after RETYPE - // in SimplifiedLowering we find out that the `x` is actually in - // Unsigned32 range (based on taking the SignedSmall feedback on - // the + operator). - function foo(x) { - x = (x >>> 0) + 1; - return bar(x) | 0; - } - - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - assertOptimized(foo); -})(); - -// Test that SpeculativeNumberModulus with Number feedback works if -// only in the end SimplifiedLowering figures out that the inputs to -// this operation are actually Signed32. -(function() { - // We need to use an object literal here to make sure that the - // SpeculativeNumberModulus is not turned into a NumberModulus - // early during JSTypedLowering. - function bar(x) { return {x}.x % 2; } - bar(undefined); // The % feedback is now NumberOrOddball. - - // Now just use the gadget above in a way that only after RETYPE - // in SimplifiedLowering we find out that the `x` is actually in - // Signed32 range (based on taking the SignedSmall feedback on - // the + operator). - function foo(x) { - x = (x | 0) + 1; - return bar(x) | 0; - } - - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(1)); - assertEquals(1, foo(2)); - assertEquals(0, foo(3)); - assertEquals(1, foo(4)); - assertOptimized(foo); -})(); - -// Test that NumberModulus works in the case where TurboFan -// can infer that the output is Signed32 \/ MinusZero, and -// there's a truncation on the result that identifies zeros -// (via the SpeculativeNumberEqual). -(function() { - // We need a separately polluted % with NumberOrOddball feedback. - function bar(x) { return x % 2; } - bar(undefined); // The % feedback is now NumberOrOddball. - - // Now we just use the gadget above on an `x` that is known - // to be in Signed32 range and compare it to 0, which passes - // a truncation that identifies zeros. - function foo(x) { - if (bar(x | 0) == 0) return 0; - return 1; - } - - assertEquals(0, foo(2)); - assertEquals(1, foo(1)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(2)); - assertEquals(1, foo(1)); - assertOptimized(foo); - - // Now `foo` should stay optimized even if `x % 2` would - // produce -0, aka when we pass a negative value for `x`. - assertEquals(0, foo(-2)); - assertEquals(1, foo(-1)); - assertOptimized(foo); -})(); - -// Test that CheckedInt32Mod handles the slow-path (when -// the left hand side is negative) correctly. -(function() { - // We need a SpeculativeNumberModulus with SignedSmall feedback. - function foo(x, y) { - return x % y; - } - - assertEquals(0, foo(2, 1)); - assertEquals(0, foo(2, 2)); - assertEquals(-1, foo(-3, 2)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(2, 1)); - assertEquals(0, foo(2, 2)); - assertEquals(-1, foo(-3, 2)); - assertOptimized(foo); - - // Now `foo` should deoptimize if the result is -0. - assertEquals(-0, foo(-2, 2)); - assertUnoptimized(foo); -})(); // Test that NumberModulus passes kIdentifiesZero to the // left hand side input when the result doesn't care about @@ -196,61 +24,3 @@ assertTrue(foo(0)); assertOptimized(foo); })(); - -// Test that NumberModulus passes kIdentifiesZero to the -// right hand side input, even when the inputs are outside -// the Signed32 range. -(function() { - function foo(x) { - return (2 ** 32) % (x * -2); - } - - assertEquals(0, foo(1)); - assertEquals(0, foo(1)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(1)); - - // Now `foo` should stay optimized even if `x * -2` would - // produce -0, aka when we pass a zero value for `x`. - assertEquals(NaN, foo(0)); - assertOptimized(foo); -})(); - -// Test that SpeculativeNumberModulus passes kIdentifiesZero -// to the right hand side input, even when feedback is consumed. -(function() { - function foo(x, y) { - return (x % (y * -2)) | 0; - } - - assertEquals(0, foo(2, 1)); - assertEquals(-1, foo(-3, 1)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(0, foo(2, 1)); - assertEquals(-1, foo(-3, 1)); - assertOptimized(foo); - - // Now `foo` should stay optimized even if `y * -2` would - // produce -0, aka when we pass a zero value for `y`. - assertEquals(0, foo(2, 0)); - assertOptimized(foo); -})(); - -// Test that SpeculativeNumberModulus passes kIdentifiesZero -// to the left hand side input, even when feedback is consumed. -(function() { - function foo(x, y) { - return ((x * -2) % y) | 0; - } - - assertEquals(-2, foo(1, 3)); - assertEquals(-2, foo(1, 3)); - %OptimizeFunctionOnNextCall(foo); - assertEquals(-2, foo(1, 3)); - assertOptimized(foo); - - // Now `foo` should stay optimized even if `x * -2` would - // produce -0, aka when we pass a zero value for `x`. - assertEquals(0, foo(0, 2)); - assertOptimized(foo); -})(); diff --git a/implementation-contributed/v8/mjsunit/compiler/regress-905555-2.js b/implementation-contributed/v8/mjsunit/compiler/regress-905555-2.js new file mode 100644 index 0000000000..5852c6dd43 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/compiler/regress-905555-2.js @@ -0,0 +1,25 @@ +// 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 --block-concurrent-recompilation --noalways-opt + +global = 1; + +function boom(value) { + return global; +} + +assertEquals(1, boom()); +assertEquals(1, boom()); +%OptimizeFunctionOnNextCall(boom, "concurrent"); +assertEquals(1, boom()); + +delete this.global; + +%UnblockConcurrentRecompilation(); + +// boom should be deoptimized because the global property cell has changed. +assertUnoptimized(boom, "sync"); + +assertThrows(boom); diff --git a/implementation-contributed/v8/mjsunit/compiler/regress-905555.js b/implementation-contributed/v8/mjsunit/compiler/regress-905555.js new file mode 100644 index 0000000000..bc7ba7428e --- /dev/null +++ b/implementation-contributed/v8/mjsunit/compiler/regress-905555.js @@ -0,0 +1,25 @@ +// 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 --block-concurrent-recompilation --noalways-opt + +global = 1; + +function boom(value) { + return global; +} + +assertEquals(1, boom()); +assertEquals(1, boom()); +%OptimizeFunctionOnNextCall(boom, "concurrent"); +assertEquals(1, boom()); + +this.__defineGetter__("global", () => 42); + +%UnblockConcurrentRecompilation(); + +// boom should be deoptimized because the global property cell has changed. +assertUnoptimized(boom, "sync"); + +assertEquals(42, boom()); diff --git a/implementation-contributed/v8/mjsunit/es6/destructuring.js b/implementation-contributed/v8/mjsunit/es6/destructuring.js index f09165a24e..30df8c63bf 100644 --- a/implementation-contributed/v8/mjsunit/es6/destructuring.js +++ b/implementation-contributed/v8/mjsunit/es6/destructuring.js @@ -1190,3 +1190,13 @@ assertEquals(undefined, eval('try {throw {foo: 1, bar: 2}} catch({foo}) {}')); assertEquals(undefined, eval('try {throw [1, 2, 3]} catch([x]) {}')); })(); + +// Property access as declaration target. +assertThrows("let [o.x=1]=[]", SyntaxError); +assertThrows("let {x:o.f=1}={x:1}", SyntaxError); +assertThrows("(o.f=1)=>0", SyntaxError); + +// Invalidly parenthesized declaration targets. +assertThrows("for (({x}) of [{x:1}]) {}", SyntaxError); +assertThrows("for (var ({x}) of [{x:1}]) {}", SyntaxError); +assertThrows("for await (({x}) of [{x:1}]) {}", SyntaxError); diff --git a/implementation-contributed/v8/mjsunit/harmony/object-fromentries.js b/implementation-contributed/v8/mjsunit/harmony/object-fromentries.js new file mode 100644 index 0000000000..8bbd6317c6 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/harmony/object-fromentries.js @@ -0,0 +1,439 @@ +// 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: --harmony-object-from-entries + +const fromEntries = Object.fromEntries; +const ObjectPrototype = Object.prototype; +const ObjectPrototypeHasOwnProperty = ObjectPrototype.hasOwnProperty; +function hasOwnProperty(O, Name) { + if (O === undefined || O === null) return false; + return ObjectPrototypeHasOwnProperty.call(O, Name); +} + +let test = { + methodExists() { + assertTrue(hasOwnProperty(Object, "fromEntries")); + assertEquals("function", typeof Object.fromEntries); + }, + + methodLength() { + assertEquals(1, Object.fromEntries.length); + }, + + methodName() { + assertEquals("fromEntries", Object.fromEntries.name); + }, + + methodPropertyDescriptor() { + let descriptor = Object.getOwnPropertyDescriptor(Object, "fromEntries"); + assertFalse(descriptor.enumerable); + assertTrue(descriptor.configurable); + assertTrue(descriptor.writable); + assertEquals(descriptor.value, Object.fromEntries); + }, + + exceptionIfNotCoercible() { + assertThrows(() => fromEntries(null), TypeError); + assertThrows(() => fromEntries(undefined), TypeError); + }, + + exceptionIfNotIterable() { + let nonIterable = [1, 2, 3, 4, 5]; + Object.defineProperty(nonIterable, Symbol.iterator, { value: undefined }); + assertThrows(() => fromEntries(nonIterable), TypeError); + }, + + exceptionIfGetIteratorThrows() { + let iterable = [1, 2, 3, 4, 5]; + class ThrewDuringGet {}; + Object.defineProperty(iterable, Symbol.iterator, { + get() { throw new ThrewDuringGet(); } + }); + assertThrows(() => fromEntries(iterable), ThrewDuringGet); + }, + + exceptionIfCallIteratorThrows() { + let iterable = [1, 2, 3, 4, 5]; + class ThrewDuringCall {}; + iterable[Symbol.iterator] = function() { + throw new ThrewDuringCall(); + } + assertThrows(() => fromEntries(iterable), ThrewDuringCall); + }, + + exceptionIfIteratorNextThrows() { + let iterable = [1, 2, 3, 4, 5]; + class ThrewDuringIteratorNext {} + iterable[Symbol.iterator] = function() { + return { + next() { throw new ThrewDuringIteratorNext; }, + return() { + throw new Error( + "IteratorClose must not be performed if IteratorStep throws"); + }, + } + } + assertThrows(() => fromEntries(iterable), ThrewDuringIteratorNext); + }, + + exceptionIfIteratorCompleteThrows() { + let iterable = [1, 2, 3, 4, 5]; + class ThrewDuringIteratorComplete {} + iterable[Symbol.iterator] = function() { + return { + next() { + return { + get value() { throw new Error( + "IteratorValue must not be performed before IteratorComplete"); + }, + get done() { + throw new ThrewDuringIteratorComplete(); + } + } + throw new ThrewDuringIteratorNext; + }, + return() { + throw new Error( + "IteratorClose must not be performed if IteratorStep throws"); + }, + } + } + assertThrows(() => fromEntries(iterable), ThrewDuringIteratorComplete); + }, + + exceptionIfEntryIsNotObject() { + { + // Fast path (Objects/Smis) + let iterables = [[null], [undefined], [1], [NaN], [false], [Symbol()], + [""]]; + for (let iterable of iterables) { + assertThrows(() => fromEntries(iterable), TypeError); + } + } + { + // Fast path (Doubles) + let iterable = [3.7, , , 3.6, 1.1, -0.4]; + assertThrows(() => fromEntries(iterable), TypeError); + } + { + // Slow path + let i = 0; + let values = [null, undefined, 1, NaN, false, Symbol(), ""]; + let iterable = { + [Symbol.iterator]() { return this; }, + next() { + return { + done: i >= values.length, + value: values[i++], + } + }, + }; + for (let k = 0; k < values.length; ++k) { + assertThrows(() => fromEntries(iterable), TypeError); + } + assertEquals({}, fromEntries(iterable)); + } + }, + + returnIfEntryIsNotObject() { + // Only observable/verifiable in the slow path :( + let i = 0; + let didCallReturn = false; + let values = [null, undefined, 1, NaN, false, Symbol(), ""]; + let iterable = { + [Symbol.iterator]() { return this; }, + next() { + return { + done: i >= values.length, + value: values[i++], + } + }, + return() { didCallReturn = true; throw new Error("Unused!"); } + }; + for (let k = 0; k < values.length; ++k) { + didCallReturn = false; + assertThrows(() => fromEntries(iterable), TypeError); + assertTrue(didCallReturn); + } + assertEquals({}, fromEntries(iterable)); + }, + + returnIfEntryKeyAccessorThrows() { + class ThrewDuringKeyAccessor {}; + let entries = [{ get 0() { throw new ThrewDuringKeyAccessor(); }, + get 1() { throw new Error("Unreachable!"); } }]; + let didCallReturn = false; + let iterator = entries[Symbol.iterator](); + iterator.return = function() { + didCallReturn = true; + throw new Error("Unused!"); + } + assertThrows(() => fromEntries(iterator), ThrewDuringKeyAccessor); + assertTrue(didCallReturn); + }, + + returnIfEntryKeyAccessorThrows() { + class ThrewDuringValueAccessor {}; + let entries = [{ get 1() { throw new ThrewDuringValueAccessor(); }, + 0: "key", + }]; + let didCallReturn = false; + let iterator = entries[Symbol.iterator](); + iterator.return = function() { + didCallReturn = true; + throw new Error("Unused!"); + }; + assertThrows(() => fromEntries(iterator), ThrewDuringValueAccessor); + assertTrue(didCallReturn); + }, + + returnIfKeyToStringThrows() { + class ThrewDuringKeyToString {}; + let operations = []; + let entries = [{ + get 0() { + operations.push("[[Get]] key"); + return { + toString() { + operations.push("toString(key)"); + throw new ThrewDuringKeyToString(); + }, + valueOf() { + operations.push("valueOf(key)"); + } + }; + }, + get 1() { + operations.push("[[Get]] value"); + return "value"; + }, + }]; + + let iterator = entries[Symbol.iterator](); + iterator.return = function() { + operations.push("IteratorClose"); + throw new Error("Unused!"); + }; + assertThrows(() => fromEntries(iterator), ThrewDuringKeyToString); + assertEquals([ + "[[Get]] key", + "[[Get]] value", + "toString(key)", + "IteratorClose", + ], operations); + }, + + throwsIfIteratorValueThrows() { + let iterable = [1, 2, 3, 4, 5]; + class ThrewDuringIteratorValue {} + iterable[Symbol.iterator] = function() { + return { + next() { + return { + get value() { throw new ThrewDuringIteratorValue(); }, + get done() { return false; } + } + throw new ThrewDuringIteratorNext; + }, + return() { + throw new Error( + "IteratorClose must not be performed if IteratorStep throws"); + }, + } + } + assertThrows(() => fromEntries(iterable), ThrewDuringIteratorValue); + }, + + emptyIterable() { + let iterables = [[], new Set(), new Map()]; + for (let iterable of iterables) { + let result = fromEntries(iterable); + assertEquals({}, result); + assertEquals(ObjectPrototype, result.__proto__); + } + }, + + keyOrderFastPath() { + let entries = [ + ["z", 1], + ["y", 2], + ["x", 3], + ["y", 4], + [100, 0], + ]; + let result = fromEntries(entries); + assertEquals({ + 100: 0, + z: 1, + y: 4, + x: 3, + }, result); + assertEquals(["100", "z", "y", "x"], Object.keys(result)); + }, + + keyOrderSlowPath() { + let entries = [ + ["z", 1], + ["y", 2], + ["x", 3], + ["y", 4], + [100, 0], + ]; + let i = 0; + let iterable = { + [Symbol.iterator]() { return this; }, + next() { + return { + done: i >= entries.length, + value: entries[i++] + } + }, + return() { throw new Error("Unreachable!"); } + }; + let result = fromEntries(iterable); + assertEquals({ + 100: 0, + z: 1, + y: 4, + x: 3, + }, result); + assertEquals(["100", "z", "y", "x"], Object.keys(result)); + }, + + doesNotUseIteratorForKeyValuePairFastCase() { + class Entry { + constructor(k, v) { + this[0] = k; + this[1] = v; + } + get [Symbol.iterator]() { + throw new Error("Should not load Symbol.iterator from Entry!"); + } + } + function e(k, v) { return new Entry(k, v); } + let entries = [e(100, 0), e('z', 1), e('y', 2), e('x', 3), e('y', 4)]; + let result = fromEntries(entries); + assertEquals({ + 100: 0, + z: 1, + y: 4, + x: 3, + }, result); + }, + + doesNotUseIteratorForKeyValuePairSlowCase() { + class Entry { + constructor(k, v) { + this[0] = k; + this[1] = v; + } + get [Symbol.iterator]() { + throw new Error("Should not load Symbol.iterator from Entry!"); + } + } + function e(k, v) { return new Entry(k, v); } + let entries = new Set( + [e(100, 0), e('z', 1), e('y', 2), e('x', 3), e('y', 4)]); + let result = fromEntries(entries); + assertEquals({ + 100: 0, + z: 1, + y: 4, + x: 3, + }, result); + }, + + createDataPropertyFastCase() { + Object.defineProperty(ObjectPrototype, "property", { + configurable: true, + get() { throw new Error("Should not invoke getter on prototype!"); }, + set() { throw new Error("Should not invoke setter on prototype!"); }, + }); + + let entries = [["property", "value"]]; + let result = fromEntries(entries); + assertEquals(result.property, "value"); + delete ObjectPrototype.property; + }, + + createDataPropertySlowCase() { + Object.defineProperty(ObjectPrototype, "property", { + configurable: true, + get() { throw new Error("Should not invoke getter on prototype!"); }, + set() { throw new Error("Should not invoke setter on prototype!"); }, + }); + + let entries = new Set([["property", "value"]]); + let result = fromEntries(entries); + assertEquals(result.property, "value"); + delete ObjectPrototype.property; + }, + + keyToPrimitiveMutatesArrayInFastCase() { + let mySymbol = Symbol(); + let entries = [[0, 1], ["a", 2], [{ + [Symbol.toPrimitive]() { + // The fast path should bail out if a key is a JSReceiver, otherwise + // assumptions about the structure of the iterable can change. If the + // fast path doesn't bail out, the 4th key would be "undefined". + delete entries[3][0]; + entries[3].__proto__ = { 0: "shfifty", }; + return mySymbol; + }, + }, 3], [3, 4]]; + let result = fromEntries(entries); + assertEquals({ + 0: 1, + "a": 2, + [mySymbol]: 3, + "shfifty": 4, + }, result); + assertEquals(["0", "a", "shfifty", mySymbol], Reflect.ownKeys(result)); + }, + + keyToStringMutatesArrayInFastCase() { + let mySymbol = Symbol(); + let entries = [[mySymbol, 1], [0, 2], [{ + toString() { + delete entries[3][0]; + entries[3].__proto__ = { 0: "shfifty", }; + return "z"; + }, + valueOf() { throw new Error("Unused!"); } + }, 3], [3, 4]]; + let result = fromEntries(entries); + assertEquals({ + [mySymbol]: 1, + 0: 2, + "z": 3, + "shfifty": 4, + }, result); + assertEquals(["0", "z", "shfifty", mySymbol], Reflect.ownKeys(result)); + }, + + keyValueOfMutatesArrayInFastCase() { + let mySymbol = Symbol(); + let entries = [[mySymbol, 1], ["z", 2], [{ + toString: undefined, + valueOf() { + delete entries[3][0]; + entries[3].__proto__ = { 0: "shfifty", }; + return 0; + }, + }, 3], [3, 4]]; + let result = fromEntries(entries); + assertEquals({ + [mySymbol]: 1, + "z": 2, + 0: 3, + "shfifty": 4, + }, result); + assertEquals(["0", "z", "shfifty", mySymbol], Reflect.ownKeys(result)); + }, +} + +for (let t of Reflect.ownKeys(test)) { + test[t](); +} diff --git a/implementation-contributed/v8/mjsunit/mjsunit.status b/implementation-contributed/v8/mjsunit/mjsunit.status index 3cf1350206..57633127dd 100644 --- a/implementation-contributed/v8/mjsunit/mjsunit.status +++ b/implementation-contributed/v8/mjsunit/mjsunit.status @@ -57,6 +57,9 @@ # Issue 5495: enable the test when the constant field tracking in enabled. 'const-field-tracking': [SKIP], + # Issue 8505: Math.pow is incorrect for asm.js + 'regress/wasm/regress-8505': [SKIP], + ############################################################################## # Too slow in debug mode with --stress-opt mode. 'regress/regress-create-exception': [PASS, ['mode == debug', SKIP]], @@ -103,12 +106,12 @@ ############################################################################## # Skip long running tests that time out in debug mode. - 'generated-transition-stub': [PASS, ['mode == debug', SKIP]], + 'generated-transition-stub': [PASS, ['mode == debug or dcheck_always_on', SKIP]], 'migrations': [SKIP], - 'array-functions-prototype-misc': [PASS, SLOW, ['mode == debug', SKIP]], - 'compiler/regress-808472': [PASS, ['mode == debug', SKIP]], + 'array-functions-prototype-misc': [PASS, SLOW, ['mode == debug or dcheck_always_on', SKIP]], + 'compiler/regress-808472': [PASS, ['mode == debug or dcheck_always_on', SKIP]], 'es6/promise-all-overflow-1': [SKIP], - 'es6/promise-all-overflow-2': [PASS, SLOW, ['mode == debug or arch != x64', SKIP]], + 'es6/promise-all-overflow-2': [PASS, SLOW, ['mode == debug or dcheck_always_on or arch != x64', SKIP]], ############################################################################## # This test sets the umask on a per-process basis and hence cannot be @@ -765,6 +768,7 @@ # Intentionally non-deterministic using shared arraybuffers. 'wasm/atomics-stress': [SKIP], 'wasm/atomics64-stress': [SKIP], + 'wasm/futex': [SKIP], }], # 'predictable == True' ############################################################################## diff --git a/implementation-contributed/v8/mjsunit/parallel-compile-tasks.js b/implementation-contributed/v8/mjsunit/parallel-compile-tasks.js index 37a6bd8d07..fbde569556 100644 --- a/implementation-contributed/v8/mjsunit/parallel-compile-tasks.js +++ b/implementation-contributed/v8/mjsunit/parallel-compile-tasks.js @@ -58,3 +58,13 @@ assertEquals(c(314), 315); (function() { class foo {}; }); // Don't call IIFE so that it is compiled during idle time + +// http://crbug.com/900535 +(function() { + "use asm"; + function bar(i, j) { + i = i|0; + j = j|0; + } + return {bar: bar}; +}); // Don't call IIFE so that it is compiled during idle time diff --git a/implementation-contributed/v8/mjsunit/regress-906893.js b/implementation-contributed/v8/mjsunit/regress-906893.js new file mode 100644 index 0000000000..4b4942d665 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress-906893.js @@ -0,0 +1,21 @@ +// 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 + +const r = /x/; +let counter = 0; + +r.exec = () => { counter++; return null; } + +function f() { + r.test("ABcd"); +} + +f(); +assertEquals(1, counter); +%OptimizeFunctionOnNextCall(f); + +f(); +assertEquals(2, counter); diff --git a/implementation-contributed/v8/mjsunit/regress-regexp-functional-replace-slow.js b/implementation-contributed/v8/mjsunit/regress-regexp-functional-replace-slow.js new file mode 100644 index 0000000000..033bcee1ef --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress-regexp-functional-replace-slow.js @@ -0,0 +1,7 @@ +// 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. + +/a/.constructor = ""; + +assertEquals("b", "a".replace(/a/, () => "b")); diff --git a/implementation-contributed/v8/mjsunit/regress-v8-8445-2.js b/implementation-contributed/v8/mjsunit/regress-v8-8445-2.js new file mode 100644 index 0000000000..828b877d0c --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress-v8-8445-2.js @@ -0,0 +1,27 @@ +// 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 --harmony-string-matchall + +class MyRegExp { + exec() { return null; } +} + +var r = /c/; + +assertEquals(["ab", ""], "abc".split(r)); +assertEquals([["c"]], [..."c".matchAll(r)]); + +r.constructor = { [Symbol.species] : MyRegExp }; + +assertEquals(["abc"], "abc".split(r)); +assertEquals([], [..."c".matchAll(r)]); + +assertEquals(["ab", ""], "abc".split(/c/)); +assertEquals([["c"]], [..."c".matchAll(/c/)]); + +RegExp.prototype.constructor = { [Symbol.species] : MyRegExp }; + +assertEquals(["abc"], "abc".split(/c/)); +assertEquals([], [..."c".matchAll(/c/)]); diff --git a/implementation-contributed/v8/mjsunit/regress-v8-8445.js b/implementation-contributed/v8/mjsunit/regress-v8-8445.js new file mode 100644 index 0000000000..7641416ba0 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress-v8-8445.js @@ -0,0 +1,17 @@ +// 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 --harmony-string-matchall + +class MyRegExp { + exec() { return null; } +} + +assertEquals(["ab", ""], "abc".split(/c/)); +assertEquals([["a"]], [..."a".matchAll(/a/)]); + +Object.defineProperty(RegExp, Symbol.species, { get() { return MyRegExp; }}); + +assertEquals(["abc"], "abc".split(/c/)); +assertEquals([], [..."a".matchAll(/a/)]); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-3027.js b/implementation-contributed/v8/mjsunit/regress/regress-3027.js index 6336594052..769a29ef55 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-3027.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-3027.js @@ -30,7 +30,7 @@ function boom() { var args = []; - for (var i = 0; i < 125000; i++) { + for (var i = 0; i < 65534; i++) { args.push(i); } return Array.apply(Array, args); @@ -38,5 +38,5 @@ function boom() { var array = boom(); -assertEquals(125000, array.length); -assertEquals(124999, array[124999]); +assertEquals(65534, array.length); +assertEquals(65533, array[65533]); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-331444.js b/implementation-contributed/v8/mjsunit/regress/regress-331444.js index c78d6fb71b..e8fb959eea 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-331444.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-331444.js @@ -29,7 +29,7 @@ function boom() { var args = []; - for (var i = 0; i < 125000; i++) + for (var i = 0; i < 65534; i++) args.push(i); return Array.apply(Array, args); } diff --git a/implementation-contributed/v8/mjsunit/regress/regress-358090.js b/implementation-contributed/v8/mjsunit/regress/regress-358090.js index d9c07e857d..65fec0a618 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-358090.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-358090.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. -var x = Array(100000); +var x = Array(65534); y = Array.apply(Array, x); y.unshift(4); y.shift(); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-732836.js b/implementation-contributed/v8/mjsunit/regress/regress-732836.js index 20e852c317..922a7e2e55 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-732836.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-732836.js @@ -4,7 +4,7 @@ function boom() { var args = []; - for (var i = 0; i < 125000; i++) + for (var i = 0; i < 65534; i++) args.push(1.1); return Array.apply(Array, args); } diff --git a/implementation-contributed/v8/mjsunit/regress/regress-803750.js b/implementation-contributed/v8/mjsunit/regress/regress-803750.js index 3541ff9a35..5a79527825 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-803750.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-803750.js @@ -3,5 +3,5 @@ // found in the LICENSE file. // Verify that very large arrays can be constructed. -assertEquals(Array.isArray(Array.of.apply(Array, Array(65536))), true); -assertEquals(Array.isArray(Array.of.apply(null, Array(65536))), true); +assertEquals(Array.isArray(Array.of.apply(Array, Array(65534))), true); +assertEquals(Array.isArray(Array.of.apply(null, Array(65534))), true); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-852765.js b/implementation-contributed/v8/mjsunit/regress/regress-852765.js index bdd3a9ddb2..393adf2079 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-852765.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-852765.js @@ -3,14 +3,14 @@ // found in the LICENSE file. // The actual regression test -assertThrows("(import(foo)) =>", undefined, "Unexpected token import"); +assertThrows("(import(foo)) =>", undefined, "Invalid destructuring assignment target"); // Other related tests -assertThrows("import(foo) =>", undefined, "Unexpected token import"); -assertThrows("(a, import(foo)) =>", undefined, "Unexpected token import"); -assertThrows("(1, import(foo)) =>", undefined, "Unexpected number"); +assertThrows("import(foo) =>", undefined, "Malformed arrow function parameter list"); +assertThrows("(a, import(foo)) =>", undefined, "Invalid destructuring assignment target"); +assertThrows("(1, import(foo)) =>", undefined, "Invalid destructuring assignment target"); assertThrows("(super(foo)) =>", undefined, "'super' keyword unexpected here"); -assertThrows("(bar(foo)) =>", undefined, "Unexpected token ("); +assertThrows("(bar(foo)) =>", undefined, "Invalid destructuring assignment target"); // No syntax errors assertThrows("[import(foo).then] = [1];", undefined, "foo is not defined"); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-869735.js b/implementation-contributed/v8/mjsunit/regress/regress-869735.js index dfa7b8385b..6fb5b3ed05 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-869735.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-869735.js @@ -10,5 +10,5 @@ function f() { var a = []; %OptimizeFunctionOnNextCall(f); -a.length = 81832; +a.length = 65534; f(...a); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-906406.js b/implementation-contributed/v8/mjsunit/regress/regress-906406.js new file mode 100644 index 0000000000..eb79ff0a0c --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-906406.js @@ -0,0 +1,7 @@ +// 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. + +for (x = 0; x < 10000; ++x) { + [(x) => x, [, 4294967295].find((x) => x), , 2].includes('x', -0); +} diff --git a/implementation-contributed/v8/mjsunit/regress/regress-907575.js b/implementation-contributed/v8/mjsunit/regress/regress-907575.js new file mode 100644 index 0000000000..2f63c3d870 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-907575.js @@ -0,0 +1,6 @@ +// 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. + +assertThrows("0 || () =>", SyntaxError); +assertThrows("++(a) =>", SyntaxError); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-907669.js b/implementation-contributed/v8/mjsunit/regress/regress-907669.js new file mode 100644 index 0000000000..155ff060d3 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-907669.js @@ -0,0 +1,5 @@ +// 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. + +assertThrows("function f() { function g() { (); ", SyntaxError); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-908231.js b/implementation-contributed/v8/mjsunit/regress/regress-908231.js new file mode 100644 index 0000000000..8af5f30591 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-908231.js @@ -0,0 +1,8 @@ +// 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. + +assertThrows(` + class C { + get [(function() { function lazy() { Syntax Error } })()]() {} + }`, SyntaxError) diff --git a/implementation-contributed/v8/mjsunit/regress/regress-908250.js b/implementation-contributed/v8/mjsunit/regress/regress-908250.js new file mode 100644 index 0000000000..78f071d230 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-908250.js @@ -0,0 +1,5 @@ +// 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. + +assertThrows("(al,al,e={}=e)=>l", SyntaxError); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-crbug-614727.js b/implementation-contributed/v8/mjsunit/regress/regress-crbug-614727.js index 0845afc5ac..2a369a2746 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-crbug-614727.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-crbug-614727.js @@ -7,10 +7,7 @@ function f(a, b, c) { return arguments } function g(...args) { return args } -// On 64-bit machine this produces a 768K array which is sufficiently small to -// not cause a stack overflow, but big enough to move the allocated arguments -// object into large object space (kMaxRegularHeapObjectSize == 600K). -var length = Math.pow(2, 15) * 3; +var length = 65534; var args = new Array(length); assertEquals(length, f.apply(null, args).length); assertEquals(length, g.apply(null, args).length); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-crbug-813450.js b/implementation-contributed/v8/mjsunit/regress/regress-crbug-813450.js index b301012950..4efc7494e5 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-crbug-813450.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-crbug-813450.js @@ -4,7 +4,7 @@ // Flags: --allow-natives-syntax -var constructorArgs = new Array(0x10100); +var constructorArgs = new Array(65534); var constructor = function() {}; var target = new Proxy(constructor, { construct: function() { diff --git a/implementation-contributed/v8/mjsunit/regress/regress-crbug-906043.js b/implementation-contributed/v8/mjsunit/regress/regress-crbug-906043.js new file mode 100644 index 0000000000..b18ea5dd7d --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-crbug-906043.js @@ -0,0 +1,54 @@ +// 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 + +function fun(arg) { + let x = arguments.length; + a1 = new Array(0x10); + a1[0] = 1.1; + a2 = new Array(0x10); + a2[0] = 1.1; + a1[(x >> 16) * 21] = 1.39064994160909e-309; // 0xffff00000000 + a1[(x >> 16) * 41] = 8.91238232205e-313; // 0x2a00000000 +} + +var a1, a2; +var a3 = [1.1,2.2]; +a3.length = 0x11000; +a3.fill(3.3); + +var a4 = [1.1]; + +for (let i = 0; i < 3; i++) fun(...a4); +%OptimizeFunctionOnNextCall(fun); +fun(...a4); + +assertThrows(() => fun(...a3), RangeError); +assertThrows(() => fun.apply(null, a3), RangeError); + +const kMaxArguments = 65534; +let big_array = []; +for (let i = 0; i < kMaxArguments + 1; i++) big_array.push(i); +assertThrows(() => fun(...big_array), RangeError); +assertThrows(() => new fun(...big_array), RangeError); +assertThrows(() => fun.apply(null, big_array), RangeError); +assertThrows(() => Reflect.construct(fun, big_array), RangeError); +assertThrows(() => Reflect.apply(fun, undefined, big_array), RangeError); + +big_array = []; +for (let i = 0; i < kMaxArguments + 1; i++) big_array.push(i + 0.1); +assertThrows(() => fun(...big_array), RangeError); +assertThrows(() => new fun(...big_array), RangeError); +assertThrows(() => fun.apply(null, big_array), RangeError); +assertThrows(() => Reflect.construct(fun, big_array), RangeError); +assertThrows(() => Reflect.apply(fun, undefined, big_array), RangeError); + +big_array = []; +for (let i = 0; i < kMaxArguments + 1; i++) big_array.push({i: i}); +assertThrows(() => fun(...big_array), RangeError); +assertThrows(() => new fun(...big_array), RangeError); +assertThrows(() => fun.apply(null, big_array), RangeError); +assertThrows(() => Reflect.construct(fun, big_array), RangeError); +assertThrows(() => Reflect.apply(fun, undefined, big_array), RangeError); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-crbug-906220.js b/implementation-contributed/v8/mjsunit/regress/regress-crbug-906220.js new file mode 100644 index 0000000000..580ff59bdd --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-crbug-906220.js @@ -0,0 +1,12 @@ +// 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 + +function foo() { new Array().pop(); } + +assertEquals(undefined, foo()); +assertEquals(undefined, foo()); +%OptimizeFunctionOnNextCall(foo); +assertEquals(undefined, foo()); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-crbug-906870.js b/implementation-contributed/v8/mjsunit/regress/regress-crbug-906870.js new file mode 100644 index 0000000000..d94ee67a4c --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-crbug-906870.js @@ -0,0 +1,49 @@ +// 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 + +(function() { + function foo() { + return Infinity / Math.max(-0, +0); + } + + assertEquals(+Infinity, foo()); + assertEquals(+Infinity, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(+Infinity, foo()); +})(); + +(function() { + function foo() { + return Infinity / Math.max(+0, -0); + } + + assertEquals(+Infinity, foo()); + assertEquals(+Infinity, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(+Infinity, foo()); +})(); + +(function() { + function foo() { + return Infinity / Math.min(-0, +0); + } + + assertEquals(-Infinity, foo()); + assertEquals(-Infinity, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(-Infinity, foo()); +})(); + +(function() { + function foo() { + return Infinity / Math.min(+0, -0); + } + + assertEquals(-Infinity, foo()); + assertEquals(-Infinity, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(-Infinity, foo()); +})(); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-crbug-908309.js b/implementation-contributed/v8/mjsunit/regress/regress-crbug-908309.js new file mode 100644 index 0000000000..c2d939001d --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-crbug-908309.js @@ -0,0 +1,27 @@ +// 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 + +const p = Object.defineProperty(Promise.resolve(), 'then', { + value() { return 0; } +}); + +(function() { + function foo() { return p.catch().catch(); } + + assertThrows(foo, TypeError); + assertThrows(foo, TypeError); + %OptimizeFunctionOnNextCall(foo); + assertThrows(foo, TypeError); +})(); + +(function() { + function foo() { return p.finally().finally(); } + + assertThrows(foo, TypeError); + assertThrows(foo, TypeError); + %OptimizeFunctionOnNextCall(foo); + assertThrows(foo, TypeError); +})(); diff --git a/implementation-contributed/v8/mjsunit/regress/regress-v8-6716.js b/implementation-contributed/v8/mjsunit/regress/regress-v8-6716.js index 3033fa7c5f..56a7aa3d54 100644 --- a/implementation-contributed/v8/mjsunit/regress/regress-v8-6716.js +++ b/implementation-contributed/v8/mjsunit/regress/regress-v8-6716.js @@ -3,5 +3,5 @@ // found in the LICENSE file. function f() {} -var a = Array(2 ** 16); // Elements in large-object-space. +var a = Array(65534); f.bind(...a); diff --git a/implementation-contributed/v8/mjsunit/regress/wasm/regress-8505.js b/implementation-contributed/v8/mjsunit/regress/wasm/regress-8505.js new file mode 100644 index 0000000000..ebc97a95b4 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/wasm/regress-8505.js @@ -0,0 +1,204 @@ +// 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: --expose-wasm --wasm-math-intrinsics --validate-asm --allow-natives-syntax + +load('test/mjsunit/wasm/wasm-constants.js'); +load('test/mjsunit/wasm/wasm-module-builder.js'); + +function verbose(args) { + // print(...args); +} + +//============================================= +// Global count of failures +//============================================= +let numFailures = 0; + +function reportFailure(name, vals, m, w) { + print(" error: " + name + "(" + vals + ") == " + w + ", expected " + m); + numFailures++; +} + +let global_imports = {Math: Math}; + +let inputs = [ + 1 / 0, + -1 / 0, + 0 / 0, + -2.70497e+38, + -1.4698e+37, + -1.22813e+35, + -1.34584e+34, + -1.0079e+32, + -6.49364e+26, + -3.06077e+25, + -1.46821e+25, + -1.17658e+23, + -1.9617e+22, + -2.7357e+20, + -9223372036854775808.0, // INT64_MIN + -1.48708e+13, + -1.89633e+12, + -4.66622e+11, + -2.22581e+11, + -1.45381e+10, + -2147483904.0, // First float32 after INT32_MIN + -2147483648.0, // INT32_MIN + -2147483520.0, // Last float32 before INT32_MIN + -1.3956e+09, + -1.32951e+09, + -1.30721e+09, + -1.19756e+09, + -9.26822e+08, + -5.09256e+07, + -964300.0, + -192446.0, + -28455.0, + -27194.0, + -20575.0, + -17069.0, + -9167.0, + -960.178, + -113.0, + -62.0, + -15.0, + -7.0, + -1.0, + -0.0256635, + -4.60374e-07, + -3.63759e-10, + -4.30175e-14, + -5.27385e-15, + -1.5707963267948966, + -1.48084e-15, + -2.220446049250313e-16, + -1.05755e-19, + -3.2995e-21, + -1.67354e-23, + -1.11885e-23, + -1.78506e-30, + -1.43718e-34, + -1.27126e-38, + -0.0, + 3e-88, + -2e66, + 0.0, + 2e66, + 1.17549e-38, + 1.56657e-37, + 4.08512e-29, + 6.25073e-22, + 4.1723e-13, + 1.44343e-09, + 1.5707963267948966, + 5.27004e-08, + 9.48298e-08, + 5.57888e-07, + 4.89988e-05, + 0.244326, + 1.0, + 12.4895, + 19.0, + 47.0, + 106.0, + 538.324, + 564.536, + 819.124, + 7048.0, + 12611.0, + 19878.0, + 20309.0, + 797056.0, + 1.77219e+09, + 2147483648.0, // INT32_MAX + 1 + 4294967296.0, // UINT32_MAX + 1 + 1.51116e+11, + 4.18193e+13, + 3.59167e+16, + 9223372036854775808.0, // INT64_MAX + 1 + 18446744073709551616.0, // UINT64_MAX + 1 + 3.38211e+19, + 2.67488e+20, + 1.78831e+21, + 9.20914e+21, + 8.35654e+23, + 1.4495e+24, + 5.94015e+25, + 4.43608e+30, + 2.44502e+33, + 1.38178e+37, + 1.71306e+37, + 3.31899e+38, + 3.40282e+38, +]; + +function assertBinop(name, math_func, wasm_func) { + let inputs2 = [ 1, 0.5, -1, -0.5, 0, -0, 1/0, -1/0, 0/0 ]; + for (val of inputs) { + verbose(" ", val); + for (val2 of inputs2) { + verbose(" ", val2); + let m = math_func(val, val2); + let w = wasm_func(val, val2); + if (!deepEquals(m, w)) reportFailure(name, [val, val2], m, w); + m = math_func(val2, val); + w = wasm_func(val2, val); + if (!deepEquals(m, w)) reportFailure(name, [val2, val], m, w); + } + } +} + +let stdlib = this; +function Module_exp(stdlib) { + "use asm"; + + var Stdlib = stdlib.Math.exp; + + function NAME(a, b) { + a = +a; + b = +b; + return +Stdlib(a, b); + } + + return {exp: exp}; +} + +function wasmBinop(name, sig) { + var builder = new WasmModuleBuilder(); + + var sig_index = builder.addType(sig); + builder.addImport('Math', name, sig_index); + builder.addFunction('main', sig_index) + .addBody([ + kExprGetLocal, 0, // -- + kExprGetLocal, 1, // -- + kExprCallFunction, 0 + ]) // -- + .exportAs('main'); + + return builder.instantiate(global_imports).exports.main; +} + +function asmBinop(name) { + let instance = Module_exp(stdlib); + assertTrue(%IsAsmWasmCode(Module_exp)); + + let asm_func = instance[name]; + if (typeof asm_func != "function") throw "asm[" + full_name + "] not found"; + return asm_func; +} + +(function TestF64() { + let name = 'exp'; + let math_func = Math[name]; + + let wasm_func = wasmBinop(name, kSig_d_dd); + assertBinop("(f64)" + name, math_func, wasm_func); + + let asm_func = asmBinop(name); + assertBinop("(f64)" + name, math_func, asm_func); +})(); + +assertEquals(0, numFailures); diff --git a/implementation-contributed/v8/mjsunit/string-indexof-1.js b/implementation-contributed/v8/mjsunit/string-indexof-1.js index 0267b2c625..64fb8a5c9c 100644 --- a/implementation-contributed/v8/mjsunit/string-indexof-1.js +++ b/implementation-contributed/v8/mjsunit/string-indexof-1.js @@ -133,7 +133,7 @@ assertEquals(-1, asciiString.indexOf("\x2061")); // Search in string containing many non-ASCII chars. var allCodePoints = []; -for (var i = 0; i < 65536; i++) allCodePoints[i] = i; +for (var i = 0; i < 65534; i++) allCodePoints[i] = i; var allCharsString = String.fromCharCode.apply(String, allCodePoints); // Search for string long enough to trigger complex search with ASCII pattern // and UC16 subject. diff --git a/implementation-contributed/v8/test262/BUILD.gn b/implementation-contributed/v8/test262/BUILD.gn index 334511168d..093e489df0 100644 --- a/implementation-contributed/v8/test262/BUILD.gn +++ b/implementation-contributed/v8/test262/BUILD.gn @@ -15,9 +15,10 @@ group("v8_test262") { "detachArrayBuffer.js", "harness/", "harness-adapt.js", + "harness-adapt-donotevaluate.js", "harness-agent.js", "test262.status", "testcfg.py", "local-tests/", ] -} \ No newline at end of file +} diff --git a/implementation-contributed/v8/test262/harness-adapt-donotevaluate.js b/implementation-contributed/v8/test262/harness-adapt-donotevaluate.js new file mode 100644 index 0000000000..d489c0008c --- /dev/null +++ b/implementation-contributed/v8/test262/harness-adapt-donotevaluate.js @@ -0,0 +1,12 @@ +// 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. + +// V8 has several long-standing bugs where "early errors", i.e. errors that are +// supposed to be thrown at parse time, end up being thrown at runtime instead. +// This file is used to implement the FAIL_PHASE_ONLY outcome as used in +// test/test262/test262.status. Tests marked with this outcome are run in a +// special mode that verifies that a) V8 throws an exception at all, and b) that +// the exception has the correct type, but ignores the fact that they are thrown +// after parsing is done. See crbug.com/v8/8467 for details. +$DONOTEVALUATE = () => {}; diff --git a/implementation-contributed/v8/test262/test262.status b/implementation-contributed/v8/test262/test262.status index 708542fcbb..cff892bbec 100644 --- a/implementation-contributed/v8/test262/test262.status +++ b/implementation-contributed/v8/test262/test262.status @@ -178,7 +178,7 @@ 'language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order': [FAIL], # https://bugs.chromium.org/p/v8/issues/detail?id=896 - 'built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F': [FAIL], + 'built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F': [FAIL_PHASE_ONLY], 'built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F-negated': [FAIL], 'built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Invalid': [FAIL], 'built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Invalid-negated': [FAIL], diff --git a/implementation-contributed/v8/test262/testcfg.py b/implementation-contributed/v8/test262/testcfg.py index 89f3874c10..e62759885a 100644 --- a/implementation-contributed/v8/test262/testcfg.py +++ b/implementation-contributed/v8/test262/testcfg.py @@ -57,10 +57,10 @@ FEATURE_FLAGS = { 'globalThis': '--harmony-global', 'well-formed-json-stringify': '--harmony-json-stringify', 'export-star-as-namespace-from-module': '--harmony-namespace-exports', + 'Object.fromEntries': '--harmony-object-from-entries', } -SKIPPED_FEATURES = set(['Object.fromEntries', - 'class-fields-private', +SKIPPED_FEATURES = set(['class-fields-private', 'class-static-fields-private', 'class-methods-private', 'class-static-methods-private']) @@ -173,6 +173,8 @@ class TestCase(testcase.D8TestCase): list(self.suite.harness) + ([os.path.join(self.suite.root, "harness-agent.js")] if self.path.startswith('built-ins/Atomics') else []) + + ([os.path.join(self.suite.root, "harness-adapt-donotevaluate.js")] + if self.fail_phase_only else []) + self._get_includes() + (["--module"] if "module" in self.test_record else []) + [self._get_source_path()]