2020-09-21 14:38:49 +00:00
|
|
|
// 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.
|
|
|
|
|
2022-03-01 21:06:15 +00:00
|
|
|
// Flags: --experimental-wasm-gc
|
2020-09-21 14:38:49 +00:00
|
|
|
|
2021-06-01 12:46:36 +00:00
|
|
|
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
2022-01-27 16:24:31 +00:00
|
|
|
/* TODO(7748): Implement cross-module subtyping.
|
2021-03-05 10:23:27 +00:00
|
|
|
(function TestTables() {
|
[wasm] Internal representation for function references
Design doc: bit.ly/3jEVgzz
We separate the internal representation of function references in Wasm
from their JSFunction-based (external) representation. This improves
performance of call_ref by requiring less indirections to load the
context and call target from a function reference. In the boundary
between wasm and JS/the C API, we add transformations between the two
representations.
Detailed changes:
- Introduce WasmInternalFunction, containing fields required by
call_ref, as well as a reference to the corresponding
WasmExternalFunction. Add a reference to the WasmInternalFunction in
WasmFunctionData. The {WasmInternalFunction::FromExternal} helper
extracts the internal out of an external function.
- Change {WasmInstanceObject::external_functions()} to internal
functions.
- Change wasm function tables to contain internal functions.
- Change the following code to use internal functions:
- call_ref in liftoff and Turbofan
- function type checks in liftoff and Turbofan
- CallRefIC and GenericJSToWasmWrapper builtins
- {InitExprInterface::RefFunc}
- module-compiler.cc in {ProcessTypeFeedback}
- In module-instantiate.cc, in function-rtt creation.
- Add transformations between internal and external functions in:
- WasmWrapperGraphBuilder::{ToJS, BuildUnpackObjectWrapper, FromJS,
BuildJSToJSWrapper}.
- debug-wasm-objects.cc in {FunctionProxy::Get},
{WasmValueObject::New} and {AddWasmTableObjectInternalProperties}.
- runtime-wasm.cc in ReplaceWrapper
- the C and JS APIs
- module-instantiate.cc, in import and export processing, as well as
{InitializeIndirectFunctionTables}
- WasmTableObject::{IsValidElement, SetFunctionTableEntry}
- {WasmGlobalObject::SetFuncRef}
- Simplify body descriptors of WasmExternalFunction variants.
- Adjust tests.
Bug: v8:11510
Change-Id: I8377f46f55c3771391ae1c5c8201a83854ee7878
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3277878
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78068}
2021-11-23 14:31:18 +00:00
|
|
|
print(arguments.callee.name);
|
2021-03-05 12:03:33 +00:00
|
|
|
var exporting_instance = (function() {
|
2020-09-21 14:38:49 +00:00
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
var binary_type = builder.addType(kSig_i_ii);
|
|
|
|
|
2021-03-05 12:03:33 +00:00
|
|
|
builder.addFunction('addition', kSig_i_ii)
|
|
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Add])
|
|
|
|
.exportFunc();
|
2020-09-21 14:38:49 +00:00
|
|
|
|
2021-03-05 12:03:33 +00:00
|
|
|
builder.addFunction('succ', kSig_i_i)
|
|
|
|
.addBody([kExprLocalGet, 0, kExprI32Const, 1, kExprI32Add])
|
|
|
|
.exportFunc();
|
2020-09-21 14:38:49 +00:00
|
|
|
|
2021-03-05 12:03:33 +00:00
|
|
|
builder.addTable(wasmOptRefType(binary_type), 1, 100).exportAs('table');
|
2020-09-21 14:38:49 +00:00
|
|
|
|
|
|
|
return builder.instantiate({});
|
|
|
|
})();
|
|
|
|
|
|
|
|
// Wrong type for imported table.
|
2021-03-05 12:03:33 +00:00
|
|
|
assertThrows(() => {
|
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
var unary_type = builder.addType(kSig_i_i);
|
|
|
|
builder.addImportedTable(
|
|
|
|
'imports', 'table', 1, 100, wasmOptRefType(unary_type));
|
|
|
|
builder.instantiate({imports: {table: exporting_instance.exports.table}})
|
|
|
|
}, WebAssembly.LinkError, /imported table does not match the expected type/)
|
2020-09-21 14:38:49 +00:00
|
|
|
|
|
|
|
// Type for imported table must match exactly.
|
2021-03-05 12:03:33 +00:00
|
|
|
assertThrows(() => {
|
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
builder.addImportedTable('imports', 'table', 1, 100, kWasmFuncRef);
|
|
|
|
builder.instantiate({imports: {table: exporting_instance.exports.table}})
|
|
|
|
}, WebAssembly.LinkError, /imported table does not match the expected type/)
|
|
|
|
|
|
|
|
var instance = (function() {
|
2020-09-21 14:38:49 +00:00
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
|
|
|
|
var unary_type = builder.addType(kSig_i_i);
|
|
|
|
var binary_type = builder.addType(kSig_i_ii);
|
|
|
|
|
2021-03-05 12:03:33 +00:00
|
|
|
builder.addImportedTable(
|
|
|
|
'imports', 'table', 1, 100, wasmOptRefType(binary_type));
|
2020-09-21 14:38:49 +00:00
|
|
|
|
2021-03-05 12:03:33 +00:00
|
|
|
var table =
|
|
|
|
builder.addTable(wasmOptRefType(unary_type), 10).exportAs('table');
|
|
|
|
builder.addTable(kWasmFuncRef, 1).exportAs('generic_table');
|
2020-09-21 14:38:49 +00:00
|
|
|
|
2021-03-05 12:03:33 +00:00
|
|
|
builder
|
|
|
|
.addFunction(
|
|
|
|
'table_test', makeSig([wasmRefType(unary_type)], [kWasmI32]))
|
|
|
|
// Set table[0] to input function, then retrieve it and call it.
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 0, kExprLocalGet, 0, kExprTableSet, table.index,
|
|
|
|
kExprI32Const, 42, kExprI32Const, 0, kExprTableGet, table.index,
|
|
|
|
kExprCallRef
|
|
|
|
])
|
|
|
|
.exportFunc();
|
2020-09-21 14:38:49 +00:00
|
|
|
|
2021-03-05 10:23:27 +00:00
|
|
|
// Same, but with table[1] and call_indirect
|
2021-03-05 12:03:33 +00:00
|
|
|
builder
|
|
|
|
.addFunction(
|
|
|
|
'table_indirect_test',
|
|
|
|
makeSig([wasmRefType(unary_type)], [kWasmI32]))
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 1, kExprLocalGet, 0, kExprTableSet, table.index,
|
|
|
|
kExprI32Const, 42, kExprI32Const, 0, kExprCallIndirect, unary_type,
|
|
|
|
table.index
|
|
|
|
])
|
|
|
|
.exportFunc();
|
2021-03-05 10:23:27 +00:00
|
|
|
|
2020-09-21 14:38:49 +00:00
|
|
|
// Instantiate with a table of the correct type.
|
|
|
|
return builder.instantiate(
|
2021-03-05 12:03:33 +00:00
|
|
|
{imports: {table: exporting_instance.exports.table}});
|
2020-09-21 14:38:49 +00:00
|
|
|
})();
|
|
|
|
|
|
|
|
// This module is valid.
|
|
|
|
assertTrue(!!instance);
|
|
|
|
|
|
|
|
// The correct function reference is preserved when setting it to and getting
|
|
|
|
// it back from a table.
|
2021-03-05 12:03:33 +00:00
|
|
|
assertEquals(
|
|
|
|
43, instance.exports.table_test(exporting_instance.exports.succ));
|
2021-03-05 10:23:27 +00:00
|
|
|
// Same for call indirect (the indirect call tables are also set correctly).
|
2021-03-05 12:03:33 +00:00
|
|
|
assertEquals(
|
|
|
|
43,
|
|
|
|
instance.exports.table_indirect_test(exporting_instance.exports.succ));
|
2020-09-21 14:38:49 +00:00
|
|
|
|
|
|
|
// Setting from JS API respects types.
|
2021-03-05 10:23:27 +00:00
|
|
|
instance.exports.generic_table.set(0, exporting_instance.exports.succ);
|
|
|
|
instance.exports.table.set(0, exporting_instance.exports.succ);
|
2020-09-21 14:38:49 +00:00
|
|
|
assertThrows(
|
2021-03-05 12:03:33 +00:00
|
|
|
() => instance.exports.table.set(0, exporting_instance.exports.addition),
|
|
|
|
TypeError,
|
|
|
|
/Argument 1 must be null or a WebAssembly function of type compatible to/);
|
2021-03-05 10:23:27 +00:00
|
|
|
})();
|
2022-01-27 16:24:31 +00:00
|
|
|
*/
|
2021-03-05 10:23:27 +00:00
|
|
|
|
|
|
|
(function TestNonNullableTables() {
|
[wasm] Internal representation for function references
Design doc: bit.ly/3jEVgzz
We separate the internal representation of function references in Wasm
from their JSFunction-based (external) representation. This improves
performance of call_ref by requiring less indirections to load the
context and call target from a function reference. In the boundary
between wasm and JS/the C API, we add transformations between the two
representations.
Detailed changes:
- Introduce WasmInternalFunction, containing fields required by
call_ref, as well as a reference to the corresponding
WasmExternalFunction. Add a reference to the WasmInternalFunction in
WasmFunctionData. The {WasmInternalFunction::FromExternal} helper
extracts the internal out of an external function.
- Change {WasmInstanceObject::external_functions()} to internal
functions.
- Change wasm function tables to contain internal functions.
- Change the following code to use internal functions:
- call_ref in liftoff and Turbofan
- function type checks in liftoff and Turbofan
- CallRefIC and GenericJSToWasmWrapper builtins
- {InitExprInterface::RefFunc}
- module-compiler.cc in {ProcessTypeFeedback}
- In module-instantiate.cc, in function-rtt creation.
- Add transformations between internal and external functions in:
- WasmWrapperGraphBuilder::{ToJS, BuildUnpackObjectWrapper, FromJS,
BuildJSToJSWrapper}.
- debug-wasm-objects.cc in {FunctionProxy::Get},
{WasmValueObject::New} and {AddWasmTableObjectInternalProperties}.
- runtime-wasm.cc in ReplaceWrapper
- the C and JS APIs
- module-instantiate.cc, in import and export processing, as well as
{InitializeIndirectFunctionTables}
- WasmTableObject::{IsValidElement, SetFunctionTableEntry}
- {WasmGlobalObject::SetFuncRef}
- Simplify body descriptors of WasmExternalFunction variants.
- Adjust tests.
Bug: v8:11510
Change-Id: I8377f46f55c3771391ae1c5c8201a83854ee7878
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3277878
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78068}
2021-11-23 14:31:18 +00:00
|
|
|
print(arguments.callee.name);
|
2021-03-05 10:23:27 +00:00
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
|
|
|
|
var binary_type = builder.addType(kSig_i_ii);
|
|
|
|
|
2022-01-27 16:24:31 +00:00
|
|
|
var addition = builder.addFunction('addition', binary_type).addBody([
|
2021-03-05 12:03:33 +00:00
|
|
|
kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Add
|
|
|
|
]);
|
|
|
|
var subtraction =
|
2022-01-27 16:24:31 +00:00
|
|
|
builder.addFunction('subtraction', binary_type)
|
2021-03-05 12:03:33 +00:00
|
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Sub])
|
|
|
|
.exportFunc();
|
2021-03-05 10:23:27 +00:00
|
|
|
|
2021-05-05 07:14:19 +00:00
|
|
|
var table = builder.addTable(wasmRefType(binary_type), 3, 3,
|
|
|
|
WasmInitExpr.RefFunc(addition.index));
|
2021-03-05 10:23:27 +00:00
|
|
|
|
2021-03-05 12:03:33 +00:00
|
|
|
builder.addFunction('init', kSig_v_v)
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 1, kExprRefFunc, subtraction.index, kExprTableSet,
|
|
|
|
table.index
|
|
|
|
])
|
|
|
|
.exportFunc();
|
2021-03-05 10:23:27 +00:00
|
|
|
|
|
|
|
// (index, arg1, arg2) -> table[index](arg1, arg2)
|
2021-03-05 12:03:33 +00:00
|
|
|
builder.addFunction('table_test', kSig_i_iii)
|
|
|
|
.addBody([
|
|
|
|
kExprLocalGet, 1, kExprLocalGet, 2, kExprLocalGet, 0, kExprCallIndirect,
|
|
|
|
binary_type, table.index
|
|
|
|
])
|
|
|
|
.exportFunc();
|
2021-03-05 10:23:27 +00:00
|
|
|
|
|
|
|
var instance = builder.instantiate({});
|
|
|
|
|
|
|
|
assertTrue(!!instance);
|
|
|
|
|
|
|
|
instance.exports.init();
|
|
|
|
assertEquals(44, instance.exports.table_test(0, 33, 11));
|
|
|
|
assertEquals(22, instance.exports.table_test(1, 33, 11));
|
2020-09-21 14:38:49 +00:00
|
|
|
})();
|
2022-03-01 21:06:15 +00:00
|
|
|
|
|
|
|
(function TestAnyRefTable() {
|
|
|
|
print(arguments.callee.name);
|
|
|
|
let builder = new WasmModuleBuilder();
|
|
|
|
|
|
|
|
let unary_type = builder.addType(kSig_i_i);
|
|
|
|
let binary_type = builder.addType(kSig_i_ii);
|
|
|
|
let struct_type = builder.addStruct([makeField(kWasmI32, false)]);
|
|
|
|
|
|
|
|
let successor = builder.addFunction('addition', unary_type)
|
|
|
|
.addBody([kExprLocalGet, 0, kExprI32Const, 1, kExprI32Add]);
|
|
|
|
|
|
|
|
let subtraction = builder.addFunction('subtraction', binary_type)
|
|
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Sub])
|
|
|
|
|
|
|
|
let table = builder.addTable(kWasmAnyRef, 4, 4);
|
|
|
|
builder.addActiveElementSegment(
|
|
|
|
table, WasmInitExpr.I32Const(0),
|
|
|
|
[WasmInitExpr.RefFunc(successor.index),
|
|
|
|
WasmInitExpr.RefFunc(subtraction.index),
|
|
|
|
WasmInitExpr.StructNew(struct_type, [WasmInitExpr.I32Const(10)]),
|
|
|
|
WasmInitExpr.RefNull(kWasmEqRef)],
|
|
|
|
kWasmAnyRef);
|
|
|
|
|
|
|
|
// return static_cast<i->i>(table[0])(local_0)
|
|
|
|
builder.addFunction("f0_getter", kSig_i_i)
|
|
|
|
.addBody([
|
|
|
|
kExprLocalGet, 0,
|
|
|
|
kExprI32Const, 0, kExprTableGet, 0,
|
|
|
|
kGCPrefix, kExprRefAsFunc, kGCPrefix, kExprRefCastStatic, unary_type,
|
|
|
|
kExprCallRef])
|
|
|
|
.exportFunc();
|
|
|
|
|
|
|
|
// return static_cast<(i,i)->i>(table[1])(local_0, local_1)
|
|
|
|
builder.addFunction("f1_getter", kSig_i_ii)
|
|
|
|
.addBody([
|
|
|
|
kExprLocalGet, 0, kExprLocalGet, 1,
|
|
|
|
kExprI32Const, 1, kExprTableGet, 0,
|
|
|
|
kGCPrefix, kExprRefAsFunc, kGCPrefix, kExprRefCastStatic, binary_type,
|
|
|
|
kExprCallRef])
|
|
|
|
.exportFunc();
|
|
|
|
|
|
|
|
// return static_cast<struct_type>(table[2]).field_0
|
|
|
|
builder.addFunction("struct_getter", kSig_i_v)
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 2, kExprTableGet, 0,
|
|
|
|
kGCPrefix, kExprRefAsData, kGCPrefix, kExprRefCastStatic, struct_type,
|
|
|
|
kGCPrefix, kExprStructGet, struct_type, 0])
|
|
|
|
.exportFunc();
|
|
|
|
|
|
|
|
// return table[3] == null
|
|
|
|
builder.addFunction("null_getter", kSig_i_v)
|
|
|
|
.addBody([kExprI32Const, 3, kExprTableGet, 0, kExprRefIsNull])
|
|
|
|
.exportFunc();
|
|
|
|
|
|
|
|
let instance = builder.instantiate({});
|
|
|
|
|
|
|
|
assertTrue(!!instance);
|
|
|
|
|
|
|
|
assertEquals(43, instance.exports.f0_getter(42));
|
|
|
|
assertEquals(-7, instance.exports.f1_getter(12, 19));
|
|
|
|
assertEquals(10, instance.exports.struct_getter());
|
|
|
|
assertEquals(1, instance.exports.null_getter());
|
|
|
|
})();
|