From a464c80f1806580174272b49855fce569cfd90f7 Mon Sep 17 00:00:00 2001
From: Simon Hausmann <simon.hausmann@qt.io>
Date: Thu, 29 Jun 2017 15:09:51 +0200
Subject: [PATCH] Fix memory of QML type registry not freed when
 clearing/trimming QML component cache

Task-number: QTBUG-61536

Squashed commit of the following:

commit e886def3ab5bd1c4ed4dba214d8161d1e37d948d
Author: Simon Hausmann <simon.hausmann@qt.io>
Date:   Thu Jun 29 14:56:05 2017 +0200

    Reduce memory consumption of stat() cache in QML type loader

    The m_importDirCache caches the result of QDir/File::exists across
    paths. By changing the data structure to a QCache we impose a limit on
    the size of the entries and thus the memory consumption for long running
    programs that access many qml files.

    Change-Id: I20c4dc77260fe353c13da570b7e1bbd3f47d4b79

commit 382e3c1b16470791acb2e246ecb1b4b2efa888da
Author: Simon Hausmann <simon.hausmann@qt.io>
Date:   Wed Jun 28 11:25:18 2017 +0200

    Improve releasing of memory allocated from compilation unit strings

    Allocate the strings in the compilation unit as regular strings, not as
    identifiers. We mark the runtimeStrings in the compilation unit, so when
    the unit is released as part of component cache trimming, those strings
    can also be collected. The JS object literal class keys have to remain
    identifiers though.

    However this is just a stop-gap as the real problem is that the
    identifier table can be triggered to grow without bounds.

    Change-Id: I7a2854b7fa9c9953348b5e34a31833f7be67cfbf

commit fbc73cf1934a3246777823c9187cf24fcfc56437
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Mon Jun 26 11:49:34 2017 +0200

    Fix void * usage in our internal APIs

    Change-Id: Ia2b5cfeab093d8be91728032528788dd238c2872

commit 62c99c0dfb0864c0fc0a281ae2e11b7ff6b8959d
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Tue Jun 27 08:55:01 2017 +0200

    Move the m_qmlLists member in the QML engine to QQmlMetaType

    This is a pure metatype id to metatype id mapping, nothing
    in there is specific to a QML engine instance. Thus move the
    mapping to QQmlMetaType and make it global for all engines.

    Change-Id: I3792567bc9f585e3e0fbbad94efd1ec3a0db3de0

commit 39aa48b31f5ed71a07faa11e08a578b1f6322499
Author: Simon Hausmann <simon.hausmann@qt.io>
Date:   Mon Jun 26 14:52:22 2017 +0200

    Remove unused types on engine destruction

    The QML engine destructor as well as trimComponentCache()
    do now clean out unused composite types that the engine
    registered internally.

    This helps avoid 'static' leaks, when more and more types
    would get registered by the engine.

    Change-Id: I5b32af4b88fbf626de8c0bfbaedb2285b09e3679

commit ada481758f54837644be034775eb8fe993d8a42c
Author: Simon Hausmann <simon.hausmann@qt.io>
Date:   Mon Jun 26 14:28:57 2017 +0200

    Remove unused variable

    Change-Id: Ia7af542e6969c167d1f05a460e0926398f56f380
    QQmlTypeModulePrivate::types is not used (anymore?).

commit 644dd15125930884826fc777d7ed316f8543737c
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Mon Jun 26 13:45:56 2017 +0200

    Change data structures in QQmlMetaTypeData

    Make sure any QQmlType stored in the meta type data
    has a refcount of 1. This should now make it possible
    to clean out unused types by iterating over the
    list of types and removing those that have a refcount
    of 1.

    Some care is still needed for C++ registered types, that
    will need to get one more refcount, so we don't accidentally
    remove them.

    Change-Id: Id2a18dae5ddcb815f34013f5fde1f05d2d9d0214

commit c6b45e0c4dc9a2879934d7898cba94c0384a3be7
Author: Simon Hausmann <simon.hausmann@qt.io>
Date:   Fri Jun 23 17:19:26 2017 +0200

    Remove QQmlEnginePrivate::typePropertyCache

    Instead of maintaining a hash per QQmlType and minor version, move the
    version specific property caches into QQmlType.

    Change-Id: I72f3990cb93e64ac5074060b4ff327043eab7966

commit 73c5d915ba92f8a3b05fc05e35b160a7032a2f35
Author: Simon Hausmann <simon.hausmann@qt.io>
Date:   Fri Jun 23 13:36:13 2017 +0200

    Move property cache from the engine to QQmlType

    Now that the property cache is independent of a specific
    engine, we can cache them in QQmlType instead of caching
    them per engine.

    This simplifies the logic and avoids duplicated property
    caches when multiple engines are running.

    Change-Id: I6f082e1e7495ae0f5b92559e8d0a3437c56e303a

commit a46c9ad88169a8380cc1269d17ada1bf01e96ff7
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Fri Jun 23 12:10:23 2017 +0200

    Move the engine pointer from the property cache to the VME meta object

    This is where it belongs, and it makes the PropertyCache independent
    of the engine used.

    Change-Id: I21c2674ee3e2895abd2418764d140b154b47b868

commit b5a158ee99806410f48bc9ccc9b31320fe8ee7b7
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Fri Jun 23 13:20:23 2017 +0200

    Use QQmlType by value

    QQmlType is now refcounted, and we need to use it by
    value, to control it's lifetime properly. This is
    required, so we can clean up the QQmlMetaTypeData
    cache on engine destruction and with trimComponentCache()

    Change-Id: If86391c86ea20a646ded7c9925d8f743f628fb91

commit 3ec22677e0a1f1308edf04996474dc7d35985e0b
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Fri Jun 23 13:38:43 2017 +0200

    Simplify logic

    Change-Id: Ibdb10dfb8d9fbd15fddc27a2802b756381755ee7

commit c9f761529c535a09fc0d59d8f81037de0104d0de
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Fri Jun 23 13:09:03 2017 +0200

    Use QQmlType by value in the type wrapper

    Change-Id: Ie40cb3a6e170331b0ec7ab5deaf7c1d7ef0cdaeb

commit ac3b35ee606b7ca85ccd81e13fd2609108912812
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Fri Jun 23 10:41:21 2017 +0200

    Use QQmlType by value in the MemberExpressionResolver

    Change-Id: Ia9a43890937399f3a109d93227e5d44420974737

commit 13eea2d8dac09a8058a6438fcd70e09b4342a499
Author: Lars Knoll <lars.knoll@qt.io>
Date:   Fri Jun 23 10:40:55 2017 +0200

    Turn QQmlType into a refcounted value type

    Change-Id: If906af2bf3afd09c23a612aaac417a751b06eba4

commit 1bfc4fc8ef9a3c599e674e7ddb9b093d8d657969
Author: Simon Hausmann <simon.hausmann@qt.io>
Date:   Tue Jun 27 15:01:44 2017 +0200

    Fix bug in designer support reference counting

    The QtQuick designer support may override the meta-object and reparent the
    property-cache of the object under editing. The code for replacing the parent
    of the property cache however was not handling the refcount of the _parent
    correctly.

    Change-Id: Ic73294fc208b297e8ec9c0b775b5da01a309dba6
    Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
    (cherry picked from commit 7dc5cd942eb5c55a26d539eedff48b2d6c8e0fc3)

commit be40ab67dd4ce2296c113725d53feedc5183c7f6
Author: Colin Ogilvie <colin.ogilvie@kdab.com>
Date:   Fri Jun 2 11:37:09 2017 +0100

    Don't leak QQmlJavaScriptExpression errors

    Ensure any error is deleted when the expression is

    Change-Id: Ibbfd28f50279d4c66830b40c5c917eb8d98f266e
    Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
    (cherry picked from commit 1e0685136d0debb2a3b62d9f4650c95afe41913b)

Change-Id: I1d0a15b263a7315d372e4c145e35d22fadf2512a
---
 src/imports/testlib/main.cpp                       |   8 +-
 .../qmldbg_debugger/qqmlenginedebugservice.cpp     |  11 +-
 src/qml/compiler/qqmlirbuilder.cpp                 |  44 +-
 src/qml/compiler/qqmltypecompiler.cpp              | 131 ++-
 src/qml/compiler/qv4compileddata.cpp               |   5 +-
 src/qml/compiler/qv4jsir_p.h                       |  15 +-
 src/qml/jsapi/qjsengine.cpp                        |  19 +-
 src/qml/jsapi/qjsengine_p.h                        |  17 +-
 src/qml/jsruntime/qv4engine.cpp                    |   6 +-
 src/qml/jsruntime/qv4function.cpp                  |   7 +-
 src/qml/jsruntime/qv4lookup.cpp                    |   5 +-
 src/qml/jsruntime/qv4qobjectwrapper.cpp            |   5 +-
 src/qml/qml/qqmlcompileddata.cpp                   |  10 +-
 src/qml/qml/qqmlcompiler_p.h                       |   4 +-
 src/qml/qml/qqmlcontextwrapper.cpp                 |   2 +-
 src/qml/qml/qqmlcustomparser.cpp                   |  10 +-
 src/qml/qml/qqmlengine.cpp                         | 181 +---
 src/qml/qml/qqmlengine_p.h                         |  19 +-
 src/qml/qml/qqmlimport.cpp                         |  84 +-
 src/qml/qml/qqmlimport_p.h                         |   8 +-
 src/qml/qml/qqmljavascriptexpression.cpp           |   1 +
 src/qml/qml/qqmllist.cpp                           |   2 +-
 src/qml/qml/qqmlmetatype.cpp                       | 934 +++++++++++++++------
 src/qml/qml/qqmlmetatype_p.h                       | 108 ++-
 src/qml/qml/qqmlobjectcreator.cpp                  |  36 +-
 src/qml/qml/qqmlopenmetaobject.cpp                 |   2 +-
 src/qml/qml/qqmlproperty.cpp                       |  25 +-
 src/qml/qml/qqmlpropertycache.cpp                  |  47 +-
 src/qml/qml/qqmlpropertycache_p.h                  |  18 +-
 src/qml/qml/qqmltypeloader.cpp                     |  67 +-
 src/qml/qml/qqmltypeloader_p.h                     |   8 +-
 src/qml/qml/qqmltypenamecache.cpp                  |  29 +-
 src/qml/qml/qqmltypenamecache_p.h                  |  73 +-
 src/qml/qml/qqmltypewrapper.cpp                    |  54 +-
 src/qml/qml/qqmltypewrapper_p.h                    |   8 +-
 src/qml/qml/qqmlvmemetaobject.cpp                  |  71 +-
 src/qml/qml/qqmlvmemetaobject_p.h                  |   3 +-
 src/qml/types/qqmldelegatemodel.cpp                |   6 +-
 src/qml/util/qqmladaptormodel.cpp                  |  15 +-
 src/qml/util/qqmladaptormodel_p.h                  |   5 +-
 src/quick/designer/qqmldesignermetaobject.cpp      |   2 +-
 src/quick/designer/qquickdesignersupportitems.cpp  |  41 +-
 .../designer/qquickdesignersupportmetainfo.cpp     |   4 +-
 .../tst_qqmlenginedebugservice.cpp                 |   4 +-
 tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp   | 104 +--
 .../qqmlpropertycache/tst_qqmlpropertycache.cpp    |  18 +-
 tests/benchmarks/qml/creation/tst_creation.cpp     |   4 +-
 tools/qmlplugindump/main.cpp                       | 126 +--
 48 files changed, 1305 insertions(+), 1101 deletions(-)

diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index b90c671cb..8e410ef97 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -78,14 +78,14 @@ public Q_SLOTS:
     {
         QString name(v.typeName());
         if (v.canConvert<QObject*>()) {
-            QQmlType *type = 0;
+            QQmlType type;
             const QMetaObject *mo = v.value<QObject*>()->metaObject();
-            while (!type && mo) {
+            while (!type.isValid() && mo) {
                 type = QQmlMetaType::qmlType(mo);
                 mo = mo->superClass();
             }
-            if (type) {
-                name = type->qmlTypeName();
+            if (type.isValid()) {
+                name = type.qmlTypeName();
             }
         }
 
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index 8f53dc6d5..376461b9f 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -397,9 +397,9 @@ QQmlEngineDebugServiceImpl::objectData(QObject *object)
     rv.objectId = QQmlDebugService::idForObject(object);
     rv.contextId = QQmlDebugService::idForObject(qmlContext(object));
     rv.parentId = QQmlDebugService::idForObject(object->parent());
-    QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
-    if (type) {
-        QString typeName = type->qmlTypeName();
+    QQmlType type = QQmlMetaType::qmlType(object->metaObject());
+    if (type.isValid()) {
+        QString typeName = type.qmlTypeName();
         int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
         rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
     } else {
@@ -693,8 +693,9 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
                 property.reset();
             } else {
                 // overwrite with default value
-                if (QQmlType *objType = QQmlMetaType::qmlType(object->metaObject())) {
-                    if (QObject *emptyObject = objType->create()) {
+                QQmlType objType = QQmlMetaType::qmlType(object->metaObject());
+                if (objType.isValid()) {
+                    if (QObject *emptyObject = objType.create()) {
                         if (emptyObject->property(parentProperty.toLatin1()).isValid()) {
                             QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read();
                             if (defaultValue.isValid()) {
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 791355a66..5a6c65362 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1586,11 +1586,11 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
 {
     QV4::IR::Type result = QV4::IR::VarType;
 
-    QQmlType *type = static_cast<QQmlType*>(resolver->data);
+    QQmlType type = resolver->qmlType;
 
     if (member->name->constData()->isUpper()) {
         bool ok = false;
-        int value = type->enumValue(qmlEngine, *member->name, &ok);
+        int value = type.enumValue(qmlEngine, *member->name, &ok);
         if (ok) {
             member->setEnumValue(value);
             resolver->clear();
@@ -1598,8 +1598,8 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
         }
     }
 
-    if (type->isCompositeSingleton()) {
-        QQmlRefPointer<QQmlTypeData> tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url);
+    if (type.isCompositeSingleton()) {
+        QQmlRefPointer<QQmlTypeData> tdata = qmlEngine->typeLoader.getType(type.singletonInstanceInfo()->url);
         Q_ASSERT(tdata);
         tdata->release(); // Decrease the reference count added from QQmlTypeLoader::getType()
         // When a singleton tries to reference itself, it may not be complete yet.
@@ -1608,17 +1608,17 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
             resolver->flags |= AllPropertiesAreFinal;
             return resolver->resolveMember(qmlEngine, resolver, member);
         }
-    }  else if (type->isSingleton()) {
-        const QMetaObject *singletonMeta = type->singletonInstanceInfo()->instanceMetaObject;
+    }  else if (type.isSingleton()) {
+        const QMetaObject *singletonMeta = type.singletonInstanceInfo()->instanceMetaObject;
         if (singletonMeta) { // QJSValue-based singletons cannot be accelerated
             initMetaObjectResolver(resolver, qmlEngine->cache(singletonMeta));
             member->kind = QV4::IR::Member::MemberOfSingletonObject;
             return resolver->resolveMember(qmlEngine, resolver, member);
         }
-    } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType(qmlEngine)) {
+    } else if (const QMetaObject *attachedMeta = type.attachedPropertiesType(qmlEngine)) {
         QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta);
         initMetaObjectResolver(resolver, cache);
-        member->setAttachedPropertiesId(type->attachedPropertiesId(qmlEngine));
+        member->setAttachedPropertiesId(type.attachedPropertiesId(qmlEngine));
         return resolver->resolveMember(qmlEngine, resolver, member);
     }
 
@@ -1626,21 +1626,21 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
     return result;
 }
 
-static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType)
+static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, const QQmlType &qmlType)
 {
     Q_ASSERT(resolver);
 
     resolver->resolveMember = &resolveQmlType;
-    resolver->data = qmlType;
-    resolver->extraData = 0;
+    resolver->qmlType = qmlType;
+    resolver->typenameCache = 0;
     resolver->flags = 0;
 }
 
 static QV4::IR::Type resolveImportNamespace(QQmlEnginePrivate *, QV4::IR::MemberExpressionResolver *resolver, QV4::IR::Member *member)
 {
     QV4::IR::Type result = QV4::IR::VarType;
-    QQmlTypeNameCache *typeNamespace = static_cast<QQmlTypeNameCache*>(resolver->extraData);
-    void *importNamespace = resolver->data;
+    QQmlTypeNameCache *typeNamespace = resolver->typenameCache;
+    const QQmlImportRef *importNamespace = resolver->import;
 
     QQmlTypeNameCache::Result r = typeNamespace->query(*member->name, importNamespace);
     if (r.isValid()) {
@@ -1648,11 +1648,11 @@ static QV4::IR::Type resolveImportNamespace(QQmlEnginePrivate *, QV4::IR::Member
         if (r.scriptIndex != -1) {
             // TODO: remember the index and replace with subscript later.
             result = QV4::IR::VarType;
-        } else if (r.type) {
+        } else if (r.type.isValid()) {
             // TODO: Propagate singleton information, so that it is loaded
             // through the singleton getter in the run-time. Until then we
             // can't accelerate access :(
-            if (!r.type->isSingleton()) {
+            if (!r.type.isSingleton()) {
                 initQmlTypeResolver(resolver, r.type);
                 return QV4::IR::QObjectType;
             }
@@ -1665,18 +1665,18 @@ static QV4::IR::Type resolveImportNamespace(QQmlEnginePrivate *, QV4::IR::Member
     return result;
 }
 
-static void initImportNamespaceResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlTypeNameCache *imports, const void *importNamespace)
+static void initImportNamespaceResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlTypeNameCache *imports, const QQmlImportRef *importNamespace)
 {
     resolver->resolveMember = &resolveImportNamespace;
-    resolver->data = const_cast<void*>(importNamespace);
-    resolver->extraData = imports;
+    resolver->import = importNamespace;
+    resolver->typenameCache = imports;
     resolver->flags = 0;
 }
 
 static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4::IR::MemberExpressionResolver *resolver, QV4::IR::Member *member)
 {
     QV4::IR::Type result = QV4::IR::VarType;
-    QQmlPropertyCache *metaObject = static_cast<QQmlPropertyCache*>(resolver->data);
+    QQmlPropertyCache *metaObject = resolver->propertyCache;
 
     if (member->name->constData()->isUpper() && (resolver->flags & LookupsIncludeEnums)) {
         const QMetaObject *mo = metaObject->createMetaObject();
@@ -1755,7 +1755,7 @@ static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver,
     Q_ASSERT(resolver);
 
     resolver->resolveMember = &resolveMetaObjectProperty;
-    resolver->data = metaObject;
+    resolver->propertyCache = metaObject;
     resolver->flags = 0;
 }
 
@@ -1814,10 +1814,10 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
         if (r.isValid()) {
             if (r.scriptIndex != -1) {
                 return subscript(_block->TEMP(_importedScriptsTemp), _block->CONST(QV4::IR::SInt32Type, r.scriptIndex));
-            } else if (r.type) {
+            } else if (r.type.isValid()) {
                 QV4::IR::Name *typeName = _block->NAME(name, line, col);
                 // Make sure the run-time loads this through the more efficient singleton getter.
-                typeName->qmlSingleton = r.type->isCompositeSingleton();
+                typeName->qmlSingleton = r.type.isCompositeSingleton();
                 typeName->freeOfSideEffects = true;
                 QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
                 _block->MOVE(result, typeName);
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 82332dfc3..d0b8fc1ef 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -66,7 +66,7 @@ bool QQmlTypeCompiler::compile()
 
     // Add any Composite Singletons that were used to the import cache
     foreach (const QQmlTypeData::TypeReference &singleton, typeData->compositeSingletons())
-        compiledData->importCache->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
+        compiledData->importCache->add(singleton.type.qmlTypeName(), singleton.type.sourceUrl(), singleton.prefix);
 
     typeData->imports().populateCache(compiledData->importCache);
 
@@ -74,11 +74,11 @@ bool QQmlTypeCompiler::compile()
     for (QHash<int, QQmlTypeData::TypeReference>::ConstIterator resolvedType = resolvedTypes.constBegin(), end = resolvedTypes.constEnd();
          resolvedType != end; ++resolvedType) {
         QScopedPointer<QQmlCompiledData::TypeReference> ref(new QQmlCompiledData::TypeReference);
-        QQmlType *qmlType = resolvedType->type;
+        QQmlType qmlType = resolvedType->type;
         if (resolvedType->typeData) {
-            if (resolvedType->needsCreation && qmlType->isCompositeSingleton()) {
+            if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) {
                 QQmlError error;
-                QString reason = tr("Composite Singleton Type %1 is not creatable.").arg(qmlType->qmlTypeName());
+                QString reason = tr("Composite Singleton Type %1 is not creatable.").arg(qmlType.qmlTypeName());
                 error.setDescription(reason);
                 error.setColumn(resolvedType->location.column);
                 error.setLine(resolvedType->location.line);
@@ -87,13 +87,13 @@ bool QQmlTypeCompiler::compile()
             }
             ref->component = resolvedType->typeData->compiledData();
             ref->component->addref();
-        } else if (qmlType) {
+        } else if (qmlType.isValid()) {
             ref->type = qmlType;
-            Q_ASSERT(ref->type);
+            Q_ASSERT(ref->type.isValid());
 
-            if (resolvedType->needsCreation && !ref->type->isCreatable()) {
+            if (resolvedType->needsCreation && !ref->type.isCreatable()) {
                 QQmlError error;
-                QString reason = ref->type->noCreationReason();
+                QString reason = ref->type.noCreationReason();
                 if (reason.isEmpty())
                     reason = tr("Element is not creatable.");
                 error.setDescription(reason);
@@ -103,9 +103,8 @@ bool QQmlTypeCompiler::compile()
                 return false;
             }
 
-            if (ref->type->containsRevisionedAttributes()) {
-                ref->typePropertyCache = engine->cache(ref->type,
-                                                       resolvedType->minorVersion);
+            if (ref->type.containsRevisionedAttributes()) {
+                ref->typePropertyCache = engine->cache(ref->type, resolvedType->minorVersion);
                 if (!ref->typePropertyCache) {
                     QQmlError cacheError;
                     cacheError.setColumn(resolvedType->location.column);
@@ -126,7 +125,7 @@ bool QQmlTypeCompiler::compile()
 
     for (QHash<int, QQmlCompiledData::TypeReference*>::ConstIterator it = compiledData->resolvedTypes.constBegin(), end = compiledData->resolvedTypes.constEnd();
          it != end; ++it) {
-        QQmlCustomParser *customParser = (*it)->type ? (*it)->type->customParser() : 0;
+        QQmlCustomParser *customParser = (*it)->type.customParser();
         if (customParser)
             customParsers.insert(it.key(), customParser);
     }
@@ -243,8 +242,8 @@ bool QQmlTypeCompiler::compile()
             compiledData->metaTypeId = typeRef->component->metaTypeId;
             compiledData->listMetaTypeId = typeRef->component->listMetaTypeId;
         } else {
-            compiledData->metaTypeId = typeRef->type->typeId();
-            compiledData->listMetaTypeId = typeRef->type->qListTypeId();
+            compiledData->metaTypeId = typeRef->type.typeId();
+            compiledData->listMetaTypeId = typeRef->type.qListTypeId();
         }
     }
 
@@ -261,8 +260,8 @@ bool QQmlTypeCompiler::compile()
         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)
+            if (typeRef->type.isValid()) {
+                if (typeRef->type.parserStatusCast() != -1)
                     ++parserStatusCount;
             }
             ++objectCount;
@@ -520,12 +519,12 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
     } else if (instantiatingBinding && instantiatingBinding->isAttachedProperty()) {
         QQmlCompiledData::TypeReference *typeRef = resolvedTypes->value(instantiatingBinding->propertyNameIndex);
         Q_ASSERT(typeRef);
-        QQmlType *qmltype = typeRef->type;
-        if (!qmltype) {
+        QQmlType qmltype = typeRef->type;
+        if (!qmltype.isValid()) {
             QString propertyName = stringAt(instantiatingBinding->propertyNameIndex);
             if (imports->resolveType(propertyName, &qmltype, 0, 0, 0)) {
-                if (qmltype->isComposite()) {
-                    QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
+                if (qmltype.isComposite()) {
+                    QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
                     Q_ASSERT(tdata);
                     Q_ASSERT(tdata->isComplete());
 
@@ -537,7 +536,7 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
             }
         }
 
-        const QMetaObject *attachedMo = qmltype ? qmltype->attachedPropertiesType(enginePrivate) : 0;
+        const QMetaObject *attachedMo = qmltype.attachedPropertiesType(enginePrivate);
         if (!attachedMo) {
             recordError(instantiatingBinding->location, tr("Non-existent attached object"));
             return false;
@@ -725,12 +724,12 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
                     // lazily resolved type
                     Q_ASSERT(param->type == QV4::CompiledData::Property::Custom);
                     const QString customTypeName = stringAt(param->customTypeNameIndex);
-                    QQmlType *qmltype = 0;
+                    QQmlType qmltype;
                     if (!imports->resolveType(customTypeName, &qmltype, 0, 0, 0))
                         COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(customTypeName));
 
-                    if (qmltype->isComposite()) {
-                        QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
+                    if (qmltype.isComposite()) {
+                        QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
                         Q_ASSERT(tdata);
                         Q_ASSERT(tdata->isComplete());
 
@@ -740,7 +739,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
 
                         tdata->release();
                     } else {
-                        paramTypes[i + 1] = qmltype->typeId();
+                        paramTypes[i + 1] = qmltype.typeId();
                     }
                 }
             }
@@ -815,14 +814,14 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
             Q_ASSERT(p->type == QV4::CompiledData::Property::CustomList ||
                      p->type == QV4::CompiledData::Property::Custom);
 
-            QQmlType *qmltype = 0;
+            QQmlType qmltype;
             if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, 0, 0, 0)) {
                 COMPILE_EXCEPTION(p, tr("Invalid property type"));
             }
 
-            Q_ASSERT(qmltype);
-            if (qmltype->isComposite()) {
-                QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
+            Q_ASSERT(qmltype.isValid());
+            if (qmltype.isComposite()) {
+                QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
                 Q_ASSERT(tdata);
                 Q_ASSERT(tdata->isComplete());
 
@@ -839,10 +838,10 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
                 tdata->release();
             } else {
                 if (p->type == QV4::CompiledData::Property::Custom) {
-                    propertyType = qmltype->typeId();
+                    propertyType = qmltype.typeId();
                     vmePropertyType = QMetaType::QObjectStar;
                 } else {
-                    propertyType = qmltype->qListTypeId();
+                    propertyType = qmltype.qListTypeId();
                     vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
                 }
             }
@@ -936,11 +935,11 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
         if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
             const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
             QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(binding->propertyNameIndex);
-            QQmlType *type = typeRef ? typeRef->type : 0;
-            if (!type) {
+            QQmlType type = typeRef ? typeRef->type : QQmlType();
+            if (!type.isValid()) {
                 if (imports->resolveType(propertyName, &type, 0, 0, 0)) {
-                    if (type->isComposite()) {
-                        QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type->sourceUrl());
+                    if (type.isComposite()) {
+                        QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type.sourceUrl());
                         Q_ASSERT(tdata);
                         Q_ASSERT(tdata->isComplete());
 
@@ -952,7 +951,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
                 }
             }
 
-            const QMetaObject *attachedType = type ? type->attachedPropertiesType(enginePrivate) : 0;
+            const QMetaObject *attachedType = type.attachedPropertiesType(enginePrivate);
             if (!attachedType)
                 COMPILE_EXCEPTION(binding, tr("Non-existent attached object"));
             QQmlPropertyCache *cache = compiler->enginePrivate()->cache(attachedType);
@@ -1009,9 +1008,9 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
                 const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
 
                 QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
-                const QQmlType *type = typeRef ? typeRef->type : 0;
-                if (type) {
-                    COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type->module()).arg(type->majorVersion()).arg(type->minorVersion()));
+                const QQmlType type = typeRef->type;
+                if (type.isValid()) {
+                    COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type.module()).arg(type.majorVersion()).arg(type.minorVersion()));
                 } else {
                     COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(originalPropertyName));
                 }
@@ -1203,17 +1202,17 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
         }
         return true;
     }
-    QQmlType *type = 0;
+    QQmlType type;
     imports->resolveType(typeName, &type, 0, 0, 0);
 
-    if (!type && !isQtObject)
+    if (!type.isValid() && !isQtObject)
         return true;
 
     int value = 0;
     bool ok = false;
 
     QQmlCompiledData::TypeReference *tr = resolvedTypes->value(obj->inheritedTypeNameIndex);
-    if (type && tr && tr->type == type) {
+    if (type.isValid() && tr && tr->type == type) {
         QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex);
 
         // When these two match, we can short cut the search
@@ -1224,8 +1223,8 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
         }
     } else {
         // Otherwise we have to search the whole type
-        if (type) {
-            value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
+        if (type.isValid()) {
+            value = type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
         } else {
             QByteArray enumName = enumValue.toUtf8();
             const QMetaObject *metaObject = StaticQtMetaObject::get();
@@ -1248,11 +1247,9 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e
     *ok = false;
 
     if (scope != QLatin1String("Qt")) {
-        QQmlType *type = 0;
+        QQmlType type;
         imports->resolveType(scope, &type, 0, 0, 0);
-        if (!type)
-            return -1;
-        return type ? type->enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+        return type.enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok);
     }
 
     const QMetaObject *mo = StaticQtMetaObject::get();
@@ -1395,8 +1392,8 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
         const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex);
         QQmlCompiledData::TypeReference *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex);
         Q_ASSERT(tr);
-        if (QQmlType *targetType = tr->type) {
-            if (targetType->metaObject() == &QQmlComponent::staticMetaObject)
+        if (tr->type.isValid()) {
+            if (tr->type.metaObject() == &QQmlComponent::staticMetaObject)
                 continue;
         } else if (tr->component) {
             if (tr->component->rootPropertyCache->firstCppMetaObject() == &QQmlComponent::staticMetaObject)
@@ -1424,18 +1421,18 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
         if (!mo)
             continue;
 
-        QQmlType *componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject);
-        Q_ASSERT(componentType);
+        QQmlType componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject);
+        Q_ASSERT(componentType.isValid());
 
         QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>();
-        syntheticComponent->init(pool, compiler->registerString(QString::fromUtf8(componentType->typeName())), compiler->registerString(QString()));
+        syntheticComponent->init(pool, compiler->registerString(QString::fromUtf8(componentType.typeName())), compiler->registerString(QString()));
         syntheticComponent->location = binding->valueLocation;
 
         if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
             QQmlCompiledData::TypeReference *typeRef = new QQmlCompiledData::TypeReference;
             typeRef->type = componentType;
-            typeRef->majorVersion = componentType->majorVersion();
-            typeRef->minorVersion = componentType->minorVersion();
+            typeRef->majorVersion = componentType.majorVersion();
+            typeRef->minorVersion = componentType.minorVersion();
             resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef);
         }
 
@@ -1478,7 +1475,7 @@ bool QQmlComponentAndAliasResolver::resolve()
         if (obj->inheritedTypeNameIndex) {
             QQmlCompiledData::TypeReference *tref = resolvedTypes->value(obj->inheritedTypeNameIndex);
             Q_ASSERT(tref);
-            if (tref->type && tref->type->metaObject() == &QQmlComponent::staticMetaObject)
+            if (tref->type.metaObject() == &QQmlComponent::staticMetaObject)
                 isExplicitComponent = true;
         }
         if (!isExplicitComponent) {
@@ -1639,8 +1636,8 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
                 QQmlCompiledData::TypeReference *typeRef = resolvedTypes->value(targetObject->inheritedTypeNameIndex);
                 Q_ASSERT(typeRef);
 
-                if (typeRef->type)
-                    type = typeRef->type->typeId();
+                if (typeRef->type.isValid())
+                    type = typeRef->type.typeId();
                 else
                     type = typeRef->component->metaTypeId;
 
@@ -1881,8 +1878,8 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
             if (notInRevision) {
                 QString typeName = stringAt(obj->inheritedTypeNameIndex);
                 QQmlCompiledData::TypeReference *objectType = resolvedTypes.value(obj->inheritedTypeNameIndex);
-                if (objectType && objectType->type) {
-                    COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type->module()).arg(objectType->majorVersion).arg(objectType->minorVersion));
+                if (objectType && objectType->type.isValid()) {
+                    COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type.module()).arg(objectType->majorVersion).arg(objectType->minorVersion));
                 } else {
                     COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name));
                 }
@@ -1900,7 +1897,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
             collectedBindingPropertyData[i] = pd;
 
         if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
-            QQmlType *type = 0;
+            QQmlType type;
             QQmlImportNamespace *typeNamespace = 0;
             compiler->imports()->resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace);
             if (typeNamespace)
@@ -2374,22 +2371,20 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
         bool isValueSource = false;
         bool isPropertyInterceptor = false;
 
-        QQmlType *qmlType = 0;
         const QV4::CompiledData::Object *targetObject = qmlUnit->objectAt(binding->value.objectIndex);
         QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex);
         if (typeRef) {
             QQmlPropertyCache *cache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
             const QMetaObject *mo = cache->firstCppMetaObject();
-            while (mo && !qmlType) {
+            QQmlType qmlType;
+            while (mo && !qmlType.isValid()) {
                 qmlType = QQmlMetaType::qmlType(mo);
                 mo = mo->superClass();
             }
-            Q_ASSERT(qmlType);
-        }
+            Q_ASSERT(qmlType.isValid());
 
-        if (qmlType) {
-            isValueSource = qmlType->propertyValueSourceCast() != -1;
-            isPropertyInterceptor = qmlType->propertyValueInterceptorCast() != -1;
+            isValueSource = qmlType.propertyValueSourceCast() != -1;
+            isPropertyInterceptor = qmlType.propertyValueInterceptorCast() != -1;
         }
 
         if (!isValueSource && !isPropertyInterceptor) {
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 20db5edaa..d87fb087f 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -41,6 +41,7 @@
 #include <private/qv4lookup_p.h>
 #include <private/qv4regexpobject_p.h>
 #include <private/qqmlpropertycache_p.h>
+#include <private/qv4identifiertable_p.h>
 #endif
 #include <private/qqmlirbuilder_p.h>
 #include <QCoreApplication>
@@ -79,7 +80,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
     // memset the strings to 0 in case a GC run happens while we're within the loop below
     memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::Heap::String*));
     for (uint i = 0; i < data->stringTableSize; ++i)
-        runtimeStrings[i] = engine->newIdentifier(data->stringAt(i));
+        runtimeStrings[i] = engine->newString(data->stringAt(i));
 
     runtimeRegularExpressions = new QV4::Value[data->regexpTableSize];
     // memset the regexps to 0 in case a GC run happens while we're within the loop below
@@ -132,7 +133,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
             const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
             QV4::InternalClass *klass = engine->emptyClass;
             for (int j = 0; j < memberCount; ++j, ++member)
-                klass = klass->addMember(runtimeStrings[member->nameOffset]->identifier, member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
+                klass = klass->addMember(engine->identifierTable->identifier(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
 
             runtimeClasses[i] = klass;
         }
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 80869dd3e..f1900f026 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -48,6 +48,9 @@
 #include <private/qqmljsmemorypool_p.h>
 #include <private/qqmljsastfwd_p.h>
 #include <private/qflagpointer_p.h>
+#ifndef V4_BOOTSTRAP
+#include <private/qqmlmetatype_p.h>
+#endif
 
 #include <QtCore/QVector>
 #include <QtCore/QString>
@@ -69,6 +72,8 @@ class QQmlType;
 class QQmlPropertyData;
 class QQmlPropertyCache;
 class QQmlEnginePrivate;
+struct QQmlImportRef;
+class QQmlTypeNameCache;
 
 namespace QV4 {
 
@@ -244,14 +249,18 @@ struct MemberExpressionResolver
     typedef Type (*ResolveFunction)(QQmlEnginePrivate *engine, MemberExpressionResolver *resolver, Member *member);
 
     MemberExpressionResolver()
-        : resolveMember(0), data(0), extraData(0), flags(0) {}
+        : resolveMember(0), import(0), propertyCache(0), typenameCache(0), flags(0) {}
 
     bool isValid() const { return !!resolveMember; }
     void clear() { *this = MemberExpressionResolver(); }
 
     ResolveFunction resolveMember;
-    void *data; // Could be pointer to meta object, importNameSpace, etc. - depends on resolveMember implementation
-    void *extraData; // Could be QQmlTypeNameCache
+#ifndef V4_BOOTSTRAP
+    QQmlType qmlType;
+#endif
+    const QQmlImportRef *import;
+    QQmlPropertyCache *propertyCache;
+    QQmlTypeNameCache *typenameCache;
     unsigned int flags;
 };
 
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 5ccbcceba..bc6252570 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -665,24 +665,7 @@ QJSEnginePrivate *QJSEnginePrivate::get(QV4::ExecutionEngine *e)
 
 QJSEnginePrivate::~QJSEnginePrivate()
 {
-    typedef QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator PropertyCacheIt;
-
-    for (PropertyCacheIt iter = propertyCache.begin(), end = propertyCache.end(); iter != end; ++iter)
-        (*iter)->release();
-}
-
-QQmlPropertyCache *QJSEnginePrivate::createCache(const QMetaObject *mo)
-{
-    if (!mo->superClass()) {
-        QQmlPropertyCache *rv = new QQmlPropertyCache(QV8Engine::getV4(q_func()), mo);
-        propertyCache.insert(mo, rv);
-        return rv;
-    } else {
-        QQmlPropertyCache *super = cache(mo->superClass());
-        QQmlPropertyCache *rv = super->copyAndAppend(mo);
-        propertyCache.insert(mo, rv);
-        return rv;
-    }
+    QQmlMetaType::freeUnusedTypesAndCaches();
 }
 
 /*!
diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h
index 8fdec0808..d4b77ae59 100644
--- a/src/qml/jsapi/qjsengine_p.h
+++ b/src/qml/jsapi/qjsengine_p.h
@@ -49,6 +49,7 @@
 #include <QtCore/qmutex.h>
 #include "qjsengine.h"
 #include "private/qtqmlglobal_p.h"
+#include <private/qqmlmetatype_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -101,14 +102,6 @@ public:
     // These methods may be called from the QML loader thread
     inline QQmlPropertyCache *cache(QObject *obj);
     inline QQmlPropertyCache *cache(const QMetaObject *);
-
-private:
-    // Must be called locked
-    QQmlPropertyCache *createCache(const QMetaObject *);
-
-    // These members must be protected by a QJSEnginePrivate::Locker as they are required by
-    // the threaded loader.  Only access them through their respective accessor methods.
-    QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
 };
 
 QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
@@ -165,9 +158,7 @@ QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj)
 
     Locker locker(this);
     const QMetaObject *mo = obj->metaObject();
-    QQmlPropertyCache *rv = propertyCache.value(mo);
-    if (!rv) rv = createCache(mo);
-    return rv;
+    return QQmlMetaType::propertyCache(mo);
 }
 
 /*!
@@ -184,9 +175,7 @@ QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject)
     Q_ASSERT(metaObject);
 
     Locker locker(this);
-    QQmlPropertyCache *rv = propertyCache.value(metaObject);
-    if (!rv) rv = createCache(metaObject);
-    return rv;
+    return QQmlMetaType::propertyCache(metaObject);
 }
 
 
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 557b678ef..f6c601aa8 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -724,10 +724,10 @@ ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
     QQmlTypeNameCache::Result r = ctx->imports->query(name);
 
     Q_ASSERT(r.isValid());
-    Q_ASSERT(r.type);
-    Q_ASSERT(r.type->isSingleton());
+    Q_ASSERT(r.type.isValid());
+    Q_ASSERT(r.type.isSingleton());
 
-    QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
+    QQmlType::SingletonInstanceInfo *siinfo = r.type.singletonInstanceInfo();
     QQmlEngine *e = qmlEngine();
     siinfo->init(e);
 
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 66b2125a4..14e83eb0d 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -38,6 +38,7 @@
 #include "qv4engine_p.h"
 #include "qv4lookup_p.h"
 #include <private/qv4mm_p.h>
+#include <private/qv4identifiertable_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -50,8 +51,6 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
         , code(codePtr)
         , codeData(0)
 {
-    Q_UNUSED(engine);
-
     internalClass = engine->emptyClass;
     const quint32 *formalsIndices = compiledFunction->formalsTable();
     // iterate backwards, so we get the right ordering for duplicate names
@@ -74,7 +73,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
 
     const quint32 *localsIndices = compiledFunction->localsTable();
     for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
-        internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+        internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
 
     activationRequired = compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject));
 }
@@ -106,7 +105,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
 
     const quint32 *localsIndices = compiledFunction->localsTable();
     for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
-        internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+        internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
 
     activationRequired = true;
 }
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index d97abdb46..4da56a549 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -34,6 +34,7 @@
 #include "qv4functionobject_p.h"
 #include "qv4scopedvalue_p.h"
 #include "qv4string_p.h"
+#include <private/qv4identifiertable_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -43,7 +44,7 @@ using namespace QV4;
 ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttributes *attrs)
 {
     ExecutionEngine *engine = o->engine();
-    Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
+    Identifier *name = engine->identifierTable->identifier(engine->current->compilationUnit->runtimeStrings[nameIndex]);
     int i = 0;
     Heap::Object *obj = o->d();
     while (i < Size && obj) {
@@ -79,7 +80,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
 {
     Heap::Object *obj = thisObject->d();
     ExecutionEngine *engine = thisObject->engine();
-    Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
+    Identifier *name = engine->identifierTable->identifier(engine->current->compilationUnit->runtimeStrings[nameIndex]);
     int i = 0;
     while (i < Size && obj) {
         classList[i] = obj->internalClass;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 6be86e3bd..1ac51433d 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -288,9 +288,8 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
                 if (r.isValid()) {
                     if (r.scriptIndex != -1) {
                         return QV4::Encode::undefined();
-                    } else if (r.type) {
-                        return QmlTypeWrapper::create(v4, d()->object,
-                                                      r.type, Heap::QmlTypeWrapper::ExcludeEnums);
+                    } else if (r.type.isValid()) {
+                        return QmlTypeWrapper::create(v4, d()->object, r.type, Heap::QmlTypeWrapper::ExcludeEnums);
                     } else if (r.importNamespace) {
                         return QmlTypeWrapper::create(v4, d()->object,
                                                       qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums);
diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp
index 9c6aab2c8..82678bdac 100644
--- a/src/qml/qml/qqmlcompileddata.cpp
+++ b/src/qml/qml/qqmlcompileddata.cpp
@@ -103,7 +103,7 @@ Returns the property cache, if one alread exists.  The cache is not referenced.
 */
 QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache() const
 {
-    if (type)
+    if (type.isValid())
         return typePropertyCache;
     else
         return component->rootPropertyCache;
@@ -116,8 +116,8 @@ QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngi
 {
     if (typePropertyCache) {
         return typePropertyCache;
-    } else if (type) {
-        typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type->metaObject());
+    } else if (type.isValid()) {
+        typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject());
         typePropertyCache->addref();
         return typePropertyCache;
     } else {
@@ -140,8 +140,8 @@ void QQmlCompiledData::TypeReference::doDynamicTypeCheck()
     const QMetaObject *mo = 0;
     if (typePropertyCache)
         mo = typePropertyCache->firstCppMetaObject();
-    else if (type)
-        mo = type->metaObject();
+    else if (type.isValid())
+        mo = type.metaObject();
     else if (component)
         mo = component->rootPropertyCache->firstCppMetaObject();
     isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 31aac6ab5..e69edff72 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -94,13 +94,13 @@ public:
     struct TypeReference
     {
         TypeReference()
-            : type(0), typePropertyCache(0), component(0)
+            : typePropertyCache(0), component(0)
             , majorVersion(0)
             , minorVersion(0)
             , isFullyDynamicType(false)
         {}
 
-        QQmlType *type;
+        QQmlType type;
         QQmlPropertyCache *typePropertyCache;
         QQmlCompiledData *component;
 
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index e3770a7ec..4c849d979 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -153,7 +153,7 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr
             if (r.scriptIndex != -1) {
                 QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
                 return scripts->getIndexed(r.scriptIndex);
-            } else if (r.type) {
+            } else if (r.type.isValid()) {
                 return QmlTypeWrapper::create(v4, scopeObject, r.type);
             } else if (r.importNamespace) {
                 return QmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 517f8d42e..9ac678c63 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -131,7 +131,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
     if (scope != QLatin1String("Qt")) {
         if (imports.isNull())
             return -1;
-        QQmlType *type = 0;
+        QQmlType type;
 
         if (imports.isT1()) {
             imports.asT1()->resolveType(scope, &type, 0, 0, 0);
@@ -141,7 +141,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
                 type = result.type;
         }
 
-        return type ? type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+        return type.enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok);
     }
 
     const QMetaObject *mo = StaticQtMetaObject::get();
@@ -160,12 +160,10 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
 */
 const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
 {
-    QQmlType *qmltype = 0;
+    QQmlType qmltype;
     if (!validator->imports().resolveType(name, &qmltype, 0, 0, 0))
         return 0;
-    if (!qmltype)
-        return 0;
-    return qmltype->metaObject();
+    return qmltype.metaObject();
 }
 
 QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 8f2253347..d1ae113aa 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -605,7 +605,6 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
 
 QQmlEnginePrivate::~QQmlEnginePrivate()
 {
-    typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::const_iterator TypePropertyCacheIt;
     typedef QHash<int, QQmlCompiledData *>::const_iterator CompositeTypesIt;
 
     if (inProgressCreations)
@@ -625,8 +624,8 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
     if (incubationController) incubationController->d = 0;
     incubationController = 0;
 
-    for (TypePropertyCacheIt iter = typePropertyCache.cbegin(), end = typePropertyCache.cend(); iter != end; ++iter)
-        (*iter)->release();
+    QQmlMetaType::freeUnusedTypesAndCaches();
+
     for (CompositeTypesIt iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) {
         iter.value()->isRegisteredWithEngine = false;
 
@@ -962,9 +961,9 @@ QQmlEngine::~QQmlEngine()
     // we do this here and not in the private dtor since otherwise a crash can
     // occur (if we are the QObject parent of the QObject singleton instance)
     // XXX TODO: performance -- store list of singleton types separately?
-    QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
-    foreach (QQmlType *currType, singletonTypes)
-        currType->singletonInstanceInfo()->destroy(this);
+    QList<QQmlType> singletonTypes = QQmlMetaType::qmlSingletonTypes();
+    foreach (const QQmlType &currType, singletonTypes)
+        currType.singletonInstanceInfo()->destroy(this);
 
     delete d->rootContext;
     d->rootContext = 0;
@@ -2098,108 +2097,6 @@ QString QQmlEngine::offlineStoragePath() const
     return d->offlineStoragePath;
 }
 
-QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion)
-{
-    QList<QQmlType *> types;
-
-    int maxMinorVersion = 0;
-
-    const QMetaObject *metaObject = type->metaObject();
-
-    while (metaObject) {
-        QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
-                                                            type->majorVersion(), minorVersion);
-        if (t) {
-            maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
-            types << t;
-        } else {
-            types << 0;
-        }
-
-        metaObject = metaObject->superClass();
-    }
-
-    if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
-        c->addref();
-        typePropertyCache.insert(qMakePair(type, minorVersion), c);
-        return c;
-    }
-
-    QQmlPropertyCache *raw = cache(type->metaObject());
-
-    bool hasCopied = false;
-
-    for (int ii = 0; ii < types.count(); ++ii) {
-        QQmlType *currentType = types.at(ii);
-        if (!currentType)
-            continue;
-
-        int rev = currentType->metaObjectRevision();
-        int moIndex = types.count() - 1 - ii;
-
-        if (raw->allowedRevisionCache[moIndex] != rev) {
-            if (!hasCopied) {
-                raw = raw->copy();
-                hasCopied = true;
-            }
-            raw->allowedRevisionCache[moIndex] = rev;
-        }
-    }
-
-    // Test revision compatibility - the basic rule is:
-    //    * Anything that is excluded, cannot overload something that is not excluded *
-
-    // Signals override:
-    //    * other signals and methods of the same name.
-    //    * properties named on<Signal Name>
-    //    * automatic <property name>Changed notify signals
-
-    // Methods override:
-    //    * other methods of the same name
-
-    // Properties override:
-    //    * other elements of the same name
-
-#if 0
-    bool overloadError = false;
-    QString overloadName;
-
-    for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
-         !overloadError && iter != raw->stringCache.end();
-         ++iter) {
-
-        QQmlPropertyData *d = *iter;
-        if (raw->isAllowedInRevision(d))
-            continue; // Not excluded - no problems
-
-        // check that a regular "name" overload isn't happening
-        QQmlPropertyData *current = d;
-        while (!overloadError && current) {
-            current = d->overrideData(current);
-            if (current && raw->isAllowedInRevision(current))
-                overloadError = true;
-        }
-    }
-
-    if (overloadError) {
-        if (hasCopied) raw->release();
-
-        error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
-        return 0;
-    }
-#endif
-
-    if (!hasCopied) raw->addref();
-    typePropertyCache.insert(qMakePair(type, minorVersion), raw);
-
-    if (minorVersion != maxMinorVersion) {
-        raw->addref();
-        typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
-    }
-
-    return raw;
-}
-
 bool QQmlEnginePrivate::isQObject(int t)
 {
     Locker locker(this);
@@ -2223,26 +2120,17 @@ QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
     Locker locker(this);
     if (m_compositeTypes.contains(t))
         return QQmlMetaType::Object;
-    else if (m_qmlLists.contains(t))
-        return QQmlMetaType::List;
-    else
-        return QQmlMetaType::typeCategory(t);
+    return QQmlMetaType::typeCategory(t);
 }
 
 bool QQmlEnginePrivate::isList(int t) const
 {
-    Locker locker(this);
-    return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
+    return QQmlMetaType::isList(t);
 }
 
 int QQmlEnginePrivate::listType(int t) const
 {
-    Locker locker(this);
-    QHash<int, int>::ConstIterator iter = m_qmlLists.constFind(t);
-    if (iter != m_qmlLists.cend())
-        return *iter;
-    else
-        return QQmlMetaType::listType(t);
+    return QQmlMetaType::listType(t);
 }
 
 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
@@ -2252,8 +2140,8 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
     if (iter != m_compositeTypes.cend()) {
         return QQmlMetaObject((*iter)->rootPropertyCache);
     } else {
-        QQmlType *type = QQmlMetaType::qmlType(t);
-        return QQmlMetaObject(type?type->baseMetaObject():0);
+        QQmlType type = QQmlMetaType::qmlType(t);
+        return QQmlMetaObject(type.baseMetaObject());
     }
 }
 
@@ -2264,8 +2152,8 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
     if (iter != m_compositeTypes.cend()) {
         return QQmlMetaObject((*iter)->rootPropertyCache);
     } else {
-        QQmlType *type = QQmlMetaType::qmlType(t);
-        return QQmlMetaObject(type?type->metaObject():0);
+        QQmlType type = QQmlMetaType::qmlType(t);
+        return QQmlMetaObject(type.metaObject());
     }
 }
 
@@ -2276,9 +2164,9 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
     if (iter != m_compositeTypes.cend()) {
         return (*iter)->rootPropertyCache;
     } else {
-        QQmlType *type = QQmlMetaType::qmlType(t);
+        QQmlType type = QQmlMetaType::qmlType(t);
         locker.unlock();
-        return type?cache(type->metaObject()):0;
+        return type.isValid() ? cache(type.metaObject()) : 0;
     }
 }
 
