]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-private.h
objc4-647.tar.gz
[apple/objc4.git] / runtime / objc-private.h
1 /*
2 * Copyright (c) 1999-2007 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 * objc-private.h
25 * Copyright 1988-1996, NeXT Software, Inc.
26 */
27
28 #ifndef _OBJC_PRIVATE_H_
29 #define _OBJC_PRIVATE_H_
30
31 #include "objc-config.h"
32
33 /* Isolate ourselves from the definitions of id and Class in the compiler
34 * and public headers.
35 */
36
37 #ifdef _OBJC_OBJC_H_
38 #error include objc-private.h before other headers
39 #endif
40
41 #define OBJC_TYPES_DEFINED 1
42 #define OBJC_OLD_DISPATCH_PROTOTYPES 0
43
44 #include <cstddef> // for nullptr_t
45 #include <stdint.h>
46 #include <assert.h>
47
48 struct objc_class;
49 struct objc_object;
50
51 typedef struct objc_class *Class;
52 typedef struct objc_object *id;
53
54 namespace {
55 class SideTable;
56 };
57
58
59 union isa_t
60 {
61 isa_t() { }
62 isa_t(uintptr_t value) : bits(value) { }
63
64 Class cls;
65 uintptr_t bits;
66
67 #if SUPPORT_NONPOINTER_ISA
68
69 // extra_rc must be the MSB-most field (so it matches carry/overflow flags)
70 // indexed must be the LSB (fixme or get rid of it)
71 // shiftcls must occupy the same bits that a real class pointer would
72 // bits + RC_ONE is equivalent to extra_rc + 1
73 // RC_HALF is the high bit of extra_rc (i.e. half of its range)
74
75 // future expansion:
76 // uintptr_t fast_rr : 1; // no r/r overrides
77 // uintptr_t lock : 2; // lock for atomic property, @synch
78 // uintptr_t extraBytes : 1; // allocated with extra bytes
79
80 # if __arm64__
81 # define ISA_MASK 0x00000001fffffff8ULL
82 # define ISA_MAGIC_MASK 0x000003fe00000001ULL
83 # define ISA_MAGIC_VALUE 0x000001a400000001ULL
84 struct {
85 uintptr_t indexed : 1;
86 uintptr_t has_assoc : 1;
87 uintptr_t has_cxx_dtor : 1;
88 uintptr_t shiftcls : 30; // MACH_VM_MAX_ADDRESS 0x1a0000000
89 uintptr_t magic : 9;
90 uintptr_t weakly_referenced : 1;
91 uintptr_t deallocating : 1;
92 uintptr_t has_sidetable_rc : 1;
93 uintptr_t extra_rc : 19;
94 # define RC_ONE (1ULL<<45)
95 # define RC_HALF (1ULL<<18)
96 };
97
98 # elif __x86_64__
99 # define ISA_MASK 0x00007ffffffffff8ULL
100 # define ISA_MAGIC_MASK 0x0000000000000001ULL
101 # define ISA_MAGIC_VALUE 0x0000000000000001ULL
102 struct {
103 uintptr_t indexed : 1;
104 uintptr_t has_assoc : 1;
105 uintptr_t has_cxx_dtor : 1;
106 uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
107 uintptr_t weakly_referenced : 1;
108 uintptr_t deallocating : 1;
109 uintptr_t has_sidetable_rc : 1;
110 uintptr_t extra_rc : 14;
111 # define RC_ONE (1ULL<<50)
112 # define RC_HALF (1ULL<<13)
113 };
114
115 # else
116 // Available bits in isa field are architecture-specific.
117 # error unknown architecture
118 # endif
119
120 // SUPPORT_NONPOINTER_ISA
121 #endif
122
123 };
124
125
126 struct objc_object {
127 private:
128 isa_t isa;
129
130 public:
131
132 // ISA() assumes this is NOT a tagged pointer object
133 Class ISA();
134
135 // getIsa() allows this to be a tagged pointer object
136 Class getIsa();
137
138 // initIsa() should be used to init the isa of new objects only.
139 // If this object already has an isa, use changeIsa() for correctness.
140 // initInstanceIsa(): objects with no custom RR/AWZ
141 // initClassIsa(): class objects
142 // initProtocolIsa(): protocol objects
143 // initIsa(): other objects
144 void initIsa(Class cls /*indexed=false*/);
145 void initClassIsa(Class cls /*indexed=maybe*/);
146 void initProtocolIsa(Class cls /*indexed=maybe*/);
147 void initInstanceIsa(Class cls, bool hasCxxDtor);
148
149 // changeIsa() should be used to change the isa of existing objects.
150 // If this is a new object, use initIsa() for performance.
151 Class changeIsa(Class newCls);
152
153 bool hasIndexedIsa();
154 bool isTaggedPointer();
155 bool isClass();
156
157 // object may have associated objects?
158 bool hasAssociatedObjects();
159 void setHasAssociatedObjects();
160
161 // object may be weakly referenced?
162 bool isWeaklyReferenced();
163 void setWeaklyReferenced_nolock();
164
165 // object may have -.cxx_destruct implementation?
166 bool hasCxxDtor();
167
168 // Optimized calls to retain/release methods
169 id retain();
170 void release();
171 id autorelease();
172
173 // Implementations of retain/release methods
174 id rootRetain();
175 bool rootRelease();
176 id rootAutorelease();
177 bool rootTryRetain();
178 bool rootReleaseShouldDealloc();
179 uintptr_t rootRetainCount();
180
181 // Implementation of dealloc methods
182 bool rootIsDeallocating();
183 void clearDeallocating();
184 void rootDealloc();
185
186 private:
187 void initIsa(Class newCls, bool indexed, bool hasCxxDtor);
188
189 // Slow paths for inline control
190 id rootAutorelease2();
191 bool overrelease_error();
192
193 #if SUPPORT_NONPOINTER_ISA
194 // Unified retain count manipulation for nonpointer isa
195 id rootRetain(bool tryRetain, bool handleOverflow);
196 bool rootRelease(bool performDealloc, bool handleUnderflow);
197 id rootRetain_overflow(bool tryRetain);
198 bool rootRelease_underflow(bool performDealloc);
199
200 void clearDeallocating_weak();
201
202 // Side table retain count overflow for nonpointer isa
203 void sidetable_lock();
204 void sidetable_unlock();
205
206 void sidetable_moveExtraRC_nolock(size_t extra_rc, bool isDeallocating, bool weaklyReferenced);
207 bool sidetable_addExtraRC_nolock(size_t delta_rc);
208 bool sidetable_subExtraRC_nolock(size_t delta_rc);
209 size_t sidetable_getExtraRC_nolock();
210 #endif
211
212 // Side-table-only retain count
213 bool sidetable_isDeallocating();
214 void sidetable_clearDeallocating();
215
216 bool sidetable_isWeaklyReferenced();
217 void sidetable_setWeaklyReferenced_nolock();
218
219 id sidetable_retain();
220 id sidetable_retain_slow(SideTable *table);
221
222 bool sidetable_release(bool performDealloc = true);
223 bool sidetable_release_slow(SideTable *table, bool performDealloc = true);
224
225 bool sidetable_tryRetain();
226
227 uintptr_t sidetable_retainCount();
228 #if !NDEBUG
229 bool sidetable_present();
230 #endif
231 };
232
233
234 #if __OBJC2__
235 typedef struct method_t *Method;
236 typedef struct ivar_t *Ivar;
237 typedef struct category_t *Category;
238 typedef struct property_t *objc_property_t;
239 #else
240 typedef struct old_method *Method;
241 typedef struct old_ivar *Ivar;
242 typedef struct old_category *Category;
243 typedef struct old_property *objc_property_t;
244 #endif
245
246 // Public headers
247
248 #include "objc.h"
249 #include "runtime.h"
250 #include "objc-os.h"
251 #include "objc-abi.h"
252 #include "objc-api.h"
253 #include "objc-auto.h"
254 #include "objc-config.h"
255 #include "objc-internal.h"
256 #include "maptable.h"
257 #include "hashtable2.h"
258
259 /* Do not include message.h here. */
260 /* #include "message.h" */
261
262 #define __APPLE_API_PRIVATE
263 #include "objc-gdb.h"
264 #undef __APPLE_API_PRIVATE
265
266
267 // Private headers
268
269 #if __OBJC2__
270 #include "objc-runtime-new.h"
271 #else
272 #include "objc-runtime-old.h"
273 #endif
274
275 #include "objc-references.h"
276 #include "objc-initialize.h"
277 #include "objc-loadmethod.h"
278
279
280 __BEGIN_DECLS
281
282
283 #if (defined(OBJC_NO_GC) && SUPPORT_GC) || \
284 (!defined(OBJC_NO_GC) && !SUPPORT_GC)
285 # error OBJC_NO_GC and SUPPORT_GC inconsistent
286 #endif
287
288 #if SUPPORT_GC
289 # include <auto_zone.h>
290 // PRIVATE_EXTERN is needed to help the compiler know "how" extern these are
291 PRIVATE_EXTERN extern int8_t UseGC; // equivalent to calling objc_collecting_enabled()
292 PRIVATE_EXTERN extern auto_zone_t *gc_zone; // the GC zone, or NULL if no GC
293 extern void objc_addRegisteredClass(Class c);
294 extern void objc_removeRegisteredClass(Class c);
295 #else
296 # define UseGC NO
297 # define gc_zone NULL
298 # define objc_addRegisteredClass(c) do {} while(0)
299 # define objc_removeRegisteredClass(c) do {} while(0)
300 /* Uses of the following must be protected with UseGC. */
301 extern id gc_unsupported_dont_call();
302 # define auto_zone_allocate_object gc_unsupported_dont_call
303 # define auto_zone_retain gc_unsupported_dont_call
304 # define auto_zone_release gc_unsupported_dont_call
305 # define auto_zone_is_valid_pointer gc_unsupported_dont_call
306 # define auto_zone_write_barrier_memmove gc_unsupported_dont_call
307 # define AUTO_OBJECT_SCANNED 0
308 #endif
309
310
311 #define _objcHeaderIsReplacement(h) ((h)->info && ((h)->info->flags & OBJC_IMAGE_IS_REPLACEMENT))
312
313 /* OBJC_IMAGE_IS_REPLACEMENT:
314 Don't load any classes
315 Don't load any categories
316 Do fix up selector refs (@selector points to them)
317 Do fix up class refs (@class and objc_msgSend points to them)
318 Do fix up protocols (@protocol points to them)
319 Do fix up superclass pointers in classes ([super ...] points to them)
320 Future: do load new classes?
321 Future: do load new categories?
322 Future: do insert new methods on existing classes?
323 Future: do insert new methods on existing categories?
324 */
325
326 #define _objcInfoSupportsGC(info) (((info)->flags & OBJC_IMAGE_SUPPORTS_GC) ? 1 : 0)
327 #define _objcInfoRequiresGC(info) (((info)->flags & OBJC_IMAGE_REQUIRES_GC) ? 1 : 0)
328 #define _objcHeaderSupportsGC(h) ((h)->info && _objcInfoSupportsGC((h)->info))
329 #define _objcHeaderRequiresGC(h) ((h)->info && _objcInfoRequiresGC((h)->info))
330
331 /* OBJC_IMAGE_SUPPORTS_GC:
332 was compiled with -fobjc-gc flag, regardless of whether write-barriers were issued
333 if executable image compiled this way, then all subsequent libraries etc. must also be this way
334 */
335
336 #define _objcHeaderOptimizedByDyld(h) ((h)->info && ((h)->info->flags & OBJC_IMAGE_OPTIMIZED_BY_DYLD))
337
338 /* OBJC_IMAGE_OPTIMIZED_BY_DYLD:
339 Assorted metadata precooked in the dyld shared cache.
340 Never set for images outside the shared cache file itself.
341 */
342
343
344 typedef struct _header_info {
345 struct _header_info *next;
346 const headerType *mhdr;
347 const objc_image_info *info;
348 const char *fname; // same as Dl_info.dli_fname
349 bool loaded;
350 bool inSharedCache;
351 bool allClassesRealized;
352
353 // Do not add fields without editing ObjCModernAbstraction.hpp
354
355 #if !__OBJC2__
356 struct old_protocol **proto_refs;
357 struct objc_module *mod_ptr;
358 size_t mod_count;
359 # if TARGET_OS_WIN32
360 struct objc_module **modules;
361 size_t moduleCount;
362 struct old_protocol **protocols;
363 size_t protocolCount;
364 void *imageinfo;
365 size_t imageinfoBytes;
366 SEL *selrefs;
367 size_t selrefCount;
368 struct objc_class **clsrefs;
369 size_t clsrefCount;
370 TCHAR *moduleName;
371 # endif
372 #endif
373 } header_info;
374
375 extern header_info *FirstHeader;
376 extern header_info *LastHeader;
377 extern int HeaderCount;
378
379 extern uint32_t AppSDKVersion; // X.Y.Z is 0xXXXXYYZZ
380
381 extern void appendHeader(header_info *hi);
382 extern void removeHeader(header_info *hi);
383
384 extern objc_image_info *_getObjcImageInfo(const headerType *head, size_t *size);
385 extern BOOL _hasObjcContents(const header_info *hi);
386
387
388 /* selectors */
389 extern void sel_init(BOOL gc, size_t selrefCount);
390 extern SEL sel_registerNameNoLock(const char *str, BOOL copy);
391 extern void sel_lock(void);
392 extern void sel_unlock(void);
393 extern BOOL sel_preoptimizationValid(const header_info *hi);
394
395 extern SEL SEL_load;
396 extern SEL SEL_initialize;
397 extern SEL SEL_resolveClassMethod;
398 extern SEL SEL_resolveInstanceMethod;
399 extern SEL SEL_cxx_construct;
400 extern SEL SEL_cxx_destruct;
401 extern SEL SEL_retain;
402 extern SEL SEL_release;
403 extern SEL SEL_autorelease;
404 extern SEL SEL_retainCount;
405 extern SEL SEL_alloc;
406 extern SEL SEL_allocWithZone;
407 extern SEL SEL_dealloc;
408 extern SEL SEL_copy;
409 extern SEL SEL_new;
410 extern SEL SEL_finalize;
411 extern SEL SEL_forwardInvocation;
412 extern SEL SEL_tryRetain;
413 extern SEL SEL_isDeallocating;
414 extern SEL SEL_retainWeakReference;
415 extern SEL SEL_allowsWeakReference;
416
417 /* preoptimization */
418 extern void preopt_init(void);
419 extern void disableSharedCacheOptimizations(void);
420 extern bool isPreoptimized(void);
421 extern header_info *preoptimizedHinfoForHeader(const headerType *mhdr);
422
423 #if SUPPORT_PREOPT && __cplusplus
424 #include <objc-shared-cache.h>
425 using objc_selopt_t = const objc_opt::objc_selopt_t;
426 #else
427 struct objc_selopt_t;
428 #endif
429
430 extern objc_selopt_t *preoptimizedSelectors(void);
431 extern Class getPreoptimizedClass(const char *name);
432 extern Class* copyPreoptimizedClasses(const char *name, int *outCount);
433
434
435 /* optional malloc zone for runtime data */
436 extern malloc_zone_t *_objc_internal_zone(void);
437 extern void *_malloc_internal(size_t size);
438 extern void *_calloc_internal(size_t count, size_t size);
439 extern void *_realloc_internal(void *ptr, size_t size);
440 extern char *_strdup_internal(const char *str);
441 extern char *_strdupcat_internal(const char *s1, const char *s2);
442 extern uint8_t *_ustrdup_internal(const uint8_t *str);
443 extern void *_memdup_internal(const void *mem, size_t size);
444 extern void _free_internal(void *ptr);
445 extern size_t _malloc_size_internal(void *ptr);
446
447 extern Class _calloc_class(size_t size);
448
449 /* method lookup */
450 extern IMP lookUpImpOrNil(Class, SEL, id obj, bool initialize, bool cache, bool resolver);
451 extern IMP lookUpImpOrForward(Class, SEL, id obj, bool initialize, bool cache, bool resolver);
452
453 extern IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel);
454 extern BOOL class_respondsToSelector_inst(Class cls, SEL sel, id inst);
455
456 extern bool objcMsgLogEnabled;
457 extern bool logMessageSend(bool isClassMethod,
458 const char *objectsClass,
459 const char *implementingClass,
460 SEL selector);
461
462 /* message dispatcher */
463 extern IMP _class_lookupMethodAndLoadCache3(id, SEL, Class);
464
465 #if !OBJC_OLD_DISPATCH_PROTOTYPES
466 extern void _objc_msgForward_impcache(void);
467 extern void _objc_ignored_method(void);
468 extern void _objc_msgSend_uncached_impcache(void);
469 #else
470 extern id _objc_msgForward_impcache(id, SEL, ...);
471 extern id _objc_ignored_method(id, SEL, ...);
472 extern id _objc_msgSend_uncached_impcache(id, SEL, ...);
473 #endif
474
475 /* errors */
476 extern void __objc_error(id, const char *, ...) __attribute__((format (printf, 2, 3), noreturn));
477 extern void _objc_inform(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
478 extern void _objc_inform_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
479 extern void _objc_inform_now_and_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
480 extern void _objc_inform_deprecated(const char *oldname, const char *newname) __attribute__((noinline));
481 extern void inform_duplicate(const char *name, Class oldCls, Class cls);
482 extern bool crashlog_header_name(header_info *hi);
483 extern bool crashlog_header_name_string(const char *name);
484
485 /* magic */
486 extern Class _objc_getFreedObjectClass (void);
487
488 /* map table additions */
489 extern void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value);
490 extern void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key);
491
492 /* hash table additions */
493 extern unsigned _NXHashCapacity(NXHashTable *table);
494 extern void _NXHashRehashToCapacity(NXHashTable *table, unsigned newCapacity);
495
496 /* property attribute parsing */
497 extern const char *copyPropertyAttributeString(const objc_property_attribute_t *attrs, unsigned int count);
498 extern objc_property_attribute_t *copyPropertyAttributeList(const char *attrs, unsigned int *outCount);
499 extern char *copyPropertyAttributeValue(const char *attrs, const char *name);
500
501 /* locking */
502 extern void lock_init(void);
503 extern rwlock_t selLock;
504 extern mutex_t cacheUpdateLock;
505 extern recursive_mutex_t loadMethodLock;
506 #if __OBJC2__
507 extern rwlock_t runtimeLock;
508 #else
509 extern mutex_t classLock;
510 extern mutex_t methodListLock;
511 #endif
512
513 /* Lock debugging */
514 #if defined(NDEBUG) || TARGET_OS_WIN32
515
516 #define mutex_lock(m) _mutex_lock_nodebug(m)
517 #define mutex_try_lock(m) _mutex_try_lock_nodebug(m)
518 #define mutex_unlock(m) _mutex_unlock_nodebug(m)
519 #define mutex_assert_locked(m) do { } while (0)
520 #define mutex_assert_unlocked(m) do { } while (0)
521
522 #define recursive_mutex_lock(m) _recursive_mutex_lock_nodebug(m)
523 #define recursive_mutex_try_lock(m) _recursive_mutex_try_lock_nodebug(m)
524 #define recursive_mutex_unlock(m) _recursive_mutex_unlock_nodebug(m)
525 #define recursive_mutex_assert_locked(m) do { } while (0)
526 #define recursive_mutex_assert_unlocked(m) do { } while (0)
527
528 #define monitor_enter(m) _monitor_enter_nodebug(m)
529 #define monitor_exit(m) _monitor_exit_nodebug(m)
530 #define monitor_wait(m) _monitor_wait_nodebug(m)
531 #define monitor_assert_locked(m) do { } while (0)
532 #define monitor_assert_unlocked(m) do { } while (0)
533
534 #define rwlock_read(m) _rwlock_read_nodebug(m)
535 #define rwlock_write(m) _rwlock_write_nodebug(m)
536 #define rwlock_try_read(m) _rwlock_try_read_nodebug(m)
537 #define rwlock_try_write(m) _rwlock_try_write_nodebug(m)
538 #define rwlock_unlock_read(m) _rwlock_unlock_read_nodebug(m)
539 #define rwlock_unlock_write(m) _rwlock_unlock_write_nodebug(m)
540 #define rwlock_assert_reading(m) do { } while (0)
541 #define rwlock_assert_writing(m) do { } while (0)
542 #define rwlock_assert_locked(m) do { } while (0)
543 #define rwlock_assert_unlocked(m) do { } while (0)
544
545 #else
546
547 extern int _mutex_lock_debug(mutex_t *lock, const char *name);
548 extern int _mutex_try_lock_debug(mutex_t *lock, const char *name);
549 extern int _mutex_unlock_debug(mutex_t *lock, const char *name);
550 extern void _mutex_assert_locked_debug(mutex_t *lock, const char *name);
551 extern void _mutex_assert_unlocked_debug(mutex_t *lock, const char *name);
552
553 extern int _recursive_mutex_lock_debug(recursive_mutex_t *lock, const char *name);
554 extern int _recursive_mutex_try_lock_debug(recursive_mutex_t *lock, const char *name);
555 extern int _recursive_mutex_unlock_debug(recursive_mutex_t *lock, const char *name);
556 extern void _recursive_mutex_assert_locked_debug(recursive_mutex_t *lock, const char *name);
557 extern void _recursive_mutex_assert_unlocked_debug(recursive_mutex_t *lock, const char *name);
558
559 extern int _monitor_enter_debug(monitor_t *lock, const char *name);
560 extern int _monitor_exit_debug(monitor_t *lock, const char *name);
561 extern int _monitor_wait_debug(monitor_t *lock, const char *name);
562 extern void _monitor_assert_locked_debug(monitor_t *lock, const char *name);
563 extern void _monitor_assert_unlocked_debug(monitor_t *lock, const char *name);
564
565 extern void _rwlock_read_debug(rwlock_t *l, const char *name);
566 extern void _rwlock_write_debug(rwlock_t *l, const char *name);
567 extern int _rwlock_try_read_debug(rwlock_t *l, const char *name);
568 extern int _rwlock_try_write_debug(rwlock_t *l, const char *name);
569 extern void _rwlock_unlock_read_debug(rwlock_t *l, const char *name);
570 extern void _rwlock_unlock_write_debug(rwlock_t *l, const char *name);
571 extern void _rwlock_assert_reading_debug(rwlock_t *l, const char *name);
572 extern void _rwlock_assert_writing_debug(rwlock_t *l, const char *name);
573 extern void _rwlock_assert_locked_debug(rwlock_t *l, const char *name);
574 extern void _rwlock_assert_unlocked_debug(rwlock_t *l, const char *name);
575
576 #define mutex_lock(m) _mutex_lock_debug (m, #m)
577 #define mutex_try_lock(m) _mutex_try_lock_debug (m, #m)
578 #define mutex_unlock(m) _mutex_unlock_debug (m, #m)
579 #define mutex_assert_locked(m) _mutex_assert_locked_debug (m, #m)
580 #define mutex_assert_unlocked(m) _mutex_assert_unlocked_debug (m, #m)
581
582 #define recursive_mutex_lock(m) _recursive_mutex_lock_debug (m, #m)
583 #define recursive_mutex_try_lock(m) _recursive_mutex_try_lock_debug (m, #m)
584 #define recursive_mutex_unlock(m) _recursive_mutex_unlock_debug (m, #m)
585 #define recursive_mutex_assert_locked(m) _recursive_mutex_assert_locked_debug (m, #m)
586 #define recursive_mutex_assert_unlocked(m) _recursive_mutex_assert_unlocked_debug (m, #m)
587
588 #define monitor_enter(m) _monitor_enter_debug(m, #m)
589 #define monitor_exit(m) _monitor_exit_debug(m, #m)
590 #define monitor_wait(m) _monitor_wait_debug(m, #m)
591 #define monitor_assert_locked(m) _monitor_assert_locked_debug(m, #m)
592 #define monitor_assert_unlocked(m) _monitor_assert_unlocked_debug(m, #m)
593
594 #define rwlock_read(m) _rwlock_read_debug(m, #m)
595 #define rwlock_write(m) _rwlock_write_debug(m, #m)
596 #define rwlock_try_read(m) _rwlock_try_read_debug(m, #m)
597 #define rwlock_try_write(m) _rwlock_try_write_debug(m, #m)
598 #define rwlock_unlock_read(m) _rwlock_unlock_read_debug(m, #m)
599 #define rwlock_unlock_write(m) _rwlock_unlock_write_debug(m, #m)
600 #define rwlock_assert_reading(m) _rwlock_assert_reading_debug(m, #m)
601 #define rwlock_assert_writing(m) _rwlock_assert_writing_debug(m, #m)
602 #define rwlock_assert_locked(m) _rwlock_assert_locked_debug(m, #m)
603 #define rwlock_assert_unlocked(m) _rwlock_assert_unlocked_debug(m, #m)
604
605 #endif
606
607 #define rwlock_unlock(m, s) \
608 do { \
609 if ((s) == RDONLY) rwlock_unlock_read(m); \
610 else if ((s) == RDWR) rwlock_unlock_write(m); \
611 } while (0)
612
613
614 /* ignored selector support */
615
616 /* Non-GC: no ignored selectors
617 GC (i386 Mac): some selectors ignored, remapped to kIgnore
618 GC (others): some selectors ignored, but not remapped
619 */
620
621 static inline int ignoreSelector(SEL sel)
622 {
623 #if !SUPPORT_GC
624 return NO;
625 #elif SUPPORT_IGNORED_SELECTOR_CONSTANT
626 return UseGC && sel == (SEL)kIgnore;
627 #else
628 return UseGC &&
629 (sel == @selector(retain) ||
630 sel == @selector(release) ||
631 sel == @selector(autorelease) ||
632 sel == @selector(retainCount) ||
633 sel == @selector(dealloc));
634 #endif
635 }
636
637 static inline int ignoreSelectorNamed(const char *sel)
638 {
639 #if !SUPPORT_GC
640 return NO;
641 #else
642 // release retain retainCount dealloc autorelease
643 return (UseGC &&
644 ( (sel[0] == 'r' && sel[1] == 'e' &&
645 (strcmp(&sel[2], "lease") == 0 ||
646 strcmp(&sel[2], "tain") == 0 ||
647 strcmp(&sel[2], "tainCount") == 0 ))
648 ||
649 (strcmp(sel, "dealloc") == 0)
650 ||
651 (sel[0] == 'a' && sel[1] == 'u' &&
652 strcmp(&sel[2], "torelease") == 0)));
653 #endif
654 }
655
656 /* GC startup */
657 extern void gc_init(BOOL wantsGC);
658 extern void gc_init2(void);
659
660 /* Exceptions */
661 struct alt_handler_list;
662 extern void exception_init(void);
663 extern void _destroyAltHandlerList(struct alt_handler_list *list);
664
665 /* Class change notifications (gdb only for now) */
666 #define OBJC_CLASS_ADDED (1<<0)
667 #define OBJC_CLASS_REMOVED (1<<1)
668 #define OBJC_CLASS_IVARS_CHANGED (1<<2)
669 #define OBJC_CLASS_METHODS_CHANGED (1<<3)
670 extern void gdb_objc_class_changed(Class cls, unsigned long changes, const char *classname)
671 __attribute__((noinline));
672
673 #if SUPPORT_GC
674
675 /* Write barrier implementations */
676 extern id objc_getAssociatedObject_non_gc(id object, const void *key);
677 extern void objc_setAssociatedObject_non_gc(id object, const void *key, id value, objc_AssociationPolicy policy);
678
679 extern id objc_getAssociatedObject_gc(id object, const void *key);
680 extern void objc_setAssociatedObject_gc(id object, const void *key, id value, objc_AssociationPolicy policy);
681
682 /* xrefs */
683 extern objc_xref_t _object_addExternalReference_non_gc(id obj, objc_xref_t type);
684 extern id _object_readExternalReference_non_gc(objc_xref_t ref);
685 extern void _object_removeExternalReference_non_gc(objc_xref_t ref);
686
687 extern objc_xref_t _object_addExternalReference_gc(id obj, objc_xref_t type);
688 extern id _object_readExternalReference_gc(objc_xref_t ref);
689 extern void _object_removeExternalReference_gc(objc_xref_t ref);
690
691 /* GC weak reference fixup. */
692 extern void gc_fixup_weakreferences(id newObject, id oldObject);
693
694 /* GC datasegment registration. */
695 extern void gc_register_datasegment(uintptr_t base, size_t size);
696 extern void gc_unregister_datasegment(uintptr_t base, size_t size);
697
698 /* objc_dumpHeap implementation */
699 extern BOOL _objc_dumpHeap(auto_zone_t *zone, const char *filename);
700
701 #endif
702
703
704 // Settings from environment variables
705 #define OPTION(var, env, help) extern bool var;
706 #include "objc-env.h"
707 #undef OPTION
708
709 extern void environ_init(void);
710
711 extern void logReplacedMethod(const char *className, SEL s, BOOL isMeta, const char *catName, IMP oldImp, IMP newImp);
712
713 static __inline uint32_t _objc_strhash(const char *s) {
714 uint32_t hash = 0;
715 for (;;) {
716 int a = *s++;
717 if (0 == a) break;
718 hash += (hash << 8) + a;
719 }
720 return hash;
721 }
722
723
724 // objc per-thread storage
725 typedef struct {
726 struct _objc_initializing_classes *initializingClasses; // for +initialize
727 struct SyncCache *syncCache; // for @synchronize
728 struct alt_handler_list *handlerList; // for exception alt handlers
729 char *printableNames[4]; // temporary demangled names for logging
730
731 // If you add new fields here, don't forget to update
732 // _objc_pthread_destroyspecific()
733
734 } _objc_pthread_data;
735
736 extern _objc_pthread_data *_objc_fetch_pthread_data(BOOL create);
737 extern void tls_init(void);
738
739 // encoding.h
740 extern unsigned int encoding_getNumberOfArguments(const char *typedesc);
741 extern unsigned int encoding_getSizeOfArguments(const char *typedesc);
742 extern unsigned int encoding_getArgumentInfo(const char *typedesc, unsigned int arg, const char **type, int *offset);
743 extern void encoding_getReturnType(const char *t, char *dst, size_t dst_len);
744 extern char * encoding_copyReturnType(const char *t);
745 extern void encoding_getArgumentType(const char *t, unsigned int index, char *dst, size_t dst_len);
746 extern char *encoding_copyArgumentType(const char *t, unsigned int index);
747
748 // sync.h
749 extern void _destroySyncCache(struct SyncCache *cache);
750
751 // arr
752 extern void arr_init(void);
753 extern id objc_autoreleaseReturnValue(id obj);
754
755 // block trampolines
756 extern IMP _imp_implementationWithBlockNoCopy(id block);
757
758 // layout.h
759 typedef struct {
760 uint8_t *bits;
761 size_t bitCount;
762 size_t bitsAllocated;
763 BOOL weak;
764 } layout_bitmap;
765 extern layout_bitmap layout_bitmap_create(const unsigned char *layout_string, size_t layoutStringInstanceSize, size_t instanceSize, BOOL weak);
766 extern layout_bitmap layout_bitmap_create_empty(size_t instanceSize, BOOL weak);
767 extern void layout_bitmap_free(layout_bitmap bits);
768 extern const unsigned char *layout_string_create(layout_bitmap bits);
769 extern void layout_bitmap_set_ivar(layout_bitmap bits, const char *type, size_t offset);
770 extern void layout_bitmap_grow(layout_bitmap *bits, size_t newCount);
771 extern void layout_bitmap_slide(layout_bitmap *bits, size_t oldPos, size_t newPos);
772 extern void layout_bitmap_slide_anywhere(layout_bitmap *bits, size_t oldPos, size_t newPos);
773 extern BOOL layout_bitmap_splat(layout_bitmap dst, layout_bitmap src,
774 size_t oldSrcInstanceSize);
775 extern BOOL layout_bitmap_or(layout_bitmap dst, layout_bitmap src, const char *msg);
776 extern BOOL layout_bitmap_clear(layout_bitmap dst, layout_bitmap src, const char *msg);
777 extern void layout_bitmap_print(layout_bitmap bits);
778
779
780 // fixme runtime
781 extern Class look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler);
782 extern const char *map_images(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]);
783 extern const char *map_images_nolock(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]);
784 extern const char * load_images(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]);
785 extern BOOL load_images_nolock(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]);
786 extern void unmap_image(const struct mach_header *mh, intptr_t vmaddr_slide);
787 extern void unmap_image_nolock(const struct mach_header *mh);
788 extern void _read_images(header_info **hList, uint32_t hCount);
789 extern void prepare_load_methods(header_info *hi);
790 extern void _unload_image(header_info *hi);
791 extern const char ** _objc_copyClassNamesForImage(header_info *hi, unsigned int *outCount);
792
793
794 extern const header_info *_headerForClass(Class cls);
795
796 extern Class _class_remap(Class cls);
797 extern Class _class_getNonMetaClass(Class cls, id obj);
798 extern Ivar _class_getVariable(Class cls, const char *name, Class *memberOf);
799 extern BOOL _class_usesAutomaticRetainRelease(Class cls);
800 extern uint32_t _class_getInstanceStart(Class cls);
801
802 extern unsigned _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone, id *results, unsigned num_requested);
803 extern id _objc_constructOrFree(id bytes, Class cls);
804
805 extern const char *_category_getName(Category cat);
806 extern const char *_category_getClassName(Category cat);
807 extern Class _category_getClass(Category cat);
808 extern IMP _category_getLoadMethod(Category cat);
809
810 extern id object_cxxConstructFromClass(id obj, Class cls);
811 extern void object_cxxDestruct(id obj);
812
813 extern void _class_resolveMethod(Class cls, SEL sel, id inst);
814
815 #define OBJC_WARN_DEPRECATED \
816 do { \
817 static int warned = 0; \
818 if (!warned) { \
819 warned = 1; \
820 _objc_inform_deprecated(__FUNCTION__, NULL); \
821 } \
822 } while (0) \
823
824 __END_DECLS
825
826
827 #ifndef STATIC_ASSERT
828 # define STATIC_ASSERT(x) _STATIC_ASSERT2(x, __LINE__)
829 # define _STATIC_ASSERT2(x, line) _STATIC_ASSERT3(x, line)
830 # define _STATIC_ASSERT3(x, line) \
831 typedef struct { \
832 int _static_assert[(x) ? 0 : -1]; \
833 } _static_assert_ ## line __attribute__((unavailable))
834 #endif
835
836 #define countof(arr) (sizeof(arr) / sizeof((arr)[0]))
837
838
839 // Global operator new and delete. We must not use any app overrides.
840 // This ALSO REQUIRES each of these be in libobjc's unexported symbol list.
841 #if __cplusplus
842 #pragma clang diagnostic push
843 #pragma clang diagnostic ignored "-Winline-new-delete"
844 #include <new>
845 inline void* operator new(std::size_t size) throw (std::bad_alloc) { return _malloc_internal(size); }
846 inline void* operator new[](std::size_t size) throw (std::bad_alloc) { return _malloc_internal(size); }
847 inline void* operator new(std::size_t size, const std::nothrow_t&) throw() { return _malloc_internal(size); }
848 inline void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return _malloc_internal(size); }
849 inline void operator delete(void* p) throw() { _free_internal(p); }
850 inline void operator delete[](void* p) throw() { _free_internal(p); }
851 inline void operator delete(void* p, const std::nothrow_t&) throw() { _free_internal(p); }
852 inline void operator delete[](void* p, const std::nothrow_t&) throw() { _free_internal(p); }
853 #pragma clang diagnostic pop
854 #endif
855
856
857 // DisguisedPtr<T> acts like pointer type T*, except the
858 // stored value is disguised to hide it from tools like `leaks`.
859 // nil is disguised as itself so zero-filled memory works as expected,
860 // which means 0x80..00 is also diguised as itself but we don't care
861 template <typename T>
862 class DisguisedPtr {
863 uintptr_t value;
864
865 static uintptr_t disguise(T* ptr) {
866 return -(uintptr_t)ptr;
867 }
868
869 static T* undisguise(uintptr_t val) {
870 return (T*)-val;
871 }
872
873 public:
874 DisguisedPtr() { }
875 DisguisedPtr(T* ptr)
876 : value(disguise(ptr)) { }
877 DisguisedPtr(const DisguisedPtr<T>& ptr)
878 : value(ptr.value) { }
879
880 DisguisedPtr<T>& operator = (T* rhs) {
881 value = disguise(rhs);
882 return *this;
883 }
884 DisguisedPtr<T>& operator = (const DisguisedPtr<T>& rhs) {
885 value = rhs.value;
886 return *this;
887 }
888
889 operator T* () const {
890 return undisguise(value);
891 }
892 T* operator -> () const {
893 return undisguise(value);
894 }
895 T& operator * () const {
896 return *undisguise(value);
897 }
898 T& operator [] (size_t i) const {
899 return undisguise(value)[i];
900 }
901
902 // pointer arithmetic operators omitted
903 // because we don't currently use them anywhere
904 };
905
906
907 // Pointer hash function.
908 // This is not a terrific hash, but it is fast
909 // and not outrageously flawed for our purposes.
910
911 // Based on principles from http://locklessinc.com/articles/fast_hash/
912 // and evaluation ideas from http://floodyberry.com/noncryptohashzoo/
913 #if __LP64__
914 static inline uint32_t ptr_hash(uint64_t key)
915 {
916 key ^= key >> 4;
917 key *= 0x8a970be7488fda55;
918 key ^= __builtin_bswap64(key);
919 return (uint32_t)key;
920 }
921 #else
922 static inline uint32_t ptr_hash(uint32_t key)
923 {
924 key ^= key >> 4;
925 key *= 0x5052acdb;
926 key ^= __builtin_bswap32(key);
927 return key;
928 }
929 #endif
930
931 /*
932 Higher-quality hash function. This is measurably slower in some workloads.
933 #if __LP64__
934 uint32_t ptr_hash(uint64_t key)
935 {
936 key -= __builtin_bswap64(key);
937 key *= 0x8a970be7488fda55;
938 key ^= __builtin_bswap64(key);
939 key *= 0x8a970be7488fda55;
940 key ^= __builtin_bswap64(key);
941 return (uint32_t)key;
942 }
943 #else
944 static uint32_t ptr_hash(uint32_t key)
945 {
946 key -= __builtin_bswap32(key);
947 key *= 0x5052acdb;
948 key ^= __builtin_bswap32(key);
949 key *= 0x5052acdb;
950 key ^= __builtin_bswap32(key);
951 return key;
952 }
953 #endif
954 */
955
956
957 // Inlined parts of objc_object's implementation
958 #include "objc-object.h"
959
960 #endif /* _OBJC_PRIVATE_H_ */
961