Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Unified Diff: runtime/vm/stub_code_mips.cc

Issue 14061012: Enables API tests on MIPS (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/stub_code_mips.cc
===================================================================
--- runtime/vm/stub_code_mips.cc (revision 22072)
+++ runtime/vm/stub_code_mips.cc (working copy)
@@ -341,13 +341,129 @@
}
+DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
+ intptr_t deopt_reason,
+ uword saved_registers_address);
+
+DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp);
+
+
+// Used by eager and lazy deoptimization. Preserve result in V0 if necessary.
+// This stub translates optimized frame into unoptimized frame. The optimized
+// frame can contain values in registers and on stack, the unoptimized
+// frame contains all values on stack.
+// Deoptimization occurs in following steps:
+// - Push all registers that can contain values.
+// - Call C routine to copy the stack and saved registers into temporary buffer.
+// - Adjust caller's frame to correct unoptimized frame size.
+// - Fill the unoptimized frame.
+// - Materialize objects that require allocation (e.g. Double instances).
+// GC can occur only after frame is fully rewritten.
+// Stack after EnterFrame(...) below:
+// +------------------+
+// | Saved FP | <- TOS
+// +------------------+
+// | return-address | (deoptimization point)
+// +------------------+
+// | optimized frame |
+// | ... |
+//
+// Parts of the code cannot GC, part of the code can GC.
+static void GenerateDeoptimizationSequence(Assembler* assembler,
+ bool preserve_result) {
+ const intptr_t kPushedRegistersSize =
+ kNumberOfCpuRegisters * kWordSize +
+ 2 * kWordSize + // FP and RA.
+ kNumberOfFRegisters * kWordSize;
+
+ __ addiu(SP, SP, Immediate(-kPushedRegistersSize * kWordSize));
+ __ sw(RA, Address(SP, kPushedRegistersSize - 1 * kWordSize));
+ __ sw(FP, Address(SP, kPushedRegistersSize - 2 * kWordSize));
+ __ addiu(FP, SP, Immediate(kPushedRegistersSize - 2 * kWordSize));
+
+
+ // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
+ // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
+ const intptr_t saved_v0_offset_from_fp = -(kNumberOfCpuRegisters - V0);
+ // Result in V0 is preserved as part of pushing all registers below.
+
+ // Push registers in their enumeration order: lowest register number at
+ // lowest address.
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ const int slot = 2 + kNumberOfCpuRegisters - i;
+ Register reg = static_cast<Register>(i);
+ __ sw(reg, Address(SP, kPushedRegistersSize - slot * kWordSize));
+ }
+ for (int i = 0; i < kNumberOfFRegisters; i++) {
+ // These go below the CPU registers.
+ const int slot = 2 + kNumberOfCpuRegisters + kNumberOfFRegisters - i;
+ FRegister reg = static_cast<FRegister>(i);
+ __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize));
+ }
+
+ __ mov(A0, SP); // Pass address of saved registers block.
+ __ ReserveAlignedFrameSpace(0);
+ __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry);
+ // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address.
+
+ if (preserve_result) {
+ // Restore result into T1 temporarily.
+ __ lw(T1, Address(FP, saved_v0_offset_from_fp * kWordSize));
+ }
+
+ __ mov(SP, FP);
+ __ lw(FP, Address(SP, 0 * kWordSize));
+ __ lw(RA, Address(SP, 1 * kWordSize));
+ __ addiu(SP, SP, Immediate(2 * kWordSize));
+
+ __ subu(SP, FP, V0);
+
+ __ addiu(SP, SP, Immediate(-2 * kWordSize));
+ __ sw(RA, Address(SP, 1 * kWordSize));
+ __ sw(FP, Address(SP, 0 * kWordSize));
+ __ mov(FP, SP);
+
+ __ mov(A0, SP); // Get last FP address.
+ if (preserve_result) {
+ __ Push(T1); // Preserve result.
+ }
+ __ ReserveAlignedFrameSpace(0);
+ __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in A0.
+ // Result (V0) is our FP.
+ if (preserve_result) {
+ // Restore result into T1.
+ __ lw(T1, Address(FP, -1 * kWordSize));
+ }
+ // Code above cannot cause GC.
+ __ mov(SP, FP);
+ __ lw(FP, Address(SP, 0 * kWordSize));
+ __ lw(RA, Address(SP, 1 * kWordSize));
+ __ addiu(SP, SP, Immediate(2 * kWordSize));
+ __ mov(FP, V0);
+
+ // Frame is fully rewritten at this point and it is safe to perform a GC.
+ // Materialize any objects that were deferred by FillFrame because they
+ // require allocation.
+ __ EnterStubFrame();
+ if (preserve_result) {
+ __ Push(T1); // Preserve result, it will be GC-d here.
+ }
+ __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry);
+ if (preserve_result) {
+ __ Pop(V0); // Restore result.
+ }
+ __ LeaveStubFrame();
+ __ Ret();
+}
+
+
void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
__ Unimplemented("DeoptimizeLazy stub");
}
void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
- __ Unimplemented("Deoptimize stub");
+ GenerateDeoptimizationSequence(assembler, false); // Don't preserve V0.
}
@@ -1261,8 +1377,40 @@
}
+// T0: function object.
+// S5: inline cache data object.
+// S4: arguments descriptor array.
void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
- __ Unimplemented("OptimizedUsageCounterIncrement stub");
+ __ TraceSimMsg("OptimizedUsageCounterIncrement");
+ Register ic_reg = S5;
+ Register func_reg = T0;
+ if (FLAG_trace_optimized_ic_calls) {
+ __ EnterStubFrame();
+ __ addiu(SP, SP, Immediate(-5 * kWordSize));
+ __ sw(T0, Address(SP, 4 * kWordSize));
+ __ sw(S5, Address(SP, 3 * kWordSize));
+ __ sw(S4, Address(SP, 2 * kWordSize)); // Preserve.
+ __ sw(ic_reg, Address(SP, 1 * kWordSize)); // Argument.
+ __ sw(func_reg, Address(SP, 0 * kWordSize)); // Argument.
+ __ CallRuntime(kTraceICCallRuntimeEntry);
+ __ lw(S4, Address(SP, 2 * kWordSize)); // Restore.
+ __ lw(S5, Address(SP, 3 * kWordSize));
+ __ lw(T0, Address(SP, 4 * kWordSize));
+ __ addiu(SP, SP, Immediate(5 * kWordSize)); // Discard argument;
+ __ LeaveStubFrame();
+ }
+ __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset()));
+ Label is_hot;
+ if (FlowGraphCompiler::CanOptimize()) {
+ ASSERT(FLAG_optimization_counter_threshold > 1);
+ __ BranchGreaterEqual(T7, FLAG_optimization_counter_threshold, &is_hot);
+ // As long as VM has no OSR do not optimize in the middle of the function
+ // but only at exit so that we have collected all type feedback before
+ // optimizing.
+ }
+ __ addiu(T7, T7, Immediate(1));
+ __ sw(T7, FieldAddress(func_reg, Function::usage_counter_offset()));
+ __ Bind(&is_hot);
}
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698