Start converting Runtime calls to 'vtable' calls

The old code was using absolute addressing for calls into
methods of the Runtime. This produces non relocatable code,
which is bad for caching.

So instead, we'll have a table of function pointers for all
runtime methods in the ExecutionEngine, and do the runtime
calls through that table.

Change-Id: I75c04f699ea11c38f742575f9ce264c0c5ad0c96
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
This commit is contained in:
Lars Knoll 2015-10-09 08:58:36 +02:00 committed by Simon Hausmann
parent 20dbb21f51
commit c810daa675
7 changed files with 46 additions and 5 deletions

View File

@ -104,6 +104,12 @@ struct LookupCall {
{}
};
struct RuntimeCall {
JSC::MacroAssembler::Address addr;
inline RuntimeCall(uint offset);
};
template <typename T>
struct ExceptionCheck {
enum { NeedsCheck = 1 };
@ -359,6 +365,17 @@ public:
call(lookupCall.addr);
}
void callAbsolute(const char *functionName, const RuntimeCall &runtimeCall)
{
call(runtimeCall.addr);
// the code below is to get proper function names in the disassembly
CallToLink ctl;
ctl.externalFunction = FunctionPtr();
ctl.functionName = functionName;
ctl.label = label();
_callsToLink.append(ctl);
}
void registerBlock(IR::BasicBlock*, IR::BasicBlock *nextBlock);
IR::BasicBlock *nextBlock() const { return _nextBlock; }
void jumpToBlock(IR::BasicBlock* current, IR::BasicBlock *target);
@ -1232,6 +1249,11 @@ void Assembler::copyValue(Result result, IR::Expr* source)
}
}
inline RuntimeCall::RuntimeCall(uint offset)
: addr(Assembler::EngineRegister, offset + qOffsetOf(QV4::ExecutionEngine, runtime))
{
}
template <typename T> inline bool prepareCall(T &, Assembler *)

View File

@ -161,7 +161,8 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
QHash<void*, const char*> functions;
foreach (CallToLink ctl, _callsToLink) {
linkBuffer.link(ctl.call, ctl.externalFunction);
if (ctl.externalFunction.value())
linkBuffer.link(ctl.call, ctl.externalFunction);
functions[linkBuffer.locationOf(ctl.label).dataLocation()] = ctl.functionName;
}
@ -393,7 +394,7 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(result, Runtime::callGlobalLookup,
generateRuntimeCall(result, callGlobalLookup,
Assembler::EngineRegister,
Assembler::TrustedImm32(index),
baseAddressForCallData());

View File

@ -246,6 +246,8 @@ private:
#define generateFunctionCall(t, function, ...) \
_as->generateFunctionCallImp(t, isel_stringIfy(function), function, __VA_ARGS__)
#define generateRuntimeCall(t, function, ...) \
_as->generateFunctionCallImp(t, "Runtime::" isel_stringIfy(function), RuntimeCall(qOffsetOf(QV4::Runtime, function)), __VA_ARGS__)
int prepareVariableArguments(IR::ExprList* args);
int prepareCallData(IR::ExprList* args, IR::Expr *thisObject);

View File

@ -110,6 +110,8 @@ public:
Value *jsStackLimit;
quintptr cStackLimit;
Runtime runtime;
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
enum { JSStackLimit = 4*1024*1024 };

View File

@ -931,7 +931,7 @@ uint Runtime::compareIn(ExecutionEngine *engine, const Value &left, const Value
}
ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData)
ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());

View File

@ -47,9 +47,20 @@ namespace QV4 {
struct NoThrowEngine;
#define RUNTIME_METHOD(returnvalue, name, args) \
typedef returnvalue (*Method_##name)args; \
static returnvalue method_##name args; \
const Method_##name name
#define INIT_RUNTIME_METHOD(name) \
name(method_##name)
struct Q_QML_PRIVATE_EXPORT Runtime {
Runtime()
: INIT_RUNTIME_METHOD(callGlobalLookup)
{ }
// call
static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData);
RUNTIME_METHOD(ReturnedValue, callGlobalLookup, (ExecutionEngine *engine, uint index, CallData *callData));
static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
static ReturnedValue callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
static ReturnedValue callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
@ -186,6 +197,9 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static void setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value);
};
#undef RUNTIME_METHOD
#undef INIT_RUNTIME_METHOD
} // namespace QV4
QT_END_NAMESPACE

View File

@ -638,7 +638,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::callGlobalLookup(engine, instr.index, callData));
STOREVALUE(instr.result, Runtime::method_callGlobalLookup(engine, instr.index, callData));
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(SetExceptionHandler)