| 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));
|
| }
|
|
|
|
|