Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,305 @@
// Copyright 2020 the V8 project 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 --turbofan --no-always-turbofan
// smi == boolean
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(2, true));
assertTrue(foo(1, true));
assertTrue(foo(0, false));
assertFalse(foo(2, false));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(2, true));
assertTrue(foo(1, true));
assertTrue(foo(0, false));
assertFalse(foo(2, false));
assertOptimized(foo);
assertFalse(foo(0, null));
assertUnoptimized(foo);
})();
// boolean == smi
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(true, 2));
assertTrue(foo(true, 1));
assertTrue(foo(false, 0));
assertFalse(foo(false, 2));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(true, 2));
assertTrue(foo(true, 1));
assertTrue(foo(false, 0));
assertFalse(foo(false, 2));
assertOptimized(foo);
assertFalse(foo(null, 0));
assertUnoptimized(foo);
})();
// smi == undefined
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(2, undefined));
assertFalse(foo(0, undefined));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(2, undefined));
assertFalse(foo(0, undefined));
assertOptimized(foo);
})();
// undefined == smi
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(undefined, 2));
assertFalse(foo(undefined, 0));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(undefined, 2));
assertFalse(foo(undefined, 0));
assertOptimized(foo);
})();
// smi == null
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(2, null));
assertFalse(foo(0, null));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(2, null));
assertFalse(foo(0, null));
assertOptimized(foo);
})();
// null == smi
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(null, 2));
assertFalse(foo(null, 0));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(null, 2));
assertFalse(foo(null, 0));
assertOptimized(foo);
})();
// smi == oddball
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(2, null));
assertFalse(foo(0, undefined));
assertFalse(foo(0, true));
assertTrue(foo(1, true));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(2, null));
assertFalse(foo(0, undefined));
assertFalse(foo(0, true));
assertTrue(foo(1, true));
assertOptimized(foo);
})();
// oddball == smi
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(null, 2));
assertFalse(foo(undefined, 0));
assertFalse(foo(true, 0));
assertTrue(foo(true, 1));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(null, 2));
assertFalse(foo(undefined, 0));
assertFalse(foo(true, 0));
assertTrue(foo(true, 1));
assertOptimized(foo);
})();
// number == boolean
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(-2.8, true));
assertTrue(foo(1, true));
assertTrue(foo(-0.0, false));
assertFalse(foo(2, false));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(-2.8, true));
assertTrue(foo(1, true));
assertTrue(foo(-0.0, false));
assertFalse(foo(2, false));
assertOptimized(foo);
assertFalse(foo(0, null));
assertUnoptimized(foo);
})();
// boolean == number
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(true, -2.8));
assertTrue(foo(true, 1));
assertTrue(foo(false, -0.0));
assertFalse(foo(false, 2));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(true, -2.8));
assertTrue(foo(true, 1));
assertTrue(foo(false, -0.0));
assertFalse(foo(false, 2));
assertOptimized(foo);
assertFalse(foo(null, 0));
assertUnoptimized(foo);
})();
// number == undefined
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(-2.8, undefined));
assertFalse(foo(-0.0, undefined));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(-2.8, undefined));
assertFalse(foo(-0.0, undefined));
assertOptimized(foo);
})();
// undefined == number
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(undefined, -2.8));
assertFalse(foo(undefined, -0.0));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(undefined, -2.8));
assertFalse(foo(undefined, -0.0));
assertOptimized(foo);
})();
// number == null
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(-2.8, null));
assertFalse(foo(-0.0, null));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(-2.8, null));
assertFalse(foo(-0.0, null));
assertOptimized(foo);
})();
// null == number
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(null, -2.8));
assertFalse(foo(null, -0.0));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(null, -2.8));
assertFalse(foo(null, -0.0));
assertOptimized(foo);
})();
// number == oddball
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(-2.8, null));
assertFalse(foo(-0.0, undefined));
assertFalse(foo(0, true));
assertTrue(foo(1.0, true));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(-2.8, null));
assertFalse(foo(-0.0, undefined));
assertFalse(foo(0, true));
assertTrue(foo(1.0, true));
assertOptimized(foo);
})();
// oddball == number
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(null, -2.8));
assertFalse(foo(undefined, -0.0));
assertFalse(foo(true, 0));
assertTrue(foo(true, 1.0));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(null, -2.8));
assertFalse(foo(undefined, -0.0));
assertFalse(foo(true, 0));
assertTrue(foo(true, 1.0));
assertOptimized(foo);
})();
// oddball == oddball
(function() {
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(null, null));
assertTrue(foo(undefined, undefined));
assertTrue(foo(false, false));
assertTrue(foo(true, true));
assertTrue(foo(undefined, null));
assertFalse(foo(undefined, false));
assertFalse(foo(null, false));
assertFalse(foo(true, undefined));
assertFalse(foo(true, null));
assertFalse(foo(true, false));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(null, null));
assertOptimized(foo);
assertTrue(foo(undefined, undefined));
assertTrue(foo(false, false));
assertTrue(foo(true, true));
assertTrue(foo(undefined, null));
assertFalse(foo(undefined, false));
assertFalse(foo(null, false));
assertFalse(foo(true, undefined));
assertFalse(foo(true, null));
assertFalse(foo(true, false));
assertOptimized(foo);
})();

View File

@ -0,0 +1,187 @@
// 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 --turbofan --noalways-turbofan
// Known receivers abstract equality.
(function() {
const a = {};
const b = {};
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo());
assertFalse(foo());
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo());
})();
// Known receiver/null abstract equality.
(function() {
const a = {};
const b = null;
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo());
assertFalse(foo());
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo());
})();
// Known null/receiver abstract equality.
(function() {
const a = null;
const b = {};
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo());
assertFalse(foo());
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo());
})();
// Known receiver/undefined abstract equality.
(function() {
const a = {};
const b = undefined;
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo());
assertFalse(foo());
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo());
})();
// Known undefined/receiver abstract equality.
(function() {
const a = undefined;
const b = {};
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo());
assertFalse(foo());
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo());
})();
// Known receiver on one side strict equality.
(function() {
const a = {};
const b = {};
function foo(a) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(b));
assertFalse(foo(a));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b));
assertFalse(foo(a));
// TurboFan bakes in feedback for the (unknown) left hand side.
assertFalse(foo(null));
assertUnoptimized(foo);
})();
// Known receiver on one side strict equality with null.
(function() {
const a = null;
const b = {};
function foo(a) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(b));
assertFalse(foo(a));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b));
assertFalse(foo(a));
// TurboFan bakes in feedback for the (unknown) left hand side.
assertFalse(foo(1));
assertUnoptimized(foo);
})();
// Known receiver on one side strict equality with undefined.
(function() {
const a = undefined;
const b = {};
function foo(a) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(b));
assertFalse(foo(a));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b));
assertFalse(foo(a));
// TurboFan bakes in feedback for the (unknown) left hand side.
assertFalse(foo(1));
assertUnoptimized(foo);
})();
// Known null on one side strict equality with receiver.
(function() {
const a = {};
const b = null;
function foo(a) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(b));
assertFalse(foo(a));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(null));
assertTrue(foo(undefined));
assertOptimized(foo);
// TurboFan doesn't need to bake in feedback, since it sees the null.
assertFalse(foo(1));
assertOptimized(foo);
})();
// Known undefined on one side strict equality with receiver.
(function() {
const a = {};
const b = undefined;
function foo(a) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(b));
assertFalse(foo(a));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(null));
assertTrue(foo(undefined));
assertOptimized(foo);
// TurboFan needs to bake in feedback, since undefined cannot
// be context specialized.
assertFalse(foo(1));
assertUnoptimized(foo);
})();

View File

@ -0,0 +1,147 @@
// 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 --turbofan --noalways-turbofan
// Known symbols abstract equality.
(function() {
const a = Symbol("a");
const b = Symbol("b");
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
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; }
%PrepareFunctionForOptimization(foo);
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
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(b));
assertFalse(foo(a));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b));
// Re-prepare the function immediately to make sure type feedback isn't
// cleared by untimely gc, as re-optimization on new feedback is tested below
%PrepareFunctionForOptimization(foo);
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
%PrepareFunctionForOptimization(foo);
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
%PrepareFunctionForOptimization(foo);
%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
%PrepareFunctionForOptimization(foo);
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
%PrepareFunctionForOptimization(foo);
%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; }
%PrepareFunctionForOptimization(foo);
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
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo("a", b));
assertOptimized(foo);
})();

View File

