Commit e43a2540 authored by Andy Wingo's avatar Andy Wingo Committed by V8 LUCI CQ

[wasm] table.get, set only calls out to C++ for function tables

Avoid a run-time dispatch for tables that don't contain subtypes of
funcref.

Change-Id: I27a55c378b0a4fcd98e77f8ff45ae9972c9d095a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3644961Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Andy Wingo <wingo@igalia.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80648}
parent 59cd199d
......@@ -168,6 +168,49 @@ builtin WasmTableGrow(table: Smi, deltaRaw: uint32, value: Object): Smi {
}
builtin WasmTableGet(tableIndex: intptr, index: int32): Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const entryIndex: intptr = ChangeInt32ToIntPtr(index);
try {
dcheck(IsValidPositiveSmi(tableIndex));
if (!IsValidPositiveSmi(entryIndex)) goto IndexOutOfRange;
const tables: FixedArray = LoadTablesFromInstance(instance);
const table: WasmTableObject = %RawDownCast<WasmTableObject>(
LoadFixedArrayElement(tables, tableIndex));
const entriesCount: intptr = Convert<intptr, Smi>(table.current_length);
if (entryIndex >= entriesCount) goto IndexOutOfRange;
const entries: FixedArray = table.entries;
const entry: Object = LoadFixedArrayElement(entries, entryIndex);
return entry;
} label IndexOutOfRange deferred {
tail ThrowWasmTrapTableOutOfBounds();
}
}
builtin WasmTableSet(tableIndex: intptr, index: int32, value: Object): Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const entryIndex: intptr = ChangeInt32ToIntPtr(index);
try {
dcheck(IsValidPositiveSmi(tableIndex));
if (!IsValidPositiveSmi(entryIndex)) goto IndexOutOfRange;
const tables: FixedArray = LoadTablesFromInstance(instance);
const table: WasmTableObject = %RawDownCast<WasmTableObject>(
LoadFixedArrayElement(tables, tableIndex));
const entriesCount: intptr = Convert<intptr, Smi>(table.current_length);
if (entryIndex >= entriesCount) goto IndexOutOfRange;
const entries: FixedArray = table.entries;
StoreFixedArrayElement(entries, entryIndex, value);
return Undefined;
} label IndexOutOfRange deferred {
tail ThrowWasmTrapTableOutOfBounds();
}
}
builtin WasmTableGetFuncRef(tableIndex: intptr, index: int32): Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const entryIndex: intptr = ChangeInt32ToIntPtr(index);
try {
......@@ -200,7 +243,8 @@ builtin WasmTableGet(tableIndex: intptr, index: int32): Object {
}
}
builtin WasmTableSet(tableIndex: intptr, index: int32, value: Object): Object {
builtin WasmTableSetFuncRef(
tableIndex: intptr, index: int32, value: Object): Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const entryIndex: intptr = ChangeInt32ToIntPtr(index);
try {
......@@ -211,22 +255,9 @@ builtin WasmTableSet(tableIndex: intptr, index: int32, value: Object): Object {
const table: WasmTableObject = %RawDownCast<WasmTableObject>(
LoadFixedArrayElement(tables, tableIndex));
// Fall back to the runtime to set funcrefs, since we have to update
// function dispatch tables.
// TODO(7748): Update this if further table types are supported.
const tableType: Smi = table.raw_type;
if (tableType != SmiConstant(kAnyTableType) &&
tableType != SmiConstant(kAnyNonNullTableType)) {
goto CallRuntime;
}
const entriesCount: intptr = Convert<intptr, Smi>(table.current_length);
if (entryIndex >= entriesCount) goto IndexOutOfRange;
const entries: FixedArray = table.entries;
StoreFixedArrayElement(entries, entryIndex, value);
return Undefined;
} label CallRuntime deferred {
tail runtime::WasmFunctionTableSet(
LoadContextFromInstance(instance), instance, SmiFromIntPtr(tableIndex),
SmiFromIntPtr(entryIndex), value);
......
......@@ -620,6 +620,7 @@ ZoneUnorderedSet<Node*>* LoopFinder::FindSmallInnermostLoopFromHeader(
WasmCode::kWasmStackGuard,
// Fast table operations.
WasmCode::kWasmTableGet, WasmCode::kWasmTableSet,
WasmCode::kWasmTableGetFuncRef, WasmCode::kWasmTableSetFuncRef,
WasmCode::kWasmTableGrow,
// Atomics.
WasmCode::kWasmAtomicNotify, WasmCode::kWasmI32AtomicWait32,
......
......@@ -3300,14 +3300,23 @@ void WasmGraphBuilder::GlobalSet(uint32_t index, Node* val) {
Node* WasmGraphBuilder::TableGet(uint32_t table_index, Node* index,
wasm::WasmCodePosition position) {
return gasm_->CallRuntimeStub(wasm::WasmCode::kWasmTableGet,
Operator::kNoThrow,
const wasm::WasmTable& table = env_->module->tables[table_index];
bool is_funcref = IsSubtypeOf(table.type, wasm::kWasmFuncRef, env_->module);
auto stub = is_funcref ? wasm::WasmCode::kWasmTableGetFuncRef
: wasm::WasmCode::kWasmTableGet;
return gasm_->CallRuntimeStub(stub, Operator::kNoThrow,
gasm_->IntPtrConstant(table_index), index);
}
void WasmGraphBuilder::TableSet(uint32_t table_index, Node* index, Node* val,
wasm::WasmCodePosition position) {
gasm_->CallRuntimeStub(wasm::WasmCode::kWasmTableSet, Operator::kNoThrow,
const wasm::WasmTable& table = env_->module->tables[table_index];
bool is_funcref = IsSubtypeOf(table.type, wasm::kWasmFuncRef, env_->module);
auto stub = is_funcref ? wasm::WasmCode::kWasmTableSetFuncRef
: wasm::WasmCode::kWasmTableSet;
gasm_->CallRuntimeStub(stub, Operator::kNoThrow,
gasm_->IntPtrConstant(table_index), index, val);
}
......
......@@ -462,6 +462,13 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableSet) {
DCHECK_LT(table_index, instance->tables().length());
auto table = handle(
WasmTableObject::cast(instance->tables().get(table_index)), isolate);
// We only use the runtime call for lazily initialized function references.
DCHECK(
table->instance().IsUndefined()
? table->type() == wasm::kWasmFuncRef
: IsSubtypeOf(table->type(), wasm::kWasmFuncRef,
WasmInstanceObject::cast(table->instance()).module()));
if (!WasmTableObject::IsInBounds(isolate, table, entry_index)) {
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
}
......
......@@ -2488,9 +2488,13 @@ class LiftoffCompiler {
LiftoffAssembler::VarState index = __ cache_state()->stack_state.back();
ValueKind result_kind = env_->module->tables[imm.index].type.kind();
CallRuntimeStub(WasmCode::kWasmTableGet,
MakeSig::Returns(result_kind).Params(kI32, kI32),
auto& table = env_->module->tables[imm.index];
ValueKind table_kind = table.type.kind();
bool is_funcref = IsSubtypeOf(table.type, kWasmFuncRef, env_->module);
auto stub =
is_funcref ? WasmCode::kWasmTableGetFuncRef : WasmCode::kWasmTableGet;
CallRuntimeStub(stub, MakeSig::Returns(table_kind).Params(kI32, kI32),
{table_index, index}, decoder->position());
// Pop parameters from the value stack.
......@@ -2498,7 +2502,7 @@ class LiftoffCompiler {
RegisterDebugSideTableEntry(decoder, DebugSideTableBuilder::kDidSpill);
__ PushRegister(result_kind, LiftoffRegister(kReturnRegister0));
__ PushRegister(table_kind, LiftoffRegister(kReturnRegister0));
}
void TableSet(FullDecoder* decoder, const Value&, const Value&,
......@@ -2513,10 +2517,13 @@ class LiftoffCompiler {
LiftoffAssembler::VarState value = __ cache_state()->stack_state.end()[-1];
LiftoffAssembler::VarState index = __ cache_state()->stack_state.end()[-2];
ValueKind table_kind = env_->module->tables[imm.index].type.kind();
auto& table = env_->module->tables[imm.index];
ValueKind table_kind = table.type.kind();
bool is_funcref = IsSubtypeOf(table.type, kWasmFuncRef, env_->module);
auto stub =
is_funcref ? WasmCode::kWasmTableSetFuncRef : WasmCode::kWasmTableSet;
CallRuntimeStub(WasmCode::kWasmTableSet,
MakeSig::Params(kI32, kI32, table_kind),
CallRuntimeStub(stub, MakeSig::Params(kI32, kI32, table_kind),
{table_index, index, value}, decoder->position());
// Pop parameters from the value stack.
......
......@@ -75,6 +75,8 @@ struct WasmModule;
V(WasmTableGrow) \
V(WasmTableGet) \
V(WasmTableSet) \
V(WasmTableGetFuncRef) \
V(WasmTableSetFuncRef) \
V(WasmStackGuard) \
V(WasmStackOverflow) \
V(WasmAllocateFixedArray) \
......
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