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 "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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user