@@ -2289,54 +2177,33 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
     if (iter != m_compositeTypes.cend()) {
         return (*iter)->rootPropertyCache;
     } else {
-        QQmlType *type = QQmlMetaType::qmlType(t);
+        QQmlType type = QQmlMetaType::qmlType(t);
         locker.unlock();
-        return type?cache(type->baseMetaObject()):0;
+        return type.isValid() ? cache(type.baseMetaObject()) : 0;
     }
 }
 
 void QQmlEnginePrivate::registerInternalCompositeType(QQmlCompiledData *data)
 {
-    QByteArray name = data->rootPropertyCache->className();
-
-    QByteArray ptr = name + '*';
-    QByteArray lst = "QQmlListProperty<" + name + '>';
-
-    int ptr_type = QMetaType::registerNormalizedType(ptr,
-                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct,
-                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct,
-                                                     sizeof(QObject*),
-                                                     static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
-                                                     0);
-    int lst_type = QMetaType::registerNormalizedType(lst,
-                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct,
-                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct,
-                                                     sizeof(QQmlListProperty<QObject>),
-                                                     static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
-                                                     static_cast<QMetaObject*>(0));
-
-    data->metaTypeId = ptr_type;
-    data->listMetaTypeId = lst_type;
+    QQmlMetaType::registerInternalCompositeType(data);
     data->isRegisteredWithEngine = true;
 
     Locker locker(this);
-    m_qmlLists.insert(lst_type, ptr_type);
     // The QQmlCompiledData is not referenced here, but it is removed from this
     // hash in the QQmlCompiledData destructor
-    m_compositeTypes.insert(ptr_type, data);
+    m_compositeTypes.insert(data->metaTypeId, data);
 }
 
 void QQmlEnginePrivate::unregisterInternalCompositeType(QQmlCompiledData *data)
 {
-    int ptr_type = data->metaTypeId;
-    int lst_type = data->listMetaTypeId;
+    data->isRegisteredWithEngine = false;
 
-    Locker locker(this);
-    m_qmlLists.remove(lst_type);
-    m_compositeTypes.remove(ptr_type);
+    {
+        Locker locker(this);
+        m_compositeTypes.remove(data->metaTypeId);
+    }
 
-    QMetaType::unregisterType(ptr_type);
-    QMetaType::unregisterType(lst_type);
+    QQmlMetaType::unregisterInternalCompositeType(data);
 }
 
 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 072a6c436..a60af423b 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -197,7 +197,7 @@ public:
     inline static void deleteInEngineThread(QQmlEngine *, T *);
 
     // These methods may be called from the loader thread
-    inline QQmlPropertyCache *cache(QQmlType *, int);
+    inline QQmlPropertyCache *cache(const QQmlType &, int);
     using QJSEnginePrivate::cache;
 
     // These methods may be called from the loader thread
@@ -250,13 +250,8 @@ public:
     mutable QMutex networkAccessManagerMutex;
 
 private:
-    // Must be called locked
-    QQmlPropertyCache *createCache(QQmlType *, int);
-
     // These members must be protected by a QQmlEnginePrivate::Locker as they are required by
     // the threaded loader.  Only access them through their respective accessor methods.
-    QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache;
-    QHash<int, int> m_qmlLists;
     QHash<int, QQmlCompiledData *> m_compositeTypes;
     QHash<QUrl, QByteArray> debugChangesHash;
     static bool s_designerMode;
@@ -335,17 +330,15 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion.
 
 The returned cache is not referenced, so if it is to be stored, call addref().
 */
-QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion)
+QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersion)
 {
-    Q_ASSERT(type);
+    Q_ASSERT(type.isValid());
 
-    if (minorVersion == -1 || !type->containsRevisionedAttributes())
-        return cache(type->metaObject());
+    if (minorVersion == -1 || !type.containsRevisionedAttributes())
+        return cache(type.metaObject());
 
     Locker locker(this);
-    QQmlPropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
-    if (!rv) rv = createCache(type, minorVersion);
-    return rv;
+    return QQmlMetaType::propertyCache(type, minorVersion);
 }
 
 QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e)
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index dfdf2edbe..24ffbc41c 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -125,13 +125,13 @@ bool isPathAbsolute(const QString &path)
 }
 
 // If the type does not already exist as a file import, add the type and return the new type
-QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeName,
+QQmlType getTypeForUrl(const QString &urlString, const QHashedStringRef& typeName,
                         bool isCompositeSingleton, QList<QQmlError> *errors,
                         int majorVersion=-1, int minorVersion=-1)
 {
     QUrl url(urlString);
-    QQmlType *ret = QQmlMetaType::qmlType(url);
-    if (!ret) { //QQmlType not yet existing for composite or composite singleton type
+    QQmlType ret = QQmlMetaType::qmlType(url);
+    if (!ret.isValid()) { //QQmlType not yet existing for composite or composite singleton type
         int dot = typeName.indexOf(QLatin1Char('.'));
         QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1);
 
@@ -146,7 +146,7 @@ QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeNa
                 minorVersion,
                 buf.constData()
             };
-            ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeSingletonRegistration, &reg));
+            ret = QQmlMetaType::registerCompositeSingletonType(reg);
         } else {
             QQmlPrivate::RegisterCompositeType reg = {
                 url,
@@ -155,16 +155,16 @@ QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeNa
                 minorVersion,
                 buf.constData()
             };
-            ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &reg));
+            ret = QQmlMetaType::registerCompositeType(reg);
+        }
+        if (!ret.isValid()) {//Usually when a type name is "found" but invalid
+            //qDebug() << ret << urlString << QQmlMetaType::qmlType(url);
+            if (!errors) // Cannot list errors properly, just quit
+                qFatal("%s", QQmlMetaType::typeRegistrationFailures().join('\n').toLatin1().constData());
+            QQmlError error;
+            error.setDescription(QQmlMetaType::typeRegistrationFailures().join('\n'));
+            errors->prepend(error);
         }
-    }
-    if (!ret) {//Usually when a type name is "found" but invalid
-        //qDebug() << ret << urlString << QQmlMetaType::qmlType(url);
-        if (!errors) // Cannot list errors properly, just quit
-            qFatal("%s", QQmlMetaType::typeRegistrationFailures().join('\n').toLatin1().constData());
-        QQmlError error;
-        error.setDescription(QQmlMetaType::typeRegistrationFailures().join('\n'));
-        errors->prepend(error);
     }
     return ret;
 }
@@ -219,7 +219,7 @@ public:
         static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin);
 
         bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
-                         int *vmajor, int *vminor, QQmlType** type_return,
+                         int *vmajor, int *vminor, QQmlType *type_return,
                          QString *base = 0, bool *typeRecursionDetected = 0) const;
     };
     QList<Import *> imports;
@@ -227,7 +227,7 @@ public:
     Import *findImport(const QString &uri);
 
     bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
-                     int *vmajor, int *vminor, QQmlType** type_return,
+                     int *vmajor, int *vminor, QQmlType *type_return,
                      QString *base = 0, QList<QQmlError> *errors = 0);
 
     // Prefix when used as a qualified import.  Otherwise empty.
@@ -261,7 +261,7 @@ public:
                              QList<QQmlError> *errors);
 
     bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor,
-                     QQmlType** type_return, QList<QQmlError> *errors);
+                     QQmlType *type_return, QList<QQmlError> *errors);
 
     QUrl baseUrl;
     QString base;
@@ -377,7 +377,7 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const
             const QQmlImportNamespace::Import *import = set.imports.at(ii);
             QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion);
             if (module) {
-                QQmlTypeNameCache::Import &typeimport = cache->m_namedImports[set.prefix];
+                QQmlImportRef &typeimport = cache->m_namedImports[set.prefix];
                 typeimport.modules.append(QQmlTypeModuleVersion(module, import->minversion));
             }
         }
@@ -519,7 +519,7 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
   \sa addFileImport(), addLibraryImport
 */
 bool QQmlImports::resolveType(const QHashedStringRef &type,
-                              QQmlType** type_return, int *vmaj, int *vmin,
+                              QQmlType *type_return, int *vmaj, int *vmin,
                               QQmlImportNamespace** ns_return, QList<QQmlError> *errors) const
 {
     QQmlImportNamespace* ns = d->findQualifiedNamespace(type);
@@ -529,17 +529,19 @@ bool QQmlImports::resolveType(const QHashedStringRef &type,
         return true;
     }
     if (type_return) {
-        if (d->resolveType(type,vmaj,vmin,type_return, errors)) {
+        if (d->resolveType(type, vmaj, vmin, type_return, errors)) {
             if (qmlImportTrace()) {
 #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \
                                               << ')' << "::resolveType: " << type.toString() << " => "
 
-                if (type_return && *type_return && (*type_return)->isCompositeSingleton())
-                    RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << ' ' << (*type_return)->sourceUrl() << " TYPE/URL-SINGLETON";
-                else if (type_return && *type_return && (*type_return)->isComposite())
-                    RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << ' ' << (*type_return)->sourceUrl() << " TYPE/URL";
-                else if (type_return && *type_return)
-                    RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << " TYPE";
+                if (type_return && type_return->isValid()) {
+                    if (type_return->isCompositeSingleton())
+                        RESOLVE_TYPE_DEBUG << type_return->typeName() << ' ' << type_return->sourceUrl() << " TYPE/URL-SINGLETON";
+                    else if (type_return->isComposite())
+                        RESOLVE_TYPE_DEBUG << type_return->typeName() << ' ' << type_return->sourceUrl() << " TYPE/URL";
+                    else
+                        RESOLVE_TYPE_DEBUG << type_return->typeName() << " TYPE";
+                }
 #undef RESOLVE_TYPE_DEBUG
             }
             return true;
@@ -604,19 +606,19 @@ QQmlDirScripts QQmlImportNamespace::Import::getVersionedScripts(const QQmlDirScr
 
   If the return pointer is 0, the corresponding search is not done.
 */
-bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QHashedStringRef &type,
-                              QQmlType** type_return, int *vmaj, int *vmin) const
+bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &type,
+                              QQmlType *type_return, int *vmaj, int *vmin) const
 {
-    return ns->resolveType(d->typeLoader,type,vmaj,vmin,type_return);
+    return ns->resolveType(d->typeLoader, type, vmaj, vmin, type_return);
 }
 
 bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
-                                              const QHashedStringRef& type, int *vmajor, int *vminor,
-                                              QQmlType** type_return, QString *base, bool *typeRecursionDetected) const
+                                              const QHashedStringRef &type, int *vmajor, int *vminor,
+                                              QQmlType *type_return, QString *base, bool *typeRecursionDetected) const
 {
     if (majversion >= 0 && minversion >= 0) {
-        QQmlType *t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
-        if (t) {
+        QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
+        if (t.isValid()) {
             if (vmajor) *vmajor = majversion;
             if (vminor) *vminor = minversion;
             if (type_return)
@@ -662,11 +664,11 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
         if (candidate != end) {
             int major = vmajor ? *vmajor : -1;
             int minor = vminor ? *vminor : -1;
-            QQmlType *returnType = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0,
-                                                 major, minor);
+            QQmlType returnType = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0,
+                                                major, minor);
             if (type_return)
                 *type_return = returnType;
-            return returnType != 0;
+            return returnType.isValid();
         }
     } else if (!isLibrary) {
         QString qmlUrl;
@@ -690,10 +692,10 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
                 if (typeRecursionDetected)
                     *typeRecursionDetected = true;
             } else {
-                QQmlType *returnType = getTypeForUrl(qmlUrl, type, false, 0);
+                QQmlType returnType = getTypeForUrl(qmlUrl, type, false, 0);
                 if (type_return)
                     *type_return = returnType;
-                return returnType != 0;
+                return returnType.isValid();
             }
         }
     }
@@ -702,7 +704,7 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
 }
 
 bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor,
-                                     QQmlType** type_return, QList<QQmlError> *errors)
+                                     QQmlType *type_return, QList<QQmlError> *errors)
 {
     QQmlImportNamespace *s = 0;
     int dot = type.indexOf(Dot);
@@ -731,12 +733,12 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
     }
     QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1);
     if (s) {
-        if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors))
+        if (s->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors))
             return true;
         if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) {
             // qualified, and only 1 url
             *type_return = getTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors);
-            return (*type_return != 0);
+            return type_return->isValid();
         }
     }
 
@@ -754,7 +756,7 @@ QQmlImportNamespace::Import *QQmlImportNamespace::findImport(const QString &uri)
 }
 
 bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
-                                      int *vmajor, int *vminor, QQmlType** type_return,
+                                      int *vmajor, int *vminor, QQmlType *type_return,
                                       QString *base, QList<QQmlError> *errors)
 {
     bool typeRecursionDetected = false;
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 951b9752f..e23312f1e 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -77,13 +77,13 @@ public:
     QUrl baseUrl() const;
 
     bool resolveType(const QHashedStringRef &type,
-                     QQmlType** type_return,
+                     QQmlType *type_return,
                      int *version_major, int *version_minor,
-                     QQmlImportNamespace** ns_return,
+                     QQmlImportNamespace **ns_return,
                      QList<QQmlError> *errors = 0) const;
-    bool resolveType(QQmlImportNamespace*,
+    bool resolveType(QQmlImportNamespace *,
                      const QHashedStringRef& type,
-                     QQmlType** type_return, int *version_major, int *version_minor) const;
+                     QQmlType *type_return, int *version_major, int *version_minor) const;
 
     bool addImplicitImport(QQmlImportDatabase *importDb, QList<QQmlError> *errors);
 
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index cd2f12021..1c4890aaa 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -100,6 +100,7 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
     }
 
     clearGuards();
+    clearError();
     if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion.
         m_scopeObject.asT2()->_s = 0;
 }
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index c379373e7..416dc1f39 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -142,7 +142,7 @@ QQmlListReference::QQmlListReference(QObject *object, const char *property, QQml
 
     d = new QQmlListReferencePrivate;
     d->object = object;
-    d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject();
+    d->elementType = p ? p->rawMetaObjectForType(listType) : QQmlMetaType::qmlType(listType).baseMetaObject();
     d->propertyType = data->propType;
 
     void *args[] = { &d->property, 0 };
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 337c3bce8..ad3322fad 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -64,18 +64,20 @@ struct QQmlMetaTypeData
 {
     QQmlMetaTypeData();
     ~QQmlMetaTypeData();
-    QList<QQmlType *> types;
-    typedef QHash<int, QQmlType *> Ids;
+    void registerType(QQmlTypePrivate *priv);
+    QList<QQmlType> types;
+    QSet<QQmlType> undeletableTypes;
+    typedef QHash<int, QQmlTypePrivate *> Ids;
     Ids idToType;
-    typedef QHash<QHashedStringRef,QQmlType *> Names;
+    typedef QHash<QHashedStringRef, QQmlTypePrivate *> Names;
     Names nameToType;
-    typedef QHash<QUrl, QQmlType *> Files; //For file imported composite types only
+    typedef QHash<QUrl, QQmlTypePrivate *> Files; //For file imported composite types only
     Files urlToType;
     Files urlToNonFileImportType; // For non-file imported composite and composite
                                   // singleton types. This way we can locate any
                                   // of them by url, even if it was registered as
                                   // a module via qmlRegisterCompositeType.
-    typedef QHash<const QMetaObject *, QQmlType *> MetaObjects;
+    typedef QHash<const QMetaObject *, QQmlTypePrivate *> MetaObjects;
     MetaObjects metaObjectToType;
     typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
     StringConverters stringConverters;
@@ -105,6 +107,12 @@ struct QQmlMetaTypeData
 
     QString typeRegistrationNamespace;
     QStringList typeRegistrationFailures;
+
+    QHash<int, int> qmlLists;
+
+    QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches;
+    QQmlPropertyCache *propertyCache(const QMetaObject *metaObject);
+    QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
 };
 
 class QQmlTypeModulePrivate
@@ -121,10 +129,11 @@ public:
     int maxMinorVersion;
     bool locked;
 
-    void add(QQmlType *);
+    void add(QQmlTypePrivate *);
+    void remove(const QQmlTypePrivate *type);
 
-    QStringHash<QList<QQmlType *> > typeHash;
-    QList<QQmlType *> types;
+    typedef QStringHash<QList<QQmlTypePrivate *> > TypeHash;
+    TypeHash typeHash;
 };
 
 Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData)
@@ -141,15 +150,16 @@ QQmlMetaTypeData::QQmlMetaTypeData()
 
 QQmlMetaTypeData::~QQmlMetaTypeData()
 {
-    for (int i = 0; i < types.count(); ++i)
-        delete types.at(i);
-
     for (TypeModules::const_iterator i = uriToModule.constBegin(), cend = uriToModule.constEnd(); i != cend; ++i)
         delete *i;
+    for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = propertyCaches.begin(), end = propertyCaches.end();
+         it != end; ++it)
+        (*it)->release();
 }
 
 class QQmlTypePrivate
 {
+    Q_DISABLE_COPY(QQmlTypePrivate)
 public:
     QQmlTypePrivate(QQmlType::RegistrationType type);
     ~QQmlTypePrivate();
@@ -158,6 +168,7 @@ public:
     void initEnums() const;
     void insertEnums(const QMetaObject *metaObject) const;
 
+    QAtomicInt refCount;
     QQmlType::RegistrationType regType;
 
     struct QQmlCppTypeData
@@ -202,7 +213,7 @@ public:
     int listId;
     int revision;
     mutable bool containsRevisionedAttributes;
-    mutable QQmlType *superType;
+    mutable QQmlType superType;
     const QMetaObject *baseMetaObject;
 
     int index;
@@ -213,8 +224,32 @@ public:
     mutable QStringHash<int> enums;
 
     static QHash<const QMetaObject *, int> attachedPropertyIds;
+
+    struct PropertyCacheByMinorVersion
+    {
+        PropertyCacheByMinorVersion() : cache(Q_NULLPTR), minorVersion(-1) {}
+        explicit PropertyCacheByMinorVersion(QQmlPropertyCache *pc, int ver) : cache(pc), minorVersion(ver) {}
+        QQmlPropertyCachePtr cache;
+        int minorVersion;
+    };
+    QVector<PropertyCacheByMinorVersion> propertyCaches;
+    QQmlPropertyCache *propertyCacheForMinorVersion(int minorVersion) const;
+    void setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache);
 };
 
+void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
+{
+    for (int i = 0; i < types.count(); ++i) {
+        if (!types.at(i).isValid()) {
+            types[i] = QQmlType(priv);
+            priv->index = i;
+            return;
+        }
+    }
+    types.append(QQmlType(priv));
+    priv->index = types.count() - 1;
+}
+
 void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
 {
     QV4::ExecutionEngine *v4 = QV8Engine::getV4(e->handle());
@@ -273,7 +308,7 @@ QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const
 QHash<const QMetaObject *, int> QQmlTypePrivate::attachedPropertyIds;
 
 QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
-: regType(type), iid(0), typeId(0), listId(0), revision(0),
+: refCount(1), regType(type), iid(0), typeId(0), listId(0), revision(0),
     containsRevisionedAttributes(false), superType(0), baseMetaObject(0),
     index(-1), isSetup(false), isEnumSetup(false), haveSuperType(false)
 {
@@ -326,21 +361,23 @@ QQmlTypePrivate::~QQmlTypePrivate()
     }
 }
 
-QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface)
-: d(new QQmlTypePrivate(InterfaceType))
+QQmlType::QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &interface)
+    : d(new QQmlTypePrivate(InterfaceType))
 {
     d->iid = interface.iid;
     d->typeId = interface.typeId;
     d->listId = interface.listId;
-    d->index = index;
     d->isSetup = true;
     d->version_maj = 0;
     d->version_min = 0;
+    data->registerType(d);
 }
 
-QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterSingletonType &type)
-: d(new QQmlTypePrivate(SingletonType))
+QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterSingletonType &type)
+    : d(new QQmlTypePrivate(SingletonType))
 {
+    data->registerType(d);
+
     d->elementName = elementName;
     d->module = QString::fromUtf8(type.uri);
 
@@ -356,8 +393,6 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg
             d->revision = type.revision;
     }
 
-    d->index = index;
-
     d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo;
     d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi;
     d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi;
@@ -366,25 +401,27 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg
         = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : 0;
 }
 
-QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterCompositeSingletonType &type)
-  : d(new QQmlTypePrivate(CompositeSingletonType))
+QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeSingletonType &type)
+    : d(new QQmlTypePrivate(CompositeSingletonType))
 {
+    data->registerType(d);
+
     d->elementName = elementName;
     d->module = QString::fromUtf8(type.uri);
 
     d->version_maj = type.versionMajor;
     d->version_min = type.versionMinor;
 
-    d->index = index;
-
     d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo;
     d->extraData.sd->singletonInstanceInfo->url = type.url;
     d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName);
 }
 
-QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterType &type)
-: d(new QQmlTypePrivate(CppType))
+QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterType &type)
+    : d(new QQmlTypePrivate(CppType))
 {
+    data->registerType(d);
+
     d->elementName = elementName;
     d->module = QString::fromUtf8(type.uri);
 
@@ -403,7 +440,7 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg
     if (d->extraData.cd->attachedPropertiesType) {
         QHash<const QMetaObject *, int>::Iterator iter = d->attachedPropertyIds.find(d->baseMetaObject);
         if (iter == d->attachedPropertyIds.end())
-            iter = d->attachedPropertyIds.insert(d->baseMetaObject, index);
+            iter = d->attachedPropertyIds.insert(d->baseMetaObject, d->index);
         d->extraData.cd->attachedPropertiesId = *iter;
     } else {
         d->extraData.cd->attachedPropertiesId = -1;
@@ -413,16 +450,16 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg
     d->extraData.cd->propertyValueInterceptorCast = type.valueInterceptorCast;
     d->extraData.cd->extFunc = type.extensionObjectCreate;
     d->extraData.cd->customParser = type.customParser;
-    d->index = index;
 
     if (type.extensionMetaObject)
         d->extraData.cd->extMetaObject = type.extensionMetaObject;
 }
 
-QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterCompositeType &type)
-: d(new QQmlTypePrivate(CompositeType))
+QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeType &type)
+    : d(new QQmlTypePrivate(CompositeType))
 {
-    d->index = index;
+    data->registerType(d);
+
     d->elementName = elementName;
 
     d->module = QString::fromUtf8(type.uri);
@@ -432,44 +469,88 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg
     d->extraData.fd->url = type.url;
 }
 
+QQmlType::QQmlType()
+    : d(0)
+{
+}
+
+QQmlType::QQmlType(const QQmlType &other)
+    : d(other.d)
+{
+    if (d)
+        d->refCount.ref();
+}
+
+QQmlType &QQmlType::operator =(const QQmlType &other)
+{
+    if (d != other.d) {
+        if (d && !d->refCount.deref())
+            delete d;
+        d = other.d;
+        if (d)
+            d->refCount.ref();
+    }
+    return *this;
+}
+
 QQmlType::~QQmlType()
 {
-    delete d;
+    if (d && !d->refCount.deref())
+        delete d;
+}
+
+QQmlType::QQmlType(QQmlTypePrivate *d)
+    : d(d)
+{
+    if (d)
+        d->refCount.ref();
 }
 
