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 opcode = GetOpcodeField(instr);
uint32_t rt_field = GetRtField(instr); uint32_t rt_field = GetRtField(instr);
uint32_t rs_field = GetRsField(instr); uint32_t rs_field = GetRsField(instr);
uint32_t label_constant = GetLabelConst(instr);
// Checks if the instruction is a branch. // Checks if the instruction is a branch.
return opcode == BEQ || return opcode == BEQ ||
opcode == BNE || opcode == BNE ||
@ -502,10 +501,13 @@ bool Assembler::IsBranch(Instr instr) {
opcode == BGTZL || opcode == BGTZL ||
(opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
rt_field == BLTZAL || rt_field == BGEZAL)) || rt_field == BLTZAL || rt_field == BGEZAL)) ||
(opcode == COP1 && rs_field == BC1) || // Coprocessor branch. (opcode == COP1 && rs_field == BC1); // Coprocessor branch.
label_constant == 0; // Emitted label const in reg-exp engine.
} }
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) { bool Assembler::IsBeq(Instr instr) {
return GetOpcodeField(instr) == BEQ; return GetOpcodeField(instr) == BEQ;
@ -796,7 +798,7 @@ void Assembler::bind_to(Label* L, int pos) {
} }
target_at_put(fixup_pos, pos); target_at_put(fixup_pos, pos);
} else { } else {
ASSERT(IsJ(instr) || IsLui(instr)); ASSERT(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr));
target_at_put(fixup_pos, pos); 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 Instr SetAddImmediateOffset(Instr instr, int16_t offset);
static bool IsAndImmediate(Instr instr); static bool IsAndImmediate(Instr instr);
static bool IsEmittedConstant(Instr instr);
void CheckTrampolinePool(); void CheckTrampolinePool();

View File

@ -1108,6 +1108,7 @@ void MacroAssembler::BranchF(Label* target,
FPURegister cmp1, FPURegister cmp1,
FPURegister cmp2, FPURegister cmp2,
BranchDelaySlot bd) { BranchDelaySlot bd) {
BlockTrampolinePoolScope block_trampoline_pool(this);
if (cc == al) { if (cc == al) {
Branch(bd, target); Branch(bd, target);
return; return;
@ -1700,6 +1701,7 @@ void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs,
if (rt.is_reg()) { if (rt.is_reg()) {
// NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or
// rt. // rt.
BlockTrampolinePoolScope block_trampoline_pool(this);
r2 = rt.rm_; r2 = rt.rm_;
switch (cond) { switch (cond) {
case cc_always: 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 // Be careful to always use shifted_branch_offset only just before the
// branch instruction, as the location will be remember for patching the // branch instruction, as the location will be remember for patching the
// target. // target.
BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) { switch (cond) {
case cc_always: case cc_always:
b(offset); b(offset);
@ -1929,6 +1932,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
Register r2 = no_reg; Register r2 = no_reg;
Register scratch = at; Register scratch = at;
if (rt.is_reg()) { if (rt.is_reg()) {
BlockTrampolinePoolScope block_trampoline_pool(this);
r2 = rt.rm_; r2 = rt.rm_;
// Be careful to always use shifted_branch_offset only just before the // Be careful to always use shifted_branch_offset only just before the
// branch instruction, as the location will be remember for patching 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 // Be careful to always use shifted_branch_offset only just before the
// branch instruction, as the location will be remember for patching the // branch instruction, as the location will be remember for patching the
// target. // target.
BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) { switch (cond) {
case cc_always: case cc_always:
offset = shifted_branch_offset(L, false); offset = shifted_branch_offset(L, false);
@ -2271,6 +2276,8 @@ void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond,
li(r2, rt); li(r2, rt);
} }
{
BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) { switch (cond) {
case cc_always: case cc_always:
bal(offset); bal(offset);
@ -2333,6 +2340,7 @@ void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond,
default: default:
UNREACHABLE(); UNREACHABLE();
} }
}
// Emit a nop in the branch delay slot if required. // Emit a nop in the branch delay slot if required.
if (bdslot == PROTECT) if (bdslot == PROTECT)
nop(); nop();
@ -2363,6 +2371,8 @@ void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
li(r2, rt); li(r2, rt);
} }
{
BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) { switch (cond) {
case cc_always: case cc_always:
offset = shifted_branch_offset(L, false); offset = shifted_branch_offset(L, false);
@ -2436,7 +2446,7 @@ void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
default: default:
UNREACHABLE(); UNREACHABLE();
} }
}
// Check that offset could actually hold on an int16_t. // Check that offset could actually hold on an int16_t.
ASSERT(is_int16(offset)); ASSERT(is_int16(offset));

View File

@ -1005,6 +1005,7 @@ void RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) {
int target = label->pos(); int target = label->pos();
__ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag)); __ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag));
} else { } else {
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
Label after_constant; Label after_constant;
__ Branch(&after_constant); __ Branch(&after_constant);
int offset = masm_->pc_offset(); int offset = masm_->pc_offset();