Skip to content

Commit aa67f08

Browse files
authored
Use __cpp_aligned_new instead of hand-rolling the implementation
Differential Revision: D75806635 Pull Request resolved: #11293
1 parent a54870e commit aa67f08

File tree

5 files changed

+62
-121
lines changed

5 files changed

+62
-121
lines changed

extension/data_loader/file_data_loader.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,29 @@ Result<FileDataLoader> FileDataLoader::from(
112112
}
113113

114114
namespace {
115+
116+
inline void* et_aligned_alloc(size_t size, std::align_val_t alignment) {
117+
return ::operator new(size, alignment);
118+
}
119+
120+
inline void et_aligned_free(void* ptr, std::align_val_t alignment) {
121+
return ::operator delete(ptr, alignment);
122+
}
123+
115124
/**
116125
* FreeableBuffer::FreeFn-compatible callback.
117126
*
118-
* `context` is the original buffer pointer. It is allocated with
119-
* ET_ALIGNED_ALLOC, and must be freed with ET_ALIGNED_FREE.
127+
* `data` is the original buffer pointer.
128+
* `context` is the original alignment.
120129
*
121-
* `data` and `size` are unused.
130+
* `size` is unused.
122131
*/
123132
void FreeSegment(void* context, void* data, ET_UNUSED size_t size) {
124-
ET_ALIGNED_FREE(context);
133+
et_aligned_free(
134+
data,
135+
static_cast<std::align_val_t>(reinterpret_cast<uintptr_t>(context)));
125136
}
137+
126138
} // namespace
127139

128140
Result<FreeableBuffer> FileDataLoader::load(
@@ -149,26 +161,31 @@ Result<FreeableBuffer> FileDataLoader::load(
149161
}
150162

151163
// Allocate memory for the FreeableBuffer.
152-
void* aligned_buffer = ET_ALIGNED_ALLOC(alignment_, size);
164+
void* aligned_buffer = et_aligned_alloc(size, alignment_);
153165
if (aligned_buffer == nullptr) {
154166
ET_LOG(
155167
Error,
156-
"Reading from %s at offset %zu: ET_ALIGNED_ALLOC(%zd, %zd) failed",
168+
"Reading from %s at offset %zu: et_aligned_alloc(%zu, %zu) failed",
157169
file_name_,
158170
offset,
159-
alignment_,
160-
size);
171+
size,
172+
static_cast<size_t>(alignment_));
161173
return Error::MemoryAllocationFailed;
162174
}
163175

164176
auto err = load_into(offset, size, segment_info, aligned_buffer);
165177
if (err != Error::Ok) {
166-
ET_ALIGNED_FREE(aligned_buffer);
178+
et_aligned_free(aligned_buffer, alignment_);
167179
return err;
168180
}
169181

170-
// Pass the aligned_buffer pointer as context to FreeSegment.
171-
return FreeableBuffer(aligned_buffer, size, FreeSegment, aligned_buffer);
182+
// Pass the alignment as context to FreeSegment.
183+
return FreeableBuffer(
184+
aligned_buffer,
185+
size,
186+
FreeSegment,
187+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
188+
reinterpret_cast<void*>(static_cast<uintptr_t>(alignment_)));
172189
}
173190

