v8/test/mjsunit/wasm/reference-globals-import.js
Manos Koukoutos d0c9775f73 Reland "[wasm-gc][test] Support recursive groups in wasm-module-builder.js"
This is a reland of commit 49b1e977ac

Change compared to original: Fix failing test.

Original change's description:
> [wasm-gc][test] Support recursive groups in wasm-module-builder.js
>
> Bug: v8:7748
> Change-Id: Iff6668891ce785ad2f45ff898d92c6ea9b5f4e7d
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4061691
> Commit-Queue: Matthias Liedtke <mliedtke@chromium.org>
> Auto-Submit: Manos Koukoutos <manoskouk@chromium.org>
> Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#84534}

Bug: v8:7748
Change-Id: I43b9e480aabe4daaa556d04d4e5d548d2144f93e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4063694
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Auto-Submit: Manos Koukoutos <manoskouk@chromium.org>
Commit-Queue: Matthias Liedtke <mliedtke@chromium.org>
Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84551}
2022-11-29 16:47:08 +00:00

503 lines
18 KiB
JavaScript

// Copyright 2022 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-gc --experimental-wasm-stringref
// Flags: --no-wasm-gc-structref-as-dataref
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
// Test type checks when creating a global with a value imported from a global
// from another module.
(function TestReferenceGlobalsImportGlobal() {
print(arguments.callee.name);
let exporting_instance = (function() {
let builder = new WasmModuleBuilder();
let type_super = builder.addStruct([makeField(kWasmI32, false)]);
let type_sub =
builder.addStruct([makeField(kWasmI32, false)], type_super);
let type_other = builder.addStruct([makeField(kWasmI64, false)]);
builder.addGlobal(wasmRefType(type_super), false,
[kExprI32Const, 42,
kGCPrefix, kExprStructNew, type_super])
.exportAs("super");
builder.addGlobal(wasmRefType(type_sub), false,
[kExprI32Const, 42,
kGCPrefix, kExprStructNew, type_sub])
.exportAs("sub");
builder.addGlobal(wasmRefType(type_other), false,
[kExprI64Const, 42,
kGCPrefix, kExprStructNew, type_other])
.exportAs("other");
// null variants
builder.addGlobal(wasmRefNullType(type_super), false,
[kExprI32Const, 42,
kGCPrefix, kExprStructNew, type_super])
.exportAs("super_nullable");
builder.addGlobal(wasmRefNullType(type_sub), false,
[kExprI32Const, 42,
kGCPrefix, kExprStructNew, type_sub])
.exportAs("sub_nullable");
builder.addGlobal(wasmRefNullType(type_other), false,
[kExprI64Const, 42,
kGCPrefix, kExprStructNew, type_other])
.exportAs("other_nullable");
return builder.instantiate({});
})();
let tests = [
//valid |type |imported_global
[true, "super", "super"],
[true, "sub", "sub"],
[true, "super", "sub"], // would be invalid for immutable global!
[false, "sub", "super"],
[false, "sub", "other"],
[false, "super", "super_nullable"],
[true, "super_nullable", "super"],
[true, "super_nullable", "sub"],
[true, "super_nullable", "sub_nullable"],
[false, "super_nullable", "other_nullable"],
[false, "sub_nullable", "super_nullable"],
];
for (let[expected_valid, type, global] of tests) {
print(`test ${type} imports ${global}`);
let builder = new WasmModuleBuilder();
let type_super = builder.addStruct([makeField(kWasmI32, false)]);
let type_sub =
builder.addStruct([makeField(kWasmI32, false)], type_super);
let types = {
super: wasmRefType(type_super),
sub: wasmRefType(type_sub),
super_nullable: wasmRefNullType(type_super),
sub_nullable: wasmRefNullType(type_sub),
};
builder.addImportedGlobal("imports", "global", types[type], false);
assertNotEquals(exporting_instance.exports[global], undefined);
let imports = { global: exporting_instance.exports[global] };
if (expected_valid) {
builder.addFunction("read_global", makeSig([], [kWasmI32]))
.addBody([
kExprGlobalGet, 0,
kGCPrefix, kExprStructGet, types[type].heap_type, 0,
])
.exportFunc();
let instance = builder.instantiate({imports});
assertEquals(42, instance.exports.read_global());
} else {
assertThrows(
() => builder.instantiate({imports}),
WebAssembly.LinkError,
/imported global does not match the expected type/
);
}
}
})();
// Test type checks when creating a global initialized with wasm objects
// provided as externref.
(function TestReferenceGlobalsImportValue() {
print(arguments.callee.name);
let exporting_instance = (function() {
let builder = new WasmModuleBuilder();
let type_super = builder.addStruct([makeField(kWasmI32, false)]);
let type_sub =
builder.addStruct([makeField(kWasmI32, false)], type_super);
let type_other = builder.addStruct([makeField(kWasmI64, false)]);
builder.addFunction("create_super", makeSig([], [kWasmExternRef]))
.addBody([
kExprI32Const, 42,
kGCPrefix, kExprStructNew, type_super,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_sub", makeSig([], [kWasmExternRef]))
.addBody([
kExprI32Const, 42,
kGCPrefix, kExprStructNew, type_sub,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_other", makeSig([], [kWasmExternRef]))
.addBody([
kExprI64Const, 42,
kGCPrefix, kExprStructNew, type_other,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_null", makeSig([], [kWasmExternRef]))
.addBody([
kExprRefNull, kNullRefCode,
kGCPrefix, kExprExternExternalize])
.exportFunc();
return builder.instantiate({});
})();
let tests = [
//valid |type |imported_value
[true, "super", "super"],
[true, "sub", "sub"],
[true, "super", "sub"],
[false, "sub", "super"],
[false, "sub", "other"],
[false, "super", "null"],
[true, "super_nullable", "super"],
[true, "super_nullable", "sub"],
[true, "super_nullable", "sub"],
[false, "super_nullable", "other"],
[false, "sub_nullable", "super"],
[true, "super_nullable", "null"],
];
for (let[expected_valid, type, imported_value] of tests) {
print(`test ${type} imports ${imported_value}`);
let builder = new WasmModuleBuilder();
let type_super = builder.addStruct([makeField(kWasmI32, false)]);
let type_sub =
builder.addStruct([makeField(kWasmI32, false)], type_super);
let types = {
super: wasmRefType(type_super),
sub: wasmRefType(type_sub),
super_nullable: wasmRefNullType(type_super),
sub_nullable: wasmRefNullType(type_sub),
};
builder.addImportedGlobal("imports", "global", types[type], false);
let init_value = exporting_instance.exports[`create_${imported_value}`]();
let imports = {global: init_value};
if (expected_valid) {
builder.addFunction("read_global", makeSig([], [kWasmI32]))
.addBody([
kExprBlock, kWasmVoid,
kExprGlobalGet, 0,
kExprBrOnNull, 0,
kGCPrefix, kExprStructGet, types[type].heap_type, 0,
kExprReturn,
kExprEnd,
...wasmI32Const(-1),
])
.exportFunc();
let instance = builder.instantiate({imports});
assertEquals(imported_value == "null" ? -1 : 42,
instance.exports.read_global());
} else {
assertThrows(
() => builder.instantiate({imports}),
WebAssembly.LinkError
);
}
}
})();
(function TestReferenceGlobalsImportInvalidJsValues() {
print(arguments.callee.name);
let invalid_values =
[undefined, {}, [], 0, NaN, null, /regex/, true, false, ""];
for (let value of invalid_values) {
print(`test invalid value ${JSON.stringify(value)}`);
let builder = new WasmModuleBuilder();
let struct_type = builder.addStruct([makeField(kWasmI32, false)]);
let ref_type = wasmRefType(struct_type);
builder.addImportedGlobal("imports", "value", ref_type, false);
assertThrows(
() => builder.instantiate({imports: {value}}),
WebAssembly.LinkError);
}
})();
(function TestReferenceGlobalsAbstractTypes() {
print(arguments.callee.name);
let exporting_instance = (function() {
let builder = new WasmModuleBuilder();
let type_struct = builder.addStruct([makeField(kWasmI32, false)]);
let type_array = builder.addArray(kWasmI32);
builder.addFunction("create_struct", makeSig([], [kWasmExternRef]))
.addBody([
kExprI32Const, 42,
kGCPrefix, kExprStructNew, type_struct,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_array", makeSig([], [kWasmExternRef]))
.addBody([
kExprI32Const, 42,
kGCPrefix, kExprArrayNewFixed, type_array, 1,
kGCPrefix, kExprExternExternalize])
.exportFunc();
return builder.instantiate({});
})();
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("imports", "any1", kWasmAnyRef, false);
builder.addImportedGlobal("imports", "any2", kWasmAnyRef, false);
builder.addImportedGlobal("imports", "any3", kWasmAnyRef, false);
builder.addImportedGlobal("imports", "any4", kWasmAnyRef, false);
builder.addImportedGlobal("imports", "any4", kWasmAnyRef, false);
builder.addImportedGlobal("imports", "any5", kWasmAnyRef, false);
builder.addImportedGlobal("imports", "eq1", kWasmEqRef, false);
builder.addImportedGlobal("imports", "eq2", kWasmEqRef, false);
builder.addImportedGlobal("imports", "eq3", kWasmEqRef, false);
builder.addImportedGlobal("imports", "array", kWasmArrayRef, false);
builder.instantiate({imports : {
any1: exporting_instance.exports.create_struct(),
any2: exporting_instance.exports.create_array(),
any3: 12345, // i31
any4: null,
any5: "test string",
eq1: 12345,
eq2: exporting_instance.exports.create_array(),
eq3: exporting_instance.exports.create_struct(),
array: exporting_instance.exports.create_array(),
}});
})();
(function TestReferenceGlobalsStrings() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("imports", "string1", kWasmStringRef, false);
builder.addImportedGlobal("imports", "string2", kWasmStringRef, false);
builder.addImportedGlobal("imports", "any", kWasmAnyRef, false);
builder.addFunction("get_string1", makeSig([], [kWasmExternRef]))
.addBody([kExprGlobalGet, 0, kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("get_string2", makeSig([], [kWasmExternRef]))
.addBody([kExprGlobalGet, 1, kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("get_any", makeSig([], [kWasmExternRef]))
.addBody([kExprGlobalGet, 2, kGCPrefix, kExprExternExternalize])
.exportFunc();
let instance = builder.instantiate({imports : {
string1: "Content of string1",
string2: null,
any: "Content of any",
}});
assertEquals("Content of string1", instance.exports.get_string1());
assertEquals(null, instance.exports.get_string2());
assertEquals("Content of any", instance.exports.get_any());
})();
(function TestAnyRefGlobalFromJS() {
print(arguments.callee.name);
let anyref_global = new WebAssembly.Global(
{ value: "anyref", mutable: true }, "initial value");
assertEquals("initial value", anyref_global.value);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("imports", "anyref_global", kWasmAnyRef, true);
let struct_type = builder.addStruct([makeField(kWasmI32, false)]);
let array_type = builder.addArray(kWasmI32);
builder.addFunction("get_extern", makeSig([], [kWasmExternRef]))
.addBody([kExprGlobalGet, 0, kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("get_struct_val", makeSig([], [kWasmI32]))
.addBody([
kExprGlobalGet, 0,
kGCPrefix, kExprRefAsStruct,
kGCPrefix, kExprRefCast, struct_type,
kGCPrefix, kExprStructGet, struct_type, 0,
])
.exportFunc();
builder.addFunction("get_array_val", makeSig([], [kWasmI32]))
.addBody([
kExprGlobalGet, 0,
kGCPrefix, kExprRefAsArray,
kGCPrefix, kExprRefCast, array_type,
kExprI32Const, 0,
kGCPrefix, kExprArrayGet, array_type,
])
.exportFunc();
builder.addFunction("create_struct", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStructNew, struct_type,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_array", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprArrayNewFixed, array_type, 1,
kGCPrefix, kExprExternExternalize])
.exportFunc();
let instance = builder.instantiate({imports : {anyref_global}});
let wasm = instance.exports;
anyref_global.value = "Set anyref from string";
assertEquals("Set anyref from string", anyref_global.value);
assertEquals("Set anyref from string", wasm.get_extern());
anyref_global.value = wasm.create_struct(42);
assertEquals(42, wasm.get_struct_val());
anyref_global.value = wasm.create_array(43);
assertEquals(43, wasm.get_array_val());
anyref_global.value = null;
assertEquals(null, anyref_global.value);
assertEquals(null, wasm.get_extern());
anyref_global.value = 12345;
assertEquals(12345, wasm.get_extern());
let o = {};
anyref_global.value = o;
assertEquals(o, anyref_global.value);
assertEquals(o, wasm.get_extern());
anyref_global.value = undefined;
assertEquals(undefined, anyref_global.value);
})();
(function TestEqRefGlobalFromJS() {
print(arguments.callee.name);
let eqref_global = new WebAssembly.Global(
{ value: "eqref", mutable: true }, null);
assertEquals(null, eqref_global.value);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("imports", "eqref_global", kWasmEqRef, true);
let struct_type = builder.addStruct([makeField(kWasmI32, false)]);
let array_type = builder.addArray(kWasmI32);
builder.addFunction("get_extern", makeSig([], [kWasmExternRef]))
.addBody([kExprGlobalGet, 0, kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("get_struct_val", makeSig([], [kWasmI32]))
.addBody([
kExprGlobalGet, 0,
kGCPrefix, kExprRefAsStruct,
kGCPrefix, kExprRefCast, struct_type,
kGCPrefix, kExprStructGet, struct_type, 0,
])
.exportFunc();
builder.addFunction("get_array_val", makeSig([], [kWasmI32]))
.addBody([
kExprGlobalGet, 0,
kGCPrefix, kExprRefAsArray,
kGCPrefix, kExprRefCast, array_type,
kExprI32Const, 0,
kGCPrefix, kExprArrayGet, array_type,
])
.exportFunc();
builder.addFunction("create_struct", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStructNew, struct_type,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_array", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprArrayNewFixed, array_type, 1,
kGCPrefix, kExprExternExternalize])
.exportFunc();
let instance = builder.instantiate({imports : {eqref_global}});
let wasm = instance.exports;
eqref_global.value = wasm.create_struct(42);
assertEquals(42, wasm.get_struct_val());
eqref_global.value = wasm.create_array(43);
assertEquals(43, wasm.get_array_val());
eqref_global.value = null;
assertEquals(null, eqref_global.value);
assertEquals(null, wasm.get_extern());
eqref_global.value = 12345;
assertEquals(12345, wasm.get_extern());
assertThrows(() => eqref_global.value = {}, TypeError);
assertThrows(() => eqref_global.value = undefined, TypeError);
assertThrows(() => eqref_global.value = "string", TypeError);
})();
(function TestStructRefGlobalFromJS() {
print(arguments.callee.name);
let structref_global = new WebAssembly.Global(
{ value: "structref", mutable: true }, null);
assertNull(structref_global.value);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("imports", "structref_global", kWasmStructRef, true);
let struct_type = builder.addStruct([makeField(kWasmI32, false)]);
let array_type = builder.addArray(kWasmI32);
builder.addFunction("get_struct_val", makeSig([], [kWasmI32]))
.addBody([
kExprGlobalGet, 0,
kGCPrefix, kExprRefAsStruct,
kGCPrefix, kExprRefCast, struct_type,
kGCPrefix, kExprStructGet, struct_type, 0,
])
.exportFunc();
builder.addFunction("create_struct", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStructNew, struct_type,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_array", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprArrayNewFixed, array_type, 1,
kGCPrefix, kExprExternExternalize])
.exportFunc();
let instance = builder.instantiate({imports : {structref_global}});
let wasm = instance.exports;
structref_global.value = wasm.create_struct(42);
assertEquals(42, wasm.get_struct_val());
structref_global.value = null;
assertEquals(null, structref_global.value);
assertThrows(() => structref_global.value = undefined, TypeError);
assertThrows(() => structref_global.value = "string", TypeError);
assertThrows(() => structref_global.value = wasm.create_array(1), TypeError);
})();
(function TestArrayRefGlobalFromJS() {
print(arguments.callee.name);
let arrayref_global = new WebAssembly.Global(
{ value: "arrayref", mutable: true }, null);
assertNull(arrayref_global.value);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("imports", "arrayref_global", kWasmArrayRef, true);
let struct_type = builder.addStruct([makeField(kWasmI32, false)]);
let array_type = builder.addArray(kWasmI32);
builder.addFunction("get_array_val", makeSig([], [kWasmI32]))
.addBody([
kExprGlobalGet, 0,
kGCPrefix, kExprRefAsArray,
kGCPrefix, kExprRefCast, array_type,
kExprI32Const, 0,
kGCPrefix, kExprArrayGet, array_type,
])
.exportFunc();
builder.addFunction("create_struct", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStructNew, struct_type,
kGCPrefix, kExprExternExternalize])
.exportFunc();
builder.addFunction("create_array", makeSig([kWasmI32], [kWasmExternRef]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprArrayNewFixed, array_type, 1,
kGCPrefix, kExprExternExternalize])
.exportFunc();
let instance = builder.instantiate({imports : {arrayref_global}});
let wasm = instance.exports;
arrayref_global.value = wasm.create_array(43);
assertEquals(43, wasm.get_array_val());
arrayref_global.value = null;
assertEquals(null, arrayref_global.value);
assertThrows(() => arrayref_global.value = undefined, TypeError);
assertThrows(() => arrayref_global.value = "string", TypeError);
assertThrows(() => arrayref_global.value = wasm.create_struct(1), TypeError);
})();