Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update snmalloc from 0.5.0 to 0.5.2 #2114

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions 3rdparty/snmalloc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ macro(clangformat_targets)
else ()
message(STATUS "Generating clangformat target using ${CLANG_FORMAT}")
file(GLOB_RECURSE ALL_SOURCE_FILES *.cc *.h *.hh)
# clangformat does not yet understand concepts well; for the moment, don't
# ask it to format them. See https://reviews.llvm.org/D79773
list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX "src/pal/pal_concept\.h$")
add_custom_target(
clangformat
COMMAND ${CLANG_FORMAT}
Expand Down Expand Up @@ -169,13 +172,14 @@ if(NOT DEFINED SNMALLOC_ONLY_HEADER_LIBRARY)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
else()
add_compile_options(-fno-exceptions -fno-rtti -g -fomit-frame-pointer)
# Static TLS model unsupported on Haiku
# Static TLS model is unsupported on Haiku.
# All symbols are always dynamic on haiku and -rdynamic is redundant (and unsupported).
if (NOT CMAKE_SYSTEM_NAME MATCHES "Haiku")
add_compile_options(-ftls-model=initial-exec)
endif()
if(SNMALLOC_CI_BUILD OR (${CMAKE_BUILD_TYPE} MATCHES "Debug"))
# Get better stack traces in CI and Debug.
target_link_libraries(snmalloc_lib INTERFACE "-rdynamic")
if(SNMALLOC_CI_BUILD OR (${CMAKE_BUILD_TYPE} MATCHES "Debug"))
# Get better stack traces in CI and Debug.
target_link_libraries(snmalloc_lib INTERFACE "-rdynamic")
endif()
endif()

if(SNMALLOC_OPTIMISE_FOR_CURRENT_MACHINE)
Expand Down Expand Up @@ -255,7 +259,7 @@ if(NOT DEFINED SNMALLOC_ONLY_HEADER_LIBRARY)
add_shim(snmallocshim SHARED ${SHARED_FILES})
add_shim(snmallocshim-1mib SHARED ${SHARED_FILES})
add_shim(snmallocshim-16mib SHARED ${SHARED_FILES})
target_compile_definitions(snmallocshim-16mib PRIVATE SNMALOC_USE_LARGE_CHUNKS)
target_compile_definitions(snmallocshim-16mib PRIVATE SNMALLOC_USE_LARGE_CHUNKS)
# Build a shim with some settings from oe.
add_shim(snmallocshim-oe SHARED ${SHARED_FILES})
oe_simulate(snmallocshim-oe)
Expand All @@ -276,7 +280,18 @@ if(NOT DEFINED SNMALLOC_ONLY_HEADER_LIBRARY)
foreach(TEST_CATEGORY ${TEST_CATEGORIES})
subdirlist(TESTS ${TESTDIR}/${TEST_CATEGORY})
foreach(TEST ${TESTS})
foreach(SUPER_SLAB_SIZE 1;16;oe)
if (WIN32
OR (CMAKE_SYSTEM_NAME STREQUAL NetBSD)
OR (CMAKE_SYSTEM_NAME STREQUAL OpenBSD)
OR (CMAKE_SYSTEM_NAME STREQUAL DragonFly))
# Windows does not support aligned allocation well enough
# for pass through.
# NetBSD, OpenBSD and DragonFlyBSD do not support malloc*size calls.
set(FLAVOURS 1;16;oe)
else()
set(FLAVOURS 1;16;oe;malloc)
endif()
foreach(SUPER_SLAB_SIZE ${FLAVOURS})
unset(SRC)
aux_source_directory(${TESTDIR}/${TEST_CATEGORY}/${TEST} SRC)
set(TESTNAME "${TEST_CATEGORY}-${TEST}-${SUPER_SLAB_SIZE}")
Expand All @@ -285,9 +300,12 @@ if(NOT DEFINED SNMALLOC_ONLY_HEADER_LIBRARY)
if (${SUPER_SLAB_SIZE} EQUAL 16)
target_compile_definitions(${TESTNAME} PRIVATE SNMALLOC_USE_LARGE_CHUNKS)
endif()
if (${SUPER_SLAB_SIZE} EQUAL oe)
if (${SUPER_SLAB_SIZE} STREQUAL "oe")
oe_simulate(${TESTNAME})
endif()
if (${SUPER_SLAB_SIZE} STREQUAL "malloc")
target_compile_definitions(${TESTNAME} PRIVATE SNMALLOC_PASS_THROUGH)
endif()
target_link_libraries(${TESTNAME} snmalloc_lib)
if (${TEST} MATCHES "release-.*")
message(STATUS "Adding test: ${TESTNAME} only for release configs")
Expand Down
12 changes: 6 additions & 6 deletions 3rdparty/snmalloc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,20 @@ your system.
The PAL must implement the following methods:

```c++
[[noreturn]] void error(const char* const str) noexcept;
[[noreturn]] static void error(const char* const str) noexcept;
```
Report a fatal error and exit.

```c++
void notify_not_using(void* p, size_t size) noexcept;
static void notify_not_using(void* p, size_t size) noexcept;
```
Notify the system that the range of memory from `p` to `p` + `size` is no
longer in use, allowing the underlying physical pages to recycled for other
purposes.

```c++
template<ZeroMem zero_mem>
void notify_using(void* p, size_t size) noexcept;
static void notify_using(void* p, size_t size) noexcept;
```
Notify the system that the range of memory from `p` to `p` + `size` is now in use.
On systems that lazily provide physical memory to virtual mappings, this
Expand All @@ -183,7 +183,7 @@ responsible for ensuring that the newly requested memory is full of zeros.

```c++
template<bool page_aligned = false>
void zero(void* p, size_t size) noexcept;
static void zero(void* p, size_t size) noexcept;
```
Zero the range of memory from `p` to `p` + `size`.
This may be a simple `memset` call, but the `page_aligned` template parameter
Expand All @@ -194,8 +194,8 @@ pages, rather than zeroing them synchronously in this call

```c++
template<bool committed>
void* reserve_aligned(size_t size) noexcept;
std::pair<void*, size_t> reserve_at_least(size_t size) noexcept;
static void* reserve_aligned(size_t size) noexcept;
static std::pair<void*, size_t> reserve_at_least(size_t size) noexcept;
```
Only one of these needs to be implemented, depending on whether the underlying
system can provide strongly aligned memory regions.
Expand Down
7 changes: 7 additions & 0 deletions 3rdparty/snmalloc/src/ds/aba.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ namespace snmalloc
Linked old;
ABA* parent;

/*
* MSVC apparently does not like the implicit constructor it creates when
* asked to interpret its input as C++20; it rejects the construction up
* in read(), above. Help it out by making the constructor explicit.
*/
Cmp(Linked old, ABA* parent) : old(old), parent(parent) {}

T* ptr()
{
return old.ptr;
Expand Down
45 changes: 30 additions & 15 deletions 3rdparty/snmalloc/src/ds/bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
#include <atomic>
#include <cstdint>
#include <type_traits>
#if defined(_WIN32) && defined(__GNUC__)
# define USE_CLZLL
#endif
#ifdef pause
# undef pause
#endif
Expand Down Expand Up @@ -76,10 +73,19 @@ namespace snmalloc

return BITS - index - 1;
# endif
#elif defined(USE_CLZLL)
return static_cast<size_t>(__builtin_clzll(x));
#else
return static_cast<size_t>(__builtin_clzl(x));
if constexpr (std::is_same_v<unsigned long, std::size_t>)
{
return static_cast<size_t>(__builtin_clzl(x));
}
else if constexpr (std::is_same_v<unsigned long long, std::size_t>)
{
return static_cast<size_t>(__builtin_clzll(x));
}
else if constexpr (std::is_same_v<unsigned int, std::size_t>)
{
return static_cast<size_t>(__builtin_clz(x));
}
#endif
}

Expand Down Expand Up @@ -142,17 +148,25 @@ namespace snmalloc

inline size_t ctz(size_t x)
{
#if __has_builtin(__builtin_ctzl)
return static_cast<size_t>(__builtin_ctzl(x));
#elif defined(_MSC_VER)
#if defined(_MSC_VER)
# ifdef SNMALLOC_VA_BITS_64
return _tzcnt_u64(x);
# else
return _tzcnt_u32((uint32_t)x);
# endif
#else
// Probably GCC at this point.
return static_cast<size_t>(__builtin_ctzl(x));
if constexpr (std::is_same_v<unsigned long, std::size_t>)
{
return static_cast<size_t>(__builtin_ctzl(x));
}
else if constexpr (std::is_same_v<unsigned long long, std::size_t>)
{
return static_cast<size_t>(__builtin_ctzll(x));
}
else if constexpr (std::is_same_v<unsigned int, std::size_t>)
{
return static_cast<size_t>(__builtin_ctz(x));
}
#endif
}

Expand Down Expand Up @@ -227,18 +241,19 @@ namespace snmalloc
return BITS - clz_const(x - 1);
}

