Skip to content

Commit 64135ef

Browse files
committed
Implement unknownRetain_n/Release_n entry points
rdar://21945003 Swift SVN r31902
1 parent 27d6f8a commit 64135ef

File tree

4 files changed

+96
-11
lines changed

4 files changed

+96
-11
lines changed

Diff for: include/swift/Runtime/HeapObject.h

+14
Original file line numberDiff line numberDiff line change
@@ -430,13 +430,20 @@ extern "C" void *swift_bridgeObjectRetain(void *value);
430430
/// Increment the strong retain count of an object which might not be a native
431431
/// Swift object.
432432
extern "C" void *swift_unknownRetain(void *value);
433+
/// Increment the strong retain count of an object which might not be a native
434+
/// Swift object by n.
435+
extern "C" void *swift_unknownRetain_n(void *value, int n);
433436

434437
#else
435438

436439
static inline void swift_unknownRetain(void *value) {
437440
swift_retain(static_cast<HeapObject *>(value));
438441
}
439442

443+
static inline void swift_unknownRetain_n(void *value, int n) {
444+
swift_retain_n(static_cast<HeapObject *>(value), n);
445+
}
446+
440447
#endif /* SWIFT_OBJC_INTEROP */
441448

442449
extern "C" void swift_bridgeObjectRelease(void *value);
@@ -446,13 +453,20 @@ extern "C" void swift_bridgeObjectRelease(void *value);
446453
/// Decrement the strong retain count of an object which might not be a native
447454
/// Swift object.
448455
extern "C" void swift_unknownRelease(void *value);
456+
/// Decrement the strong retain count of an object which might not be a native
457+
/// Swift object by n.
458+
extern "C" void swift_unknownRelease_n(void *value, int n);
449459

450460
#else
451461

452462
static inline void swift_unknownRelease(void *value) {
453463
swift_release(static_cast<HeapObject *>(value));
454464
}
455465

466+
static inline void swift_unknownRelease_n(void *value, int n) {
467+
swift_release_n(static_cast<HeapObject *>(value), n);
468+
}
469+
456470
#endif /* SWIFT_OBJC_INTEROP */
457471

458472
#if SWIFT_OBJC_INTEROP

Diff for: stdlib/public/runtime/SwiftObject.mm

+22-4
Original file line numberDiff line numberDiff line change
@@ -566,18 +566,36 @@ static bool usesNativeSwiftReferenceCounting_unowned(const void *object) {
566566
return usesNativeSwiftReferenceCounting_allocated(object);
567567
}
568568

569+
void *swift::swift_unknownRetain_n(void *object, int n) {
570+
void *objc_ret = nullptr;
571+
if (isObjCTaggedPointerOrNull(object)) return object;
572+
if (usesNativeSwiftReferenceCounting_allocated(object))
573+
return swift_retain_n(static_cast<HeapObject *>(object), n);
574+
for (int i = 0; i < n; ++i)
575+
objc_ret = objc_retain(static_cast<id>(object));
576+
return objc_ret;
577+
}
578+
579+
void swift::swift_unknownRelease_n(void *object, int n) {
580+
if (isObjCTaggedPointerOrNull(object)) return;
581+
if (usesNativeSwiftReferenceCounting_allocated(object))
582+
return swift_release_n(static_cast<HeapObject *>(object), n);
583+
for (int i = 0; i < n; ++i)
584+
objc_release(static_cast<id>(object));
585+
}
586+
569587
void *swift::swift_unknownRetain(void *object) {
570588
if (isObjCTaggedPointerOrNull(object)) return object;
571589
if (usesNativeSwiftReferenceCounting_allocated(object))
572-
return swift_retain((HeapObject*) object);
573-
return objc_retain((id) object);
590+
return swift_retain(static_cast<HeapObject *>(object));
591+
return objc_retain(static_cast<id>(object));
574592
}
575593

576594
void swift::swift_unknownRelease(void *object) {
577595
if (isObjCTaggedPointerOrNull(object)) return;
578596
if (usesNativeSwiftReferenceCounting_allocated(object))
579-
return swift_release((HeapObject*) object);
580-
return objc_release((id) object);
597+
return swift_release(static_cast<HeapObject *>(object));
598+
return objc_release(static_cast<id>(object));
581599
}
582600

583601
/// Return true iff the given BridgeObject is not known to use native

