v8/test/mjsunit/compiler/optimized-array-at.js
Darius M 702f0ff111 [compiler] Inline Array.prototype.at in JSCallReducer
Bug: v8:12865
Change-Id: I539a5b0a9c3c78ef9a767de75b71dd06de337d9a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3647351
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80740}
2022-05-25 10:01:03 +00:00

196 lines
6.2 KiB
JavaScript

// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-inline-array-builtins --turbofan
// Flags: --no-always-turbofan
// Out of bounds
(() => {
const arr = [0, 1, 2.5, 3, {}, 5, "a", 7, 8, { "x": 42 }, 10];
function testArrayAt(a, idx) {
return a.at(idx);
}
%PrepareFunctionForOptimization(testArrayAt);
testArrayAt(arr, 2);
assertEquals(arr[2], testArrayAt(arr, 2));
%OptimizeFunctionOnNextCall(testArrayAt);
testArrayAt(arr, 2);
assertOptimized(testArrayAt);
// Checking out of bounds
assertEquals(undefined, testArrayAt(arr, -20));
assertOptimized(testArrayAt);
assertEquals(undefined, testArrayAt(arr, 20));
assertOptimized(testArrayAt);
})();
// Smi array
(() => {
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function testArrayAt(a, idx) {
return a.at(idx);
}
%PrepareFunctionForOptimization(testArrayAt);
testArrayAt(arr, 2);
assertEquals(arr[2], testArrayAt(arr, 2));
%OptimizeFunctionOnNextCall(testArrayAt);
testArrayAt(arr, 2);
assertOptimized(testArrayAt);
// Positive indices
for (let idx = 0; idx < arr.length; idx++) {
assertEquals(arr[idx], testArrayAt(arr, idx));
assertOptimized(testArrayAt);
}
// Negative indices
for (let idx = 1; idx <= arr.length; idx++) {
assertEquals(arr[arr.length - idx], testArrayAt(arr, -idx));
assertOptimized(testArrayAt);
}
})();
// Double array
(() => {
const arr = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5];
function testArrayAt(a, idx) {
return a.at(idx);
}
%PrepareFunctionForOptimization(testArrayAt);
testArrayAt(arr, 2);
assertEquals(arr[2], testArrayAt(arr, 2));
%OptimizeFunctionOnNextCall(testArrayAt);
testArrayAt(arr, 2);
assertOptimized(testArrayAt);
// Positive indices
for (let idx = 0; idx < arr.length; idx++) {
assertEquals(arr[idx], testArrayAt(arr, idx));
assertOptimized(testArrayAt);
}
// Negative indices
for (let idx = 1; idx <= arr.length; idx++) {
assertEquals(arr[arr.length - idx], testArrayAt(arr, -idx));
assertOptimized(testArrayAt);
}
})();
// Obj array
(() => {
const arr = [0, 1, 2.5, 3, {}, 5, "a", 7, 8, { "x": 42 }, 10];
function testArrayAt(a, idx) {
return a.at(idx);
}
%PrepareFunctionForOptimization(testArrayAt);
testArrayAt(arr, 2);
assertEquals(arr[2], testArrayAt(arr, 2));
%OptimizeFunctionOnNextCall(testArrayAt);
testArrayAt(arr, 2);
assertOptimized(testArrayAt);
// Positive indices
for (let idx = 0; idx < arr.length; idx++) {
assertEquals(arr[idx], testArrayAt(arr, idx));
assertOptimized(testArrayAt);
}
// Negative indices
for (let idx = 1; idx <= arr.length; idx++) {
assertEquals(arr[arr.length - idx], testArrayAt(arr, -idx));
assertOptimized(testArrayAt);
}
})();
// Smi/Double/Obj arrays. This test ensure that:
// - When different kinds are present in the feedback, they all get properly
// optimized: |smis|, |doubles| and |objects| will produce 3 different
// branches in the inlined code.
//
// - The "needs_fallback_builtin_call" mechanism works as intended: while the
// |smis|, |doubles| and |objects| cases will be inlined, |dict| should
// produce a call to the builtin (without deoptimizing).
(() => {
const smis = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const doubles = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5];
const objects = [0, 1, 2.5, 3, {}, 5, "a", 7, 8, { "x": 42 }, 10];
const dict = new Array();
dict[2] = 42;
dict[10000] = 5;
assertEquals(smis.length, doubles.length);
assertEquals(smis.length, objects.length);
function testArrayAt(a, idx) {
return a.at(idx);
}
%PrepareFunctionForOptimization(testArrayAt);
testArrayAt(smis, 2);
testArrayAt(doubles, 2);
testArrayAt(objects, 2);
testArrayAt(dict, 2);
assertEquals(doubles[2], testArrayAt(doubles, 2));
assertEquals(objects[2], testArrayAt(objects, 2));
assertEquals(dict[2], testArrayAt(dict, 2));
assertEquals(smis[2], testArrayAt(smis, 2));
%OptimizeFunctionOnNextCall(testArrayAt);
testArrayAt(smis, 2);
assertOptimized(testArrayAt);
testArrayAt(doubles, 2);
assertOptimized(testArrayAt);
testArrayAt(objects, 2);
assertOptimized(testArrayAt);
testArrayAt(dict, 2);
assertOptimized(testArrayAt);
// Positive indices
for (let idx = 0; idx < smis.length; idx++) {
assertEquals(smis[idx], testArrayAt(smis, idx));
assertOptimized(testArrayAt);
assertEquals(doubles[idx], testArrayAt(doubles, idx));
assertOptimized(testArrayAt);
assertEquals(objects[idx], testArrayAt(objects, idx));
assertOptimized(testArrayAt);
assertEquals(dict[idx], testArrayAt(dict, idx));
assertOptimized(testArrayAt);
}
// Negative indices
for (let idx = 1; idx <= smis.length; idx++) {
assertEquals(smis[smis.length - idx], testArrayAt(smis, -idx));
assertOptimized(testArrayAt);
assertEquals(doubles[doubles.length - idx], testArrayAt(doubles, -idx));
assertOptimized(testArrayAt);
assertEquals(objects[objects.length - idx], testArrayAt(objects, -idx));
assertOptimized(testArrayAt);
assertEquals(dict[dict.length - idx], testArrayAt(dict, -idx));
assertOptimized(testArrayAt);
}
})();
// Checks that accessing holes in double arrays leads to deoptimization.
(() => {
let doubles = Array();
doubles[10] = 4.5;
function testArrayAt(idx) {
return doubles.at(idx);
}
%PrepareFunctionForOptimization(testArrayAt);
testArrayAt(10);
%OptimizeFunctionOnNextCall(testArrayAt);
testArrayAt(10);
assertOptimized(testArrayAt);
assertEquals(doubles[10], testArrayAt(10));
assertOptimized(testArrayAt);
assertEquals(doubles[2], testArrayAt(2));
assertUnoptimized(testArrayAt);
})();
// Checks that accessing holes in SMI array does not lead to deoptimization.
(() => {
let smis = Array();
smis[10] = 4;
function testArrayAt(idx) {
return smis.at(idx);
}
%PrepareFunctionForOptimization(testArrayAt);
testArrayAt(10);
%OptimizeFunctionOnNextCall(testArrayAt);
testArrayAt(10);
assertOptimized(testArrayAt);
assertEquals(smis[10], testArrayAt(10));
assertOptimized(testArrayAt);
assertEquals(smis[2], testArrayAt(2));
assertOptimized(testArrayAt);
})();