aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2016-06-22 10:12:13 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2016-06-22 11:07:05 +0000
commit702c4247d74ffb7e4fb1aaca96d70f4591203ba2 (patch)
tree6c0a41332cf4a8ab0051600efdd27b0746574795 /src/qml/qml
parentfd0e3c6d569a7410fff33974ce9f908dc2de0e22 (diff)
V4: Pass scope around as parameters inside the runtime.
The implementation of many (or all) runtime functions consist of first creating a QV4::Scope, which saves and restores the JS stack pointer. It also prevents tail-calls because of that restoring behavior. In many cases it suffices to do that at the entry-point of the runtime. The return value of a JS function call is now also stored in the scope. Previously, all return values were stored in a ScopedValue, got loaded on return, and immediately stored in another ScopedValue in the caller. This resulted in a lot of stores, where now there is only one store needed, and no extra ScopedValue for every function. Change-Id: I13d80fc0ce72c5702ef1536d41d12f710c5914fa Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlbinding.cpp10
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp4
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp2
-rw-r--r--src/qml/qml/qqmlexpression.cpp9
-rw-r--r--src/qml/qml/qqmlexpression_p.h2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp24
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h5
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp5
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp17
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp5
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h2
12 files changed, 39 insertions, 48 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index eacb928901..3940176107 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -189,11 +189,12 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
bool isUndefined = false;
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
+ QV4::ScopedCallData callData(scope);
+ QQmlJavaScriptExpression::evaluate(callData, &isUndefined, scope);
bool error = false;
if (!watcher.wasDeleted() && isAddedToObject() && !hasError())
- error = !write(pd, result, isUndefined, flags);
+ error = !write(pd, scope.result, isUndefined, flags);
if (!watcher.wasDeleted()) {
@@ -377,11 +378,12 @@ QVariant QQmlBinding::evaluate()
bool isUndefined = false;
QV4::Scope scope(ep->v4engine());
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
+ QV4::ScopedCallData callData(scope);
+ QQmlJavaScriptExpression::evaluate(callData, &isUndefined, scope);
ep->dereferenceScarceResources();
- return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
+ return scope.engine->toVariant(scope.result, qMetaTypeId<QList<QObject*> >());
}
QString QQmlBinding::expressionIdentifier()
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 7d6e1ffa1a..e3c4464584 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -234,7 +234,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
}
}
- QQmlJavaScriptExpression::evaluate(callData, 0);
+ QQmlJavaScriptExpression::evaluate(callData, 0, scope);
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
@@ -256,7 +256,7 @@ void QQmlBoundSignalExpression::evaluate(const QList<QVariant> &args)
callData->args[ii] = scope.engine->fromVariant(args[ii]);
}
- QQmlJavaScriptExpression::evaluate(callData, 0);
+ QQmlJavaScriptExpression::evaluate(callData, 0, scope);
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 52f6837842..854090f20b 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1527,7 +1527,7 @@ void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
QV4::ScopedCallData callData(scope, 1);
callData->thisObject = this;
callData->args[0] = QV4::Primitive::fromUInt32(s);
- f->call(callData);
+ f->call(scope, callData);
if (scope.hasException()) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error);
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index b3a0baffb4..d10a8c7718 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -74,7 +74,7 @@ void QQmlDelayedCallQueue::DelayedFunctionCall::execute(QV4::ExecutionEngine *en
const QV4::FunctionObject *callback = m_function.as<QV4::FunctionObject>();
Q_ASSERT(callback);
- callback->call(callData);
+ callback->call(scope, callData);
if (scope.engine->hasException) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index d48b6ad1d3..6afbd05e3e 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -245,14 +245,15 @@ void QQmlExpression::setExpression(const QString &expression)
}
// Must be called with a valid handle scope
-QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined)
+void QQmlExpressionPrivate::v4value(bool *isUndefined, QV4::Scope &scope)
{
if (!expressionFunctionValid) {
createQmlBinding(context(), scopeObject(), expression, url, line);
expressionFunctionValid = true;
}
- return evaluate(isUndefined);
+ QV4::ScopedCallData callData(scope);
+ evaluate(callData, isUndefined, scope);
}
QVariant QQmlExpressionPrivate::value(bool *isUndefined)
@@ -271,9 +272,9 @@ QVariant QQmlExpressionPrivate::value(bool *isUndefined)
{
QV4::Scope scope(QV8Engine::getV4(ep->v8engine()));
- QV4::ScopedValue result(scope, v4value(isUndefined));
+ v4value(isUndefined, scope);
if (!hasError())
- rv = scope.engine->toVariant(result, -1);
+ rv = scope.engine->toVariant(scope.result, -1);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index ccc629a3a3..741c25e206 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -76,7 +76,7 @@ public:
QVariant value(bool *isUndefined = 0);
- QV4::ReturnedValue v4value(bool *isUndefined = 0);
+ void v4value(bool *isUndefined, QV4::Scope &scope);
static inline QQmlExpressionPrivate *get(QQmlExpression *expr);
static inline QQmlExpression *get(QQmlExpressionPrivate *expr);
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 8ba4b5eba1..eff1a6e039 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -147,16 +147,9 @@ void QQmlJavaScriptExpression::refresh()
{
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
-{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_context->engine);
- QV4::Scope scope(v4);
- QV4::ScopedCallData callData(scope);
- return evaluate(callData, isUndefined);
-}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
+void QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined, QV4::Scope &scope)
{
Q_ASSERT(m_context && m_context->engine);
@@ -164,7 +157,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
if (!f || f->isUndefined()) {
if (isUndefined)
*isUndefined = true;
- return QV4::Encode::undefined();
+ return;
}
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine);
@@ -184,8 +177,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
capture.guards.copyAndClearPrepend(activeGuards);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
- QV4::Scope scope(v4);
- QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
+ scope.result = QV4::Primitive::undefinedValue();
callData->thisObject = v4->globalObject;
if (scopeObject()) {
QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject()));
@@ -193,7 +185,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
callData->thisObject = value;
}
- result = f->as<QV4::FunctionObject>()->call(callData);
+ f->as<QV4::FunctionObject>()->call(scope, callData);
if (scope.hasException()) {
if (watcher.wasDeleted())
scope.engine->catchException(); // ignore exception
@@ -203,7 +195,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
*isUndefined = true;
} else {
if (isUndefined)
- *isUndefined = result->isUndefined();
+ *isUndefined = scope.result.isUndefined();
if (!watcher.wasDeleted() && hasDelayedError())
delayedError()->clearError();
@@ -220,8 +212,6 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
g->Delete();
ep->propertyCapture = lastPropertyCapture;
-
- return result->asReturnedValue();
}
void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
@@ -294,11 +284,12 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n)
}
}
-void QQmlPropertyCapture::registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
+void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Function *compiledFunction, const QV4::Scope &scope)
{
// Let the caller check and avoid the function call :)
Q_ASSERT(compiledFunction->hasQmlDependencies());
+ QV4::ExecutionEngine *engine = scope.engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine());
if (!ep)
return;
@@ -306,7 +297,6 @@ void QQmlPropertyCapture::registerQmlDependencies(QV4::ExecutionEngine *engine,
if (!capture)
return;
- QV4::Scope scope(engine);
QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext());
QQmlContextData *qmlContext = context->qmlContext();
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 94479f6c5e..4472a643ff 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -103,8 +103,7 @@ public:
virtual QString expressionIdentifier() = 0;
virtual void expressionChanged() = 0;
- QV4::ReturnedValue evaluate(bool *isUndefined);
- QV4::ReturnedValue evaluate(QV4::CallData *callData, bool *isUndefined);
+ void evaluate(QV4::CallData *callData, bool *isUndefined, QV4::Scope &scope);
inline bool notifyOnValueChanged() const;
@@ -181,7 +180,7 @@ public:
void captureProperty(QQmlNotifier *);
void captureProperty(QObject *, int, int);
- static void registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
+ static void registerQmlDependencies(const QV4::CompiledData::Function *compiledFunction, const QV4::Scope &scope);
QQmlEngine *engine;
QQmlJavaScriptExpression *expression;
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 6907b26cd8..a9aec4cded 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -945,15 +945,14 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
for (uint ii = 0; ii < parameterCount; ++ii)
callData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]);
- QV4::ScopedValue result(scope);
- result = function->call(callData);
+ function->call(scope, callData);
if (scope.hasException()) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
if (error.isValid())
ep->warning(error);
if (a[0]) *(QVariant *)a[0] = QVariant();
} else {
- if (a[0]) *(QVariant *)a[0] = scope.engine->toVariant(result, 0);
+ if (a[0]) *(QVariant *)a[0] = scope.engine->toVariant(scope.result, 0);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index e2784103b0..74de30c96c 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1560,7 +1560,7 @@ void QQmlXMLHttpRequest::dispatchCallback(Object *thisObj, QQmlContextData *cont
QV4::ScopedCallData callData(scope);
callData->thisObject = Encode::undefined();
- callback->call(callData);
+ callback->call(scope, callData);
if (scope.engine->hasException) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
@@ -1621,22 +1621,23 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
c->proto->mark(e);
FunctionObject::markObjects(that, e);
}
- static ReturnedValue construct(const Managed *that, QV4::CallData *)
+ static void construct(const Managed *that, Scope &scope, QV4::CallData *)
{
- Scope scope(static_cast<const QQmlXMLHttpRequestCtor *>(that)->engine());
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>());
- if (!ctor)
- return scope.engine->throwTypeError();
+ if (!ctor) {
+ scope.result = scope.engine->throwTypeError();
+ return;
+ }
QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager());
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototype(proto);
- return w.asReturnedValue();
+ scope.result = w.asReturnedValue();
}
- static ReturnedValue call(const Managed *, QV4::CallData *) {
- return Primitive::undefinedValue().asReturnedValue();
+ static void call(const Managed *, Scope &scope, QV4::CallData *) {
+ scope.result = Primitive::undefinedValue();
}
void setupProto();
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 482da31779..a0dff482b1 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1285,11 +1285,10 @@ void QQmlBindingFunction::initBindingLocation()
d()->bindingLocation.line = frame.line;
}
-ReturnedValue QQmlBindingFunction::call(const Managed *that, CallData *callData)
+void QQmlBindingFunction::call(const Managed *that, Scope &scope, CallData *callData)
{
- Scope scope(static_cast<const QQmlBindingFunction*>(that)->engine());
ScopedFunctionObject function(scope, static_cast<const QQmlBindingFunction*>(that)->d()->originalFunction);
- return function->call(callData);
+ function->call(scope, callData);
}
void QQmlBindingFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 5404ab3616..d29983c476 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -188,7 +188,7 @@ struct QQmlBindingFunction : public QV4::FunctionObject
void initBindingLocation(); // from caller stack trace
- static ReturnedValue call(const Managed *that, CallData *callData);
+ static void call(const Managed *that, Scope &scope, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};