-const QHashedString &QQmlType::module() const
+QHashedString QQmlType::module() const
 {
+    if (!d)
+        return QHashedString();
     return d->module;
 }
 
 int QQmlType::majorVersion() const
 {
+    if (!d)
+        return -1;
     return d->version_maj;
 }
 
 int QQmlType::minorVersion() const
 {
+    if (!d)
+        return -1;
     return d->version_min;
 }
 
 bool QQmlType::availableInVersion(int vmajor, int vminor) const
 {
     Q_ASSERT(vmajor >= 0 && vminor >= 0);
+    if (!d)
+        return false;
     return vmajor == d->version_maj && vminor >= d->version_min;
 }
 
 bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const
 {
     Q_ASSERT(vmajor >= 0 && vminor >= 0);
+    if (!d)
+        return false;
     return module == d->module && vmajor == d->version_maj && vminor >= d->version_min;
 }
 
 // returns the nearest _registered_ super class
-QQmlType *QQmlType::superType() const
+QQmlType QQmlType::superType() const
 {
+    if (!d)
+        return 0;
     if (!d->haveSuperType && d->baseMetaObject) {
         const QMetaObject *mo = d->baseMetaObject->superClass();
-        while (mo && !d->superType) {
+        while (mo && !d->superType.isValid()) {
             d->superType = QQmlMetaType::qmlType(mo, d->module, d->version_maj, d->version_min);
             mo = mo->superClass();
         }
@@ -479,10 +560,10 @@ QQmlType *QQmlType::superType() const
     return d->superType;
 }
 
-QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
+QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
 {
     Q_ASSERT(isComposite());
-    if (!engine)
+    if (!engine || !d)
         return 0;
     QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
     if (td.isNull() || !td->isComplete())
@@ -495,11 +576,11 @@ QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
 int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
 {
     Q_ASSERT(isComposite());
-    *ok = false;
-    QQmlType *type = resolveCompositeBaseType(engine);
-    if (!type)
+    if (!d)
         return -1;
-    return type->enumValue(engine, name, ok);
+    *ok = false;
+    QQmlType type = resolveCompositeBaseType(engine);
+    return type.enumValue(engine, name, ok);
 }
 
 static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
@@ -619,18 +700,18 @@ void QQmlTypePrivate::init() const
 
     mo = mo->d.superdata;
     while(mo) {
-        QQmlType *t = metaTypeData()->metaObjectToType.value(mo);
+        QQmlTypePrivate *t = metaTypeData()->metaObjectToType.value(mo);
         if (t) {
-            if (t->d->regType == QQmlType::CppType) {
-                if (t->d->extraData.cd->extFunc) {
+            if (t->regType == QQmlType::CppType) {
+                if (t->extraData.cd->extFunc) {
                     QMetaObjectBuilder builder;
-                    clone(builder, t->d->extraData.cd->extMetaObject, t->d->baseMetaObject, baseMetaObject);
+                    clone(builder, t->extraData.cd->extMetaObject, t->baseMetaObject, baseMetaObject);
                     builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
                     QMetaObject *mmo = builder.toMetaObject();
                     mmo->d.superdata = baseMetaObject;
                     if (!metaObjects.isEmpty())
                         metaObjects.last().metaObject->d.superdata = mmo;
-                    QQmlProxyMetaObject::ProxyData data = { mmo, t->d->extraData.cd->extFunc, 0, 0 };
+                    QQmlProxyMetaObject::ProxyData data = { mmo, t->extraData.cd->extFunc, 0, 0 };
                     metaObjects << data;
                 }
             }
@@ -702,23 +783,47 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
     }
 }
 
+QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersion) const
+{
+    for (int i = 0; i < propertyCaches.count(); ++i)
+        if (propertyCaches.at(i).minorVersion == minorVersion)
+            return propertyCaches.at(i).cache;
+    return Q_NULLPTR;
+}
+
+void QQmlTypePrivate::setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache)
+{
+    for (int i = 0; i < propertyCaches.count(); ++i) {
+        if (propertyCaches.at(i).minorVersion == minorVersion) {
+            propertyCaches[i].cache = cache;
+            return;
+        }
+    }
+    propertyCaches.append(PropertyCacheByMinorVersion(cache, minorVersion));
+}
+
 QByteArray QQmlType::typeName() const
 {
-    if (d->regType == SingletonType || d->regType == CompositeSingletonType)
-        return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8();
-    else if (d->baseMetaObject)
-        return d->baseMetaObject->className();
-    else
-        return QByteArray();
+    if (d) {
+        if (d->regType == SingletonType || d->regType == CompositeSingletonType)
+            return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8();
+        else if (d->baseMetaObject)
+            return d->baseMetaObject->className();
+    }
+    return QByteArray();
 }
 
-const QString &QQmlType::elementName() const
+QString QQmlType::elementName() const
 {
+    if (!d)
+        return QString();
     return d->elementName;
 }
 
-const QString &QQmlType::qmlTypeName() const
+QString QQmlType::qmlTypeName() const
 {
+    if (!d)
+        return QString();
     if (d->name.isEmpty()) {
         if (!d->module.isEmpty())
             d->name = static_cast<QString>(d->module) + QLatin1Char('/') + d->elementName;
@@ -731,7 +836,7 @@ const QString &QQmlType::qmlTypeName() const
 
 QObject *QQmlType::create() const
 {
-    if (!isCreatable())
+    if (!d || !isCreatable())
         return 0;
 
     d->init();
@@ -747,7 +852,7 @@ QObject *QQmlType::create() const
 
 void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
 {
-    if (!isCreatable())
+    if (!d || !isCreatable())
         return;
 
     d->init();
@@ -764,6 +869,8 @@ void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) con
 
 QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const
 {
+    if (!d)
+        return 0;
     if (d->regType != SingletonType && d->regType != CompositeSingletonType)
         return 0;
     return d->extraData.sd->singletonInstanceInfo;
@@ -771,6 +878,8 @@ QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const
 
 QQmlCustomParser *QQmlType::customParser() const
 {
+    if (!d)
+        return 0;
     if (d->regType != CppType)
         return 0;
     return d->extraData.cd->customParser;
@@ -778,32 +887,34 @@ QQmlCustomParser *QQmlType::customParser() const
 
 QQmlType::CreateFunc QQmlType::createFunction() const
 {
-    if (d->regType != CppType)
+    if (!d || d->regType != CppType)
         return 0;
     return d->extraData.cd->newFunc;
 }
 
 QString QQmlType::noCreationReason() const
 {
-    if (d->regType != CppType)
+    if (!d || d->regType != CppType)
         return QString();
     return d->extraData.cd->noCreationReason;
 }
 
 int QQmlType::createSize() const
 {
-    if (d->regType != CppType)
+    if (!d || d->regType != CppType)
         return 0;
     return d->extraData.cd->allocationSize;
 }
 
 bool QQmlType::isCreatable() const
 {
-    return d->regType == CppType && d->extraData.cd->newFunc;
+    return d && d->regType == CppType && d->extraData.cd->newFunc;
 }
 
 bool QQmlType::isExtendedType() const
 {
+    if (!d)
+        return false;
     d->init();
 
     return !d->metaObjects.isEmpty();
@@ -811,36 +922,38 @@ bool QQmlType::isExtendedType() const
 
 bool QQmlType::isSingleton() const
 {
-    return d->regType == SingletonType || d->regType == CompositeSingletonType;
+    return d && (d->regType == SingletonType || d->regType == CompositeSingletonType);
 }
 
 bool QQmlType::isInterface() const
 {
-    return d->regType == InterfaceType;
+    return d && d->regType == InterfaceType;
 }
 
 bool QQmlType::isComposite() const
 {
-    return d->regType == CompositeType || d->regType == CompositeSingletonType;
+    return d && (d->regType == CompositeType || d->regType == CompositeSingletonType);
 }
 
 bool QQmlType::isCompositeSingleton() const
 {
-    return d->regType == CompositeSingletonType;
+    return d && d->regType == CompositeSingletonType;
 }
 
 int QQmlType::typeId() const
 {
-    return d->typeId;
+    return d ? d->typeId : -1;
 }
 
 int QQmlType::qListTypeId() const
 {
-    return d->listId;
+    return d ? d->listId : -1;
 }
 
 const QMetaObject *QQmlType::metaObject() const
 {
+    if (!d)
+        return 0;
     d->init();
 
     if (d->metaObjects.isEmpty())
@@ -852,11 +965,13 @@ const QMetaObject *QQmlType::metaObject() const
 
 const QMetaObject *QQmlType::baseMetaObject() const
 {
-    return d->baseMetaObject;
+    return d ? d->baseMetaObject : 0;
 }
 
 bool QQmlType::containsRevisionedAttributes() const
 {
+    if (!d)
+        return false;
     d->init();
 
     return d->containsRevisionedAttributes;
@@ -864,29 +979,33 @@ bool QQmlType::containsRevisionedAttributes() const
 
 int QQmlType::metaObjectRevision() const
 {
-    return d->revision;
+    return d ? d->revision : -1;
 }
 
 QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
 {
+    if (!d)
+        return 0;
     if (d->regType == CppType)
         return d->extraData.cd->attachedPropertiesFunc;
 
-    QQmlType *base = 0;
+    QQmlType base;
     if (d->regType == CompositeType)
         base = resolveCompositeBaseType(engine);
-    return base ? base->attachedPropertiesFunction(engine) : 0;
+    return base.attachedPropertiesFunction(engine);
 }
 
 const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const
 {
+    if (!d)
+        return 0;
     if (d->regType == CppType)
         return d->extraData.cd->attachedPropertiesType;
 
-    QQmlType *base = 0;
+    QQmlType base;
     if (d->regType == CompositeType)
         base = resolveCompositeBaseType(engine);
-    return base ? base->attachedPropertiesType(engine) : 0;
+    return base.attachedPropertiesType(engine);
 }
 
 /*
@@ -896,70 +1015,75 @@ Qt 4.7 and QtQuick 1.0).
 */
 int QQmlType::attachedPropertiesId(QQmlEnginePrivate *engine) const
 {
+    if (!d)
+        return -1;
     if (d->regType == CppType)
         return d->extraData.cd->attachedPropertiesId;
 
-    QQmlType *base = 0;
+    QQmlType base;
     if (d->regType == CompositeType)
         base = resolveCompositeBaseType(engine);
-    return base ? base->attachedPropertiesId(engine) : 0;
+    return base.attachedPropertiesId(engine);
 }
 
 int QQmlType::parserStatusCast() const
 {
-    if (d->regType != CppType)
+    if (!d || d->regType != CppType)
         return -1;
     return d->extraData.cd->parserStatusCast;
 }
 
 int QQmlType::propertyValueSourceCast() const
 {
-    if (d->regType != CppType)
+    if (!d || d->regType != CppType)
         return -1;
     return d->extraData.cd->propertyValueSourceCast;
 }
 
 int QQmlType::propertyValueInterceptorCast() const
 {
-    if (d->regType != CppType)
+    if (!d || d->regType != CppType)
         return -1;
     return d->extraData.cd->propertyValueInterceptorCast;
 }
 
 const char *QQmlType::interfaceIId() const
 {
-    if (d->regType != InterfaceType)
+    if (!d || d->regType != InterfaceType)
         return 0;
     return d->iid;
 }
 
 int QQmlType::index() const
 {
-    return d->index;
+    return d ? d->index : -1;
 }
 
 QUrl QQmlType::sourceUrl() const
 {
-    if (d->regType == CompositeType)
-        return d->extraData.fd->url;
-    else if (d->regType == CompositeSingletonType)
-        return d->extraData.sd->singletonInstanceInfo->url;
-    else
-        return QUrl();
+    if (d) {
+        if (d->regType == CompositeType)
+            return d->extraData.fd->url;
+        else if (d->regType == CompositeSingletonType)
+            return d->extraData.sd->singletonInstanceInfo->url;
+    }
+    return QUrl();
 }
 
 int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
 {
     Q_ASSERT(ok);
-    if (isComposite())
-        return resolveCompositeEnumValue(engine, name.toString(), ok);
-    *ok = true;
+    if (d) {
+        if (isComposite())
+            return resolveCompositeEnumValue(engine, name.toString(), ok);
+        *ok = true;
 
-    d->initEnums();
+        d->initEnums();
 
-    int *rv = d->enums.value(name);
-    if (rv)
-        return *rv;
+        int *rv = d->enums.value(name);
+        if (rv)
+            return *rv;
+    }
 
     *ok = false;
     return -1;
@@ -968,15 +1092,17 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name,
 int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
 {
     Q_ASSERT(ok);
-    if (isComposite())
-        return resolveCompositeEnumValue(engine, name.toUtf16(), ok);
-    *ok = true;
+    if (d) {
+        if (isComposite())
+            return resolveCompositeEnumValue(engine, name.toUtf16(), ok);
+        *ok = true;
 
-    d->initEnums();
+        d->initEnums();
 
-    int *rv = d->enums.value(name);
-    if (rv)
-        return *rv;
+        int *rv = d->enums.value(name);
+        if (rv)
+            return *rv;
+    }
 
     *ok = false;
     return -1;
@@ -985,20 +1111,43 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name
 int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
 {
     Q_ASSERT(ok);
-    if (isComposite())
-        return resolveCompositeEnumValue(engine, name->toQString(), ok);
-    *ok = true;
+    if (d) {
+        if (isComposite())
+            return resolveCompositeEnumValue(engine, name->toQString(), ok);
+        *ok = true;
 
-    d->initEnums();
+        d->initEnums();
 
-    int *rv = d->enums.value(name);
-    if (rv)
-        return *rv;
+        int *rv = d->enums.value(name);
+        if (rv)
+            return *rv;
+    }
 
     *ok = false;
     return -1;
 }
 
+namespace {
+template <typename QQmlTypeContainer>
+void removeQQmlTypePrivate(QQmlTypeContainer &container, const QQmlTypePrivate *reference)
+{
+    for (typename QQmlTypeContainer::iterator it = container.begin(); it != container.end();) {
+        if (*it == reference)
+            it = container.erase(it);
+        else
+            ++it;
+    }
+}
+
+struct IsQQmlTypePrivate
+{
+    const QQmlTypePrivate *reference;
+    explicit IsQQmlTypePrivate(const QQmlTypePrivate *ref) : reference(ref) {}
+
+    bool operator()(const QQmlTypePrivate *priv) const { return reference == priv; }
+};
+}
+
 QQmlTypeModule::QQmlTypeModule()
 : d(new QQmlTypeModulePrivate)
 {
@@ -1029,14 +1178,16 @@ int QQmlTypeModule::maximumMinorVersion() const
     return d->maxMinorVersion;
 }
 
-void QQmlTypeModulePrivate::add(QQmlType *type)
+void QQmlTypeModulePrivate::add(QQmlTypePrivate *type)
 {
-    minMinorVersion = qMin(minMinorVersion, type->minorVersion());
-    maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
+    int minVersion = type->version_min;
+    minMinorVersion = qMin(minMinorVersion, minVersion);
+    maxMinorVersion = qMax(maxMinorVersion, minVersion);
 
-    QList<QQmlType *> &list = typeHash[type->elementName()];
+    QList<QQmlTypePrivate *> &list = typeHash[type->elementName];
     for (int ii = 0; ii < list.count(); ++ii) {
-        if (list.at(ii)->minorVersion() < type->minorVersion()) {
+        Q_ASSERT(list.at(ii));
+        if (list.at(ii)->version_min < minVersion) {
             list.insert(ii, type);
             return;
         }
@@ -1044,46 +1195,50 @@ void QQmlTypeModulePrivate::add(QQmlType *type)
     list.append(type);
 }
 
-QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
+void QQmlTypeModulePrivate::remove(const QQmlTypePrivate *type)
 {
-    QMutexLocker lock(metaTypeDataLock());
-
-    QList<QQmlType *> *types = d->typeHash.value(name);
-    if (!types) return 0;
+    for (TypeHash::ConstIterator elementIt = typeHash.begin(); elementIt != typeHash.end();) {
+        QList<QQmlTypePrivate *> &list = typeHash[elementIt.key()];
 
-    for (int ii = 0; ii < types->count(); ++ii)
-        if (types->at(ii)->minorVersion() <= minor)
-            return types->at(ii);
+        removeQQmlTypePrivate(list, type);
 
-    return 0;
+#if 0
+        if (list.isEmpty())
+            elementIt = typeHash.erase(elementIt);
+        else
+            ++elementIt;
+#else
+        ++elementIt;
+#endif
+    }
 }
 
-QQmlType *QQmlTypeModule::type(const QV4::String *name, int minor)
+QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor)
 {
     QMutexLocker lock(metaTypeDataLock());
 
-    QList<QQmlType *> *types = d->typeHash.value(name);
-    if (!types) return 0;
-
-    for (int ii = 0; ii < types->count(); ++ii)
-        if (types->at(ii)->minorVersion() <= minor)
-            return types->at(ii);
+    QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
+    if (types) {
+        for (int ii = 0; ii < types->count(); ++ii)
+            if (types->at(ii)->version_min <= minor)
+                return types->at(ii);
+    }
 
-    return 0;
+    return QQmlType();
 }
 
-QList<QQmlType*> QQmlTypeModule::singletonTypes(int minor) const
+QQmlType QQmlTypeModule::type(const QV4::String *name, int minor)
 {
     QMutexLocker lock(metaTypeDataLock());
 
-    QList<QQmlType *> retn;
-    for (int ii = 0; ii < d->types.count(); ++ii) {
-        QQmlType *curr = d->types.at(ii);
-        if (curr->isSingleton() && curr->minorVersion() <= minor)
-            retn.append(curr);
+    QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
+    if (types) {
+        for (int ii = 0; ii < types->count(); ++ii)
+            if (types->at(ii)->version_min <= minor)
+                return types->at(ii);
     }
 
-    return retn;
+    return QQmlType();
 }
 
 QQmlTypeModuleVersion::QQmlTypeModuleVersion()
@@ -1120,16 +1275,18 @@ int QQmlTypeModuleVersion::minorVersion() const
     return m_minor;
 }
 
-QQmlType *QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
+QQmlType QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
 {
-    if (m_module) return m_module->type(name, m_minor);
-    else return 0;
+    if (!m_module)
+        return QQmlType();
+    return m_module->type(name, m_minor);
 }
 
-QQmlType *QQmlTypeModuleVersion::type(const QV4::String *name) const
+QQmlType QQmlTypeModuleVersion::type(const QV4::String *name) const
 {
-    if (m_module) return m_module->type(name, m_minor);
-    else return 0;
+    if (!m_module)
+        return QQmlType();
+    return m_module->type(name, m_minor);
 }
 
 void qmlClearTypeRegistrations() // Declared in qqml.h
@@ -1138,9 +1295,6 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    for (int i = 0; i < data->types.count(); ++i)
-        delete data->types.at(i);
-
     for (QQmlMetaTypeData::TypeModules::const_iterator i = data->uriToModule.constBegin(), cend = data->uriToModule.constEnd(); i != cend; ++i)
         delete *i;
 
@@ -1158,7 +1312,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
 #endif
 }
 
-int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
+static int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
@@ -1168,7 +1322,7 @@ int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
     return data->parentFunctions.count() - 1;
 }
 
-int registerInterface(const QQmlPrivate::RegisterInterface &interface)
+QQmlType registerInterface(const QQmlPrivate::RegisterInterface &interface)
 {
     if (interface.version > 0)
         qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
@@ -1176,16 +1330,15 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface)
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    int index = data->types.count();
+    QQmlType type(data, interface);
+    QQmlTypePrivate *priv = type.priv();
+    Q_ASSERT(priv);
 
-    QQmlType *type = new QQmlType(index, interface);
-
-    data->types.append(type);
-    data->idToType.insert(type->typeId(), type);
-    data->idToType.insert(type->qListTypeId(), type);
+    data->idToType.insert(priv->typeId, priv);
+    data->idToType.insert(priv->listId, priv);
     // XXX No insertMulti, so no multi-version interfaces?
-    if (!type->elementName().isEmpty())
-        data->nameToType.insert(type->elementName(), type);
+    if (!priv->elementName.isEmpty())
+        data->nameToType.insert(priv->elementName, priv);
 
     if (data->interfaces.size() <= interface.typeId)
         data->interfaces.resize(interface.typeId + 16);
@@ -1194,7 +1347,7 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface)
     data->interfaces.setBit(interface.typeId, true);
     data->lists.setBit(interface.listId, true);
 
-    return index;
+    return type;
 }
 
 QString registrationTypeString(QQmlType::RegistrationType typeType)
@@ -1263,32 +1416,34 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
 }
 
 // NOTE: caller must hold a QMutexLocker on "data"
-void addTypeToData(QQmlType* type, QQmlMetaTypeData *data)
+void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data)
 {
-    if (!type->elementName().isEmpty())
-        data->nameToType.insertMulti(type->elementName(), type);
+    Q_ASSERT(type);
+
+    if (!type->elementName.isEmpty())
+        data->nameToType.insertMulti(type->elementName, type);
 
-    if (type->baseMetaObject())
-        data->metaObjectToType.insertMulti(type->baseMetaObject(), type);
+    if (type->baseMetaObject)
+        data->metaObjectToType.insertMulti(type->baseMetaObject, type);
 
-    if (type->typeId()) {
-        data->idToType.insert(type->typeId(), type);
-        if (data->objects.size() <= type->typeId())
-            data->objects.resize(type->typeId() + 16);
-        data->objects.setBit(type->typeId(), true);
+    if (type->typeId) {
+        data->idToType.insert(type->typeId, type);
+        if (data->objects.size() <= type->typeId)
+            data->objects.resize(type->typeId + 16);
+        data->objects.setBit(type->typeId, true);
     }
 
-    if (type->qListTypeId()) {
-        if (data->lists.size() <= type->qListTypeId())
-            data->lists.resize(type->qListTypeId() + 16);
-        data->lists.setBit(type->qListTypeId(), true);
-        data->idToType.insert(type->qListTypeId(), type);
+    if (type->listId) {
+        if (data->lists.size() <= type->listId)
+            data->lists.resize(type->listId + 16);
+        data->lists.setBit(type->listId, true);
+        data->idToType.insert(type->listId, type);
     }
 
-    if (!type->module().isEmpty()) {
-        const QHashedString &mod = type->module();
+    if (!type->module.isEmpty()) {
+        const QHashedString &mod = type->module;
 
-        QQmlMetaTypeData::VersionedUri versionedUri(mod, type->majorVersion());
+        QQmlMetaTypeData::VersionedUri versionedUri(mod, type->version_maj);
         QQmlTypeModule *module = data->uriToModule.value(versionedUri);
         if (!module) {
             module = new QQmlTypeModule;
@@ -1299,45 +1454,39 @@ void addTypeToData(QQmlType* type, QQmlMetaTypeData *data)
     }
 }
 
-int registerType(const QQmlPrivate::RegisterType &type)
+QQmlType registerType(const QQmlPrivate::RegisterType &type)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
     QString elementName = QString::fromUtf8(type.elementName);
     if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor))
-        return -1;
+        return QQmlType();
 
-    int index = data->types.count();
+    QQmlType dtype(data, elementName, type);
 
-    QQmlType *dtype = new QQmlType(index, elementName, type);
-
-    data->types.append(dtype);
-    addTypeToData(dtype, data);
+    addTypeToData(dtype.priv(), data);
     if (!type.typeId)
-        data->idToType.insert(dtype->typeId(), dtype);
+        data->idToType.insert(dtype.typeId(), dtype.priv());
 
-    return index;
+    return dtype;
 }
 
-int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
+QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
     QString typeName = QString::fromUtf8(type.typeName);
     if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor))
-        return -1;
-
-    int index = data->types.count();
+        return QQmlType();
 
-    QQmlType *dtype = new QQmlType(index, typeName, type);
+    QQmlType dtype(data, typeName, type);
 
-    data->types.append(dtype);
-    addTypeToData(dtype, data);
+    addTypeToData(dtype.priv(), data);
 
-    return index;
+    return dtype;
 }
 
-int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type)
+QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type)
 {
     // Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
     QMutexLocker lock(metaTypeDataLock());
@@ -1347,22 +1496,19 @@ int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingleton
     if (*(type.uri) == '\0')
         fileImport = true;
     if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? 0 : type.uri, typeName))
-        return -1;
-
-    int index = data->types.count();
+        return QQmlType();
 
-    QQmlType *dtype = new QQmlType(index, typeName, type);
+    QQmlType dtype(data, typeName, type);
 
-    data->types.append(dtype);
-    addTypeToData(dtype, data);
+    addTypeToData(dtype.priv(), data);
 
     QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType);
-    files->insertMulti(type.url, dtype);
+    files->insertMulti(type.url, dtype.priv());
 
-    return index;
+    return dtype;
 }
 
-int registerCompositeType(const QQmlPrivate::RegisterCompositeType &type)
+QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterCompositeType &type)
 {
     // Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
     QMutexLocker lock(metaTypeDataLock());
@@ -1372,18 +1518,56 @@ int registerCompositeType(const QQmlPrivate::RegisterCompositeType &type)
     if (*(type.uri) == '\0')
         fileImport = true;
     if (!checkRegistration(QQmlType::CompositeType, data, fileImport?0:type.uri, typeName, type.versionMajor))
-        return -1;
+        return QQmlType();
 
-    int index = data->types.count();
-
-    QQmlType *dtype = new QQmlType(index, typeName, type);
-    data->types.append(dtype);
-    addTypeToData(dtype, data);
+    QQmlType dtype(data, typeName, type);
+    addTypeToData(dtype.priv(), data);
 
     QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType);
