1313#include " bytemap.h"
1414#include " common.h"
1515#include " list.h"
16- #include " local_cache.h"
1716#include " options.h"
1817#include " release.h"
1918#include " report.h"
19+ #include " size_class_allocator.h"
2020#include " stats.h"
2121#include " string_utils.h"
2222#include " thread_annotations.h"
@@ -52,7 +52,10 @@ template <typename Config> class SizeClassAllocator32 {
5252 static_assert ((1UL << Config::getRegionSizeLog()) >= SizeClassMap::MaxSize,
5353 "");
5454 typedef SizeClassAllocator32<Config> ThisT;
55- typedef SizeClassAllocatorLocalCache<ThisT> CacheT;
55+ using SizeClassAllocatorT =
56+ typename Conditional<Config::getEnableBlockCache(),
57+ SizeClassAllocatorLocalCache<ThisT>,
58+ SizeClassAllocatorNoCache<ThisT>>::type;
5659 typedef TransferBatch<ThisT> TransferBatchT;
5760 typedef BatchGroup<ThisT> BatchGroupT;
5861
@@ -191,25 +194,28 @@ template <typename Config> class SizeClassAllocator32 {
191194 return BlockSize > PageSize;
192195 }
193196
194- u16 popBlocks (CacheT *C , uptr ClassId, CompactPtrT *ToArray ,
195- const u16 MaxBlockCount) {
197+ u16 popBlocks (SizeClassAllocatorT *SizeClassAllocator , uptr ClassId,
198+ CompactPtrT *ToArray, const u16 MaxBlockCount) {
196199 DCHECK_LT (ClassId, NumClasses);
197200 SizeClassInfo *Sci = getSizeClassInfo (ClassId);
198201 ScopedLock L (Sci->Mutex );
199202
200- u16 PopCount = popBlocksImpl (C, ClassId, Sci, ToArray, MaxBlockCount);
203+ u16 PopCount =
204+ popBlocksImpl (SizeClassAllocator, ClassId, Sci, ToArray, MaxBlockCount);
201205 if (UNLIKELY (PopCount == 0 )) {
202- if (UNLIKELY (!populateFreeList (C , ClassId, Sci)))
206+ if (UNLIKELY (!populateFreeList (SizeClassAllocator , ClassId, Sci)))
203207 return 0U ;
204- PopCount = popBlocksImpl (C, ClassId, Sci, ToArray, MaxBlockCount);
208+ PopCount = popBlocksImpl (SizeClassAllocator, ClassId, Sci, ToArray,
209+ MaxBlockCount);
205210 DCHECK_NE (PopCount, 0U );
206211 }
207212
208213 return PopCount;
209214 }
210215
211216 // Push the array of free blocks to the designated batch group.
212- void pushBlocks (CacheT *C, uptr ClassId, CompactPtrT *Array, u32 Size) {
217+ void pushBlocks (SizeClassAllocatorT *SizeClassAllocator, uptr ClassId,
218+ CompactPtrT *Array, u32 Size) {
213219 DCHECK_LT (ClassId, NumClasses);
214220 DCHECK_GT (Size, 0 );
215221
@@ -240,7 +246,7 @@ template <typename Config> class SizeClassAllocator32 {
240246 }
241247
242248 ScopedLock L (Sci->Mutex );
243- pushBlocksImpl (C , ClassId, Sci, Array, Size, SameGroup);
249+ pushBlocksImpl (SizeClassAllocator , ClassId, Sci, Array, Size, SameGroup);
244250 }
245251
246252 void disable () NO_THREAD_SAFETY_ANALYSIS {
@@ -529,8 +535,8 @@ template <typename Config> class SizeClassAllocator32 {
529535 // memory group here.
530536 BG->CompactPtrGroupBase = 0 ;
531537 BG->BytesInBGAtLastCheckpoint = 0 ;
532- BG->MaxCachedPerBatch =
533- CacheT::getMaxCached ( getSizeByClassId (SizeClassMap::BatchClassId));
538+ BG->MaxCachedPerBatch = SizeClassAllocatorT::getMaxCached (
539+ getSizeByClassId (SizeClassMap::BatchClassId));
534540
535541 Sci->FreeListInfo .BlockList .push_front (BG);
536542 }
@@ -597,18 +603,18 @@ template <typename Config> class SizeClassAllocator32 {
597603 // same group then we will skip checking the group id of each block.
598604 //
599605 // The region mutex needs to be held while calling this method.
600- void pushBlocksImpl (CacheT *C , uptr ClassId, SizeClassInfo *Sci ,
601- CompactPtrT *Array, u32 Size, bool SameGroup = false )
602- REQUIRES(Sci->Mutex) {
606+ void pushBlocksImpl (SizeClassAllocatorT *SizeClassAllocator , uptr ClassId,
607+ SizeClassInfo *Sci, CompactPtrT *Array, u32 Size,
608+ bool SameGroup = false ) REQUIRES(Sci->Mutex) {
603609 DCHECK_NE (ClassId, SizeClassMap::BatchClassId);
604610 DCHECK_GT (Size, 0U );
605611
606612 auto CreateGroup = [&](uptr CompactPtrGroupBase) {
607- BatchGroupT *BG =
608- reinterpret_cast <BatchGroupT *>(C ->getBatchClassBlock ());
613+ BatchGroupT *BG = reinterpret_cast <BatchGroupT *>(
614+ SizeClassAllocator ->getBatchClassBlock ());
609615 BG->Batches .clear ();
610- TransferBatchT *TB =
611- reinterpret_cast <TransferBatchT *>(C ->getBatchClassBlock ());
616+ TransferBatchT *TB = reinterpret_cast <TransferBatchT *>(
617+ SizeClassAllocator ->getBatchClassBlock ());
612618 TB->clear ();
613619
614620 BG->CompactPtrGroupBase = CompactPtrGroupBase;
@@ -629,8 +635,8 @@ template <typename Config> class SizeClassAllocator32 {
629635 u16 UnusedSlots =
630636 static_cast <u16 >(BG->MaxCachedPerBatch - CurBatch->getCount ());
631637 if (UnusedSlots == 0 ) {
632- CurBatch =
633- reinterpret_cast <TransferBatchT *>(C ->getBatchClassBlock ());
638+ CurBatch = reinterpret_cast <TransferBatchT *>(
639+ SizeClassAllocator ->getBatchClassBlock ());
634640 CurBatch->clear ();
635641 Batches.push_front (CurBatch);
636642 UnusedSlots = BG->MaxCachedPerBatch ;
@@ -704,9 +710,9 @@ template <typename Config> class SizeClassAllocator32 {
704710 InsertBlocks (Cur, Array + Size - Count, Count);
705711 }
706712
707- u16 popBlocksImpl (CacheT *C , uptr ClassId, SizeClassInfo *Sci ,
708- CompactPtrT *ToArray, const u16 MaxBlockCount)
709- REQUIRES(Sci->Mutex) {
713+ u16 popBlocksImpl (SizeClassAllocatorT *SizeClassAllocator , uptr ClassId,
714+ SizeClassInfo *Sci, CompactPtrT *ToArray,
715+ const u16 MaxBlockCount) REQUIRES(Sci->Mutex) {
710716 if (Sci->FreeListInfo .BlockList .empty ())
711717 return 0U ;
712718
@@ -730,11 +736,11 @@ template <typename Config> class SizeClassAllocator32 {
730736 // So far, instead of always filling the blocks to `MaxBlockCount`, we only
731737 // examine single `TransferBatch` to minimize the time spent on the primary
732738 // allocator. Besides, the sizes of `TransferBatch` and
733- // `CacheT ::getMaxCached()` may also impact the time spent on accessing the
734- // primary allocator.
739+ // `SizeClassAllocatorT ::getMaxCached()` may also impact the time spent on
740+ // accessing the primary allocator.
735741 // TODO(chiahungduan): Evaluate if we want to always prepare `MaxBlockCount`
736742 // blocks and/or adjust the size of `TransferBatch` according to
737- // `CacheT ::getMaxCached()`.
743+ // `SizeClassAllocatorT ::getMaxCached()`.
738744 TransferBatchT *B = Batches.front ();
739745 DCHECK_NE (B, nullptr );
740746 DCHECK_GT (B->getCount (), 0U );
@@ -754,7 +760,7 @@ template <typename Config> class SizeClassAllocator32 {
754760 // deallocate. Read the comment in `pushBatchClassBlocks()` for more
755761 // details.
756762 if (ClassId != SizeClassMap::BatchClassId)
757- C ->deallocate (SizeClassMap::BatchClassId, B);
763+ SizeClassAllocator ->deallocate (SizeClassMap::BatchClassId, B);
758764
759765 if (Batches.empty ()) {
760766 BatchGroupT *BG = Sci->FreeListInfo .BlockList .front ();
@@ -766,15 +772,16 @@ template <typename Config> class SizeClassAllocator32 {
766772 // Which means, once we pop the last TransferBatch, the block is
767773 // implicitly deallocated.
768774 if (ClassId != SizeClassMap::BatchClassId)
769- C ->deallocate (SizeClassMap::BatchClassId, BG);
775+ SizeClassAllocator ->deallocate (SizeClassMap::BatchClassId, BG);
770776 }
771777 }
772778
773779 Sci->FreeListInfo .PoppedBlocks += PopCount;
774780 return PopCount;
775781 }
776782
777- NOINLINE bool populateFreeList (CacheT *C, uptr ClassId, SizeClassInfo *Sci)
783+ NOINLINE bool populateFreeList (SizeClassAllocatorT *SizeClassAllocator,
784+ uptr ClassId, SizeClassInfo *Sci)
778785 REQUIRES(Sci->Mutex) {
779786 uptr Region;
780787 uptr Offset;
@@ -791,13 +798,13 @@ template <typename Config> class SizeClassAllocator32 {
791798 Region = allocateRegion (Sci, ClassId);
792799 if (UNLIKELY (!Region))
793800 return false ;
794- C ->getStats ().add (StatMapped, RegionSize);
801+ SizeClassAllocator ->getStats ().add (StatMapped, RegionSize);
795802 Sci->CurrentRegion = Region;
796803 Offset = 0 ;
797804 }
798805
799806 const uptr Size = getSizeByClassId (ClassId);
800- const u16 MaxCount = CacheT ::getMaxCached (Size);
807+ const u16 MaxCount = SizeClassAllocatorT ::getMaxCached (Size);
801808 DCHECK_GT (MaxCount, 0U );
802809 // The maximum number of blocks we should carve in the region is dictated
803810 // by the maximum number of batches we want to fill, and the amount of
@@ -827,7 +834,8 @@ template <typename Config> class SizeClassAllocator32 {
827834 for (u32 I = 1 ; I < NumberOfBlocks; I++) {
828835 if (UNLIKELY (compactPtrGroupBase (ShuffleArray[I]) != CurGroup)) {
829836 shuffle (ShuffleArray + I - N, N, &Sci->RandState );
830- pushBlocksImpl (C, ClassId, Sci, ShuffleArray + I - N, N,
837+ pushBlocksImpl (SizeClassAllocator, ClassId, Sci, ShuffleArray + I - N,
838+ N,
831839 /* SameGroup=*/ true );
832840 N = 1 ;
833841 CurGroup = compactPtrGroupBase (ShuffleArray[I]);
@@ -837,7 +845,8 @@ template <typename Config> class SizeClassAllocator32 {
837845 }
838846
839847 shuffle (ShuffleArray + NumberOfBlocks - N, N, &Sci->RandState );
840- pushBlocksImpl (C, ClassId, Sci, &ShuffleArray[NumberOfBlocks - N], N,
848+ pushBlocksImpl (SizeClassAllocator, ClassId, Sci,
849+ &ShuffleArray[NumberOfBlocks - N], N,
841850 /* SameGroup=*/ true );
842851 } else {
843852 pushBatchClassBlocks (Sci, ShuffleArray, NumberOfBlocks);
@@ -850,7 +859,7 @@ template <typename Config> class SizeClassAllocator32 {
850859 Sci->FreeListInfo .PushedBlocks -= NumberOfBlocks;
851860
852861 const uptr AllocatedUser = Size * NumberOfBlocks;
853- C ->getStats ().add (StatFree, AllocatedUser);
862+ SizeClassAllocator ->getStats ().add (StatFree, AllocatedUser);
854863 DCHECK_LE (Sci->CurrentRegionAllocated + AllocatedUser, RegionSize);
855864 // If there is not enough room in the region currently associated to fit
856865 // more blocks, we deassociate the region by resetting CurrentRegion and
0 commit comments