Skip to content

Commit 155cd2e

Browse files
authored
Merge pull request #42355 from apple/jgrynspan/AtomicWaitQueue-aligned-allocation
2 parents 26219fc + 3f24533 commit 155cd2e

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

include/swift/Runtime/AtomicWaitQueue.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define SWIFT_RUNTIME_ATOMICWAITQUEUE_H
2121

2222
#include "swift/Runtime/Heap.h"
23+
#include "swift/Runtime/HeapObject.h"
2324
#include "swift/Runtime/Mutex.h"
2425
#include <assert.h>
2526

@@ -84,7 +85,7 @@ class AtomicWaitQueue {
8485
/// global lock and while *not* holding the wait queue lock.
8586
void release_locked() {
8687
if (referenceCount == 1) {
87-
delete &asImpl();
88+
swift_cxx_deleteObject(&asImpl());
8889
} else {
8990
referenceCount--;
9091
}
@@ -211,7 +212,7 @@ class AtomicWaitQueue {
211212
// If we created the queue but never published it, destroy it.
212213
if (CurrentQueue) {
213214
CurrentQueue->WaitQueueLock.unlock();
214-
delete CurrentQueue;
215+
swift_cxx_deleteObject(CurrentQueue);
215216
}
216217
}
217218

@@ -425,12 +426,7 @@ class AtomicWaitQueue {
425426
private:
426427
template <class... Args>
427428
static Impl *createNewQueue(Args &&...args) {
428-
#if !defined(__cpp_aligned_new)
429-
static_assert(!swift::requires_aligned_alloc<std::alignment_of<Impl>::value>::value ||
430-
is_aligned_alloc_aware<Impl>::value,
431-
"type is over-aligned for non-alignment aware operator new");
432-
#endif
433-
auto queue = new Impl(std::forward<Args>(args)...);
429+
auto queue = swift_cxx_newObject<Impl>(std::forward<Args>(args)...);
434430
queue->WaitQueueLock.lock();
435431
return queue;
436432
}

include/swift/Runtime/HeapObject.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include <cstddef>
2121
#include <cstdint>
22+
#include <new>
23+
#include <utility>
2224
#include "swift/Runtime/Config.h"
2325

2426
#if SWIFT_OBJC_INTEROP
@@ -131,6 +133,49 @@ void *swift_slowAlloc(size_t bytes, size_t alignMask);
131133
SWIFT_RUNTIME_EXPORT
132134
void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask);
133135

136+
/// Allocate and construct an instance of type \c T.
137+
///
138+
/// \param args The arguments to pass to the constructor for \c T.
139+
///
140+
/// \returns A pointer to a new, fully constructed instance of \c T. This
141+
/// function never returns \c nullptr. The caller is responsible for
142+
/// eventually destroying the resulting object by passing it to
143+
/// \c swift_cxx_deleteObject().
144+
///
145+
/// This function avoids the use of the global \c operator \c new (which may be
146+
/// overridden by other code in a process) in favor of calling
147+
/// \c swift_slowAlloc() and constructing the new object with placement new.
148+
///
149+
/// This function is capable of returning well-aligned memory even on platforms
150+
/// that do not implement the C++17 "over-aligned new" feature.
151+
template <typename T, typename... Args>
152+
static inline T *swift_cxx_newObject(Args &&... args) {
153+
auto result = reinterpret_cast<T *>(swift_slowAlloc(sizeof(T),
154+
alignof(T) - 1));
155+
::new (result) T(std::forward<Args>(args)...);
156+
return result;
157+
}
158+
159+
/// Destruct and deallocate an instance of type \c T.
160+
///
161+
/// \param ptr A pointer to an instance of type \c T previously created with a
162+
/// call to \c swift_cxx_newObject().
163+
///
164+
/// This function avoids the use of the global \c operator \c delete (which may
165+
/// be overridden by other code in a process) in favor of directly calling the
166+
/// destructor for \a *ptr and then freeing its memory by calling
167+
/// \c swift_slowDealloc().
168+
///
169+
/// The effect of passing a pointer to this function that was \em not returned
170+
/// from \c swift_cxx_newObject() is undefined.
171+
template <typename T>
172+
static inline void swift_cxx_deleteObject(T *ptr) {
173+
if (ptr) {
174+
ptr->~T();
175+
swift_slowDealloc(ptr, sizeof(T), alignof(T) - 1);
176+
}
177+
}
178+
134179
/// Atomically increments the retain count of an object.
135180
///
136181
/// \param object - may be null, in which case this is a no-op

0 commit comments

Comments
 (0)