diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-08-09 16:02:55 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-08-10 08:19:59 +0000 |
commit | 6a91dcba2e4fa85dc345c2d403c757ab7676e28c (patch) | |
tree | 502b483cd437f4a1a039717af0a59e493d40f7a2 | |
parent | 5571b666e6b9534a55347adcd249fa07b2e25c01 (diff) |
Always create a valid CallData object for interpreter calls
This will allow removing a few more special cases and to simplify
the code further.
Change-Id: I3a958e9f68e3c103ea4f2ee6825f893e5931b11d
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 29 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function.cpp | 24 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function_p.h | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4globalobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4profiling_p.h | 39 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmljavascriptexpression.cpp | 2 |
11 files changed, 68 insertions, 70 deletions
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 5732b904da..c04323c8ef 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -48,8 +48,6 @@ #include "qv4errorobject_p.h" #include "qv4string_p.h" #include "qv4qmlcontext_p.h" -#include "qv4profiling_p.h" -#include <private/qqmljavascriptexpression_p.h> using namespace QV4; @@ -226,33 +224,6 @@ bool ExecutionContext::deleteProperty(String *name) return !d()->v4Function->isStrict(); } -// Do a call with this execution context as the outer scope -ReturnedValue ExecutionContext::call(Heap::ExecutionContext *context, CallData *callData, Function *function, const FunctionObject *f) -{ - ExecutionEngine *engine = context->internalClass->engine; - Value *jsStackTop = engine->jsStackTop; - engine->jsStackTop = reinterpret_cast<QV4::Value *>(callData) + 2 + (int)function->nFormals; - for (int i = callData->argc; i < (int)function->nFormals; ++i) - callData->args[i] = Encode::undefined(); - - if (!function->canUseSimpleCall) { - context = newCallContext(context, function, callData); - if (f) - static_cast<Heap::CallContext *>(context)->function.set(engine, f->d()); - } - - ReturnedValue res = Q_V4_PROFILE(engine, context, function, f); - - if (function->hasQmlDependencies) { - Q_ASSERT(context->type == Heap::ExecutionContext::Type_QmlContext); - QQmlPropertyCapture::registerQmlDependencies(static_cast<Heap::QmlContext *>(context), engine, function->compiledFunction); - } - - engine->jsStackTop = jsStackTop; - - return res; -} - ExecutionContext::Error ExecutionContext::setProperty(String *name, const Value &value) { name->makeIdentifier(); diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 399c06c47e..697007c75b 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -227,8 +227,6 @@ struct Q_QML_EXPORT ExecutionContext : public Managed ReturnedValue argument(int i) const { return d()->callData->argument(i); } - - static ReturnedValue call(Heap::ExecutionContext *context, CallData *callData, QV4::Function *function, const QV4::FunctionObject *f = 0); }; struct Q_QML_EXPORT CallContext : public ExecutionContext diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index bcc776dc98..78fb46327a 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -38,12 +38,14 @@ ****************************************************************************/ #include "qv4function_p.h" +#include "qv4functionobject_p.h" #include "qv4managed_p.h" #include "qv4string_p.h" #include "qv4value_p.h" #include "qv4engine_p.h" #include "qv4lookup_p.h" #include <private/qv4mm_p.h> +#include <private/qqmljavascriptexpression_p.h> QT_BEGIN_NAMESPACE @@ -117,4 +119,26 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr canUseSimpleCall = false; } + +// Do a call with this execution context as the outer scope +ReturnedValue Function::call(const FunctionObject *f, CallData *callData, Heap::ExecutionContext *context, Function *function) +{ + ExecutionEngine *engine = context->internalClass->engine; + + if (!function->canUseSimpleCall) { + context = ExecutionContext::newCallContext(context, function, callData); + if (f) + static_cast<Heap::CallContext *>(context)->function.set(engine, f->d()); + } + + ReturnedValue res = function->execute(context, callData, f); + + if (function->hasQmlDependencies) { + Q_ASSERT(context->type == Heap::ExecutionContext::Type_QmlContext); + QQmlPropertyCapture::registerQmlDependencies(static_cast<Heap::QmlContext *>(context), engine, function->compiledFunction); + } + + return res; +} + QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 0976d22550..750db8c496 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -63,7 +63,15 @@ struct Q_QML_EXPORT Function { const CompiledData::Function *compiledFunction; CompiledData::CompilationUnit *compilationUnit; - typedef ReturnedValue (*Code)(Heap::ExecutionContext *c, Function *, const FunctionObject *); + ReturnedValue execute(Heap::ExecutionContext *c, CallData *callData, const FunctionObject *f = 0) { + return code(f, callData, c, this); + } + ReturnedValue call(Heap::ExecutionContext *c, CallData *callData, const FunctionObject *f = 0) { + return call(f, callData, c, this); + } + + + typedef ReturnedValue (*Code)(const FunctionObject *, CallData *, Heap::ExecutionContext *c, Function *); Code code; const uchar *codeData; @@ -95,6 +103,8 @@ struct Q_QML_EXPORT Function { return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column); } +private: + static ReturnedValue call(const FunctionObject *f, CallData *callData, Heap::ExecutionContext *context, Function *function); }; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 3549c6b9ea..27810dc836 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -368,7 +368,7 @@ ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData) QV4::Function *v4Function = f->function(); Q_ASSERT(v4Function); - ReturnedValue result = ExecutionContext::call(f->scope(), callData, v4Function, f); + ReturnedValue result = v4Function->call(f->scope(), callData, f); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); @@ -388,7 +388,7 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData) QV4::Function *v4Function = f->function(); Q_ASSERT(v4Function); - return ExecutionContext::call(f->scope(), callData, v4Function, f); + return v4Function->call(f->scope(), callData, f); } void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 761a8282ae..6c24367b67 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -383,7 +383,9 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const // set the correct v4 function for the context ctx->d()->v4Function = function; - return Q_V4_PROFILE(v4, ctx->d(), function, 0); + ScopedCallData cData(scope); + cData->thisObject = Encode::undefined(); // #### + return function->execute(ctx->d(), cData); } diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index be38690a49..9b71342467 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -59,9 +59,6 @@ #ifdef QT_NO_QML_DEBUGGER -#define Q_V4_PROFILE_ALLOC(engine, size, type) (!engine) -#define Q_V4_PROFILE_DEALLOC(engine, size, type) (!engine) -#define Q_V4_PROFILE(engine, context, function, jsFunction) (function->code(context, function, jsFunction)) QT_BEGIN_NAMESPACE @@ -75,22 +72,6 @@ QT_END_NAMESPACE #else -#define Q_V4_PROFILE_ALLOC(engine, size, type)\ - (engine->profiler() &&\ - (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\ - engine->profiler()->trackAlloc(size, type) : false) - -#define Q_V4_PROFILE_DEALLOC(engine, size, type) \ - (engine->profiler() &&\ - (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\ - engine->profiler()->trackDealloc(size, type) : false) - -#define Q_V4_PROFILE(engine, context, function, jsFunction)\ - (Q_UNLIKELY(engine->profiler()) &&\ - (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\ - Profiling::FunctionCallProfiler::profileCall(engine->profiler(), context, function, jsFunction) :\ - function->code(context, function, jsFunction)) - QT_BEGIN_NAMESPACE namespace QV4 { @@ -270,19 +251,21 @@ public: // It's enough to ref() the function in the destructor as it will probably not disappear while // it's executing ... - FunctionCallProfiler(Profiler *profiler, Function *function) : - profiler(profiler), function(function), startTime(profiler->m_timer.nsecsElapsed()) - {} - - ~FunctionCallProfiler() + FunctionCallProfiler(ExecutionEngine *engine, Function *f) + : profiler(0) { - profiler->m_data.append(FunctionCall(function, startTime, profiler->m_timer.nsecsElapsed())); + Profiler *p = engine->profiler(); + if (Q_UNLIKELY(p) && (p->featuresEnabled & (1 << Profiling::FeatureFunctionCall))) { + profiler = p; + function = f; + startTime = profiler->m_timer.nsecsElapsed(); + } } - static ReturnedValue profileCall(Profiler *profiler, Heap::ExecutionContext *context, Function *function, const FunctionObject *jsFunction) + ~FunctionCallProfiler() { - FunctionCallProfiler callProfiler(profiler, function); - return function->code(context, function, jsFunction); + if (profiler) + profiler->m_data.append(FunctionCall(function, startTime, profiler->m_timer.nsecsElapsed())); } Profiler *profiler; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index e5db62a749..d3d8c1c291 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -151,12 +151,14 @@ ReturnedValue Script::run() ContextStateSaver stateSaver(valueScope, scope); scope->d()->v4Function = vmFunction; - return Q_V4_PROFILE(engine, scope->d(), vmFunction, 0); + QV4::ScopedCallData cData(scope); + cData->thisObject = engine->globalObject; + return vmFunction->execute(scope->d(), cData); } else { Scoped<QmlContext> qml(valueScope, qmlContext.value()); ScopedCallData callData(valueScope); callData->thisObject = Primitive::undefinedValue(); - return ExecutionContext::call(qml->d(), callData, vmFunction); + return vmFunction->call(qml->d(), callData); } } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 5454356da0..e98d5a7677 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -51,6 +51,7 @@ #include <private/qv4scopedvalue_p.h> #include <private/qv4lookup_p.h> #include <private/qv4string_p.h> +#include <private/qv4profiling_p.h> #include <iostream> #include "qv4alloca_p.h" @@ -413,7 +414,7 @@ static inline const QV4::Value &constant(Function *function, int index) return function->compilationUnit->constants[index]; } -QV4::ReturnedValue VME::exec(Heap::ExecutionContext *context, Function *function, const FunctionObject *jsFunction) +QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callData, Heap::ExecutionContext *context, QV4::Function *function) { qt_v4ResolvePendingBreakpointsHook(); @@ -426,6 +427,12 @@ QV4::ReturnedValue VME::exec(Heap::ExecutionContext *context, Function *function #endif ExecutionEngine *engine = function->internalClass->engine; + Profiling::FunctionCallProfiler(engine, function); + + Value *jsStackTop = engine->jsStackTop; + engine->jsStackTop = reinterpret_cast<QV4::Value *>(callData) + 2 + (int)function->nFormals; + for (int i = callData->argc; i < (int)function->nFormals; ++i) + callData->args[i] = Encode::undefined(); EngineBase::StackFrame frame; frame.parent = engine->currentStackFrame; @@ -435,8 +442,7 @@ QV4::ReturnedValue VME::exec(Heap::ExecutionContext *context, Function *function QV4::Value *stack = nullptr; const uchar *exceptionHandler = 0; - QV4::Scope scope(engine); - stack = scope.alloc(function->compiledFunction->nRegisters + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value)); + stack = engine->jsAlloca(function->compiledFunction->nRegisters + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value)); frame.jsFrame = reinterpret_cast<EngineBase::JSStackFrame *>(stack); frame.jsFrame->context = context; if (jsFunction) @@ -1114,5 +1120,7 @@ functionExit: if (QV4::Debugging::Debugger *debugger = engine->debugger()) debugger->leavingFunction(accumulator.asReturnedValue()); engine->currentStackFrame = frame.parent; + engine->jsStackTop = jsStackTop; + return accumulator.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h index 04efb2cb06..5658459af1 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(Heap::ExecutionContext *context, QV4::Function *, const FunctionObject *jsFunction = 0); + static QV4::ReturnedValue exec(const FunctionObject *jsFunction, CallData *callData, Heap::ExecutionContext *context, QV4::Function *); }; } // namespace Moth diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 614ec46afb..aec85442b3 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -227,7 +227,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b } QV4::ExecutionContext *outer = static_cast<QV4::ExecutionContext *>(m_qmlScope.valueRef()); - result = QV4::ExecutionContext::call(outer->d(), callData, v4Function); + result = v4Function->call(outer->d(), callData); if (scope.hasException()) { if (watcher.wasDeleted()) |