aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-08-12 09:40:11 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2014-08-14 15:27:51 +0200
commitd9f33ccdef985badc56fd8940373748626beffc7 (patch)
treeccacfa93345abba1d274dfb0bae178e855efb613 /src/qml
parent17743ea6e22535bd5c6c01436c40084f0c4053bc (diff)
V4 JIT: parameterize the prologue and epilogue generation
... with the regular (non-FP) registers that need to be saved. This patch shouldn't change any of the JIT generated code, because all regular callee saved registers are passed in. Change-Id: Id11b8f37f06d80e8015ac6f0d0ccefdfa3342cbe Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jit/qv4assembler.cpp37
-rw-r--r--src/qml/jit/qv4assembler_p.h32
-rw-r--r--src/qml/jit/qv4isel_masm.cpp31
-rw-r--r--src/qml/jit/qv4isel_masm_p.h3
-rw-r--r--src/qml/jit/qv4registerinfo_p.h26
-rw-r--r--src/qml/jit/qv4targetplatform_p.h24
6 files changed, 84 insertions, 69 deletions
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 3f3fccb39d..e76d498409 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -93,10 +93,8 @@ QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int fu
const Assembler::VoidType Assembler::Void;
-Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
- int maxArgCountForBuiltins)
- : _stackLayout(function, maxArgCountForBuiltins)
- , _constTable(this)
+Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
+ : _constTable(this)
, _function(function)
, _nextBlock(0)
, _executableAllocator(executableAllocator)
@@ -241,7 +239,7 @@ void Assembler::storeValue(QV4::Primitive value, IR::Expr *destination)
storeValue(value, addr);
}
-void Assembler::enterStandardStackFrame()
+void Assembler::enterStandardStackFrame(const RegisterInformation &regularRegistersToSave)
{
platformEnterStandardStackFrame(this);
@@ -250,24 +248,28 @@ void Assembler::enterStandardStackFrame()
push(StackFrameRegister);
move(StackPointerRegister, StackFrameRegister);
- int frameSize = _stackLayout.calculateStackFrameSize();
+ int frameSize = _stackLayout->calculateStackFrameSize();
subPtr(TrustedImm32(frameSize), StackPointerRegister);
- const RegisterInformation &calleeSavedRegisters = getCalleeSavedRegisters();
- for (int i = 0; i < calleeSavedRegisterCount(); ++i)
- storePtr(calleeSavedRegisters[i].reg<RegisterID>(), Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
-
+ Address slotAddr(StackFrameRegister, -RegisterSize);
+ for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) {
+ storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr);
+ slotAddr.offset -= RegisterSize;
+ }
}
-void Assembler::leaveStandardStackFrame()
+void Assembler::leaveStandardStackFrame(const RegisterInformation &regularRegistersToSave)
{
+ Address slotAddr(StackFrameRegister, -regularRegistersToSave.size() * RegisterSize);
+
// restore the callee saved registers
- const RegisterInformation &calleeSavedRegisters = getCalleeSavedRegisters();
- for (int i = calleeSavedRegisterCount() - 1; i >= 0; --i)
- loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i].reg<RegisterID>());
+ for (int i = regularRegistersToSave.size() - 1; i >= 0; --i) {
+ loadPtr(slotAddr, regularRegistersToSave.at(i).reg<RegisterID>());
+ slotAddr.offset += RegisterSize;
+ }
- int frameSize = _stackLayout.calculateStackFrameSize();
+ int frameSize = _stackLayout->calculateStackFrameSize();
// Work around bug in ARMv7Assembler.h where add32(imm, sp, sp) doesn't
// work well for large immediates.
#if CPU(ARM_THUMB2)
@@ -388,4 +390,9 @@ Assembler::Jump Assembler::branchInt32(bool invertCondition, IR::AluOp op, IR::E
toInt32Register(right, Assembler::ReturnValueRegister));
}
+void Assembler::setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave)
+{
+ _stackLayout.reset(new StackLayout(_function, maxArgCountForBuiltins, regularRegistersToSave));
+}
+
#endif
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 5e868c3b11..7d774f93f7 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -135,9 +135,10 @@ struct ExceptionCheck<void (*)(QV4::NoThrowContext *, A, B, C)> {
class Assembler : public JSC::MacroAssembler, public TargetPlatform
{
+ Q_DISABLE_COPY(Assembler)
+
public:
- Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
- int maxArgCountForBuiltins);
+ Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator);
// Explicit type to allow distinguishing between
// pushing an address itself or the value it points
@@ -181,8 +182,8 @@ public:
class StackLayout
{
public:
- StackLayout(IR::Function *function, int maxArgCountForBuiltins)
- : calleeSavedRegCount(Assembler::calleeSavedRegisterCount() + 1)
+ StackLayout(IR::Function *function, int maxArgCountForBuiltins, int normalRegistersToSave)
+ : normalRegistersToSave(normalRegistersToSave)
, maxOutgoingArgumentCount(function->maxNumberOfArguments)
, localCount(function->tempCount)
, savedRegCount(maxArgCountForBuiltins)
@@ -215,7 +216,7 @@ public:
+ RegisterSize; // saved StackFrameRegister
// space for the callee saved registers
- int frameSize = RegisterSize * calleeSavedRegisterCount();
+ int frameSize = RegisterSize * normalRegistersToSave;
frameSize += savedRegCount * sizeof(QV4::Value); // these get written out as Values, not as native registers
Q_ASSERT(frameSize + stackSpaceAllocatedOtherwise < INT_MAX);
@@ -268,11 +269,11 @@ public:
int calleeSavedRegisterSpace() const
{
// plus 1 for the old FP
- return RegisterSize * (calleeSavedRegCount + 1);
+ return RegisterSize * (normalRegistersToSave + 1);
}
private:
- int calleeSavedRegCount;
+ int normalRegistersToSave;
/// arg count for calls to JS functions
int maxOutgoingArgumentCount;
@@ -384,7 +385,7 @@ public:
{
Q_ASSERT(t->kind == IR::Temp::StackSlot);
- return Pointer(_stackLayout.stackSlotPointer(t->index));
+ return Pointer(_stackLayout->stackSlotPointer(t->index));
}
template <int argumentNumber>
@@ -394,7 +395,7 @@ public:
return;
if (IR::Temp *t = arg.value->asTemp()) {
if (t->kind == IR::Temp::PhysicalRegister) {
- Pointer addr(_stackLayout.savedRegPointer(argumentNumber));
+ Pointer addr(_stackLayout->savedRegPointer(argumentNumber));
switch (t->type) {
case IR::BoolType:
storeBool((RegisterID) t->index, addr);
@@ -793,8 +794,8 @@ public:
void storeValue(QV4::Primitive value, IR::Expr* temp);
- void enterStandardStackFrame();
- void leaveStandardStackFrame();
+ void enterStandardStackFrame(const RegisterInformation &regularRegistersToSave);
+ void leaveStandardStackFrame(const RegisterInformation &regularRegistersToSave);
void checkException() {
loadPtr(Address(ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, engine)), ScratchRegister);
@@ -941,7 +942,7 @@ public:
Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset)
{
if (IR::Const *c = e->asConst()) {
- Address addr = _stackLayout.savedRegPointer(offset);
+ Address addr = _stackLayout->savedRegPointer(offset);
Address tagAddr = addr;
tagAddr.offset += 4;
@@ -953,7 +954,7 @@ public:
if (IR::Temp *t = e->asTemp())
if (t->kind == IR::Temp::PhysicalRegister)
- return Pointer(_stackLayout.savedRegPointer(offset));
+ return Pointer(_stackLayout->savedRegPointer(offset));
return loadAddress(tmpReg, e);
}
@@ -1145,14 +1146,15 @@ public:
JSC::MacroAssemblerCodeRef link(int *codeSize);
- const StackLayout stackLayout() const { return _stackLayout; }
+ void setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave);
+ const StackLayout &stackLayout() const { return *_stackLayout.data(); }
ConstantTable &constantTable() { return _constTable; }
Label exceptionReturnLabel;
IR::BasicBlock * catchBlock;
QVector<Jump> exceptionPropagationJumps;
private:
- const StackLayout _stackLayout;
+ QScopedPointer<const StackLayout> _stackLayout;
ConstantTable _constTable;
IR::Function *_function;
QHash<IR::BasicBlock *, Label> _addrs;
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index f5d112c072..5547190303 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -226,20 +226,23 @@ void InstructionSelection::run(int functionIndex)
static const bool withRegisterAllocator = qgetenv("QV4_NO_REGALLOC").isEmpty();
if (Assembler::RegAllocIsSupported && opt.isInSSA() && withRegisterAllocator) {
RegisterAllocator(Assembler::getRegisterInfo()).run(_function, opt);
+ calculateRegistersToSave(Assembler::getRegisterInfo());
} else {
if (opt.isInSSA())
// No register allocator available for this platform, or env. var was set, so:
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
IR::Optimizer::showMeTheCode(_function);
+ calculateRegistersToSave(Assembler::getRegisterInfo()); // FIXME: this saves all registers. We can probably do with a subset: those that are not used by the register allocator.
}
QSet<IR::Jump *> removableJumps = opt.calculateOptionalJumps();
qSwap(_removableJumps, removableJumps);
Assembler* oldAssembler = _as;
- _as = new Assembler(this, _function, executableAllocator, 6); // 6 == max argc for calls to built-ins with an argument array
-
- _as->enterStandardStackFrame();
+ _as = new Assembler(this, _function, executableAllocator);
+ _as->setStackLayout(6, // 6 == max argc for calls to built-ins with an argument array
+ regularRegistersToSave.size());
+ _as->enterStandardStackFrame(regularRegistersToSave);
#ifdef ARGUMENTS_IN_REGISTERS
_as->move(_as->registerForArgument(0), Assembler::ContextRegister);
@@ -1470,7 +1473,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
_as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext::Data, engine)), Assembler::ScratchRegister);
_as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
- _as->leaveStandardStackFrame();
+ _as->leaveStandardStackFrame(regularRegistersToSave);
_as->ret();
}
@@ -1525,6 +1528,26 @@ int InstructionSelection::prepareCallData(IR::ExprList* args, IR::Expr *thisObje
return argc;
}
+void InstructionSelection::calculateRegistersToSave(const RegisterInformation &used)
+{
+ regularRegistersToSave.clear();
+
+ foreach (const RegisterInfo &ri, Assembler::getRegisterInfo()) {
+ if (ri.isCallerSaved())
+ continue;
+
+ if (ri.isRegularRegister()) {
+#if defined(RESTORE_EBX_ON_CALL)
+ if (ri.isRegularRegister() && ri.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
+ regularRegistersToSave.append(ri);
+ continue;
+ }
+#endif // RESTORE_EBX_ON_CALL
+ if (ri.isPredefined() || used.contains(ri))
+ regularRegistersToSave.append(ri);
+ }
+ }
+}
QT_BEGIN_NAMESPACE
namespace QV4 {
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index af518a0851..bbe0f05556 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -237,6 +237,8 @@ private:
int prepareVariableArguments(IR::ExprList* args);
int prepareCallData(IR::ExprList* args, IR::Expr *thisObject);
+ void calculateRegistersToSave(const RegisterInformation &used);
+
template <typename Retval, typename Arg1, typename Arg2, typename Arg3>
void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
@@ -263,6 +265,7 @@ private:
QScopedPointer<CompilationUnit> compilationUnit;
QQmlEnginePrivate *qmlEngine;
+ RegisterInformation regularRegistersToSave;
};
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
diff --git a/src/qml/jit/qv4registerinfo_p.h b/src/qml/jit/qv4registerinfo_p.h
index b8701d72f4..ed816fdb05 100644
--- a/src/qml/jit/qv4registerinfo_p.h
+++ b/src/qml/jit/qv4registerinfo_p.h
@@ -52,27 +52,30 @@ namespace JIT {
class RegisterInfo
{
public:
- enum { InvalidRegister = -1 };
+ enum { InvalidRegister = (1 << 29) - 1 };
enum SavedBy { CallerSaved, CalleeSaved };
enum RegisterType { RegularRegister, FloatingPointRegister };
enum Usage { Predefined, RegAlloc };
public:
RegisterInfo()
- : _reg(InvalidRegister)
- , _type(RegularRegister)
- , _savedBy(CallerSaved)
+ : _savedBy(CallerSaved)
, _usage(Predefined)
+ , _type(RegularRegister)
+ , _reg(InvalidRegister)
{}
RegisterInfo(int reg, const QString &prettyName, RegisterType type, SavedBy savedBy, Usage usage)
- : _reg(reg)
- , _prettyName(prettyName)
- , _type(type)
+ : _prettyName(prettyName)
, _savedBy(savedBy)
, _usage(usage)
+ , _type(type)
+ , _reg(reg)
{}
+ bool operator==(const RegisterInfo &other) const
+ { return _type == other._type && _reg == other._reg; }
+
bool isValid() const { return _reg != InvalidRegister; }
template <typename T> T reg() const { return static_cast<T>(_reg); }
QString prettyName() const { return _prettyName; }
@@ -81,13 +84,14 @@ public:
bool isFloatingPoint() const { return _type == FloatingPointRegister; }
bool isRegularRegister() const { return _type == RegularRegister; }
bool useForRegAlloc() const { return _usage == RegAlloc; }
+ bool isPredefined() const { return _usage == Predefined; }
private:
- int _reg;
QString _prettyName;
- RegisterType _type;
- SavedBy _savedBy;
- Usage _usage;
+ unsigned _savedBy : 1;
+ unsigned _usage : 1;
+ unsigned _type : 1;
+ unsigned _reg : 29;
};
typedef QVector<RegisterInfo> RegisterInformation;
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 4b384d2fe9..b32fe66ac3 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -354,30 +354,6 @@ public: // utility functions
return info;
}
-
- static RegisterInformation &getCalleeSavedRegisters()
- {
- 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);
- }
- }
-
- return regs;
- }
-
- static int calleeSavedRegisterCount()
- {
- return getCalleeSavedRegisters().size();
- }
};
} // JIT namespace