Overhaul CapPtr

* Switch to a multidimensional taxonomy.

  Rather than encoding the abstract bound states in a single enum, move to a
  more algebraic treatment.  The dimensions themselves are within the
  snmalloc::capptr_bounds namespace so that their fairly generic names do not
  conflict with consumer code.  Aliases for many points in the space are
  established outside that namespace for ease of use elsewhere.

* Introduce several new namespaces:

    * snmalloc::capptr::dimension holds each of the dimension enums

    * snmalloc::capptr holds the bound<> type itself and a ConceptBound

    * snmalloc::capptr::bounds gives convenient specializations of bound<>

    * snmalloc::capptr also has aliases for CapPtr<> itself

  All told, rather than `CapPtr<T, CBChunk>`, we now expect client code to read
  `capptr::Chunk<T>` in almost all cases (and this is just an alias for the
  appropriate `CapPtr<T, bounds<...>>` type).  When the bound<>s themselves are
  necessary, as when calling capptr_bound, we expect that they will almost
  always be pronounced using an alias (e.g., `capptr::bounds::Alloc`).

* Chase consequences.

* Prune old taxa and aliases that are no longer in use in snmalloc2.
This commit is contained in:
Nathaniel Wesley Filardo
2021-07-19 09:49:18 +01:00
committed by Nathaniel Wesley Filardo
parent b57390663e
commit 9065893181
17 changed files with 399 additions and 348 deletions

View File

