aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit/qv4assembler_p.h
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-08-11 13:15:34 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2014-08-12 10:46:17 +0200
commit109abdb061263c28ae97424729e979cd0ff8289a (patch)
tree9e224b11e4477a3798a37ad0903ffc97f0409047 /src/qml/jit/qv4assembler_p.h
parent70d73e8ee4cbe87d2980a9ec1208515ef212119b (diff)
V4 JIT: fix LookupCall on ARM
To generate a LookupCall, the register r8 was used on ARM instead of the ReturnValue register. The reason is that the ReturnValue register is also the register for the first argument. However, now that we use callee-saved registers (r8 among them), this would clobber any value stored in r8. The fix is to actually use r0 to calculate the value, because the first argument holds the lookup table, and the call is relative to that. This leaves r8 free to be used by the register allocator. Change-Id: I5095bf69d27e16111ad32d9e5d5691c7bce14516 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jit/qv4assembler_p.h')
-rw-r--r--src/qml/jit/qv4assembler_p.h42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 4c5d2aeddd..36611b9064 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -93,6 +93,15 @@ struct RelativeCall {
{}
};
+struct LookupCall {
+ JSC::MacroAssembler::Address addr;
+ uint getterSetterOffset;
+
+ LookupCall(const JSC::MacroAssembler::Address &addr, uint getterSetterOffset)
+ : addr(addr)
+ , getterSetterOffset(getterSetterOffset)
+ {}
+};
template <typename T>
struct ExceptionCheck {
@@ -344,6 +353,11 @@ public:
call(relativeCall.addr);
}
+ void callAbsolute(const char* /*functionName*/, const LookupCall &lookupCall)
+ {
+ call(lookupCall.addr);
+ }
+
void registerBlock(IR::BasicBlock*, IR::BasicBlock *nextBlock);
IR::BasicBlock *nextBlock() const { return _nextBlock; }
void jumpToBlock(IR::BasicBlock* current, IR::BasicBlock *target);
@@ -866,8 +880,8 @@ public:
loadArgumentOnStackOrRegister<2>(arg3);
loadArgumentOnStackOrRegister<1>(arg2);
- prepareRelativeCall(function, this);
- loadArgumentOnStackOrRegister<0>(arg1);
+ if (prepareCall(function, this))
+ loadArgumentOnStackOrRegister<0>(arg1);
#ifdef RESTORE_EBX_ON_CALL
load32(ebxAddressOnStack(), JSC::X86Registers::ebx); // restore the GOT ptr
@@ -1198,11 +1212,31 @@ void Assembler::copyValue(Result result, IR::Expr* source)
-template <typename T> inline void prepareRelativeCall(const T &, Assembler *){}
-template <> inline void prepareRelativeCall(const RelativeCall &relativeCall, Assembler *as)
+template <typename T> inline bool prepareCall(T &, Assembler *)
+{ return true; }
+
+template <> inline bool prepareCall(RelativeCall &relativeCall, Assembler *as)
{
as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, lookups)),
relativeCall.addr.base);
+ return true;
+}
+
+template <> inline bool prepareCall(LookupCall &lookupCall, Assembler *as)
+{
+ // IMPORTANT! See generateLookupCall in qv4isel_masm_p.h for details!
+
+ // same as prepareCall(RelativeCall ....) : load the table from the context
+ as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, lookups)),
+ lookupCall.addr.base);
+ // pre-calculate the indirect address for the lookupCall table:
+ if (lookupCall.addr.offset)
+ as->addPtr(Assembler::TrustedImm32(lookupCall.addr.offset), lookupCall.addr.base);
+ // store it as the first argument
+ as->loadArgumentOnStackOrRegister<0>(lookupCall.addr.base);
+ // set the destination addresses offset to the getterSetterOffset. The base is the lookupCall table's address
+ lookupCall.addr.offset = lookupCall.getterSetterOffset;
+ return false;
}
} // end of namespace JIT