From 83c55fe5daca3fa492b01da507e26722a3188374 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Tue, 5 Feb 2019 13:06:24 +0000 Subject: [PATCH] Simplify remote allocator. Don't store the sizeclass, as we can find it easily, and already are going to touch though cache lines in the common case. --- src/mem/alloc.h | 34 ++++++++++++++------- src/mem/remoteallocator.h | 62 +++------------------------------------ 2 files changed, 27 insertions(+), 69 deletions(-) diff --git a/src/mem/alloc.h b/src/mem/alloc.h index 657b028..6318118 100644 --- a/src/mem/alloc.h +++ b/src/mem/alloc.h @@ -536,8 +536,7 @@ namespace snmalloc this->size += sizeclass_to_size(sizeclass); Remote* r = (Remote*)p; - r->set_sizeclass_and_target_id(target_id, sizeclass); - assert(r->sizeclass() == sizeclass); + r->set_target_id(target_id); assert(r->target_id() == target_id); RemoteList* l = &list[get_slot(target_id, 0)]; @@ -702,21 +701,34 @@ namespace snmalloc { if (p != &stub) { - uint8_t sizeclass = p->sizeclass(); + Superslab* super = Superslab::get(p); - if (p->target_id() == id()) + if (super->get_kind() == Super) { - stats().remote_receive(sizeclass); - - if (sizeclass < NUM_SMALL_CLASSES) - small_dealloc(Superslab::get(p), p, sizeclass); + Slab* slab = Slab::get(p); + Metaslab& meta = super->get_meta(slab); + if (p->target_id() == id()) + { + small_dealloc(super, p, meta.sizeclass); + } else - medium_dealloc(Mediumslab::get(p), p, sizeclass); + { + // Queue for remote dealloc elsewhere. + remote.dealloc(p->target_id(), p, meta.sizeclass); + } } else { - // Queue for remote dealloc elsewhere. - remote.dealloc(p->target_id(), p, sizeclass); + Mediumslab* slab = Mediumslab::get(p); + if (p->target_id() == id()) + { + medium_dealloc(slab, p, slab->get_sizeclass()); + } + else + { + // Queue for remote dealloc elsewhere. + remote.dealloc(p->target_id(), p, slab->get_sizeclass()); + } } } } diff --git a/src/mem/remoteallocator.h b/src/mem/remoteallocator.h index cb295bb..c61ea0a 100644 --- a/src/mem/remoteallocator.h +++ b/src/mem/remoteallocator.h @@ -10,13 +10,6 @@ namespace snmalloc { struct Remote { - static const size_t PTR_BITS = sizeof(void*) * 8; - static const size_t SIZECLASS_BITS = - bits::next_pow2_bits_const(NUM_SIZECLASSES); - static const bool USE_TOP_BITS = - SIZECLASS_BITS + bits::ADDRESS_BITS < PTR_BITS; - static const uintptr_t SIZECLASS_MASK = ((1ULL << SIZECLASS_BITS) - 1); - using alloc_id_t = size_t; union { @@ -24,66 +17,19 @@ namespace snmalloc Remote* non_atomic_next; }; - // Uses an intptr_t so that when we use the TOP_BITS to encode the - // sizeclass, then we can use signed shift to correctly handle kernel versus - // user mode. - intptr_t value; + alloc_id_t allocator_id; - // This will not exist for the minimum object size. This is only used if - // USE_TOP_BITS is false, and the bottom bit of value is set. - uint8_t possible_sizeclass; - - void set_sizeclass_and_target_id(alloc_id_t id, uint8_t sizeclass) + void set_target_id(alloc_id_t id) { - if constexpr (USE_TOP_BITS) - { - value = (intptr_t)( - (id << SIZECLASS_BITS) | ((static_cast(sizeclass)))); - } - else - { - assert((id & 1) == 0); - if (sizeclass == 0) - { - value = (intptr_t)(id | 1); - } - else - { - value = (intptr_t)id; - possible_sizeclass = sizeclass; - } - } + allocator_id = id; } alloc_id_t target_id() { - if constexpr (USE_TOP_BITS) - { - return (alloc_id_t)(value >> SIZECLASS_BITS); - } - else - { - return (alloc_id_t)(value & ~1); - } - } - - uint8_t sizeclass() - { - if constexpr (USE_TOP_BITS) - { - return (static_cast((uintptr_t)value & SIZECLASS_MASK)); - } - else - { - return ((value & 1) == 1) ? 0 : possible_sizeclass; - } + return allocator_id; } }; - static_assert( - (offsetof(Remote, possible_sizeclass)) <= MIN_ALLOC_SIZE, - "Need to be able to cast any small alloc to Remote"); - struct RemoteAllocator { using alloc_id_t = Remote::alloc_id_t;