Optimize default property resolution in compiler
authorAaron Kennedy <aaron.kennedy@nokia.com>
Fri, 22 Jul 2011 03:32:47 +0000 (13:32 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 30 Aug 2011 11:18:28 +0000 (13:18 +0200)
Change-Id: I90b677a190c0c59ba681a7643a9b13cfb938d5a1
Reviewed-on: http://codereview.qt.nokia.com/3769
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
src/declarative/qml/ftw/qdeclarativepool_p.h
src/declarative/qml/ftw/qhashedstring.cpp
src/declarative/qml/ftw/qhashedstring_p.h
src/declarative/qml/qdeclarativecompiler.cpp
src/declarative/qml/qdeclarativeparser_p.h
src/declarative/qml/qdeclarativepropertycache.cpp
src/declarative/qml/qdeclarativepropertycache_p.h

index a30839a..af3bb1e 100644 (file)
@@ -97,6 +97,10 @@ public:
 
     template<typename T>
     inline T *New();
+    template<typename T>
+    inline T *NewRaw();
+    template<typename T>
+    inline T *NewRawArray(int length);
 
     inline QString *NewString(const QString &);
     inline QByteArray *NewByteArray(const QByteArray &);
@@ -151,6 +155,18 @@ T *QDeclarativePool::New()
     return rv;
 }
 
+template<typename T>
+T *QDeclarativePool::NewRaw()
+{
+    return (T*)allocate(sizeof(T));
+}
+
+template<typename T>
+T *QDeclarativePool::NewRawArray(int length)
+{
+    return (T*)allocate(length * sizeof(T));
+}
+
 QString *QDeclarativePool::NewString(const QString &s)
 {
     QString *rv = New<StringClass>();
index 41adc26..d7f951c 100644 (file)
@@ -465,3 +465,15 @@ void QHashedStringRef::writeUtf8(char *output) const
         }
     }
 }
+
+QString QHashedCStringRef::toUtf16() const
+{
+    if (m_length == 0)
+        return QString();
+
+    QString rv;
+    rv.resize(m_length);
+    writeUtf16((uint16_t*)rv.data());
+    return rv;
+}
+
index c04e504..f6c7f20 100644 (file)
@@ -109,6 +109,7 @@ private:
     v8::Handle<v8::String> m_string;
 };
 
+class QHashedCStringRef;
 class Q_AUTOTEST_EXPORT QHashedStringRef 
 {
 public:
@@ -124,9 +125,11 @@ public:
     inline bool operator==(const QString &string) const;
     inline bool operator==(const QHashedString &string) const;
     inline bool operator==(const QHashedStringRef &string) const;
+    inline bool operator==(const QHashedCStringRef &string) const;
     inline bool operator!=(const QString &string) const;
     inline bool operator!=(const QHashedString &string) const;
     inline bool operator!=(const QHashedStringRef &string) const;
+    inline bool operator!=(const QHashedCStringRef &string) const;
 
     inline quint32 hash() const;
 
@@ -169,7 +172,14 @@ public:
 
     inline const char *constData() const;
     inline int length() const;
+
+    QString toUtf16() const;
+    inline int utf16length() const;
+    inline void writeUtf16(QChar *) const;
+    inline void writeUtf16(uint16_t *) const;
 private:
+    friend class QHashedStringRef;
+
     void computeHash() const;
 
     const char *m_data;
@@ -972,6 +982,13 @@ bool QHashedStringRef::operator==(const QHashedStringRef &string) const
            QHashedString::compare(string.m_data, m_data, m_length);
 }
 
+bool QHashedStringRef::operator==(const QHashedCStringRef &string) const
+{
+    return m_length == string.m_length && 
+           (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
+           QHashedString::compare(m_data, string.m_data, m_length);
+}
+
 bool QHashedStringRef::operator!=(const QString &string) const
 {
     return m_length != string.length() ||
@@ -992,6 +1009,13 @@ bool QHashedStringRef::operator!=(const QHashedStringRef &string) const
            QHashedString::compare(string.m_data, m_data, m_length);
 }
 
+bool QHashedStringRef::operator!=(const QHashedCStringRef &string) const
+{
+    return m_length != string.m_length ||
+           (m_hash != string.m_hash && m_hash && string.m_hash) ||
+           QHashedString::compare(m_data, string.m_data, m_length);
+}
+
 const QChar &QHashedStringRef::at(int index) const
 {
     Q_ASSERT(index < m_length);
@@ -1068,6 +1092,24 @@ int QHashedCStringRef::length() const
     return m_length;
 }
 
+int QHashedCStringRef::utf16length() const
+{
+    return m_length;
+}
+
+void QHashedCStringRef::writeUtf16(QChar *output) const
+{
+    writeUtf16((uint16_t *)output);
+}
+
+void QHashedCStringRef::writeUtf16(uint16_t *output) const
+{
+    int l = m_length;
+    const char *d = m_data;
+    while (l--) 
+        *output++ = *d++;
+}
+
 bool QHashedString::compare(const QChar *lhs, const char *rhs, int length) 
 {
     Q_ASSERT(lhs && rhs);
index 622949c..85f1fe5 100644 (file)
@@ -846,29 +846,73 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
     if (obj->defaultProperty) {
         defaultProperty = obj->defaultProperty;
 
-        const QMetaObject *metaObject = obj->metaObject();
-        Q_ASSERT(metaObject);
-        // XXX aakenned
-        QMetaProperty p = QDeclarativeMetaType::defaultProperty(metaObject);
-        if (p.name()) {
-            Property *explicitProperty = obj->getProperty(QString::fromUtf8(p.name()), false);
-            if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) {
-
-                skipProperty = explicitProperty; // We merge the values into defaultProperty
-
-                // Find the correct insertion point
-                Value *insertPos = 0;
-
-                for (Value *v = defaultProperty->values.first(); v; v = Property::ValueList::next(v)) {
-                    if (!(v->location.start < explicitProperty->values.first()->location.start))
-                        break;
-                    insertPos = v;
-                }
+        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;
+                            }
+                        }
+                    }
 
-                defaultProperty->values.insertAfter(insertPos, explicitProperty->values);
+                    if (!explicitProperty) 
+                        defaultProperty->setName(r);
 
-            } 
+                } 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 (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) {
+
+            skipProperty = explicitProperty; // We merge the values into defaultProperty
+
+            // Find the correct insertion point
+            Value *insertPos = 0;
+
+            for (Value *v = defaultProperty->values.first(); v; v = Property::ValueList::next(v)) {
+                if (!(v->location.start < explicitProperty->values.first()->location.start))
+                    break;
+                insertPos = v;
+            }
+
+            defaultProperty->values.insertAfter(insertPos, explicitProperty->values);
+        } 
     }
 
     QDeclarativeCustomParser *cp = 0;
