6#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
19static bool IsJumpAndLinkScratch(
Register reg) {
20 return reg == (FLAG_precompiled_mode ?
TMP :
CODE_REG);
24 : object_pool_(ObjectPool::Handle(
code.GetObjectPool())),
25 target_code_pool_index_(-1) {
33 ASSERT(*
reinterpret_cast<uint16_t*
>(pc - 2) == 0x9082);
35 InstructionPattern::DecodeLoadWordFromPool(pc - 6, ®,
36 &target_code_pool_index_);
37 ASSERT(IsJumpAndLinkScratch(reg));
40ICCallPattern::ICCallPattern(uword pc,
const Code& code)
41 : object_pool_(ObjectPool::Handle(
code.GetObjectPool())),
42 target_pool_index_(-1),
43 data_pool_index_(-1) {
52 ASSERT(*
reinterpret_cast<uint16_t*
>(pc - 2) == 0x9082);
55 uword data_load_end = InstructionPattern::DecodeLoadWordFromPool(
56 pc - 6, ®, &target_pool_index_);
57 ASSERT(IsJumpAndLinkScratch(reg));
59 InstructionPattern::DecodeLoadWordFromPool(data_load_end, ®,
61 ASSERT(reg == IC_DATA_REG);
64NativeCallPattern::NativeCallPattern(uword pc,
const Code& code)
65 : object_pool_(ObjectPool::Handle(
code.GetObjectPool())),
67 native_function_pool_index_(-1),
68 target_code_pool_index_(-1) {
77 ASSERT(*
reinterpret_cast<uint16_t*
>(pc - 2) == 0x9082);
80 uword native_function_load_end = InstructionPattern::DecodeLoadWordFromPool(
81 pc - 6, ®, &target_code_pool_index_);
82 ASSERT(IsJumpAndLinkScratch(reg));
83 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, ®,
84 &native_function_pool_index_);
88CodePtr NativeCallPattern::target()
const {
89 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_code_pool_index_));
92void NativeCallPattern::set_target(
const Code&
target)
const {
93 object_pool_.SetObjectAt(target_code_pool_index_,
target);
99 object_pool_.RawValueAt(native_function_pool_index_));
102void NativeCallPattern::set_native_function(NativeFunction func)
const {
103 object_pool_.SetRawValueAt(native_function_pool_index_,
104 reinterpret_cast<uword>(func));
112uword InstructionPattern::DecodeLoadWordImmediate(uword
end,
119static bool DecodeLoadX(uword
end,
124 Instr instr(LoadUnaligned(
reinterpret_cast<uint32_t*
>(
end - 4)));
126 if (instr.opcode() == LOAD && instr.funct3() == LW) {
128 if (instr.opcode() == LOAD && instr.funct3() == LD) {
132 *
offset = instr.itype_imm();
137 CInstr cinstr(*
reinterpret_cast<uint16_t*
>(
end - 2));
139 if (cinstr.opcode() == C_LW) {
141 if (cinstr.opcode() == C_LD) {
144 *
base = cinstr.rs1p();
146 *
offset = cinstr.mem4_imm();
148 *
offset = cinstr.mem8_imm();
157static bool DecodeLUI(uword
end,
161 Instr instr(LoadUnaligned(
reinterpret_cast<uint32_t*
>(
end - 4)));
162 if (instr.opcode() == LUI) {
164 *imm = instr.utype_imm();
169 CInstr cinstr(*
reinterpret_cast<uint16_t*
>(
end - 2));
170 if (cinstr.opcode() == C_LUI) {
172 *imm = cinstr.u_imm();
181uword InstructionPattern::DecodeLoadWordFromPool(uword
end,
198 *index = ObjectPool::IndexFromOffset(lo - kHeapObjectTag);
204 CInstr add_instr(*
reinterpret_cast<uint16_t*
>(
end - 2));
205 ASSERT(add_instr.opcode() ==
209 ASSERT(add_instr.rs2() == PP);
214 if (!DecodeLUI(
end, &dst, &hi, &
length)) {
219 *index = ObjectPool::IndexFromOffset(hi + lo - kHeapObjectTag);
225 uint16_t parcel = *
reinterpret_cast<uint16_t*
>(pc);
227 CInstr instr(parcel);
229 if (instr.opcode() == C_LW) {
230 intptr_t
offset = instr.mem4_imm();
232 if (instr.opcode() == C_LD) {
233 intptr_t
offset = instr.mem8_imm();
235 if (instr.rs1p() == PP) {
237 if (!Utils::IsAligned(
offset, kWordSize)) {
240 intptr_t index = ObjectPool::IndexFromOffset(
offset - kHeapObjectTag);
242 }
else if (instr.rs1p() == THR) {
243 return Thread::ObjectAtOffset(
offset, obj);
247 Instr instr(LoadUnaligned(
reinterpret_cast<uint32_t*
>(pc)));
249 if (instr.opcode() == LOAD && instr.funct3() == LW) {
251 if (instr.opcode() == LOAD && instr.funct3() == LD) {
253 intptr_t
offset = instr.itype_imm();
254 if (instr.rs1() == PP) {
256 if (!Utils::IsAligned(
offset, kWordSize)) {
259 intptr_t index = ObjectPool::IndexFromOffset(
offset - kHeapObjectTag);
261 }
else if (instr.rs1() == THR) {
262 return Thread::ObjectAtOffset(
offset, obj);
265 if ((instr.opcode() == OPIMM) && (instr.funct3() == ADDI) &&
266 (instr.rs1() == NULL_REG)) {
267 if (instr.itype_imm() == 0) {
268 *obj = Object::null();
271 if (instr.itype_imm() == kTrueOffsetFromNull) {
272 *obj = Object::bool_true().ptr();
275 if (instr.itype_imm() == kFalseOffsetFromNull) {
276 *obj = Object::bool_false().ptr();
290void InstructionPattern::EncodeLoadWordFromPoolFixed(uword
end,
295CodePtr CallPattern::TargetCode()
const {
296 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_code_pool_index_));
299void CallPattern::SetTargetCode(
const Code&
target)
const {
300 object_pool_.SetObjectAt(target_code_pool_index_,
target);
304ObjectPtr ICCallPattern::Data()
const {
305 return object_pool_.ObjectAt(data_pool_index_);
308void ICCallPattern::SetData(
const Object& data)
const {
310 object_pool_.SetObjectAt(data_pool_index_, data);
313CodePtr ICCallPattern::TargetCode()
const {
314 return static_cast<CodePtr
>(object_pool_.ObjectAt(target_pool_index_));
317void ICCallPattern::SetTargetCode(
const Code&
target)
const {
318 object_pool_.SetObjectAt(target_pool_index_,
target);
322SwitchableCallPatternBase::SwitchableCallPatternBase(
323 const ObjectPool& object_pool)
324 : object_pool_(object_pool), data_pool_index_(-1), target_pool_index_(-1) {}
326ObjectPtr SwitchableCallPatternBase::data()
const {
327 return object_pool_.ObjectAt(data_pool_index_);
330void SwitchableCallPatternBase::SetData(
const Object& data)
const {
331 ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode());
332 object_pool_.SetObjectAt(data_pool_index_, data);
335SwitchableCallPattern::SwitchableCallPattern(uword pc,
const Code& code)
336 : SwitchableCallPatternBase(ObjectPool::Handle(
code.GetObjectPool())) {
341uword SwitchableCallPattern::target_entry()
const {
342 return Code::Handle(Code::RawCast(object_pool_.ObjectAt(target_pool_index_)))
343 .MonomorphicEntryPoint();
346void SwitchableCallPattern::SetTarget(
const Code&
target)
const {
347 ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode());
348 object_pool_.SetObjectAt(target_pool_index_,
target);
351BareSwitchableCallPattern::BareSwitchableCallPattern(uword pc)
352 : SwitchableCallPatternBase(ObjectPool::Handle(
353 IsolateGroup::Current()->object_store()->global_object_pool())) {
359 ASSERT(*
reinterpret_cast<uint16_t*
>(pc - 2) == 0x9082);
362 uword target_load_end = InstructionPattern::DecodeLoadWordFromPool(
363 pc - 2, ®, &data_pool_index_);
366 InstructionPattern::DecodeLoadWordFromPool(target_load_end, ®,
367 &target_pool_index_);
371uword BareSwitchableCallPattern::target_entry()
const {
372 return object_pool_.RawValueAt(target_pool_index_);
375void BareSwitchableCallPattern::SetTarget(
const Code&
target)
const {
376 ASSERT(object_pool_.TypeAt(target_pool_index_) ==
377 ObjectPool::EntryType::kImmediate);
378 object_pool_.SetRawValueAt(target_pool_index_,
379 target.MonomorphicEntryPoint());
382ReturnPattern::ReturnPattern(uword pc) : pc_(pc) {}
384bool ReturnPattern::IsValid()
const {
385 return *
reinterpret_cast<uint16_t*
>(pc_) == 0x8082;
388bool PcRelativeCallPattern::IsValid()
const {
389 Instr aupic(LoadUnaligned(
reinterpret_cast<uint32_t*
>(pc_)));
390 if (aupic.opcode() != AUIPC)
return false;
391 Instr jalr(LoadUnaligned(
reinterpret_cast<uint32_t*
>(pc_ + 4)));
392 if (jalr.opcode() != JALR)
return false;
393 if (aupic.rd() != jalr.rs1())
return false;
394 if (jalr.rd() !=
RA)
return false;
398bool PcRelativeTailCallPattern::IsValid()
const {
399 Instr aupic(LoadUnaligned(
reinterpret_cast<uint32_t*
>(pc_)));
400 if (aupic.opcode() != AUIPC)
return false;
401 Instr jr(LoadUnaligned(
reinterpret_cast<uint32_t*
>(pc_ + 4)));
402 if (jr.opcode() != JALR)
return false;
403 if (aupic.rd() != jr.rs1())
return false;
404 if (jr.rd() != ZR)
return false;
408void PcRelativeTrampolineJumpPattern::Initialize() {
409 StoreUnaligned(
reinterpret_cast<uint32_t*
>(pc_),
411 StoreUnaligned(
reinterpret_cast<uint32_t*
>(pc_ + 4),
412 EncodeOpcode(JALR) | EncodeFunct3(F3_0) | EncodeRd(ZR) |
416intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
425 if (*
reinterpret_cast<uint16_t*
>(pc_ - 2) == 0x9982) {
429 intptr_t pool_index = -1;
430 InstructionPattern::DecodeLoadWordFromPool(pc_ - 2, ®, &pool_index);
434 ASSERT(FLAG_precompiled_mode);
438 Instr jalr(LoadUnaligned(
reinterpret_cast<uint32_t*
>(pc_ - 4)));
439 ASSERT(jalr.opcode() == JALR);
440 Instr auipc(LoadUnaligned(
reinterpret_cast<uint32_t*
>(pc_ - 8)));
441 ASSERT(auipc.opcode() == AUIPC);
444 intptr_t pool_index = -1;
445 InstructionPattern::DecodeLoadWordFromPool(pc_ - 8, ®, &pool_index);
#define RA(width, name,...)
#define ASSERT_EQUAL(expected, actual)
CallPattern(uword pc, const Code &code)
bool ObjectAtPoolIndex(const Code &code, intptr_t index, Object *obj)
uint32_t EncodeUTypeImm(intptr_t imm)
bool IsCInstruction(uint16_t parcel)
bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code &code, Object *obj)
uint32_t EncodeITypeImm(intptr_t imm)
void(* NativeFunction)(NativeArguments *arguments)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data