[proxy](7/n) self vendor array and algorithm headers (#722)

* [proxy](7/n) proxy array and algorithm headers

* [wip] address CRs

* undo comment

* format

* fix build

* simplify macro dispatching
This commit is contained in:
Schrodinger ZHU Yifan
2025-01-09 21:49:22 +08:00
committed by GitHub
parent 0027f02396
commit 0111a410a2
27 changed files with 200 additions and 58 deletions

View File

@@ -23,7 +23,7 @@ namespace snmalloc
RBTree<Rep> tree{};
};
std::array<Entry, MAX_SIZE_BITS - MIN_SIZE_BITS> entries{};
stl::Array<Entry, MAX_SIZE_BITS - MIN_SIZE_BITS> entries{};
// All RBtrees at or above this index should be empty.
size_t empty_at_or_above{0};
@@ -167,7 +167,7 @@ namespace snmalloc
{
if (Rep::equal(Rep::null, addr) || Rep::compare(e, addr))
{
addr = std::exchange(e, addr);
addr = stl::exchange(e, addr);
}
}

View File

@@ -130,7 +130,8 @@ namespace snmalloc
#define TOSTRING(expr) TOSTRING2(expr)
#define TOSTRING2(expr) #expr
#ifdef __cpp_lib_source_location
#if defined(__cpp_lib_source_location) && \
!defined(SNMALLOC_USE_SELF_VENDORED_STL)
# include <source_location>
# define SNMALLOC_CURRENT_LINE std::source_location::current().line()
# define SNMALLOC_CURRENT_FILE std::source_location::current().file_name()
@@ -203,6 +204,13 @@ namespace snmalloc
# define SNMALLOC_UNINITIALISED
#endif
// Check that the vendored STL is only used with GNU/Clang extensions.
#ifdef SNMALLOC_USE_SELF_VENDORED_STL
# if !defined(__GNUC__) && !defined(__clang__)
# error "cannot use vendored STL without GNU/Clang extensions"
# endif
#endif
namespace snmalloc
{
/**

View File

@@ -2,10 +2,10 @@
#include "bits.h"
#include "snmalloc/ds_core/defines.h"
#include "snmalloc/stl/array.h"
#include "snmalloc/stl/type_traits.h"
#include "snmalloc/stl/utility.h"
#include <array>
#include <stddef.h>
namespace snmalloc
@@ -50,7 +50,7 @@ namespace snmalloc
};
static constexpr size_t rlength = bits::next_pow2_const(length);
std::array<TWrap, rlength> array;
stl::Array<TWrap, rlength> array;
public:
constexpr const T& operator[](const size_t i) const
@@ -65,7 +65,7 @@ namespace snmalloc
};
#else
template<size_t length, typename T>
using ModArray = std::array<T, length>;
using ModArray = stl::Array<T, length>;
#endif
/**
@@ -105,7 +105,7 @@ namespace snmalloc
template<
typename Fn,
typename =
stl::enable_if_t<!stl::is_same_v<std::decay_t<Fn>, function_ref>>>
stl::enable_if_t<!stl::is_same_v<stl::decay_t<Fn>, function_ref>>>
function_ref(Fn&& fn)
{
data_ = static_cast<void*>(&fn);
@@ -144,7 +144,7 @@ namespace snmalloc
/**
* The buffer that is used to store the formatted output.
*/
std::array<char, BufferSize> buffer;
stl::Array<char, BufferSize> 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<char, 20> buf{{0}};
stl::Array<char, 20> buf{{0}};
const char digits[] = "0123456789";
for (long i = static_cast<long>(buf.size() - 1); i >= 0; i--)
{
@@ -284,7 +284,7 @@ namespace snmalloc
{
append_char('0');
append_char('x');
std::array<char, 16> buf{{0}};
stl::Array<char, 16> buf{{0}};
const char hexdigits[] = "0123456789abcdef";
// Length of string including null terminator
static_assert(sizeof(hexdigits) == 0x11);

View File

@@ -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)
{}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <array>
#include "snmalloc/stl/array.h"
#include <stddef.h>
#include <stdint.h>
@@ -259,7 +260,7 @@ namespace snmalloc
{
friend class RBTree;
std::array<RBStep, 128> path;
stl::Array<RBStep, 128> path;
size_t length = 0;
RBPath(typename Rep::Handle root)

View File

@@ -156,7 +156,7 @@ namespace snmalloc
*/
SNMALLOC_UNUSED_FUNCTION
static constexpr size_t LargestRegisterSize =
std::max(sizeof(uint64_t), sizeof(void*));
bits::max(sizeof(uint64_t), sizeof(void*));
/**
* Hook for architecture-specific optimisations.

View File

@@ -222,7 +222,7 @@ namespace snmalloc
pointer_offset(curr, rsize).template as_static<PreAllocObject>())
{
size_t insert_index = entropy.sample(count);
curr->next = std::exchange(
curr->next = stl::exchange(
pointer_offset(bumpptr, insert_index * rsize)
.template as_static<PreAllocObject>()
->next,

View File

@@ -701,11 +701,11 @@ namespace snmalloc
*/
// Pointer to the first element.
std::array<void*, LENGTH> head{nullptr};
stl::Array<void*, LENGTH> 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<void**, LENGTH> end{nullptr};
stl::Array<void**, LENGTH> end{nullptr};
[[nodiscard]] Object::BQueuePtr<BQueue>* cast_end(uint32_t ix) const
{
@@ -724,7 +724,7 @@ namespace snmalloc
}
SNMALLOC_NO_UNIQUE_ADDRESS
std::array<uint16_t, RANDOM ? 2 : (TRACK_LENGTH ? 1 : 0)> length{};
stl::Array<uint16_t, RANDOM ? 2 : (TRACK_LENGTH ? 1 : 0)> length{};
public:
constexpr Builder() = default;

View File

@@ -6,10 +6,9 @@
#include "metadata.h"
#include "remoteallocator.h"
#include "sizeclasstable.h"
#include "snmalloc/stl/array.h"
#include "snmalloc/stl/atomic.h"
#include <array>
namespace snmalloc
{
@@ -33,8 +32,8 @@ namespace snmalloc
{
static_assert(RINGS > 0);
std::array<freelist::Builder<false, true>, RINGS> open_builder;
std::array<address_t, RINGS> open_meta = {0};
stl::Array<freelist::Builder<false, true>, RINGS> open_builder;
stl::Array<address_t, RINGS> open_meta = {0};
SNMALLOC_FAST_PATH size_t
ring_set(typename Config::PagemapEntry::SlabMetadata* meta)
@@ -191,7 +190,7 @@ namespace snmalloc
template<typename Config>
struct RemoteDeallocCache
{
std::array<freelist::Builder<false>, REMOTE_SLOTS> list;
stl::Array<freelist::Builder<false>, REMOTE_SLOTS> list;
RemoteDeallocCacheBatchingImpl<Config> batching;

View File

@@ -16,6 +16,8 @@
# endif
#endif
// only define these if we are not using the vendored STL
#ifndef SNMALLOC_USE_SELF_VENDORED_STL
void* operator new(size_t size)
{
return snmalloc::libc::malloc(size);
@@ -111,3 +113,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

View File

@@ -4,8 +4,6 @@
# include "pal_consts.h"
# include "pal_ds.h"
# include <utility>
namespace snmalloc
{
/*

View File

@@ -3,6 +3,7 @@
#if defined(__linux__)
# include "../ds_core/ds_core.h"
# include "pal_posix.h"
# include "snmalloc/stl/array.h"
# include <string.h>
# include <sys/mman.h>
@@ -183,8 +184,8 @@ namespace snmalloc
// protected routine.
if (false == syscall_not_working.load(stl::memory_order_relaxed))
{
auto current = std::begin(buffer);
auto target = std::end(buffer);
auto current = stl::begin(buffer);
auto target = stl::end(buffer);
while (auto length = target - current)
{
// Reading data via syscall from system entropy pool.

View File

@@ -5,6 +5,7 @@
#if defined(SNMALLOC_BACKTRACE_HEADER)
# include SNMALLOC_BACKTRACE_HEADER
#endif
#include "snmalloc/stl/array.h"
#include "snmalloc/stl/utility.h"
#include <errno.h>
@@ -417,8 +418,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 = stl::begin(buffer);
auto target = stl::end(buffer);
while (auto length = static_cast<size_t>(target - current))
{
ret = read(fd, current, length);

7
src/snmalloc/stl/array.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#ifdef SNMALLOC_USE_SELF_VENDORED_STL
# include "snmalloc/stl/gnu/array.h"
#else
# include "snmalloc/stl/cxx/array.h"
#endif

View File

@@ -1,8 +1,6 @@
#pragma once
#include "snmalloc/stl/common.h"
#if SNMALLOC_USE_SELF_VENDORED_STL
#ifdef SNMALLOC_USE_SELF_VENDORED_STL
# include "snmalloc/stl/gnu/atomic.h"
#else
# include "snmalloc/stl/cxx/atomic.h"

View File

@@ -1,15 +0,0 @@
#pragma once
#include "snmalloc/ds_core/defines.h"
// Default on using the system STL.
#ifndef SNMALLOC_USE_SELF_VENDORED_STL
# define SNMALLOC_USE_SELF_VENDORED_STL 0
#endif
// Check that the vendored STL is only used with GNU/Clang extensions.
#if SNMALLOC_USE_SELF_VENDORED_STL
# if !defined(__GNUC__) && !defined(__clang__)
# error "cannot use vendored STL without GNU/Clang extensions"
# endif
#endif

View File

@@ -0,0 +1,15 @@
#pragma once
#include <array>
namespace snmalloc
{
namespace stl
{
template<typename T, size_t N>
using Array = std::array<T, N>;
using std::begin;
using std::end;
} // namespace stl
} // namespace snmalloc

View File

@@ -5,6 +5,7 @@ namespace snmalloc
namespace stl
{
using std::declval;
using std::exchange;
using std::forward;
using std::move;
template<class T1, class T2>

View File

@@ -0,0 +1,117 @@
#pragma once
#include "snmalloc/ds_core/defines.h"
#include <stddef.h>
namespace snmalloc
{
namespace stl
{
template<typename T, size_t N>
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<typename T, size_t N>
constexpr T* begin(Array<T, N>& a)
{
return a.begin();
}
template<typename T, size_t N>
constexpr T* end(Array<T, N>& a)
{
return a.end();
}
template<typename T, size_t N>
constexpr const T* begin(const Array<T, N>& a)
{
return a.begin();
}
template<typename T, size_t N>
constexpr const T* end(const Array<T, N>& a)
{
return a.end();
}
template<typename T, size_t N>
constexpr T* begin(T (&a)[N])
{
return &a[0];
}
template<typename T, size_t N>
constexpr T* end(T (&a)[N])
{
return &a[N];
}
template<typename T, size_t N>
constexpr const T* begin(const T (&a)[N])
{
return &a[0];
}
template<typename T, size_t N>
constexpr const T* end(const T (&a)[N])
{
return &a[N];
}
} // namespace stl
} // namespace snmalloc

View File

@@ -1,5 +1,6 @@
#pragma once
#include "snmalloc/ds_core/defines.h"
#include "snmalloc/stl/type_traits.h"
#include <stddef.h>

View File

@@ -1,5 +1,6 @@
#pragma once
#include "snmalloc/ds_core/defines.h"
#include "snmalloc/stl/type_traits.h"
// This is used by clang to provide better analysis of lifetimes.
@@ -64,5 +65,13 @@ namespace snmalloc
T1 first;
T2 second;
};
template<typename A, typename B = A>
constexpr SNMALLOC_FAST_PATH A exchange(A& obj, B&& new_value)
{
A old_value = move(obj);
obj = forward<B>(new_value);
return old_value;
}
} // namespace stl
} // namespace snmalloc

View File

@@ -1,8 +1,6 @@
#pragma once
#include "snmalloc/stl/common.h"
#if SNMALLOC_USE_SELF_VENDORED_STL
#ifdef SNMALLOC_USE_SELF_VENDORED_STL
# include "snmalloc/stl/gnu/type_traits.h"
#else
# include "snmalloc/stl/cxx/type_traits.h"

View File

@@ -1,8 +1,6 @@
#pragma once
#include "snmalloc/stl/common.h"
#if SNMALLOC_USE_SELF_VENDORED_STL
#ifdef SNMALLOC_USE_SELF_VENDORED_STL
# include "snmalloc/stl/gnu/utility.h"
#else
# include "snmalloc/stl/cxx/utility.h"

View File

@@ -30,6 +30,7 @@ int main()
# include <assert.h>
# include <csetjmp>
# include <initializer_list>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>

View File

@@ -1,3 +1,4 @@
#include <array>
#include <iostream>
#include <snmalloc/snmalloc.h>
#include <test/opt.h>
@@ -5,6 +6,7 @@
#include <test/xoroshiro.h>
#include <unordered_set>
#include <vector>
#if ((defined(__linux__) && !defined(__ANDROID__)) || defined(__sun)) || \
defined(__OpenBSD__) && !defined(SNMALLOC_QEMU_WORKAROUND)
/*

View File

@@ -2,6 +2,7 @@
# undef SNMALLOC_USE_PTHREAD_DESTRUCTORS
#endif
#include <new>
#include <snmalloc/snmalloc_core.h>
#include <test/setup.h>