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:
committed by
Nathaniel Filardo
parent
f41bb321f7
commit
aa61b59a8f
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user