aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-02-27 14:30:09 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-04 15:22:58 +0100
commit186f8e2f76dc6995d14e6632d9b9d704198feda2 (patch)
tree6213cee17297940c46c9ff0a52160a42152d0b4a
parentb02bed1caae6966925b9efb04e1db79c3e9ef687 (diff)
[new compiler] Fix some qqmlincubator tests
We need to track the objects created and pass them over to the VME guard used in the incubator. The incremental build nature of the incubator requires that to avoid crashes. For nested incubators we need to set the activeVMEData field in the root QQmlContext, to allow child incubators to locate the parent. Lastly we need can emulate most of the VME behavior in terms of build states when running with QQmlInstantiationInterrupt by presenting four build steps: The initial state, two build steps, a finalization step and the state when we're done. Change-Id: I16cd7f71744decb9d4735ec77e9d944fad18e88d Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp11
-rw-r--r--src/qml/qml/qqmlcompiler_p.h1
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmlincubator.cpp6
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp47
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h17
-rw-r--r--src/qml/qml/qqmlvme.cpp7
7 files changed, 79 insertions, 12 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 2a8536a065..6dcf15f24e 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -133,9 +133,8 @@ bool QQmlTypeCompiler::compile()
// Build property caches and VME meta object data
- const int objectCount = parsedQML->objects.count();
- compiledData->datas.reserve(objectCount);
- compiledData->propertyCaches.reserve(objectCount);
+ compiledData->datas.reserve(parsedQML->objects.count());
+ compiledData->propertyCaches.reserve(parsedQML->objects.count());
{
QQmlPropertyCacheCreator propertyCacheBuilder(this);
@@ -244,6 +243,7 @@ bool QQmlTypeCompiler::compile()
// Collect some data for instantiation later.
int bindingCount = 0;
int parserStatusCount = 0;
+ int objectCount = 0;
for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
bindingCount += obj->nBindings;
@@ -255,12 +255,15 @@ bool QQmlTypeCompiler::compile()
if (typeRef->component) {
bindingCount += typeRef->component->totalBindingsCount;
parserStatusCount += typeRef->component->totalParserStatusCount;
- }
+ objectCount += typeRef->component->totalObjectCount;
+ } else
+ ++objectCount;
}
}
compiledData->totalBindingsCount = bindingCount;
compiledData->totalParserStatusCount = parserStatusCount;
+ compiledData->totalObjectCount = objectCount;
return errors.isEmpty();
}
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 5a6291afe6..1f28e7a370 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -168,6 +168,7 @@ public:
QVector<int> customParserBindings; // index is binding identifier, value is compiled function index.
int totalBindingsCount; // Number of bindings used in this type
int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
+ int totalObjectCount; // Number of objects explicitly instantiated
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
bool isCompositeType() const { return !datas.at(qmlUnit->indexOfRootObject).isEmpty(); }
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 6fe1377a7e..6431094c4c 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1078,7 +1078,7 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
p->compiledData = d->cc;
p->compiledData->addref();
if (enginePriv->useNewCompiler) {
- p->creator.reset(new QQmlObjectCreator(contextData, d->cc, d->creationContext));
+ p->creator.reset(new QQmlObjectCreator(contextData, d->cc, d->creationContext, p.data()));
p->subComponentToCreate = d->start;
} else
p->vme.init(contextData, d->cc, d->start, d->creationContext);
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index 1cc75387a3..da4de338ee 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -298,7 +298,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
enginePriv->referenceScarceResources();
QObject *tresult = 0;
if (enginePriv->useNewCompiler) {
- tresult = creator->create(subComponentToCreate);
+ tresult = creator->create(subComponentToCreate, /*parent*/0, &i);
if (!tresult)
errors = creator->errors;
} else {
@@ -582,8 +582,12 @@ void QQmlIncubator::clear()
i->clear();
}
+ bool guardOk = d->vmeGuard.isOK();
+
d->vme.reset();
d->vmeGuard.clear();
+ if (d->creator && guardOk)
+ d->creator->clear();
d->creator.reset(0);
Q_ASSERT(d->compiledData == 0);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index e965cab179..8a28fa1211 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -80,11 +80,13 @@ static void removeBindingOnProperty(QObject *o, int index)
if (binding) binding->destroy();
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext)
- : compiledData(compiledData)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext)
+ : phase(Startup)
+ , compiledData(compiledData)
, resolvedTypes(compiledData->resolvedTypes)
, propertyCaches(compiledData->propertyCaches)
, vmeMetaObjectData(compiledData->datas)
+ , activeVMEDataForRootContext(activeVMEDataForRootContext)
{
init(parentContext);
@@ -93,15 +95,18 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
sharedState->componentAttached = 0;
sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount);
sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount);
+ sharedState->allCreatedObjects.allocate(compiledData->totalObjectCount);
sharedState->creationContext = creationContext;
sharedState->rootContext = 0;
}
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState)
- : compiledData(compiledData)
+ : phase(Startup)
+ , compiledData(compiledData)
, resolvedTypes(compiledData->resolvedTypes)
, propertyCaches(compiledData->propertyCaches)
, vmeMetaObjectData(compiledData->datas)
+ , activeVMEDataForRootContext(0)
{
init(parentContext);
@@ -148,8 +153,15 @@ QQmlObjectCreator::~QQmlObjectCreator()
}
}
-QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent)
+QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlInstantiationInterrupt *interrupt)
{
+ if (phase == CreatingObjectsPhase2) {
+ phase = ObjectsCreated;
+ return context->contextObject;
+ }
+ Q_ASSERT(phase == Startup);
+ phase = CreatingObjects;
+
int objectToCreate;
if (subComponentIndex == -1) {
@@ -171,6 +183,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent)
if (!sharedState->rootContext) {
sharedState->rootContext = context;
+ sharedState->rootContext->activeVMEData = activeVMEDataForRootContext;
sharedState->rootContext->isRootObjectInCreation = true;
}
@@ -211,6 +224,13 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent)
context->contextObject = instance;
}
+ phase = CreatingObjectsPhase2;
+
+ if (interrupt && interrupt->shouldInterrupt())
+ return 0;
+
+ phase = ObjectsCreated;
+
return instance;
}
@@ -990,6 +1010,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent)
ddata->rootObjectInCreation = true;
sharedState->rootContext->isRootObjectInCreation = false;
}
+
+ sharedState->allCreatedObjects.push(instance);
} else {
Q_ASSERT(typeRef->component);
if (typeRef->component->qmlUnit->isSingleton())
@@ -1078,6 +1100,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent)
QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
{
+ Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
+ phase = Finalizing;
+
QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data());
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
@@ -1148,9 +1173,23 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
}
}
+ phase = Done;
+
return sharedState->rootContext;
}
+void QQmlObjectCreator::clear()
+{
+ if (phase == Done || phase == Finalizing || phase == Startup)
+ return;
+ Q_ASSERT(phase != Startup);
+
+ while (!sharedState->allCreatedObjects.isEmpty())
+ delete sharedState->allCreatedObjects.pop();
+
+ phase = Done;
+}
+
bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty, bool installPropertyCache, const QBitArray &bindingsToSkip)
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 58cb55e633..cda17fe220 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -61,6 +61,7 @@ struct QQmlObjectCreatorSharedState
QQmlContextData *creationContext;
QFiniteStack<QQmlAbstractBinding*> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
+ QFiniteStack<QObject*> allCreatedObjects;
QQmlComponentAttached *componentAttached;
QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
QRecursionNode recursionNode;
@@ -70,11 +71,12 @@ class QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext);
+ QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext = 0);
~QQmlObjectCreator();
- QObject *create(int subComponentIndex = -1, QObject *parent = 0);
+ QObject *create(int subComponentIndex = -1, QObject *parent = 0, QQmlInstantiationInterrupt *interrupt = 0);
QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
+ void clear();
QQmlComponentAttached **componentAttachment() { return &sharedState->componentAttached; }
@@ -83,6 +85,7 @@ public:
QList<QQmlError> errors;
QQmlContextData *parentContextData() const { return parentContext; }
+ QFiniteStack<QObject*> &allCreatedObjects() const { return sharedState->allCreatedObjects; }
private:
QQmlObjectCreator(QQmlContextData *contextData, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState);
@@ -103,6 +106,15 @@ private:
QString stringAt(int idx) const { return qmlUnit->header.stringAt(idx); }
void recordError(const QV4::CompiledData::Location &location, const QString &description);
+ enum Phase {
+ Startup,
+ CreatingObjects,
+ CreatingObjectsPhase2,
+ ObjectsCreated,
+ Finalizing,
+ Done
+ } phase;
+
QQmlEngine *engine;
QQmlCompiledData *compiledData;
const QV4::CompiledData::QmlUnit *qmlUnit;
@@ -113,6 +125,7 @@ private:
const QVector<QByteArray> &vmeMetaObjectData;
QHash<int, int> objectIndexToId;
QFlagPointer<QQmlObjectCreatorSharedState> sharedState;
+ void *activeVMEDataForRootContext;
QObject *_qobject;
QObject *_scopeObject;
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 24f4a65392..15401e269b 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -1329,6 +1329,13 @@ void QQmlVMEGuard::guard(QQmlVME *vme)
void QQmlVMEGuard::guard(QQmlObjectCreator *creator)
{
clear();
+
+ QFiniteStack<QObject*> &objects = creator->allCreatedObjects();
+ m_objectCount = objects.count();
+ m_objects = new QPointer<QObject>[m_objectCount];
+ for (int ii = 0; ii < m_objectCount; ++ii)
+ m_objects[ii] = objects[ii];
+
m_contextCount = 1;
m_contexts = new QQmlGuardedContextData[m_contextCount];
m_contexts[0] = creator->parentContextData();