Use V4 binding for non-final properties where possible
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlcompiler.cpp
index 65247e1..6f27925 100644 (file)
@@ -44,7 +44,6 @@
 #include "qqmlpropertyvaluesource.h"
 #include "qqmlcomponent.h"
 #include <private/qmetaobjectbuilder_p.h>
-#include <private/qfastmetabuilder_p.h>
 #include "qqmlstringconverters_p.h"
 #include "qqmlengine_p.h"
 #include "qqmlengine.h"
@@ -63,7 +62,6 @@
 #include "qqmlbinding_p.h"
 #include <private/qv4compiler_p.h>
 
-#include <QColor>
 #include <QDebug>
 #include <QPointF>
 #include <QSizeF>
 #include <QAtomicInt>
 #include <QtCore/qdebug.h>
 #include <QtCore/qdatetime.h>
+#include <QtCore/qvarlengtharray.h>
 
 Q_DECLARE_METATYPE(QList<int>)
 Q_DECLARE_METATYPE(QList<qreal>)
 Q_DECLARE_METATYPE(QList<bool>)
 Q_DECLARE_METATYPE(QList<QString>)
 Q_DECLARE_METATYPE(QList<QUrl>)
+Q_DECLARE_METATYPE(QJSValue)
 
 QT_BEGIN_NAMESPACE
 
@@ -91,7 +91,7 @@ static QString id_string(QLatin1String("id"));
 static QString on_string(QLatin1String("on"));
 static QString Changed_string(QLatin1String("Changed"));
 static QString Component_string(QLatin1String("Component"));
-static QString Component_import_string(QLatin1String("QML/Component"));
+static QString Component_module_string(QLatin1String("QML"));
 static QString qsTr_string(QLatin1String("qsTr"));
 static QString qsTrId_string(QLatin1String("qsTrId"));
 
@@ -99,7 +99,7 @@ static QString qsTrId_string(QLatin1String("qsTrId"));
     Instantiate a new QQmlCompiler.
 */
 QQmlCompiler::QQmlCompiler(QQmlPool *pool)
-: pool(pool), output(0), engine(0), unitRoot(0), unit(0), cachedComponentTypeRef(-1),
+: compileState(0), pool(pool), output(0), engine(0), enginePrivate(0), unitRoot(0), unit(0), cachedComponentTypeRef(-1),
   cachedTranslationContextIndex(-1), componentStats(0)
 {
     if (compilerStatDump()) 
@@ -216,8 +216,7 @@ bool QQmlCompiler::isSignalPropertyName(const QHashedStringRef &name)
     This test corresponds to action taken by genLiteralAssignment().  Any change
     made here, must have a corresponding action in genLiteralAssigment().
 */
-bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop,
-                                                 QQmlScript::Value *v)
+bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Value *v)
 {
     const QQmlScript::Variant &value = v->value;
 
@@ -225,7 +224,7 @@ bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop,
         COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 
     if (prop->core.isEnum()) {
-        QMetaProperty p = prop->parent->metaObject()->property(prop->index);
+        QMetaProperty p = prop->parent->metatype->firstCppMetaObject()->property(prop->index);
         int enumValue;
         bool ok;
         if (p.isFlagType()) {
@@ -349,16 +348,16 @@ bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop,
             break;
         case QVariant::Vector3D:
             {
-            bool ok;
-            QQmlStringConverters::vector3DFromString(value.asString(), &ok);
-            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected"));
+            QQmlInstruction::instr_storeVector3D::QVector3D v3;
+            if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, value.asString(), &v3, sizeof(v3)))
+                COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected"));
             }
             break;
         case QVariant::Vector4D:
             {
-            bool ok;
-            QQmlStringConverters::vector4DFromString(value.asString(), &ok);
-            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected"));
+            QQmlInstruction::instr_storeVector4D::QVector4D v4;
+            if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, value.asString(), &v4, sizeof(v4)))
+                COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected"));
             }
             break;
         default:
@@ -395,26 +394,20 @@ bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop,
                     COMPILE_EXCEPTION(v, tr("Invalid property assignment: url or array of urls expected"));
                 }
                 break;
+            } else if (type == qMetaTypeId<QJSValue>()) {
+                break;
             }
 
             // otherwise, check for existence of string converter to custom type
             QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type);
             if (!converter)
-                COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName((QVariant::Type)type))));
+                COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(type))));
             }
             break;
     }
     return true;
 }
 
