/proc/self/cwd/internal/new.cc
Line | Count | Source |
1 | | // Copyright 2024 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "internal/new.h" |
16 | | |
17 | | #include <cstddef> |
18 | | #include <cstdlib> |
19 | | #include <new> |
20 | | #include <utility> |
21 | | |
22 | | #ifdef _MSC_VER |
23 | | #include <malloc.h> |
24 | | #endif |
25 | | |
26 | | #include "absl/base/config.h" |
27 | | #include "absl/base/optimization.h" |
28 | | #include "absl/log/absl_check.h" |
29 | | #include "absl/numeric/bits.h" |
30 | | #include "internal/align.h" |
31 | | |
32 | | #if defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606L |
33 | | #define CEL_INTERNAL_HAVE_ALIGNED_NEW 1 |
34 | | #endif |
35 | | |
36 | | #if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L |
37 | | #define CEL_INTERNAL_HAVE_SIZED_DELETE 1 |
38 | | #endif |
39 | | |
40 | | namespace cel::internal { |
41 | | |
42 | | namespace { |
43 | | |
44 | 0 | [[noreturn, maybe_unused]] void ThrowStdBadAlloc() { |
45 | 0 | #ifdef ABSL_HAVE_EXCEPTIONS |
46 | 0 | throw std::bad_alloc(); |
47 | 0 | #else |
48 | 0 | std::abort(); |
49 | 0 | #endif |
50 | 0 | } |
51 | | |
52 | | } // namespace |
53 | | |
54 | 15.3k | void* New(size_t size) { return ::operator new(size); } |
55 | | |
56 | 0 | void* AlignedNew(size_t size, std::align_val_t alignment) { |
57 | 0 | ABSL_DCHECK(absl::has_single_bit(static_cast<size_t>(alignment))); |
58 | 0 | #ifdef CEL_INTERNAL_HAVE_ALIGNED_NEW |
59 | 0 | return ::operator new(size, alignment); |
60 | | #else |
61 | | if (static_cast<size_t>(alignment) <= kDefaultNewAlignment) { |
62 | | return New(size); |
63 | | } |
64 | | #if defined(_MSC_VER) |
65 | | void* ptr = _aligned_malloc(size, static_cast<size_t>(alignment)); |
66 | | if (ABSL_PREDICT_FALSE(size != 0 && ptr == nullptr)) { |
67 | | ThrowStdBadAlloc(); |
68 | | } |
69 | | return ptr; |
70 | | #elif defined(__APPLE__) |
71 | | void* ptr; |
72 | | if (ABSL_PREDICT_FALSE( |
73 | | posix_memalign(&ptr, static_cast<size_t>(alignment), size) != 0)) { |
74 | | ThrowStdBadAlloc(); |
75 | | } |
76 | | return ptr; |
77 | | #else |
78 | | void* ptr = std::aligned_alloc(static_cast<size_t>(alignment), size); |
79 | | if (ABSL_PREDICT_FALSE(size != 0 && ptr == nullptr)) { |
80 | | ThrowStdBadAlloc(); |
81 | | } |
82 | | return ptr; |
83 | | #endif |
84 | | #endif |
85 | 0 | } |
86 | | |
87 | 0 | std::pair<void*, size_t> SizeReturningNew(size_t size) { |
88 | 0 | return std::pair{::operator new(size), size}; |
89 | 0 | } |
90 | | |
91 | | std::pair<void*, size_t> SizeReturningAlignedNew(size_t size, |
92 | 0 | std::align_val_t alignment) { |
93 | 0 | ABSL_DCHECK(absl::has_single_bit(static_cast<size_t>(alignment))); |
94 | 0 | #ifdef CEL_INTERNAL_HAVE_ALIGNED_NEW |
95 | 0 | return std::pair{::operator new(size, alignment), size}; |
96 | | #else |
97 | | return std::pair{AlignedNew(size, alignment), size}; |
98 | | #endif |
99 | 0 | } |
100 | | |
101 | 0 | void Delete(void* ptr) noexcept { ::operator delete(ptr); } |
102 | | |
103 | 15.3k | void SizedDelete(void* ptr, size_t size) noexcept { |
104 | 15.3k | #ifdef CEL_INTERNAL_HAVE_SIZED_DELETE |
105 | 15.3k | ::operator delete(ptr, size); |
106 | | #else |
107 | | ::operator delete(ptr); |
108 | | #endif |
109 | 15.3k | } |
110 | | |
111 | 0 | void AlignedDelete(void* ptr, std::align_val_t alignment) noexcept { |
112 | 0 | ABSL_DCHECK(absl::has_single_bit(static_cast<size_t>(alignment))); |
113 | 0 | #ifdef CEL_INTERNAL_HAVE_ALIGNED_NEW |
114 | 0 | ::operator delete(ptr, alignment); |
115 | | #else |
116 | | if (static_cast<size_t>(alignment) <= kDefaultNewAlignment) { |
117 | | ::operator delete(ptr); |
118 | | } else { |
119 | | #if defined(_MSC_VER) |
120 | | _aligned_free(ptr); |
121 | | #else |
122 | | std::free(ptr); |
123 | | #endif |
124 | | } |
125 | | #endif |
126 | 0 | } |
127 | | |
128 | | void SizedAlignedDelete(void* ptr, size_t size, |
129 | 0 | std::align_val_t alignment) noexcept { |
130 | 0 | ABSL_DCHECK(absl::has_single_bit(static_cast<size_t>(alignment))); |
131 | 0 | #ifdef CEL_INTERNAL_HAVE_ALIGNED_NEW |
132 | 0 | #ifdef CEL_INTERNAL_HAVE_SIZED_DELETE |
133 | 0 | ::operator delete(ptr, size, alignment); |
134 | | #else |
135 | | ::operator delete(ptr, alignment); |
136 | | #endif |
137 | | #else |
138 | | AlignedDelete(ptr, alignment); |
139 | | #endif |
140 | 0 | } |
141 | | |
142 | | } // namespace cel::internal |