Bug 779411 - Require use-at-start or fixed registers at call instructions. r=sstangl

This commit is contained in:
Jan de Mooij 2012-09-17 17:16:03 -07:00
Родитель 66baa7fbda
Коммит ea5eda847d
12 изменённых файлов: 124 добавлений и 71 удалений

Просмотреть файл

@ -1695,22 +1695,17 @@ bool
CodeGenerator::visitPowI(LPowI *ins)
{
FloatRegister value = ToFloatRegister(ins->value());
Register power = ToRegister(ins->power());
Register temp = ToRegister(ins->temp());
JS_ASSERT(power != temp);
// In all implementations, setupUnalignedABICall() relinquishes use of
// its scratch register. We can therefore save an input register by
// reusing the scratch register to pass constants to callWithABI.
masm.setupUnalignedABICall(2, temp);
masm.passABIArg(value);
const LAllocation *power = ins->power();
if (power->isRegister()) {
JS_ASSERT(ToRegister(power) != temp);
masm.passABIArg(ToRegister(power));
} else {
masm.move32(Imm32(ToInt32(power)), temp);
masm.passABIArg(temp);
}
masm.passABIArg(power);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, js::powi), MacroAssembler::DOUBLE);
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);

Просмотреть файл

@ -597,6 +597,20 @@ LinearScanAllocator::buildLivenessInfo()
// The first instruction, LLabel, has no uses.
JS_ASSERT(inputOf(*ins) > outputOf(block->firstId()));
// Call uses should always be at-start or fixed, since the fixed intervals
// use all registers.
JS_ASSERT_IF(ins->isCall() && !alloc.isSnapshotInput(),
use->isFixedRegister() || use->usedAtStart());
#ifdef DEBUG
// Don't allow at-start call uses if there are temps of the same kind,
// so that we don't assign the same register.
if (ins->isCall() && use->usedAtStart()) {
for (size_t i = 0; i < ins->numTemps(); i++)
JS_ASSERT(vregs[ins->getTemp(i)].isDouble() != vregs[use].isDouble());
}
#endif
CodePosition to;
if (use->isFixedRegister()) {
JS_ASSERT(!use->usedAtStart());
@ -605,12 +619,7 @@ LinearScanAllocator::buildLivenessInfo()
return false;
to = inputOf(*ins);
} else {
// Call instruction operands default to at-start, since the
// fixed intervals use all registers.
if (use->usedAtStart() || (ins->isCall() && !alloc.isSnapshotInput()))
to = inputOf(*ins);
else
to = outputOf(*ins);
to = use->usedAtStart() ? inputOf(*ins) : outputOf(*ins);
}
LiveInterval *interval = vregs[use].getInterval(0);

Просмотреть файл

