diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-05-17 16:38:25 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-06-10 11:53:19 +0200 |
commit | e20650e0702259b4be79be85a3d27e45db42efc1 (patch) | |
tree | 7536cee98f4cc502774f807d1a609940cd20d4f5 /src/qml/jsruntime/qv4stackframe_p.h | |
parent | 7fa28f98824a94396106eadfc028b329985a0cfc (diff) |
Eliminate JS call frame from metatypes calls
If we call an AOT-compiled function we never need the JavaScript call
frame. We can just skip its setup and save some overhead.
Change-Id: I39dc2ca6eea5b5a66f3b87b642a310534cecf6cd
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4stackframe_p.h')
-rw-r--r-- | src/qml/jsruntime/qv4stackframe_p.h | 157 |
1 files changed, 103 insertions, 54 deletions
diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h index ebe3b762af..1439e9f677 100644 --- a/src/qml/jsruntime/qv4stackframe_p.h +++ b/src/qml/jsruntime/qv4stackframe_p.h @@ -64,17 +64,17 @@ namespace QV4 { struct CppStackFrame; struct Q_QML_PRIVATE_EXPORT CppStackFrameBase { - enum class Kind : quint8 { Bare, JS, Meta }; + enum class Kind : quint8 { JS, Meta }; - Value *savedStackTop; CppStackFrame *parent; Function *v4Function; - CallData *jsFrame; int originalArgumentsCount; int instructionPointer; union { struct { + Value *savedStackTop; + CallData *jsFrame; const Value *originalArguments; const char *yield; const char *unwindHandler; @@ -86,6 +86,8 @@ struct Q_QML_PRIVATE_EXPORT CppStackFrameBase bool isTailCalling; }; struct { + ExecutionContext *context; + QObject *thisObject; const QMetaType *metaTypes; void **returnAndArgs; }; @@ -100,88 +102,67 @@ struct Q_QML_PRIVATE_EXPORT CppStackFrame : protected CppStackFrameBase // non-standard layout. So we have this other struct with "using" in between. using CppStackFrameBase::instructionPointer; using CppStackFrameBase::v4Function; - using CppStackFrameBase::jsFrame; - void init(Function *v4Function, int argc, Kind kind = Kind::Bare) { + void init(Function *v4Function, int argc, Kind kind) { this->v4Function = v4Function; originalArgumentsCount = argc; instructionPointer = 0; this->kind = kind; } - bool isBareStackFrame() const { return kind == Kind::Bare; } bool isJSTypesFrame() const { return kind == Kind::JS; } bool isMetaTypesFrame() const { return kind == Kind::Meta; } - static uint requiredJSStackFrameSize(uint nRegisters) { - return CallData::HeaderSize() + nRegisters; - } - static uint requiredJSStackFrameSize(Function *v4Function) { - return CallData::HeaderSize() + v4Function->compiledFunction->nRegisters; - } - uint requiredJSStackFrameSize() const { - return requiredJSStackFrameSize(v4Function); - } - - void setupJSFrame(Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope, - const Value &thisObject, const Value &newTarget = Value::undefinedValue()) - { - jsFrame = reinterpret_cast<CallData *>(stackSpace); - jsFrame->function = function; - jsFrame->context = scope->asReturnedValue(); - jsFrame->accumulator = Encode::undefined(); - jsFrame->thisObject = thisObject; - jsFrame->newTarget = newTarget; - } - QString source() const; QString function() const; int lineNumber() const; + + CppStackFrame *parentFrame() const { return parent; } + void setParentFrame(CppStackFrame *parentFrame) { parent = parentFrame; } + + int argc() const { return originalArgumentsCount; } + + inline ExecutionContext *context() const; + + Heap::CallContext *callContext() const { return callContext(context()->d()); } ReturnedValue thisObject() const; - ExecutionContext *context() const +protected: + CppStackFrame() = default; + + void push(EngineBase *engine) { - return static_cast<ExecutionContext *>(&jsFrame->context); + Q_ASSERT(kind == Kind::JS || kind == Kind::Meta); + parent = engine->currentStackFrame; + engine->currentStackFrame = this; } - void setContext(ExecutionContext *context) + void pop(EngineBase *engine) { - jsFrame->context = context; + engine->currentStackFrame = parent; } - Heap::CallContext *callContext() const + Heap::CallContext *callContext(Heap::ExecutionContext *ctx) const { - Heap::ExecutionContext *ctx = static_cast<ExecutionContext &>(jsFrame->context).d();\ while (ctx->type != Heap::ExecutionContext::Type_CallContext) ctx = ctx->outer; return static_cast<Heap::CallContext *>(ctx); } - - CppStackFrame *parentFrame() const { return parent; } - void setParentFrame(CppStackFrame *parentFrame) { parent = parentFrame; } - - int argc() const { return originalArgumentsCount; } - Value *framePointer() const { return savedStackTop; } - - void push(EngineBase *engine) { - parent = engine->currentStackFrame; - engine->currentStackFrame = this; - savedStackTop = engine->jsStackTop; - } - - void pop(EngineBase *engine) { - engine->currentStackFrame = parent; - engine->jsStackTop = savedStackTop; - } }; struct Q_QML_PRIVATE_EXPORT MetaTypesStackFrame : public CppStackFrame { - void init(Function *v4Function, void **a, const QMetaType *types, int argc) + using CppStackFrame::push; + using CppStackFrame::pop; + + void init(Function *v4Function, QObject *thisObject, ExecutionContext *context, + void **returnAndArgs, const QMetaType *metaTypes, int argc) { CppStackFrame::init(v4Function, argc, Kind::Meta); - metaTypes = types; - returnAndArgs = a; + CppStackFrameBase::thisObject = thisObject; + CppStackFrameBase::context = context; + CppStackFrameBase::metaTypes = metaTypes; + CppStackFrameBase::returnAndArgs = returnAndArgs; } QMetaType returnType() const { return metaTypes[0]; } @@ -189,10 +170,22 @@ struct Q_QML_PRIVATE_EXPORT MetaTypesStackFrame : public CppStackFrame const QMetaType *argTypes() const { return metaTypes + 1; } void **argv() const { return returnAndArgs + 1; } + + QObject *thisObject() const { return CppStackFrameBase::thisObject; } + + ExecutionContext *context() const { return CppStackFrameBase::context; } + void setContext(ExecutionContext *context) { CppStackFrameBase::context = context; } + + Heap::CallContext *callContext() const + { + return CppStackFrame::callContext(CppStackFrameBase::context->d()); + } }; struct Q_QML_PRIVATE_EXPORT JSTypesStackFrame : public CppStackFrame { + using CppStackFrame::jsFrame; + // The JIT needs to poke directly into those using offsetof using CppStackFrame::unwindHandler; using CppStackFrame::unwindLabel; @@ -215,6 +208,16 @@ struct Q_QML_PRIVATE_EXPORT JSTypesStackFrame : public CppStackFrame const Value *argv() const { return originalArguments; } + static uint requiredJSStackFrameSize(uint nRegisters) { + return CallData::HeaderSize() + nRegisters; + } + static uint requiredJSStackFrameSize(Function *v4Function) { + return CallData::HeaderSize() + v4Function->compiledFunction->nRegisters; + } + uint requiredJSStackFrameSize() const { + return requiredJSStackFrameSize(v4Function); + } + void setupJSFrame(Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope, const Value &thisObject, const Value &newTarget = Value::undefinedValue()) { setupJSFrame(stackSpace, function, scope, thisObject, newTarget, @@ -226,7 +229,12 @@ struct Q_QML_PRIVATE_EXPORT JSTypesStackFrame : public CppStackFrame Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope, const Value &thisObject, const Value &newTarget, uint nFormals, uint nRegisters) { - CppStackFrame::setupJSFrame(stackSpace, function, scope, thisObject, newTarget); + jsFrame = reinterpret_cast<CallData *>(stackSpace); + jsFrame->function = function; + jsFrame->context = scope->asReturnedValue(); + jsFrame->accumulator = Encode::undefined(); + jsFrame->thisObject = thisObject; + jsFrame->newTarget = newTarget; uint argc = uint(originalArgumentsCount); if (argc > nFormals) @@ -251,6 +259,21 @@ struct Q_QML_PRIVATE_EXPORT JSTypesStackFrame : public CppStackFrame } } + ExecutionContext *context() const + { + return static_cast<ExecutionContext *>(&jsFrame->context); + } + + void setContext(ExecutionContext *context) + { + jsFrame->context = context; + } + + Heap::CallContext *callContext() const + { + return CppStackFrame::callContext(static_cast<ExecutionContext &>(jsFrame->context).d()); + } + bool isTailCalling() const { return CppStackFrame::isTailCalling; } void setTailCalling(bool tailCalling) { CppStackFrame::isTailCalling = tailCalling; } @@ -264,8 +287,34 @@ struct Q_QML_PRIVATE_EXPORT JSTypesStackFrame : public CppStackFrame void setYieldIsIterator(bool isIter) { CppStackFrame::yieldIsIterator = isIter; } bool callerCanHandleTailCall() const { return CppStackFrame::callerCanHandleTailCall; } + + ReturnedValue thisObject() const + { + return jsFrame->thisObject.asReturnedValue(); + } + + Value *framePointer() const { return savedStackTop; } + + void push(EngineBase *engine) { + CppStackFrame::push(engine); + savedStackTop = engine->jsStackTop; + } + + void pop(EngineBase *engine) { + CppStackFrame::pop(engine); + engine->jsStackTop = savedStackTop; + } }; +inline ExecutionContext *CppStackFrame::context() const +{ + if (isJSTypesFrame()) + return static_cast<const JSTypesStackFrame *>(this)->context(); + + Q_ASSERT(isMetaTypesFrame()); + return static_cast<const MetaTypesStackFrame *>(this)->context(); +} + Q_STATIC_ASSERT(sizeof(CppStackFrame) == sizeof(JSTypesStackFrame)); Q_STATIC_ASSERT(sizeof(CppStackFrame) == sizeof(MetaTypesStackFrame)); Q_STATIC_ASSERT(std::is_standard_layout_v<CppStackFrame>); |