diff options
Diffstat (limited to 'deps/v8/test/mjsunit/compiler')
40 files changed, 3800 insertions, 9 deletions
diff --git a/deps/v8/test/mjsunit/compiler/abstract-equal-symbol.js b/deps/v8/test/mjsunit/compiler/abstract-equal-symbol.js new file mode 100644 index 0000000000..c1057e1d1b --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/abstract-equal-symbol.js @@ -0,0 +1,135 @@ +// 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 --opt --noalways-opt + +// Known symbols abstract equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo() { return a == b; } + + assertFalse(foo()); + assertFalse(foo()); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo()); +})(); + +// Known symbols abstract in-equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo() { return a != b; } + + assertTrue(foo()); + assertTrue(foo()); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo()); +})(); + +// Known symbol on one side abstract equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo(a) { return a == b; } + + // Warmup + assertTrue(foo(b)); + assertFalse(foo(a)); + assertTrue(foo(b)); + assertFalse(foo(a)); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(b)); + assertFalse(foo(a)); + assertOptimized(foo); + + // Make optimized code bail out + assertFalse(foo("a")); + assertUnoptimized(foo); + + // Make sure TurboFan learns the new feedback + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo("a")); + assertOptimized(foo); +})(); + +// Known symbol on one side abstract in-equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo(a) { return a != b; } + + // Warmup + assertFalse(foo(b)); + assertTrue(foo(a)); + assertFalse(foo(b)); + assertTrue(foo(a)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(b)); + assertTrue(foo(a)); + + // Make optimized code bail out + assertTrue(foo("a")); + assertUnoptimized(foo); + + // Make sure TurboFan learns the new feedback + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo("a")); + assertOptimized(foo); +})(); + +// Feedback based symbol abstract equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo(a, b) { return a == b; } + + // Warmup + assertTrue(foo(b, b)); + assertFalse(foo(a, b)); + assertTrue(foo(a, a)); + assertFalse(foo(b, a)); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(a, a)); + assertFalse(foo(b, a)); + + // Make optimized code bail out + assertFalse(foo("a", b)); + assertUnoptimized(foo); + + // Make sure TurboFan learns the new feedback + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo("a", b)); + assertOptimized(foo); +})(); + +// Feedback based symbol abstract in-equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo(a, b) { return a != b; } + + assertFalse(foo(b, b)); + assertTrue(foo(a, b)); + assertFalse(foo(a, a)); + assertTrue(foo(b, a)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(a, a)); + assertTrue(foo(b, a)); + + // Make optimized code bail out + assertTrue(foo("a", b)); + assertUnoptimized(foo); + + // Make sure TurboFan learns the new feedback + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo("a", b)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/array-buffer-is-view.js b/deps/v8/test/mjsunit/compiler/array-buffer-is-view.js new file mode 100644 index 0000000000..b56763b5b2 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/array-buffer-is-view.js @@ -0,0 +1,64 @@ +// 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 --opt + +// Test that ObjectIsArrayBufferView lowering works correctly +// in EffectControlLinearizer in the case that the input is +// known to be a HeapObject by TurboFan. For this we use the +// simple trick with an object literal whose field `x` will +// only ever contain HeapObjects and so the representation +// tracking is going to pick it up. +(function() { + function foo(x) { + return ArrayBuffer.isView({x}.x); + } + + assertFalse(foo(Symbol())); + assertFalse(foo("some string")); + assertFalse(foo(new Object())); + assertFalse(foo(new Array())); + assertFalse(foo(new ArrayBuffer(1))); + assertTrue(foo(new Int32Array(1))); + assertTrue(foo(new DataView(new ArrayBuffer(1)))); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(Symbol())); + assertFalse(foo("some string")); + assertFalse(foo(new Object())); + assertFalse(foo(new Array())); + assertFalse(foo(new ArrayBuffer(1))); + assertTrue(foo(new Int32Array(1))); + assertTrue(foo(new DataView(new ArrayBuffer(1)))); + assertOptimized(foo); +})(); + +// Test that ObjectIsArrayBufferView lowering works correctly +// in EffectControlLinearizer in the case that the input is +// some arbitrary tagged value. +(function() { + function foo(x) { + return ArrayBuffer.isView(x); + } + + assertFalse(foo(1)); + assertFalse(foo(1.1)); + assertFalse(foo(Symbol())); + assertFalse(foo("some string")); + assertFalse(foo(new Object())); + assertFalse(foo(new Array())); + assertFalse(foo(new ArrayBuffer(1))); + assertTrue(foo(new Int32Array(1))); + assertTrue(foo(new DataView(new ArrayBuffer(1)))); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(1)); + assertFalse(foo(1.1)); + assertFalse(foo(Symbol())); + assertFalse(foo("some string")); + assertFalse(foo(new Object())); + assertFalse(foo(new Array())); + assertFalse(foo(new ArrayBuffer(1))); + assertTrue(foo(new Int32Array(1))); + assertTrue(foo(new DataView(new ArrayBuffer(1)))); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/array-is-array.js b/deps/v8/test/mjsunit/compiler/array-is-array.js new file mode 100644 index 0000000000..37c916ddac --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/array-is-array.js @@ -0,0 +1,105 @@ +// 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 + +// Test JSObjectIsArray in JSTypedLowering for the case that the +// input value is known to be an Array literal. +(function() { + function foo() { + return Array.isArray([]); + } + + assertTrue(foo()); + assertTrue(foo()); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo()); +})(); + +// Test JSObjectIsArray in JSTypedLowering for the case that the +// input value is known to be a Proxy for an Array literal. +(function() { + function foo() { + return Array.isArray(new Proxy([], {})); + } + + assertTrue(foo()); + assertTrue(foo()); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo()); +})(); + +// Test JSObjectIsArray in JSTypedLowering for the case that the +// input value is known to be an Object literal. +(function() { + function foo() { + return Array.isArray({}); + } + + assertFalse(foo()); + assertFalse(foo()); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo()); +})(); + +// Test JSObjectIsArray in JSTypedLowering for the case that the +// input value is known to be a Proxy for an Object literal. +(function() { + function foo() { + return Array.isArray(new Proxy({}, {})); + } + + assertFalse(foo()); + assertFalse(foo()); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo()); +})(); + +// Test JSObjectIsArray in JSTypedLowering for the case that +// TurboFan doesn't know anything about the input value. +(function() { + function foo(x) { + return Array.isArray(x); + } + + assertFalse(foo({})); + assertFalse(foo(new Proxy({}, {}))); + assertTrue(foo([])); + assertTrue(foo(new Proxy([], {}))); + assertThrows(() => { + const {proxy, revoke} = Proxy.revocable([], {}); + revoke(); + foo(proxy); + }, TypeError); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo({})); + assertFalse(foo(new Proxy({}, {}))); + assertTrue(foo([])); + assertTrue(foo(new Proxy([], {}))); + assertThrows(() => { + const {proxy, revoke} = Proxy.revocable([], {}); + revoke(); + foo(proxy); + }, TypeError); +})(); + +// Test JSObjectIsArray in JSTypedLowering for the case that +// we pass a revoked proxy and catch the exception locally. +(function() { + function foo(x) { + const {proxy, revoke} = Proxy.revocable(x, {}); + revoke(); + try { + return Array.isArray(proxy); + } catch (e) { + return e; + } + } + + assertInstanceof(foo([]), TypeError); + assertInstanceof(foo({}), TypeError); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo([]), TypeError); + assertInstanceof(foo({}), TypeError); +})(); diff --git a/deps/v8/test/mjsunit/compiler/context-sensitivity.js b/deps/v8/test/mjsunit/compiler/context-sensitivity.js new file mode 100644 index 0000000000..1f0f1f274a --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/context-sensitivity.js @@ -0,0 +1,550 @@ +// 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 object1 = {[Symbol.toPrimitive]() { return 1; }}; +const thrower = {[Symbol.toPrimitive]() { throw new Error(); }}; + +// Test that JSAdd is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y + x); + } + + assertEquals(1, foo(0)); + assertEquals(2, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(0)); + assertEquals(2, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSSubtract is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y - x); + } + + assertEquals(1, foo(0)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(0)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSMultiply is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y * x); + } + + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSDivide is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y / x); + } + + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSModulus is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y % x); + } + + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSExponentiate is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y ** x); + } + + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSBitwiseOr is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y | x); + } + + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSBitwiseAnd is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y & x); + } + + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSBitwiseXor is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y ^ x); + } + + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSShiftLeft is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y << x); + } + + assertEquals(2, foo(1)); + assertEquals(2, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(1)); + assertEquals(2, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSShiftRight is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y >> x); + } + + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSShiftRightLogical is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y >>> x); + } + + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(1)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSEqual is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y == x); + } + + assertFalse(foo(0)); + assertTrue(foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(0)); + assertTrue(foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSLessThan is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y < x); + } + + assertFalse(foo(0)); + assertFalse(foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(0)); + assertFalse(foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSGreaterThan is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => x > y); + } + + assertFalse(foo(0)); + assertFalse(foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(0)); + assertFalse(foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSLessThanOrEqual is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => y <= x); + } + + assertFalse(foo(0)); + assertTrue(foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(0)); + assertTrue(foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSGreaterThanOrEqual is not context-sensitive. +(function() { + function bar(fn) { + return fn(1); + } + + function foo(x) { + return bar(y => x >= y); + } + + assertFalse(foo(0)); + assertTrue(foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(0)); + assertTrue(foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSInstanceOf is not context-sensitive. +(function() { + function bar(fn) { + return fn({}); + } + + function foo(c) { + return bar(o => o instanceof c); + } + + assertTrue(foo(Object)); + assertFalse(foo(Array)); + assertThrows(() => foo({[Symbol.hasInstance]() { throw new Error(); }})); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(Object)); + assertFalse(foo(Array)); + assertThrows(() => foo({[Symbol.hasInstance]() { throw new Error(); }})); +})(); + +// Test that JSBitwiseNot is not context-sensitive. +(function() { + function bar(fn) { + return fn(); + } + + function foo(x) { + return bar(() => ~x); + } + + assertEquals(0, foo(-1)); + assertEquals(~1, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(-1)); + assertEquals(~1, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSNegate is not context-sensitive. +(function() { + function bar(fn) { + return fn(); + } + + function foo(x) { + return bar(() => -x); + } + + assertEquals(1, foo(-1)); + assertEquals(-1, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(-1)); + assertEquals(-1, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSIncrement is not context-sensitive. +(function() { + function bar(fn) { + return fn(); + } + + function foo(x) { + return bar(() => ++x); + } + + assertEquals(1, foo(0)); + assertEquals(2, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(0)); + assertEquals(2, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSDecrement is not context-sensitive. +(function() { + function bar(fn) { + return fn(); + } + + function foo(x) { + return bar(() => --x); + } + + assertEquals(1, foo(2)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(2)); + assertEquals(0, foo(object1)); + assertThrows(() => foo(thrower)); +})(); + +// Test that JSCreateArguments[UnmappedArguments] is not context-sensitive. +(function() { + function bar(fn) { + return fn(); + } + + function foo() { + "use strict"; + return bar(() => arguments)[0]; + } + + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 2)); + assertEquals(undefined, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 2)); + assertEquals(undefined, foo()); +})(); + +// Test that JSCreateArguments[RestParameters] is not context-sensitive. +(function() { + function bar(fn) { + return fn(); + } + + function foo(...args) { + return bar(() => args)[0]; + } + + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 2)); + assertEquals(undefined, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 2)); + assertEquals(undefined, foo()); +})(); + +// Test that JSLoadGlobal/JSStoreGlobal are not context-sensitive. +(function(global) { + var actualValue = 'Some value'; + + Object.defineProperty(global, 'globalValue', { + configurable: true, + enumerable: true, + get: function() { + return actualValue; + }, + set: function(v) { + actualValue = v; + } + }); + + function bar(fn) { + return fn(); + } + + function foo(v) { + return bar(() => { + const o = globalValue; + globalValue = v; + return o; + }); + } + + assertEquals('Some value', foo('Another value')); + assertEquals('Another value', actualValue); + assertEquals('Another value', foo('Some value')); + assertEquals('Some value', actualValue); + %OptimizeFunctionOnNextCall(foo); + assertEquals('Some value', foo('Another value')); + assertEquals('Another value', actualValue); + assertEquals('Another value', foo('Some value')); + assertEquals('Some value', actualValue); +})(this); + +// Test that for..in is not context-sensitive. +(function() { + function bar(fn) { + return fn(); + } + + function foo(o) { + return bar(() => { + var s = ""; + for (var k in o) { s += k; } + return s; + }); + } + + assertEquals('abc', foo({a: 1, b: 2, c: 3})); + assertEquals('ab', foo(Object.create({a: 1, b: 2}))); + %OptimizeFunctionOnNextCall(foo); + assertEquals('abc', foo({a: 1, b: 2, c: 3})); + assertEquals("ab", foo(Object.create({a:1, b:2}))); +})(); + +// Test that most generator operations are not context-sensitive. +(function() { + function bar(fn) { + let s = undefined; + for (const x of fn()) { + if (s === undefined) s = x; + else s += x; + } + return s; + } + + function foo(x, y, z) { + return bar(function*() { + yield x; + yield y; + yield z; + }); + } + + assertEquals(6, foo(1, 2, 3)); + assertEquals("abc", foo("a", "b", "c")); + %OptimizeFunctionOnNextCall(foo); + assertEquals(6, foo(1, 2, 3)); + assertEquals("abc", foo("a", "b", "c")); +})(); diff --git a/deps/v8/test/mjsunit/compiler/dataview-constant.js b/deps/v8/test/mjsunit/compiler/dataview-constant.js new file mode 100644 index 0000000000..f5f0b5e955 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/dataview-constant.js @@ -0,0 +1,173 @@ +// 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 + +// Test DataView.prototype.getInt8()/setInt8() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setInt8(0, 42); + dv.setInt8(1, 24); + + function foo(i) { + const x = dv.getInt8(i); + dv.setInt8(i, x+1); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(1)); + assertEquals(43, foo(0)); + assertEquals(25, foo(1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(1)); +})(); + +// Test DataView.prototype.getUint8()/setUint8() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setUint8(0, 42); + dv.setUint8(1, 24); + + function foo(i) { + const x = dv.getUint8(i); + dv.setUint8(i, x+1); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(1)); + assertEquals(43, foo(0)); + assertEquals(25, foo(1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(1)); +})(); + +// Test DataView.prototype.getInt16()/setInt16() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setInt16(0, 42, true); + dv.setInt16(2, 24, true); + + function foo(i) { + const x = dv.getInt16(i, true); + dv.setInt16(i, x+1, true); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(2)); + assertEquals(43, foo(0)); + assertEquals(25, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(2)); +})(); + +// Test DataView.prototype.getUint16()/setUint16() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setUint16(0, 42, true); + dv.setUint16(2, 24, true); + + function foo(i) { + const x = dv.getUint16(i, true); + dv.setUint16(i, x+1, true); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(2)); + assertEquals(43, foo(0)); + assertEquals(25, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(2)); +})(); + +// Test DataView.prototype.getInt32()/setInt32() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setInt32(0, 42, true); + dv.setInt32(4, 24, true); + + function foo(i) { + const x = dv.getInt32(i, true); + dv.setInt32(i, x+1, true); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(4)); + assertEquals(43, foo(0)); + assertEquals(25, foo(4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(4)); +})(); + +// Test DataView.prototype.getUint32()/setUint32() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setUint32(0, 42, true); + dv.setUint32(4, 24, true); + + function foo(i) { + const x = dv.getUint32(i, true); + dv.setUint32(i, x+1, true); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(4)); + assertEquals(43, foo(0)); + assertEquals(25, foo(4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(4)); +})(); + +// Test DataView.prototype.getFloat32()/setFloat32() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setFloat32(0, 42, true); + dv.setFloat32(4, 24, true); + + function foo(i) { + const x = dv.getFloat32(i, true); + dv.setFloat32(i, x+1, true); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(4)); + assertEquals(43, foo(0)); + assertEquals(25, foo(4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(4)); +})(); + +// Test DataView.prototype.getFloat64()/setFloat64() for constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setFloat64(0, 42, true); + dv.setFloat64(8, 24, true); + + function foo(i) { + const x = dv.getFloat64(i, true); + dv.setFloat64(i, x+1, true); + return x; + } + + assertEquals(42, foo(0)); + assertEquals(24, foo(8)); + assertEquals(43, foo(0)); + assertEquals(25, foo(8)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(0)); + assertEquals(26, foo(8)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/dataview-neutered.js b/deps/v8/test/mjsunit/compiler/dataview-neutered.js new file mode 100644 index 0000000000..54b35f73c8 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/dataview-neutered.js @@ -0,0 +1,376 @@ +// 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 --opt --noalways-opt + +// Invalidate the neutering protector. +%ArrayBufferNeuter(new ArrayBuffer(1)); + +// Check DataView.prototype.getInt8() optimization. +(function() { + const ab = new ArrayBuffer(1); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getInt8(0); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.getUint8() optimization. +(function() { + const ab = new ArrayBuffer(1); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getUint8(0); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.getInt16() optimization. +(function() { + const ab = new ArrayBuffer(2); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getInt16(0, true); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.getUint16() optimization. +(function() { + const ab = new ArrayBuffer(2); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getUint16(0, true); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.getInt32() optimization. +(function() { + const ab = new ArrayBuffer(4); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getInt32(0, true); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.getUint32() optimization. +(function() { + const ab = new ArrayBuffer(4); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getUint32(0, true); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.getFloat32() optimization. +(function() { + const ab = new ArrayBuffer(4); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getFloat32(0, true); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.getFloat64() optimization. +(function() { + const ab = new ArrayBuffer(8); + const dv = new DataView(ab); + + function foo(dv) { + return dv.getFloat64(0, true); + } + + assertEquals(0, foo(dv)); + assertEquals(0, foo(dv)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(dv)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setInt8() optimization. +(function() { + const ab = new ArrayBuffer(1); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setInt8(0, x); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getInt8(0)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getInt8(0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setUint8() optimization. +(function() { + const ab = new ArrayBuffer(1); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setUint8(0, x); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getUint8(0)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getUint8(0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setInt16() optimization. +(function() { + const ab = new ArrayBuffer(2); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setInt16(0, x, true); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getInt16(0, true)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getInt16(0, true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setUint16() optimization. +(function() { + const ab = new ArrayBuffer(2); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setUint16(0, x, true); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getUint16(0, true)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getUint16(0, true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setInt32() optimization. +(function() { + const ab = new ArrayBuffer(4); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setInt32(0, x, true); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getInt32(0, true)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getInt32(0, true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setUint32() optimization. +(function() { + const ab = new ArrayBuffer(4); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setUint32(0, x, true); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getUint32(0, true)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getUint32(0, true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setFloat32() optimization. +(function() { + const ab = new ArrayBuffer(4); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setFloat32(0, x, true); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getFloat32(0, true)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getFloat32(0, true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); + +// Check DataView.prototype.setFloat64() optimization. +(function() { + const ab = new ArrayBuffer(8); + const dv = new DataView(ab); + + function foo(dv, x) { + return dv.setFloat64(0, x, true); + } + + assertEquals(undefined, foo(dv, 1)); + assertEquals(1, dv.getFloat64(0, true)); + assertEquals(undefined, foo(dv, 2)); + assertEquals(2, dv.getFloat64(0, true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(undefined, foo(dv, 3)); + assertOptimized(foo); + %ArrayBufferNeuter(ab); + assertThrows(() => foo(dv, 4), TypeError); + assertUnoptimized(foo); + %OptimizeFunctionOnNextCall(foo); + assertThrows(() => foo(dv, 5), TypeError); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/dataview-nonconstant.js b/deps/v8/test/mjsunit/compiler/dataview-nonconstant.js new file mode 100644 index 0000000000..0420660c83 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/dataview-nonconstant.js @@ -0,0 +1,173 @@ +// 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 + +// Test DataView.prototype.getInt8()/setInt8() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setInt8(0, 42); + dv.setInt8(1, 24); + + function foo(dv, i) { + const x = dv.getInt8(i); + dv.setInt8(i, x+1); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 1)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 1)); +})(); + +// Test DataView.prototype.getUint8()/setUint8() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setUint8(0, 42); + dv.setUint8(1, 24); + + function foo(dv, i) { + const x = dv.getUint8(i); + dv.setUint8(i, x+1); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 1)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 1)); +})(); + +// Test DataView.prototype.getInt16()/setInt16() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setInt16(0, 42, true); + dv.setInt16(2, 24, true); + + function foo(dv, i) { + const x = dv.getInt16(i, true); + dv.setInt16(i, x+1, true); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 2)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 2)); +})(); + +// Test DataView.prototype.getUint16()/setUint16() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setUint16(0, 42, true); + dv.setUint16(2, 24, true); + + function foo(dv, i) { + const x = dv.getUint16(i, true); + dv.setUint16(i, x+1, true); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 2)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 2)); +})(); + +// Test DataView.prototype.getInt32()/setInt32() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setInt32(0, 42, true); + dv.setInt32(4, 24, true); + + function foo(dv, i) { + const x = dv.getInt32(i, true); + dv.setInt32(i, x+1, true); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 4)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 4)); +})(); + +// Test DataView.prototype.getUint32()/setUint32() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setUint32(0, 42, true); + dv.setUint32(4, 24, true); + + function foo(dv, i) { + const x = dv.getUint32(i, true); + dv.setUint32(i, x+1, true); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 4)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 4)); +})(); + +// Test DataView.prototype.getFloat32()/setFloat32() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setFloat32(0, 42, true); + dv.setFloat32(4, 24, true); + + function foo(dv, i) { + const x = dv.getFloat32(i, true); + dv.setFloat32(i, x+1, true); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 4)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 4)); +})(); + +// Test DataView.prototype.getFloat64()/setFloat64() for non-constant DataViews. +(function() { + const dv = new DataView(new ArrayBuffer(1024)); + dv.setFloat64(0, 42, true); + dv.setFloat64(8, 24, true); + + function foo(dv, i) { + const x = dv.getFloat64(i, true); + dv.setFloat64(i, x+1, true); + return x; + } + + assertEquals(42, foo(dv, 0)); + assertEquals(24, foo(dv, 8)); + assertEquals(43, foo(dv, 0)); + assertEquals(25, foo(dv, 8)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(44, foo(dv, 0)); + assertEquals(26, foo(dv, 8)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/escape-analysis-arguments.js b/deps/v8/test/mjsunit/compiler/escape-analysis-arguments.js index f520167e19..65e736c706 100644 --- a/deps/v8/test/mjsunit/compiler/escape-analysis-arguments.js +++ b/deps/v8/test/mjsunit/compiler/escape-analysis-arguments.js @@ -185,3 +185,56 @@ %OptimizeFunctionOnNextCall(f); f(); f(); })(); + +// Test variable index access to strict arguments +// with up to 2 elements. +(function testArgumentsVariableIndexStrict() { + function g() { + "use strict"; + var s = 0; + for (var i = 0; i < arguments.length; ++i) s += arguments[i]; + return s; + } + + function f(x, y) { + // (a) arguments[i] is dead code since arguments.length is 0. + const a = g(); + // (b) arguments[i] always yields the first element. + const b = g(x); + // (c) arguments[i] can yield either x or y. + const c = g(x, y); + return a + b + c; + } + + assertEquals(4, f(1, 2)); + assertEquals(5, f(2, 1)); + %OptimizeFunctionOnNextCall(f); + assertEquals(4, f(1, 2)); + assertEquals(5, f(2, 1)); +})(); + +// Test variable index access to sloppy arguments +// with up to 2 elements. +(function testArgumentsVariableIndexSloppy() { + function g() { + var s = 0; + for (var i = 0; i < arguments.length; ++i) s += arguments[i]; + return s; + } + + function f(x, y) { + // (a) arguments[i] is dead code since arguments.length is 0. + const a = g(); + // (b) arguments[i] always yields the first element. + const b = g(x); + // (c) arguments[i] can yield either x or y. + const c = g(x, y); + return a + b + c; + } + + assertEquals(4, f(1, 2)); + assertEquals(5, f(2, 1)); + %OptimizeFunctionOnNextCall(f); + assertEquals(4, f(1, 2)); + assertEquals(5, f(2, 1)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/escape-analysis-array.js b/deps/v8/test/mjsunit/compiler/escape-analysis-array.js new file mode 100644 index 0000000000..2c44fa8c9b --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/escape-analysis-array.js @@ -0,0 +1,32 @@ +// 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 + +// Test variable index access to array with 1 element. +(function testOneElementArrayVariableIndex() { + function f(i) { + const a = new Array("first"); + return a[i]; + } + + assertEquals("first", f(0)); + assertEquals("first", f(0)); + %OptimizeFunctionOnNextCall(f); + assertEquals("first", f(0)); +})(); + +// Test variable index access to array with 2 elements. +(function testTwoElementArrayVariableIndex() { + function f(i) { + const a = new Array("first", "second"); + return a[i]; + } + + assertEquals("first", f(0)); + assertEquals("second", f(1)); + %OptimizeFunctionOnNextCall(f); + assertEquals("first", f(0)); + assertEquals("second", f(1)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/escape-analysis-rest-parameters.js b/deps/v8/test/mjsunit/compiler/escape-analysis-rest-parameters.js new file mode 100644 index 0000000000..2ac1253a18 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/escape-analysis-rest-parameters.js @@ -0,0 +1,31 @@ +// 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 + +// Test variable index access to rest parameters +// with up to 2 elements. +(function testRestParametersVariableIndex() { + function g(...args) { + let s = 0; + for (let i = 0; i < args.length; ++i) s += args[i]; + return s; + } + + function f(x, y) { + // (a) args[i] is dead code since args.length is 0. + const a = g(); + // (b) args[i] always yields the first element. + const b = g(x); + // (c) args[i] can yield either x or y. + const c = g(x, y); + return a + b + c; + } + + assertEquals(4, f(1, 2)); + assertEquals(5, f(2, 1)); + %OptimizeFunctionOnNextCall(f); + assertEquals(4, f(1, 2)); + assertEquals(5, f(2, 1)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/instanceof2.js b/deps/v8/test/mjsunit/compiler/instanceof2.js new file mode 100644 index 0000000000..ca006e3046 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/instanceof2.js @@ -0,0 +1,233 @@ +// 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 + + +// Without instance creation: + +(function() { + function Goo() {}; + const goo = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + const goo = {}; + Goo.prototype = Object.prototype; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + const goo = {}; + Goo.prototype = 42 + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); +})(); + +(function() { + function Goo() {}; + const goo = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + const goo = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); + Goo.prototype = 42; + assertThrows(_ => IsGoo(goo), TypeError); +})(); + + +// With instance creation: + +(function() { + function Goo() {}; + const goo = new Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + const goo = new Goo(); + Goo.prototype = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + const goo = new Goo(); + Goo.prototype = 42; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); +})(); + +(function() { + function Goo() {}; + const goo = new Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); + Goo.prototype = {}; + assertFalse(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + const goo = new Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); + Goo.prototype = 42 + assertThrows(_ => IsGoo(goo), TypeError); +})(); + +(function() { + function Goo() {}; + Goo.prototype = 42; + const goo = new Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); + Goo.prototype = {}; + assertFalse(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + Goo.prototype = 42; + const goo = new Goo(); + Goo.prototype = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + Goo.prototype = {}; + const goo = new Goo(); + Goo.prototype = 42; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); + +(function() { + function Goo() {}; + Goo.prototype = {}; + const goo = new Goo(); + Goo.prototype = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/instanceof3.js b/deps/v8/test/mjsunit/compiler/instanceof3.js new file mode 100644 index 0000000000..e390c42092 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/instanceof3.js @@ -0,0 +1,233 @@ +// 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 + + +// Without instance creation: + +(function() { + function* Goo() {}; + const goo = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + const goo = {}; + Goo.prototype = Object.prototype; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + const goo = {}; + Goo.prototype = 42 + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); +})(); + +(function() { + function* Goo() {}; + const goo = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + const goo = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); + Goo.prototype = 42; + assertThrows(_ => IsGoo(goo), TypeError); +})(); + + +// With instance creation: + +(function() { + function* Goo() {}; + const goo = Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + const goo = Goo(); + Goo.prototype = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + const goo = Goo(); + Goo.prototype = 42; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); +})(); + +(function() { + function* Goo() {}; + const goo = Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); + Goo.prototype = {}; + assertFalse(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + const goo = Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertTrue(IsGoo(goo)); + assertTrue(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertTrue(IsGoo(goo)); + Goo.prototype = 42 + assertThrows(_ => IsGoo(goo), TypeError); +})(); + +(function() { + function* Goo() {}; + Goo.prototype = 42; + const goo = Goo(); + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); + Goo.prototype = {}; + assertFalse(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + Goo.prototype = 42; + const goo = Goo(); + Goo.prototype = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + assertFalse(IsGoo(goo)); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + Goo.prototype = {}; + const goo = Goo(); + Goo.prototype = 42; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertThrows(_ => IsGoo(goo), TypeError); + assertThrows(_ => IsGoo(goo), TypeError); + %OptimizeFunctionOnNextCall(IsGoo); + assertThrows(_ => IsGoo(goo), TypeError); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); + +(function() { + function* Goo() {}; + Goo.prototype = {}; + const goo = Goo(); + Goo.prototype = {}; + + function IsGoo(x) { + return x instanceof Goo; + } + + assertFalse(IsGoo(goo)); + assertFalse(IsGoo(goo)); + %OptimizeFunctionOnNextCall(IsGoo); + Goo.prototype = Object.prototype; + assertTrue(IsGoo(goo)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/int64.js b/deps/v8/test/mjsunit/compiler/int64.js new file mode 100644 index 0000000000..0a88a95895 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/int64.js @@ -0,0 +1,91 @@ +// 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 + +// Test NumberAdd with PositiveSafeInteger -> PositiveSafeInteger (as Tagged). +(function() { + function foo(x) { + const i = x ? 0xFFFFFFFF : 0; + return i + 1; + } + + assertEquals(0x000000001, foo(false)); + assertEquals(0x000000001, foo(false)); + assertEquals(0x100000000, foo(true)); + assertEquals(0x100000000, foo(true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0x000000001, foo(false)); + assertEquals(0x100000000, foo(true)); +})(); + +// Test NumberAdd with SafeInteger -> SafeInteger (as Tagged). +(function() { + function foo(x) { + const i = x ? 0xFFFFFFFF : -1; + return i + 1; + } + + assertEquals(0x000000000, foo(false)); + assertEquals(0x000000000, foo(false)); + assertEquals(0x100000000, foo(true)); + assertEquals(0x100000000, foo(true)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0x000000000, foo(false)); + assertEquals(0x100000000, foo(true)); +})(); + +// NumberAdd: Smi x Unsigned32 -> SafeInteger (as Float64). +(function() { + const a = new Float64Array(1); + + function foo(o) { + a[0] = o.x + 0xFFFFFFFF; + return a[0]; + } + + assertEquals(0x0FFFFFFFF, foo({x:0})); + assertEquals(0x100000000, foo({x:1})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0x100000000, foo({x:1})); +})(); + +// NumberAdd: Smi x Unsigned32 -> SafeInteger (as TaggedSigned). +(function() { + function foo(o) { + return {x: Math.floor((o.x + 11123456789) + -11123456788)}.x; + } + + assertEquals(1, foo({x:0})); + assertEquals(2, foo({x:1})); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo({x:1})); +})(); + +// NumberSubtract: Unsigned32 x Unsigned32 -> SafeInteger (as Word32). +(function() { + function foo(a, i) { + i = ((i >>> 0)) - 0xFFFFFFFF; + return a[i]; + } + + assertEquals(1, foo([1], 0xFFFFFFFF)); + assertEquals(2, foo([2], 0xFFFFFFFF)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo([3], 0xFFFFFFFF)); +})(); + +// Test that the Deoptimizer can handle Word64 properly. +(function() { + function foo(b) { + const i = ((b >>> 0)) - 0xFFFFFFFF; + %DeoptimizeFunction(foo); + return i; + } + + assertEquals(0, foo(0xFFFFFFFF)); + assertEquals(0, foo(0xFFFFFFFF)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(0xFFFFFFFF)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/math-imul.js b/deps/v8/test/mjsunit/compiler/math-imul.js new file mode 100644 index 0000000000..1de18a6a2d --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/math-imul.js @@ -0,0 +1,76 @@ +// 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 --opt + +// Test Math.imul() with no inputs. +(function() { + function foo() { return Math.imul(); } + + assertEquals(0, foo()); + assertEquals(0, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo()); +})(); + +// Test Math.imul() with only one input. +(function() { + function foo(x) { return Math.imul(x); } + + assertEquals(0, foo(1)); + assertEquals(0, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(3)); +})(); + +// Test Math.imul() with wrong types. +(function() { + function foo(x, y) { return Math.imul(x, y); } + + assertEquals(0, foo(null, 1)); + assertEquals(0, foo(2, undefined)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(null, 1)); + assertEquals(0, foo(2, undefined)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(null, 1)); + assertEquals(0, foo(2, undefined)); + assertOptimized(foo); +})(); + +// Test Math.imul() with signed integers (statically known). +(function() { + function foo(x, y) { return Math.imul(x|0, y|0); } + + assertEquals(1, foo(1, 1)); + assertEquals(2, foo(2, 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1, 1)); + assertEquals(2, foo(2, 1)); + assertOptimized(foo); +})(); + +// Test Math.imul() with unsigned integers (statically known). +(function() { + function foo(x, y) { return Math.imul(x>>>0, y>>>0); } + + assertEquals(1, foo(1, 1)); + assertEquals(2, foo(2, 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1, 1)); + assertEquals(2, foo(2, 1)); + assertOptimized(foo); +})(); + +// Test Math.imul() with floating-point numbers. +(function() { + function foo(x, y) { return Math.imul(x, y); } + + assertEquals(1, foo(1.1, 1.1)); + assertEquals(2, foo(2.1, 1.1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1.1, 1.1)); + assertEquals(2, foo(2.1, 1.1)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/math-max.js b/deps/v8/test/mjsunit/compiler/math-max.js new file mode 100644 index 0000000000..350bdfba88 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/math-max.js @@ -0,0 +1,38 @@ +// 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 + +// Test the case where TurboFan can statically rule out -0 from the +// Math.max type. +(function() { + function foo(x) { + // Arrange x such that TurboFan infers type [-inf, inf] \/ MinusZero. + x = +x; + x = Math.round(x); + return Object.is(-0, Math.max(1, x)) + } + + assertFalse(foo(-0)); + assertFalse(foo(-1)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(-0)); + assertFalse(foo(-1)); +})(); + +// Test the case where -0 is ruled out because it's strictly less than +0. +(function() { + function foo(x) { + // Arrange x such that TurboFan infers type [-inf, inf] \/ MinusZero. + x = +x; + x = Math.round(x); + return Object.is(-0, Math.max(0, x)) + } + + assertFalse(foo(-0)); + assertFalse(foo(-1)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(-0)); + assertFalse(foo(-1)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/math-min.js b/deps/v8/test/mjsunit/compiler/math-min.js new file mode 100644 index 0000000000..882103984d --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/math-min.js @@ -0,0 +1,38 @@ +// 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 + +// Test the case where TurboFan can statically rule out -0 from the +// Math.min type. +(function() { + function foo(x) { + // Arrange x such that TurboFan infers type [-inf, inf] \/ MinusZero. + x = +x; + x = Math.round(x); + return Object.is(-0, Math.min(-1, x)) + } + + assertFalse(foo(-0)); + assertFalse(foo(-1)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(-0)); + assertFalse(foo(-1)); +})(); + +// Test the case where +0 is ruled out because it's strictly greater than -0. +(function() { + function foo(x) { + // Arrange x such that TurboFan infers type [-inf, inf] \/ MinusZero. + x = +x; + x = Math.round(x); + return Object.is(+0, Math.min(-0, x)) + } + + assertFalse(foo(-0)); + assertFalse(foo(-1)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(-0)); + assertFalse(foo(-1)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-abs.js b/deps/v8/test/mjsunit/compiler/number-abs.js new file mode 100644 index 0000000000..9eb8ab5bb5 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-abs.js @@ -0,0 +1,76 @@ +// 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 --opt + +// Test that NumberAbs correctly deals with PositiveInteger \/ MinusZero +// and turns the -0 into a 0. +(function() { + function foo(x) { + x = Math.floor(x); + x = Math.max(x, -0); + return 1 / Math.abs(x); + } + + assertEquals(Infinity, foo(-0)); + assertEquals(Infinity, foo(-0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(Infinity, foo(-0)); +})(); + +// Test that NumberAbs properly passes the kIdentifyZeros truncation +// for Signed32 \/ MinusZero inputs. +(function() { + function foo(x) { + return Math.abs(x * -2); + } + + assertEquals(2, foo(-1)); + assertEquals(4, foo(-2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(-1)); + assertEquals(4, foo(-2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); + +// Test that NumberAbs properly passes the kIdentifyZeros truncation +// for Unsigned32 \/ MinusZero inputs. +(function() { + function foo(x) { + x = x | 0; + return Math.abs(Math.max(x * -2, 0)); + } + + assertEquals(2, foo(-1)); + assertEquals(4, foo(-2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(-1)); + assertEquals(4, foo(-2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); + +// Test that NumberAbs properly passes the kIdentifyZeros truncation +// for OrderedNumber inputs. +(function() { + function foo(x) { + x = x | 0; + return Math.abs(Math.min(x * -2, 2 ** 32)); + } + + assertEquals(2, foo(-1)); + assertEquals(4, foo(-2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(-1)); + assertEquals(4, foo(-2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-add.js b/deps/v8/test/mjsunit/compiler/number-add.js new file mode 100644 index 0000000000..61e6495c52 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-add.js @@ -0,0 +1,62 @@ +// 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 + +// This tests that NumberAdd passes on the right truncations +// even if it figures out during SimplifiedLowering that it +// can indeed do a Word32 operation (based on the feedback +// baked in for its inputs by other operators). +(function() { + // We need a + with Number feedback to get to a NumberAdd + // during the typed lowering pass of TurboFan's frontend. + function foo(x, y) { return x + y; } + foo(0.1, 0.2); + foo(0.1, 0.2); + + // Now we need to fool TurboFan to think that it has to + // perform the `foo(x,-1)` on Float64 values until the + // very last moment (after the RETYPE phase of the + // SimplifiedLowering) where it realizes that the inputs + // and outputs of the NumberAdd allow it perform the + // operation on Word32. + function bar(x) { + x = Math.trunc(foo(x - 1, 1)); + return foo(x, -1); + } + + assertEquals(0, bar(1)); + assertEquals(1, bar(2)); + %OptimizeFunctionOnNextCall(bar); + assertEquals(2, bar(3)); +})(); + +// This tests that SpeculativeNumberAdd can still lower to +// Int32Add in SimplifiedLowering, which requires some magic +// to make sure that SpeculativeNumberAdd survives to that +// point, especially the JSTypedLowering needs to be unable +// to tell that the inputs to SpeculativeNumberAdd are non +// String primitives. +(function() { + // We need a function that has a + with feedback Number or + // NumberOrOddball, but for whose inputs the JSTypedLowering + // cannot reduce it to NumberAdd (with SpeculativeToNumber + // conversions). We achieve this utilizing an object literal + // indirection here. + function baz(x) { + return {x}.x + x; + } + baz(null); + baz(undefined); + + // Now we just need to truncate the result. + function foo(x) { + return baz(1) | 0; + } + + assertEquals(2, foo()); + assertEquals(2, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo()); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-ceil.js b/deps/v8/test/mjsunit/compiler/number-ceil.js new file mode 100644 index 0000000000..ce87cd0fc0 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-ceil.js @@ -0,0 +1,22 @@ +// 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 --opt + +// Test that NumberCeil propagates kIdentifyZeros truncations. +(function() { + function foo(x) { + return Math.abs(Math.ceil(x * -2)); + } + + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-comparison-truncations.js b/deps/v8/test/mjsunit/compiler/number-comparison-truncations.js new file mode 100644 index 0000000000..33abf6b913 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-comparison-truncations.js @@ -0,0 +1,152 @@ +// 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 --opt + +// Test that SpeculativeNumberEqual[SignedSmall] properly passes the +// kIdentifyZeros truncation. +(function() { + function foo(x, y) { + if (x * y === 0) return 0; + return 1; + } + + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + assertOptimized(foo); + // Even if x*y produces -0 now, it should stay optimized. + assertEquals(0, foo(-3, 0)); + assertEquals(0, foo(0, -3)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberEqual[Number] properly passes the +// kIdentifyZeros truncation. +(function() { + // Produce a SpeculativeNumberEqual with Number feedback. + function bar(x, y) { return x === y; } + bar(0.1, 0.5); + bar(-0, 100); + + function foo(x, y) { + if (bar(x * y, 0)) return 0; + return 1; + } + + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + assertOptimized(foo); + // Even if x*y produces -0 now, it should stay optimized. + assertEquals(0, foo(-3, 0)); + assertEquals(0, foo(0, -3)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberLessThan[SignedSmall] properly passes the +// kIdentifyZeros truncation. +(function() { + function foo(x, y) { + if (x * y < 0) return 0; + return 1; + } + + assertEquals(0, foo(1, -1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(1, -1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + assertOptimized(foo); + // Even if x*y produces -0 now, it should stay optimized. + assertEquals(1, foo(-3, 0)); + assertEquals(1, foo(0, -3)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberLessThan[Number] properly passes the +// kIdentifyZeros truncation. +(function() { + // Produce a SpeculativeNumberLessThan with Number feedback. + function bar(x, y) { return x < y; } + bar(0.1, 0.5); + bar(-0, 100); + + function foo(x, y) { + if (bar(x * y, 0)) return 0; + return 1; + } + + assertEquals(0, foo(1, -1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(1, -1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + assertOptimized(foo); + // Even if x*y produces -0 now, it should stay optimized. + assertEquals(1, foo(-3, 0)); + assertEquals(1, foo(0, -3)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberLessThanOrEqual[SignedSmall] properly passes the +// kIdentifyZeros truncation. +(function() { + function foo(x, y) { + if (x * y <= 0) return 0; + return 1; + } + + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + assertOptimized(foo); + // Even if x*y produces -0 now, it should stay optimized. + assertEquals(0, foo(-3, 0)); + assertEquals(0, foo(0, -3)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberLessThanOrEqual[Number] properly passes the +// kIdentifyZeros truncation. +(function() { + // Produce a SpeculativeNumberLessThanOrEqual with Number feedback. + function bar(x, y) { return x <= y; } + bar(0.1, 0.5); + bar(-0, 100); + + function foo(x, y) { + if (bar(x * y, 0)) return 0; + return 1; + } + + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(0, 1)); + assertEquals(1, foo(1, 1)); + assertEquals(1, foo(1, 2)); + assertOptimized(foo); + // Even if x*y produces -0 now, it should stay optimized. + assertEquals(0, foo(-3, 0)); + assertEquals(0, foo(0, -3)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-divide.js b/deps/v8/test/mjsunit/compiler/number-divide.js new file mode 100644 index 0000000000..c4cc8fa881 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-divide.js @@ -0,0 +1,207 @@ +// 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 --opt --noalways-opt + +// Test that NumberDivide 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(1, foo(1)); + assertEquals(1, foo(2)); + assertEquals(2, foo(3)); + assertEquals(2, foo(4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(2)); + assertEquals(2, foo(3)); + assertEquals(2, foo(4)); + assertOptimized(foo); +})(); + +// Test that NumberDivide 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(1, foo(1)); + assertEquals(1, foo(2)); + assertEquals(2, foo(3)); + assertEquals(2, foo(4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(2)); + assertEquals(2, foo(3)); + assertEquals(2, foo(4)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and +// that the "known power of two divisor" optimization works correctly. +(function() { + function foo(x) { return (x | 0) / 2; } + + // Warmup with proper int32 divisions. + assertEquals(1, foo(2)); + assertEquals(2, foo(4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo(6)); + assertOptimized(foo); + + // Make optimized code fail. + assertEquals(0.5, foo(1)); + assertUnoptimized(foo); + + // Try again with the new feedback, and now it should stay optimized. + %OptimizeFunctionOnNextCall(foo); + assertEquals(4, foo(8)); + assertOptimized(foo); + assertEquals(0.5, foo(1)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and +// that the optimized code properly bails out on "division by zero". +(function() { + function foo(x, y) { return x / y; } + + // Warmup with proper int32 divisions. + assertEquals(2, foo(4, 2)); + assertEquals(2, foo(8, 4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(2, 2)); + assertOptimized(foo); + + // Make optimized code fail. + assertEquals(Infinity, foo(1, 0)); + assertUnoptimized(foo); + + // Try again with the new feedback, and now it should stay optimized. + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(2, 1)); + assertOptimized(foo); + assertEquals(Infinity, foo(1, 0)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and +// that the optimized code properly bails out on minus zero. +(function() { + function foo(x, y) { return x / y; } + + // Warmup with proper int32 divisions. + assertEquals(2, foo(4, 2)); + assertEquals(2, foo(8, 4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(2, 2)); + assertOptimized(foo); + + // Make optimized code fail. + assertEquals(-0, foo(0, -1)); + assertUnoptimized(foo); + + // Try again with the new feedback, and now it should stay optimized. + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(2, 1)); + assertOptimized(foo); + assertEquals(-0, foo(0, -1)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and +// that the optimized code properly bails out if result is -kMinInt. +(function() { + function foo(x, y) { return x / y; } + + // Warmup with proper int32 divisions. + assertEquals(2, foo(4, 2)); + assertEquals(2, foo(8, 4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(2, 2)); + assertOptimized(foo); + + // Make optimized code fail. + assertEquals(2147483648, foo(-2147483648, -1)); + assertUnoptimized(foo); + + // Try again with the new feedback, and now it should stay optimized. + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(2, 1)); + assertOptimized(foo); + assertEquals(2147483648, foo(-2147483648, -1)); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberDivide turns into CheckedUint32Div, and +// that the "known power of two divisor" optimization works correctly. +(function() { + function foo(s) { return s.length / 2; } + + // Warmup with proper uint32 divisions. + assertEquals(1, foo("ab".repeat(1))); + assertEquals(2, foo("ab".repeat(2))); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo("ab".repeat(3))); + assertOptimized(foo); + + // Make optimized code fail. + assertEquals(0.5, foo("a")); + assertUnoptimized(foo); + + // Try again with the new feedback, and now it should stay optimized. + %OptimizeFunctionOnNextCall(foo); + assertEquals(4, foo("ab".repeat(4))); + assertOptimized(foo); + assertEquals(0.5, foo("a")); + assertOptimized(foo); +})(); + +// Test that SpeculativeNumberDivide turns into CheckedUint32Div, and +// that the optimized code properly bails out on "division by zero". +(function() { + function foo(x, y) { return (x >>> 0) / (y >>> 0); } + + // Warmup with proper uint32 divisions. + assertEquals(2, foo(4, 2)); + assertEquals(2, foo(8, 4)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(2, 2)); + assertOptimized(foo); + + // Make optimized code fail. + assertEquals(Infinity, foo(1, 0)); + assertUnoptimized(foo); + + // Try again with the new feedback, and now it should stay optimized. + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(2, 1)); + assertOptimized(foo); + assertEquals(Infinity, foo(1, 0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-floor.js b/deps/v8/test/mjsunit/compiler/number-floor.js new file mode 100644 index 0000000000..180b89e559 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-floor.js @@ -0,0 +1,22 @@ +// 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 --opt + +// Test that NumberFloor propagates kIdentifyZeros truncations. +(function() { + function foo(x) { + return Math.abs(Math.floor(x * -2)); + } + + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-issafeinteger.js b/deps/v8/test/mjsunit/compiler/number-issafeinteger.js index 192fb6c124..b705e95ed5 100644 --- a/deps/v8/test/mjsunit/compiler/number-issafeinteger.js +++ b/deps/v8/test/mjsunit/compiler/number-issafeinteger.js @@ -40,11 +40,19 @@ function test(f) { assertFalse(f(2 * near_lower - 7)); } -function f(x) { - return Number.isSafeInteger(+x); -} +// Check that the NumberIsSafeInteger simplified operator in +// TurboFan does the right thing. +function NumberIsSafeInteger(x) { return Number.isSafeInteger(+x); } +test(NumberIsSafeInteger); +test(NumberIsSafeInteger); +%OptimizeFunctionOnNextCall(NumberIsSafeInteger); +test(NumberIsSafeInteger); -test(f); -test(f); -%OptimizeFunctionOnNextCall(f); -test(f); +// Check that the ObjectIsSafeInteger simplified operator in +// TurboFan does the right thing as well (i.e. when TurboFan +// is not able to tell statically that the inputs are numbers). +function ObjectIsSafeInteger(x) { return Number.isSafeInteger(x); } +test(ObjectIsSafeInteger); +test(ObjectIsSafeInteger); +%OptimizeFunctionOnNextCall(ObjectIsSafeInteger); +test(ObjectIsSafeInteger); diff --git a/deps/v8/test/mjsunit/compiler/number-max.js b/deps/v8/test/mjsunit/compiler/number-max.js new file mode 100644 index 0000000000..7e5a4a4ad1 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-max.js @@ -0,0 +1,23 @@ +// 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 --opt + +// Test that NumberMax properly passes the kIdentifyZeros truncation. +(function() { + function foo(x) { + if (Math.max(x * -2, 1) == 1) 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`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-min.js b/deps/v8/test/mjsunit/compiler/number-min.js new file mode 100644 index 0000000000..72bff78686 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-min.js @@ -0,0 +1,23 @@ +// 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 --opt + +// Test that NumberMin properly passes the kIdentifyZeros truncation. +(function() { + function foo(x) { + if (Math.min(x * -2, -1) == -2) return 0; + return 1; + } + + assertEquals(0, foo(1)); + assertEquals(1, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo(1)); + assertEquals(1, foo(2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(1, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-modulus.js b/deps/v8/test/mjsunit/compiler/number-modulus.js new file mode 100644 index 0000000000..5f695d1ee5 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-modulus.js @@ -0,0 +1,256 @@ +// 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 --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 +// 0 vs -0, even when the inputs are outside Signed32. +(function() { + function foo(x) { + return (x * -2) % (2 ** 32) === 0; + } + + assertFalse(foo(2)); + assertFalse(foo(1)); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo(2)); + assertFalse(foo(1)); + + // Now `foo` should stay optimized even if `x * -2` would + // produce -0, aka when we pass a zero value for `x`. + 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/deps/v8/test/mjsunit/compiler/number-round.js b/deps/v8/test/mjsunit/compiler/number-round.js new file mode 100644 index 0000000000..9aec7f7a12 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-round.js @@ -0,0 +1,22 @@ +// 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 --opt + +// Test that NumberRound propagates kIdentifyZeros truncations. +(function() { + function foo(x) { + return Math.abs(Math.round(x * -2)); + } + + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-subtract.js b/deps/v8/test/mjsunit/compiler/number-subtract.js new file mode 100644 index 0000000000..cb3e1c7e70 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-subtract.js @@ -0,0 +1,34 @@ +// 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 + +// This tests that SpeculativeNumberSubtract can still lower to +// Int32Sub in SimplifiedLowering, which requires some magic +// to make sure that SpeculativeNumberSubtract survives to that +// point, especially the JSTypedLowering needs to be unable +// to tell that the inputs to SpeculativeNumberAdd are not +// Number, Undefined, Null or Boolean. +(function() { + // We need a function that has a - with feedback Number or + // NumberOrOddball, but for whose inputs the JSTypedLowering + // cannot reduce it to NumberSubtract (with SpeculativeToNumber + // conversions). We achieve this utilizing an object literal + // indirection here. + function baz(x) { + return {x}.x - x; + } + baz(null); + baz(undefined); + + // Now we just need to truncate the result. + function foo(x) { + return baz(42) | 0; + } + + assertEquals(0, foo()); + assertEquals(0, foo()); + %OptimizeFunctionOnNextCall(foo); + assertEquals(0, foo()); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-toboolean.js b/deps/v8/test/mjsunit/compiler/number-toboolean.js new file mode 100644 index 0000000000..02b30b3ed6 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-toboolean.js @@ -0,0 +1,45 @@ +// 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 --opt + +// Test that NumberToBoolean properly passes the kIdentifyZeros truncation +// for Signed32 \/ MinusZero inputs. +(function() { + function foo(x) { + if (x * -2) return 1; + return 0; + } + + assertEquals(1, foo(1)); + assertEquals(1, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(1)); + assertEquals(1, foo(2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); + + +// Test that NumberToBoolean properly passes the kIdentifyZeros truncation +// for Unsigned32 \/ MinusZero inputs. +(function() { + function foo(x) { + x = x | 0; + if (Math.max(x * -2, 0)) return 1; + return 0; + } + + assertEquals(1, foo(-1)); + assertEquals(1, foo(-2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo(-1)); + assertEquals(1, foo(-2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/number-trunc.js b/deps/v8/test/mjsunit/compiler/number-trunc.js new file mode 100644 index 0000000000..aa7d02c20f --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/number-trunc.js @@ -0,0 +1,22 @@ +// 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 --opt + +// Test that NumberTrunc propagates kIdentifyZeros truncations. +(function() { + function foo(x) { + return Math.abs(Math.trunc(x * -2)); + } + + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(2, foo(1)); + assertEquals(4, foo(2)); + assertOptimized(foo); + // Now `foo` should stay optimized even if `x * -2` would produce `-0`. + assertEquals(0, foo(0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/redundancy-elimination.js b/deps/v8/test/mjsunit/compiler/redundancy-elimination.js new file mode 100644 index 0000000000..1e5185adb7 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/redundancy-elimination.js @@ -0,0 +1,194 @@ +// 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 --opt + +// Test the RedundancyElimination::ReduceSpeculativeNumberOperation() +// TurboFan optimization for the case of SpeculativeNumberAdd with +// Number feedback. +(function() { + function bar(i) { + return ++i; + } + bar(0.1); + + function foo(a, i) { + const x = a[i]; + const y = a[bar(i)]; + return x + y; + } + + assertEquals(3, foo([1, 2], 0)); + assertEquals(3, foo([1, 2], 0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo([1, 2], 0)); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberOperation() +// TurboFan optimization for the case of SpeculativeNumberAdd with +// NumberOrOddball feedback. +(function() { + function bar(i) { + return ++i; + } + assertEquals(NaN, bar(undefined)); + + function foo(a, i) { + const x = a[i]; + const y = a[bar(i)]; + return x + y; + } + + assertEquals(3, foo([1, 2], 0)); + assertEquals(3, foo([1, 2], 0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo([1, 2], 0)); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberOperation() +// TurboFan optimization for the case of SpeculativeNumberSubtract with +// Number feedback. +(function() { + function bar(i) { + return --i; + } + assertEquals(-0.9, bar(0.1)); + + function foo(a, i) { + const x = a[i]; + const y = a[bar(i)]; + return x + y; + } + + assertEquals(3, foo([1, 2], 1)); + assertEquals(3, foo([1, 2], 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo([1, 2], 1)); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberOperation() +// TurboFan optimization for the case of SpeculativeNumberSubtract with +// NumberOrOddball feedback. +(function() { + function bar(i) { + return --i; + } + assertEquals(NaN, bar(undefined)); + + function foo(a, i) { + const x = a[i]; + const y = a[bar(i)]; + return x + y; + } + + assertEquals(3, foo([1, 2], 1)); + assertEquals(3, foo([1, 2], 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo([1, 2], 1)); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberOperation() +// TurboFan optimization for the case of SpeculativeToNumber. +(function() { + function foo(a, i) { + const x = a[i]; + const y = i++; + return x + y; + } + + assertEquals(1, foo([1, 2], 0)); + assertEquals(1, foo([1, 2], 0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo([1, 2], 0)); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberOperation() +// TurboFan optimization for the case of SpeculativeSafeIntegerAdd. +(function() { + function foo(a, i) { + const x = a[i]; + const y = a[++i]; + return x + y; + } + + assertEquals(3, foo([1, 2], 0)); + assertEquals(3, foo([1, 2], 0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo([1, 2], 0)); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberOperation() +// TurboFan optimization for the case of SpeculativeSafeIntegerSubtract. +(function() { + function foo(a, i) { + const x = a[i]; + const y = a[--i]; + return x + y; + } + + assertEquals(3, foo([1, 2], 1)); + assertEquals(3, foo([1, 2], 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(3, foo([1, 2], 1)); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberComparison() +// TurboFan optimization for the case of SpeculativeNumberEqual. +(function() { + function foo(a, i) { + const x = a[i]; + if (i === 0) return x; + return i; + } + + assertEquals(1, foo([1, 2], 0)); + assertEquals(1, foo([1, 2], 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo([1, 2], 0)); + assertEquals(1, foo([1, 2], 1)); + // Even passing -0 should not deoptimize and + // of course still pass the equality test above. + assertEquals(9, foo([9, 2], -0)); + assertOptimized(foo); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberComparison() +// TurboFan optimization for the case of SpeculativeNumberLessThan. +(function() { + function foo(a, i) { + const x = a[i]; + if (i < 1) return x; + return i; + } + + assertEquals(1, foo([1, 2], 0)); + assertEquals(1, foo([1, 2], 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo([1, 2], 0)); + assertEquals(1, foo([1, 2], 1)); + // Even passing -0 should not deoptimize and + // of course still pass the equality test above. + assertEquals(9, foo([9, 2], -0)); + assertOptimized(foo); +})(); + +// Test the RedundancyElimination::ReduceSpeculativeNumberComparison() +// TurboFan optimization for the case of SpeculativeNumberLessThanOrEqual. +(function() { + function foo(a, i) { + const x = a[i]; + if (i <= 0) return x; + return i; + } + + assertEquals(1, foo([1, 2], 0)); + assertEquals(1, foo([1, 2], 1)); + %OptimizeFunctionOnNextCall(foo); + assertEquals(1, foo([1, 2], 0)); + assertEquals(1, foo([1, 2], 1)); + // Even passing -0 should not deoptimize and + // of course still pass the equality test above. + assertEquals(9, foo([9, 2], -0)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/regress-7121.js b/deps/v8/test/mjsunit/compiler/regress-7121.js index 98c1a1ac19..bdf3133bb8 100644 --- a/deps/v8/test/mjsunit/compiler/regress-7121.js +++ b/deps/v8/test/mjsunit/compiler/regress-7121.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --harmony-bigint +// Flags: --allow-natives-syntax function foo() { %_ToLength(42n) } assertThrows(foo, TypeError); diff --git a/deps/v8/test/mjsunit/compiler/regress-884052.js b/deps/v8/test/mjsunit/compiler/regress-884052.js new file mode 100644 index 0000000000..babfcc3cea --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-884052.js @@ -0,0 +1,16 @@ +// 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() { + var a = new Array(2); + for (var i = 1; i > -1; i = i - 2) { + if (i < a.length) a = new Array(i); + } +} + +foo(); +%OptimizeFunctionOnNextCall(foo); +foo(); diff --git a/deps/v8/test/mjsunit/compiler/regress-890057.js b/deps/v8/test/mjsunit/compiler/regress-890057.js new file mode 100644 index 0000000000..655c4431e9 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-890057.js @@ -0,0 +1,16 @@ +// 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 f() {} +function g() { + f.prototype = undefined; + f(); + new f(); +} + +// Do not use %OptimizeFunctionOnNextCall here, this particular bug needs +// to trigger truly concurrent compilation. +for (let i = 0; i < 10000; i++) g(); diff --git a/deps/v8/test/mjsunit/compiler/regress-890620.js b/deps/v8/test/mjsunit/compiler/regress-890620.js new file mode 100644 index 0000000000..f5fc7f4f65 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-890620.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 + +var a = 42; + +function g(n) { + while (n > 0) { + a = new Array(n); + n--; + } +} + +g(1); + +function f() { + g(); +} + +f(); +%OptimizeFunctionOnNextCall(f); +f(); +assertEquals(1, a.length); diff --git a/deps/v8/test/mjsunit/compiler/regress-895799.js b/deps/v8/test/mjsunit/compiler/regress-895799.js new file mode 100644 index 0000000000..4305b7427b --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-895799.js @@ -0,0 +1,26 @@ +// 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 + +class C extends Object { + constructor() { + try { super(); } catch (e) { }; + return 1; + } +} + +class A extends C { + constructor() { + super(); + throw new Error(); + return { get: () => this }; + } +} + +var D = new Proxy(A, { get() { %DeoptimizeFunction(A); } }); + +try { Reflect.construct(A, [], D); } catch(e) {} +%OptimizeFunctionOnNextCall(A); +try { Reflect.construct(A, [], D); } catch(e) {} diff --git a/deps/v8/test/mjsunit/compiler/strict-equal-symbol.js b/deps/v8/test/mjsunit/compiler/strict-equal-symbol.js new file mode 100644 index 0000000000..aee1ecfa60 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/strict-equal-symbol.js @@ -0,0 +1,50 @@ +// 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 + +// Known symbols strict equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo() { return a === b; } + + assertFalse(foo()); + assertFalse(foo()); + %OptimizeFunctionOnNextCall(foo); + assertFalse(foo()); +})(); + +// Known symbol on one side strict equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo(a) { return a === b; } + + assertTrue(foo(b)); + assertFalse(foo(a)); + assertTrue(foo(b)); + assertFalse(foo(a)); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(b)); + assertFalse(foo(a)); +})(); + +// Feedback based symbol strict equality. +(function() { + const a = Symbol("a"); + const b = Symbol("b"); + + function foo(a, b) { return a === b; } + + assertTrue(foo(b, b)); + assertFalse(foo(a, b)); + assertTrue(foo(a, a)); + assertFalse(foo(b, a)); + %OptimizeFunctionOnNextCall(foo); + assertTrue(foo(a, a)); + assertFalse(foo(b, a)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/string-add-try-catch.js b/deps/v8/test/mjsunit/compiler/string-add-try-catch.js index d7a3d2583c..5ae5b00d18 100644 --- a/deps/v8/test/mjsunit/compiler/string-add-try-catch.js +++ b/deps/v8/test/mjsunit/compiler/string-add-try-catch.js @@ -4,6 +4,9 @@ // Flags: --allow-natives-syntax +// Test that string concatenation overflow (going over string max length) +// is handled gracefully, i.e. an error is thrown + var a = "a".repeat(%StringMaxLength()); (function() { @@ -37,3 +40,57 @@ var a = "a".repeat(%StringMaxLength()); foo("a"); assertInstanceof(foo(a), RangeError); })(); + +(function() { + function foo(a, b) { + try { + return "0123456789012".concat(a); + } catch (e) { + return e; + } + } + + foo("a"); + foo("a"); + %OptimizeFunctionOnNextCall(foo); + foo("a"); + assertInstanceof(foo(a), RangeError); +})(); + +var obj = { + toString: function() { + throw new Error('toString has thrown'); + } +}; + +(function() { + function foo(a, b) { + try { + return "0123456789012" + obj; + } catch (e) { + return e; + } + } + + foo("a"); + foo("a"); + %OptimizeFunctionOnNextCall(foo); + foo("a"); + assertInstanceof(foo(a), Error); +})(); + +(function() { + function foo(a, b) { + try { + return a + 123; + } catch (e) { + return e; + } + } + + foo("a"); + foo("a"); + %OptimizeFunctionOnNextCall(foo); + foo("a"); + assertInstanceof(foo(a), RangeError); +})(); diff --git a/deps/v8/test/mjsunit/compiler/string-from-code-point.js b/deps/v8/test/mjsunit/compiler/string-from-code-point.js new file mode 100644 index 0000000000..165ea0c234 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/string-from-code-point.js @@ -0,0 +1,32 @@ +// 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 --opt --noalways-opt + +// Test that String.fromCodePoint() properly identifies zeros. +(function() { + function foo(x) { + return String.fromCodePoint(x); + } + + assertEquals("\u0000", foo(0)); + assertEquals("\u0000", foo(-0)); + %OptimizeFunctionOnNextCall(foo); + assertEquals("\u0000", foo(0)); + assertEquals("\u0000", foo(-0)); + assertOptimized(foo); + + // Now passing anything outside the valid code point + // range should invalidate the optimized code. + assertThrows(_ => foo(-1)); + assertUnoptimized(foo); + + // And TurboFan should not inline the builtin anymore + // from now on (aka no deoptimization loop). + %OptimizeFunctionOnNextCall(foo); + assertEquals("\u0000", foo(0)); + assertEquals("\u0000", foo(-0)); + assertThrows(_ => foo(-1)); + assertOptimized(foo); +})(); diff --git a/deps/v8/test/mjsunit/compiler/typed-array-constructor.js b/deps/v8/test/mjsunit/compiler/typed-array-constructor.js index a785eadf37..07d6a7ca4e 100644 --- a/deps/v8/test/mjsunit/compiler/typed-array-constructor.js +++ b/deps/v8/test/mjsunit/compiler/typed-array-constructor.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --harmony-bigint +// Flags: --allow-natives-syntax const limit = %MaxSmi() + 1; |