Commit 4ef8ed71 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm][anyref] Allow element section entries for multiple tables

With the introduction of multiple tables the element section is able to
initialize any of the defined tables. However, the spec says that only
tables of type AnyFunc can be initialized.

With this CL we validate that entries in the element section only
target AnyFunc tables.

R=titzer@chromium.org

Bug: v8:7581
Change-Id: Ifea383b13c91f582813b2aa4f01a5f724575cfa0
Reviewed-on: https://chromium-review.googlesource.com/1130519
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54400}
parent c6effdbb
......@@ -2048,7 +2048,8 @@ void InstanceBuilder::InitializeTables(Handle<WasmInstanceObject> instance) {
const WasmTable& table = module_->tables[index];
TableInstance& table_instance = table_instances_[index];
if (!instance->has_indirect_function_table()) {
if (!instance->has_indirect_function_table() &&
table.type == kWasmAnyFunc) {
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
instance, table.initial_size);
table_instance.table_size = table.initial_size;
......@@ -2058,74 +2059,71 @@ void InstanceBuilder::InitializeTables(Handle<WasmInstanceObject> instance) {
void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
NativeModule* native_module = module_object_->native_module();
int table_count = static_cast<int>(module_->tables.size());
for (int index = 0; index < table_count; ++index) {
for (auto& table_init : module_->table_inits) {
uint32_t base = EvalUint32InitExpr(table_init.offset);
uint32_t num_entries = static_cast<uint32_t>(table_init.entries.size());
uint32_t index = table_init.table_index;
TableInstance& table_instance = table_instances_[index];
DCHECK(in_bounds(base, num_entries, table_instance.table_size));
for (uint32_t i = 0; i < num_entries; ++i) {
uint32_t func_index = table_init.entries[i];
const WasmFunction* function = &module_->functions[func_index];
int table_index = static_cast<int>(i + base);
// Update the local dispatch table first.
uint32_t sig_id = module_->signature_ids[function->sig_index];
WasmInstanceObject* target_instance = *instance;
Address call_target;
const bool is_import = func_index < module_->num_imported_functions;
if (is_import) {
// For imported calls, take target instance and address from the
// import table.
ImportedFunctionEntry entry(instance, func_index);
target_instance = entry.instance();
call_target = entry.target();
} else {
call_target = native_module->GetCallTargetForFunction(func_index);
}
IndirectFunctionTableEntry(instance, table_index)
.set(sig_id, target_instance, call_target);
// TODO(titzer): this does redundant work if there are multiple tables,
// since initializations are not sorted by table index.
for (auto& table_init : module_->table_inits) {
uint32_t base = EvalUint32InitExpr(table_init.offset);
uint32_t num_entries = static_cast<uint32_t>(table_init.entries.size());
DCHECK(in_bounds(base, num_entries, table_instance.table_size));
for (uint32_t i = 0; i < num_entries; ++i) {
uint32_t func_index = table_init.entries[i];
const WasmFunction* function = &module_->functions[func_index];
int table_index = static_cast<int>(i + base);
// Update the local dispatch table first.
uint32_t sig_id = module_->signature_ids[function->sig_index];
WasmInstanceObject* target_instance = *instance;
Address call_target;
const bool is_import = func_index < module_->num_imported_functions;
if (is_import) {
// For imported calls, take target instance and address from the
// import table.
ImportedFunctionEntry entry(instance, func_index);
target_instance = entry.instance();
call_target = entry.target();
} else {
call_target = native_module->GetCallTargetForFunction(func_index);
}
IndirectFunctionTableEntry(instance, table_index)
.set(sig_id, target_instance, call_target);
if (!table_instance.table_object.is_null()) {
// Update the table object's other dispatch tables.
if (js_wrappers_[func_index].is_null()) {
// No JSFunction entry yet exists for this function. Create one.
// TODO(titzer): We compile JS->wasm wrappers for functions are
// not exported but are in an exported table. This should be done
// at module compile time and cached instead.
Handle<Code> wrapper_code =
js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
isolate_, native_module, func_index, use_trap_handler());
MaybeHandle<String> func_name;
if (module_->origin == kAsmJsOrigin) {
// For modules arising from asm.js, honor the names section.
WireBytesRef func_name_ref = module_->LookupFunctionName(
native_module->wire_bytes(), func_index);
func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate_, module_object_, func_name_ref)
.ToHandleChecked();
}
Handle<WasmExportedFunction> js_function =
WasmExportedFunction::New(
isolate_, instance, func_name, func_index,
static_cast<int>(function->sig->parameter_count()),
wrapper_code);
js_wrappers_[func_index] = js_function;
if (!table_instance.table_object.is_null()) {
// Update the table object's other dispatch tables.
if (js_wrappers_[func_index].is_null()) {
// No JSFunction entry yet exists for this function. Create one.
// TODO(titzer): We compile JS->wasm wrappers for functions are
// not exported but are in an exported table. This should be done
// at module compile time and cached instead.
Handle<Code> wrapper_code =
js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
isolate_, native_module, func_index, use_trap_handler());
MaybeHandle<String> func_name;
if (module_->origin == kAsmJsOrigin) {
// For modules arising from asm.js, honor the names section.
WireBytesRef func_name_ref = module_->LookupFunctionName(
native_module->wire_bytes(), func_index);
func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate_, module_object_, func_name_ref)
.ToHandleChecked();
}
table_instance.js_wrappers->set(table_index,
*js_wrappers_[func_index]);
// UpdateDispatchTables() should update this instance as well.
WasmTableObject::UpdateDispatchTables(
isolate_, table_instance.table_object, table_index, function->sig,
instance, call_target);
Handle<WasmExportedFunction> js_function = WasmExportedFunction::New(
isolate_, instance, func_name, func_index,
static_cast<int>(function->sig->parameter_count()), wrapper_code);
js_wrappers_[func_index] = js_function;
}
table_instance.js_wrappers->set(table_index, *js_wrappers_[func_index]);
// UpdateDispatchTables() should update this instance as well.
WasmTableObject::UpdateDispatchTables(
isolate_, table_instance.table_object, table_index, function->sig,
instance, call_target);
}
}
}
int table_count = static_cast<int>(module_->tables.size());
for (int index = 0; index < table_count; ++index) {
TableInstance& table_instance = table_instances_[index];
// TODO(titzer): we add the new dispatch table at the end to avoid
// redundant work and also because the new instance is not yet fully
......
......@@ -477,7 +477,14 @@ class ModuleDecoderImpl : public Decoder {
module_->tables.emplace_back();
WasmTable* table = &module_->tables.back();
table->imported = true;
expect_u8("element type", kLocalAnyFunc);
ValueType type = consume_reference_type();
if (!FLAG_experimental_wasm_anyref) {
if (type != kWasmAnyFunc) {
error(pc_ - 1, "invalid table type");
break;
}
}
table->type = type;
uint8_t flags = validate_table_flags("element count");
consume_resizable_limits(
"element count", "elements", FLAG_wasm_max_table_size,
......@@ -702,13 +709,18 @@ class ModuleDecoderImpl : public Decoder {
for (uint32_t i = 0; ok() && i < element_count; ++i) {
const byte* pos = pc();
uint32_t table_index = consume_u32v("table index");
if (table_index != 0) {
if (!FLAG_experimental_wasm_anyref && table_index != 0) {
errorf(pos, "illegal table index %u != 0", table_index);
}
if (table_index >= module_->tables.size()) {
errorf(pos, "out of bounds table index %u", table_index);
break;
}
if (module_->tables[table_index].type != kWasmAnyFunc) {
errorf(pos, "Invalid element segment. Table %u is not of type AnyFunc",
table_index);
break;
}
WasmInitExpr offset = consume_init_expr(module_.get(), kWasmI32);
uint32_t num_elem =
consume_count("number of elements", kV8MaxWasmTableEntries);
......
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