]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-internal.h
f77cb183db56f708975125ad8630517acd7ac010
[apple/objc4.git] / runtime / objc-internal.h
1 /*
2 * Copyright (c) 2009 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #ifndef _OBJC_INTERNAL_H
26 #define _OBJC_INTERNAL_H
27
28 /*
29 * WARNING DANGER HAZARD BEWARE EEK
30 *
31 * Everything in this file is for Apple Internal use only.
32 * These will change in arbitrary OS updates and in unpredictable ways.
33 * When your program breaks, you get to keep both pieces.
34 */
35
36 /*
37 * objc-internal.h: Private SPI for use by other system frameworks.
38 */
39
40 #include <objc/objc.h>
41 #include <objc/runtime.h>
42 #include <Availability.h>
43 #include <malloc/malloc.h>
44 #include <dispatch/dispatch.h>
45
46 __BEGIN_DECLS
47
48 // This is the allocation size required for each of the class and the metaclass
49 // with objc_initializeClassPair() and objc_readClassPair().
50 // The runtime's class structure will never grow beyond this.
51 #define OBJC_MAX_CLASS_SIZE (32*sizeof(void*))
52
53 // In-place construction of an Objective-C class.
54 // cls and metacls must each be OBJC_MAX_CLASS_SIZE bytes.
55 // Returns nil if a class with the same name already exists.
56 // Returns nil if the superclass is under construction.
57 // Call objc_registerClassPair() when you are done.
58 OBJC_EXPORT Class objc_initializeClassPair(Class superclass, const char *name, Class cls, Class metacls)
59 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
60
61 // Class and metaclass construction from a compiler-generated memory image.
62 // cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
63 // Extra bytes not used the the metadata must be zero.
64 // info is the same objc_image_info that would be emitted by a static compiler.
65 // Returns nil if a class with the same name already exists.
66 // Returns nil if the superclass is nil and the class is not marked as a root.
67 // Returns nil if the superclass is under construction.
68 // Do not call objc_registerClassPair().
69 #if __OBJC2__
70 struct objc_image_info;
71 OBJC_EXPORT Class objc_readClassPair(Class cls,
72 const struct objc_image_info *info)
73 __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0);
74 #endif
75
76 // Batch object allocation using malloc_zone_batch_malloc().
77 OBJC_EXPORT unsigned class_createInstances(Class cls, size_t extraBytes,
78 id *results, unsigned num_requested)
79 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
80 OBJC_ARC_UNAVAILABLE;
81
82 // Get the isa pointer written into objects just before being freed.
83 OBJC_EXPORT Class _objc_getFreedObjectClass(void)
84 __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
85
86 // Return YES if GC is on and `object` is a GC allocation.
87 OBJC_EXPORT BOOL objc_isAuto(id object)
88 __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA);
89
90 // env NSObjCMessageLoggingEnabled
91 OBJC_EXPORT void instrumentObjcMessageSends(BOOL flag)
92 __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
93
94 // Initializer called by libSystem
95 #if __OBJC2__
96 OBJC_EXPORT void _objc_init(void)
97 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
98 #endif
99
100 #ifndef OBJC_NO_GC
101 // GC startup callback from Foundation
102 OBJC_EXPORT malloc_zone_t *objc_collect_init(int (*callback)(void))
103 __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA);
104 #endif
105
106 // Plainly-implemented GC barriers. Rosetta used to use these.
107 OBJC_EXPORT id objc_assign_strongCast_generic(id value, id *dest)
108 UNAVAILABLE_ATTRIBUTE;
109 OBJC_EXPORT id objc_assign_global_generic(id value, id *dest)
110 UNAVAILABLE_ATTRIBUTE;
111 OBJC_EXPORT id objc_assign_threadlocal_generic(id value, id *dest)
112 UNAVAILABLE_ATTRIBUTE;
113 OBJC_EXPORT id objc_assign_ivar_generic(id value, id dest, ptrdiff_t offset)
114 UNAVAILABLE_ATTRIBUTE;
115
116 // Install missing-class callback. Used by the late unlamented ZeroLink.
117 OBJC_EXPORT void _objc_setClassLoader(BOOL (*newClassLoader)(const char *)) OBJC2_UNAVAILABLE;
118
119 // Install handler for allocation failures.
120 // Handler may abort, or throw, or provide an object to return.
121 OBJC_EXPORT void _objc_setBadAllocHandler(id (*newHandler)(Class isa))
122 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
123
124 // This can go away when AppKit stops calling it (rdar://7811851)
125 #if __OBJC2__
126 OBJC_EXPORT void objc_setMultithreaded (BOOL flag)
127 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA);
128 #endif
129
130 // Used by ExceptionHandling.framework
131 #if !__OBJC2__
132 OBJC_EXPORT void _objc_error(id rcv, const char *fmt, va_list args)
133 __attribute__((noreturn))
134 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA);
135
136 #endif
137
138
139 // Tagged pointer objects.
140
141 #if __LP64__
142 #define OBJC_HAVE_TAGGED_POINTERS 1
143 #endif
144
145 #if OBJC_HAVE_TAGGED_POINTERS
146
147 // Tagged pointer layout and usage is subject to change
148 // on different OS versions. The current layout is:
149 // (MSB)
150 // 60 bits payload
151 // 3 bits tag index
152 // 1 bit 1 for tagged pointer objects, 0 for ordinary objects
153 // (LSB)
154
155 #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
156 enum objc_tag_index_t : uint8_t
157 #else
158 typedef uint8_t objc_tag_index_t;
159 enum
160 #endif
161 {
162 OBJC_TAG_NSAtom = 0,
163 OBJC_TAG_1 = 1,
164 OBJC_TAG_NSString = 2,
165 OBJC_TAG_NSNumber = 3,
166 OBJC_TAG_NSIndexPath = 4,
167 OBJC_TAG_NSManagedObjectID = 5,
168 OBJC_TAG_NSDate = 6,
169 OBJC_TAG_7 = 7
170 };
171 #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
172 typedef enum objc_tag_index_t objc_tag_index_t;
173 #endif
174
175 OBJC_EXPORT void _objc_registerTaggedPointerClass(objc_tag_index_t tag, Class cls)
176 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
177
178 OBJC_EXPORT Class _objc_getClassForTag(objc_tag_index_t tag)
179 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
180
181 static inline bool
182 _objc_taggedPointersEnabled(void)
183 {
184 extern uintptr_t objc_debug_taggedpointer_mask;
185 return (objc_debug_taggedpointer_mask != 0);
186 }
187
188 #if TARGET_OS_IPHONE
189 // tagged pointer marker is MSB
190
191 static inline void *
192 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
193 {
194 // assert(_objc_taggedPointersEnabled());
195 // assert((unsigned int)tag < 8);
196 // assert(((value << 4) >> 4) == value);
197 return (void*)((1UL << 63) | ((uintptr_t)tag << 60) | (value & ~(0xFUL << 60)));
198 }
199
200 static inline bool
201 _objc_isTaggedPointer(const void *ptr)
202 {
203 return (intptr_t)ptr < 0; // a.k.a. ptr & 0x8000000000000000
204 }
205
206 static inline objc_tag_index_t
207 _objc_getTaggedPointerTag(const void *ptr)
208 {
209 // assert(_objc_isTaggedPointer(ptr));
210 return (objc_tag_index_t)(((uintptr_t)ptr >> 60) & 0x7);
211 }
212
213 static inline uintptr_t
214 _objc_getTaggedPointerValue(const void *ptr)
215 {
216 // assert(_objc_isTaggedPointer(ptr));
217 return (uintptr_t)ptr & 0x0fffffffffffffff;
218 }
219
220 static inline intptr_t
221 _objc_getTaggedPointerSignedValue(const void *ptr)
222 {
223 // assert(_objc_isTaggedPointer(ptr));
224 return ((intptr_t)ptr << 4) >> 4;
225 }
226
227 // TARGET_OS_IPHONE
228 #else
229 // not TARGET_OS_IPHONE
230 // tagged pointer marker is LSB
231
232 static inline void *
233 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
234 {
235 // assert(_objc_taggedPointersEnabled());
236 // assert((unsigned int)tag < 8);
237 // assert(((value << 4) >> 4) == value);
238 return (void *)((value << 4) | ((uintptr_t)tag << 1) | 1);
239 }
240
241 static inline bool
242 _objc_isTaggedPointer(const void *ptr)
243 {
244 return (uintptr_t)ptr & 1;
245 }
246
247 static inline objc_tag_index_t
248 _objc_getTaggedPointerTag(const void *ptr)
249 {
250 // assert(_objc_isTaggedPointer(ptr));
251 return (objc_tag_index_t)(((uintptr_t)ptr & 0xe) >> 1);
252 }
253
254 static inline uintptr_t
255 _objc_getTaggedPointerValue(const void *ptr)
256 {
257 // assert(_objc_isTaggedPointer(ptr));
258 return (uintptr_t)ptr >> 4;
259 }
260
261 static inline intptr_t
262 _objc_getTaggedPointerSignedValue(const void *ptr)
263 {
264 // assert(_objc_isTaggedPointer(ptr));
265 return (intptr_t)ptr >> 4;
266 }
267
268 // not TARGET_OS_IPHONE
269 #endif
270
271
272 OBJC_EXPORT void _objc_insert_tagged_isa(unsigned char slotNumber, Class isa)
273 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7,__MAC_10_9, __IPHONE_4_3,__IPHONE_7_0);
274
275 #endif
276
277
278 // External Reference support. Used to support compaction.
279
280 enum {
281 OBJC_XREF_STRONG = 1,
282 OBJC_XREF_WEAK = 2
283 };
284 typedef uintptr_t objc_xref_type_t;
285 typedef uintptr_t objc_xref_t;
286
287 OBJC_EXPORT objc_xref_t _object_addExternalReference(id object, objc_xref_type_t type)
288 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
289 OBJC_EXPORT void _object_removeExternalReference(objc_xref_t xref)
290 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
291 OBJC_EXPORT id _object_readExternalReference(objc_xref_t xref)
292 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
293
294 OBJC_EXPORT uintptr_t _object_getExternalHash(id object)
295 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
296
297 /**
298 * Returns the method implementation of an object.
299 *
300 * @param obj An Objective-C object.
301 * @param name An Objective-C selector.
302 *
303 * @return The IMP corresponding to the instance method implemented by
304 * the class of \e obj.
305 *
306 * @note Equivalent to:
307 *
308 * class_getMethodImplementation(object_getClass(obj), name);
309 */
310 OBJC_EXPORT IMP object_getMethodImplementation(id obj, SEL name)
311 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
312
313 OBJC_EXPORT IMP object_getMethodImplementation_stret(id obj, SEL name)
314 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0)
315 OBJC_ARM64_UNAVAILABLE;
316
317
318 // Instance-specific instance variable layout.
319
320 OBJC_EXPORT void _class_setIvarLayoutAccessor(Class cls_gen, const uint8_t* (*accessor) (id object))
321 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
322 OBJC_EXPORT const uint8_t *_object_getIvarLayout(Class cls_gen, id object)
323 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
324
325 OBJC_EXPORT BOOL _class_usesAutomaticRetainRelease(Class cls)
326 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
327
328 OBJC_EXPORT BOOL _class_isFutureClass(Class cls)
329 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
330
331
332 // Obsolete ARC conversions.
333
334 // hack - remove and reinstate objc.h's definitions
335 #undef objc_retainedObject
336 #undef objc_unretainedObject
337 #undef objc_unretainedPointer
338 OBJC_EXPORT id objc_retainedObject(objc_objectptr_t pointer)
339 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
340 OBJC_EXPORT id objc_unretainedObject(objc_objectptr_t pointer)
341 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
342 OBJC_EXPORT objc_objectptr_t objc_unretainedPointer(id object)
343 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
344 #if __has_feature(objc_arc)
345 # define objc_retainedObject(o) ((__bridge_transfer id)(objc_objectptr_t)(o))
346 # define objc_unretainedObject(o) ((__bridge id)(objc_objectptr_t)(o))
347 # define objc_unretainedPointer(o) ((__bridge objc_objectptr_t)(id)(o))
348 #else
349 # define objc_retainedObject(o) ((id)(objc_objectptr_t)(o))
350 # define objc_unretainedObject(o) ((id)(objc_objectptr_t)(o))
351 # define objc_unretainedPointer(o) ((objc_objectptr_t)(id)(o))
352 #endif
353
354 // API to only be called by root classes like NSObject or NSProxy
355
356 OBJC_EXPORT
357 id
358 _objc_rootRetain(id obj)
359 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
360
361 OBJC_EXPORT
362 void
363 _objc_rootRelease(id obj)
364 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
365
366 OBJC_EXPORT
367 bool
368 _objc_rootReleaseWasZero(id obj)
369 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
370
371 OBJC_EXPORT
372 bool
373 _objc_rootTryRetain(id obj)
374 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
375
376 OBJC_EXPORT
377 bool
378 _objc_rootIsDeallocating(id obj)
379 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
380
381 OBJC_EXPORT
382 id
383 _objc_rootAutorelease(id obj)
384 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
385
386 OBJC_EXPORT
387 uintptr_t
388 _objc_rootRetainCount(id obj)
389 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
390
391 OBJC_EXPORT
392 id
393 _objc_rootInit(id obj)
394 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
395
396 OBJC_EXPORT
397 id
398 _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone)
399 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
400
401 OBJC_EXPORT
402 id
403 _objc_rootAlloc(Class cls)
404 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
405
406 OBJC_EXPORT
407 void
408 _objc_rootDealloc(id obj)
409 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
410
411 OBJC_EXPORT
412 void
413 _objc_rootFinalize(id obj)
414 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
415
416 OBJC_EXPORT
417 malloc_zone_t *
418 _objc_rootZone(id obj)
419 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
420
421 OBJC_EXPORT
422 uintptr_t
423 _objc_rootHash(id obj)
424 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
425
426 OBJC_EXPORT
427 void *
428 objc_autoreleasePoolPush(void)
429 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
430
431 OBJC_EXPORT
432 void
433 objc_autoreleasePoolPop(void *context)
434 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
435
436
437 OBJC_EXPORT id objc_alloc(Class cls)
438 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
439
440 OBJC_EXPORT id objc_allocWithZone(Class cls)
441 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
442
443 OBJC_EXPORT id objc_retain(id obj)
444 __asm__("_objc_retain")
445 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
446
447 OBJC_EXPORT void objc_release(id obj)
448 __asm__("_objc_release")
449 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
450
451 OBJC_EXPORT id objc_autorelease(id obj)
452 __asm__("_objc_autorelease")
453 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
454
455 // Prepare a value at +1 for return through a +0 autoreleasing convention.
456 OBJC_EXPORT
457 id
458 objc_autoreleaseReturnValue(id obj)
459 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
460
461 // Prepare a value at +0 for return through a +0 autoreleasing convention.
462 OBJC_EXPORT
463 id
464 objc_retainAutoreleaseReturnValue(id obj)
465 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
466
467 // Accept a value returned through a +0 autoreleasing convention for use at +1.
468 OBJC_EXPORT
469 id
470 objc_retainAutoreleasedReturnValue(id obj)
471 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
472
473 // Accept a value returned through a +0 autoreleasing convention for use at +0.
474 OBJC_EXPORT
475 id
476 objc_unsafeClaimAutoreleasedReturnValue(id obj)
477 __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0);
478
479 OBJC_EXPORT
480 void
481 objc_storeStrong(id *location, id obj)
482 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
483
484 OBJC_EXPORT
485 id
486 objc_retainAutorelease(id obj)
487 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
488
489 // obsolete.
490 OBJC_EXPORT id objc_retain_autorelease(id obj)
491 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
492
493 OBJC_EXPORT
494 id
495 objc_loadWeakRetained(id *location)
496 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
497
498 OBJC_EXPORT
499 id
500 objc_initWeak(id *location, id val)
501 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
502
503 // Like objc_storeWeak, but stores nil if the new object is deallocating
504 // or the new object's class does not support weak references.
505 // Returns the value stored (either the new object or nil).
506 OBJC_EXPORT
507 id
508 objc_storeWeakOrNil(id *location, id obj)
509 __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0);
510
511 // Like objc_initWeak, but stores nil if the new object is deallocating
512 // or the new object's class does not support weak references.
513 // Returns the value stored (either the new object or nil).
514 OBJC_EXPORT
515 id
516 objc_initWeakOrNil(id *location, id val)
517 __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0);
518
519 OBJC_EXPORT
520 void
521 objc_destroyWeak(id *location)
522 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
523
524 OBJC_EXPORT
525 void
526 objc_copyWeak(id *to, id *from)
527 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
528
529 OBJC_EXPORT
530 void
531 objc_moveWeak(id *to, id *from)
532 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
533
534
535 OBJC_EXPORT
536 void
537 _objc_autoreleasePoolPrint(void)
538 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
539
540 OBJC_EXPORT BOOL objc_should_deallocate(id object)
541 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
542
543 OBJC_EXPORT void objc_clear_deallocating(id object)
544 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
545
546
547 // to make CF link for now
548
549 OBJC_EXPORT
550 void *
551 _objc_autoreleasePoolPush(void)
552 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
553
554 OBJC_EXPORT
555 void
556 _objc_autoreleasePoolPop(void *context)
557 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
558
559
560 // Extra @encode data for XPC, or NULL
561 OBJC_EXPORT const char *_protocol_getMethodTypeEncoding(Protocol *p, SEL sel, BOOL isRequiredMethod, BOOL isInstanceMethod)
562 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
563
564
565 // API to only be called by classes that provide their own reference count storage
566
567 OBJC_EXPORT
568 void
569 _objc_deallocOnMainThreadHelper(void *context)
570 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
571
572 // On async versus sync deallocation and the _dealloc2main flag
573 //
574 // Theory:
575 //
576 // If order matters, then code must always: [self dealloc].
577 // If order doesn't matter, then always async should be safe.
578 //
579 // Practice:
580 //
581 // The _dealloc2main bit is set for GUI objects that may be retained by other
582 // threads. Once deallocation begins on the main thread, doing more async
583 // deallocation will at best cause extra UI latency and at worst cause
584 // use-after-free bugs in unretained delegate style patterns. Yes, this is
585 // extremely fragile. Yes, in the long run, developers should switch to weak
586 // references.
587 //
588 // Note is NOT safe to do any equality check against the result of
589 // dispatch_get_current_queue(). The main thread can and does drain more than
590 // one dispatch queue. That is why we call pthread_main_np().
591 //
592
593 typedef enum {
594 _OBJC_RESURRECT_OBJECT = -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
595 _OBJC_DEALLOC_OBJECT_NOW = 1, /* call [self dealloc] immediately. */
596 _OBJC_DEALLOC_OBJECT_LATER = 2 /* call [self dealloc] on the main queue. */
597 } _objc_object_disposition_t;
598
599 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
600 -(id)retain { \
601 /* this will fail to compile if _rc_ivar is an unsigned type */ \
602 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
603 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
604 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
605 __builtin_trap(); /* BUG: retain of over-released ref */ \
606 } \
607 return self; \
608 } \
609 -(oneway void)release { \
610 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
611 if (_prev > 0) { \
612 return; \
613 } else if (_prev < 0) { \
614 __builtin_trap(); /* BUG: over-release */ \
615 } \
616 _objc_object_disposition_t fate = _logicBlock(self); \
617 if (fate == _OBJC_RESURRECT_OBJECT) { \
618 return; \
619 } \
620 /* mark the object as deallocating. */ \
621 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
622 __builtin_trap(); /* BUG: dangling ref did a retain */ \
623 } \
624 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
625 [self dealloc]; \
626 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
627 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
628 _objc_deallocOnMainThreadHelper); \
629 } else { \
630 __builtin_trap(); /* BUG: bogus fate value */ \
631 } \
632 } \
633 -(NSUInteger)retainCount { \
634 return (_rc_ivar + 2) >> 1; \
635 } \
636 -(BOOL)_tryRetain { \
637 __typeof__(_rc_ivar) _prev; \
638 do { \
639 _prev = _rc_ivar; \
640 if (_prev & 1) { \
641 return 0; \
642 } else if (_prev == -2) { \
643 return 0; \
644 } else if (_prev < -2) { \
645 __builtin_trap(); /* BUG: over-release elsewhere */ \
646 } \
647 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
648 return 1; \
649 } \
650 -(BOOL)_isDeallocating { \
651 if (_rc_ivar == -2) { \
652 return 1; \
653 } else if (_rc_ivar < -2) { \
654 __builtin_trap(); /* BUG: over-release elsewhere */ \
655 } \
656 return _rc_ivar & 1; \
657 }
658
659 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
660 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
661 if (_dealloc2main && !pthread_main_np()) { \
662 return _OBJC_DEALLOC_OBJECT_LATER; \
663 } else { \
664 return _OBJC_DEALLOC_OBJECT_NOW; \
665 } \
666 }))
667
668 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
669 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)
670
671 __END_DECLS
672
673 #endif