diff --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp --- a/libcxxabi/src/stdlib_new_delete.cpp +++ b/libcxxabi/src/stdlib_new_delete.cpp @@ -12,6 +12,7 @@ #include <__memory/aligned_alloc.h> #include #include +#include <__utility/unreachable.h> #if !defined(_THROW_BAD_ALLOC) || !defined(_LIBCXXABI_WEAK) #error The _THROW_BAD_ALLOC and _LIBCXXABI_WEAK libc++ macros must \ @@ -39,28 +40,26 @@ #ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_alloc(); #else - break; + std::__libcpp_unreachable(); #endif } return p; } _LIBCXXABI_WEAK -void* -operator new(size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new(size); -#ifndef _LIBCXXABI_NO_EXCEPTIONS - } - catch (...) - { +void* operator new(size_t size, const std::nothrow_t&) noexcept { + if (size == 0) + size = 1; + void* p; + while ((p = ::malloc(size)) == nullptr) { + // If malloc fails and there is a new_handler, + // call it to try free up memory. + std::new_handler nh = std::get_new_handler(); + if (nh) + nh(); + else + break; } -#endif // _LIBCXXABI_NO_EXCEPTIONS return p; } @@ -72,23 +71,7 @@ } _LIBCXXABI_WEAK -void* -operator new[](size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new[](size); -#ifndef _LIBCXXABI_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCXXABI_NO_EXCEPTIONS - return p; -} +void* operator new[](size_t size, const std::nothrow_t& nothrow) noexcept { return ::operator new(size, nothrow); } _LIBCXXABI_WEAK void @@ -159,7 +142,7 @@ #ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_alloc(); #else - break; + std::__libcpp_unreachable(); #endif } } @@ -170,18 +153,26 @@ void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { - void* p = nullptr; -#ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new(size, alignment); -#ifndef _LIBCXXABI_NO_EXCEPTIONS - } - catch (...) - { + if (size == 0) + size = 1; + if (static_cast(alignment) < sizeof(void*)) + alignment = std::align_val_t(sizeof(void*)); + + // Try allocating memory. If allocation fails and there is a new_handler, + // call it to try free up memory, and try again until it succeeds, or until + // the new_handler decides to terminate. + // + // If allocation fails and there is no new_handler, we throw bad_alloc + // (or return nullptr if exceptions are disabled). + void* p; + while ((p = std::__libcpp_aligned_alloc(static_cast(alignment), size)) == nullptr) { + std::new_handler nh = std::get_new_handler(); + if (nh) + nh(); + else { + break; + } } -#endif // _LIBCXXABI_NO_EXCEPTIONS return p; } @@ -193,22 +184,8 @@ } _LIBCXXABI_WEAK -void* -operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new[](size, alignment); -#ifndef _LIBCXXABI_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCXXABI_NO_EXCEPTIONS - return p; +void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t& nothrow) noexcept { + return ::operator new(size, alignment, nothrow); } _LIBCXXABI_WEAK