aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-05-22 14:45:59 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2014-06-17 14:44:23 +0200
commitc6921eca61d1f393f6cd08484da29da7d67d9695 (patch)
tree82605ddef1a519c2772836eaf692eb66210b7035
parent7acdace9be3a68954152455acd527fa052c47b09 (diff)
V4 JIT: teach regalloc about callee-saved registers.
Callee-saved registers won't get clobbered by a call, so any value stored in it will survive the call. Change-Id: I2b61b84617b01bf7ce7e81cd0119a6da689ee9d5 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/jit/qv4regalloc.cpp20
-rw-r--r--src/qml/jit/qv4targetplatform_p.h15
2 files changed, 26 insertions, 9 deletions
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index e21676e520..6a2f5ca640 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -1280,19 +1280,23 @@ void RegisterAllocator::prepareRanges()
const int regCount = _normalRegisters.size();
_fixedRegisterRanges.reserve(regCount);
for (int reg = 0; reg < regCount; ++reg) {
- LifeTimeInterval *lti = cloneFixedInterval(reg, false, ltiWithCalls);
- _fixedRegisterRanges.append(lti);
- if (lti->isValid())
- _active.append(lti);
+ if (_normalRegisters.at(reg)->isCallerSaved()) {
+ LifeTimeInterval *lti = cloneFixedInterval(reg, false, ltiWithCalls);
+ _fixedRegisterRanges.append(lti);
+ if (lti->isValid())
+ _active.append(lti);
+ }
}
const int fpRegCount = _fpRegisters.size();
_fixedFPRegisterRanges.reserve(fpRegCount);
for (int fpReg = 0; fpReg < fpRegCount; ++fpReg) {
- LifeTimeInterval *lti = cloneFixedInterval(fpReg, true, ltiWithCalls);
- _fixedFPRegisterRanges.append(lti);
- if (lti->isValid())
- _active.append(lti);
+ if (_fpRegisters.at(fpReg)->isCallerSaved()) {
+ LifeTimeInterval *lti = cloneFixedInterval(fpReg, true, ltiWithCalls);
+ _fixedFPRegisterRanges.append(lti);
+ if (lti->isValid())
+ _active.append(lti);
+ }
}
}
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 1f08a0df2b..95db247d0f 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -61,6 +61,13 @@ namespace JIT {
// restore ebx (which holds the GOT ptr) before a call
// - All (supported) ARM platforms, where the only variety is the platform specific usage of r9,
// and the frame-pointer in Thumb/Thumb2 v.s. ARM mode.
+//
+// Specific handling of ebx when it holds the GOT:
+// In this case we can use it, but it needs to be restored when doing a call. So, the handling is as
+// follows: it is marked as caller saved, meaning the value in it won't survive a call. When
+// calculating the list of callee saved registers in getCalleeSavedRegisters (which is used to
+// generate push/pop instructions in the prelude/postlude), we add ebx too. Then when synthesizing
+// a call, we add a load it right before emitting the call instruction.
class TargetPlatform
{
public:
@@ -81,7 +88,7 @@ public:
typedef RegisterInfo RI;
return RegisterInformation()
<< RI(JSC::X86Registers::edx, QStringLiteral("edx"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
- << RI(JSC::X86Registers::ebx, QStringLiteral("ebx"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::ebx, QStringLiteral("ebx"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
<< RI(JSC::X86Registers::edi, QStringLiteral("edi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
<< RI(JSC::X86Registers::esi, QStringLiteral("esi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
<< RI(JSC::X86Registers::xmm2, QStringLiteral("xmm2"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
@@ -351,6 +358,12 @@ public: // utility functions
static RegisterInformation regs;
if (regs.isEmpty()) {
foreach (const RegisterInfo &info, getRegisterInfo()) {
+#if defined(RESTORE_EBX_ON_CALL)
+ if (info.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
+ regs.append(info);
+ continue;
+ }
+#endif // RESTORE_EBX_ON_CALL
if (info.isCalleeSaved())
regs.append(info);
}