Index: runtime/vm/assembler_mips.cc |
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc |
index b9227a48624df7cc8b1dd63e756e66c2796adec7..954978ff291aca9785291962dc40a2549014e6c2 100644 |
--- a/runtime/vm/assembler_mips.cc |
+++ b/runtime/vm/assembler_mips.cc |
@@ -355,22 +355,24 @@ void Assembler::Bind(Label* label) { |
} |
-void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) { |
- ASSERT(constant_pool_allowed()); |
+void Assembler::LoadWordFromPoolOffset(Register rd, |
+ int32_t offset, |
+ Register pp) { |
+ ASSERT((pp != PP) || 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)); |
} |
} |
} |
@@ -457,22 +459,43 @@ void Assembler::SubuDetectOverflow(Register rd, Register rs, Register rt, |
} |
-void Assembler::Branch(const StubEntry& stub_entry) { |
- ASSERT(!in_delay_slot_); |
- LoadImmediate(TMP, stub_entry.label().address()); |
- jr(TMP); |
+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::BranchPatchable(const StubEntry& stub_entry) { |
+void Assembler::RestoreCodePointer() { |
+ lw(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize)); |
+ CheckCodePointer(); |
+} |
+ |
+ |
+void Assembler::Branch(const StubEntry& stub_entry, Register pp) { |
ASSERT(!in_delay_slot_); |
- 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. |
+ 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); |
} |
@@ -487,7 +510,21 @@ 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(T9, offset - kHeapObjectTag); |
+ 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())); |
jalr(T9); |
if (patchable == kPatchable) { |
delay_slot_available_ = false; // CodePatcher expects a nop. |
@@ -497,12 +534,12 @@ void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { |
void Assembler::BranchLink(const StubEntry& stub_entry, |
Patchability patchable) { |
- BranchLink(&stub_entry.label(), patchable); |
+ BranchLink(Code::Handle(stub_entry.code()), patchable); |
} |
void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { |
- BranchLink(&stub_entry.label(), kPatchable); |
+ BranchLink(Code::Handle(stub_entry.code()), kPatchable); |
} |
@@ -568,6 +605,15 @@ 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) { |
@@ -645,6 +691,7 @@ 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)); |
@@ -839,17 +886,8 @@ void Assembler::LeaveFrameAndReturn() { |
} |
-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(); |
+void Assembler::EnterStubFrame(intptr_t frame_size) { |
+ EnterDartFrame(frame_size); |
} |
@@ -859,13 +897,7 @@ void Assembler::LeaveStubFrame() { |
void Assembler::LeaveStubFrameAndReturn(Register 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)); |
+ LeaveDartFrameAndReturn(ra); |
} |
@@ -1085,31 +1117,19 @@ 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, 2 * kWordSize)); |
- sw(FP, Address(SP, 1 * kWordSize)); |
+ sw(RA, Address(SP, 3 * kWordSize)); |
+ sw(FP, Address(SP, 2 * kWordSize)); |
+ sw(CODE_REG, 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(kWordSize)); |
+ addiu(FP, SP, Immediate(2 * kWordSize)); |
- // Load the pool pointer. offset has already been subtracted from TMP. |
- lw(PP, Address(TMP, -object_pool_pc_dist + offset)); |
+ LoadPoolPointer(); |
// Reserve space for locals. |
AddImmediate(SP, -frame_size); |
@@ -1125,55 +1145,43 @@ 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. |
- lw(PP, Address(TMP, -object_pool_pc_dist - offset)); |
+ RestoreCodePointer(); |
+ LoadPoolPointer(); |
// Reserve space for locals. |
AddImmediate(SP, -extra_size); |
} |
-void Assembler::LeaveDartFrame() { |
+void Assembler::LeaveDartFrame(RestorePP restore_pp) { |
ASSERT(!in_delay_slot_); |
- addiu(SP, FP, Immediate(-kWordSize)); |
+ addiu(SP, FP, Immediate(-2 * kWordSize)); |
- lw(RA, Address(SP, 2 * kWordSize)); |
- lw(FP, Address(SP, 1 * kWordSize)); |
- lw(PP, Address(SP, 0 * kWordSize)); |
+ lw(RA, Address(SP, 3 * kWordSize)); |
+ lw(FP, Address(SP, 2 * kWordSize)); |
+ if (restore_pp == kRestoreCallerPP) { |
+ 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() { |
+void Assembler::LeaveDartFrameAndReturn(Register ra) { |
ASSERT(!in_delay_slot_); |
- addiu(SP, FP, Immediate(-kWordSize)); |
+ addiu(SP, FP, Immediate(-2 * kWordSize)); |
- lw(RA, Address(SP, 2 * kWordSize)); |
- lw(FP, Address(SP, 1 * kWordSize)); |
+ lw(RA, Address(SP, 3 * kWordSize)); |
+ lw(FP, Address(SP, 2 * kWordSize)); |
lw(PP, Address(SP, 0 * kWordSize)); |
// Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. |
- Ret(); |
+ jr(ra); |
delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
} |