Skip to content

Commit aea9c0c

Browse files
committed
[Runtime] Allow weak references to ErrorObjects.
When ObjC interop is not available, Error values are represented in ErrorObject boxes. These are full HeapObjects, but unowned refcounting ops asserted that the metadata was class metadata. This assert would be hit when destroying an ErrorObject that was weakly referenced. Expand the asserts to accept ErrorObject metadata as well. rdar://150214921
1 parent 749e9ee commit aea9c0c

File tree

1 file changed

+14
-12
lines changed

1 file changed

+14
-12
lines changed

stdlib/public/runtime/HeapObject.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,16 @@ HeapObject *swift::swift_unownedRetain(HeapObject *object) {
547547
#endif
548548
}
549549

550+
// Assert that the metadata is a class or ErrorObject, for unowned operations.
551+
// Other types of metadata are not supposed to be used with unowned.
552+
static void checkMetadataForUnownedRR(HeapObject *object) {
553+
assert(object->metadata->isClassObject() ||
554+
object->metadata->getKind() == MetadataKind::ErrorObject);
555+
if (object->metadata->isClassObject())
556+
assert(
557+
static_cast<const ClassMetadata *>(object->metadata)->isTypeMetadata());
558+
}
559+
550560
void swift::swift_unownedRelease(HeapObject *object) {
551561
#ifdef SWIFT_THREADING_NONE
552562
swift_nonatomic_unownedRelease(object);
@@ -555,9 +565,7 @@ void swift::swift_unownedRelease(HeapObject *object) {
555565
if (!isValidPointerForNativeRetain(object))
556566
return;
557567

558-
// Only class objects can be unowned-retained and unowned-released.
559-
assert(object->metadata->isClassObject());
560-
assert(static_cast<const ClassMetadata*>(object->metadata)->isTypeMetadata());
568+
checkMetadataForUnownedRR(object);
561569

562570
if (object->refCounts.decrementUnownedShouldFree(1)) {
563571
auto classMetadata = static_cast<const ClassMetadata*>(object->metadata);
@@ -582,9 +590,7 @@ void swift::swift_nonatomic_unownedRelease(HeapObject *object) {
582590
if (!isValidPointerForNativeRetain(object))
583591
return;
584592

585-
// Only class objects can be unowned-retained and unowned-released.
586-
assert(object->metadata->isClassObject());
587-
assert(static_cast<const ClassMetadata*>(object->metadata)->isTypeMetadata());
593+
checkMetadataForUnownedRR(object);
588594

589595
if (object->refCounts.decrementUnownedShouldFreeNonAtomic(1)) {
590596
auto classMetadata = static_cast<const ClassMetadata*>(object->metadata);
@@ -615,9 +621,7 @@ void swift::swift_unownedRelease_n(HeapObject *object, int n) {
615621
if (!isValidPointerForNativeRetain(object))
616622
return;
617623

618-
// Only class objects can be unowned-retained and unowned-released.
619-
assert(object->metadata->isClassObject());
620-
assert(static_cast<const ClassMetadata*>(object->metadata)->isTypeMetadata());
624+
checkMetadataForUnownedRR(object);
621625

622626
if (object->refCounts.decrementUnownedShouldFree(n)) {
623627
auto classMetadata = static_cast<const ClassMetadata*>(object->metadata);
@@ -641,9 +645,7 @@ void swift::swift_nonatomic_unownedRelease_n(HeapObject *object, int n) {
641645
if (!isValidPointerForNativeRetain(object))
642646
return;
643647

644-
// Only class objects can be unowned-retained and unowned-released.
645-
assert(object->metadata->isClassObject());
646-
assert(static_cast<const ClassMetadata*>(object->metadata)->isTypeMetadata());
648+
checkMetadataForUnownedRR(object);
647649

648650
if (object->refCounts.decrementUnownedShouldFreeNonAtomic(n)) {
649651
auto classMetadata = static_cast<const ClassMetadata*>(object->metadata);

0 commit comments

Comments
 (0)