diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2014-08-12 16:28:49 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@digia.com> | 2014-08-14 15:27:59 +0200 |
commit | 8e47157252b41c537bb1e05c621d16654c2639fd (patch) | |
tree | 81ec3733176bff10bb0085bfa281fbdb634e173f | |
parent | a503efe0df31742bac7d5af6ed4a53ee79a4c2a7 (diff) |
V4 JIT: support saving used callee saved FP registers.
This is not used yet by any platform/abi we support, because we do not
define any callee-saved FP registers. Yet.
Change-Id: I5857a452456175398c5e9681ff33800b9431b9da
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r-- | src/qml/jit/qv4assembler.cpp | 37 | ||||
-rw-r--r-- | src/qml/jit/qv4assembler_p.h | 17 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 12 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 1 |
4 files changed, 46 insertions, 21 deletions
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index e76d498409..130a673484 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -239,37 +239,50 @@ void Assembler::storeValue(QV4::Primitive value, IR::Expr *destination) storeValue(value, addr); } -void Assembler::enterStandardStackFrame(const RegisterInformation ®ularRegistersToSave) +void Assembler::enterStandardStackFrame(const RegisterInformation ®ularRegistersToSave, + const RegisterInformation &fpRegistersToSave) { platformEnterStandardStackFrame(this); - // ### FIXME: Handle through calleeSavedRegisters mechanism - // or eliminate StackFrameRegister altogether. push(StackFrameRegister); move(StackPointerRegister, StackFrameRegister); - int frameSize = _stackLayout->calculateStackFrameSize(); - + const int frameSize = _stackLayout->calculateStackFrameSize(); subPtr(TrustedImm32(frameSize), StackPointerRegister); - Address slotAddr(StackFrameRegister, -RegisterSize); + Address slotAddr(StackFrameRegister, 0); for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) { - storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr); + Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister()); slotAddr.offset -= RegisterSize; + storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr); + } + for (int i = 0, ei = fpRegistersToSave.size(); i < ei; ++i) { + Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint()); + slotAddr.offset -= sizeof(double); + JSC::MacroAssembler::storeDouble(fpRegistersToSave.at(i).reg<FPRegisterID>(), slotAddr); } } -void Assembler::leaveStandardStackFrame(const RegisterInformation ®ularRegistersToSave) +void Assembler::leaveStandardStackFrame(const RegisterInformation ®ularRegistersToSave, + const RegisterInformation &fpRegistersToSave) { - Address slotAddr(StackFrameRegister, -regularRegistersToSave.size() * RegisterSize); + Address slotAddr(StackFrameRegister, -regularRegistersToSave.size() * RegisterSize - fpRegistersToSave.size() * sizeof(double)); // restore the callee saved registers + for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) { + Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint()); + JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>()); + slotAddr.offset += sizeof(double); + } for (int i = regularRegistersToSave.size() - 1; i >= 0; --i) { + Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister()); loadPtr(slotAddr, regularRegistersToSave.at(i).reg<RegisterID>()); slotAddr.offset += RegisterSize; } - int frameSize = _stackLayout->calculateStackFrameSize(); + Q_ASSERT(slotAddr.offset == 0); + + const 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) @@ -390,9 +403,9 @@ Assembler::Jump Assembler::branchInt32(bool invertCondition, IR::AluOp op, IR::E toInt32Register(right, Assembler::ReturnValueRegister)); } -void Assembler::setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave) +void Assembler::setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave, int fpRegistersToSave) { - _stackLayout.reset(new StackLayout(_function, maxArgCountForBuiltins, regularRegistersToSave)); + _stackLayout.reset(new StackLayout(_function, maxArgCountForBuiltins, regularRegistersToSave, fpRegistersToSave)); } #endif diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 7d774f93f7..8f50610072 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -182,8 +182,9 @@ public: class StackLayout { public: - StackLayout(IR::Function *function, int maxArgCountForBuiltins, int normalRegistersToSave) + StackLayout(IR::Function *function, int maxArgCountForBuiltins, int normalRegistersToSave, int fpRegistersToSave) : normalRegistersToSave(normalRegistersToSave) + , fpRegistersToSave(fpRegistersToSave) , maxOutgoingArgumentCount(function->maxNumberOfArguments) , localCount(function->tempCount) , savedRegCount(maxArgCountForBuiltins) @@ -216,7 +217,7 @@ public: + RegisterSize; // saved StackFrameRegister // space for the callee saved registers - int frameSize = RegisterSize * normalRegistersToSave; + int frameSize = RegisterSize * normalRegistersToSave + sizeof(double) * fpRegistersToSave; frameSize += savedRegCount * sizeof(QV4::Value); // these get written out as Values, not as native registers Q_ASSERT(frameSize + stackSpaceAllocatedOtherwise < INT_MAX); @@ -269,11 +270,13 @@ public: int calleeSavedRegisterSpace() const { // plus 1 for the old FP - return RegisterSize * (normalRegistersToSave + 1); + return RegisterSize * (normalRegistersToSave + 1) + + sizeof(double) * fpRegistersToSave; } private: int normalRegistersToSave; + int fpRegistersToSave; /// arg count for calls to JS functions int maxOutgoingArgumentCount; @@ -794,8 +797,10 @@ public: void storeValue(QV4::Primitive value, IR::Expr* temp); - void enterStandardStackFrame(const RegisterInformation ®ularRegistersToSave); - void leaveStandardStackFrame(const RegisterInformation ®ularRegistersToSave); + void enterStandardStackFrame(const RegisterInformation ®ularRegistersToSave, + const RegisterInformation &fpRegistersToSave); + void leaveStandardStackFrame(const RegisterInformation ®ularRegistersToSave, + const RegisterInformation &fpRegistersToSave); void checkException() { loadPtr(Address(ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, engine)), ScratchRegister); @@ -1146,7 +1151,7 @@ public: JSC::MacroAssemblerCodeRef link(int *codeSize); - void setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave); + void setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave, int fpRegistersToSave); const StackLayout &stackLayout() const { return *_stackLayout.data(); } ConstantTable &constantTable() { return _constTable; } diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 39e7c0fbc2..104cd2e903 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -242,8 +242,9 @@ void InstructionSelection::run(int functionIndex) Assembler* oldAssembler = _as; _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); + regularRegistersToSave.size(), + fpRegistersToSave.size()); + _as->enterStandardStackFrame(regularRegistersToSave, fpRegistersToSave); #ifdef ARGUMENTS_IN_REGISTERS _as->move(_as->registerForArgument(0), Assembler::ContextRegister); @@ -1474,7 +1475,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(regularRegistersToSave); + _as->leaveStandardStackFrame(regularRegistersToSave, fpRegistersToSave); _as->ret(); } @@ -1532,6 +1533,7 @@ int InstructionSelection::prepareCallData(IR::ExprList* args, IR::Expr *thisObje void InstructionSelection::calculateRegistersToSave(const RegisterInformation &used) { regularRegistersToSave.clear(); + fpRegistersToSave.clear(); foreach (const RegisterInfo &ri, Assembler::getRegisterInfo()) { if (ri.isCallerSaved()) @@ -1546,6 +1548,10 @@ void InstructionSelection::calculateRegistersToSave(const RegisterInformation &u #endif // RESTORE_EBX_ON_CALL if (ri.isPredefined() || used.contains(ri)) regularRegistersToSave.append(ri); + } else { + Q_ASSERT(ri.isFloatingPoint()); + if (ri.isPredefined() || used.contains(ri)) + fpRegistersToSave.append(ri); } } } diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index bbe0f05556..264ad2d179 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -266,6 +266,7 @@ private: QScopedPointer<CompilationUnit> compilationUnit; QQmlEnginePrivate *qmlEngine; RegisterInformation regularRegistersToSave; + RegisterInformation fpRegistersToSave; }; class Q_QML_EXPORT ISelFactory: public EvalISelFactory |