[Development] What's Q_PRIMITIVE_TYPE for?

Andrei Golubev andrei.golubev at qt.io
Tue Nov 10 18:27:59 CET 2020


Hello,

There's another subtle case when your type has in-class member initializers - or whatever the name is - thus it's not primitive but it really could/should be and you want it to be: https://gcc.godbolt.org/z/3TP83f. This is something I accidentally discovered.

And I don't think that compilers are smart enough already to turn a for
loop that is filling with zeros into a memset, so we need the type info
for this. Or am I wrong?

When profiling, memcpy/memmove resulted into an AVX-based function call to some internal library function, memset might as well be similar (but not sure).
NB: for Movable types, we do not simply memset everything to zero, we call placement-new. It's not quite the same as what QPodArrayOps are doing, I believe.

--
Best Regards,
Andrei
________________________________
From: Development <development-bounces at qt-project.org> on behalf of Giuseppe D'Angelo via Development <development at qt-project.org>
Sent: Monday, November 9, 2020 5:16 PM
To: Lars Knoll <lars.knoll at qt.io>
Cc: Qt development mailing list <development at qt-project.org>
Subject: Re: [Development] What's Q_PRIMITIVE_TYPE for?

Hello,

On 09/11/2020 11:33, Lars Knoll wrote:
>>> Q_PRIMITIVE_TYPE specifies that Type is a POD (plain old data) type with no constructor or destructor, or else a type where every bit pattern is a valid object and memcpy() creates a valid independent copy of the object.
>> With this definition in mind, why is QUuid primitive, QVector3D primitive, but QSize not primitive? They all are non-trivial types, they all have default constructors that set their contents to 0. Which one is correct? Can the others be changed while keeping BC?
> If a type is relocatable, it’s default constructor memsets all bits of the object to 0, the copy constructor just does a memcpy of those bits and the destructor does nothing you can just as well mark the type as primitive.
>
> I think the fact that QSize is not marked primitive is a bug and should be fixed. Fortunately, changing that does not affect ABI.
>> Then: is this definition actually exploited anywhere?
> It’s being used to select the QPodArrayOps for QList. The advantage it that we in this case use memset() instead of constructors, and memcpy/memmove to copy or move data.
>
> This does still make a difference compared to Q_RELOCATABLE_TYPE, where we need to use a combination of memmove and copy constructors, and also need to take care of at least basic exception safety when constructing items in the list. For primitive types we can avoid both copy constructors and the rollback handling for potential exceptions.

Thank you! This is what I missed. And indeed this is what is missing
from the Q_PRIMITIVE_TYPE documentation: the condition "every bit
pattern is a valid object" is necessary but not sufficient. It also
needs: "value construction sets all (non-padding) bytes to 0", which is
what gets actually exploited in the current code.

This explains why QSize isn't primitive: every bit pattern is a valid
QSize, but its default constructor sets the extents to -1. So you can't
build a QSize by allocating memory and memsetting it to 0.

And I don't think that compilers are smart enough already to turn a for
loop that is filling with zeros into a memset, so we need the type info
for this. Or am I wrong?


>> The only other place that cares about primitive types is QMetaType, which uses this information to set the "NeedsConstruction" or "NeedsDestruction" type flags. But these type flags are never used anywhere inside of Qt; QMetaType value/copy/move constructs, and destructs, every type.
> This would actually be something to look into. We could avoid creating those methods, and instead have a flag and in those cases the implementation in QMetaType could simply use memset and memcpy.

To be honest, I don't see an advantage here, given QMetaType doesn't
need to "bulk" construct or destroy N objects but only 1, and it could
just call its constructor/destructor rather than short circuiting the
operations to memset/memcpy.


Thank you,
--
Giuseppe D'Angelo | giuseppe.dangelo at kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20201110/b021a650/attachment-0001.html>


More information about the Development mailing list