Details
-
Task
-
Resolution: Fixed
-
P2: Important
-
6.x
-
None
-
5
-
8be744df8 (dev)
Description
The tag that distinguishes L1/U8/U16 encoding is currently placed in the MSBs of the QAnyStringView::m_size member. This means that the tag values are large 64-bit quantities that are inefficient to construct in a CPU register for ANDing into m_size to get the actual size or even construct a QAnyStringView object.
Example inline isEmpty() on x86-64 (%r15 represents m_size):
movabsq $4611686018427387903, %rax # imm = 0x3FFFFFFFFFFFFFFF andq %rax, %r15 je <target>
I'm sure there are more compact ways to create the value in a register (move 0x1 into a register, shift register left by 62), but the fact remains that a register is needed to construct the value first, which exerts register pressure esp. in the traditionally register-starved x86 architecture, leading to more registers that need to be saved on the stack on function entry and restored on function exit than would otherwise be necessary.
If, OTOH, the tag would be stored in the LSBs of m_size, then size() would be a right-shift by two, and getting the tag would be an and with three. Both small constants can usually be stored in the immediate field of the corresponding instruction, so they're much more space- and runtime-efficient.
thiago mentioned this problem before QAnyStringView was merged, but I didn't fully appreciate the problem back then and forgot to follow up.
We should make sure that we get rid of this in Qt 7.
Acceptance criteria:
- QAnyStringView::Tag is stored in the LSBs of m_size, not the MSBs
- pre-programmed for QT_VERSION_CHECK(7, 0, 0) and already enabled in bootstrap builds