Skip to content

Commit d64f763

Browse files
authored
Merge pull request #7732 from jckarter/retain-negative-pointers
Runtime: Have native refcounting entry points ignore negative pointer values on x86-64 and arm64.
2 parents fc86f35 + 24367fa commit d64f763

File tree

3 files changed

+45
-21
lines changed

3 files changed

+45
-21
lines changed

lib/IRGen/SwiftTargetInfo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ static void configureARM64(IRGenModule &IGM, const llvm::Triple &triple,
5454

5555
// arm64 requires ISA-masking.
5656
target.ObjCUseISAMask = true;
57+
58+
// arm64 tops out at 56 effective bits of address space and reserves the high
59+
// half for the kernel.
60+
target.SwiftRetainIgnoresNegativeValues = true;
5761
}
5862

5963
/// Configures target-specific information for x86-64 platforms.
@@ -75,6 +79,10 @@ static void configureX86_64(IRGenModule &IGM, const llvm::Triple &triple,
7579

7680
// x86-64 requires ISA-masking.
7781
target.ObjCUseISAMask = true;
82+
83+
// x86-64 only has 48 effective bits of address space and reserves the high
84+
// half for the kernel.
85+
target.SwiftRetainIgnoresNegativeValues = true;
7886
}
7987

8088
/// Configures target-specific information for 32-bit x86 platforms.

lib/IRGen/SwiftTargetInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ class SwiftTargetInfo {
9595
/// The value stored in a Builtin.once predicate to indicate that an
9696
/// initialization has already happened, if known.
9797
Optional<int64_t> OnceDonePredicateValue = None;
98+
99+
/// True if `swift_retain` and `swift_release` are no-ops when passed
100+
/// "negative" pointer values.
101+
bool SwiftRetainIgnoresNegativeValues = false;
98102
};
99103

100104
}

stdlib/public/runtime/HeapObject.cpp

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@
4343

4444
using namespace swift;
4545

