v8/test/mjsunit/wasm/call-ref.js
Manos Koukoutos 2f852102d9 [wasm-gc] Final types
We add final types to wasm-gc.
- We introduce a `kWasmSubtypeFinalCode` as an alternative to
  `kWasmSubtypeCode`.
- Behind a flag, we interpret types behind this code as final, as well
  as types outside a subtype definition by default.
- For final types, type checks for call_indirect and ref.test etc. are
  reduced to simple type identity checks.

Bug: v8:7748
Change-Id: Iabf147b2a15f43abc4c7d1c582f460dbdc645d66
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4096478
Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84955}
2022-12-20 14:03:30 +00:00

217 lines
7.6 KiB
JavaScript

// Copyright 2020 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-type-reflection --experimental-wasm-gc
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
(function TestImportedRefCall() {
print(arguments.callee.name);
var exporting_instance = (function () {
var builder = new WasmModuleBuilder();
builder.addFunction("addition", kSig_i_ii)
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Add])
.exportFunc();
return builder.instantiate({});
})();
var instance = (function () {
var builder = new WasmModuleBuilder();
var sig_index = builder.addType(kSig_i_ii);
var imported_js_api_function_index =
builder.addImport("imports", "js_api_mul", sig_index);
var imported_js_function_index =
builder.addImport("imports", "js_add", sig_index);
var imported_wasm_function_index =
builder.addImport("imports", "wasm_add", sig_index);
var locally_defined_function =
builder.addFunction("sub", sig_index)
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Sub])
.exportFunc();
builder.addFunction("main", makeSig(
[wasmRefType(sig_index), kWasmI32, kWasmI32], [kWasmI32]))
.addBody([kExprLocalGet, 1, kExprLocalGet, 2, kExprLocalGet, 0,
kExprCallRef, sig_index])
.exportFunc();
builder.addFunction("test_local", kSig_i_v)
.addBody([kExprI32Const, 55, kExprI32Const, 42,
kExprRefFunc, locally_defined_function.index,
kExprCallRef, sig_index])
.exportFunc();
builder.addFunction("test_js_import", kSig_i_v)
.addBody([kExprI32Const, 15, kExprI32Const, 42,
kExprRefFunc, imported_js_function_index,
kExprCallRef, sig_index])
.exportFunc();
builder.addFunction("test_wasm_import", kSig_i_v)
.addBody([kExprI32Const, 15, kExprI32Const, 42,
kExprRefFunc, imported_wasm_function_index,
kExprCallRef, sig_index])
.exportFunc();
builder.addFunction("test_js_api_import", kSig_i_v)
.addBody([kExprI32Const, 3, kExprI32Const, 7,
kExprRefFunc, imported_js_api_function_index,
kExprCallRef, sig_index])
.exportFunc();
builder.addExport("reexported_js_function", imported_js_function_index);
// Just to make these functions eligible for call_ref.
builder.addDeclarativeElementSegment([imported_wasm_function_index,
imported_js_api_function_index]);
return builder.instantiate({imports: {
js_add: function(a, b) { return a + b; },
wasm_add: exporting_instance.exports.addition,
js_api_mul: new WebAssembly.Function(
{parameters:['i32', 'i32'], results: ['i32']},
function(a, b) { return a * b; })
}});
})();
// Check that the modules exist.
assertTrue(!!exporting_instance);
assertTrue(!!instance);
print("--locally defined func--");
assertEquals(13, instance.exports.test_local());
print("--locally defined exported func--")
assertEquals(5, instance.exports.main(instance.exports.sub, 12, 7));
print("--imported js func--");
assertEquals(57, instance.exports.test_js_import());
print("--imported and reexported js func--")
assertEquals(19, instance.exports.main(
instance.exports.reexported_js_function, 12, 7));
print("--imported function from another module--");
assertEquals(57, instance.exports.test_wasm_import());
print("--not imported function defined in another module--");
assertEquals(19, instance.exports.main(
exporting_instance.exports.addition, 12, 7));
print("--imported WebAssembly.Function--")
assertEquals(21, instance.exports.test_js_api_import());
print("--not imported WebAssembly.Function--")
assertEquals(-5, instance.exports.main(
new WebAssembly.Function(
{parameters:['i32', 'i32'], results: ['i32']},
function(a, b) { return a - b; }),
10, 15));
print("--not imported WebAssembly.Function, arity mismatch--")
assertEquals(100, instance.exports.main(
new WebAssembly.Function(
{parameters:['i32', 'i32'], results: ['i32']},
function(a) { return a * a; }),
10, 15));
})();
(function TestFromJSSlowPath() {
print(arguments.callee.name);
var builder = new WasmModuleBuilder();
var sig_index = builder.addType(kSig_i_i);
builder.addFunction("main", makeSig(
[wasmRefType(sig_index), kWasmI32], [kWasmI32]))
.addBody([kExprLocalGet, 1, kExprLocalGet, 0, kExprCallRef, sig_index])
.exportFunc();
var instance = builder.instantiate({});
var fun = new WebAssembly.Function(
{ parameters: ['i32'], results: ['i32'] }, (a) => undefined);
// {undefined} is converted to 0.
assertEquals(0, instance.exports.main(fun, 1000));
})();
(function TestImportedFunctionSubtyping() {
print(arguments.callee.name);
var exporting_instance = (function () {
var builder = new WasmModuleBuilder();
let super_struct = builder.addStruct([makeField(kWasmI32, true)]);
let sub_struct = builder.addStruct(
[makeField(kWasmI32, true), makeField(kWasmI64, true)], super_struct);
let super_sig = builder.addType(makeSig([wasmRefNullType(sub_struct)],
[kWasmI32]), kNoSuperType, false)
let sub_sig = builder.addType(makeSig([wasmRefNullType(super_struct)],
[kWasmI32]), super_sig)
builder.addFunction("exported_function", sub_sig)
.addBody([kExprLocalGet, 0, kGCPrefix, kExprStructGet, super_struct, 0])
.exportFunc();
return builder.instantiate({});
})();
var builder = new WasmModuleBuilder();
// These should canonicalize to the same types as the exporting instance.
let super_struct = builder.addStruct([makeField(kWasmI32, true)]);
let sub_struct = builder.addStruct(
[makeField(kWasmI32, true), makeField(kWasmI64, true)], super_struct);
let super_sig = builder.addType(
makeSig([wasmRefNullType(sub_struct)], [kWasmI32]), kNoSuperType, false);
builder.addImport("m", "f", super_sig);
// Import is a function of the declared type.
return builder.instantiate({m: {f:
exporting_instance.exports.exported_function}});
})();
(function TestJSFunctionCanonicallyDifferent() {
print(arguments.callee.name);
let imp = new WebAssembly.Function({parameters: ["i32"], results: ["i32"]},
x => x + 1);
(function () {
var builder = new WasmModuleBuilder();
let sig = builder.addType(kSig_i_i);
builder.addImport("m", "f", sig);
// This succeeds
builder.instantiate({m: {f: imp}});
})();
(function () {
var builder = new WasmModuleBuilder();
let sig = builder.addType(kSig_i_i, kNoSuperType, false);
let sig_sub = builder.addType(kSig_i_i, sig);
builder.addImport("m", "f", sig_sub);
// Import is a function of the declared type.
assertThrows(() => builder.instantiate({m: {f: imp}}),
WebAssembly.LinkError,
/imported function does not match the expected type/);
})();
(function () {
var builder = new WasmModuleBuilder();
builder.startRecGroup();
let sig_in_group = builder.addType(kSig_i_i);
builder.addType(kSig_i_v);
builder.endRecGroup();
builder.addImport("m", "f", sig_in_group);
// Import is a function of the declared type.
assertThrows(() => builder.instantiate({m: {f: imp}}),
WebAssembly.LinkError,
/imported function does not match the expected type/);
})();
})();