From 8be744df8a67401fcbe598eb1be76d8bf88fffd1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 4 Dec 2022 12:30:25 -0800 Subject: [PATCH] QAnyStringView: move the tag bits to the LSB for Qt 7 This removes the TODO that was left in the file. It's also applied for bootstrapped use of QAnyStringView, even though it's currently not used in the bootstrap lib. Along with the previous commit of inverting the order of the members, the code generated by GCC 12 for a visitation compares as: _Z1f14QAnyStringView: _Z1f14QAnyStringView: movabsq $4611686018427387903, %rcx | movq %rsi, %rax movq %rdi, %rdx | shrq $2, %rsi movabsq $-4611686018427387904, %rax | andl $3, %eax andq %rsi, %rax | cmpq $2, %rax andq %rcx, %rsi < movabsq $-9223372036854775808, %rcx < cmpq %rcx, %rax < je .L15 je .L15 movabsq $4611686018427387904, %rcx | cmpq $1, %rax cmpq %rcx, %rax < je .L16 je .L16 jmp _Z1fI20QBasicUtf8StringViewILb0EEEvT_ jmp _Z1fI20QBasicUtf8StringViewILb0EEEvT_ .L16: .L16: movq %rsi, %rdi | jmp _Z1fI17QLatin1StringViewEvT_ movq %rdx, %rsi < jmp _Z1fI13QLatin1StringEvT_ < .L15: .L15: movq %rsi, %rdi < movq %rdx, %rsi < jmp _Z1fI11QStringViewEvT_ jmp _Z1fI11QStringViewEvT_ Fixes: QTBUG-109086 Change-Id: I51d12ccdc56c4ad2af07fffd172db128ca4105a5 Reviewed-by: Marc Mutz --- src/corelib/text/qanystringview.h | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/corelib/text/qanystringview.h b/src/corelib/text/qanystringview.h index fd17462b6d..7f8b1d6155 100644 --- a/src/corelib/text/qanystringview.h +++ b/src/corelib/text/qanystringview.h @@ -33,20 +33,25 @@ public: typedef qptrdiff difference_type; typedef qsizetype size_type; private: - // TODO: Optimize by inverting and storing the flags in the low bits and - // the size in the high. static_assert(std::is_same_v); static_assert(sizeof(size_t) == sizeof(qsizetype)); static constexpr size_t SizeMask = (std::numeric_limits::max)() / 4; +#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) + static constexpr int SizeShift = 2; + static constexpr size_t Latin1Flag = 1; +#else + static constexpr int SizeShift = 0; static constexpr size_t Latin1Flag = SizeMask + 1; +#endif static constexpr size_t TwoByteCodePointFlag = Latin1Flag << 1; - static constexpr size_t TypeMask = (std::numeric_limits::max)() & ~SizeMask; + static constexpr size_t TypeMask = ~(SizeMask << SizeShift); static_assert(TypeMask == (Latin1Flag|TwoByteCodePointFlag)); - // HI HI LO LO ... - // 0 0 SZ SZ Utf8 - // 0 1 SZ SZ Latin1 - // 1 0 SZ SZ Utf16 - // 1 1 SZ SZ Unused + + // Tag bits + // 0 0 Utf8 + // 0 1 Latin1 + // 1 0 Utf16 + // 1 1 Unused // ^ ^ latin1 // | sizeof code-point == 2 enum Tag : size_t { @@ -130,7 +135,8 @@ private: Q_ASSERT(sz >= 0); Q_ASSERT(sz <= qsizetype(SizeMask)); Q_ASSERT(str || !sz); - return std::size_t(sz) | uint(sizeof(Char) == sizeof(char16_t)) * Tag::Utf16 + return (std::size_t(sz) << SizeShift) + | uint(sizeof(Char) == sizeof(char16_t)) * Tag::Utf16 | uint(isAsciiOnlyCharsAtCompileTime(str, sz)) * Tag::Latin1; } @@ -247,7 +253,8 @@ public: [[nodiscard]] inline QString toString() const; // defined in qstring.h - [[nodiscard]] constexpr qsizetype size() const noexcept { return qsizetype(m_size & SizeMask); } + [[nodiscard]] constexpr qsizetype size() const noexcept + { return qsizetype((m_size >> SizeShift) & SizeMask); } [[nodiscard]] constexpr const void *data() const noexcept { return m_data; } [[nodiscard]] Q_CORE_EXPORT static int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;