@@ -474,25 +474,11 @@ using TagVector = __uint128_t;
474
474
constexpr std::size_t kRequiredVectorAlignment =
475
475
constexpr_max (std::size_t {16 }, alignof(max_align_t ));
476
476
477
- struct alignas (kRequiredVectorAlignment ) F14EmptyTagVector {
478
- std::array<uint8_t , sizeof (void *)> tags_{};
479
- FOLLY_CONSTEVAL F14EmptyTagVector () noexcept {
480
- for (auto & t : tags_) {
481
- t = 1 ;
482
- }
483
- }
484
- };
477
+ using EmptyTagVectorType = std::aligned_storage_t <
478
+ sizeof (TagVector) + kRequiredVectorAlignment ,
479
+ alignof (max_align_t )>;
485
480
486
- FOLLY_EXPORT inline F14EmptyTagVector& getF14EmptyTagVector () noexcept {
487
- static constexpr F14EmptyTagVector instance;
488
- auto const raw = reinterpret_cast <uintptr_t >(&instance);
489
- FOLLY_SAFE_DCHECK (
490
- (raw % kRequiredVectorAlignment ) == 0 ,
491
- raw,
492
- " not aligned to " ,
493
- kRequiredVectorAlignment );
494
- return const_cast <F14EmptyTagVector&>(instance);
495
- }
481
+ FOLLY_EXPORT extern EmptyTagVectorType kEmptyTagVector ;
496
482
497
483
template <typename ItemType>
498
484
struct alignas (kRequiredVectorAlignment ) F14Chunk {
@@ -538,14 +524,20 @@ struct alignas(kRequiredVectorAlignment) F14Chunk {
538
524
539
525
std::array<aligned_storage_for_t <Item>, kAllocatedCapacity > rawItems_;
540
526
541
- FOLLY_EXPORT static F14Chunk* getSomeEmptyInstance () noexcept {
542
- return &reinterpret_cast <F14Chunk&>(getF14EmptyTagVector ());
543
- }
544
-
545
- bool isEmptyInstance () const noexcept {
546
- F14EmptyTagVector self;
547
- std::memcpy (&self, this , sizeof (self));
548
- return self.tags_ == F14EmptyTagVector{}.tags_ ;
527
+ static F14Chunk* emptyInstance () {
528
+ auto raw = reinterpret_cast <char *>(&kEmptyTagVector );
529
+ if constexpr (kRequiredVectorAlignment > alignof (max_align_t )) {
530
+ auto delta = kRequiredVectorAlignment -
531
+ (reinterpret_cast <uintptr_t >(raw) % kRequiredVectorAlignment );
532
+ raw += delta;
533
+ }
534
+ auto rv = reinterpret_cast <F14Chunk*>(raw);
535
+ FOLLY_SAFE_DCHECK (
536
+ (reinterpret_cast <uintptr_t >(rv) % kRequiredVectorAlignment ) == 0 ,
537
+ reinterpret_cast <uintptr_t >(rv),
538
+ " not aligned to " ,
539
+ kRequiredVectorAlignment );
540
+ return rv;
549
541
}
550
542
551
543
void clear () {
@@ -585,7 +577,7 @@ struct alignas(kRequiredVectorAlignment) F14Chunk {
585
577
586
578
void setCapacityScale (std::size_t scale) {
587
579
FOLLY_SAFE_DCHECK (
588
- ! isEmptyInstance () && scale > 0 &&
580
+ this != emptyInstance () && scale > 0 &&
589
581
scale < (std::size_t {1 } << kCapacityScaleBits ),
590
582
" " );
591
583
if constexpr (kCapacityScaleBits == 4 ) {
@@ -618,7 +610,8 @@ struct alignas(kRequiredVectorAlignment) F14Chunk {
618
610
std::size_t tag (std::size_t index ) const { return tags_[index ]; }
619
611
620
612
void setTag (std::size_t index , std::size_t tag) {
621
- FOLLY_SAFE_DCHECK (!isEmptyInstance () && tag >= 0x80 && tag <= 0xff , " " );
613
+ FOLLY_SAFE_DCHECK (
614
+ this != emptyInstance () && tag >= 0x80 && tag <= 0xff , " " );
622
615
FOLLY_SAFE_CHECK (tags_[index ] == 0 , " " );
623
616
tags_[index ] = static_cast <uint8_t >(tag);
624
617
}
@@ -741,9 +734,8 @@ struct alignas(kRequiredVectorAlignment) F14Chunk {
741
734
}
742
735
743
736
bool occupied (std::size_t index ) const {
744
- auto const tag = tags_[index ];
745
- FOLLY_SAFE_DCHECK ((tag & ~1 ) == 0 || (tag & 0x80 ) != 0 , " " );
746
- return to_signed (tag) < 0 ;
737
+ FOLLY_SAFE_DCHECK (tags_[index ] == 0 || (tags_[index ] & 0x80 ) != 0 , " " );
738
+ return tags_[index ] != 0 ;
747
739
}
748
740
749
741
Item* itemAddr (std::size_t i) const {
@@ -1243,7 +1235,7 @@ class F14Table : public Policy {
1243
1235
private:
1244
1236
// ////// begin fields
1245
1237
1246
- ChunkPtr chunks_{Chunk::getSomeEmptyInstance ()};
1238
+ ChunkPtr chunks_{Chunk::emptyInstance ()};
1247
1239
SizeAndChunkShiftAndPackedBegin<ItemIter, kEnableItemIteration >
1248
1240
sizeAndChunkShiftAndPackedBegin_;
1249
1241
@@ -2060,8 +2052,7 @@ class F14Table : public Policy {
2060
2052
void initialReserve (std::size_t desiredCapacity) {
2061
2053
FOLLY_SAFE_DCHECK (size () == 0 , " " );
2062
2054
FOLLY_SAFE_DCHECK (chunkShift () == 0 , " " );
2063
- FOLLY_SAFE_DCHECK (!!chunks_);
2064
- FOLLY_SAFE_DCHECK (chunks_->isEmptyInstance (), " " );
2055
+ FOLLY_SAFE_DCHECK (chunks_ == Chunk::emptyInstance (), " " );
2065
2056
if (desiredCapacity == 0 ) {
2066
2057
return ;
2067
2058
}
@@ -2279,8 +2270,7 @@ class F14Table : public Policy {
2279
2270
// We want to support the pattern
2280
2271
// map.reserve(map.size() + 2); auto& r1 = map[k1]; auto& r2 = map[k2];
2281
2272
debugModeOnReserve (capacity);
2282
- FOLLY_SAFE_DCHECK (!!chunks_);
2283
- if (chunks_->isEmptyInstance ()) {
2273
+ if (chunks_ == Chunk::emptyInstance ()) {
2284
2274
initialReserve (capacity);
2285
2275
} else {
2286
2276
reserveImpl (capacity);
@@ -2364,8 +2354,7 @@ class F14Table : public Policy {
2364
2354
private:
2365
2355
template <bool Reset>
2366
2356
void clearImpl () noexcept {
2367
- FOLLY_SAFE_DCHECK (!!chunks_);
2368
- if (chunks_->isEmptyInstance ()) {
2357
+ if (chunks_ == Chunk::emptyInstance ()) {
2369
2358
FOLLY_SAFE_DCHECK (empty () && bucket_count () == 0 , " " );
2370
2359
return ;
2371
2360
}
@@ -2419,7 +2408,7 @@ class F14Table : public Policy {
2419
2408
std::size_t rawSize =
2420
2409
chunkAllocSize (chunkCount (), chunks_->capacityScale ());
2421
2410
2422
- chunks_ = Chunk::getSomeEmptyInstance ();
2411
+ chunks_ = Chunk::emptyInstance ();
2423
2412
sizeAndChunkShiftAndPackedBegin_.setChunkCount (1 );
2424
2413
2425
2414
this ->afterReset (origSize, origCapacity, rawAllocation, rawSize);
@@ -2577,7 +2566,7 @@ class F14Table : public Policy {
2577
2566
}
2578
2567
2579
2568
FOLLY_SAFE_DCHECK (
2580
- (chunks_-> isEmptyInstance ()) == (bucket_count () == 0 ), " " );
2569
+ (chunks_ == Chunk::emptyInstance ()) == (bucket_count () == 0 ), " " );
2581
2570
2582
2571
std::size_t n1 = 0 ;
2583
2572
std::size_t n2 = 0 ;
0 commit comments