-static QUrl urlFromUserString(const QString &data)
-{
-    QUrl u;
-    // Preserve any valid percent-encoded octets supplied by the source
-    u.setEncodedUrl(data.toUtf8(), QUrl::TolerantMode);
-    return u;
-}
-
 /*!
     Generate a store instruction for assigning literal \a v to property \a prop.
 
@@ -443,7 +436,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
             if (v->value.isNumber()) {
                 double n = v->value.asNumber();
                 if (double(int(n)) == n) {
-                    if (prop->core.isVMEProperty()) {
+                    if (prop->core.isVarProperty()) {
                         Instruction::StoreVarInteger instr;
                         instr.propertyIndex = prop->index;
                         instr.value = int(n);
@@ -455,7 +448,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
                         output->addInstruction(instr);
                     }
                 } else {
-                    if (prop->core.isVMEProperty()) {
+                    if (prop->core.isVarProperty()) {
                         Instruction::StoreVarDouble instr;
                         instr.propertyIndex = prop->index;
                         instr.value = n;
@@ -468,7 +461,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
                     }
                 }
             } else if (v->value.isBoolean()) {
-                if (prop->core.isVMEProperty()) {
+                if (prop->core.isVarProperty()) {
                     Instruction::StoreVarBool instr;
                     instr.propertyIndex = prop->index;
                     instr.value = v->value.asBoolean();
@@ -480,7 +473,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
                     output->addInstruction(instr);
                 }
             } else {
-                if (prop->core.isVMEProperty()) {
+                if (prop->core.isVarProperty()) {
                     Instruction::StoreVar instr;
                     instr.propertyIndex = prop->index;
                     instr.value = output->indexForString(v->value.asString());
@@ -522,7 +515,9 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
             {
             Instruction::StoreUrl instr;
             QString string = v->value.asString();
-            QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string));
+            // Encoded dir-separators defeat QUrl processing - decode them first
+            string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
+            QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string));
             instr.propertyIndex = prop->index;
             instr.value = output->indexForUrl(u);
             output->addInstruction(instr);
@@ -563,9 +558,8 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
         case QVariant::Color:
             {
             Instruction::StoreColor instr;
-            QColor c = QQmlStringConverters::colorFromString(v->value.asString());
             instr.propertyIndex = prop->index;
-            instr.value = c.rgba();
+            instr.value = QQmlStringConverters::rgbaFromString(v->value.asString());
             output->addInstruction(instr);
             }
             break;
@@ -684,25 +678,16 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
         case QVariant::Vector3D:
             {
             Instruction::StoreVector3D instr;
-            bool ok;
-            QVector3D vector = QQmlStringConverters::vector3DFromString(v->value.asString(), &ok);
             instr.propertyIndex = prop->index;
-            instr.vector.xp = vector.x();
-            instr.vector.yp = vector.y();
-            instr.vector.zp = vector.z();
+            QQmlStringConverters::createFromString(QMetaType::QVector3D, v->value.asString(), &instr.vector, sizeof(instr.vector));
             output->addInstruction(instr);
             }
             break;
     case QVariant::Vector4D:
             {
             Instruction::StoreVector4D instr;
-            bool ok;
-            QVector4D vector = QQmlStringConverters::vector4DFromString(v->value.asString(), &ok);
             instr.propertyIndex = prop->index;
-            instr.vector.xp = vector.x();
-            instr.vector.yp = vector.y();
-            instr.vector.zp = vector.z();
-            instr.vector.wp = vector.w();
+            QQmlStringConverters::createFromString(QMetaType::QVector4D, v->value.asString(), &instr.vector, sizeof(instr.vector));
             output->addInstruction(instr);
             }
             break;
@@ -731,7 +716,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
             } else if (type == qMetaTypeId<QList<QUrl> >()) {
                 Instruction::StoreUrlQList instr;
                 QString string = v->value.asString();
-                QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string));
+                QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string));
                 instr.propertyIndex = prop->index;
                 instr.value = output->indexForUrl(u);
                 output->addInstruction(instr);
@@ -742,6 +727,32 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
                 instr.value = output->indexForString(v->value.asString());
                 output->addInstruction(instr);
                 break;
+            } else if (type == qMetaTypeId<QJSValue>()) {
+                if (v->value.isBoolean()) {
+                    Instruction::StoreJSValueBool instr;
+                    instr.propertyIndex = prop->index;
+                    instr.value = v->value.asBoolean();
+                    output->addInstruction(instr);
+                } else if (v->value.isNumber()) {
+                    double n = v->value.asNumber();
+                    if (double(int(n)) == n) {
+                        Instruction::StoreJSValueInteger instr;
+                        instr.propertyIndex = prop->index;
+                        instr.value = int(n);
+                        output->addInstruction(instr);
+                    } else {
+                        Instruction::StoreJSValueDouble instr;
+                        instr.propertyIndex = prop->index;
+                        instr.value = n;
+                        output->addInstruction(instr);
+                    }
+                } else {
+                    Instruction::StoreJSValueString instr;
+                    instr.propertyIndex = prop->index;
+                    instr.value = output->indexForString(v->value.asString());
+                    output->addInstruction(instr);
+                }
+                break;
             }
 
             // otherwise, generate custom type literal assignment
@@ -811,22 +822,23 @@ bool QQmlCompiler::compile(QQmlEngine *engine,
                 QString err = ref.type->noCreationReason();
                 if (err.isEmpty())
                     err = tr( "Element is not creatable.");
-                COMPILE_EXCEPTION(parserRef->refObjects.first(), err);
+                COMPILE_EXCEPTION(parserRef->firstUse, err);
             }
             
             if (ref.type->containsRevisionedAttributes()) {
                 QQmlError cacheError;
-                ref.typePropertyCache = enginePrivate->cache(ref.type, resolvedTypes.at(ii).minorVersion, 
+                ref.typePropertyCache = enginePrivate->cache(ref.type,
+                                                             resolvedTypes.at(ii).minorVersion,
                                                              cacheError);
                 if (!ref.typePropertyCache) 
-                    COMPILE_EXCEPTION(parserRef->refObjects.first(), cacheError.description());
+                    COMPILE_EXCEPTION(parserRef->firstUse, cacheError.description());
                 ref.typePropertyCache->addref();
             }
 
         } else if (tref.typeData) {
             ref.component = tref.typeData->compiledData();
+            ref.component->addref();
         }
-        ref.className = parserRef->name;
         out->types << ref;
     }
 
@@ -932,14 +944,17 @@ void QQmlCompiler::compileTree(QQmlScript::Object *tree)
     output->addInstruction(done);
 
     Q_ASSERT(tree->metatype);
-
-    if (tree->metadata.isEmpty()) {
-        output->root = tree->metatype;
+    if (!tree->synthdata.isEmpty()) {
+        enginePrivate->registerCompositeType(output);
+    } else if (output->types.at(tree->type).component) {
+        output->metaTypeId = output->types.at(tree->type).component->metaTypeId;
+        output->listMetaTypeId = output->types.at(tree->type).component->listMetaTypeId;
     } else {
-        static_cast<QMetaObject &>(output->rootData) = *tree->metaObject();
-        output->root = &output->rootData;
+        Q_ASSERT(output->types.at(tree->type).type);
+        output->metaTypeId = output->types.at(tree->type).type->typeId();
+        output->listMetaTypeId = output->types.at(tree->type).type->qListTypeId();
     }
-    if (!tree->metadata.isEmpty()) 
+    if (!tree->synthdata.isEmpty())
         enginePrivate->registerCompositeType(output);
 }
 
@@ -958,14 +973,11 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
         componentStats->componentStat.objects++;
 
     Q_ASSERT (obj->type != -1);
-    const QQmlCompiledData::TypeReference &tr = output->types.at(obj->type);
-    obj->metatype = tr.metaObject();
-
-    if (tr.type) 
-        obj->typeName = tr.type->qmlTypeName();
+    QQmlCompiledData::TypeReference &tr = output->types[obj->type];
+    obj->metatype = tr.createPropertyCache(engine);
 
-    // This object is a "Component" element
-    if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) {
+    // This object is a "Component" element.
+    if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
         COMPILE_CHECK(buildComponent(obj, ctxt));
         return true;
     } 
@@ -990,7 +1002,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
     // Create the synthesized meta object, ignoring aliases
     COMPILE_CHECK(checkDynamicMeta(obj)); 
     COMPILE_CHECK(mergeDynamicMetaProperties(obj));
-    COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases));
+    COMPILE_CHECK(buildDynamicMeta(obj, Normal));
 
     // Find the native type and check for the QQmlParserStatus interface
     QQmlType *type = toQmlType(obj);
@@ -1027,54 +1039,22 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
 
         Property *explicitProperty = 0;
 
-        const QMetaObject *mo = obj->metatype;
-        int idx = mo->indexOfClassInfo("DefaultProperty"); 
-        if (idx != -1) {
-            QMetaClassInfo info = mo->classInfo(idx);
-            const char *p = info.value();
-            if (p) {
-                int plen = 0;
-                char ord = 0;
-                while (char c = p[plen++]) { ord |= c; };
-                --plen;
-
-                if (ord & 0x80) {
-                    // Utf8 - unoptimal, but seldom hit
-                    QString *s = pool->NewString(QString::fromUtf8(p, plen));
-                    QHashedStringRef r(*s);
-
-                    if (obj->propertiesHashField.test(r.hash())) {
-                        for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
-                            if (ep->name() == r) {
-                                explicitProperty = ep;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (!explicitProperty)
-                        defaultProperty->setName(r);
+        QString defaultPropertyName = obj->metatype->defaultPropertyName();
+        if (!defaultPropertyName.isEmpty()) {
+            QString *s = pool->NewString(defaultPropertyName);
+            QHashedStringRef r(*s);
 
-                } else {
-                    QHashedCStringRef r(p, plen); 
-
-                    if (obj->propertiesHashField.test(r.hash())) {
-                        for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
-                            if (ep->name() == r) {
-                                explicitProperty = ep;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (!explicitProperty) {
-                        // Set the default property name
-                        QChar *buffer = pool->NewRawArray<QChar>(r.length());
-                        r.writeUtf16(buffer);
-                        defaultProperty->setName(QHashedStringRef(buffer, r.length(), r.hash()));
+            if (obj->propertiesHashField.test(r.hash())) {
+                for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
+                    if (ep->name() == r) {
+                        explicitProperty = ep;
+                        break;
                     }
                 }
             }
+
+            if (!explicitProperty)
+                defaultProperty->setName(r);
         }
 
         if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) {
@@ -1177,10 +1157,10 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
     return true;
 }
 
-void QQmlCompiler::genObject(QQmlScript::Object *obj)
+void QQmlCompiler::genObject(QQmlScript::Object *obj, bool parentToSuper)
 {
     QQmlCompiledData::TypeReference &tr = output->types[obj->type];
-    if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) {
+    if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
         genComponent(obj);
         return;
     }
@@ -1195,6 +1175,7 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
         create.type = obj->type;
         create.line = obj->location.start.line;
         create.column = obj->location.start.column;
+        create.parentToSuper = parentToSuper;
         output->addInstruction(create);
 
     } else {
@@ -1208,6 +1189,7 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
                 create.data = output->indexForByteArray(obj->custom);
             create.type = obj->type;
             create.isRoot = (compileState->root == obj);
+            create.parentToSuper = parentToSuper;
             output->addInstruction(create);
         } else {
             Instruction::CreateQMLObject create;
@@ -1231,9 +1213,8 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
     }
 
     // Setup the synthesized meta object if necessary
-    if (!obj->metadata.isEmpty()) {
+    if (!obj->synthdata.isEmpty()) {
         Instruction::StoreMetaObject meta;
-        meta.data = output->indexForByteArray(obj->metadata);
         meta.aliasData = output->indexForByteArray(obj->synthdata);
         meta.propertyCache = output->propertyCaches.count();
 
@@ -1241,17 +1222,6 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
         Q_ASSERT(propertyCache);
         propertyCache->addref();
 
-        // Add flag for alias properties
-        if (!obj->synthdata.isEmpty()) {
-            const QQmlVMEMetaData *vmeMetaData = 
-                reinterpret_cast<const QQmlVMEMetaData *>(obj->synthdata.constData());
-            for (int ii = 0; ii < vmeMetaData->aliasCount; ++ii) {
-                int index = obj->metaObject()->propertyOffset() + vmeMetaData->propertyCount + ii;
-                QQmlPropertyData *data = propertyCache->property(index);
-                data->setFlags(data->getFlags() | QQmlPropertyData::IsAlias);
-            }
-        }
-
         if (obj == unitRoot) {
             propertyCache->addref();
             output->rootPropertyCache = propertyCache;
@@ -1379,11 +1349,14 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
         fetch.line = prop->location.start.line;
         output->addInstruction(fetch);
 
-        if (!prop->value->metadata.isEmpty()) {
+        if (!prop->value->synthdata.isEmpty()) {
             Instruction::StoreMetaObject meta;
-            meta.data = output->indexForByteArray(prop->value->metadata);
             meta.aliasData = output->indexForByteArray(prop->value->synthdata);
-            meta.propertyCache = -1;
+            meta.propertyCache = output->propertyCaches.count();
+            QQmlPropertyCache *propertyCache = prop->value->synthCache;
+            Q_ASSERT(propertyCache);
+            propertyCache->addref();
+            output->propertyCaches << propertyCache;
             output->addInstruction(meta);
         }
 
@@ -1440,6 +1413,8 @@ void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Prop
     pop.type = prop->type;
     pop.bindingSkipList = 0;
     output->addInstruction(pop);
+
+    genPropertyAssignment(prop, obj);
 }
 
 void QQmlCompiler::genComponent(QQmlScript::Object *obj)
@@ -1624,7 +1599,7 @@ bool QQmlCompiler::buildSubObject(QQmlScript::Object *obj, const BindingContext
 int QQmlCompiler::componentTypeRef()
 {
     if (cachedComponentTypeRef == -1) {
-        QQmlType *t = QQmlMetaType::qmlType(Component_import_string,1,0);
+        QQmlType *t = QQmlMetaType::qmlType(Component_string, Component_module_string, 1, 0);
         for (int ii = output->types.count() - 1; ii >= 0; --ii) {
             if (output->types.at(ii).type == t) {
                 cachedComponentTypeRef = ii;
@@ -1632,7 +1607,6 @@ int QQmlCompiler::componentTypeRef()
             }
         }
         QQmlCompiledData::TypeReference ref;
-        ref.className = Component_string;
         ref.type = t;
         output->types << ref;
         cachedComponentTypeRef = output->types.count() - 1;
@@ -1657,7 +1631,7 @@ int QQmlCompiler::translationContextIndex()
 bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
                                        const BindingContext &ctxt)
 {
-    Q_ASSERT(obj->metaObject());
+    Q_ASSERT(obj->metatype);
 
     const QHashedStringRef &propName = prop->name();
 
@@ -1699,7 +1673,7 @@ bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *o
         if (prop->value || !prop->values.isOne())
             COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment"));
 
-        prop->index = sig->coreIndex;
+        prop->index = propertyCacheForObject(obj)->methodIndexToSignalIndex(sig->coreIndex);
         prop->core = *sig;
 
         obj->addSignalProperty(prop);
@@ -1746,9 +1720,6 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
     if (prop->isEmpty()) 
         COMPILE_EXCEPTION(prop, tr("Empty property assignment"));
 
-    const QMetaObject *metaObject = obj->metaObject();
-    Q_ASSERT(metaObject);
-
     if (isAttachedPropertyName(prop->name())) {
         // Setup attached property data
 
@@ -1760,8 +1731,8 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
         }
 
         QQmlType *type = 0;
-        QQmlImportedNamespace *typeNamespace = 0;
-        unit->imports().resolveType(prop->name().toString(), &type, 0, 0, 0, &typeNamespace);
+        QQmlImportNamespace *typeNamespace = 0;
+        unit->imports().resolveType(prop->name(), &type, 0, 0, 0, &typeNamespace);
 
         if (typeNamespace) {
             COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, 
@@ -1776,7 +1747,7 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
 
         Q_ASSERT(type->attachedPropertiesFunction());
         prop->index = type->attachedPropertiesId();
-        prop->value->metatype = type->attachedPropertiesType();
+        prop->value->metatype = enginePrivate->cache(type->attachedPropertiesType());
     } else {
         // Setup regular property data
         bool notInRevision = false;
@@ -1795,13 +1766,13 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
             prop->index = d->coreIndex;
             prop->core = *d;
         } else if (prop->isDefault) {
-            QMetaProperty p = QQmlMetaType::defaultProperty(metaObject);
-            QQmlPropertyData defaultPropertyData;
-            defaultPropertyData.load(p, engine);
-            if (p.name())
-                prop->setName(QLatin1String(p.name()));
-            prop->core = defaultPropertyData;
-            prop->index = prop->core.coreIndex;
+            QString defaultPropertyName = obj->metatype->defaultPropertyName();
+
+            if (!defaultPropertyName.isEmpty()) {
+                prop->setName(defaultPropertyName);
+                prop->core = *obj->metatype->defaultProperty();
+                prop->index = prop->core.coreIndex;
+            }
         }
 
         // We can't error here as the "id" property does not require a
@@ -1867,10 +1838,10 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
     return true;
 }
 
-bool QQmlCompiler::buildPropertyInNamespace(QQmlImportedNamespace *ns,
-                                                    QQmlScript::Property *nsProp, 
-                                                    QQmlScript::Object *obj, 
-                                                    const BindingContext &ctxt)
+bool QQmlCompiler::buildPropertyInNamespace(QQmlImportNamespace *ns,
+                                            QQmlScript::Property *nsProp,
+                                            QQmlScript::Object *obj,
+                                            const BindingContext &ctxt)
 {
     if (!nsProp->value)
         COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace"));
@@ -1883,7 +1854,7 @@ bool QQmlCompiler::buildPropertyInNamespace(QQmlImportedNamespace *ns,
         // Setup attached property data
 
         QQmlType *type = 0;
-        unit->imports().resolveType(ns, prop->name().toString(), &type, 0, 0, 0);
+        unit->imports().resolveType(ns, prop->name(), &type, 0, 0, 0);
 
         if (!type || !type->attachedPropertiesType()) 
             COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
@@ -1893,7 +1864,7 @@ bool QQmlCompiler::buildPropertyInNamespace(QQmlImportedNamespace *ns,
 
         Q_ASSERT(type->attachedPropertiesFunction());
         prop->index = type->index();
-        prop->value->metatype = type->attachedPropertiesType();
+        prop->value->metatype = enginePrivate->cache(type->attachedPropertiesType());
 
         COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
     }
@@ -1971,7 +1942,7 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
 
             } else if (prop->type == QMetaType::QVariant) {
 
-                if (prop->core.isVMEProperty()) {
+                if (prop->core.isVarProperty()) {
                     Instruction::StoreVarObject store;
                     store.line = v->object->location.start.line;
                     store.propertyIndex = prop->index;
@@ -2010,31 +1981,25 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
                  v->type == Value::ValueInterceptor);
 
         if (v->type == Value::ValueSource) {
-            genObject(v->object);
+            genObject(v->object, valueTypeProperty?true:false);
 
             Instruction::StoreValueSource store;
-            if (valueTypeProperty) {
+            if (valueTypeProperty)
                 store.property = genValueTypeData(prop, valueTypeProperty);
-                store.owner = 1;
-            } else {
+            else
                 store.property = prop->core;
-                store.owner = 0;
-            }
             QQmlType *valueType = toQmlType(v->object);
             store.castValue = valueType->propertyValueSourceCast();
             output->addInstruction(store);
 
         } else if (v->type == Value::ValueInterceptor) {
-            genObject(v->object);
+            genObject(v->object, valueTypeProperty?true:false);
 
             Instruction::StoreValueInterceptor store;
-            if (valueTypeProperty) {
+            if (valueTypeProperty)
                 store.property = genValueTypeData(prop, valueTypeProperty);
-                store.owner = 1;
-            } else {
+            else
                 store.property = prop->core;
-                store.owner = 0;
-            }
             QQmlType *valueType = toQmlType(v->object);
             store.castValue = valueType->propertyValueInterceptorCast();
             output->addInstruction(store);
@@ -2143,10 +2108,15 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
         if (prop->type >= 0 && enginePrivate->valueTypes[prop->type]) {
 
             if (!prop->values.isEmpty()) {
-                if (prop->values.first()->location < prop->value->location) {
-                    COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value"));
-                } else {
-                    COMPILE_EXCEPTION(prop->values.first(), tr( "Property has already been assigned a value"));
+                // Only error if we are assigning values, and not e.g. a property interceptor
+                for (Property *dotProp = prop->value->properties.first(); dotProp; dotProp = prop->value->properties.next(dotProp)) {
+                    if (!dotProp->values.isEmpty()) {
+                        if (prop->values.first()->location < prop->value->location) {
+                            COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value"));
+                        } else {
+                            COMPILE_EXCEPTION(prop->values.first(), tr( "Property has already been assigned a value"));
+                        }
+                    }
                 }
             }
 
@@ -2154,7 +2124,6 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
                 COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
             }
 
-
             if (prop->isAlias) {
                 for (Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) {
                     vtProp->isAlias = true;
@@ -2163,14 +2132,33 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
 
             COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type],
                                                  prop->value, obj, ctxt.incr()));
+
+            // When building a value type where sub components are declared, this
+            // code path is followed from buildProperty, even if there is a previous
+            // assignment to the value type as a whole. Therefore we need to look
+            // for (and build) assignments to the entire value type before looking
+            // for any onValue assignments.
+            for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
+                if (v->object) {
+                    COMPILE_EXCEPTION(v->object, tr("Objects cannot be assigned to value types"));
+                }
+                COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
+            }
+
+            for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
+                Q_ASSERT(v->object);
+                COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
+            }
+
             obj->addValueTypeProperty(prop);
+
         } else {
             COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
         }
 
     } else {
         // Load the nested property's meta type
-        prop->value->metatype = enginePrivate->metaObjectForType(prop->type);
+        prop->value->metatype = enginePrivate->propertyCacheForType(prop->type);
         if (!prop->value->metatype)
             COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
 
@@ -2198,7 +2186,7 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
 
     if (obj->defaultProperty)
         COMPILE_EXCEPTION(obj, tr("Invalid property use"));
-    obj->metatype = type->metaObject();
+    obj->metatype = enginePrivate->cache(type);
 
     for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
 
@@ -2227,7 +2215,7 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
                 //optimization for <Type>.<EnumValue> enum assignments
                 bool isEnumAssignment = false;
 
-                if (prop->core.isEnum()
+                if (prop->core.isEnum() || prop->core.propType == QMetaType::Int)
                     COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, value, &isEnumAssignment));
 
                 if (isEnumAssignment) {
@@ -2388,22 +2376,22 @@ bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
         // meta object earlier to test for assignability.  It doesn't matter
         // that there may still be outstanding synthesized meta object changes
         // on this type, as they are not relevant for assignability testing
-        v->object->metatype = output->types.at(v->object->type).metaObject();
-        Q_ASSERT(v->object->metaObject());
+        v->object->metatype = output->types[v->object->type].createPropertyCache(engine);
+        Q_ASSERT(v->object->metatype);
 
         // We want to raw metaObject here as the raw metaobject is the
         // actual property type before we applied any extensions that might
         // effect the properties on the type, but don't effect assignability
-        const QMetaObject *propertyMetaObject = enginePrivate->rawMetaObjectForType(prop->type);
+        QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(prop->type);
 
         // Will be true if the assgned type inherits propertyMetaObject
         bool isAssignable = false;
         // Determine isAssignable value
         if (propertyMetaObject) {
-            const QMetaObject *c = v->object->metatype;
-            while(c) {
-                isAssignable |= (QQmlPropertyPrivate::equal(c, propertyMetaObject));
-                c = c->superClass();
+            QQmlPropertyCache *c = v->object->metatype;
+            while (c && !isAssignable) {
+                isAssignable |= c == propertyMetaObject;
+                c = c->parent();
             }
         }
 
@@ -2412,13 +2400,12 @@ bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
             COMPILE_CHECK(buildObject(v->object, ctxt));
 
             v->type = Value::CreatedObject;
-        } else if (propertyMetaObject == &QQmlComponent::staticMetaObject) {
+        } else if (propertyMetaObject && propertyMetaObject->metaObject() == &QQmlComponent::staticMetaObject) {
             // Automatic "Component" insertion
             QQmlScript::Object *root = v->object;
             QQmlScript::Object *component = pool->New<Object>();
             component->type = componentTypeRef();
-            component->typeName = QStringLiteral("Qt/Component");
-            component->metatype = &QQmlComponent::staticMetaObject;
+            component->metatype = enginePrivate->cache(&QQmlComponent::staticMetaObject);
             component->location = root->location;
             QQmlScript::Value *componentValue = pool->New<Value>();
             componentValue->object = root;
@@ -2458,8 +2445,8 @@ bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
     // meta object earlier to test for assignability.  It doesn't matter
     // that there may still be outstanding synthesized meta object changes
     // on this type, as they are not relevant for assignability testing
-    v->object->metatype = output->types.at(v->object->type).metaObject();
-    Q_ASSERT(v->object->metaObject());
+    v->object->metatype = output->types[v->object->type].createPropertyCache(engine);
+    Q_ASSERT(v->object->metatype);
 
     // Will be true if the assigned type inherits QQmlPropertyValueSource
     bool isPropertyValue = false;
@@ -2474,11 +2461,11 @@ bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
         // Assign as a property value source
         COMPILE_CHECK(buildObject(v->object, ctxt));
 
-        if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
+        if (isPropertyInterceptor && baseObj->synthdata.isEmpty())
             buildDynamicMeta(baseObj, ForceCreation);
         v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
     } else {
-        COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(v->object->typeName).arg(prop->name().toString()));
+        COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(elementName(v->object)).arg(prop->name().toString()));
     }
 
     return true;
@@ -2495,7 +2482,7 @@ bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop,
     if (v->value.isScript()) {
 
         //optimization for <Type>.<EnumValue> enum assignments
-        if (prop->core.isEnum()) {
+        if (prop->core.isEnum() || prop->core.propType == QMetaType::Int) {
             bool isEnumAssignment = false;
             COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, v, &isEnumAssignment));
             if (isEnumAssignment) {
@@ -2520,16 +2507,23 @@ bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop,
     return true;
 }
 
+struct StaticQtMetaObject : public QObject
+{
+    static const QMetaObject *get()
+        { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
 bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
                                                        QQmlScript::Object *obj,
                                                        QQmlScript::Value *v,
                                                        bool *isAssignment)
 {
+    bool isIntProp = (prop->core.propType == QMetaType::Int) && !prop->core.isEnum();
     *isAssignment = false;
-    if (!prop->core.isEnum())
+    if (!prop->core.isEnum() && !isIntProp)
         return true;
 
-    QMetaProperty mprop = obj->metaObject()->property(prop->index);
+    QMetaProperty mprop = obj->metatype->firstCppMetaObject()->property(prop->index);
 
     if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
         COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
@@ -2538,30 +2532,38 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
     if (!string.at(0).isUpper())
         return true;
 
-    QStringList parts = string.split(QLatin1Char('.'));
-    if (parts.count() != 2)
+    int dot = string.indexOf(QLatin1Char('.'));
+    if (dot == -1 || dot == string.length()-1)
         return true;
 
-    QString typeName = parts.at(0);
-    QQmlType *type = 0;
-    unit->imports().resolveType(typeName, &type, 0, 0, 0, 0);
+    if (string.indexOf(QLatin1Char('.'), dot+1) != -1)
+        return true;
 
-    //handle enums on value types (where obj->typeName is empty)
-    QString objTypeName = obj->typeName;
-    if (objTypeName.isEmpty()) {
-        QQmlType *objType = toQmlType(obj);
-        if (objType)
-            objTypeName = objType->qmlTypeName();
+    QHashedStringRef typeName(string.constData(), dot);
+    QString enumValue = string.mid(dot+1);
+
+    if (isIntProp) {
+        // Allow enum assignment to ints.
+        bool ok;
+        int enumval = evaluateEnum(typeName, enumValue.toUtf8(), &ok);
+        if (ok) {
+            v->type = Value::Literal;
+            v->value = QQmlScript::Variant((double)enumval);
+            *isAssignment = true;
+        }
+        return true;
     }
 
-    if (!type)
+    QQmlType *type = 0;
+    unit->imports().resolveType(typeName, &type, 0, 0, 0, 0);
+
+    if (!type && typeName != QLatin1String("Qt"))
         return true;
 
-    QString enumValue = parts.at(1);
-    int value;
-    bool ok;
+    int value = 0;
+    bool ok = false;
 
-    if (objTypeName == type->qmlTypeName()) {
+    if (type && toQmlType(obj) == type) {
         // When these two match, we can short cut the search
         if (mprop.isFlagType()) {
             value = mprop.enumerator().keysToValue(enumValue.toUtf8().constData(), &ok);
@@ -2570,13 +2572,15 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
         }
     } else {
         // Otherwise we have to search the whole type
-        // This matches the logic in QV8TypeWrapper
-        QByteArray enumName = enumValue.toUtf8();
-        const QMetaObject *metaObject = type->baseMetaObject();
-        ok = false;
-        for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) {
-            QMetaEnum e = metaObject->enumerator(ii);
-            value = e.keyToValue(enumName.constData(), &ok);
+        if (type) {
+            value = type->enumValue(QHashedStringRef(enumValue), &ok);
+        } else {
+            QByteArray enumName = enumValue.toUtf8();
+            const QMetaObject *metaObject = StaticQtMetaObject::get();
+            for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) {
+                QMetaEnum e = metaObject->enumerator(ii);
+                value = e.keyToValue(enumName.constData(), &ok);
+            }
         }
     }
 
@@ -2590,31 +2594,24 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
     return true;
 }
 
-struct StaticQtMetaObject : public QObject
-{
-    static const QMetaObject *get()
-        { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
-};
-
 // Similar logic to above, but not knowing target property.
-int QQmlCompiler::evaluateEnum(const QByteArray& script) const
+int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const
 {
-    int dot = script.indexOf('.');
-    if (dot > 0) {
-        const QByteArray &scope = script.left(dot);
+    Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
+    *ok = false;
+
+    if (scope != QLatin1String("Qt")) {
         QQmlType *type = 0;
-        unit->imports().resolveType(QString::fromUtf8(script.left(dot)), &type, 0, 0, 0, 0);
-        if (!type && scope != "Qt")
-            return -1;
-        const QMetaObject *mo = type ? type->metaObject() : StaticQtMetaObject::get();
-        const char *key = script.constData() + dot+1;
-        int i = mo->enumeratorCount();
-        while (i--) {
-            bool ok;
-            int v = mo->enumerator(i).keyToValue(key, &ok);
-            if (ok)
-                return v;
-        }
+        unit->imports().resolveType(scope, &type, 0, 0, 0, 0);
+        return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+    }
+
+    const QMetaObject *mo = StaticQtMetaObject::get();
+    int i = mo->enumeratorCount();
+    while (i--) {
+        int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
+        if (*ok)
+            return v;
     }
     return -1;
 }
@@ -2762,7 +2759,27 @@ bool QQmlCompiler::mergeDynamicMetaProperties(QQmlScript::Object *obj)
     return true;
 }
 
-Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter)
+#include <private/qqmljsparser_p.h>
+
+static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
+{
+    if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) {
+        QString name =
+            static_cast<QQmlJS::AST::IdentifierExpression *>(node)->name.toString();
+        return QStringList() << name;
+    } else if (node->kind == QQmlJS::AST::Node::Kind_FieldMemberExpression) {
+        QQmlJS::AST::FieldMemberExpression *expr = static_cast<QQmlJS::AST::FieldMemberExpression *>(node);
+
+        QStringList rv = astNodeToStringList(expr->base);
+        if (rv.isEmpty())
+            return rv;
+        rv.append(expr->name.toString());
+        return rv;
+    }
+    return QStringList();
+}
+
+static QAtomicInt classIndexCounter(0);
 
 bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode)
 {
@@ -2775,569 +2792,542 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
         obj->dynamicSlots.isEmpty())
         return true;
 
-    bool resolveAlias = (mode == ResolveAliases);
+    Q_ASSERT(obj->synthCache == 0);
+
+    struct TypeData {
+        Object::DynamicProperty::Type dtype;
+        int metaType;
+    } builtinTypes[] = {
+        { Object::DynamicProperty::Var, QMetaType::QVariant },
+        { Object::DynamicProperty::Variant, QMetaType::QVariant },
+        { Object::DynamicProperty::Int, QMetaType::Int },
+        { Object::DynamicProperty::Bool, QMetaType::Bool },
+        { Object::DynamicProperty::Real, QMetaType::Double },
+        { Object::DynamicProperty::String, QMetaType::QString },
+        { Object::DynamicProperty::Url, QMetaType::QUrl },
+        { Object::DynamicProperty::Color, QMetaType::QColor },
+        { Object::DynamicProperty::Time, QMetaType::QTime },
+        { Object::DynamicProperty::Date, QMetaType::QDate },
+        { Object::DynamicProperty::DateTime, QMetaType::QDateTime },
+        { Object::DynamicProperty::Rect, QMetaType::QRectF },
+    };
+    static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
+
+    QByteArray newClassName;
+
+    if (compileState->root == obj && !compileState->nested) {
+        QString path = output->url.path();
+        int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+        if (lastSlash > -1) {
+            QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
+            if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
+                newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
+                               QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
+        }
+    }
+    if (newClassName.isEmpty()) {
+        newClassName = QQmlMetaObject(obj->metatype).className();
+        newClassName.append("_QML_");
+        newClassName.append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
+    }
+    QQmlPropertyCache *cache = obj->metatype->copyAndReserve(engine, obj->dynamicProperties.count(),
+                                                             obj->dynamicProperties.count() +
+                                                             obj->dynamicSignals.count() +
+                                                             obj->dynamicSlots.count(),
+                                                             obj->dynamicProperties.count() +
+                                                             obj->dynamicSignals.count());
+
+    cache->_dynamicClassName = newClassName;
+
+    int cStringNameCount = 0;
 
-    const Object::DynamicProperty *defaultProperty = 0;
     int aliasCount = 0;
     int varPropCount = 0;
-    int totalPropCount = 0;
-    int firstPropertyVarIndex = 0;
 
-    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+         p = obj->dynamicProperties.next(p)) {
 
         if (p->type == Object::DynamicProperty::Alias)
             aliasCount++;
-        if (p->type == Object::DynamicProperty::Var)
+        else if (p->type == Object::DynamicProperty::Var)
             varPropCount++;
 
-        if (p->isDefaultProperty && 
-            (resolveAlias || p->type != Object::DynamicProperty::Alias))
-            defaultProperty = p;
+        if (p->name.isLatin1()) {
+            p->nameIndex = cStringNameCount;
+            cStringNameCount += p->name.length() + 7 /* strlen("Changed") */;
+        }
+
+        // No point doing this for both the alias and non alias cases
+        QQmlPropertyData *d = property(obj, p->name);
+        if (d && d->isFinal())
+            COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
+    }
 
