From e24e5710ec8e29a46c58d124dd8299f97072f81c Mon Sep 17 00:00:00 2001 From: Andreas Haas Date: Tue, 30 Apr 2019 16:55:07 +0200 Subject: [PATCH] [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 Reviewed-by: Clemens Hammacher Cr-Commit-Position: refs/heads/master@{#61129} --- src/wasm/module-instantiate.cc | 89 +++++++++++++++--------- test/mjsunit/wasm/anyref-table.js | 16 +++++ test/mjsunit/wasm/wasm-module-builder.js | 6 +- 3 files changed, 75 insertions(+), 36 deletions(-) diff --git a/src/wasm/module-instantiate.cc b/src/wasm/module-instantiate.cc index bbeabc8a8b..9706d24181 100644 --- a/src/wasm/module-instantiate.cc +++ b/src/wasm/module-instantiate.cc @@ -140,6 +140,11 @@ class InstanceBuilder { Handle import_name, Handle value); + // Initialize imported tables of type anyfunc. + bool InitializeImportedIndirectFunctionTable( + Handle instance, int import_index, + Handle table_object); + // Process a single imported table. bool ProcessImportedTable(Handle instance, int import_index, int table_index, @@ -808,6 +813,49 @@ bool InstanceBuilder::ProcessImportedFunction( return true; } +bool InstanceBuilder::InitializeImportedIndirectFunctionTable( + Handle instance, int import_index, + Handle 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 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 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 instance, int import_index, int table_index, Handle module_name, @@ -851,42 +899,17 @@ bool InstanceBuilder::ProcessImportedTable(Handle 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 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 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; } diff --git a/test/mjsunit/wasm/anyref-table.js b/test/mjsunit/wasm/anyref-table.js index f9248199a2..f4e82d32c8 100644 --- a/test/mjsunit/wasm/anyref-table.js +++ b/test/mjsunit/wasm/anyref-table.js @@ -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/); +})(); diff --git a/test/mjsunit/wasm/wasm-module-builder.js b/test/mjsunit/wasm/wasm-module-builder.js index 7f63ea8662..bb1bcf4b40 100644 --- a/test/mjsunit/wasm/wasm-module-builder.js +++ b/test/mjsunit/wasm/wasm-module-builder.js @@ -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