-    files->insertMulti(type.url, dtype);
+    files->insertMulti(type.url, dtype.priv());
 
-    return index;
+    return dtype;
+}
+
+void QQmlMetaType::registerInternalCompositeType(QQmlCompiledData *data)
+{
+    QByteArray name = data->rootPropertyCache->className();
+
+    QByteArray ptr = name + '*';
+    QByteArray lst = "QQmlListProperty<" + name + '>';
+
+    int ptr_type = QMetaType::registerNormalizedType(ptr,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct,
+                                                     sizeof(QObject*),
+                                                     static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
+                                                     0);
+    int lst_type = QMetaType::registerNormalizedType(lst,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct,
+                                                     sizeof(QQmlListProperty<QObject>),
+                                                     static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
+                                                     static_cast<QMetaObject*>(0));
+
+    data->metaTypeId = ptr_type;
+    data->listMetaTypeId = lst_type;
+
+    QMutexLocker lock(metaTypeDataLock());
+    QQmlMetaTypeData *d = metaTypeData();
+    d->qmlLists.insert(lst_type, ptr_type);
+}
+
+void QQmlMetaType::unregisterInternalCompositeType(QQmlCompiledData *data)
+{
+    int ptr_type = data->metaTypeId;
+    int lst_type = data->listMetaTypeId;
+
+    QMutexLocker lock(metaTypeDataLock());
+    QQmlMetaTypeData *d = metaTypeData();
+    d->qmlLists.remove(lst_type);
+
+    QMetaType::unregisterType(ptr_type);
+    QMetaType::unregisterType(lst_type);
 }
 
 int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration)
@@ -1402,22 +1586,30 @@ the future without adding exported symbols.
 */
 int QQmlPrivate::qmlregister(RegistrationType type, void *data)
 {
-    if (type == TypeRegistration) {
-        return registerType(*reinterpret_cast<RegisterType *>(data));
-    } else if (type == InterfaceRegistration) {
-        return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
-    } else if (type == AutoParentRegistration) {
+    if (type == AutoParentRegistration)
         return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
-    } else if (type == SingletonRegistration) {
-        return registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data));
-    } else if (type == CompositeRegistration) {
-        return registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data));
-    } else if (type == CompositeSingletonRegistration) {
-        return registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data));
-    } else if (type == QmlUnitCacheHookRegistration) {
+    else if (type == QmlUnitCacheHookRegistration)
         return registerQmlUnitCacheHook(*reinterpret_cast<RegisterQmlUnitCacheHook *>(data));
-    }
-    return -1;
+
+    QQmlType dtype;
+    if (type == TypeRegistration)
+        dtype = registerType(*reinterpret_cast<RegisterType *>(data));
+    else if (type == InterfaceRegistration)
+        dtype = registerInterface(*reinterpret_cast<RegisterInterface *>(data));
+    else if (type == SingletonRegistration)
+        dtype = registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data));
+    else if (type == CompositeRegistration)
+        dtype = QQmlMetaType::registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data));
+    else if (type == CompositeSingletonRegistration)
+        dtype = QQmlMetaType::registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data));
+    else
+        return -1;
+
+    QMutexLocker lock(metaTypeDataLock());
+    QQmlMetaTypeData *typeData = metaTypeData();
+    typeData->undeletableTypes.insert(dtype);
+
+    return dtype.index();
 }
 
 //From qqml.h
@@ -1443,8 +1635,8 @@ bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri, int majorV
 
     // Has any type previously been installed to this namespace?
     QHashedString nameSpace(uri);
-    foreach (const QQmlType *type, data->types)
-        if (type->module() == nameSpace && type->majorVersion() == majorVersion)
+    foreach (const QQmlType &type, data->types)
+        if (type.module() == nameSpace && type.majorVersion() == majorVersion)
             return true;
 
     return false;
@@ -1576,9 +1768,12 @@ int QQmlMetaType::listType(int id)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
-    QQmlType *type = data->idToType.value(id);
-    if (type && type->qListTypeId() == id)
-        return type->typeId();
+    QHash<int, int>::ConstIterator iter = data->qmlLists.constFind(id);
+    if (iter != data->qmlLists.cend())
+        return *iter;
+    QQmlTypePrivate *type = data->idToType.value(id);
+    if (type && type->listId == id)
+        return type->typeId;
     else
         return 0;
 }
@@ -1588,9 +1783,9 @@ int QQmlMetaType::attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMet
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    QQmlType *type = data->metaObjectToType.value(mo);
-    if (type && type->attachedPropertiesFunction(engine))
-        return type->attachedPropertiesId(engine);
+    QQmlType type(data->metaObjectToType.value(mo));
+    if (type.attachedPropertiesFunction(engine))
+        return type.attachedPropertiesId(engine);
     else
         return -1;
 }
@@ -1601,7 +1796,7 @@ QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(QQmlEnginePr
         return 0;
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
-    return data->types.at(id)->attachedPropertiesFunction(engine);
+    return data->types.at(id).attachedPropertiesFunction(engine);
 }
 
 QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
@@ -1665,7 +1860,9 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
 
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
-    if (userType < data->objects.size() && data->objects.testBit(userType))
+    if (data->qmlLists.contains(userType))
+        return List;
+    else if (userType < data->objects.size() && data->objects.testBit(userType))
         return Object;
     else if (userType < data->lists.size() && data->lists.testBit(userType))
         return List;
@@ -1684,10 +1881,10 @@ const char *QQmlMetaType::interfaceIId(int userType)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
-    QQmlType *type = data->idToType.value(userType);
+    QQmlType type = data->idToType.value(userType);
     lock.unlock();
-    if (type && type->isInterface() && type->typeId() == userType)
-        return type->interfaceIId();
+    if (type.isInterface() && type.typeId() == userType)
+        return type.interfaceIId();
     else
         return 0;
 }
@@ -1696,6 +1893,8 @@ bool QQmlMetaType::isList(int userType)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
+    if (data->qmlLists.contains(userType))
+        return true;
     return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
 }
 
@@ -1740,7 +1939,7 @@ QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
     Returns the type (if any) of URI-qualified named \a qualifiedName and version specified
     by \a version_major and \a version_minor.
 */
-QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor)
+QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor)
 {
     int slash = qualifiedName.indexOf(QLatin1Char('/'));
     if (slash <= 0)
@@ -1756,7 +1955,7 @@ QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major,
     Returns the type (if any) of \a name in \a module and version specified
     by \a version_major and \a version_minor.
 */
-QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
+QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
 {
     Q_ASSERT(version_major >= 0 && version_minor >= 0);
     QMutexLocker lock(metaTypeDataLock());
@@ -1764,20 +1963,21 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin
 
     QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name);
     while (it != data->nameToType.cend() && it.key() == name) {
+        QQmlType t(*it);
         // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
-        if (version_major < 0 || module.isEmpty() || (*it)->availableInVersion(module, version_major,version_minor))
-            return (*it);
+        if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor))
+            return t;
         ++it;
     }
 
-    return 0;
+    return QQmlType();
 }
 
 /*!
     Returns the type (if any) that corresponds to the \a metaObject.  Returns null if no
     type is registered.
 */
-QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
+QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
@@ -1790,7 +1990,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
     by \a version_major and \a version_minor in module specified by \a uri.  Returns null if no
     type is registered.
 */
-QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
+QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
 {
     Q_ASSERT(version_major >= 0 && version_minor >= 0);
     QMutexLocker lock(metaTypeDataLock());
@@ -1798,26 +1998,26 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri
 
     QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject);
     while (it != data->metaObjectToType.cend() && it.key() == metaObject) {
-        QQmlType *t = *it;
-        if (version_major < 0 || module.isEmpty() || t->availableInVersion(module, version_major,version_minor))
+        QQmlType t(*it);
+        if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor))
             return t;
         ++it;
     }
 
-    return 0;
+    return QQmlType();
 }
 
 /*!
     Returns the type (if any) that corresponds to the QVariant::Type \a userType.
     Returns null if no type is registered.
 */
-QQmlType *QQmlMetaType::qmlType(int userType)
+QQmlType QQmlMetaType::qmlType(int userType)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    QQmlType *type = data->idToType.value(userType);
-    if (type && type->typeId() == userType)
+    QQmlTypePrivate *type = data->idToType.value(userType);
+    if (type && type->typeId == userType)
         return type;
     else
         return 0;
@@ -1829,34 +2029,209 @@ QQmlType *QQmlMetaType::qmlType(int userType)
 
     Returns null if no such type is registered.
 */
-QQmlType *QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */)
+QQmlType QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */)
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    QQmlType *type = data->urlToType.value(url);
-    if (!type && includeNonFileImports)
+    QQmlType type(data->urlToType.value(url));
+    if (!type.isValid() && includeNonFileImports)
         type = data->urlToNonFileImportType.value(url);
 
-    if (type && type->sourceUrl() == url)
+    if (type.sourceUrl() == url)
         return type;
     else
+        return QQmlType();
+}
+
+QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject)
+{
+    if (QQmlPropertyCache *rv = propertyCaches.value(metaObject))
+        return rv;
+
+    if (!metaObject->superClass()) {
+        QQmlPropertyCache *rv = new QQmlPropertyCache(metaObject);
+        propertyCaches.insert(metaObject, rv);
+        return rv;
+    }
+    QQmlPropertyCache *super = propertyCache(metaObject->superClass());
+    QQmlPropertyCache *rv = super->copyAndAppend(metaObject);
+    propertyCaches.insert(metaObject, rv);
+    return rv;
+}
+
+QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject)
+{
+    QMutexLocker lock(metaTypeDataLock());
+    QQmlMetaTypeData *data = metaTypeData();
+    return data->propertyCache(metaObject);
+}
+
+QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion)
+{
+    Q_ASSERT(type.isValid());
+
+    if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(minorVersion))
+        return pc;
+
+    QVector<QQmlType> types;
+
+    int maxMinorVersion = 0;
+
+    const QMetaObject *metaObject = type.metaObject();
+
+    while (metaObject) {
+        QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion);
+        if (t.isValid()) {
+            maxMinorVersion = qMax(maxMinorVersion, t.minorVersion());
+            types << t;
+        } else {
+            types << 0;
+        }
+
+        metaObject = metaObject->superClass();
+    }
+
+    if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(maxMinorVersion)) {
+        const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, pc);
+        return pc;
+    }
+
+    QQmlPropertyCache *raw = propertyCache(type.metaObject());
+
+    bool hasCopied = false;
+
+    for (int ii = 0; ii < types.count(); ++ii) {
+        QQmlType currentType = types.at(ii);
+        if (!currentType.isValid())
+            continue;
+
+        int rev = currentType.metaObjectRevision();
+        int moIndex = types.count() - 1 - ii;
+
+        if (raw->allowedRevisionCache[moIndex] != rev) {
+            if (!hasCopied) {
+                raw = raw->copy();
+                hasCopied = true;
+            }
+            raw->allowedRevisionCache[moIndex] = rev;
+        }
+    }
+
+    // Test revision compatibility - the basic rule is:
+    //    * Anything that is excluded, cannot overload something that is not excluded *
+
+    // Signals override:
+    //    * other signals and methods of the same name.
+    //    * properties named on<Signal Name>
+    //    * automatic <property name>Changed notify signals
+
+    // Methods override:
+    //    * other methods of the same name
+
+    // Properties override:
+    //    * other elements of the same name
+
+#if 0
+    bool overloadError = false;
+    QString overloadName;
+
+    for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
+         !overloadError && iter != raw->stringCache.end();
+         ++iter) {
+
+        QQmlPropertyData *d = *iter;
+        if (raw->isAllowedInRevision(d))
+            continue; // Not excluded - no problems
+
+        // check that a regular "name" overload isn't happening
+        QQmlPropertyData *current = d;
+        while (!overloadError && current) {
+            current = d->overrideData(current);
+            if (current && raw->isAllowedInRevision(current))
+                overloadError = true;
+        }
+    }
+
+    if (overloadError) {
+        if (hasCopied) raw->release();
+
+        error.setDescription(QLatin1String("Type ") + type.qmlTypeName() + QLatin1Char(' ') + QString::number(type.majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
         return 0;
+    }
+#endif
+
+    const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, raw);
+
+    if (hasCopied)
+        raw->release();
+
+    if (minorVersion != maxMinorVersion)
+        const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(maxMinorVersion, raw);
+
+    return raw;
 }
 
-/*!
-    Returns the type (if any) with the given \a index in the global type store.
-    This is for use when you just got the index back from a qmlRegister function.
-    Returns null if the index is out of bounds.
-*/
-QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx)
+QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVersion)
+{
+    QMutexLocker lock(metaTypeDataLock());
+    QQmlMetaTypeData *data = metaTypeData();
+    return data->propertyCache(type, minorVersion);
+}
+
+void QQmlMetaType::freeUnusedTypesAndCaches()
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    if (idx < 0 || idx >= data->types.count())
-            return 0;
-    return data->types[idx];
+    {
+        bool deletedAtLeastOneType;
+        do {
+            deletedAtLeastOneType = false;
+            QList<QQmlType>::Iterator it = data->types.begin();
+            while (it != data->types.end()) {
+                const QQmlTypePrivate *d = (*it).priv();
+                if (d && d->refCount == 1) {
+                    deletedAtLeastOneType = true;
+
+                    removeQQmlTypePrivate(data->idToType, d);
+                    removeQQmlTypePrivate(data->nameToType, d);
+                    removeQQmlTypePrivate(data->urlToType, d);
+                    removeQQmlTypePrivate(data->urlToNonFileImportType, d);
+                    removeQQmlTypePrivate(data->metaObjectToType, d);
+
+                    for (QQmlMetaTypeData::TypeModules::Iterator module = data->uriToModule.begin(); module != data->uriToModule.end(); ++module) {
+                        QQmlTypeModulePrivate *modulePrivate = (*module)->priv();
+                        modulePrivate->remove(d);
+                    }
+
+                    *it = QQmlType();
+                } else {
+                    ++it;
+                }
+            }
+        } while (deletedAtLeastOneType);
+    }
+
+    {
+        bool deletedAtLeastOneCache;
+        do {
+            deletedAtLeastOneCache = false;
+            QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = data->propertyCaches.begin();
+            while (it != data->propertyCaches.end()) {
+
+                if ((*it)->count() == 1) {
+                    QQmlPropertyCache *pc = Q_NULLPTR;
+                    qSwap(pc, *it);
+                    it = data->propertyCaches.erase(it);
+                    pc->release();
+                    deletedAtLeastOneCache = true;
+                } else {
+                    ++it;
+                }
+            }
+        } while (deletedAtLeastOneCache);
+    }
 }
 
 /*!
@@ -1871,7 +2246,8 @@ QList<QString> QQmlMetaType::qmlTypeNames()
     names.reserve(data->nameToType.count());
     QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.cbegin();
     while (it != data->nameToType.cend()) {
-        names += (*it)->qmlTypeName();
+        QQmlType t(*it);
+        names += t.qmlTypeName();
         ++it;
     }
 
@@ -1881,18 +2257,22 @@ QList<QString> QQmlMetaType::qmlTypeNames()
 /*!
     Returns the list of registered QML types.
 */
-QList<QQmlType*> QQmlMetaType::qmlTypes()
+QList<QQmlType> QQmlMetaType::qmlTypes()
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    return data->nameToType.values();
+    QList<QQmlType> types;
+    foreach (QQmlTypePrivate *t, data->nameToType)
+        types.append(t);
+
+    return types;
 }
 
 /*!
     Returns the list of all registered types.
 */
-QList<QQmlType*> QQmlMetaType::qmlAllTypes()
+QList<QQmlType> QQmlMetaType::qmlAllTypes()
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
@@ -1903,17 +2283,17 @@ QList<QQmlType*> QQmlMetaType::qmlAllTypes()
 /*!
     Returns the list of registered QML singleton types.
 */
-QList<QQmlType*> QQmlMetaType::qmlSingletonTypes()
+QList<QQmlType> QQmlMetaType::qmlSingletonTypes()
 {
     QMutexLocker lock(metaTypeDataLock());
     QQmlMetaTypeData *data = metaTypeData();
 
-    QList<QQmlType*> alltypes = data->nameToType.values();
-    QList<QQmlType*> retn;
-    foreach (QQmlType* t, alltypes) {
-        if (t->isSingleton()) {
-            retn.append(t);
-        }
+    const QList<QQmlTypePrivate *> alltypes = data->nameToType.values();
+    QList<QQmlType> retn;
+    foreach (QQmlTypePrivate *t, alltypes) {
+        QQmlType type(t);
+        if (type.isSingleton())
+            retn.append(type);
     }
 
     return retn;
@@ -1941,9 +2321,9 @@ QString QQmlMetaType::prettyTypeName(const QObject *object)
     if (!object)
         return typeName;
 
-    const QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
-    if (type) {
-        typeName = type->qmlTypeName();
+    QQmlType type = QQmlMetaType::qmlType(object->metaObject());
+    if (type.isValid()) {
+        typeName = type.qmlTypeName();
         const int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
         if (lastSlash != -1)
             typeName = typeName.mid(lastSlash + 1);
@@ -1958,8 +2338,8 @@ QString QQmlMetaType::prettyTypeName(const QObject *object)
             typeName = typeName.left(marker);
             typeName += QLatin1Char('*');
             type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1()));
-            if (type) {
-                typeName = type->qmlTypeName();
+            if (type.isValid()) {
+                typeName = type.qmlTypeName();
                 const int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
                 if (lastSlash != -1)
                     typeName = typeName.mid(lastSlash + 1);
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index c120941a0..24649d8f7 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -64,24 +64,36 @@ class QQmlTypeModule;
 class QHashedString;
 class QHashedStringRef;
 class QMutex;
+class QQmlPropertyCache;
+class QQmlCompiledData;
 
 namespace QV4 { struct String; }
 
 class Q_QML_PRIVATE_EXPORT QQmlMetaType
 {
 public:
+    static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type);
+    static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type);
+
+    static void registerInternalCompositeType(QQmlCompiledData *data);
+    static void unregisterInternalCompositeType(QQmlCompiledData *data);
+
     static QList<QString> qmlTypeNames();
-    static QList<QQmlType*> qmlTypes();
-    static QList<QQmlType*> qmlSingletonTypes();
-    static QList<QQmlType*> qmlAllTypes();
-
-    static QQmlType *qmlType(const QString &qualifiedName, int, int);
-    static QQmlType *qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int);
-    static QQmlType *qmlType(const QMetaObject *);
-    static QQmlType *qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor);
-    static QQmlType *qmlType(int);
-    static QQmlType *qmlType(const QUrl &url, bool includeNonFileImports = false);
-    static QQmlType *qmlTypeFromIndex(int);
+    static QList<QQmlType> qmlTypes();
+    static QList<QQmlType> qmlSingletonTypes();
+    static QList<QQmlType> qmlAllTypes();
+
+    static QQmlType qmlType(const QString &qualifiedName, int, int);
+    static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int);
+    static QQmlType qmlType(const QMetaObject *);
+    static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor);
+    static QQmlType qmlType(int);
+    static QQmlType qmlType(const QUrl &url, bool includeNonFileImports = false);
+
+    static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject);
+    static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
+
+    static void freeUnusedTypesAndCaches();
 
     static QMetaProperty defaultProperty(const QMetaObject *);
     static QMetaProperty defaultProperty(QObject *);
@@ -132,11 +144,23 @@ class QHashedCStringRef;
 class Q_QML_PRIVATE_EXPORT QQmlType
 {
 public:
+    QQmlType();
+    QQmlType(const QQmlType &other);
+    QQmlType &operator =(const QQmlType &other);
+    ~QQmlType();
+
+    bool operator ==(const QQmlType &other) const {
+        return d == other.d;
+    }
+
+    bool isValid() const { return d != 0; }
+    const QQmlTypePrivate *key() const { return d; }
+
     QByteArray typeName() const;
-    const QString &qmlTypeName() const;
-    const QString &elementName() const;
+    QString qmlTypeName() const;
+    QString elementName() const;
 
-    const QHashedString &module() const;
+    QHashedString module() const;
     int majorVersion() const;
     int minorVersion() const;
 
@@ -210,12 +234,9 @@ public:
     int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const;
     int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const;
     int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
-private:
-    QQmlType *superType() const;
-    QQmlType *resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
-    int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
-    friend class QQmlTypePrivate;
-    friend struct QQmlMetaTypeData;
+
+    QQmlType(QQmlTypePrivate *d);
+    QQmlTypePrivate *priv() { return d; }
 
     enum RegistrationType {
         CppType = 0,
@@ -224,25 +245,37 @@ private:
         CompositeType = 3,
         CompositeSingletonType = 4
     };
+private:
+    QQmlType superType() const;
+    QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
+    int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
+    friend class QQmlTypePrivate;
+
     friend QString registrationTypeString(RegistrationType);
     friend bool checkRegistration(RegistrationType, QQmlMetaTypeData *, const char *, const QString &, int);
-    friend int registerType(const QQmlPrivate::RegisterType &);
-    friend int registerSingletonType(const QQmlPrivate::RegisterSingletonType &);
-    friend int registerInterface(const QQmlPrivate::RegisterInterface &);
-    friend int registerCompositeType(const QQmlPrivate::RegisterCompositeType &);
-    friend int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &);
+    friend QQmlType registerType(const QQmlPrivate::RegisterType &);
+    friend QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &);
+    friend QQmlType registerInterface(const QQmlPrivate::RegisterInterface &);
     friend int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &);
+    friend uint qHash(const QQmlType &t, uint seed);
     friend Q_QML_EXPORT void qmlClearTypeRegistrations();
-    QQmlType(int, const QQmlPrivate::RegisterInterface &);
-    QQmlType(int, const QString &, const QQmlPrivate::RegisterSingletonType &);
-    QQmlType(int, const QString &, const QQmlPrivate::RegisterType &);
-    QQmlType(int, const QString &, const QQmlPrivate::RegisterCompositeType &);
-    QQmlType(int, const QString &, const QQmlPrivate::RegisterCompositeSingletonType &);
-    ~QQmlType();
+    friend class QQmlMetaType;
+
+    QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &);
+    QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterSingletonType &);
+    QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterType &);
+    QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeType &);
+    QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeSingletonType &);
 
     QQmlTypePrivate *d;
 };
 
+Q_DECLARE_TYPEINFO(QQmlMetaType, Q_MOVABLE_TYPE);
+
+
+inline uint qHash(const QQmlType &t, uint seed = 0) { return qHash(reinterpret_cast<quintptr>(t.d), seed); }
+
+
 class QQmlTypeModulePrivate;
 class QQmlTypeModule
 {
@@ -253,14 +286,13 @@ public:
     int minimumMinorVersion() const;
     int maximumMinorVersion() const;
 
-    QQmlType *type(const QHashedStringRef &, int);
-    QQmlType *type(const QV4::String *, int);
-
-    QList<QQmlType*> singletonTypes(int) const;
+    QQmlType type(const QHashedStringRef &, int);
+    QQmlType type(const QV4::String *, int);
 
+    QQmlTypeModulePrivate *priv() { return d; }
 private:
     //Used by register functions and creates the QQmlTypeModule for them
-    friend void addTypeToData(QQmlType* type, QQmlMetaTypeData *data);
+    friend void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data);
     friend struct QQmlMetaTypeData;
     friend Q_QML_EXPORT void qmlClearTypeRegistrations();
     friend class QQmlTypeModulePrivate;
@@ -281,8 +313,8 @@ public:
     QQmlTypeModule *module() const;
     int minorVersion() const;
 
-    QQmlType *type(const QHashedStringRef &) const;
-    QQmlType *type(const QV4::String *) const;
+    QQmlType type(const QHashedStringRef &) const;
+    QQmlType type(const QV4::String *) const;
 
 private:
     QQmlTypeModule *m_module;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 8fa1f48d1..64c7b1318 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -640,11 +640,11 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
     }
 }
 
