From 6c56cc3de5dbe4b513d9beccd90174a3acd4e9ec Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Thu, 11 Apr 2013 00:50:58 +0000 Subject: [PATCH] MIPS: Fix OSR for nested loops. Port r14202 (b8949f01), r14208 (06cc8568) BUG= Review URL: https://codereview.chromium.org/14119002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14219 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/deoptimizer-mips.cc | 111 ++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc index 7158e4f551..f662e1f44a 100644 --- a/src/mips/deoptimizer-mips.cc +++ b/src/mips/deoptimizer-mips.cc @@ -116,76 +116,93 @@ void Deoptimizer::DeoptimizeFunctionWithPreparedFunctionList( } -void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code, +// This structure comes from FullCodeGenerator::EmitBackEdgeBookkeeping. +// The back edge bookkeeping code matches the pattern: +// +// sltu at, sp, t0 / slt at, a3, zero_reg (in case of count based interrupts) +// beq at, zero_reg, ok +// lui t9, upper +// ori t9, lower +// jalr t9 +// nop +// ok-label ----- pc_after points here +// +// We patch the code to the following form: +// +// addiu at, zero_reg, 1 +// beq at, zero_reg, ok ;; Not changed +// lui t9, upper +// ori t9, lower +// jalr t9 ;; Not changed +// nop ;; Not changed +// ok-label ----- pc_after points here + +void Deoptimizer::PatchInterruptCodeAt(Code* unoptimized_code, Address pc_after, - Code* check_code, + Code* interrupt_code, Code* replacement_code) { - const int kInstrSize = Assembler::kInstrSize; - // This structure comes from FullCodeGenerator::EmitBackEdgeBookkeeping. - // The call of the stack guard check has the following form: - // sltu at, sp, t0 / slt at, a3, zero_reg (in case of count based interrupts) - // beq at, zero_reg, ok - // lui t9, upper - // ori t9, lower - // jalr t9 - // nop - // ----- pc_after points here - - ASSERT(Assembler::IsBeq(Assembler::instr_at(pc_after - 5 * kInstrSize))); - + ASSERT(!InterruptCodeIsPatched(unoptimized_code, + pc_after, + interrupt_code, + replacement_code)); + static const int kInstrSize = Assembler::kInstrSize; // Replace the sltu instruction with load-imm 1 to at, so beq is not taken. CodePatcher patcher(pc_after - 6 * kInstrSize, 1); patcher.masm()->addiu(at, zero_reg, 1); - // Replace the stack check address in the load-immediate (lui/ori pair) // with the entry address of the replacement code. - ASSERT(reinterpret_cast( - Assembler::target_address_at(pc_after - 4 * kInstrSize)) == - reinterpret_cast(check_code->entry())); Assembler::set_target_address_at(pc_after - 4 * kInstrSize, replacement_code->entry()); - // We patched the code to the following form: - // addiu at, zero_reg, 1 - // beq at, zero_reg, ok ;; Not changed - // lui t9, upper - // ori t9, lower - // jalr t9 ;; Not changed - // nop ;; Not changed - // ----- pc_after points here - unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( unoptimized_code, pc_after - 4 * kInstrSize, replacement_code); } -void Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code, - Address pc_after, - Code* check_code, - Code* replacement_code) { - // Exact opposite of the function above. - const int kInstrSize = Assembler::kInstrSize; - ASSERT(Assembler::IsAddImmediate( - Assembler::instr_at(pc_after - 6 * kInstrSize))); - ASSERT(Assembler::IsBeq(Assembler::instr_at(pc_after - 5 * kInstrSize))); - +void Deoptimizer::RevertInterruptCodeAt(Code* unoptimized_code, + Address pc_after, + Code* interrupt_code, + Code* replacement_code) { + ASSERT(InterruptCodeIsPatched(unoptimized_code, + pc_after, + interrupt_code, + replacement_code)); + static const int kInstrSize = Assembler::kInstrSize; // Restore the sltu instruction so beq can be taken again. CodePatcher patcher(pc_after - 6 * kInstrSize, 1); patcher.masm()->slt(at, a3, zero_reg); - - // Replace the on-stack replacement address in the load-immediate (lui/ori - // pair) with the entry address of the normal stack-check code. - ASSERT(reinterpret_cast( - Assembler::target_address_at(pc_after - 4 * kInstrSize)) == - reinterpret_cast(replacement_code->entry())); + // Restore the original call address. Assembler::set_target_address_at(pc_after - 4 * kInstrSize, - check_code->entry()); + interrupt_code->entry()); - check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( - unoptimized_code, pc_after - 4 * kInstrSize, check_code); + interrupt_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( + unoptimized_code, pc_after - 4 * kInstrSize, interrupt_code); } +#ifdef DEBUG +bool Deoptimizer::InterruptCodeIsPatched(Code* unoptimized_code, + Address pc_after, + Code* interrupt_code, + Code* replacement_code) { + static const int kInstrSize = Assembler::kInstrSize; + ASSERT(Assembler::IsBeq(Assembler::instr_at(pc_after - 5 * kInstrSize))); + if (Assembler::IsAddImmediate( + Assembler::instr_at(pc_after - 6 * kInstrSize))) { + ASSERT(reinterpret_cast( + Assembler::target_address_at(pc_after - 4 * kInstrSize)) == + reinterpret_cast(replacement_code->entry())); + return true; + } else { + ASSERT(reinterpret_cast( + Assembler::target_address_at(pc_after - 4 * kInstrSize)) == + reinterpret_cast(interrupt_code->entry())); + return false; + } +} +#endif // DEBUG + + static int LookupBailoutId(DeoptimizationInputData* data, BailoutId ast_id) { ByteArray* translations = data->TranslationByteArray(); int length = data->DeoptCount();