6#if defined(TARGET_ARCH_ARM)
19static bool IsBranchLinkScratch(
Register reg) {
25 : object_pool_(ObjectPool::Handle(
code.GetObjectPool())),
26 target_code_pool_index_(-1) {
29 ASSERT(*(
reinterpret_cast<uint32_t*
>(pc) - 1) == 0xe12fff3e);
32 InstructionPattern::DecodeLoadWordFromPool(pc - 2 * Instr::kInstrSize, ®,
33 &target_code_pool_index_);
34 ASSERT(IsBranchLinkScratch(reg));
37ICCallPattern::ICCallPattern(
uword pc,
const Code&
code)
38 : object_pool_(ObjectPool::Handle(
code.GetObjectPool())),
39 target_pool_index_(-1),
40 data_pool_index_(-1) {
43 ASSERT(*(
reinterpret_cast<uint32_t*
>(pc) - 1) == 0xe12fff3e);
46 uword data_load_end = InstructionPattern::DecodeLoadWordFromPool(
47 pc - 2 * Instr::kInstrSize, ®, &target_pool_index_);
48 ASSERT(IsBranchLinkScratch(reg));
50 InstructionPattern::DecodeLoadWordFromPool(data_load_end, ®,
55NativeCallPattern::NativeCallPattern(
uword pc,
const Code&
code)
56 : object_pool_(ObjectPool::Handle(
code.GetObjectPool())),
58 native_function_pool_index_(-1),
59 target_code_pool_index_(-1) {
62 ASSERT(*(
reinterpret_cast<uint32_t*
>(end_) - 1) == 0xe12fff3e);
65 uword native_function_load_end = InstructionPattern::DecodeLoadWordFromPool(
66 end_ - 2 * Instr::kInstrSize, ®, &target_code_pool_index_);
67 ASSERT(IsBranchLinkScratch(reg));
68 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, ®,
69 &native_function_pool_index_);
74 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_code_pool_index_));
77void NativeCallPattern::set_target(
const Code& new_target)
const {
78 object_pool_.SetObjectAt(target_code_pool_index_, new_target);
84 object_pool_.RawValueAt(native_function_pool_index_));
87void NativeCallPattern::set_native_function(
NativeFunction func)
const {
88 object_pool_.SetRawValueAt(native_function_pool_index_,
89 reinterpret_cast<uword>(func));
101 int32_t instr = Instr::At(
start)->InstructionBits();
103 if ((instr & 0xfff00000) == 0xe3400000) {
104 imm |= (instr & 0xf0000) << 12;
105 imm |= (instr & 0xfff) << 16;
106 start -= Instr::kInstrSize;
107 instr = Instr::At(
start)->InstructionBits();
109 ASSERT((instr & 0xfff00000) == 0xe3000000);
110 imm |= (instr & 0xf0000) >> 4;
111 imm |= instr & 0xfff;
112 *reg =
static_cast<Register>((instr & 0xf000) >> 12);
117void InstructionPattern::EncodeLoadWordImmediate(
uword end,
120 uint16_t low16 =
value & 0xffff;
121 uint16_t high16 = (
value >> 16) & 0xffff;
124 uint32_t movw_instr = 0xe3000000;
125 movw_instr |= (low16 >> 12) << 16;
126 movw_instr |= (reg << 12);
127 movw_instr |= (low16 & 0xfff);
130 uint32_t movt_instr = 0xe3400000;
131 movt_instr |= (high16 >> 12) << 16;
132 movt_instr |= (reg << 12);
133 movt_instr |= (high16 & 0xfff);
135 uint32_t* cursor =
reinterpret_cast<uint32_t*
>(
end);
136 *(--cursor) = movt_instr;
137 *(--cursor) = movw_instr;
141 intptr_t decoded_value;
142 DecodeLoadWordImmediate(
end, &decoded_reg, &decoded_value);
143 ASSERT(reg == decoded_reg);
148static bool IsLoadWithOffset(int32_t instr,
152 if ((instr & 0xffff0000) == (0xe5900000 | (
base << 16))) {
155 *
dst =
static_cast<Register>((instr & 0xf000) >> 12);
170 int32_t instr = Instr::At(
start)->InstructionBits();
172 if (IsLoadWithOffset(instr,
PP, &
offset, reg)) {
175 ASSERT((instr & 0xfff00000) == 0xe5900000);
177 start -= Instr::kInstrSize;
178 instr = Instr::At(
start)->InstructionBits();
179 if ((instr & 0xffff0000) == (0xe2850000 | (
PP << 16))) {
181 const intptr_t rot = (instr & 0xf00) >> 7;
182 const intptr_t imm8 = instr & 0xff;
183 offset += (imm8 >> rot) | (imm8 << (32 - rot));
184 *reg =
static_cast<Register>((instr & 0xf000) >> 12);
186 ASSERT((instr & 0xffff0000) == (0xe0800000 | (
PP << 16)));
193 *index = ObjectPool::IndexFromOffset(
offset);
200 int32_t instr = Instr::At(pc)->InstructionBits();
204 intptr_t index = ObjectPool::IndexFromOffset(
offset);
206 }
else if (IsLoadWithOffset(instr,
THR, &
offset, &
dst)) {
207 return Thread::ObjectAtOffset(
offset, obj);
214CodePtr CallPattern::TargetCode()
const {
215 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_code_pool_index_));
218void CallPattern::SetTargetCode(
const Code& target_code)
const {
219 object_pool_.SetObjectAt(target_code_pool_index_, target_code);
223 return object_pool_.ObjectAt(data_pool_index_);
226void ICCallPattern::SetData(
const Object&
data)
const {
228 object_pool_.SetObjectAt(data_pool_index_,
data);
231CodePtr ICCallPattern::TargetCode()
const {
232 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_pool_index_));
235void ICCallPattern::SetTargetCode(
const Code& target_code)
const {
236 object_pool_.SetObjectAt(target_pool_index_, target_code);
239SwitchableCallPatternBase::SwitchableCallPatternBase(
240 const ObjectPool& object_pool)
241 : object_pool_(object_pool), data_pool_index_(-1), target_pool_index_(-1) {}
244 return object_pool_.ObjectAt(data_pool_index_);
247void SwitchableCallPatternBase::SetData(
const Object&
data)
const {
248 ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode());
249 object_pool_.SetObjectAt(data_pool_index_,
data);
252SwitchableCallPattern::SwitchableCallPattern(
uword pc,
const Code&
code)
253 : SwitchableCallPatternBase(ObjectPool::Handle(
code.GetObjectPool())) {
256 ASSERT(*(
reinterpret_cast<uint32_t*
>(pc) - 1) == 0xe12fff3e);
259 uword data_load_end = InstructionPattern::DecodeLoadWordFromPool(
260 pc - Instr::kInstrSize, ®, &data_pool_index_);
262 InstructionPattern::DecodeLoadWordFromPool(data_load_end - Instr::kInstrSize,
263 ®, &target_pool_index_);
264 ASSERT(IsBranchLinkScratch(reg));
267uword SwitchableCallPattern::target_entry()
const {
268 return Code::Handle(Code::RawCast(object_pool_.ObjectAt(target_pool_index_)))
269 .MonomorphicEntryPoint();
272void SwitchableCallPattern::SetTarget(
const Code&
target)
const {
273 ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode());
274 object_pool_.SetObjectAt(target_pool_index_,
target);
277BareSwitchableCallPattern::BareSwitchableCallPattern(
uword pc)
278 : SwitchableCallPatternBase(ObjectPool::Handle(
279 IsolateGroup::Current()->object_store()->global_object_pool())) {
281 ASSERT(*(
reinterpret_cast<uint32_t*
>(pc) - 1) == 0xe12fff3e);
284 uword data_load_end = InstructionPattern::DecodeLoadWordFromPool(
285 pc - Instr::kInstrSize, ®, &data_pool_index_);
288 InstructionPattern::DecodeLoadWordFromPool(data_load_end, ®,
289 &target_pool_index_);
293uword BareSwitchableCallPattern::target_entry()
const {
294 return object_pool_.RawValueAt(target_pool_index_);
297void BareSwitchableCallPattern::SetTarget(
const Code&
target)
const {
298 ASSERT(object_pool_.TypeAt(target_pool_index_) ==
299 ObjectPool::EntryType::kImmediate);
300 object_pool_.SetRawValueAt(target_pool_index_,
301 target.MonomorphicEntryPoint());
304ReturnPattern::ReturnPattern(
uword pc) : pc_(pc) {}
306bool ReturnPattern::IsValid()
const {
307 Instr* bx_lr = Instr::At(pc_);
308 const int32_t
B4 = 1 << 4;
309 const int32_t
B21 = 1 << 21;
310 const int32_t
B24 = 1 << 24;
312 B21 | (0xfff << 8) |
B4 |
314 return bx_lr->InstructionBits() == instruction;
317bool PcRelativeCallPattern::IsValid()
const {
319 const uint32_t
word = *
reinterpret_cast<uint32_t*
>(pc_);
320 const uint32_t branch = 0x05;
326bool PcRelativeTailCallPattern::IsValid()
const {
328 const uint32_t
word = *
reinterpret_cast<uint32_t*
>(pc_);
329 const uint32_t branch = 0x05;
336#if !defined(DART_PRECOMPILED_RUNTIME)
338 reinterpret_cast<uint32_t*
>(pattern_start_ + 2 * Instr::kInstrSize);
339 *add_pc = kAddPcEncoding;
347#if !defined(DART_PRECOMPILED_RUNTIME)
348 const uword end = pattern_start_ + 2 * Instr::kInstrSize;
351 InstructionPattern::DecodeLoadWordImmediate(
end, ®, &
value);
352 value -= kDistanceOffset;
361void PcRelativeTrampolineJumpPattern::set_distance(int32_t
distance) {
362#if !defined(DART_PRECOMPILED_RUNTIME)
363 const uword end = pattern_start_ + 2 * Instr::kInstrSize;
364 InstructionPattern::EncodeLoadWordImmediate(
end,
TMP,
371bool PcRelativeTrampolineJumpPattern::IsValid()
const {
372#if !defined(DART_PRECOMPILED_RUNTIME)
373 const uword end = pattern_start_ + 2 * Instr::kInstrSize;
376 InstructionPattern::DecodeLoadWordImmediate(
end, ®, &
value);
379 reinterpret_cast<uint32_t*
>(pattern_start_ + 2 * Instr::kInstrSize);
381 return reg ==
TMP && *add_pc == kAddPcEncoding;
388intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
400 uword pc = pc_ - Instr::kInstrSize;
401 const uint32_t blx_r9 = 0xe12fff39;
402 if (*
reinterpret_cast<uint32_t*
>(pc) != blx_r9) {
403 PcRelativeCallPattern pattern(pc);
407 const uword load_instr_end = pc;
410 intptr_t pool_index = -1;
411 InstructionPattern::DecodeLoadWordFromPool(load_instr_end, ®, &pool_index);
#define ASSERT_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
CallPattern(uword pc, const Code &code)
def link(from_root, to_root)
bool ObjectAtPoolIndex(const Code &code, intptr_t index, Object *obj)
bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code &code, Object *obj)
void(* NativeFunction)(NativeArguments *arguments)
struct PathData * Data(SkPath *path)
void Initialize(zx::channel directory_request, std::optional< zx::eventpair > view_ref)
Initializes Dart bindings for the Fuchsia application model.
std::shared_ptr< const fml::Mapping > data