[libcxx-commits] [libcxxabi] a78aaa1 - [libc++] Factor out common logic for calling aligned allocation

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Nov 25 12:45:05 PST 2020


Author: Louis Dionne
Date: 2020-11-25T15:44:50-05:00
New Revision: a78aaa1ad51214b2e04f41762e76bb43067ea1fd

URL: https://github.com/llvm/llvm-project/commit/a78aaa1ad51214b2e04f41762e76bb43067ea1fd
DIFF: https://github.com/llvm/llvm-project/commit/a78aaa1ad51214b2e04f41762e76bb43067ea1fd.diff

LOG: [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

Added: 
    

Modified: 
    libcxx/include/new
    libcxx/src/new.cpp
    libcxxabi/src/fallback_malloc.cpp
    libcxxabi/src/stdlib_new_delete.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/new b/libcxx/include/new
index 66747b04d4d7..8b17003b7b87 100644
--- a/libcxx/include/new
+++ b/libcxx/include/new
@@ -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

diff  --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index ec60ca64815f..57f948fbb052 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -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

diff  --git a/libcxxabi/src/fallback_malloc.cpp b/libcxxabi/src/fallback_malloc.cpp
index 75c01efebed2..78720187affc 100644
--- a/libcxxabi/src/fallback_malloc.cpp
+++ b/libcxxabi/src/fallback_malloc.cpp
@@ -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);
   }
 }
 

diff  --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp
index 58f181eb357f..643108f29691 100644
--- a/libcxxabi/src/stdlib_new_delete.cpp
+++ b/libcxxabi/src/stdlib_new_delete.cpp
@@ -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


        


More information about the libcxx-commits mailing list