backend ranges: use Arena bounds throughout

Update the backend concept so that metadata allocations are Arena-bounded.
This commit is contained in:
Nathaniel Wesley Filardo
2022-05-31 15:33:17 +01:00
committed by Nathaniel Filardo
parent a78a16e637
commit 86124ba26c
6 changed files with 28 additions and 25 deletions

View File

@@ -35,10 +35,10 @@ namespace snmalloc
* does not avail itself of this degree of freedom.
*/
template<typename T>
static capptr::Chunk<void>
static capptr::Arena<void>
alloc_meta_data(LocalState* local_state, size_t size)
{
capptr::Chunk<void> p;
capptr::Arena<void> p;
if (local_state != nullptr)
{
p = local_state->get_meta_range().alloc_range_with_leftover(size);
@@ -84,7 +84,7 @@ namespace snmalloc
return {nullptr, nullptr};
}
auto p = local_state.get_object_range()->alloc_range(size);
capptr::Arena<void> p = local_state.get_object_range()->alloc_range(size);
#ifdef SNMALLOC_TRACING
message<1024>("Alloc chunk: {} ({})", p.unsafe_ptr(), size);
@@ -140,13 +140,13 @@ namespace snmalloc
Pagemap::set_metaentry(address_cast(alloc), size, t);
local_state.get_meta_range().dealloc_range(
capptr::Chunk<void>::unsafe_from(&slab_metadata), sizeof(SlabMetadata));
capptr::Arena<void>::unsafe_from(&slab_metadata), sizeof(SlabMetadata));
// On non-CHERI platforms, we don't need to re-derive to get a pointer to
// the chunk. On CHERI platforms this will need to be stored in the
// SlabMetadata or similar.
auto chunk = capptr::Chunk<void>::unsafe_from(alloc.unsafe_ptr());
local_state.get_object_range()->dealloc_range(chunk, size);
auto arena = capptr::Arena<void>::unsafe_from(alloc.unsafe_ptr());
local_state.get_object_range()->dealloc_range(arena, size);
}
template<bool potentially_out_of_range = false>

View File

