From: Simon Hausmann Date: Fri, 14 Aug 2015 00:57:45 +0000 (+0200) Subject: Avoid firing up the JS parser/JIT/interpreter when instantiating objects X-Git-Tag: v5.5.90+alpha1~65 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=94e337fa95425d259e81b4d21f4d0853108553bd;p=platform%2Fupstream%2Fqtdeclarative.git Avoid firing up the JS parser/JIT/interpreter when instantiating objects For setting the initial properties there's no need to run a JavaScript function. Change-Id: I129fa8e7128cd7aa784e34912ce636cd33b1dd66 Reviewed-by: Lars Knoll --- diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index c511c8116..d62aada9c 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -62,23 +63,6 @@ #include #include "qqmlmemoryprofiler_p.h" -#define INITIALPROPERTIES_SOURCE \ - "(function(object, values) {"\ - "try {"\ - "for (var property in values) {" \ - "try {"\ - "var properties = property.split(\".\");"\ - "var o = object;"\ - "for (var ii = 0; ii < properties.length - 1; ++ii) {"\ - "o = o[properties[ii]];"\ - "}"\ - "o[properties[properties.length - 1]] = values[property];"\ - "} catch(e) {}"\ - "}"\ - "} catch(e) {}"\ - "})" - - namespace { QThreadStorage creationDepth; } @@ -1195,6 +1179,46 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent) \sa incubateObject() */ + +static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value &o, const QV4::Value &v) +{ + QV4::Scope scope(engine); + QV4::ScopedObject object(scope); + QV4::ScopedObject valueMap(scope, v); + QV4::ObjectIterator it(scope, valueMap, QV4::ObjectIterator::EnumerableOnly|QV4::ObjectIterator::WithProtoChain); + QV4::ScopedString name(scope); + QV4::ScopedValue val(scope); + if (engine->hasException) + return; + + while (1) { + name = it.nextPropertyNameAsString(val); + if (!name) + break; + object = o; + const QStringList properties = name->toQString().split(QLatin1Char('.')); + for (int i = 0; i < properties.length() - 1; ++i) { + name = engine->newString(properties.at(i)); + object = object->get(name); + if (engine->hasException || !object) { + break; + } + } + if (engine->hasException || !object) { + engine->hasException = false; + continue; + } + name = engine->newString(properties.last()); + object->put(name, val); + if (engine->hasException) { + engine->hasException = false; + continue; + } + } + + engine->hasException = false; +} + /*! \internal */ @@ -1240,16 +1264,8 @@ void QQmlComponent::createObject(QQmlV4Function *args) QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv)); Q_ASSERT(object->isObject()); - if (!valuemap->isUndefined()) { - QV4::ScopedObject qmlglobal(scope, args->qmlGlobal()); - QV4::ScopedValue f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal)); - Q_ASSERT(f->as()); - QV4::ScopedCallData callData(scope, 2); - callData->thisObject = v4->globalObject; - callData->args[0] = object; - callData->args[1] = valuemap; - f->as()->call(callData); - } + if (!valuemap->isUndefined()) + setInitialProperties(v4, object, valuemap); d->completeCreate(); @@ -1381,7 +1397,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) } // XXX used by QSGLoader -void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate) +void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate) { QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine()); @@ -1390,16 +1406,8 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate)); Q_ASSERT(object->as()); - if (!valuemap.isUndefined()) { - QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal); - QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4engine, - QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj)); - QV4::ScopedCallData callData(scope, 2); - callData->thisObject = v4engine->globalObject; - callData->args[0] = object; - callData->args[1] = valuemap; - f->call(callData); - } + if (!valuemap.isUndefined()) + setInitialProperties(v4engine, object, valuemap); } QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4) @@ -1489,13 +1497,8 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o) if (!d()->valuemap.isUndefined()) { QV4::ExecutionEngine *v4 = engine(); QV4::Scope scope(v4); - - QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.as())); - QV4::ScopedCallData callData(scope, 2); - callData->thisObject = v4->globalObject; - callData->args[0] = QV4::QObjectWrapper::wrap(v4, o); - callData->args[1] = d()->valuemap; - f->call(callData); + QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o)); + setInitialProperties(v4, obj, d()->valuemap); } } diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index adc6e173d..15ec88dd5 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -82,7 +82,7 @@ public: QObject *beginCreate(QQmlContextData *); void completeCreate(); - void initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate); + void initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate); QQmlTypeData *typeData; virtual void typeDataReady(QQmlTypeData *); diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index df0978089..d46e25d25 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -576,7 +576,6 @@ void QQuickLoader::setSource(QQmlV4Function *args) if (!ipv->isUndefined()) { d->disposeInitialPropertyValues(); d->initialPropertyValues.set(args->v4engine(), ipv); - d->qmlGlobalForIpv.set(args->v4engine(), args->qmlGlobal()); } setSource(sourceUrl, false); // already cleared and set ipv above. @@ -642,11 +641,11 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj) QQmlComponentPrivate *d = QQmlComponentPrivate::get(component); Q_ASSERT(d && d->engine); - QV4::ExecutionEngine *v4 = qmlGlobalForIpv.engine(); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(d->engine); Q_ASSERT(v4); QV4::Scope scope(v4); QV4::ScopedValue ipv(scope, initialPropertyValues.value()); - d->initializeObjectWithInitialProperties(*qmlGlobalForIpv.valueRef(), ipv, obj); + d->initializeObjectWithInitialProperties(ipv, obj); } void QQuickLoaderIncubator::statusChanged(Status status) diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index fb1263f0b..9677318b5 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -102,7 +102,6 @@ public: QQmlContext *itemContext; QQuickLoaderIncubator *incubator; QV4::PersistentValue initialPropertyValues; - QV4::PersistentValue qmlGlobalForIpv; bool updatingSize: 1; bool active : 1; bool loadingFromSource : 1;