@ -141,8 +141,8 @@ LIRGenerator::visitNewCallObject(MNewCallObject *ins)
bool
LIRGenerator::visitInitProp(MInitProp *ins)
{
LInitProp *lir = new LInitProp(useRegister(ins->getObject()));
if (!useBox(lir, LInitProp::ValueIndex, ins->getValue()))
LInitProp *lir = new LInitProp(useRegisterAtStart(ins->getObject()));
if (!useBoxAtStart(lir, LInitProp::ValueIndex, ins->getValue()))
return false;
return add(lir, ins) && assignSafepoint(lir, ins);
@ -189,8 +189,8 @@ LIRGenerator::visitCreateThis(MCreateThis *ins)
return define(lir, ins) && assignSafepoint(lir, ins);
}
LCreateThisVM *lir = new LCreateThisVM(useRegisterOrConstant(ins->getCallee()),
useRegisterOrConstant(ins->getPrototype()));
LCreateThisVM *lir = new LCreateThisVM(useRegisterOrConstantAtStart(ins->getCallee()),
useRegisterOrConstantAtStart(ins->getPrototype()));
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
@ -277,17 +277,9 @@ LIRGenerator::visitApplyArgs(MApplyArgs *apply)
tempFixed(CallTempReg2)); // copy register
MDefinition *self = apply->getThis();
size_t index = LApplyArgsGeneric::ThisIndex;
if (!ensureDefined(self))
if (!useBoxFixed(lir, LApplyArgsGeneric::ThisIndex, self, CallTempReg4, CallTempReg5))
return false;
#if defined(JS_NUNBOX32)
lir->setOperand(index + 0, LUse(CallTempReg4, self->virtualRegister()));
lir->setOperand(index + 1, LUse(CallTempReg5, VirtualRegisterOfPayload(self)));
#elif defined(JS_PUNBOX64)
lir->setOperand(index + 0, LUse(CallTempReg4, self->virtualRegister()));
#endif
// Bailout is only needed in the case of possible non-JSFunction callee.
if (!target && !assignSnapshot(lir))
return false;
@ -496,9 +488,9 @@ LIRGenerator::visitCompare(MCompare *comp)
}
LCompareV *lir = new LCompareV();
if (!useBox(lir, LCompareV::LhsInput, left))
if (!useBoxAtStart(lir, LCompareV::LhsInput, left))
return false;
if (!useBox(lir, LCompareV::RhsInput, right))
if (!useBoxAtStart(lir, LCompareV::RhsInput, right))
return false;
return defineVMReturn(lir, comp) && assignSafepoint(lir, comp);
}
@ -528,9 +520,9 @@ LIRGenerator::lowerBitOp(JSOp op, MInstruction *ins)
}
LBitOpV *lir = new LBitOpV(op);
if (!useBox(lir, LBitOpV::LhsInput, lhs))
if (!useBoxAtStart(lir, LBitOpV::LhsInput, lhs))
return false;
if (!useBox(lir, LBitOpV::RhsInput, rhs))
if (!useBoxAtStart(lir, LBitOpV::RhsInput, rhs))
return false;
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
@ -552,9 +544,9 @@ bool
LIRGenerator::visitToId(MToId *ins)
{
LToIdV *lir = new LToIdV();
if (!useBox(lir, LToIdV::Object, ins->lhs()))
if (!useBoxAtStart(lir, LToIdV::Object, ins->lhs()))
return false;
if (!useBox(lir, LToIdV::Index, ins->rhs()))
if (!useBoxAtStart(lir, LToIdV::Index, ins->rhs()))
return false;
if (!defineVMReturn(lir, ins))
return false;
@ -570,7 +562,7 @@ LIRGenerator::visitBitNot(MBitNot *ins)
return lowerForALU(new LBitNotI(), ins, input);
LBitNotV *lir = new LBitNotV;
if (!useBox(lir, LBitNotV::Input, input))
if (!useBoxAtStart(lir, LBitNotV::Input, input))
return false;
if (!defineVMReturn(lir, ins))
return false;
@ -618,20 +610,16 @@ LIRGenerator::lowerShiftOp(JSOp op, MShiftInstruction *ins)
JS_ASSERT(ins->specialization() == MIRType_None);
if (op == JSOP_URSH) {
LBinaryV *lir = new LBinaryV(op);
if (!useBox(lir, LBinaryV::LhsInput, lhs))
return false;
if (!useBox(lir, LBinaryV::RhsInput, rhs))
return false;
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
} else {
LBitOpV *lir = new LBitOpV(op);
if (!useBox(lir, LBitOpV::LhsInput, lhs))
return false;
if (!useBox(lir, LBitOpV::RhsInput, rhs))
return false;
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
// Result is either int32 or double so we have to use BinaryV.
return lowerBinaryV(JSOP_URSH, ins);
}
LBitOpV *lir = new LBitOpV(op);
if (!useBoxAtStart(lir, LBitOpV::LhsInput, lhs))
return false;
if (!useBoxAtStart(lir, LBitOpV::RhsInput, rhs))
return false;
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
bool
@ -725,12 +713,15 @@ LIRGenerator::visitPow(MPow *ins)
JS_ASSERT(power->type() == MIRType_Int32 || power->type() == MIRType_Double);
if (power->type() == MIRType_Int32) {
LPowI *lir = new LPowI(useRegister(input), useFixed(power, CallTempReg1),
// Note: useRegisterAtStart here is safe, the temp is a GP register so
// it will never get the same register.
LPowI *lir = new LPowI(useRegisterAtStart(input), useFixed(power, CallTempReg1),
tempFixed(CallTempReg0));
return defineFixed(lir, ins, LAllocation(AnyRegister(ReturnFloatReg)));
}
LPowD *lir = new LPowD(useRegister(input), useRegister(power), tempFixed(CallTempReg0));
LPowD *lir = new LPowD(useRegisterAtStart(input), useRegisterAtStart(power),
tempFixed(CallTempReg0));
return defineFixed(lir, ins, LAllocation(AnyRegister(ReturnFloatReg)));
}
@ -739,7 +730,10 @@ LIRGenerator::visitMathFunction(MMathFunction *ins)
{
JS_ASSERT(ins->type() == MIRType_Double);
JS_ASSERT(ins->input()->type() == MIRType_Double);
LMathFunctionD *lir = new LMathFunctionD(useRegister(ins->input()), tempFixed(CallTempReg0));
// Note: useRegisterAtStart is safe here, the temp is not a FP register.
LMathFunctionD *lir = new LMathFunctionD(useRegisterAtStart(ins->input()),
tempFixed(CallTempReg0));
return defineFixed(lir, ins, LAllocation(AnyRegister(ReturnFloatReg)));
}
@ -846,7 +840,10 @@ LIRGenerator::visitMod(MMod *ins)
if (ins->specialization() == MIRType_Double) {
JS_ASSERT(ins->type() == MIRType_Double);
JS_ASSERT(ins->lhs()->type() == MIRType_Double);
LModD *lir = new LModD(useRegister(ins->lhs()), useRegister(ins->rhs()),
JS_ASSERT(ins->rhs()->type() == MIRType_Double);
// Note: useRegisterAtStart is safe here, the temp is not a FP register.
LModD *lir = new LModD(useRegisterAtStart(ins->lhs()), useRegisterAtStart(ins->rhs()),
tempFixed(CallTempReg0));
return defineFixed(lir, ins, LAllocation(AnyRegister(ReturnFloatReg)));
}
@ -864,9 +861,9 @@ LIRGenerator::lowerBinaryV(JSOp op, MBinaryInstruction *ins)
JS_ASSERT(rhs->type() == MIRType_Value);
LBinaryV *lir = new LBinaryV(op);
if (!useBox(lir, LBinaryV::LhsInput, lhs))
if (!useBoxAtStart(lir, LBinaryV::LhsInput, lhs))
return false;
if (!useBox(lir, LBinaryV::RhsInput, rhs))
if (!useBoxAtStart(lir, LBinaryV::RhsInput, rhs))
return false;
if (!defineVMReturn(lir, ins))
return false;
@ -882,7 +879,7 @@ LIRGenerator::visitConcat(MConcat *ins)
JS_ASSERT(lhs->type() == MIRType_String);
JS_ASSERT(rhs->type() == MIRType_String);
LConcat *lir = new LConcat(useRegister(lhs), useRegister(rhs));
LConcat *lir = new LConcat(useRegisterAtStart(lhs), useRegisterAtStart(rhs));
if (!defineVMReturn(lir, ins))
return false;
return assignSafepoint(lir, ins);
@ -1088,7 +1085,7 @@ LIRGenerator::visitToString(MToString *ins)
break;
case MIRType_Int32: {
LIntToString *lir = new LIntToString(useRegister(opd));
LIntToString *lir = new LIntToString(useRegisterAtStart(opd));
if (!defineVMReturn(lir, ins))
return false;
@ -1119,7 +1116,7 @@ LIRGenerator::visitLambda(MLambda *ins)
//
// If UseNewTypeForClone is true, we will assign a singleton type to
// the clone and we have to clone the script, we can't do that inline.
LLambdaForSingleton *lir = new LLambdaForSingleton(useRegister(ins->scopeChain()));
LLambdaForSingleton *lir = new LLambdaForSingleton(useRegisterAtStart(ins->scopeChain()));
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
@ -1652,7 +1649,7 @@ bool
LIRGenerator::visitCallGetProperty(MCallGetProperty *ins)
{
LCallGetProperty *lir = new LCallGetProperty();
if (!useBox(lir, LCallGetProperty::Value, ins->value()))
if (!useBoxAtStart(lir, LCallGetProperty::Value, ins->value()))
return false;
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
@ -1664,9 +1661,9 @@ LIRGenerator::visitCallGetElement(MCallGetElement *ins)
JS_ASSERT(ins->rhs()->type() == MIRType_Value);
LCallGetElement *lir = new LCallGetElement();
if (!useBox(lir, LCallGetElement::LhsInput, ins->lhs()))
if (!useBoxAtStart(lir, LCallGetElement::LhsInput, ins->lhs()))
return false;
if (!useBox(lir, LCallGetElement::RhsInput, ins->rhs()))
if (!useBoxAtStart(lir, LCallGetElement::RhsInput, ins->rhs()))
return false;
if (!defineVMReturn(lir, ins))
return false;
@ -1676,8 +1673,8 @@ LIRGenerator::visitCallGetElement(MCallGetElement *ins)
bool
LIRGenerator::visitCallSetProperty(MCallSetProperty *ins)
{
LInstruction *lir = new LCallSetProperty(useRegister(ins->obj()));
if (!useBox(lir, LCallSetProperty::Value, ins->value()))
LInstruction *lir = new LCallSetProperty(useRegisterAtStart(ins->obj()));
if (!useBoxAtStart(lir, LCallSetProperty::Value, ins->value()))
return false;
if (!add(lir, ins))
return false;
@ -1688,7 +1685,7 @@ bool
LIRGenerator::visitDeleteProperty(MDeleteProperty *ins)
{
LCallDeleteProperty *lir = new LCallDeleteProperty();
if(!useBox(lir, LCallDeleteProperty::Value, ins->value()))
if(!useBoxAtStart(lir, LCallDeleteProperty::Value, ins->value()))
return false;
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
@ -1723,10 +1720,10 @@ LIRGenerator::visitCallSetElement(MCallSetElement *ins)
JS_ASSERT(ins->value()->type() == MIRType_Value);
LCallSetElement *lir = new LCallSetElement();
lir->setOperand(0, useRegister(ins->object()));
if (!useBox(lir, LCallSetElement::Index, ins->index()))
lir->setOperand(0, useRegisterAtStart(ins->object()));
if (!useBoxAtStart(lir, LCallSetElement::Index, ins->index()))
return false;
if (!useBox(lir, LCallSetElement::Value, ins->value()))
if (!useBoxAtStart(lir, LCallSetElement::Value, ins->value()))
return false;
return add(lir, ins) && assignSafepoint(lir, ins);
}
@ -1736,7 +1733,7 @@ LIRGenerator::visitIteratorStart(MIteratorStart *ins)
{
// Call a stub if this is not a simple for-in loop.
if (ins->flags() != JSITER_ENUMERATE) {
LCallIteratorStart *lir = new LCallIteratorStart(useRegister(ins->object()));
LCallIteratorStart *lir = new LCallIteratorStart(useRegisterAtStart(ins->object()));
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
@ -1792,7 +1789,7 @@ LIRGenerator::visitThrow(MThrow *ins)
JS_ASSERT(value->type() == MIRType_Value);
LThrow *lir = new LThrow;
if (!useBox(lir, LThrow::Value, value))
if (!useBoxAtStart(lir, LThrow::Value, value))
return false;
return add(lir, ins) && assignSafepoint(lir, ins);
}
@ -1837,7 +1834,7 @@ LIRGenerator::visitSetDOMProperty(MSetDOMProperty *ins)
useFixed(ins->object(), CallTempReg1),
tempFixed(CallTempReg2),
tempFixed(CallTempReg3));
if (!useBox(lir, LSetDOMProperty::Value, val))
if (!useBoxFixed(lir, LSetDOMProperty::Value, val, CallTempReg4, CallTempReg5))
return false;
return add(lir, ins) && assignSafepoint(lir, ins);

Просмотреть файл

@ -25,6 +25,20 @@ LIRGeneratorARM::useBox(LInstruction *lir, size_t n, MDefinition *mir,
return true;
}
bool
LIRGeneratorARM::useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1,
Register reg2)
{
JS_ASSERT(mir->type() == MIRType_Value);
JS_ASSERT(reg1 != reg2);
if (!ensureDefined(mir))
return false;
lir->setOperand(n, LUse(reg1, mir->virtualRegister()));
lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir)));
return true;
}
bool
LIRGeneratorARM::lowerConstantDouble(double d, MInstruction *mir)
{

Просмотреть файл

@ -25,6 +25,7 @@ class LIRGeneratorARM : public LIRGeneratorShared
// |n+1| to the payload.
bool useBox(LInstruction *lir, size_t n, MDefinition *mir,
LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register reg2);
void lowerUntypedPhiInput(MPhi *phi, uint32 inputPosition, LBlock *block, size_t lirIndex);
bool defineUntypedPhi(MPhi *phi, size_t lirIndex);

Просмотреть файл

@ -257,7 +257,15 @@ LIRGeneratorShared::useRegisterOrConstant(MDefinition *mir)
{
if (mir->isConstant())
return LAllocation(mir->toConstant()->vp());
return use(mir, LUse(LUse::REGISTER));
return useRegister(mir);
}
LAllocation
LIRGeneratorShared::useRegisterOrConstantAtStart(MDefinition *mir)
{
if (mir->isConstant())
return LAllocation(mir->toConstant()->vp());
return useRegisterAtStart(mir);
}
LAllocation
@ -265,7 +273,7 @@ LIRGeneratorShared::useRegisterOrNonDoubleConstant(MDefinition *mir)
{
if (mir->isConstant() && mir->type() != MIRType_Double)
return LAllocation(mir->toConstant()->vp());
return use(mir, LUse(LUse::REGISTER));
return useRegister(mir);
}
#if defined(JS_CPU_ARM)

Просмотреть файл

@ -80,6 +80,7 @@ class LIRGeneratorShared : public MInstructionVisitor
inline LAllocation useAnyOrConstant(MDefinition *mir);
inline LAllocation useKeepaliveOrConstant(MDefinition *mir);
inline LAllocation useRegisterOrConstant(MDefinition *mir);
inline LAllocation useRegisterOrConstantAtStart(MDefinition *mir);
inline LAllocation useRegisterOrNonDoubleConstant(MDefinition *mir);
#ifdef JS_NUNBOX32

Просмотреть файл

@ -80,6 +80,7 @@ static const Register CallTempReg1 = rdi;
static const Register CallTempReg2 = rbx;
static const Register CallTempReg3 = rcx;
static const Register CallTempReg4 = rsi;
static const Register CallTempReg5 = rdx;
// Different argument registers for WIN64
#if defined(_WIN64)

Просмотреть файл

@ -25,6 +25,17 @@ LIRGeneratorX64::useBox(LInstruction *lir, size_t n, MDefinition *mir,
return true;
}
bool
LIRGeneratorX64::useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register)
{
JS_ASSERT(mir->type() == MIRType_Value);
if (!ensureDefined(mir))
return false;
lir->setOperand(n, LUse(reg1, mir->virtualRegister()));
return true;
}
bool
LIRGeneratorX64::lowerConstantDouble(double d, MInstruction *mir)
{

Просмотреть файл

@ -27,6 +27,7 @@ class LIRGeneratorX64 : public LIRGeneratorX86Shared
// Adds a use at operand |n| of a value-typed insturction.
bool useBox(LInstruction *lir, size_t n, MDefinition *mir,
LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register);
bool lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir, MDefinition *lhs,
MDefinition *rhs);

Просмотреть файл

@ -26,6 +26,20 @@ LIRGeneratorX86::useBox(LInstruction *lir, size_t n, MDefinition *mir,
return true;
}
bool
LIRGeneratorX86::useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1,
Register reg2)
{
JS_ASSERT(mir->type() == MIRType_Value);
JS_ASSERT(reg1 != reg2);
if (!ensureDefined(mir))
return false;
lir->setOperand(n, LUse(reg1, mir->virtualRegister()));
lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir)));
return true;
}
bool
LIRGeneratorX86::lowerConstantDouble(double d, MInstruction *mir)
{

Просмотреть файл

@ -25,6 +25,7 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared
// |n+1| to the payload.
bool useBox(LInstruction *lir, size_t n, MDefinition *mir,
LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register reg2);
void lowerUntypedPhiInput(MPhi *phi, uint32 inputPosition, LBlock *block, size_t lirIndex);
bool defineUntypedPhi(MPhi *phi, size_t lirIndex);