-static QQmlType *qmlTypeForObject(QObject *object)
+static QQmlType qmlTypeForObject(QObject *object)
 {
-    QQmlType *type = 0;
+    QQmlType type;
     const QMetaObject *mo = object->metaObject();
-    while (mo && !type) {
+    while (mo && !type.isValid()) {
         type = QQmlMetaType::qmlType(mo);
         mo = mo->superClass();
     }
@@ -681,7 +681,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
         } else if (binding) {
             QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
 
-            if (qmlTypeForObject(_bindingTarget)) {
+            if (qmlTypeForObject(_bindingTarget).isValid()) {
                 quint32 bindingSkipList = 0;
 
                 QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
@@ -731,15 +731,15 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
         Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
         QQmlCompiledData::TypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
         Q_ASSERT(tr);
-        QQmlType *attachedType = tr->type;
-        if (!attachedType) {
+        QQmlType attachedType = tr->type;
+        if (!attachedType.isValid()) {
             QQmlTypeNameCache::Result res = context->imports->query(stringAt(binding->propertyNameIndex));
             if (res.isValid())
                 attachedType = res.type;
             else
                 return false;
         }
-        const int id = attachedType->attachedPropertiesId(QQmlEnginePrivate::get(engine));
+        const int id = attachedType.attachedPropertiesId(QQmlEnginePrivate::get(engine));
         QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject);
         if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject, /*value type property*/0))
             return false;
@@ -868,21 +868,21 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
     if (binding->type == QV4::CompiledData::Binding::Type_Object) {
         if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
             // ### determine value source and interceptor casts ahead of time.
-            QQmlType *type = qmlTypeForObject(createdSubObject);
-            Q_ASSERT(type);
+            QQmlType type = qmlTypeForObject(createdSubObject);
+            Q_ASSERT(type.isValid());
 
             QQmlPropertyData targetCorePropertyData = *property;
             if (_valueTypeProperty)
                 targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
 
-            int valueSourceCast = type->propertyValueSourceCast();
+            int valueSourceCast = type.propertyValueSourceCast();
             if (valueSourceCast != -1) {
                 QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
                 QObject *target = createdSubObject->parent();
                 vs->setTarget(QQmlPropertyPrivate::restore(target, targetCorePropertyData, context));
                 return true;
             }
-            int valueInterceptorCast = type->propertyValueInterceptorCast();
+            int valueInterceptorCast = type.propertyValueInterceptorCast();
             if (valueInterceptorCast != -1) {
                 QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
                 QObject *target = createdSubObject->parent();
@@ -1065,21 +1065,21 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
         QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
         Q_ASSERT(typeRef);
         installPropertyCache = !typeRef->isFullyDynamicType;
-        QQmlType *type = typeRef->type;
-        if (type) {
-            Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(),
+        QQmlType type = typeRef->type;
+        if (type.isValid()) {
+            Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type.qmlTypeName(),
                     context->url(), obj->location.line, obj->location.column));
-            instance = type->create();
+            instance = type.create();
             if (!instance) {
                 recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
                 return 0;
             }
 
-            const int parserStatusCast = type->parserStatusCast();
+            const int parserStatusCast = type.parserStatusCast();
             if (parserStatusCast != -1)
                 parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast);
 
-            customParser = type->customParser();
+            customParser = type.customParser();
 
             if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation) {
                 QQmlData *ddata = QQmlData::get(instance, /*create*/true);
@@ -1307,7 +1307,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
     if (!data.isEmpty()) {
         Q_ASSERT(!cache.isNull());
         // install on _object
-        vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
+        vmeMetaObject = new QQmlVMEMetaObject(v4, _qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
         if (_ddata->propertyCache)
             _ddata->propertyCache->release();
         _ddata->propertyCache = cache;
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 0e60cae92..0cbc7da66 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -370,7 +370,7 @@ void QQmlOpenMetaObject::setCached(bool c)
     QQmlData *qmldata = QQmlData::get(d->object, true);
     if (d->cacheProperties) {
         if (!d->type->d->cache)
-            d->type->d->cache = new QQmlPropertyCache(QV8Engine::getV4(d->type->d->engine), this);
+            d->type->d->cache = new QQmlPropertyCache(this);
         qmldata->propertyCache = d->type->d->cache;
         d->type->d->cache->addref();
     } else {
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 1eaff6b60..2e0c4eb87 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -247,24 +247,24 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
         if (typeNameCache) {
             QQmlTypeNameCache::Result r = typeNameCache->query(pathName);
             if (r.isValid()) {
-                if (r.type) {
+                if (r.type.isValid()) {
                     QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
-                    QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(enginePrivate);
+                    QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
                     if (!func) return; // Not an attachable type
 
-                    currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(enginePrivate), currentObject);
+                    currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
                     if (!currentObject) return; // Something is broken with the attachable type
                 } else if (r.importNamespace) {
                     if ((ii + 1) == path.count()) return; // No type following the namespace
 
                     ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace);
-                    if (!r.type) return; // Invalid type in namespace
+                    if (!r.type.isValid()) return; // Invalid type in namespace
 
                     QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
-                    QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(enginePrivate);
+                    QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
                     if (!func) return; // Not an attachable type
 
-                    currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(enginePrivate), currentObject);
+                    currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
                     if (!currentObject) return; // Something is broken with the attachable type
 
                 } else if (r.scriptIndex != -1) {
@@ -1283,9 +1283,10 @@ bool QQmlPropertyPrivate::write(QObject *object,
         if (enginePriv) {
             listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType));
         } else {
-            QQmlType *type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType));
-            if (!type) return false;
-            listType = type->baseMetaObject();
+            QQmlType type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType));
+            if (!type.isValid())
+                return false;
+            listType = type.baseMetaObject();
         }
         if (listType.isNull()) return false;
 
@@ -1405,9 +1406,9 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi
         return metaType.metaObject();
     if (engine)
         return engine->rawMetaObjectForType(userType);
-    QQmlType *type = QQmlMetaType::qmlType(userType);
-    if (type)
-        return QQmlMetaObject(type->baseMetaObject());
+    QQmlType type = QQmlMetaType::qmlType(userType);
+    if (type.isValid())
+        return QQmlMetaObject(type.baseMetaObject());
     return QQmlMetaObject((QObject*)0);
 }
 
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index e8c9989fd..e3fe78134 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -95,7 +95,7 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p)
 
 // Flags that do depend on the property's QMetaProperty::userType() and thus are slow to
 // load
-static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *engine)
+static QQmlPropertyData::Flags flagsForPropertyType(int propType)
 {
     Q_ASSERT(propType != -1);
 
@@ -113,9 +113,7 @@ static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *en
     } else if (propType == qMetaTypeId<QQmlV4Handle>()) {
         flags |= QQmlPropertyData::IsV4Handle;
     } else {
-        QQmlMetaType::TypeCategory cat =
-            engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType)
-                   : QQmlMetaType::typeCategory(propType);
+        QQmlMetaType::TypeCategory cat = QQmlMetaType::typeCategory(propType);
 
         if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject)
             flags |= QQmlPropertyData::IsQObjectDerived;
@@ -135,9 +133,9 @@ static int metaObjectSignalCount(const QMetaObject *metaObject)
 }
 
 QQmlPropertyData::Flags
-QQmlPropertyData::flagsForProperty(const QMetaProperty &p, QQmlEngine *engine)
+QQmlPropertyData::flagsForProperty(const QMetaProperty &p)
 {
-    return fastFlagsForProperty(p) | flagsForPropertyType(p.userType(), engine);
+    return fastFlagsForProperty(p) | flagsForPropertyType(p.userType());
 }
 
 void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
@@ -166,10 +164,11 @@ void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
 
 void QQmlPropertyData::load(const QMetaProperty &p, QQmlEngine *engine)
 {
+    Q_UNUSED(engine);
     propType = p.userType();
     coreIndex = p.propertyIndex();
     notifyIndex = QMetaObjectPrivate::signalIndex(p.notifySignal());
-    flags = fastFlagsForProperty(p) | flagsForPropertyType(propType, engine);
+    flags = fastFlagsForProperty(p) | flagsForPropertyType(propType);
     Q_ASSERT(p.revision() <= Q_INT16_MAX);
     revision = p.revision();
 }
@@ -231,23 +230,21 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
 /*!
 Creates a new empty QQmlPropertyCache.
 */
-QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e)
-    : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+QQmlPropertyCache::QQmlPropertyCache()
+    : _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
       signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
       _metaObject(0), argumentsCache(0)
 {
-    Q_ASSERT(engine);
 }
 
 /*!
 Creates a new QQmlPropertyCache of \a metaObject.
 */
-QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject *metaObject)
-    : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject)
+    : _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
       signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
       _metaObject(0), argumentsCache(0)
 {
-    Q_ASSERT(engine);
     Q_ASSERT(metaObject);
 
     update(metaObject);
@@ -255,8 +252,6 @@ QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject
 
 QQmlPropertyCache::~QQmlPropertyCache()
 {
-    clear();
-
     QQmlPropertyCacheMethodArguments *args = argumentsCache;
     while (args) {
         QQmlPropertyCacheMethodArguments *next = args->next;
@@ -274,24 +269,11 @@ QQmlPropertyCache::~QQmlPropertyCache()
     if (_ownMetaObject) free(const_cast<QMetaObject *>(_metaObject));
     _metaObject = 0;
     _parent = 0;
-    engine = 0;
-}
-
-void QQmlPropertyCache::destroy()
-{
-    delete this;
-}
-
-// This is inherited from QQmlCleanup, so it should only clear the things
-// that are tied to the specific QQmlEngine.
-void QQmlPropertyCache::clear()
-{
-    engine = 0;
 }
 
 QQmlPropertyCache *QQmlPropertyCache::copy(int reserve)
 {
-    QQmlPropertyCache *cache = new QQmlPropertyCache(engine);
+    QQmlPropertyCache *cache = new QQmlPropertyCache();
     cache->_parent = this;
     cache->_parent->addref();
     cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart;
@@ -449,7 +431,12 @@ QQmlPropertyCache *QQmlPropertyCache::parent() const
 
 void QQmlPropertyCache::setParent(QQmlPropertyCache *newParent)
 {
+    if (_parent == newParent)
+        return;
+    if (_parent)
+        _parent->release();
     _parent = newParent;
+    _parent->addref();
 }
 
 // Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
@@ -735,7 +722,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
                 data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
             }
         }
-        data->flags |= flagsForPropertyType(data->propType, engine->qmlEngine());
+        data->flags |= flagsForPropertyType(data->propType);
     }
 
     data->flags &= ~QQmlPropertyData::NotFullyResolved;
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 610709ef7..5a782e4f6 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -224,7 +224,7 @@ public:
 
     inline bool operator==(const QQmlPropertyRawData &);
 
-    static Flags flagsForProperty(const QMetaProperty &, QQmlEngine *engine = 0);
+    static Flags flagsForProperty(const QMetaProperty &);
     void load(const QMetaProperty &, QQmlEngine *engine = 0);
     void load(const QMetaMethod &);
     QString name(QObject *) const;
@@ -240,11 +240,11 @@ private:
 };
 
 class QQmlPropertyCacheMethodArguments;
-class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
+class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount
 {
 public:
-    QQmlPropertyCache(QV4::ExecutionEngine *);
-    QQmlPropertyCache(QV4::ExecutionEngine *, const QMetaObject *);
+    QQmlPropertyCache();
+    QQmlPropertyCache(const QMetaObject *);
     virtual ~QQmlPropertyCache();
 
     void update(const QMetaObject *);
@@ -322,16 +322,13 @@ public:
 
     void toMetaObjectBuilder(QMetaObjectBuilder &);
 
-protected:
-    virtual void destroy();
-    virtual void clear();
-
 private:
     friend class QQmlEnginePrivate;
     friend class QQmlCompiler;
     friend class QQmlPropertyCacheCreator;
     friend class QQmlComponentAndAliasResolver;
     friend class QQmlMetaObject;
+    friend struct QQmlMetaTypeData;
 
     inline QQmlPropertyCache *copy(int reserve);
 
@@ -368,9 +365,6 @@ private:
         _hasPropertyOverrides |= isOverride;
     }
 
-public:
-    QV4::ExecutionEngine *engine;
-
 private:
     QQmlPropertyCache *_parent;
     int propertyIndexCacheStart;
@@ -392,6 +386,8 @@ private:
     QQmlPropertyCacheMethodArguments *argumentsCache;
 };
 
+typedef QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCachePtr;
+
 // QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
 // This is necessary as we delay creation of QMetaObject for synthesized QObjects, but
 // we don't want to needlessly generate QQmlPropertyCaches every time we encounter a
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 648042021..988bfbdf6 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1434,8 +1434,8 @@ bool QQmlTypeLoader::Blob::addPragma(const QmlIR::Pragma &pragma, QList<QQmlErro
     if (pragma.type == QmlIR::Pragma::PragmaSingleton) {
         QUrl myUrl = finalUrl();
 
-        QQmlType *ret = QQmlMetaType::qmlType(myUrl, true);
-        if (!ret) {
+        QQmlType ret = QQmlMetaType::qmlType(myUrl, true);
+        if (!ret.isValid()) {
             QQmlError error;
             error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
             error.setUrl(myUrl);
@@ -1445,9 +1445,9 @@ bool QQmlTypeLoader::Blob::addPragma(const QmlIR::Pragma &pragma, QList<QQmlErro
             return false;
         }
 
-        if (!ret->isCompositeSingleton()) {
+        if (!ret.isCompositeSingleton()) {
             QQmlError error;
-            error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(ret->qmlTypeName()));
+            error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(ret.qmlTypeName()));
             error.setUrl(myUrl);
             error.setLine(pragma.location.line);
             error.setColumn(pragma.location.column);
@@ -1775,23 +1775,21 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path)
 #endif
 
     int lastSlash = path.lastIndexOf(QLatin1Char('/'));
-    QStringRef dirPath(&path, 0, lastSlash);
+    QString dirPath(path.left(lastSlash));
 
-    StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length()));
-    if (!fileSet) {
-        QHashedString dirPathString(dirPath.toString());
-        bool exists = QDir(dirPathString).exists();
-        QStringHash<bool> *files = exists ? new QStringHash<bool> : 0;
-        m_importDirCache.insert(dirPathString, files);
-        fileSet = m_importDirCache.value(dirPathString);
+    if (!m_importDirCache.contains(dirPath)) {
+        bool exists = QDir(dirPath).exists();
+        QCache<QString, bool> *entry = exists ? new QCache<QString, bool> : 0;
+        m_importDirCache.insert(dirPath, entry);
     }
-    if (!(*fileSet))
+    QCache<QString, bool> *fileSet = m_importDirCache.object(dirPath);
+    if (!fileSet)
         return QString();
 
     QString absoluteFilePath;
-    QHashedStringRef fileName(path.constData()+lastSlash+1, path.length()-lastSlash-1);
+    QString fileName(path.mid(lastSlash+1, path.length()-lastSlash-1));
 
-    bool *value = (*fileSet)->value(fileName);
+    bool *value = fileSet->object(fileName);
     if (value) {
         if (*value)
             absoluteFilePath = path;
@@ -1805,7 +1803,7 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path)
 #else
         exists = QFile::exists(path);
 #endif
-        (*fileSet)->insert(fileName.toString(), exists);
+        fileSet->insert(fileName, new bool(exists));
         if (exists)
             absoluteFilePath = path;
     }
@@ -1840,18 +1838,16 @@ bool QQmlTypeLoader::directoryExists(const QString &path)
     int length = path.length();
     if (path.endsWith(QLatin1Char('/')))
         --length;
-    QStringRef dirPath(&path, 0, length);
+    QString dirPath(path.left(length));
 
-    StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length()));
-    if (!fileSet) {
-        QHashedString dirPathString(dirPath.toString());
-        bool exists = QDir(dirPathString).exists();
-        QStringHash<bool> *files = exists ? new QStringHash<bool> : 0;
-        m_importDirCache.insert(dirPathString, files);
-        fileSet = m_importDirCache.value(dirPathString);
+    if (!m_importDirCache.contains(dirPath)) {
+        bool exists = QDir(dirPath).exists();
+        QCache<QString, bool> *files = exists ? new QCache<QString, bool> : 0;
+        m_importDirCache.insert(dirPath, files);
     }
 
-    return (*fileSet);
+    QCache<QString, bool> *fileSet = m_importDirCache.object(dirPath);
+    return fileSet != 0;
 }
 
 
@@ -1935,7 +1931,7 @@ void QQmlTypeLoader::clearCache()
         (*iter)->release();
     for (QmldirCache::Iterator iter = m_qmldirCache.begin(), end = m_qmldirCache.end(); iter != end; ++iter)
         (*iter)->release();
-    qDeleteAll(m_importDirCache);
+
     qDeleteAll(m_importQmlDirCache);
 
     m_typeCache.clear();
@@ -1944,6 +1940,7 @@ void QQmlTypeLoader::clearCache()
     m_qmldirCache.clear();
     m_importDirCache.clear();
     m_importQmlDirCache.clear();
+    QQmlMetaType::freeUnusedTypesAndCaches();
 }
 
 void QQmlTypeLoader::updateTypeCacheTrimThreshold()
@@ -1984,6 +1981,8 @@ void QQmlTypeLoader::trimCache()
 
     updateTypeCacheTrimThreshold();
 
+    QQmlMetaType::freeUnusedTypesAndCaches();
+
     // TODO: release any scripts which are no longer referenced by any types
 }
 
@@ -2103,7 +2102,7 @@ void QQmlTypeData::done()
         const TypeReference &type = m_compositeSingletons.at(ii);
         Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
         if (type.typeData && type.typeData->isError()) {
-            QString typeName = type.type->qmlTypeName();
+            QString typeName = type.type.qmlTypeName();
 
             QList<QQmlError> errors = type.typeData->errors();
             QQmlError error;
@@ -2118,9 +2117,9 @@ void QQmlTypeData::done()
 
     // If the type is CompositeSingleton but there was no pragma Singleton in the
     // QML file, lets report an error.
-    QQmlType *type = QQmlMetaType::qmlType(url(), true);
-    if (!isError() && type && type->isCompositeSingleton() && !m_isSingleton) {
-        QString typeName = type->qmlTypeName();
+    QQmlType type = QQmlMetaType::qmlType(url(), true);
+    if (!isError() && type.isCompositeSingleton() && !m_isSingleton) {
+        QString typeName = type.qmlTypeName();
 
         QQmlError error;
         error.setDescription(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
@@ -2347,8 +2346,8 @@ void QQmlTypeData::resolveTypes()
         if (!resolveType(typeName, majorVersion, minorVersion, ref))
             return;
 
-        if (ref.type->isCompositeSingleton()) {
-            ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
+        if (ref.type.isCompositeSingleton()) {
+            ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
             addDependency(ref.typeData);
             ref.prefix = csRef.prefix;
 
@@ -2410,8 +2409,8 @@ void QQmlTypeData::resolveTypes()
             return;
         }
 
-        if (ref.type && ref.type->isComposite()) {
-            ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
+        if (ref.type.isComposite()) {
+            ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
             addDependency(ref.typeData);
         }
         ref.majorVersion = majorVersion;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index f565bcd31..476570c54 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -47,6 +47,7 @@
 
 #include <QtCore/qobject.h>
 #include <QtCore/qatomic.h>
+#include <QtCore/qcache.h>
 #include <QtNetwork/qnetworkreply.h>
 #include <QtQml/qqmlerror.h>
 #include <QtQml/qqmlengine.h>
@@ -350,8 +351,7 @@ private:
     typedef QHash<QUrl, QQmlTypeData *> TypeCache;
     typedef QHash<QUrl, QQmlScriptBlob *> ScriptCache;
     typedef QHash<QUrl, QQmlQmldirData *> QmldirCache;
-    typedef QStringHash<bool> StringSet;
-    typedef QStringHash<StringSet*> ImportDirCache;
+    typedef QCache<QString, QCache<QString, bool> > ImportDirCache;
     typedef QStringHash<QmldirContent *> ImportQmlDirCache;
 
     QQmlEngine *m_engine;
@@ -378,10 +378,10 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
 public:
     struct TypeReference
     {
-        TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0), needsCreation(true) {}
+        TypeReference() : majorVersion(0), minorVersion(0), typeData(0), needsCreation(true) {}
 
         QV4::CompiledData::Location location;
-        QQmlType *type;
+        QQmlType type;
         int majorVersion;
         int minorVersion;
         QQmlTypeData *typeData;
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index 23cc12c89..b90771956 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -48,7 +48,7 @@ QQmlTypeNameCache::~QQmlTypeNameCache()
 void QQmlTypeNameCache::add(const QHashedString &name, const QUrl &url, const QHashedString &nameSpace)
 {
     if (nameSpace.length() != 0) {
-        Import *i = m_namedImports.value(nameSpace);
+        QQmlImportRef *i = m_namedImports.value(nameSpace);
         Q_ASSERT(i != 0);
         i->compositeSingletons.insert(name, url);
         return;
@@ -62,11 +62,11 @@ void QQmlTypeNameCache::add(const QHashedString &name, const QUrl &url, const QH
 
 void QQmlTypeNameCache::add(const QHashedString &name, int importedScriptIndex, const QHashedString &nameSpace)
 {
-    Import import;
+    QQmlImportRef import;
     import.scriptIndex = importedScriptIndex;
 
     if (nameSpace.length() != 0) {
-        Import *i = m_namedImports.value(nameSpace);
+        QQmlImportRef *i = m_namedImports.value(nameSpace);
         Q_ASSERT(i != 0);
         m_namespacedImports[i].insert(name, import);
         return;
@@ -91,17 +91,14 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name)
     return result;
 }
 
-QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name,
-                                                                   const void *importNamespace)
+QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name, const QQmlImportRef *importNamespace)
 {
-    Q_ASSERT(importNamespace);
-    const Import *i = static_cast<const Import *>(importNamespace);
-    Q_ASSERT(i->scriptIndex == -1);
+    Q_ASSERT(importNamespace && importNamespace->scriptIndex == -1);
 
-    Result result = typeSearch(i->modules, name);
+    Result result = typeSearch(importNamespace->modules, name);
 
     if (!result.isValid())
-        result = query(i->compositeSingletons, name);
+        result = query(importNamespace->compositeSingletons, name);
 
     return result;
 }
@@ -119,23 +116,21 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name)
     return result;
 }
 
-QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, const void *importNamespace)
+QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, const QQmlImportRef *importNamespace)
 {
-    Q_ASSERT(importNamespace);
-    const Import *i = static_cast<const Import *>(importNamespace);
-    Q_ASSERT(i->scriptIndex == -1);
+    Q_ASSERT(importNamespace && importNamespace->scriptIndex == -1);
 
-    QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.constFind(i);
+    QMap<const QQmlImportRef *, QStringHash<QQmlImportRef> >::const_iterator it = m_namespacedImports.constFind(importNamespace);
     if (it != m_namespacedImports.constEnd()) {
         Result r = query(*it, name);
         if (r.isValid())
             return r;
     }
 
-    Result r = typeSearch(i->modules, name);
+    Result r = typeSearch(importNamespace->modules, name);
 
     if (!r.isValid())
-        r = query(i->compositeSingletons, name);
+        r = query(importNamespace->compositeSingletons, name);
 
     return r;
 }
diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h
index 9c62a55fa..78c527554 100644
--- a/src/qml/qml/qqmltypenamecache_p.h
+++ b/src/qml/qml/qqmltypenamecache_p.h
@@ -55,6 +55,20 @@
 
 QT_BEGIN_NAMESPACE
 
+struct QQmlImportRef {
+    inline QQmlImportRef()
+        : scriptIndex(-1)
+    {}
+    // Imported module
+    QVector<QQmlTypeModuleVersion> modules;
+
+    // Or, imported script
+    int scriptIndex;
+
+    // Or, imported compositeSingletons
+    QStringHash<QUrl> compositeSingletons;
+};
+
 class QQmlType;
 class QQmlEngine;
 class QQmlTypeNameCache : public QQmlRefCount
@@ -70,46 +84,34 @@ public:
 
     struct Result {
         inline Result();
-        inline Result(const void *importNamespace);
-        inline Result(QQmlType *type);
+        inline Result(const QQmlImportRef *importNamespace);
+        inline Result(const QQmlType &type);
         inline Result(int scriptIndex);
         inline Result(const Result &);
 
         inline bool isValid() const;
 
-        QQmlType *type;
-        const void *importNamespace;
+        QQmlType type;
+        const QQmlImportRef *importNamespace;
         int scriptIndex;
     };
     Result query(const QHashedStringRef &);
-    Result query(const QHashedStringRef &, const void *importNamespace);
+    Result query(const QHashedStringRef &, const QQmlImportRef *importNamespace);
     Result query(const QV4::String *);
-    Result query(const QV4::String *, const void *importNamespace);
+    Result query(const QV4::String *, const QQmlImportRef *importNamespace);
 
 private:
     friend class QQmlImports;
 
-    struct Import {
-        inline Import();
-        // Imported module
-        QVector<QQmlTypeModuleVersion> modules;
-
-        // Or, imported script
-        int scriptIndex;
-
-        // Or, imported compositeSingletons
-        QStringHash<QUrl> compositeSingletons;
-    };
-
     template<typename Key>
-    Result query(const QStringHash<Import> &imports, Key key)
+    Result query(const QStringHash<QQmlImportRef> &imports, Key key)
     {
-        Import *i = imports.value(key);
+        QQmlImportRef *i = imports.value(key);
         if (i) {
             if (i->scriptIndex != -1) {
                 return Result(i->scriptIndex);
             } else {
-                return Result(static_cast<const void *>(i));
+                return Result(i);
             }
         }
 
@@ -121,9 +123,8 @@ private:
     {
         QUrl *url = urls.value(key);
         if (url) {
-            QQmlType *type = QQmlMetaType::qmlType(*url);
-            if (type)
-                return Result(type);
+            QQmlType type = QQmlMetaType::qmlType(*url);
+            return Result(type);
         }
 
         return Result();
@@ -134,36 +135,37 @@ private:
     {
         QVector<QQmlTypeModuleVersion>::const_iterator end = modules.constEnd();
         for (QVector<QQmlTypeModuleVersion>::const_iterator it = modules.constBegin(); it != end; ++it) {
-            if (QQmlType *type = it->type(key))
+            QQmlType type = it->type(key);
+            if (type.isValid())
                 return Result(type);
         }
 
         return Result();
     }
 
-    QStringHash<Import> m_namedImports;
-    QMap<const Import *, QStringHash<Import> > m_namespacedImports;
+    QStringHash<QQmlImportRef> m_namedImports;
+    QMap<const QQmlImportRef *, QStringHash<QQmlImportRef> > m_namespacedImports;
     QVector<QQmlTypeModuleVersion> m_anonymousImports;
     QStringHash<QUrl> m_anonymousCompositeSingletons;
 };
 
 QQmlTypeNameCache::Result::Result()
-: type(0), importNamespace(0), scriptIndex(-1)
+: importNamespace(0), scriptIndex(-1)
 {
 }
 
-QQmlTypeNameCache::Result::Result(const void *importNamespace)
-: type(0), importNamespace(importNamespace), scriptIndex(-1)
+QQmlTypeNameCache::Result::Result(const QQmlImportRef *importNamespace)
+: importNamespace(importNamespace), scriptIndex(-1)
 {
 }
 
-QQmlTypeNameCache::Result::Result(QQmlType *type)
+QQmlTypeNameCache::Result::Result(const QQmlType &type)
 : type(type), importNamespace(0), scriptIndex(-1)
 {
 }
 
 QQmlTypeNameCache::Result::Result(int scriptIndex)
-: type(0), importNamespace(0), scriptIndex(scriptIndex)
+: importNamespace(0), scriptIndex(scriptIndex)
 {
 }
 
@@ -174,12 +176,7 @@ QQmlTypeNameCache::Result::Result(const Result &o)
 
 bool QQmlTypeNameCache::Result::isValid() const
 {
-    return type || importNamespace || scriptIndex != -1;
-}
-
-QQmlTypeNameCache::Import::Import()
-: scriptIndex(-1)
-{
+    return type.isValid() || importNamespace || scriptIndex != -1;
 }
 
 bool QQmlTypeNameCache::isEmpty() const
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 7ae8332ec..9cc9fb37f 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -61,7 +61,7 @@ Heap::QmlTypeWrapper::~QmlTypeWrapper()
 
 bool QmlTypeWrapper::isSingleton() const
 {
-    return d()->type && d()->type->isSingleton();
+    return d()->type.isSingleton();
 }
 
 QObject* QmlTypeWrapper::singletonObject() const
@@ -70,22 +70,16 @@ QObject* QmlTypeWrapper::singletonObject() const
         return 0;
 
     QQmlEngine *e = engine()->qmlEngine();
-    QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo();
+    QQmlType::SingletonInstanceInfo *siinfo = d()->type.singletonInstanceInfo();
     siinfo->init(e);
     return siinfo->qobjectApi(e);
 }
 
 QVariant QmlTypeWrapper::toVariant() const
 {
-    if (d()->type && d()->type->isSingleton()) {
-        QQmlEngine *e = engine()->qmlEngine();
-        QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo();
-        siinfo->init(e); // note: this will also create QJSValue singleton which isn't strictly required.
-        QObject *qobjectSingleton = siinfo->qobjectApi(e);
-        if (qobjectSingleton) {
-            return QVariant::fromValue<QObject*>(qobjectSingleton);
-        }
-    }
+    QObject *qobjectSingleton = singletonObject();
+    if (qobjectSingleton)
+        return QVariant::fromValue<QObject*>(qobjectSingleton);
 
     // only QObject Singleton Type can be converted to a variant.
     return QVariant();
@@ -93,10 +87,10 @@ QVariant QmlTypeWrapper::toVariant() const
 
 
 // Returns a type wrapper for type t on o.  This allows access of enums, and attached properties.
-ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t,
+ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, const QQmlType &t,
                                      Heap::QmlTypeWrapper::TypeNameMode mode)
 {
-    Q_ASSERT(t);
+    Q_ASSERT(t.isValid());
     Scope scope(engine);
 
     Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>());
@@ -106,7 +100,7 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
 
 // Returns a type wrapper for importNamespace (of t) on o.  This allows nested resolution of a type in a
 // namespace.
-ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace,
+ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const QQmlImportRef *importNamespace,
                                      Heap::QmlTypeWrapper::TypeNameMode mode)
 {
     Q_ASSERT(t);
@@ -134,11 +128,11 @@ static int enumForSingleton(String *name, QObject *qobjectSingleton)
     return -1;
 }
 
-static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *name, QQmlType *type)
+static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *name, const QQmlType &type)
 {
     const QString message =
             QStringLiteral("Cannot access enum value '%1' of '%2', enum values need to start with an uppercase letter.")
-                .arg(name->toQString()).arg(QLatin1String(type->typeName()));
+                .arg(name->toQString()).arg(QLatin1String(type.typeName()));
     return v4->throwTypeError(message);
 }
 
