Index: runtime/vm/assembler_mips.cc |
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc |
index 5bfa9af60987c48c03024627fe923988d6f08f34..4bdc206dc85f2abae0e4309b0a3a56bb0bf98ecf 100644 |
--- a/runtime/vm/assembler_mips.cc |
+++ b/runtime/vm/assembler_mips.cc |
@@ -355,24 +355,22 @@ void Assembler::Bind(Label* label) { |
} |
-void Assembler::LoadWordFromPoolOffset(Register rd, |
- int32_t offset, |
- Register pp) { |
- ASSERT((pp != PP) || constant_pool_allowed()); |
+void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) { |
+ ASSERT(constant_pool_allowed()); |
ASSERT(!in_delay_slot_); |
- ASSERT(rd != pp); |
+ ASSERT(rd != PP); |
if (Address::CanHoldOffset(offset)) { |
- lw(rd, Address(pp, offset)); |
+ lw(rd, Address(PP, offset)); |
} else { |
const int16_t offset_low = Utils::Low16Bits(offset); // Signed. |
offset -= offset_low; |
const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned. |
if (offset_high != 0) { |
lui(rd, Immediate(offset_high)); |
- addu(rd, rd, pp); |
+ addu(rd, rd, PP); |
lw(rd, Address(rd, offset_low)); |
} else { |
- lw(rd, Address(pp, offset_low)); |
+ lw(rd, Address(PP, offset_low)); |
} |
} |
} |
@@ -459,43 +457,22 @@ void Assembler::SubuDetectOverflow(Register rd, Register rs, Register rt, |
} |
-void Assembler::CheckCodePointer() { |
-#ifdef DEBUG |
- Label cid_ok, instructions_ok; |
- Push(CMPRES1); |
- Push(CMPRES2); |
- LoadClassId(CMPRES1, CODE_REG); |
- BranchEqual(CMPRES1, Immediate(kCodeCid), &cid_ok); |
- break_(0); |
- Bind(&cid_ok); |
- GetNextPC(CMPRES1, TMP); |
- const intptr_t entry_offset = CodeSize() - Instr::kInstrSize + |
- Instructions::HeaderSize() - kHeapObjectTag; |
- AddImmediate(CMPRES1, CMPRES1, -entry_offset); |
- lw(CMPRES2, FieldAddress(CODE_REG, Code::saved_instructions_offset())); |
- BranchEqual(CMPRES1, CMPRES2, &instructions_ok); |
- break_(1); |
- Bind(&instructions_ok); |
- Pop(CMPRES2); |
- Pop(CMPRES1); |
-#endif |
-} |
- |
- |
-void Assembler::RestoreCodePointer() { |
- lw(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize)); |
- CheckCodePointer(); |
+void Assembler::Branch(const StubEntry& stub_entry) { |
+ ASSERT(!in_delay_slot_); |
+ LoadImmediate(TMP, stub_entry.label().address()); |
+ jr(TMP); |
} |
-void Assembler::Branch(const StubEntry& stub_entry, Register pp) { |
+void Assembler::BranchPatchable(const StubEntry& stub_entry) { |
ASSERT(!in_delay_slot_); |
- const Code& target_code = Code::Handle(stub_entry.code()); |
- const int32_t offset = ObjectPool::element_offset( |
- object_pool_wrapper_.FindObject(target_code, kPatchable)); |
- LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, pp); |
- lw(TMP, FieldAddress(CODE_REG, Code::entry_point_offset())); |
- jr(TMP); |
+ const ExternalLabel& label = stub_entry.label(); |
+ const uint16_t low = Utils::Low16Bits(label.address()); |
+ const uint16_t high = Utils::High16Bits(label.address()); |
+ lui(T9, Immediate(high)); |
+ ori(T9, T9, Immediate(low)); |
+ jr(T9); |
+ delay_slot_available_ = false; // CodePatcher expects a nop. |
} |
@@ -510,21 +487,7 @@ void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { |
ASSERT(!in_delay_slot_); |
const int32_t offset = ObjectPool::element_offset( |
object_pool_wrapper_.FindExternalLabel(label, patchable)); |
- LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag); |
- lw(T9, FieldAddress(CODE_REG, Code::entry_point_offset())); |
- jalr(T9); |
- if (patchable == kPatchable) { |
- delay_slot_available_ = false; // CodePatcher expects a nop. |
- } |
-} |
- |
- |
-void Assembler::BranchLink(const Code& target, Patchability patchable) { |
- ASSERT(!in_delay_slot_); |
- const int32_t offset = ObjectPool::element_offset( |
- object_pool_wrapper_.FindObject(target, patchable)); |
- LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag); |
- lw(T9, FieldAddress(CODE_REG, Code::entry_point_offset())); |
+ LoadWordFromPoolOffset(T9, offset - kHeapObjectTag); |
jalr(T9); |
if (patchable == kPatchable) { |
delay_slot_available_ = false; // CodePatcher expects a nop. |
@@ -534,12 +497,12 @@ void Assembler::BranchLink(const Code& target, Patchability patchable) { |
void Assembler::BranchLink(const StubEntry& stub_entry, |
Patchability patchable) { |
- BranchLink(Code::Handle(stub_entry.code()), patchable); |
+ BranchLink(&stub_entry.label(), patchable); |
} |
void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { |
- BranchLink(Code::Handle(stub_entry.code()), kPatchable); |
+ BranchLink(&stub_entry.label(), kPatchable); |
} |
@@ -594,15 +557,6 @@ void Assembler::LoadExternalLabel(Register rd, |
} |
-void Assembler::LoadFunctionFromCalleePool(Register dst, |
- const Function& function, |
- Register new_pp) { |
- const int32_t offset = |
- ObjectPool::element_offset(object_pool_wrapper_.FindObject(function)); |
- LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp); |
-} |
- |
- |
void Assembler::LoadNativeEntry(Register rd, |
const ExternalLabel* label, |
Patchability patchable) { |
@@ -680,7 +634,6 @@ void Assembler::StoreIntoObject(Register object, |
if (object != T0) { |
mov(T0, object); |
} |
- lw(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset())); |
lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset())); |
jalr(T9); |
lw(RA, Address(SP, 0 * kWordSize)); |
@@ -875,8 +828,17 @@ void Assembler::LeaveFrameAndReturn() { |
} |
-void Assembler::EnterStubFrame(intptr_t frame_size) { |
- EnterDartFrame(frame_size); |
+void Assembler::EnterStubFrame() { |
+ ASSERT(!in_delay_slot_); |
+ SetPrologueOffset(); |
+ addiu(SP, SP, Immediate(-4 * kWordSize)); |
+ sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. |
+ sw(RA, Address(SP, 2 * kWordSize)); |
+ sw(FP, Address(SP, 1 * kWordSize)); |
+ sw(PP, Address(SP, 0 * kWordSize)); |
+ addiu(FP, SP, Immediate(1 * kWordSize)); |
+ // Setup pool pointer for this stub. |
+ LoadPoolPointer(); |
} |
@@ -886,7 +848,13 @@ void Assembler::LeaveStubFrame() { |
void Assembler::LeaveStubFrameAndReturn(Register ra) { |
- LeaveDartFrameAndReturn(ra); |
+ ASSERT(!in_delay_slot_); |
+ addiu(SP, FP, Immediate(-1 * kWordSize)); |
+ lw(RA, Address(SP, 2 * kWordSize)); |
+ lw(FP, Address(SP, 1 * kWordSize)); |
+ lw(PP, Address(SP, 0 * kWordSize)); |
+ jr(ra); |
+ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
} |
@@ -1106,19 +1074,31 @@ void Assembler::CallRuntime(const RuntimeEntry& entry, |
void Assembler::EnterDartFrame(intptr_t frame_size) { |
ASSERT(!in_delay_slot_); |
+ const intptr_t offset = CodeSize(); |
SetPrologueOffset(); |
addiu(SP, SP, Immediate(-4 * kWordSize)); |
- sw(RA, Address(SP, 3 * kWordSize)); |
- sw(FP, Address(SP, 2 * kWordSize)); |
- sw(CODE_REG, Address(SP, 1 * kWordSize)); |
+ sw(RA, Address(SP, 2 * kWordSize)); |
+ sw(FP, Address(SP, 1 * kWordSize)); |
sw(PP, Address(SP, 0 * kWordSize)); |
+ GetNextPC(TMP); // TMP gets the address of the next instruction. |
+ |
+ // Calculate the offset of the pool pointer from the PC. |
+ const intptr_t object_pool_pc_dist = |
+ Instructions::HeaderSize() - Instructions::object_pool_offset() + |
+ CodeSize(); |
+ |
+ // Save PC in frame for fast identification of corresponding code. |
+ AddImmediate(TMP, -offset); |
+ sw(TMP, Address(SP, 3 * kWordSize)); |
+ |
// Set FP to the saved previous FP. |
- addiu(FP, SP, Immediate(2 * kWordSize)); |
+ addiu(FP, SP, Immediate(kWordSize)); |
- LoadPoolPointer(); |
+ // Load the pool pointer. offset has already been subtracted from TMP. |
+ lw(PP, Address(TMP, -object_pool_pc_dist + offset)); |
// Reserve space for locals. |
AddImmediate(SP, -frame_size); |
@@ -1134,43 +1114,55 @@ void Assembler::EnterOsrFrame(intptr_t extra_size) { |
ASSERT(!in_delay_slot_); |
Comment("EnterOsrFrame"); |
+ GetNextPC(TMP); // TMP gets the address of the next instruction. |
+ |
+ // The runtime system assumes that the code marker address is |
+ // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no |
+ // code to set up the frame pointer, etc., the address needs to be adjusted. |
+ const intptr_t offset = EntryPointToPcMarkerOffset() - CodeSize(); |
+ // Calculate the offset of the pool pointer from the PC. |
+ const intptr_t object_pool_pc_dist = |
+ Instructions::HeaderSize() - Instructions::object_pool_offset() + |
+ CodeSize(); |
+ |
+ // Adjust PC by the offset, and store it in the stack frame. |
+ AddImmediate(TMP, TMP, offset); |
+ sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); |
+ |
// Restore return address. |
lw(RA, Address(FP, 1 * kWordSize)); |
// Load the pool pointer. offset has already been subtracted from temp. |
- RestoreCodePointer(); |
- LoadPoolPointer(); |
+ lw(PP, Address(TMP, -object_pool_pc_dist - offset)); |
// Reserve space for locals. |
AddImmediate(SP, -extra_size); |
} |
-void Assembler::LeaveDartFrame(RestorePP restore_pp) { |
+void Assembler::LeaveDartFrame() { |
ASSERT(!in_delay_slot_); |
- addiu(SP, FP, Immediate(-2 * kWordSize)); |
+ addiu(SP, FP, Immediate(-kWordSize)); |
- lw(RA, Address(SP, 3 * kWordSize)); |
- lw(FP, Address(SP, 2 * kWordSize)); |
- if (restore_pp == kRestoreCallerPP) { |
- lw(PP, Address(SP, 0 * kWordSize)); |
- } |
+ lw(RA, Address(SP, 2 * kWordSize)); |
+ lw(FP, Address(SP, 1 * kWordSize)); |
+ lw(PP, Address(SP, 0 * kWordSize)); |
// Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. |
addiu(SP, SP, Immediate(4 * kWordSize)); |
} |
-void Assembler::LeaveDartFrameAndReturn(Register ra) { |
+void Assembler::LeaveDartFrameAndReturn() { |
ASSERT(!in_delay_slot_); |
- addiu(SP, FP, Immediate(-2 * kWordSize)); |
+ addiu(SP, FP, Immediate(-kWordSize)); |
- lw(RA, Address(SP, 3 * kWordSize)); |
- lw(FP, Address(SP, 2 * kWordSize)); |
+ lw(RA, Address(SP, 2 * kWordSize)); |
+ lw(FP, Address(SP, 1 * kWordSize)); |
lw(PP, Address(SP, 0 * kWordSize)); |
// Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. |
- jr(ra); |
+ Ret(); |
delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
} |