Index: src/compiler/wasm-compiler.cc |
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
index 7270ddd24848854d9e42a020404ed04bdcca7ed4..7ac90362dd35b6ad0b7edaae380a7ee7ab673a5b 100644 |
--- a/src/compiler/wasm-compiler.cc |
+++ b/src/compiler/wasm-compiler.cc |
@@ -1908,7 +1908,8 @@ Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, |
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); |
@@ -3309,6 +3310,36 @@ Handle<Code> WasmCompilationUnit::FinishCompilation() { |
return code; |
} |
+void Link(Isolate* isolate, std::vector<Handle<Code>>& functions) { |
ahaas
2016/06/02 13:48:27
What's the reason why you move the code for linkin
Mircea Trofin
2016/06/02 14:46:21
I didn't realize that was the separation. I though
|
+ // 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; |
+ for (Handle<Code> code : functions) { |
+ int mode_mask = RelocInfo::kWasmDirectCallMask; |
+ 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> code = functions[f_index]; |
+ worklist.push_back( |
+ std::make_pair(*it.rinfo(), code->instruction_start())); |
+ } |
+ 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 |