diff options
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 21 | ||||
-rw-r--r-- | src/qml/qml/ftw/qfinitestack_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompileddata.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 114 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 15 |
6 files changed, 100 insertions, 57 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 4466b430fe..dae57fe6f4 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -244,6 +244,27 @@ bool QQmlTypeCompiler::compile() if (!validator.validate()) return false; + // Collect some data for instantiation later. + int bindingCount = 0; + int parserStatusCount = 0; + for (quint32 i = 0; i < qmlUnit->nObjects; ++i) { + const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i); + bindingCount += obj->nBindings; + if (QQmlCompiledData::TypeReference *typeRef = compiledData->resolvedTypes.value(obj->inheritedTypeNameIndex)) { + if (QQmlType *qmlType = typeRef->type) { + if (qmlType->parserStatusCast() != -1) + ++parserStatusCount; + } + if (typeRef->component) { + bindingCount += typeRef->component->totalBindingsCount; + parserStatusCount += typeRef->component->totalParserStatusCount; + } + } + } + + compiledData->totalBindingsCount = bindingCount; + compiledData->totalParserStatusCount = parserStatusCount; + return errors.isEmpty(); } diff --git a/src/qml/qml/ftw/qfinitestack_p.h b/src/qml/qml/ftw/qfinitestack_p.h index 31a530fa64..6bfd353771 100644 --- a/src/qml/qml/ftw/qfinitestack_p.h +++ b/src/qml/qml/ftw/qfinitestack_p.h @@ -114,6 +114,7 @@ T &QFiniteStack<T>::top() template<typename T> void QFiniteStack<T>::push(const T &o) { + Q_ASSERT(_size < _alloc); if (QTypeInfo<T>::isComplex) { new (_array + _size++) T(o); } else { @@ -124,6 +125,7 @@ void QFiniteStack<T>::push(const T &o) template<typename T> T QFiniteStack<T>::pop() { + Q_ASSERT(_size > 0); --_size; if (QTypeInfo<T>::isComplex) { diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp index 05ec0ab9c7..75740e17e6 100644 --- a/src/qml/qml/qqmlcompileddata.cpp +++ b/src/qml/qml/qqmlcompileddata.cpp @@ -88,7 +88,7 @@ int QQmlCompiledData::indexForUrl(const QUrl &data) QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine) : engine(engine), importCache(0), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false), - rootPropertyCache(0), compilationUnit(0), qmlUnit(0) + rootPropertyCache(0), compilationUnit(0), qmlUnit(0), totalBindingsCount(0), totalParserStatusCount(0) { Q_ASSERT(engine); diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index c63f430b0a..2ce850da5d 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -85,6 +85,7 @@ class QQmlComponent; class QQmlContext; class QQmlContextData; +// ### Merge with QV4::CompiledData::CompilationUnit class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup { public: @@ -161,6 +162,8 @@ public: // hash key is object index QHash<int, QByteArray> customParserData; 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 bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); } bool isCompositeType() const { return !datas.at(qmlUnit->indexOfRootObject).isEmpty(); } diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 38edfc0360..2b69955dde 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -80,7 +80,8 @@ static void removeBindingOnProperty(QObject *o, int index) if (binding) binding->destroy(); } -QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, QQmlContextData *rootContext) +QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, QQmlContextData *rootContext, + QFiniteStack<QQmlAbstractBinding *> *inheritedBindingStack, QFiniteStack<QQmlParserStatus *> *inheritedParserStatusStack) : componentAttached(0) , url(compiledData->url) , engine(parentContext->engine) @@ -92,6 +93,9 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledD , resolvedTypes(compiledData->resolvedTypes) , propertyCaches(compiledData->propertyCaches) , vmeMetaObjectData(compiledData->datas) + , allCreatedBindings(0) + , allParserStatusCallbacks(0) + , ownBindingAndParserStatusStacks(false) , compiledData(compiledData) , rootContext(rootContext) , _qobject(0) @@ -105,12 +109,48 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledD { if (!compiledData->isInitialized()) compiledData->initialize(engine); + + if (inheritedBindingStack) { + Q_ASSERT(rootContext); + Q_ASSERT(inheritedParserStatusStack); + allCreatedBindings = inheritedBindingStack; + allParserStatusCallbacks = inheritedParserStatusStack; + ownBindingAndParserStatusStacks = false; + } else { + ownBindingAndParserStatusStacks = true; + allCreatedBindings = new QFiniteStack<QQmlAbstractBinding*>; + allCreatedBindings->allocate(compiledData->totalBindingsCount); + allParserStatusCallbacks = new QFiniteStack<QQmlParserStatus*>; + allParserStatusCallbacks->allocate(compiledData->totalParserStatusCount); + } +} + +QmlObjectCreator::~QmlObjectCreator() +{ + if (ownBindingAndParserStatusStacks) { + for (int i = 0; i < allCreatedBindings->count(); ++i) { + QQmlAbstractBinding *b = allCreatedBindings->at(i); + if (b) + b->m_mePtr = 0; + } + for (int i = 0; i < allParserStatusCallbacks->count(); ++i) { + QQmlParserStatus *ps = allParserStatusCallbacks->at(i); + if (ps) + ps->d = 0; + } + + delete allCreatedBindings; + delete allParserStatusCallbacks; + } } QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent) { int objectToCreate; + Q_ASSERT(!ownBindingAndParserStatusStacks || allCreatedBindings->isEmpty()); + Q_ASSERT(!ownBindingAndParserStatusStacks || allParserStatusCallbacks->isEmpty()); + if (subComponentIndex == -1) { objectIndexToId = compiledData->objectIndexToIdForRoot; objectToCreate = qmlUnit->indexOfRootObject; @@ -158,10 +198,6 @@ QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent) context->importedScripts = creationContext->importedScripts; } - QVector<QQmlParserStatus*> parserStatusCallbacks; - parserStatusCallbacks.resize(qmlUnit->nObjects); - qSwap(_parserStatusCallbacks, parserStatusCallbacks); - QObject *instance = createInstance(objectToCreate, parent); if (instance) { QQmlData *ddata = QQmlData::get(instance); @@ -172,9 +208,6 @@ QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent) context->contextObject = instance; } - qSwap(_parserStatusCallbacks, parserStatusCallbacks); - allParserStatusCallbacks.prepend(parserStatusCallbacks); - return instance; } @@ -602,14 +635,14 @@ void QmlObjectCreator::setupBindings() } - if (!setPropertyValue(property, i, binding)) + if (!setPropertyBinding(property, binding)) return; } qSwap(_currentList, savedList); } -bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingIndex, const QV4::CompiledData::Binding *binding) +bool QmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) { if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty()); @@ -747,8 +780,8 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI qmlBinding->addToObject(); } - _createdBindings[bindingIndex] = qmlBinding; - qmlBinding->m_mePtr = &_createdBindings[bindingIndex]; + allCreatedBindings->push(qmlBinding); + qmlBinding->m_mePtr = &allCreatedBindings->top(); } return true; } @@ -940,7 +973,7 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex))); return 0; } - QmlObjectCreator subCreator(context, typeRef->component, creationContext, rootContext); + QmlObjectCreator subCreator(context, typeRef->component, creationContext, rootContext, allCreatedBindings, allParserStatusCallbacks); instance = subCreator.create(); if (!instance) { errors += subCreator.errors; @@ -948,8 +981,6 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) } if (subCreator.componentAttached) subCreator.componentAttached->add(&componentAttached); - allCreatedBindings << subCreator.allCreatedBindings; - allParserStatusCallbacks << subCreator.allParserStatusCallbacks; } // ### use no-event variant if (parent) @@ -976,8 +1007,8 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) if (parserStatus) { parserStatus->classBegin(); - _parserStatusCallbacks[index] = parserStatus; - parserStatus->d = &_parserStatusCallbacks[index]; + allParserStatusCallbacks->push(parserStatus); + parserStatus->d = &allParserStatusCallbacks->top(); } QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(index); @@ -1023,45 +1054,34 @@ QQmlContextData *QmlObjectCreator::finalize() QQmlTrace trace("VME Binding Enable"); trace.event("begin binding eval"); - Q_ASSERT(allCreatedBindings.isEmpty() || allCreatedBindings.isDetached()); - - for (QLinkedList<QVector<QQmlAbstractBinding*> >::Iterator it = allCreatedBindings.begin(), end = allCreatedBindings.end(); - it != end; ++it) { - const QVector<QQmlAbstractBinding *> &bindings = *it; - for (int i = 0; i < bindings.count(); ++i) { - QQmlAbstractBinding *b = bindings.at(i); - if (!b) - continue; - b->m_mePtr = 0; - QQmlData *data = QQmlData::get(b->object()); - Q_ASSERT(data); - data->clearPendingBindingBit(b->propertyIndex()); - b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor | - QQmlPropertyPrivate::DontRemoveBinding); - } + while (!allCreatedBindings->isEmpty()) { + QQmlAbstractBinding *b = allCreatedBindings->pop(); + if (!b) + continue; + b->m_mePtr = 0; + QQmlData *data = QQmlData::get(b->object()); + Q_ASSERT(data); + data->clearPendingBindingBit(b->propertyIndex()); + b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor | + QQmlPropertyPrivate::DontRemoveBinding); } } if (true /* ### componentCompleteEnabled()*/) { // the qml designer does the component complete later QQmlTrace trace("VME Component Complete"); - for (QLinkedList<QVector<QQmlParserStatus*> >::ConstIterator it = allParserStatusCallbacks.constBegin(), end = allParserStatusCallbacks.constEnd(); - it != end; ++it) { - const QVector<QQmlParserStatus *> &parserStatusCallbacks = *it; - for (int i = parserStatusCallbacks.count() - 1; i >= 0; --i) { - QQmlParserStatus *status = parserStatusCallbacks.at(i); - - if (status && status->d) { - status->d = 0; - status->componentComplete(); - } + while (!allParserStatusCallbacks->isEmpty()) { + QQmlParserStatus *status = allParserStatusCallbacks->pop(); + + if (status && status->d) { + status->d = 0; + status->componentComplete(); + } #if 0 // ### if (watcher.hasRecursed() || interrupt.shouldInterrupt()) return 0; #endif - } } - allParserStatusCallbacks.clear(); } { @@ -1135,14 +1155,10 @@ bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPoi qSwap(_vmeMetaObject, vmeMetaObject); QVector<QQmlAbstractBinding*> createdBindings(_compiledObject->nBindings, 0); - qSwap(_createdBindings, createdBindings); setupFunctions(); setupBindings(); - allCreatedBindings.append(_createdBindings); - - qSwap(_createdBindings, createdBindings); qSwap(_vmeMetaObject, vmeMetaObject); qSwap(_bindingTarget, bindingTarget); qSwap(_ddata, declarativeData); diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index e5fe4e3b81..cb23f61c84 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -46,7 +46,7 @@ #include <private/qv4compileddata_p.h> #include <private/qqmlcompiler_p.h> #include <private/qqmltypecompiler_p.h> -#include <QLinkedList> +#include <private/qfinitestack_p.h> QT_BEGIN_NAMESPACE @@ -57,7 +57,9 @@ class QmlObjectCreator { Q_DECLARE_TR_FUNCTIONS(QmlObjectCreator) public: - QmlObjectCreator(QQmlContextData *contextData, QQmlCompiledData *compiledData, QQmlContextData *creationContext, QQmlContextData *rootContext = 0); + QmlObjectCreator(QQmlContextData *contextData, QQmlCompiledData *compiledData, QQmlContextData *creationContext, QQmlContextData *rootContext = 0, + QFiniteStack<QQmlAbstractBinding*> *inheritedBindingStack = 0, QFiniteStack<QQmlParserStatus*> *inheritedParserStatusStack = 0); + ~QmlObjectCreator(); QObject *create(int subComponentIndex = -1, QObject *parent = 0); QQmlContextData *finalize(); @@ -73,7 +75,7 @@ private: bool populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty); void setupBindings(); - bool setPropertyValue(QQmlPropertyData *property, int index, const QV4::CompiledData::Binding *binding); + bool setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); void setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); void setupFunctions(); @@ -91,8 +93,9 @@ private: const QVector<QQmlPropertyCache *> propertyCaches; const QVector<QByteArray> vmeMetaObjectData; QHash<int, int> objectIndexToId; - QLinkedList<QVector<QQmlAbstractBinding*> > allCreatedBindings; - QLinkedList<QVector<QQmlParserStatus*> > allParserStatusCallbacks; + QFiniteStack<QQmlAbstractBinding*> *allCreatedBindings; + QFiniteStack<QQmlParserStatus*> *allParserStatusCallbacks; + bool ownBindingAndParserStatusStacks; QQmlCompiledData *compiledData; QQmlContextData *rootContext; @@ -105,10 +108,8 @@ private: QQmlData *_ddata; QQmlRefPointer<QQmlPropertyCache> _propertyCache; QQmlVMEMetaObject *_vmeMetaObject; - QVector<QQmlAbstractBinding*> _createdBindings; QQmlListProperty<void> _currentList; QV4::ExecutionContext *_qmlContext; - QVector<QQmlParserStatus*> _parserStatusCallbacks; }; QT_END_NAMESPACE |