NFC: Generalize smallbuddyrange bounds annotations

Make these generic, with the SmallBuddyRange taking its cue from the parent
Range, since we're about to change them anyway and might want to vary them again
in the future.
This commit is contained in:
Nathaniel Wesley Filardo
2022-06-06 23:39:46 +01:00
committed by Nathaniel Filardo
parent f41bb321f7
commit aa61b59a8f

View File

@@ -10,20 +10,22 @@ namespace snmalloc
* struct for representing the redblack nodes
* directly inside the meta data.
*/
template<SNMALLOC_CONCEPT(capptr::ConceptBound) bounds>
struct FreeChunk
{
capptr::Chunk<FreeChunk> left;
capptr::Chunk<FreeChunk> right;
CapPtr<FreeChunk, bounds> left;
CapPtr<FreeChunk, bounds> right;
};
/**
* Class for using the allocations own space to store in the RBTree.
*/
template<SNMALLOC_CONCEPT(capptr::ConceptBound) bounds>
class BuddyInplaceRep
{
public:
using Handle = capptr::Chunk<FreeChunk>*;
using Contents = capptr::Chunk<FreeChunk>;
using Handle = CapPtr<FreeChunk<bounds>, bounds>*;
using Contents = CapPtr<FreeChunk<bounds>, bounds>;
static constexpr Contents null = nullptr;
static constexpr Contents root = nullptr;
@@ -33,17 +35,17 @@ namespace snmalloc
{
SNMALLOC_ASSERT((address_cast(r) & MASK) == 0);
if (r == nullptr)
*ptr = capptr::Chunk<FreeChunk>::unsafe_from(
reinterpret_cast<FreeChunk*>((*ptr).unsafe_uintptr() & MASK));
*ptr = CapPtr<FreeChunk<bounds>, bounds>::unsafe_from(
reinterpret_cast<FreeChunk<bounds>*>((*ptr).unsafe_uintptr() & MASK));
else
// Preserve lower bit.
*ptr = pointer_offset(r, (address_cast(*ptr) & MASK))
.template as_static<FreeChunk>();
.template as_static<FreeChunk<bounds>>();
}
static Contents get(Handle ptr)
{
return pointer_align_down<2, FreeChunk>((*ptr).as_void());
return pointer_align_down<2, FreeChunk<bounds>>((*ptr).as_void());
}
static Handle ref(bool direction, Contents r)
@@ -66,15 +68,16 @@ namespace snmalloc
if (new_is_red != is_red(k))
{
auto r = ref(false, k);
auto old_addr = pointer_align_down<2, FreeChunk>(r->as_void());
auto old_addr = pointer_align_down<2, FreeChunk<bounds>>(r->as_void());
if (new_is_red)
{
if (old_addr == nullptr)
*r = capptr::Chunk<FreeChunk>::unsafe_from(
reinterpret_cast<FreeChunk*>(MASK));
*r = CapPtr<FreeChunk<bounds>, bounds>::unsafe_from(
reinterpret_cast<FreeChunk<bounds>*>(MASK));
else
*r = pointer_offset(old_addr, MASK).template as_static<FreeChunk>();
*r = pointer_offset(old_addr, MASK)
.template as_static<FreeChunk<bounds>>();
}
else
{
@@ -86,21 +89,22 @@ namespace snmalloc
static Contents offset(Contents k, size_t size)
{
return pointer_offset(k, size).template as_static<FreeChunk>();
return pointer_offset(k, size).template as_static<FreeChunk<bounds>>();
}
static Contents buddy(Contents k, size_t size)
{
// This is just doing xor size, but with what API
// exists on capptr.
auto base = pointer_align_down<FreeChunk>(k.as_void(), size * 2);
auto base = pointer_align_down<FreeChunk<bounds>>(k.as_void(), size * 2);
auto offset = (address_cast(k) & size) ^ size;
return pointer_offset(base, offset).template as_static<FreeChunk>();
return pointer_offset(base, offset)
.template as_static<FreeChunk<bounds>>();
}
static Contents align_down(Contents k, size_t size)
{
return pointer_align_down<FreeChunk>(k.as_void(), size);
return pointer_align_down<FreeChunk<bounds>>(k.as_void(), size);
}
static bool compare(Contents k1, Contents k2)
@@ -149,30 +153,38 @@ namespace snmalloc
template<typename ParentRange = EmptyRange<>>
class Type : public ContainsParent<ParentRange>
{
public:
using ChunkBounds = typename ParentRange::ChunkBounds;
private:
using ContainsParent<ParentRange>::parent;
static constexpr size_t MIN_BITS =
bits::next_pow2_bits_const(sizeof(FreeChunk));
bits::next_pow2_bits_const(sizeof(FreeChunk<ChunkBounds>));
Buddy<BuddyInplaceRep, MIN_BITS, MIN_CHUNK_BITS> buddy_small;
Buddy<BuddyInplaceRep<ChunkBounds>, MIN_BITS, MIN_CHUNK_BITS> buddy_small;
/**
* 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<void, ChunkBounds> base, size_t length)
{
range_to_pow_2_blocks<MIN_BITS>(
base, length, [this](capptr::Chunk<void> base, size_t align, bool) {
capptr::Chunk<void> overflow =
buddy_small.add_block(base.as_reinterpret<FreeChunk>(), align)
base,
length,
[this](CapPtr<void, ChunkBounds> base, size_t align, bool) {
CapPtr<void, ChunkBounds> overflow =
buddy_small
.add_block(
base.template as_reinterpret<FreeChunk<ChunkBounds>>(), align)
.template as_reinterpret<void>();
if (overflow != nullptr)
parent.dealloc_range(overflow, bits::one_at_bit(MIN_CHUNK_BITS));
});
}
capptr::Chunk<void> refill(size_t size)
CapPtr<void, ChunkBounds> refill(size_t size)
{
auto refill = parent.alloc_range(MIN_CHUNK_SIZE);
@@ -188,11 +200,9 @@ namespace snmalloc
static constexpr bool ConcurrencySafe = false;
using ChunkBounds = capptr::bounds::Chunk;
constexpr Type() = default;
capptr::Chunk<void> alloc_range(size_t size)
CapPtr<void, ChunkBounds> alloc_range(size_t size)
{
if (size >= MIN_CHUNK_SIZE)
{
@@ -209,7 +219,7 @@ namespace snmalloc
return refill(size);
}
capptr::Chunk<void> alloc_range_with_leftover(size_t size)
CapPtr<void, ChunkBounds> alloc_range_with_leftover(size_t size)
{
SNMALLOC_ASSERT(size <= MIN_CHUNK_SIZE);
@@ -227,7 +237,7 @@ namespace snmalloc
return result.template as_reinterpret<void>();
}
void dealloc_range(capptr::Chunk<void> base, size_t size)
void dealloc_range(CapPtr<void, ChunkBounds> base, size_t size)
{
if (size >= MIN_CHUNK_SIZE)
{