Bug 539379 - TM: Crash [@ ExecuteTrace] or [@ ExecuteTree]. r=edwsmith.

--HG--
extra : convert_revision : a5115ee971c8496182e9b4f6847ad91619b4a585
This commit is contained in:
Nicholas Nethercote 2010-01-15 15:07:32 +11:00
parent 6a8645f974
commit 0c9683a5c5
8 changed files with 65 additions and 49 deletions

View File

@ -371,34 +371,39 @@ namespace nanojit
}
#endif /* _DEBUG */
void Assembler::findRegFor2(RegisterMask allow, LIns* ia, Register& ra, LIns* ib, Register& rb)
void Assembler::findRegFor2(RegisterMask allowa, LIns* ia, Register& ra,
RegisterMask allowb, LIns* ib, Register& rb)
{
// There should be some overlap between 'allowa' and 'allowb', else
// there's no point calling this function.
NanoAssert(allowa & allowb);
if (ia == ib) {
ra = rb = findRegFor(ia, allow);
ra = rb = findRegFor(ia, allowa & allowb); // use intersection(allowa, allowb)
} else {
// You might think we could just do this:
//
// ra = findRegFor(ia, allow);
// rb = findRegFor(ib, allow & ~rmask(ra));
// ra = findRegFor(ia, allowa);
// rb = findRegFor(ib, allowb & ~rmask(ra));
//
// But if 'ib' was already in an allowed register, the first
// findRegFor() call could evict it, whereupon the second
// findRegFor() call would immediately restore it, which is
// sub-optimal. What we effectively do instead is this:
//
// ra = findRegFor(ia, allow & ~rmask(rb));
// rb = findRegFor(ib, allow & ~rmask(ra));
// ra = findRegFor(ia, allowa & ~rmask(rb));
// rb = findRegFor(ib, allowb & ~rmask(ra));
//
// but we have to determine what 'rb' initially is to avoid the
// mutual dependency between the assignments.
bool rbDone = !ib->isUnusedOrHasUnknownReg() && (rb = ib->getReg(), allow & rmask(rb));
bool rbDone = !ib->isUnusedOrHasUnknownReg() && (rb = ib->getReg(), allowb & rmask(rb));
if (rbDone) {
allow &= ~rmask(rb); // ib already in an allowable reg, keep that one
allowa &= ~rmask(rb); // ib already in an allowable reg, keep that one
}
ra = findRegFor(ia, allow);
ra = findRegFor(ia, allowa);
if (!rbDone) {
allow &= ~rmask(ra);
rb = findRegFor(ib, allow);
allowb &= ~rmask(ra);
rb = findRegFor(ib, allowb);
}
}
}
@ -432,6 +437,27 @@ namespace nanojit
return findRegFor(i, allow);
}
// Like findRegFor2(), but used for stores where the base value has the
// same type as the stored value, eg. in asm_store32() on 32-bit platforms
// and asm_store64() on 64-bit platforms. Similar to getBaseReg(),
// findRegFor2() can be called instead, but this function can optimize the
// case where the base value is a LIR_alloc.
void Assembler::getBaseReg2(RegisterMask allowValue, LIns* value, Register& rv,
RegisterMask allowBase, LIns* base, Register& rb, int &d)
{
#if !PEDANTIC
if (base->isop(LIR_alloc)) {
rb = FP;
d += findMemFor(base);
rv = findRegFor(value, allowValue);
return;
}
#else
(void) d;
#endif
findRegFor2(allowValue, value, rv, allowBase, base, rb);
}
// Finds a register in 'allow' to hold the result of 'ins'. Used when we
// encounter a use of 'ins'. The actions depend on the prior regstate of
// 'ins':

View File

@ -327,13 +327,16 @@ namespace nanojit
LInsp findVictim(RegisterMask allow);
Register getBaseReg(LIns *i, int &d, RegisterMask allow);
void getBaseReg2(RegisterMask allowValue, LIns* value, Register& rv,
RegisterMask allowBase, LIns* base, Register& rb, int &d);
#if NJ_USES_QUAD_CONSTANTS
const uint64_t*
findQuadConstant(uint64_t q);
#endif
int findMemFor(LIns* i);
Register findRegFor(LIns* i, RegisterMask allow);
void findRegFor2(RegisterMask allow, LIns* ia, Register &ra, LIns *ib, Register &rb);
void findRegFor2(RegisterMask allowa, LIns* ia, Register &ra,
RegisterMask allowb, LIns *ib, Register &rb);
Register findSpecificRegFor(LIns* i, Register r);
Register findSpecificRegForUnallocated(LIns* i, Register r);
Register prepResultReg(LIns *i, RegisterMask allow);

View File

