From 610ad370a3f805c2b064f52ad0ccb769bf4c0614 Mon Sep 17 00:00:00 2001 From: "dimich@chromium.org" Date: Tue, 1 Jun 2010 08:01:50 +0000 Subject: [PATCH] Fix an occasional crash in Assembler::ldr() for arm. A peephole optimization can be attempted on a buffer that contains only a single command. The crash happens when running debug on Snow Leopard with --simulator=arm. Review URL: http://codereview.chromium.org/2454001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4762 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/assembler-arm.cc | 51 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index 6dd381f..846464a 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -1213,31 +1213,32 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { // Both instructions can be eliminated if ry = rx. // If ry != rx, a register copy from ry to rx is inserted // after eliminating the push and the pop instructions. - Instr push_instr = instr_at(pc_ - 2 * kInstrSize); - Instr pop_instr = instr_at(pc_ - 1 * kInstrSize); - - if (can_peephole_optimize(2) && - IsPush(push_instr) && - IsPop(pop_instr)) { - if ((pop_instr & kRdMask) != (push_instr & kRdMask)) { - // For consecutive push and pop on different registers, - // we delete both the push & pop and insert a register move. - // push ry, pop rx --> mov rx, ry - Register reg_pushed, reg_popped; - reg_pushed = GetRd(push_instr); - reg_popped = GetRd(pop_instr); - pc_ -= 2 * kInstrSize; - // Insert a mov instruction, which is better than a pair of push & pop - mov(reg_popped, reg_pushed); - if (FLAG_print_peephole_optimization) { - PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset()); - } - } else { - // For consecutive push and pop on the same register, - // both the push and the pop can be deleted. - pc_ -= 2 * kInstrSize; - if (FLAG_print_peephole_optimization) { - PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); + if (can_peephole_optimize(2)) { + Instr push_instr = instr_at(pc_ - 2 * kInstrSize); + Instr pop_instr = instr_at(pc_ - 1 * kInstrSize); + + if (IsPush(push_instr) && IsPop(pop_instr)) { + if ((pop_instr & kRdMask) != (push_instr & kRdMask)) { + // For consecutive push and pop on different registers, + // we delete both the push & pop and insert a register move. + // push ry, pop rx --> mov rx, ry + Register reg_pushed, reg_popped; + reg_pushed = GetRd(push_instr); + reg_popped = GetRd(pop_instr); + pc_ -= 2 * kInstrSize; + // Insert a mov instruction, which is better than a pair of push & pop + mov(reg_popped, reg_pushed); + if (FLAG_print_peephole_optimization) { + PrintF("%x push/pop (diff reg) replaced by a reg move\n", + pc_offset()); + } + } else { + // For consecutive push and pop on the same register, + // both the push and the pop can be deleted. + pc_ -= 2 * kInstrSize; + if (FLAG_print_peephole_optimization) { + PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); + } } } } -- 2.7.4