From 76f05314f5eb2ab3a13656647e99e20575471bed Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Thu, 11 Feb 2021 10:29:25 +0100 Subject: QHashedString(Ref): Use QStringView internally We cannot store a QStringView internally, as that would increase the size of our objects (QHashedString(Ref) does not support strings with sizes that do not fit into 32bit, thus it can store the hash and the size in one 64 bit block). What we can however do is to construct a QStringView on demand (which is cheap), and use its methods. The benefits are twofold: We get rid of some accidental complexity in qtdeclarative; and the code in QStringView is actually SIMD optimized. Change-Id: I2445a2d5a16b253f4971d7f3be0e1b274326eacb Reviewed-by: Maximilian Goldstein Reviewed-by: Ulf Hermann --- src/qml/qml/ftw/qhashedstring.cpp | 81 +++------------------------------------ src/qml/qml/ftw/qhashedstring_p.h | 44 ++++++++++----------- src/qml/qml/ftw/qstringhash_p.h | 2 +- 3 files changed, 28 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp index 4553fa9359..b822e1b120 100644 --- a/src/qml/qml/ftw/qhashedstring.cpp +++ b/src/qml/qml/ftw/qhashedstring.cpp @@ -41,60 +41,6 @@ QT_BEGIN_NAMESPACE -// Copy of QString's qMemCompare -bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length) -{ - Q_ASSERT((lhs && rhs) || !length); - const quint16 *a = (const quint16 *)lhs; - const quint16 *b = (const quint16 *)rhs; - - if (a == b || !length) - return true; - - union { - const quint16 *w; - const quint32 *d; - quintptr value; - } sa, sb; - sa.w = a; - sb.w = b; - - // check alignment - if ((sa.value & 2) == (sb.value & 2)) { - // both addresses have the same alignment - if (sa.value & 2) { - // both addresses are not aligned to 4-bytes boundaries - // compare the first character - if (*sa.w != *sb.w) - return false; - --length; - ++sa.w; - ++sb.w; - - // now both addresses are 4-bytes aligned - } - - // both addresses are 4-bytes aligned - // do a fast 32-bit comparison - const quint32 *e = sa.d + (length >> 1); - for ( ; sa.d != e; ++sa.d, ++sb.d) { - if (*sa.d != *sb.d) - return false; - } - - // do we have a tail? - return (length & 1) ? *sa.w == *sb.w : true; - } else { - // one of the addresses isn't 4-byte aligned but the other is - const quint16 *e = sa.w + length; - for ( ; sa.w != e; ++sa.w, ++sb.w) { - if (*sa.w != *sb.w) - return false; - } - } - return true; -} - QHashedStringRef QHashedStringRef::mid(int offset, int length) const { Q_ASSERT(offset < m_length); @@ -123,35 +69,20 @@ QVector QHashedStringRef::split(const QChar sep) const bool QHashedStringRef::endsWith(const QString &s) const { - return s.length() < m_length && - QHashedString::compare(s.constData(), m_data + m_length - s.length(), s.length()); + QStringView view {m_data, m_length}; + return view.endsWith(s); } bool QHashedStringRef::startsWith(const QString &s) const { - return s.length() < m_length && - QHashedString::compare(s.constData(), m_data, s.length()); -} - -static int findChar(const QChar *str, int len, QChar ch, int from) -{ - const ushort *s = (const ushort *)str; - ushort c = ch.unicode(); - if (from < 0) - from = qMax(from + len, 0); - if (from < len) { - const ushort *n = s + from - 1; - const ushort *e = s + len; - while (++n != e) - if (*n == c) - return n - s; - } - return -1; + QStringView view {m_data, m_length}; + return view.startsWith(s); } int QHashedStringRef::indexOf(const QChar &c, int from) const { - return findChar(m_data, m_length, c, from); + QStringView view {m_data, m_length}; + return view.indexOf(c, from); } QString QHashedStringRef::toString() const diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index c5353acdb1..8f0bd74c53 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -79,7 +79,6 @@ public: inline quint32 hash() const; inline quint32 existingHash() const; - static bool compare(const QChar *lhs, const QChar *rhs, int length); static inline bool compare(const QChar *lhs, const char *rhs, int length); static inline bool compare(const char *lhs, const char *rhs, int length); @@ -217,9 +216,10 @@ bool QHashedString::operator==(const QHashedString &string) const bool QHashedString::operator==(const QHashedStringRef &string) const { - return length() == string.m_length && - (string.m_hash == m_hash || !string.m_hash || !m_hash) && - QHashedString::compare(constData(), string.m_data, string.m_length); + if (m_hash && string.m_hash && m_hash != string.m_hash) + return false; + QStringView otherView {string.m_data, string.m_length}; + return static_cast(*this) == otherView; } quint32 QHashedString::hash() const @@ -277,22 +277,26 @@ QHashedStringRef &QHashedStringRef::operator=(const QHashedStringRef &o) bool QHashedStringRef::operator==(const QString &string) const { - return m_length == string.length() && - QHashedString::compare(string.constData(), m_data, m_length); + QStringView view {m_data, m_length}; + return view == string; } bool QHashedStringRef::operator==(const QHashedString &string) const { - return m_length == string.length() && - (m_hash == string.m_hash || !m_hash || !string.m_hash) && - QHashedString::compare(string.constData(), m_data, m_length); + if (m_hash && string.m_hash && m_hash != string.m_hash) + return false; + QStringView view {m_data, m_length}; + QStringView otherView {string.constData(), string.length()}; + return view == otherView; } bool QHashedStringRef::operator==(const QHashedStringRef &string) const { - return m_length == string.m_length && - (m_hash == string.m_hash || !m_hash || !string.m_hash) && - QHashedString::compare(string.m_data, m_data, m_length); + if (m_hash && string.m_hash && m_hash != string.m_hash) + return false; + QStringView view {m_data, m_length}; + QStringView otherView {string.m_data, string.m_length}; + return view == otherView; } bool QHashedStringRef::operator==(const QHashedCStringRef &string) const @@ -304,29 +308,22 @@ bool QHashedStringRef::operator==(const QHashedCStringRef &string) const bool QHashedStringRef::operator!=(const QString &string) const { - return m_length != string.length() || - !QHashedString::compare(string.constData(), m_data, m_length); + return !(*this == string); } bool QHashedStringRef::operator!=(const QHashedString &string) const { - return m_length != string.length() || - (m_hash != string.m_hash && m_hash && string.m_hash) || - !QHashedString::compare(string.constData(), m_data, m_length); + return !(*this == string); } bool QHashedStringRef::operator!=(const QHashedStringRef &string) const { - return m_length != string.m_length || - (m_hash != string.m_hash && m_hash && string.m_hash) || - QHashedString::compare(string.m_data, m_data, m_length); + return !(*this == string); } 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); + return !(*this == string); } QChar *QHashedStringRef::data() @@ -452,6 +449,7 @@ bool QHashedString::compare(const char *lhs, const char *rhs, int length) return 0 == ::memcmp(lhs, rhs, length); } + quint32 QHashedString::stringHash(const QChar *data, int length) { return QV4::String::createHashValue(data, length, nullptr); diff --git a/src/qml/qml/ftw/qstringhash_p.h b/src/qml/qml/ftw/qstringhash_p.h index c4411b4814..25d66f81d1 100644 --- a/src/qml/qml/ftw/qstringhash_p.h +++ b/src/qml/qml/ftw/qstringhash_p.h @@ -164,7 +164,7 @@ public: inline bool equals(const QHashedStringRef &string) const { return length == string.length() && hash == string.hash() && - (isQString()?QHashedString::compare(string.constData(), (const QChar *)utf16Data(), length): + (isQString()? string == QStringView {utf16Data(), length}: QHashedString::compare(string.constData(), cStrData(), length)); } -- cgit v1.2.3