5#ifndef RUNTIME_VM_COMPILER_RELOCATION_H_
6#define RUNTIME_VM_COMPILER_RELOCATION_H_
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
21#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
25class UnresolvedCall :
public IntrusiveDListEntry<UnresolvedCall>,
26 public IntrusiveDListEntry<UnresolvedCall, 2> {
28 UnresolvedCall(CodePtr caller,
32 intptr_t offset_into_target,
35 call_offset(call_offset),
36 text_offset(text_offset),
38 offset_into_target(offset_into_target),
39 is_tail_call(is_tail_call) {}
41 UnresolvedCall(
const UnresolvedCall& other)
42 : IntrusiveDListEntry<UnresolvedCall>(),
43 IntrusiveDListEntry<UnresolvedCall, 2>(),
45 call_offset(other.call_offset),
46 text_offset(other.text_offset),
48 offset_into_target(other.offset_into_target),
49 is_tail_call(other.is_tail_call) {}
55 const intptr_t call_offset;
57 const intptr_t text_offset;
61 const intptr_t offset_into_target;
63 const bool is_tail_call;
67using AllUnresolvedCallsList = IntrusiveDList<UnresolvedCall>;
70using SameDestinationUnresolvedCallsList = IntrusiveDList<UnresolvedCall, 2>;
79class UnresolvedTrampoline :
public IntrusiveDListEntry<UnresolvedTrampoline> {
81 UnresolvedTrampoline(CodePtr callee,
82 intptr_t offset_into_target,
83 uint8_t* trampoline_bytes,
86 offset_into_target(offset_into_target),
87 trampoline_bytes(trampoline_bytes),
88 text_offset(text_offset) {}
93 intptr_t offset_into_target;
96 uint8_t* trampoline_bytes;
101using UnresolvedTrampolineList = IntrusiveDList<UnresolvedTrampoline>;
103template <
typename ValueType, ValueType kNoValue>
104class InstructionsMapTraits {
107 InstructionsPtr instructions;
110 Pair() : instructions(nullptr),
value(kNoValue) {}
111 Pair(InstructionsPtr
i,
const ValueType&
value)
115 typedef const InstructionsPtr
Key;
116 typedef const ValueType
Value;
118 static Key KeyOf(
Pair kv) {
return kv.instructions; }
119 static ValueType ValueOf(
Pair kv) {
return kv.value; }
123 static inline bool IsKeyEqual(
Pair pair,
Key key) {
124 return pair.instructions ==
key;
128using InstructionsPosition =
129 DirectChainedHashMap<InstructionsMapTraits<intptr_t, -1>>;
131using TrampolinesMap = DirectChainedHashMap<
132 InstructionsMapTraits<UnresolvedTrampolineList*, nullptr>>;
134using InstructionsUnresolvedCalls = DirectChainedHashMap<
135 InstructionsMapTraits<SameDestinationUnresolvedCallsList*, nullptr>>;
142class CodeRelocator :
public StackResource {
149 static void Relocate(Thread* thread,
150 GrowableArray<CodePtr>* code_objects,
151 GrowableArray<ImageWriterCommand>*
commands,
152 bool is_vm_isolate) {
153 CodeRelocator relocator(thread, code_objects,
commands);
154 relocator.Relocate(is_vm_isolate);
158 CodeRelocator(Thread* thread,
159 GrowableArray<CodePtr>* code_objects,
160 GrowableArray<ImageWriterCommand>*
commands);
162 void Relocate(
bool is_vm_isolate);
164 void FindLargestInstruction();
166 bool AddInstructionsToText(CodePtr
code, intptr_t* code_text_offset);
167 void ScanCallTargets(
const Code&
code,
168 const Array& call_targets,
169 intptr_t code_text_offset);
171 UnresolvedTrampoline* FindTrampolineFor(UnresolvedCall* unresolved_call);
172 void AddTrampolineToText(InstructionsPtr destination,
173 uint8_t* trampoline_bytes,
174 intptr_t trampoline_length);
176 void EnqueueUnresolvedCall(UnresolvedCall* unresolved_call);
177 void EnqueueUnresolvedTrampoline(UnresolvedTrampoline* unresolved_trampoline);
179 bool TryResolveBackwardsCall(UnresolvedCall* unresolved_call);
180 void ResolveUnresolvedCallsTargeting(
const InstructionsPtr instructions);
181 void ResolveCall(UnresolvedCall* unresolved_call);
182 void ResolveCallToDestination(UnresolvedCall* unresolved_call,
183 intptr_t destination_text);
184 void ResolveTrampoline(UnresolvedTrampoline* unresolved_trampoline);
186 void BuildTrampolinesForAlmostOutOfRangeCalls(
187 const Code& next_caller,
188 const Array& next_caller_targets);
190 intptr_t FindDestinationInText(
const InstructionsPtr destination,
191 intptr_t offset_into_target);
193 static intptr_t AdjustPayloadOffset(intptr_t payload_offset);
195 bool IsTargetInRangeFor(UnresolvedCall* unresolved_call,
196 intptr_t target_text_offset);
202 NoSafepointScope no_savepoint_scope_;
205 const GrowableArray<CodePtr>* code_objects_;
206 GrowableArray<ImageWriterCommand>* commands_;
209 intptr_t max_instructions_size_ = 0;
211 intptr_t max_calls_ = 0;
214 intptr_t next_text_offset_ = 0;
215 InstructionsPosition text_offsets_;
216 TrampolinesMap trampolines_by_destination_;
217 InstructionsUnresolvedCalls unresolved_calls_by_destination_;
218 AllUnresolvedCallsList all_unresolved_calls_;
221 Smi& kind_type_and_offset_;
static uint32_t WordHash(intptr_t key)
StaticCallsTable::TupleView StaticCallsTableEntry
static uint32_t Hash(uint32_t key)