Refactor checks to improve codegen.
This commit is contained in:
committed by
Matthew Parkinson
parent
0983f1837b
commit
ed615eade9
118
src/mem/alloc.h
118
src/mem/alloc.h
@@ -763,16 +763,19 @@ namespace snmalloc
|
|||||||
|
|
||||||
for (size_t i = 0; i < NUM_SMALL_CLASSES; i++)
|
for (size_t i = 0; i < NUM_SMALL_CLASSES; i++)
|
||||||
{
|
{
|
||||||
while (!small_fast_free_lists[i].empty())
|
if (!small_fast_free_lists[i].empty())
|
||||||
{
|
{
|
||||||
auto curr = small_fast_free_lists[i].take();
|
auto head = small_fast_free_lists[i].peek();
|
||||||
|
auto super = Superslab::get(head);
|
||||||
|
auto slab = Metaslab::get_slab(head);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
auto curr = small_fast_free_lists[i].take();
|
||||||
|
small_dealloc_offseted_inner(super, slab, curr, i);
|
||||||
|
} while (!small_fast_free_lists[i].empty());
|
||||||
|
|
||||||
Superslab* super = Superslab::get(curr);
|
test(small_classes[i]);
|
||||||
Slab* slab = Metaslab::get_slab(curr);
|
|
||||||
small_dealloc_offseted_inner(super, slab, curr, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test(small_classes[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& medium_class : medium_classes)
|
for (auto& medium_class : medium_classes)
|
||||||
@@ -828,10 +831,9 @@ namespace snmalloc
|
|||||||
// Destined for my slabs
|
// Destined for my slabs
|
||||||
Superslab* super = Superslab::get(p);
|
Superslab* super = Superslab::get(p);
|
||||||
|
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
if (p->trunc_target_id() != (super->get_allocator()->trunc_id()))
|
p->trunc_target_id() == super->get_allocator()->trunc_id(),
|
||||||
error("Detected memory corruption. Potential use-after-free");
|
"Detected memory corruption. Potential use-after-free");
|
||||||
#endif
|
|
||||||
|
|
||||||
void* start = remove_cache_friendly_offset(p, p->sizeclass());
|
void* start = remove_cache_friendly_offset(p, p->sizeclass());
|
||||||
dealloc_not_large_local(super, start, p, p->sizeclass());
|
dealloc_not_large_local(super, start, p, p->sizeclass());
|
||||||
@@ -1178,13 +1180,9 @@ namespace snmalloc
|
|||||||
SNMALLOC_FAST_PATH void
|
SNMALLOC_FAST_PATH void
|
||||||
small_dealloc_unchecked(Superslab* super, void* p, sizeclass_t sizeclass)
|
small_dealloc_unchecked(Superslab* super, void* p, sizeclass_t sizeclass)
|
||||||
{
|
{
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
uint8_t chunkmap_slab_kind = chunkmap().get(address_cast(p));
|
chunkmap().get(address_cast(p)) == CMSuperslab,
|
||||||
if (chunkmap_slab_kind != CMSuperslab)
|
"Claimed small deallocation is not in a Superslab");
|
||||||
{
|
|
||||||
error("Claimed small deallocation is not in a Superslab");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
small_dealloc_checked_chunkmap(super, p, sizeclass);
|
small_dealloc_checked_chunkmap(super, p, sizeclass);
|
||||||
}
|
}
|
||||||
@@ -1193,13 +1191,9 @@ namespace snmalloc
|
|||||||
Superslab* super, void* p, sizeclass_t sizeclass)
|
Superslab* super, void* p, sizeclass_t sizeclass)
|
||||||
{
|
{
|
||||||
Slab* slab = Metaslab::get_slab(p);
|
Slab* slab = Metaslab::get_slab(p);
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
Metaslab& meta = super->get_meta(slab);
|
sizeclass == super->get_meta(slab).sizeclass,
|
||||||
if (sizeclass != meta.sizeclass)
|
"Claimed small deallocation with mismatching size class");
|
||||||
{
|
|
||||||
error("Claimed small deallocation with mismatching size class");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
small_dealloc_checked_sizeclass(super, slab, p, sizeclass);
|
small_dealloc_checked_sizeclass(super, slab, p, sizeclass);
|
||||||
}
|
}
|
||||||
@@ -1207,12 +1201,9 @@ namespace snmalloc
|
|||||||
SNMALLOC_FAST_PATH void small_dealloc_checked_sizeclass(
|
SNMALLOC_FAST_PATH void small_dealloc_checked_sizeclass(
|
||||||
Superslab* super, Slab* slab, void* p, sizeclass_t sizeclass)
|
Superslab* super, Slab* slab, void* p, sizeclass_t sizeclass)
|
||||||
{
|
{
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
if (!Metaslab::is_start_of_object(&Slab::get_meta(slab), p))
|
Metaslab::is_start_of_object(&Slab::get_meta(slab), p),
|
||||||
{
|
"Not deallocating start of an object");
|
||||||
error("Not deallocating start of an object");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
small_dealloc_start(super, slab, p, sizeclass);
|
small_dealloc_start(super, slab, p, sizeclass);
|
||||||
}
|
}
|
||||||
@@ -1363,13 +1354,9 @@ namespace snmalloc
|
|||||||
void
|
void
|
||||||
medium_dealloc_unchecked(Mediumslab* slab, void* p, sizeclass_t sizeclass)
|
medium_dealloc_unchecked(Mediumslab* slab, void* p, sizeclass_t sizeclass)
|
||||||
{
|
{
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
uint8_t chunkmap_slab_kind = chunkmap().get(address_cast(p));
|
chunkmap().get(address_cast(p)) == CMMediumslab,
|
||||||
if (chunkmap_slab_kind != CMMediumslab)
|
"Claimed medium deallocation is not in a Mediumslab");
|
||||||
{
|
|
||||||
error("Claimed medium deallocation is not in a Mediumslab");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
medium_dealloc_checked_chunkmap(slab, p, sizeclass);
|
medium_dealloc_checked_chunkmap(slab, p, sizeclass);
|
||||||
}
|
}
|
||||||
@@ -1378,12 +1365,9 @@ namespace snmalloc
|
|||||||
void medium_dealloc_checked_chunkmap(
|
void medium_dealloc_checked_chunkmap(
|
||||||
Mediumslab* slab, void* p, sizeclass_t sizeclass)
|
Mediumslab* slab, void* p, sizeclass_t sizeclass)
|
||||||
{
|
{
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
if (slab->get_sizeclass() != sizeclass)
|
slab->get_sizeclass() == sizeclass,
|
||||||
{
|
"Claimed medium deallocation of the wrong sizeclass");
|
||||||
error("Claimed medium deallocation of the wrong sizeclass");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
medium_dealloc_checked_sizeclass(slab, p, sizeclass);
|
medium_dealloc_checked_sizeclass(slab, p, sizeclass);
|
||||||
}
|
}
|
||||||
@@ -1392,14 +1376,11 @@ namespace snmalloc
|
|||||||
void medium_dealloc_checked_sizeclass(
|
void medium_dealloc_checked_sizeclass(
|
||||||
Mediumslab* slab, void* p, sizeclass_t sizeclass)
|
Mediumslab* slab, void* p, sizeclass_t sizeclass)
|
||||||
{
|
{
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
if (!is_multiple_of_sizeclass(
|
is_multiple_of_sizeclass(
|
||||||
sizeclass_to_size(sizeclass),
|
sizeclass_to_size(sizeclass),
|
||||||
pointer_diff(p, pointer_offset(slab, SUPERSLAB_SIZE))))
|
pointer_diff(p, pointer_offset(slab, SUPERSLAB_SIZE))),
|
||||||
{
|
"Not deallocating start of an object");
|
||||||
error("Not deallocating start of an object");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
medium_dealloc_start(slab, p, sizeclass);
|
medium_dealloc_start(slab, p, sizeclass);
|
||||||
}
|
}
|
||||||
@@ -1482,37 +1463,22 @@ namespace snmalloc
|
|||||||
|
|
||||||
void large_dealloc_unchecked(void* p, size_t size)
|
void large_dealloc_unchecked(void* p, size_t size)
|
||||||
{
|
{
|
||||||
size_t claimed_chunkmap_slab_kind = bits::next_pow2_bits(size);
|
uint8_t claimed_chunkmap_slab_kind =
|
||||||
uint8_t chunkmap_slab_kind;
|
static_cast<uint8_t>(bits::next_pow2_bits(size));
|
||||||
|
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
chunkmap_slab_kind = chunkmap().get(address_cast(p));
|
chunkmap().get(address_cast(p)) == claimed_chunkmap_slab_kind,
|
||||||
if (chunkmap_slab_kind < CMLargeMin)
|
"Claimed large deallocation with wrong size class");
|
||||||
{
|
|
||||||
error("Claimed large deallocation is not in a large slab");
|
|
||||||
}
|
|
||||||
if (chunkmap_slab_kind != claimed_chunkmap_slab_kind)
|
|
||||||
{
|
|
||||||
error("Claimed large deallocation with wrong size class");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Trusting sort, aren't we?
|
|
||||||
chunkmap_slab_kind = static_cast<uint8_t>(claimed_chunkmap_slab_kind);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
large_dealloc_checked_sizeclass(p, size, chunkmap_slab_kind);
|
large_dealloc_checked_sizeclass(p, size, claimed_chunkmap_slab_kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
void large_dealloc_checked_sizeclass(
|
void large_dealloc_checked_sizeclass(
|
||||||
void* p, size_t size, uint8_t chunkmap_slab_kind)
|
void* p, size_t size, uint8_t chunkmap_slab_kind)
|
||||||
{
|
{
|
||||||
#ifdef CHECK_CLIENT
|
check_client(
|
||||||
Superslab* super = Superslab::get(p);
|
address_cast(Superslab::get(p)) == address_cast(p),
|
||||||
if (address_cast(super) != address_cast(p))
|
"Not deallocating start of an object");
|
||||||
{
|
|
||||||
error("Not deallocating start of an object");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
SNMALLOC_ASSERT(bits::one_at_bit(chunkmap_slab_kind) >= SUPERSLAB_SIZE);
|
SNMALLOC_ASSERT(bits::one_at_bit(chunkmap_slab_kind) >= SUPERSLAB_SIZE);
|
||||||
|
|
||||||
large_dealloc_start(p, size, chunkmap_slab_kind);
|
large_dealloc_start(p, size, chunkmap_slab_kind);
|
||||||
|
|||||||
@@ -8,6 +8,22 @@ namespace snmalloc
|
|||||||
// calling the API correctly.
|
// calling the API correctly.
|
||||||
#if !defined(NDEBUG) && !defined(CHECK_CLIENT)
|
#if !defined(NDEBUG) && !defined(CHECK_CLIENT)
|
||||||
# define CHECK_CLIENT
|
# define CHECK_CLIENT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SNMALLOC_FAST_PATH void check_client_impl(bool test, const char* const str)
|
||||||
|
{
|
||||||
|
#ifdef CHECK_CLIENT
|
||||||
|
if (unlikely(!test))
|
||||||
|
error(str);
|
||||||
|
#else
|
||||||
|
UNUSED(test);
|
||||||
|
UNUSED(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef CHECK_CLIENT
|
||||||
|
# define check_client(test, str) check_client_impl(test, str)
|
||||||
|
#else
|
||||||
|
# define check_client(test, str)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 0 intermediate bits results in power of 2 small allocs. 1 intermediate
|
// 0 intermediate bits results in power of 2 small allocs. 1 intermediate
|
||||||
|
|||||||
@@ -139,10 +139,9 @@ namespace snmalloc
|
|||||||
# ifndef NDEBUG
|
# ifndef NDEBUG
|
||||||
if (next != nullptr)
|
if (next != nullptr)
|
||||||
{
|
{
|
||||||
if (unlikely(different_slab(prev, next)))
|
check_client(
|
||||||
{
|
!different_slab(prev, next),
|
||||||
error("Heap corruption - free list corrupted!");
|
"Heap corruption - free list corrupted!");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
prev = address_cast(curr);
|
prev = address_cast(curr);
|
||||||
@@ -162,10 +161,8 @@ namespace snmalloc
|
|||||||
void move_next()
|
void move_next()
|
||||||
{
|
{
|
||||||
#ifdef CHECK_CLIENT
|
#ifdef CHECK_CLIENT
|
||||||
if (unlikely(different_slab(prev, curr)))
|
check_client(
|
||||||
{
|
!different_slab(prev, curr), "Heap corruption - free list corrupted!");
|
||||||
error("Heap corruption - free list corrupted!");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
update_cursor(curr->read_next(get_prev()));
|
update_cursor(curr->read_next(get_prev()));
|
||||||
}
|
}
|
||||||
@@ -221,6 +218,14 @@ namespace snmalloc
|
|||||||
return front.get_curr() == nullptr;
|
return front.get_curr() == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current head without affecting the iterator.
|
||||||
|
*/
|
||||||
|
void* peek()
|
||||||
|
{
|
||||||
|
return front.get_curr();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the iterator on, and returns the current value.
|
* Moves the iterator on, and returns the current value.
|
||||||
*/
|
*/
|
||||||
@@ -258,7 +263,7 @@ namespace snmalloc
|
|||||||
*/
|
*/
|
||||||
void* peek_head()
|
void* peek_head()
|
||||||
{
|
{
|
||||||
return front.get_curr();
|
return peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -81,10 +81,7 @@ namespace snmalloc
|
|||||||
dealloc_fast(Slab* self, Superslab* super, void* p)
|
dealloc_fast(Slab* self, Superslab* super, void* p)
|
||||||
{
|
{
|
||||||
Metaslab& meta = super->get_meta(self);
|
Metaslab& meta = super->get_meta(self);
|
||||||
#ifdef CHECK_CLIENT
|
SNMALLOC_ASSERT(!meta.is_unused());
|
||||||
if (meta.is_unused())
|
|
||||||
error("Detected potential double free.");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (unlikely(meta.return_object()))
|
if (unlikely(meta.return_object()))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user