aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-07-04 12:41:21 +1000
committerQt by Nokia <qt-info@nokia.com>2011-07-04 07:27:11 +0200
commit71114ff964582f58e68d68bf0301cd42110751cc (patch)
treee3ad3d3e1af59ef9dc32aa28ce12a6d70a89a03a /src/declarative/qml
parent8371e37e47967848ec470a4b34f46b1c8591c3c1 (diff)
Optimize QDeclarativePropertyCache
The creation of QDeclarativePropertyCaches contributes significantly to the initial compile time of a QML app. Change-Id: Iac5d1578155dfa4678a0e21eab51f4c1675762a9 Reviewed-on: http://codereview.qt.nokia.com/1026 Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp10
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug.cpp2
-rw-r--r--src/declarative/qml/qdeclarativelist.cpp2
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp44
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp250
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h56
-rw-r--r--src/declarative/qml/v4/qdeclarativev4irbuilder.cpp14
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper.cpp10
-rw-r--r--src/declarative/qml/v8/qv8valuetypewrapper.cpp2
9 files changed, 244 insertions, 146 deletions
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index bca9c65fcc..32025cc416 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -981,7 +981,8 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj)
reinterpret_cast<const QDeclarativeVMEMetaData *>(obj->synthdata.constData());
for (int ii = 0; ii < vmeMetaData->aliasCount; ++ii) {
int index = obj->metaObject()->propertyOffset() + vmeMetaData->propertyCount + ii;
- propertyCache->property(index)->flags |= QDeclarativePropertyCache::Data::IsAlias;
+ QDeclarativePropertyCache::Data *data = propertyCache->property(index);
+ data->setFlags(data->getFlags() | QDeclarativePropertyCache::Data::IsAlias);
}
}
@@ -1546,8 +1547,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
output->types.at(prop->parent->type).component) {
QDeclarativePropertyCache *cache = output->types.at(prop->parent->type).component->rootPropertyCache;
- if (cache && cache->property(prop->index) &&
- cache->property(prop->index)->flags & QDeclarativePropertyCache::Data::IsAlias)
+ if (cache && cache->property(prop->index) && cache->property(prop->index)->isAlias())
prop->isAlias = true;
}
@@ -3138,7 +3138,7 @@ int QDeclarativeCompiler::indexOfSignal(QDeclarativeParser::Object *object, cons
QDeclarativePropertyCache::Data *d = cache->property(strName);
if (notInRevision) *notInRevision = false;
- while (d && !(d->flags & QDeclarativePropertyCache::Data::IsFunction))
+ while (d && !(d->isFunction()))
d = cache->overrideData(d);
if (d && !cache->isAllowedInRevision(d)) {
@@ -3178,7 +3178,7 @@ int QDeclarativeCompiler::indexOfProperty(QDeclarativeParser::Object *object, co
QDeclarativePropertyCache::Data *d = cache->property(strName);
// Find the first property
- while (d && d->flags & QDeclarativePropertyCache::Data::IsFunction)
+ while (d && d->isFunction())
d = cache->overrideData(d);
if (d && !cache->isAllowedInRevision(d)) {
diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp
index 7844d30e86..af99f05e95 100644
--- a/src/declarative/qml/qdeclarativeenginedebug.cpp
+++ b/src/declarative/qml/qdeclarativeenginedebug.cpp
@@ -678,7 +678,7 @@ void QDeclarativeEngineDebugServer::setMethodBody(int objectId, const QString &m
QDeclarativePropertyCache::Data *prop =
QDeclarativePropertyCache::property(context->engine(), object, method, dummy);
- if (!prop || !(prop->flags & QDeclarativePropertyCache::Data::IsVMEFunction))
+ if (!prop || !prop->isVMEFunction())
return;
QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
diff --git a/src/declarative/qml/qdeclarativelist.cpp b/src/declarative/qml/qdeclarativelist.cpp
index ff3dfc9458..458812a896 100644
--- a/src/declarative/qml/qdeclarativelist.cpp
+++ b/src/declarative/qml/qdeclarativelist.cpp
@@ -139,7 +139,7 @@ QDeclarativeListReference::QDeclarativeListReference(QObject *object, const char
QDeclarativePropertyCache::Data *data =
QDeclarativePropertyCache::property(engine, object, QLatin1String(property), local);
- if (!data || !(data->flags & QDeclarativePropertyCache::Data::IsQList)) return;
+ if (!data || !data->isQList()) return;
QDeclarativeEnginePrivate *p = engine?QDeclarativeEnginePrivate::get(engine):0;
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index dcab6be3d3..088379e8d2 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -255,7 +255,7 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name
QDeclarativePropertyCache::property(engine, obj, pathName, local);
if (!property) return; // Not a property
- if (property->flags & QDeclarativePropertyCache::Data::IsFunction)
+ if (property->isFunction())
return; // Not an object property
if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) {
@@ -277,7 +277,7 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name
return;
} else {
- if (!(property->flags & QDeclarativePropertyCache::Data::IsQObjectDerived))
+ if (!property->isQObject())
return; // Not an object property
void *args[] = { &currentObject, 0 };
@@ -311,7 +311,7 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name
QDeclarativePropertyCache::Data local;
QDeclarativePropertyCache::Data *property =
QDeclarativePropertyCache::property(engine, currentObject, terminal, local);
- if (property && !(property->flags & QDeclarativePropertyCache::Data::IsFunction)) {
+ if (property && !property->isFunction()) {
object = currentObject;
core = *property;
nameCache = terminal;
@@ -371,9 +371,9 @@ QDeclarativePropertyPrivate::propertyTypeCategory() const
return QDeclarativeProperty::InvalidCategory;
else if (QDeclarativeValueTypeFactory::isValueType((uint)type))
return QDeclarativeProperty::Normal;
- else if (core.flags & QDeclarativePropertyCache::Data::IsQObjectDerived)
+ else if (core.isQObject())
return QDeclarativeProperty::Object;
- else if (core.flags & QDeclarativePropertyCache::Data::IsQList)
+ else if (core.isQList())
return QDeclarativeProperty::List;
else
return QDeclarativeProperty::Normal;
@@ -457,7 +457,7 @@ int QDeclarativePropertyPrivate::propertyType() const
QDeclarativeProperty::Type QDeclarativePropertyPrivate::type() const
{
- if (core.flags & QDeclarativePropertyCache::Data::IsFunction)
+ if (core.isFunction())
return QDeclarativeProperty::SignalProperty;
else if (core.isValid())
return QDeclarativeProperty::Property;
@@ -520,12 +520,12 @@ bool QDeclarativeProperty::isWritable() const
return false;
if (!d->object)
return false;
- if (d->core.flags & QDeclarativePropertyCache::Data::IsQList) //list
+ if (d->core.isQList()) //list
return true;
- else if (d->core.flags & QDeclarativePropertyCache::Data::IsFunction) //signal handler
+ else if (d->core.isFunction()) //signal handler
return false;
- else if (d->core.isValid()) //normal property
- return d->core.flags & QDeclarativePropertyCache::Data::IsWritable;
+ else if (d->core.isValid()) //normal property
+ return d->core.isWritable();
else
return false;
}
@@ -551,7 +551,7 @@ bool QDeclarativeProperty::isResettable() const
if (!d)
return false;
if (type() & Property && d->core.isValid() && d->object)
- return d->core.flags & QDeclarativePropertyCache::Data::IsResettable;
+ return d->core.isResettable();
else
return false;
}
@@ -682,7 +682,7 @@ QDeclarativePropertyPrivate::binding(QObject *object, int coreIndex, int valueTy
QDeclarativePropertyCache::Data *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) {
+ if (propertyData && propertyData->isAlias()) {
const QDeclarativeVMEMetaObject *vme =
static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
@@ -723,7 +723,7 @@ void QDeclarativePropertyPrivate::findAliasTarget(QObject *object, int bindingIn
if (data) {
QDeclarativePropertyCache::Data *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) {
+ if (propertyData && propertyData->isAlias()) {
const QDeclarativeVMEMetaObject *vme =
static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
@@ -757,7 +757,7 @@ QDeclarativePropertyPrivate::setBinding(QObject *object, int coreIndex, int valu
if (data) {
QDeclarativePropertyCache::Data *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) {
+ if (propertyData && propertyData->isAlias()) {
const QDeclarativeVMEMetaObject *vme =
static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
@@ -811,7 +811,7 @@ QDeclarativePropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex,
if (data) {
QDeclarativePropertyCache::Data *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) {
+ if (propertyData && propertyData->isAlias()) {
const QDeclarativeVMEMetaObject *vme =
static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
@@ -994,14 +994,14 @@ QVariant QDeclarativePropertyPrivate::readValueProperty()
if (!ep) delete valueType;
return rv;
- } else if (core.flags & QDeclarativePropertyCache::Data::IsQList) {
+ } else if (core.isQList()) {
QDeclarativeListProperty<QObject> prop;
void *args[] = { &prop, 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
return QVariant::fromValue(QDeclarativeListReferencePrivate::init(prop, core.propType, engine));
- } else if (core.flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
+ } else if (core.isQObject()) {
QObject *rv = 0;
void *args[] = { &rv, 0 };
@@ -1077,7 +1077,7 @@ bool QDeclarativePropertyPrivate::writeValueProperty(const QVariant &value, Writ
writeBack->read(object, core.coreIndex);
QDeclarativePropertyCache::Data data = core;
- data.flags = valueType.flags;
+ data.setFlags(valueType.flags);
data.coreIndex = valueType.valueTypeCoreIdx;
data.propType = valueType.valueTypePropType;
rv = write(writeBack, data, value, context, flags);
@@ -1101,7 +1101,7 @@ bool QDeclarativePropertyPrivate::write(QObject *object, const QDeclarativePrope
int coreIdx = property.coreIndex;
int status = -1; //for dbus
- if (property.flags & QDeclarativePropertyCache::Data::IsEnumType) {
+ if (property.isEnum()) {
QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant v = value;
// Enum values come through the script engine as doubles
@@ -1153,7 +1153,7 @@ bool QDeclarativePropertyPrivate::write(QObject *object, const QDeclarativePrope
void *a[] = { (void *)&value, 0, &status, &flags };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
- } else if (property.flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
+ } else if (property.isQObject()) {
const QMetaObject *valMo = rawMetaObjectForType(enginePriv, value.userType());
@@ -1180,7 +1180,7 @@ bool QDeclarativePropertyPrivate::write(QObject *object, const QDeclarativePrope
return false;
}
- } else if (property.flags & QDeclarativePropertyCache::Data::IsQList) {
+ } else if (property.isQList()) {
const QMetaObject *listType = 0;
if (enginePriv) {
@@ -1703,7 +1703,7 @@ static inline void flush_vme_signal(const QObject *object, int index)
if (data && data->propertyCache) {
QDeclarativePropertyCache::Data *property = data->propertyCache->method(index);
- if (property && property->flags & QDeclarativePropertyCache::Data::IsVMESignal) {
+ if (property && property->isVMESignal()) {
const QMetaObject *metaObject = object->metaObject();
int methodOffset = metaObject->methodOffset();
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 6a4cf4f710..24dc15aeb1 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -54,41 +54,78 @@ Q_DECLARE_METATYPE(QDeclarativeV8Handle);
QT_BEGIN_NAMESPACE
-QDeclarativePropertyCache::Data::Flags QDeclarativePropertyCache::Data::flagsForProperty(const QMetaProperty &p, QDeclarativeEngine *engine)
+// Flags that do *NOT* depend on the property's QMetaProperty::userType() and thus are quick
+// to load
+static QDeclarativePropertyCache::Data::Flags fastFlagsForProperty(const QMetaProperty &p)
{
- int propType = p.userType();
-
- Flags flags;
+ QDeclarativePropertyCache::Data::Flags flags;
if (p.isConstant())
- flags |= Data::IsConstant;
+ flags |= QDeclarativePropertyCache::Data::IsConstant;
if (p.isWritable())
- flags |= Data::IsWritable;
+ flags |= QDeclarativePropertyCache::Data::IsWritable;
if (p.isResettable())
- flags |= Data::IsResettable;
+ flags |= QDeclarativePropertyCache::Data::IsResettable;
if (p.isFinal())
- flags |= Data::IsFinal;
+ flags |= QDeclarativePropertyCache::Data::IsFinal;
+ if (p.isEnumType())
+ flags |= QDeclarativePropertyCache::Data::IsEnumType;
+
+ return flags;
+}
- if (propType == qMetaTypeId<QDeclarativeBinding *>()) {
- flags |= Data::IsQmlBinding;
+// Flags that do depend on the property's QMetaProperty::userType() and thus are slow to
+// load
+static QDeclarativePropertyCache::Data::Flags flagsForPropertyType(int propType, QDeclarativeEngine *engine)
+{
+ QDeclarativePropertyCache::Data::Flags flags;
+
+ if (propType < QMetaType::User) {
+ } else if (propType == qMetaTypeId<QDeclarativeBinding *>()) {
+ flags |= QDeclarativePropertyCache::Data::IsQmlBinding;
} else if (propType == qMetaTypeId<QScriptValue>()) {
- flags |= Data::IsQScriptValue;
+ flags |= QDeclarativePropertyCache::Data::IsQScriptValue;
} else if (propType == qMetaTypeId<QDeclarativeV8Handle>()) {
- flags |= Data::IsV8Handle;
- } else if (p.isEnumType()) {
- flags |= Data::IsEnumType;
+ flags |= QDeclarativePropertyCache::Data::IsV8Handle;
} else {
- QDeclarativeMetaType::TypeCategory cat = engine ? QDeclarativeEnginePrivate::get(engine)->typeCategory(propType)
- : QDeclarativeMetaType::typeCategory(propType);
+ QDeclarativeMetaType::TypeCategory cat =
+ engine ? QDeclarativeEnginePrivate::get(engine)->typeCategory(propType)
+ : QDeclarativeMetaType::typeCategory(propType);
+
if (cat == QDeclarativeMetaType::Object)
- flags |= Data::IsQObjectDerived;
+ flags |= QDeclarativePropertyCache::Data::IsQObjectDerived;
else if (cat == QDeclarativeMetaType::List)
- flags |= Data::IsQList;
+ flags |= QDeclarativePropertyCache::Data::IsQList;
}
return flags;
}
+QDeclarativePropertyCache::Data::Flags
+QDeclarativePropertyCache::Data::flagsForProperty(const QMetaProperty &p, QDeclarativeEngine *engine)
+{
+ return fastFlagsForProperty(p) | flagsForPropertyType(p.userType(), engine);
+}
+
+void QDeclarativePropertyCache::Data::lazyLoad(const QMetaProperty &p, QDeclarativeEngine *engine)
+{
+ Q_UNUSED(engine);
+
+ coreIndex = p.propertyIndex();
+ notifyIndex = p.notifySignalIndex();
+ revision = p.revision();
+
+ flags = fastFlagsForProperty(p);
+
+ int type = p.type();
+ if (type == QVariant::UserType || type == -1) {
+ propTypeName = p.typeName();
+ flags |= QDeclarativePropertyCache::Data::NotFullyResolved;
+ } else {
+ propType = type;
+ }
+}
+
void QDeclarativePropertyCache::Data::load(const QMetaProperty &p, QDeclarativeEngine *engine)
{
propType = p.userType();
@@ -96,7 +133,7 @@ void QDeclarativePropertyCache::Data::load(const QMetaProperty &p, QDeclarativeE
propType = qMetaTypeId<QVariant>();
coreIndex = p.propertyIndex();
notifyIndex = p.notifySignalIndex();
- flags = flagsForProperty(p, engine);
+ flags = fastFlagsForProperty(p) | flagsForPropertyType(propType, engine);
revision = p.revision();
}
@@ -113,23 +150,54 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m)
if (returnType)
propType = QMetaType::type(returnType);
- QList<QByteArray> params = m.parameterTypes();
- if (!params.isEmpty()) {
+ const char *signature = m.signature();
+ while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; }
+
+ ++signature;
+ if (*signature != ')') {
flags |= Data::HasArguments;
- if (params.at(0).length() == 23 &&
- 0 == qstrcmp(params.at(0).constData(), "QDeclarativeV8Function*")) {
+ if (0 == ::strcmp(signature, "QDeclarativeV8Function*)")) {
flags |= Data::IsV8Function;
}
}
+
revision = m.revision();
}
+void QDeclarativePropertyCache::Data::lazyLoad(const QMetaMethod &m)
+{
+ coreIndex = m.methodIndex();
+ relatedIndex = -1;
+ flags |= Data::IsFunction;
+ if (m.methodType() == QMetaMethod::Signal)
+ flags |= Data::IsSignal;
+ propType = QVariant::Invalid;
+
+ const char *returnType = m.typeName();
+ if (returnType && *returnType) {
+ propTypeName = returnType;
+ flags |= Data::NotFullyResolved;
+ }
+
+ const char *signature = m.signature();
+ while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; }
+
+ ++signature;
+ if (*signature != ')') {
+ flags |= Data::HasArguments;
+ if (0 == ::strcmp(signature, "QDeclarativeV8Function*)")) {
+ flags |= Data::IsV8Function;
+ }
+ }
+
+ revision = m.revision();
+}
/*!
Creates a new empty QDeclarativePropertyCache.
*/
QDeclarativePropertyCache::QDeclarativePropertyCache(QDeclarativeEngine *e)
-: QDeclarativeCleanup(e), engine(e)
+: QDeclarativeCleanup(e), engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0)
{
Q_ASSERT(engine);
}
@@ -138,7 +206,7 @@ QDeclarativePropertyCache::QDeclarativePropertyCache(QDeclarativeEngine *e)
Creates a new QDeclarativePropertyCache of \a metaObject.
*/
QDeclarativePropertyCache::QDeclarativePropertyCache(QDeclarativeEngine *e, const QMetaObject *metaObject)
-: QDeclarativeCleanup(e), engine(e)
+: QDeclarativeCleanup(e), engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0)
{
Q_ASSERT(engine);
Q_ASSERT(metaObject);
@@ -153,22 +221,13 @@ QDeclarativePropertyCache::~QDeclarativePropertyCache()
void QDeclarativePropertyCache::clear()
{
- for (int ii = 0; ii < indexCache.count(); ++ii) {
- if (indexCache.at(ii)) indexCache.at(ii)->release();
- }
-
- for (int ii = 0; ii < methodIndexCache.count(); ++ii) {
- RData *data = methodIndexCache.at(ii);
- if (data) data->release();
- }
+ if (parent) parent->release();
+ parent = 0;
- for (StringCache::ConstIterator iter = stringCache.begin();
- iter != stringCache.end(); ++iter) {
- RData *data = (*iter);
- data->release();
- }
+ propertyIndexCacheStart = 0;
+ methodIndexCacheStart = 0;
- indexCache.clear();
+ propertyIndexCache.clear();
methodIndexCache.clear();
stringCache.clear();
qPersistentDispose(constructor);
@@ -219,23 +278,16 @@ QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObj
return rv;
}
-QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const
+QDeclarativePropertyCache *QDeclarativePropertyCache::copy()
{
QDeclarativePropertyCache *cache = new QDeclarativePropertyCache(engine);
- cache->indexCache = indexCache;
- cache->methodIndexCache = methodIndexCache;
+ cache->parent = this;
+ cache->parent->addref();
+ cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart;
+ cache->methodIndexCacheStart = methodIndexCache.count() + methodIndexCacheStart;
cache->stringCache = stringCache;
cache->allowedRevisionCache = allowedRevisionCache;
- for (int ii = 0; ii < indexCache.count(); ++ii) {
- if (indexCache.at(ii)) indexCache.at(ii)->addref();
- }
- for (int ii = 0; ii < methodIndexCache.count(); ++ii) {
- if (methodIndexCache.at(ii)) methodIndexCache.at(ii)->addref();
- }
- for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
- (*iter)->addref();
-
// We specifically do *NOT* copy the constructor
return cache;
@@ -259,65 +311,64 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
allowedRevisionCache.append(0);
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
int methodCount = metaObject->methodCount();
// 3 to block the destroyed signal and the deleteLater() slot
int methodOffset = qMax(3, metaObject->methodOffset());
- methodIndexCache.resize(methodCount);
+ methodIndexCache.resize(methodCount - methodIndexCacheStart);
for (int ii = methodOffset; ii < methodCount; ++ii) {
QMetaMethod m = metaObject->method(ii);
if (m.access() == QMetaMethod::Private)
continue;
- QString methodName = QString::fromUtf8(m.signature());
- int parenIdx = methodName.indexOf(QLatin1Char('('));
- Q_ASSERT(parenIdx != -1);
- methodName = methodName.left(parenIdx);
+ // Extract method name
+ const char *signature = m.signature();
+ const char *cptr = signature;
+ while (*cptr != '(') { Q_ASSERT(*cptr != 0); ++cptr; }
+ QString str = dynamicMetaObject?QString::fromUtf8(signature, cptr - signature):
+ QString::fromLatin1(signature, cptr - signature);
+ QHashedString methodName(str);
- RData *data = new RData;
- methodIndexCache[ii] = data;
+ Data *data = &methodIndexCache[ii - methodIndexCacheStart];
- data->load(m);
- if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method)
- data->flags |= methodFlags;
- else if (m.methodType() == QMetaMethod::Signal)
+ data->lazyLoad(m);
+ if (data->isSignal())
data->flags |= signalFlags;
+ else
+ data->flags |= methodFlags;
if (!dynamicMetaObject)
data->flags |= Data::IsDirect;
data->metaObjectOffset = allowedRevisionCache.count() - 1;
- if (stringCache.contains(methodName)) {
- RData *old = stringCache[methodName];
+ if (Data **old = stringCache.value(methodName)) {
// We only overload methods in the same class, exactly like C++
- if (old->flags & Data::IsFunction && old->coreIndex >= methodOffset)
- data->relatedIndex = old->coreIndex;
- data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
- data->overrideIndex = old->coreIndex;
- stringCache[methodName]->release();
+ if ((*old)->flags & Data::IsFunction && (*old)->coreIndex >= methodOffset)
+ data->relatedIndex = (*old)->coreIndex;
+ data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction);
+ data->overrideIndex = (*old)->coreIndex;
}
stringCache.insert(methodName, data);
- data->addref();
}
int propCount = metaObject->propertyCount();
int propOffset = metaObject->propertyOffset();
- indexCache.resize(propCount);
+ propertyIndexCache.resize(propCount - propertyIndexCacheStart);
for (int ii = propOffset; ii < propCount; ++ii) {
QMetaProperty p = metaObject->property(ii);
if (!p.isScriptable())
continue;
- QString propName = QString::fromUtf8(p.name());
+ QString str = dynamicMetaObject?QString::fromUtf8(p.name()):
+ QString::fromLatin1(p.name());
+ QHashedString propName(str);
- RData *data = new RData;
- indexCache[ii] = data;
+ Data *data = &propertyIndexCache[ii - propertyIndexCacheStart];
- data->load(p, engine);
+ data->lazyLoad(p, engine);
data->flags |= propertyFlags;
if (!dynamicMetaObject)
@@ -325,18 +376,30 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
data->metaObjectOffset = allowedRevisionCache.count() - 1;
- if (stringCache.contains(propName)) {
- RData *old = stringCache[propName];
- data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
- data->overrideIndex = old->coreIndex;
- stringCache[propName]->release();
+ if (Data **old = stringCache.value(propName)) {
+ data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction);
+ data->overrideIndex = (*old)->coreIndex;
}
stringCache.insert(propName, data);
- data->addref();
}
}
+void QDeclarativePropertyCache::resolve(Data *data) const
+{
+ Q_ASSERT(data->notFullyResolved());
+
+ data->propType = QMetaType::type(data->propTypeName);
+ if (QVariant::Type(data->propType) == QVariant::LastType)
+ data->propType = qMetaTypeId<QVariant>();
+
+
+ if (!(data->flags & Data::IsFunction))
+ data->flags |= flagsForPropertyType(data->propType, engine);
+
+ data->flags &= ~Data::NotFullyResolved;
+}
+
void QDeclarativePropertyCache::updateRecur(QDeclarativeEngine *engine, const QMetaObject *metaObject)
{
if (!metaObject)
@@ -355,7 +418,7 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb
clear();
// Optimization to prevent unnecessary reallocation of lists
- indexCache.reserve(metaObject->propertyCount());
+ propertyIndexCache.reserve(metaObject->propertyCount());
methodIndexCache.reserve(metaObject->methodCount());
updateRecur(engine,metaObject);
@@ -364,25 +427,36 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb
QDeclarativePropertyCache::Data *
QDeclarativePropertyCache::property(int index) const
{
- if (index < 0 || index >= indexCache.count())
+ if (index < 0 || index >= (propertyIndexCacheStart + propertyIndexCache.count()))
return 0;
+
+ if (index < propertyIndexCacheStart)
+ return parent->property(index);
- return indexCache.at(index);
+ Data *rv = const_cast<Data *>(&propertyIndexCache.at(index - propertyIndexCacheStart));
+ if (rv->notFullyResolved()) resolve(rv);
+ return rv;
}
QDeclarativePropertyCache::Data *
QDeclarativePropertyCache::method(int index) const
{
- if (index < 0 || index >= methodIndexCache.count())
+ if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
return 0;
- return methodIndexCache.at(index);
+ if (index < methodIndexCacheStart)
+ return parent->method(index);
+
+ Data *rv = const_cast<Data *>(&methodIndexCache.at(index - methodIndexCacheStart));
+ if (rv->notFullyResolved()) resolve(rv);
+ return rv;
}
QDeclarativePropertyCache::Data *
QDeclarativePropertyCache::property(const QString &str) const
{
- QDeclarativePropertyCache::RData **rv = stringCache.value(str);
+ QDeclarativePropertyCache::Data **rv = stringCache.value(str);
+ if (rv && (*rv)->notFullyResolved()) resolve(*rv);
return rv?*rv:0;
}
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 69e810aa97..1787e6ad14 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -104,11 +104,18 @@ public:
HasArguments = 0x00004000, // Function takes arguments
IsSignal = 0x00008000, // Function is a signal
IsVMESignal = 0x00010000, // Signal was added by QML
- IsV8Function = 0x00020000 // Function takes QDeclarativeV8Function* args
+ IsV8Function = 0x00020000, // Function takes QDeclarativeV8Function* args
+
+ // Internal QDeclarativePropertyCache flags
+ NotFullyResolved = 0x00040000 // True if the type data is to be lazily resolved
};
Q_DECLARE_FLAGS(Flags, Flag)
+ Flags getFlags() const { return flags; }
+ void setFlags(Flags f) { flags = f; }
+
bool isValid() const { return coreIndex != -1; }
+
bool isConstant() const { return flags & IsConstant; }
bool isWritable() const { return flags & IsWritable; }
bool isResettable() const { return flags & IsResettable; }
@@ -122,9 +129,16 @@ public:
bool isQmlBinding() const { return flags & IsQmlBinding; }
bool isQScriptValue() const { return flags & IsQScriptValue; }
bool isV8Handle() const { return flags & IsV8Handle; }
+ bool isVMEFunction() const { return flags & IsVMEFunction; }
+ bool hasArguments() const { return flags & HasArguments; }
+ bool isSignal() const { return flags & IsSignal; }
+ bool isVMESignal() const { return flags & IsVMESignal; }
+ bool isV8Function() const { return flags & IsV8Function; }
- Flags flags;
- int propType;
+ union {
+ int propType; // When !NotFullyResolved
+ const char *propTypeName; // When NotFullyResolved
+ };
int coreIndex;
union {
int notifyIndex; // When !IsFunction
@@ -140,6 +154,13 @@ public:
void load(const QMetaMethod &);
QString name(QObject *);
QString name(const QMetaObject *);
+
+ private:
+ void lazyLoad(const QMetaProperty &, QDeclarativeEngine *engine = 0);
+ void lazyLoad(const QMetaMethod &);
+ bool notFullyResolved() const { return flags & NotFullyResolved; }
+ friend class QDeclarativePropertyCache;
+ Flags flags;
};
struct ValueTypeData {
@@ -152,7 +173,7 @@ public:
void update(QDeclarativeEngine *, const QMetaObject *);
- QDeclarativePropertyCache *copy() const;
+ QDeclarativePropertyCache *copy();
void append(QDeclarativeEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags,
Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags);
void append(QDeclarativeEngine *, const QMetaObject *, int revision, Data::Flag propertyFlags = Data::NoFlags,
@@ -184,18 +205,20 @@ private:
// Implemented in v8/qv8qobjectwrapper.cpp
v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
- // XXX is this worth it anymore?
- struct RData : public Data, public QDeclarativeRefCount {
- };
-
- typedef QVector<RData *> IndexCache;
- typedef QStringHash<RData *> StringCache;
+ typedef QVector<Data> IndexCache;
+ typedef QStringHash<Data *> StringCache;
typedef QVector<int> AllowedRevisionCache;
+ void resolve(Data *) const;
void updateRecur(QDeclarativeEngine *, const QMetaObject *);
QDeclarativeEngine *engine;
- IndexCache indexCache;
+
+ QDeclarativePropertyCache *parent;
+ int propertyIndexCacheStart;
+ int methodIndexCacheStart;
+
+ IndexCache propertyIndexCache;
IndexCache methodIndexCache;
StringCache stringCache;
AllowedRevisionCache allowedRevisionCache;
@@ -204,8 +227,8 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyCache::Data::Flags);
QDeclarativePropertyCache::Data::Data()
-: flags(0), propType(0), coreIndex(-1), notifyIndex(-1), overrideIndexIsProperty(false), overrideIndex(-1),
- revision(0), metaObjectOffset(-1)
+: propType(0), coreIndex(-1), notifyIndex(-1), overrideIndexIsProperty(false), overrideIndex(-1),
+ revision(0), metaObjectOffset(-1), flags(0)
{
}
@@ -225,9 +248,9 @@ QDeclarativePropertyCache::overrideData(Data *data) const
return 0;
if (data->overrideIndexIsProperty)
- return indexCache.at(data->overrideIndex);
+ return property(data->overrideIndex);
else
- return methodIndexCache.at(data->overrideIndex);
+ return method(data->overrideIndex);
}
QDeclarativePropertyCache::ValueTypeData::ValueTypeData()
@@ -255,7 +278,8 @@ QDeclarativeEngine *QDeclarativePropertyCache::qmlEngine() const
QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(const QHashedV8String &str) const
{
- QDeclarativePropertyCache::RData **rv = stringCache.value(str);
+ QDeclarativePropertyCache::Data **rv = stringCache.value(str);
+ if (rv && (*rv)->notFullyResolved()) resolve(*rv);
return rv?*rv:0;
}
diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
index 928fea4487..9232292c48 100644
--- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
@@ -472,7 +472,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast)
return false;
}
- if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) {
+ if (data && !data->isFunction()) {
IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
_expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column);
found = true;
@@ -493,7 +493,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast)
return false;
}
- if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) {
+ if (data && !data->isFunction()) {
IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
_expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column);
found = true;
@@ -611,10 +611,10 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast)
QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta);
QDeclarativePropertyCache::Data *data = cache->property(name);
- if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
+ if (!data || data->isFunction())
return false; // Don't support methods (or non-existing properties ;)
- if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) {
+ if(!data->isFinal()) {
if (qmlVerboseCompiler())
qWarning() << "*** non-final attached property:"
<< (baseName->id + QLatin1String(".") + ast->name->asString());
@@ -633,7 +633,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast)
QDeclarativePropertyCache::Data *data = cache->property(name);
- if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
+ if (!data || data->isFunction())
return false; // Don't support methods (or non-existing properties ;)
if (data->revision != 0) {
@@ -657,10 +657,10 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast)
QDeclarativePropertyCache::Data *data = cache->property(name);
- if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
+ if (!data || data->isFunction())
return false; // Don't support methods (or non-existing properties ;)
- if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) {
+ if(!data->isFinal()) {
if (qmlVerboseCompiler())
qWarning() << "*** non-final property access:"
<< (baseName->id + QLatin1String(".") + ast->name->asString());
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
index 7e5bd4ecbd..e59df8dc53 100644
--- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
@@ -436,9 +436,9 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty;
if (result->isFunction()) {
- if (result->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
+ if (result->isVMEFunction()) {
return ((QDeclarativeVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
- } else if (result->flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ } else if (result->isV8Function()) {
return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex);
} else {
return MethodClosure::create(engine, object, objectHandle, result->coreIndex);
@@ -1558,7 +1558,7 @@ static const QDeclarativePropertyCache::Data * RelatedMethod(QObject *object,
static v8::Handle<v8::Value> CallPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
QV8Engine *engine, CallArgs &callArgs)
{
- if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
+ if (data.hasArguments()) {
QMetaMethod m = object->metaObject()->method(data.coreIndex);
QList<QByteArray> argTypeNames = m.parameterTypes();
@@ -1620,7 +1620,7 @@ static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativeP
do {
QList<QByteArray> methodArgTypeNames;
- if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
+ if (attempt->hasArguments())
methodArgTypeNames = object->metaObject()->method(attempt->coreIndex).parameterTypes();
int methodArgumentCount = methodArgTypeNames.count();
@@ -1780,7 +1780,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
return v8::Undefined();
}
- if (method.flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ if (method.isV8Function()) {
v8::Handle<v8::Value> rv;
v8::Handle<v8::Object> qmlglobal = args[2]->ToObject();
diff --git a/src/declarative/qml/v8/qv8valuetypewrapper.cpp b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
index f4f79ce92e..f3100cf7b5 100644
--- a/src/declarative/qml/v8/qv8valuetypewrapper.cpp
+++ b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
@@ -231,7 +231,7 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::Setter(v8::Local<v8::String> property
v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
QDeclarativePropertyCache::Data cacheData;
- cacheData.flags = QDeclarativePropertyCache::Data::IsWritable;
+ cacheData.setFlags(QDeclarativePropertyCache::Data::IsWritable);
cacheData.propType = reference->object->metaObject()->property(reference->property).userType();
cacheData.coreIndex = reference->property;