#include "partition_alloc/thread_cache.h"
#include <algorithm>
#include <atomic>
#include <vector>
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/extended_api.h"
#include "partition_alloc/internal_allocator.h"
#include "partition_alloc/partition_address_space.h"
#include "partition_alloc/partition_alloc_base/thread_annotations.h"
#include "partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h"
#include "partition_alloc/partition_alloc_config.h"
#include "partition_alloc/partition_alloc_for_testing.h"
#include "partition_alloc/partition_freelist_entry.h"
#include "partition_alloc/partition_lock.h"
#include "partition_alloc/partition_root.h"
#include "partition_alloc/tagging.h"
#include "testing/gtest/include/gtest/gtest.h"
#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && \
PA_CONFIG(THREAD_CACHE_SUPPORTED)
namespace partition_alloc {
BucketDistribution;
PartitionFreelistEncoding;
struct ThreadCacheTestParam { … };
const std::vector<ThreadCacheTestParam> params = …;
namespace {
constexpr size_t kSmallSize = …;
constexpr size_t kDefaultCountForSmallBucket = …;
constexpr size_t kFillCountForSmallBucket = …;
constexpr size_t kMediumSize = …;
constexpr size_t kDefaultCountForMediumBucket = …;
constexpr size_t kFillCountForMediumBucket = …;
static_assert …;
class DeltaCounter { … };
std::unique_ptr<PartitionAllocatorForTesting> CreateAllocator(
internal::PartitionFreelistEncoding encoding =
internal::PartitionFreelistEncoding::kEncodedFreeList) { … }
}
class PartitionAllocThreadCacheTest
: public ::testing::TestWithParam<ThreadCacheTestParam> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(PartitionAllocThreadCacheTest, Simple) { … }
TEST_P(PartitionAllocThreadCacheTest, InexactSizeMatch) { … }
TEST_P(PartitionAllocThreadCacheTest, MultipleObjectsCachedPerBucket) { … }
TEST_P(PartitionAllocThreadCacheTest, ObjectsCachedCountIsLimited) { … }
TEST_P(PartitionAllocThreadCacheTest, Purge) { … }
TEST_P(PartitionAllocThreadCacheTest, NoCrossPartitionCache) { … }
#if PA_CONFIG(THREAD_CACHE_ENABLE_STATISTICS)
TEST_P(PartitionAllocThreadCacheTest, LargeAllocationsAreNotCached) { … }
#endif
TEST_P(PartitionAllocThreadCacheTest, DirectMappedAllocationsAreNotCached) { … }
TEST_P(PartitionAllocThreadCacheTest, DirectMappedReallocMetrics) { … }
namespace {
size_t FillThreadCacheAndReturnIndex(PartitionRoot* root,
size_t size,
BucketDistribution bucket_distribution,
size_t count = 1) { … }
class ThreadDelegateForMultipleThreadCaches
: public internal::base::PlatformThreadForTesting::Delegate { … };
}
TEST_P(PartitionAllocThreadCacheTest, MultipleThreadCaches) { … }
namespace {
class ThreadDelegateForThreadCacheReclaimedWhenThreadExits
: public internal::base::PlatformThreadForTesting::Delegate { … };
}
TEST_P(PartitionAllocThreadCacheTest, ThreadCacheReclaimedWhenThreadExits) { … }
namespace {
class ThreadDelegateForThreadCacheRegistry
: public internal::base::PlatformThreadForTesting::Delegate { … };
}
TEST_P(PartitionAllocThreadCacheTest, ThreadCacheRegistry) { … }
#if PA_CONFIG(THREAD_CACHE_ENABLE_STATISTICS)
TEST_P(PartitionAllocThreadCacheTest, RecordStats) { … }
namespace {
class ThreadDelegateForMultipleThreadCachesAccounting
: public internal::base::PlatformThreadForTesting::Delegate { … };
}
TEST_P(PartitionAllocThreadCacheTest, MultipleThreadCachesAccounting) { … }
#endif
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_PurgeAll …
#else
#define MAYBE_PurgeAll …
#endif
namespace {
class ThreadDelegateForPurgeAll
: public internal::base::PlatformThreadForTesting::Delegate { … };
}
TEST_P(PartitionAllocThreadCacheTest, MAYBE_PurgeAll)
PA_NO_THREAD_SAFETY_ANALYSIS { … }
TEST_P(PartitionAllocThreadCacheTest, PeriodicPurge) { … }
namespace {
void FillThreadCacheWithMemory(PartitionRoot* root,
size_t target_cached_memory,
BucketDistribution bucket_distribution) { … }
class ThreadDelegateForPeriodicPurgeSumsOverAllThreads
: public internal::base::PlatformThreadForTesting::Delegate { … };
}
TEST_P(PartitionAllocThreadCacheTest,
DISABLED_PeriodicPurgeSumsOverAllThreads) { … }
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_DynamicCountPerBucket …
#else
#define MAYBE_DynamicCountPerBucket …
#endif
TEST_P(PartitionAllocThreadCacheTest, MAYBE_DynamicCountPerBucket) { … }
TEST_P(PartitionAllocThreadCacheTest, DynamicCountPerBucketClamping) { … }
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_DynamicCountPerBucketMultipleThreads …
#else
#define MAYBE_DynamicCountPerBucketMultipleThreads …
#endif
namespace {
class ThreadDelegateForDynamicCountPerBucketMultipleThreads
: public internal::base::PlatformThreadForTesting::Delegate { … };
}
TEST_P(PartitionAllocThreadCacheTest,
MAYBE_DynamicCountPerBucketMultipleThreads) { … }
TEST_P(PartitionAllocThreadCacheTest, DynamicSizeThreshold) { … }
TEST_P(PartitionAllocThreadCacheTest, DISABLED_DynamicSizeThresholdPurge) { … }
TEST_P(PartitionAllocThreadCacheTest, ClearFromTail) { … }
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_Bookkeeping …
#else
#define MAYBE_Bookkeeping …
#endif
TEST_P(PartitionAllocThreadCacheTest, MAYBE_Bookkeeping) { … }
TEST_P(PartitionAllocThreadCacheTest, TryPurgeNoAllocs) { … }
TEST_P(PartitionAllocThreadCacheTest, TryPurgeMultipleCorrupted) { … }
TEST(AlternateBucketDistributionTest, SizeToIndex) { … }
TEST_P(PartitionAllocThreadCacheTest, AllocationRecording) { … }
TEST_P(PartitionAllocThreadCacheTest, AllocationRecordingAligned) { … }
TEST_P(PartitionAllocThreadCacheTest, AllocationRecordingRealloc) { … }
TEST(AlternateBucketDistributionTest, SwitchBeforeAlloc) { … }
TEST(AlternateBucketDistributionTest, SwitchAfterAlloc) { … }
}
#endif