17
17
using namespace swift ;
18
18
19
19
struct TestObject : HeapObject {
20
+ constexpr TestObject (HeapMetadata const *newMetadata)
21
+ : HeapObject(newMetadata, InlineRefCounts::Immortal)
22
+ , Addr(NULL ), Value(0 ) {}
23
+
20
24
size_t *Addr;
21
25
size_t Value;
22
26
};
@@ -34,6 +38,8 @@ static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
34
38
{ { nullptr }, ClassFlags::UsesSwiftRefcounting, 0 , 0 , 0 , 0 , 0 , 0 }
35
39
};
36
40
41
+ static TestObject ImmortalTestObject{&TestClassObjectMetadata};
42
+
37
43
// / Create an object that, when deallocated, stores the given value to
38
44
// / the given pointer.
39
45
static TestObject *allocTestObject (size_t *addr, size_t value) {
@@ -220,3 +226,49 @@ TEST(RefcountingTest, nonatomic_unknown_retain_release_n) {
220
226
EXPECT_EQ (0u , value);
221
227
EXPECT_EQ (1u , swift_retainCount (object));
222
228
}
229
+
230
+ // Verify that refcounting operations on immortal objects never changes the
231
+ // refcount field.
232
+ TEST (RefcountingTest, immortal_retain_release) {
233
+ auto initialBitsValue = ImmortalTestObject.refCounts .getBitsValue ();
234
+
235
+ swift_retain (&ImmortalTestObject);
236
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
237
+ swift_release (&ImmortalTestObject);
238
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
239
+ swift_nonatomic_retain (&ImmortalTestObject);
240
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
241
+ swift_nonatomic_release (&ImmortalTestObject);
242
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
243
+
244
+ swift_unownedRetain (&ImmortalTestObject);
245
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
246
+ swift_unownedRelease (&ImmortalTestObject);
247
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
248
+ swift_nonatomic_unownedRetain (&ImmortalTestObject);
249
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
250
+ swift_nonatomic_unownedRelease (&ImmortalTestObject);
251
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
252
+
253
+ for (unsigned i = 0 ; i < 32 ; i++) {
254
+ uint32_t amount = 1U << i;
255
+
256
+ swift_retain_n (&ImmortalTestObject, amount);
257
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
258
+ swift_release_n (&ImmortalTestObject, amount);
259
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
260
+ swift_nonatomic_retain_n (&ImmortalTestObject, amount);
261
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
262
+ swift_nonatomic_release_n (&ImmortalTestObject, amount);
263
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
264
+
265
+ swift_unownedRetain_n (&ImmortalTestObject, amount);
266
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
267
+ swift_unownedRelease_n (&ImmortalTestObject, amount);
268
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
269
+ swift_nonatomic_unownedRetain_n (&ImmortalTestObject, amount);
270
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
271
+ swift_nonatomic_unownedRelease_n (&ImmortalTestObject, amount);
272
+ EXPECT_EQ (initialBitsValue, ImmortalTestObject.refCounts .getBitsValue ());
273
+ }
274
+ }
0 commit comments