[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: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61129}
This commit is contained in:
Andreas Haas 2019-04-30 16:55:07 +02:00 committed by Commit Bot
parent a30fd9ea92
commit e24e5710ec
3 changed files with 75 additions and 36 deletions

View File

@ -140,6 +140,11 @@ class InstanceBuilder {
Handle<String> import_name,
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.
bool ProcessImportedTable(Handle<WasmInstanceObject> instance,
int import_index, int table_index,
@ -808,6 +813,49 @@ bool InstanceBuilder::ProcessImportedFunction(
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,
int import_index, int table_index,
Handle<String> module_name,
@ -851,42 +899,17 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
}
}
// Allocate a new dispatch table.
if (!instance->has_indirect_function_table()) {
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
instance, imported_table_size);
if (table.type != table_object->type()) {
ReportLinkError("imported table does not match the expected type",
import_index, module_name, import_name);
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 =
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);
if (table.type == kWasmAnyFunc && !InitializeImportedIndirectFunctionTable(
instance, import_index, table_object)) {
return false;
}
return true;
}

View File

@ -29,3 +29,19 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
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/);
})();

View File

@ -843,12 +843,12 @@ class WasmModuleBuilder {
return this;
}
addImportedTable(module, name, initial, maximum) {
addImportedTable(module, name, initial, maximum, type) {
if (this.tables.length != 0) {
throw new Error('Imported tables must be declared before local ones');
}
let o = {module: module, name: name, kind: kExternalTable, initial: initial,
maximum: maximum};
maximum: maximum, type: type || kWasmAnyFunctionTypeForm};
this.imports.push(o);
return this.num_imported_tables++;
}
@ -999,7 +999,7 @@ class WasmModuleBuilder {
section.emit_u32v(imp.initial); // initial
if (has_max) section.emit_u32v(imp.maximum); // maximum
} else if (imp.kind == kExternalTable) {
section.emit_u8(kWasmAnyFunctionTypeForm);
section.emit_u8(imp.type);
var has_max = (typeof imp.maximum) != "undefined";
section.emit_u8(has_max ? 1 : 0); // flags
section.emit_u32v(imp.initial); // initial