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

Stanislav Mekhanoshin via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 18 11:26:51 PDT 2023


https://github.com/rampitec updated https://github.com/llvm/llvm-project/pull/69407

>From fc787ffea516f9b518937f915005a815ccdc9cb3 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                  | 36 +++++++++++++++-----------
 libcxxabi/src/stdlib_new_delete.cpp | 40 +++++++++++++++++------------
 2 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index a1c9be6107bee62..033bba5c1fc95b6 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -20,7 +20,7 @@
 // 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;
@@ -31,15 +31,20 @@ _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
     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 {
   void* p = nullptr;
 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
@@ -82,7 +87,7 @@ _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator del
 
 #  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*))
@@ -91,25 +96,26 @@ _LIBCPP_WEAK void* operator new(std::size_t size, std::align_val_t alignment) _T
   // 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) {
     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 {
   void* p = nullptr;
 #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
diff --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp
index 71c98793cae4093..6c9990f063dde66 100644
--- a/libcxxabi/src/stdlib_new_delete.cpp
+++ b/libcxxabi/src/stdlib_new_delete.cpp
@@ -30,8 +30,7 @@
 // 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;
@@ -42,15 +41,21 @@ void* operator new(std::size_t size) _THROW_BAD_ALLOC {
     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 {
   void* p = nullptr;
@@ -102,8 +107,7 @@ void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
 
 #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*))
@@ -112,25 +116,27 @@ void* operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLO
   // 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) {
     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 {
   void* p = nullptr;



More information about the libcxx-commits mailing list