Bug 817943 part 1. Introduce a GetTempRegForIntArg function that can be used to get registers to store things you plan to pass to a function call in, and use it for DOM getters/setters/methods. r=pierron

This commit is contained in:
Boris Zbarsky 2012-12-28 12:40:44 -08:00
parent 39a4dffd71
commit d4903aebb9
4 changed files with 138 additions and 13 deletions

View File

@ -16,6 +16,7 @@
#include "jsnum.h"
#include "jsobjinlines.h"
#include "shared/Lowering-shared-inl.h"
#include "mozilla/DebugOnly.h"
using namespace js;
using namespace ion;
@ -282,9 +283,16 @@ LIRGenerator::visitCall(MCall *call)
// Call DOM functions.
if (call->isDOMFunction()) {
JS_ASSERT(target && target->isNative());
LCallDOMNative *lir = new LCallDOMNative(argslot, tempFixed(CallTempReg0),
tempFixed(CallTempReg1), tempFixed(CallTempReg2),
tempFixed(CallTempReg3), tempFixed(CallTempReg4));
Register cxReg, objReg, privReg, argcReg, valueReg;
GetTempRegForIntArg(0, 0, &cxReg);
GetTempRegForIntArg(1, 0, &objReg);
GetTempRegForIntArg(2, 0, &privReg);
GetTempRegForIntArg(3, 0, &argcReg);
mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(4, 0, &valueReg);
MOZ_ASSERT(ok, "How can we not have five temp registers?");
LCallDOMNative *lir = new LCallDOMNative(argslot, tempFixed(cxReg),
tempFixed(objReg), tempFixed(privReg),
tempFixed(argcReg), tempFixed(valueReg));
return (defineReturn(lir, call) && assignSafepoint(lir, call));
}
@ -2144,11 +2152,23 @@ LIRGenerator::visitSetDOMProperty(MSetDOMProperty *ins)
{
MDefinition *val = ins->value();
LSetDOMProperty *lir = new LSetDOMProperty(tempFixed(CallTempReg0),
useFixed(ins->object(), CallTempReg1),
tempFixed(CallTempReg2),
tempFixed(CallTempReg3));
if (!useBoxFixed(lir, LSetDOMProperty::Value, val, CallTempReg4, CallTempReg5))
Register cxReg, objReg, privReg, valueReg;
GetTempRegForIntArg(0, 0, &cxReg);
GetTempRegForIntArg(1, 0, &objReg);
GetTempRegForIntArg(2, 0, &privReg);
GetTempRegForIntArg(3, 0, &valueReg);
LSetDOMProperty *lir = new LSetDOMProperty(tempFixed(cxReg),
useFixed(ins->object(), objReg),
tempFixed(privReg),
tempFixed(valueReg));
// Keep using GetTempRegForIntArg, since we want to make sure we
// don't clobber registers we're already using.
Register tempReg1, tempReg2;
GetTempRegForIntArg(2, 0, &tempReg1);
mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &tempReg2);
MOZ_ASSERT(ok, "How can we not have six temp registers?");
if (!useBoxFixed(lir, LSetDOMProperty::Value, val, tempReg1, tempReg2))
return false;
return add(lir, ins) && assignSafepoint(lir, ins);
@ -2157,10 +2177,16 @@ LIRGenerator::visitSetDOMProperty(MSetDOMProperty *ins)
bool
LIRGenerator::visitGetDOMProperty(MGetDOMProperty *ins)
{
LGetDOMProperty *lir = new LGetDOMProperty(tempFixed(CallTempReg0),
useFixed(ins->object(), CallTempReg1),
tempFixed(CallTempReg2),
tempFixed(CallTempReg3));
Register cxReg, objReg, privReg, valueReg;
GetTempRegForIntArg(0, 0, &cxReg);
GetTempRegForIntArg(1, 0, &objReg);
GetTempRegForIntArg(2, 0, &privReg);
mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &valueReg);
MOZ_ASSERT(ok, "How can we not have four temp registers?");
LGetDOMProperty *lir = new LGetDOMProperty(tempFixed(cxReg),
useFixed(ins->object(), objReg),
tempFixed(privReg),
tempFixed(valueReg));
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
}

View File

