Commit c65c71b5 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[wasm] Avoid signature map lookup if possible

When updating the dispatch tables, the other instances are often
generated from the same wire bytes, or there is only the one original
instance in that list of instances. In both cases we can avoid the
costly hash table lookup, and just use the signature index from the
originating module.

For big modules, this saves more than 50% of time for updating the
dispatch tables, and ~25% of overall instantiation time.

R=manoskouk@chromium.org

Bug: v8:12593
Change-Id: I356d5dd10f6c0738330e9a8d1cb27f60ff21215a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3432212Reviewed-by: 's avatarManos Koukoutos <manoskouk@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78941}
parent 75a8335d
......@@ -1909,7 +1909,7 @@ V8_INLINE void SetFunctionTablePlaceholder(Isolate* isolate,
*wasm_internal_function.ToHandleChecked());
}
WasmTableObject::UpdateDispatchTables(isolate, *table_object, entry_index,
function->sig, *instance, func_index);
function, *instance);
}
V8_INLINE void SetFunctionTableNullEntry(Isolate* isolate,
......
......@@ -356,10 +356,8 @@ void WasmTableObject::SetFunctionTableEntry(Isolate* isolate,
isolate);
int func_index = exported_function->function_index();
auto* wasm_function = &target_instance->module()->functions[func_index];
DCHECK_NOT_NULL(wasm_function);
DCHECK_NOT_NULL(wasm_function->sig);
UpdateDispatchTables(isolate, *table, entry_index, wasm_function->sig,
*target_instance, func_index);
UpdateDispatchTables(isolate, *table, entry_index, wasm_function,
*target_instance);
} else if (WasmJSFunction::IsWasmJSFunction(*external)) {
UpdateDispatchTables(isolate, table, entry_index,
Handle<WasmJSFunction>::cast(external));
......@@ -481,9 +479,8 @@ void WasmTableObject::Fill(Isolate* isolate, Handle<WasmTableObject> table,
void WasmTableObject::UpdateDispatchTables(Isolate* isolate,
WasmTableObject table,
int entry_index,
const wasm::FunctionSig* sig,
WasmInstanceObject target_instance,
int target_func_index) {
const wasm::WasmFunction* func,
WasmInstanceObject target_instance) {
DisallowGarbageCollection no_gc;
// We simply need to update the IFTs for each instance that imports
......@@ -492,14 +489,15 @@ void WasmTableObject::UpdateDispatchTables(Isolate* isolate,
DCHECK_EQ(0, dispatch_tables.length() % kDispatchTableNumElements);
Object call_ref =
target_func_index <
static_cast<int>(target_instance.module()->num_imported_functions)
func->imported
// The function in the target instance was imported. Use its imports
// table, which contains a tuple needed by the import wrapper.
? target_instance.imported_function_refs().get(target_func_index)
? target_instance.imported_function_refs().get(func->func_index)
// For wasm functions, just pass the target instance.
: target_instance;
Address call_target = target_instance.GetCallTarget(target_func_index);
Address call_target = target_instance.GetCallTarget(func->func_index);
int original_sig_id = func->sig_index;
for (int i = 0, len = dispatch_tables.length(); i < len;
i += kDispatchTableNumElements) {
......@@ -507,9 +505,21 @@ void WasmTableObject::UpdateDispatchTables(Isolate* isolate,
Smi::cast(dispatch_tables.get(i + kDispatchTableIndexOffset)).value();
WasmInstanceObject instance = WasmInstanceObject::cast(
dispatch_tables.get(i + kDispatchTableInstanceOffset));
// 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);
const WasmModule* module = instance.module();
// Try to avoid the signature map lookup by checking if the signature in
// {module} at {original_sig_id} matches {func->sig}.
int sig_id;
// TODO(7748): wasm-gc signatures cannot be canonicalized this way because
// references could wrongly be detected as identical.
if (module->has_signature(original_sig_id) &&
*module->signature(original_sig_id) == *func->sig) {
sig_id = module->canonicalized_type_ids[original_sig_id];
DCHECK_EQ(sig_id, module->signature_map.Find(*func->sig));
} else {
// Note that {SignatureMap::Find} may return {-1} if the signature is
// not found; it will simply never match any check.
sig_id = module->signature_map.Find(*func->sig);
}
WasmIndirectFunctionTable ift = WasmIndirectFunctionTable::cast(
instance.indirect_function_tables().get(table_index));
ift.Set(entry_index, sig_id, call_target, call_ref);
......
......@@ -32,6 +32,7 @@ namespace wasm {
class InterpretedFrame;
class NativeModule;
class WasmCode;
struct WasmFunction;
struct WasmGlobal;
struct WasmModule;
struct WasmTag;
......@@ -204,9 +205,8 @@ class WasmTableObject
// TODO(wasm): Unify these three methods into one.
static void UpdateDispatchTables(Isolate* isolate, WasmTableObject table,
int entry_index,
const wasm::FunctionSig* sig,
WasmInstanceObject target_instance,
int target_func_index);
const wasm::WasmFunction* func,
WasmInstanceObject target_instance);
static void UpdateDispatchTables(Isolate* isolate,
Handle<WasmTableObject> table,
int entry_index,
......
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