#include "override.h"
#include "snmalloc/snmalloc.h"
#include <new>
#ifdef _WIN32
# ifdef __clang__
# define EXCEPTSPEC noexcept
# else
# define EXCEPTSPEC
# endif
#else
# ifdef _GLIBCXX_USE_NOEXCEPT
# define EXCEPTSPEC _GLIBCXX_USE_NOEXCEPT
# elif defined(_NOEXCEPT)
# define EXCEPTSPEC _NOEXCEPT
# else
# define EXCEPTSPEC
# endif
#endif
#ifndef SNMALLOC_USE_SELF_VENDORED_STL
namespace snmalloc
{
namespace handler
{
class Base
{
public:
static void*
success(void* p, size_t size, bool secondary_allocator = false)
{
UNUSED(secondary_allocator, size);
SNMALLOC_ASSERT(p != nullptr);
SNMALLOC_ASSERT(
secondary_allocator ||
is_start_of_object(size_to_sizeclass_full(size), address_cast(p)));
return p;
}
};
class Throw : public Base
{
public:
static void* failure(size_t size)
{
auto new_handler = std::get_new_handler();
if (new_handler != nullptr)
{
new_handler();
return alloc<Throw>(size);
}
throw std::bad_alloc();
}
};
class NoThrow : public Base
{
public:
static void* failure(size_t size) noexcept
{
auto new_handler = std::get_new_handler();
if (new_handler != nullptr)
{
try
{
new_handler();
}
catch (...)
{
return nullptr;
}
return alloc<NoThrow>(size);
}
errno = ENOMEM;
return nullptr;
}
};
}
}
SNMALLOC_EXPORT void* operator new(size_t size)
{
return snmalloc::alloc<snmalloc::handler::Throw>(size);
}
SNMALLOC_EXPORT void* operator new[](size_t size)
{
return snmalloc::alloc<snmalloc::handler::Throw>(size);
}
SNMALLOC_EXPORT void* operator new(size_t size, const std::nothrow_t&) noexcept
{
return snmalloc::alloc<snmalloc::handler::NoThrow>(size);
}
SNMALLOC_EXPORT void*
operator new[](size_t size, const std::nothrow_t&) noexcept
{
return snmalloc::alloc<snmalloc::handler::NoThrow>(size);
}
SNMALLOC_EXPORT void operator delete(void* p) EXCEPTSPEC
{
snmalloc::libc::free(p);
}
SNMALLOC_EXPORT void operator delete(void* p, size_t size) EXCEPTSPEC
{
snmalloc::libc::free_sized(p, size);
}
SNMALLOC_EXPORT void operator delete(void* p, const std::nothrow_t&) noexcept
{
snmalloc::libc::free(p);
}
SNMALLOC_EXPORT void operator delete[](void* p) EXCEPTSPEC
{
snmalloc::libc::free(p);
}
SNMALLOC_EXPORT void operator delete[](void* p, size_t size) EXCEPTSPEC
{
snmalloc::libc::free_sized(p, size);
}
SNMALLOC_EXPORT void operator delete[](void* p, const std::nothrow_t&) noexcept
{
snmalloc::libc::free(p);
}
SNMALLOC_EXPORT void* operator new(size_t size, std::align_val_t val)
{
size = snmalloc::aligned_size(size_t(val), size);
return snmalloc::alloc<snmalloc::handler::Throw>(size);
}
SNMALLOC_EXPORT void* operator new[](size_t size, std::align_val_t val)
{
size = snmalloc::aligned_size(size_t(val), size);
return snmalloc::alloc<snmalloc::handler::Throw>(size);
}
SNMALLOC_EXPORT void*
operator new(size_t size, std::align_val_t val, const std::nothrow_t&) noexcept
{
size = snmalloc::aligned_size(size_t(val), size);
return snmalloc::alloc<snmalloc::handler::NoThrow>(size);
}
SNMALLOC_EXPORT void* operator new[](
size_t size, std::align_val_t val, const std::nothrow_t&) noexcept
{
size = snmalloc::aligned_size(size_t(val), size);
return snmalloc::alloc<snmalloc::handler::NoThrow>(size);
}
SNMALLOC_EXPORT void operator delete(void* p, std::align_val_t) EXCEPTSPEC
{
snmalloc::libc::free(p);
}
SNMALLOC_EXPORT void operator delete[](void* p, std::align_val_t) EXCEPTSPEC
{
snmalloc::libc::free(p);
}
SNMALLOC_EXPORT 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);
}
SNMALLOC_EXPORT 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