diff --git a/src/ds/helpers.h b/src/ds/helpers.h index 57a7fef..d96769b 100644 --- a/src/ds/helpers.h +++ b/src/ds/helpers.h @@ -32,6 +32,34 @@ namespace snmalloc } }; + /** + * Wrapper for wrapping values. + * + * Wraps on read. This allows code to trust the value is in range, even when + * there is a memory corruption. + **/ + template + class Mod + { + static_assert(length == bits::next_pow2_const(length), + "Must be a power of two."); + + private: + T value; + + public: + operator T() + { + return (T)(value & (length - 1)); + } + + T& operator=(const T v) + { + value = v; + return value; + } + }; + template class ModArray { diff --git a/src/mem/metaslab.h b/src/mem/metaslab.h index d38ff02..cd820e2 100644 --- a/src/mem/metaslab.h +++ b/src/mem/metaslab.h @@ -1,6 +1,7 @@ #pragma once #include "../ds/dllist.h" +#include "../ds/helpers.h" #include "sizeclass.h" namespace snmalloc @@ -51,11 +52,11 @@ namespace snmalloc // The terminal value in the free list, and the terminal value in // the SlabLink previous field will alias. The SlabLink uses ~0 for // its terminal value to be a valid terminal bump ptr. - uint16_t head; + Mod head; // When a slab has free space it will be on the has space list for // that size class. We use an empty block in this slab to be the // doubly linked node into that size class's free list. - uint16_t link; + Mod link; uint8_t sizeclass; uint8_t next; diff --git a/src/mem/superslab.h b/src/mem/superslab.h index 53855ac..7c43c0b 100644 --- a/src/mem/superslab.h +++ b/src/mem/superslab.h @@ -1,5 +1,6 @@ #pragma once +#include "allocslab.h" #include "metaslab.h" #include "../ds/helpers.h" #include @@ -30,7 +31,7 @@ namespace snmalloc // are the relative offset to the next entry minus 1. This means that // all zeros is a list that chains through all the blocks, so the zero // initialised memory requires no more work. - uint8_t head; + Mod head; // Represents twice the number of full size slabs used // plus 1 for the short slab. i.e. using 3 slabs and the @@ -180,15 +181,16 @@ namespace snmalloc template Slab* alloc_slab(uint8_t sizeclass, MemoryProvider& memory_provider) { - Slab* slab = (Slab*)((size_t)this + ((size_t)head << SLAB_BITS)); + uint8_t h = head; + Slab* slab = (Slab*)((size_t)this + ((size_t)h << SLAB_BITS)); - uint8_t n = meta[head].next; + uint8_t n = meta[h].next; - meta[head].head = get_slab_offset(sizeclass, false); - meta[head].sizeclass = sizeclass; - meta[head].link = SLABLINK_INDEX; + meta[h].head = get_slab_offset(sizeclass, false); + meta[h].sizeclass = sizeclass; + meta[h].link = SLABLINK_INDEX; - head = head + n + 1; + head = h + n + 1; used += 2; if (decommit_strategy == DecommitAll)