Refactor checks to improve codegen.

This commit is contained in:
Matthew Parkinson
2021-03-17 18:41:56 +00:00
committed by Matthew Parkinson
parent 0983f1837b
commit ed615eade9
4 changed files with 73 additions and 89 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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();
} }
/** /**

View File

@@ -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;