Commit 3b59a3dd authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Refactor all call targets to be Addresses

With the introduction of a jump table, call targets will not be
{WasmCode} objects any more. Instead, we just call any {Address}.
This CL does not change anything yet, but changes interfaces to accept
an {Address} instead of {WasmCode*}.

R=titzer@chromium.org

Bug: v8:7758
Change-Id: Id299738bb7cc6a1891e4a03d7f67c24cde6d1699
Reviewed-on: https://chromium-review.googlesource.com/1058793
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53191}
parent 37e9017f
...@@ -4298,7 +4298,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -4298,7 +4298,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
return instance; return instance;
} }
void BuildJSToWasmWrapper(wasm::WasmCode* wasm_code) { void BuildJSToWasmWrapper(Address call_target) {
const int wasm_count = static_cast<int>(sig_->parameter_count()); const int wasm_count = static_cast<int>(sig_->parameter_count());
const int count = const int count =
wasm_count + 4; // wasm_code, instance_node, effect, and control. wasm_count + 4; // wasm_code, instance_node, effect, and control.
...@@ -4327,10 +4327,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -4327,10 +4327,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
DCHECK_NULL(instance_node_); DCHECK_NULL(instance_node_);
instance_node_ = BuildLoadInstanceFromExportedFunction(js_closure); instance_node_ = BuildLoadInstanceFromExportedFunction(js_closure);
Address instr_start =
wasm_code == nullptr ? kNullAddress : wasm_code->instruction_start();
Node* wasm_code_node = mcgraph()->RelocatableIntPtrConstant( Node* wasm_code_node = mcgraph()->RelocatableIntPtrConstant(
instr_start, RelocInfo::JS_TO_WASM_CALL); call_target, RelocInfo::JS_TO_WASM_CALL);
if (!wasm::IsJSCompatibleSignature(sig_)) { if (!wasm::IsJSCompatibleSignature(sig_)) {
// Throw a TypeError. Use the js_context of the calling javascript // Throw a TypeError. Use the js_context of the calling javascript
// function (passed as a parameter), such that the generated code is // function (passed as a parameter), such that the generated code is
...@@ -4691,7 +4689,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -4691,7 +4689,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
} // namespace } // namespace
Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module, Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
wasm::WasmCode* wasm_code, uint32_t index, Address call_target, uint32_t index,
wasm::UseTrapHandler use_trap_handler) { wasm::UseTrapHandler use_trap_handler) {
const wasm::WasmFunction* func = &module->functions[index]; const wasm::WasmFunction* func = &module->functions[index];
...@@ -4714,7 +4712,7 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module, ...@@ -4714,7 +4712,7 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
WasmWrapperGraphBuilder builder(&zone, &env, &jsgraph, func->sig, nullptr); WasmWrapperGraphBuilder builder(&zone, &env, &jsgraph, func->sig, nullptr);
builder.set_control_ptr(&control); builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect); builder.set_effect_ptr(&effect);
builder.BuildJSToWasmWrapper(wasm_code); builder.BuildJSToWasmWrapper(call_target);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Run the compilation pipeline. // Run the compilation pipeline.
......
...@@ -110,7 +110,7 @@ Handle<Code> CompileWasmToJSWrapper(Isolate*, Handle<JSReceiver> target, ...@@ -110,7 +110,7 @@ Handle<Code> CompileWasmToJSWrapper(Isolate*, Handle<JSReceiver> target,
// Wraps a given wasm code object, producing a code object. // Wraps a given wasm code object, producing a code object.
V8_EXPORT_PRIVATE Handle<Code> CompileJSToWasmWrapper(Isolate*, V8_EXPORT_PRIVATE Handle<Code> CompileJSToWasmWrapper(Isolate*,
wasm::WasmModule*, wasm::WasmModule*,
wasm::WasmCode*, Address call_target,
uint32_t index, uint32_t index,
wasm::UseTrapHandler); wasm::UseTrapHandler);
......
This diff is collapsed.
...@@ -697,16 +697,19 @@ WasmCode* NativeModule::Lookup(Address pc) { ...@@ -697,16 +697,19 @@ WasmCode* NativeModule::Lookup(Address pc) {
WasmCodeUniquePtrComparator()); WasmCodeUniquePtrComparator());
if (iter == owned_code_.begin()) return nullptr; if (iter == owned_code_.begin()) return nullptr;
--iter; --iter;
WasmCode* candidate = (*iter).get(); WasmCode* candidate = iter->get();
DCHECK_NOT_NULL(candidate); DCHECK_NOT_NULL(candidate);
return candidate->contains(pc) ? candidate : nullptr; return candidate->contains(pc) ? candidate : nullptr;
} }
WasmCode* NativeModule::GetIndirectlyCallableCode(uint32_t func_index) { Address NativeModule::GetCallTargetForFunction(uint32_t func_index) {
// TODO(clemensh): Introduce a jump table and return a slot of it here.
WasmCode* wasm_code = code(func_index); WasmCode* wasm_code = code(func_index);
if (!wasm_code || wasm_code->kind() != WasmCode::kLazyStub) { if (!wasm_code) return kNullAddress;
return wasm_code; if (wasm_code->kind() != WasmCode::kLazyStub) {
return wasm_code->instruction_start();
} }
#if DEBUG #if DEBUG
auto num_imported_functions = auto num_imported_functions =
shared_module_data()->module()->num_imported_functions; shared_module_data()->module()->num_imported_functions;
...@@ -718,7 +721,7 @@ WasmCode* NativeModule::GetIndirectlyCallableCode(uint32_t func_index) { ...@@ -718,7 +721,7 @@ WasmCode* NativeModule::GetIndirectlyCallableCode(uint32_t func_index) {
// If the function wasn't imported, its index should match. // If the function wasn't imported, its index should match.
DCHECK_IMPLIES(func_index >= num_imported_functions, DCHECK_IMPLIES(func_index >= num_imported_functions,
func_index == wasm_code->index()); func_index == wasm_code->index());
return wasm_code; return wasm_code->instruction_start();
} }
if (!lazy_compile_stubs_.get()) { if (!lazy_compile_stubs_.get()) {
lazy_compile_stubs_ = lazy_compile_stubs_ =
...@@ -732,7 +735,7 @@ WasmCode* NativeModule::GetIndirectlyCallableCode(uint32_t func_index) { ...@@ -732,7 +735,7 @@ WasmCode* NativeModule::GetIndirectlyCallableCode(uint32_t func_index) {
lazy_compile_stubs_.get()->at(func_index) = cloned_code; lazy_compile_stubs_.get()->at(func_index) = cloned_code;
} }
DCHECK_EQ(func_index, cloned_code->index()); DCHECK_EQ(func_index, cloned_code->index());
return cloned_code; return cloned_code->instruction_start();
} }
WasmCode* NativeModule::CloneCode(const WasmCode* original_code, WasmCode* NativeModule::CloneCode(const WasmCode* original_code,
......
...@@ -259,15 +259,21 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -259,15 +259,21 @@ class V8_EXPORT_PRIVATE NativeModule final {
code_table_[index] = wasm_code; code_table_[index] = wasm_code;
} }
bool has_code(uint32_t index) const {
DCHECK_LT(index, function_count());
return code_table_[index] != nullptr;
}
// Register/release the protected instructions in all code objects with the // Register/release the protected instructions in all code objects with the
// global trap handler for this process. // global trap handler for this process.
void UnpackAndRegisterProtectedInstructions(); void UnpackAndRegisterProtectedInstructions();
void ReleaseProtectedInstructions(); void ReleaseProtectedInstructions();
// Gets code suitable for indirect or import calls for the given function // Returns the instruction start of code suitable for indirect or import calls
// index. If the code at the given index is the lazy compile stub, it will // for the given function index. If the code at the given index is the lazy
// clone a non-anonymous lazy compile stub for the purpose. // compile stub, it will clone a non-anonymous lazy compile stub for the
WasmCode* GetIndirectlyCallableCode(uint32_t func_index); // purpose. This will soon change to always return a jump table slot.
Address GetCallTargetForFunction(uint32_t index);
bool SetExecutable(bool executable); bool SetExecutable(bool executable);
......
...@@ -113,10 +113,9 @@ bool CodeSpecialization::ApplyToWholeModule( ...@@ -113,10 +113,9 @@ bool CodeSpecialization::ApplyToWholeModule(
switch (mode) { switch (mode) {
case RelocInfo::JS_TO_WASM_CALL: { case RelocInfo::JS_TO_WASM_CALL: {
changed = true; changed = true;
const WasmCode* new_code = Address new_target =
native_module->GetIndirectlyCallableCode(exp.index); native_module->GetCallTargetForFunction(exp.index);
it.rinfo()->set_js_to_wasm_address(new_code->instruction_start(), it.rinfo()->set_js_to_wasm_address(new_target, icache_flush_mode);
icache_flush_mode);
} break; } break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -405,16 +405,16 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table, ...@@ -405,16 +405,16 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
auto* wasm_function = &other_instance->module()->functions[func_index]; auto* wasm_function = &other_instance->module()->functions[func_index];
DCHECK_NOT_NULL(wasm_function); DCHECK_NOT_NULL(wasm_function);
DCHECK_NOT_NULL(wasm_function->sig); DCHECK_NOT_NULL(wasm_function->sig);
wasm::WasmCode* wasm_code = exported_function->GetWasmCode(); Address call_target = exported_function->GetWasmCallTarget();
UpdateDispatchTables(isolate, table, table_index, wasm_function->sig, UpdateDispatchTables(isolate, table, table_index, wasm_function->sig,
handle(exported_function->instance()), wasm_code); handle(exported_function->instance()), call_target);
array->set(table_index, *function); array->set(table_index, *function);
} }
void WasmTableObject::UpdateDispatchTables( void WasmTableObject::UpdateDispatchTables(
Isolate* isolate, Handle<WasmTableObject> table, int table_index, Isolate* isolate, Handle<WasmTableObject> table, int table_index,
wasm::FunctionSig* sig, Handle<WasmInstanceObject> from_instance, wasm::FunctionSig* sig, Handle<WasmInstanceObject> from_instance,
wasm::WasmCode* wasm_code) { Address call_target) {
// We simply need to update the IFTs for each instance that imports // We simply need to update the IFTs for each instance that imports
// this table. // this table.
Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
...@@ -430,7 +430,7 @@ void WasmTableObject::UpdateDispatchTables( ...@@ -430,7 +430,7 @@ void WasmTableObject::UpdateDispatchTables(
// not found; it will simply never match any check. // not found; it will simply never match any check.
auto sig_id = to_instance->module()->signature_map.Find(sig); auto sig_id = to_instance->module()->signature_map.Find(sig);
IndirectFunctionTableEntry(to_instance, table_index) IndirectFunctionTableEntry(to_instance, table_index)
.set(sig_id, *from_instance, wasm_code); .set(sig_id, *from_instance, call_target);
} }
} }
...@@ -672,13 +672,12 @@ void IndirectFunctionTableEntry::clear() { ...@@ -672,13 +672,12 @@ void IndirectFunctionTableEntry::clear() {
} }
void IndirectFunctionTableEntry::set(int sig_id, WasmInstanceObject* instance, void IndirectFunctionTableEntry::set(int sig_id, WasmInstanceObject* instance,
const wasm::WasmCode* wasm_code) { Address call_target) {
TRACE_IFT("IFT entry %p[%d] = {sig_id=%d, instance=%p, target=%p}\n", TRACE_IFT("IFT entry %p[%d] = {sig_id=%d, instance=%p, target=%" PRIuPTR
*instance_, index_, sig_id, instance, "}\n",
wasm_code->instructions().start()); *instance_, index_, sig_id, instance, call_target);
instance_->indirect_function_table_sig_ids()[index_] = sig_id; instance_->indirect_function_table_sig_ids()[index_] = sig_id;
instance_->indirect_function_table_targets()[index_] = instance_->indirect_function_table_targets()[index_] = call_target;
wasm_code->instruction_start();
instance_->indirect_function_table_instances()->set(index_, instance); instance_->indirect_function_table_instances()->set(index_, instance);
} }
...@@ -707,14 +706,13 @@ void ImportedFunctionEntry::set_wasm_to_js( ...@@ -707,14 +706,13 @@ void ImportedFunctionEntry::set_wasm_to_js(
} }
void ImportedFunctionEntry::set_wasm_to_wasm(WasmInstanceObject* instance, void ImportedFunctionEntry::set_wasm_to_wasm(WasmInstanceObject* instance,
const wasm::WasmCode* wasm_code) { Address call_target) {
TRACE_IFT("Import WASM %p[%d] = {instance=%p, target=%p}\n", *instance_, TRACE_IFT("Import WASM %p[%d] = {instance=%p, target=%" PRIuPTR "}\n",
index_, instance, wasm_code->instructions().start()); *instance_, index_, instance, call_target);
instance_->imported_function_instances()->set(index_, instance); instance_->imported_function_instances()->set(index_, instance);
instance_->imported_function_callables()->set( instance_->imported_function_callables()->set(
index_, instance_->GetHeap()->undefined_value()); index_, instance_->GetHeap()->undefined_value());
instance_->imported_function_targets()[index_] = instance_->imported_function_targets()[index_] = call_target;
wasm_code->instruction_start();
} }
WasmInstanceObject* ImportedFunctionEntry::instance() { WasmInstanceObject* ImportedFunctionEntry::instance() {
...@@ -947,15 +945,19 @@ Handle<WasmExportedFunction> WasmExportedFunction::New( ...@@ -947,15 +945,19 @@ Handle<WasmExportedFunction> WasmExportedFunction::New(
} }
wasm::WasmCode* WasmExportedFunction::GetWasmCode() { wasm::WasmCode* WasmExportedFunction::GetWasmCode() {
Address target = GetWasmCallTarget();
wasm::WasmCode* wasm_code =
GetIsolate()->wasm_engine()->code_manager()->LookupCode(target);
return wasm_code;
}
Address WasmExportedFunction::GetWasmCallTarget() {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
Handle<Code> export_wrapper_code = handle(this->code()); DCHECK_EQ(code()->kind(), Code::JS_TO_WASM_FUNCTION);
DCHECK_EQ(export_wrapper_code->kind(), Code::JS_TO_WASM_FUNCTION);
int mask = RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL); int mask = RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL);
RelocIterator it(*export_wrapper_code, mask); RelocIterator it(code(), mask);
DCHECK(!it.done()); DCHECK(!it.done());
wasm::WasmCode* target = Address target = it.rinfo()->js_to_wasm_address();
GetIsolate()->wasm_engine()->code_manager()->LookupCode(
it.rinfo()->js_to_wasm_address());
#ifdef DEBUG #ifdef DEBUG
// There should only be this one call to wasm code. // There should only be this one call to wasm code.
it.next(); it.next();
......
...@@ -57,8 +57,7 @@ class IndirectFunctionTableEntry { ...@@ -57,8 +57,7 @@ class IndirectFunctionTableEntry {
inline IndirectFunctionTableEntry(Handle<WasmInstanceObject>, int index); inline IndirectFunctionTableEntry(Handle<WasmInstanceObject>, int index);
void clear(); void clear();
void set(int sig_id, WasmInstanceObject* instance, void set(int sig_id, WasmInstanceObject* instance, Address call_target);
const wasm::WasmCode* wasm_code);
WasmInstanceObject* instance(); WasmInstanceObject* instance();
int sig_id(); int sig_id();
...@@ -89,7 +88,7 @@ class ImportedFunctionEntry { ...@@ -89,7 +88,7 @@ class ImportedFunctionEntry {
const wasm::WasmCode* wasm_to_js_wrapper); const wasm::WasmCode* wasm_to_js_wrapper);
// Initialize this entry as a WASM to WASM call. // Initialize this entry as a WASM to WASM call.
void set_wasm_to_wasm(WasmInstanceObject* target_instance, void set_wasm_to_wasm(WasmInstanceObject* target_instance,
const wasm::WasmCode* wasm_function); Address call_target);
WasmInstanceObject* instance(); WasmInstanceObject* instance();
JSReceiver* callable(); JSReceiver* callable();
...@@ -176,7 +175,7 @@ class WasmTableObject : public JSObject { ...@@ -176,7 +175,7 @@ class WasmTableObject : public JSObject {
Handle<WasmTableObject> table, Handle<WasmTableObject> table,
int table_index, wasm::FunctionSig* sig, int table_index, wasm::FunctionSig* sig,
Handle<WasmInstanceObject> from_instance, Handle<WasmInstanceObject> from_instance,
wasm::WasmCode* wasm_code); Address call_target);
static void ClearDispatchTables(Isolate* isolate, static void ClearDispatchTables(Isolate* isolate,
Handle<WasmTableObject> table, int index); Handle<WasmTableObject> table, int index);
...@@ -377,7 +376,12 @@ class WasmExportedFunction : public JSFunction { ...@@ -377,7 +376,12 @@ class WasmExportedFunction : public JSFunction {
int func_index, int arity, int func_index, int arity,
Handle<Code> export_wrapper); Handle<Code> export_wrapper);
// TODO(clemensh): Remove this. There might not be a WasmCode object available
// yet.
// TODO(all): Replace all uses by {GetWasmCallTarget()}.
wasm::WasmCode* GetWasmCode(); wasm::WasmCode* GetWasmCode();
Address GetWasmCallTarget();
}; };
// Information for a WasmExportedFunction which is referenced as the function // Information for a WasmExportedFunction which is referenced as the function
......
...@@ -120,7 +120,7 @@ Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) { ...@@ -120,7 +120,7 @@ Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
Link(); Link();
wasm::WasmCode* code = native_module_->code(index); wasm::WasmCode* code = native_module_->code(index);
Handle<Code> ret_code = compiler::CompileJSToWasmWrapper( Handle<Code> ret_code = compiler::CompileJSToWasmWrapper(
isolate_, test_module_ptr_, code, index, isolate_, test_module_ptr_, code->instruction_start(), index,
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler); trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler);
Handle<JSFunction> ret = WasmExportedFunction::New( Handle<JSFunction> ret = WasmExportedFunction::New(
isolate_, instance_object(), MaybeHandle<String>(), isolate_, instance_object(), MaybeHandle<String>(),
...@@ -166,7 +166,8 @@ void TestingModuleBuilder::PopulateIndirectFunctionTable() { ...@@ -166,7 +166,8 @@ void TestingModuleBuilder::PopulateIndirectFunctionTable() {
WasmFunction& function = test_module_->functions[table.values[j]]; WasmFunction& function = test_module_->functions[table.values[j]];
int sig_id = test_module_->signature_map.Find(function.sig); int sig_id = test_module_->signature_map.Find(function.sig);
auto wasm_code = native_module_->code(function.func_index); auto wasm_code = native_module_->code(function.func_index);
IndirectFunctionTableEntry(instance, j).set(sig_id, *instance, wasm_code); IndirectFunctionTableEntry(instance, j)
.set(sig_id, *instance, wasm_code->instruction_start());
} }
} }
} }
......
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