]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-internal.h
73d553a4f603c677f12f3e264bb6547e7532b7f1
[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 <Availability.h>
42 #include <malloc/malloc.h>
43 #include <dispatch/dispatch.h>
44
45 __BEGIN_DECLS
46
47 // In-place construction of an Objective-C class.
48 OBJC_EXPORT Class objc_initializeClassPair(Class superclass_gen, const char *name, Class cls_gen, Class meta_gen)
49 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
50
51 #if __OBJC2__ && __LP64__
52 // Register a tagged pointer class.
53 OBJC_EXPORT void _objc_insert_tagged_isa(unsigned char slotNumber, Class isa)
54 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
55 #endif
56
57 // Batch object allocation using malloc_zone_batch_malloc().
58 OBJC_EXPORT unsigned class_createInstances(Class cls, size_t extraBytes,
59 id *results, unsigned num_requested)
60 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
61 OBJC_ARC_UNAVAILABLE;
62
63 // Get the isa pointer written into objects just before being freed.
64 OBJC_EXPORT Class _objc_getFreedObjectClass(void)
65 __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
66
67 // Substitute receiver for messages to nil.
68 // Not supported for all messages to nil.
69 OBJC_EXPORT id _objc_setNilReceiver(id newNilReceiver)
70 __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA);
71 OBJC_EXPORT id _objc_getNilReceiver(void)
72 __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA);
73
74 // Return NO if no instance of `cls` has ever owned an associative reference.
75 OBJC_EXPORT BOOL class_instancesHaveAssociatedObjects(Class cls)
76 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
77
78 // Return YES if GC is on and `object` is a GC allocation.
79 OBJC_EXPORT BOOL objc_isAuto(id object)
80 __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA);
81
82 // env NSObjCMessageLoggingEnabled
83 OBJC_EXPORT void instrumentObjcMessageSends(BOOL flag)
84 __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
85
86 // Initializer called by libSystem
87 #if __OBJC2__
88 OBJC_EXPORT void _objc_init(void)
89 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
90 #endif
91
92 // GC startup callback from Foundation
93 OBJC_EXPORT malloc_zone_t *objc_collect_init(int (*callback)(void))
94 __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA);
95
96 // Plainly-implemented GC barriers. Rosetta used to use these.
97 OBJC_EXPORT id objc_assign_strongCast_generic(id value, id *dest)
98 UNAVAILABLE_ATTRIBUTE;
99 OBJC_EXPORT id objc_assign_global_generic(id value, id *dest)
100 UNAVAILABLE_ATTRIBUTE;
101 OBJC_EXPORT id objc_assign_threadlocal_generic(id value, id *dest)
102 UNAVAILABLE_ATTRIBUTE;
103 OBJC_EXPORT id objc_assign_ivar_generic(id value, id dest, ptrdiff_t offset)
104 UNAVAILABLE_ATTRIBUTE;
105
106 // Install missing-class callback. Used by the late unlamented ZeroLink.
107 OBJC_EXPORT void _objc_setClassLoader(BOOL (*newClassLoader)(const char *)) OBJC2_UNAVAILABLE;
108
109 // Install handler for allocation failures.
110 // Handler may abort, or throw, or provide an object to return.
111 OBJC_EXPORT void _objc_setBadAllocHandler(id (*newHandler)(Class isa))
112 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
113
114 // This can go away when AppKit stops calling it (rdar://7811851)
115 #if __OBJC2__
116 OBJC_EXPORT void objc_setMultithreaded (BOOL flag)
117 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA);
118 #endif
119
120 // Used by ExceptionHandling.framework
121 #if !__OBJC2__
122 OBJC_EXPORT void _objc_error(id rcv, const char *fmt, va_list args)
123 __attribute__((noreturn))
124 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA);
125
126 #endif
127
128 // External Reference support. Used to support compaction.
129
130 enum {
131 OBJC_XREF_STRONG = 1,
132 OBJC_XREF_WEAK = 2
133 };
134 typedef uintptr_t objc_xref_type_t;
135 typedef uintptr_t objc_xref_t;
136
137 OBJC_EXPORT objc_xref_t _object_addExternalReference(id object, objc_xref_type_t type)
138 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
139 OBJC_EXPORT void _object_removeExternalReference(objc_xref_t xref)
140 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
141 OBJC_EXPORT id _object_readExternalReference(objc_xref_t xref)
142 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
143
144 OBJC_EXPORT uintptr_t _object_getExternalHash(id object)
145 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
146
147 // Instance-specific instance variable layout.
148
149 OBJC_EXPORT void _class_setIvarLayoutAccessor(Class cls_gen, const uint8_t* (*accessor) (id object))
150 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
151 OBJC_EXPORT const uint8_t *_object_getIvarLayout(Class cls_gen, id object)
152 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
153
154 OBJC_EXPORT BOOL _class_usesAutomaticRetainRelease(Class cls)
155 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
156
157 // Obsolete ARC conversions.
158
159 // hack - remove and reinstate objc.h's definitions
160 #undef objc_retainedObject
161 #undef objc_unretainedObject
162 #undef objc_unretainedPointer
163 OBJC_EXPORT id objc_retainedObject(objc_objectptr_t pointer)
164 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
165 OBJC_EXPORT id objc_unretainedObject(objc_objectptr_t pointer)
166 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
167 OBJC_EXPORT objc_objectptr_t objc_unretainedPointer(id object)
168 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
169 #if __has_feature(objc_arc)
170 # define objc_retainedObject(o) ((__bridge_transfer id)(objc_objectptr_t)(o))
171 # define objc_unretainedObject(o) ((__bridge id)(objc_objectptr_t)(o))
172 # define objc_unretainedPointer(o) ((__bridge objc_objectptr_t)(id)(o))
173 #else
174 # define objc_retainedObject(o) ((id)(objc_objectptr_t)(o))
175 # define objc_unretainedObject(o) ((id)(objc_objectptr_t)(o))
176 # define objc_unretainedPointer(o) ((objc_objectptr_t)(id)(o))
177 #endif
178
179 // API to only be called by root classes like NSObject or NSProxy
180
181 OBJC_EXPORT
182 id
183 _objc_rootRetain(id obj)
184 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
185
186 OBJC_EXPORT
187 void
188 _objc_rootRelease(id obj)
189 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
190
191 OBJC_EXPORT
192 bool
193 _objc_rootReleaseWasZero(id obj)
194 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
195
196 OBJC_EXPORT
197 bool
198 _objc_rootTryRetain(id obj)
199 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
200
201 OBJC_EXPORT
202 bool
203 _objc_rootIsDeallocating(id obj)
204 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
205
206 OBJC_EXPORT
207 id
208 _objc_rootAutorelease(id obj)
209 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
210
211 OBJC_EXPORT
212 uintptr_t
213 _objc_rootRetainCount(id obj)
214 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
215
216 OBJC_EXPORT
217 id
218 _objc_rootInit(id obj)
219 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
220
221 OBJC_EXPORT
222 id
223 _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone)
224 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
225
226 OBJC_EXPORT
227 id
228 _objc_rootAlloc(Class cls)
229 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
230
231 OBJC_EXPORT
232 void
233 _objc_rootDealloc(id obj)
234 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
235
236 OBJC_EXPORT
237 void
238 _objc_rootFinalize(id obj)
239 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
240
241 OBJC_EXPORT
242 malloc_zone_t *
243 _objc_rootZone(id obj)
244 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
245
246 OBJC_EXPORT
247 uintptr_t
248 _objc_rootHash(id obj)
249 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
250
251 OBJC_EXPORT
252 void *
253 objc_autoreleasePoolPush(void)
254 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
255
256 OBJC_EXPORT
257 void
258 objc_autoreleasePoolPop(void *context)
259 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
260
261
262 OBJC_EXPORT id objc_retain(id obj)
263 __asm__("_objc_retain")
264 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
265
266 OBJC_EXPORT void objc_release(id obj)
267 __asm__("_objc_release")
268 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
269
270 OBJC_EXPORT id objc_autorelease(id obj)
271 __asm__("_objc_autorelease")
272 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
273
274 // wraps objc_autorelease(obj) in a useful way when used with return values
275 OBJC_EXPORT
276 id
277 objc_autoreleaseReturnValue(id obj)
278 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
279
280 // wraps objc_autorelease(objc_retain(obj)) in a useful way when used with return values
281 OBJC_EXPORT
282 id
283 objc_retainAutoreleaseReturnValue(id obj)
284 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
285
286 // called ONLY by ARR by callers to undo the autorelease (if possible), otherwise objc_retain
287 OBJC_EXPORT
288 id
289 objc_retainAutoreleasedReturnValue(id obj)
290 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
291
292 OBJC_EXPORT
293 void
294 objc_storeStrong(id *location, id obj)
295 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
296
297 OBJC_EXPORT
298 id
299 objc_retainAutorelease(id obj)
300 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
301
302 // obsolete.
303 OBJC_EXPORT id objc_retain_autorelease(id obj)
304 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
305
306 OBJC_EXPORT
307 id
308 objc_loadWeakRetained(id *location)
309 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
310
311 OBJC_EXPORT
312 id
313 objc_initWeak(id *addr, id val)
314 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
315
316 OBJC_EXPORT
317 void
318 objc_destroyWeak(id *addr)
319 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
320
321 OBJC_EXPORT
322 void
323 objc_copyWeak(id *to, id *from)
324 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
325
326 OBJC_EXPORT
327 void
328 objc_moveWeak(id *to, id *from)
329 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
330
331
332 OBJC_EXPORT
333 void
334 _objc_autoreleasePoolPrint(void)
335 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
336
337 OBJC_EXPORT BOOL objc_should_deallocate(id object)
338 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
339
340 OBJC_EXPORT void objc_clear_deallocating(id object)
341 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
342
343
344 // to make CF link for now
345
346 OBJC_EXPORT
347 void *
348 _objc_autoreleasePoolPush(void)
349 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
350
351 OBJC_EXPORT
352 void
353 _objc_autoreleasePoolPop(void *context)
354 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
355
356
357 // Extra @encode data for XPC, or NULL
358 OBJC_EXPORT const char *_protocol_getMethodTypeEncoding(Protocol *p, SEL sel, BOOL isRequiredMethod, BOOL isInstanceMethod)
359 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
360
361
362 // API to only be called by classes that provide their own reference count storage
363
364 OBJC_EXPORT
365 void
366 _objc_deallocOnMainThreadHelper(void *context)
367 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
368
369 // On async versus sync deallocation and the _dealloc2main flag
370 //
371 // Theory:
372 //
373 // If order matters, then code must always: [self dealloc].
374 // If order doesn't matter, then always async should be safe.
375 //
376 // Practice:
377 //
378 // The _dealloc2main bit is set for GUI objects that may be retained by other
379 // threads. Once deallocation begins on the main thread, doing more async
380 // deallocation will at best cause extra UI latency and at worst cause
381 // use-after-free bugs in unretained delegate style patterns. Yes, this is
382 // extremely fragile. Yes, in the long run, developers should switch to weak
383 // references.
384 //
385 // Note is NOT safe to do any equality check against the result of
386 // dispatch_get_current_queue(). The main thread can and does drain more than
387 // one dispatch queue. That is why we call pthread_main_np().
388 //
389
390 typedef enum {
391 _OBJC_RESURRECT_OBJECT = -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
392 _OBJC_DEALLOC_OBJECT_NOW = 1, /* call [self dealloc] immediately. */
393 _OBJC_DEALLOC_OBJECT_LATER = 2 /* call [self dealloc] on the main queue. */
394 } _objc_object_disposition_t;
395
396 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
397 -(id)retain { \
398 /* this will fail to compile if _rc_ivar is an unsigned type */ \
399 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
400 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
401 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
402 __builtin_trap(); /* BUG: retain of over-released ref */ \
403 } \
404 return self; \
405 } \
406 -(oneway void)release { \
407 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
408 if (_prev > 0) { \
409 return; \
410 } else if (_prev < 0) { \
411 __builtin_trap(); /* BUG: over-release */ \
412 } \
413 _objc_object_disposition_t fate = _logicBlock(self); \
414 if (fate == _OBJC_RESURRECT_OBJECT) { \
415 return; \
416 } \
417 /* mark the object as deallocating. */ \
418 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
419 __builtin_trap(); /* BUG: dangling ref did a retain */ \
420 } \
421 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
422 [self dealloc]; \
423 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
424 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
425 _objc_deallocOnMainThreadHelper); \
426 } else { \
427 __builtin_trap(); /* BUG: bogus fate value */ \
428 } \
429 } \
430 -(NSUInteger)retainCount { \
431 return (_rc_ivar + 2) >> 1; \
432 } \
433 -(BOOL)_tryRetain { \
434 __typeof__(_rc_ivar) _prev; \
435 do { \
436 _prev = _rc_ivar; \
437 if (_prev & 1) { \
438 return 0; \
439 } else if (_prev == -2) { \
440 return 0; \
441 } else if (_prev < -2) { \
442 __builtin_trap(); /* BUG: over-release elsewhere */ \
443 } \
444 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
445 return 1; \
446 } \
447 -(BOOL)_isDeallocating { \
448 if (_rc_ivar == -2) { \
449 return 1; \
450 } else if (_rc_ivar < -2) { \
451 __builtin_trap(); /* BUG: over-release elsewhere */ \
452 } \
453 return _rc_ivar & 1; \
454 }
455
456 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
457 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
458 if (_dealloc2main && !pthread_main_np()) { \
459 return _OBJC_DEALLOC_OBJECT_LATER; \
460 } else { \
461 return _OBJC_DEALLOC_OBJECT_NOW; \
462 } \
463 }))
464
465 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
466 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)
467
468 __END_DECLS
469
470 #endif