testroot.i 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // testroot.i
  2. // Implementation of class TestRoot
  3. // Include this file into your main test file to use it.
  4. #include "test.h"
  5. #include <dlfcn.h>
  6. #include <objc/objc-internal.h>
  7. atomic_int TestRootLoad;
  8. atomic_int TestRootInitialize;
  9. atomic_int TestRootAlloc;
  10. atomic_int TestRootAllocWithZone;
  11. atomic_int TestRootCopy;
  12. atomic_int TestRootCopyWithZone;
  13. atomic_int TestRootMutableCopy;
  14. atomic_int TestRootMutableCopyWithZone;
  15. atomic_int TestRootInit;
  16. atomic_int TestRootDealloc;
  17. atomic_int TestRootRetain;
  18. atomic_int TestRootRelease;
  19. atomic_int TestRootAutorelease;
  20. atomic_int TestRootRetainCount;
  21. atomic_int TestRootTryRetain;
  22. atomic_int TestRootIsDeallocating;
  23. atomic_int TestRootPlusRetain;
  24. atomic_int TestRootPlusRelease;
  25. atomic_int TestRootPlusAutorelease;
  26. atomic_int TestRootPlusRetainCount;
  27. @implementation TestRoot
  28. // These all use void* pending rdar://9310005.
  29. static void *
  30. retain_fn(void *self, SEL _cmd __unused) {
  31. atomic_fetch_add_explicit(&TestRootRetain, 1, memory_order_relaxed);
  32. void * (*fn)(void *) = (typeof(fn))_objc_rootRetain;
  33. return fn(self);
  34. }
  35. static void
  36. release_fn(void *self, SEL _cmd __unused) {
  37. atomic_fetch_add_explicit(&TestRootRelease, 1, memory_order_relaxed);
  38. void (*fn)(void *) = (typeof(fn))_objc_rootRelease;
  39. fn(self);
  40. }
  41. static void *
  42. autorelease_fn(void *self, SEL _cmd __unused) {
  43. atomic_fetch_add_explicit(&TestRootAutorelease, 1, memory_order_relaxed);
  44. void * (*fn)(void *) = (typeof(fn))_objc_rootAutorelease;
  45. return fn(self);
  46. }
  47. static unsigned long
  48. retaincount_fn(void *self, SEL _cmd __unused) {
  49. atomic_fetch_add_explicit(&TestRootRetainCount, 1, memory_order_relaxed);
  50. unsigned long (*fn)(void *) = (typeof(fn))_objc_rootRetainCount;
  51. return fn(self);
  52. }
  53. static void *
  54. copywithzone_fn(void *self, SEL _cmd __unused, void *zone) {
  55. atomic_fetch_add_explicit(&TestRootCopyWithZone, 1, memory_order_relaxed);
  56. void * (*fn)(void *, void *) =
  57. (typeof(fn))dlsym(RTLD_DEFAULT, "object_copy");
  58. return fn(self, zone);
  59. }
  60. static void *
  61. plusretain_fn(void *self __unused, SEL _cmd __unused) {
  62. atomic_fetch_add_explicit(&TestRootPlusRetain, 1, memory_order_relaxed);
  63. return self;
  64. }
  65. static void
  66. plusrelease_fn(void *self __unused, SEL _cmd __unused) {
  67. atomic_fetch_add_explicit(&TestRootPlusRelease, 1, memory_order_relaxed);
  68. }
  69. static void *
  70. plusautorelease_fn(void *self, SEL _cmd __unused) {
  71. atomic_fetch_add_explicit(&TestRootPlusAutorelease, 1, memory_order_relaxed);
  72. return self;
  73. }
  74. static unsigned long
  75. plusretaincount_fn(void *self __unused, SEL _cmd __unused) {
  76. atomic_fetch_add_explicit(&TestRootPlusRetainCount, 1, memory_order_relaxed);
  77. return ULONG_MAX;
  78. }
  79. +(void) load {
  80. atomic_fetch_add_explicit(&TestRootLoad, 1, memory_order_relaxed);
  81. // install methods that ARC refuses to compile
  82. class_addMethod(self, sel_registerName("retain"), (IMP)retain_fn, "");
  83. class_addMethod(self, sel_registerName("release"), (IMP)release_fn, "");
  84. class_addMethod(self, sel_registerName("autorelease"), (IMP)autorelease_fn, "");
  85. class_addMethod(self, sel_registerName("retainCount"), (IMP)retaincount_fn, "");
  86. class_addMethod(self, sel_registerName("copyWithZone:"), (IMP)copywithzone_fn, "");
  87. class_addMethod(object_getClass(self), sel_registerName("retain"), (IMP)plusretain_fn, "");
  88. class_addMethod(object_getClass(self), sel_registerName("release"), (IMP)plusrelease_fn, "");
  89. class_addMethod(object_getClass(self), sel_registerName("autorelease"), (IMP)plusautorelease_fn, "");
  90. class_addMethod(object_getClass(self), sel_registerName("retainCount"), (IMP)plusretaincount_fn, "");
  91. }
  92. +(void) initialize {
  93. atomic_fetch_add_explicit(&TestRootInitialize, 1, memory_order_relaxed);
  94. }
  95. -(id) self {
  96. return self;
  97. }
  98. +(Class) class {
  99. return self;
  100. }
  101. -(Class) class {
  102. return object_getClass(self);
  103. }
  104. +(Class) superclass {
  105. return class_getSuperclass(self);
  106. }
  107. -(Class) superclass {
  108. return class_getSuperclass([self class]);
  109. }
  110. +(id) new {
  111. return [[self alloc] init];
  112. }
  113. +(id) alloc {
  114. atomic_fetch_add_explicit(&TestRootAlloc, 1, memory_order_relaxed);
  115. void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc;
  116. return (__bridge_transfer id)(fn(self));
  117. }
  118. +(id) allocWithZone:(void *)zone {
  119. atomic_fetch_add_explicit(&TestRootAllocWithZone, 1, memory_order_relaxed);
  120. void * (*fn)(id __unsafe_unretained, void *) = (typeof(fn))_objc_rootAllocWithZone;
  121. return (__bridge_transfer id)(fn(self, zone));
  122. }
  123. +(id) copy {
  124. return self;
  125. }
  126. +(id) copyWithZone:(void *) __unused zone {
  127. return self;
  128. }
  129. -(id) copy {
  130. atomic_fetch_add_explicit(&TestRootCopy, 1, memory_order_relaxed);
  131. return [self copyWithZone:NULL];
  132. }
  133. +(id) mutableCopyWithZone:(void *) __unused zone {
  134. fail("+mutableCopyWithZone: called");
  135. }
  136. -(id) mutableCopy {
  137. atomic_fetch_add_explicit(&TestRootMutableCopy, 1, memory_order_relaxed);
  138. return [self mutableCopyWithZone:NULL];
  139. }
  140. -(id) mutableCopyWithZone:(void *) __unused zone {
  141. atomic_fetch_add_explicit(&TestRootMutableCopyWithZone, 1, memory_order_relaxed);
  142. void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc;
  143. return (__bridge_transfer id)(fn(object_getClass(self)));
  144. }
  145. -(id) init {
  146. atomic_fetch_add_explicit(&TestRootInit, 1, memory_order_relaxed);
  147. return _objc_rootInit(self);
  148. }
  149. +(void) dealloc {
  150. fail("+dealloc called");
  151. }
  152. -(void) dealloc {
  153. atomic_fetch_add_explicit(&TestRootDealloc, 1, memory_order_relaxed);
  154. _objc_rootDealloc(self);
  155. }
  156. +(BOOL) _tryRetain {
  157. return YES;
  158. }
  159. -(BOOL) _tryRetain {
  160. atomic_fetch_add_explicit(&TestRootTryRetain, 1, memory_order_relaxed);
  161. return _objc_rootTryRetain(self);
  162. }
  163. +(BOOL) _isDeallocating {
  164. return NO;
  165. }
  166. -(BOOL) _isDeallocating {
  167. atomic_fetch_add_explicit(&TestRootIsDeallocating, 1, memory_order_relaxed);
  168. return _objc_rootIsDeallocating(self);
  169. }
  170. -(BOOL) allowsWeakReference {
  171. return ! [self _isDeallocating];
  172. }
  173. -(BOOL) retainWeakReference {
  174. return [self _tryRetain];
  175. }
  176. @end