commit cfd25f0b1a30b21bc37348ff95aad5e48f3700e8
Author: David McFarland <corngood@gmail.com>
Date:   Thu Aug 15 22:28:30 2013 -0300

    first attempt at breaking cycles in qml
    
    Change-Id: I256ae23c63e1c79f3b5fa6c35ba3091706ef8b42

diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp
index cd527f6..91df981 100644
--- a/src/qml/qml/qqmlcompileddata.cpp
+++ b/src/qml/qml/qqmlcompileddata.cpp
@@ -110,8 +110,8 @@ QQmlCompiledData::~QQmlCompiledData()
     clear();
 
     for (int ii = 0; ii < types.count(); ++ii) {
-        if (types.at(ii).component)
-            types.at(ii).component->release();
+        if (types[ii].component())
+            types[ii].component()->release();
         if (types.at(ii).typePropertyCache)
             types.at(ii).typePropertyCache->release();
     }
@@ -138,15 +138,25 @@ void QQmlCompiledData::clear()
         qPersistentDispose(programs[ii].bindings);
 }
 
+QQmlCompiledData *QQmlCompiledData::TypeReference::component() {
+    if (typeData) {
+        _component = typeData->compiledData();
+        _component->addref();
+        typeData->release();
+        typeData = 0;
+    }
+    return _component;
+}
+
 /*!
 Returns the property cache, if one alread exists.  The cache is not referenced.
 */
-QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache() const
+QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache()
 {
     if (type)
         return typePropertyCache;
     else
-        return component->rootPropertyCache;
+        return component()->rootPropertyCache;
 }
 
 /*!
@@ -161,7 +171,7 @@ QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngi
         typePropertyCache->addref();
         return typePropertyCache;
     } else {
-        return component->rootPropertyCache;
+        return component()->rootPropertyCache;
     }
 }
 
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 7b27a4c..db93e91 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -794,12 +794,14 @@ void QQmlCompiler::reset(QQmlCompiledData *data)
 */
 bool QQmlCompiler::compile(QQmlEngine *engine,
                                    QQmlTypeData *unit,
-                                   QQmlCompiledData *out)
+                                   QQmlCompiledData *out,
+                                   bool firstTime,
+                                   bool fromDependency)
 {
     exceptions.clear();
 
     Q_ASSERT(out);
-    reset(out);
+    if (firstTime) reset(out);
 
     QQmlScript::Object *root = unit->parser().tree();
     Q_ASSERT(root);
@@ -810,43 +812,52 @@ bool QQmlCompiler::compile(QQmlEngine *engine,
     this->unitRoot = root;
     this->output = out;
 
-    // Compile types
-    const QList<QQmlTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
-    QList<QQmlScript::TypeReference *> referencedTypes = unit->parser().referencedTypes();
-
-    for (int ii = 0; ii < resolvedTypes.count(); ++ii) {
-        QQmlCompiledData::TypeReference ref;
-
-        const QQmlTypeData::TypeReference &tref = resolvedTypes.at(ii);
-        QQmlScript::TypeReference *parserRef = referencedTypes.at(ii);
+    if (firstTime) {
+        // Compile types
+        const QList<QQmlTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
+        QList<QQmlScript::TypeReference *> referencedTypes = unit->parser().referencedTypes();
+
+        for (int ii = 0; ii < resolvedTypes.count(); ++ii) {
+            QQmlCompiledData::TypeReference ref;
+
+            const QQmlTypeData::TypeReference &tref = resolvedTypes.at(ii);
+            QQmlScript::TypeReference *parserRef = referencedTypes.at(ii);
+
+            if (tref.typeData) { //QML-based type
+                ref.typeData = tref.typeData;
+                ref.typeData->addref();
+            } else if (tref.type) {//C++-based type
+                ref.type = tref.type;
+                if (!ref.type->isCreatable()) {
+                    QString err = ref.type->noCreationReason();
+                    if (err.isEmpty())
+                        err = tr( "Element is not creatable.");
+                    COMPILE_EXCEPTION(parserRef->firstUse, err);
+                }
 
-        if (tref.typeData) { //QML-based type
-            ref.component = tref.typeData->compiledData();
-            ref.component->addref();
-        } else if (tref.type) {//C++-based type
-            ref.type = tref.type;
-            if (!ref.type->isCreatable()) {
-                QString err = ref.type->noCreationReason();
-                if (err.isEmpty())
-                    err = tr( "Element is not creatable.");
-                COMPILE_EXCEPTION(parserRef->firstUse, err);
+                if (ref.type->containsRevisionedAttributes()) {
+                    QQmlError cacheError;
+                    ref.typePropertyCache = enginePrivate->cache(ref.type,
+                                                                 resolvedTypes.at(ii).minorVersion,
+                                                                 cacheError);
+                    if (!ref.typePropertyCache)
+                        COMPILE_EXCEPTION(parserRef->firstUse, cacheError.description());
+                    ref.typePropertyCache->addref();
+                }
             }
 
-            if (ref.type->containsRevisionedAttributes()) {
-                QQmlError cacheError;
-                ref.typePropertyCache = enginePrivate->cache(ref.type,
-                                                             resolvedTypes.at(ii).minorVersion,
-                                                             cacheError);
-                if (!ref.typePropertyCache)
-                    COMPILE_EXCEPTION(parserRef->firstUse, cacheError.description());
-                ref.typePropertyCache->addref();
-            }
+            out->types << ref;
         }
 
-        out->types << ref;
+        {
+            Q_ASSERT(!out->rootPropertyCache);
+            QQmlCompiledData::TypeReference &tr = out->types[root->type];
+            out->rootPropertyCache = tr.createPropertyCache(engine);
+            out->rootPropertyCache->addref();
+        }
     }
 
-    compileTree(root);
+    compileTree(root, firstTime, fromDependency);
 
     if (!isError()) {
         if (compilerDump())
@@ -870,96 +881,97 @@ bool QQmlCompiler::compile(QQmlEngine *engine,
     return !isError();
 }
 
-void QQmlCompiler::compileTree(QQmlScript::Object *tree)
+void QQmlCompiler::compileTree(QQmlScript::Object *tree, bool firstTime, bool fromDependency)
 {
-    compileState = pool->New<ComponentCompileState>();
+    if (firstTime) {
+        compileState = pool->New<ComponentCompileState>();
 
-    compileState->root = tree;
-    if (componentStats)
-        componentStats->componentStat.lineNumber = tree->location.start.line;
+        compileState->root = tree;
+        if (componentStats)
+            componentStats->componentStat.lineNumber = tree->location.start.line;
 
-    // We generate the importCache before we build the tree so that
-    // it can be used in the binding compiler.  Given we "expect" the
-    // QML compilation to succeed, this isn't a waste.
-    output->importCache = new QQmlTypeNameCache();
-    foreach (const QString &ns, unit->namespaces()) {
-        output->importCache->add(ns);
-    }
+        // We generate the importCache before we build the tree so that
+        // it can be used in the binding compiler.  Given we "expect" the
+        // QML compilation to succeed, this isn't a waste.
+        output->importCache = new QQmlTypeNameCache();
+        foreach (const QString &ns, unit->namespaces()) {
+            output->importCache->add(ns);
+        }
+
+        int scriptIndex = 0;
+        foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) {
+            QString qualifier = script.qualifier;
+            QString enclosingNamespace;
 
-    int scriptIndex = 0;
-    foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) {
-        QString qualifier = script.qualifier;
-        QString enclosingNamespace;
+            const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
+            if (lastDotIndex != -1) {
+                enclosingNamespace = qualifier.left(lastDotIndex);
+                qualifier = qualifier.mid(lastDotIndex+1);
+            }
 
-        const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
-        if (lastDotIndex != -1) {
-            enclosingNamespace = qualifier.left(lastDotIndex);
-            qualifier = qualifier.mid(lastDotIndex+1);
+            output->importCache->add(qualifier, scriptIndex++, enclosingNamespace);
         }
 
-        output->importCache->add(qualifier, scriptIndex++, enclosingNamespace);
-    }
+        unit->imports().populateCache(output->importCache);
 
-    unit->imports().populateCache(output->importCache);
+        if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
+            return;
 
-    if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
-        return;
+        Instruction::Init init;
+        init.bindingsSize = compileState->totalBindingsCount;
+        init.parserStatusSize = compileState->parserStatusCount;
+        init.contextCache = genContextCache();
+        init.objectStackSize = compileState->objectDepth.maxDepth();
+        init.listStackSize = compileState->listDepth.maxDepth();
+        if (compileState->compiledBindingData.isEmpty())
+            init.compiledBinding = -1;
+        else
+            init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
+        output->addInstruction(init);
 
-    Instruction::Init init;
-    init.bindingsSize = compileState->totalBindingsCount;
-    init.parserStatusSize = compileState->parserStatusCount;
-    init.contextCache = genContextCache();
-    init.objectStackSize = compileState->objectDepth.maxDepth();
-    init.listStackSize = compileState->listDepth.maxDepth();
-    if (compileState->compiledBindingData.isEmpty())
-        init.compiledBinding = -1;
-    else
-        init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
-    output->addInstruction(init);
+        foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) {
+            Instruction::StoreImportedScript import;
+            import.value = output->scripts.count();
 
-    foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) {
-        Instruction::StoreImportedScript import;
-        import.value = output->scripts.count();
+            QQmlScriptData *scriptData = script.script->scriptData();
+            scriptData->addref();
+            output->scripts << scriptData;
+            output->addInstruction(import);
+        }
 
-        QQmlScriptData *scriptData = script.script->scriptData();
-        scriptData->addref();
-        output->scripts << scriptData;
-        output->addInstruction(import);
-    }
+        if (!compileState->v8BindingProgram.isEmpty()) {
+            Instruction::InitV8Bindings bindings;
+            int index = output->programs.count();
 
-    if (!compileState->v8BindingProgram.isEmpty()) {
-        Instruction::InitV8Bindings bindings;
-        int index = output->programs.count();
+            typedef QQmlCompiledData::V8Program V8Program;
+            output->programs.append(V8Program(compileState->v8BindingProgram, output));
 
-        typedef QQmlCompiledData::V8Program V8Program;
-        output->programs.append(V8Program(compileState->v8BindingProgram, output));
+            bindings.programIndex = index;
+            bindings.line = compileState->v8BindingProgramLine;
+            output->addInstruction(bindings);
+        }
 
-        bindings.programIndex = index;
-        bindings.line = compileState->v8BindingProgramLine;
-        output->addInstruction(bindings);
-    }
+        genObject(tree);
 
-    genObject(tree);
+        Instruction::SetDefault def;
+        output->addInstruction(def);
 
-    Instruction::SetDefault def;
-    output->addInstruction(def);
+        Instruction::Done done;
+        output->addInstruction(done);
+    }
 
-    Instruction::Done done;
-    output->addInstruction(done);
+    if (!fromDependency) {
+        QMutableListIterator<QQmlScript::Object *> i(output->unbuiltComponents);
+        while (i.hasNext()) {
+            QQmlScript::Object *component = i.next();
+            QQmlScript::Object *root = component->defaultProperty->values.first()->object;
+            if (!buildComponentFromRoot(root, BindingContext()))
+                return;
+        }
 
-    Q_ASSERT(tree->metatype);
-    if (!tree->synthdata.isEmpty()) {
-        enginePrivate->registerInternalCompositeType(output);
-    } else if (output->types.at(tree->type).component) {
-        output->metaTypeId = output->types.at(tree->type).component->metaTypeId;
-        output->listMetaTypeId = output->types.at(tree->type).component->listMetaTypeId;
-    } else {
-        Q_ASSERT(output->types.at(tree->type).type);
-        output->metaTypeId = output->types.at(tree->type).type->typeId();
-        output->listMetaTypeId = output->types.at(tree->type).type->qListTypeId();
+        foreach (QQmlScript::Object *component, output->unbuiltComponents)
+            genComponentBody(component);
     }
-    if (!tree->synthdata.isEmpty())
-        enginePrivate->registerInternalCompositeType(output);
 }
 
 static bool QStringList_contains(const QStringList &list, const QHashedStringRef &string)
@@ -980,16 +992,28 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
     QQmlCompiledData::TypeReference &tr = output->types[obj->type];
     obj->metatype = tr.createPropertyCache(engine);
 
+    if (obj == unitRoot) {
+        Q_ASSERT(obj->metatype);
+        if (output->types[obj->type].component()) {
+            output->metaTypeId = output->types[obj->type].component()->metaTypeId;
+            output->listMetaTypeId = output->types[obj->type].component()->listMetaTypeId;
+        } else {
+            Q_ASSERT(output->types.at(obj->type).type);
+            output->metaTypeId = output->types.at(obj->type).type->typeId();
+            output->listMetaTypeId = output->types.at(obj->type).type->qListTypeId();
+        }
+    }
+
     // This object is a "Component" element.
     if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
         COMPILE_CHECK(buildComponent(obj, ctxt));
         return true;
     } 
 
-    if (tr.component) {
+    if (tr.component()) {
         typedef QQmlInstruction I; 
-        const I *init = ((const I *)tr.component->bytecode.constData());
-        Q_ASSERT(init && tr.component->instructionType(init) == QQmlInstruction::Init);
+        const I *init = ((const I *)tr.component()->bytecode.constData());
+        Q_ASSERT(init && tr.component()->instructionType(init) == QQmlInstruction::Init);
  
         // Adjust stack depths to include nested components
         compileState->objectDepth.pushPop(init->init.objectStackSize);
@@ -1226,16 +1250,8 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj, bool parentToSuper)
         Q_ASSERT(propertyCache);
         propertyCache->addref();
 
-        if (obj == unitRoot) {
-            propertyCache->addref();
-            output->rootPropertyCache = propertyCache;
-        }
-
         output->propertyCaches << propertyCache;
         output->addInstruction(meta);
-    } else if (obj == unitRoot) {
-        output->rootPropertyCache = tr.createPropertyCache(engine);
-        output->rootPropertyCache->addref();
     }
 
     // Set the object id
@@ -1407,7 +1423,7 @@ void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Prop
     fetch.type = prop->type;
     fetch.bindingSkipList = 0;
 
-    if (obj->type == -1 || output->types.at(obj->type).component) {
+    if (obj->type == -1 || output->types[obj->type].component()) {
         // We only have to do this if this is a composite type.  If it is a builtin
         // type it can't possibly already have bindings that need to be cleared.
         for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) {
@@ -1433,6 +1449,55 @@ void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Prop
     genPropertyAssignment(prop, obj);
 }
 
+void QQmlCompiler::genComponentBody(QQmlScript::Object *obj)
+{
+    QQmlScript::Object *root = obj->defaultProperty->values.first()->object;
+
+    ComponentCompileState *oldCompileState = compileState;
+    compileState = componentState(root);
+
+    int nextInstructionIndex = output->nextInstructionIndex();
+
+    Instruction::Init init;
+    init.bindingsSize = compileState->totalBindingsCount;
+    init.parserStatusSize = compileState->parserStatusCount;
+    init.contextCache = genContextCache();
+    init.objectStackSize = compileState->objectDepth.maxDepth();
+    init.listStackSize = compileState->listDepth.maxDepth();
+    if (compileState->compiledBindingData.isEmpty())
+        init.compiledBinding = -1;
+    else
+        init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
+    output->addInstruction(init);
+
+    if (!compileState->v8BindingProgram.isEmpty()) {
+        Instruction::InitV8Bindings bindings;
+        int index = output->programs.count();
+
+        typedef QQmlCompiledData::V8Program V8Program;
+        output->programs.append(V8Program(compileState->v8BindingProgram, output));
+
+        bindings.programIndex = index;
+        bindings.line = compileState->v8BindingProgramLine;
+        output->addInstruction(bindings);
+    }
+
+    genObject(root);
+
+    Instruction::SetDefault def;
+    output->addInstruction(def);
+
+    Instruction::Done done;
+    output->addInstruction(done);
+
+    output->instruction(obj->createComponentInstruction)->createComponent.jump =
+        nextInstructionIndex;
+    output->instruction(obj->createComponentInstruction)->createComponent.count =
+        output->nextInstructionIndex() - nextInstructionIndex;
+
+    compileState = oldCompileState;
+}
+
 void QQmlCompiler::genComponent(QQmlScript::Object *obj)
 {
     QQmlScript::Object *root = obj->defaultProperty->values.first()->object;
@@ -1444,6 +1509,8 @@ void QQmlCompiler::genComponent(QQmlScript::Object *obj)
     create.endLine = root->location.end.line;
     create.isRoot = (compileState->root == obj);
     int createInstruction = output->addInstruction(create);
+
+#if 0
     int nextInstructionIndex = output->nextInstructionIndex();
 
     ComponentCompileState *oldCompileState = compileState;
@@ -1485,6 +1552,9 @@ void QQmlCompiler::genComponent(QQmlScript::Object *obj)
         output->nextInstructionIndex() - nextInstructionIndex;
 
     compileState = oldCompileState;
+#endif
+    obj->createComponentInstruction = createInstruction;
+    output->instruction(createInstruction)->createComponent.jump = -1;
 
     if (!obj->id.isEmpty()) {
         Instruction::SetId id;
@@ -1494,6 +1564,7 @@ void QQmlCompiler::genComponent(QQmlScript::Object *obj)
     }
 
     if (obj == unitRoot) {
+        output->rootPropertyCache->release();
         output->rootPropertyCache = output->types[obj->type].createPropertyCache(engine);
         output->rootPropertyCache->addref();
     }
@@ -1551,7 +1622,7 @@ bool QQmlCompiler::buildComponent(QQmlScript::Object *obj,
         COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification"));
 
     // Build the component tree
-    COMPILE_CHECK(buildComponentFromRoot(root, ctxt));
+    output->unbuiltComponents.push_back(obj);
 
     compileState->objectDepth.pop();
 
@@ -1809,9 +1880,9 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
         if (prop->index != -1 && 
             prop->parent && 
             prop->parent->type != -1 && 
-            output->types.at(prop->parent->type).component) {
+            output->types[prop->parent->type].component()) {
 
-            QQmlPropertyCache *cache = output->types.at(prop->parent->type).component->rootPropertyCache;
+            QQmlPropertyCache *cache = output->types[prop->parent->type].component()->rootPropertyCache;
             if (cache && cache->property(prop->index) && cache->property(prop->index)->isAlias())
                 prop->isAlias = true;
         }
@@ -2871,6 +2942,13 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
 
     cache->_dynamicClassName = newClassName;
 
+    if (obj == unitRoot) {
+        output->rootPropertyCache->release();
+        output->rootPropertyCache = cache;
+        cache->addref();
+        enginePrivate->registerInternalCompositeType(output);
+    }
+
     int cStringNameCount = 0;
 
     int aliasCount = 0;
@@ -3358,11 +3436,11 @@ bool QQmlCompiler::buildDynamicMetaAliases(QQmlScript::Object *obj)
         } else {
             Q_ASSERT(idObject->type != -1); // How else did it get an id?
 
-            const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type);
+            QQmlCompiledData::TypeReference &ref = output->types[idObject->type];
             if (ref.type)
                 type = ref.type->typeId();
             else
-                type = ref.component->metaTypeId;
+                type = ref.component()->metaTypeId;
 
             flags |= QML_ALIAS_FLAG_PTR;
             propertyFlags |= QQmlPropertyData::IsQObjectDerived;
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 5ad2ee5..4fb207b 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -95,13 +95,15 @@ public:
     struct TypeReference 
     {
         TypeReference()
-        : type(0), typePropertyCache(0), component(0) {}
+        : type(0), typePropertyCache(0), typeData(0), _component(0) {}
 
         QQmlType *type;
         QQmlPropertyCache *typePropertyCache;
-        QQmlCompiledData *component;
+        QQmlTypeData *typeData;
+        QQmlCompiledData *_component;
 
-        QQmlPropertyCache *propertyCache() const;
+        QQmlCompiledData *component();
+        QQmlPropertyCache *propertyCache();
         QQmlPropertyCache *createPropertyCache(QQmlEngine *);
     };
     QList<TypeReference> types;
@@ -125,6 +127,7 @@ public:
     QList<QQmlIntegerCache *> contextCaches;
     QList<QQmlScriptData *> scripts;
     QList<QUrl> urls;
+    QList<QQmlScript::Object *> unbuiltComponents;
 
     struct Instruction {
 #define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I;
@@ -287,7 +290,7 @@ class Q_AUTOTEST_EXPORT QQmlCompiler
 public:
     QQmlCompiler(QQmlPool *);
 
-    bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
+    bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *, bool, bool);
 
     bool isError() const;
     QList<QQmlError> errors() const;
@@ -307,7 +310,7 @@ private:
 
     static void reset(QQmlCompiledData *);
 
-    void compileTree(QQmlScript::Object *tree);
+    void compileTree(QQmlScript::Object *tree, bool firstTime, bool fromDependency);
 
 
     bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
@@ -379,6 +382,7 @@ private:
     void genObjectBody(QQmlScript::Object *obj);
     void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
     void genComponent(QQmlScript::Object *obj);
+    void genComponentBody(QQmlScript::Object *obj);
     void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
     void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
     void genPropertyAssignment(QQmlScript::Property *prop, 
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index 328b246..924babb 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -427,6 +427,7 @@ union QQmlInstruction
     };
     struct instr_createComponent {
         QML_INSTR_HEADER
+        int jump;
         int count;
         int endLine;
         int metaObject;
diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h
index 9a07d65..296901e 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -451,7 +451,10 @@ public:
     int aggregateDynamicSlotParameterCount() const;
 
     // Used by compiler
-    QQmlCompilerTypes::ComponentCompileState *componentCompileState;
+    union {
+        QQmlCompilerTypes::ComponentCompileState *componentCompileState;
+        int createComponentInstruction;
+    };
 
     // Used by ComponentCompileState::AliasingObjectsList
     Object *nextAliasingObject;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 933b36f..92d7c37 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -441,6 +441,10 @@ void QQmlDataBlob::addDependency(QQmlDataBlob *blob)
 {
     ASSERT_CALLBACK();
 
+#ifdef DATABLOB_DEBUG
+    qWarning("QQmlDataBlob::addDependency() %s -> %s", qPrintable(url().toString()), qPrintable(blob->url().toString()));
+#endif
+
     Q_ASSERT(status() != Null);
 
     if (!blob ||
@@ -598,9 +602,56 @@ void QQmlDataBlob::completed()
 {
 }
 
+void QQmlDataBlob::breakCycles()
+{
+    if (!isWaiting() || m_waitingFor.count() == 0)
+        return;
+
+    QSet<QQmlDataBlob *> found, visited;
+    found.insert(this);
+    while (found.count() > 0) {
+        QQmlDataBlob *blob = *found.begin();
+        if (!blob->isWaiting()) return;
+        found.remove(blob);
+        visited.insert(blob);
+        foreach (QQmlDataBlob *dep, blob->m_waitingFor) {
+            if(!visited.contains(dep) && !found.contains(dep))
+                found.insert(dep);
+        }
+    }
+
+#ifdef DATABLOB_DEBUG
+    if (visited.count() > 0) {
+        Q_ASSERT(found.count() == 0);
+        qWarning("QQmlDataBlob::breakCycles() breaking detected cycles:");
+        foreach (QQmlDataBlob *dep, visited)
+            qWarning("%s", qPrintable(dep->url().toString()));
+    }
+#endif
+
+    foreach (QQmlDataBlob *dep, visited) {
+        dep->m_isDone = true;
+        if (dep->status() != Error)
+            dep->m_data.setStatus(Complete);
+        Q_ASSERT(!dep->isWaiting());
+    }
+    Q_ASSERT(!isWaiting());
+
+    foreach (QQmlDataBlob *dep, visited) {
+        dep->notifyAllWaitingOnMe();
+    }
+
+    foreach (QQmlDataBlob *dep, visited)
+        dep->done();
+
+    foreach (QQmlDataBlob *dep, visited)
+        dep->cancelAllWaitingFor();
+}
 
 void QQmlDataBlob::tryDone()
 {
+    breakCycles();
+
     if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) {
         m_isDone = true;
         addref();
@@ -1927,7 +1978,8 @@ QQmlTypeData::TypeDataCallback::~TypeDataCallback()
 QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader::Options options, 
                                            QQmlTypeLoader *manager)
 : QQmlTypeLoader::Blob(url, QmlFile, manager), m_options(options),
-   m_typesResolved(false), m_compiledData(0), m_implicitImport(0), m_implicitImportLoaded(false)
+   m_typesResolved(false), m_compiling(false), m_compiledData(0),
+   m_implicitImport(0), m_implicitImportLoaded(false)
 {
 }
 
@@ -1962,8 +2014,11 @@ const QSet<QString> &QQmlTypeData::namespaces() const
     return m_namespaces;
 }
 
-QQmlCompiledData *QQmlTypeData::compiledData() const
+QQmlCompiledData *QQmlTypeData::compiledData()
 {
+    if (!m_compiledData)
+        compile(true);
+
     return m_compiledData;
 }
 
@@ -1982,46 +2037,7 @@ void QQmlTypeData::unregisterCallback(TypeDataCallback *callback)
 
 void QQmlTypeData::done()
 {
-    // Check all script dependencies for errors
-    for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
-        const ScriptReference &script = m_scripts.at(ii);
-        Q_ASSERT(script.script->isCompleteOrError());
-        if (script.script->isError()) {
-            QList<QQmlError> errors = script.script->errors();
-            QQmlError error;
-            error.setUrl(finalUrl());
-            error.setLine(script.location.line);
-            error.setColumn(script.location.column);
-            error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
-            errors.prepend(error);
-            setError(errors);
-        }
-    }
-
-    // Check all type dependencies for errors
-    for (int ii = 0; !isError() && ii < m_types.count(); ++ii) {
-        const TypeReference &type = m_types.at(ii);
-        Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
-        if (type.typeData && type.typeData->isError()) {
-            QString typeName = scriptParser.referencedTypes().at(ii)->name;
-
-            QList<QQmlError> errors = type.typeData->errors();
-            QQmlError error;
-            error.setUrl(finalUrl());
-            error.setLine(type.location.line);
-            error.setColumn(type.location.column);
-            error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
-            errors.prepend(error);
-            setError(errors);
-        }
-    }
-
-    // Compile component
-    if (!isError()) 
-        compile();
-
-    if (!(m_options & QQmlTypeLoader::PreserveParser))
-        scriptParser.clear();
+    compile();
 }
 
 void QQmlTypeData::completed()
@@ -2144,22 +2160,74 @@ void QQmlTypeData::downloadProgressChanged(qreal p)
     }
 }
 
-void QQmlTypeData::compile()
+void QQmlTypeData::compile(bool fromDependency)
 {
-    Q_ASSERT(m_compiledData == 0);
+    Q_ASSERT(!m_compiling);
+    if(m_compiling) return;
 
-    m_compiledData = new QQmlCompiledData(typeLoader()->engine());
-    m_compiledData->url = finalUrl();
-    m_compiledData->name = finalUrlString();
+    m_compiling = true;
 
-    QQmlCompilingProfiler prof(m_compiledData->name);
+    if(!m_compiledData) {
+        // Check all script dependencies for errors
+        for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
+            const ScriptReference &script = m_scripts.at(ii);
+            Q_ASSERT(script.script->isCompleteOrError());
+            if (script.script->isError()) {
+                QList<QQmlError> errors = script.script->errors();
+                QQmlError error;
+                error.setUrl(finalUrl());
+                error.setLine(script.location.line);
+                error.setColumn(script.location.column);
+                error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
+                errors.prepend(error);
+                setError(errors);
+            }
+        }
 
-    QQmlCompiler compiler(&scriptParser._pool);
-    if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) {
-        setError(compiler.errors());
-        m_compiledData->release();
-        m_compiledData = 0;
+        // Check all type dependencies for errors
+        for (int ii = 0; !isError() && ii < m_types.count(); ++ii) {
+            const TypeReference &type = m_types.at(ii);
+            Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
+            if (type.typeData && type.typeData->isError()) {
+                QString typeName = scriptParser.referencedTypes().at(ii)->name;
+
+                QList<QQmlError> errors = type.typeData->errors();
+                QQmlError error;
+                error.setUrl(finalUrl());
+                error.setLine(type.location.line);
+                error.setColumn(type.location.column);
+                error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
+                errors.prepend(error);
+                setError(errors);
+            }
+        }
+    }
+
+    // Compile component
+    if (!isError()) {
+        bool firstTime = m_compiledData == 0;
+        if (firstTime) {
+            m_compiledData = new QQmlCompiledData(typeLoader()->engine());
+            m_compiledData->url = finalUrl();
+            m_compiledData->name = finalUrlString();
+        }
+
+        QQmlCompilingProfiler prof(m_compiledData->name);
+
+        QQmlCompiler compiler(&scriptParser._pool);
+        if (!compiler.compile(typeLoader()->engine(), this, m_compiledData, firstTime, fromDependency)) {
+            setError(compiler.errors());
+            if (!fromDependency) {
+                m_compiledData->release();
+                m_compiledData = 0;
+            }
+        }
     }
+
+    if (!fromDependency && !(m_options & QQmlTypeLoader::PreserveParser))
+        scriptParser.clear();
+
+    m_compiling = false;
 }
 
 void QQmlTypeData::resolveTypes()
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 1bd0766..ff7f7ff 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -162,6 +162,7 @@ private:
     friend class QQmlDataLoader;
     friend class QQmlDataLoaderThread;
 
+    void breakCycles();
     void tryDone();
     void cancelAllWaitingFor();
     void notifyAllWaitingOnMe();
@@ -428,7 +429,7 @@ public:
     const QList<ScriptReference> &resolvedScripts() const;
     const QSet<QString> &namespaces() const;
 
-    QQmlCompiledData *compiledData() const;
+    QQmlCompiledData *compiledData();
 
     // Used by QQmlComponent to get notifications
     struct TypeDataCallback {
@@ -448,7 +449,7 @@ protected:
 
 private:
     void resolveTypes();
-    void compile();
+    void compile(bool fromDependency = false);
 
     virtual void scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &nameSpace);
 
@@ -462,6 +463,8 @@ private:
 
     QList<TypeReference> m_types;
     bool m_typesResolved:1;
+    bool m_compiled:1;
+    bool m_compiling:1;
 
     QQmlCompiledData *m_compiledData;
 
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index c2cb460..e60d7ed 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -494,8 +494,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
         QML_END_INSTR(Done)
 
         QML_BEGIN_INSTR(CreateQMLObject)
-            const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
-            Q_ASSERT(type.component);
+            QQmlCompiledData::TypeReference &type = TYPES[instr.type];
+            Q_ASSERT(type.component());
 
             states.push(State());
 
@@ -503,8 +503,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
             State *nState = &states[states.count() - 1];
 
             nState->context = cState->context;
-            nState->compiledData = type.component;
-            nState->instructionStream = type.component->bytecode.constData();
+            nState->compiledData = type.component();
+            nState->instructionStream = type.component()->bytecode.constData();
 
             if (instr.bindingBits != -1) {
                 const QByteArray &bits = cState->compiledData->datas.at(instr.bindingBits);
@@ -668,7 +668,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
 
         QML_BEGIN_INSTR(CreateComponent)
             QQmlComponent *qcomp = 
-                new QQmlComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
+                new QQmlComponent(CTXT->engine, COMP, instr.jump,
                                           objects.isEmpty() ? 0 : objects.top());
 
             QQmlData *ddata = QQmlData::get(qcomp, true);
@@ -693,7 +693,6 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
             QQmlComponentPrivate::get(qcomp)->creationContext = CTXT;
 
             objects.push(qcomp);
-            INSTRUCTIONSTREAM += instr.count;
         QML_END_INSTR(CreateComponent)
 
         QML_BEGIN_INSTR(StoreMetaObject)