@ -1219,13 +1219,7 @@ Assembler::asm_store32(LOpcode op, LIns *value, int dr, LIns *base)
}
Register ra, rb;
if (base->isop(LIR_alloc)) {
rb = FP;
dr += findMemFor(base);
ra = findRegFor(value, GpRegs);
} else {
findRegFor2(GpRegs, value, ra, base, rb);
}
getBaseReg2(GpRegs, value, ra, GpRegs, base, rb, dr);
if (isU12(-dr) || isU12(dr)) {
STR(ra, rb, dr);
@ -2102,7 +2096,7 @@ Assembler::asm_fcmp(LInsp ins)
NanoAssert(op >= LIR_feq && op <= LIR_fge);
Register ra, rb;
findRegFor2(FpRegs, lhs, ra, rhs, rb);
findRegFor2(FpRegs, lhs, ra, FpRegs, rhs, rb);
int e_bit = (op != LIR_feq);
@ -2215,7 +2209,7 @@ Assembler::asm_cmp(LIns *cond)
}
} else {
Register ra, rb;
findRegFor2(GpRegs, lhs, ra, rhs, rb);
findRegFor2(GpRegs, lhs, ra, GpRegs, rhs, rb);
CMP(ra, rb);
}
}

View File

@ -972,7 +972,7 @@ namespace nanojit
RegisterMask allow = FpRegs;
Register rr = prepResultReg(ins, allow);
Register ra, rb;
findRegFor2(allow, lhs, ra, rhs, rb);
findRegFor2(allow, lhs, ra, allow, rhs, rb);
switch (op) {
case LIR_fadd: FADD(rr, ra, rb); break;
case LIR_fsub: FSUB(rr, ra, rb); break;

View File

@ -334,17 +334,13 @@ namespace nanojit
{
// make sure what is in a register
Register ra, rb;
if (base->isop(LIR_alloc)) {
rb = FP;
dr += findMemFor(base);
ra = findRegFor(value, GpRegs);
} else if (base->isconst()) {
if (base->isconst()) {
// absolute address
dr += base->imm32();
ra = findRegFor(value, GpRegs);
rb = G0;
} else {
findRegFor2(GpRegs, value, ra, base, rb);
getBaseReg2(GpRegs, value, ra, GpRegs, base, rb, dr);
}
STW32(ra, dr, rb);
}
@ -601,7 +597,7 @@ namespace nanojit
else
{
Register ra, rb;
findRegFor2(GpRegs, lhs, ra, rhs, rb);
findRegFor2(GpRegs, lhs, ra, GpRegs, rhs, rb);
SUBCC(ra, rb, G0);
}
}

View File

@ -1155,7 +1155,7 @@ namespace nanojit
LIns *a = cond->oprnd1();
Register ra, rb;
if (a != b) {
findRegFor2(GpRegs, a, ra, b, rb);
findRegFor2(GpRegs, a, ra, GpRegs, b, rb);
} else {
// optimize-me: this will produce a const result!
ra = rb = findRegFor(a, GpRegs);
@ -1287,7 +1287,7 @@ namespace nanojit
void Assembler::fcmp(LIns *a, LIns *b) {
Register ra, rb;
findRegFor2(FpRegs, a, ra, b, rb);
findRegFor2(FpRegs, a, ra, FpRegs, b, rb);
UCOMISD(ra, rb);
}
@ -1463,20 +1463,21 @@ namespace nanojit
void Assembler::asm_store64(LOpcode op, LIns *value, int d, LIns *base) {
NanoAssert(value->isQuad());
Register b = getBaseReg(base, d, BaseRegs);
switch (op) {
case LIR_stqi: {
Register r = findRegFor(value, GpRegs & ~rmask(b));
Register r, b;
getBaseReg2(GpRegs, value, r, BaseRegs, base, b, d);
MOVQMR(r, d, b); // gpr store
break;
}
case LIR_stfi: {
Register b = getBaseReg(base, d, BaseRegs);
Register r = findRegFor(value, FpRegs);
MOVSDMR(r, d, b); // xmm store
break;
}
case LIR_st32f: {
Register b = getBaseReg(base, d, BaseRegs);
Register r = findRegFor(value, FpRegs);
Register t = registerAllocTmp(FpRegs & ~rmask(r));

View File

@ -504,17 +504,13 @@ namespace nanojit
GpRegs;
Register ra, rb;
if (base->isop(LIR_alloc)) {
rb = FP;
dr += findMemFor(base);
ra = findRegFor(value, SrcRegs);
} else if (base->isconst()) {
if (base->isconst()) {
// absolute address
rb = UnknownReg;
dr += base->imm32();
ra = findRegFor(value, SrcRegs);
} else {
findRegFor2(SrcRegs, value, ra, base, rb);
getBaseReg2(SrcRegs, value, ra, GpRegs, base, rb, dr);
}
switch (op) {
case LIR_stb:
@ -854,7 +850,7 @@ namespace nanojit
} else {
Register ra, rb;
findRegFor2(GpRegs, lhs, ra, rhs, rb);
findRegFor2(GpRegs, lhs, ra, GpRegs, rhs, rb);
CMP(ra, rb);
}
}
@ -1937,7 +1933,7 @@ namespace nanojit
evictIfActive(EAX);
Register ra, rb;
findRegFor2(XmmRegs, lhs, ra, rhs, rb);
findRegFor2(XmmRegs, lhs, ra, XmmRegs, rhs, rb);
TEST_AH(mask);
LAHF();
@ -1961,7 +1957,7 @@ namespace nanojit
// LESS_THAN 001 SETAE/JAE fails
Register ra, rb;
findRegFor2(XmmRegs, lhs, ra, rhs, rb);
findRegFor2(XmmRegs, lhs, ra, XmmRegs, rhs, rb);
SSE_UCOMISD(ra, rb);
}

View File

@ -933,28 +933,28 @@ namespace nanojit
#define FSTPQ(d,b) FSTQ(1,d,b)
#define FCOM(p,d,b) do { count_fpuld(); FPUm(0xdc02|(p), d, b); asm_output("fcom%s %d(%s)",((p)?"p":""),d,gpn(b)); if (p) fpu_pop(); } while(0)
#define FCOMdm(p,m) do { const double* const dm = m; \
count_fpuld(); FPUdm(0xdc02|(p), dm); asm_output("fcom%s (%p)",((p)?"p":""),dm); if (p) fpu_pop(); } while(0)
count_fpuld(); FPUdm(0xdc02|(p), dm); asm_output("fcom%s (%p)",((p)?"p":""),(void*)dm); if (p) fpu_pop(); } while(0)
#define FLD32(d,b) do { count_ldq(); FPUm(0xd900, d, b); asm_output("fld32 %d(%s)",d,gpn(b)); fpu_push();} while(0)
#define FLDQ(d,b) do { count_ldq(); FPUm(0xdd00, d, b); asm_output("fldq %d(%s)",d,gpn(b)); fpu_push();} while(0)
#define FLDQdm(m) do { const double* const dm = m; \
count_ldq(); FPUdm(0xdd00, dm); asm_output("fldq (%p)",dm); fpu_push();} while(0)
count_ldq(); FPUdm(0xdd00, dm); asm_output("fldq (%p)",(void*)dm); fpu_push();} while(0)
#define FILDQ(d,b) do { count_fpuld(); FPUm(0xdf05, d, b); asm_output("fildq %d(%s)",d,gpn(b)); fpu_push(); } while(0)
#define FILD(d,b) do { count_fpuld(); FPUm(0xdb00, d, b); asm_output("fild %d(%s)",d,gpn(b)); fpu_push(); } while(0)
#define FIST(p,d,b) do { count_fpu(); FPUm(0xdb02|(p), d, b); asm_output("fist%s %d(%s)",((p)?"p":""),d,gpn(b)); if(p) fpu_pop(); } while(0)
#define FADD(d,b) do { count_fpu(); FPUm(0xdc00, d, b); asm_output("fadd %d(%s)",d,gpn(b)); } while(0)
#define FADDdm(m) do { const double* const dm = m; \
count_ldq(); FPUdm(0xdc00, dm); asm_output("fadd (%p)",dm); } while(0)
count_ldq(); FPUdm(0xdc00, dm); asm_output("fadd (%p)",(void*)dm); } while(0)
#define FSUB(d,b) do { count_fpu(); FPUm(0xdc04, d, b); asm_output("fsub %d(%s)",d,gpn(b)); } while(0)
#define FSUBR(d,b) do { count_fpu(); FPUm(0xdc05, d, b); asm_output("fsubr %d(%s)",d,gpn(b)); } while(0)
#define FSUBRdm(m) do { const double* const dm = m; \
count_ldq(); FPUdm(0xdc05, dm); asm_output("fsubr (%p)",dm); } while(0)
count_ldq(); FPUdm(0xdc05, dm); asm_output("fsubr (%p)",(void*)dm); } while(0)
#define FMUL(d,b) do { count_fpu(); FPUm(0xdc01, d, b); asm_output("fmul %d(%s)",d,gpn(b)); } while(0)
#define FMULdm(m) do { const double* const dm = m; \
count_ldq(); FPUdm(0xdc01, dm); asm_output("fmul (%p)",dm); } while(0)
count_ldq(); FPUdm(0xdc01, dm); asm_output("fmul (%p)",(void*)dm); } while(0)
#define FDIV(d,b) do { count_fpu(); FPUm(0xdc06, d, b); asm_output("fdiv %d(%s)",d,gpn(b)); } while(0)
#define FDIVR(d,b) do { count_fpu(); FPUm(0xdc07, d, b); asm_output("fdivr %d(%s)",d,gpn(b)); } while(0)
#define FDIVRdm(m) do { const double* const dm = m; \
count_ldq(); FPUdm(0xdc07, dm); asm_output("fdivr (%p)",dm); } while(0)
count_ldq(); FPUdm(0xdc07, dm); asm_output("fdivr (%p)",(void*)dm); } while(0)
#define FINCSTP() do { count_fpu(); FPUc(0xd9f7); asm_output("fincstp"); } while(0)
#define FSTP(r) do { count_fpu(); FPU(0xddd8, r&7); asm_output("fstp %s",fpn(r)); fpu_pop();} while(0)
#define FCOMP() do { count_fpu(); FPUc(0xD8D9); asm_output("fcomp"); fpu_pop();} while(0)