static SNMALLOC_FAST_PATH size_t align_down(size_t value, size_t alignment)
constexpr SNMALLOC_FAST_PATH size_t
align_down(size_t value, size_t alignment)
{
SNMALLOC_ASSERT(next_pow2(alignment) == alignment);
SNMALLOC_ASSERT(next_pow2_const(alignment) == alignment);

size_t align_1 = alignment - 1;
value &= ~align_1;
return value;
}

static inline size_t align_up(size_t value, size_t alignment)
constexpr SNMALLOC_FAST_PATH size_t align_up(size_t value, size_t alignment)
{
SNMALLOC_ASSERT(next_pow2(alignment) == alignment);
SNMALLOC_ASSERT(next_pow2_const(alignment) == alignment);

size_t align_1 = alignment - 1;
value += align_1;
Expand Down
40 changes: 40 additions & 0 deletions 3rdparty/snmalloc/src/ds/concept.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

/**
* C++20 concepts are referenced as if they were types in declarations within
* template parameters (e.g. "template<FooConcept Foo> ..."). That is, they
* take the place of the "typename"/"class" keyword on template parameters.
* If the compiler understands concepts, this macro expands as its argument;
* otherwise, it expands to the keyword "typename", so snmalloc templates that
* use concept-qualified parameters should use this to remain compatible across
* C++ versions: "template<SNMALLOC_CONCEPT(FooConcept) Foo>"
*/
#ifdef __cpp_concepts
# define SNMALLOC_CONCEPT(c) c
#else
# define SNMALLOC_CONCEPT(c) typename
#endif

#ifdef __cpp_concepts
namespace snmalloc
{
/**
* C++20 concepts are more than just new syntax; there's a new support
* library specified as well. As C++20 is quite new, however, there are some
* environments, notably Clang, that understand the syntax but do not yet
* offer the library. Fortunately, alternate pronouciations are possible.
*/
# ifdef _cpp_lib_concepts
/**
* ConceptSame<T,U> is true if T and U are the same type and false otherwise.
* When specifying a concept, use ConceptSame<U> to indicate that an
* expression must evaluate precisely to the type U.
*/
template<typename T, typename U>
concept ConceptSame = std::same_as<T, U>;
# else
template<typename T, typename U>
concept ConceptSame = std::is_same<T, U>::value;
# endif
} // namespace snmalloc
#endif
9 changes: 9 additions & 0 deletions 3rdparty/snmalloc/src/ds/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ namespace snmalloc
}
#endif

#define SNMALLOC_CHECK(expr) \
{ \
if (!(expr)) \
{ \
snmalloc::error("Check fail: " #expr " in " __FILE__ \
" on " TOSTRING(__LINE__)); \
} \
}

#ifndef NDEBUG
# define SNMALLOC_ASSUME(x) SNMALLOC_ASSERT(x)
#else
Expand Down
27 changes: 12 additions & 15 deletions 3rdparty/snmalloc/src/mem/address_space.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ namespace snmalloc
* It cannot unreserve memory, so this does not require the
* usual complexity of a buddy allocator.
*/
template<typename Pal>
class AddressSpaceManager : public Pal
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
class AddressSpaceManager
{
/**
* Stores the blocks of address space
Expand Down Expand Up @@ -160,7 +160,7 @@ namespace snmalloc
auto page_start = pointer_align_down<OS_PAGE_SIZE, char>(base);
auto page_end =
pointer_align_up<OS_PAGE_SIZE, char>(pointer_offset(base, size));
Pal::template notify_using<NoZero>(
PAL::template notify_using<NoZero>(
page_start, static_cast<size_t>(page_end - page_start));
}

Expand All @@ -178,11 +178,10 @@ namespace snmalloc
SNMALLOC_ASSERT(bits::next_pow2(size) == size);
SNMALLOC_ASSERT(size >= sizeof(void*));

if constexpr (pal_supports<AlignedAllocation, Pal>)
if constexpr (pal_supports<AlignedAllocation, PAL>)
{
if (size >= Pal::minimum_alloc_size)
return static_cast<Pal*>(this)->template reserve_aligned<committed>(
size);
if (size >= PAL::minimum_alloc_size)
return PAL::template reserve_aligned<committed>(size);
}

void* res;
Expand All @@ -194,20 +193,18 @@ namespace snmalloc
// Allocation failed ask OS for more memory
void* block;
size_t block_size;
if constexpr (pal_supports<AlignedAllocation, Pal>)
if constexpr (pal_supports<AlignedAllocation, PAL>)
{
block_size = Pal::minimum_alloc_size;
block = static_cast<Pal*>(this)->template reserve_aligned<false>(
block_size);
block_size = PAL::minimum_alloc_size;
block = PAL::template reserve_aligned<false>(block_size);
}
else
{
// Need at least 2 times the space to guarantee alignment.
// Hold lock here as a race could cause additional requests to
// the Pal, and this could lead to suprious OOM. This is
// particularly bad if the Pal gives all the memory on first call.
auto block_and_size =
static_cast<Pal*>(this)->reserve_at_least(size * 2);
// the PAL, and this could lead to suprious OOM. This is
// particularly bad if the PAL gives all the memory on first call.
auto block_and_size = PAL::reserve_at_least(size * 2);
block = block_and_size.first;
block_size = block_and_size.second;

Expand Down
Loading