mirror of
https://github.com/nodejs/node.git
synced 2025-05-15 08:02:06 +00:00

PR-URL: https://github.com/nodejs/node/pull/54077 Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
162 lines
7.2 KiB
JavaScript
162 lines
7.2 KiB
JavaScript
// Copyright 2023 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --experimental-wasm-stringref --allow-natives-syntax
|
|
// Flags: --experimental-wasm-imported-strings
|
|
// Flags: --trace-wasm-inlining --liftoff
|
|
// Also explicitly enable inlining and disable debug code to avoid differences
|
|
// between --future and --no-future or debug and release builds.
|
|
// Flags: --experimental-wasm-inlining --no-debug-code
|
|
// Also explicitly set Turboshaft, since its trace output is different from
|
|
// TurboFan.
|
|
// Flags: --turboshaft-wasm
|
|
|
|
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
|
|
|
// Tests the basic mechanism: imports can be recognized, optimized code will
|
|
// be discarded when the same module is instantiated with other imports.
|
|
(function TestBasics() {
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_w_w = makeSig([kWasmStringRef], [kWasmStringRef]);
|
|
let toLowerCase = builder.addImport("m", "toLowerCase", sig_w_w);
|
|
|
|
builder.addFunction('call_tolower', sig_w_w).exportFunc().addBody([
|
|
kExprLocalGet, 0,
|
|
kExprCallFunction, toLowerCase,
|
|
]);
|
|
|
|
let module = builder.toModule();
|
|
|
|
let recognizable = Function.prototype.call.bind(String.prototype.toLowerCase);
|
|
let recognizable_imports = { m: { toLowerCase: recognizable } };
|
|
|
|
let instance1 = new WebAssembly.Instance(module, recognizable_imports);
|
|
let call_tolower = instance1.exports.call_tolower;
|
|
call_tolower("ABC");
|
|
%WasmTierUpFunction(call_tolower);
|
|
call_tolower("ABC");
|
|
|
|
// Creating a second instance with identical imports should not cause
|
|
// recompilation.
|
|
console.log("Second instance.");
|
|
let instance2 = new WebAssembly.Instance(module, recognizable_imports);
|
|
let call_tolower2 = instance2.exports.call_tolower;
|
|
call_tolower2("DEF");
|
|
console.log("Still optimized: " + %IsTurboFanFunction(call_tolower2));
|
|
|
|
// Creating a third instance with different imports must not reuse the
|
|
// existing optimized code.
|
|
console.log("Third instance.");
|
|
let other_imports = { m: { toLowerCase: () => "foo" } };
|
|
let instance3 = new WebAssembly.Instance(module, other_imports);
|
|
let call_tolower3 = instance3.exports.call_tolower;
|
|
call_tolower3("GHI");
|
|
console.log("Still optimized: " + %IsTurboFanFunction(call_tolower3));
|
|
})();
|
|
|
|
// Tests that the builtins we aim to recognize actually are recognized.
|
|
(function TestRecognizedBuiltins() {
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_d_w = makeSig([kWasmStringRef], [kWasmF64]);
|
|
let sig_i_wwi =
|
|
makeSig([kWasmStringRef, kWasmStringRef, kWasmI32], [kWasmI32]);
|
|
let sig_w_d = makeSig([kWasmF64], [kWasmStringRef]);
|
|
let sig_w_ii = makeSig([kWasmI32, kWasmI32], [kWasmStringRef]);
|
|
let sig_w_ww = makeSig([kWasmStringRef, kWasmStringRef], [kWasmStringRef]);
|
|
let nn_string = wasmRefType(kWasmStringRef);
|
|
let sig_w_ww_nonnullable = makeSig([nn_string, nn_string], [nn_string]);
|
|
builder.addImport("m", "intToString", sig_w_ii);
|
|
builder.addImport("m", "doubleToString", sig_w_d);
|
|
builder.addImport("m", "parseFloat", sig_d_w);
|
|
builder.addImport("m", "indexOf", sig_i_wwi);
|
|
builder.addImport("m", "toLocaleLowerCase", sig_w_ww);
|
|
builder.addImport("m", "toLocaleLowerCase_nn", sig_w_ww_nonnullable);
|
|
let indexOf = Function.prototype.call.bind(String.prototype.indexOf);
|
|
let intToString = Function.prototype.call.bind(Number.prototype.toString);
|
|
let doubleToString = intToString;
|
|
let toLocaleLowerCase =
|
|
Function.prototype.call.bind(String.prototype.toLocaleLowerCase);
|
|
builder.instantiate({
|
|
m: {
|
|
intToString,
|
|
doubleToString,
|
|
parseFloat,
|
|
indexOf,
|
|
toLocaleLowerCase,
|
|
toLocaleLowerCase_nn: toLocaleLowerCase,
|
|
}
|
|
});
|
|
})();
|
|
|
|
// Tests imported strings.
|
|
(function TestImportedStrings() {
|
|
console.log("Testing imported strings");
|
|
// We use "r" for nullable "externref", and "e" for non-nullable "ref extern".
|
|
let kRefExtern = wasmRefType(kWasmExternRef);
|
|
let kSig_e_ii = makeSig([kWasmI32, kWasmI32], [kRefExtern]);
|
|
let kSig_e_d = makeSig([kWasmF64], [kRefExtern]);
|
|
let kSig_i_ri = makeSig([kWasmExternRef, kWasmI32], [kWasmI32]);
|
|
let kSig_i_rr = makeSig([kWasmExternRef, kWasmExternRef], [kWasmI32]);
|
|
let kSig_i_rri =
|
|
makeSig([kWasmExternRef, kWasmExternRef, kWasmI32], [kWasmI32]);
|
|
let kSig_e_r = makeSig([kWasmExternRef], [kRefExtern]);
|
|
let kSig_e_i = makeSig([kWasmI32], [kRefExtern]);
|
|
let kSig_e_rii = makeSig([kWasmExternRef, kWasmI32, kWasmI32],
|
|
[kRefExtern]);
|
|
let kSig_e_rr = makeSig([kWasmExternRef, kWasmExternRef], [kRefExtern]);
|
|
|
|
let builder = new WasmModuleBuilder();
|
|
builder.startRecGroup();
|
|
let kArrayI16 = builder.addArray(kWasmI16, true, kNoSuperType, true);
|
|
builder.endRecGroup();
|
|
builder.startRecGroup();
|
|
let kArrayI8 = builder.addArray(kWasmI8, true, kNoSuperType, true);
|
|
builder.endRecGroup();
|
|
let a16ref = wasmRefNullType(kArrayI16);
|
|
let a8ref = wasmRefNullType(kArrayI8);
|
|
|
|
builder.addImport('wasm:js-string', 'cast', kSig_e_r);
|
|
builder.addImport('wasm:js-string', 'test', kSig_i_r);
|
|
builder.addImport('wasm:js-string', 'fromCharCodeArray',
|
|
makeSig([a16ref, kWasmI32, kWasmI32], [kRefExtern]));
|
|
builder.addImport('wasm:text-decoder', 'decodeStringFromUTF8Array',
|
|
makeSig([a8ref, kWasmI32, kWasmI32], [kRefExtern]));
|
|
builder.addImport('wasm:js-string', 'intoCharCodeArray',
|
|
makeSig([kWasmExternRef, a16ref, kWasmI32], [kWasmI32]));
|
|
builder.addImport('wasm:js-string', 'fromCharCode', kSig_e_i);
|
|
builder.addImport('wasm:js-string', 'fromCodePoint', kSig_e_i);
|
|
builder.addImport('wasm:js-string', 'charCodeAt', kSig_i_ri);
|
|
builder.addImport('wasm:js-string', 'codePointAt', kSig_i_ri);
|
|
builder.addImport('wasm:js-string', 'length', kSig_i_r);
|
|
builder.addImport('wasm:js-string', 'concat', kSig_e_rr);
|
|
builder.addImport('wasm:js-string', 'substring', kSig_e_rii);
|
|
builder.addImport('wasm:js-string', 'equals', kSig_i_rr);
|
|
builder.addImport('wasm:js-string', 'compare', kSig_i_rr);
|
|
|
|
builder.addImport('wasm:text-encoder', 'measureStringAsUTF8', kSig_i_r);
|
|
builder.addImport('wasm:text-encoder', 'encodeStringIntoUTF8Array',
|
|
makeSig([kWasmExternRef, a8ref, kWasmI32], [kWasmI32]));
|
|
builder.addImport('wasm:text-encoder', 'encodeStringToUTF8Array',
|
|
makeSig([kWasmExternRef], [wasmRefType(kArrayI8)]));
|
|
|
|
builder.addImport('related', 'intToString', kSig_e_ii);
|
|
builder.addImport('related', 'doubleToString', kSig_e_d);
|
|
builder.addImport('related', 'stringIndexOf', kSig_i_rri);
|
|
builder.addImport('related', 'stringToLowerCase', kSig_r_r);
|
|
|
|
// String-consuming imports like "toLowerCase" are not (yet?) supported for
|
|
// special-casing with imported strings due to lack of static typing.
|
|
let intToString = Function.prototype.call.bind(Number.prototype.toString);
|
|
let doubleToString = intToString;
|
|
let stringIndexOf = Function.prototype.call.bind(String.prototype.indexOf);
|
|
let stringToLowerCase =
|
|
Function.prototype.call.bind(String.prototype.toLowerCase);
|
|
|
|
builder.instantiate({
|
|
related: {intToString, doubleToString, stringIndexOf, stringToLowerCase},
|
|
}, {
|
|
builtins: ['js-string', 'text-decoder', 'text-encoder'],
|
|
});
|
|
})();
|