@ -14,6 +14,7 @@
#include "ion/IonCode.h"
#include "ion/arm/Architecture-arm.h"
#include "ion/shared/IonAssemblerBufferWithConstantPools.h"
#include "mozilla/Util.h"
namespace js {
namespace ion {
@ -54,6 +55,10 @@ static const Register CallTempReg3 = r8;
static const Register CallTempReg4 = r0;
static const Register CallTempReg5 = r1;
static const Register CallTempNonArgRegs[] = { r5, r6, r7, r8 };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
static const Register PreBarrierReg = r1;
static const Register InvalidReg = { Registers::invalid_reg };
@ -1952,6 +1957,26 @@ GetIntArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out)
return true;
}
// Get a register in which we plan to put a quantity that will be used as an
// integer argument. This differs from GetIntArgReg in that if we have no more
// actual argument registers to use we will fall back on using whatever
// CallTempReg* don't overlap the argument registers, and only fail once those
// run out too.
static inline bool
GetTempRegForIntArg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out)
{
if (GetIntArgReg(usedIntArgs, usedFloatArgs, out))
return true;
// Unfortunately, we have to assume things about the point at which
// GetIntArgReg returns false, because we need to know how many registers it
// can allocate.
usedIntArgs -= NumIntArgRegs;
if (usedIntArgs >= NumCallTempNonArgRegs)
return false;
*out = CallTempNonArgRegs[usedIntArgs];
return true;
}
static inline bool
GetFloatArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, FloatRegister *out)
{
@ -1990,13 +2015,33 @@ GetFloatArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *pad
static inline bool
GetIntArgReg(uint32_t arg, uint32_t floatArg, Register *out)
{
if (arg < 4) {
if (arg < NumIntArgRegs) {
*out = Register::FromCode(arg);
return true;
}
return false;
}
// Get a register in which we plan to put a quantity that will be used as an
// integer argument. This differs from GetIntArgReg in that if we have no more
// actual argument registers to use we will fall back on using whatever
// CallTempReg* don't overlap the argument registers, and only fail once those
// run out too.
static inline bool
GetTempRegForIntArg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out)
{
if (GetIntArgReg(usedIntArgs, usedFloatArgs, out))
return true;
// Unfortunately, we have to assume things about the point at which
// GetIntArgReg returns false, because we need to know how many registers it
// can allocate.
usedIntArgs -= NumIntArgRegs;
if (usedIntArgs >= NumCallTempNonArgRegs)
return false;
*out = CallTempNonArgRegs[usedIntArgs];
return true;
}
static inline uint32_t
GetArgStackDisp(uint32_t arg)
{

View File

@ -11,6 +11,7 @@
#include "ion/shared/Assembler-shared.h"
#include "ion/CompactBuffer.h"
#include "ion/IonCode.h"
#include "mozilla/Util.h"
namespace js {
namespace ion {
@ -91,6 +92,10 @@ static const Register IntArgReg3 = r9;
static const uint32_t NumIntArgRegs = 4;
static const Register IntArgRegs[NumIntArgRegs] = { rcx, rdx, r8, r9 };
static const Register CallTempNonArgRegs[] = { rax, rdi, rbx, rsi };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
static const FloatRegister FloatArgReg0 = xmm0;
static const FloatRegister FloatArgReg1 = xmm1;
static const FloatRegister FloatArgReg2 = xmm2;
@ -107,6 +112,10 @@ static const Register IntArgReg5 = r9;
static const uint32_t NumIntArgRegs = 6;
static const Register IntArgRegs[NumIntArgRegs] = { rdi, rsi, rdx, rcx, r8, r9 };
static const Register CallTempNonArgRegs[] = { rax, rbx };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
static const FloatRegister FloatArgReg0 = xmm0;
static const FloatRegister FloatArgReg1 = xmm1;
static const FloatRegister FloatArgReg2 = xmm2;
@ -561,6 +570,31 @@ GetIntArgReg(uint32_t intArg, uint32_t floatArg, Register *out)
return true;
}
// Get a register in which we plan to put a quantity that will be used as an
// integer argument. This differs from GetIntArgReg in that if we have no more
// actual argument registers to use we will fall back on using whatever
// CallTempReg* don't overlap the argument registers, and only fail once those
// run out too.
static inline bool
GetTempRegForIntArg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out)
{
if (GetIntArgReg(usedIntArgs, usedFloatArgs, out))
return true;
// Unfortunately, we have to assume things about the point at which
// GetIntArgReg returns false, because we need to know how many registers it
// can allocate.
#if defined(_WIN64)
uint32_t arg = usedIntArgs + usedFloatArgs;
#else
uint32_t arg = usedIntArgs;
#endif
arg -= NumIntArgRegs;
if (arg >= NumCallTempNonArgRegs)
return false;
*out = CallTempNonArgRegs[arg];
return true;
}
static inline bool
GetFloatArgReg(uint32_t intArg, uint32_t floatArg, FloatRegister *out)
{

View File

@ -12,6 +12,7 @@
#include "assembler/assembler/X86Assembler.h"
#include "ion/CompactBuffer.h"
#include "ion/IonCode.h"
#include "mozilla/Util.h"
#include "jsscriptinlines.h"
@ -55,6 +56,11 @@ static const Register CallTempReg3 = ecx;
static const Register CallTempReg4 = esi;
static const Register CallTempReg5 = edx;
// We have no arg regs, so our NonArgRegs are just our CallTempReg*
static const Register CallTempNonArgRegs[] = { edi, eax, ebx, ecx, esi, edx };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
static const Register OsrFrameReg = edx;
static const Register PreBarrierReg = edx;
@ -392,6 +398,20 @@ class Assembler : public AssemblerX86Shared
}
};
// Get a register in which we plan to put a quantity that will be used as an
// integer argument. This differs from GetIntArgReg in that if we have no more
// actual argument registers to use we will fall back on using whatever
// CallTempReg* don't overlap the argument registers, and only fail once those
// run out too.
static inline bool
GetTempRegForIntArg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out)
{
if (usedIntArgs >= NumCallTempNonArgRegs)
return false;
*out = CallTempNonArgRegs[usedIntArgs];
return true;
}
} // namespace ion
} // namespace js