-        if (!resolveAlias) {
-            // No point doing this for both the alias and non alias cases
-            QQmlPropertyData *d = property(obj, p->name);
-            if (d && d->isFinal())
-                COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
+    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+        if (s->name.isLatin1()) {
+            s->nameIndex = cStringNameCount;
+            cStringNameCount += s->name.length();
         }
     }
 
-    bool buildData = resolveAlias || aliasCount == 0;
+    for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+        if (s->name.isLatin1()) {
+            s->nameIndex = cStringNameCount;
+            cStringNameCount += s->name.length();
+        }
+    }
 
-    QByteArray dynamicData;
-    if (buildData) {
-        typedef QQmlVMEMetaData VMD;
+    char *cStringData = 0;
+    if (cStringNameCount) {
+        cache->_dynamicStringData.resize(cStringNameCount);
+        cStringData = cache->_dynamicStringData.data();
 
-        dynamicData = QByteArray(sizeof(QQmlVMEMetaData) +
-                                 (obj->dynamicProperties.count() - aliasCount) * sizeof(VMD::PropertyData) +
-                                 obj->dynamicSlots.count() * sizeof(VMD::MethodData) +
-                                 aliasCount * sizeof(VMD::AliasData), 0);
-    }
+        for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+             p = obj->dynamicProperties.next(p)) {
 
-    int uniqueClassId = classIndexCounter()->fetchAndAddRelaxed(1);
+            if (p->nameIndex == -1) continue;
 
-    QByteArray newClassName = obj->metatype->className();
-    newClassName.append("_QML_");
-    newClassName.append(QByteArray::number(uniqueClassId));
+            char *myData = cStringData + p->nameIndex;
+            for (int ii = 0; ii < p->name.length(); ++ii)
+                *myData++ = p->name.at(ii).unicode();
+            *myData++ = 'C'; *myData++ = 'h'; *myData++ = 'a'; *myData++ = 'n';
+            *myData++ = 'g'; *myData++ = 'e'; *myData++ = 'd';
+        }
 
-    if (compileState->root == obj && !compileState->nested) {
-        QString path = output->url.path();
-        int lastSlash = path.lastIndexOf(QLatin1Char('/'));
-        if (lastSlash > -1) {
-            QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
-            if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
-                newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(uniqueClassId);
+        for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+
+            if (s->nameIndex == -1) continue;
+
+            char *myData = cStringData + s->nameIndex;
+            for (int ii = 0; ii < s->name.length(); ++ii)
+                *myData++ = s->name.at(ii).unicode();
+        }
+
+        for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s;
+             s = obj->dynamicSignals.next(s)) {
+
+            if (s->nameIndex == -1) continue;
+
+            char *myData = cStringData + s->nameIndex;
+            for (int ii = 0; ii < s->name.length(); ++ii)
+                *myData++ = s->name.at(ii).unicode();
         }
     }
 
-    QFastMetaBuilder builder;
-    QFastMetaBuilder::StringRef classNameRef = builder.init(newClassName.length(), 
-            obj->dynamicProperties.count() - (resolveAlias?0:aliasCount),
-            obj->dynamicSlots.count(),
-            obj->dynamicSignals.count() + obj->dynamicProperties.count(),
-            defaultProperty?1:0);
+    QByteArray dynamicData;
+    typedef QQmlVMEMetaData VMD;
 
