Skip to content

Commit 19e954f

Browse files
committed
Sidetables should not use operator new or operator delete.
1 parent f652a9d commit 19e954f

File tree

4 files changed

+66
-62
lines changed

4 files changed

+66
-62
lines changed

include/swift/Runtime/Heap.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,72 @@
2020
#include <cstddef>
2121
#include <cstdint>
2222
#include <cstdlib>
23+
#include <new>
2324
#include <type_traits>
25+
#include <utility>
26+
27+
#include "swift/Runtime/Config.h"
2428

2529
#if defined(_WIN32)
2630
#include <malloc.h>
2731
#endif
2832

2933
namespace swift {
34+
// Allocate plain old memory. This is the generalized entry point
35+
// Never returns nil. The returned memory is uninitialized.
36+
//
37+
// An "alignment mask" is just the alignment (a power of 2) minus 1.
38+
SWIFT_RUNTIME_EXPORT
39+
void *swift_slowAlloc(size_t bytes, size_t alignMask);
40+
41+
// If the caller cannot promise to zero the object during destruction,
42+
// then call these corresponding APIs:
43+
SWIFT_RUNTIME_EXPORT
44+
void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask);
45+
46+
/// Allocate and construct an instance of type \c T.
47+
///
48+
/// \param args The arguments to pass to the constructor for \c T.
49+
///
50+
/// \returns A pointer to a new, fully constructed instance of \c T. This
51+
/// function never returns \c nullptr. The caller is responsible for
52+
/// eventually destroying the resulting object by passing it to
53+
/// \c swift_cxx_deleteObject().
54+
///
55+
/// This function avoids the use of the global \c operator \c new (which may be
56+
/// overridden by other code in a process) in favor of calling
57+
/// \c swift_slowAlloc() and constructing the new object with placement new.
58+
///
59+
/// This function is capable of returning well-aligned memory even on platforms
60+
/// that do not implement the C++17 "over-aligned new" feature.
61+
template <typename T, typename... Args>
62+
static inline T *swift_cxx_newObject(Args &&... args) {
63+
auto result = reinterpret_cast<T *>(swift_slowAlloc(sizeof(T),
64+
alignof(T) - 1));
65+
::new (result) T(std::forward<Args>(args)...);
66+
return result;
67+
}
68+
69+
/// Destruct and deallocate an instance of type \c T.
70+
///
71+
/// \param ptr A pointer to an instance of type \c T previously created with a
72+
/// call to \c swift_cxx_newObject().
73+
///
74+
/// This function avoids the use of the global \c operator \c delete (which may
75+
/// be overridden by other code in a process) in favor of directly calling the
76+
/// destructor for \a *ptr and then freeing its memory by calling
77+
/// \c swift_slowDealloc().
78+
///
79+
/// The effect of passing a pointer to this function that was \em not returned
80+
/// from \c swift_cxx_newObject() is undefined.
81+
template <typename T>
82+
static inline void swift_cxx_deleteObject(T *ptr) {
83+
if (ptr) {
84+
ptr->~T();
85+
swift_slowDealloc(ptr, sizeof(T), alignof(T) - 1);
86+
}
87+
}
88+
3089
namespace {
3190
// This is C++17 and newer, so we simply re-define it. Since the codebase is
3291
// C++14, assume that DR1558 is accounted for and that unused parameters in alias

include/swift/Runtime/HeapObject.h

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

2020
#include <cstddef>
2121
#include <cstdint>
22-
#include <new>
23-
#include <utility>
2422
#include "swift/Runtime/Config.h"
2523

2624
#if SWIFT_OBJC_INTEROP
@@ -120,62 +118,6 @@ BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
120118
SWIFT_RUNTIME_EXPORT
121119
HeapObject* swift_allocEmptyBox();
122120

123-
// Allocate plain old memory. This is the generalized entry point
124-
// Never returns nil. The returned memory is uninitialized.
125-
//
126-
// An "alignment mask" is just the alignment (a power of 2) minus 1.
127-
128-
SWIFT_RUNTIME_EXPORT
129-
void *swift_slowAlloc(size_t bytes, size_t alignMask);
130-
131-
// If the caller cannot promise to zero the object during destruction,
132-
// then call these corresponding APIs:
133-
SWIFT_RUNTIME_EXPORT
134-
void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask);
135-
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-
179121
/// Atomically increments the retain count of an object.
180122
///
181123
/// \param object - may be null, in which case this is a no-op

stdlib/public/SwiftShims/RefCount.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,9 @@ class HeapObjectSideTableEntry {
13291329
#endif
13301330
{ }
13311331

1332+
void *operator new(size_t) = delete;
1333+
void operator delete(void *) = delete;
1334+
13321335
#pragma clang diagnostic push
13331336
#pragma clang diagnostic ignored "-Winvalid-offsetof"
13341337
static ptrdiff_t refCountsOffset() {
@@ -1455,7 +1458,7 @@ class HeapObjectSideTableEntry {
14551458
// Weak ref count is now zero. Delete the side table entry.
14561459
// FREED -> DEAD
14571460
assert(refCounts.getUnownedCount() == 0);
1458-
delete this;
1461+
swift_cxx_deleteObject(this);
14591462
}
14601463

14611464
void decrementWeakNonAtomic() {
@@ -1468,7 +1471,7 @@ class HeapObjectSideTableEntry {
14681471
// Weak ref count is now zero. Delete the side table entry.
14691472
// FREED -> DEAD
14701473
assert(refCounts.getUnownedCount() == 0);
1471-
delete this;
1474+
swift_cxx_deleteObject(this);
14721475
}
14731476

14741477
uint32_t getWeakCount() const {

stdlib/public/runtime/RefCount.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ HeapObjectSideTableEntry* RefCounts<InlineRefCountBits>::allocateSideTable(bool
9797
// Preflight passed. Allocate a side table.
9898

9999
// FIXME: custom side table allocator
100-
HeapObjectSideTableEntry *side = new HeapObjectSideTableEntry(getHeapObject());
100+
auto side = swift_cxx_newObject<HeapObjectSideTableEntry>(getHeapObject());
101101

102102
auto newbits = InlineRefCountBits(side);
103103

@@ -106,7 +106,7 @@ HeapObjectSideTableEntry* RefCounts<InlineRefCountBits>::allocateSideTable(bool
106106
// Already have a side table. Return it and delete ours.
107107
// Read before delete to streamline barriers.
108108
auto result = oldbits.getSideTable();
109-
delete side;
109+
swift_cxx_deleteObject(side);
110110
return result;
111111
}
112112
else if (failIfDeiniting && oldbits.getIsDeiniting()) {

0 commit comments

Comments
 (0)