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