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,63 @@
// 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 --turbolev --turbofan
let uint32_arr = new Uint32Array(5);
uint32_arr[1] = 168;
uint32_arr[2] = 5896;
let uint8_clamped_arr = new Uint8ClampedArray(10);
function store_clamped_array(x, small_num, large_num, nan) {
// Storing Float64 (< 255)
let f64_small = x + 3.45;
uint8_clamped_arr[0] = f64_small;
// Storing Float64 (> 255);
let f64_large = x + 18956.586;
uint8_clamped_arr[1] = f64_large;
// Storing Int32 (< 255)
let i32_small = x + 17;
uint8_clamped_arr[2] = i32_small;
// Storing Int32 (> 255)
let i32_large = x + 25896;
uint8_clamped_arr[3] = i32_large;
// Storing uint32 (< 255)
let uint32_small = uint32_arr[1];
uint8_clamped_arr[4] = uint32_small;
let uint32_large = uint32_arr[2];
uint8_clamped_arr[5] = uint32_large;
// Storing number (small)
uint8_clamped_arr[6] = small_num;
// Storing number (large)
uint8_clamped_arr[7] = large_num;
// Storing number (NaN)
uint8_clamped_arr[8] = nan;
}
let expected = new Uint8ClampedArray([7,255,21,255,168,255,6,255,0,0]);
%PrepareFunctionForOptimization(store_clamped_array);
store_clamped_array(4, 6, 1896.365, NaN);
assertEquals(expected, uint8_clamped_arr);
// Reseting the array
uint8_clamped_arr = new Uint8ClampedArray(10);
%OptimizeFunctionOnNextCall(store_clamped_array);
store_clamped_array(4, 6, 1896.365, NaN);
assertEquals(expected, uint8_clamped_arr);
assertOptimized(store_clamped_array);
// Triggering deopt when trying to store a non-number
store_clamped_array(4, "abc", 1896.365);
expected[6] = 0;
assertEquals(expected, uint8_clamped_arr);
// Note: we don't AssertUnoptimized here because in some configurations where
// some clamped Uint8 operations are not supported, the stores of
// `store_clamped_array` are compiled to SetKeyedGeneric by Maglev, and thus
// do not deopt for non-numbers. If the result is correct, then deopt or not,
// the correct thing probably happened.

View File

@ -0,0 +1,17 @@
// 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 --turbolev --turbofan
function add_double_property(o) {
o.x = 1.1;
return o;
}
%PrepareFunctionForOptimization(add_double_property);
assertEquals({x:1.1}, add_double_property({}));
assertEquals({x:1.1}, add_double_property({}));
%OptimizeFunctionOnNextCall(add_double_property);
assertEquals({x:1.1}, add_double_property({}));
assertOptimized(add_double_property);

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
// Flags: --no-maglev-inline-api-calls
// Flags: --no-rcs
function g() { }
function main() {
var err = new Error();
return err.stack;
}
Error.prepareStackTrace = function() { return "The stack trace\n"; };
%PrepareFunctionForOptimization(main);
let stack = main();
%OptimizeFunctionOnNextCall(main);
assertEquals(stack, main());
assertOptimized(main);

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
// Flags: --no-maglev-inline-api-calls
// Flags: --rcs
function g() { }
function main() {
var err = new Error();
return err.stack;
}
Error.prepareStackTrace = function() { return "The stack trace\n"; };
%PrepareFunctionForOptimization(main);
let stack = main();
%OptimizeFunctionOnNextCall(main);
assertEquals(stack, main());
assertOptimized(main);

View File

@ -0,0 +1,29 @@
// 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 --turbolev --turbofan
// Flags: --no-always-turbofan
function array_buffer_load(arr) {
return arr[1];
}
let float32_arr = new Float32Array(10);
float32_arr[1] = 16.625;
%PrepareFunctionForOptimization(array_buffer_load);
assertEquals(16.625, array_buffer_load(float32_arr));
%OptimizeFunctionOnNextCall(array_buffer_load);
assertEquals(16.625, array_buffer_load(float32_arr));
assertOptimized(array_buffer_load);
// Invalidating ArrayBufferDetachingProtector.
let int32_arr = new Int32Array(10);
%ArrayBufferDetach(int32_arr.buffer);
// This should have triggered a deopt of `array_buffer_load`.
assertUnoptimized(array_buffer_load);
// Reopting without the protector valid.
%OptimizeFunctionOnNextCall(array_buffer_load);
assertEquals(16.625, array_buffer_load(float32_arr));
assertOptimized(array_buffer_load);

View File

@ -0,0 +1,16 @@
// 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 --turbolev --turbofan
function destruct_arr() {
[a, b] = [4, 9];
return a + b;
}
%PrepareFunctionForOptimization(destruct_arr);
assertEquals(13, destruct_arr());
%OptimizeFunctionOnNextCall(destruct_arr);
assertEquals(13, destruct_arr());
assertOptimized(destruct_arr);

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function load_double_arr(arr, idx) {
return arr[2] + arr[idx];
}
let double_arr = [1.552, 2.425, 3.526, 4.596, 5.986, 6.321];
%PrepareFunctionForOptimization(load_double_arr);
assertEquals(8.122, load_double_arr(double_arr, 3));
assertEquals(8.122, load_double_arr(double_arr, 3));
%OptimizeFunctionOnNextCall(load_double_arr);
assertEquals(8.122, load_double_arr(double_arr, 3));
assertOptimized(load_double_arr);
// String indices currently work without requiring deopt.
assertEquals(5.951, load_double_arr(double_arr, '1'));
assertOptimized(load_double_arr);

View File

@ -0,0 +1,36 @@
// 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 --turbolev --turbofan
function for_each_input_fun(f) {
[1, 2, 3].forEach(f);
}
%PrepareFunctionForOptimization(for_each_input_fun);
assertThrows(() => for_each_input_fun(undefined), TypeError);
assertThrows(() => for_each_input_fun(undefined), TypeError);
%OptimizeFunctionOnNextCall(for_each_input_fun);
assertThrows(() => for_each_input_fun(undefined), TypeError);
assertThrows(() => for_each_input_fun(1), TypeError);
assertThrows(() => for_each_input_fun([]), TypeError);
assertOptimized(for_each_input_fun);
let glob = 0;
assertEquals(undefined, for_each_input_fun(function(v){glob += v}));
assertEquals(glob, 6);
assertOptimized(for_each_input_fun);
function for_each_local_closure(n) {
let s = 0;
[1, 2, 3].forEach((v) => s += v + n);
return s;
}
%PrepareFunctionForOptimization(for_each_local_closure);
assertEquals(15, for_each_local_closure(3));
assertEquals(15, for_each_local_closure(3));
%OptimizeFunctionOnNextCall(for_each_local_closure);
assertEquals(15, for_each_local_closure(3));
assertOptimized(for_each_local_closure);

View File

@ -0,0 +1,28 @@
// 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 --turbolev --turbofan
// Flags: --no-always-turbofan
function load_holey_fixed_double(arr, idx) {
return arr[idx];
}
let holey_double_arr = [2.58,3.41,,4.55];
%PrepareFunctionForOptimization(load_holey_fixed_double);
assertEquals(3.41, load_holey_fixed_double(holey_double_arr, 1));
%OptimizeFunctionOnNextCall(load_holey_fixed_double);
assertEquals(3.41, load_holey_fixed_double(holey_double_arr, 1));
assertOptimized(load_holey_fixed_double);
// Loading a hole should trigger a deopt
assertEquals(undefined, load_holey_fixed_double(holey_double_arr, 2));
assertUnoptimized(load_holey_fixed_double);
// Reoptimizing, holes should now be handled
%OptimizeMaglevOnNextCall(load_holey_fixed_double);
assertEquals(3.41, load_holey_fixed_double(holey_double_arr, 1));
%OptimizeFunctionOnNextCall(load_holey_fixed_double);
assertEquals(3.41, load_holey_fixed_double(holey_double_arr, 1));
assertEquals(undefined, load_holey_fixed_double(holey_double_arr, 2));
assertOptimized(load_holey_fixed_double);

View File

@ -0,0 +1,16 @@
// 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 --turbolev --turbofan
function load_hole(arr, idx) {
return arr[idx];
}
let holey_arr = [ {}, 3.41, /* hole */, 4.55 ];
%PrepareFunctionForOptimization(load_hole);
assertEquals(undefined, load_hole(holey_arr, 2));
%OptimizeFunctionOnNextCall(load_hole);
assertEquals(undefined, load_hole(holey_arr, 2));
assertOptimized(load_hole);

View File

