Commit e24e5710 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm] Support importing anyref tables

R=clemensh@chromium.org

Bug: v8:7581
Change-Id: I6b20698e556ed3808f8b190f88cb700301825b54
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1588432
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61129}
parent a30fd9ea
...@@ -140,6 +140,11 @@ class InstanceBuilder { ...@@ -140,6 +140,11 @@ class InstanceBuilder {
Handle<String> import_name, Handle<String> import_name,
Handle<Object> value); Handle<Object> value);
// Initialize imported tables of type anyfunc.
bool InitializeImportedIndirectFunctionTable(
Handle<WasmInstanceObject> instance, int import_index,
Handle<WasmTableObject> table_object);
// Process a single imported table. // Process a single imported table.
bool ProcessImportedTable(Handle<WasmInstanceObject> instance, bool ProcessImportedTable(Handle<WasmInstanceObject> instance,
int import_index, int table_index, int import_index, int table_index,
...@@ -808,6 +813,49 @@ bool InstanceBuilder::ProcessImportedFunction( ...@@ -808,6 +813,49 @@ bool InstanceBuilder::ProcessImportedFunction(
return true; return true;
} }
bool InstanceBuilder::InitializeImportedIndirectFunctionTable(
Handle<WasmInstanceObject> instance, int import_index,
Handle<WasmTableObject> table_object) {
int imported_table_size = table_object->elements().length();
// Allocate a new dispatch table.
if (!instance->has_indirect_function_table()) {
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
instance, imported_table_size);
}
// Initialize the dispatch table with the (foreign) JS functions
// that are already in the table.
for (int i = 0; i < imported_table_size; ++i) {
bool is_valid;
bool is_null;
MaybeHandle<WasmInstanceObject> maybe_target_instance;
int function_index;
WasmTableObject::GetFunctionTableEntry(isolate_, table_object, i, &is_valid,
&is_null, &maybe_target_instance,
&function_index);
if (!is_valid) {
thrower_->LinkError("table import %d[%d] is not a wasm function",
import_index, i);
return false;
}
if (is_null) continue;
Handle<WasmInstanceObject> target_instance =
maybe_target_instance.ToHandleChecked();
FunctionSig* sig = target_instance->module_object()
->module()
->functions[function_index]
.sig;
// Look up the signature's canonical id. If there is no canonical
// id, then the signature does not appear at all in this module,
// so putting {-1} in the table will cause checks to always fail.
IndirectFunctionTableEntry(instance, i)
.Set(module_->signature_map.Find(*sig), target_instance,
function_index);
}
return true;
}
bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance, bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
int import_index, int table_index, int import_index, int table_index,
Handle<String> module_name, Handle<String> module_name,
...@@ -851,42 +899,17 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance, ...@@ -851,42 +899,17 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
} }
} }
// Allocate a new dispatch table. if (table.type != table_object->type()) {
if (!instance->has_indirect_function_table()) { ReportLinkError("imported table does not match the expected type",
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( import_index, module_name, import_name);
instance, imported_table_size); return false;
} }
// Initialize the dispatch table with the (foreign) JS functions
// that are already in the table.
for (int i = 0; i < imported_table_size; ++i) {
bool is_valid;
bool is_null;
MaybeHandle<WasmInstanceObject> maybe_target_instance;
int function_index;
WasmTableObject::GetFunctionTableEntry(isolate_, table_object, i, &is_valid,
&is_null, &maybe_target_instance,
&function_index);
if (!is_valid) {
thrower_->LinkError("table import %d[%d] is not a wasm function",
import_index, i);
return false;
}
if (is_null) continue;
Handle<WasmInstanceObject> target_instance = if (table.type == kWasmAnyFunc && !InitializeImportedIndirectFunctionTable(
maybe_target_instance.ToHandleChecked(); instance, import_index, table_object)) {
FunctionSig* sig = target_instance->module_object() return false;
->module()
->functions[function_index]
.sig;
// Look up the signature's canonical id. If there is no canonical
// id, then the signature does not appear at all in this module,
// so putting {-1} in the table will cause checks to always fail.
IndirectFunctionTableEntry(instance, i)
.Set(module_->signature_map.Find(*sig), target_instance,
function_index);
} }
return true; return true;
} }
......
...@@ -29,3 +29,19 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -29,3 +29,19 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
assertThrows(() => table.set(12), RangeError); assertThrows(() => table.set(12), RangeError);
})(); })();
(function TestImportAnyRefTable() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
const table_index = builder.addImportedTable("imp", "table", 3, 10, kWasmAnyRef);
builder.addFunction('get', kSig_r_v)
.addBody([kExprI32Const, 0, kExprGetTable, table_index]);
let table_ref = new WebAssembly.Table({element: "anyref", initial: 3, maximum: 10});
builder.instantiate({imp:{table: table_ref}});
let table_func = new WebAssembly.Table({ element: "anyfunc", initial: 3, maximum: 10 });
assertThrows(() => builder.instantiate({ imp: { table: table_func } }),
WebAssembly.LinkError, /imported table does not match the expected type/);
})();
...@@ -843,12 +843,12 @@ class WasmModuleBuilder { ...@@ -843,12 +843,12 @@ class WasmModuleBuilder {
return this; return this;
} }
addImportedTable(module, name, initial, maximum) { addImportedTable(module, name, initial, maximum, type) {
if (this.tables.length != 0) { if (this.tables.length != 0) {
throw new Error('Imported tables must be declared before local ones'); throw new Error('Imported tables must be declared before local ones');
} }
let o = {module: module, name: name, kind: kExternalTable, initial: initial, let o = {module: module, name: name, kind: kExternalTable, initial: initial,
maximum: maximum}; maximum: maximum, type: type || kWasmAnyFunctionTypeForm};
this.imports.push(o); this.imports.push(o);
return this.num_imported_tables++; return this.num_imported_tables++;
} }
...@@ -999,7 +999,7 @@ class WasmModuleBuilder { ...@@ -999,7 +999,7 @@ class WasmModuleBuilder {
section.emit_u32v(imp.initial); // initial section.emit_u32v(imp.initial); // initial
if (has_max) section.emit_u32v(imp.maximum); // maximum if (has_max) section.emit_u32v(imp.maximum); // maximum
} else if (imp.kind == kExternalTable) { } else if (imp.kind == kExternalTable) {
section.emit_u8(kWasmAnyFunctionTypeForm); section.emit_u8(imp.type);
var has_max = (typeof imp.maximum) != "undefined"; var has_max = (typeof imp.maximum) != "undefined";
section.emit_u8(has_max ? 1 : 0); // flags section.emit_u8(has_max ? 1 : 0); // flags
section.emit_u32v(imp.initial); // initial section.emit_u32v(imp.initial); // initial
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment