aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-09 16:02:55 +0200
committerLars Knoll <lars.knoll@qt.io>2017-08-10 08:19:59 +0000
commit6a91dcba2e4fa85dc345c2d403c757ab7676e28c (patch)
tree502b483cd437f4a1a039717af0a59e493d40f7a2
parent5571b666e6b9534a55347adcd249fa07b2e25c01 (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.cpp29
-rw-r--r--src/qml/jsruntime/qv4context_p.h2
-rw-r--r--src/qml/jsruntime/qv4function.cpp24
-rw-r--r--src/qml/jsruntime/qv4function_p.h12
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h39
-rw-r--r--src/qml/jsruntime/qv4script.cpp6
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp14
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp2
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())