From ded3fa4ba21430eaa48ca4dcfdd4f297ad8e7b4a Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 22 Jul 2016 10:46:17 +0200 Subject: QML: Make use of all inline bits for bindingBits on 64bit platforms Also initialize the size of the bindingBits to the size of the inline value, so there is no need to check this every time a bit is set. Change-Id: I56be4511ceb6801d6a109a6ab78f7430124fa82b Reviewed-by: Simon Hausmann --- src/qml/qml/qqmldata_p.h | 37 ++++++++++++++++++++++++------------- src/qml/qml/qqmlengine.cpp | 40 ++++++++++++++++++++-------------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index d9a69a9ca3..dce75c51aa 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -129,14 +129,16 @@ public: quint32 parentFrozen:1; quint32 dummy:21; - // When bindingBitsSize < 32, we store the binding bit flags inside - // bindingBitsValue. When we need more than 32 bits, we allocated + // When bindingBitsSize < sizeof(ptr), we store the binding bit flags inside + // bindingBitsValue. When we need more than sizeof(ptr) bits, we allocated // sufficient space and use bindingBits to point to it. int bindingBitsSize; + typedef quintptr BindingBitsType; union { - quint32 *bindingBits; - quint32 bindingBitsValue; + BindingBitsType *bindingBits; + BindingBitsType bindingBitsValue; }; + enum { MaxInlineBits = sizeof(BindingBitsType) * 8 }; struct NotifyList { quint64 connectionMask; @@ -236,6 +238,17 @@ private: mutable QQmlDataExtended *extendedData; void flushPendingBindingImpl(QQmlPropertyIndex index); + + Q_ALWAYS_INLINE bool hasBitSet(int bit) const + { + if (bindingBitsSize <= bit) + return false; + + if (bindingBitsSize == MaxInlineBits) + return bindingBitsValue & (BindingBitsType(1) << bit); + else + return bindingBits[bit / MaxInlineBits] & (BindingBitsType(1) << (bit % MaxInlineBits)); + } }; bool QQmlData::wasDeleted(QObject *object) @@ -281,20 +294,18 @@ inline bool QQmlData::signalHasEndpoint(int index) const bool QQmlData::hasBindingBit(int coreIndex) const { - int bit = coreIndex * 2; + Q_ASSERT(coreIndex >= 0); + Q_ASSERT(coreIndex <= 0xffff); - return bindingBitsSize > bit && - ((bindingBitsSize == 32) ? (bindingBitsValue & (1 << bit)) : - (bindingBits[bit / 32] & (1 << (bit % 32)))); + return hasBitSet(coreIndex * 2); } -bool QQmlData::hasPendingBindingBit(int index) const +bool QQmlData::hasPendingBindingBit(int coreIndex) const { - int bit = index * 2 + 1; + Q_ASSERT(coreIndex >= 0); + Q_ASSERT(coreIndex <= 0xffff); - return bindingBitsSize > bit && - ((bindingBitsSize == 32) ? (bindingBitsValue & (1 << bit)) : - (bindingBits[bit / 32] & (1 << (bit % 32)))); + return hasBitSet(coreIndex * 2 + 1); } void QQmlData::flushPendingBinding(QObject *o, QQmlPropertyIndex propertyIndex) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 48832f3b07..2b49eae4de 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -105,6 +105,9 @@ Q_DECLARE_METATYPE(QQmlProperty) QT_BEGIN_NAMESPACE +typedef QQmlData::BindingBitsType BindingBitsType; +enum { MaxInlineBits = QQmlData::MaxInlineBits }; + void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor) { QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor); @@ -677,7 +680,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) QQmlData::QQmlData() : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false), - hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0), + hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), + bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0), context(0), outerContext(0), bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), lineNumber(0), columnNumber(0), jsEngineId(0), compilationUnit(0), deferredData(0), propertyCache(0), guards(0), extendedData(0) @@ -1690,7 +1694,7 @@ void QQmlData::destroyed(QObject *object) signalHandler = next; } - if (bindingBitsSize > 32) + if (bindingBitsSize > MaxInlineBits) free(bindingBits); if (propertyCache) @@ -1740,31 +1744,27 @@ void QQmlData::parentChanged(QObject *object, QObject *parent) static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit) { - if (data->bindingBitsSize == 0 && bit < 32) { - data->bindingBitsSize = 32; - } - - if (data->bindingBitsSize <= bit) { + if (Q_UNLIKELY(data->bindingBitsSize <= bit)) { int props = QQmlMetaObject(obj).propertyCount(); Q_ASSERT(bit < 2 * props); - int arraySize = (2 * props + 31) / 32; + int arraySize = (2 * props + MaxInlineBits - 1) / MaxInlineBits; Q_ASSERT(arraySize > 1); // special handling for 32 here is to make sure we wipe the first byte // when going from bindingBitsValue to bindingBits, and preserve the old // set bits so we can restore them after the allocation - int oldArraySize = data->bindingBitsSize > 32 ? data->bindingBitsSize / 32 : 0; - quint32 oldValue = data->bindingBitsSize == 32 ? data->bindingBitsValue : 0; + int oldArraySize = data->bindingBitsSize > MaxInlineBits ? data->bindingBitsSize / MaxInlineBits : 0; + quintptr oldValue = data->bindingBitsSize == MaxInlineBits ? data->bindingBitsValue : 0; - data->bindingBits = (quint32 *)realloc((data->bindingBitsSize == 32) ? 0 : data->bindingBits, - arraySize * sizeof(quint32)); + data->bindingBits = static_cast(realloc((data->bindingBitsSize == MaxInlineBits) ? 0 : data->bindingBits, + arraySize * sizeof(BindingBitsType))); memset(data->bindingBits + oldArraySize, 0x00, - sizeof(quint32) * (arraySize - oldArraySize)); + sizeof(BindingBitsType) * (arraySize - oldArraySize)); - data->bindingBitsSize = arraySize * 32; + data->bindingBitsSize = arraySize * MaxInlineBits; // reinstate bindingBitsValue after we dropped it if (oldValue) { @@ -1772,19 +1772,19 @@ static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit) } } - if (data->bindingBitsSize == 32) - data->bindingBitsValue |= (1 << (bit % 32)); + if (data->bindingBitsSize == MaxInlineBits) + data->bindingBitsValue |= BindingBitsType(1) << bit; else - data->bindingBits[bit / 32] |= (1 << (bit % 32)); + data->bindingBits[bit / MaxInlineBits] |= (BindingBitsType(1) << (bit % MaxInlineBits)); } static void QQmlData_clearBit(QQmlData *data, int bit) { if (data->bindingBitsSize > bit) { - if (data->bindingBitsSize == 32) - data->bindingBitsValue &= ~(1 << (bit % 32)); + if (data->bindingBitsSize == MaxInlineBits) + data->bindingBitsValue &= ~(BindingBitsType(1) << (bit % MaxInlineBits)); else - data->bindingBits[bit / 32] &= ~(1 << (bit % 32)); + data->bindingBits[bit / MaxInlineBits] &= ~(BindingBitsType(1) << (bit % MaxInlineBits)); } } -- cgit v1.2.3