@@ -1486,16 +1530,12 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl
 bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop,
                                              QDeclarativeParser::Object *obj)
 {
+    if (prop->name().isEmpty())
+        return false;
     if(isAttachedPropertyName(prop->name()) || prop->name() == id_string)
         return true;
 
-    if (prop->isDefault) {
-        const QMetaObject *mo = obj->metaObject();
-        QMetaProperty p = QDeclarativeMetaType::defaultProperty(mo);
-        return p.name() != 0;
-    } else {
-        return property(obj, prop->name()) != 0;
-    }
+    return property(obj, prop->name()) != 0;
 }
 
 bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
@@ -1538,34 +1578,21 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
         prop->value->metatype = type->attachedPropertiesType();
     } else {
         // Setup regular property data
+        bool notInRevision = false;
+        QDeclarativePropertyCache::Data *d = 
+            prop->name().isEmpty()?0:property(obj, prop->name(), &notInRevision);
 
-        if (prop->isDefault) {
-            QMetaProperty p = QDeclarativeMetaType::defaultProperty(metaObject);
-
-            if (p.name()) {
-                prop->setName(QString::fromLatin1(p.name()));
-
-                QDeclarativePropertyCache::Data *d = property(obj, p.propertyIndex());
-                prop->index = d->coreIndex;
-                prop->core = *d;
-            }
-
-        } else {
-            bool notInRevision = false;
-            QDeclarativePropertyCache::Data *d = property(obj, prop->name(), &notInRevision);
-
-            if (d == 0 && notInRevision) {
-                const QList<QDeclarativeTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
-                const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type);
-                if (type.type) {
-                    COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion));
-                } else {
-                    COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
-                }
-            } else if (d) {
-                prop->index = d->coreIndex;
-                prop->core = *d;
+        if (d == 0 && notInRevision) {
+            const QList<QDeclarativeTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
+            const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type);
+            if (type.type) {
+                COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion));
+            } else {
+                COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
             }
+        } else if (d) {
+            prop->index = d->coreIndex;
+            prop->core = *d;
         }
 
         // We can't error here as the "id" property does not require a
index d7af045..aa1efb4 100644 (file)
@@ -255,6 +255,7 @@ namespace QDeclarativeParser
         // The property name
         const QHashedStringRef &name() const { return _name; }
         void setName(const QString &n) { _name = QHashedStringRef(pool()->NewString(n)); }
+        void setName(const QHashedStringRef &n) { _name = n; }
         // True if this property was accessed as the default property.  
         bool isDefault;
         // True if the setting of this property will be deferred.  Set by the
index 09c441d..bc3811a 100644 (file)
@@ -483,6 +483,14 @@ QDeclarativePropertyCache::property(const QHashedStringRef &str) const
 }
 
 QDeclarativePropertyCache::Data *
+QDeclarativePropertyCache::property(const QHashedCStringRef &str) const
+{
+    QDeclarativePropertyCache::Data **rv = stringCache.value(str);
+    if (rv && (*rv)->notFullyResolved()) resolve(*rv);
+    return rv?*rv:0;
+}
+
+QDeclarativePropertyCache::Data *
 QDeclarativePropertyCache::property(const QString &str) const
 {
     QDeclarativePropertyCache::Data **rv = stringCache.value(str);
index dcb8ad6..8a1da19 100644 (file)
@@ -182,6 +182,7 @@ public:
 
     inline Data *property(const QHashedV8String &) const;
     Data *property(const QHashedStringRef &) const;
+    Data *property(const QHashedCStringRef &) const;
     Data *property(const QString &) const;
     Data *property(int) const;
     Data *method(int) const;