Commit e83bb2fdfc2dc899526c8157fd8b77a68cdde9da
- Diff rendering mode:
- inline
- side by side
src/corelib/global/qmalloc.cpp
(0 / 3)
|   | |||
| 144 | 144 | // faked-sizeof(void*) is properly aligned for a pointer | |
| 145 | 145 | faked.pptr[-1] = real.ptr; | |
| 146 | 146 | ||
| 147 | // and save the actual size just before the pointer | ||
| 148 | //reinterpret_cast<size_t *>(faked.pptr - 1)[-1] = size; | ||
| 149 | |||
| 150 | 147 | return faked.ptr; | |
| 151 | 148 | #endif | |
| 152 | 149 | } |
src/corelib/tools/qcontiguouscache.cpp
(10 / 0)
|   | |||
| 56 | 56 | } | |
| 57 | 57 | #endif | |
| 58 | 58 | ||
| 59 | QContiguousCacheData *QContiguousCacheData::allocate(int size, int alignment) | ||
| 60 | { | ||
| 61 | return static_cast<QContiguousCacheData *>(qMallocAligned(size, alignment)); | ||
| 62 | } | ||
| 63 | |||
| 64 | void QContiguousCacheData::free(QContiguousCacheData *data) | ||
| 65 | { | ||
| 66 | qFreeAligned(data); | ||
| 67 | } | ||
| 68 | |||
| 59 | 69 | /*! \class QContiguousCache | |
| 60 | 70 | \brief The QContiguousCache class is a template class that provides a contiguous cache. | |
| 61 | 71 | \ingroup tools |
src/corelib/tools/qcontiguouscache.h
(13 / 2)
|   | |||
| 69 | 69 | // there will be an 8 byte gap here if T requires 16-byte alignment | |
| 70 | 70 | // (such as long double on 64-bit platforms, __int128, __float128) | |
| 71 | 71 | ||
| 72 | static QContiguousCacheData *allocate(int size, int alignment); | ||
| 73 | static void free(QContiguousCacheData *data); | ||
| 74 | |||
| 72 | 75 | #ifdef QT_QCONTIGUOUSCACHE_DEBUG | |
| 73 | 76 | void dump() const; | |
| 74 | 77 | #endif | |
| … | … | ||
| 164 | 164 | // count the padding at the end | |
| 165 | 165 | return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this); | |
| 166 | 166 | } | |
| 167 | int alignOfTypedData() const | ||
| 168 | { | ||
| 169 | #ifdef Q_ALIGNOF | ||
| 170 | return qMax<int>(sizeof(void*), Q_ALIGNOF(Data)); | ||
| 171 | #else | ||
| 172 | return 0; | ||
| 173 | #endif | ||
| 174 | } | ||
| 167 | 175 | }; | |
| 168 | 176 | ||
| 169 | 177 | template <typename T> | |
| … | … | ||
| 273 | 273 | template <typename T> | |
| 274 | 274 | inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc) | |
| 275 | 275 | { | |
| 276 | return static_cast<QContiguousCacheData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T))); | ||
| 276 | return QContiguousCacheData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData()); | ||
| 277 | 277 | } | |
| 278 | 278 | ||
| 279 | 279 | template <typename T> | |
| … | … | ||
| 328 | 328 | i = p->array; | |
| 329 | 329 | } | |
| 330 | 330 | } | |
| 331 | qFree(x); | ||
| 331 | x->free(x); | ||
| 332 | 332 | } | |
| 333 | 333 | template <typename T> | |
| 334 | 334 | void QContiguousCache<T>::append(const T &value) |
src/corelib/tools/qhash.cpp
(19 / 8)
|   | |||
| 166 | 166 | const int MinNumBits = 4; | |
| 167 | 167 | ||
| 168 | 168 | QHashData QHashData::shared_null = { | |
| 169 | 0, 0, Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, MinNumBits, 0, 0, true | ||
| 169 | 0, 0, Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, MinNumBits, 0, 0, true, false | ||
| 170 | 170 | }; | |
| 171 | 171 | ||
| 172 | 172 | void *QHashData::allocateNode() | |
| 173 | 173 | { | |
| 174 | void *ptr = qMalloc(nodeSize); | ||
| 174 | return allocateNode(0); | ||
| 175 | } | ||
| 176 | |||
| 177 | void *QHashData::allocateNode(int nodeAlign) | ||
| 178 | { | ||
| 179 | void *ptr = strictAlignment ? qMallocAligned(nodeSize, nodeAlign) : qMalloc(nodeSize); | ||
| 175 | 180 | Q_CHECK_PTR(ptr); | |
| 176 | 181 | return ptr; | |
| 177 | 182 | } | |
| 178 | 183 | ||
| 179 | 184 | void QHashData::freeNode(void *node) | |
| 180 | 185 | { | |
| 181 | qFree(node); | ||
| 186 | if (strictAlignment) | ||
| 187 | qFreeAligned(node); | ||
| 188 | else | ||
| 189 | qFree(node); | ||
| 182 | 190 | } | |
| 183 | 191 | ||
| 184 | 192 | QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize) | |
| 185 | 193 | { | |
| 186 | return detach_helper( node_duplicate, 0, nodeSize ); | ||
| 194 | return detach_helper2( node_duplicate, 0, nodeSize, 0 ); | ||
| 187 | 195 | } | |
| 188 | 196 | ||
| 189 | QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), | ||
| 190 | void (*node_delete)(Node *), | ||
| 191 | int nodeSize) | ||
| 197 | QHashData *QHashData::detach_helper2(void (*node_duplicate)(Node *, void *), | ||
| 198 | void (*node_delete)(Node *), | ||
| 199 | int nodeSize, | ||
| 200 | int nodeAlign) | ||
| 192 | 201 | { | |
| 193 | 202 | union { | |
| 194 | 203 | QHashData *d; | |
| … | … | ||
| 213 | 213 | d->numBits = numBits; | |
| 214 | 214 | d->numBuckets = numBuckets; | |
| 215 | 215 | d->sharable = true; | |
| 216 | d->strictAlignment = nodeAlign > 8; | ||
| 216 | 217 | ||
| 217 | 218 | if (numBuckets) { | |
| 218 | 219 | QT_TRY { | |
| … | … | ||
| 232 | 232 | Node *oldNode = buckets[i]; | |
| 233 | 233 | while (oldNode != this_e) { | |
| 234 | 234 | QT_TRY { | |
| 235 | Node *dup = static_cast<Node *>(allocateNode()); | ||
| 235 | Node *dup = static_cast<Node *>(allocateNode(nodeAlign)); | ||
| 236 | 236 | ||
| 237 | 237 | QT_TRY { | |
| 238 | 238 | node_duplicate(oldNode, dup); | |
| … | … | ||
| 272 | 272 | while (cur != this_e) { | |
| 273 | 273 | Node *next = cur->next; | |
| 274 | 274 | node_delete(cur); | |
| 275 | freeNode(cur); | ||
| 275 | 276 | cur = next; | |
| 276 | 277 | } | |
| 277 | 278 | } |
src/corelib/tools/qhash.h
(23 / 13)
|   | |||
| 125 | 125 | short numBits; | |
| 126 | 126 | int numBuckets; | |
| 127 | 127 | uint sharable : 1; | |
| 128 | uint strictAlignment : 1; | ||
| 128 | 129 | ||
| 129 | void *allocateNode(); | ||
| 130 | void *allocateNode(); // ### Qt5 remove me | ||
| 131 | void *allocateNode(int nodeAlign); | ||
| 130 | 132 | void freeNode(void *node); | |
| 131 | 133 | QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize); // ### Qt5 remove me | |
| 132 | QHashData *detach_helper(void (*node_duplicate)(Node *, void *), void (*node_delete)(Node *), | ||
| 133 | int nodeSize); | ||
| 134 | QHashData *detach_helper2(void (*node_duplicate)(Node *, void *), void (*node_delete)(Node *), | ||
| 135 | int nodeSize, int nodeAlign); | ||
| 134 | 136 | void mightGrow(); | |
| 135 | 137 | bool willGrow(); | |
| 136 | 138 | void hasShrunk(); | |
| … | … | ||
| 269 | 269 | return reinterpret_cast<Node *>(node); | |
| 270 | 270 | } | |
| 271 | 271 | ||
| 272 | #ifdef Q_ALIGNOF | ||
| 273 | static inline int alignOfNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(Node)); } | ||
| 274 | static inline int alignOfDummyNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(DummyNode)); } | ||
| 275 | #else | ||
| 276 | static inline int alignOfNode() { return 0; } | ||
| 277 | static inline int alignOfDummyNode() { return 0; } | ||
| 278 | #endif | ||
| 279 | |||
| 272 | 280 | public: | |
| 273 | 281 | inline QHash() : d(&QHashData::shared_null) { d->ref.ref(); } | |
| 274 | 282 | inline QHash(const QHash<Key, T> &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); } | |
| … | … | ||
| 493 | 493 | Node **findNode(const Key &key, uint *hp = 0) const; | |
| 494 | 494 | Node *createNode(uint h, const Key &key, const T &value, Node **nextNode); | |
| 495 | 495 | void deleteNode(Node *node); | |
| 496 | static void deleteNode(QHashData::Node *node); | ||
| 496 | static void deleteNode2(QHashData::Node *node); | ||
| 497 | 497 | ||
| 498 | 498 | static void duplicateNode(QHashData::Node *originalNode, void *newNode); | |
| 499 | 499 | }; | |
| … | … | ||
| 502 | 502 | template <class Key, class T> | |
| 503 | 503 | Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(Node *node) | |
| 504 | 504 | { | |
| 505 | deleteNode(reinterpret_cast<QHashData::Node*>(node)); | ||
| 505 | deleteNode2(reinterpret_cast<QHashData::Node*>(node)); | ||
| 506 | d->freeNode(node); | ||
| 506 | 507 | } | |
| 507 | 508 | ||
| 508 | |||
| 509 | 509 | template <class Key, class T> | |
| 510 | Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(QHashData::Node *node) | ||
| 510 | Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode2(QHashData::Node *node) | ||
| 511 | 511 | { | |
| 512 | 512 | #ifdef Q_CC_BOR | |
| 513 | 513 | concrete(node)->~QHashNode<Key, T>(); | |
| … | … | ||
| 516 | 516 | #else | |
| 517 | 517 | concrete(node)->~Node(); | |
| 518 | 518 | #endif | |
| 519 | qFree(node); | ||
| 520 | 519 | } | |
| 521 | 520 | ||
| 522 | 521 | template <class Key, class T> | |
| … | … | ||
| 536 | 536 | Node *node; | |
| 537 | 537 | ||
| 538 | 538 | if (QTypeInfo<T>::isDummy) { | |
| 539 | node = reinterpret_cast<Node *>(new (d->allocateNode()) DummyNode(akey)); | ||
| 539 | node = reinterpret_cast<Node *>(new (d->allocateNode(alignOfDummyNode())) DummyNode(akey)); | ||
| 540 | 540 | } else { | |
| 541 | node = new (d->allocateNode()) Node(akey, avalue); | ||
| 541 | node = new (d->allocateNode(alignOfNode())) Node(akey, avalue); | ||
| 542 | 542 | } | |
| 543 | 543 | ||
| 544 | 544 | node->h = ah; | |
| … | … | ||
| 563 | 563 | template <class Key, class T> | |
| 564 | 564 | Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x) | |
| 565 | 565 | { | |
| 566 | x->free_helper(deleteNode); | ||
| 566 | x->free_helper(deleteNode2); | ||
| 567 | 567 | } | |
| 568 | 568 | ||
| 569 | 569 | template <class Key, class T> | |
| … | … | ||
| 575 | 575 | template <class Key, class T> | |
| 576 | 576 | Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper() | |
| 577 | 577 | { | |
| 578 | QHashData *x = d->detach_helper(duplicateNode, deleteNode, | ||
| 579 | QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node)); | ||
| 578 | QHashData *x = d->detach_helper2(duplicateNode, deleteNode2, | ||
| 579 | QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node), | ||
| 580 | QTypeInfo<T>::isDummy ? alignOfDummyNode() : alignOfNode()); | ||
| 580 | 581 | if (!d->ref.deref()) | |
| 581 | 582 | freeData(d); | |
| 582 | 583 | d = x; |
src/corelib/tools/qmap.cpp
(26 / 5)
|   | |||
| 53 | 53 | QMapData QMapData::shared_null = { | |
| 54 | 54 | &shared_null, | |
| 55 | 55 | { &shared_null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
| 56 | Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, 0, false, true | ||
| 56 | Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, 0, false, true, false | ||
| 57 | 57 | }; | |
| 58 | 58 | ||
| 59 | 59 | QMapData *QMapData::createData() | |
| 60 | 60 | { | |
| 61 | return createData(0); | ||
| 62 | } | ||
| 63 | |||
| 64 | QMapData *QMapData::createData(int alignment) | ||
| 65 | { | ||
| 61 | 66 | QMapData *d = new QMapData; | |
| 62 | 67 | Q_CHECK_PTR(d); | |
| 63 | 68 | Node *e = reinterpret_cast<Node *>(d); | |
| … | … | ||
| 74 | 74 | d->randomBits = 0; | |
| 75 | 75 | d->insertInOrder = false; | |
| 76 | 76 | d->sharable = true; | |
| 77 | d->strictAlignment = alignment > 8; | ||
| 77 | 78 | return d; | |
| 78 | 79 | } | |
| 79 | 80 | ||
| … | … | ||
| 86 | 86 | while (cur != e) { | |
| 87 | 87 | prev = cur; | |
| 88 | 88 | cur = cur->forward[0]; | |
| 89 | qFree(reinterpret_cast<char *>(prev) - offset); | ||
| 89 | if (strictAlignment) | ||
| 90 | qFreeAligned(reinterpret_cast<char *>(prev) - offset); | ||
| 91 | else | ||
| 92 | qFree(reinterpret_cast<char *>(prev) - offset); | ||
| 90 | 93 | } | |
| 91 | 94 | delete this; | |
| 92 | 95 | } | |
| 93 | 96 | ||
| 97 | QMapData::Node *QMapData::node_create(Node *update[], int offset) | ||
| 98 | { | ||
| 99 | return node_create(update, offset, 0); | ||
| 100 | } | ||
| 101 | |||
| 94 | 102 | /*! | |
| 95 | 103 | Creates a new node inside the data structure. | |
| 96 | 104 | ||
| … | … | ||
| 108 | 108 | \a offset is an amount of bytes that needs to reserved just before the | |
| 109 | 109 | QMapData::Node structure. | |
| 110 | 110 | ||
| 111 | \a alignment dictates the alignment for the data. | ||
| 112 | |||
| 111 | 113 | \internal | |
| 112 | 114 | \since 4.6 | |
| 113 | 115 | */ | |
| 114 | QMapData::Node *QMapData::node_create(Node *update[], int offset) | ||
| 116 | QMapData::Node *QMapData::node_create(Node *update[], int offset, int alignment) | ||
| 115 | 117 | { | |
| 116 | 118 | int level = 0; | |
| 117 | 119 | uint mask = (1 << Sparseness) - 1; | |
| … | … | ||
| 134 | 134 | if (level == 3 && !insertInOrder) | |
| 135 | 135 | randomBits = qrand(); | |
| 136 | 136 | ||
| 137 | void *concreteNode = qMalloc(offset + sizeof(Node) + level * sizeof(Node *)); | ||
| 137 | void *concreteNode = strictAlignment ? | ||
| 138 | qMallocAligned(offset + sizeof(Node) + level * sizeof(Node *), alignment) : | ||
| 139 | qMalloc(offset + sizeof(Node) + level * sizeof(Node *)); | ||
| 138 | 140 | Q_CHECK_PTR(concreteNode); | |
| 139 | 141 | ||
| 140 | 142 | Node *abstractNode = reinterpret_cast<Node *>(reinterpret_cast<char *>(concreteNode) + offset); | |
| … | … | ||
| 163 | 163 | update[i]->forward[i] = node->forward[i]; | |
| 164 | 164 | } | |
| 165 | 165 | --size; | |
| 166 | qFree(reinterpret_cast<char *>(node) - offset); | ||
| 166 | if (strictAlignment) | ||
| 167 | qFreeAligned(reinterpret_cast<char *>(node) - offset); | ||
| 168 | else | ||
| 169 | qFree(reinterpret_cast<char *>(node) - offset); | ||
| 167 | 170 | } | |
| 168 | 171 | ||
| 169 | 172 | #ifdef QT_QMAP_DEBUG |
src/corelib/tools/qmap.h
(15 / 5)
|   | |||
| 74 | 74 | uint randomBits; | |
| 75 | 75 | uint insertInOrder : 1; | |
| 76 | 76 | uint sharable : 1; | |
| 77 | uint strictAlignment : 1; | ||
| 77 | 78 | ||
| 78 | static QMapData *createData(); | ||
| 79 | static QMapData *createData(); // ### Qt5 remove me | ||
| 80 | static QMapData *createData(int alignment); | ||
| 79 | 81 | void continueFreeData(int offset); | |
| 80 | Node *node_create(Node *update[], int offset); | ||
| 82 | Node *node_create(Node *update[], int offset); // ### Qt5 remove me | ||
| 83 | Node *node_create(Node *update[], int offset, int alignment); | ||
| 81 | 84 | void node_delete(Node *update[], int offset, Node *node); | |
| 82 | 85 | #ifdef QT_QMAP_DEBUG | |
| 83 | 86 | uint adjust_ptr(Node *node); | |
| … | … | ||
| 148 | 148 | }; | |
| 149 | 149 | ||
| 150 | 150 | static inline int payload() { return sizeof(PayloadNode) - sizeof(QMapData::Node *); } | |
| 151 | static inline int alignment() { | ||
| 152 | #ifdef Q_ALIGNOF | ||
| 153 | return qMax(sizeof(void*), Q_ALIGNOF(Node)); | ||
| 154 | #else | ||
| 155 | return 0; | ||
| 156 | #endif | ||
| 157 | } | ||
| 151 | 158 | static inline Node *concrete(QMapData::Node *node) { | |
| 152 | 159 | return reinterpret_cast<Node *>(reinterpret_cast<char *>(node) - payload()); | |
| 153 | 160 | } | |
| … | … | ||
| 424 | 424 | Q_INLINE_TEMPLATE typename QMapData::Node * | |
| 425 | 425 | QMap<Key, T>::node_create(QMapData *adt, QMapData::Node *aupdate[], const Key &akey, const T &avalue) | |
| 426 | 426 | { | |
| 427 | QMapData::Node *abstractNode = adt->node_create(aupdate, payload()); | ||
| 427 | QMapData::Node *abstractNode = adt->node_create(aupdate, payload(), alignment()); | ||
| 428 | 428 | QT_TRY { | |
| 429 | 429 | Node *concreteNode = concrete(abstractNode); | |
| 430 | 430 | new (&concreteNode->key) Key(akey); | |
| … | … | ||
| 725 | 725 | Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper() | |
| 726 | 726 | { | |
| 727 | 727 | union { QMapData *d; QMapData::Node *e; } x; | |
| 728 | x.d = QMapData::createData(); | ||
| 728 | x.d = QMapData::createData(alignment()); | ||
| 729 | 729 | if (d->size) { | |
| 730 | 730 | x.d->insertInOrder = true; | |
| 731 | 731 | QMapData::Node *update[QMapData::LastLevel + 1]; | |
| … | … | ||
| 915 | 915 | template <class Key, class T> | |
| 916 | 916 | Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other) | |
| 917 | 917 | { | |
| 918 | d = QMapData::createData(); | ||
| 918 | d = QMapData::createData(alignment()); | ||
| 919 | 919 | d->insertInOrder = true; | |
| 920 | 920 | typename std::map<Key,T>::const_iterator it = other.end(); | |
| 921 | 921 | while (it != other.begin()) { |
src/corelib/tools/qvector.cpp
(27 / 0)
|   | |||
| 45 | 45 | ||
| 46 | 46 | QT_BEGIN_NAMESPACE | |
| 47 | 47 | ||
| 48 | static inline int alignmentThreshold() | ||
| 49 | { | ||
| 50 | // malloc on 32-bit platforms should return pointers that are 8-byte aligned or more | ||
| 51 | // while on 64-bit platforms they should be 16-byte aligned or more | ||
| 52 | return 2 * sizeof(void*); | ||
| 53 | } | ||
| 54 | |||
| 48 | 55 | QVectorData QVectorData::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, true, false }; | |
| 49 | 56 | ||
| 50 | 57 | QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init) | |
| … | … | ||
| 60 | 60 | Q_CHECK_PTR(p); | |
| 61 | 61 | ::memcpy(p, init, sizeofTypedData + (qMin(size, init->alloc) - 1) * sizeofT); | |
| 62 | 62 | return p; | |
| 63 | } | ||
| 64 | |||
| 65 | QVectorData *QVectorData::allocate(int size, int alignment) | ||
| 66 | { | ||
| 67 | return static_cast<QVectorData *>(alignment > alignmentThreshold() ? qMallocAligned(size, alignment) : qMalloc(size)); | ||
| 68 | } | ||
| 69 | |||
| 70 | QVectorData *QVectorData::reallocate(QVectorData *x, int newsize, int oldsize, int alignment) | ||
| 71 | { | ||
| 72 | if (alignment > alignmentThreshold()) | ||
| 73 | return static_cast<QVectorData *>(qReallocAligned(x, newsize, oldsize, alignment)); | ||
| 74 | return static_cast<QVectorData *>(qRealloc(x, newsize)); | ||
| 75 | } | ||
| 76 | |||
| 77 | void QVectorData::free(QVectorData *x, int alignment) | ||
| 78 | { | ||
| 79 | if (alignment > alignmentThreshold()) | ||
| 80 | qFreeAligned(x); | ||
| 81 | else | ||
| 82 | qFree(x); | ||
| 63 | 83 | } | |
| 64 | 84 | ||
| 65 | 85 | int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive) |
src/corelib/tools/qvector.h
(17 / 3)
|   | |||
| 79 | 79 | // some debugges when the QVector is member of a class within an unnamed namespace. | |
| 80 | 80 | // ### Qt 5: can be removed completely. (Ralf) | |
| 81 | 81 | static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init); | |
| 82 | static QVectorData *allocate(int size, int alignment); | ||
| 83 | static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment); | ||
| 84 | static void free(QVectorData *data, int alignment); | ||
| 82 | 85 | static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive); | |
| 83 | 86 | }; | |
| 84 | 87 | ||
| … | … | ||
| 90 | 90 | { // private inheritance as we must not access QVectorData member thought QVectorTypedData | |
| 91 | 91 | // as this would break strict aliasing rules. (in the case of shared_null) | |
| 92 | 92 | T array[1]; | |
| 93 | |||
| 94 | static inline void free(QVectorTypedData *x, int alignment) { QVectorData::free(x, alignment); } | ||
| 93 | 95 | }; | |
| 94 | 96 | ||
| 95 | 97 | class QRegion; | |
| … | … | ||
| 307 | 307 | // count the padding at the end | |
| 308 | 308 | return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this); | |
| 309 | 309 | } | |
| 310 | inline int alignOfTypedData() const | ||
| 311 | { | ||
| 312 | #ifdef Q_ALIGNOF | ||
| 313 | return qMax<int>(sizeof(void*), Q_ALIGNOF(Data)); | ||
| 314 | #else | ||
| 315 | return 0; | ||
| 316 | #endif | ||
| 317 | } | ||
| 310 | 318 | }; | |
| 311 | 319 | ||
| 312 | 320 | template <typename T> | |
| … | … | ||
| 386 | 386 | template <typename T> | |
| 387 | 387 | inline QVectorData *QVector<T>::malloc(int aalloc) | |
| 388 | 388 | { | |
| 389 | QVectorData *vectordata = static_cast<QVectorData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T))); | ||
| 389 | QVectorData *vectordata = QVectorData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData()); | ||
| 390 | 390 | Q_CHECK_PTR(vectordata); | |
| 391 | 391 | return vectordata; | |
| 392 | 392 | } | |
| … | … | ||
| 433 | 433 | while (i-- != b) | |
| 434 | 434 | i->~T(); | |
| 435 | 435 | } | |
| 436 | qFree(x); | ||
| 436 | x->free(x, alignOfTypedData()); | ||
| 437 | 437 | } | |
| 438 | 438 | ||
| 439 | 439 | template <typename T> | |
| … | … | ||
| 472 | 472 | } | |
| 473 | 473 | } else { | |
| 474 | 474 | QT_TRY { | |
| 475 | QVectorData *mem = static_cast<QVectorData *>(qRealloc(p, sizeOfTypedData() + (aalloc - 1) * sizeof(T))); | ||
| 475 | QVectorData *mem = QVectorData::reallocate(d, sizeOfTypedData() + (aalloc - 1) * sizeof(T), | ||
| 476 | sizeOfTypedData() + (d->alloc - 1) * sizeof(T), alignOfTypedData()); | ||
| 476 | 477 | Q_CHECK_PTR(mem); | |
| 477 | 478 | x.d = d = mem; | |
| 478 | 479 | x.d->size = d->size; |
tests/auto/collections/tst_collections.cpp
(109 / 0)
|   | |||
| 164 | 164 | void qtimerList(); | |
| 165 | 165 | void containerTypedefs(); | |
| 166 | 166 | void forwardDeclared(); | |
| 167 | void alignment(); | ||
| 167 | 168 | }; | |
| 168 | 169 | ||
| 169 | 170 | struct LargeStatic { | |
| … | … | ||
| 3481 | 3481 | { typedef QQueue<T1> C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } | |
| 3482 | 3482 | { typedef QSet<T1> C; C *x = 0; /* C::iterator i; */ C::const_iterator j; Q_UNUSED(x) } | |
| 3483 | 3483 | } | |
| 3484 | |||
| 3485 | #if defined(Q_ALIGNOF) && defined(Q_DECL_ALIGN) | ||
| 3486 | |||
| 3487 | class Q_DECL_ALIGN(4) Aligned4 | ||
| 3488 | { | ||
| 3489 | char i; | ||
| 3490 | public: | ||
| 3491 | Aligned4(int i = 0) : i(i) {} | ||
| 3492 | bool checkAligned() const | ||
| 3493 | { | ||
| 3494 | return (quintptr(this) & 3) == 0; | ||
| 3495 | } | ||
| 3496 | |||
| 3497 | inline bool operator==(const Aligned4 &other) const { return i == other.i; } | ||
| 3498 | inline bool operator<(const Aligned4 &other) const { return i < other.i; } | ||
| 3499 | friend inline int qHash(const Aligned4 &a) { return qHash(a.i); } | ||
| 3500 | }; | ||
| 3501 | |||
| 3502 | class Q_DECL_ALIGN(128) Aligned128 | ||
| 3503 | { | ||
| 3504 | char i; | ||
| 3505 | public: | ||
| 3506 | Aligned128(int i = 0) : i(i) {} | ||
| 3507 | bool checkAligned() const | ||
| 3508 | { | ||
| 3509 | return (quintptr(this) & 127) == 0; | ||
| 3510 | } | ||
| 3511 | |||
| 3512 | inline bool operator==(const Aligned128 &other) const { return i == other.i; } | ||
| 3513 | inline bool operator<(const Aligned128 &other) const { return i < other.i; } | ||
| 3514 | friend inline int qHash(const Aligned128 &a) { return qHash(a.i); } | ||
| 3515 | }; | ||
| 3516 | |||
| 3517 | template<typename C> | ||
| 3518 | void testVectorAlignment() | ||
| 3519 | { | ||
| 3520 | typedef typename C::value_type Aligned; | ||
| 3521 | C container; | ||
| 3522 | container.append(Aligned()); | ||
| 3523 | QVERIFY(container[0].checkAligned()); | ||
| 3524 | |||
| 3525 | for (int i = 0; i < 200; ++i) | ||
| 3526 | container.append(Aligned()); | ||
| 3527 | |||
| 3528 | for (int i = 0; i < container.size(); ++i) | ||
| 3529 | QVERIFY(container.at(i).checkAligned()); | ||
| 3530 | } | ||
| 3531 | |||
| 3532 | template<typename C> | ||
| 3533 | void testContiguousCacheAlignment() | ||
| 3534 | { | ||
| 3535 | typedef typename C::value_type Aligned; | ||
| 3536 | C container(150); | ||
| 3537 | container.append(Aligned()); | ||
| 3538 | QVERIFY(container[container.firstIndex()].checkAligned()); | ||
| 3539 | |||
| 3540 | for (int i = 0; i < 200; ++i) | ||
| 3541 | container.append(Aligned()); | ||
| 3542 | |||
| 3543 | for (int i = container.firstIndex(); i < container.lastIndex(); ++i) | ||
| 3544 | QVERIFY(container.at(i).checkAligned()); | ||
| 3545 | } | ||
| 3546 | |||
| 3547 | template<typename C> | ||
| 3548 | void testAssociativeContainerAlignment() | ||
| 3549 | { | ||
| 3550 | typedef typename C::key_type Key; | ||
| 3551 | typedef typename C::mapped_type Value; | ||
| 3552 | C container; | ||
| 3553 | container.insert(Key(), Value()); | ||
| 3554 | |||
| 3555 | typename C::const_iterator it = container.constBegin(); | ||
| 3556 | QVERIFY(it.key().checkAligned()); | ||
| 3557 | QVERIFY(it.value().checkAligned()); | ||
| 3558 | |||
| 3559 | // add some more elements | ||
| 3560 | for (int i = 0; i < 200; ++i) | ||
| 3561 | container.insert(Key(i), Value(i)); | ||
| 3562 | |||
| 3563 | it = container.constBegin(); | ||
| 3564 | for ( ; it != container.constEnd(); ++it) { | ||
| 3565 | QVERIFY(it.key().checkAligned()); | ||
| 3566 | QVERIFY(it.value().checkAligned()); | ||
| 3567 | } | ||
| 3568 | } | ||
| 3569 | |||
| 3570 | void tst_Collections::alignment() | ||
| 3571 | { | ||
| 3572 | testVectorAlignment<QVector<Aligned4> >(); | ||
| 3573 | testVectorAlignment<QVector<Aligned128> >(); | ||
| 3574 | testContiguousCacheAlignment<QContiguousCache<Aligned4> >(); | ||
| 3575 | testContiguousCacheAlignment<QContiguousCache<Aligned128> >(); | ||
| 3576 | testAssociativeContainerAlignment<QMap<Aligned4, Aligned4> >(); | ||
| 3577 | testAssociativeContainerAlignment<QMap<Aligned4, Aligned128> >(); | ||
| 3578 | testAssociativeContainerAlignment<QMap<Aligned128, Aligned4> >(); | ||
| 3579 | testAssociativeContainerAlignment<QMap<Aligned128, Aligned128> >(); | ||
| 3580 | testAssociativeContainerAlignment<QHash<Aligned4, Aligned4> >(); | ||
| 3581 | testAssociativeContainerAlignment<QHash<Aligned4, Aligned128> >(); | ||
| 3582 | testAssociativeContainerAlignment<QHash<Aligned128, Aligned4> >(); | ||
| 3583 | testAssociativeContainerAlignment<QHash<Aligned128, Aligned128> >(); | ||
| 3584 | } | ||
| 3585 | |||
| 3586 | #else | ||
| 3587 | void tst_Collections::alignment() | ||
| 3588 | { | ||
| 3589 | QSKIP("Compiler doesn't support necessary extension keywords", SkipAll) | ||
| 3590 | } | ||
| 3591 | #endif | ||
| 3484 | 3592 | ||
| 3485 | 3593 | QTEST_APPLESS_MAIN(tst_Collections) | |
| 3486 | 3594 | #include "tst_collections.moc" |
Comments
Add a new comment:
Login or create an account to post a comment
Add your comment
Please log in to comment

