forked from OSchip/llvm-project
[libc++] Factor out common logic for calling aligned allocation
There were a couple of places where we needed to call the underlying platform's aligned allocation/deallocation function. Instead of having the same logic all over the place, extract the logic into a pair of helper functions __libcpp_aligned_alloc and __libcpp_aligned_free. The code in libcxxabi/src/fallback_malloc.cpp looks like it could be simplified after this change -- I purposefully did not simplify it further to keep this change as straightforward as possible, since it is touching very important parts of the library. Also, the changes in libcxx/src/new.cpp and libcxxabi/src/stdlib_new_delete.cpp are basically the same -- I just kept both source files in sync. The underlying reason for this refactoring is to make it easier to support platforms that provide aligned allocation through C11's aligned_alloc function instead of posix_memalign. After this change, we'll only have to add support for that in a single place. Differential Revision: https://reviews.llvm.org/D91379
This commit is contained in:
parent
cbf336ad76
commit
a78aaa1ad5
|
@ -88,13 +88,11 @@ void operator delete[](void* ptr, void*) noexcept;
|
|||
|
||||
#include <__config>
|
||||
#include <__availability>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <version>
|
||||
#ifdef _LIBCPP_NO_EXCEPTIONS
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_ABI_VCRUNTIME)
|
||||
#include <new.h>
|
||||
|
@ -303,6 +301,36 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate_unsized(void* __ptr, s
|
|||
#endif
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
|
||||
// Low-level helpers to call the aligned allocation and deallocation functions
|
||||
// on the target platform. This is used to implement libc++'s own memory
|
||||
// allocation routines -- if you need to allocate memory inside the library,
|
||||
// chances are that you want to use `__libcpp_allocate` instead.
|
||||
//
|
||||
// Returns the allocated memory, or `nullptr` on failure.
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) {
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
return ::_aligned_malloc(__size, __alignment);
|
||||
#else
|
||||
void* __result = nullptr;
|
||||
::posix_memalign(&__result, __alignment, __size);
|
||||
// If posix_memalign fails, __result is unmodified so we still return `nullptr`.
|
||||
return __result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __libcpp_aligned_free(void* __ptr) {
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
::_aligned_free(__ptr);
|
||||
#else
|
||||
::free(__ptr);
|
||||
#endif
|
||||
}
|
||||
#endif // !_LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 inline
|
||||
_LIBCPP_CONSTEXPR _Tp* __launder(_Tp* __p) _NOEXCEPT
|
||||
|
|
|
@ -179,15 +179,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
|||
size = 1;
|
||||
if (static_cast<size_t>(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;
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
|
||||
#else
|
||||
while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
|
||||
#endif
|
||||
while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
|
||||
{
|
||||
// If posix_memalign 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();
|
||||
|
@ -195,7 +196,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
|||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
p = nullptr; // posix_memalign doesn't initialize 'p' on failure
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -252,12 +252,9 @@ _LIBCPP_WEAK
|
|||
void
|
||||
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
|
||||
{
|
||||
if (ptr)
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
::_aligned_free(ptr);
|
||||
#else
|
||||
::free(ptr);
|
||||
#endif
|
||||
if (ptr) {
|
||||
std::__libcpp_aligned_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <stdlib.h> // for malloc, calloc, free
|
||||
#include <string.h> // for memset
|
||||
#include <new> // for std::__libcpp_aligned_{alloc,free}
|
||||
|
||||
// A small, simple heap manager based (loosely) on
|
||||
// the startup heap manager from FreeBSD, optimized for space.
|
||||
|
@ -204,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {};
|
|||
|
||||
void* __aligned_malloc_with_fallback(size_t size) {
|
||||
#if defined(_WIN32)
|
||||
if (void* dest = _aligned_malloc(size, alignof(__aligned_type)))
|
||||
if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size))
|
||||
return dest;
|
||||
#elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
|
||||
if (void* dest = ::malloc(size))
|
||||
|
@ -212,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) {
|
|||
#else
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void* dest;
|
||||
if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0)
|
||||
if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size))
|
||||
return dest;
|
||||
#endif
|
||||
return fallback_malloc(size);
|
||||
|
@ -234,11 +234,7 @@ void __aligned_free_with_fallback(void* ptr) {
|
|||
if (is_fallback_ptr(ptr))
|
||||
fallback_free(ptr);
|
||||
else {
|
||||
#if defined(_WIN32)
|
||||
::_aligned_free(ptr);
|
||||
#else
|
||||
::free(ptr);
|
||||
#endif
|
||||
std::__libcpp_aligned_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,15 +142,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
|||
size = 1;
|
||||
if (static_cast<size_t>(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;
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
|
||||
#else
|
||||
while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
|
||||
#endif
|
||||
while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
|
||||
{
|
||||
// If posix_memalign 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();
|
||||
|
@ -158,7 +159,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
|||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
p = nullptr; // posix_memalign doesn't initialize 'p' on failure
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -215,12 +215,9 @@ _LIBCXXABI_WEAK
|
|||
void
|
||||
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
|
||||
{
|
||||
if (ptr)
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
::_aligned_free(ptr);
|
||||
#else
|
||||
::free(ptr);
|
||||
#endif
|
||||
if (ptr) {
|
||||
std::__libcpp_aligned_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
|
|
Loading…
Reference in New Issue