@ -0,0 +1,24 @@
// 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 --turbolev --turbofan
let a = [1, 2, 3, 4];
let b = [5, 6, 7, 8];
function arr_oob_load(a, b) {
let s = [0, 0, 0, 0, 0, 0];
for (let i = 0; i < 6; i++) {
// This will load out of bounds in {a} and {b}, which is fine.
s[i] = a[i] + b[i];
}
return s;
}
%PrepareFunctionForOptimization(arr_oob_load);
assertEquals([6, 8, 10, 12, NaN, NaN], arr_oob_load(a, b));
assertEquals([6, 8, 10, 12, NaN, NaN], arr_oob_load(a, b));
%OptimizeFunctionOnNextCall(arr_oob_load);
assertEquals([6, 8, 10, 12, NaN, NaN], arr_oob_load(a, b));
assertOptimized(arr_oob_load);

View File

@ -0,0 +1,46 @@
// 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 --turbolev --turbofan --no-always-turbofan
load('test/mjsunit/elements-kinds-helpers.js');
function plusOne(x) {
return x + 1;
}
%PrepareFunctionForOptimization(plusOne);
function foo(a) {
return a.map(plusOne);
}
%PrepareFunctionForOptimization(foo);
// First optimize the function normally.
const array = [1, 2, 3];
foo(array);
%OptimizeFunctionOnNextCall(foo);
foo(array);
assertOptimized(foo);
const array2 = [1, 2, 3];
MakeArrayDictionaryMode(array2, () => { return 0; });
// Having Array.prototype.map create a dictionary mode array will invalidate
// the array constructor inlining protector. However, foo will not be
// deoptimized, since it doesn't depend on the protector.
array2.map(plusOne);
assertOptimized(foo);
// But if a dictionary mode array is passed to foo, it will deopt.
foo(array2);
assertUnoptimized(foo);
// The next time foo is optimized, the feedback contains a dictionary mode
// array, so Array.prototype.map will not be lowered.
%OptimizeFunctionOnNextCall(foo);
foo(array);
assertOptimized(foo);
foo(array2);
assertOptimized(foo);

View File

@ -0,0 +1,90 @@
// 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 --turbolev --turbofan --no-always-turbofan
// Flags: --no-optimize-on-next-call-optimizes-to-maglev
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,583 @@
// 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 --turbolev --turbofan --no-always-turbofan
// Flags: --no-optimize-on-next-call-optimizes-to-maglev
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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedSmiElements(result2));
assertTrue(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);
assertEquals(result, result2);
assertTrue(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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
// 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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
// TODO(399393885): Make the optimized version use the same elements kind as
// the unoptimized version.
// assertTrue(HasPackedObjectElements(result2));
assertTrue(HasHoleyObjectElements(result2));
// The callback will deopt.
assertUnoptimized(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);
assertEquals(result, result2);
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);
assertEquals(result, result2);
assertTrue(HasHoleySmiElements(result2));
assertEquals(undefined, result2[2]);
// Unoptimized because the array length changed during iteration.
assertUnoptimized(foo);
})();

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
function array_push_grow_once(arr, x, y) {
// The 1st push will have to grow the array.
arr.push(x);
arr.push(y);
return arr.at(-1) + arr.at(-2) + arr.at(-3);
}
arr = [0, 1, 2, 3, 4, 5];
%PrepareFunctionForOptimization(array_push_grow_once);
assertEquals(29, array_push_grow_once(arr, 11, 13));
arr = [0, 1, 2, 3, 4, 5];
%OptimizeFunctionOnNextCall(array_push_grow_once);
assertEquals(29, array_push_grow_once(arr, 11, 13));
assertOptimized(array_push_grow_once);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
function array_push_pop(arr, x) {
let v = arr.pop();
arr.push(x); // This doesn't require growing the array.
return v + arr[5];
}
let arr = [0, 1, 2, 3, 4, 5];
%PrepareFunctionForOptimization(array_push_pop);
assertEquals(16, array_push_pop(arr, 11));
arr[5] = 5;
%OptimizeFunctionOnNextCall(array_push_pop);
assertEquals(16, array_push_pop(arr, 11));
assertOptimized(array_push_pop);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
function load_smi_arr(arr, idx) {
return arr[1] + arr[idx];
}
let smi_arr = [1, 2, 3, 4, {}];
%PrepareFunctionForOptimization(load_smi_arr);
assertEquals(6, load_smi_arr(smi_arr, 3));
assertEquals(6, load_smi_arr(smi_arr, 3));
%OptimizeFunctionOnNextCall(load_smi_arr);
assertEquals(6, load_smi_arr(smi_arr, 3));
assertOptimized(load_smi_arr);
// String indices currently work without requiring deopt.
assertEquals(5, load_smi_arr(smi_arr, '2'));
assertOptimized(load_smi_arr);

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 --turbolev --turbofan
function transition_arr(arr) {
var object = new Object();
arr[0] = object;
}
let smi_arr = [1, 2, 3, 4];
let holey_smi_arr = [1, 2, 3, /* hole */, 4];
%PrepareFunctionForOptimization(transition_arr);
transition_arr(smi_arr);
transition_arr(holey_smi_arr);
// Resetting the arrays to collect feedback one more time.
smi_arr = [1, 2, 3, 4];
holey_smi_arr = [1, 2, 3, /* hole */, 4];
transition_arr(smi_arr);
transition_arr(holey_smi_arr);
let expected_smi_arr = smi_arr;
let expected_holey_smi_arr = holey_smi_arr;
%OptimizeFunctionOnNextCall(transition_arr);
// Resetting the arrays
smi_arr = [1, 2, 3, 4];
holey_smi_arr = [1, 2, 3, /* hole */, 4];
// Triggering transitions
transition_arr(smi_arr);
assertEquals(expected_smi_arr, smi_arr);
transition_arr(holey_smi_arr);
assertEquals(expected_holey_smi_arr, holey_smi_arr)
assertOptimized(transition_arr);
// Not trigering transitions (because arrays already transitioned)
transition_arr(smi_arr);
transition_arr(holey_smi_arr);
assertOptimized(transition_arr);
// Triggering deopt
let double_arr = [1.5, 3.32, 6.28];
transition_arr(double_arr);
assertEquals([{}, 3.32, 6.28], double_arr);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
function bitwise_smi(a, b) {
let x = a | b;
x = x & 52358961;
x = x ^ b;
x = x >> 2;
x = x << 5;
x = x >>> 1;
return ~x;
}
%PrepareFunctionForOptimization(bitwise_smi);
assertEquals(-23041, bitwise_smi(1548, 45235));
assertEquals(-23041, bitwise_smi(1548, 45235));
%OptimizeFunctionOnNextCall(bitwise_smi);
assertEquals(-23041, bitwise_smi(1548, 45235));
assertOptimized(bitwise_smi);

View File

@ -0,0 +1,37 @@
// 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 --turbolev --turbofan
function branch_cmp(w32, f64) {
let c1 = w32 + 2;
let v;
if (c1) {
v = c1 + 12;
} else {
v = c1 + 17;
}
let c2 = f64 + 1.5;
if (c2) {
v += 10;
} else {
v += 3;
}
if (f64 > 1.5) {
v += 2;
} else {
v += 7;
}
return v;
}
%PrepareFunctionForOptimization(branch_cmp);
assertEquals(41, branch_cmp(15, 3.25));
assertEquals(29, branch_cmp(-2, 3.25));
assertEquals(27, branch_cmp(-2, -1.5));
%OptimizeFunctionOnNextCall(branch_cmp);
assertEquals(41, branch_cmp(15, 3.25));
assertEquals(29, branch_cmp(-2, 3.25));
assertEquals(27, branch_cmp(-2, -1.5));
assertOptimized(branch_cmp);

View File

@ -0,0 +1,38 @@
// 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 --turbolev --turbofan
// Testing instanceof and builtin continuations.
// (copy-pasted from test/mjsunit/maglev/nested-continuations.js)
function Foo() {}
Object.defineProperty(Foo, Symbol.hasInstance, { value: Math.round });
let foo = new Foo();
function test_instanceof_foo(f) {
// `f instanceof Foo` runs `%ToBoolean(Foo[Symbol.hasInstance](f))`, where
// `Foo[Symbol.hasInstance]` is `Math.round`.
//
// So with sufficient builtin inlining, this will call
// `%ToBoolean(round(%ToNumber(f)))`, which will call `f.valueOf`. If this
// deopts (which in this test it will), we need to make sure to both round it,
// and then convert that rounded value to a boolean.
return f instanceof Foo;
}
foo.valueOf = () => {
%DeoptimizeFunction(test_instanceof_foo);
// Return a value which, when rounded, has ToBoolean false, and when not
// rounded, has ToBoolean true.
return 0.2;
}
%PrepareFunctionForOptimization(test_instanceof_foo);
assertFalse(test_instanceof_foo(foo));
assertFalse(test_instanceof_foo(foo));
%OptimizeFunctionOnNextCall(test_instanceof_foo);
assertFalse(test_instanceof_foo(foo));

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function f(a, b, c) {
return a + b + c;
}
let short_arr = [11, 27];
function f_spread_plus_args(short_arr, x) {
return f(...short_arr, x);
}
%PrepareFunctionForOptimization(f_spread_plus_args);
assertEquals(41, f_spread_plus_args(short_arr, 3));
%OptimizeFunctionOnNextCall(f_spread_plus_args);
assertEquals(41, f_spread_plus_args(short_arr, 3));
assertOptimized(f_spread_plus_args);

