Chromium Code Reviews| Index: runtime/vm/stub_code_mips.cc |
| =================================================================== |
| --- runtime/vm/stub_code_mips.cc (revision 22187) |
| +++ runtime/vm/stub_code_mips.cc (working copy) |
| @@ -81,10 +81,11 @@ |
| __ addiu(A2, A2, Immediate(kWordSize)); // Set argv in NativeArguments. |
| ASSERT(retval_offset == 3 * kWordSize); |
| - __ addiu(A3, A2, Immediate(kWordSize)); // Retval is next to 1st argument. |
| // Call runtime or redirection via simulator. |
| __ jalr(S5); |
| + // Retval is next to 1st argument. |
| + __ delay_slot()->addiu(A3, A2, Immediate(kWordSize)); |
| __ TraceSimMsg("CallToRuntimeStub return"); |
| // Reset exit frame information in Isolate structure. |
| @@ -175,10 +176,9 @@ |
| __ sw(A1, Address(SP, 1 * kWordSize)); |
| __ sw(A0, Address(SP, 0 * kWordSize)); |
| - __ mov(A0, SP); // Pass the pointer to the NativeArguments. |
| - |
| // Call native function or redirection via simulator. |
| __ jalr(T5); |
| + __ delay_slot()->mov(A0, SP); // Pass the pointer to the NativeArguments. |
| __ TraceSimMsg("CallNativeCFunctionStub return"); |
| // Reset exit frame information in Isolate structure. |
| @@ -228,6 +228,7 @@ |
| __ lw(T0, FieldAddress(T0, Code::instructions_offset())); |
| __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); |
| __ jr(T0); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| } |
| @@ -250,10 +251,12 @@ |
| __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| // Remove the stub frame. |
| __ LeaveStubFrame(); |
| + |
| // Jump to the dart function. |
| __ lw(T0, FieldAddress(T0, Code::instructions_offset())); |
| __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag); |
| __ jr(T0); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| } |
| @@ -274,19 +277,21 @@ |
| __ sll(T1, A1, 1); |
| __ addu(T1, FP, T1); |
| __ AddImmediate(T1, (kLastParamSlotIndex - 1) * kWordSize); |
| - __ AddImmediate(T2, V0, Array::data_offset() - kHeapObjectTag); |
| // T1: address of first argument on stack. |
| // T2: address of first argument in array. |
| - Label loop, loop_condition; |
| - __ b(&loop_condition); |
| + |
| + Label loop, loop_exit; |
| + __ blez(A1, &loop_exit); |
| + __ delay_slot()->addiu(T2, V0, |
| + Immediate(Array::data_offset() - kHeapObjectTag)); |
| __ Bind(&loop); |
| __ lw(TMP, Address(T1)); |
| - __ sw(TMP, Address(T2)); |
| - __ AddImmediate(T1, -kWordSize); |
| - __ AddImmediate(T2, kWordSize); |
| - __ Bind(&loop_condition); |
| - __ AddImmediate(A1, -Smi::RawValue(1)); // A1 is Smi. |
| - __ BranchSignedGreaterEqual(A1, ZR, &loop); |
| + __ addiu(A1, A1, Immediate(-Smi::RawValue(1))); |
| + __ addiu(T1, T1, Immediate(-kWordSize)); |
| + __ addiu(T2, T2, Immediate(kWordSize)); |
| + __ bgez(A1, &loop); |
| + __ delay_slot()->sw(TMP, Address(T2, -kWordSize)); |
| + __ Bind(&loop_exit); |
| } |
| @@ -338,6 +343,7 @@ |
| __ addiu(SP, SP, Immediate(5 * kWordSize)); // Get result into V0. |
| __ LeaveStubFrame(); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| } |
| @@ -454,6 +460,7 @@ |
| } |
| __ LeaveStubFrame(); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| } |
| @@ -570,17 +577,21 @@ |
| // T2: new object end address. |
| // A1: Array length as Smi. |
| __ AddImmediate(T3, V0, Array::data_offset() - kHeapObjectTag); |
| - // R1: iterator which initially points to the start of the variable |
| + // T3: iterator which initially points to the start of the variable |
| // data area to be initialized. |
| - __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null())); |
| - Label loop, test; |
| - __ b(&test); |
| + |
| + Label loop, loop_exit; |
| + intptr_t null = reinterpret_cast<intptr_t>(Object::null()); |
| + uint16_t null_lo = Utils::Low16Bits(null); |
| + uint16_t null_hi = Utils::High16Bits(null); |
| + __ lui(TMP1, Immediate(null_hi)); |
| + __ BranchUnsignedGreaterEqual(T3, T2, &loop_exit); |
| + __ delay_slot()->ori(TMP1, TMP1, Immediate(null_lo)); |
| __ Bind(&loop); |
| - // TODO(cshapiro): StoreIntoObjectNoBarrier |
| - __ sw(TMP1, Address(T3, 0)); |
| - __ AddImmediate(T3, kWordSize); |
| - __ Bind(&test); |
| + __ addiu(T3, T3, Immediate(kWordSize)); |
| __ bne(T3, T2, &loop); |
| + __ delay_slot()->sw(TMP1, Address(T3, -kWordSize)); |
| + __ Bind(&loop_exit); |
| // Done allocating and initializing the array. |
| // V0: new object. |
| @@ -611,6 +622,7 @@ |
| __ mov(V0, TMP1); |
| __ LeaveStubFrame(); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| } |
| @@ -682,6 +694,7 @@ |
| // Remove the stub frame as we are about to jump to the closure function. |
| __ LeaveStubFrame(); |
| + __ LeaveStubFrameSPRestore(); |
| __ Bind(&function_compiled); |
| // T0: Code. |
| @@ -727,6 +740,7 @@ |
| // Remove the stub frame as we are about to return. |
| __ LeaveStubFrame(); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| } |
| @@ -795,12 +809,13 @@ |
| // Compute address of 'arguments array' data area into A2. |
| __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle)); |
| - __ AddImmediate(A2, Array::data_offset() - kHeapObjectTag); |
| // Set up arguments for the Dart call. |
| Label push_arguments; |
| Label done_push_arguments; |
| __ beq(T1, ZR, &done_push_arguments); // check if there are arguments. |
| + __ delay_slot()->addiu(A2, A2, |
| + Immediate(Array::data_offset() - kHeapObjectTag)); |
| __ mov(A1, ZR); |
| __ Bind(&push_arguments); |
| __ lw(A3, Address(A2)); |
| @@ -845,6 +860,7 @@ |
| // Restore the frame pointer and return. |
| __ LeaveStubFrame(); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| } |
| @@ -927,26 +943,24 @@ |
| // T2: isolate, not an object. |
| __ sw(T2, FieldAddress(V0, Context::isolate_offset())); |
| - // Setup the parent field. |
| - // V0: new object. |
| - // T1: number of context variables. |
| __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null())); |
| - __ sw(T2, FieldAddress(V0, Context::parent_offset())); |
| // Initialize the context variables. |
| // V0: new object. |
| // T1: number of context variables. |
| // T2: raw null. |
| - Label loop, loop_test; |
| + Label loop, loop_exit; |
| + __ blez(T1, &loop_exit); |
| + // Setup the parent field. |
| + __ delay_slot()->sw(T2, FieldAddress(V0, Context::parent_offset())); |
| __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag); |
| - __ b(&loop_test); |
| - __ delay_slot()->sll(T1, T1, 2); |
| + __ sll(T1, T1, 2); |
| __ Bind(&loop); |
| + __ addiu(T1, T1, Immediate(-kWordSize)); |
| __ addu(TMP1, T3, T1); |
| - __ sw(T2, Address(TMP1)); |
| - __ Bind(&loop_test); |
| - __ addiu(T1, T1, Immediate(-kWordSize)); |
| - __ bne(T1, ZR, &loop); // Loop if R1 not zero. |
| + __ bgtz(T1, &loop); |
| + __ delay_slot()->sw(T2, Address(TMP1)); |
| + __ Bind(&loop_exit); |
| // Done allocating and initializing the context. |
| // V0: new object. |
| @@ -970,6 +984,7 @@ |
| // V0: new object |
| // Restore the frame pointer. |
| __ LeaveStubFrame(); |
| + __ LeaveStubFrameSPRestore(); |
|
regis
2013/05/01 01:21:46
Why didn't you use the delay slot here?
zra
2013/05/01 16:53:17
Missed it. Thanks!
|
| __ Ret(); |
| } |
| @@ -1152,14 +1167,13 @@ |
| // T3: next object start. |
| // T4: next word to be initialized. |
| // T1: new object type arguments (if is_cls_parameterized). |
| - Label init_loop; |
| - Label done; |
| - __ Bind(&init_loop); |
| - __ BranchUnsignedGreaterEqual(T4, T3, &done); // Done if T4 >= T3. |
| - __ sw(T0, Address(T4)); |
| - __ AddImmediate(T4, kWordSize); |
| - __ b(&init_loop); |
| - __ Bind(&done); |
| + Label loop, loop_exit; |
| + __ BranchUnsignedGreaterEqual(T4, T3, &loop_exit); |
| + __ Bind(&loop); |
| + __ addiu(T4, T4, Immediate(kWordSize)); |
| + __ bne(T4, T3, &loop); |
| + __ delay_slot()->sw(T0, Address(T4, -kWordSize)); |
| + __ Bind(&loop_exit); |
| } |
| if (is_cls_parameterized) { |
| // R1: new object type arguments. |
| @@ -1206,6 +1220,7 @@ |
| // Restore the frame pointer. |
| __ LeaveStubFrame(true); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(true); |
| } |
| @@ -1322,6 +1337,7 @@ |
| __ addiu(V0, T2, Immediate(kHeapObjectTag)); |
| __ LeaveStubFrame(true); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(true); |
| __ Bind(&slow_case); |
| } |
| @@ -1369,6 +1385,7 @@ |
| // Restore the frame pointer. |
| __ LeaveStubFrame(true); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(true); |
| } |
| @@ -1398,6 +1415,7 @@ |
| __ lw(T0, Address(SP, 4 * kWordSize)); |
| __ addiu(SP, SP, Immediate(5 * kWordSize)); // Discard argument; |
| __ LeaveStubFrame(); |
| + __ LeaveStubFrameSPRestore(); |
| } |
| __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); |
| Label is_hot; |
| @@ -1583,6 +1601,7 @@ |
| Label call_target_function; |
| __ BranchNotEqual(T3, reinterpret_cast<intptr_t>(Object::null()), |
| &call_target_function); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| // NoSuchMethod or closure. |
| // Mark IC call that it may be a closure call that does not collect |
| // type feedback. |
| @@ -1611,6 +1630,8 @@ |
| __ lw(T3, FieldAddress(T3, Code::instructions_offset())); |
| __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); |
| __ jr(T3); |
| + __ delay_slot()->addiu(T3, T3, |
| + Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| // Instance in T3, return its class-id in T3 as Smi. |
| __ Bind(&get_class_id_as_smi); |
| @@ -1618,13 +1639,13 @@ |
| // Test if Smi -> load Smi class for comparison. |
| __ andi(TMP1, T3, Immediate(kSmiTagMask)); |
| __ bne(TMP1, ZR, ¬_smi); |
| - __ LoadImmediate(T3, Smi::RawValue(kSmiCid)); |
| __ jr(RA); |
| + __ delay_slot()->addiu(T3, ZR, Immediate(Smi::RawValue(kSmiCid))); |
| __ Bind(¬_smi); |
| __ LoadClassId(T3, T3); |
| - __ SmiTag(T3); |
| __ jr(RA); |
| + __ delay_slot()->SmiTag(T3); |
| } |
| @@ -1706,6 +1727,7 @@ |
| __ lw(S4, Address(SP, 1 * kWordSize)); |
| __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| __ LeaveStubFrame(); |
| + __ LeaveStubFrameSPRestore(); |
| // Now call the static function. The breakpoint handler function |
| // ensures that the call target is compiled. |
| @@ -1725,6 +1747,7 @@ |
| __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); |
| __ Pop(V0); |
| __ LeaveStubFrame(); |
| + __ LeaveStubFrameSPRestore(); |
| // Instead of returning to the patched Dart function, emulate the |
| // smashed return code pattern and return to the function's caller. |
| @@ -1748,6 +1771,7 @@ |
| __ lw(S5, Address(SP, 1 * kWordSize)); |
| __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| __ LeaveStubFrame(); |
| + __ LeaveStubFrameSPRestore(); |
| // Find out which dispatch stub to call. |
| __ lw(TMP1, FieldAddress(S5, ICData::num_args_tested_offset())); |
| @@ -1825,12 +1849,17 @@ |
| } |
| } |
| __ Bind(&next_iteration); |
| - __ AddImmediate(T2, kWordSize * SubtypeTestCache::kTestEntryLength); |
| __ b(&loop); |
| + __ delay_slot()->addiu(T2, T2, |
| + Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); |
| // Fall through to not found. |
| __ Bind(¬_found); |
| - __ LoadImmediate(V0, reinterpret_cast<intptr_t>(Object::null())); |
| + intptr_t null = reinterpret_cast<intptr_t>(Object::null()); |
| + uint16_t null_lo = Utils::Low16Bits(null); |
| + uint16_t null_hi = Utils::High16Bits(null); |
| + __ lui(V0, Immediate(null_hi)); |
| __ Ret(); |
| + __ delay_slot()->ori(V0, V0, Immediate(null_lo)); |
| __ Bind(&found); |
| __ Ret(); |
| @@ -1893,8 +1922,8 @@ |
| __ mov(V0, A3); // Exception object. |
| __ lw(V1, Address(SP, 0)); // StackTrace object. |
| __ mov(FP, A2); // Frame_pointer. |
| - __ mov(SP, A1); // Stack pointer. |
| __ jr(A0); // Jump to the exception handler code. |
| + __ delay_slot()->mov(SP, A1); // Stack pointer. |
| } |
| @@ -1939,8 +1968,14 @@ |
| __ beq(T2, T3, &found); // Class id match? |
| __ Bind(&no_match); |
| // Next check group. |
| - __ AddImmediate(T6, kWordSize * ICData::TestEntryLengthFor(kNumArgsTested)); |
| - __ BranchNotEqual(T3, Smi::RawValue(kIllegalCid), &loop); // Done? |
| + intptr_t entry_bytes = kWordSize * ICData::TestEntryLengthFor(kNumArgsTested); |
| + if (Utils::IsInt(kImmBits, entry_bytes)) { |
| + __ BranchNotEqual(T3, Smi::RawValue(kIllegalCid), &loop); // Done? |
| + __ delay_slot()->addiu(T6, T6, Immediate(entry_bytes)); |
| + } else { |
| + __ AddImmediate(T6, entry_bytes); |
| + __ BranchNotEqual(T3, Smi::RawValue(kIllegalCid), &loop); // Done? |
| + } |
| Label update_ic_data; |
| __ b(&update_ic_data); |
| @@ -1965,6 +2000,7 @@ |
| __ movn(V0, TMP2, CMPRES); |
| __ LeaveStubFrame(); |
| __ Ret(); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| __ Bind(&get_class_id_as_smi); |
| // Test if Smi -> load Smi class for comparison. |
| @@ -2016,6 +2052,7 @@ |
| __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); |
| __ LeaveStubFrame(); |
| __ jr(T0); |
| + __ delay_slot()->LeaveStubFrameSPRestore(); |
| __ break_(0); |
| } |
| @@ -2109,6 +2146,7 @@ |
| __ TraceSimMsg("IdenticalWithNumberCheckStub return"); |
| // Result in V0, 0 means equal. |
| __ LeaveStubFrame(); |
| + __ LeaveStubFrameSPRestore(); |
| __ b(&done); |
| __ delay_slot()->mov(CMPRES, V0); |