Skip to content

Commit 4d1b6e2

Browse files
committed
Reform the runtime interface for unowned reference-counting.
This is a bit of a hodge-podge of related changes that I decided weren't quite worth teasing apart: First, rename the weak{Retain,Release} entrypoints to unowned{Retain,Release} to better reflect their actual use from generated code. Second, standardize the names of the rest of the entrypoints around unowned{operation}. Third, standardize IRGen's internal naming scheme and API for reference-counting so that (1) there are generic functions for emitting operations using a given reference-counting style and (2) all operations explicitly call out the kind and style of reference counting. Finally, implement a number of new entrypoints for unknown unowned reference-counting. These entrypoints use a completely different and incompatible scheme for working with ObjC references. The primary difference is that the new scheme abandons the flawed idea (which I take responsibility for) that we can simulate an unowned reference count for ObjC references, and instead moves towards an address-only scheme when the reference might store an ObjC reference. (The current implementation is still trivially takable, but that is not something we should be relying on.) These will be tested in a follow-up commit. For now, we still rely on the bad assumption of reference-countability.
1 parent bebb76b commit 4d1b6e2

26 files changed

+1112
-460
lines changed

include/swift/Runtime/HeapObject.h

Lines changed: 286 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ extern "C" void swift_release_n(HeapObject *object, uint32_t n);
228228

229229
/// ObjC compatibility. Never call this.
230230
extern "C" size_t swift_retainCount(HeapObject *object);
231-
extern "C" size_t swift_weakRetainCount(HeapObject *object);
231+
extern "C" size_t swift_unownedRetainCount(HeapObject *object);
232232

233233
/// Is this pointer a non-null unique reference to an object
234234
/// that uses Swift reference counting?
@@ -381,24 +381,103 @@ class SwiftRAII {
381381
HeapObject *operator *() const { return object; }
382382
};
383383

384-
/// Increment the weak retain count.
385-
extern "C" void swift_weakRetain(HeapObject *value);
384+
/*****************************************************************************/
385+
/**************************** UNOWNED REFERENCES *****************************/
386+
/*****************************************************************************/
386387

387-
/// Decrement the weak retain count.
388-
extern "C" void swift_weakRelease(HeapObject *value);
388+
/// An unowned reference in memory. This is ABI.
389+
struct UnownedReference {
390+
HeapObject *Value;
391+
};
392+
393+
/// Increment the weak/unowned retain count.
394+
extern "C" void swift_unownedRetain(HeapObject *value);
389395

390-
/// Increment the weak retain count by n.
391-
extern "C" void swift_weakRetain_n(HeapObject *value, int n);
396+
/// Decrement the weak/unowned retain count.
397+
extern "C" void swift_unownedRelease(HeapObject *value);
392398

393-
/// Decrement the weak retain count by n.
394-
extern "C" void swift_weakRelease_n(HeapObject *value, int n);
399+
/// Increment the weak/unowned retain count by n.
400+
extern "C" void swift_unownedRetain_n(HeapObject *value, int n);
401+
402+
/// Decrement the weak/unowned retain count by n.
403+
extern "C" void swift_unownedRelease_n(HeapObject *value, int n);
404+
405+
/// Increment the strong retain count of an object, aborting if it has
406+
/// been deallocated.
407+
extern "C" void swift_unownedRetainStrong(HeapObject *value);
395408

396409
/// Increment the strong retain count of an object which may have been
397-
/// deallocated.
398-
extern "C" void swift_retainUnowned(HeapObject *value);
410+
/// deallocated, aborting if it has been deallocated, and decrement its
411+
/// weak/unowned reference count.
412+
extern "C" void swift_unownedRetainStrongAndRelease(HeapObject *value);
399413

