Commit 5fbeb5c5 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[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: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64323}
parent c2e95a36
......@@ -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);
......
......@@ -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;
}
......
......@@ -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) ||
......
......@@ -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));
})();
......@@ -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;
......
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