aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp21
-rw-r--r--src/qml/qml/ftw/qfinitestack_p.h2
-rw-r--r--src/qml/qml/qqmlcompileddata.cpp2
-rw-r--r--src/qml/qml/qqmlcompiler_p.h3
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp114
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h15
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