@@ -157,14 +151,14 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
     QQmlContextData *context = v4->callingQmlContext();
 
     QObject *object = w->d()->object;
-    QQmlType *type = w->d()->type;
+    QQmlType type = w->d()->type;
 
-    if (type) {
+    if (type.isValid()) {
 
         // singleton types are handled differently to other types.
-        if (type->isSingleton()) {
+        if (type.isSingleton()) {
             QQmlEngine *e = v4->qmlEngine();
-            QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
+            QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
             siinfo->init(e);
 
             QObject *qobjectSingleton = siinfo->qobjectApi(e);
@@ -205,14 +199,14 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
 
             if (name->startsWithUpper()) {
                 bool ok = false;
-                int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
+                int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
                 if (ok)
                     return QV4::Primitive::fromInt32(value).asReturnedValue();
 
                 // Fall through to base implementation
 
             } else if (w->d()->object) {
-                QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(v4->qmlEngine())), object);
+                QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(v4->qmlEngine())), object);
                 if (ao)
                     return QV4::QObjectWrapper::getQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
 
@@ -229,7 +223,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
         QQmlTypeNameCache::Result r = w->d()->typeNamespace->query(name, w->d()->importNamespace);
 
         if (r.isValid()) {
-            if (r.type) {
+            if (r.type.isValid()) {
                 return create(scope.engine, object, r.type, w->d()->mode);
             } else if (r.scriptIndex != -1) {
                 QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
@@ -254,9 +248,9 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
         *hasProperty = ok;
 
     // Warn when attempting to access a lowercased enum value, non-singleton case
-    if (!ok && type && !type->isSingleton() && !name->startsWithUpper()) {
+    if (!ok && type.isValid() && !type.isSingleton() && !name->startsWithUpper()) {
         bool enumOk = false;
-        type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &enumOk);
+        type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &enumOk);
         if (enumOk)
             return throwLowercaseEnumError(v4, name, type);
     }
@@ -276,16 +270,16 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
     QV4::Scope scope(v4);
     QQmlContextData *context = v4->callingQmlContext();
 
-    QQmlType *type = w->d()->type;
-    if (type && !type->isSingleton() && w->d()->object) {
+    QQmlType type = w->d()->type;
+    if (type.isValid() && !type.isSingleton() && w->d()->object) {
         QObject *object = w->d()->object;
         QQmlEngine *e = scope.engine->qmlEngine();
-        QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(e)), object);
+        QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(e)), object);
         if (ao)
             QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
-    } else if (type && type->isSingleton()) {
+    } else if (type.isSingleton()) {
         QQmlEngine *e = scope.engine->qmlEngine();
-        QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
+        QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
         siinfo->init(e);
 
         QObject *qobjectSingleton = siinfo->qobjectApi(e);
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index e67b457c5..687693cf8 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -71,9 +71,9 @@ struct QmlTypeWrapper : Object {
     TypeNameMode mode;
     QPointer<QObject> object;
 
-    QQmlType *type;
+    QQmlType type;
     QQmlTypeNameCache *typeNamespace;
-    const void *importNamespace;
+    const QQmlImportRef *importNamespace;
 };
 
 }
@@ -88,9 +88,9 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object
 
     QVariant toVariant() const;
 
-    static ReturnedValue create(ExecutionEngine *, QObject *, QQmlType *,
+    static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlType &,
                                 Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
-    static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const void *,
+    static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const QQmlImportRef *,
                                 Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
 
 
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index aed5f5af3..7f1c309ba 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -270,14 +270,17 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje
     return this;
 }
 
-QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
+QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine,
+                                     QObject *obj,
                                      QQmlPropertyCache *cache,
                                      const QQmlVMEMetaData *meta)
     : QQmlInterceptorMetaObject(obj, cache),
+      engine(engine),
       ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta),
       aliasEndpoints(0),
       methods(0)
 {
+    Q_ASSERT(engine);
     cache->addref();
 
     QQmlData::get(obj)->hasVMEMetaObject = true;
@@ -353,56 +356,56 @@ void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = cache->engine->newString(v);
+        *(md->data() + id) = engine->newString(v);
 }
 
 void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+        *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
 }
 
 void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+        *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
 }
 
 void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+        *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
 }
 
 void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+        *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
 }
 
 void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+        *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
 }
 
 void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+        *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
 }
 
 void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
 {
     QV4::MemberData *md = propertiesAsMemberData();
     if (md)
-        *(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
+        *(md->data() + id) = QV4::QObjectWrapper::wrap(engine, v);
 
     QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
     if (v && !guard) {
@@ -419,7 +422,7 @@ int QQmlVMEMetaObject::readPropertyAsInt(int id)
     if (!md)
         return 0;
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     if (!sv->isInt32())
         return 0;
@@ -432,7 +435,7 @@ bool QQmlVMEMetaObject::readPropertyAsBool(int id)
     if (!md)
         return false;
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     if (!sv->isBoolean())
         return false;
@@ -445,7 +448,7 @@ double QQmlVMEMetaObject::readPropertyAsDouble(int id)
     if (!md)
         return 0.0;
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     if (!sv->isDouble())
         return 0.0;
@@ -458,7 +461,7 @@ QString QQmlVMEMetaObject::readPropertyAsString(int id)
     if (!md)
         return QString();
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     if (!sv->isString())
         return QString();
@@ -471,7 +474,7 @@ QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
     if (!md)
         return QUrl();
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
     if (!v || v->d()->data.type() != QVariant::Url)
@@ -485,7 +488,7 @@ QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
     if (!md)
         return QDate();
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
     if (!v || v->d()->data.type() != QVariant::Date)
@@ -499,7 +502,7 @@ QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
     if (!md)
         return QDateTime();
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
     if (!v || v->d()->data.type() != QVariant::DateTime)
@@ -513,7 +516,7 @@ QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
     if (!md)
         return QSizeF();
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
     if (!v || v->d()->data.type() != QVariant::SizeF)
@@ -527,7 +530,7 @@ QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
     if (!md)
         return QPointF();
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
     if (!v || v->d()->data.type() != QVariant::PointF)
@@ -541,7 +544,7 @@ QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
     if (!md)
         return 0;
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     const QV4::QObjectWrapper *wrapper = sv->as<QV4::QObjectWrapper>();
     if (!wrapper)
@@ -555,11 +558,11 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id)
     if (!md)
         return 0;
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::Scoped<QV4::VariantObject> v(scope, *(md->data() + id));
     if (!v || (int)v->d()->data.userType() != qMetaTypeId<QList<QObject *> >()) {
         QVariant variant(qVariantFromValue(QList<QObject*>()));
-        v = cache->engine->newVariantObject(variant);
+        v = engine->newVariantObject(variant);
         *(md->data() + id) = v;
     }
     return static_cast<QList<QObject *> *>(v->d()->data.data());
@@ -571,7 +574,7 @@ QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id)
     if (!md)
         return QRectF();
 
-    QV4::Scope scope(cache->engine);
+    QV4::Scope scope(engine);
     QV4::ScopedValue sv(scope, *(md->data() + id));
     const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
     if (!v || v->d()->data.type() != QVariant::RectF)
@@ -730,7 +733,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
                             if (md) {
                                 QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
                                 if (!v) {
-                                    *(md->data() + id) = cache->engine->newVariantObject(QVariant());
+                                    *(md->data() + id) = engine->newVariantObject(QVariant());
                                     v = (md->data() + id)->as<QV4::VariantObject>();
                                     QQml_valueTypeProvider()->initValueType(t, v->d()->data);
                                 }
@@ -909,7 +912,7 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
         const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
         if (v)
             return v->d()->data;
-        return cache->engine->toVariant(*(md->data() + id), -1);
+        return engine->toVariant(*(md->data() + id), -1);
     }
     return QVariant();
 }
@@ -969,8 +972,8 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
 
         // And, if the new value is a scarce resource, we need to ensure that it does not get
         // automatically released by the engine until no other references to it exist.
-        QV4::Scope scope(cache->engine);
-        QV4::ScopedValue newv(scope, cache->engine->fromVariant(value));
+        QV4::Scope scope(engine);
+        QV4::ScopedValue newv(scope, engine->fromVariant(value));
         QV4::Scoped<QV4::VariantObject> v(scope, newv);
         if (!!v)
             v->addVmePropertyReference();
@@ -995,7 +998,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
                                  v->d()->data != value);
                 if (v)
                     v->removeVmePropertyReference();
-                *(md->data() + id) = cache->engine->newVariantObject(value);
+                *(md->data() + id) = engine->newVariantObject(value);
                 v = static_cast<QV4::VariantObject *>(md->data() + id);
                 v->addVmePropertyReference();
             }
@@ -1102,15 +1105,13 @@ void QQmlVMEMetaObject::setVMEProperty(int index, const QV4::Value &v)
 
 void QQmlVMEMetaObject::ensureQObjectWrapper()
 {
-    Q_ASSERT(cache && cache->engine);
-    QV4::ExecutionEngine *v4 = cache->engine;
-    QV4::QObjectWrapper::wrap(v4, object);
+    Q_ASSERT(cache);
+    QV4::QObjectWrapper::wrap(engine, object);
 }
 
 void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
 {
-    QV4::ExecutionEngine *v4 = cache ? cache->engine : 0;
-    if (v4 != e)
+    if (engine != e)
         return;
 
     properties.markOnce(e);
@@ -1121,11 +1122,9 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
 
 void QQmlVMEMetaObject::allocateProperties()
 {
-    Q_ASSERT(cache && cache->engine);
     Q_ASSERT(!properties.valueRef());
-    QV4::ExecutionEngine *v4 = cache->engine;
-    QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount);
-    properties.set(v4, data);
+    QV4::Heap::MemberData *data = QV4::MemberData::allocate(engine, metaData->propertyCount);
+    properties.set(engine, data);
     for (uint i = 0; i < data->size; ++i)
         data->data[i] = QV4::Encode::undefined();
 }
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 7da44e3b8..fc43b8f23 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -195,7 +195,7 @@ class QQmlVMEMetaObjectEndpoint;
 class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
 {
 public:
-    QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data);
+    QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data);
     ~QQmlVMEMetaObject();
 
     bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
@@ -220,6 +220,7 @@ public:
     friend class QQmlVMEVariantQObjectPtr;
     friend class QQmlPropertyCache;
 
+    QV4::ExecutionEngine *engine;
     QQmlGuardedContextData ctxt;
 
     const QQmlVMEMetaData *metaData;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index f2de91172..04c8bac00 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -927,7 +927,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
     QQmlDelegateModelItem *cacheItem = it->inCache() ? m_cache.at(it.cacheIndex) : 0;
 
     if (!cacheItem) {
-        cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), it.modelIndex());
+        cacheItem = m_adaptorModel.createItem(m_cacheMetaType, it.modelIndex());
         if (!cacheItem)
             return 0;
 
@@ -1626,7 +1626,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
     if (!m_context || !m_context->isValid())
         return false;
 
-    QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), -1);
+    QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, -1);
     if (!cacheItem)
         return false;
     if (!object.isObject())
@@ -2474,7 +2474,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
 
     if (!cacheItem) {
         cacheItem = model->m_adaptorModel.createItem(
-                model->m_cacheMetaType, model->m_context->engine(), it.modelIndex());
+                model->m_cacheMetaType, it.modelIndex());
         if (!cacheItem)
             return QQmlV4Handle(QV4::Encode::undefined());
         cacheItem->groups = it->flags;
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index c61144dd8..e291e7c70 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -513,16 +513,15 @@ public:
     QQmlDelegateModelItem *createItem(
             QQmlAdaptorModel &model,
             QQmlDelegateModelItemMetaType *metaType,
-            QQmlEngine *engine,
-            int index) const
+            int index) const Q_DECL_OVERRIDE
     {
         VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
         if (!metaObject)
-            dataType->initializeMetaType(model, engine);
+            dataType->initializeMetaType(model);
         return new QQmlDMAbstractItemModelData(metaType, dataType, index);
     }
 
-    void initializeMetaType(QQmlAdaptorModel &model, QQmlEngine *engine)
+    void initializeMetaType(QQmlAdaptorModel &model)
     {
         QMetaObjectBuilder builder;
         setModelDataType<QQmlDMAbstractItemModelData>(&builder, this);
@@ -547,7 +546,7 @@ public:
 
         metaObject = builder.toMetaObject();
         *static_cast<QMetaObject *>(this) = *metaObject;
-        propertyCache = new QQmlPropertyCache(QV8Engine::getV4(engine), metaObject);
+        propertyCache = new QQmlPropertyCache(metaObject);
     }
 };
 
@@ -661,8 +660,7 @@ public:
     QQmlDelegateModelItem *createItem(
             QQmlAdaptorModel &model,
             QQmlDelegateModelItemMetaType *metaType,
-            QQmlEngine *,
-            int index) const
+            int index) const Q_DECL_OVERRIDE
     {
         return new QQmlDMListAccessorData(
                 metaType,
@@ -746,8 +744,7 @@ public:
     QQmlDelegateModelItem *createItem(
             QQmlAdaptorModel &model,
             QQmlDelegateModelItemMetaType *metaType,
-            QQmlEngine *,
-            int index) const
+            int index) const Q_DECL_OVERRIDE
     {
         VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
         if (!metaObject)
diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h
index 9da04462a..f7d79fc0c 100644
--- a/src/qml/util/qqmladaptormodel_p.h
+++ b/src/qml/util/qqmladaptormodel_p.h
@@ -76,7 +76,6 @@ public:
         virtual QQmlDelegateModelItem *createItem(
                 QQmlAdaptorModel &,
                 QQmlDelegateModelItemMetaType *,
-                QQmlEngine *,
                 int) const { return 0; }
 
         virtual bool notify(
@@ -116,8 +115,8 @@ public:
     inline int count() const { return qMax(0, accessors->count(*this)); }
     inline QVariant value(int index, const QString &role) const {
         return accessors->value(*this, index, role); }
-    inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, QQmlEngine *engine, int index) {
-        return accessors->createItem(*this, metaType, engine, index); }
+    inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, int index) {
+        return accessors->createItem(*this, metaType, index); }
     inline bool hasProxyObject() const {
         return list.type() == QQmlListAccessor::Instance || list.type() == QQmlListAccessor::ListProperty; }
 
diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp
index 9ee814e1a..232ed960e 100644
--- a/src/quick/designer/qqmldesignermetaobject.cpp
+++ b/src/quick/designer/qqmldesignermetaobject.cpp
@@ -151,7 +151,7 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine)
 }
 
 QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine)
-    : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object)),
+    : QQmlVMEMetaObject(QQmlEnginePrivate::getV4Engine(engine), object, cacheForObject(object, engine), vMEMetaDataForObject(object)),
       m_context(engine->contextForObject(object)),
       m_data(new MetaPropertyData),
       m_cache(0)
diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp
index 4f23fe663..d10dbc48f 100644
--- a/src/quick/designer/qquickdesignersupportitems.cpp
+++ b/src/quick/designer/qquickdesignersupportitems.cpp
@@ -161,29 +161,24 @@ static bool isWindow(QObject *object) {
     return false;
 }
 
-static QQmlType *getQmlType(const QString &typeName, int majorNumber, int minorNumber)
+static bool isCrashingType(const QQmlType &type)
 {
-     return QQmlMetaType::qmlType(typeName, majorNumber, minorNumber);
-}
+    QString name = type.qmlTypeName();
 
-static bool isCrashingType(QQmlType *type)
-{
-    if (type) {
-        if (type->qmlTypeName() == QStringLiteral("QtMultimedia/MediaPlayer"))
-            return true;
+    if (name == QStringLiteral("QtMultimedia/MediaPlayer"))
+        return true;
 
-        if (type->qmlTypeName() == QStringLiteral("QtMultimedia/Audio"))
-            return true;
+    if (name == QStringLiteral("QtMultimedia/Audio"))
+        return true;
 
-        if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/MenuItem"))
-            return true;
+    if (name == QStringLiteral("QtQuick.Controls/MenuItem"))
+        return true;
 
-        if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/Menu"))
-            return true;
+    if (name == QStringLiteral("QtQuick.Controls/Menu"))
+        return true;
 
-        if (type->qmlTypeName() == QStringLiteral("QtQuick/Timer"))
-            return true;
-    }
+    if (name == QStringLiteral("QtQuick/Timer"))
+        return true;
 
     return false;
 }
@@ -195,19 +190,19 @@ QObject *QQuickDesignerSupportItems::createPrimitive(const QString &typeName, in
     Q_UNUSED(disableComponentComplete)
 
     QObject *object = 0;
-    QQmlType *type = getQmlType(typeName, majorNumber, minorNumber);
+    QQmlType type = QQmlMetaType::qmlType(typeName, majorNumber, minorNumber);
 
     if (isCrashingType(type)) {
         object = new QObject;
-    } else if (type) {
-        if ( type->isComposite()) {
-             object = createComponent(type->sourceUrl(), context);
+    } else if (type.isValid()) {
+        if ( type.isComposite()) {
+             object = createComponent(type.sourceUrl(), context);
         } else
         {
-            if (type->typeName() == "QQmlComponent") {
+            if (type.typeName() == "QQmlComponent") {
                 object = new QQmlComponent(context->engine(), 0);
             } else  {
-                object = type->create();
+                object = type.create();
             }
         }
 
diff --git a/src/quick/designer/qquickdesignersupportmetainfo.cpp b/src/quick/designer/qquickdesignersupportmetainfo.cpp
index c6c7ed38b..8ba07fbb8 100644
--- a/src/quick/designer/qquickdesignersupportmetainfo.cpp
+++ b/src/quick/designer/qquickdesignersupportmetainfo.cpp
@@ -46,8 +46,8 @@ bool QQuickDesignerSupportMetaInfo::isSubclassOf(QObject *object, const QByteArr
     const QMetaObject *metaObject = object->metaObject();
 
     while (metaObject) {
-         QQmlType *qmlType =  QQmlMetaType::qmlType(metaObject);
-         if (qmlType && qmlType->qmlTypeName() == QLatin1String(superTypeName)) // ignore version numbers
+         QQmlType qmlType =  QQmlMetaType::qmlType(metaObject);
+         if (qmlType.qmlTypeName() == QLatin1String(superTypeName)) // ignore version numbers
              return true;
 
          if (metaObject->className() == superTypeName)
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index bc3220ad8..aa3131a84 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -181,8 +181,8 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(
 {
     const QMetaObject *meta = o->metaObject();
 
-    QQmlType *type = QQmlMetaType::qmlType(meta);
-    QString className = type ? QString(type->qmlTypeName())
+    QQmlType type = QQmlMetaType::qmlType(meta);
+    QString className = type.isValid() ? QString(type.qmlTypeName())
                              : QString(meta->className());
     className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1);
 
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index 27e92f67a..4b9452f36 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -126,14 +126,14 @@ void tst_qqmlmetatype::initTestCase()
 
 void tst_qqmlmetatype::qmlParserStatusCast()
 {
-    QVERIFY(!QQmlMetaType::qmlType(QVariant::Int));
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
-    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->parserStatusCast(), -1);
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()) != 0);
-    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>())->parserStatusCast(), -1);
-
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
-    int cast = QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->parserStatusCast();
+    QVERIFY(!QQmlMetaType::qmlType(QVariant::Int).isValid());
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid());
+    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).parserStatusCast(), -1);
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).isValid());
+    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).parserStatusCast(), -1);
+
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid());
+    int cast = QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).parserStatusCast();
     QVERIFY(cast != -1);
     QVERIFY(cast != 0);
 
