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 <Dusan.Milosavljevic@rt-rk.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14013 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
palfia@homejinni.com 2013-03-20 17:29:04 +00:00
parent fc856413fa
commit d6ceb193fe
4 changed files with 146 additions and 132 deletions

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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));

View File

@ -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();