@ -0,0 +1,149 @@
// 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 --turbofan --noalways-turbofan
const undetectable = %GetUndetectable();
// Known undetectable abstract equality.
(function() {
const a = undetectable;
const b = {};
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertFalse(foo());
assertFalse(foo());
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo());
})();
// Known undetectable/null abstract equality.
(function() {
const a = undetectable;
const b = null;
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Known undetectable/receiver abstract equality.
(function() {
const a = null;
const b = undetectable;
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Known undetectable/undefined abstract equality.
(function() {
const a = undetectable;
const b = undefined;
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Known undefined/undetectable abstract equality.
(function() {
const a = undefined;
const b = undetectable;
function foo() { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Known undetectable on one side strict equality with receiver.
(function() {
const a = {};
const b = undetectable;
function foo(a) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b));
assertFalse(foo(a));
assertTrue(foo(b));
assertFalse(foo(a));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b));
assertFalse(foo(a));
})();
// Unknown undetectable on one side strict equality with receiver.
(function() {
const a = undetectable;
const b = {};
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(b, b));
assertFalse(foo(a, b));
assertTrue(foo(a, a));
assertFalse(foo(b, a));
assertTrue(foo(a, null));
assertFalse(foo(b, null));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(b, b));
assertFalse(foo(a, b));
assertTrue(foo(a, a));
assertFalse(foo(b, a));
assertTrue(foo(a, null));
assertFalse(foo(b, null));
assertOptimized(foo);
// TurboFan bakes in feedback on the inputs.
assertFalse(foo(1));
assertUnoptimized(foo);
})();
// Unknown undetectable on both sides.
(function() {
const a = undetectable;
function foo(a, b) { return a == b; }
%PrepareFunctionForOptimization(foo);
assertTrue(foo(a, a));
assertTrue(foo(a, undefined));
assertTrue(foo(undefined, a));
assertFalse(foo(a, %GetUndetectable()));
assertFalse(foo(%GetUndetectable(), a));
assertFalse(foo(%GetUndetectable(), %GetUndetectable()));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(a, a));
assertTrue(foo(a, undefined));
assertTrue(foo(undefined, a));
assertFalse(foo(a, %GetUndetectable()));
assertFalse(foo(%GetUndetectable(), a));
assertFalse(foo(%GetUndetectable(), %GetUndetectable()));
assertOptimized(foo);
// TurboFan bakes in feedback on the inputs.
assertFalse(foo(1));
assertUnoptimized(foo);
})();

View File

@ -0,0 +1,22 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var o = {}
Object.defineProperty(o, "x", {
get: function() { throw 7; }
});
function foo(o) {
var x = 1;
try { o.x; } catch (e) { x = e; }
return x;
}
%PrepareFunctionForOptimization(foo);
assertEquals(7, foo(o));
assertEquals(7, foo(o));
%OptimizeFunctionOnNextCall(foo);
assertEquals(7, foo(o));

View File

@ -0,0 +1,22 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var o = {}
Object.defineProperty(o, "x", {
set: function(v) { throw 7; }
});
function foo(o) {
var x = 1;
try { o.x = 2; } catch (e) { x = e; }
return x;
}
%PrepareFunctionForOptimization(foo);
assertEquals(7, foo(o));
assertEquals(7, foo(o));
%OptimizeFunctionOnNextCall(foo);
assertEquals(7, foo(o));

View File

@ -0,0 +1,44 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Try to get a GC because of a heap number allocation while we
// have live values (o) in a register.
function f(o) {
var x = 1.5;
var y = 2.5;
for (var i = 1; i < 3; i += 1) {
%SetAllocationTimeout(1, 0, false);
o.val = x + y + i;
%SetAllocationTimeout(-1, -1, true);
}
return o;
}
var o = { val: 0 };
f(o);

View File

@ -0,0 +1,20 @@
// Copyright 2010 the V8 project 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: --max-semi-space-size=1 --max-old-space-size=10
// This test is specific to release builds. alloc-number-debug.js
// has a fast version for debug builds.
// Try to get a GC because of a heap number allocation while we
// have live values (o) in a register.
function f(o) {
var x = 1.5;
var y = 2.5;
for (var i = 1; i < 10000; i+=2) o.val = x + y + i;
return o;
}
var o = { val: 0 };
for (var i = 0; i < 10; i++) f(o);

View File

@ -0,0 +1,311 @@
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Flags: --max-inlined-bytecode-size=999999
// Flags: --max-inlined-bytecode-size-cumulative=999999
// Test that huge constructors (more than 256 this assignments) are
// handled correctly.
// Test huge constructor when being inlined into hydrogen.
function test() {
return new huge();
}
%PrepareFunctionForOptimization(test);
test();
test();
%OptimizeFunctionOnNextCall(test);
var o = test();
assertEquals(1, o.foo1);
assertEquals(257, o.foo257);
// Test huge constructor with specialized constructor stub.
var o = new huge();
assertEquals(1, o.foo1);
assertEquals(257, o.foo257);
// The huge constructor, nothing interesting beyond this point.
function huge() {
this.foo1 = 1;
this.foo2 = 2;
this.foo3 = 3;
this.foo4 = 4;
this.foo5 = 5;
this.foo6 = 6;
this.foo7 = 7;
this.foo8 = 8;
this.foo9 = 9;
this.foo10 = 10;
this.foo11 = 11;
this.foo12 = 12;
this.foo13 = 13;
this.foo14 = 14;
this.foo15 = 15;
this.foo16 = 16;
this.foo17 = 17;
this.foo18 = 18;
this.foo19 = 19;
this.foo20 = 20;
this.foo21 = 21;
this.foo22 = 22;
this.foo23 = 23;
this.foo24 = 24;
this.foo25 = 25;
this.foo26 = 26;
this.foo27 = 27;
this.foo28 = 28;
this.foo29 = 29;
this.foo30 = 30;
this.foo31 = 31;
this.foo32 = 32;
this.foo33 = 33;
this.foo34 = 34;
this.foo35 = 35;
this.foo36 = 36;
this.foo37 = 37;
this.foo38 = 38;
this.foo39 = 39;
this.foo40 = 40;
this.foo41 = 41;
this.foo42 = 42;
this.foo43 = 43;
this.foo44 = 44;
this.foo45 = 45;
this.foo46 = 46;
this.foo47 = 47;
this.foo48 = 48;
this.foo49 = 49;
this.foo50 = 50;
this.foo51 = 51;
this.foo52 = 52;
this.foo53 = 53;
this.foo54 = 54;
this.foo55 = 55;
this.foo56 = 56;
this.foo57 = 57;
this.foo58 = 58;
this.foo59 = 59;
this.foo60 = 60;
this.foo61 = 61;
this.foo62 = 62;
this.foo63 = 63;
this.foo64 = 64;
this.foo65 = 65;
this.foo66 = 66;
this.foo67 = 67;
this.foo68 = 68;
this.foo69 = 69;
this.foo70 = 70;
this.foo71 = 71;
this.foo72 = 72;
this.foo73 = 73;
this.foo74 = 74;
this.foo75 = 75;
this.foo76 = 76;
this.foo77 = 77;
this.foo78 = 78;
this.foo79 = 79;
this.foo80 = 80;
this.foo81 = 81;
this.foo82 = 82;
this.foo83 = 83;
this.foo84 = 84;
this.foo85 = 85;
this.foo86 = 86;
this.foo87 = 87;
this.foo88 = 88;
this.foo89 = 89;
this.foo90 = 90;
this.foo91 = 91;
this.foo92 = 92;
this.foo93 = 93;
this.foo94 = 94;
this.foo95 = 95;
this.foo96 = 96;
this.foo97 = 97;
this.foo98 = 98;
this.foo99 = 99;
this.foo100 = 100;
this.foo101 = 101;
this.foo102 = 102;
this.foo103 = 103;
this.foo104 = 104;
this.foo105 = 105;
this.foo106 = 106;
this.foo107 = 107;
this.foo108 = 108;
this.foo109 = 109;
this.foo110 = 110;
this.foo111 = 111;
this.foo112 = 112;
this.foo113 = 113;
this.foo114 = 114;
this.foo115 = 115;
this.foo116 = 116;
this.foo117 = 117;
this.foo118 = 118;
this.foo119 = 119;
this.foo120 = 120;
this.foo121 = 121;
this.foo122 = 122;
this.foo123 = 123;
this.foo124 = 124;
this.foo125 = 125;
this.foo126 = 126;
this.foo127 = 127;
this.foo128 = 128;
this.foo129 = 129;
this.foo130 = 130;
this.foo131 = 131;
this.foo132 = 132;
this.foo133 = 133;
this.foo134 = 134;
this.foo135 = 135;
this.foo136 = 136;
this.foo137 = 137;
this.foo138 = 138;
this.foo139 = 139;
this.foo140 = 140;
this.foo141 = 141;
this.foo142 = 142;
this.foo143 = 143;
this.foo144 = 144;
this.foo145 = 145;
this.foo146 = 146;
this.foo147 = 147;
this.foo148 = 148;
this.foo149 = 149;
this.foo150 = 150;
this.foo151 = 151;
this.foo152 = 152;
this.foo153 = 153;
this.foo154 = 154;
this.foo155 = 155;
this.foo156 = 156;
this.foo157 = 157;
this.foo158 = 158;
this.foo159 = 159;
this.foo160 = 160;
this.foo161 = 161;
this.foo162 = 162;
this.foo163 = 163;
this.foo164 = 164;
this.foo165 = 165;
this.foo166 = 166;
this.foo167 = 167;
this.foo168 = 168;
this.foo169 = 169;
this.foo170 = 170;
this.foo171 = 171;
this.foo172 = 172;
this.foo173 = 173;
this.foo174 = 174;
this.foo175 = 175;
this.foo176 = 176;
this.foo177 = 177;
this.foo178 = 178;
this.foo179 = 179;
this.foo180 = 180;
this.foo181 = 181;
this.foo182 = 182;
this.foo183 = 183;
this.foo184 = 184;
this.foo185 = 185;
this.foo186 = 186;
this.foo187 = 187;
this.foo188 = 188;
this.foo189 = 189;
this.foo190 = 190;
this.foo191 = 191;
this.foo192 = 192;
this.foo193 = 193;
this.foo194 = 194;
this.foo195 = 195;
this.foo196 = 196;
this.foo197 = 197;
this.foo198 = 198;
this.foo199 = 199;
this.foo200 = 200;
this.foo201 = 201;
this.foo202 = 202;
this.foo203 = 203;
this.foo204 = 204;
this.foo205 = 205;
this.foo206 = 206;
this.foo207 = 207;
this.foo208 = 208;
this.foo209 = 209;
this.foo210 = 210;
this.foo211 = 211;
this.foo212 = 212;
this.foo213 = 213;
this.foo214 = 214;
this.foo215 = 215;
this.foo216 = 216;
this.foo217 = 217;
this.foo218 = 218;
this.foo219 = 219;
this.foo220 = 220;
this.foo221 = 221;
this.foo222 = 222;
this.foo223 = 223;
this.foo224 = 224;
this.foo225 = 225;
this.foo226 = 226;
this.foo227 = 227;
this.foo228 = 228;
this.foo229 = 229;
this.foo230 = 230;
this.foo231 = 231;
this.foo232 = 232;
this.foo233 = 233;
this.foo234 = 234;
this.foo235 = 235;
this.foo236 = 236;
this.foo237 = 237;
this.foo238 = 238;
this.foo239 = 239;
this.foo240 = 240;
this.foo241 = 241;
this.foo242 = 242;
this.foo243 = 243;
this.foo244 = 244;
this.foo245 = 245;
this.foo246 = 246;
this.foo247 = 247;
this.foo248 = 248;
this.foo249 = 249;
this.foo250 = 250;
this.foo251 = 251;
this.foo252 = 252;
this.foo253 = 253;
this.foo254 = 254;
this.foo255 = 255;
this.foo256 = 256;
this.foo257 = 257;
}

View File

@ -0,0 +1,91 @@
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Test that inlined object allocation works for different layouts of
// objects (e.g. in object properties, slack tracking in progress or
// changing of function prototypes)
function test_helper(construct, a, b) {
return new construct(a, b);
}
function test(construct) {
%DeoptimizeFunction(test);
%PrepareFunctionForOptimization(test_helper);
test_helper(construct, 0, 0);
test_helper(construct, 0, 0);
%OptimizeFunctionOnNextCall(test_helper);
// Test adding a new property after allocation was inlined.
var o = test_helper(construct, 1, 2);
o.z = 3;
assertEquals(1, o.x);
assertEquals(2, o.y);
assertEquals(3, o.z);
// Test changing the prototype after allocation was inlined.
construct.prototype = { z:6 };
var o = test_helper(construct, 4, 5);
assertEquals(4, o.x);
assertEquals(5, o.y);
assertEquals(6, o.z);
%DeoptimizeFunction(test_helper);
%ClearFunctionFeedback(test_helper);
}
function finalize_slack_tracking(construct) {
// Value chosen based on kGenerousAllocationCount = 8.
for (var i = 0; i < 8; i++) {
new construct(0, 0);
}
}
// Both properties are pre-allocated in object properties.
function ConstructInObjectPreAllocated(a, b) {
this.x = a;
this.y = b;
}
finalize_slack_tracking(ConstructInObjectPreAllocated);
test(ConstructInObjectPreAllocated);
// Both properties are unused in object properties.
function ConstructInObjectUnused(a, b) {
this.x = a < 0 ? 0 : a;
this.y = b > 0 ? b : 0;
}
finalize_slack_tracking(ConstructInObjectUnused);
test(ConstructInObjectUnused);
// Test inlined allocation while slack tracking is still in progress.
function ConstructWhileSlackTracking(a, b) {
this.x = a;
this.y = b;
}
test(ConstructWhileSlackTracking);

View File

@ -0,0 +1,178 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --noturbo-inlining
// Helper function to compare two arguments objects of strict mode functions.
// Access to arguments.callee results in TypeError for them, so assertEquals
// can't be used directly.
function assertEqualsArgumentsStrict(a, b) {
assertEquals(JSON.stringify(a), JSON.stringify(b));
}
// Ensure that arguments in sloppy mode function works
// properly when called directly from optimized code.
(function() {
function g() { return arguments; }
function f() { return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();
// Ensure that arguments in strict mode function works
// properly when called directly from optimized code.
(function() {
"use strict";
function g() { return arguments; }
function f() { return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEqualsArgumentsStrict(g(1, 2, 3), f());
assertEqualsArgumentsStrict(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEqualsArgumentsStrict(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
%OptimizeFunctionOnNextCall(g);
assertEqualsArgumentsStrict(g(1, 2, 3), f());
})();
// Ensure that arguments in sloppy mode function works
// properly when called directly from optimized code,
// and the access to "arguments" is hidden inside eval().
(function() {
function g() { return eval("arguments"); }
function f() { return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();
// Ensure that arguments in strict mode function works
// properly when called directly from optimized code,
// and the access to "arguments" is hidden inside eval().
(function() {
"use strict";
function g() { return eval("arguments"); }
function f() { return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEqualsArgumentsStrict(g(1, 2, 3), f());
assertEqualsArgumentsStrict(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEqualsArgumentsStrict(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
assertEqualsArgumentsStrict(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(g);
assertEqualsArgumentsStrict(g(1, 2, 3), f());
})();
// Ensure that `Function.arguments` accessor does the
// right thing in sloppy mode functions called directly
// from optimized code.
(function() {
function h() { return g.arguments; }
function g() { return h(); }
function f() { return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();
(function() {
function h() { return g.arguments; }
function g() { return h(); }
function f() { "use strict"; return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();
(function() {
function h() { "use strict"; return g.arguments; }
function g() { return h(); }
function f() { return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();
(function() {
function h() { "use strict"; return g.arguments; }
function g() { return h(); }
function f() { "use strict"; return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();
// Ensure that `Function.arguments` works properly in
// combination with the `Function.caller` proper.
(function() {
function h() { return h.caller.arguments; }
function g() { return h(); }
function f() { return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();
(function() {
function h() { return h.caller.arguments; }
function g() { return h(); }
function f() { "use strict"; return g(1, 2, 3); }
%PrepareFunctionForOptimization(f);
assertEquals(g(1, 2, 3), f());
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(f);
assertEquals(g(1, 2, 3), f());
%PrepareFunctionForOptimization(g);
assertEquals(g(1, 2, 3), f());
%OptimizeFunctionOnNextCall(g);
assertEquals(g(1, 2, 3), f());
})();

View File

@ -0,0 +1,214 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function Get0(a) {
return a[0];
}
function GetN(a,n) {
return a[n];
}
function GetA0(a) {
return a[a[0]];
}
function GetAN(a,n) {
return a[a[n]];
}
function GetAAN(a,n) {
return a[a[a[n]]];
}
function RunGetTests(packed=true) {
if (packed) {
var a = [2,0,1];
assertEquals(2, Get0(a));
assertEquals(2, GetN(a, 0));
assertEquals(0, GetN(a, 1));
assertEquals(1, GetN(a, 2));
assertEquals(1, GetA0(a));
assertEquals(1, GetAN(a,0));
assertEquals(2, GetAN(a,1));
assertEquals(0, GetAN(a,2));
assertEquals(0, GetAAN(a,0));
assertEquals(1, GetAAN(a,1));
assertEquals(2, GetAAN(a,2));
} else {
var a = ['2','0','1'];
assertEquals('2', Get0(a));
assertEquals('2', GetN(a, 0));
assertEquals('0', GetN(a, 1));
assertEquals('1', GetN(a, 2));
assertEquals('1', GetA0(a));
assertEquals('1', GetAN(a,0));
assertEquals('2', GetAN(a,1));
assertEquals('0', GetAN(a,2));
assertEquals('0', GetAAN(a,0));
assertEquals('1', GetAAN(a,1));
assertEquals('2', GetAAN(a,2));
}
}
function Set07(a) {
a[0] = 7;
}
function Set0V(a, v) {
a[0] = v;
}
function SetN7(a, n) {
a[n] = 7;
}
function SetNX(a, n, x) {
a[n] = x;
}
function RunSetTests(a, packed=true) {
Set07(a);
if (packed) {
assertEquals(7, a[0]);
}
assertEquals(0, a[1]);
assertEquals(0, a[2]);
Set0V(a, 1);
if (packed) {
assertEquals(1, a[0]);
}
assertEquals(0, a[1]);
assertEquals(0, a[2]);
SetN7(a, 2);
if (packed) {
assertEquals(1, a[0]);
}
assertEquals(0, a[1]);
assertEquals(7, a[2]);
SetNX(a, 1, 5);
if (packed) {
assertEquals(1, a[0]);
}
assertEquals(5, a[1]);
assertEquals(7, a[2]);
for (var i = 0; i < 3; i++) SetNX(a, i, 0);
if (packed) {
assertEquals(0, a[0]);
}
assertEquals(0, a[1]);
assertEquals(0, a[2]);
}
function RunArrayBoundsCheckTest() {
var g = [1,2,3];
function f(a, i) { a[i] = 42; }
for (var i = 0; i < 100000; i++) { f(g, 0); }
f(g, 4);
assertEquals(42, g[0]);
assertEquals(42, g[4]);
}
var a = [0,0,0];
var o = {0: 0, 1: 0, 2: 0};
for (var i = 0; i < 1000; i++) {
RunGetTests();
RunSetTests(a);
RunSetTests(o);
}
RunArrayBoundsCheckTest();
// Packed
// Non-extensible
a = Object.preventExtensions([0,0,0,'a']);
o = Object.preventExtensions({0: 0, 1: 0, 2: 0});
for (var i = 0; i < 1000; i++) {
RunGetTests();
RunGetTests(false);
RunSetTests(a);
RunSetTests(o);
}
// Sealed
a = Object.seal([0,0,0,'a']);
o = Object.seal({0: 0, 1: 0, 2: 0});
for (var i = 0; i < 1000; i++) {
RunGetTests();
RunGetTests(false);
RunSetTests(a);
RunSetTests(o);
}
// Frozen
a = Object.freeze([0,0,0,'a']);
o = Object.freeze({0: 0, 1: 0, 2: 0});
for (var i = 0; i < 1000; i++) {
RunGetTests();
RunGetTests(false);
}
// Holey
// Non-extensible
a = Object.preventExtensions([,0,0,'a']);
for (var i = 0; i < 1000; i++) {
RunGetTests();
RunGetTests(false);
RunSetTests(a, false);
}
// Sealed
a = Object.seal([,0,0,'a']);
for (var i = 0; i < 1000; i++) {
RunGetTests();
RunGetTests(false);
RunSetTests(a, false);
}
// Frozen
a = Object.freeze([,0,0,'a']);
for (var i = 0; i < 1000; i++) {
RunGetTests();
RunGetTests(false);
}

View File

@ -0,0 +1,66 @@
// 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 --turbofan
// 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);
}
%PrepareFunctionForOptimization(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))));
%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);
}
%PrepareFunctionForOptimization(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))));
%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);
})();

View File

@ -0,0 +1,189 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Test Array call with known Boolean.
(() => {
function foo(x) { return Array(!!x); }
%PrepareFunctionForOptimization(foo);
assertEquals([true], foo(true));
assertEquals([false], foo(false));
%OptimizeFunctionOnNextCall(foo);
assertEquals([true], foo(true));
assertEquals([false], foo(false));
})();
// Test Array construct with known Boolean.
(() => {
function foo(x) { return new Array(!!x); }
%PrepareFunctionForOptimization(foo);
assertEquals([true], foo(true));
assertEquals([false], foo(false));
%OptimizeFunctionOnNextCall(foo);
assertEquals([true], foo(true));
assertEquals([false], foo(false));
})();
// Test Array call with known String.
(() => {
function foo(x) { return Array("" + x); }
%PrepareFunctionForOptimization(foo);
assertEquals(["a"], foo("a"));
assertEquals(["b"], foo("b"));
%OptimizeFunctionOnNextCall(foo);
assertEquals(["a"], foo("a"));
assertEquals(["b"], foo("b"));
})();
// Test Array construct with known String.
(() => {
function foo(x) { return new Array("" + x); }
%PrepareFunctionForOptimization(foo);
assertEquals(["a"], foo("a"));
assertEquals(["b"], foo("b"));
%OptimizeFunctionOnNextCall(foo);
assertEquals(["a"], foo("a"));
assertEquals(["b"], foo("b"));
})();
// Test Array call with known fixed small integer.
(() => {
function foo() { return Array(2); }
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo().length);
assertEquals(2, foo().length);
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo().length);
})();
// Test Array construct with known fixed small integer.
(() => {
function foo() { return new Array(2); }
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo().length);
assertEquals(2, foo().length);
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo().length);
})();
// Test Array call with multiple parameters.
(() => {
function foo(x, y, z) { return Array(x, y, z); }
%PrepareFunctionForOptimization(foo);
assertEquals([1, 2, 3], foo(1, 2, 3));
assertEquals([1, 2, 3], foo(1, 2, 3));
%OptimizeFunctionOnNextCall(foo);
assertEquals([1, 2, 3], foo(1, 2, 3));
})();
// Test Array construct with multiple parameters.
(() => {
function foo(x, y, z) { return new Array(x, y, z); }
%PrepareFunctionForOptimization(foo);
assertEquals([1, 2, 3], foo(1, 2, 3));
assertEquals([1, 2, 3], foo(1, 2, 3));
%OptimizeFunctionOnNextCall(foo);
assertEquals([1, 2, 3], foo(1, 2, 3));
})();
// Test Array construct inside try-catch block.
(() => {
function foo(x) { try { return new Array(x) } catch (e) { return e } }
%PrepareFunctionForOptimization(foo);
assertEquals([], foo(0));
assertEquals([], foo(0));
%OptimizeFunctionOnNextCall(foo);
assertEquals([], foo(0));
assertInstanceof(foo(-1), RangeError);
})();
// Packed
// Test non-extensible Array call with multiple parameters.
(() => {
function foo(x, y, z, t) { return Object.preventExtensions(new Array(x, y, z, t)); }
%PrepareFunctionForOptimization(foo);
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertFalse(Object.isExtensible(foo(1,2,3, 'a')));
%OptimizeFunctionOnNextCall(foo);
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertFalse(Object.isExtensible(foo(1,2,3, 'a')));
})();
// Test sealed Array call with multiple parameters.
(() => {
function foo(x, y, z, t) { return Object.seal(new Array(x, y, z, t)); }
%PrepareFunctionForOptimization(foo);
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isSealed(foo(1,2,3, 'a')));
%OptimizeFunctionOnNextCall(foo);
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isSealed(foo(1,2,3, 'a')));
})();
// Test frozen Array call with multiple parameters.
(() => {
function foo(x, y, z, t) { return Object.freeze(new Array(x, y, z, t)); }
%PrepareFunctionForOptimization(foo);
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isFrozen(foo(1,2,3, 'a')));
%OptimizeFunctionOnNextCall(foo);
assertEquals([1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isFrozen(foo(1,2,3, 'a')));
})();
// Holey
// Test non-extensible Array call with multiple parameters.
(() => {
function foo(x, y, z, t) { return Object.preventExtensions([, x, y, z, t]); }
%PrepareFunctionForOptimization(foo);
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertFalse(Object.isExtensible(foo(1,2,3, 'a')));
%OptimizeFunctionOnNextCall(foo);
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertFalse(Object.isExtensible(foo(1,2,3, 'a')));
})();
// Test sealed Array call with multiple parameters.
(() => {
function foo(x, y, z, t) { return Object.seal([, x, y, z, t]); }
%PrepareFunctionForOptimization(foo);
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isSealed(foo(1,2,3, 'a')));
%OptimizeFunctionOnNextCall(foo);
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isSealed(foo(1,2,3, 'a')));
})();
// Test frozen Array call with multiple parameters.
(() => {
function foo(x, y, z, t) { return Object.freeze([, x, y, z, t]); }
%PrepareFunctionForOptimization(foo);
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isFrozen(foo(1,2,3, 'a')));
%OptimizeFunctionOnNextCall(foo);
assertEquals([, 1, 2, 3, 'a'], foo(1, 2, 3, 'a'));
assertTrue(Object.isFrozen(foo(1,2,3, 'a')));
})();

View File

@ -0,0 +1,69 @@
// 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
// Basic loop peeling test case with Array.prototype.every().
(function() {
function foo(a, o) {
return a.every(x => x === o.x);
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo([3, 3, 3], {x:3}));
assertFalse(foo([3, 3, 2], {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo([3, 3, 3], {x:3}));
assertFalse(foo([3, 3, 2], {x:3}));
// Packed
// Non-extensible array
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.preventExtensions(['3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions(['3', '3', '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.preventExtensions(['3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions(['3', '3', '2']), {x:'3'}));
// Sealed array
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.seal(['3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.seal(['3', '3', '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.seal(['3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.seal(['3', '3', '2']), {x:'3'}));
// Frozen array
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.freeze(['3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.freeze(['3', '3', '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.freeze(['3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.freeze(['3', '3', '2']), {x:'3'}));
// Holey
// Non-extensible array
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.preventExtensions([, '3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions([, '3', '3', '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.preventExtensions([, '3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions([, '3', '3', '2']), {x:'3'}));
// Sealed array
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.seal([, '3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.seal([, '3', '3', '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.seal([, '3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.seal([, '3', '3', '2']), {x:'3'}));
// Frozen array
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.freeze([, '3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.freeze([, '3', '3', '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.freeze([, '3', '3', '3']), {x:'3'}));
assertFalse(foo(Object.freeze([, '3', '3', '2']), {x:'3'}));
})();

View File

@ -0,0 +1,69 @@
// 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
// Basic loop peeling test case with Array.prototype.find().
(function() {
function foo(a, o) {
return a.find(x => x === o.x);
}
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo([1, 2, 3], {x:3}));
assertEquals(undefined, foo([0, 1, 2], {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo([1, 2, 3], {x:3}));
assertEquals(undefined, foo([0, 1, 2], {x:3}));
// Packed
// Non-extensible
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.preventExtensions(['1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.preventExtensions(['0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.preventExtensions(['1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.preventExtensions(['0', 1, 2]), {x:3}));
// Sealed
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.seal(['1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.seal(['0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.seal(['1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.seal(['0', 1, 2]), {x:3}));
// Frozen
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.freeze(['1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.freeze(['0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.freeze(['1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.freeze(['0', 1, 2]), {x:3}));
// Holey
// Non-extensible
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.preventExtensions([, '1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.preventExtensions([, '0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.preventExtensions([, '1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.preventExtensions([, '0', 1, 2]), {x:3}));
// Sealed
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.seal([, '1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.seal([, '0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.seal([, '1', 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.seal([, '0', 1, 2]), {x:3}));
// Frozen
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.freeze([, 1, 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.freeze([, 0, 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.freeze([, 1, 2, 3]), {x:3}));
assertEquals(undefined, foo(Object.freeze([, 0, 1, 2]), {x:3}));
})();

View File

@ -0,0 +1,69 @@
// 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
// Basic loop peeling test case with Array.prototype.findIndex().
(function() {
function foo(a, o) {
return a.findIndex(x => x === o.x);
}
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo([1, 2, 3], {x:3}));
assertEquals(-1, foo([0, 1, 2], {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo([1, 2, 3], {x:3}));
assertEquals(-1, foo([0, 1, 2], {x:3}));
// Packed
// Non-extensible
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(Object.preventExtensions(['1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.preventExtensions(['0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(Object.preventExtensions(['1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.preventExtensions(['0', 1, 2]), {x:3}));
// Sealed
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(Object.seal(['1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.seal(['0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(Object.seal(['1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.seal(['0', 1, 2]), {x:3}));
// Frozen
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(Object.freeze(['1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.freeze(['0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(Object.freeze(['1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.freeze(['0', 1, 2]), {x:3}));
// Holey
// Non-extensible
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.preventExtensions([, '1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.preventExtensions([, '0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.preventExtensions([, '1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.preventExtensions([, '0', 1, 2]), {x:3}));
// Sealed
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.seal([, '1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.seal([, '0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.seal([, '1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.seal([, '0', 1, 2]), {x:3}));
// Frozen
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(Object.freeze([, '1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.freeze([, '0', 1, 2]), {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(Object.freeze([, '1', 2, 3]), {x:3}));
assertEquals(-1, foo(Object.freeze([, '0', 1, 2]), {x:3}));
})();

View File

@ -0,0 +1,197 @@
// 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([]);
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be a Proxy for an Array literal.
(function() {
function foo() {
return Array.isArray(new Proxy([], {}));
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be an Object literal.
(function() {
function foo() {
return Array.isArray({});
}
%PrepareFunctionForOptimization(foo);
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({}, {}));
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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;
}
}
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo([]), TypeError);
assertInstanceof(foo({}), TypeError);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo([]), TypeError);
assertInstanceof(foo({}), TypeError);
})();
// Packed
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be a non-extensible Array literal.
(function() {
function foo() {
return Array.isArray(Object.preventExtensions([]));
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be a sealed Array literal.
(function() {
function foo() {
return Array.isArray(Object.seal([]));
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be a frozen Array literal.
(function() {
function foo() {
return Array.isArray(Object.freeze([]));
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Holey
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be a non-extensible Array literal.
(function() {
function foo() {
return Array.isArray(Object.preventExtensions([,]));
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be a sealed Array literal.
(function() {
function foo() {
return Array.isArray(Object.seal([,]));
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();
// Test JSObjectIsArray in JSTypedLowering for the case that the
// input value is known to be a frozen Array literal.
(function() {
function foo() {
return Array.isArray(Object.freeze([,]));
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo());
assertTrue(foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo());
})();

View File

@ -0,0 +1,91 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
function ArrayLength(a) { return a.length; }
function Test(a0, a2, a5) {
assertEquals(0, ArrayLength(a0));
assertEquals(2, ArrayLength(a2));
assertEquals(5, ArrayLength(a5));
}
var a0 = [];
var a2 = [1,2];
var a5 = [1,2,3,4,5];
function MainTest() {
%PrepareFunctionForOptimization(ArrayLength);
for (var i = 0; i < 5; i++) Test(a0, a2, a5);
%OptimizeFunctionOnNextCall(ArrayLength);
Test(a0, a2, a5);
%PrepareFunctionForOptimization(Test);
%OptimizeFunctionOnNextCall(Test);
Test(a0, a2, a5);
assertEquals("undefined", typeof(ArrayLength(0)));
%PrepareFunctionForOptimization(Test);
for (var i = 0; i < 5; i++) Test(a0, a2, a5);
%OptimizeFunctionOnNextCall(Test);
Test(a0, a2, a5);
assertEquals(4, ArrayLength("hest"));
}
MainTest();
// Packed
// Non-extensible, sealed, frozen
a0 = Object.preventExtensions([]);
a2 = Object.seal([1,'2']);
a5 = Object.freeze([1,2,'3',4,5]);
MainTest();
a0 = Object.seal([]);
a2 = Object.freeze([1,'2']);
a5 = Object.preventExtensions([1,2,'3',4,5]);
MainTest();
a0 = Object.freeze([]);
a2 = Object.preventExtensions([1,'2']);
a5 = Object.seal([1,2,'3',4,5]);
MainTest();
// Holey
// Non-extensible, sealed, frozen
a0 = Object.preventExtensions([]);
a2 = Object.seal([,'2']);
a5 = Object.freeze([,2,'3',4,5]);
MainTest();
a0 = Object.seal([]);
a2 = Object.freeze([,'2']);
a5 = Object.preventExtensions([,2,'3',4,5]);
MainTest();
a0 = Object.freeze([]);
a2 = Object.preventExtensions([,'2']);
a5 = Object.seal([,2,3,4,5]);
MainTest();

View File

@ -0,0 +1,188 @@
// 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 --turbofan --no-always-turbofan
// Flags: --no-stress-background-compile --trace-opt --trace-deopt
let id = 0;
function runTest(f, message, mkICTraining, deoptArg, speculationCheck) {
function test(f, message, ictraining, deoptArg, speculationCheck) {
// Train the call ic to the maps.
let t = ictraining;
// We put the training data into local variables
// to ensure their maps are kepts alive. If the
// maps die, gc *may* deoptimize {f}, which makes
// the test flaky.
let t1 = t();
let t2 = t();
let t3 = t();
%PrepareFunctionForOptimization(f);
for (let a of t1) {
f(a.arr, () => a.el);
}
for (let a of t2) {
f(a.arr, () => a.el);
}
%OptimizeFunctionOnNextCall(f);
message += " trained with" + JSON.stringify(t());
if (deoptArg == undefined) {
// Make sure the optimized function can handle
// all trained maps without deopt.
for (let a of t3) {
message += " for args " + JSON.stringify(a) + " should have been optimized";
f(a.arr, () => a.el);
assertOptimized(f, message);
}
} else {
// Trigger deopt, causing no-speculation bit to be set.
let a1 = deoptArg;
let a2 = deoptArg;
let a3 = deoptArg;
message += " for args " + JSON.stringify(a1);
message_unoptimized = message + " should have been unoptimized"
message_optimized = message + " should have been optimized"
f(a1.darr, () => a1.del);
assertUnoptimized(f, message_unoptimized);
if (speculationCheck) {
%PrepareFunctionForOptimization(f);
%OptimizeFunctionOnNextCall(f);
f(a2.darr, () => a2.del);
assertUnoptimized(f, message_unoptimized);
}
%PrepareFunctionForOptimization(f);
%OptimizeFunctionOnNextCall(f);
// No speculation should protect against further deopts.
f(a3.darr, () => a3.del);
assertOptimized(f, message_optimized);
}
}
// Get function as a string.
var testString = test.toString();
// Remove the function header..
testString = testString.replace(new RegExp("[^\n]*"), "let f = " + f.toString() + ";");
// ..and trailing '}'.
testString = testString.replace(new RegExp("[^\n]*$"), "");
// Substitute parameters.
testString = testString.replace(new RegExp("ictraining", 'g'), mkICTraining.toString());
testString = testString.replace(new RegExp("deoptArg", 'g'),
deoptArg ? JSON.stringify(deoptArg).replace(/"/g,'') : "undefined");
testString = testString.replace(new RegExp("speculationCheck", 'g'),
speculationCheck ? JSON.stringify(deoptArg).replace(/"/g,'') : "undefined");
// Make field names unique to avoid learning of types.
id = id + 1;
testString = testString.replace(/[.]el/g, '.el' + id);
testString = testString.replace(/el:/g, 'el' + id + ':');
testString = testString.replace(/[.]arr/g, '.arr' + id);
testString = testString.replace(/arr:/g, 'arr' + id + ':');
testString = testString.replace(/[.]del/g, '.del' + id);
testString = testString.replace(/[.]darr/g, '.darr' + id);
var modTest = new Function("message", testString);
modTest(message);
}
let checks = {
smiReceiver:
{ mkTrainingArguments : () => [{arr:[1], el:3}],
deoptingArguments : [{darr:[0.1], del:1}, {darr:[{}], del:1}]
},
objectReceiver:
{ mkTrainingArguments : () => [{arr:[{}], el:0.1}],
deoptingArguments : []
},
multipleSmiReceivers:
{ mkTrainingArguments : () => { let b = [1]; b.x=3; return [{arr:[1], el:3}, {arr:b, el:3}] },
deoptingArguments : [{darr:[0.1], del:1}, {darr:[{}], del:1}]
},
multipleSmiReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [1]; b[100] = 3; return [{arr:[1], el:3}, {arr:b, el:3}] },
deoptingArguments : [{darr:[0.1], del:1}, {darr:[{}], del:1}]
},
multipleDoubleReceivers:
{ mkTrainingArguments : () => { let b = [0.1]; b.x=0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{darr:[{}], del:true}, {darr:[1], del: 1}]
},
multipleDoubleReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [0.1]; b[100] = 0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{darr:[{}], del:true}, {darr:[1], del: 1}]
},
multipleMixedReceivers:
{ mkTrainingArguments : () => { let b = [0.1]; b.x=0.3; return [{arr:[1], el:1}, {arr:[{}], el:true}, {arr:b, el:0.3}] },
deoptingArguments : []
},
multipleMixedReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [0.1]; b[100] = 0.3; return [{arr:[1], el:1}, {arr:[{}], el:true}, {arr:b, el:0.3}] },
deoptingArguments : []
},
};
let no_speculation_checks = {
smiReceiver:
{ mkTrainingArguments : () => [{arr:[1], el:3}],
deoptingArguments : [{darr:[0.1], del:true}]
},
multipleSmiReceivers:
{ mkTrainingArguments : () => { let b = [1]; b.x=3; return [{arr:[1], el:3}, {arr:[1], el:3}] },
deoptingArguments : [{darr:[0.1], del:true}]
},
multipleSmiReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [1]; b[100] = 3; return [{arr:[1], el:3}, {arr:b, el:3}] },
deoptingArguments : [{darr:[0.1], del:true}]
},
multipleDoubleReceivers:
{ mkTrainingArguments : () => { let b = [0.1]; b.x=0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{darr:[1], del:true}]
},
multipleDoubleReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [0.1]; b[100] = 0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{darr:[1], del:true}]
},
};
const functions = {
push_reliable: (a,g) => { let b = g(); return a.push(2, b); },
push_unreliable: (a,g) => { return a.push(2, g()); },
pop_reliable: (a,g) => { let b = g(); return a.pop(2, b); },
pop_unreliable: (a,g) => { return a.pop(2, g()); },
shift_reliable: (a,g) => { let b = g(); return a.shift(2, b); },
shift_unreliable: (a,g) => { return a.shift(2, g()); }
}
const push_functions = {
push_reliable: (a,g) => { let b = g(); return a.push(2, b); },
push_unreliable: (a,g) => { return a.push(2, g()); },
}
Object.keys(checks).forEach(
key => {
let check = checks[key];
for (fnc in functions) {
runTest(functions[fnc], "test-" + fnc + "-" + key, check.mkTrainingArguments);
// Test each deopting arg separately.
for (let deoptArg of check.deoptingArguments) {
runTest(functions[fnc], "testDeopt-" + fnc + "-" + key, check.mkTrainingArguments, deoptArg);
}
}
}
);
Object.keys(no_speculation_checks).forEach(
key => {
let check = no_speculation_checks[key];
for (fnc in push_functions) {
runTest(functions[fnc], "test-spec-check-" + fnc + "-" + key, check.mkTrainingArguments);
// Test each deopting arg separately.
for (let deoptArg of check.deoptingArguments) {
runTest(functions[fnc], "testDeopt-spec-check-" + fnc + "-" + key, check.mkTrainingArguments, deoptArg, true);
}
}
}
);

View File

@ -0,0 +1,94 @@
// Copyright 2025 the V8 project 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 --turbofan --no-always-turbofan
// Flags: --no-optimize-on-next-call-optimizes-to-maglev --no-turbolev
// TODO(399393885): --no-optimize-on-next-call-optimizes-to-maglev and
// --no-turbolev can be removed once the bug is fixed, since then Turbofan and
// Maglev implementations will behave the same way.
load('test/mjsunit/elements-kinds-helpers.js');
// Tests calling Array.prototype.map on a dictionary mode array invalidate the
// "array constructor" protector, so they must be in a separate file.
function plusOne(x) {
return x + 1;
}
%PrepareFunctionForOptimization(plusOne);
function plusOneInObject(x) {
return {a: x.a + 1};
}
%PrepareFunctionForOptimization(plusOneInObject);
(function testDictionaryElements1() {
function foo(a) {
return a.map(plusOne);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, 3];
const array2 = [1, 2, 3];
MakeArrayDictionaryMode(array, () => { return 0; });
MakeArrayDictionaryMode(array2, () => { return 0; });
assertTrue(%HasDictionaryElements(array));
assertTrue(%HasDictionaryElements(array2));
const result = foo(array);
assertTrue(HasHoleySmiElements(result));
%OptimizeFunctionOnNextCall(foo);
const result2 = foo(array2);
assertTrue(HasHoleySmiElements(result2));
assertOptimized(foo);
})();
(function testDictionaryElements2() {
function foo(a) {
return a.map(plusOne);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, 3];
const array2 = [1, 2, 3];
MakeArrayDictionaryMode(array, () => { return 0.1; });
MakeArrayDictionaryMode(array2, () => { return 0.1; });
assertTrue(%HasDictionaryElements(array));
assertTrue(%HasDictionaryElements(array2));
const result = foo(array);
assertTrue(HasHoleyDoubleElements(result));
%OptimizeFunctionOnNextCall(foo);
const result2 = foo(array2);
assertTrue(HasHoleyDoubleElements(result2));
assertOptimized(foo);
})();
(function testDictionaryElements3() {
function foo(a) {
return a.map(plusOneInObject);
}
%PrepareFunctionForOptimization(foo);
const array = [{a: 1}, {a: 2}, {a: 3}];
const array2 = [{a: 1}, {a: 2}, {a: 3}];
MakeArrayDictionaryMode(array, () => { return {a: 0}; });
MakeArrayDictionaryMode(array2, () => { return {a: 0}; });
assertTrue(%HasDictionaryElements(array));
assertTrue(%HasDictionaryElements(array2));
const result = foo(array);
assertTrue(HasHoleyObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
const result2 = foo(array2);
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();

View File

@ -0,0 +1,568 @@
// Copyright 2025 the V8 project 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 --turbofan --no-always-turbofan
// Flags: --no-optimize-on-next-call-optimizes-to-maglev --no-turbolev
// TODO(399393885): --no-optimize-on-next-call-optimizes-to-maglev and
// --no-turbolev can be removed once the bug is fixed, since then Turbofan and
// Maglev implementations will behave the same way.
load('test/mjsunit/elements-kinds-helpers.js');
function identity(x) {
return x;
}
%PrepareFunctionForOptimization(identity);
function plusOne(x) {
return x + 1;
}
%PrepareFunctionForOptimization(plusOne);
function plusOneAndMore(x) {
return x + 1.1;
}
%PrepareFunctionForOptimization(plusOneAndMore);
function plusOneInObject(x) {
return {a: x.a + 1};
}
%PrepareFunctionForOptimization(plusOneInObject);
function wrapInObject(x) {
return {a: x};
}
%PrepareFunctionForOptimization(wrapInObject);
function unwrapObject(x) {
return x.a;
}
%PrepareFunctionForOptimization(unwrapObject);
let ix = 0;
function transitionFromSmiToDouble(x) {
if (ix++ == 0) {
return 0;
}
return 1.1;
}
%PrepareFunctionForOptimization(transitionFromSmiToDouble);
function transitionFromSmiToObject(x) {
if (ix++ == 0) {
return 0;
}
return {a: 1};
}
%PrepareFunctionForOptimization(transitionFromSmiToObject);
function transitionFromDoubleToObject(x) {
if (ix++ == 0) {
return 1.1;
}
return {a: 1};
}
%PrepareFunctionForOptimization(transitionFromDoubleToObject);
function transitionFromObjectToDouble(x) {
if (ix++ == 0) {
return {a: 1};
}
return 1.1;
}
%PrepareFunctionForOptimization(transitionFromObjectToDouble);
function resetTransitionFunctions() {
ix = 0;
}
(function testPackedSmiElementsWithIdentity() {
function foo(a) {
return a.map(identity);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, 3];
const result = foo(array);
assertTrue(HasPackedSmiElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, 3];
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedSmiElements(result2));
assertTrue(HasHoleySmiElements(result2));
assertOptimized(foo);
})();
(function testPackedSmiElements() {
function foo(a) {
return a.map(plusOne);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, 3];
const result = foo(array);
assertTrue(HasPackedSmiElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, 3];
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedSmiElements(result2));
assertTrue(HasHoleyDoubleElements(result2) || HasHoleySmiElements(result2));
assertOptimized(foo);
})();
(function testHoleySmiElements() {
function foo(a) {
return a.map(plusOne);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, , 3];
const result = foo(array);
assertTrue(HasHoleySmiElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, , 3];
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasHoleySmiElements(result2));
assertTrue(HasHoleyDoubleElements(result2) || HasHoleySmiElements(result2));
assertOptimized(foo);
})();
(function testPackedDoubleElements1() {
function foo(a) {
return a.map(plusOne);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, 3.3];
const result = foo(array);
assertTrue(HasPackedDoubleElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, 3.3];
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedDoubleElements(result2));
assertTrue(HasHoleyDoubleElements(result2));
assertOptimized(foo);
})();
(function testPackedDoubleElements2() {
function foo(a) {
return a.map(plusOneAndMore);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, 3];
const result = foo(array);
assertTrue(HasPackedDoubleElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, 3];
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedDoubleElements(result2));
assertTrue(HasHoleyDoubleElements(result2));
assertOptimized(foo);
})();
(function testHoleyDoubleElements1() {
function foo(a) {
return a.map(plusOne);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, , 3.3];
const result = foo(array);
assertTrue(HasHoleyDoubleElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, , 3.3];
const result2 = foo(array2);
assertTrue(HasHoleyDoubleElements(result2));
assertOptimized(foo);
})();
(function testHoleyDoubleElements2() {
function foo(a) {
return a.map(plusOneAndMore);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, , 3];
const result = foo(array);
assertTrue(HasHoleyDoubleElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, , 3];
const result2 = foo(array2);
assertTrue(HasHoleyDoubleElements(result2));
assertOptimized(foo);
})();
(function testPackedElements1() {
function foo(a) {
return a.map(plusOneInObject);
}
%PrepareFunctionForOptimization(foo);
const array = [{a: 1}, {a: 2}, {a: 3}];
const result = foo(array);
assertTrue(HasPackedObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [{a: 1}, {a: 2}, {a: 3}];
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedObjectElements(result2));
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testPackedElements2() {
function foo(a) {
return a.map(wrapInObject);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, 3];
const result = foo(array);
assertTrue(HasPackedObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, 3];
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedObjectElements(result2));
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testHoleyObjectElements1() {
function foo(a) {
return a.map(plusOneInObject);
}
%PrepareFunctionForOptimization(foo);
const array = [{a: 1}, {a: 2}, , {a: 3}];
const result = foo(array);
assertTrue(HasHoleyObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [{a: 1}, {a: 2}, , {a: 3}];
const result2 = foo(array2);
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testHoleyObjectElements2() {
function foo(a) {
return a.map(wrapInObject);
}
%PrepareFunctionForOptimization(foo);
const array = [1, 2, , 3];
const result = foo(array);
assertTrue(HasHoleyObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
const array2 = [1, 2, , 3];
const result2 = foo(array2);
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testFromObjectToPackedSmi() {
function foo(a) {
return a.map(unwrapObject);
}
%PrepareFunctionForOptimization(foo);
const array = [{a: 1}, {a: 2}, {a: 3}];
const array2 = [{a: 1}, {a: 2}, {a: 3}];
const result = foo(array);
assertTrue(HasPackedSmiElements(result));
%OptimizeFunctionOnNextCall(foo);
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedSmiElements(result2));
assertTrue(HasHoleySmiElements(result2));
assertOptimized(foo);
})();
(function testFromObjectToHoleySmi() {
function foo(a) {
return a.map(unwrapObject);
}
%PrepareFunctionForOptimization(foo);
const array = [{a: 1}, {a: 2}, , {a: 3}];
const array2 = [{a: 1}, {a: 2}, , {a: 3}];
const result = foo(array);
assertTrue(HasHoleySmiElements(result));
%OptimizeFunctionOnNextCall(foo);
const result2 = foo(array2);
assertTrue(HasHoleySmiElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromPackedSmiToDoubleWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromSmiToDouble);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, 0];
const array2 = [0, 0, 0];
const result = foo(array);
assertTrue(HasPackedDoubleElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedDoubleElements(result2));
assertTrue(HasHoleyDoubleElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromHoleySmiToDoubleWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromSmiToDouble);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, , 0];
const array2 = [0, 0, , 0];
const result = foo(array);
assertTrue(HasHoleyDoubleElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
assertTrue(HasHoleyDoubleElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromPackedSmiToObjectWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromSmiToObject);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, 0];
const array2 = [0, 0, 0];
const result = foo(array);
assertTrue(HasPackedObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedObjectElements(result2));
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromHoleySmiToObjectWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromSmiToObject);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, , 0];
const array2 = [0, 0, , 0];
const result = foo(array);
assertTrue(HasHoleyObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromPackedSmiToDoubleToObjectWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromDoubleToObject);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, 0];
const array2 = [0, 0, 0];
const result = foo(array);
assertTrue(HasPackedObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedObjectElements(result2));
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromHoleySmiToDoubleToObjectWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromDoubleToObject);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, , 0];
const array2 = [0, 0, , 0];
const result = foo(array);
assertTrue(HasHoleyObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromPackedSmiToObjectToDoubleWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromObjectToDouble);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, 0];
const array2 = [0, 0, 0];
const result = foo(array);
assertTrue(HasPackedObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedObjectElements(result2));
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testTransitionFromHoleySmiToObjectToDoubleWhileMapping() {
resetTransitionFunctions();
function foo(a) {
return a.map(transitionFromObjectToDouble);
}
%PrepareFunctionForOptimization(foo);
const array = [0, 0, , 0];
const array2 = [0, 0, , 0];
const result = foo(array);
assertTrue(HasHoleyObjectElements(result));
%OptimizeFunctionOnNextCall(foo);
resetTransitionFunctions();
const result2 = foo(array2);
assertTrue(HasHoleyObjectElements(result2));
assertOptimized(foo);
})();
(function testMapperReducesLength() {
let array = [0, 1, 2];
function evil(x) {
if (x == 1) {
array.length = 1;
}
return x;
}
%PrepareFunctionForOptimization(evil);
function foo(a) {
return a.map(evil);
}
%PrepareFunctionForOptimization(foo);
const result = foo(array);
assertTrue(HasHoleySmiElements(result));
assertEquals(undefined, result[2]);
array = [0, 1, 2];
%OptimizeFunctionOnNextCall(foo);
const result2 = foo(array);
assertTrue(HasHoleySmiElements(result2));
assertEquals(undefined, result2[2]);
// Deopted since we iterated the array out of bounds.
assertUnoptimized(foo);
})();

View File

@ -0,0 +1,263 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
// Test multiple arguments push for PACKED_SMI_ELEMENTS.
(function() {
function push0(a) {
return a.push();
}
%PrepareFunctionForOptimization(push0);
assertEquals(0, push0([]));
assertEquals(1, push0([1]));
%OptimizeFunctionOnNextCall(push0);
assertEquals(2, push0([1, 2]));
function push1(a) {
return a.push(1);
}
%PrepareFunctionForOptimization(push1);
assertEquals(1, push1([]));
assertEquals(2, push1([1]));
%OptimizeFunctionOnNextCall(push1);
assertEquals(3, push1([1, 2]));
function push2(a) {
return a.push(1, 2);
}
%PrepareFunctionForOptimization(push2);
assertEquals(2, push2([]));
assertEquals(3, push2([1]));
%OptimizeFunctionOnNextCall(push2);
assertEquals(4, push2([1, 2]));
function push3(a) {
return a.push(1, 2, 3);
}
%PrepareFunctionForOptimization(push3);
assertEquals(3, push3([]));
assertEquals(4, push3([1]));
%OptimizeFunctionOnNextCall(push3);
assertEquals(5, push3([1, 2]));
})();
// Test multiple arguments push for HOLEY_SMI_ELEMENTS.
(function() {
function push0(a) {
return a.push();
}
%PrepareFunctionForOptimization(push0);
assertEquals(1, push0(new Array(1)));
assertEquals(2, push0(new Array(2)));
%OptimizeFunctionOnNextCall(push0);
assertEquals(3, push0(new Array(3)));
function push1(a) {
return a.push(1);
}
%PrepareFunctionForOptimization(push1);
assertEquals(2, push1(new Array(1)));
assertEquals(3, push1(new Array(2)));
%OptimizeFunctionOnNextCall(push1);
assertEquals(4, push1(new Array(3)));
function push2(a) {
return a.push(1, 2);
}
%PrepareFunctionForOptimization(push2);
assertEquals(3, push2(new Array(1)));
assertEquals(4, push2(new Array(2)));
%OptimizeFunctionOnNextCall(push2);
assertEquals(5, push2(new Array(3)));
function push3(a) {
return a.push(1, 2, 3);
}
%PrepareFunctionForOptimization(push3);
assertEquals(4, push3(new Array(1)));
assertEquals(5, push3(new Array(2)));
%OptimizeFunctionOnNextCall(push3);
assertEquals(6, push3(new Array(3)));
})();
// Test multiple arguments push for PACKED_DOUBLE_ELEMENTS.
(function() {
function push0(a) {
return a.push();
}
%PrepareFunctionForOptimization(push0);
assertEquals(1, push0([1.1]));
assertEquals(2, push0([1.1, 2.2]));
%OptimizeFunctionOnNextCall(push0);
assertEquals(3, push0([1.1, 2.2, 3.3]));
function push1(a) {
return a.push(1.1);
}
%PrepareFunctionForOptimization(push1);
assertEquals(2, push1([1.1]));
assertEquals(3, push1([1.1, 2.2]));
%OptimizeFunctionOnNextCall(push1);
assertEquals(4, push1([1.1, 2.2, 3.3]));
function push2(a) {
return a.push(1.1, 2.2);
}
%PrepareFunctionForOptimization(push2);
assertEquals(3, push2([1.1]));
assertEquals(4, push2([1.1, 2.2]));
%OptimizeFunctionOnNextCall(push2);
assertEquals(5, push2([1.1, 2.2, 3.3]));
function push3(a) {
return a.push(1.1, 2.2, 3.3);
}
%PrepareFunctionForOptimization(push3);
assertEquals(4, push3([1.1]));
assertEquals(5, push3([1.1, 2.2]));
%OptimizeFunctionOnNextCall(push3);
assertEquals(6, push3([1.1, 2.2, 3.3]));
})();
// Test multiple arguments push for HOLEY_DOUBLE_ELEMENTS.
(function() {
function push0(a) {
return a.push();
}
%PrepareFunctionForOptimization(push0);
assertEquals(2, push0([, 1.1]));
assertEquals(3, push0([, 1.1, 2.2]));
%OptimizeFunctionOnNextCall(push0);
assertEquals(4, push0([, 1.1, 2.2, 3.3]));
function push1(a) {
return a.push(1.1);
}
%PrepareFunctionForOptimization(push1);
assertEquals(3, push1([, 1.1]));
assertEquals(4, push1([, 1.1, 2.2]));
%OptimizeFunctionOnNextCall(push1);
assertEquals(5, push1([, 1.1, 2.2, 3.3]));
function push2(a) {
return a.push(1.1, 2.2);
}
%PrepareFunctionForOptimization(push2);
assertEquals(4, push2([, 1.1]));
assertEquals(5, push2([, 1.1, 2.2]));
%OptimizeFunctionOnNextCall(push2);
assertEquals(6, push2([, 1.1, 2.2, 3.3]));
function push3(a) {
return a.push(1.1, 2.2, 3.3);
}
%PrepareFunctionForOptimization(push3);
assertEquals(5, push3([, 1.1]));
assertEquals(6, push3([, 1.1, 2.2]));
%OptimizeFunctionOnNextCall(push3);
assertEquals(7, push3([, 1.1, 2.2, 3.3]));
})();
// Test multiple arguments push for PACKED_ELEMENTS.
(function() {
function push0(a) {
return a.push();
}
%PrepareFunctionForOptimization(push0);
assertEquals(1, push0(['1']));
assertEquals(2, push0(['1', '2']));
%OptimizeFunctionOnNextCall(push0);
assertEquals(3, push0(['1', '2', '3']));
function push1(a) {
return a.push('1');
}
%PrepareFunctionForOptimization(push1);
assertEquals(2, push1(['1']));
assertEquals(3, push1(['1', '2']));
%OptimizeFunctionOnNextCall(push1);
assertEquals(4, push1(['1', '2', '3']));
function push2(a) {
return a.push('1', '2');
}
%PrepareFunctionForOptimization(push2);
assertEquals(3, push2(['1']));
assertEquals(4, push2(['1', '2']));
%OptimizeFunctionOnNextCall(push2);
assertEquals(5, push2(['1', '2', '3']));
function push3(a) {
return a.push('1', '2', '3');
}
%PrepareFunctionForOptimization(push3);
assertEquals(4, push3(['1']));
assertEquals(5, push3(['1', '2']));
%OptimizeFunctionOnNextCall(push3);
assertEquals(6, push3(['1', '2', '3']));
})();
// Test multiple arguments push for HOLEY_ELEMENTS.
(function() {
function push0(a) {
return a.push();
}
%PrepareFunctionForOptimization(push0);
assertEquals(2, push0([, '1']));
assertEquals(3, push0([, '1', '2']));
%OptimizeFunctionOnNextCall(push0);
assertEquals(4, push0([, '1', '2', '3']));
function push1(a) {
return a.push('1');
}
%PrepareFunctionForOptimization(push1);
assertEquals(3, push1([, '1']));
assertEquals(4, push1([, '1', '2']));
%OptimizeFunctionOnNextCall(push1);
assertEquals(5, push1([, '1', '2', '3']));
function push2(a) {
return a.push('1', '2');
}
%PrepareFunctionForOptimization(push2);
assertEquals(4, push2([, '1']));
assertEquals(5, push2([, '1', '2']));
%OptimizeFunctionOnNextCall(push2);
assertEquals(6, push2([, '1', '2', '3']));
function push3(a) {
return a.push('1', '2', '3');
}
%PrepareFunctionForOptimization(push3);
assertEquals(5, push3([, '1']));
assertEquals(6, push3([, '1', '2']));
%OptimizeFunctionOnNextCall(push3);
assertEquals(7, push3([, '1', '2', '3']));
})();

View File

@ -0,0 +1,71 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
// Test elements transition from SMI to DOUBLE.
(function() {
const a = [];
const foo = (x, y) => a.push(x, y);
%PrepareFunctionForOptimization(foo);
foo(1, 2);
foo(3, 4);
%OptimizeFunctionOnNextCall(foo);
foo(5, 6.6);
assertEquals([1, 2, 3, 4, 5, 6.6], a);
})();
(function() {
const a = [];
const foo = (x, y) => a.push(x, y);
%PrepareFunctionForOptimization(foo);
foo(1, 2);
foo(3, 4);
%OptimizeFunctionOnNextCall(foo);
foo(5.5, 6.6);
assertEquals([1, 2, 3, 4, 5.5, 6.6], a);
})();
// Test elements transition from SMI to OBJECT.
(function() {
const a = [];
const foo = (x, y) => a.push(x, y);
%PrepareFunctionForOptimization(foo);
foo(1, 2);
foo(3, 4);
%OptimizeFunctionOnNextCall(foo);
foo(5, '6');
assertEquals([1, 2, 3, 4, 5, '6'], a);
})();
(function() {
const a = [];
const foo = (x, y) => a.push(x, y);
%PrepareFunctionForOptimization(foo);
foo(1, 2);
foo(3, 4);
%OptimizeFunctionOnNextCall(foo);
foo('5', '6');
assertEquals([1, 2, 3, 4, '5', '6'], a);
})();
// Test elements transition from DOUBLE to OBJECT.
(function() {
const a = [0.5];
const foo = (x, y) => a.push(x, y);
%PrepareFunctionForOptimization(foo);
foo(1, 2);
foo(3, 4);
%OptimizeFunctionOnNextCall(foo);
foo(5, '6');
assertEquals([0.5, 1, 2, 3, 4, 5, '6'], a);
})();
(function() {
const a = [0.5];
const foo = (x, y) => a.push(x, y);
%PrepareFunctionForOptimization(foo);
foo(1, 2);
foo(3, 4);
%OptimizeFunctionOnNextCall(foo);
foo('5', '6');
assertEquals([0.5, 1, 2, 3, 4, '5', '6'], a);
})();

View File

@ -0,0 +1,54 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
// Test side effects on arguments evaluation.
(function() {
const a = [];
const bar = x => { a.push(x); return x; };
const foo = x => a.push(bar(x), bar(x));
%PrepareFunctionForOptimization(foo);
foo(1);
foo(2);
%OptimizeFunctionOnNextCall(foo);
foo(3);
assertEquals([1,1,1,1, 2,2,2,2, 3,3,3,3], a);
})();
// Test invalidation on arguments evaluation.
(function() {
let y = 1;
const a = [];
const bar = x => { a.push(y); return x; }
const foo = x => a.push(bar(x), bar(x));
%PrepareFunctionForOptimization(foo);
foo(1);
y = 2;
foo(2);
%OptimizeFunctionOnNextCall(foo);
y = 3;
foo(3);
assertOptimized(foo);
y = 4.4;
foo(4);
assertEquals([1,1,1,1, 2,2,2,2, 3,3,3,3, 4.4,4.4,4,4], a);
})();
(function() {
let y = 1;
const a = [0.5];
const bar = x => { a.push(y); return x; }
const foo = x => a.push(bar(x), bar(x));
%PrepareFunctionForOptimization(foo);
foo(1);
y = 2;
foo(2);
%OptimizeFunctionOnNextCall(foo);
y = 3;
foo(3);
assertOptimized(foo);
y = '4';
foo(4);
assertEquals([0.5, 1,1,1,1, 2,2,2,2, 3,3,3,3, '4','4',4,4], a);
})();

View File

@ -0,0 +1,483 @@
// 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 --turbofan --no-stress-flush-code
// Flags: --no-lazy-feedback-allocation
// Test CloneFastJSArray inserted by JSCallReducer for Array.prototype.slice.
// CloneFastJSArray produces COW arrays if the original array is COW.
// Trigger JSCallReducer on slice() and slice(0)
(function() {
const arr = [1,2,3,4,5];
function slice() {
return arr.slice();
}
function slice0() {
return arr.slice(0);
}
%PrepareFunctionForOptimization(slice0);
%PrepareFunctionForOptimization(slice);
assertEquals(arr, slice());
assertFalse(arr === slice());
assertEquals(slice(), slice0());
assertEquals(slice0(), slice());
%OptimizeFunctionOnNextCall(slice0);
assertEquals(slice(), slice0());
%OptimizeFunctionOnNextCall(slice);
assertEquals(slice(), slice0());
assertOptimized(slice); assertOptimized(slice0);
})();
// This will cause deopt of slice by a CheckMap installed by
// JSNativeContextSpecialization::ReduceNamedAccess
(function() {
const arr = [1,2,3,4,5];
function slice() {
return arr.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(arr, slice());
assertEquals(slice(), arr);
%OptimizeFunctionOnNextCall(slice);
slice();
// Trigger deopt here
arr.push(7.2);
assertEquals(slice()[5], 7.2);
})();
// There should not be a deopt cycle.
(function() {
const arr = [1,2,3,4,5];
function slice() {
return arr.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(arr, slice());
assertEquals(slice(), arr);
%OptimizeFunctionOnNextCall(slice);
// Trigger opt
assertEquals(slice(), arr);
// Trigger deopt by CheckMap from JSNativeContextSpecialization
arr.push(7.2);
slice();
%PrepareFunctionForOptimization(slice);
%OptimizeFunctionOnNextCall(slice);
// Trigger opt again
slice();
// Should not deopt again
arr.push(8.2);
slice();
assertOptimized(slice);
})();
// JSCallReducer will not reduce because the species has been modified
(function() {
const array = [3,4,5];
function slice(){
return array.slice();
}
class MyArray extends Array {};
array.constructor = MyArray;
%PrepareFunctionForOptimization(slice);
slice(); slice();
%OptimizeFunctionOnNextCall(slice);
var narr = slice();
assertInstanceof(narr, MyArray);
})();
(function() {
const array = [3,4,5];
function slice(){
return array.slice();
}
%PrepareFunctionForOptimization(slice);
slice(); slice();
%OptimizeFunctionOnNextCall(slice);
slice();
class MyArray extends Array {};
array.constructor = MyArray;
// deopt
var narr = slice();
// if not deopt, narr will be instanceof Array
assertTrue(narr instanceof MyArray);
})();
// JSCallReducer adds check for UnreliableReceiverMaps
(function() {
const arr = [1,2,3,4,5];
function slice() {
return arr.slice();
}
%PrepareFunctionForOptimization(slice);
slice(); slice();
arr.foo = 6.2;
%OptimizeFunctionOnNextCall(slice);
// JSCallReducer will add check for UnreliableReceiverMaps
slice();
// Trigger deopt because of DependOnStableMaps
// installed by JSNativeContextSpecialization,
// but not the check installed by ReduceArrayPrototypeSlice itself
arr.bar = 7.2;
let narr = slice();
assertEquals(arr, narr);
assertEquals(narr.foo, undefined);
assertEquals(narr.bar, undefined);
})();
// Multiple maps
(function() {
const iarr = [1,2,3];
const darr = [2.1, 3.3, 0.2];
function slice(arr) {
return arr.slice();
}
%PrepareFunctionForOptimization(slice);
slice(iarr); slice(darr);
slice(iarr); slice(darr);
%OptimizeFunctionOnNextCall(slice);
// The optimization works for both maps
assertEquals(iarr, slice(iarr));
assertEquals(darr, slice(darr));
assertOptimized(slice);
})();
// Tests for the branch of CanInlineArrayIteratingBuiltin
// JSCallReducer will not reduce to CloneFastJSArray
// if array's prototype is not JS_ARRAY_TYPE
(function () {
class MyArray extends Array {
constructor() {
super();
this[6]= 6;
}
}
let array = new MyArray(3, 5, 4);
function slice() {
return array.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(slice(),array);
slice();
%OptimizeFunctionOnNextCall(slice);
let narr = slice();
// here, slice supposes to call MyArray's constructor.
// If we optimize with CloneFastJSArray, Array's constructor is called instead.
assertEquals(narr[6], 6);
assertTrue(narr instanceof MyArray);
})();
// JSCallReducer will not reduce to CloneFastJSArray
// if array's instance type is not JS_ARRAY_TYPE.
// CloneFastJSArray does not work with non JS_ARRAY_TYPE.
// Check : receiver_map->instance_type() == JS_ARRAY_TYPE
(function () {
var x = {"0" : 0, "2": 2} ;
x.__proto__ = Array.prototype;
function slice() {
return x.slice();
}
%PrepareFunctionForOptimization(slice);
slice(); slice();
%OptimizeFunctionOnNextCall(slice);
assertEquals(slice(), []);
})();
// JSCallReducer will not reduce to CloneFastJSArray
// since array is not Fast Elements Kind
// Check : IsFastElementsKind(receiver_map->elements_kind())
(function () {
var array = [3, 4, 5];
function slice() {
return array.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(slice(),array);
slice();
// a sparse array switches to Dictionary Elements
array[9999] = 0;
%OptimizeFunctionOnNextCall(slice);
var narr = slice();
assertEquals(narr, array);
})();
(function () {
var array = [3, 4, 5];
function slice() {
return array.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(slice(),array);
slice();
%OptimizeFunctionOnNextCall(slice);
slice();
// a sparse array switches to Dictionary Elements
array[9999] = 0;
// trigger deopt because map changes
assertEquals(slice(),array);
})();
// JSCallReducer will not reduce to CloneFastJSArray
// if array is used as a prototype and has unstable map
(function () {
var array = [3, 5, 4];
function slice(arr) {
return arr.slice();
}
%PrepareFunctionForOptimization(slice);
// make array's map is_prototype_map()
var x = {__proto__ : array};
assertEquals(slice(array),array);
slice(array);
// make array's map unstable
array.push(6.3);
slice(array);
%OptimizeFunctionOnNextCall(slice);
assertEquals(slice(array),array);
})();
// JSCallReducer will not reduce to CloneFastJSArray
// if the Array prototype got some elements.
// Check: isolate->IsNoElementsProtectorIntact()
(function () {
var array = [, 6, 6];
function slice() {
return array.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(slice(),array);
slice();
array.__proto__.push(6);
%OptimizeFunctionOnNextCall(slice);
// if we optimized, we would get [ , 6, 6]
// here, slice copies elements from both the object and the prototype
let narr = slice();
assertNotEquals(Object.getOwnPropertyDescriptor(narr,0), undefined);
assertEquals(narr, [6, 6, 6]);
})();
(function () {
var array = [, 6, 6];
function slice() {
return array.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(slice(),array);
slice();
%OptimizeFunctionOnNextCall(slice);
slice();
// Deopt
array.__proto__.push(6);
let narr = slice();
assertNotEquals(Object.getOwnPropertyDescriptor(narr, 0), undefined);
assertEquals(narr[0], 6);
})();
// JSCallReducer will not reduce to CloneFastJSArray
// if the Array prototype is not original
// Check: isolate->IsAnyInitialArrayPrototype(receiver_prototype)
(function () {
var array = [6, , 6];
function slice() {
return array.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(slice(),array);
slice();
// change the prototype
array.__proto__ = [ , 6, ];
%OptimizeFunctionOnNextCall(slice);
let narr = slice();
// if optimized, we would get [6, , 6]
assertNotEquals(Object.getOwnPropertyDescriptor(narr, 1), undefined);
assertEquals(narr, [6,6,6]);
})();
(function () {
var array = [6, ,6];
function slice() {
return array.slice();
}
%PrepareFunctionForOptimization(slice);
assertEquals(slice(),array);
slice();
%OptimizeFunctionOnNextCall(slice);
slice();
// change the prototype
array.__proto__ = [,6,];
// deopt because of map changed
let narr = slice();
// if optimized, we would get [6, , 6]
assertNotEquals(Object.getOwnPropertyDescriptor(narr, 1), undefined);
assertEquals(narr, [6,6,6]);
})();
// Packed
// Trigger JSCallReducer on slice() and slice(0)
(function() {
// Non-extensible:
var arr = Object.preventExtensions([1,2,'a',4,5]);
function slice() {
return arr.slice();
}
function slice0() {
return arr.slice(0);
}
function test() {
%PrepareFunctionForOptimization(slice0);
%PrepareFunctionForOptimization(slice);
assertEquals(arr, slice());
assertFalse(arr === slice());
assertEquals(slice(), slice0());
assertEquals(slice0(), slice());
%OptimizeFunctionOnNextCall(slice0);
assertEquals(slice(), slice0());
%OptimizeFunctionOnNextCall(slice);
assertEquals(slice(), slice0());
assertOptimized(slice); assertOptimized(slice0);
}
test();
// Sealed
arr = Object.seal([1,2,'a',4,5]);
test();
// Frozen
arr = Object.freeze([1,2,'a',4,5]);
test();
})();
// Holey
// Trigger JSCallReducer on slice() and slice(0)
(function() {
// Non-extensible:
var arr = Object.preventExtensions([,1,2,'a',4,5]);
function slice() {
return arr.slice();
}
function slice0() {
return arr.slice(0);
}
function test() {
%PrepareFunctionForOptimization(slice0);
%PrepareFunctionForOptimization(slice);
assertEquals(arr, slice());
assertFalse(arr === slice());
assertEquals(slice(), slice0());
assertEquals(slice0(), slice());
%OptimizeFunctionOnNextCall(slice0);
assertEquals(slice(), slice0());
%OptimizeFunctionOnNextCall(slice);
assertEquals(slice(), slice0());
assertOptimized(slice0);
assertOptimized(slice);
}
test();
// Sealed
arr = Object.seal([,1,2,'a',4,5]);
test();
// Frozen
arr = Object.freeze([,1,2,'a',4,5]);
test();
})();

View File

@ -0,0 +1,69 @@
// 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
// Basic loop peeling test case with Array.prototype.some().
(function() {
function foo(a, o) {
return a.some(x => x === o.x);
}
%PrepareFunctionForOptimization(foo);
assertTrue(foo([1, 2, 3], {x:3}));
assertFalse(foo([0, 1, 2], {x:3}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo([1, 2, 3], {x:3}));
assertFalse(foo([0, 1, 2], {x:3}));
// Packed
// Non-extensible
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.preventExtensions([1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions([0, 1, '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.preventExtensions([1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions([0, 1, '2']), {x:'3'}));
// Sealed
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.seal([1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.seal([0, 1, '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.seal([1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.seal([0, 1, '2']), {x:'3'}));
// Frozen
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.freeze([1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.freeze([0, 1, '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.freeze([1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.freeze([0, 1, '2']), {x:'3'}));
// Holey
// Non-extensible
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.preventExtensions([, 1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions([, 0, 1, '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.preventExtensions([, 1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.preventExtensions([, 0, 1, '2']), {x:'3'}));
// Sealed
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.seal([, 1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.seal([, 0, 1, '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.seal([, 1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.seal([, 0, 1, '2']), {x:'3'}));
// Frozen
%PrepareFunctionForOptimization(foo);
assertTrue(foo(Object.freeze([, 1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.freeze([, 0, 1, '2']), {x:'3'}));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(Object.freeze([, 1, 2, '3']), {x:'3'}));
assertFalse(foo(Object.freeze([, 0, 1, '2']), {x:'3'}));
})();

View File

@ -0,0 +1,35 @@
// 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() {}
function f() {
return [42].map(_ => 88);
}
let y;
%PrepareFunctionForOptimization(f);
y = f();
assertFalse(y instanceof Foo);
assertInstanceof(y, Array);
y = f();
assertFalse(y instanceof Foo);
assertInstanceof(y, Array);
%OptimizeFunctionOnNextCall(f);
y = f();
assertFalse(y instanceof Foo);
assertInstanceof(y, Array);
assertTrue(Reflect.defineProperty(Array, Symbol.species, {value: Foo}));
y = f();
assertInstanceof(y, Foo);
assertFalse(y instanceof Array);

View File

@ -0,0 +1,682 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Test Array subclass default constructor with no parameters.
(function() {
const A = class A extends Array { };
function foo() { return new A; }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(0, foo().length);
assertInstanceof(foo(), A);
assertEquals(0, foo().length);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(0, foo().length);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass default constructor with small constant length.
(function() {
const A = class A extends Array { };
const L = 4;
function foo() { return new A(L); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass default constructor with large constant length.
(function() {
const A = class A extends Array { };
const L = 1024 * 1024;
function foo() { return new A(L); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass default constructor with known boolean.
(function() {
const A = class A extends Array { };
function foo() { return new A(true); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals(true, foo()[0]);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals(true, foo()[0]);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals(true, foo()[0]);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass default constructor with known string.
(function() {
const A = class A extends Array { };
function foo() { return new A(""); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals("", foo()[0]);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals("", foo()[0]);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals("", foo()[0]);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass default constructor with known object.
(function() {
const A = class A extends Array { };
const O = {foo: "foo"};
function foo() { return new A(O); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertSame(O, foo()[0]);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertSame(O, foo()[0]);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertSame(O, foo()[0]);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);})();
// Test Array subclass default constructor with known small integers.
(function() {
const A = class A extends Array { };
function foo() { return new A(1, 2, 3); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1, foo()[0]);
assertEquals(2, foo()[1]);
assertEquals(3, foo()[2]);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1, foo()[0]);
assertEquals(2, foo()[1]);
assertEquals(3, foo()[2]);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass default constructor with known numbers.
(function() {
const A = class A extends Array { };
function foo() { return new A(1.1, 2.2, 3.3); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1.1, foo()[0]);
assertEquals(2.2, foo()[1]);
assertEquals(3.3, foo()[2]);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1.1, foo()[0]);
assertEquals(2.2, foo()[1]);
assertEquals(3.3, foo()[2]);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass default constructor with known strings.
(function() {
const A = class A extends Array { };
function foo() { return new A("a", "b", "c", "d"); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(4, foo().length);
assertEquals("a", foo()[0]);
assertEquals("b", foo()[1]);
assertEquals("c", foo()[2]);
assertEquals("d", foo()[3]);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(4, foo().length);
assertEquals("a", foo()[0]);
assertEquals("b", foo()[1]);
assertEquals("c", foo()[2]);
assertEquals("d", foo()[3]);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with no parameters.
(function() {
const A = class A extends Array {
constructor() {
super();
this.bar = 1;
}
};
function foo() { return new A; }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(0, foo().length);
assertEquals(1, foo().bar);
assertInstanceof(foo(), A);
assertEquals(0, foo().length);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(0, foo().length);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);})();
// Test Array subclass constructor with small constant length.
(function() {
const A = class A extends Array {
constructor(n) {
super(n);
this.bar = 1;
}
};
const L = 4;
function foo() { return new A(L); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertEquals(1, foo().bar);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with large constant length.
(function() {
const A = class A extends Array {
constructor(n) {
super(n);
this.bar = 1;
}
};
const L = 1024 * 1024;
function foo() { return new A(L); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertEquals(1, foo().bar);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(L, foo().length);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with known boolean.
(function() {
const A = class A extends Array {
constructor(n) {
super(n);
this.bar = 1;
}
};
function foo() { return new A(true); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals(true, foo()[0]);
assertEquals(1, foo().bar);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals(true, foo()[0]);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals(true, foo()[0]);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with known string.
(function() {
const A = class A extends Array {
constructor(n) {
super(n);
this.bar = 1;
}
};
function foo() { return new A(""); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals("", foo()[0]);
assertEquals(1, foo().bar);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals("", foo()[0]);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertEquals("", foo()[0]);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with known object.
(function() {
const A = class A extends Array {
constructor(n) {
super(n);
this.bar = 1;
}
};
const O = {foo: "foo"};
function foo() { return new A(O); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertSame(O, foo()[0]);
assertEquals(1, foo().bar);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertSame(O, foo()[0]);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(1, foo().length);
assertSame(O, foo()[0]);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with known small integers.
(function() {
const A = class A extends Array {
constructor(x, y, z) {
super(x, y, z);
this.bar = 1;
}
};
function foo() { return new A(1, 2, 3); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1, foo()[0]);
assertEquals(2, foo()[1]);
assertEquals(3, foo()[2]);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1, foo()[0]);
assertEquals(2, foo()[1]);
assertEquals(3, foo()[2]);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with known numbers.
(function() {
const A = class A extends Array {
constructor(x, y, z) {
super(x, y, z);
this.bar = 1;
}
};
function foo() { return new A(1.1, 2.2, 3.3); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1.1, foo()[0]);
assertEquals(2.2, foo()[1]);
assertEquals(3.3, foo()[2]);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(3, foo().length);
assertEquals(1.1, foo()[0]);
assertEquals(2.2, foo()[1]);
assertEquals(3.3, foo()[2]);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();
// Test Array subclass constructor with known strings.
(function() {
const A = class A extends Array {
constructor(a, b, c, d) {
super(a, b, c, d);
this.bar = 1;
}
};
function foo() { return new A("a", "b", "c", "d"); }
function test(foo) {
%PrepareFunctionForOptimization(foo);
assertInstanceof(foo(), A);
assertEquals(4, foo().length);
assertEquals("a", foo()[0]);
assertEquals("b", foo()[1]);
assertEquals("c", foo()[2]);
assertEquals("d", foo()[3]);
assertEquals(1, foo().bar);
%OptimizeFunctionOnNextCall(foo);
assertInstanceof(foo(), A);
assertEquals(4, foo().length);
assertEquals("a", foo()[0]);
assertEquals("b", foo()[1]);
assertEquals("c", foo()[2]);
assertEquals("d", foo()[3]);
assertEquals(1, foo().bar);
}
test(foo);
// Non-extensible
function fooPreventExtensions() { return Object.preventExtensions(foo()); }
test(fooPreventExtensions);
// Sealed
function fooSeal() { return Object.seal(foo()); }
test(fooSeal);
// Frozen
function fooFreeze() { return Object.freeze(foo()); }
test(fooFreeze);
})();

View File

@ -0,0 +1,191 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Test deopt with count operation on parameter.
var max_smi = 1073741823;
var o = {x:0};
function assign1(x) { x += 1; o.x = x; }
assign1(max_smi);
assertEquals(max_smi + 1, o.x);
assign1(1.1);
assertEquals(2.1, o.x);
// Test deopt with count operation on named property.
function assign2(p) { p.x += 1 }
%PrepareFunctionForOptimization(assign2);
o.x = "42";
assign2(o);
assertEquals("421", o.x);
var s = max_smi - 10;
o.x = s;
for(var i = 0; i < 20; i++) {
assign2(o);
if (i == 4) {
%OptimizeFunctionOnNextCall(assign2);
}
}
assertEquals(max_smi + 10, o.x);
// Test deopt with count operation on keyed property.
function assign3(a, b) { a[b] += 1; }
%PrepareFunctionForOptimization(assign3);
o = ["42"];
assign3(o, 0);
assertEquals("421", o[0]);
var s = max_smi - 10;
o[0] = s;
for(var i = 0; i < 20; i++) {
assign3(o, 0);
if (i == 4) {
%OptimizeFunctionOnNextCall(assign3);
}
}
assertEquals(max_smi + 10, o[0]);
assign3(o, "0");
assertEquals(max_smi + 11, o[0]);
// Test bailout when accessing a non-existing array element.
o[0] = 0;
for(var i = 0; i < 5; i++) {
assign3(o, 0);
}
%PrepareFunctionForOptimization(assign3);
%OptimizeFunctionOnNextCall(assign3);
assign3(o, 0);
assign3(o, 1);
// Test bailout with count operation in a value context.
function assign5(x,y) { return (x += 1) + y; }
%PrepareFunctionForOptimization(assign5);
for (var i = 0; i < 5; ++i) assertEquals(4, assign5(2, 1));
%OptimizeFunctionOnNextCall(assign5);
assertEquals(4, assign5(2, 1));
assertEquals(4.1, assign5(2, 1.1));
assertEquals(4.1, assign5(2.1, 1));
function assign7(o,y) { return (o.x += 1) + y; }
%PrepareFunctionForOptimization(assign7);
o = {x:0};
for (var i = 0; i < 5; ++i) {
o.x = 42;
assertEquals(44, assign7(o, 1));
}
%OptimizeFunctionOnNextCall(assign7);
o.x = 42;
assertEquals(44, assign7(o, 1));
o.x = 42;
assertEquals(44.1, assign7(o, 1.1));
o.x = 42.1;
assertEquals(44.1, assign7(o, 1));
function assign9(o,y) { return (o[0] += 1) + y; }
%PrepareFunctionForOptimization(assign9);
q = [0];
for (var i = 0; i < 5; ++i) {
q[0] = 42;
assertEquals(44, assign9(q, 1));
}
%OptimizeFunctionOnNextCall(assign9);
q[0] = 42;
assertEquals(44, assign9(q, 1));
q[0] = 42;
assertEquals(44.1, assign9(q, 1.1));
q[0] = 42.1;
assertEquals(44.1, assign9(q, 1));
// Test deopt because of a failed map check on the load.
function assign10(p) { return p.x += 1 }
%PrepareFunctionForOptimization(assign10);
var g1 = {x:0};
var g2 = {y:0, x:42};
for (var i = 0; i < 5; ++i) {
g1.x = 42;
assertEquals(43, assign10(g1));
assertEquals(43, g1.x);
}
%OptimizeFunctionOnNextCall(assign10);
g1.x = 42;
assertEquals(43, assign10(g1));
assertEquals(43, g1.x);
assertEquals(43, assign10(g2));
assertEquals(43, g2.x);
// Test deopt because of a failed map check on the store.
// The binary operation changes the map as a side effect.
o = {x:0};
var g3 = { valueOf: function() { o.y = "bar"; return 42; }};
function assign11(p) { return p.x += 1; }
%PrepareFunctionForOptimization(assign11);
for (var i = 0; i < 5; i++) {
o.x = "a";
assign11(o);
}
%OptimizeFunctionOnNextCall(assign11);
o.x = "a";
assign11(o);
assertEquals("a11", assign11(o));
o.x = g3;
assertEquals(43, assign11(o));
assertEquals("bar", o.y);
o = [0];
var g4 = { valueOf: function() { o.y = "bar"; return 42; }};
function assign12(p) { return p[0] += 1; }
%PrepareFunctionForOptimization(assign12);
for (var i = 0; i < 5; i++) {
o[0] = "a";
assign12(o);
}
%OptimizeFunctionOnNextCall(assign12);
o[0] = "a";
assign12(o);
assertEquals("a11", assign12(o));
o[0] = g4;
assertEquals(43, assign12(o));
assertEquals("bar", o.y);

View File

@ -0,0 +1,283 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Tests for compound assignments at the top level
z = 2;
z += 4;
assertEquals(z, 6);
a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
// Test compound assignments in an anonymous function with local variables.
(function () {
var z = 2;
z += 4;
assertEquals(z, 6);
var a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
var b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
})();
// Test compound assignments in an anonymous function with global variables.
(function () {
z = 2;
z += 4;
assertEquals(z, 6);
a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
})();
// Test compound assignments in a named function with local variables.
function foo() {
var z = 3;
z += 4;
assertEquals(z, 7);
var a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
var b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
}
foo();
// Test compound assignments in a named function with global variables.
function bar() {
z = 2;
z += 5;
assertEquals(z, 7);
a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
}
bar();
// Entire series of tests repeated, in loops.
// -------------------------------------------
// Tests for compound assignments in a loop at the top level
for (i = 0; i < 5; ++i) {
z = 2;
z += 4;
assertEquals(z, 6);
a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
}
// Test compound assignments in an anonymous function with local variables.
(function () {
for (var i = 0; i < 5; ++i) {
var z = 2;
z += 4;
assertEquals(z, 6);
var a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
var b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
}
})();
// Test compound assignments in an anonymous function with global variables.
(function () {
for (i = 0; i < 5; ++i) {
z = 2;
z += 4;
assertEquals(z, 6);
a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
}
})();
// Test compound assignments in a named function with local variables.
function foo_loop() {
for (i = 0; i < 5; ++i) {
var z = 3;
z += 4;
assertEquals(z, 7);
var a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
var b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
}
}
foo_loop();
// Test compound assignments in a named function with global variables.
function bar_loop() {
for (i = 0; i < 5; ++i) {
z = 2;
z += 5;
assertEquals(z, 7);
a = new Array(10);
a[2] += 7;
a[2] = 15;
a[2] += 2;
assertEquals(17, a[2]);
b = new Object();
b.foo = 5;
b.foo += 12;
assertEquals(17, b.foo);
}
}
bar_loop();
// Test assignment in test context.
function test_assign(x, y) { if (x = y) return x; }
assertEquals(42, test_assign(0, 42));
assertEquals("undefined", typeof test_assign(42, 0));
// Test for assignment using a keyed store ic:
function store_i_in_element_i_of_object_i() {
var i = new Object();
i[i] = i;
}
// Run three times to exercise caches.
store_i_in_element_i_of_object_i();
store_i_in_element_i_of_object_i();
store_i_in_element_i_of_object_i();

View File

@ -0,0 +1,31 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax
function f(x) {
var y = 0;
for (var i = 0; i < x; i++) {
y = 1;
}
return y;
}
function g(iter) {
if (%IsTurbofanEnabled()) {
while (!%ActiveTierIsTurbofan(f) && --iter) f(10);
}
}
%NeverOptimizeFunction(g);
if (!%IsTurbofanEnabled()) quit();
if (%SetBatterySaverMode(true)) {
g(10000);
assertFalse(%ActiveTierIsTurbofan(f));
if (%SetBatterySaverMode(false)) {
g(10000000);
assertTrue(%ActiveTierIsTurbofan(f));
}
}

View File

@ -0,0 +1,40 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan --no-always-turbofan
const big = 2n ** BigInt((2 ** 30)-1);
function testAdd(x, y) {
return x + y;
}
%PrepareFunctionForOptimization(testAdd);
testAdd(3n, 7n);
testAdd(17n, -54n);
%OptimizeFunctionOnNextCall(testAdd);
assertEquals(testAdd(6n, 2n), 8n);
// Re-prepare the function immediately to make sure type feedback isn't cleared
// by an untimely gc, as re-optimization on new feedback is tested below
%PrepareFunctionForOptimization(testAdd);
assertOptimized(testAdd);
assertThrows(() => testAdd(big, big), RangeError);
if (%Is64Bit()) {
assertUnoptimized(testAdd);
}
testAdd(30n, -50n);
testAdd(23n, 5n);
%OptimizeFunctionOnNextCall(testAdd);
assertEquals(testAdd(-7n, -12n), -19n);
assertOptimized(testAdd);
assertThrows(() => testAdd(big, big), RangeError);
assertOptimized(testAdd);
assertThrows(() => testAdd(big, big), RangeError);
assertOptimized(testAdd);

View File

@ -0,0 +1,26 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
{
let a = 0n;
a = 3n;
function TestAdd() {
let sum = 0n;
for (let i = 0; i < 3; ++i) {
sum = a + sum;
}
return sum;
}
%PrepareFunctionForOptimization(TestAdd);
TestAdd();
TestAdd();
%OptimizeFunctionOnNextCall(TestAdd);
TestAdd();
TestAdd();
}

View File

@ -0,0 +1,39 @@
// Copyright 2021 the V8 project 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 --turbofan --no-always-turbofan
function f(x) {
return BigInt.asIntN(3, x);
}
%PrepareFunctionForOptimization(f);
assertEquals(-1n, f(7n));
assertEquals(1n, f(9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(-1n, f(7n));
assertEquals(1n, f(9n));
assertOptimized(f);
// BigInt.asIntN throws TypeError for non-BigInt arguments.
assertThrows(() => f(2), TypeError);
if(%Is64Bit()) {
// On 64 bit architectures TurboFan optimizes BigInt.asIntN to native code
// that deoptimizes on non-BigInt arguments.
assertUnoptimized(f);
// The next time the function is optimized, speculation should be disabled
// so the builtin call is kept, which won't deoptimize again.
%PrepareFunctionForOptimization(f);
assertEquals(-1n, f(7n));
assertEquals(1n, f(9n));
%OptimizeFunctionOnNextCall(f);
}
assertEquals(-1n, f(7n));
assertOptimized(f);
// Re-optimized still throws but does not deopt-loop.
assertThrows(() => f(2), TypeError);
assertOptimized(f);

View File

@ -0,0 +1,39 @@
// Copyright 2021 the V8 project 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 --turbofan --no-always-turbofan
function f(x) {
return BigInt.asUintN(3, x);
}
%PrepareFunctionForOptimization(f);
assertEquals(7n, f(7n));
assertEquals(1n, f(9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(7n, f(7n));
assertEquals(1n, f(9n));
assertOptimized(f);
// BigInt.asUintN throws TypeError for non-BigInt arguments.
assertThrows(() => f(2), TypeError);
if(%Is64Bit()) {
// On 64 bit architectures TurboFan optimizes BigInt.asUintN to native code
// that deoptimizes on non-BigInt arguments.
assertUnoptimized(f);
// The next time the function is optimized, speculation should be disabled
// so the builtin call is kept, which won't deoptimize again.
%PrepareFunctionForOptimization(f);
assertEquals(7n, f(7n));
assertEquals(1n, f(9n));
%OptimizeFunctionOnNextCall(f);
}
assertEquals(7n, f(7n));
assertOptimized(f);
// Re-optimized still throws but does not deopt-loop.
assertThrows(() => f(2), TypeError);
assertOptimized(f);

View File

@ -0,0 +1,36 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
function TestBitwiseAnd(a, b) {
return a & b;
}
function OptimizeAndTest(fn) {
%PrepareFunctionForOptimization(fn);
assertEquals(0b1000n, fn(0b1100n, 0b1010n));
assertEquals(-0b1000n, fn(-0b100n, -0b110n));
assertEquals(0b1000n, fn(-0b100n, 0b1010n));
assertEquals(0b1000n, fn(0b1100n, -0b110n));
// The result grows out of one digit
assertEquals(-(2n ** 64n), fn(-(2n ** 63n + 1n), -(2n ** 63n)));
%OptimizeFunctionOnNextCall(fn);
fn(0b1100n, 0b1010n);
assertOptimized(fn);
assertEquals(0b1000n, fn(0b1100n, 0b1010n));
assertEquals(-0b1000n, fn(-0b100n, -0b110n));
assertEquals(0b1000n, fn(-0b100n, 0b1010n));
assertEquals(0b1000n, fn(0b1100n, -0b110n));
// The result grows out of one digit
assertEquals(-(2n ** 64n), fn(-(2n ** 63n + 1n), -(2n ** 63n)));
assertOptimized(fn);
assertEquals(0b1000, fn(0b1100, 0b1010));
assertUnoptimized(fn);
}
OptimizeAndTest(TestBitwiseAnd);

View File

@ -0,0 +1,31 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTest() {
function fn(a, b) {
return a | b;
}
%PrepareFunctionForOptimization(fn);
assertEquals(0b1110n, fn(0b1100n, 0b1010n));
assertEquals(-0b0010n, fn(-0b100n, -0b110n));
assertEquals(-0b0010n, fn(-0b100n, 0b1010n));
assertEquals(-0b0010n, fn(0b1100n, -0b110n));
assertEquals(-(2n ** 64n) + 1n, fn(-(2n ** 64n) + 1n, -(2n ** 64n)));
%OptimizeFunctionOnNextCall(fn);
fn(0b1100n, 0b1010n);
assertOptimized(fn);
assertEquals(0b1110n, fn(0b1100n, 0b1010n));
assertEquals(-0b0010n, fn(-0b100n, -0b110n));
assertEquals(-0b0010n, fn(-0b100n, 0b1010n));
assertEquals(-0b0010n, fn(0b1100n, -0b110n));
assertEquals(-(2n ** 64n) + 1n, fn(-(2n ** 64n) + 1n, -(2n ** 64n)));
assertOptimized(fn);
assertEquals(0b1110, fn(0b1100, 0b1010));
assertUnoptimized(fn);
})();

View File

@ -0,0 +1,31 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTest() {
function fn(a, b) {
return a ^ b;
}
%PrepareFunctionForOptimization(fn);
assertEquals(0b0110n, fn(0b1100n, 0b1010n));
assertEquals(0b0110n, fn(-0b100n, -0b110n));
assertEquals(-0b1010n, fn(-0b100n, 0b1010n));
assertEquals(-0b1010n, fn(0b1100n, -0b110n));
assertEquals(1n, fn(-(2n ** 64n) + 1n, -(2n ** 64n)));
%OptimizeFunctionOnNextCall(fn);
fn(0b1100n, 0b1010n);
assertOptimized(fn);
assertEquals(0b0110n, fn(0b1100n, 0b1010n));
assertEquals(0b0110n, fn(-0b100n, -0b110n));
assertEquals(-0b1010n, fn(-0b100n, 0b1010n));
assertEquals(-0b1010n, fn(0b1100n, -0b110n));
assertEquals(1n, fn(-(2n ** 64n) + 1n, -(2n ** 64n)));
assertOptimized(fn);
assertEquals(0b0110, fn(0b1100, 0b1010));
assertUnoptimized(fn);
})();

View File

@ -0,0 +1,61 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
function LessThan(x, y) {
return x < y;
}
function LessThanOrEqual(x, y) {
return x <= y;
}
function GreaterThan(x, y) {
return x > y;
}
function GreaterThanOrEqual(x, y) {
return x >= y;
}
function Test(f, large, lt, eq) {
assertEquals(lt, f(1n, 2n));
assertEquals(!lt, f(0n, -1n));
assertEquals(eq, f(-42n, -42n));
assertEquals(!lt, f(-(2n ** 62n), -(2n ** 63n) + 1n));
assertEquals(lt, f(-(2n ** 63n) + 1n, (2n ** 63n) - 1n));
if (large) {
assertEquals(lt, f(2n ** 63n - 1n, 2n ** 63n));
assertEquals(!lt, f(-(2n ** 63n) + 1n, -(2n ** 63n)));
assertEquals(lt, f(-(13n ** 70n), 13n ** 70n)); // Different signs
assertEquals(!lt, f(13n ** 70n, -(13n ** 70n)));
assertEquals(lt, f(13n ** 80n, 13n ** 90n)); // Different lengths
assertEquals(!lt, f(-(13n ** 70n), -(13n ** 80n))); // Same length
assertEquals(eq, f(13n ** 70n, 13n ** 70n));
}
}
function OptAndTest(f, large) {
const lt = f === LessThan || f === LessThanOrEqual;
const eq = f === LessThanOrEqual || f === GreaterThanOrEqual;
%PrepareFunctionForOptimization(f);
Test(f, large, lt, eq);
assertUnoptimized(f);
%OptimizeFunctionOnNextCall(f);
Test(f, large, lt, eq);
assertOptimized(f);
}
OptAndTest(LessThan, false);
OptAndTest(LessThanOrEqual, false);
OptAndTest(GreaterThan, false);
OptAndTest(GreaterThanOrEqual, false);
if (%Is64Bit()) {
// Should deopt on large bigints and there should not be deopt loops.
OptAndTest(LessThan, true);
OptAndTest(LessThanOrEqual, true);
OptAndTest(GreaterThan, true);
OptAndTest(GreaterThanOrEqual, true);
}

View File

@ -0,0 +1,107 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function () {
function ToBigInt(x) {
return BigInt(x);
}
%PrepareFunctionForOptimization(ToBigInt);
assertEquals(0n, ToBigInt(0));
%OptimizeFunctionOnNextCall(ToBigInt);
// Test the builtin ToBigIntConvertNumber.
assertThrows(() => ToBigInt(undefined), TypeError);
assertEquals(0n, ToBigInt(false));
assertEquals(1n, ToBigInt(true));
assertEquals(42n, ToBigInt(42n));
assertEquals(3n, ToBigInt(3));
assertEquals(0xdeadbeefn, ToBigInt(0xdeadbeef));
assertEquals(-0xdeadbeefn, ToBigInt(-0xdeadbeef));
assertEquals(2n, ToBigInt("2"));
assertEquals(0xdeadbeefdeadbeefdn, ToBigInt("0xdeadbeefdeadbeefd"));
assertThrows(() => ToBigInt("-0x10"), SyntaxError);
assertThrows(() => ToBigInt(Symbol("foo")), TypeError);
assertOptimized(ToBigInt);
})();
{
// Test constants to BigInts.
function OptimizeAndTest(expected, fun) {
%PrepareFunctionForOptimization(fun);
assertEquals(expected, fun());
%OptimizeFunctionOnNextCall(fun);
assertEquals(expected, fun());
assertOptimized(fun);
}
OptimizeAndTest(42n, () => BigInt(42n));
// MinusZero
OptimizeAndTest(0n, () => BigInt(-0));
OptimizeAndTest(0n, () => BigInt.asIntN(32, BigInt(-0)));
OptimizeAndTest(0n, () => BigInt.asUintN(32, BigInt(-0)));
OptimizeAndTest(0n, () => 0n + BigInt(-0));
// Smi
OptimizeAndTest(42n, () => BigInt(42));
OptimizeAndTest(42n, () => BigInt.asIntN(32, BigInt(42)));
OptimizeAndTest(42n, () => BigInt.asUintN(32, BigInt(42)));
OptimizeAndTest(42n, () => 0n + BigInt(42));
// Signed32
OptimizeAndTest(-0x80000000n, () => BigInt(-0x80000000));
OptimizeAndTest(-0x80000000n, () => BigInt.asIntN(32, BigInt(-0x80000000)));
OptimizeAndTest(0x80000000n, () => BigInt.asUintN(32, BigInt(-0x80000000)));
OptimizeAndTest(-0x80000000n, () => 0n + BigInt(-0x80000000));
// Unsigned32
OptimizeAndTest(0x80000000n, () => BigInt(0x80000000));
OptimizeAndTest(-0x80000000n, () => BigInt.asIntN(32, BigInt(0x80000000)));
OptimizeAndTest(0x80000000n, () => BigInt.asUintN(32, BigInt(0x80000000)));
OptimizeAndTest(0x80000000n, () => 0n + BigInt(0x80000000));
}
(function () {
function SmiToBigInt(arr) {
return BigInt(arr[0]);
}
// Element kind: PACKED_SMI_ELEMENTS
const numbers = [0x3fffffff, 0, -0x40000000];
%PrepareFunctionForOptimization(SmiToBigInt);
assertEquals(0x3fffffffn, SmiToBigInt(numbers));
%OptimizeFunctionOnNextCall(SmiToBigInt);
assertEquals(0x3fffffffn, SmiToBigInt(numbers));
assertOptimized(SmiToBigInt);
// Change the map of {numbers}.
numbers[1] = 0x80000000;
assertEquals(0x3fffffffn, SmiToBigInt(numbers));
assertUnoptimized(SmiToBigInt);
})();
(function () {
function ToBigInt() {
return BigInt(123);
}
%PrepareFunctionForOptimization(ToBigInt);
assertEquals(123n, ToBigInt());
%OptimizeFunctionOnNextCall(ToBigInt);
assertEquals(123n, ToBigInt());
assertOptimized(ToBigInt);
// Replace the global BigInt object.
BigInt = () => 42;
assertUnoptimized(ToBigInt);
assertEquals(42, ToBigInt());
})();

View File

@ -0,0 +1,46 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
function OptimizeAndTest() {
function fn(a, b) {
return a / b;
}
%PrepareFunctionForOptimization(fn);
assertEquals(0n, fn(3n, 4n));
assertEquals(3n, fn(3n, 1n));
assertEquals(4n, fn(30n, 7n));
%OptimizeFunctionOnNextCall(fn);
assertEquals(0n, fn(3n, 4n));
assertEquals(3n, fn(3n, 1n));
assertEquals(4n, fn(30n, 7n));
assertOptimized(fn);
assertEquals(5, fn(30, 6));
assertUnoptimized(fn);
}
function OptimizeAndTestDivZero() {
function fn(a, b) {
return a / b;
}
%PrepareFunctionForOptimization(fn);
assertEquals(0n, fn(3n, 4n));
assertEquals(4n, fn(30n, 7n));
%OptimizeFunctionOnNextCall(fn);
assertEquals(4n, fn(30n, 7n));
assertOptimized(fn);
assertThrows(() => fn(3n, 0n), RangeError);
assertUnoptimized(fn);
}
OptimizeAndTest();
OptimizeAndTestDivZero();

View File

@ -0,0 +1,44 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
const bi = 42n;
function Equal(x, y) {
return x == y;
}
function StrictEqual(x, y) {
return x === y;
}
function Test(f, large) {
assertEquals(false, f(1n, 2n));
assertEquals(false, f(1n, -1n));
assertEquals(true, f(-1n, -1n));
assertEquals(true, f(bi, bi));
assertEquals(false, f(2n ** 63n - 1n, -(2n ** 63n) + 1n));
if (large) {
assertEquals(false, f(2n ** 63n, -(2n ** 63n)));
assertEquals(true, f(13n ** 70n, 13n ** 70n));
}
}
function OptAndTest(f, large) {
%PrepareFunctionForOptimization(f);
Test(f, large);
assertUnoptimized(f);
%OptimizeFunctionOnNextCall(f);
Test(f, large);
assertOptimized(f);
}
OptAndTest(Equal, false);
OptAndTest(StrictEqual, false);
if (%Is64Bit()) {
// Should deopt on large bigints and there should not be deopt loops.
OptAndTest(Equal, true);
OptAndTest(StrictEqual, true);
}

View File

@ -0,0 +1,88 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
function TestAsIntN() {
assertEquals(0n, BigInt.asIntN(64, 0n));
assertEquals(0n, BigInt.asIntN(8, 0n));
assertEquals(0n, BigInt.asIntN(1, 0n));
assertEquals(0n, BigInt.asIntN(0, 0n));
assertEquals(0n, BigInt.asIntN(100, 0n));
assertEquals(123n, BigInt.asIntN(64, 123n));
assertEquals(123n, BigInt.asIntN(32, 123n));
assertEquals(123n, BigInt.asIntN(8, 123n));
assertEquals(-5n, BigInt.asIntN(6, 123n));
assertEquals(-5n, BigInt.asIntN(5, 123n));
assertEquals(-5n, BigInt.asIntN(4, 123n));
assertEquals(-1n, BigInt.asIntN(1, 123n));
assertEquals(0n, BigInt.asIntN(0, 123n));
assertEquals(123n, BigInt.asIntN(72, 123n));
assertEquals(-123n, BigInt.asIntN(64, -123n));
assertEquals(-123n, BigInt.asIntN(32, -123n));
assertEquals(-123n, BigInt.asIntN(8, -123n));
assertEquals(5n, BigInt.asIntN(6, -123n));
assertEquals(5n, BigInt.asIntN(5, -123n));
assertEquals(5n, BigInt.asIntN(4, -123n));
assertEquals(-1n, BigInt.asIntN(1, -123n));
assertEquals(0n, BigInt.asIntN(0, -123n));
assertEquals(-123n, BigInt.asIntN(72, -123n));
}
function TestInt64LoweredOperations() {
assertEquals(0n, BigInt.asIntN(64, -0n));
assertEquals(0n, BigInt.asIntN(64, 15n + -15n));
assertEquals(0n, BigInt.asIntN(64, 0n + 0n));
assertEquals(14n, BigInt.asIntN(32, 8n + 6n));
assertEquals(-211n, BigInt.asIntN(10, 1013n + -200n));
assertEquals(-1n, BigInt.asIntN(4, -319n + 302n));
assertEquals(32n, BigInt.asIntN(64, (2n ** 100n + 64n) - 32n));
assertEquals(-32n, BigInt.asIntN(64, 32n - (2n ** 100n + 64n)));
assertEquals(-5n, BigInt.asIntN(4, 800n - 789n));
assertEquals(5n, BigInt.asIntN(4, 789n - 800n));
for (let i = 0; i < 2; ++i) {
let x = 32n; // x = 32n
if (i === 1) {
x = BigInt.asIntN(64, x + 3n); // x = 35n
const y = x + -8n + x; // x = 35n, y = 62n
x = BigInt.asIntN(6, y + x); // x = -31n, y = 62n
x = -9n + y - x; // x = 84n
x = BigInt.asIntN(10000 * i, x); // x = 84n
} else {
x = x + 400n; // x = 432n
x = 176n + BigInt.asIntN(8, 500n) + x; // x = 596n
}
assertEquals(84n, BigInt.asIntN(8, x));
}
let x = 7n;
for (let i = 0; i < 10; ++i) {
x = x + 5n;
}
assertEquals(-7n, BigInt.asIntN(6, x));
let y = 7n;
for(let i = 0; i < 10; ++i) {
y = BigInt.asIntN(4, y + 16n);
}
assertEquals(7n, y);
}
function OptimizeAndTest(fn) {
%PrepareFunctionForOptimization(fn);
%PrepareFunctionForOptimization(assertEquals);
%PrepareFunctionForOptimization(deepEquals);
fn();
fn();
%OptimizeFunctionOnNextCall(fn);
fn();
assertOptimized(fn);
fn();
}
OptimizeAndTest(TestAsIntN);
OptimizeAndTest(TestInt64LoweredOperations);

View File

@ -0,0 +1,44 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTest() {
function fn(a, b) {
return a % b;
}
%PrepareFunctionForOptimization(fn);
assertEquals(3n, fn(3n, 4n));
assertEquals(0n, fn(3n, 1n));
assertEquals(2n, fn(2n ** 64n, 7n));
%OptimizeFunctionOnNextCall(fn);
assertEquals(3n, fn(3n, 4n));
assertEquals(0n, fn(3n, 1n));
assertEquals(-5n, fn(-32n, 9n));
assertEquals(2n, fn(2n ** 64n, 7n));
assertOptimized(fn);
assertEquals(4, fn(32, 7));
assertUnoptimized(fn);
})();
(function OptimizeAndTestDivZero() {
function fn(a, b) {
return a % b;
}
%PrepareFunctionForOptimization(fn);
assertEquals(3n, fn(3n, 4n));
assertEquals(2n, fn(2n ** 64n, 7n));
%OptimizeFunctionOnNextCall(fn);
assertEquals(2n, fn(2n ** 64n, 7n));
assertOptimized(fn);
assertThrows(() => fn(3n, 0n), RangeError);
assertUnoptimized(fn);
})();

View File

@ -0,0 +1,26 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
function TestMultiplyAndTruncate(a, b) {
return BigInt.asIntN(3, a * b);
}
function OptimizeAndTest(fn) {
let bi = 2n ** (2n ** 29n);
if (%Is64Bit()) {
%PrepareFunctionForOptimization(fn);
assertEquals(-4n, fn(3n, 4n));
assertEquals(-2n, fn(5n, 6n));
%OptimizeFunctionOnNextCall(fn);
// After optimization, operands are truncated to Word64
// before being multiplied. No exceptions should be thrown
// and the correct result is expected.
assertEquals(-4n, fn(bi + 3n, bi + 4n));
assertOptimized(fn);
}
}
OptimizeAndTest(TestMultiplyAndTruncate);

View File

@ -0,0 +1,22 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
function TestMultiply(a, b) {
return a * b;
}
function OptimizeAndTest(fn) {
%PrepareFunctionForOptimization(fn);
assertEquals(12n, fn(3n, 4n));
assertEquals(30n, fn(5n, 6n));
%OptimizeFunctionOnNextCall(fn);
assertEquals(56n, fn(7n, 8n));
assertOptimized(fn);
assertEquals(56, fn(7, 8));
assertUnoptimized(fn);
}
OptimizeAndTest(TestMultiply);

View File

@ -0,0 +1,26 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
function TestNegate() {
assertEquals(0n, -0n);
const x = 15n;
assertEquals(-15n, -x);
assertEquals(15n, - -x);
assertEquals(30n, -(-x + -x));
}
function OptimizeAndTest(fn) {
%PrepareFunctionForOptimization(fn);
fn();
fn();
%OptimizeFunctionOnNextCall(fn);
fn();
assertOptimized(fn);
fn();
}
OptimizeAndTest(TestNegate);

View File

@ -0,0 +1,156 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTestAsUintN() {
function f(x) {
// Will be lowered to Int64Constant(-1) and stored as an immediate.
let y = BigInt.asUintN(64, -1n);
try {
return x + y;
} catch(_) {
return y;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(2n ** 64n, f(1n));
assertEquals(2n ** 64n + 1n, f(2n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n ** 64n, f(1n));
assertOptimized(f);
// Should be rematerialized to 2n ** 64n - 1n in code generation.
assertEquals(2n ** 64n - 1n, f(0));
if (%Is64Bit()) {
assertUnoptimized(f);
}
})();
(function OptimizeAndTestAsUintN() {
function f(x) {
// Will be lowered to Int64Sub because exponentiation is not truncated and
// stored in a register.
let y = BigInt.asUintN(64, -(2n ** 0n));
try {
return x + y;
} catch(_) {
return y;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(2n ** 64n, f(1n));
assertEquals(2n ** 64n + 1n, f(2n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n ** 64n, f(1n));
assertOptimized(f);
// Should be rematerialized to 2n ** 64n - 1n in deoptimization.
assertEquals(2n ** 64n - 1n, f(0));
if (%Is64Bit()) {
assertUnoptimized(f);
}
})();
(function OptimizeAndTestAsUintN() {
function f(x) {
// Will be lowered to Int64Sub because exponentiation is not truncated and
// stored in a stack slot.
let y = BigInt.asUintN(64, -(2n ** 0n));
try {
// The recursion is used to make sure `y` is stored on the stack.
return (x < 3n) ? (x + y) : f(x - 1n);
} catch(_) {
return y;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(2n ** 64n, f(1n));
assertEquals(2n ** 64n + 1n, f(2n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n ** 64n, f(1n));
assertOptimized(f);
// Should be rematerialized to 2n ** 64n - 1n in deoptimization.
assertEquals(2n ** 64n - 1n, f(0));
if (%Is64Bit()) {
assertUnoptimized(f);
}
})();
(function OptimizeAndTestAsIntN() {
function f(x) {
// Will be lowered to Int64Constant(-1) and stored as an immediate.
let y = BigInt.asIntN(64, -1n);
try {
return x + y;
} catch (_) {
return y;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(1n));
assertEquals(1n, f(2n));
%OptimizeFunctionOnNextCall(f);
assertEquals(0n, f(1n));
assertOptimized(f);
// Should be rematerialized to -1n in code generation.
assertEquals(-1n, f(0));
if (%Is64Bit()) {
assertUnoptimized(f);
}
})();
(function OptimizeAndTestAsIntN() {
function f(x) {
// Will be lowered to Int64Sub because exponentiation is not truncated and
// stored in a register.
let y = BigInt.asIntN(64, -(2n ** 0n));
try {
return x + y;
} catch(_) {
return y;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(1n));
assertEquals(1n, f(2n));
%OptimizeFunctionOnNextCall(f);
assertEquals(0n, f(1n));
assertOptimized(f);
// Should be rematerialized to -1n in deoptimization.
assertEquals(-1n, f(0));
if (%Is64Bit()) {
assertUnoptimized(f);
}
})();
(function OptimizeAndTestAsIntN() {
function f(x) {
// Will be lowered to Int64Sub because exponentiation is not truncated and
// stored in a stack slot.
let y = BigInt.asIntN(64, -(2n ** 0n));
try {
// The recursion is used to make sure `y` is stored on the stack.
return (x < 3n) ? (x + y) : f(x - 1n);
} catch(_) {
return y;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(1n));
assertEquals(1n, f(2n));
%OptimizeFunctionOnNextCall(f);
assertEquals(0n, f(1n));
assertOptimized(f);
// Should be rematerialized to -1n in deoptimization.
assertEquals(-1n, f(0));
if (%Is64Bit()) {
assertUnoptimized(f);
}
})();

View File

@ -0,0 +1,110 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTest() {
function ShiftLeft(a, b) {
return a << b;
}
%PrepareFunctionForOptimization(ShiftLeft);
assertEquals(0n, ShiftLeft(0n, 42n));
assertEquals(-42n, ShiftLeft(-42n, 0n));
assertEquals(2n ** 42n, ShiftLeft(1n, 42n));
assertEquals(-2n, ShiftLeft(-(2n ** 512n), -511n));
assertEquals(-1n, ShiftLeft(-(2n ** 512n), -513n));
%OptimizeFunctionOnNextCall(ShiftLeft);
assertEquals(0n, ShiftLeft(0n, 42n));
assertEquals(-42n, ShiftLeft(-42n, 0n));
assertEquals(2n ** 42n, ShiftLeft(1n, 42n));
assertEquals(-2n, ShiftLeft(-(2n ** 512n), -511n));
assertEquals(-1n, ShiftLeft(-(2n ** 512n), -513n));
assertOptimized(ShiftLeft);
assertThrows(() => ShiftLeft(1n, 2n ** 30n), RangeError);
assertUnoptimized(ShiftLeft);
})();
(function OptimizeAndTest() {
function ShiftLeftByPositive(a) {
return BigInt.asIntN(62, a << 42n);
}
%PrepareFunctionForOptimization(ShiftLeftByPositive);
assertEquals(0n, ShiftLeftByPositive(0n));
%OptimizeFunctionOnNextCall(ShiftLeftByPositive);
assertEquals(0n, ShiftLeftByPositive(0n));
assertEquals(2n ** 42n, ShiftLeftByPositive(1n));
assertEquals(2n ** 42n, ShiftLeftByPositive(1n + 2n ** 62n));
assertEquals(-(2n ** 42n), ShiftLeftByPositive(-1n - 2n ** 64n));
assertOptimized(ShiftLeftByPositive);
assertThrows(() => ShiftLeftByPositive(0), TypeError);
assertUnoptimized(ShiftLeftByPositive);
})();
(function OptimizeAndTest() {
const minus42 = -42n;
function ShiftLeftByNegative(a) {
return BigInt.asIntN(62, BigInt.asUintN(64, a) << minus42);
}
%PrepareFunctionForOptimization(ShiftLeftByNegative);
assertEquals(0n, ShiftLeftByNegative(0n));
%OptimizeFunctionOnNextCall(ShiftLeftByNegative);
assertEquals(0n, ShiftLeftByNegative(42n));
assertEquals(4194303n, ShiftLeftByNegative(-42n));
assertEquals(2n ** 20n, ShiftLeftByNegative(1n + 2n ** 62n));
assertEquals(3145727n, ShiftLeftByNegative(-1n - 2n ** 62n - 2n ** 64n));
assertOptimized(ShiftLeftByNegative);
assertThrows(() => ShiftLeftByNegative(0), TypeError);
if (%Is64Bit()) {
// BigInt truncation is not inlined on 32-bit platforms so there is no
// checks for BigInt, thus deopt will not be triggered.
assertUnoptimized(ShiftLeftByNegative);
}
})();
(function OptimizeAndTest() {
function ShiftLeftBy64(a) {
return BigInt.asIntN(62, a << 64n);
}
%PrepareFunctionForOptimization(ShiftLeftBy64);
assertEquals(0n, ShiftLeftBy64(0n));
%OptimizeFunctionOnNextCall(ShiftLeftBy64);
assertEquals(0n, ShiftLeftBy64(0n));
assertEquals(0n, ShiftLeftBy64(1n));
assertEquals(0n, ShiftLeftBy64(1n + 2n ** 62n));
assertEquals(0n, ShiftLeftBy64(-1n - 2n ** 64n));
assertOptimized(ShiftLeftBy64);
assertThrows(() => ShiftLeftBy64(0), TypeError);
assertUnoptimized(ShiftLeftBy64);
})();
(function OptimizeAndTest() {
const bi = 2n ** 62n;
function ShiftLeftByLarge(a) {
return BigInt.asIntN(62, a << bi);
}
%PrepareFunctionForOptimization(ShiftLeftByLarge);
assertEquals(0n, ShiftLeftByLarge(0n));
%OptimizeFunctionOnNextCall(ShiftLeftByLarge);
assertEquals(0n, ShiftLeftByLarge(0n));
if (%Is64Bit()) {
// After optimization, a truncated left shift will not throw a
// BigIntTooBig exception just as truncated addition.
assertEquals(0n, ShiftLeftByLarge(1n));
assertEquals(0n, ShiftLeftByLarge(1n + 2n ** 62n));
assertEquals(0n, ShiftLeftByLarge(-1n - 2n ** 64n));
}
assertOptimized(ShiftLeftByLarge);
assertThrows(() => ShiftLeftByLarge(0), TypeError);
assertUnoptimized(ShiftLeftByLarge);
})();

View File

@ -0,0 +1,140 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTest() {
function ShiftRight(a, b) {
return a >> b;
}
%PrepareFunctionForOptimization(ShiftRight);
assertEquals(0n, ShiftRight(0n, 42n));
assertEquals(-42n, ShiftRight(-42n, 0n));
assertEquals(-3n, ShiftRight(-5n, 1n));
assertEquals(0n, ShiftRight(42n, 2n ** 64n));
assertEquals(-1n, ShiftRight(-42n, 64n));
assertEquals(-1n, ShiftRight(-42n, 2n ** 64n));
%OptimizeFunctionOnNextCall(ShiftRight);
assertEquals(0n, ShiftRight(0n, 42n));
assertEquals(-42n, ShiftRight(-42n, 0n));
assertEquals(-3n, ShiftRight(-5n, 1n));
assertEquals(0n, ShiftRight(42n, 2n ** 64n));
assertEquals(-1n, ShiftRight(-42n, 64n));
assertEquals(-1n, ShiftRight(-42n, 2n ** 64n));
assertOptimized(ShiftRight);
assertThrows(() => ShiftRight(1n, -(2n ** 30n)), RangeError);
assertUnoptimized(ShiftRight);
})();
(function OptimizeAndTest() {
function ShiftRightUnsignedByPositive(a) {
return BigInt.asIntN(62, BigInt.asUintN(64, a) >> 42n);
}
%PrepareFunctionForOptimization(ShiftRightUnsignedByPositive);
assertEquals(0n, ShiftRightUnsignedByPositive(0n));
%OptimizeFunctionOnNextCall(ShiftRightUnsignedByPositive);
assertEquals(0n, ShiftRightUnsignedByPositive(42n));
assertEquals(4194303n, ShiftRightUnsignedByPositive(-42n));
assertEquals(2n ** 20n, ShiftRightUnsignedByPositive(1n + 2n ** 62n));
assertEquals(3145727n,
ShiftRightUnsignedByPositive(-1n - 2n ** 62n - 2n ** 64n));
assertOptimized(ShiftRightUnsignedByPositive);
assertThrows(() => ShiftRightUnsignedByPositive(0), TypeError);
if (%Is64Bit()) {
// BigInt truncation is not inlined on 32-bit platforms so there is no
// checks for BigInt, thus deopt will not be triggered.
assertUnoptimized(ShiftRightUnsignedByPositive);
}
})();
(function OptimizeAndTest() {
function ShiftRightSignedByPositive(a) {
return BigInt.asIntN(62, BigInt.asIntN(64, a) >> 42n);
}
%PrepareFunctionForOptimization(ShiftRightSignedByPositive);
assertEquals(0n, ShiftRightSignedByPositive(0n));
%OptimizeFunctionOnNextCall(ShiftRightSignedByPositive);
assertEquals(0n, ShiftRightSignedByPositive(42n));
assertEquals(-1n, ShiftRightSignedByPositive(-42n));
assertEquals(2n ** 20n, ShiftRightSignedByPositive(1n + 2n ** 62n));
assertEquals(-(2n ** 20n),
ShiftRightSignedByPositive(-(2n ** 62n) - 2n ** 64n));
assertOptimized(ShiftRightSignedByPositive);
assertThrows(() => ShiftRightSignedByPositive(0), TypeError);
if (%Is64Bit()) {
// BigInt truncation is not inlined on 32-bit platforms so there is no
// checks for BigInt, thus deopt will not be triggered.
assertUnoptimized(ShiftRightSignedByPositive);
}
})();
(function OptimizeAndTest() {
const minus42 = -42n;
function ShiftRightByNegative(a) {
return BigInt.asIntN(62, a >> minus42);
}
%PrepareFunctionForOptimization(ShiftRightByNegative);
assertEquals(0n, ShiftRightByNegative(0n));
%OptimizeFunctionOnNextCall(ShiftRightByNegative);
assertEquals(0n, ShiftRightByNegative(0n));
assertEquals(2n ** 42n, ShiftRightByNegative(1n));
assertEquals(2n ** 42n, ShiftRightByNegative(1n + 2n ** 62n));
assertEquals(-(2n ** 42n), ShiftRightByNegative(-1n - 2n ** 64n));
assertOptimized(ShiftRightByNegative);
assertThrows(() => ShiftRightByNegative(0), TypeError);
assertUnoptimized(ShiftRightByNegative);
})();
(function OptimizeAndTest() {
function ShiftRightBy64(a) {
return BigInt.asIntN(62, BigInt.asUintN(64, a) >> 64n);
}
%PrepareFunctionForOptimization(ShiftRightBy64);
assertEquals(0n, ShiftRightBy64(0n));
%OptimizeFunctionOnNextCall(ShiftRightBy64);
assertEquals(0n, ShiftRightBy64(0n));
assertEquals(0n, ShiftRightBy64(1n));
assertEquals(0n, ShiftRightBy64(1n + 2n ** 62n));
assertEquals(0n, ShiftRightBy64(-1n - 2n ** 64n));
assertOptimized(ShiftRightBy64);
assertThrows(() => ShiftRightBy64(0), TypeError);
if (%Is64Bit()) {
// BigInt truncation is not inlined on 32-bit platforms so there is no
// checks for BigInt, thus deopt will not be triggered.
assertUnoptimized(ShiftRightBy64);
}
})();
(function OptimizeAndTest() {
const bi = 2n ** 64n;
function ShiftRightByLarge(a) {
return BigInt.asIntN(62, BigInt.asIntN(64, a) >> bi);
}
%PrepareFunctionForOptimization(ShiftRightByLarge);
assertEquals(0n, ShiftRightByLarge(0n));
%OptimizeFunctionOnNextCall(ShiftRightByLarge);
assertEquals(0n, ShiftRightByLarge(0n));
assertEquals(-1n, ShiftRightByLarge(-1n));
assertEquals(0n, ShiftRightByLarge(1n + 2n ** 62n));
assertEquals(-1n, ShiftRightByLarge(-1n - 2n ** 64n));
assertOptimized(ShiftRightByLarge);
assertThrows(() => ShiftRightByLarge(0), TypeError);
if (%Is64Bit()) {
// BigInt truncation is not inlined on 32-bit platforms so there is no
// checks for BigInt, thus deopt will not be triggered.
assertUnoptimized(ShiftRightByLarge);
}
})();

View File

@ -0,0 +1,88 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
function TestAsUintN() {
assertEquals(0n, BigInt.asUintN(64, 0n));
assertEquals(0n, BigInt.asUintN(8, 0n));
assertEquals(0n, BigInt.asUintN(1, 0n));
assertEquals(0n, BigInt.asUintN(0, 0n));
assertEquals(0n, BigInt.asUintN(100, 0n));
assertEquals(123n, BigInt.asUintN(64, 123n));
assertEquals(123n, BigInt.asUintN(32, 123n));
assertEquals(123n, BigInt.asUintN(8, 123n));
assertEquals(59n, BigInt.asUintN(6, 123n));
assertEquals(27n, BigInt.asUintN(5, 123n));
assertEquals(11n, BigInt.asUintN(4, 123n));
assertEquals(1n, BigInt.asUintN(1, 123n));
assertEquals(0n, BigInt.asUintN(0, 123n));
assertEquals(123n, BigInt.asUintN(72, 123n));
assertEquals(BigInt("0xFFFFFFFFFFFFFF85"), BigInt.asUintN(64, -123n));
assertEquals(BigInt("0xFFFFFF85"), BigInt.asUintN(32, -123n));
assertEquals(BigInt("0x85"), BigInt.asUintN(8, -123n));
assertEquals(5n, BigInt.asUintN(6, -123n));
assertEquals(5n, BigInt.asUintN(5, -123n));
assertEquals(5n, BigInt.asUintN(4, -123n));
assertEquals(1n, BigInt.asUintN(1, -123n));
assertEquals(0n, BigInt.asUintN(0, -123n));
assertEquals(BigInt("0xFFFFFFFFFFFFFFFF85"), BigInt.asUintN(72, -123n));
}
function TestUint64LoweredOperations() {
assertEquals(0n, BigInt.asUintN(64, -0n));
assertEquals(0n, BigInt.asUintN(64, 15n + -15n));
assertEquals(0n, BigInt.asUintN(64, 0n + 0n));
assertEquals(14n, BigInt.asUintN(32, 8n + 6n));
assertEquals(813n, BigInt.asUintN(10, 1013n + -200n));
assertEquals(15n, BigInt.asUintN(4, -319n + 302n));
assertEquals(32n, BigInt.asUintN(64, (2n ** 100n + 64n) - 32n));
assertEquals(2n ** 64n - 32n, BigInt.asUintN(64, 32n - (2n ** 100n + 64n)));
assertEquals(11n, BigInt.asUintN(4, 800n - 789n));
assertEquals(5n, BigInt.asUintN(4, 789n - 800n));
for (let i = 0; i < 2; ++i) {
let x = 32n; // x = 32n
if (i === 1) {
x = BigInt.asUintN(64, x + 3n); // x = 35n
const y = x + -8n + x; // x = 35n, y = 62n
x = BigInt.asUintN(6, y + x); // x = 33n, y = 62n
x = -9n + y - x; // x = 20n
x = BigInt.asUintN(10000 * i, x); // x = 20n
} else {
x = x + 400n; // x = 432n
x = -144n + BigInt.asUintN(8, 500n) + x; // x = 532n
}
assertEquals(20n, BigInt.asUintN(8, x));
}
let x = 7n;
for (let i = 0; i < 10; ++i) {
x = x + 5n;
}
assertEquals(57n, BigInt.asUintN(8, x));
let y = 7n;
for(let i = 0; i < 10; ++i) {
y = BigInt.asUintN(4, y + 16n);
}
assertEquals(7n, y);
}
function OptimizeAndTest(fn) {
%PrepareFunctionForOptimization(fn);
%PrepareFunctionForOptimization(assertEquals);
%PrepareFunctionForOptimization(deepEquals);
fn();
fn();
%OptimizeFunctionOnNextCall(fn);
fn();
assertOptimized(fn);
fn();
}
OptimizeAndTest(TestAsUintN);
OptimizeAndTest(TestUint64LoweredOperations);

View File

@ -0,0 +1,73 @@
// Copyright 2022 the V8 project 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 --turbofan
function WarmupAndOptimize(f) {
%PrepareFunctionForOptimization(f);
f(1n, 1n);
%OptimizeFunctionOnNextCall(f);
f(1n, 1n);
assertOptimized(f);
}
%NeverOptimizeFunction(WarmupAndOptimize);
function TestBinary(f) {
WarmupAndOptimize(f);
assertThrows(() => { f(1, 1n); }, TypeError);
// Recompile in case the above deopts.
WarmupAndOptimize(f);
assertThrows(() => { f(1n, 1); }, TypeError);
}
%NeverOptimizeFunction(TestBinary);
function Add(a, b) {
let [c] = [1n];
let temp = 0n;
temp = a + c;
temp = c + b;
temp = 42n;
result = temp;
}
TestBinary(Add);
function Subtract(a, b) {
let [c] = [1n];
let temp = 0n;
temp = a - c;
temp = c - b;
temp = 42n;
result = temp;
}
TestBinary(Subtract);
function Multiply(a, b) {
let [c] = [1n];
let temp = 0n;
temp = a * c;
temp = c * b;
temp = 42n;
result = temp;
}
TestBinary(Multiply);
function Divide(a, b) {
let [c] = [1n];
let temp = 0n;
temp = a / c;
temp = c / b;
temp = 42n;
result = temp;
}
TestBinary(Divide);
function BitwiseAnd(a, b) {
let [c] = [1n];
let temp = 0n;
temp = a & c;
temp = c & b;
temp = 42n;
result = temp;
}
TestBinary(BitwiseAnd);

View File

@ -0,0 +1,97 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTestNegativeLimit() {
function f(x, y) {
return x + y;
}
%PrepareFunctionForOptimization(f);
assertEquals(1n, f(0n, 1n));
assertEquals(5n, f(2n, 3n));
%OptimizeFunctionOnNextCall(f);
assertEquals(-(2n ** 63n), f(-(2n ** 63n), 0n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an umtimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckBigInt64 should trigger deopt on INT_MIN - 1.
assertEquals(-(2n ** 63n) - 1n, f(-(2n ** 63n) - 1n, 0n));
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(1n, f(0n, 1n));
assertEquals(5n, f(2n, 3n));
%OptimizeFunctionOnNextCall(f);
assertEquals(-(2n ** 63n), f(-(2n ** 63n), 0n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertEquals(-(2n ** 63n) - 1n, f(-(2n ** 63n) - 1n, 0n));
assertOptimized(f);
}
})();
(function OptimizeAndTestPositiveLimit() {
function f(x, y) {
return x + y;
}
%PrepareFunctionForOptimization(f);
assertEquals(1n, f(0n, 1n));
assertEquals(5n, f(2n, 3n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n ** 63n - 1n, f(2n ** 63n - 1n, 0n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an untimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckBigInt64 should trigger deopt on INT_MAX + 1.
assertEquals(2n ** 63n, f(2n ** 63n, 0n));
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(1n, f(0n, 1n));
assertEquals(5n, f(2n, 3n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n ** 63n - 1n, f(2n ** 63n - 1n, 0n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertEquals(2n ** 63n, f(2n ** 63n, 0n));
assertOptimized(f);
}
})();
(function OptimizeAndTestOverflow() {
function f(x, y) {
return x + y;
}
%PrepareFunctionForOptimization(f);
assertEquals(1n, f(0n, 1n));
assertEquals(5n, f(2n, 3n));
%OptimizeFunctionOnNextCall(f);
assertEquals(9n, f(4n, 5n));
assertOptimized(f);
assertEquals(-(2n ** 63n), f(-(2n ** 62n), -(2n ** 62n)));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an umtimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckedInt64Add will trigger deopt due to overflow.
assertEquals(-(2n ** 63n) - 1n, f(-(2n ** 62n + 1n), -(2n ** 62n)));
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(1n, f(0n, 1n));
assertEquals(5n, f(2n, 3n));
%OptimizeFunctionOnNextCall(f);
assertEquals(9n, f(4n, 5n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertEquals(-(2n ** 63n) - 1n, f(-(2n ** 62n + 1n), -(2n ** 62n)));
assertOptimized(f);
}
})();

View File

@ -0,0 +1,71 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
const bi = 18446744073709551615n; // 2n ** 64n - 1n
function storeAndLoad(x) {
let buffer = new ArrayBuffer(16);
let biArray = new BigInt64Array(buffer);
biArray[0] = bi;
biArray[1] = x;
return biArray[0] + biArray[1];
}
%PrepareFunctionForOptimization(storeAndLoad);
assertEquals(-1n, storeAndLoad(0n));
assertEquals(41n, storeAndLoad(2n ** 64n + 42n));
assertEquals(0n, storeAndLoad(-bi));
assertEquals(-2n, storeAndLoad(bi));
%OptimizeFunctionOnNextCall(storeAndLoad);
assertEquals(-1n, storeAndLoad(0n));
assertEquals(41n, storeAndLoad(2n ** 64n + 42n));
assertEquals(0n, storeAndLoad(-bi));
assertEquals(-2n, storeAndLoad(bi));
assertOptimized(storeAndLoad);
assertEquals(-1n, storeAndLoad(false));
if (%Is64Bit()) {
assertUnoptimized(storeAndLoad);
}
%PrepareFunctionForOptimization(storeAndLoad);
assertEquals(-1n, storeAndLoad(0n));
%OptimizeFunctionOnNextCall(storeAndLoad);
assertEquals(0n, storeAndLoad(true));
// TODO(panq): Uncomment the assertion once the deopt loop is eliminated.
// assertOptimized(storeAndLoad);
function storeAndLoadUnsigned(x) {
let buffer = new ArrayBuffer(16);
let biArray = new BigUint64Array(buffer);
biArray[0] = bi;
biArray[1] = x;
return biArray[0] + biArray[1];
}
%PrepareFunctionForOptimization(storeAndLoadUnsigned);
assertEquals(bi, storeAndLoadUnsigned(0n));
assertEquals(bi + 42n, storeAndLoadUnsigned(2n ** 64n + 42n));
assertEquals(bi + 1n, storeAndLoadUnsigned(-bi));
assertEquals(bi * 2n, storeAndLoadUnsigned(bi));
%OptimizeFunctionOnNextCall(storeAndLoadUnsigned);
assertEquals(bi, storeAndLoadUnsigned(0n));
assertEquals(bi + 42n, storeAndLoadUnsigned(2n ** 64n + 42n));
assertEquals(bi + 1n, storeAndLoadUnsigned(-bi));
assertEquals(bi * 2n, storeAndLoadUnsigned(bi));
assertOptimized(storeAndLoadUnsigned);
assertEquals(bi, storeAndLoadUnsigned(false));
if (%Is64Bit()) {
assertUnoptimized(storeAndLoadUnsigned);
}
%PrepareFunctionForOptimization(storeAndLoadUnsigned);
assertEquals(bi, storeAndLoadUnsigned(0n));
%OptimizeFunctionOnNextCall(storeAndLoadUnsigned);
assertEquals(bi + 1n, storeAndLoadUnsigned(true));
// TODO(panq): Uncomment the assertion once the deopt loop is eliminated.
// assertOptimized(storeAndLoadUnsigned);

View File

@ -0,0 +1,67 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTestDivZero() {
function f(x, y) {
return x / y;
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-3n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n, f(14n, 5n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an untimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckedInt64Div will trigger deopt due to divide-by-zero.
assertThrows(() => f(42n, 0n), RangeError);
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-3n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n, f(14n, 5n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertThrows(() => f(42n, 0n), RangeError);
assertOptimized(f);
}
})();
(function OptimizeAndTestOverflow() {
function f(x, y) {
return x / y;
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-3n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n, f(14n, 5n));
assertOptimized(f);
assertEquals(-(2n ** 63n), f(-(2n ** 63n), 1n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an umtimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckedInt64Div will trigger deopt due to overflow.
assertEquals(2n ** 63n, f(-(2n ** 63n), -1n));
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-3n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(2n, f(14n, 5n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertEquals(2n ** 63n, f(-(2n ** 63n), -1n));
assertOptimized(f);
}
})();

View File

@ -0,0 +1,65 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTestDivZero() {
function f(x, y) {
return x % y;
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-5n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(4n, f(14n, 5n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an untimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckedInt64Mod will trigger deopt due to divide-by-zero.
assertThrows(() => f(42n, 0n), RangeError);
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-5n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(4n, f(14n, 5n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertThrows(() => f(42n, 0n), RangeError);
assertOptimized(f);
}
})();
(function OptimizeAndTestOverflow() {
function f(x, y) {
return x % y;
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-5n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(4n, f(14n, 5n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an umtimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckedInt64Mod will trigger deopt due to overflow.
assertEquals(0n, f(-(2n ** 63n), -1n));
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(0n, f(0n, 1n));
assertEquals(-5n, f(-32n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(4n, f(14n, 5n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertEquals(0n, f(-(2n ** 63n), -1n));
assertOptimized(f);
}
})();

View File

@ -0,0 +1,37 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTestOverflow() {
function f(x, y) {
return x * y;
}
%PrepareFunctionForOptimization(f);
assertEquals(0n, f(0n, 1n));
assertEquals(18n, f(2n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(70n, f(14n, 5n));
assertOptimized(f);
assertEquals(-(2n ** 63n), f(-(2n ** 32n), 2n ** 31n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an untimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckedInt64Mul will trigger deopt due to overflow.
assertEquals(-(2n ** 63n) - 1n, f(-77158673929n, 119537721n));
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(0n, f(0n, 1n));
assertEquals(18n, f(2n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(70n, f(14n, 5n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertEquals(-(2n ** 63n) - 1n, f(-77158673929n, 119537721n));
assertOptimized(f);
}
})();

View File

@ -0,0 +1,37 @@
// Copyright 2022 the V8 project 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 --turbofan --no-always-turbofan
(function OptimizeAndTestOverflow() {
function f(x, y) {
return x - y;
}
%PrepareFunctionForOptimization(f);
assertEquals(-1n, f(0n, 1n));
assertEquals(-7n, f(2n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(9n, f(14n, 5n));
assertOptimized(f);
assertEquals(-(2n ** 63n), f(-(2n ** 62n), 2n ** 62n));
assertOptimized(f);
// Re-prepare the function before the first deopt to ensure type feedback is
// not cleared by an untimely gc.
%PrepareFunctionForOptimization(f);
assertOptimized(f);
// CheckedInt64Sub will trigger deopt due to overflow.
assertEquals(-(2n ** 63n) - 1n, f(-(2n ** 62n + 1n), 2n ** 62n));
if (%Is64Bit()) {
assertUnoptimized(f);
assertEquals(-1n, f(0n, 1n));
assertEquals(-7n, f(2n, 9n));
%OptimizeFunctionOnNextCall(f);
assertEquals(9n, f(14n, 5n));
assertOptimized(f);
// Ensure there is no deopt loop.
assertEquals(-(2n ** 63n) - 1n, f(-(2n ** 62n + 1n), 2n ** 62n));
assertOptimized(f);
}
})();

View File

@ -0,0 +1,55 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Values in distinct spans.
function or_test0(x, y) { return x | y; }
function and_test0(x, y) { return x & y; }
function add_test0(x, y) { return x + y; }
assertEquals(3, or_test0(1, 2)); // 1 | 2
assertEquals(2, and_test0(3, 6)); // 3 & 6
assertEquals(5, add_test0(2, 3)); // 2 + 3
// Values in the same span.
function or_test1(x, y) { return x | x; }
function and_test1(x, y) { return x & x; }
function add_test1(x, y) { return x + x; }
assertEquals(1, or_test1(1, 2)); // 1 | 1
assertEquals(3, and_test1(3, 6)); // 3 & 3
assertEquals(4, add_test1(2, 3)); // 2 + 2
// Values in distinct spans that alias.
function or_test2(x, y) { x = y; return x | y; }
function and_test2(x, y) { x = y; return x & y; }
function add_test2(x, y) { x = y; return x + y; }
assertEquals(2, or_test2(1, 2)); // 2 | 2
assertEquals(6, and_test2(3, 6)); // 6 & 6
assertEquals(6, add_test2(2, 3)); // 3 + 3

View File

@ -0,0 +1,47 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
function test1(s) {
return s.toString;
}
%PrepareFunctionForOptimization(test1);
assertSame(test1(false), Boolean.prototype.toString);
assertSame(test1(true), Boolean.prototype.toString);
%OptimizeFunctionOnNextCall(test1);
assertSame(test1(false), Boolean.prototype.toString);
assertSame(test1(true), Boolean.prototype.toString);
function test2(s) {
return s.valueOf;
}
%PrepareFunctionForOptimization(test2);
assertSame(test2(false), Boolean.prototype.valueOf);
assertSame(test2(true), Boolean.prototype.valueOf);
%OptimizeFunctionOnNextCall(test2);
assertSame(test2(false), Boolean.prototype.valueOf);
assertSame(test2(true), Boolean.prototype.valueOf);
Boolean.prototype.foo = 42;
function test3(s) {
return s["foo"];
}
%PrepareFunctionForOptimization(test3);
assertEquals(test3(false), 42);
assertEquals(test3(true), 42);
%OptimizeFunctionOnNextCall(test3);
assertEquals(test3(false), 42);
assertEquals(test3(true), 42);
Boolean.prototype.bar = function bar() { "use strict"; return this; }
function test4(s) {
return s.bar();
}
%PrepareFunctionForOptimization(test4);
assertEquals(test4(false), false);
assertEquals(test4(true), true);
%OptimizeFunctionOnNextCall(test4);
assertEquals(test4(false), false);
assertEquals(test4(true), true);

View File

@ -0,0 +1,31 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax --turbofan --noalways-turbofan
class C {};
const c = new C;
const getPrototypeOf = Object.getPrototypeOf;
function bar(f) {
return f();
}
function foo() {
return bar(getPrototypeOf.bind(undefined, c));
}
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
bar(function() {});
foo();
%OptimizeFunctionOnNextCall(foo);
foo();
assertOptimized(foo);
c.prop = 42;
// Assert that the call reducer optimized the call to Object.getPrototypeOf
// by asserting that foo gets deopted when c's previous map becomes
// unstable.
assertUnoptimized(foo);
foo();

View File

@ -0,0 +1,38 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
A = {}
A.i = [];
A.i.push(function () { });
A.i.push(function () { });
function f (event) {
for(var i = 0, j = A.i.length; i < j; ++i)
A.i[i]();
}
f(null);

View File

@ -0,0 +1,45 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-optimize-apply --turbofan
// These tests do not work well if this script is run more than once; after a
// few runs the whole function is immediately compiled and assertions would
// fail. We prevent re-runs.
// Flags: --no-always-turbofan
// These tests do not work well if we flush the feedback vector, which causes
// deoptimization.
// Flags: --no-stress-flush-code --no-flush-bytecode
// Tests for optimization of CallWithSpread and CallWithArrayLike.
// This test is in a separate file because it invalidates protectors.
// Test with holey array with default values.
(function () {
"use strict";
// Setting value to be retrieved in place of hole.
Array.prototype[2] = 'x';
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y) {
return sum_js.apply(null, ["", x, ,y]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('AxB', foo('A', 'B'));
assertTrue(sum_js_got_interpreted);
// The protector should be invalidated, which prevents inlining.
%OptimizeFunctionOnNextCall(foo);
assertEquals('AxB', foo('A', 'B'));
assertTrue(sum_js_got_interpreted);
assertOptimized(foo);
})();

View File

@ -0,0 +1,52 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-optimize-apply --turbofan
// Flags: --no-always-turbofan
// These tests do not work well if we flush the feedback vector, which causes
// deoptimization.
// Flags: --no-stress-flush-code --no-flush-bytecode
// The test relies on optimizing/deoptimizing at predictable moments, so
// it's not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0
// Tests for optimization of CallWithSpread and CallWithArrayLike.
// This test is in a separate file because it invalidates protectors.
// Test with array prototype modified after compilation.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y) {
return sum_js.apply(null, ["", x, ,y]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('AundefinedB', foo('A', 'B'));
assertTrue(sum_js_got_interpreted);
%OptimizeFunctionOnNextCall(foo);
assertEquals('AundefinedB', foo('A', 'B'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
// Modify the array prototype, define a default value for element [1].
Array.prototype[2] = 'x';
assertUnoptimized(foo);
// Now the call will not be inlined.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals('AxB', foo('A', 'B'));
assertTrue(sum_js_got_interpreted);
assertOptimized(foo);
})();

View File

@ -0,0 +1,67 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-optimize-apply --turbofan
// Flags: --no-always-turbofan
// These tests do not work well if we flush the feedback vector, which causes
// deoptimization.
// Flags: --no-stress-flush-code --no-flush-bytecode
// The test relies on optimizing/deoptimizing at predictable moments, so
// this is not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0 --interrupt-budget=1024
// Tests for optimization of CallWithSpread and CallWithArrayLike.
// Test deopt when array map changes.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c;
}
function foo(x, y, z, str) {
let v = [x, y, z];
if (str) {
v[0] = str;
}
return sum_js.apply(null, v);
}
%PrepareFunctionForOptimization(sum_js);
for (let i = 0; i < 5; i++) {
%PrepareFunctionForOptimization(foo);
assertEquals(78, foo(26, 6, 46, null));
assertTrue(sum_js_got_interpreted);
// Compile function foo; inlines 'sum_js' into 'foo'.
%OptimizeFunctionOnNextCall(foo);
assertEquals(78, foo(26, 6, 46, null));
assertOptimized(foo);
%PrepareFunctionForOptimization(foo);
if (i < 3) {
assertFalse(sum_js_got_interpreted);
} else {
// i: 3: Speculation mode prevents optimization of sum_js.apply() call.
assertTrue(sum_js_got_interpreted);
}
// This should deoptimize:
// i: 0: Deopt soft: insufficient type feedback for generic keyed access.
// i: 1,2: Deopt eager: wrong map.
// i: 3: Won't deopt anymore.
assertEquals("v8646", foo(26, 6, 46, "v8"));
assertTrue(sum_js_got_interpreted);
if (i < 3) {
assertUnoptimized(foo);
} else {
assertOptimized(foo);
%PrepareFunctionForOptimization(foo);
}
}
})();

View File

@ -0,0 +1,55 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-optimize-apply --turbofan
// Flags: --no-always-turbofan
// These tests do not work well if we flush the feedback vector, which causes
// deoptimization.
// Flags: --no-stress-flush-code --no-flush-bytecode
// Some of the tests rely on optimizing/deoptimizing at predictable moments, so
// this is not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0
// Test for optimization of CallWithSpread when the array iterator is replaced
// with a generator function.
//
// Note: this test must be in a separate file because the test invalidates a
// protector, which then remains invalidated.
(function () {
"use strict";
// This invalidates the DependOnArrayIteratorProtector.
Object.defineProperty(Array.prototype, Symbol.iterator, {
value: function* () {
yield 42;
},
});
var log_got_interpreted = true;
function log(a) {
assertEquals(1, arguments.length);
log_got_interpreted = %IsBeingInterpreted();
return a;
}
function foo() {
return log(...[1]);
}
%PrepareFunctionForOptimization(log);
%PrepareFunctionForOptimization(foo);
assertEquals(42, foo());
assertTrue(log_got_interpreted);
// Compile foo.
%OptimizeFunctionOnNextCall(log);
%OptimizeFunctionOnNextCall(foo);
assertEquals(42, foo());
// The call with spread should not have been inlined, because of the
// generator/iterator.
assertFalse(log_got_interpreted);
assertOptimized(foo);
})();

View File

@ -0,0 +1,55 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-optimize-apply --turbofan
// Flags: --no-always-turbofan
// These tests do not work well if we flush the feedback vector, which causes
// deoptimization.
// Flags: --no-stress-flush-code --no-flush-bytecode
// Some of the tests rely on optimizing/deoptimizing at predictable moments, so
// this is not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0
// Test for optimization of CallWithSpread when the array iterator is replaced
// with a generator function and the array in empty.
//
// Note: this test must be in a separate file because the test invalidates a
// protector, which then remains invalidated.
(function () {
"use strict";
// This invalidates the DependOnArrayIteratorProtector.
Object.defineProperty(Array.prototype, Symbol.iterator, {
value: function* () {
yield 42;
},
});
var log_got_interpreted = true;
function log(a) {
assertEquals(1, arguments.length);
log_got_interpreted = %IsBeingInterpreted();
return a;
}
function foo() {
return log(...[]);
}
%PrepareFunctionForOptimization(log);
%PrepareFunctionForOptimization(foo);
assertEquals(42, foo());
assertTrue(log_got_interpreted);
// Compile foo.
%OptimizeFunctionOnNextCall(log);
%OptimizeFunctionOnNextCall(foo);
assertEquals(42, foo());
// The call with spread should not have been inlined, because of the
// generator/iterator.
assertFalse(log_got_interpreted);
assertOptimized(foo);
})();

View File

@ -0,0 +1,69 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-optimize-apply --turbofan
// Flags: --no-always-turbofan
// These tests do not work well if we flush the feedback vector, which causes
// deoptimization.
// Flags: --no-stress-flush-code --no-flush-bytecode
// Some of the tests rely on optimizing/deoptimizing at predictable moments, so
// this is not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0
// Test for optimization of CallWithSpread when the array iterator is replaced
// with a generator function after a function is compiled.
//
// Note: this test must be in a separate file because the test invalidates a
// protector, which then remains invalidated.
(function () {
"use strict";
var log_got_interpreted = true;
%NeverOptimizeFunction(assertEquals);
function log(a) {
assertEquals(1, arguments.length);
log_got_interpreted = %IsBeingInterpreted();
return a;
}
function foo() {
return log(...[1]);
}
%PrepareFunctionForOptimization(log);
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertTrue(log_got_interpreted);
// Compile foo.
%OptimizeFunctionOnNextCall(log);
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
// The call with spread should have been inlined.
assertFalse(log_got_interpreted);
assertOptimized(foo);
%PrepareFunctionForOptimization(foo);
// This invalidates the DependOnArrayIteratorProtector and causes deopt.
Object.defineProperty(Array.prototype, Symbol.iterator, {
value: function* () {
yield 42;
},
});
// Now we expect the value yielded by the generator.
assertUnoptimized(foo);
assertEquals(42, foo());
assertFalse(log_got_interpreted);
// Recompile 'foo'.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(42, foo());
// The call with spread will not be inlined because we have redefined the
// array iterator.
assertFalse(log_got_interpreted);
assertOptimized(foo);
})();

View File

@ -0,0 +1,805 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-optimize-apply --turbofan
// Flags: --no-always-turbofan
// These tests do not work well if we flush the feedback vector, which causes
// deoptimization.
// Flags: --no-stress-flush-code --no-flush-bytecode
// Some of the tests rely on optimizing/deoptimizing at predictable moments, so
// this is not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0
// Tests for optimization of CallWithSpread and CallWithArrayLike.
// Test JSCallReducer::ReduceJSCallWithArrayLike.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y, z) {
return sum_js.apply(null, ["", x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abc', foo('a', 'b', 'c'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abc', foo('a', 'b', 'c'));
assertOptimized(foo);
assertFalse(sum_js_got_interpreted);
})();
// Test using receiver
(function () {
function bar() {
return this.gaga;
}
function foo(receiver) {
return bar.apply(receiver, [""]);
}
%PrepareFunctionForOptimization(bar);
%PrepareFunctionForOptimization(foo);
var receiver = { gaga: 42 };
assertEquals(42, foo(receiver));
%OptimizeFunctionOnNextCall(foo);
assertEquals(42, foo(receiver));
assertOptimized(foo);
})();
// Test with holey array.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y) {
return sum_js.apply(null, ["",x,,y]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('AundefinedB', foo('A', 'B'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('AundefinedB', foo('A', 'B'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test with holey-double array.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + (c ? c : .0) + d;
}
function foo(x, y) {
return sum_js.apply(null, [3.14, x, , y]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals(45.31, foo(16.11, 26.06));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
// We optimize in the next call and sum_js stays inlined.
assertEquals(45.31, foo(16.11, 26.06));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test deopt when array size changes.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y, z) {
let a = ["", x, y, z];
a.push('*');
return sum_js.apply(null, a);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
// Here array size changes.
assertEquals('abc', foo('a', 'b', 'c'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
// Here it should deoptimize.
assertEquals('abc', foo('a', 'b', 'c'));
assertUnoptimized(foo);
assertTrue(sum_js_got_interpreted);
// Now speculation mode prevents the optimization.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals('abc', foo('a', 'b', 'c'));
assertTrue(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test with FixedDoubleArray.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y, z) {
return sum_js.apply(null, [3.14, x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals(56.34, foo(11.03, 16.11, 26.06));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals(56.34, foo(11.03, 16.11, 26.06));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test with empty array.
(function () {
"use strict";
var got_interpreted = true;
function fortytwo() {
got_interpreted = %IsBeingInterpreted();
return 42;
}
function foo() {
return fortytwo.apply(null, []);
}
%PrepareFunctionForOptimization(fortytwo);
%PrepareFunctionForOptimization(foo);
assertEquals(42, foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(got_interpreted);
assertEquals(42, foo());
assertFalse(got_interpreted);
assertOptimized(foo);
})();
// Test with empty array that changes size.
(function () {
"use strict";
var got_interpreted = true;
function fortytwo() {
got_interpreted = %IsBeingInterpreted();
return 42 + arguments.length;
}
var len = 2;
function foo() {
let args = []
for (var i = 0; i < len; i++) { args.push(1); }
let result = fortytwo.apply(null, args);
return result;
}
%PrepareFunctionForOptimization(fortytwo);
%PrepareFunctionForOptimization(foo);
assertEquals(44, foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(got_interpreted);
assertEquals(44, foo());
assertTrue(got_interpreted);
assertOptimized(foo);
len = 0;
assertEquals(42, foo());
assertFalse(got_interpreted);
assertOptimized(foo);
})();
// Test with FixedDoubleArray and Math.min/max.
(function () {
"use strict";
function arrayMin(val) {
return Math.min.apply(Math, val);
}
function arrayMax(val) {
return Math.max.apply(Math, val);
}
%PrepareFunctionForOptimization(arrayMin);
%PrepareFunctionForOptimization(arrayMin);
assertEquals(11.03, arrayMin([11.03, 16.11, 26.06]));
%PrepareFunctionForOptimization(arrayMax);
%PrepareFunctionForOptimization(arrayMax);
assertEquals(26.06, arrayMax([11.03, 16.11, 26.06]));
%OptimizeFunctionOnNextCall(arrayMin);
%OptimizeFunctionOnNextCall(arrayMax);
assertEquals(11.03, arrayMin([11.03, 16.11, 26.06]));
assertEquals(26.06, arrayMax([11.03, 16.11, 26.06]));
assertOptimized(arrayMin);
assertOptimized(arrayMax);
})();
// Test with holey double array and Math.min/max.
(function () {
"use strict";
function arrayMin(val) {
return Math.min.apply(Math, val);
}
function arrayMax(val) {
return Math.max.apply(Math, val);
}
%PrepareFunctionForOptimization(arrayMin);
%PrepareFunctionForOptimization(arrayMin);
assertEquals(NaN, arrayMin([11.03, 16.11, , 26.06]));
%PrepareFunctionForOptimization(arrayMax);
%PrepareFunctionForOptimization(arrayMax);
assertEquals(NaN, arrayMax([11.03, 16.11, , 26.06]));
%OptimizeFunctionOnNextCall(arrayMin);
%OptimizeFunctionOnNextCall(arrayMax);
assertEquals(NaN, arrayMin([11.03, 16.11, , 26.06]));
assertEquals(NaN, arrayMax([11.03, 16.11, , 26.06]));
assertOptimized(arrayMin);
assertOptimized(arrayMax);
})();
// Test Reflect.apply().
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y ,z) {
return Reflect.apply(sum_js, null, ["", x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abc', foo('a', 'b', 'c'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abc', foo('a', 'b', 'c'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test Reflect.apply() with empty array.
(function () {
"use strict";
var got_interpreted = true;
function fortytwo() {
got_interpreted = %IsBeingInterpreted();
return 42;
}
function foo() {
return Reflect.apply(fortytwo, null, []);
}
%PrepareFunctionForOptimization(fortytwo);
%PrepareFunctionForOptimization(foo);
assertEquals(42, foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(got_interpreted);
assertEquals(42, foo());
assertFalse(got_interpreted);
assertOptimized(foo);
})();
// Test Reflect.apply() with empty array that changes size.
(function () {
"use strict";
var got_interpreted = true;
function fortytwo() {
got_interpreted = %IsBeingInterpreted();
return 42 + arguments.length;
}
var len = 2;
function foo() {
let args = []
for (var i = 0; i < len; i++) { args.push(1); }
let result = Reflect.apply(fortytwo, null, args);
return result;
}
%PrepareFunctionForOptimization(fortytwo);
%PrepareFunctionForOptimization(foo);
assertEquals(44, foo());
%OptimizeFunctionOnNextCall(foo);
assertTrue(got_interpreted);
assertEquals(44, foo());
assertTrue(got_interpreted);
assertOptimized(foo);
len = 0;
assertEquals(42, foo());
assertFalse(got_interpreted);
assertOptimized(foo);
})();
// Test JSCallReducer::ReduceJSCallWithSpread.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y, z) {
const numbers = ["", x, y, z];
return sum_js(...numbers);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abc', foo('a', 'b', 'c'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abc', foo('a', 'b', 'c'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test spread call with empty array.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c;
}
function foo(x, y, z) {
const args = [];
return sum_js(x, y, z, ...args);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abc', foo('a', 'b', 'c'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abc', foo('a', 'b', 'c'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test spread call with empty array that changes size.
(function () {
"use strict";
var max_got_interpreted = true;
function max() {
max_got_interpreted = %IsBeingInterpreted();
return Math.max(...arguments);
}
var len = 2;
function foo(x, y, z) {
let args = [];
for (var i = 0; i < len; i++) { args.push(4 + i); }
return max(x, y, z, ...args);
}
%PrepareFunctionForOptimization(max);
%PrepareFunctionForOptimization(foo);
assertEquals(5, foo(1, 2, 3));
%OptimizeFunctionOnNextCall(foo);
assertTrue(max_got_interpreted);
assertEquals(5, foo(1, 2, 3));
assertTrue(max_got_interpreted);
assertOptimized(foo);
len = 0;
assertEquals(3, foo(1, 2, 3));
assertFalse(max_got_interpreted);
assertOptimized(foo);
})();
// Test spread call with more args.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d, e, f, g) {
assertEquals(7, arguments.length);
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d + e + f + g;
}
function foo(x, y, z) {
const numbers = ["", z, y, x];
return sum_js(x, y, z, ...numbers);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abccba', foo('a', 'b', 'c'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abccba', foo('a', 'b', 'c'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test on speculative optimization of introduced JSCall (array_size != 0).
(function () {
"use strict";
var F = Math.max;
var len;
function foo(x, y, z) {
var args = [z];
for (var i = 0; i < len; i++) { args.push(0); }
return F(x, y, ...args);
}
function foo1(x, y, z) {
var args = [z];
for (var i = 0; i < len; i++) { args.push(0); }
return F(x, y, ...args);
}
// Optimize JSCallWithSpread and Math.max
len = 0;
%PrepareFunctionForOptimization(foo);
assertEquals(3, foo(1, 2, 3));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(1, 2, 3));
assertOptimized(foo);
// Deoptimize when input of Math.max is not number
foo('a', 'b', 3);
assertUnoptimized(foo);
// Optimize JSCallWithSpread and Math.max
len = 2;
%PrepareFunctionForOptimization(foo1);
assertEquals(3, foo1(1, 2, 3));
%OptimizeFunctionOnNextCall(foo1);
assertEquals(3, foo1(1, 2, 3));
//Deoptimize when array length changes
assertUnoptimized(foo1);
})();
// Test on speculative optimization of introduced JSCall (array_size == 0).
(function () {
"use strict";
var F = Math.max;
var len;
function foo(x, y, z) {
var args = [];
for (var i = 0; i < len; i++) { args.push(z); }
return F(x, y, ...args);
}
function foo1(x, y, z) {
var args = [];
for (var i = 0; i < len; i++) { args.push(z); }
return F(x, y, ...args);
}
// Optimize JSCallWithSpread and Math.max
len = 0;
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(1, 2, 3));
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(1, 2, 3));
assertOptimized(foo);
// Deoptimzie when input of Math.max is not number
foo('a', 'b', 3);
assertUnoptimized(foo);
// Optimize JSCallWithSpread and Math.max
len = 2;
%PrepareFunctionForOptimization(foo1);
assertEquals(3, foo1(1, 2, 3));
%OptimizeFunctionOnNextCall(foo1);
assertEquals(3, foo1(1, 2, 3));
assertOptimized(foo1);
// No Deoptimization when array length changes
foo(1, 2, 3);
assertUnoptimized(foo);
})();
// Test apply on JSCreateClosure.
(function () {
"use strict";
var sum_got_interpreted = true;
function foo_closure() {
return function(a, b, c, d) {
sum_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
}
const _foo_closure = foo_closure();
%PrepareFunctionForOptimization(_foo_closure);
function foo(x, y, z) {
return foo_closure().apply(null, ["", x, y, z]);
}
%PrepareFunctionForOptimization(foo_closure);
%PrepareFunctionForOptimization(foo);
assertEquals('abc', foo('a', 'b', 'c'));
%OptimizeFunctionOnNextCall(foo_closure);
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_got_interpreted);
assertEquals('abc', foo('a', 'b', 'c'));
assertFalse(sum_got_interpreted);
assertOptimized(foo);
})();
// Test apply with JSBoundFunction
(function () {
"use strict";
var sum_got_interpreted = true;
function sum_js(a, b, c, d, e) {
sum_got_interpreted = %IsBeingInterpreted();
return this.x + a + b + c + d + e;
}
const f = sum_js.bind({ x: 26 }, 11, 3);
function foo(a, b, c) {
return f.apply(null, [a, b, c]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals(166, foo(40, 42, 44));
assertTrue(sum_got_interpreted);
%OptimizeFunctionOnNextCall(foo);
assertEquals(166, foo(40, 42, 44));
assertFalse(sum_got_interpreted);
assertOptimized(foo);
})();
// Test apply with nested bindings
(function () {
"use strict";
var sum_got_interpreted = true;
function sum_js(a, b, c, d, e) {
sum_got_interpreted = %IsBeingInterpreted();
return this.x + a + b + c + d + e;
}
const f = sum_js.bind({ x: 26 }, 11).bind({ y: 4 }, 3);
function foo(x, y, z) {
return f.apply(null, [x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals(166, foo(40, 42, 44));
assertTrue(sum_got_interpreted);
%OptimizeFunctionOnNextCall(foo);
assertEquals(166, foo(40, 42, 44));
assertFalse(sum_got_interpreted);
assertOptimized(foo);
})();
// Test apply on bound function (JSCreateBoundFunction).
(function () {
"use strict";
var sum_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_got_interpreted = %IsBeingInterpreted();
return this.x + a + b + c + d;
}
function foo(x, y, z) {
return sum_js.bind({ x: 42 }).apply(null, ["", x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('42abc', foo('a', 'b', 'c'));
assertTrue(sum_got_interpreted);
%OptimizeFunctionOnNextCall(foo);
assertEquals('42abc', foo('a', 'b', 'c'));
assertFalse(sum_got_interpreted);
assertOptimized(foo);
})();
// Test apply on bound function (JSCreateBoundFunction) with args.
(function () {
"use strict";
var sum_got_interpreted = true;
function sum_js(a, b, c, d, e, f) {
sum_got_interpreted = %IsBeingInterpreted();
return this.x + a + b + c + d + e + f;
}
function foo(x, y, z) {
return sum_js.bind({ x: 3 }, 11, 31).apply(null, ["", x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('45abc', foo('a', 'b', 'c'));
assertTrue(sum_got_interpreted);
%OptimizeFunctionOnNextCall(foo);
assertEquals('45abc', foo('a', 'b', 'c'));
assertFalse(sum_got_interpreted);
assertOptimized(foo);
})();
// Test call with array-like under-application.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d + arguments.length;
}
function foo(x, y) {
return sum_js.apply(null, ["", x, y]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('ABundefined3', foo('A', 'B'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('ABundefined3', foo('A', 'B'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test call with array-like over-application.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d + arguments.length;
}
function foo(v, w, x, y, z) {
return sum_js.apply(null, ["", v, w, x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abc6', foo('a', 'b', 'c', 'd', 'e'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abc6', foo('a', 'b', 'c', 'd', 'e'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test call with spread under-application.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d + arguments.length;
}
function foo(x, y) {
const numbers = ["", x, y];
return sum_js(...numbers);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('ABundefined3', foo('A', 'B'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('ABundefined3', foo('A', 'B'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test call with spread over-application.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d + arguments.length;
}
function foo(v, w, x, y, z) {
const numbers = ["", v, w, x, y, z];
return sum_js(...numbers);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abc6', foo('a', 'b', 'c', 'd', 'e'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abc6', foo('a', 'b', 'c', 'd', 'e'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test calling function that has rest parameters.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, ...moreArgs) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + moreArgs[0] + moreArgs[1] + moreArgs[2] + moreArgs[3];
}
function foo(v, w, x, y, z) {
return sum_js.apply(null, ["", v, w, x, y, z]);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abcde', foo('a', 'b', 'c', 'd', 'e'));
%OptimizeFunctionOnNextCall(foo);
assertTrue(sum_js_got_interpreted);
assertEquals('abcde', foo('a', 'b', 'c', 'd', 'e'));
assertFalse(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test with 'arguments'.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c;
}
function foo() {
return sum_js.apply(null, arguments);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
assertEquals('abc', foo('a', 'b', 'c'));
assertTrue(sum_js_got_interpreted);
// The call is not inlined with CreateArguments.
%OptimizeFunctionOnNextCall(foo);
assertEquals('abc', foo('a', 'b', 'c'));
assertTrue(sum_js_got_interpreted);
assertOptimized(foo);
})();
// Test with inlined calls.
(function () {
"use strict";
var sum_js_got_interpreted = true;
function sum_js(a, b, c, d) {
sum_js_got_interpreted = %IsBeingInterpreted();
return a + b + c + d;
}
function foo(x, y, z) {
return sum_js.apply(null, ["", x, y, z]);
}
function bar(a, b, c) {
return foo(c, b, a);
}
%PrepareFunctionForOptimization(sum_js);
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
assertEquals('cba', bar('a', 'b', 'c'));
assertTrue(sum_js_got_interpreted);
// Optimization also works if the call is in an inlined function.
%OptimizeFunctionOnNextCall(bar);
assertEquals('cba', bar('a', 'b', 'c'));
assertFalse(sum_js_got_interpreted);
assertOptimized(bar);
})();

View File

@ -0,0 +1,17 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var foo = (function() {
var x = 42;
function bar(s) { return x + s; }
return (function (s) { return bar(s); })
})();
var baz = (function (s) { return foo(s) });
%PrepareFunctionForOptimization(baz);
%OptimizeFunctionOnNextCall(baz);
assertEquals(42 + 12, baz(12));

View File

@ -0,0 +1,67 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turboshaft-enable-debug-features
const obj = { a: 42 };
function boom() {
throw "boom";
}
// Ensure that we optimize the monomorphic case.
(function() {
function bar(x) {
try {
boom();
++i;
} catch(_) {
%TurbofanStaticAssert(x.a == 42);
return x.a;
}
}
function foo() {
return bar(obj);
}
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
foo();
foo();
%OptimizeFunctionOnNextCall(foo);
foo();
})();
// And the megamorphic case.
(function() {
function bar(x) {
try {
boom();
++i;
} catch(_) {
%TurbofanStaticAssert(x.a == 42);
return x.a;
}
}
function foo() {
return bar(obj);
}
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
bar({b: 42});
bar({c: 42});
bar({d: 42});
bar({e: 42});
bar({f: 42});
foo();
foo();
%OptimizeFunctionOnNextCall(foo);
foo();
})();

View File

@ -0,0 +1,40 @@
// Copyright 2024 the V8 project 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 --turbofan --no-always-turbofan
class Vector {
constructor(x) {
this.x = x;
}
}
function magnitude(v) {
return v.x;
}
const zero = new Vector(0); // Map1
const anotherOldObject = new Vector(0); // Map1
%PrepareFunctionForOptimization(magnitude);
magnitude(zero);
const nonzero = new Vector(0.6); // Map2
// Map1 is now deprecated but Map2 is not a migration target.
%OptimizeFunctionOnNextCall(magnitude);
magnitude(zero);
// The first call immediately deopts
assertUnoptimized(magnitude);
// But we learn and don't deopt any more.
%OptimizeFunctionOnNextCall(magnitude);
magnitude(zero);
assertOptimized(magnitude);
// Also passing other old objects won't deopt.
magnitude(anotherOldObject);
assertOptimized(magnitude);

View File

@ -0,0 +1,31 @@
// Copyright 2024 the V8 project 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 --turbofan --no-always-turbofan
class Vector {
constructor(x) {
this.x = x;
}
}
function magnitude(v) {
return v.x;
}
const zero = new Vector(0); // Map1
const anotherOldObject = new Vector(0); // Map1
%PrepareFunctionForOptimization(magnitude);
magnitude(zero);
const nonzero = new Vector(0.6); // Map2
// Map1 is now deprecated but Map2 is not a migration target.
%OptimizeFunctionOnNextCall(magnitude);
magnitude(nonzero);
// The first doesn't deopt if we pass a new object right away.
assertOptimized(magnitude);

View File

@ -0,0 +1,44 @@
// Copyright 2024 the V8 project 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 --turbofan --no-always-turbofan
class Vector {
constructor(x) {
this.x = x;
}
}
function magnitude(v) {
return v.x;
}
const zero = new Vector(0); // Map1
const anotherOldObject = new Vector(0); // Map1
%PrepareFunctionForOptimization(magnitude);
magnitude(zero);
// Make the feedback polymorphic with an unrelated map.
const unrelated = {a: 0, b: 0, c: 0, x: 0};
magnitude(unrelated);
const nonzero = new Vector(0.6); // Map2
// Map1 is now deprecated but Map2 is not a migration target.
%OptimizeFunctionOnNextCall(magnitude);
magnitude(zero);
// The first call immediately deopts
assertUnoptimized(magnitude);
// But we learn and don't deopt any more.
%OptimizeFunctionOnNextCall(magnitude);
magnitude(zero);
assertOptimized(magnitude);
// Also passing other old objects won't deopt.
magnitude(anotherOldObject);
assertOptimized(magnitude);

View File

@ -0,0 +1,35 @@
// Copyright 2024 the V8 project 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 --turbofan --no-always-turbofan
class Vector {
constructor(x) {
this.x = x;
}
}
function magnitude(v) {
return v.x;
}
const zero = new Vector(0); // Map1
const anotherOldObject = new Vector(0); // Map1
%PrepareFunctionForOptimization(magnitude);
magnitude(zero);
// Make the feedback polymorphic with an unrelated map.
const unrelated = {a: 0, b: 0, c: 0, x: 0};
magnitude(unrelated);
const nonzero = new Vector(0.6); // Map2
// Map1 is now deprecated but Map2 is not a migration target.
%OptimizeFunctionOnNextCall(magnitude);
magnitude(nonzero);
// The first call doesn't deopt if called with a new object.
assertOptimized(magnitude);

View File

@ -0,0 +1,41 @@
// Copyright 2024 the V8 project 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 --turbofan --no-always-turbofan
class Vector {
constructor(x) {
this.x = x;
}
}
function magnitude(v) {
return v.x;
}
%PrepareFunctionForOptimization(magnitude);
const oldObject = new Vector(0); // Map1
const anotherOldObject = new Vector(0); // Map1
const newObject = new Vector(0.6); // Map2
// Make Map2 a migration target.
oldObject.x = 0.3;
// Make `magnitude` polymorphic with Map2 (a migration target) and an unrelated
// map.
magnitude(newObject);
const unrelated = {a: 0, b: 0, c: 0, x: 0};
magnitude(unrelated);
%OptimizeFunctionOnNextCall(magnitude);
magnitude(newObject);
assertOptimized(magnitude);
// It should now migrate old objects.
magnitude(anotherOldObject);
// TODO(turbofan): Fix https://issues.chromium.org/u/1/issues/383318227
// assertOptimized(magnitude);

View File

@ -0,0 +1,77 @@
// Copyright 2022 the V8 project 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() {
const map = new Map();
map.set(true, true);
for (let i = 0; i < 10000; i += 1) {
map.set(i, i);
map.set(`${i} number`, i);
}
function foo(x) {
return map.has(x);
}
%PrepareFunctionForOptimization(foo);
assertFalse(foo(1.5));
assertTrue(foo(1));
assertFalse(foo('1.5 number'));
assertTrue(foo('1 number'));
assertFalse(foo(false));
assertTrue(foo(true));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(1.5));
assertTrue(foo(1));
assertFalse(foo('1.5 number'));
assertTrue(foo('1 number'));
assertFalse(foo(false));
assertTrue(foo(true));
})();
(function() {
const set = new Set();
set.add(true);
for (let i = 0; i < 10000; i += 1) {
set.add(i);
set.add(`${i} number`);
}
function foo(x) {
return set.has(x);
}
%PrepareFunctionForOptimization(foo);
assertFalse(foo(1.5));
assertTrue(foo(1));
assertFalse(foo('1.5 number'));
assertTrue(foo('1 number'));
assertFalse(foo(false));
assertTrue(foo(true));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(1.5));
assertTrue(foo(1));
assertFalse(foo('1.5 number'));
assertTrue(foo('1 number'));
assertFalse(foo(false));
assertTrue(foo(true));
})();

View File

@ -0,0 +1,53 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --check-elimination
a = {
f: function() { this.y = 3; }
};
b = {
f: function() { this.y = 4; }
};
function x(z) {
return z.f();
}
%PrepareFunctionForOptimization(x);
x(a);
x(b);
x(a);
x(b);
x(a);
x(b);
%OptimizeFunctionOnNextCall(x)
x(a);
x(b);

View File

@ -0,0 +1,136 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --check-elimination
function test_empty() {
function foo(o) {
return { value: o.value };
}
%PrepareFunctionForOptimization(foo);
function Base() {
this.v_ = 5;
}
Base.prototype.__defineGetter__("value", function() { return 1; });
var a = new Base();
a.a = 1;
foo(a);
Base.prototype.__defineGetter__("value", function() { return this.v_; });
var b = new Base();
b.b = 1;
foo(b);
var d = new Base();
d.d = 1;
d.value;
%OptimizeFunctionOnNextCall(foo);
var o = foo(b);
}
function test_narrow1() {
function foo(o) {
return { value: o.value };
}
%PrepareFunctionForOptimization(foo);
function Base() {
this.v_ = 5;
}
Base.prototype.__defineGetter__("value", function() { return 1; });
var a = new Base();
a.a = 1;
foo(a);
Base.prototype.__defineGetter__("value", function() { return this.v_; });
var b = new Base();
b.b = 1;
foo(b);
var c = new Base();
c.c = 1;
foo(c);
var d = new Base();
d.d = 1;
d.value;
%OptimizeFunctionOnNextCall(foo);
var o = foo(b);
}
function test_narrow2() {
function foo(o, flag) {
return { value: o.value(flag) };
}
%PrepareFunctionForOptimization(foo);
function Base() {
this.v_ = 5;
}
Base.prototype.value = function(flag) { return flag ? this.v_ : this.v_; };
var a = new Base();
a.a = 1;
foo(a, false);
foo(a, false);
var b = new Base();
b.b = 1;
foo(b, true);
var c = new Base();
c.c = 1;
foo(c, true);
var d = new Base();
d.d = 1;
d.value(true);
%OptimizeFunctionOnNextCall(foo);
var o = foo(b);
}
test_empty();
test_narrow1();
test_narrow2();

View File

@ -0,0 +1,87 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --check-elimination
function A(x, y) {
this.x = x;
this.y = y;
}
function B(x, y) {
this.x = x;
this.y = y;
}
function F1(a, b) {
if (a == b) return a.x;
else return b.x;
}
function F2(a, b) {
if (a == b) return a.x;
else return b.x;
}
function F3(a, b) {
var f = a.y;
if (a == b) return a.x;
else return b.x;
}
function F4(a, b) {
var f = b.y;
if (a == b) return a.x;
else return b.x;
}
%NeverOptimizeFunction(test);
function test(f, a, b) {
%PrepareFunctionForOptimization(f);
f(a, a);
f(a, b);
f(b, a);
f(b, c);
f(b, b);
f(c, c);
%OptimizeFunctionOnNextCall(f)
assertEquals(a.x, f(a, a));
assertEquals(b.x, f(b, b));
}
var a = new A(3, 5);
var b = new B(2, 6);
var c = new A(1, 7);
test(F1, a, c);
test(F2, a, b);
test(F3, a, b);
test(F4, a, b);

108
deps/v8/test/mjsunit/compiler/compare.js vendored Normal file
View File

@ -0,0 +1,108 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function MaxLT(x, y) {
if (x < y) return y;
return x;
}
function MaxLE(x, y) {
if (x <= y) return y;
return x;
}
function MaxGE(x, y) {
if (x >= y) return x;
return y;
}
function MaxGT(x, y) {
if (x > y) return x;
return y;
}
// First test primitive values.
function TestPrimitive(max, x, y) {
assertEquals(max, MaxLT(x, y), "MaxLT - primitive");
assertEquals(max, MaxLE(x, y), "MaxLE - primitive");
assertEquals(max, MaxGE(x, y), "MaxGE - primitive");
assertEquals(max, MaxGT(x, y), "MaxGT - primitive");
}
TestPrimitive(1, 0, 1);
TestPrimitive(1, 1, 0);
TestPrimitive(4, 3, 4);
TestPrimitive(4, 4, 3);
TestPrimitive(0, -1, 0);
TestPrimitive(0, 0, -1)
TestPrimitive(-2, -2, -3);
TestPrimitive(-2, -3, -2);
TestPrimitive(1, 0.1, 1);
TestPrimitive(1, 1, 0.1);
TestPrimitive(4, 3.1, 4);
TestPrimitive(4, 4, 3.1);
TestPrimitive(0, -1.1, 0);
TestPrimitive(0, 0, -1.1)
TestPrimitive(-2, -2, -3.1);
TestPrimitive(-2, -3.1, -2);
// Test non-primitive values and watch for valueOf call order.
function TestNonPrimitive(order, f) {
var result = "";
var x = { valueOf: function() { result += "x"; } };
var y = { valueOf: function() { result += "y"; } };
f(x, y);
assertEquals(order, result);
}
TestNonPrimitive("xy", MaxLT);
TestNonPrimitive("xy", MaxLE);
TestNonPrimitive("xy", MaxGE);
TestNonPrimitive("xy", MaxGT);
// Test compare in case of aliased registers.
function CmpX(x) { if (x == x) return 42; }
assertEquals(42, CmpX(0));
function CmpXY(x) { var y = x; if (x == y) return 42; }
assertEquals(42, CmpXY(0));
// Test compare against null.
function CmpNullValue(x) { return x == null; }
assertEquals(false, CmpNullValue(42));
function CmpNullTest(x) { if (x == null) return 42; return 0; }
assertEquals(42, CmpNullTest(null));
var g1 = 0;
function CmpNullEffect() { (g1 = 42) == null; }
CmpNullEffect();
assertEquals(42, g1);

View File

@ -0,0 +1,50 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function TestNamed(m) {
var o = {};
var result = [];
for (o.p in m) result.push(o.p);
return result;
}
assertArrayEquals(['x','y'], TestNamed({x:0, y:1}));
assertArrayEquals(['0','1'], TestNamed([1,2]));
function TestKeyed(m) {
var a = [];
var result = [];
var i = 0;
for (a[i++] in m) result.push(a[i - 1]);
assertEquals(i, a.length);
return result;
}
assertArrayEquals(['x','y'], TestKeyed({x:0, y:1}));
assertArrayEquals(['0','1'], TestKeyed([1,2]));

View File

@ -0,0 +1,26 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turboshaft-enable-debug-features
// This test ensures that we manage to serialize the global.gaga function for
// compilation and therefore are able to inline it. Since the call feedback in
// bar is megamorphic, this relies on recording the correct accumulator hint for
// the named load of obj.gaga while serializing bar (in turn while serializing
// foo).
const global = this;
global.gaga = function gaga() { return true; };
function bar(obj) { return obj.gaga(); };
function foo() { return %TurbofanStaticAssert(bar(global)); }
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
%PrepareFunctionForOptimization(global.gaga);
bar({gaga() {}});
foo();
%OptimizeFunctionOnNextCall(foo);
foo();

View File

@ -0,0 +1,26 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turboshaft-enable-debug-features
// This test ensures that we manage to serialize the global.gaga function for
// compilation and therefore are able to inline it. Since the call feedback in
// bar is megamorphic, this relies on recording the correct accumulator hint for
// the named load of obj.gaga while serializing bar (in turn while serializing
// foo).
const global = this;
global.gaga = function gaga() { return true; };
function bar(obj) { return obj.gaga(); }
function foo(obj) { obj.gaga; %TurbofanStaticAssert(bar(obj)); }
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
%PrepareFunctionForOptimization(global.gaga);
bar({gaga() {}});
foo(global);
%OptimizeFunctionOnNextCall(foo);
foo(global);

View File

@ -0,0 +1,73 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --concurrent-recompilation --no-always-turbofan
if (!%IsConcurrentRecompilationSupported()) {
print("Concurrent recompilation is disabled. Skipping this test.");
quit();
}
function new_object() {
var o = {};
o.a = 1;
o.b = 2;
return o;
}
function add_field(obj) {
// Assign twice to make the field non-constant.
obj.c = 0;
obj.c = 3;
}
%PrepareFunctionForOptimization(add_field);
var obj1 = new_object();
var obj2 = new_object();
add_field(obj1);
add_field(obj2);
%DisableOptimizationFinalization();
%OptimizeFunctionOnNextCall(add_field, "concurrent");
var o = new_object();
// Kick off recompilation.
add_field(o);
// Invalidate transition map after compile graph has been created.
%WaitForBackgroundOptimization();
o.c = 2.2;
assertUnoptimized(add_field);
// Sync with background thread to conclude optimization that bailed out.
%FinalizeOptimization();
if (!%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11457) Currently, we cannot inline property stores if there is a
// dictionary mode prototype on the prototype chain. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get invalidated when the
// transition map changes.
assertUnoptimized(add_field);
}
// Clear type info for stress runs.
%ClearFunctionFeedback(add_field);

View File

@ -0,0 +1,53 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --no-always-turbofan --concurrent-recompilation
function f(foo) { return foo.bar(); }
%PrepareFunctionForOptimization(f);
var o = {};
o.__proto__ = { __proto__: { bar: function() { return 1; } } };
assertEquals(1, f(o));
assertEquals(1, f(o));
%DisableOptimizationFinalization();
%OptimizeFunctionOnNextCall(f, "concurrent");
// Kick off recompilation.
assertEquals(1, f(o));
// Change the prototype chain after compile graph has been created.
%WaitForBackgroundOptimization();
o.__proto__.__proto__ = { bar: function() { return 2; } };
assertUnoptimized(f);
%FinalizeOptimization();
// Optimization failed due to map dependency.
assertUnoptimized(f);
assertEquals(2, f(o));
// Clear type info for stress runs.
%ClearFunctionFeedback(f);

View File

@ -0,0 +1,123 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Generates a function of the form
//
// function(x) {
// return (x === threshold) ? threshold*threshold :
// (x === threshold+1) ? (threshold+1)*(threshold+1) :
// ...
// (x === threshold+num_if_else-1) ?
// (threshold+num_if_else-1)*(threshold+num_if_else-1) :
// (threshold+num_if_else)*(threshold+num_if_else);
// }
//
function generate_long_conditional_chain(num_if_else, threshold = 0) {
let str = "(function(x){";
str += "return ";
for (let j = 0; j < num_if_else; j++) {
let i = j + threshold;
str += "(x === "+i+") ? "+i*i+" : ";
}
let i = num_if_else + threshold;
str += i*i+";})";
return eval(str);
}
// Generates a function of the form
//
// function(x, y) {
// return (x === 0 && y === 0) ? 0*0 + threshold :
// (x === 0 && y === 1) ? 0*1 + threshold :
// ...
// (x === 1 && y === 1) ? 1*1 + threshold :
// (x === 1 && y === 2) ? 1*2 + threshold :
// ...
// (x === 2 && y === 1) ? 2*1 + threshold :
// (x === 2 && y === 2) ? 2*2 + threshold :
// (x === 2 && y === 3) ? 2*3 + threshold :
// ...
// (x === num_x-1 && y === num_y-1) ?
// (num_x-1)*(num_y-1) + threshold :
// (num_x)*(num_y) + threshold;
function generate_double_conditional_chain(num_x, num_y, threshold = 0) {
let str = "(function(x, y){";
str += "return ";
for (let i = 0; i < num_x; i++) {
for (let j = 0; j < num_y; j++) {
str += "(x === "+i+" && y === "+j+") ? "+(i*j + threshold)+" : ";
}
}
str += (num_x*num_y + threshold)+";})";
return eval(str);
}
(function() {
let conditional_chain = generate_long_conditional_chain(110);
assertEquals(5*5, conditional_chain(5));
assertEquals(6*6, conditional_chain(6));
assertEquals(100*100, conditional_chain(100));
assertEquals(109*109, conditional_chain(109));
assertEquals(110*110, conditional_chain(110));
assertEquals(110*110, conditional_chain(111));
assertEquals(110*110, conditional_chain(200));
assertEquals(110*110, conditional_chain(1000));
})();
// Test that the result of the conditional chain is correct for a double
// conditional chain. While the result given should be correct, there should
// not be any crashes even if the length of the chain is very long.
(function() {
let threshold = 100;
let double_conditional_chain =
generate_double_conditional_chain(17, 19, threshold);
assertEquals(5*5 + threshold, double_conditional_chain(5, 5));
assertEquals(6*6 + threshold, double_conditional_chain(6, 6));
assertEquals(4*5 + threshold, double_conditional_chain(4, 5));
assertEquals(5*4 + threshold, double_conditional_chain(5, 4));
assertEquals(9*2 + threshold, double_conditional_chain(9, 2));
assertEquals(17*19 + threshold, double_conditional_chain(100, 12));
assertEquals(17*19 + threshold, double_conditional_chain(100, 100));
assertEquals(17*19 + threshold, double_conditional_chain(100, 1000));
assertEquals(17*19 + threshold, double_conditional_chain(1000, 100));
assertEquals(17*19 + threshold, double_conditional_chain(1000, 1000));
})();
// Test that the result of the conditional chain is correct.
// The size of the chain is stretched to 50000 to make sure that the
// conditional chain will not crash even if the length of the chain is very
// long.
(function() {
let threshold = 100;
let chain_length = 50000;
let conditional_chain =
generate_long_conditional_chain(chain_length, threshold);
assertEquals(
(chain_length + threshold)*(chain_length + threshold),
conditional_chain(0));
assertEquals(
(chain_length + threshold)*(chain_length + threshold),
conditional_chain(1));
assertEquals(
(1 + threshold)*(1 + threshold),
conditional_chain(1 + threshold));
assertEquals(
(2 + threshold)*(2 + threshold),
conditional_chain(2 + threshold));
assertEquals(
(chain_length - 1 + threshold)*(chain_length - 1 + threshold),
conditional_chain(chain_length - 1 + threshold));
assertEquals(
(chain_length + threshold)*(chain_length + threshold),
conditional_chain(chain_length + threshold));
assertEquals(
(chain_length + threshold)*(chain_length + threshold),
conditional_chain(chain_length + 1 + threshold));
assertEquals(
(chain_length + threshold)*(chain_length + threshold),
conditional_chain(chain_length + 100 + threshold));
assertEquals(
(chain_length + threshold)*(chain_length + threshold),
conditional_chain(chain_length + 1000 + threshold));
})();

View File

@ -0,0 +1,30 @@
// Copyright 2020 the V8 project 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 f1(n) {
var a = n + 2;
return a + 3;
}
%PrepareFunctionForOptimization(f1);
assertEquals(f1(1), 6);
assertEquals(f1(2), 7);
%OptimizeFunctionOnNextCall(f1);
assertEquals(f1(13), 18);
assertEquals(f1(14), 19);
function f2(n, odd) {
var a = n + 2;
if (odd) return a;
return a + 3;
}
%PrepareFunctionForOptimization(f2);
assertEquals(f2(1, true), 3);
assertEquals(f2(2, false), 7);
%OptimizeFunctionOnNextCall(f2);
assertEquals(f2(13, true), 15);
assertEquals(f2(14, false), 19);

View File

@ -0,0 +1,18 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --no-assert-types
// Flags: --turboshaft-enable-debug-features
// Check that constant-folding of arithmetic results in identical nodes.
(function() {
function foo(x) {
%TurbofanStaticAssert(1 * x == x + 0);
};
%PrepareFunctionForOptimization(foo);
foo(121);
foo(122);
%OptimizeFunctionOnNextCall(foo);
foo(123);
})();

View File

@ -0,0 +1,123 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --no-always-turbofan --turbofan
// Check that we properly deoptimize TurboFan'ed code when we constant-fold
// elements from a COW array and we change the length of the array.
(function() {
const a = [1, 2, 3];
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a.length = 1;
assertEquals(1, foo());
assertUnoptimized(foo);
})();
// Check that we properly deoptimize TurboFan'ed code when we constant-fold
// elements from a COW array and we change the element of the array.
(function() {
const a = [1, 2, 3];
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a[0] = 42;
assertEquals(42, foo());
assertUnoptimized(foo);
})();
// Packed
// Non-extensible
(function() {
const a = Object.preventExtensions([1, 2, '3']);
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a[0] = 42;
assertEquals(42, foo());
})();
// Sealed
(function() {
const a = Object.seal([1, 2, '3']);
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a[0] = 42;
assertEquals(42, foo());
})();
// Frozen
(function() {
const a = Object.freeze([1, 2, '3']);
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a[0] = 42;
assertEquals(1, foo());
})();
// Holey
// Non-extensible
(function() {
const a = Object.preventExtensions([1, 2, , '3']);
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a[0] = 42;
assertEquals(42, foo());
})();
// Sealed
(function() {
const a = Object.seal([1, 2, , '3']);
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a[0] = 42;
assertEquals(42, foo());
})();
// Frozen
(function() {
const a = Object.freeze([1, 2, , '3']);
const foo = () => a[0];
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo());
assertEquals(1, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo());
assertOptimized(foo);
a[0] = 42;
assertEquals(1, foo());
})();

View File

@ -0,0 +1,28 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --no-always-turbofan --turbofan
// Check that constant-folding of ToString operations works properly for NaN.
(function() {
const foo = () => `${NaN}`;
%PrepareFunctionForOptimization(foo);
assertEquals("NaN", foo());
assertEquals("NaN", foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals("NaN", foo());
})();
// Check that constant-folding of ToString operations works properly for 0/-0.
(function() {
const foo = x => `${x ? 0 : -0}`;
%PrepareFunctionForOptimization(foo);
assertEquals("0", foo(true));
assertEquals("0", foo(false));
assertEquals("0", foo(true));
assertEquals("0", foo(false));
%OptimizeFunctionOnNextCall(foo);
assertEquals("0", foo(true));
assertEquals("0", foo(false));
})();

View File

@ -0,0 +1,34 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan --turboshaft-enable-debug-features
class C extends Object {
bla() {}
}
const bla = C.prototype.bla;
function bar(c) {
%TurbofanStaticAssert(c.bla === bla);
}
const boundC = C.bind(null);
function foo() {
let c = new boundC();
bar(c);
}
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
%PrepareFunctionForOptimization(C);
bar({});
bar({a:1});
bar({aa:1});
bar({aaa:1});
bar({aaaa:1});
bar({aaaaa:1});
foo();
foo();
%OptimizeFunctionOnNextCall(foo);
foo();

View File

@ -0,0 +1,30 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan --turboshaft-enable-debug-features
Object.prototype.bla = function() {}
const bla = Object.prototype.bla;
function bar(c) {
%TurbofanStaticAssert(c.bla === bla);
}
function foo() {
var c = new Object();
bar(c);
}
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
bar({});
bar({a:1});
bar({aa:1});
bar({aaa:1});
bar({aaaa:1});
bar({aaaaa:1});
foo();
foo();
%OptimizeFunctionOnNextCall(foo);
foo();

View File

@ -0,0 +1,29 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turboshaft-enable-debug-features
class C {
bla() {};
constructor() { %TurbofanStaticAssert(this.bla === bla); }
}
const bla = C.prototype.bla;
function bar(f) { return new f; }
var CC = C;
function foo() { return bar(CC); }
%PrepareFunctionForOptimization(C);
%PrepareFunctionForOptimization(bla);
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
// Make {this.bla} in C megamorphic
new class extends C { constructor() { super(); this.a = 1 } }
new class extends C { constructor() { super(); this.b = 1 } }
new class extends C { constructor() { super(); this.c = 1 } }
new class extends C { constructor() { super(); this.d = 1 } }
foo();
%OptimizeFunctionOnNextCall(foo);
foo();

View File

@ -0,0 +1,110 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --stress-inline
var counter = 0;
var deopt_at = -1;
class Base {
constructor(use, x){
if (deopt_at-- == 0) {
%_DeoptimizeNow();
%DeoptimizeFunction(testConstructorInlining);
}
counter++;
this.x = x;
if (use) {
return x;
}
}
}
class Derived extends Base {
constructor(use, x, y, deopt = false) {
super(use, x);
counter++;
if (deopt_at-- == 0) %_DeoptimizeNow();
this.y = y;
if (use) {
return y;
}
}
}
var DerivedDeoptCreate = new Proxy(Derived, {
get: function(target, name) {
if (name=='prototype') {
counter++;
if (deopt_at-- == 0) %DeoptimizeFunction(Derived);
}
return target[name];
}
});
function Constr(use, x){
counter++;
if (deopt_at-- == 0) %_DeoptimizeNow();
this.x = x;
if (use) {
return x;
}
}
var a = {};
var b = {};
function testConstructorInlining(){
assertEquals(a, new Constr(true, a));
assertEquals(7, new Constr(false, 7).x);
assertEquals(5, new Constr(true, 5).x);
assertEquals(a, new Base(true, a));
assertEquals(7, new Base(false, 7).x);
assertEquals(5, new Base(true, 5).x);
assertEquals(b, new Derived(true, a, b));
assertEquals(a, new Derived(true, a, undefined));
assertEquals(5, new Derived(false, 5, 7).x);
assertEquals(7, new Derived(false, 5, 7).y);
try {
new Derived(true, a, 7)
assertTrue(false);
} catch (e) {
if (!(e instanceof TypeError)) throw e;
}
assertEquals(a, new Derived(true, 5, a));
%PrepareFunctionForOptimization(Derived);
%OptimizeFunctionOnNextCall(Derived);
assertEquals(b, new DerivedDeoptCreate(true, a, b));
%PrepareFunctionForOptimization(Derived);
%OptimizeFunctionOnNextCall(Derived);
assertEquals(a, new DerivedDeoptCreate(true, a, undefined));
%PrepareFunctionForOptimization(Derived);
%OptimizeFunctionOnNextCall(Derived);
assertEquals(5, new DerivedDeoptCreate(false, 5, 7).x);
%PrepareFunctionForOptimization(Derived);
%OptimizeFunctionOnNextCall(Derived);
assertEquals(7, new DerivedDeoptCreate(false, 5, 7).y);
}
testConstructorInlining();
%PrepareFunctionForOptimization(testConstructorInlining);
%OptimizeFunctionOnNextCall(testConstructorInlining);
testConstructorInlining();
var last = undefined;
for(var i = 0; deopt_at < 0; ++i) {
deopt_at = i;
counter = 0;
%PrepareFunctionForOptimization(testConstructorInlining);
%OptimizeFunctionOnNextCall(testConstructorInlining);
testConstructorInlining();
if (last !== undefined) {
assertEquals(counter, last)
}
last = counter;
}

View File

@ -0,0 +1,577 @@
// 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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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);
}
%PrepareFunctionForOptimization(foo);
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];
}
%PrepareFunctionForOptimization(foo);
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];
}
%PrepareFunctionForOptimization(foo);
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;
});
}
%PrepareFunctionForOptimization(foo);
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;
});
}
%PrepareFunctionForOptimization(foo);
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;
});
}
%PrepareFunctionForOptimization(foo);
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"));
})();

View File

@ -0,0 +1,44 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function f() {
return (42 + (0 == 1 ? 1 : 2));
}
function g(x) {
return (x + (0 == 1 ? 1 : 2));
}
function h(x) {
return ((x + 1) + (0 == 1 ? 1 : 2));
}
assertEquals(44, f());
assertEquals(45, g(43));
assertEquals(47, h(44));

View File

@ -0,0 +1,55 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var global = this;
function f0(x) {
assertTrue(this === global);
return x;
}
function g0(x, y) {
return f0(x == y);
}
assertTrue(g0(0, 0));
assertFalse(g0(0, 1));
var o = {};
o.f1 = f1;
function f1(x) {
assertTrue(this === o);
return x;
}
function g1(x, y) {
return o.f1(x == y);
}
assertTrue(g1(0, 0));
assertFalse(g1(0, 1));

View File

@ -0,0 +1,34 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function f(a,b) {
return (b < a) - (a < b);
}
assertEquals(0, f(0,0));
assertEquals(1, f(1,0));
assertEquals(-1, f(0,1));

Some files were not shown because too many files have changed in this diff Show More