]> git.saurik.com Git - apple/libdispatch.git/blobdiff - src/object.m
libdispatch-500.1.5.tar.gz
[apple/libdispatch.git] / src / object.m
index e64a4fda769530261e1f7c39720f06c0e819c4ca..1a98d7e0e6232dd7b635a3beaaa9e51068e606d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2014 Apple Inc. All rights reserved.
  *
  * @APPLE_APACHE_LICENSE_HEADER_START@
  *
@@ -48,6 +48,7 @@ _os_object_gc_init(void)
        _os_object_have_gc = objc_collectingEnabled();
        if (slowpath(_os_object_have_gc)) {
                _os_object_gc_zone = objc_collectableZone();
+               (void)[OS_OBJECT_CLASS(object) class]; // OS_object class realization
        }
 }
 
@@ -69,22 +70,55 @@ _os_object_make_collectable(_os_object_t obj)
        return obj;
 }
 
-#define _os_objc_gc_retain(obj) \
-       if (slowpath(_os_object_have_gc)) { \
-               return auto_zone_retain(_os_object_gc_zone, obj); \
+DISPATCH_NOINLINE
+static id
+_os_objc_gc_retain(id obj)
+{
+       if (fastpath(obj)) {
+               auto_zone_retain(_os_object_gc_zone, obj);
+       }
+       return obj;
+}
+
+DISPATCH_NOINLINE
+static void
+_os_objc_gc_release(id obj)
+{
+       if (fastpath(obj)) {
+               (void)auto_zone_release(_os_object_gc_zone, obj);
        }
+       asm(""); // prevent tailcall
+}
 
-#define _os_objc_gc_release(obj) \
-       if (slowpath(_os_object_have_gc)) { \
-               return (void)auto_zone_release(_os_object_gc_zone, obj); \
+DISPATCH_NOINLINE
+static id
+_os_object_gc_retain(id obj)
+{
+       if ([obj isKindOfClass:OS_OBJECT_OBJC_CLASS(object)]) {
+               return _os_object_retain(obj);
+       } else {
+               return _os_objc_gc_retain(obj);
        }
+}
+
+DISPATCH_NOINLINE
+static void
+_os_object_gc_release(id obj)
+{
+       if ([obj isKindOfClass:OS_OBJECT_OBJC_CLASS(object)]) {
+               return _os_object_release(obj);
+       } else {
+               return _os_objc_gc_release(obj);
+       }
+}
 
 #else // __OBJC_GC__
 #define _os_object_gc_init()
 #define _os_object_make_uncollectable(obj) (obj)
 #define _os_object_make_collectable(obj) (obj)
-#define _os_objc_gc_retain(obj)
-#define _os_objc_gc_release(obj)
+#define _os_object_have_gc 0
+#define _os_object_gc_retain(obj) (obj)
+#define _os_object_gc_release(obj)
 #endif // __OBJC_GC__
 
 #pragma mark -
@@ -101,11 +135,34 @@ _os_objc_alloc(Class cls, size_t size)
        return obj;
 }
 
+static void*
+_os_objc_destructInstance(id obj)
+{
+       // noop if only Libystem is loaded
+       return obj;
+}
+
+#if DISPATCH_COCOA_COMPAT
+static bool _os_object_debug_missing_pools;
+#endif
+
 void
 _os_object_init(void)
 {
        _objc_init();
        _os_object_gc_init();
+       if (slowpath(_os_object_have_gc)) return;
+       Block_callbacks_RR callbacks = {
+               sizeof(Block_callbacks_RR),
+               (void (*)(const void *))&objc_retain,
+               (void (*)(const void *))&objc_release,
+               (void (*)(const void *))&_os_objc_destructInstance
+       };
+       _Block_use_RR2(&callbacks);
+#if DISPATCH_COCOA_COMPAT
+       const char *v = getenv("OBJC_DEBUG_MISSING_POOLS");
+       _os_object_debug_missing_pools = v && !strcmp(v, "YES");
+#endif
 }
 
 _os_object_t
@@ -132,15 +189,35 @@ _os_object_dealloc(_os_object_t obj)
 void
 _os_object_xref_dispose(_os_object_t obj)
 {
+       struct _os_object_s *o = (struct _os_object_s *)obj;
+       _os_object_xrefcnt_dispose_barrier(o);
        [obj _xref_dispose];
 }
 
 void
 _os_object_dispose(_os_object_t obj)
 {
+       struct _os_object_s *o = (struct _os_object_s *)obj;
+       _os_object_refcnt_dispose_barrier(o);
        [obj _dispose];
 }
 
+#undef os_retain
+void*
+os_retain(void *obj)
+{
+       if (slowpath(_os_object_have_gc)) return _os_object_gc_retain(obj);
+       return objc_retain(obj);
+}
+
+#undef os_release
+void
+os_release(void *obj)
+{
+       if (slowpath(_os_object_have_gc)) return _os_object_gc_release(obj);
+       return objc_release(obj);
+}
+
 #pragma mark -
 #pragma mark _os_object
 
@@ -190,15 +267,13 @@ _dispatch_objc_alloc(Class cls, size_t size)
 void
 _dispatch_objc_retain(dispatch_object_t dou)
 {
-       _os_objc_gc_retain(dou);
-       return (void)[dou retain];
+       return (void)os_retain(dou);
 }
 
 void
 _dispatch_objc_release(dispatch_object_t dou)
 {
-       _os_objc_gc_release(dou);
-       return [dou release];
+       return os_release(dou);
 }
 
 void
@@ -341,6 +416,58 @@ DISPATCH_CLASS_IMPL(io)
 DISPATCH_CLASS_IMPL(operation)
 DISPATCH_CLASS_IMPL(disk)
 
+@implementation OS_OBJECT_CLASS(voucher)
+DISPATCH_OBJC_LOAD()
+
+- (id)init {
+       self = [super init];
+       [self release];
+       self = nil;
+       return self;
+}
+
+- (void)_xref_dispose {
+       return _voucher_xref_dispose(self); // calls _os_object_release_internal()
+}
+
+- (void)_dispose {
+       return _voucher_dispose(self); // calls _os_object_dealloc()
+}
+
+- (NSString *)debugDescription {
+       Class nsstring = objc_lookUpClass("NSString");
+       if (!nsstring) return nil;
+       char buf[2048];
+       _voucher_debug(self, buf, sizeof(buf));
+       return [nsstring stringWithFormat:
+                       [nsstring stringWithUTF8String:"<%s: %s>"],
+                       class_getName([self class]), buf];
+}
+
+@end
+
+#if VOUCHER_ENABLE_RECIPE_OBJECTS
+@implementation OS_OBJECT_CLASS(voucher_recipe)
+DISPATCH_OBJC_LOAD()
+
+- (id)init {
+       self = [super init];
+       [self release];
+       self = nil;
+       return self;
+}
+
+- (void)_dispose {
+
+}
+
+- (NSString *)debugDescription {
+       return nil; // TODO: voucher_recipe debugDescription
+}
+
+@end
+#endif
+
 #pragma mark -
 #pragma mark dispatch_autorelease_pool
 
@@ -348,12 +475,17 @@ DISPATCH_CLASS_IMPL(disk)
 
 void *
 _dispatch_autorelease_pool_push(void) {
-       return objc_autoreleasePoolPush();
+       if (!slowpath(_os_object_debug_missing_pools)) {
+               return objc_autoreleasePoolPush();
+       }
+       return NULL;
 }
 
 void
 _dispatch_autorelease_pool_pop(void *context) {
-       return objc_autoreleasePoolPop(context);
+       if (!slowpath(_os_object_debug_missing_pools)) {
+               return objc_autoreleasePoolPop(context);
+       }
 }
 
 #endif // DISPATCH_COCOA_COMPAT
@@ -362,7 +494,7 @@ _dispatch_autorelease_pool_pop(void *context) {
 #pragma mark dispatch_client_callout
 
 // Abort on uncaught exceptions thrown from client callouts rdar://8577499
-#if DISPATCH_USE_CLIENT_CALLOUT && !__arm__
+#if DISPATCH_USE_CLIENT_CALLOUT && !__USING_SJLJ_EXCEPTIONS__
 // On platforms with zero-cost exceptions, use a compiler-generated catch-all
 // exception handler.
 
@@ -392,19 +524,6 @@ _dispatch_client_callout2(void *ctxt, size_t i, void (*f)(void *, size_t))
        }
 }
 
-#undef _dispatch_client_callout3
-bool
-_dispatch_client_callout3(void *ctxt, dispatch_data_t region, size_t offset,
-               const void *buffer, size_t size, dispatch_data_applier_function_t f)
-{
-       @try {
-               return f(ctxt, region, offset, buffer, size);
-       }
-       @catch (...) {
-               objc_terminate();
-       }
-}
-
 #undef _dispatch_client_callout4
 void
 _dispatch_client_callout4(void *ctxt, dispatch_mach_reason_t reason,