node/deps/v8/test/message/wasm-recognize-imports.js
Michaël Zasso 9d7cd9b864
deps: update V8 to 12.8.374.13
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>
2024-08-16 16:03:01 +02:00

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'],
});
})();