/*
- * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2014 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
_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
}
}
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 -
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
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
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
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
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
#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.
}
}
-#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,