2 // Implementation of class TestRoot
3 // Include this file into your main test file to use it.
7 #include <objc/objc-internal.h>
9 atomic_int TestRootLoad;
10 atomic_int TestRootInitialize;
11 atomic_int TestRootAlloc;
12 atomic_int TestRootAllocWithZone;
13 atomic_int TestRootCopy;
14 atomic_int TestRootCopyWithZone;
15 atomic_int TestRootMutableCopy;
16 atomic_int TestRootMutableCopyWithZone;
17 atomic_int TestRootInit;
18 atomic_int TestRootDealloc;
19 atomic_int TestRootRetain;
20 atomic_int TestRootRelease;
21 atomic_int TestRootAutorelease;
22 atomic_int TestRootRetainCount;
23 atomic_int TestRootTryRetain;
24 atomic_int TestRootIsDeallocating;
25 atomic_int TestRootPlusRetain;
26 atomic_int TestRootPlusRelease;
27 atomic_int TestRootPlusAutorelease;
28 atomic_int TestRootPlusRetainCount;
31 @implementation TestRoot
33 // These all use void* pending rdar://9310005.
36 retain_fn(void *self, SEL _cmd __unused) {
37 atomic_fetch_add_explicit(&TestRootRetain, 1, memory_order_relaxed);
38 void * (*fn)(void *) = (typeof(fn))_objc_rootRetain;
43 release_fn(void *self, SEL _cmd __unused) {
44 atomic_fetch_add_explicit(&TestRootRelease, 1, memory_order_relaxed);
45 void (*fn)(void *) = (typeof(fn))_objc_rootRelease;
50 autorelease_fn(void *self, SEL _cmd __unused) {
51 atomic_fetch_add_explicit(&TestRootAutorelease, 1, memory_order_relaxed);
52 void * (*fn)(void *) = (typeof(fn))_objc_rootAutorelease;
57 retaincount_fn(void *self, SEL _cmd __unused) {
58 atomic_fetch_add_explicit(&TestRootRetainCount, 1, memory_order_relaxed);
59 unsigned long (*fn)(void *) = (typeof(fn))_objc_rootRetainCount;
64 copywithzone_fn(void *self, SEL _cmd __unused, void *zone) {
65 atomic_fetch_add_explicit(&TestRootCopyWithZone, 1, memory_order_relaxed);
66 void * (*fn)(void *, void *) =
67 (typeof(fn))dlsym(RTLD_DEFAULT, "object_copy");
68 return fn(self, zone);
72 plusretain_fn(void *self __unused, SEL _cmd __unused) {
73 atomic_fetch_add_explicit(&TestRootPlusRetain, 1, memory_order_relaxed);
78 plusrelease_fn(void *self __unused, SEL _cmd __unused) {
79 atomic_fetch_add_explicit(&TestRootPlusRelease, 1, memory_order_relaxed);
83 plusautorelease_fn(void *self, SEL _cmd __unused) {
84 atomic_fetch_add_explicit(&TestRootPlusAutorelease, 1, memory_order_relaxed);
89 plusretaincount_fn(void *self __unused, SEL _cmd __unused) {
90 atomic_fetch_add_explicit(&TestRootPlusRetainCount, 1, memory_order_relaxed);
95 atomic_fetch_add_explicit(&TestRootLoad, 1, memory_order_relaxed);
97 // install methods that ARC refuses to compile
98 class_addMethod(self, sel_registerName("retain"), (IMP)retain_fn, "");
99 class_addMethod(self, sel_registerName("release"), (IMP)release_fn, "");
100 class_addMethod(self, sel_registerName("autorelease"), (IMP)autorelease_fn, "");
101 class_addMethod(self, sel_registerName("retainCount"), (IMP)retaincount_fn, "");
102 class_addMethod(self, sel_registerName("copyWithZone:"), (IMP)copywithzone_fn, "");
104 class_addMethod(object_getClass(self), sel_registerName("retain"), (IMP)plusretain_fn, "");
105 class_addMethod(object_getClass(self), sel_registerName("release"), (IMP)plusrelease_fn, "");
106 class_addMethod(object_getClass(self), sel_registerName("autorelease"), (IMP)plusautorelease_fn, "");
107 class_addMethod(object_getClass(self), sel_registerName("retainCount"), (IMP)plusretaincount_fn, "");
112 atomic_fetch_add_explicit(&TestRootInitialize, 1, memory_order_relaxed);
124 return object_getClass(self);
127 +(Class) superclass {
128 return class_getSuperclass(self);
131 -(Class) superclass {
132 return class_getSuperclass([self class]);
136 return [[self alloc] init];
140 atomic_fetch_add_explicit(&TestRootAlloc, 1, memory_order_relaxed);
141 void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc;
142 return (__bridge_transfer id)(fn(self));
145 +(id) allocWithZone:(void *)zone {
146 atomic_fetch_add_explicit(&TestRootAllocWithZone, 1, memory_order_relaxed);
147 void * (*fn)(id __unsafe_unretained, void *) = (typeof(fn))_objc_rootAllocWithZone;
148 return (__bridge_transfer id)(fn(self, zone));
155 +(id) copyWithZone:(void *) __unused zone {
160 atomic_fetch_add_explicit(&TestRootCopy, 1, memory_order_relaxed);
161 return [self copyWithZone:NULL];
164 +(id) mutableCopyWithZone:(void *) __unused zone {
165 fail("+mutableCopyWithZone: called");
169 atomic_fetch_add_explicit(&TestRootMutableCopy, 1, memory_order_relaxed);
170 return [self mutableCopyWithZone:NULL];
173 -(id) mutableCopyWithZone:(void *) __unused zone {
174 atomic_fetch_add_explicit(&TestRootMutableCopyWithZone, 1, memory_order_relaxed);
175 void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc;
176 return (__bridge_transfer id)(fn(object_getClass(self)));
180 atomic_fetch_add_explicit(&TestRootInit, 1, memory_order_relaxed);
181 return _objc_rootInit(self);
185 fail("+dealloc called");
189 atomic_fetch_add_explicit(&TestRootDealloc, 1, memory_order_relaxed);
190 _objc_rootDealloc(self);
198 atomic_fetch_add_explicit(&TestRootTryRetain, 1, memory_order_relaxed);
199 return _objc_rootTryRetain(self);
202 +(BOOL) _isDeallocating {
206 -(BOOL) _isDeallocating {
207 atomic_fetch_add_explicit(&TestRootIsDeallocating, 1, memory_order_relaxed);
208 return _objc_rootIsDeallocating(self);
211 -(BOOL) allowsWeakReference {
212 return ! [self _isDeallocating];
215 -(BOOL) retainWeakReference {
216 return [self _tryRetain];