[wasm] Remove IndirectFunctionTableEntry

Since the indirect function table at index 0 in an instance is now
represented like the other tables, the IndirectFunctionTableEntry
abstraction is no more useful. We replace it with direct access to the
tables and a simpler abstraction {FunctionTargetAndRef}.

Bug: v8:11510
Change-Id: Iab4a6ca7eda8eb1757dbd321cb3997e98e78267e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3247030
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77754}
This commit is contained in:
Manos Koukoutos 2021-11-08 05:06:01 +00:00 committed by V8 LUCI CQ
parent 04899013ba
commit 5bf06b536d
6 changed files with 90 additions and 140 deletions

View File

@ -1185,9 +1185,10 @@ bool InstanceBuilder::InitializeImportedIndirectFunctionTable(
// Look up the signature's canonical id. If there is no canonical
// id, then the signature does not appear at all in this module,
// so putting {-1} in the table will cause checks to always fail.
IndirectFunctionTableEntry(instance, table_index, i)
.Set(module_->signature_map.Find(*sig), target_instance,
function_index);
FunctionTargetAndRef entry(target_instance, function_index);
instance->GetIndirectFunctionTable(isolate_, table_index)
->Set(i, module_->signature_map.Find(*sig), entry.call_target(),
*entry.ref());
}
return true;
}
@ -1869,7 +1870,8 @@ void SetNullTableEntry(Isolate* isolate, Handle<WasmInstanceObject> instance,
uint32_t table_index, uint32_t entry_index) {
const WasmModule* module = instance->module();
if (IsSubtypeOf(table_object->type(), kWasmFuncRef, module)) {
IndirectFunctionTableEntry(instance, table_index, entry_index).clear();
instance->GetIndirectFunctionTable(isolate, table_index)
->Clear(entry_index);
}
WasmTableObject::Set(isolate, table_object, entry_index,
isolate->factory()->null_value());
@ -1896,8 +1898,9 @@ void SetFunctionTableEntry(Isolate* isolate,
// Update the local dispatch table first if necessary.
uint32_t sig_id = module->canonicalized_type_ids[function->sig_index];
IndirectFunctionTableEntry(instance, table_index, entry_index)
.Set(sig_id, instance, func_index);
FunctionTargetAndRef entry(instance, func_index);
instance->GetIndirectFunctionTable(isolate, table_index)
->Set(entry_index, sig_id, entry.call_target(), *entry.ref());
// Update the table object's other dispatch tables.
MaybeHandle<WasmExternalFunction> wasm_external_function =

View File

@ -269,22 +269,6 @@ void WasmInstanceObject::clear_padding() {
}
}
IndirectFunctionTableEntry::IndirectFunctionTableEntry(
Handle<WasmInstanceObject> instance, int table_index, int entry_index)
: IndirectFunctionTableEntry(
handle(WasmIndirectFunctionTable::cast(
instance->indirect_function_tables().get(table_index)),
instance->GetIsolate()),
entry_index) {}
IndirectFunctionTableEntry::IndirectFunctionTableEntry(
Handle<WasmIndirectFunctionTable> table, int entry_index)
: table_(table), index_(entry_index) {
DCHECK(!table->is_null());
DCHECK_GE(entry_index, 0);
DCHECK_LT(entry_index, table_->size());
}
ImportedFunctionEntry::ImportedFunctionEntry(
Handle<WasmInstanceObject> instance, int index)
: instance_(instance), index_(index) {

View File

@ -319,8 +319,8 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
Handle<WasmInstanceObject> instance(
WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
DCHECK_EQ(old_size, WasmInstanceObject::IndirectFunctionTableSize(
isolate, instance, table_index));
DCHECK_EQ(old_size,
instance->GetIndirectFunctionTable(isolate, table_index)->size());
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
instance, table_index, new_size);
}
@ -513,8 +513,9 @@ void WasmTableObject::UpdateDispatchTables(
// Note that {SignatureMap::Find} may return {-1} if the signature is
// not found; it will simply never match any check.
auto sig_id = instance->module()->signature_map.Find(*sig);
IndirectFunctionTableEntry(instance, table_index, entry_index)
.Set(sig_id, target_instance, target_func_index);
FunctionTargetAndRef entry(target_instance, target_func_index);
instance->GetIndirectFunctionTable(isolate, table_index)
->Set(entry_index, sig_id, entry.call_target(), *entry.ref());
}
}
@ -594,11 +595,11 @@ void WasmTableObject::UpdateDispatchTables(
// Note that {SignatureMap::Find} may return {-1} if the signature is
// not found; it will simply never match any check.
auto sig_id = instance->module()->signature_map.Find(sig);
IndirectFunctionTableEntry(instance, table_index, entry_index)
.Set(sig_id, wasm_code->instruction_start(),
WasmCapiFunctionData::cast(
capi_function->shared().function_data(kAcquireLoad))
.ref());
instance->GetIndirectFunctionTable(isolate, table_index)
->Set(entry_index, sig_id, wasm_code->instruction_start(),
WasmCapiFunctionData::cast(
capi_function->shared().function_data(kAcquireLoad))
.ref());
}
}
@ -615,9 +616,10 @@ void WasmTableObject::ClearDispatchTables(Isolate* isolate,
WasmInstanceObject::cast(
dispatch_tables->get(i + kDispatchTableInstanceOffset)),
isolate);
DCHECK_LT(index, WasmInstanceObject::IndirectFunctionTableSize(
isolate, target_instance, table_index));
IndirectFunctionTableEntry(target_instance, table_index, index).clear();
Handle<WasmIndirectFunctionTable> table =
target_instance->GetIndirectFunctionTable(isolate, table_index);
DCHECK_LT(index, table->size());
table->Clear(index);
}
}
@ -709,10 +711,24 @@ Handle<WasmIndirectFunctionTable> WasmIndirectFunctionTable::New(
isolate, IftNativeAllocations::SizeInMemory(size), table, size);
table->set_managed_native_allocations(*native_allocations);
for (uint32_t i = 0; i < size; ++i) {
IndirectFunctionTableEntry(table, static_cast<int>(i)).clear();
table->Clear(i);
}
return table;
}
void WasmIndirectFunctionTable::Set(uint32_t index, int sig_id,
Address call_target, Object ref) {
sig_ids()[index] = sig_id;
targets()[index] = call_target;
refs().set(index, ref);
}
void WasmIndirectFunctionTable::Clear(uint32_t index) {
sig_ids()[index] = -1;
targets()[index] = 0;
refs().set(
index,
ReadOnlyRoots(GetIsolateFromWritableObject(*this)).undefined_value());
}
void WasmIndirectFunctionTable::Resize(Isolate* isolate,
Handle<WasmIndirectFunctionTable> table,
@ -730,7 +746,7 @@ void WasmIndirectFunctionTable::Resize(Isolate* isolate,
table->set_refs(*new_refs);
table->set_size(new_size);
for (uint32_t i = old_size; i < new_size; ++i) {
IndirectFunctionTableEntry(table, static_cast<int>(i)).clear();
table->Clear(i);
}
}
@ -1026,56 +1042,21 @@ MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
return global_obj;
}
void IndirectFunctionTableEntry::clear() {
table_->sig_ids()[index_] = -1;
table_->targets()[index_] = 0;
table_->refs().set(
index_,
ReadOnlyRoots(GetIsolateFromWritableObject(*table_)).undefined_value());
}
void IndirectFunctionTableEntry::Set(int sig_id,
Handle<WasmInstanceObject> target_instance,
int target_func_index) {
TRACE_IFT(
"IFT entry 0x%" PRIxPTR "[%d] = {sig_id=%d, target_instance=0x%" PRIxPTR
", target_func_index=%d}\n",
table_->ptr(), index_, sig_id, target_instance->ptr(), target_func_index);
Object ref;
Address call_target = 0;
FunctionTargetAndRef::FunctionTargetAndRef(
Handle<WasmInstanceObject> target_instance, int target_func_index) {
Isolate* isolate = target_instance->native_context().GetIsolate();
if (target_func_index <
static_cast<int>(target_instance->module()->num_imported_functions)) {
// The function in the target instance was imported. Use its imports table,
// which contains a tuple needed by the import wrapper.
ImportedFunctionEntry entry(target_instance, target_func_index);
ref = entry.object_ref();
call_target = entry.target();
ref_ = handle(entry.object_ref(), isolate);
call_target_ = entry.target();
} else {
// The function in the target instance was not imported.
ref = *target_instance;
call_target = target_instance->GetCallTarget(target_func_index);
ref_ = target_instance;
call_target_ = target_instance->GetCallTarget(target_func_index);
}
Set(sig_id, call_target, ref);
}
void IndirectFunctionTableEntry::Set(int sig_id, Address call_target,
Object ref) {
table_->sig_ids()[index_] = sig_id;
table_->targets()[index_] = call_target;
table_->refs().set(index_, ref);
}
Object IndirectFunctionTableEntry::object_ref() const {
return table_->refs().get(index_);
}
int IndirectFunctionTableEntry::sig_id() const {
return table_->sig_ids()[index_];
}
Address IndirectFunctionTableEntry::target() const {
return table_->targets()[index_];
}
void ImportedFunctionEntry::SetWasmToJs(
@ -1132,10 +1113,8 @@ bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
uint32_t minimum_size) {
Isolate* isolate = instance->GetIsolate();
DCHECK_LT(table_index, instance->indirect_function_tables().length());
auto table =
handle(WasmIndirectFunctionTable::cast(
instance->indirect_function_tables().get(table_index)),
isolate);
Handle<WasmIndirectFunctionTable> table =
instance->GetIndirectFunctionTable(isolate, table_index);
WasmIndirectFunctionTable::Resize(isolate, table, minimum_size);
if (table_index == 0) {
instance->SetIndirectFunctionTableShortcuts(isolate);
@ -1295,13 +1274,20 @@ Address WasmInstanceObject::GetCallTarget(uint32_t func_index) {
return native_module->GetCallTargetForFunction(func_index);
}
Handle<WasmIndirectFunctionTable> WasmInstanceObject::GetIndirectFunctionTable(
Isolate* isolate, uint32_t table_index) {
DCHECK_LT(table_index, indirect_function_tables().length());
return handle(WasmIndirectFunctionTable::cast(
indirect_function_tables().get(table_index)),
isolate);
}
void WasmInstanceObject::SetIndirectFunctionTableShortcuts(Isolate* isolate) {
if (indirect_function_tables().length() > 0 &&
indirect_function_tables().get(0).IsWasmIndirectFunctionTable()) {
HandleScope scope(isolate);
auto table0 = handle(
WasmIndirectFunctionTable::cast(indirect_function_tables().get(0)),
isolate);
Handle<WasmIndirectFunctionTable> table0 =
GetIndirectFunctionTable(isolate, 0);
set_indirect_function_table_size(table0->size());
set_indirect_function_table_refs(table0->refs());
set_indirect_function_table_sig_ids(table0->sig_ids());
@ -1309,16 +1295,6 @@ void WasmInstanceObject::SetIndirectFunctionTableShortcuts(Isolate* isolate) {
}
}
int WasmInstanceObject::IndirectFunctionTableSize(
Isolate* isolate, Handle<WasmInstanceObject> instance,
uint32_t table_index) {
auto table =
handle(WasmIndirectFunctionTable::cast(
instance->indirect_function_tables().get(table_index)),
isolate);
return table->size();
}
// static
bool WasmInstanceObject::CopyTableEntries(Isolate* isolate,
Handle<WasmInstanceObject> instance,
@ -1494,8 +1470,9 @@ void WasmInstanceObject::ImportWasmJSFunctionIntoTable(
// Update the dispatch table.
Handle<WasmApiFunctionRef> ref =
isolate->factory()->NewWasmApiFunctionRef(callable);
IndirectFunctionTableEntry(instance, table_index, entry_index)
.Set(sig_id, call_target, *ref);
WasmIndirectFunctionTable::cast(
instance->indirect_function_tables().get(table_index))
.Set(entry_index, sig_id, call_target, *ref);
}
// static

View File

@ -61,33 +61,16 @@ class Managed;
DECL_GETTER(has_##name, bool) \
DECL_ACCESSORS(name, type)
// A helper for an entry in an indirect function table (IFT).
// The underlying storage in the instance is used by generated code to
// call functions indirectly at runtime.
// Each entry has the following fields:
// - object = target instance, if a Wasm function, tuple if imported
// - sig_id = signature id of function
// - target = entrypoint to Wasm code or import wrapper code
class V8_EXPORT_PRIVATE IndirectFunctionTableEntry {
class V8_EXPORT_PRIVATE FunctionTargetAndRef {
public:
inline IndirectFunctionTableEntry(Handle<WasmInstanceObject>, int table_index,
int entry_index);
inline IndirectFunctionTableEntry(Handle<WasmIndirectFunctionTable> table,
int entry_index);
void clear();
void Set(int sig_id, Handle<WasmInstanceObject> target_instance,
int target_func_index);
void Set(int sig_id, Address call_target, Object ref);
Object object_ref() const;
int sig_id() const;
Address target() const;
FunctionTargetAndRef(Handle<WasmInstanceObject> target_instance,
int target_func_index);
Handle<Object> ref() { return ref_; }
Address call_target() { return call_target_; }
private:
Handle<WasmIndirectFunctionTable> const table_;
int const index_;
Handle<Object> ref_;
Address call_target_;
};
// A helper for an entry for an imported function, indexed statically.
@ -478,11 +461,10 @@ class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject {
Address GetCallTarget(uint32_t func_index);
void SetIndirectFunctionTableShortcuts(Isolate* isolate);
Handle<WasmIndirectFunctionTable> GetIndirectFunctionTable(
Isolate*, uint32_t table_index);
static int IndirectFunctionTableSize(Isolate* isolate,
Handle<WasmInstanceObject> instance,
uint32_t table_index);
void SetIndirectFunctionTableShortcuts(Isolate* isolate);
// Copies table entries. Returns {false} if the ranges are out-of-bounds.
static bool CopyTableEntries(Isolate* isolate,
@ -695,6 +677,9 @@ class WasmIndirectFunctionTable
Isolate* isolate, uint32_t size);
static void Resize(Isolate* isolate, Handle<WasmIndirectFunctionTable> table,
uint32_t new_size);
V8_EXPORT_PRIVATE void Set(uint32_t index, int sig_id, Address call_target,
Object ref);
void Clear(uint32_t index);
DECL_PRINTER(WasmIndirectFunctionTable)

View File

@ -231,8 +231,9 @@ void TestingModuleBuilder::AddIndirectFunctionTable(
for (uint32_t i = 0; i < table_size; ++i) {
WasmFunction& function = test_module_->functions[function_indexes[i]];
int sig_id = test_module_->signature_map.Find(*function.sig);
IndirectFunctionTableEntry(instance, table_index, i)
.Set(sig_id, instance, function.func_index);
FunctionTargetAndRef entry(instance, function.func_index);
instance->GetIndirectFunctionTable(isolate_, table_index)
->Set(i, sig_id, entry.call_target(), *entry.ref());
WasmTableObject::SetFunctionTablePlaceholder(
isolate_, table_obj, i, instance_object_, function_indexes[i]);
}

View File

@ -4094,21 +4094,20 @@ class WasmInterpreterInternals {
uint32_t expected_sig_id = module()->canonicalized_type_ids[sig_index];
DCHECK_EQ(expected_sig_id,
module()->signature_map.Find(*module()->signature(sig_index)));
// Bounds check against table size.
if (entry_index >=
static_cast<uint32_t>(WasmInstanceObject::IndirectFunctionTableSize(
isolate_, instance_object_, table_index))) {
return {CallResult::INVALID_FUNC};
}
IndirectFunctionTableEntry entry(instance_object_, table_index,
entry_index);
Handle<WasmIndirectFunctionTable> table =
instance_object_->GetIndirectFunctionTable(isolate_, table_index);
// Bounds check against table size.
if (entry_index >= table->size()) return {CallResult::INVALID_FUNC};
// Signature check.
if (entry.sig_id() != static_cast<int32_t>(expected_sig_id)) {
if (table->sig_ids()[entry_index] != expected_sig_id) {
return {CallResult::SIGNATURE_MISMATCH};
}
Handle<Object> object_ref = handle(entry.object_ref(), isolate_);
Handle<Object> object_ref =
handle(table->refs().get(entry_index), isolate_);
// Check that this is an internal call (within the same instance).
CHECK(object_ref->IsWasmInstanceObject() &&
instance_object_.is_identical_to(object_ref));
@ -4118,13 +4117,14 @@ class WasmInterpreterInternals {
#ifdef DEBUG
{
WasmCodeRefScope code_ref_scope;
WasmCode* wasm_code = native_module->Lookup(entry.target());
WasmCode* wasm_code =
native_module->Lookup(table->targets()[entry_index]);
DCHECK_EQ(native_module, wasm_code->native_module());
DCHECK_EQ(WasmCode::kJumpTable, wasm_code->kind());
}
#endif
uint32_t func_index =
native_module->GetFunctionIndexFromJumpTableSlot(entry.target());
uint32_t func_index = native_module->GetFunctionIndexFromJumpTableSlot(
table->targets()[entry_index]);
return {CallResult::INTERNAL, codemap_.GetCode(func_index)};
}