From fd221cf6e056b7239fc2fa2faeccd9ddeb542199 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 7 Aug 2017 08:10:15 +0200 Subject: Introduce a JS stack frame that corresponds to the C++ stack frame The frame currently contains the function itself and the current context. Change-Id: I7d3402627fbc90e860a7bdc277585f365f5b4cb5 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4codegen.cpp | 3 +++ src/qml/jsruntime/qv4context.cpp | 4 ++-- src/qml/jsruntime/qv4enginebase_p.h | 8 ++++++++ src/qml/jsruntime/qv4function.cpp | 3 +-- src/qml/jsruntime/qv4function_p.h | 6 +++--- src/qml/jsruntime/qv4globalobject.cpp | 2 +- src/qml/jsruntime/qv4profiling_p.h | 12 ++++++------ src/qml/jsruntime/qv4script.cpp | 2 +- src/qml/jsruntime/qv4vme_moth.cpp | 8 ++++++-- src/qml/jsruntime/qv4vme_moth_p.h | 2 +- 10 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index f75839ad4b..6505469a8b 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1771,6 +1771,9 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, savedBytecodeGenerator = bytecodeGenerator; bytecodeGenerator = &bytecode; + // allocate the js stack frame (Context & js Function) + bytecodeGenerator->newRegisterArray(2); + int returnAddress = bytecodeGenerator->newRegister(); if (!_context->parent || _context->usesArgumentsObject == Context::ArgumentsObjectUnknown) diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 1019770275..8678529916 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -244,7 +244,7 @@ ReturnedValue ExecutionContext::call(ExecutionEngine *engine, CallData *callData ctx->d()->function.set(engine, f->d()); engine->pushContext(ctx); - ReturnedValue res = Q_V4_PROFILE(engine, function); + ReturnedValue res = Q_V4_PROFILE(engine, function, f); if (function->hasQmlDependencies) QQmlPropertyCapture::registerQmlDependencies(engine, function->compiledFunction); @@ -271,7 +271,7 @@ ReturnedValue QV4::ExecutionContext::simpleCall(ExecutionEngine *engine, CallDat engine->pushContext(ctx); Q_ASSERT(engine->current == ctx); - ReturnedValue res = Q_V4_PROFILE(engine, function); + ReturnedValue res = Q_V4_PROFILE(engine, function, 0); if (function->hasQmlDependencies) QQmlPropertyCapture::registerQmlDependencies(engine, function->compiledFunction); diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h index cc049fb296..a713e8eab4 100644 --- a/src/qml/jsruntime/qv4enginebase_p.h +++ b/src/qml/jsruntime/qv4enginebase_p.h @@ -63,9 +63,17 @@ namespace QV4 { #pragma pack(push, 1) #endif struct EngineBase { + struct JSStackFrame { + // callData is directly before this + QV4::Value jsFunction; + QV4::Value context; + // registers follow + }; + struct StackFrame { StackFrame *parent; Function *v4Function; + JSStackFrame *jsFrame; int line = -1; int column = -1; diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index d21afa3b87..bcc776dc98 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -49,8 +49,7 @@ QT_BEGIN_NAMESPACE using namespace QV4; -Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, - ReturnedValue (*codePtr)(Function *)) +Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, Code codePtr) : compiledFunction(function) , compilationUnit(unit) , code(codePtr) diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 9fc51e90af..17311ca3c1 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -63,7 +63,8 @@ struct Q_QML_EXPORT Function { const CompiledData::Function *compiledFunction; CompiledData::CompilationUnit *compilationUnit; - ReturnedValue (*code)(Function *); + typedef ReturnedValue (*Code)(Function *, const FunctionObject *); + Code code; const uchar *codeData; // first nArguments names in internalClass are the actual arguments @@ -72,8 +73,7 @@ struct Q_QML_EXPORT Function { bool hasQmlDependencies; bool canUseSimpleCall; - Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, - ReturnedValue (*codePtr)(Function *)); + Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, Code codePtr); ~Function(); // used when dynamically assigning signal handlers (QQmlConnection) diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 69d9683eaa..71140e5386 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -386,7 +386,7 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const ctx->d()->strictMode = false; ctx->d()->v4Function = function; - return Q_V4_PROFILE(ctx->engine(), function); + return Q_V4_PROFILE(ctx->engine(), function, 0); } diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index e7b6909690..adf9853f62 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -61,7 +61,7 @@ #define Q_V4_PROFILE_ALLOC(engine, size, type) (!engine) #define Q_V4_PROFILE_DEALLOC(engine, size, type) (!engine) -#define Q_V4_PROFILE(engine, function) (function->code(function)) +#define Q_V4_PROFILE(engine, function, jsFunction) (function->code(function, jsFunction)) QT_BEGIN_NAMESPACE @@ -85,11 +85,11 @@ QT_END_NAMESPACE (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\ engine->profiler()->trackDealloc(size, type) : false) -#define Q_V4_PROFILE(engine, function)\ +#define Q_V4_PROFILE(engine, function, jsFunction)\ (Q_UNLIKELY(engine->profiler()) &&\ (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\ - Profiling::FunctionCallProfiler::profileCall(engine->profiler(), function) :\ - function->code(function)) + Profiling::FunctionCallProfiler::profileCall(engine->profiler(), function, jsFunction) :\ + function->code(function, jsFunction)) QT_BEGIN_NAMESPACE @@ -279,10 +279,10 @@ public: profiler->m_data.append(FunctionCall(function, startTime, profiler->m_timer.nsecsElapsed())); } - static ReturnedValue profileCall(Profiler *profiler, Function *function) + static ReturnedValue profileCall(Profiler *profiler, Function *function, const FunctionObject *jsFunction) { FunctionCallProfiler callProfiler(profiler, function); - return function->code(function); + return function->code(function, jsFunction); } Profiler *profiler; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 2b97a0f1d4..188b66d8d3 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -153,7 +153,7 @@ ReturnedValue Script::run() scope->d()->strictMode = vmFunction->isStrict(); scope->d()->v4Function = vmFunction; - return Q_V4_PROFILE(engine, vmFunction); + return Q_V4_PROFILE(engine, vmFunction, 0); } else { Scoped qml(valueScope, qmlContext.value()); ScopedCallData callData(valueScope); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 21a2095196..747101fef2 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -432,7 +432,7 @@ static inline const QV4::Value &constant(Function *function, int index) return function->compilationUnit->constants[index]; } -QV4::ReturnedValue VME::exec(Function *function) +QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunction) { qt_v4ResolvePendingBreakpointsHook(); @@ -456,11 +456,15 @@ QV4::ReturnedValue VME::exec(Function *function) QV4::Scope scope(engine); int nFormals = function->nFormals; - stack = scope.alloc(function->compiledFunction->nRegisters + nFormals + 2); + stack = scope.alloc(function->compiledFunction->nRegisters + nFormals + 2 + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value)); QV4::Value &accumulator = *stack; ++stack; memcpy(stack, &engine->current->callData->thisObject, (nFormals + 1)*sizeof(Value)); stack += nFormals + 1; + frame.jsFrame = reinterpret_cast(stack); + frame.jsFrame->context = engine->current; + if (jsFunction) + frame.jsFrame->jsFunction = *jsFunction; if (QV4::Debugging::Debugger *debugger = engine->debugger()) debugger->enteringFunction(); diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h index 51ea5fbdac..5055af65fd 100644 --- a/src/qml/jsruntime/qv4vme_moth_p.h +++ b/src/qml/jsruntime/qv4vme_moth_p.h @@ -65,7 +65,7 @@ namespace Moth { class VME { public: - static QV4::ReturnedValue exec(QV4::Function *); + static QV4::ReturnedValue exec(QV4::Function *, const FunctionObject *jsFunction = 0); }; } // namespace Moth -- cgit v1.2.3