46+
/// Returns true if the pointer passed to a native retain or release is valid.
47+
/// If false, the operation should immediately return.
48+
static inline bool isValidPointerForNativeRetain(const void *p) {
49+
#if defined(__x86_64__) || defined(__arm64__)
50+
// On these platforms, the upper half of address space is reserved for the
51+
// kernel, so we can assume that pointer values in this range are invalid.
52+
return (intptr_t)p > 0;
53+
#else
54+
return p != nullptr;
55+
#endif
56+
}
57+
4658
HeapObject *swift::swift_allocObject(HeapMetadata const *metadata,
4759
size_t requiredSize,
4860
size_t requiredAlignmentMask)
@@ -185,7 +197,7 @@ OpaqueValue *swift::swift_projectBox(HeapObject *o) {
185197
// for boxes of empty type. The address of an empty value is always undefined,
186198
// so we can just return nil back in this case.
187199
if (!o)
188-
return reinterpret_cast<OpaqueValue*>(o);
200+
return nullptr;
189201
auto metadata = static_cast<const GenericBoxHeapMetadata *>(o->metadata);
190202
return metadata->project(o);
191203
}
@@ -206,7 +218,7 @@ void swift::swift_nonatomic_retain(HeapObject *object) {
206218
SWIFT_RT_ENTRY_IMPL_VISIBILITY
207219
extern "C"
208220
void SWIFT_RT_ENTRY_IMPL(swift_nonatomic_retain)(HeapObject *object) {
209-
if (object)
221+
if (isValidPointerForNativeRetain(object))
210222
object->refCounts.incrementNonAtomic(1);
211223
}
212224

@@ -217,15 +229,15 @@ void swift::swift_nonatomic_release(HeapObject *object) {
217229
SWIFT_RT_ENTRY_IMPL_VISIBILITY
218230
extern "C"
219231
void SWIFT_RT_ENTRY_IMPL(swift_nonatomic_release)(HeapObject *object) {
220-
if (object)
232+
if (isValidPointerForNativeRetain(object))
221233
object->refCounts.decrementAndMaybeDeinitNonAtomic(1);
222234
}
223235

224236
SWIFT_RT_ENTRY_IMPL_VISIBILITY
225237
extern "C"
226238
void SWIFT_RT_ENTRY_IMPL(swift_retain)(HeapObject *object)
227239
SWIFT_CC(RegisterPreservingCC_IMPL) {
228-
if (object)
240+
if (isValidPointerForNativeRetain(object))
229241
object->refCounts.increment(1);
230242
}
231243

@@ -238,7 +250,7 @@ SWIFT_RT_ENTRY_IMPL_VISIBILITY
238250
extern "C"
239251
void SWIFT_RT_ENTRY_IMPL(swift_retain_n)(HeapObject *object, uint32_t n)
240252
SWIFT_CC(RegisterPreservingCC_IMPL) {
241-
if (object)
253+
if (isValidPointerForNativeRetain(object))
242254
object->refCounts.increment(n);
243255
}
244256

@@ -251,7 +263,7 @@ SWIFT_RT_ENTRY_IMPL_VISIBILITY
251263
extern "C"
252264
void SWIFT_RT_ENTRY_IMPL(swift_nonatomic_retain_n)(HeapObject *object, uint32_t n)
253265
SWIFT_CC(RegisterPreservingCC_IMPL) {
254-
if (object)
266+
if (isValidPointerForNativeRetain(object))
255267
object->refCounts.incrementNonAtomic(n);
256268
}
257269

@@ -264,7 +276,7 @@ SWIFT_RT_ENTRY_IMPL_VISIBILITY
264276
extern "C"
265277
void SWIFT_RT_ENTRY_IMPL(swift_release)(HeapObject *object)
266278
SWIFT_CC(RegisterPreservingCC_IMPL) {
267-
if (object)
279+
if (isValidPointerForNativeRetain(object))
268280
object->refCounts.decrementAndMaybeDeinit(1);
269281
}
270282

@@ -277,7 +289,7 @@ SWIFT_RT_ENTRY_IMPL_VISIBILITY
277289
extern "C"
278290
void SWIFT_RT_ENTRY_IMPL(swift_release_n)(HeapObject *object, uint32_t n)
279291
SWIFT_CC(RegisterPreservingCC_IMPL) {
280-
if (object)
292+
if (isValidPointerForNativeRetain(object))
281293
object->refCounts.decrementAndMaybeDeinit(n);
282294
}
283295

@@ -294,7 +306,7 @@ SWIFT_RT_ENTRY_IMPL_VISIBILITY
294306
extern "C"
295307
void SWIFT_RT_ENTRY_IMPL(swift_nonatomic_release_n)(HeapObject *object, uint32_t n)
296308
SWIFT_CC(RegisterPreservingCC_IMPL) {
297-
if (object)
309+
if (isValidPointerForNativeRetain(object))
298310
object->refCounts.decrementAndMaybeDeinitNonAtomic(n);
299311
}
300312

@@ -308,15 +320,15 @@ size_t swift::swift_unownedRetainCount(HeapObject *object) {
308320

309321
void swift::swift_unownedRetain(HeapObject *object)
310322
SWIFT_CC(RegisterPreservingCC_IMPL) {
311-
if (!object)
323+
if (!isValidPointerForNativeRetain(object))
312324
return;
313325

314326
object->refCounts.incrementUnowned(1);
315327
}
316328

317329
void swift::swift_unownedRelease(HeapObject *object)
318330
SWIFT_CC(RegisterPreservingCC_IMPL) {
319-
if (!object)
331+
if (!isValidPointerForNativeRetain(object))
320332
return;
321333

322334
// Only class objects can be unowned-retained and unowned-released.
@@ -334,15 +346,15 @@ void swift::swift_unownedRelease(HeapObject *object)
334346

335347
void swift::swift_unownedRetain_n(HeapObject *object, int n)
336348
SWIFT_CC(RegisterPreservingCC_IMPL) {
337-
if (!object)
349+
if (!isValidPointerForNativeRetain(object))
338350
return;
339351

340352
object->refCounts.incrementUnowned(n);
341353
}
342354

343355
void swift::swift_unownedRelease_n(HeapObject *object, int n)
344356
SWIFT_CC(RegisterPreservingCC_IMPL) {
345-
if (!object)
357+
if (!isValidPointerForNativeRetain(object))
346358
return;
347359

348360
// Only class objects can be unowned-retained and unowned-released.
@@ -359,7 +371,7 @@ void swift::swift_unownedRelease_n(HeapObject *object, int n)
359371

360372
HeapObject *swift::swift_tryPin(HeapObject *object)
361373
SWIFT_CC(RegisterPreservingCC_IMPL) {
362-
assert(object);
374+
assert(isValidPointerForNativeRetain(object));
363375

364376
// Try to set the flag. If this succeeds, the caller will be
365377
// responsible for clearing it.
@@ -373,7 +385,7 @@ HeapObject *swift::swift_tryPin(HeapObject *object)
373385

374386
void swift::swift_unpin(HeapObject *object)
375387
SWIFT_CC(RegisterPreservingCC_IMPL) {
376-
if (object)
388+
if (isValidPointerForNativeRetain(object))
377389
object->refCounts.decrementAndUnpinAndMaybeDeinit();
378390
}
379391

@@ -398,15 +410,15 @@ HeapObject *swift::swift_nonatomic_tryPin(HeapObject *object)
398410

399411
void swift::swift_nonatomic_unpin(HeapObject *object)
400412
SWIFT_CC(RegisterPreservingCC_IMPL) {
401-
if (object)
413+
if (isValidPointerForNativeRetain(object))
402414
object->refCounts.decrementAndUnpinAndMaybeDeinitNonAtomic();
403415
}
404416

405417
SWIFT_RT_ENTRY_IMPL_VISIBILITY
406418
extern "C"
407419
HeapObject *SWIFT_RT_ENTRY_IMPL(swift_tryRetain)(HeapObject *object)
408420
SWIFT_CC(RegisterPreservingCC_IMPL) {
409-
if (!object)
421+
if (!isValidPointerForNativeRetain(object))
410422
return nullptr;
411423

412424
if (object->refCounts.tryIncrement()) return object;
@@ -421,14 +433,14 @@ bool swift_isDeallocating(HeapObject *object) {
421433
SWIFT_RT_ENTRY_IMPL_VISIBILITY
422434
extern "C"
423435
bool SWIFT_RT_ENTRY_IMPL(swift_isDeallocating)(HeapObject *object) {
424-
if (!object)
436+
if (!isValidPointerForNativeRetain(object))
425437
return false;
426438
return object->refCounts.isDeiniting();
427439
}
428440

429441
void swift::swift_unownedRetainStrong(HeapObject *object)
430442
SWIFT_CC(RegisterPreservingCC_IMPL) {
431-
if (!object)
443+
if (!isValidPointerForNativeRetain(object))
432444
return;
433445
assert(object->refCounts.getUnownedCount() &&
434446
"object is not currently unowned-retained");
@@ -439,7 +451,7 @@ void swift::swift_unownedRetainStrong(HeapObject *object)
439451

440452
void swift::swift_unownedRetainStrongAndRelease(HeapObject *object)
441453
SWIFT_CC(RegisterPreservingCC_IMPL) {
442-
if (!object)
454+
if (!isValidPointerForNativeRetain(object))
443455
return;
444456
assert(object->refCounts.getUnownedCount() &&
445457
"object is not currently unowned-retained");
@@ -454,7 +466,7 @@ void swift::swift_unownedRetainStrongAndRelease(HeapObject *object)
454466
}
455467

456468
void swift::swift_unownedCheck(HeapObject *object) {
457-
if (!object) return;
469+
if (!isValidPointerForNativeRetain(object)) return;
458470
assert(object->refCounts.getUnownedCount() &&
459471
"object is not currently unowned-retained");
460472

0 commit comments

Comments
 (0)