Index: src/compiler/wasm-compiler.cc |
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
index 1d547113d270d6536bf719d10750dd6e8467b4f5..2db46c38fd0fe207282ca6fe859c17ad27438b76 100644 |
--- a/src/compiler/wasm-compiler.cc |
+++ b/src/compiler/wasm-compiler.cc |
@@ -1874,7 +1874,8 @@ Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
} |
Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args, |
- wasm::WasmCodePosition position) { |
+ wasm::WasmCodePosition position, |
+ bool internal) { |
const size_t params = sig->parameter_count(); |
const size_t extra = 2; // effect and control inputs. |
const size_t count = 1 + params + extra; |
@@ -1887,7 +1888,7 @@ Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args, |
args[params + 2] = *control_; |
CallDescriptor* descriptor = |
- wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); |
+ wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig, internal); |
const Operator* op = jsgraph()->common()->Call(descriptor); |
Node* call = graph()->NewNode(op, static_cast<int>(count), args); |
SetSourcePosition(call, position); |
@@ -1900,22 +1901,21 @@ Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, |
wasm::WasmCodePosition position) { |
DCHECK_NULL(args[0]); |
- // Add code object as constant. |
- args[0] = HeapConstant(module_->GetCodeOrPlaceholder(index)); |
+ args[0] = |
+ jsgraph()->RelocatableInt32Constant(index, RelocInfo::WASM_DIRECT_CALL); |
wasm::FunctionSig* sig = module_->GetFunctionSignature(index); |
- return BuildWasmCall(sig, args, position); |
+ return BuildWasmCall(sig, args, position, true); |
} |
Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args, |
wasm::WasmCodePosition position) { |
DCHECK_NULL(args[0]); |
- // Add code object as constant. |
- args[0] = HeapConstant(module_->GetImportCode(index)); |
+ args[0] = |
+ jsgraph()->RelocatableInt32Constant(index, RelocInfo::WASM_IMPORT_CALL); |
wasm::FunctionSig* sig = module_->GetImportSignature(index); |
- |
- return BuildWasmCall(sig, args, position); |
+ return BuildWasmCall(sig, args, position, true); |
} |
Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, |
@@ -3302,6 +3302,43 @@ Handle<Code> WasmCompilationUnit::FinishCompilation() { |
return code; |
} |
+void Link(Isolate* isolate, std::vector<Handle<Code>>& unlinked_functions, |
+ const std::vector<Handle<Code>>& functions_to_link, int mode_mask) { |
+ // On architectures supporting constant pools, if a function A calls another |
+ // function B in a number of places, then the same slot in the constant pool |
+ // would be used for the call to B. We can't update eagerly the location, |
+ // because that would mean that the next time we look at the location to find |
+ // the index of the function being called, we'd find the actual address |
+ // instead. So we keep a worklist. To keep the code simple, we maintain the |
+ // worklist even on architectures that do not support constant pools. |
+ |
+ std::vector<std::pair<RelocInfo, Address>> worklist; |
+ { |
+ DisallowHeapAllocation no_gc_scope; |
+ RelocInfoWriter writer; |
+ for (Handle<Code> code : unlinked_functions) { |
+ AllowDeferredHandleDereference embedding_raw_address; |
+ for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
+ size_t f_index = it.rinfo()->wasm_function_index(); |
+ Handle<Code> to_link = functions_to_link[f_index]; |
+ worklist.push_back( |
+ std::make_pair(*it.rinfo(), to_link->instruction_start())); |
+ writer.Reposition(it.mode_pos(), it.rinfo()->pc()); |
+ writer.WriteModeNoAdvance(RelocInfo::CODE_TARGET); |
+ } |
+ for (auto pair : worklist) { |
+ pair.first.set_target_address(pair.second, SKIP_WRITE_BARRIER, |
+ SKIP_ICACHE_FLUSH); |
+ } |
+ if (!worklist.empty()) { |
+ worklist.clear(); |
+ Assembler::FlushICache(isolate, code->instruction_start(), |
+ code->instruction_size()); |
+ } |
+ } |
+ } |
+} |
+ |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |