Skip to content
Merged
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
87 changes: 48 additions & 39 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ endif()
function(add_warning_flags name)
target_compile_options(${name} PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/Zi /W4 /WX /wd4127 /wd4324 /wd4201>
$<$<NOT:$<OR:$<CXX_COMPILER_ID:MSVC>,$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>>:-fno-exceptions -fno-rtti -Wall -Wextra -Werror -Wundef>
$<$<NOT:$<OR:$<CXX_COMPILER_ID:MSVC>,$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>>:-fno-rtti -Wall -Wextra -Werror -Wundef>
$<$<CXX_COMPILER_ID:Clang>:-Wsign-conversion -Wconversion>)
target_link_options(${name} PRIVATE
$<$<BOOL:${SNMALLOC_LINKER_SUPPORT_NO_ALLOW_SHLIB_UNDEF}>:-Wl,--no-undefined>
Expand Down Expand Up @@ -503,29 +503,29 @@ if(NOT SNMALLOC_HEADER_ONLY_LIBRARY)
message(WARNING "Compiler does not support `-march=native` required by SNMALLOC_OPTIMISE_FOR_CURRENT_MACHINE")
set(SNMALLOC_OPTIMISE_FOR_CURRENT_MACHINE FALSE)
endif()
endif()
endif()


function(add_shim name type)
add_library(${name} ${type} ${ARGN})
function(compile name TYPE ${ARGN})
add_library(${name} ${TYPE} ${ARGN})
target_link_libraries(${name} snmalloc)
set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET hidden INTERPROCEDURAL_OPTIMIZATION ${SNMALLOC_COMPILER_SUPPORT_IPO})
target_compile_definitions(${name} PRIVATE "SNMALLOC_USE_${SNMALLOC_CLEANUP}")

if(MSVC)
target_compile_definitions(${name} PRIVATE -D_HAS_EXCEPTIONS=0)
endif()

add_warning_flags(${name})
if(NOT MSVC)
target_compile_definitions(${name} PRIVATE "SNMALLOC_EXPORT=__attribute__((visibility(\"default\")))")
target_compile_options(${name} PRIVATE
-fomit-frame-pointer -ffunction-sections)
set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET hidden INTERPROCEDURAL_OPTIMIZATION ${SNMALLOC_COMPILER_SUPPORT_IPO})
# Make debugging harder, and code faster.
target_compile_options(${name} PRIVATE -fomit-frame-pointer)

set_property(TARGET ${name} PROPERTY POSITION_INDEPENDENT_CODE ON)

# Check for prefetch write support.
check_cxx_compiler_flag("-Werror -Wextra -Wall -mprfchw" SUPPORT_PREFETCH_WRITE)
if (SUPPORT_PREFETCH_WRITE)
target_compile_options(${name} PRIVATE -mprfchw)
endif()

# Static TLS model is unsupported on Haiku.
if (SNMALLOC_STATIC_MODE_TLS)
target_compile_options(${name} PRIVATE -ftls-model=initial-exec)
Expand All @@ -536,18 +536,8 @@ endif()
target_compile_options(${name} PRIVATE -march=native)
endif()

# Ensure that we do not link against C++ stdlib when compiling shims.
# If the compiler supports excluding the C++ stdlib implementation, use
# it. Otherwise, fall back to linking the library as if it were C, which
# has roughly the same effect.
if (NOT ${SNMALLOC_CLEANUP} STREQUAL CXX11_DESTRUCTORS)
if (SNMALLOC_LINKER_SUPPORT_NOSTDLIBXX)
target_link_options(${name} PRIVATE -nostdlib++)
else()
set_target_properties(${name} PROPERTIES LINKER_LANGUAGE C)
endif()
endif()
# Remove all the duplicate new/malloc and free/delete definitions
target_compile_options(${name} PRIVATE -ffunction-sections)
target_link_options(${name} PRIVATE $<$<BOOL:${LLD_WORKS}>:$<$<BOOL:${SNMALLOC_LINK_ICF}>:-Wl,--icf=all> -fuse-ld=lld>)
endif()

Expand All @@ -556,40 +546,59 @@ endif()
target_compile_definitions(${name} PRIVATE
SNMALLOC_PAGEID=$<IF:$<BOOL:${SNMALLOC_PAGEID}>,true,false>)

install(TARGETS ${name} EXPORT snmallocConfig)
if(MSVC)
else()
# We can't do --nostdlib++ as we are using exceptions, but we
# can make it a static dependency, which we aren't really using
# as the interesting stuff for exceptions is in libgcc_s
target_link_options(${name} PRIVATE -static-libstdc++)
endif()

if (SNMALLOC_RUST_LIBC_API)
target_compile_definitions(${name} PRIVATE SNMALLOC_RUST_LIBC_API)
endif()
install(TARGETS ${name} EXPORT snmallocConfig)
endfunction()

set(SHIM_FILES src/snmalloc/override/malloc.cc src/snmalloc/override/new.cc)
set(SHIM_FILES_MEMCPY src/snmalloc/override/memcpy.cc)
# Various files for overriding libc/rust behaviours.
set(MALLOC src/snmalloc/override/malloc.cc)
set(NEW src/snmalloc/override/new.cc)
set(MEMCPY src/snmalloc/override/memcpy.cc)
set(RUST src/snmalloc/override/rust.cc)

add_shim(snmalloc-new-override STATIC src/snmalloc/override/new.cc)
set(ALLOC ${MALLOC} ${NEW})
set(ALL ${ALLOC} ${MEMCPY})

if (SNMALLOC_STATIC_LIBRARY)
add_shim(snmallocshim-static STATIC ${SHIM_FILES})
compile(snmallocshim-static STATIC ${ALLOC})
target_compile_definitions(snmallocshim-static PRIVATE
SNMALLOC_STATIC_LIBRARY_PREFIX=${SNMALLOC_STATIC_LIBRARY_PREFIX})
endif ()

compile(snmalloc-new-override STATIC ${NEW})

if(NOT WIN32)
add_shim(snmallocshim SHARED ${SHIM_FILES})
compile(snmallocshim SHARED ${ALLOC})

if (SNMALLOC_MEMCPY_OVERRIDE)
add_shim(snmallocshim-checks-memcpy-only SHARED ${SHIM_FILES} ${SHIM_FILES_MEMCPY})
add_shim(snmallocshim-checks SHARED ${SHIM_FILES} ${SHIM_FILES_MEMCPY})
compile(snmallocshim-checks-memcpy-only SHARED ${ALL})
compile(snmallocshim-checks SHARED ${ALL})
else()
add_shim(snmallocshim-checks SHARED ${SHIM_FILES})
compile(snmallocshim-checks SHARED ${ALLOC})
endif()
target_compile_definitions(snmallocshim-checks PRIVATE SNMALLOC_CHECK_CLIENT)

compile(snmalloc-minimal SHARED ${MALLOC})
target_compile_options(snmalloc-minimal PRIVATE -fno-exceptions)
if (SNMALLOC_LINKER_SUPPORT_NOSTDLIBXX AND NOT ${SNMALLOC_CLEANUP} STREQUAL CXX11_DESTRUCTORS)
target_compile_options(snmalloc-minimal PRIVATE -fno-exceptions -nostdlib++)
endif ()
endif()

if(SNMALLOC_RUST_SUPPORT)
add_shim(snmallocshim-rust STATIC src/snmalloc/override/rust.cc)
add_shim(snmallocshim-checks-rust STATIC src/snmalloc/override/rust.cc)
compile(snmallocshim-rust STATIC ${RUST})
compile(snmallocshim-checks-rust STATIC ${RUST})
target_compile_definitions(snmallocshim-checks-rust PRIVATE SNMALLOC_CHECK_CLIENT)
if (SNMALLOC_RUST_LIBC_API)
target_compile_definitions(snmallocshim-rust PRIVATE SNMALLOC_RUST_LIBC_API)
target_compile_definitions(snmallocshim-checks-rust PRIVATE SNMALLOC_RUST_LIBC_API)
endif()
endif()

if (SNMALLOC_BUILD_TESTING)
Expand Down Expand Up @@ -625,7 +634,7 @@ endif()

foreach (MITIGATION ${MITIGATIONS})
set(DEFINES "SNMALLOC_CHECK_CLIENT_MITIGATIONS=${MITIGATION}")
add_shim(snmallocshim-${MITIGATION} SHARED ${SHIM_FILES})
compile(snmallocshim-${MITIGATION} SHARED ${ALLOC})
target_compile_definitions(snmallocshim-${MITIGATION} PRIVATE ${DEFINES})
if (SNMALLOC_BUILD_TESTING)
make_tests(${MITIGATION} ${DEFINES})
Expand All @@ -640,7 +649,7 @@ endif()
set(MITIGATIONSET "${MITIGATIONSET}+${MITIGATION}")
message(STATUS "MITIGATIONSET: ${COUNT} -> ${MITIGATIONSET}")
set(DEFINES "-DSNMALLOC_CHECK_CLIENT_MITIGATIONS=${MITIGATIONSET}")
add_shim(snmallocshim-${MITIGATIONNAME} SHARED ${SHIM_FILES})
compile(snmallocshim-${MITIGATIONNAME} SHARED ${ALLOC})
target_compile_definitions(snmallocshim-${MITIGATIONNAME} PRIVATE ${DEFINES})
if (SNMALLOC_BUILD_TESTING)
make_tests(${MITIGATIONNAME} ${DEFINES})
Expand Down
52 changes: 29 additions & 23 deletions src/snmalloc/mem/corealloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace snmalloc
return p;
}

static void* failure(size_t size)
static void* failure(size_t size) noexcept
{
UNUSED(size);
// If we are here, then the allocation failed.
Expand Down Expand Up @@ -401,25 +401,25 @@ namespace snmalloc
* the stack as often closing over the arguments would cause less good
* codegen.
*/
template<typename Action, typename... Args>
template<bool noexc, typename Action, typename... Args>
SNMALLOC_FAST_PATH decltype(auto)
handle_message_queue(Action action, Args... args)
handle_message_queue(Action action, Args... args) noexcept(noexc)
{
// Inline the empty check, but not necessarily the full queue handling.
if (SNMALLOC_LIKELY(!has_messages()))
{
return action(args...);
}

return handle_message_queue_slow(action, args...);
return handle_message_queue_slow<noexc>(action, args...);
}

/**
* Process remote frees into this allocator.
*/
template<typename Action, typename... Args>
template<bool noexc, typename Action, typename... Args>
SNMALLOC_SLOW_PATH decltype(auto)
handle_message_queue_slow(Action action, Args... args)
handle_message_queue_slow(Action action, Args... args) noexcept(noexc)
{
bool need_post = false;
size_t bytes_freed = 0;
Expand Down Expand Up @@ -602,7 +602,8 @@ namespace snmalloc
* required. It is defaulted to do nothing.
*/
template<typename Conts = Uninit, typename CheckInit = CheckInitNoOp>
SNMALLOC_FAST_PATH ALLOCATOR void* alloc(size_t size)
SNMALLOC_FAST_PATH ALLOCATOR void*
alloc(size_t size) noexcept(noexcept(Conts::failure(0)))
{
// Perform the - 1 on size, so that zero wraps around and ends up on
// slow path.
Expand All @@ -621,7 +622,8 @@ namespace snmalloc
* Fast allocation for small objects.
*/
template<typename Conts, typename CheckInit>
SNMALLOC_FAST_PATH void* small_alloc(size_t size)
SNMALLOC_FAST_PATH void*
small_alloc(size_t size) noexcept(noexcept(Conts::failure(0)))
{
auto domesticate =
[this](freelist::QueuePtr p) SNMALLOC_FAST_PATH_LAMBDA {
Expand All @@ -637,7 +639,7 @@ namespace snmalloc
return finish_alloc<Conts>(p, size);
}

return handle_message_queue(
return handle_message_queue<noexcept(Conts::failure(0))>(
[](
Allocator* alloc,
smallsizeclass_t sizeclass,
Expand All @@ -661,8 +663,8 @@ namespace snmalloc
* register.
*/
template<typename Conts, typename CheckInit>
static SNMALLOC_SLOW_PATH void*
alloc_not_small(size_t size, Allocator* self)
static SNMALLOC_SLOW_PATH void* alloc_not_small(
size_t size, Allocator* self) noexcept(noexcept(Conts::failure(0)))
{
if (size == 0)
{
Expand All @@ -672,7 +674,7 @@ namespace snmalloc
return self->small_alloc<Conts, CheckInit>(1);
}

return self->handle_message_queue(
return self->template handle_message_queue<noexcept(Conts::failure(0))>(
[](Allocator* self, size_t size) SNMALLOC_FAST_PATH_LAMBDA {
return CheckInit::check_init(
[self, size]() SNMALLOC_FAST_PATH_LAMBDA {
Expand Down Expand Up @@ -739,7 +741,9 @@ namespace snmalloc

template<typename Conts, typename CheckInit>
SNMALLOC_FAST_PATH void* small_refill(
smallsizeclass_t sizeclass, freelist::Iter<>& fast_free_list, size_t size)
smallsizeclass_t sizeclass,
freelist::Iter<>& fast_free_list,
size_t size) noexcept(noexcept(Conts::failure(0)))
{
void* result = Config::SecondaryAllocator::allocate(
[size]() -> stl::Pair<size_t, size_t> {
Expand Down Expand Up @@ -809,7 +813,9 @@ namespace snmalloc

template<typename Conts, typename CheckInit>
SNMALLOC_SLOW_PATH void* small_refill_slow(
smallsizeclass_t sizeclass, freelist::Iter<>& fast_free_list, size_t size)
smallsizeclass_t sizeclass,
freelist::Iter<>& fast_free_list,
size_t size) noexcept(noexcept(Conts::failure(0)))
{
return CheckInit::check_init(
[this, size, sizeclass, &fast_free_list]() SNMALLOC_FAST_PATH_LAMBDA {
Expand Down Expand Up @@ -994,7 +1000,7 @@ namespace snmalloc
* deallocation to the other allocators.
***************************************************************************/
template<typename CheckInit = CheckInitNoOp>
SNMALLOC_FAST_PATH void dealloc(void* p_raw)
SNMALLOC_FAST_PATH void dealloc(void* p_raw) noexcept
{
#ifdef __CHERI_PURE_CAPABILITY__
/*
Expand Down Expand Up @@ -1043,7 +1049,7 @@ namespace snmalloc

SNMALLOC_FAST_PATH void dealloc_local_object(
CapPtr<void, capptr::bounds::Alloc> p,
const typename Config::PagemapEntry& entry)
const typename Config::PagemapEntry& entry) noexcept
{
auto meta = entry.get_slab_metadata();

Expand Down Expand Up @@ -1078,7 +1084,7 @@ namespace snmalloc
SNMALLOC_SLOW_PATH void dealloc_local_object_slow(
capptr::Alloc<void> p,
const PagemapEntry& entry,
BackendSlabMetadata* meta)
BackendSlabMetadata* meta) noexcept
{
// TODO: Handle message queue on this path?

Expand Down Expand Up @@ -1273,8 +1279,8 @@ namespace snmalloc
}

template<typename CheckInit>
SNMALLOC_FAST_PATH void
dealloc_remote(const PagemapEntry& entry, capptr::Alloc<void> p_tame)
SNMALLOC_FAST_PATH void dealloc_remote(
const PagemapEntry& entry, capptr::Alloc<void> p_tame) noexcept
{
if (SNMALLOC_LIKELY(entry.is_owned()))
{
Expand Down Expand Up @@ -1327,8 +1333,8 @@ namespace snmalloc
* as we might acquire the originating allocator.
*/
template<typename CheckInit>
SNMALLOC_SLOW_PATH void
dealloc_remote_slow(const PagemapEntry& entry, capptr::Alloc<void> p)
SNMALLOC_SLOW_PATH void dealloc_remote_slow(
const PagemapEntry& entry, capptr::Alloc<void> p) noexcept
{
CheckInit::check_init(
[this, &entry, p]() SNMALLOC_FAST_PATH_LAMBDA {
Expand All @@ -1344,7 +1350,7 @@ namespace snmalloc

post();
},
[](Allocator* a, void* p) {
[](Allocator* a, void* p) SNMALLOC_FAST_PATH_LAMBDA {
// Recheck what kind of dealloc we should do in case the allocator
// we get from lazy_init is the originating allocator.
a->dealloc(p); // TODO don't double count statistics
Expand Down Expand Up @@ -1385,7 +1391,7 @@ namespace snmalloc
// Process incoming message queue
// Loop as normally only processes a batch
while (has_messages())
handle_message_queue([]() {});
handle_message_queue<true>([]() {});
}

auto& key = freelist::Object::key_root;
Expand Down
2 changes: 1 addition & 1 deletion src/snmalloc/mem/ticker.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace snmalloc
* how many calls for the next time we hit the slow path.
*/
template<typename T = void*>
SNMALLOC_SLOW_PATH T check_tick_slow(T p = nullptr)
SNMALLOC_SLOW_PATH T check_tick_slow(T p = nullptr) noexcept
{
uint64_t now_ms = PAL::time_in_ms();

Expand Down
Loading
Loading