From: Aaron Kennedy Date: Fri, 22 Jul 2011 03:32:47 +0000 (+1000) Subject: Optimize default property resolution in compiler X-Git-Tag: qt-v5.0.0-alpha1~1820 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=540774d7dfe2a309fca181d9e54e14ba87069bbd;p=profile%2Fivi%2Fqtdeclarative.git Optimize default property resolution in compiler Change-Id: I90b677a190c0c59ba681a7643a9b13cfb938d5a1 Reviewed-on: http://codereview.qt.nokia.com/3769 Reviewed-by: Roberto Raggi --- diff --git a/src/declarative/qml/ftw/qdeclarativepool_p.h b/src/declarative/qml/ftw/qdeclarativepool_p.h index a30839a..af3bb1e 100644 --- a/src/declarative/qml/ftw/qdeclarativepool_p.h +++ b/src/declarative/qml/ftw/qdeclarativepool_p.h @@ -97,6 +97,10 @@ public: template inline T *New(); + template + inline T *NewRaw(); + template + 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 +T *QDeclarativePool::NewRaw() +{ + return (T*)allocate(sizeof(T)); +} + +template +T *QDeclarativePool::NewRawArray(int length) +{ + return (T*)allocate(length * sizeof(T)); +} + QString *QDeclarativePool::NewString(const QString &s) { QString *rv = New(); diff --git a/src/declarative/qml/ftw/qhashedstring.cpp b/src/declarative/qml/ftw/qhashedstring.cpp index 41adc26..d7f951c 100644 --- a/src/declarative/qml/ftw/qhashedstring.cpp +++ b/src/declarative/qml/ftw/qhashedstring.cpp @@ -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; +} + diff --git a/src/declarative/qml/ftw/qhashedstring_p.h b/src/declarative/qml/ftw/qhashedstring_p.h index c04e504..f6c7f20 100644 --- a/src/declarative/qml/ftw/qhashedstring_p.h +++ b/src/declarative/qml/ftw/qhashedstring_p.h @@ -109,6 +109,7 @@ private: v8::Handle 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); diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 622949c..85f1fe5 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -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(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(), ¬InRevision); - 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(), ¬InRevision); - - if (d == 0 && notInRevision) { - const QList &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 &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 diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index d7af045..aa1efb4 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -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 diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 09c441d..bc3811a 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -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); diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index dcb8ad6..8a1da19 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -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;