174191
Result<size_t> FileDataLoader::size() const {

extension/data_loader/file_data_loader.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class FileDataLoader final : public executorch::runtime::DataLoader {
5858
fd_(rhs.fd_) {
5959
const_cast<const char*&>(rhs.file_name_) = nullptr;
6060
const_cast<size_t&>(rhs.file_size_) = 0;
61-
const_cast<size_t&>(rhs.alignment_) = 0;
61+
const_cast<std::align_val_t&>(rhs.alignment_) = {};
6262
const_cast<int&>(rhs.fd_) = -1;
6363
}
6464

@@ -86,7 +86,7 @@ class FileDataLoader final : public executorch::runtime::DataLoader {
8686
const char* file_name)
8787
: file_name_(file_name),
8888
file_size_(file_size),
89-
alignment_(alignment),
89+
alignment_{alignment},
9090
fd_(fd) {}
9191

9292
// Not safely copyable.
@@ -96,7 +96,7 @@ class FileDataLoader final : public executorch::runtime::DataLoader {
9696

9797
const char* const file_name_; // Owned by the instance.
9898
const size_t file_size_;
99-
const size_t alignment_;
99+
const std::align_val_t alignment_;
100100
const int fd_; // Owned by the instance.
101101
};
102102

extension/data_loader/file_descriptor_data_loader.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,29 @@ FileDescriptorDataLoader::fromFileDescriptorUri(
123123
}
124124

125125
namespace {
126+
127+
inline void* et_aligned_alloc(size_t size, std::align_val_t alignment) {
128+
return ::operator new(size, alignment);
129+
}
130+
131+
inline void et_aligned_free(void* ptr, std::align_val_t alignment) {
132+
return ::operator delete(ptr, alignment);
133+
}
134+
126135
/**
127136
* FreeableBuffer::FreeFn-compatible callback.
128137
*
129-
* `context` is the original buffer pointer. It is allocated with
130-
* ET_ALIGNED_ALLOC, and must be freed with ET_ALIGNED_FREE.
138+
* `data` is the original buffer pointer.
139+
* `context` is the original alignment.
131140
*
132-
* `data` and `size` are unused.
141+
* `size` is unused.
133142
*/
134143
void FreeSegment(void* context, void* data, ET_UNUSED size_t size) {
135-
ET_ALIGNED_FREE(context);
144+
et_aligned_free(
145+
data,
146+
static_cast<std::align_val_t>(reinterpret_cast<uintptr_t>(context)));
136147
}
148+
137149
} // namespace
138150

139151
Result<FreeableBuffer> FileDescriptorDataLoader::load(
@@ -160,24 +172,31 @@ Result<FreeableBuffer> FileDescriptorDataLoader::load(
160172
}
161173

162174
// Allocate memory for the FreeableBuffer.
163-
void* aligned_buffer = ET_ALIGNED_ALLOC(alignment_, size);
175+
void* aligned_buffer = et_aligned_alloc(size, alignment_);
164176
if (aligned_buffer == nullptr) {
165177
ET_LOG(
166178
Error,
167-
"Reading from %s at offset %zu: ET_ALIGNED_ALLOC(%zd) failed",
179+
"Reading from %s at offset %zu: et_aligned_alloc(%zu, %zu) failed",
168180
file_descriptor_uri_,
169181
offset,
170-
size);
182+
size,
183+
static_cast<size_t>(alignment_));
171184
return Error::MemoryAllocationFailed;
172185
}
173186

174187
auto err = load_into(offset, size, segment_info, aligned_buffer);
175188
if (err != Error::Ok) {
176-
ET_ALIGNED_FREE(aligned_buffer);
189+
et_aligned_free(aligned_buffer, alignment_);
177190
return err;
178191
}
179192

180-
return FreeableBuffer(aligned_buffer, size, FreeSegment, aligned_buffer);
193+
// Pass the alignment as context to FreeSegment.
194+
return FreeableBuffer(
195+
aligned_buffer,
196+
size,
197+
FreeSegment,
198+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
199+
reinterpret_cast<void*>(static_cast<uintptr_t>(alignment_)));
181200
}
182201

183202
Result<size_t> FileDescriptorDataLoader::size() const {

extension/data_loader/file_descriptor_data_loader.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class FileDescriptorDataLoader final : public executorch::runtime::DataLoader {
5656
fd_(rhs.fd_) {
5757
const_cast<const char*&>(rhs.file_descriptor_uri_) = nullptr;
5858
const_cast<size_t&>(rhs.file_size_) = 0;
59-
const_cast<size_t&>(rhs.alignment_) = 0;
59+
const_cast<std::align_val_t&>(rhs.alignment_) = {};
6060
const_cast<int&>(rhs.fd_) = -1;
6161
}
6262

@@ -84,7 +84,7 @@ class FileDescriptorDataLoader final : public executorch::runtime::DataLoader {
8484
const char* file_descriptor_uri)
8585
: file_descriptor_uri_(file_descriptor_uri),
8686
file_size_(file_size),
87-
alignment_(alignment),
87+
alignment_{alignment},
8888
fd_(fd) {}
8989

9090
// Not safely copyable.
@@ -94,7 +94,7 @@ class FileDescriptorDataLoader final : public executorch::runtime::DataLoader {
9494

9595
const char* const file_descriptor_uri_; // Owned by the instance.
9696
const size_t file_size_;
97-
const size_t alignment_;
97+
const std::align_val_t alignment_;
9898
const int fd_; // Owned by the instance.
9999
};
100100

runtime/platform/compiler.h

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -171,101 +171,6 @@
171171
using ssize_t = ptrdiff_t;
172172
#endif
173173

174-
/**
175-
* Platform-specific aligned memory allocation and deallocation.
176-
*
177-
* Usage:
178-
* void* ptr = ET_ALIGNED_ALLOC(alignment, size);
179-
* // use ptr...
180-
* ET_ALIGNED_FREE(ptr);
181-
*
182-
* Note: alignment must be a power of 2 and size must be an integral multiple of
183-
* alignment.
184-
*/
185-
#if defined(_MSC_VER)
186-
#include <malloc.h>
187-
#define ET_ALIGNED_ALLOC(alignment, size) \
188-
_aligned_malloc(((size + alignment - 1) & ~(alignment - 1)), (alignment))
189-
#define ET_ALIGNED_FREE(ptr) _aligned_free(ptr)
190-
#elif defined(__APPLE__)
191-
#include <stdlib.h> // For posix_memalign and free
192-
inline void* et_apple_aligned_alloc(size_t alignment, size_t size) {
193-
void* ptr = nullptr;
194-
// The address of the allocated memory must be a multiple of sizeof(void*).
195-
if (alignment < sizeof(void*)) {
196-
alignment = sizeof(void*);
197-
}
198-
if (posix_memalign(
199-
&ptr, alignment, (size + alignment - 1) & ~(alignment - 1)) != 0) {
200-
return nullptr;
201-
}
202-
return ptr;
203-
}
204-
#define ET_ALIGNED_ALLOC(alignment, size) \
205-
et_apple_aligned_alloc((alignment), (size))
206-
#define ET_ALIGNED_FREE(ptr) free(ptr)
207-
#elif __has_builtin(__builtin_aligned_alloc) || defined(_ISOC11_SOURCE)
208-
// Linux and posix systems that support aligned_alloc and are >= C++17.
209-
#include <cstdlib>
210-
#define ET_ALIGNED_ALLOC(alignment, size) \
211-
::aligned_alloc(alignment, (size + alignment - 1) & ~(alignment - 1))
212-
#define ET_ALIGNED_FREE(ptr) free(ptr)
213-
#else
214-
// If the platform doesn't support aligned_alloc, fallback to malloc.
215-
#include <stdint.h>
216-
#include <cstdlib>
217-
inline void* et_aligned_malloc(size_t alignment, size_t size) {
218-
// Place to store the offset to the original pointer.
219-
size_t offset_size = sizeof(uint16_t);
220-
221-
// Malloc extra space for offset + alignment.
222-
size_t alloc_size = size + offset_size + alignment - 1;
223-
void* ptr = std::malloc(alloc_size);
224-
225-
if (ptr == nullptr) {
226-
// Malloc failed.
227-
return nullptr;
228-
}
229-
230-
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
231-
// Align the address past addr + offset_size bytes.
232-
// This provides space to store the offset before the aligned pointer.
233-
addr = addr + offset_size;
234-
uintptr_t aligned_ptr = (addr + alignment - 1) & ~(alignment - 1);
235-
236-
// Check that alignment didn't overflow the buffer.
237-
if (reinterpret_cast<uintptr_t>(aligned_ptr) + size >
238-
reinterpret_cast<uintptr_t>(ptr) + alloc_size) {
239-
std::free(ptr);
240-
return nullptr;
241-
}
242-
243-
// Store the offset to the original pointer.
244-
// Used to free the original allocated buffer.
245-
*(reinterpret_cast<uint16_t*>(aligned_ptr) - 1) =
246-
(uint16_t)(reinterpret_cast<uintptr_t>(aligned_ptr) -
247-
reinterpret_cast<uintptr_t>(ptr));
248-
249-
return reinterpret_cast<uint16_t*>(aligned_ptr);
250-
}
251-
252-
inline void et_aligned_free(void* ptr) {
253-
if (ptr == nullptr) {
254-
return;
255-
}
256-
257-
// Get the original pointer using the offset.
258-
uint16_t* original_ptr = reinterpret_cast<uint16_t*>(
259-
reinterpret_cast<uintptr_t>(ptr) -
260-
*(reinterpret_cast<uint16_t*>(ptr) - 1));
261-
std::free(original_ptr);
262-
}
263-
264-
#define ET_ALIGNED_ALLOC(alignment, size) et_aligned_malloc((alignment), (size))
265-
#define ET_ALIGNED_FREE(ptr) et_aligned_free(ptr)
266-
267-
#endif
268-
269174
// DEPRECATED: Use the non-underscore-prefixed versions instead.
270175
// TODO(T199005537): Remove these once all users have stopped using them.
271176
#define __ET_DEPRECATED ET_DEPRECATED

0 commit comments

Comments
 (0)