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 <lars.knoll@theqtcompany.com>
This commit is contained in:
parent
26a230ee0e
commit
94e337fa95
|
@ -54,6 +54,7 @@
|
||||||
#include <private/qv4functionobject_p.h>
|
#include <private/qv4functionobject_p.h>
|
||||||
#include <private/qv4script_p.h>
|
#include <private/qv4script_p.h>
|
||||||
#include <private/qv4scopedvalue_p.h>
|
#include <private/qv4scopedvalue_p.h>
|
||||||
|
#include <private/qv4objectiterator_p.h>
|
||||||
|
|
||||||
#include <QStack>
|
#include <QStack>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
@ -62,23 +63,6 @@
|
||||||
#include <qqmlinfo.h>
|
#include <qqmlinfo.h>
|
||||||
#include "qqmlmemoryprofiler_p.h"
|
#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 {
|
namespace {
|
||||||
QThreadStorage<int> creationDepth;
|
QThreadStorage<int> creationDepth;
|
||||||
}
|
}
|
||||||
|
@ -1195,6 +1179,46 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
|
||||||
\sa incubateObject()
|
\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
|
\internal
|
||||||
*/
|
*/
|
||||||
|
@ -1240,16 +1264,8 @@ void QQmlComponent::createObject(QQmlV4Function *args)
|
||||||
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv));
|
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv));
|
||||||
Q_ASSERT(object->isObject());
|
Q_ASSERT(object->isObject());
|
||||||
|
|
||||||
if (!valuemap->isUndefined()) {
|
if (!valuemap->isUndefined())
|
||||||
QV4::ScopedObject qmlglobal(scope, args->qmlGlobal());
|
setInitialProperties(v4, object, valuemap);
|
||||||
QV4::ScopedValue f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal));
|
|
||||||
Q_ASSERT(f->as<QV4::FunctionObject>());
|
|
||||||
QV4::ScopedCallData callData(scope, 2);
|
|
||||||
callData->thisObject = v4->globalObject;
|
|
||||||
callData->args[0] = object;
|
|
||||||
callData->args[1] = valuemap;
|
|
||||||
f->as<QV4::FunctionObject>()->call(callData);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->completeCreate();
|
d->completeCreate();
|
||||||
|
|
||||||
|
@ -1381,7 +1397,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX used by QSGLoader
|
// 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);
|
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
|
||||||
QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine());
|
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));
|
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate));
|
||||||
Q_ASSERT(object->as<QV4::Object>());
|
Q_ASSERT(object->as<QV4::Object>());
|
||||||
|
|
||||||
if (!valuemap.isUndefined()) {
|
if (!valuemap.isUndefined())
|
||||||
QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal);
|
setInitialProperties(v4engine, object, valuemap);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
|
QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
|
||||||
|
@ -1489,13 +1497,8 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
|
||||||
if (!d()->valuemap.isUndefined()) {
|
if (!d()->valuemap.isUndefined()) {
|
||||||
QV4::ExecutionEngine *v4 = engine();
|
QV4::ExecutionEngine *v4 = engine();
|
||||||
QV4::Scope scope(v4);
|
QV4::Scope scope(v4);
|
||||||
|
QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
|
||||||
QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.as<Object>()));
|
setInitialProperties(v4, obj, d()->valuemap);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
|
|
||||||
QObject *beginCreate(QQmlContextData *);
|
QObject *beginCreate(QQmlContextData *);
|
||||||
void completeCreate();
|
void completeCreate();
|
||||||
void initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate);
|
void initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate);
|
||||||
|
|
||||||
QQmlTypeData *typeData;
|
QQmlTypeData *typeData;
|
||||||
virtual void typeDataReady(QQmlTypeData *);
|
virtual void typeDataReady(QQmlTypeData *);
|
||||||
|
|
|
@ -576,7 +576,6 @@ void QQuickLoader::setSource(QQmlV4Function *args)
|
||||||
if (!ipv->isUndefined()) {
|
if (!ipv->isUndefined()) {
|
||||||
d->disposeInitialPropertyValues();
|
d->disposeInitialPropertyValues();
|
||||||
d->initialPropertyValues.set(args->v4engine(), ipv);
|
d->initialPropertyValues.set(args->v4engine(), ipv);
|
||||||
d->qmlGlobalForIpv.set(args->v4engine(), args->qmlGlobal());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSource(sourceUrl, false); // already cleared and set ipv above.
|
setSource(sourceUrl, false); // already cleared and set ipv above.
|
||||||
|
@ -642,11 +641,11 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
|
||||||
|
|
||||||
QQmlComponentPrivate *d = QQmlComponentPrivate::get(component);
|
QQmlComponentPrivate *d = QQmlComponentPrivate::get(component);
|
||||||
Q_ASSERT(d && d->engine);
|
Q_ASSERT(d && d->engine);
|
||||||
QV4::ExecutionEngine *v4 = qmlGlobalForIpv.engine();
|
QV4::ExecutionEngine *v4 = QV8Engine::getV4(d->engine);
|
||||||
Q_ASSERT(v4);
|
Q_ASSERT(v4);
|
||||||
QV4::Scope scope(v4);
|
QV4::Scope scope(v4);
|
||||||
QV4::ScopedValue ipv(scope, initialPropertyValues.value());
|
QV4::ScopedValue ipv(scope, initialPropertyValues.value());
|
||||||
d->initializeObjectWithInitialProperties(*qmlGlobalForIpv.valueRef(), ipv, obj);
|
d->initializeObjectWithInitialProperties(ipv, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQuickLoaderIncubator::statusChanged(Status status)
|
void QQuickLoaderIncubator::statusChanged(Status status)
|
||||||
|
|
|
@ -102,7 +102,6 @@ public:
|
||||||
QQmlContext *itemContext;
|
QQmlContext *itemContext;
|
||||||
QQuickLoaderIncubator *incubator;
|
QQuickLoaderIncubator *incubator;
|
||||||
QV4::PersistentValue initialPropertyValues;
|
QV4::PersistentValue initialPropertyValues;
|
||||||
QV4::PersistentValue qmlGlobalForIpv;
|
|
||||||
bool updatingSize: 1;
|
bool updatingSize: 1;
|
||||||
bool active : 1;
|
bool active : 1;
|
||||||
bool loadingFromSource : 1;
|
bool loadingFromSource : 1;
|
||||||
|
|
Loading…
Reference in New Issue