[libcxx-commits] [libcxxabi] [libc++][NFC] Refactor the core logic of operator new into helper functions (PR #69407)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 17 19:15:45 PDT 2023


https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/69407

This will make it easier to implement new(nothrow) without calling the throwing version of new when exceptions are disabled. See https://llvm.org/D150610 for the full discussion.

>From 57827e7b8aad619a8cd773c6e9e2741d3e7bebd2 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 14 Jun 2023 16:07:05 -0700
Subject: [PATCH] [libc++][NFC] Refactor the core logic of operator new into
 helper functions

This will make it easier to implement new(nothrow) without calling
the throwing version of new when exceptions are disabled. See
https://llvm.org/D150610 for the full discussion.
---
 libcxx/src/new.cpp                  | 54 ++++++++++++++++-------------
 libcxxabi/src/stdlib_new_delete.cpp | 54 ++++++++++++++++-------------
 2 files changed, 58 insertions(+), 50 deletions(-)

diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index c435c5ffc809c61..d045b0d4570d096 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -20,30 +20,34 @@
 // in this shared library, so that they can be overridden by programs
 // that define non-weak copies of the functions.
 
-_LIBCPP_WEAK
-void *
-operator new(std::size_t size) _THROW_BAD_ALLOC
-{
+static void* operator_new_impl(std::size_t size) noexcept {
     if (size == 0)
         size = 1;
     void* p;
-    while ((p = std::malloc(size)) == nullptr)
-    {
+    while ((p = std::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
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
-            throw std::bad_alloc();
-#else
             break;
-#endif
     }
     return p;
 }
 
+_LIBCPP_WEAK
+void *
+operator new(std::size_t size) _THROW_BAD_ALLOC
+{
+    void* p = operator_new_impl(size);
+#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+    if (p == nullptr)
+        throw std::bad_alloc();
+#endif
+    return p;
+}
+
 _LIBCPP_WEAK
 void*
 operator new(size_t size, const std::nothrow_t&) noexcept
@@ -133,10 +137,7 @@ operator delete[] (void* ptr, size_t) noexcept
 
 #if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
 
-_LIBCPP_WEAK
-void *
-operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
-{
+static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) noexcept {
     if (size == 0)
         size = 1;
     if (static_cast<size_t>(alignment) < sizeof(void*))
@@ -145,26 +146,29 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
     // 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<std::size_t>(alignment), size)) == nullptr)
-    {
+    while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
         std::new_handler nh = std::get_new_handler();
         if (nh)
             nh();
-        else {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
-            throw std::bad_alloc();
-#else
+        else
             break;
-#endif
-        }
     }
     return p;
 }
 
+_LIBCPP_WEAK
+void *
+operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
+{
+    void* p = operator_new_aligned_impl(size, alignment);
+#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+    if (p == nullptr)
+        throw std::bad_alloc();
+#endif
+    return p;
+}
+
 _LIBCPP_WEAK
 void*
 operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
diff --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp
index 080f932ccc60ecf..7946d07a59b72a7 100644
--- a/libcxxabi/src/stdlib_new_delete.cpp
+++ b/libcxxabi/src/stdlib_new_delete.cpp
@@ -30,30 +30,34 @@
 // in this shared library, so that they can be overridden by programs
 // that define non-weak copies of the functions.
 
-_LIBCPP_WEAK
-void *
-operator new(std::size_t size) _THROW_BAD_ALLOC
-{
+static void* operator_new_impl(std::size_t size) noexcept {
     if (size == 0)
         size = 1;
     void* p;
-    while ((p = std::malloc(size)) == nullptr)
-    {
+    while ((p = std::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
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
-            throw std::bad_alloc();
-#else
             break;
-#endif
     }
     return p;
 }
 
+_LIBCPP_WEAK
+void *
+operator new(std::size_t size) _THROW_BAD_ALLOC
+{
+    void* p = operator_new_impl(size);
+#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+    if (p == nullptr)
+        throw std::bad_alloc();
+#endif
+    return p;
+}
+
 _LIBCPP_WEAK
 void*
 operator new(size_t size, const std::nothrow_t&) noexcept
@@ -143,10 +147,7 @@ operator delete[] (void* ptr, size_t) noexcept
 
 #if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
 
-_LIBCPP_WEAK
-void *
-operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
-{
+static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) noexcept {
     if (size == 0)
         size = 1;
     if (static_cast<size_t>(alignment) < sizeof(void*))
@@ -155,26 +156,29 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
     // 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<std::size_t>(alignment), size)) == nullptr)
-    {
+    while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
         std::new_handler nh = std::get_new_handler();
         if (nh)
             nh();
-        else {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
-            throw std::bad_alloc();
-#else
+        else
             break;
-#endif
-        }
     }
     return p;
 }
 
+_LIBCPP_WEAK
+void *
+operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
+{
+    void* p = operator_new_aligned_impl(size, alignment);
+#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+    if (p == nullptr)
+        throw std::bad_alloc();
+#endif
+    return p;
+}
+
 _LIBCPP_WEAK
 void*
 operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept



More information about the libcxx-commits mailing list