Flutter Engine
The Flutter Engine
code_patcher_arm64.cc
Go to the documentation of this file.
1// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6#if defined(TARGET_ARCH_ARM64)
7
8#include "vm/code_patcher.h"
9#include "vm/cpu.h"
10#include "vm/instructions.h"
11#include "vm/object.h"
12
13namespace dart {
14
15class PoolPointerCall : public ValueObject {
16 public:
17 PoolPointerCall(uword pc, const Code& code)
18 : end_(pc), object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
19 // Last instruction: blr lr.
20 ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f03c0);
22 &reg_, &index_);
23 }
24
25 intptr_t pp_index() const { return index_; }
26
27 CodePtr Target() const {
28 return static_cast<CodePtr>(object_pool_.ObjectAt(pp_index()));
29 }
30
31 void SetTarget(const Code& target) const {
32 object_pool_.SetObjectAt(pp_index(), target);
33 // No need to flush the instruction cache, since the code is not modified.
34 }
35
36 private:
37 static constexpr int kCallPatternSize = 3 * Instr::kInstrSize;
38 uword end_;
39 const ObjectPool& object_pool_;
40 Register reg_;
41 intptr_t index_;
42 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
43};
44
45CodePtr CodePatcher::GetStaticCallTargetAt(uword return_address,
46 const Code& code) {
47 ASSERT(code.ContainsInstructionAt(return_address));
48 PoolPointerCall call(return_address, code);
49 return call.Target();
50}
51
52void CodePatcher::PatchStaticCallAt(uword return_address,
53 const Code& code,
54 const Code& new_target) {
55 PatchPoolPointerCallAt(return_address, code, new_target);
56}
57
59 const Code& code,
60 const Code& new_target) {
61 ASSERT(code.ContainsInstructionAt(return_address));
62 PoolPointerCall call(return_address, code);
63 call.SetTarget(new_target);
64}
65
68}
69
70CodePtr CodePatcher::GetInstanceCallAt(uword return_address,
71 const Code& caller_code,
72 Object* data) {
73 ASSERT(caller_code.ContainsInstructionAt(return_address));
74 ICCallPattern call(return_address, caller_code);
75 if (data != nullptr) {
76 *data = call.Data();
77 }
78 return call.TargetCode();
79}
80
81void CodePatcher::PatchInstanceCallAt(uword return_address,
82 const Code& caller_code,
83 const Object& data,
84 const Code& target) {
85 auto thread = Thread::Current();
86 thread->isolate_group()->RunWithStoppedMutators([&]() {
87 PatchInstanceCallAtWithMutatorsStopped(thread, return_address, caller_code,
88 data, target);
89 });
90}
91
93 Thread* thread,
94 uword return_address,
95 const Code& caller_code,
96 const Object& data,
97 const Code& target) {
98 ASSERT(caller_code.ContainsInstructionAt(return_address));
99 ICCallPattern call(return_address, caller_code);
100 call.SetData(data);
101 call.SetTargetCode(target);
102}
103
104FunctionPtr CodePatcher::GetUnoptimizedStaticCallAt(uword return_address,
105 const Code& code,
106 ICData* ic_data_result) {
107 ASSERT(code.ContainsInstructionAt(return_address));
108 ICCallPattern static_call(return_address, code);
109 ICData& ic_data = ICData::Handle();
110 ic_data ^= static_call.Data();
111 if (ic_data_result != nullptr) {
112 *ic_data_result = ic_data.ptr();
113 }
114 return ic_data.GetTargetAt(0);
115}
116
117void CodePatcher::PatchSwitchableCallAt(uword return_address,
118 const Code& caller_code,
119 const Object& data,
120 const Code& target) {
121 auto thread = Thread::Current();
122 // Ensure all threads are suspended as we update data and target pair.
123 thread->isolate_group()->RunWithStoppedMutators([&]() {
124 PatchSwitchableCallAtWithMutatorsStopped(thread, return_address,
125 caller_code, data, target);
126 });
127}
128
130 Thread* thread,
131 uword return_address,
132 const Code& caller_code,
133 const Object& data,
134 const Code& target) {
135 if (FLAG_precompiled_mode) {
136 BareSwitchableCallPattern call(return_address);
137 call.SetData(data);
138 call.SetTarget(target);
139 } else {
140 SwitchableCallPattern call(return_address, caller_code);
141 call.SetData(data);
142 call.SetTarget(target);
143 }
144}
145
147 const Code& caller_code) {
148 if (FLAG_precompiled_mode) {
149 BareSwitchableCallPattern call(return_address);
150 return call.target_entry();
151 } else {
152 SwitchableCallPattern call(return_address, caller_code);
153 return call.target_entry();
154 }
155}
156
157ObjectPtr CodePatcher::GetSwitchableCallDataAt(uword return_address,
158 const Code& caller_code) {
159 if (FLAG_precompiled_mode) {
160 BareSwitchableCallPattern call(return_address);
161 return call.data();
162 } else {
163 SwitchableCallPattern call(return_address, caller_code);
164 return call.data();
165 }
166}
167
168void CodePatcher::PatchNativeCallAt(uword return_address,
169 const Code& caller_code,
171 const Code& trampoline) {
173 ASSERT(caller_code.ContainsInstructionAt(return_address));
174 NativeCallPattern call(return_address, caller_code);
175 call.set_target(trampoline);
176 call.set_native_function(target);
177 });
178}
179
180CodePtr CodePatcher::GetNativeCallAt(uword return_address,
181 const Code& caller_code,
183 ASSERT(caller_code.ContainsInstructionAt(return_address));
184 NativeCallPattern call(return_address, caller_code);
185 *target = call.native_function();
186 return call.target();
187}
188
189} // namespace dart
190
191#endif // defined TARGET_ARCH_ARM64
#define UNREACHABLE()
Definition: assert.h:248
static void PatchInstanceCallAt(uword return_address, const Code &caller_code, const Object &data, const Code &target)
static void PatchPoolPointerCallAt(uword return_address, const Code &code, const Code &new_target)
static CodePtr GetStaticCallTargetAt(uword return_address, const Code &code)
static void PatchSwitchableCallAtWithMutatorsStopped(Thread *thread, uword return_address, const Code &caller_code, const Object &data, const Code &target)
static void PatchInstanceCallAtWithMutatorsStopped(Thread *thread, uword return_address, const Code &caller_code, const Object &data, const Code &target)
static void PatchSwitchableCallAt(uword return_address, const Code &caller_code, const Object &data, const Code &target)
static FunctionPtr GetUnoptimizedStaticCallAt(uword return_address, const Code &code, ICData *ic_data)
static uword GetSwitchableCallTargetEntryAt(uword return_address, const Code &caller_code)
static ObjectPtr GetSwitchableCallDataAt(uword return_address, const Code &caller_code)
static void InsertDeoptimizationCallAt(uword start)
static CodePtr GetInstanceCallAt(uword return_address, const Code &caller_code, Object *data)
static CodePtr GetNativeCallAt(uword return_address, const Code &caller_code, NativeFunction *target)
static void PatchStaticCallAt(uword return_address, const Code &code, const Code &new_target)
static void PatchNativeCallAt(uword return_address, const Code &caller_code, NativeFunction target, const Code &trampoline)
static uword DecodeLoadWordFromPool(uword end, Register *reg, intptr_t *index)
void RunWithStoppedMutators(T single_current_mutator, S otherwise, bool use_force_growth_in_otherwise=false)
Definition: isolate.h:611
static Object & Handle()
Definition: object.h:407
static Thread * Current()
Definition: thread.h:362
IsolateGroup * isolate_group() const
Definition: thread.h:541
#define ASSERT(E)
uint32_t * target
Definition: dart_vm.cc:33
uintptr_t uword
Definition: globals.h:501
static int8_t data[kExtLength]
void(* NativeFunction)(NativeArguments *arguments)
def call(args)
Definition: dom.py:159
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName)
Definition: globals.h:593