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