400414
/// Aborts if the object has been deallocated.
401-
extern "C" void swift_checkUnowned(HeapObject *value);
415+
extern "C" void swift_unownedCheck(HeapObject *value);
416+
417+
static inline void swift_unownedInit(UnownedReference *ref, HeapObject *value) {
418+
ref->Value = value;
419+
swift_unownedRetain(value);
420+
}
421+
422+
static inline void swift_unownedAssign(UnownedReference *ref,
423+
HeapObject *value) {
424+
auto oldValue = ref->Value;
425+
if (value != oldValue) {
426+
swift_unownedRetain(value);
427+
ref->Value = value;
428+
swift_unownedRelease(oldValue);
429+
}
430+
}
431+
432+
static inline HeapObject *swift_unownedLoadStrong(UnownedReference *ref) {
433+
auto value = ref->Value;
434+
swift_unownedRetainStrong(value);
435+
return value;
436+
}
437+
438+
static inline void *swift_unownedTakeStrong(UnownedReference *ref) {
439+
auto value = ref->Value;
440+
swift_unownedRetainStrongAndRelease(value);
441+
return value;
442+
}
443+
444+
static inline void swift_unownedDestroy(UnownedReference *ref) {
445+
swift_unownedRelease(ref->Value);
446+
}
447+
448+
static inline void swift_unownedCopyInit(UnownedReference *dest,
449+
UnownedReference *src) {
450+
dest->Value = src->Value;
451+
swift_unownedRetain(dest->Value);
452+
}
453+
454+
static inline void swift_unownedTakeInit(UnownedReference *dest,
455+
UnownedReference *src) {
456+
dest->Value = src->Value;
457+
}
458+
459+
static inline void swift_unownedCopyAssign(UnownedReference *dest,
460+
UnownedReference *src) {
461+
auto newValue = src->Value;
462+
auto oldValue = dest->Value;
463+
if (newValue != oldValue) {
464+
dest->Value = newValue;
465+
swift_unownedRetain(newValue);
466+
swift_unownedRelease(oldValue);
467+
}
468+
}
469+
470+
static inline void swift_unownedTakeAssign(UnownedReference *dest,
471+
UnownedReference *src) {
472+
auto newValue = src->Value;
473+
auto oldValue = dest->Value;
474+
dest->Value = newValue;
475+
swift_unownedRelease(oldValue);
476+
}
477+
478+
/*****************************************************************************/
479+
/****************************** WEAK REFERENCES ******************************/
480+
/*****************************************************************************/
402481