@@ -43,7 +43,7 @@ namespace snmalloc
* arena_map for use in subsequent amplification.
*/
template<bool committed, SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap>
CapPtr<void, CBChunk>
capptr::Chunk<void>
reserve(typename Pagemap::LocalState* local_state, size_t size)
{
#ifdef SNMALLOC_TRACING
@@ -62,21 +62,21 @@ namespace snmalloc
{
if (size >= PAL::minimum_alloc_size)
{
auto base = CapPtr<void, CBChunk>(
PAL::template reserve_aligned<committed>(size));
auto base =
capptr::Chunk<void>(PAL::template reserve_aligned<committed>(size));
Pagemap::register_range(local_state, address_cast(base), size);
return base;
}
}
CapPtr<void, CBChunk> res;
capptr::Chunk<void> res;
{
FlagLock lock(spin_lock);
res = core.template reserve<PAL, Pagemap>(local_state, size);
if (res == nullptr)
{
// Allocation failed ask OS for more memory
CapPtr<void, CBChunk> block = nullptr;
capptr::Chunk<void> block = nullptr;
size_t block_size = 0;
if constexpr (pal_supports<AlignedAllocation, PAL>)
{
@@ -92,7 +92,7 @@ namespace snmalloc
// It's a bit of a lie to convert without applying bounds, but the
// platform will have bounded block for us and it's better that
// the rest of our internals expect CBChunk bounds.
block = CapPtr<void, CBChunk>(block_raw);
block = capptr::Chunk<void>(block_raw);
}
else if constexpr (!pal_supports<NoAllocation, PAL>)
{
@@ -110,7 +110,7 @@ namespace snmalloc
size_request >= needed_size;
size_request = size_request / 2)
{
block = CapPtr<void, CBChunk>(PAL::reserve(size_request));
block = capptr::Chunk<void>(PAL::reserve(size_request));
if (block != nullptr)
{
block_size = size_request;
@@ -158,7 +158,7 @@ namespace snmalloc
* used, by smaller objects.
*/
template<bool committed, SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap>
CapPtr<void, CBChunk> reserve_with_left_over(
capptr::Chunk<void> reserve_with_left_over(
typename Pagemap::LocalState* local_state, size_t size)
{
SNMALLOC_ASSERT(size >= sizeof(void*));
@@ -198,7 +198,7 @@ namespace snmalloc
template<SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
void add_range(
typename Pagemap::LocalState* local_state,
CapPtr<void, CBChunk> base,
capptr::Chunk<void> base,
size_t length)
{
FlagLock lock(spin_lock);

View File

@@ -25,7 +25,7 @@ namespace snmalloc
{
struct FreeChunk
{
CapPtr<FreeChunk, CBChunk> next;
capptr::Chunk<FreeChunk> next;
};
/**
@@ -43,12 +43,12 @@ namespace snmalloc
* bits::BITS is used for simplicity, we do not use below the pointer size,
* and large entries will be unlikely to be supported by the platform.
*/
std::array<CapPtr<FreeChunk, CBChunk>, bits::BITS> ranges = {};
std::array<capptr::Chunk<FreeChunk>, bits::BITS> ranges = {};
/**
* Checks a block satisfies its invariant.
*/
inline void check_block(CapPtr<FreeChunk, CBChunk> base, size_t align_bits)
inline void check_block(capptr::Chunk<FreeChunk> base, size_t align_bits)
{
SNMALLOC_ASSERT(
address_cast(base) ==
@@ -72,8 +72,8 @@ namespace snmalloc
void set_next(
typename Pagemap::LocalState* local_state,
size_t align_bits,
CapPtr<FreeChunk, CBChunk> base,
CapPtr<FreeChunk, CBChunk> next)
capptr::Chunk<FreeChunk> base,
capptr::Chunk<FreeChunk> next)
{
if (align_bits >= MIN_CHUNK_BITS)
{
@@ -102,16 +102,16 @@ namespace snmalloc
* particular size.
*/
template<SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
CapPtr<FreeChunk, CBChunk> get_next(
capptr::Chunk<FreeChunk> get_next(
typename Pagemap::LocalState* local_state,
size_t align_bits,
CapPtr<FreeChunk, CBChunk> base)
capptr::Chunk<FreeChunk> base)
{
if (align_bits >= MIN_CHUNK_BITS)
{
const MetaEntry& t = Pagemap::template get_metaentry<false>(
local_state, address_cast(base));
return CapPtr<FreeChunk, CBChunk>(
return capptr::Chunk<FreeChunk>(
reinterpret_cast<FreeChunk*>(t.get_metaslab()));
}
@@ -127,7 +127,7 @@ namespace snmalloc
void add_block(
typename Pagemap::LocalState* local_state,
size_t align_bits,
CapPtr<FreeChunk, CBChunk> base)
capptr::Chunk<FreeChunk> base)
{
check_block(base, align_bits);
SNMALLOC_ASSERT(align_bits < 64);
@@ -143,10 +143,10 @@ namespace snmalloc
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
CapPtr<void, CBChunk>
capptr::Chunk<void>
remove_block(typename Pagemap::LocalState* local_state, size_t align_bits)
{
CapPtr<FreeChunk, CBChunk> first = ranges[align_bits];
capptr::Chunk<FreeChunk> first = ranges[align_bits];
if (first == nullptr)
{
if (align_bits == (bits::BITS - 1))
@@ -156,7 +156,7 @@ namespace snmalloc
}
// Look for larger block and split up recursively
CapPtr<void, CBChunk> bigger =
capptr::Chunk<void> bigger =
remove_block<PAL, Pagemap>(local_state, align_bits + 1);
if (bigger != nullptr)
{
@@ -174,7 +174,8 @@ namespace snmalloc
add_block<PAL, Pagemap>(
local_state,
align_bits,
Aal::capptr_bound<FreeChunk, CBChunk>(left_over, left_over_size));
Aal::capptr_bound<FreeChunk, capptr::bounds::Chunk>(
left_over, left_over_size));
check_block(left_over.as_static<FreeChunk>(), align_bits);
}
check_block(bigger.as_static<FreeChunk>(), align_bits + 1);
@@ -196,7 +197,7 @@ namespace snmalloc
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
void add_range(
typename Pagemap::LocalState* local_state,
CapPtr<void, CBChunk> base,
capptr::Chunk<void> base,
size_t length)
{
// For start and end that are not chunk sized, we need to
@@ -233,7 +234,7 @@ namespace snmalloc
* Commit a block of memory
*/
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
void commit_block(CapPtr<void, CBChunk> base, size_t size)
void commit_block(capptr::Chunk<void> base, size_t size)
{
// Rounding required for sub-page allocations.
auto page_start = pointer_align_down<OS_PAGE_SIZE, char>(base);
@@ -257,7 +258,7 @@ namespace snmalloc
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
CapPtr<void, CBChunk>
capptr::Chunk<void>
reserve(typename Pagemap::LocalState* local_state, size_t size)
{
#ifdef SNMALLOC_TRACING
@@ -281,7 +282,7 @@ namespace snmalloc
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
CapPtr<void, CBChunk> reserve_with_left_over(
capptr::Chunk<void> reserve_with_left_over(
typename Pagemap::LocalState* local_state, size_t size)
{
SNMALLOC_ASSERT(size >= sizeof(void*));

View File

@@ -39,7 +39,7 @@ namespace snmalloc
* Backend allocator may use guard pages and separate area of
* address space to protect this from corruption.
*/
static CapPtr<void, CBChunk> alloc_meta_data(
static capptr::Chunk<void> alloc_meta_data(
AddressSpaceManager<PAL>& global, LocalState* local_state, size_t size)
{
return reserve<true>(global, local_state, size);
@@ -54,7 +54,7 @@ namespace snmalloc
* (remote, sizeclass, metaslab)
* where metaslab, is the second element of the pair return.
*/
static std::pair<CapPtr<void, CBChunk>, Metaslab*> alloc_chunk(
static std::pair<capptr::Chunk<void>, Metaslab*> alloc_chunk(
AddressSpaceManager<PAL>& global,
LocalState* local_state,
size_t size,
@@ -70,7 +70,7 @@ namespace snmalloc
if (meta == nullptr)
return {nullptr, nullptr};
CapPtr<void, CBChunk> p = reserve<false>(global, local_state, size);
capptr::Chunk<void> p = reserve<false>(global, local_state, size);
#ifdef SNMALLOC_TRACING
std::cout << "Alloc chunk: " << p.unsafe_ptr() << " (" << size << ")"
@@ -98,7 +98,7 @@ namespace snmalloc
* space managers.
*/
template<bool is_meta>
static CapPtr<void, CBChunk> reserve(
static capptr::Chunk<void> reserve(
AddressSpaceManager<PAL>& global, LocalState* local_state, size_t size)
{
#ifdef SNMALLOC_CHECK_CLIENT
@@ -108,7 +108,7 @@ namespace snmalloc
constexpr auto MAX_CACHED_SIZE = LOCAL_CACHE_BLOCK;
#endif
CapPtr<void, CBChunk> p;
capptr::Chunk<void> p;
if ((local_state != nullptr) && (size <= MAX_CACHED_SIZE))
{
#ifdef SNMALLOC_CHECK_CLIENT
@@ -182,8 +182,8 @@ namespace snmalloc
* the range [base, base+full_size]. The first and last slot are not used
* so that the edges can be used for guard pages.
*/
static CapPtr<void, CBChunk>
sub_range(CapPtr<void, CBChunk> base, size_t full_size, size_t sub_size)
static capptr::Chunk<void>
sub_range(capptr::Chunk<void> base, size_t full_size, size_t sub_size)
{
SNMALLOC_ASSERT(bits::is_pow2(full_size));
SNMALLOC_ASSERT(bits::is_pow2(sub_size));
@@ -318,7 +318,7 @@ namespace snmalloc
auto [heap_base, heap_length] =
Pagemap::concretePagemap.init(base, length);
address_space.template add_range<Pagemap>(
local_state, CapPtr<void, CBChunk>(heap_base), heap_length);
local_state, capptr::Chunk<void>(heap_base), heap_length);
}
/**
@@ -332,7 +332,7 @@ namespace snmalloc
* places or with different policies.
*/
template<typename T>
static CapPtr<void, CBChunk>
static capptr::Chunk<void>
alloc_meta_data(LocalState* local_state, size_t size)
{
return AddressSpaceAllocator::alloc_meta_data(
@@ -348,7 +348,7 @@ namespace snmalloc
* (remote, sizeclass, metaslab)
* where metaslab, is the second element of the pair return.
*/
static std::pair<CapPtr<void, CBChunk>, Metaslab*> alloc_chunk(
static std::pair<capptr::Chunk<void>, Metaslab*> alloc_chunk(
LocalState* local_state,
size_t size,
RemoteAllocator* remote,