@@ -78,9 +78,9 @@ namespace snmalloc
// Push memory into the global range.
range_to_pow_2_blocks<MIN_CHUNK_BITS>(
capptr::Chunk<void>::unsafe_from(heap_base),
capptr::Arena<void>::unsafe_from(heap_base),
heap_length,
[&](capptr::Chunk<void> p, size_t sz, bool) {
[&](capptr::Arena<void> p, size_t sz, bool) {
typename LocalState::GlobalR g;
g.dealloc_range(p, sz);
});

View File

@@ -3,7 +3,7 @@
namespace snmalloc
{
template<SNMALLOC_CONCEPT(capptr::ConceptBound) B = capptr::bounds::Chunk>
template<SNMALLOC_CONCEPT(capptr::ConceptBound) B = capptr::bounds::Arena>
class EmptyRange
{
public:

View File

@@ -231,14 +231,14 @@ namespace snmalloc
*/
template<bool exists = MAX_SIZE_BITS != (bits::BITS - 1)>
std::enable_if_t<exists>
parent_dealloc_range(capptr::Chunk<void> base, size_t size)
parent_dealloc_range(capptr::Arena<void> base, size_t size)
{
static_assert(
MAX_SIZE_BITS != (bits::BITS - 1), "Don't set SFINAE parameter");
parent.dealloc_range(base, size);
}
void dealloc_overflow(capptr::Chunk<void> overflow)
void dealloc_overflow(capptr::Arena<void> overflow)
{
if constexpr (MAX_SIZE_BITS != (bits::BITS - 1))
{
@@ -258,19 +258,19 @@ namespace snmalloc
* Add a range of memory to the address space.
* Divides blocks into power of two sizes with natural alignment
*/
void add_range(capptr::Chunk<void> base, size_t length)
void add_range(capptr::Arena<void> base, size_t length)
{
range_to_pow_2_blocks<MIN_CHUNK_BITS>(
base, length, [this](capptr::Chunk<void> base, size_t align, bool) {
base, length, [this](capptr::Arena<void> base, size_t align, bool) {
auto overflow =
capptr::Chunk<void>::unsafe_from(reinterpret_cast<void*>(
capptr::Arena<void>::unsafe_from(reinterpret_cast<void*>(
buddy_large.add_block(base.unsafe_uintptr(), align)));
dealloc_overflow(overflow);
});
}
capptr::Chunk<void> refill(size_t size)
capptr::Arena<void> refill(size_t size)
{
if (ParentRange::Aligned)
{
@@ -342,11 +342,14 @@ namespace snmalloc
static constexpr bool ConcurrencySafe = false;
using ChunkBounds = capptr::bounds::Chunk;
/* The large buddy allocator always deals in Arena-bounded pointers. */
using ChunkBounds = capptr::bounds::Arena;
static_assert(
std::is_same_v<typename ParentRange::ChunkBounds, ChunkBounds>);
constexpr Type() = default;
capptr::Chunk<void> alloc_range(size_t size)
capptr::Arena<void> alloc_range(size_t size)
{
SNMALLOC_ASSERT(size >= MIN_CHUNK_SIZE);
SNMALLOC_ASSERT(bits::is_pow2(size));
@@ -359,7 +362,7 @@ namespace snmalloc
return nullptr;
}
auto result = capptr::Chunk<void>::unsafe_from(
auto result = capptr::Arena<void>::unsafe_from(
reinterpret_cast<void*>(buddy_large.remove_block(size)));
if (result != nullptr)
@@ -368,7 +371,7 @@ namespace snmalloc
return refill(size);
}
void dealloc_range(capptr::Chunk<void> base, size_t size)
void dealloc_range(capptr::Arena<void> base, size_t size)
{
SNMALLOC_ASSERT(size >= MIN_CHUNK_SIZE);
SNMALLOC_ASSERT(bits::is_pow2(size));
@@ -383,7 +386,7 @@ namespace snmalloc
}
auto overflow =
capptr::Chunk<void>::unsafe_from(reinterpret_cast<void*>(
capptr::Arena<void>::unsafe_from(reinterpret_cast<void*>(
buddy_large.add_block(base.unsafe_uintptr(), size)));
dealloc_overflow(overflow);
}

View File

@@ -14,11 +14,11 @@ namespace snmalloc
// need to be changed.
static constexpr bool ConcurrencySafe = true;
using ChunkBounds = capptr::bounds::Chunk;
using ChunkBounds = capptr::bounds::Arena;
constexpr PalRange() = default;
capptr::Chunk<void> alloc_range(size_t size)
capptr::Arena<void> alloc_range(size_t size)
{
if (bits::next_pow2_bits(size) >= bits::BITS - 1)
{
@@ -28,7 +28,7 @@ namespace snmalloc
if constexpr (pal_supports<AlignedAllocation, PAL>)
{
SNMALLOC_ASSERT(size >= PAL::minimum_alloc_size);
auto result = capptr::Chunk<void>::unsafe_from(
auto result = capptr::Arena<void>::unsafe_from(
PAL::template reserve_aligned<false>(size));
#ifdef SNMALLOC_TRACING
@@ -38,7 +38,7 @@ namespace snmalloc
}
else
{
auto result = capptr::Chunk<void>::unsafe_from(PAL::reserve(size));
auto result = capptr::Arena<void>::unsafe_from(PAL::reserve(size));
#ifdef SNMALLOC_TRACING
message<1024>("Pal range alloc: {} ({})", result.unsafe_ptr(), size);

View File

@@ -122,7 +122,7 @@ namespace snmalloc
{
Backend::template alloc_meta_data<void*>(local_state, size)
}
->ConceptSame<capptr::Chunk<void>>;
->ConceptSame<capptr::Arena<void>>;
}
&&requires(
LocalState& local_state,