From d6ceb193fe7f5189cd14ca340a40d4a0d33602af Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Wed, 20 Mar 2013 17:29:04 +0000 Subject: [PATCH] MIPS: Critical fix for label binding in RegExp engine when trampoline is emitted. TEST=mjsunit/regress/regress-crbug-178790 BUG= Review URL: https://codereview.chromium.org/12939010 Patch from Dusan Milosavljevic . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14013 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/assembler-mips.cc | 10 +- src/mips/assembler-mips.h | 1 + src/mips/macro-assembler-mips.cc | 266 ++++++++++++------------ src/mips/regexp-macro-assembler-mips.cc | 1 + 4 files changed, 146 insertions(+), 132 deletions(-) diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc index 4c11c7f549..c255d0fbda 100644 --- a/src/mips/assembler-mips.cc +++ b/src/mips/assembler-mips.cc @@ -490,7 +490,6 @@ bool Assembler::IsBranch(Instr instr) { uint32_t opcode = GetOpcodeField(instr); uint32_t rt_field = GetRtField(instr); uint32_t rs_field = GetRsField(instr); - uint32_t label_constant = GetLabelConst(instr); // Checks if the instruction is a branch. return opcode == BEQ || opcode == BNE || @@ -502,10 +501,13 @@ bool Assembler::IsBranch(Instr instr) { opcode == BGTZL || (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || rt_field == BLTZAL || rt_field == BGEZAL)) || - (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. - label_constant == 0; // Emitted label const in reg-exp engine. + (opcode == COP1 && rs_field == BC1); // Coprocessor branch. } +bool Assembler::IsEmittedConstant(Instr instr) { + uint32_t label_constant = GetLabelConst(instr); + return label_constant == 0; // Emitted label const in reg-exp engine. +} bool Assembler::IsBeq(Instr instr) { return GetOpcodeField(instr) == BEQ; @@ -796,7 +798,7 @@ void Assembler::bind_to(Label* L, int pos) { } target_at_put(fixup_pos, pos); } else { - ASSERT(IsJ(instr) || IsLui(instr)); + ASSERT(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr)); target_at_put(fixup_pos, pos); } } diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h index e6c9e76c78..9d3d39b83e 100644 --- a/src/mips/assembler-mips.h +++ b/src/mips/assembler-mips.h @@ -942,6 +942,7 @@ class Assembler : public AssemblerBase { static Instr SetAddImmediateOffset(Instr instr, int16_t offset); static bool IsAndImmediate(Instr instr); + static bool IsEmittedConstant(Instr instr); void CheckTrampolinePool(); diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 603f1be70e..33ff9aba64 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -1108,6 +1108,7 @@ void MacroAssembler::BranchF(Label* target, FPURegister cmp1, FPURegister cmp2, BranchDelaySlot bd) { + BlockTrampolinePoolScope block_trampoline_pool(this); if (cc == al) { Branch(bd, target); return; @@ -1700,6 +1701,7 @@ void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, if (rt.is_reg()) { // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or // rt. + BlockTrampolinePoolScope block_trampoline_pool(this); r2 = rt.rm_; switch (cond) { case cc_always: @@ -1785,6 +1787,7 @@ void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, // Be careful to always use shifted_branch_offset only just before the // branch instruction, as the location will be remember for patching the // target. + BlockTrampolinePoolScope block_trampoline_pool(this); switch (cond) { case cc_always: b(offset); @@ -1929,6 +1932,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs, Register r2 = no_reg; Register scratch = at; if (rt.is_reg()) { + BlockTrampolinePoolScope block_trampoline_pool(this); r2 = rt.rm_; // Be careful to always use shifted_branch_offset only just before the // branch instruction, as the location will be remember for patching the @@ -2035,6 +2039,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs, // Be careful to always use shifted_branch_offset only just before the // branch instruction, as the location will be remember for patching the // target. + BlockTrampolinePoolScope block_trampoline_pool(this); switch (cond) { case cc_always: offset = shifted_branch_offset(L, false); @@ -2271,67 +2276,70 @@ void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond, li(r2, rt); } - switch (cond) { - case cc_always: - bal(offset); - break; - case eq: - bne(rs, r2, 2); - nop(); - bal(offset); - break; - case ne: - beq(rs, r2, 2); - nop(); - bal(offset); - break; + { + BlockTrampolinePoolScope block_trampoline_pool(this); + switch (cond) { + case cc_always: + bal(offset); + break; + case eq: + bne(rs, r2, 2); + nop(); + bal(offset); + break; + case ne: + beq(rs, r2, 2); + nop(); + bal(offset); + break; - // Signed comparison. - case greater: - slt(scratch, r2, rs); - addiu(scratch, scratch, -1); - bgezal(scratch, offset); - break; - case greater_equal: - slt(scratch, rs, r2); - addiu(scratch, scratch, -1); - bltzal(scratch, offset); - break; - case less: - slt(scratch, rs, r2); - addiu(scratch, scratch, -1); - bgezal(scratch, offset); - break; - case less_equal: - slt(scratch, r2, rs); - addiu(scratch, scratch, -1); - bltzal(scratch, offset); - break; + // Signed comparison. + case greater: + slt(scratch, r2, rs); + addiu(scratch, scratch, -1); + bgezal(scratch, offset); + break; + case greater_equal: + slt(scratch, rs, r2); + addiu(scratch, scratch, -1); + bltzal(scratch, offset); + break; + case less: + slt(scratch, rs, r2); + addiu(scratch, scratch, -1); + bgezal(scratch, offset); + break; + case less_equal: + slt(scratch, r2, rs); + addiu(scratch, scratch, -1); + bltzal(scratch, offset); + break; - // Unsigned comparison. - case Ugreater: - sltu(scratch, r2, rs); - addiu(scratch, scratch, -1); - bgezal(scratch, offset); - break; - case Ugreater_equal: - sltu(scratch, rs, r2); - addiu(scratch, scratch, -1); - bltzal(scratch, offset); - break; - case Uless: - sltu(scratch, rs, r2); - addiu(scratch, scratch, -1); - bgezal(scratch, offset); - break; - case Uless_equal: - sltu(scratch, r2, rs); - addiu(scratch, scratch, -1); - bltzal(scratch, offset); - break; + // Unsigned comparison. + case Ugreater: + sltu(scratch, r2, rs); + addiu(scratch, scratch, -1); + bgezal(scratch, offset); + break; + case Ugreater_equal: + sltu(scratch, rs, r2); + addiu(scratch, scratch, -1); + bltzal(scratch, offset); + break; + case Uless: + sltu(scratch, rs, r2); + addiu(scratch, scratch, -1); + bgezal(scratch, offset); + break; + case Uless_equal: + sltu(scratch, r2, rs); + addiu(scratch, scratch, -1); + bltzal(scratch, offset); + break; - default: - UNREACHABLE(); + default: + UNREACHABLE(); + } } // Emit a nop in the branch delay slot if required. if (bdslot == PROTECT) @@ -2363,80 +2371,82 @@ void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs, li(r2, rt); } - switch (cond) { - case cc_always: - offset = shifted_branch_offset(L, false); - bal(offset); - break; - case eq: - bne(rs, r2, 2); - nop(); - offset = shifted_branch_offset(L, false); - bal(offset); - break; - case ne: - beq(rs, r2, 2); - nop(); - offset = shifted_branch_offset(L, false); - bal(offset); - break; + { + BlockTrampolinePoolScope block_trampoline_pool(this); + switch (cond) { + case cc_always: + offset = shifted_branch_offset(L, false); + bal(offset); + break; + case eq: + bne(rs, r2, 2); + nop(); + offset = shifted_branch_offset(L, false); + bal(offset); + break; + case ne: + beq(rs, r2, 2); + nop(); + offset = shifted_branch_offset(L, false); + bal(offset); + break; - // Signed comparison. - case greater: - slt(scratch, r2, rs); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bgezal(scratch, offset); - break; - case greater_equal: - slt(scratch, rs, r2); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bltzal(scratch, offset); - break; - case less: - slt(scratch, rs, r2); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bgezal(scratch, offset); - break; - case less_equal: - slt(scratch, r2, rs); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bltzal(scratch, offset); - break; + // Signed comparison. + case greater: + slt(scratch, r2, rs); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bgezal(scratch, offset); + break; + case greater_equal: + slt(scratch, rs, r2); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bltzal(scratch, offset); + break; + case less: + slt(scratch, rs, r2); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bgezal(scratch, offset); + break; + case less_equal: + slt(scratch, r2, rs); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bltzal(scratch, offset); + break; - // Unsigned comparison. - case Ugreater: - sltu(scratch, r2, rs); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bgezal(scratch, offset); - break; - case Ugreater_equal: - sltu(scratch, rs, r2); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bltzal(scratch, offset); - break; - case Uless: - sltu(scratch, rs, r2); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bgezal(scratch, offset); - break; - case Uless_equal: - sltu(scratch, r2, rs); - addiu(scratch, scratch, -1); - offset = shifted_branch_offset(L, false); - bltzal(scratch, offset); - break; + // Unsigned comparison. + case Ugreater: + sltu(scratch, r2, rs); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bgezal(scratch, offset); + break; + case Ugreater_equal: + sltu(scratch, rs, r2); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bltzal(scratch, offset); + break; + case Uless: + sltu(scratch, rs, r2); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bgezal(scratch, offset); + break; + case Uless_equal: + sltu(scratch, r2, rs); + addiu(scratch, scratch, -1); + offset = shifted_branch_offset(L, false); + bltzal(scratch, offset); + break; - default: - UNREACHABLE(); + default: + UNREACHABLE(); + } } - // Check that offset could actually hold on an int16_t. ASSERT(is_int16(offset)); diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc index 036cbb13e4..2fbc0eaa56 100644 --- a/src/mips/regexp-macro-assembler-mips.cc +++ b/src/mips/regexp-macro-assembler-mips.cc @@ -1005,6 +1005,7 @@ void RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) { int target = label->pos(); __ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag)); } else { + Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); Label after_constant; __ Branch(&after_constant); int offset = masm_->pc_offset();