diff options
author | Andrew den Exter <andrew.den-exter@nokia.com> | 2011-12-19 13:10:06 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-20 05:40:33 +0100 |
commit | 901bdf833cff3db5ef152c3539096b4a7f1de95b (patch) | |
tree | 5ef79bb716f786e2b55761420997504cec022bba /src/declarative | |
parent | f217b776c8a41ea93e3b25a4009573bb94344ac2 (diff) |
Fix QDeclarativePropertyCache crash.
Reserve enough space in the signalHandlerIndexCache so that it will
not reallocated while the property cache is being built as this will
invalidate the pointers stored in the stringCache. Also ensure
signals for all cached meta-objects are included in
signalHandlerIndexCache, and don't over allocate propertyIndexCache
and methodIndexCache.
Change-Id: Ic285d832d4b86106176bfe723ff10bdd65143910
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qdeclarativepropertycache.cpp | 46 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativepropertycache_p.h | 1 |
2 files changed, 34 insertions, 13 deletions
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 239b7942da..67d0cea086 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -117,6 +117,14 @@ static QDeclarativePropertyData::Flags flagsForPropertyType(int propType, QDecla return flags; } +static int metaObjectSignalCount(const QMetaObject *metaObject) +{ + int signalCount = 0; + for (const QMetaObject *obj = metaObject; obj; obj = obj->superClass()) + signalCount += QMetaObjectPrivate::get(obj)->signalCount; + return signalCount; +} + QDeclarativePropertyData::Flags QDeclarativePropertyData::flagsForProperty(const QMetaProperty &p, QDeclarativeEngine *engine) { @@ -220,8 +228,8 @@ void QDeclarativePropertyData::lazyLoad(const QMetaMethod &m) Creates a new empty QDeclarativePropertyCache. */ QDeclarativePropertyCache::QDeclarativePropertyCache(QDeclarativeEngine *e) -: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), metaObject(0), - argumentsCache(0) +: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), + signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0) { Q_ASSERT(engine); } @@ -230,8 +238,8 @@ QDeclarativePropertyCache::QDeclarativePropertyCache(QDeclarativeEngine *e) Creates a new QDeclarativePropertyCache of \a metaObject. */ QDeclarativePropertyCache::QDeclarativePropertyCache(QDeclarativeEngine *e, const QMetaObject *metaObject) -: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), metaObject(0), - argumentsCache(0) +: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), + signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0) { Q_ASSERT(engine); Q_ASSERT(metaObject); @@ -279,6 +287,7 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy(int reserve) cache->parent->addref(); cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart; cache->methodIndexCacheStart = methodIndexCache.count() + methodIndexCacheStart; + cache->signalHanderIndexCacheStart = signalHandlerIndexCache.count() + signalHanderIndexCacheStart; cache->stringCache.copyAndReserve(stringCache, reserve); cache->allowedRevisionCache = allowedRevisionCache; cache->metaObject = metaObject; @@ -313,7 +322,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb int methodCount = metaObject->methodCount(); Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4); - int signalCount = QMetaObjectPrivate::get(metaObject)->signalCount; + int signalCount = metaObjectSignalCount(metaObject); int classInfoCount = QMetaObjectPrivate::get(metaObject)->classInfoCount; QDeclarativeAccessorProperties::Properties accessorProperties; @@ -350,10 +359,13 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb // 3 to block the destroyed signal and the deleteLater() slot int methodOffset = qMax(3, metaObject->methodOffset()); + int signalOffset = signalCount - QMetaObjectPrivate::get(metaObject)->signalCount; + // update() should have reserved enough space in the vector that this doesn't cause a realloc + // and invalidate the stringCache. methodIndexCache.resize(methodCount - methodIndexCacheStart); - signalHandlerIndexCache.resize(signalCount); - int signalHandlerIndex = 0; + signalHandlerIndexCache.resize(signalCount - signalHanderIndexCacheStart); + int signalHandlerIndex = signalOffset; for (int ii = methodOffset; ii < methodCount; ++ii) { QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) @@ -386,7 +398,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb data->metaObjectOffset = allowedRevisionCache.count() - 1; if (data->isSignal()) { - sigdata = &signalHandlerIndexCache[signalHandlerIndex]; + sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHanderIndexCacheStart]; *sigdata = *data; sigdata->flags |= QDeclarativePropertyData::IsSignalHandler; } @@ -439,6 +451,8 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb int propCount = metaObject->propertyCount(); int propOffset = metaObject->propertyOffset(); + // update() should have reserved enough space in the vector that this doesn't cause a realloc + // and invalidate the stringCache. propertyIndexCache.resize(propCount - propertyIndexCacheStart); for (int ii = propOffset; ii < propCount; ++ii) { QMetaProperty p = metaObject->property(ii); @@ -524,13 +538,19 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb Q_ASSERT(metaObject); Q_ASSERT(stringCache.isEmpty()); - // Optimization to prevent unnecessary reallocation of lists + // Preallocate enough space in the index caches for all the properties/methods/signals that + // are not cached in a parent cache so that the caches never need to be reallocated as this + // would invalidate pointers stored in the stringCache. int pc = metaObject->propertyCount(); int mc = metaObject->methodCount(); - propertyIndexCache.reserve(pc); - methodIndexCache.reserve(mc); - - stringCache.reserve(pc + mc); + int sc = metaObjectSignalCount(metaObject); + propertyIndexCache.reserve(pc - propertyIndexCacheStart); + methodIndexCache.reserve(mc - methodIndexCacheStart); + signalHandlerIndexCache.reserve(sc - signalHanderIndexCacheStart); + + // Reserve enough space in the stringCache for all properties/methods/signals including those + // cached in a parent cache. + stringCache.reserve(pc + mc + sc); updateRecur(engine,metaObject); } diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 3deafdf9c5..746c1fe8e8 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -272,6 +272,7 @@ private: QDeclarativePropertyCache *parent; int propertyIndexCacheStart; int methodIndexCacheStart; + int signalHanderIndexCacheStart; IndexCache propertyIndexCache; IndexCache methodIndexCache; |