From 04a185e6345a143f0346dc59540f40df87469ced Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Mon, 22 Mar 2021 10:52:33 +0000 Subject: [PATCH] Remove allocated field from Metaslab The metaslab contains a field specifying how many elements have been allocated. As the code has evolved this field has now always become the maximum capacity of the slab for the sizeclass. This commit looks up this value based on the sizeclass, and removes the field from the slab's metadata. --- src/mem/metaslab.h | 14 +++++--------- src/mem/sizeclass.h | 2 ++ src/mem/sizeclasstable.h | 18 ++++++++++++++++++ src/mem/slab.h | 6 ++++-- src/mem/superslab.h | 6 ------ 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/mem/metaslab.h b/src/mem/metaslab.h index 7121105..b39d552 100644 --- a/src/mem/metaslab.h +++ b/src/mem/metaslab.h @@ -30,7 +30,7 @@ namespace snmalloc /** * Pointer to first free entry in this slab * - * The list will be (allocated - needed) long. + * The list will be (slab_capacity - needed) long. */ FreeListBuilder free_queue; @@ -44,11 +44,6 @@ namespace snmalloc */ uint16_t needed = 0; - /** - * How many entries have been allocated from this slab. - */ - uint16_t allocated = 0; - uint8_t sizeclass; // Initially zero to encode the superslabs relative list of slabs. uint8_t next = 0; @@ -136,7 +131,8 @@ namespace snmalloc void* n = fast_free_list.take(); // Treat stealing the free list as allocating it all. - self->needed = self->allocated; + self->needed = + get_slab_capacity(self->sizeclass, Metaslab::is_short(slab)); self->remove(); self->set_full(); @@ -195,8 +191,8 @@ namespace snmalloc SNMALLOC_ASSERT(SLAB_SIZE >= accounted_for); } - auto bumpptr = (allocated * size) + offset; - // Check we haven't allocaated more than gits in a slab + auto bumpptr = (get_slab_capacity(sizeclass, is_short) * size) + offset; + // Check we haven't allocated more than fits in a slab SNMALLOC_ASSERT(bumpptr <= SLAB_SIZE); // Account for to be bump allocated space diff --git a/src/mem/sizeclass.h b/src/mem/sizeclass.h index 35e3d74..24080e7 100644 --- a/src/mem/sizeclass.h +++ b/src/mem/sizeclass.h @@ -14,6 +14,8 @@ namespace snmalloc constexpr static uintptr_t SIZECLASS_MASK = 0xFF; constexpr static uint16_t get_initial_offset(sizeclass_t sc, bool is_short); + constexpr static uint16_t get_slab_capacity(sizeclass_t sc, bool is_short); + constexpr static size_t sizeclass_to_size(sizeclass_t sizeclass); constexpr static size_t sizeclass_to_cache_friendly_mask(sizeclass_t sizeclass); diff --git a/src/mem/sizeclasstable.h b/src/mem/sizeclasstable.h index 6db06aa..390bce7 100644 --- a/src/mem/sizeclasstable.h +++ b/src/mem/sizeclasstable.h @@ -29,6 +29,8 @@ namespace snmalloc ModArray inverse_cache_friendly_mask; ModArray initial_offset_ptr; ModArray short_initial_offset_ptr; + ModArray capacity; + ModArray short_capacity; ModArray medium_slab_slots; // Table of constants for reciprocal division for each sizeclass. ModArray div_mult; @@ -41,6 +43,8 @@ namespace snmalloc inverse_cache_friendly_mask(), initial_offset_ptr(), short_initial_offset_ptr(), + capacity(), + short_capacity(), medium_slab_slots(), div_mult(), mod_mult() @@ -90,6 +94,11 @@ namespace snmalloc initial_offset_ptr[i] = static_cast(correction); short_initial_offset_ptr[i] = static_cast(header_size + short_correction); + + capacity[i] = static_cast( + (SLAB_SIZE - initial_offset_ptr[i]) / (size[i])); + short_capacity[i] = static_cast( + (SLAB_SIZE - short_initial_offset_ptr[i]) / (size[i])); } for (sizeclass_t i = NUM_SMALL_CLASSES; i < NUM_SIZECLASSES; i++) @@ -111,6 +120,15 @@ namespace snmalloc return sizeclass_metadata.initial_offset_ptr[sc]; } + static inline constexpr uint16_t + get_slab_capacity(sizeclass_t sc, bool is_short) + { + if (is_short) + return sizeclass_metadata.short_capacity[sc]; + + return sizeclass_metadata.capacity[sc]; + } + constexpr static inline size_t sizeclass_to_size(sizeclass_t sizeclass) { return sizeclass_metadata.size[sizeclass]; diff --git a/src/mem/slab.h b/src/mem/slab.h index 295bba8..860bb6f 100644 --- a/src/mem/slab.h +++ b/src/mem/slab.h @@ -109,8 +109,10 @@ namespace snmalloc if (meta.is_full()) { + auto allocated = get_slab_capacity( + meta.sizeclass, Metaslab::is_short(Metaslab::get_slab(p))); // We are not on the sizeclass list. - if (meta.allocated == 1) + if (allocated == 1) { // Dealloc on the superslab. if (Metaslab::is_short(self)) @@ -120,7 +122,7 @@ namespace snmalloc } SNMALLOC_ASSERT(meta.free_queue.empty()); meta.free_queue.open(p); - meta.needed = meta.allocated - 1; + meta.needed = allocated - 1; // Push on the list of slabs for this sizeclass. sl->insert_prev(&meta); diff --git a/src/mem/superslab.h b/src/mem/superslab.h index 4398fa4..d689d09 100644 --- a/src/mem/superslab.h +++ b/src/mem/superslab.h @@ -170,9 +170,6 @@ namespace snmalloc // returned all the elements, but this is a slab that is still being bump // allocated from. Hence, the bump allocator slab will never be returned // for use in another size class. - meta[0].allocated = static_cast( - (SLAB_SIZE - get_initial_offset(sizeclass, true)) / - sizeclass_to_size(sizeclass)); meta[0].set_full(); meta[0].sizeclass = static_cast(sizeclass); @@ -194,9 +191,6 @@ namespace snmalloc // returned all the elements, but this is a slab that is still being bump // allocated from. Hence, the bump allocator slab will never be returned // for use in another size class. - meta[h].allocated = static_cast( - (SLAB_SIZE - get_initial_offset(sizeclass, false)) / - sizeclass_to_size(sizeclass)); meta[h].set_full(); meta[h].sizeclass = static_cast(sizeclass);