6#if defined(TARGET_ARCH_ARM64)
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) == 0xd63f03c0);
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) == 0xd63f03c0);
47 InstructionPattern::DecodeLoadDoubleWordFromPool(
48 pc - 2 * Instr::kInstrSize, &data_reg, &code_reg, &pool_index);
50 ASSERT(IsBranchLinkScratch(code_reg));
52 data_pool_index_ = pool_index;
53 target_pool_index_ = pool_index + 1;
56NativeCallPattern::NativeCallPattern(
uword pc,
const Code&
code)
57 : object_pool_(ObjectPool::Handle(
code.GetObjectPool())),
59 native_function_pool_index_(-1),
60 target_code_pool_index_(-1) {
63 ASSERT(*(
reinterpret_cast<uint32_t*
>(end_) - 1) == 0xd63f03c0);
66 uword native_function_load_end = InstructionPattern::DecodeLoadWordFromPool(
67 end_ - 2 * Instr::kInstrSize, ®, &target_code_pool_index_);
68 ASSERT(IsBranchLinkScratch(reg));
69 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, ®,
70 &native_function_pool_index_);
75 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_code_pool_index_));
78void NativeCallPattern::set_target(
const Code&
target)
const {
79 object_pool_.SetObjectAt(target_code_pool_index_,
target);
85 object_pool_.RawValueAt(native_function_pool_index_));
88void NativeCallPattern::set_native_function(
NativeFunction func)
const {
89 object_pool_.SetRawValueAt(native_function_pool_index_,
90 reinterpret_cast<uword>(func));
108 Instr* instr = Instr::At(
start);
112 if (instr->IsLogicalImmOp()) {
113 ASSERT(instr->Bit(29) == 1);
117 start -= Instr::kInstrSize;
118 instr = Instr::At(
start);
123 if (instr->IsLoadStoreRegOp()) {
133 ASSERT(instr->IsMoveWideOp());
134 ASSERT(instr->Bits(29, 2) == 3);
135 ASSERT(instr->HWField() == 3);
136 *reg = instr->RdField();
137 *
value =
static_cast<int64_t
>(instr->Imm16Field()) << 48;
139 start -= Instr::kInstrSize;
140 instr = Instr::At(
start);
141 ASSERT(instr->IsMoveWideOp());
142 ASSERT(instr->Bits(29, 2) == 3);
143 ASSERT(instr->HWField() == 2);
144 ASSERT(instr->RdField() == *reg);
145 *
value |=
static_cast<int64_t
>(instr->Imm16Field()) << 32;
147 start -= Instr::kInstrSize;
148 instr = Instr::At(
start);
149 ASSERT(instr->IsMoveWideOp());
150 ASSERT(instr->Bits(29, 2) == 3);
151 ASSERT(instr->HWField() == 1);
152 ASSERT(instr->RdField() == *reg);
153 *
value |=
static_cast<int64_t
>(instr->Imm16Field()) << 16;
155 start -= Instr::kInstrSize;
156 instr = Instr::At(
start);
157 ASSERT(instr->IsMoveWideOp());
158 ASSERT(instr->Bits(29, 2) == 2);
159 ASSERT(instr->HWField() == 0);
160 ASSERT(instr->RdField() == *reg);
161 *
value |=
static_cast<int64_t
>(instr->Imm16Field());
179 Instr* instr = Instr::At(
start);
183 ASSERT(instr->IsLoadStoreRegOp() && (instr->Bit(22) == 1) &&
184 (instr->Bits(30, 2) == 3));
187 *reg = instr->RtField();
189 if (instr->Bit(24) == 1) {
192 offset |= (instr->Imm12Field() << 3);
193 if (instr->RnField() == *reg) {
194 start -= Instr::kInstrSize;
195 instr = Instr::At(
start);
196 ASSERT(instr->IsAddSubImmOp());
198 ASSERT(instr->RdField() == *reg);
199 offset |= (instr->Imm12Field() << 12);
202 ASSERT(instr->Bits(10, 2) == 2);
206 start -= Instr::kInstrSize;
207 instr = Instr::At(
start);
208 ASSERT(instr->IsMoveWideOp());
209 ASSERT(instr->RdField() == *reg);
210 if (instr->Bits(29, 2) == 2) {
211 ASSERT(instr->HWField() == 0);
212 offset = instr->Imm16Field();
215 ASSERT(instr->Bits(29, 2) == 3);
216 ASSERT(instr->HWField() == 1);
217 offset = instr->Imm16Field() << 16;
219 start -= Instr::kInstrSize;
220 instr = Instr::At(
start);
221 ASSERT(instr->IsMoveWideOp());
222 ASSERT(instr->RdField() == *reg);
223 ASSERT(instr->Bits(29, 2) == 2);
224 ASSERT(instr->HWField() == 0);
225 offset |= instr->Imm16Field();
235uword InstructionPattern::DecodeLoadDoubleWordFromPool(
uword end,
253 Instr* ldr_instr = Instr::At(
start);
256 ASSERT(ldr_instr->IsLoadStoreRegPairOp() && (ldr_instr->Bit(22) == 1));
259 *reg1 = ldr_instr->RtField();
260 *reg2 = ldr_instr->Rt2Field();
262 Register base_reg = ldr_instr->RnField();
263 const int base_offset = 8 * ldr_instr->Imm7Field();
265 intptr_t pool_offset = 0;
266 if (base_reg ==
PP) {
268 pool_offset = base_offset;
273 pool_offset = base_offset;
275 start -= Instr::kInstrSize;
276 Instr* add_instr = Instr::At(
start);
277 ASSERT(add_instr->IsAddSubImmOp());
280 const auto shift = add_instr->Imm12ShiftField();
281 ASSERT(shift == 0 || shift == 1);
282 pool_offset += (add_instr->Imm12Field() << (shift == 1 ? 12 : 0));
284 if (add_instr->RnField() ==
TMP) {
285 start -= Instr::kInstrSize;
286 Instr* prev_add_instr = Instr::At(
start);
287 ASSERT(prev_add_instr->IsAddSubImmOp());
288 ASSERT(prev_add_instr->RnField() ==
PP);
290 const auto shift = prev_add_instr->Imm12ShiftField();
291 ASSERT(shift == 0 || shift == 1);
292 pool_offset += (prev_add_instr->Imm12Field() << (shift == 1 ? 12 : 0));
297 *index = ObjectPool::IndexFromOffset(pool_offset -
kHeapObjectTag);
304 Instr* instr = Instr::At(pc);
305 if (instr->IsLoadStoreRegOp() && (instr->Bit(22) == 1) &&
306 (instr->Bits(30, 2) == 3) && instr->Bit(24) == 1) {
307 intptr_t
offset = (instr->Imm12Field() << 3);
308 if (instr->RnField() ==
PP) {
313 }
else if (instr->RnField() ==
THR) {
314 return Thread::ObjectAtOffset(
offset, obj);
316 if (instr->RnField() == instr->RtField()) {
317 Instr* add = Instr::At(pc - Instr::kInstrSize);
318 if (add->IsAddSubImmOp() && (add->SFField() != 0) &&
319 (instr->Bit(22) == 1) && (add->RdField() == add->RtField())) {
321 if (add->RnField() ==
PP) {
326 }
else if (add->RnField() ==
THR) {
327 return Thread::ObjectAtOffset(
offset, obj);
334 if (instr->IsAddSubImmOp() && (instr->SFField() != 0) &&
336 uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12)
337 : (instr->Imm12Field());
339 *obj = Object::bool_true().ptr();
342 *obj = Object::bool_false().ptr();
354void InstructionPattern::EncodeLoadWordFromPoolFixed(
uword end,
357 Instr* instr = Instr::At(
start);
358 const int32_t upper12 =
offset & 0x00fff000;
359 const int32_t lower12 =
offset & 0x00000fff;
361 ASSERT(((lower12 >> 3) << 3) == lower12);
362 instr->SetImm12Bits(instr->InstructionBits(), lower12 >> 3);
364 start -= Instr::kInstrSize;
365 instr = Instr::At(
start);
366 instr->SetImm12Bits(instr->InstructionBits(), upper12 >> 12);
367 instr->SetInstructionBits(instr->InstructionBits() |
B22);
370CodePtr CallPattern::TargetCode()
const {
371 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_code_pool_index_));
374void CallPattern::SetTargetCode(
const Code&
target)
const {
375 object_pool_.SetObjectAt(target_code_pool_index_,
target);
380 return object_pool_.ObjectAt(data_pool_index_);
383void ICCallPattern::SetData(
const Object&
data)
const {
385 object_pool_.SetObjectAt(data_pool_index_,
data);
388CodePtr ICCallPattern::TargetCode()
const {
389 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_pool_index_));
392void ICCallPattern::SetTargetCode(
const Code&
target)
const {
393 object_pool_.SetObjectAt(target_pool_index_,
target);
397SwitchableCallPatternBase::SwitchableCallPatternBase(
398 const ObjectPool& object_pool)
399 : object_pool_(object_pool), data_pool_index_(-1), target_pool_index_(-1) {}
402 return object_pool_.ObjectAt(data_pool_index_);
405void SwitchableCallPatternBase::SetData(
const Object&
data)
const {
406 ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode());
407 object_pool_.SetObjectAt(data_pool_index_,
data);
410SwitchableCallPattern::SwitchableCallPattern(
uword pc,
const Code&
code)
411 : SwitchableCallPatternBase(ObjectPool::Handle(
code.GetObjectPool())) {
414 ASSERT(*(
reinterpret_cast<uint32_t*
>(pc) - 1) == 0xd63f03c0);
418 InstructionPattern::DecodeLoadDoubleWordFromPool(
419 pc - 2 * Instr::kInstrSize, &ic_data_reg, &code_reg, &pool_index);
421 ASSERT(IsBranchLinkScratch(code_reg));
423 data_pool_index_ = pool_index;
424 target_pool_index_ = pool_index + 1;
427uword SwitchableCallPattern::target_entry()
const {
428 return Code::Handle(Code::RawCast(object_pool_.ObjectAt(target_pool_index_)))
429 .MonomorphicEntryPoint();
432void SwitchableCallPattern::SetTarget(
const Code&
target)
const {
433 ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode());
434 object_pool_.SetObjectAt(target_pool_index_,
target);
437BareSwitchableCallPattern::BareSwitchableCallPattern(
uword pc)
438 : SwitchableCallPatternBase(ObjectPool::Handle(
439 IsolateGroup::Current()->object_store()->global_object_pool())) {
441 ASSERT(*(
reinterpret_cast<uint32_t*
>(pc) - 1) == 0xd63f03c0);
445 InstructionPattern::DecodeLoadDoubleWordFromPool(
446 pc - Instr::kInstrSize, &ic_data_reg, &code_reg, &pool_index);
450 data_pool_index_ = pool_index;
451 target_pool_index_ = pool_index + 1;
454uword BareSwitchableCallPattern::target_entry()
const {
455 return object_pool_.RawValueAt(target_pool_index_);
458void BareSwitchableCallPattern::SetTarget(
const Code&
target)
const {
459 ASSERT(object_pool_.TypeAt(target_pool_index_) ==
460 ObjectPool::EntryType::kImmediate);
461 object_pool_.SetRawValueAt(target_pool_index_,
462 target.MonomorphicEntryPoint());
465ReturnPattern::ReturnPattern(
uword pc) : pc_(pc) {}
467bool ReturnPattern::IsValid()
const {
468 Instr* bx_lr = Instr::At(pc_);
470 const int32_t instruction =
RET | (
static_cast<int32_t
>(crn) <<
kRnShift);
471 return bx_lr->InstructionBits() == instruction;
474bool PcRelativeCallPattern::IsValid()
const {
476 const uint32_t
word = *
reinterpret_cast<uint32_t*
>(pc_);
477 const uint32_t branch_link = 0x25;
478 return (
word >> 26) == branch_link;
481bool PcRelativeTailCallPattern::IsValid()
const {
483 const uint32_t
word = *
reinterpret_cast<uint32_t*
>(pc_);
484 const uint32_t branch_link = 0x5;
485 return (
word >> 26) == branch_link;
489#if !defined(DART_PRECOMPILED_RUNTIME)
490 uint32_t* pattern =
reinterpret_cast<uint32_t*
>(pattern_start_);
491 pattern[0] = kAdrEncoding;
492 pattern[1] = kMovzEncoding;
493 pattern[2] = kAddTmpTmp2;
494 pattern[3] = kJumpEncoding;
502#if !defined(DART_PRECOMPILED_RUNTIME)
503 uint32_t* pattern =
reinterpret_cast<uint32_t*
>(pattern_start_);
504 const uint32_t adr = pattern[0];
505 const uint32_t movz = pattern[1];
506 const uint32_t lower16 =
507 (((adr >> 5) & ((1 << 19) - 1)) << 2) | ((adr >> 29) & 0x3);
508 const uint32_t higher16 = (movz >>
kImm16Shift) & 0xffff;
509 return (higher16 << 16) | lower16;
516void PcRelativeTrampolineJumpPattern::set_distance(int32_t
distance) {
517#if !defined(DART_PRECOMPILED_RUNTIME)
518 uint32_t* pattern =
reinterpret_cast<uint32_t*
>(pattern_start_);
520 uint32_t high16 = (
distance >> 16) & 0xffff;
521 pattern[0] = kAdrEncoding | ((low16 & 0x3) << 29) | ((low16 >> 2) << 5);
522 pattern[1] = kMovzEncoding | (high16 <<
kImm16Shift);
529bool PcRelativeTrampolineJumpPattern::IsValid()
const {
530#if !defined(DART_PRECOMPILED_RUNTIME)
531 const uint32_t adr_mask = (3 << 29) | (((1 << 19) - 1) << 5);
532 const uint32_t movz_mask = 0xffff << 5;
533 uint32_t* pattern =
reinterpret_cast<uint32_t*
>(pattern_start_);
534 return ((pattern[0] & ~adr_mask) == kAdrEncoding) &&
535 ((pattern[1] & ~movz_mask) == kMovzEncoding) &&
536 (pattern[2] == kAddTmpTmp2) && (pattern[3] == kJumpEncoding);
543intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
555 uword pc = pc_ - Instr::kInstrSize;
556 const uword blr_r9 = 0xd63f0120;
557 if (*
reinterpret_cast<uint32_t*
>(pc) != blr_r9) {
558 PcRelativeCallPattern pattern(pc);
562 const uword load_instr_end = pc;
565 intptr_t pool_index = -1;
566 InstructionPattern::DecodeLoadWordFromPool(load_instr_end, ®, &pool_index);
#define ASSERT_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
CallPattern(uword pc, const Code &code)
bool ObjectAtPoolIndex(const Code &code, intptr_t index, Object *obj)
static constexpr intptr_t kFalseOffsetFromNull
static constexpr intptr_t kTrueOffsetFromNull
Register ConcreteRegister(LinkRegister)
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