123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- // testroot.i
- // Implementation of class TestRoot
- // Include this file into your main test file to use it.
- #include "test.h"
- #include <dlfcn.h>
- #include <objc/objc-internal.h>
- atomic_int TestRootLoad;
- atomic_int TestRootInitialize;
- atomic_int TestRootAlloc;
- atomic_int TestRootAllocWithZone;
- atomic_int TestRootCopy;
- atomic_int TestRootCopyWithZone;
- atomic_int TestRootMutableCopy;
- atomic_int TestRootMutableCopyWithZone;
- atomic_int TestRootInit;
- atomic_int TestRootDealloc;
- atomic_int TestRootRetain;
- atomic_int TestRootRelease;
- atomic_int TestRootAutorelease;
- atomic_int TestRootRetainCount;
- atomic_int TestRootTryRetain;
- atomic_int TestRootIsDeallocating;
- atomic_int TestRootPlusRetain;
- atomic_int TestRootPlusRelease;
- atomic_int TestRootPlusAutorelease;
- atomic_int TestRootPlusRetainCount;
- @implementation TestRoot
- // These all use void* pending rdar://9310005.
- static void *
- retain_fn(void *self, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootRetain, 1, memory_order_relaxed);
- void * (*fn)(void *) = (typeof(fn))_objc_rootRetain;
- return fn(self);
- }
- static void
- release_fn(void *self, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootRelease, 1, memory_order_relaxed);
- void (*fn)(void *) = (typeof(fn))_objc_rootRelease;
- fn(self);
- }
- static void *
- autorelease_fn(void *self, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootAutorelease, 1, memory_order_relaxed);
- void * (*fn)(void *) = (typeof(fn))_objc_rootAutorelease;
- return fn(self);
- }
- static unsigned long
- retaincount_fn(void *self, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootRetainCount, 1, memory_order_relaxed);
- unsigned long (*fn)(void *) = (typeof(fn))_objc_rootRetainCount;
- return fn(self);
- }
- static void *
- copywithzone_fn(void *self, SEL _cmd __unused, void *zone) {
- atomic_fetch_add_explicit(&TestRootCopyWithZone, 1, memory_order_relaxed);
- void * (*fn)(void *, void *) =
- (typeof(fn))dlsym(RTLD_DEFAULT, "object_copy");
- return fn(self, zone);
- }
- static void *
- plusretain_fn(void *self __unused, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootPlusRetain, 1, memory_order_relaxed);
- return self;
- }
- static void
- plusrelease_fn(void *self __unused, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootPlusRelease, 1, memory_order_relaxed);
- }
- static void *
- plusautorelease_fn(void *self, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootPlusAutorelease, 1, memory_order_relaxed);
- return self;
- }
- static unsigned long
- plusretaincount_fn(void *self __unused, SEL _cmd __unused) {
- atomic_fetch_add_explicit(&TestRootPlusRetainCount, 1, memory_order_relaxed);
- return ULONG_MAX;
- }
- +(void) load {
- atomic_fetch_add_explicit(&TestRootLoad, 1, memory_order_relaxed);
-
- // install methods that ARC refuses to compile
- class_addMethod(self, sel_registerName("retain"), (IMP)retain_fn, "");
- class_addMethod(self, sel_registerName("release"), (IMP)release_fn, "");
- class_addMethod(self, sel_registerName("autorelease"), (IMP)autorelease_fn, "");
- class_addMethod(self, sel_registerName("retainCount"), (IMP)retaincount_fn, "");
- class_addMethod(self, sel_registerName("copyWithZone:"), (IMP)copywithzone_fn, "");
- class_addMethod(object_getClass(self), sel_registerName("retain"), (IMP)plusretain_fn, "");
- class_addMethod(object_getClass(self), sel_registerName("release"), (IMP)plusrelease_fn, "");
- class_addMethod(object_getClass(self), sel_registerName("autorelease"), (IMP)plusautorelease_fn, "");
- class_addMethod(object_getClass(self), sel_registerName("retainCount"), (IMP)plusretaincount_fn, "");
- }
- +(void) initialize {
- atomic_fetch_add_explicit(&TestRootInitialize, 1, memory_order_relaxed);
- }
- -(id) self {
- return self;
- }
- +(Class) class {
- return self;
- }
- -(Class) class {
- return object_getClass(self);
- }
- +(Class) superclass {
- return class_getSuperclass(self);
- }
- -(Class) superclass {
- return class_getSuperclass([self class]);
- }
- +(id) new {
- return [[self alloc] init];
- }
- +(id) alloc {
- atomic_fetch_add_explicit(&TestRootAlloc, 1, memory_order_relaxed);
- void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc;
- return (__bridge_transfer id)(fn(self));
- }
- +(id) allocWithZone:(void *)zone {
- atomic_fetch_add_explicit(&TestRootAllocWithZone, 1, memory_order_relaxed);
- void * (*fn)(id __unsafe_unretained, void *) = (typeof(fn))_objc_rootAllocWithZone;
- return (__bridge_transfer id)(fn(self, zone));
- }
- +(id) copy {
- return self;
- }
- +(id) copyWithZone:(void *) __unused zone {
- return self;
- }
- -(id) copy {
- atomic_fetch_add_explicit(&TestRootCopy, 1, memory_order_relaxed);
- return [self copyWithZone:NULL];
- }
- +(id) mutableCopyWithZone:(void *) __unused zone {
- fail("+mutableCopyWithZone: called");
- }
- -(id) mutableCopy {
- atomic_fetch_add_explicit(&TestRootMutableCopy, 1, memory_order_relaxed);
- return [self mutableCopyWithZone:NULL];
- }
- -(id) mutableCopyWithZone:(void *) __unused zone {
- atomic_fetch_add_explicit(&TestRootMutableCopyWithZone, 1, memory_order_relaxed);
- void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc;
- return (__bridge_transfer id)(fn(object_getClass(self)));
- }
- -(id) init {
- atomic_fetch_add_explicit(&TestRootInit, 1, memory_order_relaxed);
- return _objc_rootInit(self);
- }
- +(void) dealloc {
- fail("+dealloc called");
- }
- -(void) dealloc {
- atomic_fetch_add_explicit(&TestRootDealloc, 1, memory_order_relaxed);
- _objc_rootDealloc(self);
- }
- +(BOOL) _tryRetain {
- return YES;
- }
- -(BOOL) _tryRetain {
- atomic_fetch_add_explicit(&TestRootTryRetain, 1, memory_order_relaxed);
- return _objc_rootTryRetain(self);
- }
- +(BOOL) _isDeallocating {
- return NO;
- }
- -(BOOL) _isDeallocating {
- atomic_fetch_add_explicit(&TestRootIsDeallocating, 1, memory_order_relaxed);
- return _objc_rootIsDeallocating(self);
- }
- -(BOOL) allowsWeakReference {
- return ! [self _isDeallocating];
- }
- -(BOOL) retainWeakReference {
- return [self _tryRetain];
- }
- @end
|