mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
39a4dffd71
commit
d4903aebb9
@ -16,6 +16,7 @@
|
|||||||
#include "jsnum.h"
|
#include "jsnum.h"
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
#include "shared/Lowering-shared-inl.h"
|
#include "shared/Lowering-shared-inl.h"
|
||||||
|
#include "mozilla/DebugOnly.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace ion;
|
using namespace ion;
|
||||||
@ -282,9 +283,16 @@ LIRGenerator::visitCall(MCall *call)
|
|||||||
// Call DOM functions.
|
// Call DOM functions.
|
||||||
if (call->isDOMFunction()) {
|
if (call->isDOMFunction()) {
|
||||||
JS_ASSERT(target && target->isNative());
|
JS_ASSERT(target && target->isNative());
|
||||||
LCallDOMNative *lir = new LCallDOMNative(argslot, tempFixed(CallTempReg0),
|
Register cxReg, objReg, privReg, argcReg, valueReg;
|
||||||
tempFixed(CallTempReg1), tempFixed(CallTempReg2),
|
GetTempRegForIntArg(0, 0, &cxReg);
|
||||||
tempFixed(CallTempReg3), tempFixed(CallTempReg4));
|
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));
|
return (defineReturn(lir, call) && assignSafepoint(lir, call));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2144,11 +2152,23 @@ LIRGenerator::visitSetDOMProperty(MSetDOMProperty *ins)
|
|||||||
{
|
{
|
||||||
MDefinition *val = ins->value();
|
MDefinition *val = ins->value();
|
||||||
|
|
||||||
LSetDOMProperty *lir = new LSetDOMProperty(tempFixed(CallTempReg0),
|
Register cxReg, objReg, privReg, valueReg;
|
||||||
useFixed(ins->object(), CallTempReg1),
|
GetTempRegForIntArg(0, 0, &cxReg);
|
||||||
tempFixed(CallTempReg2),
|
GetTempRegForIntArg(1, 0, &objReg);
|
||||||
tempFixed(CallTempReg3));
|
GetTempRegForIntArg(2, 0, &privReg);
|
||||||
if (!useBoxFixed(lir, LSetDOMProperty::Value, val, CallTempReg4, CallTempReg5))
|
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 false;
|
||||||
|
|
||||||
return add(lir, ins) && assignSafepoint(lir, ins);
|
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||||
@ -2157,10 +2177,16 @@ LIRGenerator::visitSetDOMProperty(MSetDOMProperty *ins)
|
|||||||
bool
|
bool
|
||||||
LIRGenerator::visitGetDOMProperty(MGetDOMProperty *ins)
|
LIRGenerator::visitGetDOMProperty(MGetDOMProperty *ins)
|
||||||
{
|
{
|
||||||
LGetDOMProperty *lir = new LGetDOMProperty(tempFixed(CallTempReg0),
|
Register cxReg, objReg, privReg, valueReg;
|
||||||
useFixed(ins->object(), CallTempReg1),
|
GetTempRegForIntArg(0, 0, &cxReg);
|
||||||
tempFixed(CallTempReg2),
|
GetTempRegForIntArg(1, 0, &objReg);
|
||||||
tempFixed(CallTempReg3));
|
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);
|
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "ion/IonCode.h"
|
#include "ion/IonCode.h"
|
||||||
#include "ion/arm/Architecture-arm.h"
|
#include "ion/arm/Architecture-arm.h"
|
||||||
#include "ion/shared/IonAssemblerBufferWithConstantPools.h"
|
#include "ion/shared/IonAssemblerBufferWithConstantPools.h"
|
||||||
|
#include "mozilla/Util.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace ion {
|
namespace ion {
|
||||||
@ -54,6 +55,10 @@ static const Register CallTempReg3 = r8;
|
|||||||
static const Register CallTempReg4 = r0;
|
static const Register CallTempReg4 = r0;
|
||||||
static const Register CallTempReg5 = r1;
|
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 PreBarrierReg = r1;
|
||||||
|
|
||||||
static const Register InvalidReg = { Registers::invalid_reg };
|
static const Register InvalidReg = { Registers::invalid_reg };
|
||||||
@ -1952,6 +1957,26 @@ GetIntArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out)
|
|||||||
return true;
|
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
|
static inline bool
|
||||||
GetFloatArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, FloatRegister *out)
|
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
|
static inline bool
|
||||||
GetIntArgReg(uint32_t arg, uint32_t floatArg, Register *out)
|
GetIntArgReg(uint32_t arg, uint32_t floatArg, Register *out)
|
||||||
{
|
{
|
||||||
if (arg < 4) {
|
if (arg < NumIntArgRegs) {
|
||||||
*out = Register::FromCode(arg);
|
*out = Register::FromCode(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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
|
static inline uint32_t
|
||||||
GetArgStackDisp(uint32_t arg)
|
GetArgStackDisp(uint32_t arg)
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "ion/shared/Assembler-shared.h"
|
#include "ion/shared/Assembler-shared.h"
|
||||||
#include "ion/CompactBuffer.h"
|
#include "ion/CompactBuffer.h"
|
||||||
#include "ion/IonCode.h"
|
#include "ion/IonCode.h"
|
||||||
|
#include "mozilla/Util.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace ion {
|
namespace ion {
|
||||||
@ -91,6 +92,10 @@ static const Register IntArgReg3 = r9;
|
|||||||
static const uint32_t NumIntArgRegs = 4;
|
static const uint32_t NumIntArgRegs = 4;
|
||||||
static const Register IntArgRegs[NumIntArgRegs] = { rcx, rdx, r8, r9 };
|
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 FloatArgReg0 = xmm0;
|
||||||
static const FloatRegister FloatArgReg1 = xmm1;
|
static const FloatRegister FloatArgReg1 = xmm1;
|
||||||
static const FloatRegister FloatArgReg2 = xmm2;
|
static const FloatRegister FloatArgReg2 = xmm2;
|
||||||
@ -107,6 +112,10 @@ static const Register IntArgReg5 = r9;
|
|||||||
static const uint32_t NumIntArgRegs = 6;
|
static const uint32_t NumIntArgRegs = 6;
|
||||||
static const Register IntArgRegs[NumIntArgRegs] = { rdi, rsi, rdx, rcx, r8, r9 };
|
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 FloatArgReg0 = xmm0;
|
||||||
static const FloatRegister FloatArgReg1 = xmm1;
|
static const FloatRegister FloatArgReg1 = xmm1;
|
||||||
static const FloatRegister FloatArgReg2 = xmm2;
|
static const FloatRegister FloatArgReg2 = xmm2;
|
||||||
@ -561,6 +570,31 @@ GetIntArgReg(uint32_t intArg, uint32_t floatArg, Register *out)
|
|||||||
return true;
|
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
|
static inline bool
|
||||||
GetFloatArgReg(uint32_t intArg, uint32_t floatArg, FloatRegister *out)
|
GetFloatArgReg(uint32_t intArg, uint32_t floatArg, FloatRegister *out)
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "assembler/assembler/X86Assembler.h"
|
#include "assembler/assembler/X86Assembler.h"
|
||||||
#include "ion/CompactBuffer.h"
|
#include "ion/CompactBuffer.h"
|
||||||
#include "ion/IonCode.h"
|
#include "ion/IonCode.h"
|
||||||
|
#include "mozilla/Util.h"
|
||||||
|
|
||||||
#include "jsscriptinlines.h"
|
#include "jsscriptinlines.h"
|
||||||
|
|
||||||
@ -55,6 +56,11 @@ static const Register CallTempReg3 = ecx;
|
|||||||
static const Register CallTempReg4 = esi;
|
static const Register CallTempReg4 = esi;
|
||||||
static const Register CallTempReg5 = edx;
|
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 OsrFrameReg = edx;
|
||||||
static const Register PreBarrierReg = 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 ion
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user