Diff for: unittests/runtime/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND
77
find_library(FOUNDATION_LIBRARY Foundation)
88
list(APPEND PLATFORM_SOURCES
99
weak.mm
10+
Refcounting.mm
1011
)
1112
list(APPEND PLATFORM_TARGET_LINK_LIBRARIES
1213
${FOUNDATION_LIBRARY}
@@ -17,7 +18,6 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND
1718
add_swift_unittest(SwiftRuntimeTests
1819
Metadata.cpp
1920
Enum.cpp
20-
Refcounting.cpp
2121
${PLATFORM_SOURCES}
2222
)
2323

Diff for: unittests/runtime/Refcounting.cpp renamed to unittests/runtime/Refcounting.mm

+59-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,27 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include <Foundation/NSObject.h>
14+
#include <objc/runtime.h>
1315
#include "swift/Runtime/HeapObject.h"
1416
#include "swift/Runtime/Metadata.h"
1517
#include "gtest/gtest.h"
1618

1719
using namespace swift;
1820

21+
static unsigned DestroyedObjCCount = 0;
22+
/// A trivial class that increments DestroyedObjCCount when deallocated.
23+
@interface ObjCTestClass : NSObject @end
24+
@implementation ObjCTestClass
25+
- (void) dealloc {
26+
DestroyedObjCCount++;
27+
[super dealloc];
28+
}
29+
@end
30+
static HeapObject *make_objc_object() {
31+
return static_cast<HeapObject *>([ObjCTestClass new]);
32+
}
33+
1934
struct TestObject : HeapObject {
2035
size_t *Addr;
2136
size_t Value;
@@ -29,18 +44,19 @@ static void destroyTestObject(HeapObject *_object) {
2944
swift_deallocObject(object, sizeof(TestObject), alignof(TestObject) - 1);
3045
}
3146

32-
static const FullMetadata<HeapMetadata> TestObjectMetadata{
33-
HeapMetadataHeader{{destroyTestObject}, {nullptr}},
34-
HeapMetadata{Metadata{MetadataKind::HeapLocalVariable}}
47+
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
48+
{ { &destroyTestObject }, { &_TWVBo } },
49+
{ { { MetadataKind::Class } }, 0, /*rodata*/ 1,
50+
ClassFlags::UsesSwift1Refcounting, nullptr, 0, 0, 0, 0, 0 }
3551
};
3652

3753
/// Create an object that, when deallocated, stores the given value to
3854
/// the given pointer.
3955
static TestObject *allocTestObject(size_t *addr, size_t value) {
4056
auto result =
41-
static_cast<TestObject*>(swift_allocObject(&TestObjectMetadata,
42-
sizeof(TestObject),
43-
alignof(TestObject) - 1));
57+
static_cast<TestObject *>(swift_allocObject(&TestClassObjectMetadata,
58+
sizeof(TestObject),
59+
alignof(TestObject) - 1));
4460
result->Addr = addr;
4561
result->Value = value;
4662
return result;
@@ -120,3 +136,40 @@ TEST(RefcountingTest, retain_release_n) {
120136
swift_release(object);
121137
EXPECT_EQ(1u, value);
122138
}
139+
140+
TEST(RefcountingTest, unknown_retain_release_n) {
141+
size_t value = 0;
142+
auto object = allocTestObject(&value, 1);
143+
EXPECT_EQ(0u, value);
144+
auto retainResult = swift_unknownRetain_n(object, 32);
145+
EXPECT_EQ(object, retainResult);
146+
retainResult = swift_unknownRetain(object);
147+
EXPECT_EQ(object, retainResult);
148+
EXPECT_EQ(0u, value);
149+
EXPECT_EQ(34u, swift_retainCount(object));
150+
swift_unknownRelease_n(object, 31);
151+
EXPECT_EQ(0u, value);
152+
EXPECT_EQ(3u, swift_retainCount(object));
153+
swift_unknownRelease(object);
154+
EXPECT_EQ(0u, value);
155+
EXPECT_EQ(2u, swift_retainCount(object));
156+
swift_unknownRelease_n(object, 1);
157+
EXPECT_EQ(0u, value);
158+
EXPECT_EQ(1u, swift_retainCount(object));
159+
swift_unknownRelease(object);
160+
EXPECT_EQ(1u, value);
161+
}
162+
163+
TEST(RefcountingTest, objc_unknown_retain_release_n) {
164+
auto object = make_objc_object();
165+
auto retainResult = swift_unknownRetain_n(object, 32);
166+
EXPECT_EQ(object, retainResult);
167+
retainResult = swift_unknownRetain(object);
168+
EXPECT_EQ(object, retainResult);
169+
swift_unknownRelease_n(object, 31);
170+
swift_unknownRelease(object);
171+
swift_unknownRelease_n(object, 1);
172+
swift_unknownRelease(object);
173+
// The object should be destroyed by now.
174+
EXPECT_EQ(1u, DestroyedObjCCount);
175+
}

0 commit comments

Comments
 (0)