403482
/// A weak reference value object. This is ABI.
404483
struct WeakReference {
@@ -461,10 +540,18 @@ extern "C" void swift_weakCopyAssign(WeakReference *dest, WeakReference *src);
461540
/// \param src - never null, but can refer to a null object
462541
extern "C" void swift_weakTakeAssign(WeakReference *dest, WeakReference *src);
463542

543+
/*****************************************************************************/
544+
/************************* OTHER REFERENCE-COUNTING **************************/
545+
/*****************************************************************************/
546+
464547
extern "C" void *swift_bridgeObjectRetain(void *value);
465548
/// Increment the strong retain count of a bridged object by n.
466549
extern "C" void *swift_bridgeObjectRetain_n(void *value, int n);
467550

551+
/*****************************************************************************/
552+
/************************ UNKNOWN REFERENCE-COUNTING *************************/
553+
/*****************************************************************************/
554+
468555
#if SWIFT_OBJC_INTEROP
469556

470557
/// Increment the strong retain count of an object which might not be a native
@@ -511,47 +598,9 @@ static inline void swift_unknownRelease_n(void *value, int n) {
511598

512599
#endif /* SWIFT_OBJC_INTEROP */
513600

514-
#if SWIFT_OBJC_INTEROP
515-
516-
/// Increment the strong retain count of an object which may have been
517-
/// deallocated and which might not be a native Swift object.
518-
extern "C" void swift_unknownRetainUnowned(void *value);
519-
520-
#else
521-
522-
static inline void swift_unknownRetainUnowned(void *value) {
523-
swift_retainUnowned(static_cast<HeapObject *>(value));
524-
}
525-
526-
#endif /* SWIFT_OBJC_INTEROP */
527-
528-
#if SWIFT_OBJC_INTEROP
529-
530-
/// Increment the weak-reference count of an object that might not be
531-
/// a native Swift object.
532-
extern "C" void swift_unknownWeakRetain(void *value);
533-
534-
#else
535-
536-
static inline void swift_unknownWeakRetain(void *value) {
537-
swift_weakRetain(static_cast<HeapObject *>(value));
538-
}
539-
540-
#endif /* SWIFT_OBJC_INTEROP */
541-
542-
#if SWIFT_OBJC_INTEROP
543-
544-
/// Decrement the weak-reference count of an object that might not be
545-
/// a native Swift object.
546-
extern "C" void swift_unknownWeakRelease(void *value);
547-
548-
#else
549-
550-
static inline void swift_unknownWeakRelease(void *value) {
551-
swift_weakRelease(static_cast<HeapObject *>(value));
552-
}
553-
554-
#endif /* SWIFT_OBJC_INTEROP */
601+
/*****************************************************************************/
602+
/************************** UNKNOWN WEAK REFERENCES **************************/
603+
/*****************************************************************************/
555604

556605
#if SWIFT_OBJC_INTEROP
557606

@@ -690,6 +739,190 @@ static inline void swift_unknownWeakTakeAssign(WeakReference *dest, WeakReferenc
690739

691740
#endif /* SWIFT_OBJC_INTEROP */
692741

742+
/*****************************************************************************/
743+
/************************ UNKNOWN UNOWNED REFERENCES *************************/
744+
/*****************************************************************************/
745+
746+
// TODO: these first three functions cannot be correctly supported.
747+
748+
#if SWIFT_OBJC_INTEROP
749+
750+
/// Increment the strong retain count of an object which may have been
751+
/// deallocated and which might not be a native Swift object.
752+
extern "C" void swift_unknownUnownedRetainStrong(void *value);
753+
754+
#else
755+
756+
static inline void swift_unknownUnownedRetainStrong(void *value) {
757+
swift_unownedRetain(static_cast<HeapObject *>(value));
758+
}
759+
760+
#endif /* SWIFT_OBJC_INTEROP */
761+
762+
#if SWIFT_OBJC_INTEROP
763+
764+
/// Increment the weak/unowned reference count of an object that might
765+
/// not be a native Swift object.
766+
extern "C" void swift_unknownUnownedRetain(void *value);
767+
768+
#else
769+
770+
static inline void swift_unknownUnownedRetain(void *value) {
771+
swift_unownedRetain(static_cast<HeapObject *>(value));
772+
}
773+
774+
#endif /* SWIFT_OBJC_INTEROP */
775+
776+
#if SWIFT_OBJC_INTEROP
777+
778+
/// Decrement the weak/unowned reference count of an object that might not be
779+
/// a native Swift object.
780+
extern "C" void swift_unknownUnownedRelease(void *value);
781+
782+
#else
783+
784+
static inline void swift_unknownUnownedRelease(void *value) {
785+
swift_unownedRelease(static_cast<HeapObject *>(value));
786+
}
787+
788+
#endif /* SWIFT_OBJC_INTEROP */
789+
790+
#if SWIFT_OBJC_INTEROP
791+
792+
/// Initialize an unowned reference to an object with unknown reference
793+
/// counting.
794+
extern "C" void swift_unknownUnownedInit(UnownedReference *ref, void *value);
795+
796+
#else
797+
798+
static inline void swift_unknownUnownedInit(UnownedReference *ref,
799+
void *value) {
800+
swift_unownedInit(ref, static_cast<HeapObject*>(value));
801+
}
802+
803+
#endif /* SWIFT_OBJC_INTEROP */
804+
805+
#if SWIFT_OBJC_INTEROP
806+
807+
/// Assign to an unowned reference holding an object with unknown reference
808+
/// counting.
809+
extern "C" void swift_unknownUnownedAssign(UnownedReference *ref, void *value);
810+
811+
#else
812+
813+
static inline void swift_unknownUnownedAssign(UnownedReference *ref,
814+
void *value) {
815+
swift_unownedAssign(ref, static_cast<HeapObject*>(value));
816+
}
817+
818+
#endif /* SWIFT_OBJC_INTEROP */
819+
820+
#if SWIFT_OBJC_INTEROP
821+
822+
/// Load from an unowned reference to an object with unknown reference
823+
/// counting.
824+
extern "C" void *swift_unknownUnownedLoadStrong(UnownedReference *ref);
825+
826+
#else
827+
828+
static inline void *swift_unknownUnownedLoadStrong(UnownedReference *ref) {
829+
return swift_unownedLoadStrong(ref);
830+
}
831+
832+
#endif /* SWIFT_OBJC_INTEROP */
833+
834+
#if SWIFT_OBJC_INTEROP
835+
836+
/// Take from an unowned reference to an object with unknown reference
837+
/// counting.
838+
extern "C" void *swift_unknownUnownedTakeStrong(UnownedReference *ref);
839+
840+
#else
841+
842+
static inline void *swift_unknownUnownedTakeStrong(UnownedReference *ref) {
843+
return swift_unownedTakeStrong(ref);
844+
}
845+
846+
#endif /* SWIFT_OBJC_INTEROP */
847+
848+
#if SWIFT_OBJC_INTEROP
849+
850+
/// Destroy an unowned reference to an object with unknown reference counting.
851+
extern "C" void swift_unknownUnownedDestroy(UnownedReference *ref);
852+
853+
#else
854+
855+
static inline void swift_unknownUnownedDestroy(UnownedReference *ref) {
856+
swift_unownedDestroy(ref);
857+
}
858+
859+
#endif /* SWIFT_OBJC_INTEROP */
860+
861+
#if SWIFT_OBJC_INTEROP
862+
863+
/// Copy-initialize an unowned reference variable from one that might not
864+
/// refer to a native Swift object.
865+
extern "C" void swift_unknownUnownedCopyInit(UnownedReference *dest,
866+
UnownedReference *src);
867+
868+
#else
869+
870+
static inline void swift_unknownUnownedCopyInit(UnownedReference *dest,
871+
UnownedReference *src) {
872+
swift_unownedCopyInit(dest, src);
873+
}
874+
875+
#endif /* SWIFT_OBJC_INTEROP */
876+
877+
#if SWIFT_OBJC_INTEROP
878+
879+
/// Take-initialize an unowned reference variable from one that might not
880+
/// refer to a native Swift object.
881+
extern "C" void swift_unknownUnownedTakeInit(UnownedReference *dest,
882+
UnownedReference *src);
883+
884+
#else
885+
886+
static inline void swift_unknownUnownedTakeInit(UnownedReference *dest,
887+
UnownedReference *src) {
888+
swift_unownedTakeInit(dest, src);
889+
}
890+
891+
#endif /* SWIFT_OBJC_INTEROP */
892+
893+
#if SWIFT_OBJC_INTEROP
894+
895+
/// Copy-assign an unowned reference variable from another when either
896+
/// or both variables might not refer to a native Swift object.
897+
extern "C" void swift_unknownUnownedCopyAssign(UnownedReference *dest,
898+
UnownedReference *src);
899+
900+
#else
901+
902+
static inline void swift_unknownUnownedCopyAssign(UnownedReference *dest,
903+
UnownedReference *src) {
904+
swift_unownedCopyAssign(dest, src);
905+
}
906+
907+
#endif /* SWIFT_OBJC_INTEROP */
908+
909+
#if SWIFT_OBJC_INTEROP
910+
911+
/// Take-assign an unowned reference variable from another when either
912+
/// or both variables might not refer to a native Swift object.
913+
extern "C" void swift_unknownUnownedTakeAssign(UnownedReference *dest,
914+
UnownedReference *src);
915+
916+
#else
917+
918+
static inline void swift_unknownUnownedTakeAssign(UnownedReference *dest,
919+
UnownedReference *src) {
920+
swift_unownedTakeAssign(dest, src);
921+
}
922+
923+
#endif /* SWIFT_OBJC_INTEROP */
924+
925+
693926
} // end namespace swift
694927

695928
#endif /* SWIFT_RUNTIME_ALLOC_H */

lib/IRGen/GenClass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ static bool getInstanceSizeByMethod(IRGenFunction &IGF,
672672

673673
// Retain 'self' if necessary.
674674
if (fnType->getParameters()[0].isConsumed()) {
675-
IGF.emitRetainCall(selfValue);
675+
IGF.emitNativeStrongRetain(selfValue);
676676
}
677677

678678
// Adjust down to the defining subclass type if necessary.

0 commit comments

Comments
 (0)