node/deps/v8/test/mjsunit/undefined-double.js
Michaël Zasso c2843b722c
deps: update V8 to 14.2.231.9
PR-URL: https://github.com/nodejs/node/pull/60111
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2025-10-23 07:36:34 +02:00

249 lines
5.8 KiB
JavaScript

// Copyright 2025 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbofan
const kUndefinedPattern = 0xFFF6FFFF;
function CreateBuffer(i32pattern) {
let buffer = new ArrayBuffer(16);
let i32 = new Int32Array(buffer);
for(let i = 0; i < 4; ++i) {
i32[i] = i32pattern;
}
return buffer;
}
function assertHasHoleyDoubles(a) {
// If undefined doubles are disabled, this is ignored.
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(a));
assertTrue(%HasHoleyElements(a));
}
}
%NeverOptimizeFunction(CreateBuffer);
%NeverOptimizeFunction(assertHasHoleyDoubles);
(function LoadUndefinedPatternFromTypedArray() {
function foo(f64) {
return f64[0];
}
let f64 = new Float64Array(CreateBuffer(kUndefinedPattern));
let x = foo(f64);
assertNotEquals(undefined, x);
assertTrue(Number.isNaN(x));
})();
(function HasOwnPropertyWithUndefined() {
function foo(a, i) {
return a.hasOwnProperty(i);
}
let arr = new Array();
arr[3] = 3.14;
arr[1] = undefined;
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(arr));
}
assertFalse(foo(arr, 0));
assertTrue(foo(arr, 1));
assertFalse(foo(arr, 2));
assertTrue(foo(arr, 3));
})();
(function LoadUndefinedFromArray() {
function foo(a, i) {
return a[i];
}
let arr = new Array();
arr[3] = 3.14;
arr[1] = undefined;
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(arr));
}
assertEquals(undefined, foo(arr, 0));
assertEquals(undefined, foo(arr, 1));
assertEquals(undefined, foo(arr, 2));
assertEquals(3.14, foo(arr, 3));
})();
(function StoreMaybeSilencedValue() {
function foo(cond, a, f64) {
let result = new Array(...[3.14, , 9.88]);
// This is an interesting case because the store must silence the undefined
// pattern loaded from f64[0], but preserve the one from a[0].
result[0] = cond ? a[0] : f64[0];
return result;
}
// Interpreted
{
%PrepareFunctionForOptimization(foo);
const arr = new Array();
arr[0] = undefined;
const f64 = new Float64Array(CreateBuffer(kUndefinedPattern));
assertEquals(undefined, foo(true, arr, f64)[0]);
const r = foo(false, arr, f64);
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(r));
}
assertNotEquals(undefined, r[0]);
assertTrue(Number.isNaN(r[0]));
}
// TF-compiled
{
%OptimizeFunctionOnNextCall(foo);
const arr = new Array();
arr[0] = undefined;
const f64 = new Float64Array(CreateBuffer(kUndefinedPattern));
let r = foo(false, arr, f64);
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(r));
}
assertNotEquals(undefined, r[0]);
assertTrue(Number.isNaN(r[0]));
assertEquals(undefined, foo(true, arr, f64)[0]);
r = foo(false, arr, f64);
assertNotEquals(undefined, r[0]);
assertTrue(Number.isNaN(r[0]));
}
})();
(function StoreToArrayWithProto() {
function foo(a) {
a[3] = undefined;
}
let arr_base = new Array(0, 1, 2, 3, 4, 5);
let arr = new Array();
arr.__proto__ = arr_base;
arr[7] = 7.7;
foo(arr);
if(%IsUndefinedDoubleEnabled()) {
%HasDoubleElements(arr);
}
assertEquals(3, arr_base[3]);
assertEquals(undefined, arr[3]);
assertEquals(undefined, arr[6]);
assertEquals(7.7, arr[7]);
})();
const largeHoleyArray = new Array(1e4);
for (var i = 0; i < 10; i++) {
largeHoleyArray[i] = i;
}
for (var i = 50; i < 55; i++) {
largeHoleyArray[i] = i;
}
(function LoadFromHoleySmiArray() {
function foo() {
var newArr = [];
for (let i = 0; i < largeHoleyArray.length; ++i) {
newArr[i] = largeHoleyArray[i];
}
return newArr;
}
%PrepareFunctionForOptimization(foo);
let r = foo();
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(r));
}
assertEquals(52, r[52]);
assertEquals(undefined, r[42]);
%OptimizeFunctionOnNextCall(foo);
r = foo();
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(r));
}
assertEquals(52, r[52]);
assertEquals(undefined, r[42]);
})();
(function ArrayConcatSlowPath() {
function foo() {
var a = [1, 2, 3];
a.foo = "hello world";
var b = Array(4096).fill(1.1);
b[4098] = 1.2;
b[4096] = undefined;
b[4097] = undefined;
return a.concat(b);
}
const r = foo();
assertEquals(1, r[0]);
assertEquals(2, r[1]);
assertEquals(3, r[2]);
assertEquals(1.1, r[3]);
assertEquals(1.1, r[4098]);
assertEquals(undefined, r[4099]);
assertEquals(undefined, r[4100]);
assertEquals(1.2, r[4101]);
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(r));
}
})();
(function ArrayPrototypeWith() {
function foo() {
let a = [-2.2,,4.4];
let b = a.with(1);
Math.min(b);
return b;
}
%PrepareFunctionForOptimization(foo);
let r = foo();
assertArrayEquals([-2.2, undefined, 4.4], r);
if(%IsUndefinedDoubleEnabled()) {
assertTrue(%HasDoubleElements(r));
assertTrue(%HasHoleyElements(r));
}
for(let i = 0; i < 5; ++i) {
%OptimizeFunctionOnNextCall(foo);
r = foo();
assertArrayEquals([-2.2, undefined, 4.4], r);
assertHasHoleyDoubles(r);
if(i > 0) assertOptimized(foo);
}
})();
(function ArrayPrototypeFilter() {
function p(x) { return x === undefined || x > 100; }
function foo() {
const a = [3.2, 105.3, undefined, 2.4, undefined];
return a.filter(p);
}
%PrepareFunctionForOptimization(p);
%PrepareFunctionForOptimization(foo);
foo();
let r = foo();
assertArrayEquals([105.3, undefined, undefined], r);
assertHasHoleyDoubles(r);
%OptimizeFunctionOnNextCall(foo);
r = foo();
assertArrayEquals([105.3, undefined, undefined], r);
assertHasHoleyDoubles(r);
assertOptimized(foo);
})();