nodejs/deps/v8/test/mjsunit/wasm/growable-stacks.js
Michaël Zasso 918fe04351
deps: update V8 to 13.6.233.8
PR-URL: https://github.com/nodejs/node/pull/58070
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
2025-05-02 15:06:53 +02:00

251 lines
6.9 KiB
JavaScript

// 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 --experimental-wasm-growable-stacks
// Flags: --expose-gc --wasm-stack-switching-stack-size=4
// Flags: --wasm-staging --stack-size=400
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
function flatRange(upperBound, gen) {
const res = [];
for (let i = 0; i < upperBound; i++) {
res.push(gen(i));
}
return res.flat();
}
function growAndShrinkTwice(depth, paramType, constFn, addOp, result, heavy = false) {
const builder = new WasmModuleBuilder();
builder.addGlobal(kWasmI32, true).exportAs('depth');
const numIntArgs = 10;
const numTypes = Array(numIntArgs).fill(paramType);
var sig = makeSig(numTypes, numTypes);
builder.addImport('m', 'import', sig);
let sig_if = builder.addType(makeSig([], numTypes));
let deep_calc = builder.addFunction("deep_calc", sig);
deep_calc
.addLocals(kWasmI64, heavy ? 512 : 0) // make a frame bigger than 4kb
.addBody([
// decrement global
kExprGlobalGet, 0,
kExprI32Const, 1,
kExprI32Sub,
kExprGlobalSet, 0,
// should we recurse deeper?
kExprGlobalGet, 0,
kExprIf, sig_if,
// then
kExprLocalGet, 9,
...constFn(1),
addOp,
...flatRange(numIntArgs - 1, i => [kExprLocalGet, i]),
kExprCallFunction, deep_calc.index,
// else
kExprElse,
...flatRange(numIntArgs, i => [kExprLocalGet, i]),
kExprCallFunction, 0,
kExprEnd
])
builder.addFunction("test", makeSig([], numTypes))
.addBody([
// do stack expensive job
...flatRange(numIntArgs, constFn),
kExprCallFunction, deep_calc.index,
...flatRange(numIntArgs, () => kExprDrop),
// Reset the recursion budget.
...wasmI32Const(depth),
kExprGlobalSet, 0,
// do more stack expensive job
// to check limits was updated properly on shrink
...flatRange(numIntArgs, constFn),
kExprCallFunction, deep_calc.index,
]).exportFunc();
const js_import = new WebAssembly.Suspending((...args) => {
return Promise.resolve(args)
})
const instance = builder.instantiate({ m: { import: js_import } });
const wrapper = WebAssembly.promising(instance.exports.test);
instance.exports.depth.value = depth;
assertPromiseResult(
wrapper(),
r => result.forEach((v, i) => assertEquals(r[i], v))
);
}
(function TestStackGrowI32() {
print(arguments.callee.name);
growAndShrinkTwice(
430,
kWasmI32,
wasmI32Const,
kExprI32Add,
[44, 45, 46, 47, 48, 49, 50, 51, 52, 42]
);
})();
(function TestStackGrowI64() {
print(arguments.callee.name);
growAndShrinkTwice(
430,
kWasmI64,
wasmI64Const,
kExprI64Add,
[44n, 45n, 46n, 47n, 48n, 49n, 50n, 51n, 52n, 42n]
);
})();
(function TestStackGrowF32() {
print(arguments.callee.name);
growAndShrinkTwice(
430,
kWasmF32,
wasmF32Const,
kExprF32Add,
[44, 45, 46, 47, 48, 49, 50, 51, 52, 42]
);
})();
(function TestStackGrowF64() {
print(arguments.callee.name);
growAndShrinkTwice(
430,
kWasmF64,
wasmF64Const,
kExprF64Add,
[44, 45, 46, 47, 48, 49, 50, 51, 52, 42]
);
})();
(function TestStackGrowHeavyFrameI32() {
print(arguments.callee.name);
growAndShrinkTwice(
20,
kWasmI32,
wasmI32Const,
kExprI32Add,
[3, 4, 5, 6, 7, 8, 9, 10, 11, 1],
true
);
})();
(function TestStackGrowHeavyFrameI64() {
print(arguments.callee.name);
growAndShrinkTwice(
20,
kWasmI64,
wasmI64Const,
kExprI64Add,
[3n, 4n, 5n, 6n, 7n, 8n, 9n, 10n, 11n, 1n],
true
);
})();
(function TestStackGrowHeavyFrameF32() {
print(arguments.callee.name);
growAndShrinkTwice(
20,
kWasmF32,
wasmF32Const,
kExprF32Add,
[3, 4, 5, 6, 7, 8, 9, 10, 11, 1],
true
);
})();
(function TestStackGrowHeavyFrameF64() {
print(arguments.callee.name);
growAndShrinkTwice(
20,
kWasmF64,
wasmF64Const,
kExprF64Add,
[3, 4, 5, 6, 7, 8, 9, 10, 11, 1],
true
);
})();
(function TestStackGrowWithGCAndRefParams() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
const call_stack_depth = 430;
builder.addGlobal(kWasmI32, true).exportAs('depth');
const numRefArgs = 10;
const refTypes = Array(numRefArgs).fill(kWasmExternRef);
var sig = makeSig(refTypes, refTypes);
const imp = builder.addImport('m', 'import', sig);
let sig_if = builder.addType(makeSig([], refTypes));
let deep_calc = builder.addFunction("deep_calc", sig);
deep_calc.addBody([
// decrement global
kExprGlobalGet, 0,
kExprI32Const, 1,
kExprI32Sub,
kExprGlobalSet, 0,
// should we recurse deeper?
kExprGlobalGet, 0,
kExprIf, sig_if,
// then
...flatRange(numRefArgs, i => [kExprLocalGet, i]),
kExprCallFunction, deep_calc.index,
// else
kExprElse,
...flatRange(numRefArgs, i => [kExprLocalGet, i]),
kExprCallFunction, imp,
kExprEnd
]);
builder.addFunction("test", makeSig([kWasmExternRef], refTypes))
.addBody([
// do stack expensive job
...flatRange(numRefArgs, () => [kExprLocalGet, 0]),
kExprCallFunction, deep_calc.index,
...flatRange(numRefArgs, () => kExprDrop),
// Reset the recursion budget.
...wasmI32Const(call_stack_depth),
kExprGlobalSet, 0,
// do more stack expensive job
// to check limits was updated properly on shrink
...flatRange(numRefArgs, () => [kExprLocalGet, 0]),
kExprCallFunction, deep_calc.index,
]).exportFunc();
const js_import = new WebAssembly.Suspending((...args) => {
gc();
return Promise.resolve(args)
});
const instance = builder.instantiate({ m: { import: js_import } });
const wrapper = WebAssembly.promising(instance.exports.test);
instance.exports.depth.value = call_stack_depth;
const ref = {};
assertPromiseResult(
wrapper(ref),
res => res.forEach(r => assertEquals(r, ref))
);
})();
(function TestStackOverflow() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("test", kSig_i_v)
.addBody([
kExprCallFunction, 0
]).exportFunc();
let instance = builder.instantiate();
let wrapper = WebAssembly.promising(instance.exports.test);
assertThrowsAsync(wrapper(), RangeError, /Maximum call stack size exceeded/);
})();
(function TestStackOverflowWithHeavyFrames() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("test", kSig_i_r)
.addLocals(kWasmI64, 512) // make a frame bigger than 4kb
.addBody([
kExprLocalGet, 0,
kExprCallFunction, 0
]).exportFunc();
let instance = builder.instantiate();
let wrapper = WebAssembly.promising(instance.exports.test);
assertThrowsAsync(wrapper(), RangeError, /Maximum call stack size exceeded/);
})();