From 9aa79fa196c259044410536623bfae11fa9f17c9 Mon Sep 17 00:00:00 2001 From: schrodingerzhu Date: Sat, 21 Dec 2024 18:01:48 -0500 Subject: [PATCH] [proxy](7/n) proxy array and algorithm headers --- src/snmalloc/backend_helpers/buddy.h | 5 +- src/snmalloc/ds_core/bits.h | 8 +- src/snmalloc/ds_core/defines.h | 6 +- src/snmalloc/ds_core/helpers.h | 16 ++-- src/snmalloc/ds_core/ptrwrap.h | 4 +- src/snmalloc/ds_core/redblacktree.h | 5 +- src/snmalloc/global/memcpy.h | 3 +- src/snmalloc/mem/corealloc.h | 3 +- src/snmalloc/mem/freelist.h | 6 +- src/snmalloc/mem/remotecache.h | 9 +- src/snmalloc/override/new.cc | 7 ++ src/snmalloc/pal/pal_linux.h | 4 +- src/snmalloc/pal/pal_posix.h | 4 +- src/snmalloc/proxy/algorithm.h | 53 ++++++++++++ src/snmalloc/proxy/array.h | 118 +++++++++++++++++++++++++++ src/test/func/memory/memory.cc | 2 + 16 files changed, 220 insertions(+), 33 deletions(-) create mode 100644 src/snmalloc/proxy/algorithm.h create mode 100644 src/snmalloc/proxy/array.h diff --git a/src/snmalloc/backend_helpers/buddy.h b/src/snmalloc/backend_helpers/buddy.h index d7406468e..21ab0acdb 100644 --- a/src/snmalloc/backend_helpers/buddy.h +++ b/src/snmalloc/backend_helpers/buddy.h @@ -1,6 +1,7 @@ #pragma once #include "../ds/ds.h" +#include "snmalloc/proxy/algorithm.h" namespace snmalloc { @@ -23,7 +24,7 @@ namespace snmalloc RBTree tree{}; }; - std::array entries{}; + proxy::Array entries{}; // All RBtrees at or above this index should be empty. size_t empty_at_or_above{0}; @@ -167,7 +168,7 @@ namespace snmalloc { if (Rep::equal(Rep::null, addr) || Rep::compare(e, addr)) { - addr = std::exchange(e, addr); + addr = proxy::exchange(e, addr); } } diff --git a/src/snmalloc/ds_core/bits.h b/src/snmalloc/ds_core/bits.h index 8a1468a4b..bae41e8b2 100644 --- a/src/snmalloc/ds_core/bits.h +++ b/src/snmalloc/ds_core/bits.h @@ -371,9 +371,9 @@ namespace snmalloc } /** - * Implementation of `std::min` + * Implementation of `proxy::min` * - * `std::min` is in ``, so pulls in a lot of unneccessary code + * `proxy::min` is in ``, so pulls in a lot of unneccessary code * We write our own to reduce the code that potentially needs reviewing. */ template @@ -383,9 +383,9 @@ namespace snmalloc } /** - * Implementation of `std::max` + * Implementation of `proxy::max` * - * `std::max` is in ``, so pulls in a lot of unneccessary code + * `proxy::max` is in ``, so pulls in a lot of unneccessary code * We write our own to reduce the code that potentially needs reviewing. */ template diff --git a/src/snmalloc/ds_core/defines.h b/src/snmalloc/ds_core/defines.h index 9638b5527..d5cfb9744 100644 --- a/src/snmalloc/ds_core/defines.h +++ b/src/snmalloc/ds_core/defines.h @@ -130,7 +130,11 @@ namespace snmalloc #define TOSTRING(expr) TOSTRING2(expr) #define TOSTRING2(expr) #expr -#ifdef __cpp_lib_source_location +#ifndef SNMALLOC_USE_SELF_VENDORED_STL +# define SNMALLOC_USE_SELF_VENDORED_STL 0 +#endif + +#if defined(__cpp_lib_source_location) && !SNMALLOC_USE_SELF_VENDORED_STL # include # define SNMALLOC_CURRENT_LINE std::source_location::current().line() # define SNMALLOC_CURRENT_FILE std::source_location::current().file_name() diff --git a/src/snmalloc/ds_core/helpers.h b/src/snmalloc/ds_core/helpers.h index 9c203ec63..0b50422b4 100644 --- a/src/snmalloc/ds_core/helpers.h +++ b/src/snmalloc/ds_core/helpers.h @@ -2,10 +2,10 @@ #include "bits.h" #include "snmalloc/ds_core/defines.h" +#include "snmalloc/proxy/array.h" #include "snmalloc/proxy/type_traits.h" #include "snmalloc/proxy/utility.h" -#include #include namespace snmalloc @@ -50,7 +50,7 @@ namespace snmalloc }; static constexpr size_t rlength = bits::next_pow2_const(length); - std::array array; + proxy::Array array; public: constexpr const T& operator[](const size_t i) const @@ -65,7 +65,7 @@ namespace snmalloc }; #else template - using ModArray = std::array; + using ModArray = proxy::Array; #endif /** @@ -105,7 +105,7 @@ namespace snmalloc template< typename Fn, typename = - proxy::enable_if_t, function_ref>>> + proxy::enable_if_t, function_ref>>> function_ref(Fn&& fn) { data_ = static_cast(&fn); @@ -144,7 +144,7 @@ namespace snmalloc /** * The buffer that is used to store the formatted output. */ - std::array buffer; + proxy::Array buffer; /** * Space in the buffer, excluding a trailing null terminator. @@ -208,7 +208,7 @@ namespace snmalloc /** * Append a nullptr */ - void append(std::nullptr_t) + void append(decltype(nullptr)) { append("(nullptr)"); } @@ -254,7 +254,7 @@ namespace snmalloc append_char('-'); s = 0 - s; } - std::array buf{{0}}; + proxy::Array buf{{0}}; const char digits[] = "0123456789"; for (long i = static_cast(buf.size() - 1); i >= 0; i--) { @@ -284,7 +284,7 @@ namespace snmalloc { append_char('0'); append_char('x'); - std::array buf{{0}}; + proxy::Array buf{{0}}; const char hexdigits[] = "0123456789abcdef"; // Length of string including null terminator static_assert(sizeof(hexdigits) == 0x11); diff --git a/src/snmalloc/ds_core/ptrwrap.h b/src/snmalloc/ds_core/ptrwrap.h index 38e268eb6..fcb58dfdf 100644 --- a/src/snmalloc/ds_core/ptrwrap.h +++ b/src/snmalloc/ds_core/ptrwrap.h @@ -276,7 +276,7 @@ namespace snmalloc /** * nullptr is implicitly constructable at any bounds type */ - constexpr SNMALLOC_FAST_PATH CapPtr(const std::nullptr_t n) + constexpr SNMALLOC_FAST_PATH CapPtr(const decltype(nullptr) n) : unsafe_capptr(n) {} @@ -465,7 +465,7 @@ namespace snmalloc /** * nullptr is constructable at any bounds type */ - constexpr SNMALLOC_FAST_PATH AtomicCapPtr(const std::nullptr_t n) + constexpr SNMALLOC_FAST_PATH AtomicCapPtr(const decltype(nullptr) n) : unsafe_capptr(n) {} diff --git a/src/snmalloc/ds_core/redblacktree.h b/src/snmalloc/ds_core/redblacktree.h index 37b90ddb2..251fd3caa 100644 --- a/src/snmalloc/ds_core/redblacktree.h +++ b/src/snmalloc/ds_core/redblacktree.h @@ -1,6 +1,7 @@ #pragma once -#include +#include "snmalloc/proxy/array.h" + #include #include @@ -260,7 +261,7 @@ namespace snmalloc { friend class RBTree; - std::array path; + proxy::Array path; size_t length = 0; RBPath(typename Rep::Handle root) diff --git a/src/snmalloc/global/memcpy.h b/src/snmalloc/global/memcpy.h index 0cb3fe97e..1b35f947e 100644 --- a/src/snmalloc/global/memcpy.h +++ b/src/snmalloc/global/memcpy.h @@ -1,5 +1,6 @@ #pragma once #include "bounds_checks.h" +#include "snmalloc/proxy/algorithm.h" namespace snmalloc { @@ -156,7 +157,7 @@ namespace snmalloc */ SNMALLOC_UNUSED_FUNCTION static constexpr size_t LargestRegisterSize = - std::max(sizeof(uint64_t), sizeof(void*)); + proxy::max(sizeof(uint64_t), sizeof(void*)); /** * Hook for architecture-specific optimisations. diff --git a/src/snmalloc/mem/corealloc.h b/src/snmalloc/mem/corealloc.h index 0115ce634..7f5557891 100644 --- a/src/snmalloc/mem/corealloc.h +++ b/src/snmalloc/mem/corealloc.h @@ -6,6 +6,7 @@ #include "pool.h" #include "remotecache.h" #include "sizeclasstable.h" +#include "snmalloc/proxy/algorithm.h" #include "snmalloc/proxy/new.h" #include "ticker.h" @@ -222,7 +223,7 @@ namespace snmalloc pointer_offset(curr, rsize).template as_static()) { size_t insert_index = entropy.sample(count); - curr->next = std::exchange( + curr->next = proxy::exchange( pointer_offset(bumpptr, insert_index * rsize) .template as_static() ->next, diff --git a/src/snmalloc/mem/freelist.h b/src/snmalloc/mem/freelist.h index 6e47ee20f..298c14ef9 100644 --- a/src/snmalloc/mem/freelist.h +++ b/src/snmalloc/mem/freelist.h @@ -701,11 +701,11 @@ namespace snmalloc */ // Pointer to the first element. - std::array head{nullptr}; + proxy::Array head{nullptr}; // Pointer to the reference to the last element. // In the empty case end[i] == &head[i] // This enables branch free enqueuing. - std::array end{nullptr}; + proxy::Array end{nullptr}; [[nodiscard]] Object::BQueuePtr* cast_end(uint32_t ix) const { @@ -724,7 +724,7 @@ namespace snmalloc } SNMALLOC_NO_UNIQUE_ADDRESS - std::array length{}; + proxy::Array length{}; public: constexpr Builder() = default; diff --git a/src/snmalloc/mem/remotecache.h b/src/snmalloc/mem/remotecache.h index 02b843e12..dd4812bc5 100644 --- a/src/snmalloc/mem/remotecache.h +++ b/src/snmalloc/mem/remotecache.h @@ -6,10 +6,9 @@ #include "metadata.h" #include "remoteallocator.h" #include "sizeclasstable.h" +#include "snmalloc/proxy/array.h" #include "snmalloc/proxy/atomic.h" -#include - namespace snmalloc { @@ -33,8 +32,8 @@ namespace snmalloc { static_assert(RINGS > 0); - std::array, RINGS> open_builder; - std::array open_meta = {0}; + proxy::Array, RINGS> open_builder; + proxy::Array open_meta = {0}; SNMALLOC_FAST_PATH size_t ring_set(typename Config::PagemapEntry::SlabMetadata* meta) @@ -191,7 +190,7 @@ namespace snmalloc template struct RemoteDeallocCache { - std::array, REMOTE_SLOTS> list; + proxy::Array, REMOTE_SLOTS> list; RemoteDeallocCacheBatchingImpl batching; diff --git a/src/snmalloc/override/new.cc b/src/snmalloc/override/new.cc index 19aa9f58c..3e904a766 100644 --- a/src/snmalloc/override/new.cc +++ b/src/snmalloc/override/new.cc @@ -16,6 +16,12 @@ # endif #endif +#ifndef SNMALLOC_USE_SELF_VENDORED_STL +# define SNMALLOC_USE_SELF_VENDORED_STL 0 +#endif + +// only define these if we are not using the vendored STL +#if !SNMALLOC_USE_SELF_VENDORED_STL void* operator new(size_t size) { return snmalloc::libc::malloc(size); @@ -111,3 +117,4 @@ void operator delete[](void* p, size_t size, std::align_val_t val) EXCEPTSPEC size = snmalloc::aligned_size(size_t(val), size); snmalloc::libc::free_sized(p, size); } +#endif diff --git a/src/snmalloc/pal/pal_linux.h b/src/snmalloc/pal/pal_linux.h index 133e00674..16090c839 100644 --- a/src/snmalloc/pal/pal_linux.h +++ b/src/snmalloc/pal/pal_linux.h @@ -183,8 +183,8 @@ namespace snmalloc // protected routine. if (false == syscall_not_working.load(proxy::memory_order_relaxed)) { - auto current = std::begin(buffer); - auto target = std::end(buffer); + auto current = proxy::begin(buffer); + auto target = proxy::end(buffer); while (auto length = target - current) { // Reading data via syscall from system entropy pool. diff --git a/src/snmalloc/pal/pal_posix.h b/src/snmalloc/pal/pal_posix.h index ac0e4c6d9..118e30b53 100644 --- a/src/snmalloc/pal/pal_posix.h +++ b/src/snmalloc/pal/pal_posix.h @@ -419,8 +419,8 @@ namespace snmalloc auto fd = open("/dev/urandom", flags, 0); if (fd > 0) { - auto current = std::begin(buffer); - auto target = std::end(buffer); + auto current = proxy::begin(buffer); + auto target = proxy::end(buffer); while (auto length = static_cast(target - current)) { ret = read(fd, current, length); diff --git a/src/snmalloc/proxy/algorithm.h b/src/snmalloc/proxy/algorithm.h new file mode 100644 index 000000000..db3c38040 --- /dev/null +++ b/src/snmalloc/proxy/algorithm.h @@ -0,0 +1,53 @@ +#pragma once + +#include "snmalloc/ds_core/defines.h" + +#ifndef SNMALLOC_USE_SELF_VENDORED_STL +# define SNMALLOC_USE_SELF_VENDORED_STL 0 +#endif + +#if SNMALLOC_USE_SELF_VENDORED_STL +# include "snmalloc/proxy/utility.h" +# if !defined(__GNUC__) && !defined(__clang__) +# error "cannot use vendored STL without GNU/Clang extensions" +# endif + +namespace snmalloc +{ + namespace proxy + { + template + constexpr SNMALLOC_FAST_PATH const T& max(const T& a, const T& b) + { + return a < b ? b : a; + } + + template + constexpr SNMALLOC_FAST_PATH const T& min(const T& a, const T& b) + { + return a < b ? a : b; + } + + template + constexpr SNMALLOC_FAST_PATH A exchange(A& obj, B&& new_value) + { + A old_value = move(obj); + obj = forward(new_value); + return old_value; + } + + } // namespace proxy +} // namespace snmalloc +#else +# include + +namespace snmalloc +{ + namespace proxy + { + using std::exchange; + using std::max; + using std::min; + } // namespace proxy +} // namespace snmalloc +#endif diff --git a/src/snmalloc/proxy/array.h b/src/snmalloc/proxy/array.h new file mode 100644 index 000000000..7c4898fdf --- /dev/null +++ b/src/snmalloc/proxy/array.h @@ -0,0 +1,118 @@ +#pragma once + +#include "snmalloc/ds_core/defines.h" + +#ifndef SNMALLOC_USE_SELF_VENDORED_STL +# define SNMALLOC_USE_SELF_VENDORED_STL 0 +#endif + +#if SNMALLOC_USE_SELF_VENDORED_STL + +# if !defined(__GNUC__) && !defined(__clang__) +# error "cannot use vendored STL without GNU/Clang extensions" +# endif + +# include + +namespace snmalloc +{ + namespace proxy + { + template + struct Array + { + // N is potentially 0, so we mark it with __extension__ attribute. + // expose this to public to allow aggregate initialization + __extension__ T storage[N]; + + [[nodiscard]] constexpr SNMALLOC_FAST_PATH size_t size() const + { + return N; + } + + constexpr T& operator[](size_t i) + { + return storage[i]; + } + + constexpr const T& operator[](size_t i) const + { + return storage[i]; + } + + using value_type = T; + using size_type = size_t; + using iterator = T*; + using const_iterator = const T*; + + [[nodiscard]] constexpr SNMALLOC_FAST_PATH iterator begin() + { + return &storage[0]; + } + + [[nodiscard]] constexpr SNMALLOC_FAST_PATH const_iterator begin() const + { + return &storage[0]; + } + + [[nodiscard]] constexpr SNMALLOC_FAST_PATH iterator end() + { + return &storage[N]; + } + + [[nodiscard]] constexpr SNMALLOC_FAST_PATH const_iterator end() const + { + return &storage[N]; + } + + [[nodiscard]] constexpr SNMALLOC_FAST_PATH T* data() + { + return &storage[0]; + } + + [[nodiscard]] constexpr SNMALLOC_FAST_PATH const T* data() const + { + return &storage[0]; + } + }; + + template + constexpr T* begin(Array& a) + { + return a.begin(); + } + + template + constexpr T* end(Array& a) + { + return a.end(); + } + + template + constexpr const T* begin(const Array& a) + { + return a.begin(); + } + + template + constexpr const T* end(const Array& a) + { + return a.end(); + } + } // namespace proxy +} // namespace snmalloc +#else +# include + +namespace snmalloc +{ + namespace proxy + { + template + using Array = std::array; + + using std::begin; + using std::end; + } // namespace proxy +} // namespace snmalloc +#endif diff --git a/src/test/func/memory/memory.cc b/src/test/func/memory/memory.cc index c85659eab..6b52e89a8 100644 --- a/src/test/func/memory/memory.cc +++ b/src/test/func/memory/memory.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,7 @@ #include #include #include + #if ((defined(__linux__) && !defined(__ANDROID__)) || defined(__sun)) || \ defined(__OpenBSD__) && !defined(SNMALLOC_QEMU_WORKAROUND) /*