1349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
906c3fb27SDimitry Andric #include <__memory/aligned_alloc.h>
1006c3fb27SDimitry Andric #include <cstdlib>
1181ad6265SDimitry Andric #include <new>
120b57cec5SDimitry Andric 
1306c3fb27SDimitry Andric #if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_VCRUNTIME)
140b57cec5SDimitry Andric 
1506c3fb27SDimitry Andric // The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp
1606c3fb27SDimitry Andric // file. The version in this file is the canonical one.
170b57cec5SDimitry Andric 
1806c3fb27SDimitry Andric // ------------------ BEGIN COPY ------------------
190b57cec5SDimitry Andric // Implement all new and delete operators as weak definitions
200b57cec5SDimitry Andric // in this shared library, so that they can be overridden by programs
210b57cec5SDimitry Andric // that define non-weak copies of the functions.
220b57cec5SDimitry Andric 
235f757f3fSDimitry Andric static void* operator_new_impl(std::size_t size) noexcept {
240b57cec5SDimitry Andric   if (size == 0)
250b57cec5SDimitry Andric     size = 1;
260b57cec5SDimitry Andric   void* p;
275f757f3fSDimitry Andric   while ((p = std::malloc(size)) == nullptr) {
280b57cec5SDimitry Andric     // If malloc fails and there is a new_handler,
290b57cec5SDimitry Andric     // call it to try free up memory.
300b57cec5SDimitry Andric     std::new_handler nh = std::get_new_handler();
310b57cec5SDimitry Andric     if (nh)
320b57cec5SDimitry Andric       nh();
330b57cec5SDimitry Andric     else
340b57cec5SDimitry Andric       break;
350b57cec5SDimitry Andric   }
360b57cec5SDimitry Andric   return p;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
395f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
405f757f3fSDimitry Andric   void* p = operator_new_impl(size);
415f757f3fSDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
425f757f3fSDimitry Andric   if (p == nullptr)
435f757f3fSDimitry Andric     throw std::bad_alloc();
445f757f3fSDimitry Andric #  endif
455f757f3fSDimitry Andric   return p;
465f757f3fSDimitry Andric }
475f757f3fSDimitry Andric 
485f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
49e8d8bef9SDimitry Andric   void* p = nullptr;
5006c3fb27SDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
515f757f3fSDimitry Andric   try {
5206c3fb27SDimitry Andric #  endif // _LIBCPP_HAS_NO_EXCEPTIONS
530b57cec5SDimitry Andric     p = ::operator new(size);
5406c3fb27SDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
555f757f3fSDimitry Andric   } catch (...) {
560b57cec5SDimitry Andric   }
5706c3fb27SDimitry Andric #  endif // _LIBCPP_HAS_NO_EXCEPTIONS
580b57cec5SDimitry Andric   return p;
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
615f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { return ::operator new(size); }
620b57cec5SDimitry Andric 
635f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
64e8d8bef9SDimitry Andric   void* p = nullptr;
6506c3fb27SDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
665f757f3fSDimitry Andric   try {
6706c3fb27SDimitry Andric #  endif // _LIBCPP_HAS_NO_EXCEPTIONS
680b57cec5SDimitry Andric     p = ::operator new[](size);
6906c3fb27SDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
705f757f3fSDimitry Andric   } catch (...) {
710b57cec5SDimitry Andric   }
7206c3fb27SDimitry Andric #  endif // _LIBCPP_HAS_NO_EXCEPTIONS
730b57cec5SDimitry Andric   return p;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
765f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
770b57cec5SDimitry Andric 
785f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }
790b57cec5SDimitry Andric 
805f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }
810b57cec5SDimitry Andric 
825f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }
830b57cec5SDimitry Andric 
845f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }
850b57cec5SDimitry Andric 
865f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric #  if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
890b57cec5SDimitry Andric 
905f757f3fSDimitry Andric static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) noexcept {
910b57cec5SDimitry Andric   if (size == 0)
920b57cec5SDimitry Andric     size = 1;
930b57cec5SDimitry Andric   if (static_cast<size_t>(alignment) < sizeof(void*))
940b57cec5SDimitry Andric     alignment = std::align_val_t(sizeof(void*));
95e8d8bef9SDimitry Andric 
96e8d8bef9SDimitry Andric   // Try allocating memory. If allocation fails and there is a new_handler,
97e8d8bef9SDimitry Andric   // call it to try free up memory, and try again until it succeeds, or until
98e8d8bef9SDimitry Andric   // the new_handler decides to terminate.
990b57cec5SDimitry Andric   void* p;
1005f757f3fSDimitry Andric   while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
1010b57cec5SDimitry Andric     std::new_handler nh = std::get_new_handler();
1020b57cec5SDimitry Andric     if (nh)
1030b57cec5SDimitry Andric       nh();
1045f757f3fSDimitry Andric     else
1050b57cec5SDimitry Andric       break;
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric   return p;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1105f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
1115f757f3fSDimitry Andric   void* p = operator_new_aligned_impl(size, alignment);
1125f757f3fSDimitry Andric #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1135f757f3fSDimitry Andric   if (p == nullptr)
1145f757f3fSDimitry Andric     throw std::bad_alloc();
1155f757f3fSDimitry Andric #    endif
1165f757f3fSDimitry Andric   return p;
1175f757f3fSDimitry Andric }
1185f757f3fSDimitry Andric 
1195f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
120e8d8bef9SDimitry Andric   void* p = nullptr;
12106c3fb27SDimitry Andric #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1225f757f3fSDimitry Andric   try {
12306c3fb27SDimitry Andric #    endif // _LIBCPP_HAS_NO_EXCEPTIONS
1240b57cec5SDimitry Andric     p = ::operator new(size, alignment);
12506c3fb27SDimitry Andric #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1265f757f3fSDimitry Andric   } catch (...) {
1270b57cec5SDimitry Andric   }
12806c3fb27SDimitry Andric #    endif // _LIBCPP_HAS_NO_EXCEPTIONS
1290b57cec5SDimitry Andric   return p;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1325f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
1330b57cec5SDimitry Andric   return ::operator new(size, alignment);
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1365f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
137e8d8bef9SDimitry Andric   void* p = nullptr;
13806c3fb27SDimitry Andric #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1395f757f3fSDimitry Andric   try {
14006c3fb27SDimitry Andric #    endif // _LIBCPP_HAS_NO_EXCEPTIONS
1410b57cec5SDimitry Andric     p = ::operator new[](size, alignment);
14206c3fb27SDimitry Andric #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1435f757f3fSDimitry Andric   } catch (...) {
1440b57cec5SDimitry Andric   }
14506c3fb27SDimitry Andric #    endif // _LIBCPP_HAS_NO_EXCEPTIONS
1460b57cec5SDimitry Andric   return p;
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
1495f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }
1500b57cec5SDimitry Andric 
1515f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
1520b57cec5SDimitry Andric   ::operator delete(ptr, alignment);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1555f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept {
1560b57cec5SDimitry Andric   ::operator delete(ptr, alignment);
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1595f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept {
1600b57cec5SDimitry Andric   ::operator delete(ptr, alignment);
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1635f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
1640b57cec5SDimitry Andric   ::operator delete[](ptr, alignment);
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
1675f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept {
1680b57cec5SDimitry Andric   ::operator delete[](ptr, alignment);
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric #  endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
17206c3fb27SDimitry Andric // ------------------ END COPY ------------------
17306c3fb27SDimitry Andric 
17406c3fb27SDimitry Andric #endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME
175