{}
};
+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 {
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);
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
-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
template <typename Retval, typename Arg1, typename Arg2, typename Arg3>
void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
- Assembler::RegisterID lookupRegister;
-#if CPU(ARM)
- lookupRegister = JSC::ARMRegisters::r8;
-#else
- lookupRegister = Assembler::ReturnValueRegister;
-#endif
- Assembler::Pointer lookupAddr(lookupRegister, index * sizeof(QV4::Lookup));
-
- Assembler::Address getterSetter = lookupAddr;
- getterSetter.offset += getterSetterOffset;
+ // Note: using the return value register is intentional: for ABIs where the first parameter
+ // goes into the same register as the return value (currently only ARM), the prepareCall
+ // will combine loading the looupAddr into the register and calculating the indirect call
+ // address.
+ Assembler::Pointer lookupAddr(Assembler::ReturnValueRegister, index * sizeof(QV4::Lookup));
_as->generateFunctionCallImp(retval, "lookup getter/setter",
- RelativeCall(getterSetter), lookupAddr, arg1, arg2, arg3);
+ LookupCall(lookupAddr, getterSetterOffset), lookupAddr,
+ arg1, arg2, arg3);
}
template <typename Retval, typename Arg1, typename Arg2>