@@ -146,14 +146,14 @@ void tst_qqmlmetatype::qmlParserStatusCast()
 
 void tst_qqmlmetatype::qmlPropertyValueSourceCast()
 {
-    QVERIFY(!QQmlMetaType::qmlType(QVariant::Int));
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
-    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueSourceCast(), -1);
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
-    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->propertyValueSourceCast(), -1);
-
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()) != 0);
-    int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>())->propertyValueSourceCast();
+    QVERIFY(!QQmlMetaType::qmlType(QVariant::Int).isValid());
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid());
+    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).propertyValueSourceCast(), -1);
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid());
+    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).propertyValueSourceCast(), -1);
+
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).isValid());
+    int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).propertyValueSourceCast();
     QVERIFY(cast != -1);
     QVERIFY(cast != 0);
 
@@ -166,14 +166,14 @@ void tst_qqmlmetatype::qmlPropertyValueSourceCast()
 
 void tst_qqmlmetatype::qmlPropertyValueInterceptorCast()
 {
-    QVERIFY(!QQmlMetaType::qmlType(QVariant::Int));
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
-    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueInterceptorCast(), -1);
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
-    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->propertyValueInterceptorCast(), -1);
-
-    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>()) != 0);
-    int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>())->propertyValueInterceptorCast();
+    QVERIFY(!QQmlMetaType::qmlType(QVariant::Int).isValid());
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid());
+    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).propertyValueInterceptorCast(), -1);
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid());
+    QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).propertyValueInterceptorCast(), -1);
+
+    QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>()).isValid());
+    int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>()).propertyValueInterceptorCast();
     QVERIFY(cast != -1);
     QVERIFY(cast != 0);
 
@@ -186,17 +186,17 @@ void tst_qqmlmetatype::qmlPropertyValueInterceptorCast()
 
 void tst_qqmlmetatype::qmlType()
 {
-    QQmlType *type = QQmlMetaType::qmlType(QString("ParserStatusTestType"), QString("Test"), 1, 0);
-    QVERIFY(type);
-    QVERIFY(type->module() == QLatin1String("Test"));
-    QVERIFY(type->elementName() == QLatin1String("ParserStatusTestType"));
-    QCOMPARE(type->qmlTypeName(), QLatin1String("Test/ParserStatusTestType"));
+    QQmlType type = QQmlMetaType::qmlType(QString("ParserStatusTestType"), QString("Test"), 1, 0);
+    QVERIFY(type.isValid());
+    QVERIFY(type.module() == QLatin1String("Test"));
+    QVERIFY(type.elementName() == QLatin1String("ParserStatusTestType"));
+    QCOMPARE(type.qmlTypeName(), QLatin1String("Test/ParserStatusTestType"));
 
     type = QQmlMetaType::qmlType("Test/ParserStatusTestType", 1, 0);
-    QVERIFY(type);
-    QVERIFY(type->module() == QLatin1String("Test"));
-    QVERIFY(type->elementName() == QLatin1String("ParserStatusTestType"));
-    QCOMPARE(type->qmlTypeName(), QLatin1String("Test/ParserStatusTestType"));
+    QVERIFY(type.isValid());
+    QVERIFY(type.module() == QLatin1String("Test"));
+    QVERIFY(type.elementName() == QLatin1String("ParserStatusTestType"));
+    QCOMPARE(type.qmlTypeName(), QLatin1String("Test/ParserStatusTestType"));
 }
 
 void tst_qqmlmetatype::invalidQmlTypeName()
@@ -240,23 +240,23 @@ void tst_qqmlmetatype::defaultObject()
 
 void tst_qqmlmetatype::registrationType()
 {
-    QQmlType *type = QQmlMetaType::qmlType(QString("TestType"), QString("Test"), 1, 0);
-    QVERIFY(type);
-    QVERIFY(!type->isInterface());
-    QVERIFY(!type->isSingleton());
-    QVERIFY(!type->isComposite());
+    QQmlType type = QQmlMetaType::qmlType(QString("TestType"), QString("Test"), 1, 0);
+    QVERIFY(type.isValid());
+    QVERIFY(!type.isInterface());
+    QVERIFY(!type.isSingleton());
+    QVERIFY(!type.isComposite());
 
     type = QQmlMetaType::qmlType(QString("TestTypeSingleton"), QString("Test"), 1, 0);
-    QVERIFY(type);
-    QVERIFY(!type->isInterface());
-    QVERIFY(type->isSingleton());
-    QVERIFY(!type->isComposite());
+    QVERIFY(type.isValid());
+    QVERIFY(!type.isInterface());
+    QVERIFY(type.isSingleton());
+    QVERIFY(!type.isComposite());
 
     type = QQmlMetaType::qmlType(QString("TestTypeComposite"), QString("Test"), 1, 0);
-    QVERIFY(type);
-    QVERIFY(!type->isInterface());
-    QVERIFY(!type->isSingleton());
-    QVERIFY(type->isComposite());
+    QVERIFY(type.isValid());
+    QVERIFY(!type.isInterface());
+    QVERIFY(!type.isSingleton());
+    QVERIFY(type.isComposite());
 }
 
 void tst_qqmlmetatype::compositeType()
@@ -268,12 +268,12 @@ void tst_qqmlmetatype::compositeType()
     QObject* obj = c.create();
     QVERIFY(obj);
 
-    QQmlType *type = QQmlMetaType::qmlType(QString("ImplicitType"), QString(""), 1, 0);
-    QVERIFY(type);
-    QVERIFY(type->module().isEmpty());
-    QCOMPARE(type->elementName(), QLatin1String("ImplicitType"));
-    QCOMPARE(type->qmlTypeName(), QLatin1String("ImplicitType"));
-    QCOMPARE(type->sourceUrl(), testFileUrl("ImplicitType.qml"));
+    QQmlType type = QQmlMetaType::qmlType(QString("ImplicitType"), QString(""), 1, 0);
+    QVERIFY(type.isValid());
+    QVERIFY(type.module().isEmpty());
+    QCOMPARE(type.elementName(), QLatin1String("ImplicitType"));
+    QCOMPARE(type.qmlTypeName(), QLatin1String("ImplicitType"));
+    QCOMPARE(type.sourceUrl(), testFileUrl("ImplicitType.qml"));
 }
 
 QTEST_MAIN(tst_qqmlmetatype)
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index a5ae27d44..250fc634a 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -103,11 +103,10 @@ QQmlPropertyData *cacheProperty(QQmlPropertyCache *cache, const char *name)
 void tst_qqmlpropertycache::properties()
 {
     QQmlEngine engine;
-    QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
     DerivedObject object;
     const QMetaObject *metaObject = object.metaObject();
 
-    QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
+    QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(metaObject));
     QQmlPropertyData *data;
 
     QVERIFY(data = cacheProperty(cache, "propertyA"));
@@ -126,11 +125,10 @@ void tst_qqmlpropertycache::properties()
 void tst_qqmlpropertycache::propertiesDerived()
 {
     QQmlEngine engine;
-    QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
     DerivedObject object;
     const QMetaObject *metaObject = object.metaObject();
 
-    QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(v4, &BaseObject::staticMetaObject));
+    QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(&BaseObject::staticMetaObject));
     QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
     QQmlPropertyData *data;
 
@@ -150,11 +148,10 @@ void tst_qqmlpropertycache::propertiesDerived()
 void tst_qqmlpropertycache::methods()
 {
     QQmlEngine engine;
-    QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
     DerivedObject object;
     const QMetaObject *metaObject = object.metaObject();
 
-    QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
+    QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(metaObject));
     QQmlPropertyData *data;
 
     QVERIFY(data = cacheProperty(cache, "slotA"));
@@ -185,11 +182,10 @@ void tst_qqmlpropertycache::methods()
 void tst_qqmlpropertycache::methodsDerived()
 {
     QQmlEngine engine;
-    QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
     DerivedObject object;
     const QMetaObject *metaObject = object.metaObject();
 
-    QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(v4, &BaseObject::staticMetaObject));
+    QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(&BaseObject::staticMetaObject));
     QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
     QQmlPropertyData *data;
 
@@ -221,11 +217,10 @@ void tst_qqmlpropertycache::methodsDerived()
 void tst_qqmlpropertycache::signalHandlers()
 {
     QQmlEngine engine;
-    QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
     DerivedObject object;
     const QMetaObject *metaObject = object.metaObject();
 
-    QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
+    QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(metaObject));
     QQmlPropertyData *data;
 
     QVERIFY(data = cacheProperty(cache, "onSignalA"));
@@ -250,11 +245,10 @@ void tst_qqmlpropertycache::signalHandlers()
 void tst_qqmlpropertycache::signalHandlersDerived()
 {
     QQmlEngine engine;
-    QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
     DerivedObject object;
     const QMetaObject *metaObject = object.metaObject();
 
-    QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(v4, &BaseObject::staticMetaObject));
+    QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(&BaseObject::staticMetaObject));
     QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
     QQmlPropertyData *data;
 
diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp
index dbda07be5..1c77ecd5e 100644
--- a/tests/benchmarks/qml/creation/tst_creation.cpp
+++ b/tests/benchmarks/qml/creation/tst_creation.cpp
@@ -194,10 +194,10 @@ void tst_creation::qobject_10tree_cpp()
 
 void tst_creation::qobject_qmltype()
 {
-    QQmlType *t = QQmlMetaType::qmlType("QtQuick/QtObject", 2, 0);
+    QQmlType t = QQmlMetaType::qmlType("QtQuick/QtObject", 2, 0);
 
     QBENCHMARK {
-        QObject *obj = t->create();
+        QObject *obj = t.create();
         delete obj;
     }
 }
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 393abc888..6292b8b14 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -136,11 +136,11 @@ void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *met
     }
 }
 
-void collectReachableMetaObjects(QQmlEnginePrivate *engine, const QQmlType *ty, QSet<const QMetaObject *> *metas)
+void collectReachableMetaObjects(QQmlEnginePrivate *engine, const QQmlType &ty, QSet<const QMetaObject *> *metas)
 {
-    collectReachableMetaObjects(ty->metaObject(), metas, ty->isExtendedType());
-    if (ty->attachedPropertiesType(engine))
-        collectReachableMetaObjects(ty->attachedPropertiesType(engine), metas);
+    collectReachableMetaObjects(ty.metaObject(), metas, ty.isExtendedType());
+    if (ty.attachedPropertiesType(engine))
+        collectReachableMetaObjects(ty.attachedPropertiesType(engine), metas);
 }
 
 /* We want to add the MetaObject for 'Qt' to the list, this is a
@@ -156,11 +156,11 @@ public:
    To do this, we need to find the QQmlTypes associated with this
    QMetaObject.
 */
-static QHash<QByteArray, QSet<const QQmlType *> > qmlTypesByCppName;
+static QHash<QByteArray, QSet<QQmlType> > qmlTypesByCppName;
 
 /* A composite type is completely specified by name, major version and minor version.
 */
-static QMap<QString, QSet<const QQmlType *> > qmlTypesByCompositeName;
+static QMap<QString, QSet<QQmlType> > qmlTypesByCompositeName;
 
 static QHash<QByteArray, QByteArray> cppToId;
 
@@ -204,12 +204,12 @@ QByteArray convertToId(const QMetaObject *mo)
 
 // Collect all metaobjects for types registered with qmlRegisterType() without parameters
 void collectReachableMetaObjectsWithoutQmlName(QQmlEnginePrivate *engine, QSet<const QMetaObject *>& metas ) {
-    foreach (const QQmlType *ty, QQmlMetaType::qmlAllTypes()) {
-        if ( ! metas.contains(ty->metaObject()) ) {
-            if (!ty->isComposite()) {
+    foreach (const QQmlType &ty, QQmlMetaType::qmlAllTypes()) {
+        if ( ! metas.contains(ty.metaObject()) ) {
+            if (!ty.isComposite()) {
                 collectReachableMetaObjects(engine, ty, &metas);
             } else {
-                qmlTypesByCompositeName[ty->elementName()].insert(ty);
+                qmlTypesByCompositeName[ty.elementName()].insert(ty);
             }
        }
     }
@@ -218,24 +218,24 @@ void collectReachableMetaObjectsWithoutQmlName(QQmlEnginePrivate *engine, QSet<c
 QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
                                                       QSet<const QMetaObject *> &noncreatables,
                                                       QSet<const QMetaObject *> &singletons,
-                                                      const QList<QQmlType *> &skip = QList<QQmlType *>())
+                                                      const QList<QQmlType> &skip = QList<QQmlType>())
 {
     QSet<const QMetaObject *> metas;
     metas.insert(FriendlyQObject::qtMeta());
 
     QHash<QByteArray, QSet<QByteArray> > extensions;
-    foreach (const QQmlType *ty, QQmlMetaType::qmlTypes()) {
-        if (!ty->isCreatable())
-            noncreatables.insert(ty->metaObject());
-        if (ty->isSingleton())
-            singletons.insert(ty->metaObject());
-        if (!ty->isComposite()) {
-            qmlTypesByCppName[ty->metaObject()->className()].insert(ty);
-            if (ty->isExtendedType())
-                extensions[ty->typeName()].insert(ty->metaObject()->className());
+    foreach (const QQmlType &ty, QQmlMetaType::qmlTypes()) {
+        if (!ty.isCreatable())
+            noncreatables.insert(ty.metaObject());
+        if (ty.isSingleton())
+            singletons.insert(ty.metaObject());
+        if (!ty.isComposite()) {
+            qmlTypesByCppName[ty.metaObject()->className()].insert(ty);
+            if (ty.isExtendedType())
+                extensions[ty.typeName()].insert(ty.metaObject()->className());
             collectReachableMetaObjects(QQmlEnginePrivate::get(engine), ty, &metas);
         } else {
-            qmlTypesByCompositeName[ty->elementName()].insert(ty);
+            qmlTypesByCompositeName[ty.elementName()].insert(ty);
         }
     }
 
@@ -244,21 +244,21 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
     // Example: QDeclarativeGraphicsWidget overrides the QtQuick/QGraphicsWidget export
     //          of QGraphicsWidget.
     foreach (const QByteArray &baseCpp, extensions.keys()) {
-        QSet<const QQmlType *> baseExports = qmlTypesByCppName.value(baseCpp);
+        QSet<QQmlType> baseExports = qmlTypesByCppName.value(baseCpp);
 
         const QSet<QByteArray> extensionCppNames = extensions.value(baseCpp);
         foreach (const QByteArray &extensionCppName, extensionCppNames) {
-            const QSet<const QQmlType *> extensionExports = qmlTypesByCppName.value(extensionCppName);
+            const QSet<QQmlType> extensionExports = qmlTypesByCppName.value(extensionCppName);
 
             // remove extension exports from base imports
             // unfortunately the QQmlType pointers don't match, so can't use QSet::subtract
-            QSet<const QQmlType *> newBaseExports;
-            foreach (const QQmlType *baseExport, baseExports) {
+            QSet<QQmlType> newBaseExports;
+            foreach (const QQmlType &baseExport, baseExports) {
                 bool match = false;
-                foreach (const QQmlType *extensionExport, extensionExports) {
-                    if (baseExport->qmlTypeName() == extensionExport->qmlTypeName()
-                            && baseExport->majorVersion() == extensionExport->majorVersion()
-                            && baseExport->minorVersion() == extensionExport->minorVersion()) {
+                foreach (const QQmlType &extensionExport, extensionExports) {
+                    if (baseExport.qmlTypeName() == extensionExport.qmlTypeName()
+                            && baseExport.majorVersion() == extensionExport.majorVersion()
+                            && baseExport.minorVersion() == extensionExport.minorVersion()) {
                         match = true;
                         break;
                     }
@@ -274,17 +274,17 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
     if (creatable) {
         // find even more QMetaObjects by instantiating QML types and running
         // over the instances
-        foreach (QQmlType *ty, QQmlMetaType::qmlTypes()) {
+        foreach (const QQmlType &ty, QQmlMetaType::qmlTypes()) {
             if (skip.contains(ty))
                 continue;
-            if (ty->isExtendedType())
+            if (ty.isExtendedType())
                 continue;
-            if (!ty->isCreatable())
+            if (!ty.isCreatable())
                 continue;
-            if (ty->typeName() == "QQmlComponent")
+            if (ty.typeName() == "QQmlComponent")
                 continue;
 
-            QString tyName = ty->qmlTypeName();
+            QString tyName = ty.qmlTypeName();
             tyName = tyName.mid(tyName.lastIndexOf(QLatin1Char('/')) + 1);
             if (tyName.isEmpty())
                 continue;
@@ -292,11 +292,11 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
             inObjectInstantiation = tyName;
             QObject *object = 0;
 
-            if (ty->isSingleton()) {
-                QQmlType::SingletonInstanceInfo *siinfo = ty->singletonInstanceInfo();
+            if (ty.isSingleton()) {
+                QQmlType::SingletonInstanceInfo *siinfo = ty.singletonInstanceInfo();
                 if (!siinfo) {
                     std::cerr << "Internal error, " << qPrintable(tyName)
-                              << "(" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")"
+                              << "(" << qPrintable( QString::fromUtf8(ty.typeName()) ) << ")"
                               << " is singleton, but has no singletonInstanceInfo" << std::endl;
                     continue;
                 }
@@ -314,8 +314,8 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
             } else {
                 if (verbose)
                     std::cerr << "Trying to create object " << qPrintable( tyName )
-                              << " (" << qPrintable( QString::fromUtf8(ty->typeName()) )  << ")" << std::endl;
-                object = ty->create();
+                              << " (" << qPrintable( QString::fromUtf8(ty.typeName()) )  << ")" << std::endl;
+                object = ty.create();
             }
 
             inObjectInstantiation.clear();
@@ -323,7 +323,7 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
             if (object) {
                 if (verbose)
                     std::cerr << "Got " << qPrintable( tyName )
-                              << " (" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")" << std::endl;
+                              << " (" << qPrintable( QString::fromUtf8(ty.typeName()) ) << ")" << std::endl;
                 collectReachableMetaObjects(object, &metas);
                 object->deleteLater();
             } else {
@@ -466,17 +466,17 @@ public:
         return prototypeName;
     }
 
-    void dumpComposite(QQmlEngine *engine, const QSet<const QQmlType *> &compositeType, QSet<QByteArray> &defaultReachableNames)
+    void dumpComposite(QQmlEngine *engine, const QSet<QQmlType> &compositeType, QSet<QByteArray> &defaultReachableNames)
     {
-        foreach (const QQmlType *type, compositeType)
+        foreach (const QQmlType &type, compositeType)
             dumpCompositeItem(engine, type, defaultReachableNames);
     }
 
-    void dumpCompositeItem(QQmlEngine *engine, const QQmlType *compositeType, QSet<QByteArray> &defaultReachableNames)
+    void dumpCompositeItem(QQmlEngine *engine, const QQmlType &compositeType, QSet<QByteArray> &defaultReachableNames)
     {
-        QQmlComponent e(engine, compositeType->sourceUrl());
+        QQmlComponent e(engine, compositeType.sourceUrl());
         if (!e.isReady()) {
-            std::cerr << "WARNING: skipping module " << compositeType->elementName().toStdString()
+            std::cerr << "WARNING: skipping module " << compositeType.elementName().toStdString()
                       << std::endl << e.errorString().toStdString() << std::endl;
             return;
         }
@@ -497,14 +497,14 @@ public:
                                                                  &objectsToMerge);
         qml->writeScriptBinding(QLatin1String("prototype"), enquote(prototypeName));
 
-        QString qmlTyName = compositeType->qmlTypeName();
-        const QString exportString = getExportString(qmlTyName, compositeType->majorVersion(), compositeType->minorVersion());
+        QString qmlTyName = compositeType.qmlTypeName();
+        const QString exportString = getExportString(qmlTyName, compositeType.majorVersion(), compositeType.minorVersion());
         qml->writeScriptBinding(QLatin1String("name"), exportString);
         qml->writeArrayBinding(QLatin1String("exports"), QStringList() << exportString);
-        qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() << QString::number(compositeType->minorVersion()));
+        qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() << QString::number(compositeType.minorVersion()));
         qml->writeBooleanBinding(QLatin1String("isComposite"), true);
 
-        if (compositeType->isSingleton()) {
+        if (compositeType.isSingleton()) {
             qml->writeBooleanBinding(QLatin1String("isCreatable"), false);
             qml->writeBooleanBinding(QLatin1String("isSingleton"), true);
         }
@@ -541,13 +541,13 @@ public:
         if (meta->superClass())
             qml->writeScriptBinding(QLatin1String("prototype"), enquote(convertToId(meta->superClass())));
 
-        QSet<const QQmlType *> qmlTypes = qmlTypesByCppName.value(meta->className());
+        QSet<QQmlType> qmlTypes = qmlTypesByCppName.value(meta->className());
         if (!qmlTypes.isEmpty()) {
-            QHash<QString, const QQmlType *> exports;
+            QHash<QString, QQmlType> exports;
 
-            foreach (const QQmlType *qmlTy, qmlTypes) {
-                const QString exportString = getExportString(qmlTy->qmlTypeName(), qmlTy->majorVersion(), qmlTy->minorVersion());
-                exports.insert(exportString, qmlTy);
+            foreach (const QQmlType &qmlType, qmlTypes) {
+                const QString exportString = getExportString(qmlType.qmlTypeName(), qmlType.majorVersion(), qmlType.minorVersion());
+                exports.insert(exportString, qmlType);
             }
 
             // ensure exports are sorted and don't change order when the plugin is dumped again
@@ -564,12 +564,12 @@ public:
             // write meta object revisions
             QStringList metaObjectRevisions;
             foreach (const QString &exportString, exportStrings) {
-                int metaObjectRevision = exports[exportString]->metaObjectRevision();
+                int metaObjectRevision = exports[exportString].metaObjectRevision();
                 metaObjectRevisions += QString::number(metaObjectRevision);
             }
             qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), metaObjectRevisions);
 
-            if (const QMetaObject *attachedType = (*qmlTypes.begin())->attachedPropertiesType(engine)) {
+            if (const QMetaObject *attachedType = (*qmlTypes.begin()).attachedPropertiesType(engine)) {
                 // Can happen when a type is registered that returns itself as attachedPropertiesType()
                 // because there is no creatable type to attach to.
                 if (attachedType != meta) {
@@ -1131,7 +1131,7 @@ int main(int argc, char *argv[])
     QSet<const QMetaObject *> uncreatableMetas;
     QSet<const QMetaObject *> singletonMetas;
     QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas);
-    QList<QQmlType *> defaultTypes = QQmlMetaType::qmlTypes();
+    QList<QQmlType> defaultTypes = QQmlMetaType::qmlTypes();
 
     // add some otherwise unreachable QMetaObjects
     defaultReachable.insert(&QQuickMouseEvent::staticMetaObject);
@@ -1172,16 +1172,16 @@ int main(int argc, char *argv[])
     } else {
         // find a valid QtQuick import
         QByteArray importCode;
-        QQmlType *qtObjectType = QQmlMetaType::qmlType(&QObject::staticMetaObject);
-        if (!qtObjectType) {
+        QQmlType qtObjectType = QQmlMetaType::qmlType(&QObject::staticMetaObject);
+        if (!qtObjectType.isValid()) {
             std::cerr << "Could not find QtObject type" << std::endl;
             importCode = qtQmlImportString.toUtf8();
         } else {
-            QString module = qtObjectType->qmlTypeName();
+            QString module = qtObjectType.qmlTypeName();
             module = module.mid(0, module.lastIndexOf(QLatin1Char('/')));
             importCode = QString("import %1 %2.%3").arg(module,
-                                                        QString::number(qtObjectType->majorVersion()),
-                                                        QString::number(qtObjectType->minorVersion())).toUtf8();
+                                                        QString::number(qtObjectType.majorVersion()),
+                                                        QString::number(qtObjectType.minorVersion())).toUtf8();
         }
         // avoid importing dependencies?
         foreach (const QString &moduleToImport, dependencies) {
@@ -1269,7 +1269,7 @@ int main(int argc, char *argv[])
         dumper.dump(QQmlEnginePrivate::get(&engine), meta, uncreatableMetas.contains(meta), singletonMetas.contains(meta));
     }
 
-    QMap<QString, QSet<const QQmlType *> >::const_iterator iter = qmlTypesByCompositeName.constBegin();
+    QMap<QString, QSet<QQmlType> >::const_iterator iter = qmlTypesByCompositeName.constBegin();
     for (; iter != qmlTypesByCompositeName.constEnd(); ++iter)
         dumper.dumpComposite(&engine, iter.value(), defaultReachableNames);
 
-- 
2.11.0

