222 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "include/aligned_alloc.h"10#include "include/overridable_function.h"11#include <__assert>12#include <cstddef>13#include <cstdlib>14#include <new>15 16#if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_VCRUNTIME)17 18// The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp19// file. The version in this file is the canonical one.20 21inline void __throw_bad_alloc_shim() { std::__throw_bad_alloc(); }22 23# define _LIBCPP_ASSERT_SHIM(expr, str) _LIBCPP_ASSERT(expr, str)24 25// ------------------ BEGIN COPY ------------------26// Implement all new and delete operators as weak definitions27// in this shared library, so that they can be overridden by programs28// that define non-weak copies of the functions.29 30static void* operator_new_impl(std::size_t size) {31 if (size == 0)32 size = 1;33 void* p;34 while ((p = std::malloc(size)) == nullptr) {35 // If malloc fails and there is a new_handler,36 // call it to try free up memory.37 std::new_handler nh = std::get_new_handler();38 if (nh)39 nh();40 else41 break;42 }43 return p;44}45 46_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new, (std::size_t size)) _THROW_BAD_ALLOC {47 void* p = operator_new_impl(size);48 if (p == nullptr)49 __throw_bad_alloc_shim();50 return p;51}52 53_LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {54# if !_LIBCPP_HAS_EXCEPTIONS55# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION56 _LIBCPP_ASSERT_SHIM(57 (!std::__is_function_overridden < void*(std::size_t), &operator new>()),58 "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "59 "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "60 "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "61 "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "62 "contract (since it should return nullptr upon failure). Please make sure you override "63 "`operator new(size_t, nothrow_t)` as well.");64# endif65 66 return operator_new_impl(size);67# else68 void* p = nullptr;69 try {70 p = ::operator new(size);71 } catch (...) {72 }73 return p;74# endif75}76 77_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size)) _THROW_BAD_ALLOC { return ::operator new(size); }78 79_LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {80# if !_LIBCPP_HAS_EXCEPTIONS81# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION82 _LIBCPP_ASSERT_SHIM(83 (!std::__is_function_overridden < void*(std::size_t), &operator new[]>()),84 "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "85 "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "86 "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "87 "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "88 "contract (since it should return nullptr upon failure). Please make sure you override "89 "`operator new[](size_t, nothrow_t)` as well.");90# endif91 92 return operator_new_impl(size);93# else94 void* p = nullptr;95 try {96 p = ::operator new[](size);97 } catch (...) {98 }99 return p;100# endif101}102 103_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }104 105_LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }106 107_LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }108 109_LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }110 111_LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }112 113_LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }114 115# if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION116 117static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {118 if (size == 0)119 size = 1;120 if (static_cast<size_t>(alignment) < sizeof(void*))121 alignment = std::align_val_t(sizeof(void*));122 123 // Try allocating memory. If allocation fails and there is a new_handler,124 // call it to try free up memory, and try again until it succeeds, or until125 // the new_handler decides to terminate.126 void* p;127 while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {128 std::new_handler nh = std::get_new_handler();129 if (nh)130 nh();131 else132 break;133 }134 return p;135}136 137_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new, (std::size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {138 void* p = operator_new_aligned_impl(size, alignment);139 if (p == nullptr)140 __throw_bad_alloc_shim();141 return p;142}143 144_LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {145# if !_LIBCPP_HAS_EXCEPTIONS146# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION147 _LIBCPP_ASSERT_SHIM(148 (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new>()),149 "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "150 "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "151 "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "152 "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "153 "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "154 "`operator new(size_t, align_val_t, nothrow_t)` as well.");155# endif156 157 return operator_new_aligned_impl(size, alignment);158# else159 void* p = nullptr;160 try {161 p = ::operator new(size, alignment);162 } catch (...) {163 }164 return p;165# endif166}167 168_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {169 return ::operator new(size, alignment);170}171 172_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {173# if !_LIBCPP_HAS_EXCEPTIONS174# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION175 _LIBCPP_ASSERT_SHIM(176 (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new[]>()),177 "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "178 "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "179 "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "180 "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "181 "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "182 "override `operator new[](size_t, align_val_t, nothrow_t)` as well.");183# endif184 185 return operator_new_aligned_impl(size, alignment);186# else187 void* p = nullptr;188 try {189 p = ::operator new[](size, alignment);190 } catch (...) {191 }192 return p;193# endif194}195 196_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }197 198_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {199 ::operator delete(ptr, alignment);200}201 202_LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept {203 ::operator delete(ptr, alignment);204}205 206_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept {207 ::operator delete(ptr, alignment);208}209 210_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {211 ::operator delete[](ptr, alignment);212}213 214_LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept {215 ::operator delete[](ptr, alignment);216}217 218# endif // _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION219// ------------------ END COPY ------------------220 221#endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME222