@@ -27,6 +27,9 @@ namespace cachelib {
2727
2828class SlabAllocator ;
2929
30+ template <typename PtrType, typename AllocatorContainer>
31+ class PtrCompressor ;
32+
3033// the following are for pointer compression for the memory allocator. We
3134// compress pointers by storing the slab index and the alloc index of the
3235// allocation inside the slab. With slab worth kNumSlabBits of data, if we
@@ -41,7 +44,7 @@ class SlabAllocator;
4144// decompress a CompressedPtr than compress a pointer while creating one.
4245class CACHELIB_PACKED_ATTR CompressedPtr {
4346 public:
44- using PtrType = uint32_t ;
47+ using PtrType = uint64_t ;
4548 // Thrift doesn't support unsigned type
4649 using SerializedPtrType = int64_t ;
4750
@@ -83,14 +86,14 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
8386 private:
8487 // null pointer representation. This is almost never guaranteed to be a
8588 // valid pointer that we can compress to.
86- static constexpr PtrType kNull = 0xffffffff ;
89+ static constexpr PtrType kNull = 0x00000000ffffffff ;
8790
8891 // default construct to null.
8992 PtrType ptr_{kNull };
9093
9194 // create a compressed pointer for a valid memory allocation.
92- CompressedPtr (uint32_t slabIdx, uint32_t allocIdx)
93- : ptr_(compress(slabIdx, allocIdx)) {}
95+ CompressedPtr (uint32_t slabIdx, uint32_t allocIdx, TierId tid = 0 )
96+ : ptr_(compress(slabIdx, allocIdx, tid )) {}
9497
9598 constexpr explicit CompressedPtr (PtrType ptr) noexcept : ptr_{ptr} {}
9699
@@ -100,40 +103,60 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
100103 static constexpr unsigned int kNumAllocIdxBits =
101104 Slab::kNumSlabBits - Slab::kMinAllocPower ;
102105
106+ // Use topmost 32 bits for TierId
107+ // XXX: optimize
108+ static constexpr unsigned int kNumTierIdxOffset = 32 ;
109+
103110 static constexpr PtrType kAllocIdxMask = ((PtrType)1 << kNumAllocIdxBits ) - 1 ;
104111
112+ // kNumTierIdxBits most significant bits
113+ static constexpr PtrType kTierIdxMask = (((PtrType)1 << kNumTierIdxOffset ) - 1 ) << (NumBits<PtrType>::value - kNumTierIdxOffset );
114+
105115 // Number of bits for the slab index. This will be the top 16 bits of the
106116 // compressed ptr.
107117 static constexpr unsigned int kNumSlabIdxBits =
108- NumBits<PtrType>::value - kNumAllocIdxBits ;
118+ NumBits<PtrType>::value - kNumTierIdxOffset - kNumAllocIdxBits ;
109119
110- // Compress the given slabIdx and allocIdx into a 32 -bit compressed
120+ // Compress the given slabIdx and allocIdx into a 64 -bit compressed
111121 // pointer.
112- static PtrType compress (uint32_t slabIdx, uint32_t allocIdx) noexcept {
122+ static PtrType compress (uint32_t slabIdx, uint32_t allocIdx, TierId tid ) noexcept {
113123 XDCHECK_LE (allocIdx, kAllocIdxMask );
114124 XDCHECK_LT (slabIdx, (1u << kNumSlabIdxBits ) - 1 );
115- return (slabIdx << kNumAllocIdxBits ) + allocIdx;
125+ return (static_cast < uint64_t >(tid) << kNumTierIdxOffset ) + ( slabIdx << kNumAllocIdxBits ) + allocIdx;
116126 }
117127
118128 // Get the slab index of the compressed ptr
119129 uint32_t getSlabIdx () const noexcept {
120130 XDCHECK (!isNull ());
121- return static_cast <uint32_t >(ptr_ >> kNumAllocIdxBits );
131+ auto noTierIdPtr = ptr_ & ~kTierIdxMask ;
132+ return static_cast <uint32_t >(noTierIdPtr >> kNumAllocIdxBits );
122133 }
123134
124135 // Get the allocation index of the compressed ptr
125136 uint32_t getAllocIdx () const noexcept {
126137 XDCHECK (!isNull ());
127- return static_cast <uint32_t >(ptr_ & kAllocIdxMask );
138+ auto noTierIdPtr = ptr_ & ~kTierIdxMask ;
139+ return static_cast <uint32_t >(noTierIdPtr & kAllocIdxMask );
140+ }
141+
142+ uint32_t getTierId () const noexcept {
143+ XDCHECK (!isNull ());
144+ return static_cast <uint32_t >(ptr_ >> kNumTierIdxOffset );
145+ }
146+
147+ void setTierId (TierId tid) noexcept {
148+ ptr_ += static_cast <uint64_t >(tid) << kNumTierIdxOffset ;
128149 }
129150
130151 friend SlabAllocator;
152+ template <typename CPtrType, typename AllocatorContainer>
153+ friend class PtrCompressor ;
131154};
132155
133156template <typename PtrType, typename AllocatorT>
134- class PtrCompressor {
157+ class SingleTierPtrCompressor {
135158 public:
136- explicit PtrCompressor (const AllocatorT& allocator) noexcept
159+ explicit SingleTierPtrCompressor (const AllocatorT& allocator) noexcept
137160 : allocator_(allocator) {}
138161
139162 const CompressedPtr compress (const PtrType* uncompressed) const {
@@ -144,17 +167,61 @@ class PtrCompressor {
144167 return static_cast <PtrType*>(allocator_.unCompress (compressed));
145168 }
146169
147- bool operator ==(const PtrCompressor & rhs) const noexcept {
170+ bool operator ==(const SingleTierPtrCompressor & rhs) const noexcept {
148171 return &allocator_ == &rhs.allocator_ ;
149172 }
150173
151- bool operator !=(const PtrCompressor & rhs) const noexcept {
174+ bool operator !=(const SingleTierPtrCompressor & rhs) const noexcept {
152175 return !(*this == rhs);
153176 }
154177
155178 private:
156179 // memory allocator that does the pointer compression.
157180 const AllocatorT& allocator_;
158181};
182+
183+ template <typename PtrType, typename AllocatorContainer>
184+ class PtrCompressor {
185+ public:
186+ explicit PtrCompressor (const AllocatorContainer& allocators) noexcept
187+ : allocators_(allocators) {}
188+
189+ const CompressedPtr compress (const PtrType* uncompressed) const {
190+ if (uncompressed == nullptr )
191+ return CompressedPtr{};
192+
193+ TierId tid;
194+ for (tid = 0 ; tid < allocators_.size (); tid++) {
195+ if (allocators_[tid]->isMemoryInAllocator (static_cast <const void *>(uncompressed)))
196+ break ;
197+ }
198+
199+ auto cptr = allocators_[tid]->compress (uncompressed);
200+ cptr.setTierId (tid);
201+
202+ return cptr;
203+ }
204+
205+ PtrType* unCompress (const CompressedPtr compressed) const {
206+ if (compressed.isNull ()) {
207+ return nullptr ;
208+ }
209+
210+ auto &allocator = *allocators_[compressed.getTierId ()];
211+ return static_cast <PtrType*>(allocator.unCompress (compressed));
212+ }
213+
214+ bool operator ==(const PtrCompressor& rhs) const noexcept {
215+ return &allocators_ == &rhs.allocators_ ;
216+ }
217+
218+ bool operator !=(const PtrCompressor& rhs) const noexcept {
219+ return !(*this == rhs);
220+ }
221+
222+ private:
223+ // memory allocator that does the pointer compression.
224+ const AllocatorContainer& allocators_;
225+ };
159226} // namespace cachelib
160227} // namespace facebook
0 commit comments