-    struct TypeData {
-        Object::DynamicProperty::Type dtype;
-        int metaType;
-        const char *cppType;
-    } builtinTypes[] = {
-        { Object::DynamicProperty::Var, QMetaType::QVariant, "QVariant" },
-        { Object::DynamicProperty::Variant, QMetaType::QVariant, "QVariant" },
-        { Object::DynamicProperty::Int, QMetaType::Int, "int" },
-        { Object::DynamicProperty::Bool, QMetaType::Bool, "bool" },
-        { Object::DynamicProperty::Real, QMetaType::Double, "double" },
-        { Object::DynamicProperty::String, QMetaType::QString, "QString" },
-        { Object::DynamicProperty::Url, QMetaType::QUrl, "QUrl" },
-        { Object::DynamicProperty::Color, QMetaType::QColor, "QColor" },
-        { Object::DynamicProperty::Time, QMetaType::QTime, "QTime" },
-        { Object::DynamicProperty::Date, QMetaType::QDate, "QDate" },
-        { Object::DynamicProperty::DateTime, QMetaType::QDateTime, "QDateTime" },
-    };
-    static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
-    QFastMetaBuilder::StringRef typeRefs[builtinTypeCount]; 
+    dynamicData = QByteArray(sizeof(QQmlVMEMetaData) +
+                             obj->dynamicProperties.count() * sizeof(VMD::PropertyData) +
+                             obj->dynamicSlots.count() * sizeof(VMD::MethodData) +
+                             aliasCount * sizeof(VMD::AliasData), 0);
 
-    // Reserve dynamic properties
-    if (obj->dynamicProperties.count()) {
-        typedef QQmlVMEMetaData VMD;
+    int effectivePropertyIndex = cache->propertyIndexCacheStart;
+    int effectiveMethodIndex = cache->methodIndexCacheStart;
 
-        int effectivePropertyIndex = 0;
-        for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+    // First set up notify signals for properties - first normal, then var, then alias
+    enum { NSS_Normal = 0, NSS_Var = 1, NSS_Alias = 2 };
+    for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
 
-            // Reserve space for name
-            p->nameRef = builder.newString(p->name.utf8length());
+        if (ii == NSS_Var && varPropCount == 0) continue;
+        else if (ii == NSS_Alias && aliasCount == 0) continue;
 
-            int propertyType = 0;
-            bool readonly = false;
-            QFastMetaBuilder::StringRef typeRef;
+        for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+             p = obj->dynamicProperties.next(p)) {
 
-            if (p->type == Object::DynamicProperty::Alias) {
+            if ((ii == NSS_Normal && (p->type == Object::DynamicProperty::Alias ||
+                                      p->type == Object::DynamicProperty::Var)) ||
+                ((ii == NSS_Var) && (p->type != Object::DynamicProperty::Var)) ||
+                ((ii == NSS_Alias) && (p->type != Object::DynamicProperty::Alias)))
                 continue;
-            } else if (p->type < builtinTypeCount) {
-                Q_ASSERT(builtinTypes[p->type].dtype == p->type);
-                propertyType = builtinTypes[p->type].metaType;
-                if (typeRefs[p->type].isEmpty()) 
-                    typeRefs[p->type] = builder.newString(strlen(builtinTypes[p->type].cppType));
-                typeRef = typeRefs[p->type];
 
-            } else {
-                Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
-                         p->type == Object::DynamicProperty::Custom);
-
-                // XXX don't double resolve this in the case of an alias run
-
-                QByteArray customTypeName;
-                QQmlType *qmltype = 0;
-                QString url;
-                if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0))
-                    COMPILE_EXCEPTION(p, tr("Invalid property type"));
-
-                if (!qmltype) {
-                    QQmlTypeData *tdata = enginePrivate->typeLoader.get(QUrl(url));
-                    Q_ASSERT(tdata);
-                    Q_ASSERT(tdata->isComplete());
-
-                    QQmlCompiledData *data = tdata->compiledData();
-                    customTypeName = data->root->className();
-                    data->release();
-                    tdata->release();
-                } else {
-                    customTypeName = qmltype->typeName();
-                }
+            quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+                            QQmlPropertyData::IsVMESignal;
 
-                if (p->type == Object::DynamicProperty::Custom) {
-                    customTypeName += '*';
-                    propertyType = QMetaType::QObjectStar;
-                } else {
-                    readonly = true;
-                    customTypeName = QByteArray("QQmlListProperty<") + customTypeName + QByteArray(">");
-                    propertyType = qMetaTypeId<QQmlListProperty<QObject> >();
-                }
+            if (p->nameIndex != -1) {
+                QHashedCStringRef changedSignalName(cStringData + p->nameIndex,
+                                                    p->name.length() + 7 /* strlen("Changed") */);
+                cache->appendSignal(changedSignalName, flags, effectiveMethodIndex++);
+            } else {
+                QString changedSignalName = p->name.toString() + QLatin1String("Changed");
 
-                p->resolvedCustomTypeName = pool->NewByteArray(customTypeName);
-                p->typeRef = builder.newString(customTypeName.length());
-                typeRef = p->typeRef;
+                cache->appendSignal(changedSignalName, flags, effectiveMethodIndex++);
             }
+        }
+    }
 
-            if (p->type == Object::DynamicProperty::Var)
-                continue;
-
-            if (p->isReadOnly)
-                readonly = true;
-
-            if (buildData) {
-                VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
-                vmd->propertyCount++;
-                (vmd->propertyData() + effectivePropertyIndex)->propertyType = propertyType;
-            }
-
-            if (p->type < builtinTypeCount)
-                builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, (QMetaType::Type)propertyType, 
-                                    readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, 
-                                    effectivePropertyIndex);
-            else 
-                builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, 
-                                    readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, 
-                                    effectivePropertyIndex);
-
-            p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
-            builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
-
-            effectivePropertyIndex++;
-        }
-
-        if (varPropCount) {
-            VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
-            if (buildData)
-                vmd->varPropertyCount = varPropCount;
-            firstPropertyVarIndex = effectivePropertyIndex;
-            totalPropCount = varPropCount + effectivePropertyIndex;
-            for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
-                if (p->type == Object::DynamicProperty::Var) {
-                    QFastMetaBuilder::StringRef typeRef = typeRefs[p->type];
-                    if (buildData) {
-                        vmd->propertyCount++;
-                        (vmd->propertyData() + effectivePropertyIndex)->propertyType = QMetaType::QVariant;
-                    }
+    // Dynamic signals
+    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+        int paramCount = s->parameterNames.count();
 
-                    builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef,
-                                        QMetaType::QVariant,
-                                        p->isReadOnly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
-                                        effectivePropertyIndex);
+        QList<QByteArray> names;
+        QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
 
-                    p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
-                    builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
+        if (paramCount) {
+            paramTypes[0] = paramCount;
 
-                    effectivePropertyIndex++;
-                }
+            for (int i = 0; i < paramCount; ++i) {
+                Q_ASSERT(s->parameterTypes.at(i) < builtinTypeCount);
+                paramTypes[i + 1] = builtinTypes[s->parameterTypes.at(i)].metaType;
+                names.append(s->parameterNames.at(i).toString().toUtf8());
             }
         }
-        
-        if (aliasCount) {
-            int aliasIndex = 0;
-            for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
-                if (p->type == Object::DynamicProperty::Alias) {
-                    if (resolveAlias) {
-                        Q_ASSERT(buildData);
-                        ((QQmlVMEMetaData *)dynamicData.data())->aliasCount++;
-                        COMPILE_CHECK(compileAlias(builder, dynamicData, obj, effectivePropertyIndex, 
-                                                   aliasIndex, *p));
-                    }
-                    // Even if we aren't resolving the alias, we need a fake signal so that the 
-                    // metaobject remains consistent across the resolve and non-resolve alias runs
-                    p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
-                    builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
-                    effectivePropertyIndex++;
-                    aliasIndex++;
-                }
-            }
+
+        ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
+
+        quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+                        QQmlPropertyData::IsVMESignal;
+        if (paramCount)
+            flags |= QQmlPropertyData::HasArguments;
+
+        if (s->nameIndex != -1) {
+            QHashedCStringRef name(cStringData + s->nameIndex, s->name.length(), s->name.hash());
+            cache->appendSignal(name, flags, effectiveMethodIndex++,
+                                paramCount?paramTypes.constData():0, names);
+        } else {
+            QString name = s->name.toString();
+            cache->appendSignal(name, flags, effectiveMethodIndex++,
+                                paramCount?paramTypes.constData():0, names);
         }
     }
 
-    // Reserve default property
-    QFastMetaBuilder::StringRef defPropRef;
-    if (defaultProperty) {
-        defPropRef = builder.newString(strlen("DefaultProperty"));
-        builder.setClassInfo(0, defPropRef, defaultProperty->nameRef);
-    }
-
-    // Reserve dynamic signals
-    int signalIndex = 0;
-    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
 
+    // Dynamic slots
+    for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
         int paramCount = s->parameterNames.count();
 
-        int signatureSize = s->name.utf8length() + 2 /* paren */;
-        int namesSize = 0;
-        if (paramCount) signatureSize += s->parameterTypesLength() + (paramCount - 1) /* commas */;
-        if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1) /* commas */;
+        quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
 
-        s->signatureRef = builder.newString(signatureSize);
-        if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
+        if (paramCount)
+            flags |= QQmlPropertyData::HasArguments;
 
-        if (buildData)
-            ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
-        
-        builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->signatureRef, s->parameterNamesRef);
-        ++signalIndex;
+        if (s->nameIndex != -1) {
+            QHashedCStringRef name(cStringData + s->nameIndex, s->name.length(), s->name.hash());
+            cache->appendMethod(name, flags, effectiveMethodIndex++, s->parameterNames);
+        } else {
+            QString name = s->name.toString();
+            cache->appendMethod(name, flags, effectiveMethodIndex++, s->parameterNames);
+        }
     }
 
-    // Reserve dynamic slots
-    if (obj->dynamicSlots.count()) {
 
-        // Allocate QVariant string
-        if (typeRefs[0].isEmpty()) 
-            typeRefs[0] = builder.newString(strlen(builtinTypes[0].cppType));
+    // Dynamic properties (except var and aliases)
+    int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
+    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+         p = obj->dynamicProperties.next(p)) {
 
-        typedef QQmlVMEMetaData VMD;
+        if (p->type == Object::DynamicProperty::Alias ||
+            p->type == Object::DynamicProperty::Var)
+            continue;
 
-        int methodIndex = 0;
-        for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
-            int paramCount = s->parameterNames.count();
-
-            int signatureSize = s->name.utf8length() + 2 /* paren */;
-            int namesSize = 0; 
-            if (paramCount) signatureSize += (paramCount * strlen("QVariant") + (paramCount - 1));
-            if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */); 
-
-            s->signatureRef = builder.newString(signatureSize);
-            if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
-
-            builder.setMethod(methodIndex, s->signatureRef, s->parameterNamesRef, typeRefs[0]);
-
-            if (buildData) {
-                QString funcScript;
-                funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ + 
-                        namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
-                funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
-                for (int jj = 0; jj < paramCount; ++jj) {
-                    if (jj) funcScript.append(QLatin1Char(','));
-                    funcScript.append(QLatin1String(s->parameterNames.at(jj)));
-                }
-                funcScript += QLatin1Char(')') + s->body + QLatin1Char(')');
+        int propertyType = 0;
+        int vmePropertyType = 0;
+        quint32 propertyFlags = 0;
 
-                QByteArray utf8 = funcScript.toUtf8();
-                VMD::MethodData methodData = { s->parameterNames.count(), 0, 
-                                               utf8.length(),
-                                               s->location.start.line };
+        if (p->type < builtinTypeCount) {
+            propertyType = builtinTypes[p->type].metaType;
+            vmePropertyType = propertyType;
 
-                VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
-                vmd->methodCount++;
+            if (p->type == Object::DynamicProperty::Variant)
+                propertyFlags |= QQmlPropertyData::IsQVariant;
+        } else {
+            Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
+                     p->type == Object::DynamicProperty::Custom);
 
-                VMD::MethodData &md = *(vmd->methodData() + methodIndex);
-                md = methodData;
-                md.bodyOffset = dynamicData.size();
+            QQmlType *qmltype = 0;
+            QString url;
+            if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0))
+                COMPILE_EXCEPTION(p, tr("Invalid property type"));
 
-                dynamicData.append((const char *)utf8.constData(), utf8.length());
-            }
+            if (!qmltype) {
+                QQmlTypeData *tdata = enginePrivate->typeLoader.getType(QUrl(url));
+                Q_ASSERT(tdata);
+                Q_ASSERT(tdata->isComplete());
 
+                QQmlCompiledData *data = tdata->compiledData();
 
-            methodIndex++;
-        }
-    }
+                if (p->type == Object::DynamicProperty::Custom) {
+                    propertyType = data->metaTypeId;
+                    vmePropertyType = QMetaType::QObjectStar;
+                } else {
+                    propertyType = data->listMetaTypeId;
+                    vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
+                }
 
-    // Now allocate used builtin types
-    for (int ii = 0; ii < builtinTypeCount; ++ii) {
-        if (!typeRefs[ii].isEmpty())
-            typeRefs[ii].load(builtinTypes[ii].cppType);
-    }
+                tdata->release();
+            } else {
+                if (p->type == Object::DynamicProperty::Custom) {
+                    propertyType = qmltype->typeId();
+                    vmePropertyType = QMetaType::QObjectStar;
+                } else {
+                    propertyType = qmltype->qListTypeId();
+                    vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
+                }
+            }
 
-    // Now allocate properties
-    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+            if (p->type == Object::DynamicProperty::Custom)
+                propertyFlags |= QQmlPropertyData::IsQObjectDerived;
+            else
+                propertyFlags |= QQmlPropertyData::IsQList;
+        }
 
-        char *d = p->changedSignatureRef.data();
-        p->name.writeUtf8(d);
-        strcpy(d + p->name.utf8length(), "Changed()");
+        if (!p->isReadOnly && p->type != Object::DynamicProperty::CustomList)
+            propertyFlags |= QQmlPropertyData::IsWritable;
 
-        if (p->type == Object::DynamicProperty::Alias && !resolveAlias)
-            continue;
+        if (p->nameIndex != -1) {
+            QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
+                                           p->name.hash());
+            if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
+            cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+                                  propertyType, effectiveSignalIndex);
+        } else {
+            QString propertyName = p->name.toString();
+            if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
+            cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+                                  propertyType, effectiveSignalIndex);
+        }
 
-        p->nameRef.load(p->name);
+        effectiveSignalIndex++;
 
-        if (p->type >= builtinTypeCount) {
-            Q_ASSERT(p->resolvedCustomTypeName);
-            p->typeRef.load(*p->resolvedCustomTypeName);
-        }
+        VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+        (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
+        vmd->propertyCount++;
     }
 
-    // Allocate default property if necessary
-    if (defaultProperty) 
-        strcpy(defPropRef.data(), "DefaultProperty");
-
-    // Now allocate signals
-    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+    // Now do var properties
+    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p && varPropCount;
+         p = obj->dynamicProperties.next(p)) {
 
-        char *d = s->signatureRef.data();
-        char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
-        s->name.writeUtf8(d); d += s->name.utf8length();
-        *d++ = '('; 
+        if (p->type != Object::DynamicProperty::Var)
+            continue;
 
-        for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
-            if (jj != 0) { *d++ = ','; *d2++ = ','; }
-            strcpy(d, s->parameterTypes.at(jj).constData());
-            d += s->parameterTypes.at(jj).length();
-            s->parameterNames.at(jj).writeUtf8(d2);
-            d2 += s->parameterNames.at(jj).utf8length();
+        quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
+        if (!p->isReadOnly)
+            propertyFlags |= QQmlPropertyData::IsWritable;
+
+        VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+        (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
+        vmd->propertyCount++;
+        ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
+
+        if (p->nameIndex != -1) {
+            QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
+                                           p->name.hash());
+            if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
+            cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+                                  QMetaType::QVariant, effectiveSignalIndex);
+        } else {
+            QString propertyName = p->name.toString();
+            if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
+            cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+                                  QMetaType::QVariant, effectiveSignalIndex);
         }
-        *d++ = ')';
-        *d = 0;
-        if (d2) *d2 = 0;
-    }
 
-    // Now allocate methods
-    for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
-        char *d = s->signatureRef.data();
-        char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
-        s->name.writeUtf8(d); d += s->name.utf8length();
-        *d++ = '('; 
-        for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
-            if (jj != 0) { *d++ = ','; *d2++ = ','; }
-            strcpy(d, "QVariant");
-            d += strlen("QVariant");
-            strcpy(d2, s->parameterNames.at(jj).constData());
-            d2 += s->parameterNames.at(jj).length();
-        }
-        *d++ = ')';
-        *d = 0;
-        if (d2) *d2 = 0;
+        effectiveSignalIndex++;
     }
 
-    // Now allocate class name
-    classNameRef.load(newClassName);
+    // Alias property count.  Actual data is setup in buildDynamicMetaAliases
+    ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
+
+    // Dynamic slot data - comes after the property data
+    for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+        int paramCount = s->parameterNames.count();
 
-    obj->metadata = builder.toData();
-    builder.fromData(&obj->extObject, obj->metatype, obj->metadata);
+        QString funcScript;
+        int namesSize = 0;
+        if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */);
+        funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ +
+                           namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
+        funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
+        for (int jj = 0; jj < paramCount; ++jj) {
+            if (jj) funcScript.append(QLatin1Char(','));
+            funcScript.append(QLatin1String(s->parameterNames.at(jj)));
+        }
+        funcScript += QLatin1Char(')') + s->body + QLatin1Char(')');
 
-    if (mode == IgnoreAliases && aliasCount) 
-        compileState->aliasingObjects.append(obj);
+        QByteArray utf8 = funcScript.toUtf8();
+        VMD::MethodData methodData = { s->parameterNames.count(),
+                                       dynamicData.size(),
+                                       utf8.length(),
+                                       s->location.start.line };
 
-    obj->synthdata = dynamicData;
+        VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+        VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
+        vmd->methodCount++;
+        md = methodData;
 
-    if (obj->synthCache) {
-        obj->synthCache->release();
-        obj->synthCache = 0;
+        dynamicData.append((const char *)utf8.constData(), utf8.length());
     }
 
-    if (obj->type != -1) {
-        QQmlPropertyCache *superCache = output->types[obj->type].createPropertyCache(engine);
-        QQmlPropertyCache *cache =
-            superCache->copyAndAppend(engine, &obj->extObject,
-                                      QQmlPropertyData::NoFlags,
-                                      QQmlPropertyData::IsVMEFunction,
-                                      QQmlPropertyData::IsVMESignal);
-
-        // now we modify the flags appropriately for var properties.
-        int propertyOffset = obj->extObject.propertyOffset();
-        QQmlPropertyData *currPropData = 0;
-        for (int pvi = firstPropertyVarIndex; pvi < totalPropCount; ++pvi) {
-            currPropData = cache->property(pvi + propertyOffset);
-            currPropData->setFlags(currPropData->getFlags() | QQmlPropertyData::IsVMEProperty);
-        }
+    if (aliasCount)
+        compileState->aliasingObjects.append(obj);
 
-        obj->synthCache = cache;
-    }
+    obj->synthdata = dynamicData;
+    obj->synthCache = cache;
+    obj->metatype = cache;
 
     return true;
 }
 
-bool QQmlCompiler::checkValidId(QQmlScript::Value *v, const QString &val)
+bool QQmlCompiler::buildDynamicMetaAliases(QQmlScript::Object *obj)
 {
-    if (val.isEmpty()) 
-        COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
+    Q_ASSERT(obj->synthCache);
 
-    QChar ch = val.at(0);
-    if (ch.isLetter() && !ch.isLower())
-        COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
+    QByteArray &dynamicData = obj->synthdata;
 
-    QChar u(QLatin1Char('_'));
-    if (!ch.isLetter() && ch != u)
-        COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
+    QQmlPropertyCache *cache = obj->synthCache;
+    char *cStringData = cache->_dynamicStringData.data();
 
-    for (int ii = 1; ii < val.count(); ++ii) {
-        ch = val.at(ii);
-        if (!ch.isLetterOrNumber() && ch != u)
-            COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
-    }
+    int effectiveSignalIndex = cache->signalHandlerIndexCacheStart + cache->propertyIndexCache.count();
+    int effectivePropertyIndex = cache->propertyIndexCacheStart + cache->propertyIndexCache.count();
+    int effectiveAliasIndex = 0;
 
-    if (enginePrivate->v8engine()->illegalNames().contains(val))
-        COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
+    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+         p = obj->dynamicProperties.next(p)) {
 
-    return true;
-}
+        if (p->type != Object::DynamicProperty::Alias)
+            continue;
 
-#include <private/qqmljsparser_p.h>
+        if (!p->defaultValue)
+            COMPILE_EXCEPTION(obj, tr("No property alias location"));
 
-static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
-{
-    if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) {
-        QString name =
-            static_cast<QQmlJS::AST::IdentifierExpression *>(node)->name.toString();
-        return QStringList() << name;
-    } else if (node->kind == QQmlJS::AST::Node::Kind_FieldMemberExpression) {
-        QQmlJS::AST::FieldMemberExpression *expr = static_cast<QQmlJS::AST::FieldMemberExpression *>(node);
+        if (!p->defaultValue->values.isOne() ||
+            p->defaultValue->values.first()->object ||
+            !p->defaultValue->values.first()->value.isScript())
+            COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
 
-        QStringList rv = astNodeToStringList(expr->base);
-        if (rv.isEmpty())
-            return rv;
-        rv.append(expr->name.toString());
-        return rv;
-    }
-    return QStringList();
-}
+        QQmlJS::AST::Node *node = p->defaultValue->values.first()->value.asAST();
+        Q_ASSERT(node);
 
-bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder,
-                                        QByteArray &data,
-                                        QQmlScript::Object *obj,
-                                        int propIndex, int aliasIndex,
-                                        Object::DynamicProperty &prop)
-{
-    if (!prop.defaultValue)
-        COMPILE_EXCEPTION(obj, tr("No property alias location"));
+        QStringList alias = astNodeToStringList(node);
+        if (alias.count() < 1 || alias.count() > 3)
+            COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
 
-    if (!prop.defaultValue->values.isOne() ||
-        prop.defaultValue->values.first()->object ||
-        !prop.defaultValue->values.first()->value.isScript())
-        COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
+        QQmlScript::Object *idObject = compileState->ids.value(alias.at(0));
+        if (!idObject)
+            COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
 
-    QQmlJS::AST::Node *node = prop.defaultValue->values.first()->value.asAST();
-    if (!node)
-        COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen?
+        int propIdx = -1;
+        int notifySignal = -1;
+        int flags = 0;
+        int type = 0;
+        bool writable = false;
+        bool resettable = false;
 
-    QStringList alias = astNodeToStringList(node);
+        quint32 propertyFlags = QQmlPropertyData::IsAlias;
 
-    if (alias.count() < 1 || alias.count() > 3)
-        COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+        if (alias.count() == 2 || alias.count() == 3) {
+            QQmlPropertyData *property = this->property(idObject, alias.at(1));
 
-    QQmlScript::Object *idObject = compileState->ids.value(alias.at(0));
-    if (!idObject)
-        COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
+            if (!property || property->coreIndex > 0xFFFF)
+                COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
 
-    QByteArray typeName;
+            propIdx = property->coreIndex;
+            type = property->propType;
 
-    int propIdx = -1;
-    int flags = 0;
-    int type = 0;
-    bool writable = false;
-    bool resettable = false;
-    if (alias.count() == 2 || alias.count() == 3) {
-        propIdx = indexOfProperty(idObject, alias.at(1));
+            writable = property->isWritable();
+            resettable = property->isResettable();
+            notifySignal = property->notifyIndex;
 
-        if (-1 == propIdx) {
-            COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
-        } else if (propIdx > 0xFFFF) {
-            COMPILE_EXCEPTION(prop.defaultValue, tr("Alias property exceeds alias bounds"));
-        }
+            if (alias.count() == 3) {
+                QQmlValueType *valueType = enginePrivate->valueTypes[type]; // XXX threadsafe?
+                if (!valueType)
+                    COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
 
-        QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx);
-        if (!aliasProperty.isScriptable())
-            COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
+                propIdx |= ((unsigned int)type) << 24;
+                int valueTypeIndex =
+                    valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData());
+                if (valueTypeIndex == -1)
+                    COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
+                Q_ASSERT(valueTypeIndex <= 0xFF);
 
-        writable = aliasProperty.isWritable() && !prop.isReadOnly;
-        resettable = aliasProperty.isResettable() && !prop.isReadOnly;
+                propIdx |= (valueTypeIndex << 16);
+                if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
+                    type = QVariant::Int;
+                else
+                    type = valueType->metaObject()->property(valueTypeIndex).userType();
 
-        if (aliasProperty.type() < QVariant::UserType
-            || uint(aliasProperty.type()) == QMetaType::QVariant)
-            type = aliasProperty.type();
+            } else {
+                if (property->isEnum()) {
+                    type = QVariant::Int;
+                } else {
+                    // Copy type flags
+                    propertyFlags |= property->getFlags() & QQmlPropertyData::PropTypeFlagMask;
 
-        if (alias.count() == 3) {
-            QQmlValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()];
-            if (!valueType)
-                COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
+                    if (property->isVarProperty())
+                        propertyFlags |= QQmlPropertyData::IsQVariant;
 
-            propIdx |= ((unsigned int)aliasProperty.type()) << 24;
+                    if (property->isQObject())
+                        flags |= QML_ALIAS_FLAG_PTR;
+                }
+            }
+        } else {
+            Q_ASSERT(idObject->type != -1); // How else did it get an id?
 
-            int valueTypeIndex = valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData());
-            if (valueTypeIndex == -1)
-                COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
-            Q_ASSERT(valueTypeIndex <= 0xFF);
-            
-            aliasProperty = valueType->metaObject()->property(valueTypeIndex);
-            propIdx |= (valueTypeIndex << 16);
+            const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type);
+            if (ref.type)
+                type = ref.type->typeId();
+            else
+                type = ref.component->metaTypeId;
 
-            // update the property type
-            type = aliasProperty.type();
-            if (type >= (int)QVariant::UserType)
-                type = 0;
+            flags |= QML_ALIAS_FLAG_PTR;
+            propertyFlags |= QQmlPropertyData::IsQObjectDerived;
         }
 
-        if (aliasProperty.isEnumType()) 
-            typeName = "int";  // Avoid introducing a dependency on the aliased metaobject
-        else
-            typeName = aliasProperty.typeName();
-    } else {
-        Q_ASSERT(idObject->type != -1); // How else did it get an id?
+        QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags, notifySignal };
+
+        typedef QQmlVMEMetaData VMD;
+        VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+        *(vmd->aliasData() + effectiveAliasIndex++) = aliasData;
 
-        const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type);
-        if (ref.type)
-            typeName = ref.type->typeName();
+        if (!p->isReadOnly && writable)
+            propertyFlags |= QQmlPropertyData::IsWritable;
         else
-            typeName = ref.component->root->className();
+            propertyFlags &= ~QQmlPropertyData::IsWritable;
 
-        typeName += '*';
+        if (resettable)
+            propertyFlags |= QQmlPropertyData::IsResettable;
+        else
+            propertyFlags &= ~QQmlPropertyData::IsResettable;
+
+        if (p->nameIndex != -1) {
+            QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
+                                           p->name.hash());
+            if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
+            cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+                                  type, effectiveSignalIndex++);
+        } else {
+            QString propertyName = p->name.toString();
+            if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
+            cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+                                  type, effectiveSignalIndex++);
+        }
     }
 
-    if (typeName.endsWith('*'))
-        flags |= QML_ALIAS_FLAG_PTR;
+    return true;
+}
 
-    QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags };
+bool QQmlCompiler::checkValidId(QQmlScript::Value *v, const QString &val)
+{
+    if (val.isEmpty())
+        COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
 
-    typedef QQmlVMEMetaData VMD;
-    VMD *vmd = (QQmlVMEMetaData *)data.data();
-    *(vmd->aliasData() + aliasIndex) = aliasData;
+    QChar ch = val.at(0);
+    if (ch.isLetter() && !ch.isLower())
+        COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
 
-    prop.nameRef = builder.newString(prop.name.utf8length());
-    prop.resolvedCustomTypeName = pool->NewByteArray(typeName);
-    prop.typeRef = builder.newString(typeName.length());
+    QChar u(QLatin1Char('_'));
+    if (!ch.isLetter() && ch != u)
+        COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
 
-    int propertyFlags = 0;
-    if (writable)
-        propertyFlags |= QFastMetaBuilder::Writable;
-    if (resettable)
-        propertyFlags |= QFastMetaBuilder::Resettable;
+    for (int ii = 1; ii < val.count(); ++ii) {
+        ch = val.at(ii);
+        if (!ch.isLetterOrNumber() && ch != u)
+            COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
+    }
 
-    builder.setProperty(propIndex, prop.nameRef, prop.typeRef, (QMetaType::Type)type, 
-                        (QFastMetaBuilder::PropertyFlag)propertyFlags,
-                        propIndex);
+    if (enginePrivate->v8engine()->illegalNames().contains(val))
+        COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
 
     return true;
 }
