[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/+/3644961 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Andy Wingo <wingo@igalia.com> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#80648}
This commit is contained in:
parent
59cd199d51
commit
e43a2540ab
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user