[wasm] Support tables with exnref type entries.

This extends existing table support to be able to store 'exnref' in
addition to 'anyref' types. Tools can use this to maintain data
structures for exception packages.

R=ahaas@chromium.org
TEST=mjsunit/wasm/exceptions-anyref
BUG=v8:8091

Change-Id: Iccbcfdc328db81a366921bcdd98c2256f66e7fc8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1781046
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64323}
This commit is contained in:
Michael Starzinger 2019-10-16 15:34:08 +02:00 committed by Commit Bot
parent c2e95a362a
commit 5fbeb5c5bd
5 changed files with 64 additions and 9 deletions

View File

@ -3489,7 +3489,8 @@ void WasmGraphBuilder::GetTableBaseAndOffset(uint32_t table_index,
Node* WasmGraphBuilder::TableGet(uint32_t table_index, Node* index,
wasm::WasmCodePosition position) {
if (env_->module->tables[table_index].type == wasm::kWasmAnyRef) {
if (env_->module->tables[table_index].type == wasm::kWasmAnyRef ||
env_->module->tables[table_index].type == wasm::kWasmExnRef) {
Node* base = nullptr;
Node* offset = nullptr;
GetTableBaseAndOffset(table_index, index, position, &base, &offset);
@ -3518,7 +3519,8 @@ Node* WasmGraphBuilder::TableGet(uint32_t table_index, Node* index,
Node* WasmGraphBuilder::TableSet(uint32_t table_index, Node* index, Node* val,
wasm::WasmCodePosition position) {
if (env_->module->tables[table_index].type == wasm::kWasmAnyRef) {
if (env_->module->tables[table_index].type == wasm::kWasmAnyRef ||
env_->module->tables[table_index].type == wasm::kWasmExnRef) {
Node* base = nullptr;
Node* offset = nullptr;
GetTableBaseAndOffset(table_index, index, position, &base, &offset);

View File

@ -1635,6 +1635,12 @@ class ModuleDecoderImpl : public Decoder {
"Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
}
return kWasmAnyRef;
case kLocalExnRef:
if (!enabled_features_.eh) {
error(pc_ - 1,
"Invalid type. Set --experimental-wasm-eh to use 'ExnRef'");
}
return kWasmExnRef;
default:
break;
}

View File

@ -529,8 +529,11 @@ bool WasmTableObject::IsInBounds(Isolate* isolate,
bool WasmTableObject::IsValidElement(Isolate* isolate,
Handle<WasmTableObject> table,
Handle<Object> entry) {
// Anyref tables take everything.
if (table->type() == wasm::kWasmAnyRef) return true;
// Anyref and exnref tables take everything.
if (table->type() == wasm::kWasmAnyRef ||
table->type() == wasm::kWasmExnRef) {
return true;
}
// FuncRef tables can store {null}, {WasmExportedFunction}, {WasmJSFunction},
// or {WasmCapiFunction} objects.
if (entry->IsNull(isolate)) return true;
@ -548,7 +551,8 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
Handle<FixedArray> entries(table->entries(), isolate);
// The FixedArray is addressed with int's.
int entry_index = static_cast<int>(index);
if (table->type() == wasm::kWasmAnyRef) {
if (table->type() == wasm::kWasmAnyRef ||
table->type() == wasm::kWasmExnRef) {
entries->set(entry_index, *entry);
return;
}
@ -592,8 +596,11 @@ Handle<Object> WasmTableObject::Get(Isolate* isolate,
Handle<Object> entry(entries->get(entry_index), isolate);
// First we handle the easy anyref table case.
if (table->type() == wasm::kWasmAnyRef) return entry;
// First we handle the easy anyref and exnref table case.
if (table->type() == wasm::kWasmAnyRef ||
table->type() == wasm::kWasmExnRef) {
return entry;
}
// Now we handle the funcref case.
if (WasmExportedFunction::IsWasmExportedFunction(*entry) ||

View File

@ -143,3 +143,42 @@ load("test/mjsunit/wasm/exceptions-utils.js");
assertEquals(2.3, instance.exports.throw_catch_param(2.3));
assertEquals("str", instance.exports.throw_catch_param("str"));
})();
// Test storing and loading to/from an exception type table.
(function TestTableExnRef() {
let kSig_e_i = makeSig([kWasmI32], [kWasmExnRef]);
let kSig_v_ie = makeSig([kWasmI32, kWasmExnRef], []);
let builder = new WasmModuleBuilder();
let table = builder.addTable(kWasmExnRef, 2).exportAs("table");
builder.addFunction("table_load", kSig_e_i)
.addBody([
kExprLocalGet, 0,
kExprTableGet, table.index
]).exportFunc();
builder.addFunction("table_store", kSig_v_ie)
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprTableSet, table.index
]).exportFunc();
let instance = builder.instantiate();
let e0 = new Error("my encapsulated error");
let e1 = new Error("my other encapsulated error");
assertNull(instance.exports.table_load(0));
assertNull(instance.exports.table_load(1));
assertNull(instance.exports.table.get(0));
assertNull(instance.exports.table.get(1));
instance.exports.table_store(0, e0);
assertSame(e0, instance.exports.table_load(0));
assertNull(instance.exports.table_load(1));
assertSame(e0, instance.exports.table.get(0));
assertNull(instance.exports.table.get(1));
instance.exports.table.set(1, e1);
assertSame(e0, instance.exports.table_load(0));
assertSame(e1, instance.exports.table_load(1));
assertSame(e0, instance.exports.table.get(0));
assertSame(e1, instance.exports.table.get(1));
})();

View File

@ -799,8 +799,9 @@ class WasmModuleBuilder {
}
addTable(type, initial_size, max_size = undefined) {
if (type != kWasmAnyRef && type != kWasmAnyFunc) {
throw new Error('Tables must be of type kWasmAnyRef or kWasmAnyFunc');
if (type != kWasmAnyRef && type != kWasmAnyFunc && type != kWasmExnRef) {
throw new Error(
'Tables must be of type kWasmAnyRef, kWasmAnyFunc, or kWasmExnRef');
}
let table = new WasmTableBuilder(this, type, initial_size, max_size);
table.index = this.tables.length + this.num_imported_tables;