@@ -3348,7 +3338,7 @@ bool QQmlCompiler::buildBinding(QQmlScript::Value *value,
 {
     Q_ASSERT(prop->index != -1);
     Q_ASSERT(prop->parent);
-    Q_ASSERT(prop->parent->metaObject());
+    Q_ASSERT(prop->parent->metatype);
 
     if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration)
         COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
@@ -3468,8 +3458,10 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
 
         Instruction::StoreV4Binding store;
         store.value = js.compiledIndex;
+        store.fallbackValue = js.sharedIndex;
         store.context = js.bindingContext.stack;
         store.owner = js.bindingContext.owner;
+        store.isAlias = prop->isAlias;
         if (valueTypeProperty) {
             store.property = (valueTypeProperty->index & 0xFFFF) |
                              ((valueTypeProperty->type & 0xFF)) << 16 |
@@ -3482,18 +3474,27 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
         store.line = binding->location.start.line;
         store.column = binding->location.start.column;
         output->addInstruction(store);
+
+        if (store.fallbackValue > -1) {
+            //also create v8 instruction (needed to properly configure the fallback v8 binding)
+            JSBindingReference &js = static_cast<JSBindingReference &>(*binding->bindingReference);
+            js.dataType = BindingReference::V8;
+            genBindingAssignment(binding, prop, obj, valueTypeProperty);
+        }
     } else if (ref.dataType == BindingReference::V8) {
         const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
 
         Instruction::StoreV8Binding store;
-        store.value = js.compiledIndex;
+        store.value = js.sharedIndex;
         store.context = js.bindingContext.stack;
         store.owner = js.bindingContext.owner;
+        store.isAlias = prop->isAlias;
         if (valueTypeProperty) {
             store.isRoot = (compileState->root == valueTypeProperty->parent);
         } else {
             store.isRoot = (compileState->root == obj);
         }
+        store.isFallback = js.compiledIndex > -1;
         store.line = binding->location.start.line;
         store.column = binding->location.start.column;
 
@@ -3509,30 +3510,30 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
     } else if (ref.dataType == BindingReference::QtScript) {
         const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
 
-        QQmlInstruction store;
-        store.assignBinding.value = output->indexForString(js.rewrittenExpression);
-        store.assignBinding.context = js.bindingContext.stack;
-        store.assignBinding.owner = js.bindingContext.owner;
-        store.assignBinding.line = binding->location.start.line;
-        store.assignBinding.column = binding->location.start.column;
+        Instruction::StoreBinding store;
+        store.value = output->indexForString(js.rewrittenExpression);
+        store.context = js.bindingContext.stack;
+        store.owner = js.bindingContext.owner;
+        store.line = binding->location.start.line;
+        store.column = binding->location.start.column;
+        store.isAlias = prop->isAlias;
 
         if (valueTypeProperty) {
-            store.assignBinding.isRoot = (compileState->root == valueTypeProperty->parent);
+            store.isRoot = (compileState->root == valueTypeProperty->parent);
         } else {
-            store.assignBinding.isRoot = (compileState->root == obj);
+            store.isRoot = (compileState->root == obj);
         }
+        store.isFallback = false;
 
         Q_ASSERT(js.bindingContext.owner == 0 ||
                  (js.bindingContext.owner != 0 && valueTypeProperty));
         if (js.bindingContext.owner) {
-            store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
+            store.property = genValueTypeData(prop, valueTypeProperty);
         } else {
-            store.assignBinding.property = prop->core;
+            store.property = prop->core;
         }
-        output->addInstructionHelper(
-            !prop->isAlias ? QQmlInstruction::StoreBinding
-                           : QQmlInstruction::StoreBindingOnAlias
-            , store);
+
+        output->addInstruction(store);
     } else {
         Q_ASSERT(!"Unhandled BindingReference::DataType type");
     }
@@ -3557,8 +3558,7 @@ QQmlCompiler::genValueTypeData(QQmlScript::Property *valueTypeProp,
                                        QQmlScript::Property *prop)
 {
     typedef QQmlPropertyPrivate QDPP;
-    return QDPP::saveValueType(prop->parent->metaObject(), prop->index, 
-                               enginePrivate->valueTypes[prop->type]->metaObject(), 
+    return QDPP::saveValueType(prop->core, enginePrivate->valueTypes[prop->type]->metaObject(),
                                valueTypeProp->index, engine);
 }
 
@@ -3569,7 +3569,7 @@ bool QQmlCompiler::completeComponentBuild()
 
     for (Object *aliasObject = compileState->aliasingObjects.first(); aliasObject; 
          aliasObject = compileState->aliasingObjects.next(aliasObject)) 
-        COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
+        COMPILE_CHECK(buildDynamicMetaAliases(aliasObject));
 
     QV4Compiler::Expression expr(unit->imports());
     expr.component = compileState->root;
@@ -3584,21 +3584,27 @@ bool QQmlCompiler::completeComponentBuild()
 
         JSBindingReference &binding = *b;
 
-        // ### We don't currently optimize for bindings on alias's - because 
-        // of the solution to QTBUG-13719
-        if (!binding.property->isAlias) {
-            expr.context = binding.bindingContext.object;
-            expr.property = binding.property;
-            expr.expression = binding.expression;
-
-            int index = bindingCompiler.compile(expr, enginePrivate);
-            if (index != -1) {
-                binding.dataType = BindingReference::V4;
-                binding.compiledIndex = index;
-                if (componentStats)
-                    componentStats->componentStat.optimizedBindings.append(b->value->location);
+        // First try v4
+        expr.context = binding.bindingContext.object;
+        expr.property = binding.property;
+        expr.expression = binding.expression;
+
+        bool needsFallback = false;
+        int index = bindingCompiler.compile(expr, enginePrivate, &needsFallback);
+        if (index != -1) {
+            // Ensure the index value fits within the available space
+            Q_ASSERT(index < (1 << 15));
+
+            binding.dataType = BindingReference::V4;
+            binding.compiledIndex = index;
+            binding.sharedIndex = -1;
+            if (componentStats)
+                componentStats->componentStat.optimizedBindings.append(b->value->location);
+
+            if (!needsFallback)
                 continue;
-            } 
+
+            // Drop through. We need to create a V8 binding in case the V4 binding is invalidated
         }
 
         // Pre-rewrite the expression
@@ -3609,16 +3615,23 @@ bool QQmlCompiler::completeComponentBuild()
         bool isSharable = false;
         binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable);
 
-        if (isSharable && !binding.property->isValueTypeSubProperty && !binding.property->isAlias /* See above re alias */ &&
-            binding.property->type != qMetaTypeId<QQmlBinding*>()) {
-            binding.dataType = BindingReference::V8;
+        if (isSharable && binding.property->type != qMetaTypeId<QQmlBinding*>()) {
             sharedBindings.append(b);
+
+            if (!needsFallback) {
+                binding.dataType = BindingReference::V8;
+                binding.compiledIndex = -1;
+
+                if (componentStats)
+                    componentStats->componentStat.sharedBindings.append(b->value->location);
+            }
         } else {
+            Q_ASSERT(!needsFallback);
             binding.dataType = BindingReference::QtScript;
-        }
 
-        if (componentStats)
-            componentStats->componentStat.scriptBindings.append(b->value->location);
+            if (componentStats)
+                componentStats->componentStat.scriptBindings.append(b->value->location);
+        }
     }
 
     if (!sharedBindings.isEmpty()) {
@@ -3650,7 +3663,10 @@ bool QQmlCompiler::completeComponentBuild()
 
             functionArray += expression.toUtf8();
             lineNumber += expression.count(QLatin1Char('\n'));
-            reference->compiledIndex = ii;
+
+            // Ensure the index value fits within the available space
+            Q_ASSERT(ii < (1 << 15));
+            reference->sharedIndex = ii;
         }
         functionArray.append("]", 1);
 
@@ -3689,9 +3705,9 @@ void QQmlCompiler::dumpStats()
                 output.append("            ");
             }
 
-            output.append("(");
+            output.append('(');
             output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.line));
-            output.append(":");
+            output.append(':');
             output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.column));
             output.append(") ");
         }
@@ -3699,18 +3715,37 @@ void QQmlCompiler::dumpStats()
             qWarning().nospace() << output.constData();
         }
 
+        qWarning().nospace() << "        Shared Bindings:    " << stat.sharedBindings.count();
+        {
+        QByteArray output;
+        for (int ii = 0; ii < stat.sharedBindings.count(); ++ii) {
+            if (0 == (ii % 10)) {
+                if (ii) output.append('\n');
+                output.append("            ");
+            }
+
+            output.append('(');
+            output.append(QByteArray::number(stat.sharedBindings.at(ii).start.line));
+            output.append(':');
+            output.append(QByteArray::number(stat.sharedBindings.at(ii).start.column));
+            output.append(") ");
+        }
+        if (!output.isEmpty())
+            qWarning().nospace() << output.constData();
+        }
+
         qWarning().nospace() << "        QScript Bindings:   " << stat.scriptBindings.count();
         {
         QByteArray output;
         for (int ii = 0; ii < stat.scriptBindings.count(); ++ii) {
             if (0 == (ii % 10)) {
-                if (ii) output.append("\n");
+                if (ii) output.append('\n');
                 output.append("            ");
             }
 
-            output.append("(");
+            output.append('(');
             output.append(QByteArray::number(stat.scriptBindings.at(ii).start.line));
-            output.append(":");
+            output.append(':');
             output.append(QByteArray::number(stat.scriptBindings.at(ii).start.column));
             output.append(") ");
         }
@@ -3726,13 +3761,13 @@ void QQmlCompiler::dumpStats()
 */
 bool QQmlCompiler::canCoerce(int to, QQmlScript::Object *from)
 {
-    const QMetaObject *toMo = enginePrivate->rawMetaObjectForType(to);
-    const QMetaObject *fromMo = from->metaObject();
+    QQmlPropertyCache *toMo = enginePrivate->rawPropertyCacheForType(to);
+    QQmlPropertyCache *fromMo = from->metatype;
 
     while (fromMo) {
-        if (QQmlPropertyPrivate::equal(fromMo, toMo))
+        if (fromMo == toMo)
             return true;
-        fromMo = fromMo->superClass();
+        fromMo = fromMo->parent();
     }
     return false;
 }
@@ -3744,7 +3779,7 @@ QString QQmlCompiler::elementName(QQmlScript::Object *o)
 {
     Q_ASSERT(o);
     if (o->type != -1) {
-        return output->types.at(o->type).className;
+        return unit->parser().referencedTypes().at(o->type)->name;
     } else {
         return QString();
     }
@@ -3752,8 +3787,10 @@ QString QQmlCompiler::elementName(QQmlScript::Object *o)
 
 QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from)
 {
-    // ### Optimize
-    const QMetaObject *mo = from->metatype;
+    if (from->type != -1 && output->types.at(from->type).type)
+        return output->types.at(from->type).type;
+
+    const QMetaObject *mo = from->metatype->firstCppMetaObject();
     QQmlType *type = 0;
     while (!type && mo) {
         type = QQmlMetaType::qmlType(mo);
@@ -3764,7 +3801,7 @@ QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from)
 
 QStringList QQmlCompiler::deferredProperties(QQmlScript::Object *obj)
 {
-    const QMetaObject *mo = obj->metatype;
+    const QMetaObject *mo = obj->metatype->firstCppMetaObject();
 
     int idx = mo->indexOfClassInfo("DeferredPropertyNames");
     if (idx == -1)
@@ -3775,17 +3812,21 @@ QStringList QQmlCompiler::deferredProperties(QQmlScript::Object *obj)
     return rv;
 }
 
+QQmlPropertyCache *
+QQmlCompiler::propertyCacheForObject(QQmlScript::Object *object)
+ {
+     if (object->synthCache)
+        return object->synthCache;
+     else if (object->type != -1)
+        return output->types[object->type].createPropertyCache(engine);
+     else
+        return object->metatype;
+}
+
 QQmlPropertyData *
 QQmlCompiler::property(QQmlScript::Object *object, int index)
 {
-    QQmlPropertyCache *cache = 0;
-
-    if (object->synthCache)
-        cache = object->synthCache;
-    else if (object->type != -1)
-        cache = output->types[object->type].createPropertyCache(engine);
-    else
-        cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+    QQmlPropertyCache *cache = propertyCacheForObject(object);
 
     return cache->property(index);
 }
@@ -3795,14 +3836,7 @@ QQmlCompiler::property(QQmlScript::Object *object, const QHashedStringRef &name,
 {
     if (notInRevision) *notInRevision = false;
 
-    QQmlPropertyCache *cache = 0;
-
-    if (object->synthCache)
-        cache = object->synthCache;
-    else if (object->type != -1)
-        cache = output->types[object->type].createPropertyCache(engine);
-    else
-        cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+    QQmlPropertyCache *cache = propertyCacheForObject(object);
 
     QQmlPropertyData *d = cache->property(name);
 
@@ -3824,14 +3858,7 @@ QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, b
 {
     if (notInRevision) *notInRevision = false;
 
-    QQmlPropertyCache *cache = 0;
-
-    if (object->synthCache)
-        cache = object->synthCache;
-    else if (object->type != -1)
-        cache = output->types[object->type].createPropertyCache(engine);
-    else
-        cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+    QQmlPropertyCache *cache = propertyCacheForObject(object);
 
 
     QQmlPropertyData *d = cache->property(name);
@@ -3843,7 +3870,7 @@ QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, b
     if (d && !cache->isAllowedInRevision(d)) {
         if (notInRevision) *notInRevision = true;
         return 0;
-    } else if (d) {
+    } else if (d && d->isSignal()) {
         return d;
     }
 
@@ -3852,7 +3879,7 @@ QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, b
 
         d = property(object, propName, notInRevision);
         if (d) 
-            return cache->method(d->notifyIndex);
+            return cache->signal(d->notifyIndex);
     }
 
     return 0;