View File

@ -0,0 +1,25 @@
// 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 --turbolev --turbofan
function f(x, y, z) {
return x + y + z;
}
%NeverOptimizeFunction(f);
let arr = [17, 13, 5, 23];
function f_spread(arr) {
return f(...arr);
}
%PrepareFunctionForOptimization(f_spread);
assertEquals(35, f_spread(arr));
%OptimizeFunctionOnNextCall(f_spread);
assertEquals(35, f_spread(arr));
assertOptimized(f_spread);
let small_arr = [3, 5];
assertEquals(NaN, f_spread(small_arr));
assertOptimized(f_spread);

View File

@ -0,0 +1,28 @@
// 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 --turbolev --turbofan
function h(x) {
if (x) { willThrow(); }
else { return 17; }
}
%NeverOptimizeFunction(h);
function exc_f(a) {
try {
return h(a);
} catch (e) {
// Stringifying the exception for easier comparison.
return 'abc' + e;
}
}
%PrepareFunctionForOptimization(exc_f);
assertEquals(17, exc_f(0));
let err = exc_f(1); // Will cause an exception.
%OptimizeFunctionOnNextCall(exc_f);
assertEquals(17, exc_f(0));
assertEquals(err, exc_f(1));
assertOptimized(exc_f);

View File

@ -0,0 +1,33 @@
// 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 --turbolev --turbofan
// Testing exceptions (multiple throwing points, using the exception value).
function h(x) {
if (x) { willThrow(); }
else { return 17; }
}
%NeverOptimizeFunction(h);
function multi_exc_f(a, b) {
let r = a;
try {
r = h(a);
return h(b) + r;
} catch (e) {
// Stringifying the exception for easier comparison.
return 'abc' + e + r;
}
}
%PrepareFunctionForOptimization(multi_exc_f);
assertEquals(34, multi_exc_f(0, 0)); // Won't cause an exception.
let err1 = multi_exc_f(0, 11); // Will cause an exception on the 2nd call to h.
let err2 = multi_exc_f(7, 0); // Will cause an exception on the 1st call to h.
%OptimizeFunctionOnNextCall(multi_exc_f);
assertEquals(34, multi_exc_f(0, 0));
assertEquals(err1, multi_exc_f(0, 11));
assertEquals(err2, multi_exc_f(7, 0));
assertOptimized(multi_exc_f);

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 --turbolev --turbofan
function h(x) {
if (x) { willThrow(); }
else { return 17; }
}
%NeverOptimizeFunction(h);
function f(a, b) {
let r = a;
try {
r = h(a);
return h(b) + r;
} catch {
return r * b;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(34, f(0, 0)); // Won't cause an exception
assertEquals(187, f(0, 11)); // Will cause an exception on the 2nd call to h
assertEquals(0, f(7, 0)); // Will cause an exception on the 1st call to h
%OptimizeFunctionOnNextCall(f);
assertEquals(34, f(0, 0));
assertEquals(187, f(0, 11));
assertEquals(0, f(7, 0));
assertOptimized(f);

View File

@ -0,0 +1,15 @@
// 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 --turbolev --turbofan
function string_char_at(s) {
return s.charAt(2);
}
%PrepareFunctionForOptimization(string_char_at);
assertEquals("c", string_char_at("abcdef"));
%OptimizeFunctionOnNextCall(string_char_at);
assertEquals("c", string_char_at("abcdef"));
assertOptimized(string_char_at);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
// Flags: --no-always-turbofan
function charCodeAt(idx) {
return "abc".charCodeAt(idx);
}
%PrepareFunctionForOptimization(charCodeAt);
assertSame(97, charCodeAt(0.0));
%OptimizeFunctionOnNextCall(charCodeAt);
assertSame(97, charCodeAt(0.0));
assertOptimized(charCodeAt);
// Using max-uint32+1 as index. This should trigger a deopt (and should
// definitely not wrap around and be considered as 0!).
assertSame(NaN, charCodeAt(4294967296));
assertUnoptimized(charCodeAt);

View File

@ -0,0 +1,24 @@
// 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 --turbolev --turbofan
// Flags: --no-always-turbofan
var glob = NaN;
function foo(val) {
glob = val;
}
%PrepareFunctionForOptimization(foo);
foo(NaN);
%OptimizeFunctionOnNextCall(foo);
foo(NaN);
assertEquals(NaN, glob);
assertOptimized(foo);
foo(42);
assertEquals(42, glob);
assertUnoptimized(foo);

View File

@ -0,0 +1,16 @@
// 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 --turbolev --turbofan
var e;
function foo() {
for (let v0 = 0; v0 < 5; v0++) {
%OptimizeOsr();
e = v0 ** v0;
}
}
%PrepareFunctionForOptimization(foo);
foo();

View File

@ -0,0 +1,47 @@
// 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 --turbolev --turbofan
// Flags: --no-always-turbofan --const-tracking-let
let glob_a = 0;
let glob_b = 3.35;
{
function compute_val(v) { return v + 1.15; }
function read() { return glob_a + glob_b; }
function write(v, w) {
glob_a = v;
let f64 = compute_val(w);
glob_b = f64;
}
%PrepareFunctionForOptimization(compute_val);
%PrepareFunctionForOptimization(read);
assertEquals(3.35, read());
%OptimizeFunctionOnNextCall(read);
assertEquals(3.35, read());
assertOptimized(read);
%PrepareFunctionForOptimization(write);
// Write the same value. This won't invalidate the constness.
write(0, 2.2);
glob_b = 3.35;
assertEquals(3.35, read());
%OptimizeFunctionOnNextCall(write);
write(0, 2.2);
assertEquals(3.35, read());
assertOptimized(read);
// Invalidating {glob_a} constness.
write(1, 2.2);
assertUnoptimized(write);
assertEquals(4.35, read());
%OptimizeFunctionOnNextCall(write);
write(1, 2.2);
assertEquals(4.35, read());
assertOptimized(write);
}

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
function foo(t) {
return new t();
}
%PrepareFunctionForOptimization(foo);
a = foo(Array);
a[0] = 3.5;
a = foo(Array);
a[0] = 3.5;
b = foo(Array);
assertTrue(%HasDoubleElements(b));
%OptimizeFunctionOnNextCall(foo);
b = foo(Array);
assertTrue(%HasDoubleElements(b));
assertOptimized(foo);

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
function C(a, b, c, d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
function construct(arr) {
return new C(...arr);
}
%PrepareFunctionForOptimization(construct);
let o1 = construct([17, 3.5, {}]);
%OptimizeFunctionOnNextCall(construct);
assertEquals(o1, construct([17, 3.5, {}]));
assertOptimized(construct);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
// Testing ThrowIfNotSuperConstructor (which triggers because the base class
// of A1 is "null", which doesn't have a constructor).
class A1 extends null {
constructor() {
super();
}
}
%PrepareFunctionForOptimization(A1);
assertThrows(() => new A1(), TypeError,
"Super constructor null of A1 is not a constructor");
%OptimizeFunctionOnNextCall(A1);
assertThrows(() => new A1(), TypeError,
"Super constructor null of A1 is not a constructor");
assertOptimized(A1);

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
// Testing ThrowSuperAlreadyCalledIfNotHole (which triggers because we call
// super() twice).
class A2 extends Object {
constructor() {
super();
super();
}
}
%PrepareFunctionForOptimization(A2);
assertThrows(() => new A2(), ReferenceError,
"Super constructor may only be called once");
%OptimizeFunctionOnNextCall(A2);
assertThrows(() => new A2(), ReferenceError,
"Super constructor may only be called once");
assertOptimized(A2);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
// Testing ThrowSuperNotCalledIfHole (which triggers because we call
// don't call super()).
class A3 extends Object {
constructor() {}
}
%PrepareFunctionForOptimization(A3);
assertThrows(() => new A3(), ReferenceError,
"Must call super constructor in derived class before " +
"accessing 'this' or returning from derived constructor");
%OptimizeFunctionOnNextCall(A3);
assertThrows(() => new A3(), ReferenceError,
"Must call super constructor in derived class before " +
"accessing 'this' or returning from derived constructor");
assertOptimized(A3);

View File

@ -0,0 +1,26 @@
// 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 --turbolev --turbofan
class A extends Object {
constructor(b) {
super();
this.x = b;
this.y = 42;
}
}
class B extends A {
constructor(b) {
super(b);
this.z = 12;
}
}
%PrepareFunctionForOptimization(B);
let o = new B();
%OptimizeFunctionOnNextCall(B);
assertEquals(o, new B());
assertOptimized(B);

View File

@ -0,0 +1,54 @@
// 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 --turbolev --turbofan
var object = { f: function() { return 42; }, x: 42 };
delete object.x;
function call_f_receiver_obj(o) {
return o.f();
}
%PrepareFunctionForOptimization(call_f_receiver_obj);
assertEquals(42, call_f_receiver_obj(object));
%OptimizeFunctionOnNextCall(call_f_receiver_obj);
assertEquals(42, call_f_receiver_obj(object));
assertOptimized(call_f_receiver_obj);
function call_f_receiver_number(o) {
return o.f();
}
Number.prototype.f = function() { return 12 };
%PrepareFunctionForOptimization(call_f_receiver_number);
assertEquals(12, call_f_receiver_number(7));
%OptimizeFunctionOnNextCall(call_f_receiver_number);
assertEquals(12, call_f_receiver_number(7));
assertEquals(12, call_f_receiver_number(4.56));
assertOptimized(call_f_receiver_number);
function f() {
return this.x;
}
function call_f_receiver_undefined(o) {
return f.call(o);
}
%PrepareFunctionForOptimization(call_f_receiver_undefined);
assertEquals(undefined, call_f_receiver_undefined(undefined));
assertEquals(undefined, call_f_receiver_undefined(null));
%OptimizeFunctionOnNextCall(call_f_receiver_undefined);
assertEquals(undefined, call_f_receiver_undefined(undefined));
assertEquals(undefined, call_f_receiver_undefined(null));
assertOptimized(call_f_receiver_undefined);
// Since the global proxy is passed to `f`, changing `x` here should change the
// return value of `f`.
var x = 23;
assertEquals(x, call_f_receiver_undefined(undefined));
assertEquals(x, call_f_receiver_undefined(null));
assertOptimized(call_f_receiver_undefined);

View File

@ -0,0 +1,23 @@
// 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 --turbolev --turbofan
// Generate a function {f} containing a large array literal of doubles.
eval("function create_arr_lit() { return [" + String("0.1,").repeat(65535) + "] }");
%PrepareFunctionForOptimization(create_arr_lit);
// Running the function once will initialize the boilerplate.
assertEquals(65535, create_arr_lit().length);
// Running the function again will perform cloning.
assertEquals(65535, create_arr_lit().length);
let expected = create_arr_lit();
// Running the function as optimized code next.
%OptimizeFunctionOnNextCall(create_arr_lit);
assertEquals(expected, create_arr_lit());
assertOptimized(create_arr_lit);

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function create_closure(v) {
let o = {};
let x = 4;
o.x = (c) => v + x++ + 2 + c;
return o;
}
%PrepareFunctionForOptimization(create_closure);
create_closure(7);
%OptimizeFunctionOnNextCall(create_closure);
let o = create_closure(7);
assertEquals(7+4+2+2, o.x(2));
assertEquals(7+5+2+5, o.x(5));
assertOptimized(create_closure);

View File

@ -0,0 +1,16 @@
// 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 --turbolev --turbofan
function create_obj_lit(v) {
return { 1024 : v } ;
}
%PrepareFunctionForOptimization(create_obj_lit);
assertEquals({ 1024 : 42 }, create_obj_lit(42));
assertEquals({ 1024 : 42 }, create_obj_lit(42));
%OptimizeFunctionOnNextCall(create_obj_lit);
assertEquals({ 1024 : 42 }, create_obj_lit(42));
assertOptimized(create_obj_lit);

View File

@ -0,0 +1,16 @@
// 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 --turbolev --turbofan
function create_regexp_lit() {
return /abc/;
}
%PrepareFunctionForOptimization(create_regexp_lit);
assertEquals(/abc/, create_regexp_lit());
assertEquals(/abc/, create_regexp_lit());
%OptimizeFunctionOnNextCall(create_regexp_lit);
assertEquals(/abc/, create_regexp_lit());
assertOptimized(create_regexp_lit);

View File

@ -0,0 +1,14 @@
// 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 --turbolev --turbofan
eval("function f(b) { return [ " + ",".repeat(4000) + " ...b ] }");
%PrepareFunctionForOptimization(f);
f([1, 2, 3]);
let arr = f([1, 2, 3]);
%OptimizeFunctionOnNextCall(f);
assertEquals(arr, f([1, 2, 3]));
assertOptimized(f);

View File

@ -0,0 +1,19 @@
// 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 --turbolev --turbofan
function g(o) { return o.u; }
function create_shallow_obj(x) {
var o = {u: x};
return g(o);
}
%PrepareFunctionForOptimization(create_shallow_obj);
assertEquals(42, create_shallow_obj(42));
assertEquals(3.56, create_shallow_obj(3.56));
%OptimizeFunctionOnNextCall(create_shallow_obj);
assertEquals(42, create_shallow_obj(42));
assertEquals(3.56, create_shallow_obj(3.56));

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
function dataview() {
const buffer = new ArrayBuffer(40);
const dw = new DataView(buffer);
dw.setInt8(4, 32);
dw.setInt16(2, 152515);
dw.setFloat64(8, 12.2536);
return [dw.getInt16(0), dw.getInt8(4), dw.getFloat64(2), dw.getInt32(7)];
}
%PrepareFunctionForOptimization(dataview);
dataview();
let a1 = dataview();
%OptimizeFunctionOnNextCall(dataview);
let a2 = dataview();
assertEquals(a1, a2);
assertOptimized(dataview);

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function delete_prop_sloppy(o) {
delete o.y;
}
o = { x : 25, y : 42 };
%PrepareFunctionForOptimization(delete_prop_sloppy);
delete_prop_sloppy(o);
assertEquals({x:25}, o);
o.y = 42;
%OptimizeFunctionOnNextCall(delete_prop_sloppy);
delete_prop_sloppy(o);
assertEquals({x:25}, o);
assertOptimized(delete_prop_sloppy);

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
function delete_prop_strict(o) {
'use strict';
delete o.x;
}
let o = { x : 25, y : 42 };
%PrepareFunctionForOptimization(delete_prop_strict);
delete_prop_strict(o);
assertEquals({y:42}, o);
o.x = 25;
%OptimizeFunctionOnNextCall(delete_prop_strict);
delete_prop_strict(o);
assertEquals({y:42}, o);
assertOptimized(delete_prop_strict);

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 --turbolev --turbofan
let n = 5;
n = 2; // Making {n} not constant.
function dematerialized_arguments_length() {
let len = arguments.length;
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {len} will thus have no
// use besides the frame state for this deopt).
n + 5;
return len;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_arguments_length);
n = 5;
assertEquals(7, dematerialized_arguments_length(2, 3));
assertEquals(7, dematerialized_arguments_length(2, 3, 4, 9));
%OptimizeFunctionOnNextCall(dematerialized_arguments_length);
assertEquals(7, dematerialized_arguments_length(2, 3));
n = -1;
assertEquals(4, dematerialized_arguments_length(2, 3, 4, 9));

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 --turbolev --turbofan
let n = 5;
n = 2; // Making {n} not constant.
function dematerialized_arguments() {
let args = arguments;
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {args} will thus have no
// use besides the frame state for this deopt).
n + 5;
return args;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_arguments);
n = 5;
assertEquals(7, dematerialized_arguments(2, 3));
assertEquals(7, dematerialized_arguments(2, 3, 4, 9));
%OptimizeFunctionOnNextCall(dematerialized_arguments);
assertEquals(7, dematerialized_arguments(2, 3));
n = -1;
assertEquals([2, 3, 4, 9], [... dematerialized_arguments(2, 3, 4, 9)]);

View File

@ -0,0 +1,25 @@
// 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 --turbolev --turbofan
function dematerialized_double_array(n) {
let arr = [ 1.1, 2.2, 3.3 ];
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {arr} will thus have no
// use besides the frame state for this deopt).
n + 5;
return arr;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_double_array);
assertEquals(7, dematerialized_double_array(5));
assertEquals(7, dematerialized_double_array(5));
%OptimizeFunctionOnNextCall(dematerialized_double_array);
assertEquals(7, dematerialized_double_array(5));
assertEquals([1.1, 2.2, 3.3], dematerialized_double_array(-1));

View File

@ -0,0 +1,32 @@
// 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 --turbolev --turbofan
function dematerialized_duplicated(n) {
let o1 = { x : 42 };
let o2 = { x : o1, y : o1, z : undefined };
o2.z = o2;
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {o1} and {o2} will thus
// have no use besides the frame state for this deopt).
n + 5;
return [ o1, o2 ];
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_duplicated);
assertEquals(7, dematerialized_duplicated(5));
assertEquals(7, dematerialized_duplicated(5));
%OptimizeFunctionOnNextCall(dematerialized_duplicated);
assertEquals(7, dematerialized_duplicated(5));
let [o1, o2] = dematerialized_duplicated(-1);
assertSame(o1, o2.x);
assertSame(o1, o2.y);
assertSame(o2.x, o2.y);
assertSame(o2, o2.z);

View File

@ -0,0 +1,29 @@
// 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 --turbolev --turbofan
function dematerialized_duplicated(n) {
let o1 = { x : 42 };
let o2 = { x : o1, y : o1 };
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {o2} will thus have no
// use besides the frame state for this deopt).
n + 5;
return o2;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_duplicated);
assertEquals(7, dematerialized_duplicated(5));
assertEquals(7, dematerialized_duplicated(5));
%OptimizeFunctionOnNextCall(dematerialized_duplicated);
assertEquals(7, dematerialized_duplicated(5));
let o = dematerialized_duplicated(-1);
assertSame(o.x, o.y);
assertEquals({ x : { x : 42 }, y : { x : 42 } }, o);

View File

@ -0,0 +1,23 @@
// 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 --turbolev --turbofan
function dematerialized_heap_number(n) {
let f64 = 17.72;
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {f64} will thus have no
// use besides the frame state for this deopt).
return f64 + 5;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_heap_number);
assertEquals(7, dematerialized_heap_number(5));
%OptimizeFunctionOnNextCall(dematerialized_heap_number);
assertEquals(7, dematerialized_heap_number(5));
assertEquals(22.72, dematerialized_heap_number(-1));

View File

@ -0,0 +1,25 @@
// 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 --turbolev --turbofan
// An unconditional deopt will be inserted after {o} has been created, but
// before it is initialized with "arg + 1.5" and "arg + 41.5". These 2 fields
// are thus initialized with the Float64 hole. If {o} is escape-analyzed away,
// then the deopt state will have 2 identical HeapNumbers as input. These
// shouldn't be GVNed, because they are mutable.
function foo(arg) {
var o = {
x: arg + 1.5,
y: arg + 41.5,
};
return o.x + o.y;
}
%PrepareFunctionForOptimization(foo);
assertEquals(NaN, foo());
assertEquals(NaN, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(45, foo(1));

View File

@ -0,0 +1,42 @@
// 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 --turbolev --turbofan
function dematerialized_object(n) {
let o = { x : 42 };
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here.
n + 5;
return o;
}
o.x = 17;
if (n == 1) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here.
n + 5;
return o;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_object);
assertEquals(7, dematerialized_object(5));
assertEquals(7, dematerialized_object(5));
%OptimizeFunctionOnNextCall(dematerialized_object);
assertEquals(7, dematerialized_object(5));
assertEquals({x : 42}, dematerialized_object(-1));
%ClearFunctionFeedback(dematerialized_object);
%PrepareFunctionForOptimization(dematerialized_object);
assertEquals(7, dematerialized_object(5));
assertEquals(7, dematerialized_object(5));
%OptimizeFunctionOnNextCall(dematerialized_object);
assertEquals(7, dematerialized_object(5));
assertEquals({x : 17}, dematerialized_object(1));

View File

@ -0,0 +1,27 @@
// 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 --turbolev --turbofan
function dematerialized_nested_object(n) {
let o = { a : 42, b : { c : 3.75 , d : [ 4 ] } };
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {o} will thus have no use
// besides the frame state for this deopt).
n + 5;
return o;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_nested_object);
assertEquals(7, dematerialized_nested_object(5));
assertEquals(7, dematerialized_nested_object(5));
%OptimizeFunctionOnNextCall(dematerialized_nested_object);
assertEquals(7, dematerialized_nested_object(5));
assertEquals({ a : 42, b : { c : 3.75 , d : [ 4 ] } },
dematerialized_nested_object(-1));

View File

@ -0,0 +1,39 @@
// 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 --turbolev --turbofan
// Flags: --no-always-turbofan
function bar(re) {
let match1 = re.test("123Art");
let match2 = re.test("b123ze");
let match3 = re.test("C");
let nomatch1 = re.test("1234556");
let nomatch2 = re.test("iopdsd4 ,!:^");
return match1 && match2 && match3 && !nomatch1 && !nomatch2;
}
%NeverOptimizeFunction(bar);
function foo(b) {
let re = /[abc]/i;
if (b) {
// We're not collecting feedback for this case. We'll just have an
// unconditional deopt here, and {re} will be escape-analyzed away and will
// flow in the FrameState here. Since RegExp data are in trusted space,
// the FrameState will thus have a trusted object as input.
return bar(re);
}
return 42;
}
%PrepareFunctionForOptimization(foo);
assertEquals(42, foo(false));
assertEquals(42, foo(false));
%OptimizeFunctionOnNextCall(foo);
assertEquals(42, foo(false));
assertOptimized(foo);
// Triggering a deopt, which will materialize the regex object.
assertEquals(true, foo(true));
assertUnoptimized(foo);

View File

@ -0,0 +1,26 @@
// 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 --turbolev --turbofan
function dematerialized_rest(n, ...rest) {
let len = rest.length;
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {len} will thus have no
// use besides the frame state for this deopt).
n + 5;
return len;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_rest);
assertEquals(7, dematerialized_rest(5, 2, 3));
assertEquals(7, dematerialized_rest(5, 2, 3, 4));
%OptimizeFunctionOnNextCall(dematerialized_rest);
assertEquals(7, dematerialized_rest(5, 2, 3));
assertEquals(3, dematerialized_rest(-1, 2, 3, 4));

View File

@ -0,0 +1,25 @@
// 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 --turbolev --turbofan
function dematerialized_rest(n, ...rest) {
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {rest} will thus have
// no use besides the frame state for this deopt).
n + 5;
return rest;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_rest);
assertEquals(7, dematerialized_rest(5, 2, 3));
assertEquals(7, dematerialized_rest(5, 2, 3, 4));
%OptimizeFunctionOnNextCall(dematerialized_rest);
assertEquals(7, dematerialized_rest(5, 2, 3));
assertEquals([2, 3, 4], dematerialized_rest(-1, 2, 3, 4));

View File

@ -0,0 +1,25 @@
// 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 --turbolev --turbofan
function dematerialized_simple_object(n) {
let o = { x : 42, y : n };
if (n < 0) {
// We won't execute this code when collecting feedback, which means that
// Maglev will do an unconditional deopt here (and {o} will thus have no
// use besides the frame state for this deopt).
n + 5;
return o;
}
return n + 2;
}
%PrepareFunctionForOptimization(dematerialized_simple_object);
assertEquals(7, dematerialized_simple_object(5));
assertEquals(7, dematerialized_simple_object(5));
%OptimizeFunctionOnNextCall(dematerialized_simple_object);
assertEquals(7, dematerialized_simple_object(5));
assertEquals({ x : 42, y : -1 }, dematerialized_simple_object(-1));

View File

@ -0,0 +1,33 @@
// 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 --turbolev --turbofan
// Flags: --no-always-turbofan
// Testing deopt with raw floats and raw integers in the frame state.
%NeverOptimizeFunction(sum);
function sum(...args) {
return args.reduce((a,b) => a + b, 0);
}
function f(a, b, c) {
let x = a * 4.25;
let y = b * 17;
// This call to `sum` causes `x` and `y` to be part of the frame state.
let s = sum(a, b);
let z = b + c;
// This call is just to use the values we computed before.
return sum(s, x, y, z);
}
%PrepareFunctionForOptimization(f);
assertEquals(113.39, f(2.36, 5, 6));
assertEquals(113.39, f(2.36, 5, 6));
%OptimizeFunctionOnNextCall(f);
assertEquals(113.39, f(2.36, 5, 6));
assertOptimized(f);
assertEquals(113.93, f(2.36, 5, 6.54));
assertUnoptimized(f);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
function f_eval() {
let i = 0.1;
eval();
if (i) {
const c = {};
eval();
}
}
%PrepareFunctionForOptimization(f_eval);
f_eval();
f_eval();
%OptimizeFunctionOnNextCall(f_eval);
f_eval();
assertOptimized(f_eval);

View File

@ -0,0 +1,38 @@
// 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 --turbolev --turbofan
function g(b) {
if (b) { will_throw(); }
}
%NeverOptimizeFunction(g);
function f(a, b1, b2, b3) {
let s = a;
try {
g(b1);
s += 3;
for (let i = 0; i < 9; i++) {
g(b2);
s += 10;
}
g(b3);
} catch(e) {
return s + 136;
}
return s + 585;
}
%PrepareFunctionForOptimization(f);
assertEquals(141, f(5, true, false, false));
assertEquals(144, f(5, false, true, false,));
assertEquals(234, f(5, false, false, true));
assertEquals(683, f(5, false, false, false));
%OptimizeFunctionOnNextCall(f);
assertEquals(141, f(5, true, false, false));
assertEquals(144, f(5, false, true, false,));
assertEquals(234, f(5, false, false, true));
assertEquals(683, f(5, false, false, false));
assertOptimized(f);

View File

@ -0,0 +1,39 @@
// 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 --turbolev --turbofan
// Flags: --maglev-extend-properties-backing-store
// TODO(dmercadier): this test is exactly the same as
// test/mjsunit/maglev/extend-properties-backing-store-1.js, but with an
// %OptimizeFunctionOnNextCall instead of the %OptimizeMaglevOnNextCall.
// Consider unifying the 2 tests.
const s = new Set();
function foo(o) {
// One of these stores will exhaust the slack and we need to add a property
// backing store.
o.b1 = 0;
o.b2 = 0;
o.b3 = 0;
}
%PrepareFunctionForOptimization(foo);
let o1 = {a: 1}; // One in-object property.
// Make the StoreIC in `foo` polymorphic.
foo(o1);
foo({a: 0, b: 2});
%OptimizeFunctionOnNextCall(foo);
foo({a: 1, b: 3});
let o2 = {a: 1};
s.add(o2); // Force creating the hash.
foo(o2);
// Assert that the hash value was preseved when adding the properties backing
// store.
assertTrue(s.has(o2));

View File

@ -0,0 +1,49 @@
// 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 --turbolev --turbofan
// Flags: --maglev-extend-properties-backing-store
// TODO(dmercadier): this test is exactly the same as
// test/mjsunit/maglev/extend-properties-backing-store-2.js, but with a
// %OptimizeFunctionOnNextCall instead of the %OptimizeMaglevOnNextCall.
// Consider unifying the 2 tests.
function addProperties(o) {
// Add enough properties to exhaust the slack, so that adding the property
// in `foo` will need to grow the property backing store.
o.a1 = 1;
o.a2 = 2;
o.a3 = 3;
o.a4 = 4;
o.a5 = 5;
o.a6 = 6;
o.a7 = 7;
}
const s = new Set();
function foo(o) {
o.b = 2;
}
%PrepareFunctionForOptimization(foo);
let o1 = {};
addProperties(o1);
// Make the StoreIC in `foo` polymorphic.
foo(o1);
foo({a: 0, b: 2});
%OptimizeFunctionOnNextCall(foo);
foo({a: 1, b: 3});
let o2 = {};
addProperties(o2);
s.add(o2); // Force creating the hash.
foo(o2);
// Assert that the hash value was preseved when extending the properties
// backing store.
assertTrue(s.has(o2));

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function fact(n) {
let s = 1;
while (n > 1) {
s *= n;
n--;
}
return s;
}
%PrepareFunctionForOptimization(fact);
let n1 = fact(42);
%OptimizeFunctionOnNextCall(fact);
assertEquals(n1, fact(42));
assertOptimized(fact);

View File

@ -0,0 +1,23 @@
// 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 --turbolev --turbofan
function math_float(x, y) {
let a = x * y;
let b = a + 152.56;
let c = b / x;
let e = c - Math.round(y);
let f = e % 5.56;
let g = f ** x;
let h = -g;
return h;
}
%PrepareFunctionForOptimization(math_float);
math_float(4.21, 3.56);
let expected = math_float(4.21, 3.56);
%OptimizeFunctionOnNextCall(math_float);
assertEquals(expected, math_float(4.21, 3.56));
assertOptimized(math_float);

View File

@ -0,0 +1,99 @@
// 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 --turbolev --turbofan
function cmp_float64(which, a, b) {
if (which == 0) { return a > b; }
if (which == 1) { return a >= b; }
if (which == 2) { return a < b; }
if (which == 3) { return a <= b; }
if (which == 4) { return a == b; }
if (which == 5) { return a != b; }
assertUnreachable();
}
%PrepareFunctionForOptimization(cmp_float64);
// >
assertEquals(false, cmp_float64(0, 10.25, 20.25));
assertEquals(true, cmp_float64(0, 20.25, 10.25));
assertEquals(false, cmp_float64(0, 15.25, 15.25));
assertEquals(false, cmp_float64(0, NaN, 2.35));
assertEquals(false, cmp_float64(0, 2.35, NaN));
assertEquals(false, cmp_float64(0, 2.35, NaN));
// >=
assertEquals(false, cmp_float64(1, 10.25, 20.25));
assertEquals(true, cmp_float64(1, 20.25, 10.25));
assertEquals(true, cmp_float64(1, 15.25, 15.25));
assertEquals(false, cmp_float64(1, NaN, 2.35));
assertEquals(false, cmp_float64(1, 2.35, NaN));
assertEquals(false, cmp_float64(1, 2.35, NaN));
// <
assertEquals(true, cmp_float64(2, 10.25, 20.25));
assertEquals(false, cmp_float64(2, 20.25, 10.25));
assertEquals(false, cmp_float64(2, 15.25, 15.25));
assertEquals(false, cmp_float64(2, NaN, 2.35));
assertEquals(false, cmp_float64(2, 2.35, NaN));
assertEquals(false, cmp_float64(2, 2.35, NaN));
// <=
assertEquals(true, cmp_float64(3, 10.25, 20.25));
assertEquals(false, cmp_float64(3, 20.25, 10.25));
assertEquals(true, cmp_float64(3, 15.25, 15.25));
assertEquals(false, cmp_float64(3, NaN, 2.35));
assertEquals(false, cmp_float64(3, 2.35, NaN));
assertEquals(false, cmp_float64(3, 2.35, NaN));
// ==
assertEquals(true, cmp_float64(4, 10.25, 10.25));
assertEquals(false, cmp_float64(4, 10.25, 15.25));
assertEquals(false, cmp_float64(4, 10.25, NaN));
assertEquals(false, cmp_float64(4, NaN, 15.25));
assertEquals(false, cmp_float64(4, NaN, NaN));
// !=
assertEquals(false, cmp_float64(5, 10.25, 10.25));
assertEquals(true, cmp_float64(5, 10.25, 15.25));
assertEquals(true, cmp_float64(5, 10.25, NaN));
assertEquals(true, cmp_float64(5, NaN, 15.25));
assertEquals(true, cmp_float64(5, NaN, NaN));
%OptimizeFunctionOnNextCall(cmp_float64);
// >
assertEquals(false, cmp_float64(0, 10.25, 20.25));
assertEquals(true, cmp_float64(0, 20.25, 10.25));
assertEquals(false, cmp_float64(0, 15.25, 15.25));
assertEquals(false, cmp_float64(0, NaN, 2.35));
assertEquals(false, cmp_float64(0, 2.35, NaN));
assertEquals(false, cmp_float64(0, 2.35, NaN));
// >=
assertEquals(false, cmp_float64(1, 10.25, 20.25));
assertEquals(true, cmp_float64(1, 20.25, 10.25));
assertEquals(true, cmp_float64(1, 15.25, 15.25));
assertEquals(false, cmp_float64(1, NaN, 2.35));
assertEquals(false, cmp_float64(1, 2.35, NaN));
assertEquals(false, cmp_float64(1, 2.35, NaN));
// <
assertEquals(true, cmp_float64(2, 10.25, 20.25));
assertEquals(false, cmp_float64(2, 20.25, 10.25));
assertEquals(false, cmp_float64(2, 15.25, 15.25));
assertEquals(false, cmp_float64(2, NaN, 2.35));
assertEquals(false, cmp_float64(2, 2.35, NaN));
assertEquals(false, cmp_float64(2, 2.35, NaN));
// <=
assertEquals(true, cmp_float64(3, 10.25, 20.25));
assertEquals(false, cmp_float64(3, 20.25, 10.25));
assertEquals(true, cmp_float64(3, 15.25, 15.25));
assertEquals(false, cmp_float64(3, NaN, 2.35));
assertEquals(false, cmp_float64(3, 2.35, NaN));
assertEquals(false, cmp_float64(3, 2.35, NaN));
// ==
assertEquals(true, cmp_float64(4, 10.25, 10.25));
assertEquals(false, cmp_float64(4, 10.25, 15.25));
assertEquals(false, cmp_float64(4, 10.25, NaN));
assertEquals(false, cmp_float64(4, NaN, 15.25));
assertEquals(false, cmp_float64(4, NaN, NaN));
// !=
assertEquals(false, cmp_float64(5, 10.25, 10.25));
assertEquals(true, cmp_float64(5, 10.25, 15.25));
assertEquals(true, cmp_float64(5, 10.25, NaN));
assertEquals(true, cmp_float64(5, NaN, 15.25));
assertEquals(true, cmp_float64(5, NaN, NaN));

View File

@ -0,0 +1,19 @@
// 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 --turbolev --turbofan
function foo() {
let v1 = 3.45;
for (let i = 0; i < 5; i++) {
const v8 = v1 + 2.25; // Float64 use
v1 = 2.5; // Float64 input for v1's phi
%OptimizeOsr();
}
}
%PrepareFunctionForOptimization(foo);
foo();

View File

@ -0,0 +1,24 @@
// 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 --turbolev --turbofan
function branch_on(a) {
let v = a * 1.35;
if (v) {
return 17;
} else {
return 42;
}
}
%PrepareFunctionForOptimization(branch_on);
assertEquals(17, branch_on(1.5));
assertEquals(42, branch_on(0));
assertEquals(42, branch_on(NaN));
%OptimizeFunctionOnNextCall(branch_on);
assertEquals(17, branch_on(1.5));
assertEquals(42, branch_on(0));
assertEquals(42, branch_on(NaN));
assertOptimized(branch_on);

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function ret_bool(a) {
let v = a * 1.35;
return !v;
}
%PrepareFunctionForOptimization(ret_bool);
assertEquals(false, ret_bool(1.5));
assertEquals(true, ret_bool(0));
assertEquals(true, ret_bool(NaN));
%OptimizeFunctionOnNextCall(ret_bool);
assertEquals(false, ret_bool(1.5));
assertEquals(true, ret_bool(0));
assertEquals(true, ret_bool(NaN));
assertOptimized(ret_bool);

View File

@ -0,0 +1,16 @@
// 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 --turbolev --turbofan
function foo() {
for (var x in this) {}
return x;
};
%PrepareFunctionForOptimization(foo);
let val = foo();
%OptimizeFunctionOnNextCall(foo);
assertEquals(val, foo());
assertOptimized(foo);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
function forin(o) {
let s = 0;
for (let i in o) {
s += o[i];
}
return s;
}
let o = { x : 42, y : 19, z: 5 };
%PrepareFunctionForOptimization(forin);
assertEquals(66, forin(o));
%OptimizeFunctionOnNextCall(forin);
assertEquals(66, forin(o));
assertOptimized(forin);

View File

@ -0,0 +1,19 @@
// 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 --turbolev --turbofan
var arr = [1, 2, 3];
function test_for_in(a, b) {
let s = a + b;
for (x in arr) {}
return s;
}
%PrepareFunctionForOptimization(test_for_in);
assertEquals(3, test_for_in(1, 2));
%OptimizeFunctionOnNextCall(test_for_in);
assertEquals(3, test_for_in(1, 2));
assertOptimized(test_for_in);

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
function f(x, y, z) {
return x + y + z;
}
%NeverOptimizeFunction(f);
function f_forward_args() {
return f.apply(null, arguments);
}
%PrepareFunctionForOptimization(f_forward_args);
assertEquals(24, f_forward_args(12, 5, 7));
assertEquals(24, f_forward_args(12, 5, 7, 19));
%OptimizeFunctionOnNextCall(f_forward_args);
assertEquals(24, f_forward_args(12, 5, 7));
assertEquals(24, f_forward_args(12, 5, 7, 19));
assertOptimized(f_forward_args);

View File

@ -0,0 +1,21 @@
// 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 --turbolev --turbofan
function f(x, y, z) {
return x + y + z;
}
%NeverOptimizeFunction(f);
let arr = [17, 13, 5, 23];
function f_apply(arr) {
return f.apply(null, arr);
}
%PrepareFunctionForOptimization(f_apply);
assertEquals(35, f_apply(arr));
%OptimizeFunctionOnNextCall(f_apply);
assertEquals(35, f_apply(arr));
assertOptimized(f_apply);

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function add3(a, b, c) { return a + b + c; }
function add2(a, b) { return a + b; }
function call_arg(f, a, b, c) {
return f(a, b, c);
}
%PrepareFunctionForOptimization(call_arg);
assertEquals(15, call_arg(add3, 3, 5, 7));
assertEquals(8, call_arg(add2, 3, 5, 7));
%OptimizeFunctionOnNextCall(call_arg);
assertEquals(15, call_arg(add3, 3, 5, 7));
assertEquals(8, call_arg(add2, 3, 5, 7));
assertOptimized(call_arg);

View File

@ -0,0 +1,23 @@
// 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 --turbolev --turbofan
async function foo(x) {
let res = 0;
for (let i = 0; i < x; i++) {
if (i % 2 == 0) {
res += await i;
}
}
return res;
}
%PrepareFunctionForOptimization(foo);
foo(4).then(function(result) {
assertEquals(2, result);
%OptimizeFunctionOnNextCall(foo);
foo(4).then((result) => assertEquals(2, result));
});

View File

@ -0,0 +1,12 @@
// 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 --turbolev --turbofan
async function* foo() {}
%PrepareFunctionForOptimization(foo);
foo();
%OptimizeFunctionOnNextCall(foo);
foo();

View File

@ -0,0 +1,39 @@
// 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 --turbolev --turbofan
function* foo(x) {
yield 5;
yield 7;
if (x) {
yield 9;
}
}
%PrepareFunctionForOptimization(foo);
let gen = foo(true);
assertEquals(5, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(9, gen.next().value);
assertEquals(undefined, gen.next().value);
gen = foo(false);
assertEquals(5, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(undefined, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(true);
assertEquals(5, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(9, gen.next().value);
assertEquals(undefined, gen.next().value);
gen = foo(false);
assertEquals(5, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(undefined, gen.next().value);
assertEquals(undefined, gen.next().value);

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 --turbolev --turbofan
function* foo() {
try {
yield 42;
for (;;) {
if (true) {
} else {
yield;
}
}
} catch(e) {
yield 17;
}
}
%PrepareFunctionForOptimization(foo);
let gen = foo();
assertEquals(42, gen.next().value);
assertEquals(17, gen.throw().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo();
assertEquals(42, gen.next().value);
assertEquals(17, gen.throw().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,28 @@
// 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 --turbolev --turbofan
function* foo(x) {
for (let i = 0; i < x; i++) {
if (i % 2 == 0) {
yield i;
}
}
yield 42;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,37 @@
// 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 --turbolev --turbofan
function* foo(x) {
let s = 625;
for (let i = 0; i < x; i++) {
s -= i;
if (i % 2 == 0) {
yield s;
s -= 21;
} else if (i % 3 == 0) {
yield x ^ 42;
}
s *= i;
}
s &= 42;
yield s;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(4);
assertEquals(625, gen.next().value);
assertEquals(-3, gen.next().value);
assertEquals(46, gen.next().value);
assertEquals(34, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(4);
assertEquals(625, gen.next().value);
assertEquals(-3, gen.next().value);
assertEquals(46, gen.next().value);
assertEquals(34, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,20 @@
// 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 --turbolev --turbofan
function* foo(o) {
o.x; // No feedback for this load --> will be an unconditional deopt in the
// Maglev graph. As a result, the while-loop below won't have a forward
// edge.
let i = 0;
while (true) { yield i++; }
}
let gen = foo({ x : 1 });
for (let i = 0; i < 20000; i++) {
// OSR will eventually kick in.
assertEquals(i, gen.next().value);
}

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 --turbolev --turbofan
// Note that loop phis of resumable loops cannot currently be untagged, because
// they always have a `GeneratorRestoreRegister` input, which prevents
// untagging. Still, this test is meant more as a "future" test: if we can ever
// untag loop phis in resumable loops, then this test will help make sure that
// it works correctly.
function* foo(n) {
let f64 = 3.45;
let i32 = 17;
for (let i = 0; i < n; i++) {
f64 += 4.45;
i32 += 4;
if (i % 2 == 0) {
yield i;
}
}
yield f64;
yield i32;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(21.25, gen.next().value);
assertEquals(33, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(21.25, gen.next().value);
assertEquals(33, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,30 @@
// 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 --turbolev --turbofan
function* foo(x) {
for (let i = 0; i < x; i++) {
yield i;
}
yield 42;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(1, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(3, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(1, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(3, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,50 @@
// 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 --turbolev --turbofan
function* foo(x) {
for (let i = 0; i < x; i++) {
for (let j = 0; j < x; j++) {
for (let k = 0; k < x; k++) {
if (j % 2 == 0) {
yield i*32+j*8+k;
}
}
yield j + 625;
}
yield i + 1459;
}
yield 42;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(2);
assertEquals(0, gen.next().value);
assertEquals(1, gen.next().value);
assertEquals(625, gen.next().value);
assertEquals(626, gen.next().value);
assertEquals(1459, gen.next().value);
assertEquals(32, gen.next().value);
assertEquals(33, gen.next().value);
assertEquals(625, gen.next().value);
assertEquals(626, gen.next().value);
assertEquals(1460, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(2);
assertEquals(0, gen.next().value);
assertEquals(1, gen.next().value);
assertEquals(625, gen.next().value);
assertEquals(626, gen.next().value);
assertEquals(1459, gen.next().value);
assertEquals(32, gen.next().value);
assertEquals(33, gen.next().value);
assertEquals(625, gen.next().value);
assertEquals(626, gen.next().value);
assertEquals(1460, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);

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 --turbolev --turbofan
let glob = 0;
function* foo(x) {
for (let i = 0; i < x; i++) {
try {
yield i * 10;
yield i + 2;
} catch(e) {
} finally {
glob = i;
}
i++;
}
}
%PrepareFunctionForOptimization(foo);
let gen = foo(8);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(20, gen.next().value);
assertEquals(4, gen.next().value);
assertEquals(19, gen.return(19).value);
assertEquals(undefined, gen.next().value);
assertEquals(2, glob);
%OptimizeFunctionOnNextCall(foo);
gen = foo(8);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(20, gen.next().value);
assertEquals(4, gen.next().value);
assertEquals(19, gen.return(19).value);
assertEquals(undefined, gen.next().value);
assertEquals(2, glob);

View File

@ -0,0 +1,34 @@
// 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 --turbolev --turbofan
let glob = 0;
function* foo() {
yield 11;
try {
yield 42;
yield 15;
} catch(e) {
} finally {
glob++;
}
}
%PrepareFunctionForOptimization(foo);
let gen = foo();
assertEquals(11, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(19, gen.return(19).value);
assertEquals(undefined, gen.next().value);
assertEquals(1, glob);
%OptimizeFunctionOnNextCall(foo);
gen = foo();
assertEquals(11, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(19, gen.return(19).value);
assertEquals(undefined, gen.next().value);
assertEquals(2, glob);

View File

@ -0,0 +1,22 @@
// 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 --turbolev --turbofan
function* foo() {
yield 42;
yield 15;
}
%PrepareFunctionForOptimization(foo);
let gen = foo();
assertEquals(42, gen.next().value);
assertEquals(19, gen.return(19).value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo();
assertEquals(42, gen.next().value);
assertEquals(19, gen.return(19).value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,25 @@
// 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 --turbolev --turbofan
function* foo() {
yield 5;
yield 7;
yield 9;
}
%PrepareFunctionForOptimization(foo);
let gen = foo();
assertEquals(5, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(9, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(true);
assertEquals(5, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(9, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,82 @@
// 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 --turbolev --turbofan
function* foo(x) {
let s = 0;
for (let i = 0; i < x + 2; i++) {
s += 2;
try {
yield i + 17;
s += 1;
// The following `yield` looks like it's out of the loop when looking at
// the regular .next() path, because it's predecessor is outside of the
// loop (we always jump on it through a resume), and because it's a
// `yield`, it has no successors.
// However, if we resume with .throw() after the yield,
yield i * 14;
s += 3;
} catch (e) {
i++;
}
s += 4;
if (i < 2) {
yield i - 1;
}
s += 5;
}
yield s;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(2);
assertEquals(17, gen.next().value);
assertEquals(0, gen.throw().value);
assertEquals(19, gen.next().value);
assertEquals(28, gen.next().value);
assertEquals(23, gen.throw().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(2);
assertEquals(17, gen.next().value);
assertEquals(0, gen.throw().value);
assertEquals(19, gen.next().value);
assertEquals(28, gen.next().value);
assertEquals(23, gen.throw().value);
assertEquals(undefined, gen.next().value);
// B1 --> header = <none>
// B2 --> header = <none>
// B3 --> header = <none>
// B4 --> header = <none>
// B5 --> header = <none>
// B6 --> header = <none>
// B7 --> header = <none>
// B8 --> header = <none>
// B9 --> header = <none>
// B10 --> header = <none>
// B11 --> header = <none>
// B12 --> header = <none>
// B13 --> header = <none>
// B14 --> header = <none>
// B15 --> header = <none>
// B16 --> header = <none>
// B17 --> header = <none>
// B18 --> header = <none>
// B19 --> header = B9
// B20 --> header = <none>
// B21 --> header = B9
// B22 --> header = <none>
// B23 --> header = <none>
// B24 --> header = B9
// B25 --> header = B9
// B26 --> header = B9
// B27 --> header = <none>
// B28 --> header = <none>
// B29 --> header = <none>
// B30 --> header = <none>
// B31 --> header = <none>

View File

@ -0,0 +1,34 @@
// 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 --turbolev --turbofan
function* foo(x) {
for (let i = 0; i < x; i++) {
try {
if (i % 2 == 0) {
yield i + 17;
}
} catch (e) {
yield i + 3;
}
}
yield 42;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(4);
assertEquals(17, gen.next().value);
assertEquals(3, gen.throw().value);
assertEquals(19, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(4);
assertEquals(17, gen.next().value);
assertEquals(3, gen.throw().value);
assertEquals(19, gen.next().value);
assertEquals(42, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,42 @@
// 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 --turbolev --turbofan
function* foo(x) {
for (let i = 0; i < x; i++) {
try {
for (let j = 0; j < x; j++) {
if (j % 2 == 0) {
// The .next resume after this yield is inside the inner loop, while
// the .throw goes to the catch, which is in the outer loop.
yield i * 10 + j;
}
}
} catch (e) {
i++;
}
}
yield 42;
}
%PrepareFunctionForOptimization(foo);
let gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(20, gen.throw().value);
assertEquals(22, gen.next().value);
assertEquals(30, gen.next().value);
assertEquals(42, gen.throw().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo(4);
assertEquals(0, gen.next().value);
assertEquals(2, gen.next().value);
assertEquals(20, gen.throw().value);
assertEquals(22, gen.next().value);
assertEquals(30, gen.next().value);
assertEquals(42, gen.throw().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,27 @@
// 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 --turbolev --turbofan
function* foo() {
try {
yield 42;
} catch (e) {
return 14;
}
}
%PrepareFunctionForOptimization(foo);
let gen = foo();
assertEquals(42, gen.next().value);
assertEquals(14, gen.throw().value);
assertEquals(25, gen.return(25).value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(foo);
gen = foo();
assertEquals(42, gen.next().value);
assertEquals(14, gen.throw().value);
assertEquals(25, gen.return(25).value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,32 @@
// 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 --turbolev --turbofan
function* g(x) {
yield x+4;
}
%NeverOptimizeFunction(g);
function* f(x) {
for (let i = 0; i < x; i++) {
yield* g(i);
}
}
%PrepareFunctionForOptimization(f);
let gen = f(4);
assertEquals(4, gen.next().value);
assertEquals(5, gen.next().value);
assertEquals(6, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(f);
gen = f(4);
assertEquals(4, gen.next().value);
assertEquals(5, gen.next().value);
assertEquals(6, gen.next().value);
assertEquals(7, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,36 @@
// 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 --turbolev --turbofan
function* g(x) {
yield x+4;
}
%NeverOptimizeFunction(g);
function* f(x) {
for (let i = 0; i < x; i++) {
if (i % 2 == 0) {
yield* g(i);
} else {
yield i * 13;
}
}
}
%PrepareFunctionForOptimization(f);
let gen = f(4);
assertEquals(4, gen.next().value);
assertEquals(13, gen.next().value);
assertEquals(6, gen.next().value);
assertEquals(39, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(f);
gen = f(4);
assertEquals(4, gen.next().value);
assertEquals(13, gen.next().value);
assertEquals(6, gen.next().value);
assertEquals(39, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,27 @@
// 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 --turbolev --turbofan
function* g(x) {
yield x+4;
}
%NeverOptimizeFunction(g);
function* f(x) {
yield* g(x);
yield* g(5);
}
%PrepareFunctionForOptimization(f);
let gen = f(4);
assertEquals(8, gen.next().value);
assertEquals(9, gen.next().value);
assertEquals(undefined, gen.next().value);
%OptimizeFunctionOnNextCall(f);
gen = f(4);
assertEquals(8, gen.next().value);
assertEquals(9, gen.next().value);
assertEquals(undefined, gen.next().value);

View File

@ -0,0 +1,23 @@
// 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 --turbolev --turbofan
function f(a, b) {
try {
return a + b;
} catch(_) {
return b;
}
}
%PrepareFunctionForOptimization(f);
assertEquals(3n, f(1n, 2n));
%OptimizeFunctionOnNextCall(f);
assertEquals(3n, f(1n, 2n));
assertOptimized(f);
// Triggering exception by mixing int and bigint, which will lazy deopt the
// function, since the catch block had never been used so far.
assertEquals(2n, f(1, 2n));

View File

@ -0,0 +1,55 @@
// 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 --turbolev --turbofan
function f(a, b, c, d) {
let x1 = a + b;
let x2 = a - b;
let x3 = a * b;
let x4 = a / b;
let x5 = a % b;
let x6 = a ** b;
let x7 = a & b;
let x8 = a | b;
let x9 = a ^ b;
let x10 = a << b;
let x11 = a >> b;
let x12 = a >>> b;
let x13 = ~a;
let x14 = -a;
let x15 = a < b;
let x16 = a <= b;
let x17 = a > b;
let x18 = a >= b;
let x19 = a == b;
let x20 = a === b;
// It's important to do the increment/decrement last, because they lead to
// having numeric alternatives for {a} and {b} in Maglev, which leads Maglev
// to compiling subsequent <, <=, >, and >= to Float64 comparisons despite
// their generic feedback.
let x21 = a++;
let x22 = b--;
let x23 = ++c;
let x24 = --d;
return [
x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12,
x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24
];
}
%PrepareFunctionForOptimization(f);
let expected_1 = f(1, 2, 1, 2);
let expected_2 = f("1", 2, "1", 2);
let expected_3 = f(2, "1", 2, "1");
let expected_4 = f([], 1, [], 1);
let expected_5 = f({}, 1, {}, 1);
%OptimizeFunctionOnNextCall(f);
assertEquals(expected_1, f(1, 2, 1, 2));
assertEquals(expected_2, f("1", 2, "1", 2));
assertEquals(expected_3, f(2, "1", 2, "1"));
assertEquals(expected_4, f([], 1, [], 1));
assertEquals(expected_5, f({}, 1, {}, 1));
assertOptimized(f);

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