Skip to content

Instantly share code, notes, and snippets.

@colemancda
Last active May 26, 2022 23:49
Show Gist options
  • Save colemancda/d88a775f2bf3e234f4fa705c46b66b37 to your computer and use it in GitHub Desktop.
Save colemancda/d88a775f2bf3e234f4fa705c46b66b37 to your computer and use it in GitHub Desktop.
Swift 5.6.1 runtime patch for AtomicWaitQueue
diff --git a/include/swift/Runtime/AtomicWaitQueue.h b/include/swift/Runtime/AtomicWaitQueue.h
index 9fdd9288fe2..0985067828b 100644
--- a/include/swift/Runtime/AtomicWaitQueue.h
+++ b/include/swift/Runtime/AtomicWaitQueue.h
@@ -19,6 +19,8 @@
#ifndef SWIFT_RUNTIME_ATOMICWAITQUEUE_H
#define SWIFT_RUNTIME_ATOMICWAITQUEUE_H
+#include "swift/Runtime/Heap.h"
+#include "swift/Runtime/HeapObject.h"
#include "swift/Runtime/Mutex.h"
#include <assert.h>
@@ -83,7 +85,7 @@ class AtomicWaitQueue {
/// global lock and while *not* holding the wait queue lock.
void release_locked() {
if (referenceCount == 1) {
- delete &asImpl();
+ swift_cxx_deleteObject(&asImpl());
} else {
referenceCount--;
}
@@ -210,7 +212,7 @@ public:
// If we created the queue but never published it, destroy it.
if (CurrentQueue) {
CurrentQueue->WaitQueueLock.unlock();
- delete CurrentQueue;
+ swift_cxx_deleteObject(CurrentQueue);
}
}
@@ -424,7 +426,7 @@ public:
private:
template <class... Args>
static Impl *createNewQueue(Args &&...args) {
- auto queue = new Impl(std::forward<Args>(args)...);
+ auto queue = swift_cxx_newObject<Impl>(std::forward<Args>(args)...);
queue->WaitQueueLock.lock();
return queue;
}
diff --git a/include/swift/Runtime/HeapObject.h b/include/swift/Runtime/HeapObject.h
index e3487eaef3c..3642cab775b 100644
--- a/include/swift/Runtime/HeapObject.h
+++ b/include/swift/Runtime/HeapObject.h
@@ -19,6 +19,8 @@
#include <cstddef>
#include <cstdint>
+#include <new>
+#include <utility>
#include "swift/Runtime/Config.h"
#if SWIFT_OBJC_INTEROP
@@ -131,6 +133,49 @@ void *swift_slowAlloc(size_t bytes, size_t alignMask);
SWIFT_RUNTIME_EXPORT
void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask);
+/// Allocate and construct an instance of type \c T.
+///
+/// \param args The arguments to pass to the constructor for \c T.
+///
+/// \returns A pointer to a new, fully constructed instance of \c T. This
+/// function never returns \c nullptr. The caller is responsible for
+/// eventually destroying the resulting object by passing it to
+/// \c swift_cxx_deleteObject().
+///
+/// This function avoids the use of the global \c operator \c new (which may be
+/// overridden by other code in a process) in favor of calling
+/// \c swift_slowAlloc() and constructing the new object with placement new.
+///
+/// This function is capable of returning well-aligned memory even on platforms
+/// that do not implement the C++17 "over-aligned new" feature.
+template <typename T, typename... Args>
+static inline T *swift_cxx_newObject(Args &&... args) {
+ auto result = reinterpret_cast<T *>(swift_slowAlloc(sizeof(T),
+ alignof(T) - 1));
+ ::new (result) T(std::forward<Args>(args)...);
+ return result;
+}
+
+/// Destruct and deallocate an instance of type \c T.
+///
+/// \param ptr A pointer to an instance of type \c T previously created with a
+/// call to \c swift_cxx_newObject().
+///
+/// This function avoids the use of the global \c operator \c delete (which may
+/// be overridden by other code in a process) in favor of directly calling the
+/// destructor for \a *ptr and then freeing its memory by calling
+/// \c swift_slowDealloc().
+///
+/// The effect of passing a pointer to this function that was \em not returned
+/// from \c swift_cxx_newObject() is undefined.
+template <typename T>
+static inline void swift_cxx_deleteObject(T *ptr) {
+ if (ptr) {
+ ptr->~T();
+ swift_slowDealloc(ptr, sizeof(T), alignof(T) - 1);
+ }
+}
+
/// Atomically increments the retain count of an object.
///
/// \param object - may be null, in which case this is a no-op
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment