2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright 1999-2002, Apple, Inc. All rights reserved.
25 Responsibility: Christopher Kane
28 #define ENABLE_ZOMBIES 1
30 #include "CFRuntime.h"
31 #include "CFInternal.h"
36 #include <mach-o/dyld.h>
38 #include <crt_externs.h>
40 #include "auto_stubs.h"
42 #define __CFRecordAllocationEvent(a, b, c, d, e) ((void)0)
45 // retain/release recording constants -- must match values
46 // used by OA for now; probably will change in the future
47 __kCFRetainEvent
= 28,
48 __kCFReleaseEvent
= 29
51 #include <malloc/malloc.h>
53 extern void __HALT(void);
55 static CFTypeID __kCFNotATypeTypeID
= _kCFRuntimeNotATypeID
;
57 #if !defined (__cplusplus)
58 static const CFRuntimeClass __CFNotATypeClass
= {
70 static CFTypeID __kCFTypeTypeID
= _kCFRuntimeNotATypeID
;
72 static const CFRuntimeClass __CFTypeClass
= {
84 void SIG1(CFTypeRef
){__HALT();};;
85 CFTypeRef
SIG2(CFAllocatorRef
,CFTypeRef
){__HALT();return NULL
;};
86 Boolean
SIG3(CFTypeRef
,CFTypeRef
){__HALT();return FALSE
;};
87 CFHashCode
SIG4(CFTypeRef
){__HALT(); return 0;};
88 CFStringRef
SIG5(CFTypeRef
,CFDictionaryRef
){__HALT();return NULL
;};
89 CFStringRef
SIG6(CFTypeRef
){__HALT();return NULL
;};
91 static const CFRuntimeClass __CFNotATypeClass
= {
103 static CFTypeID __kCFTypeTypeID
= _kCFRuntimeNotATypeID
;
105 static const CFRuntimeClass __CFTypeClass
= {
118 static CFRuntimeClass
** __CFRuntimeClassTable
= NULL
;
119 int32_t __CFRuntimeClassTableSize
= 0;
120 static int32_t __CFRuntimeClassTableCount
= 0;
122 __private_extern__
void * (*__CFSendObjCMsg
)(const void *, SEL
, ...) = NULL
;
124 __private_extern__ malloc_zone_t
*__CFCollectableZone
= NULL
;
126 bool (*__CFObjCIsCollectable
)(void *) = NULL
;
128 static const void* objc_AssignIvar_none(const void *value
, const void *base
, const void **slot
) { return (*slot
= value
); }
129 const void* (*__CFObjCAssignIvar
)(const void *value
, const void *base
, const void **slot
) = objc_AssignIvar_none
;
131 static const void* objc_StrongAssign_none(const void *value
, const void **slot
) { return (*slot
= value
); }
132 const void* (*__CFObjCStrongAssign
)(const void *value
, const void **slot
) = objc_StrongAssign_none
;
134 void* (*__CFObjCMemmoveCollectable
)(void *dst
, const void *, size_t) = memmove
;
136 // GC: to be moved to objc if necessary.
137 static void objc_WriteBarrierRange_none(void *ptr
, size_t size
) {}
138 static void objc_WriteBarrierRange_auto(void *ptr
, size_t size
) { auto_zone_write_barrier_range(__CFCollectableZone
, ptr
, size
); }
139 void (*__CFObjCWriteBarrierRange
)(void *, size_t) = objc_WriteBarrierRange_none
;
141 // Compiler uses this symbol name; must match compiler built-in decl
143 int __CFConstantStringClassReference
[24] = {0};
145 int __CFConstantStringClassReference
[12] = {0};
148 // #warning the whole business of reallocating the ClassTables is not thread-safe, because access to those values is not protected
150 CFTypeID
_CFRuntimeRegisterClass(const CFRuntimeClass
* const cls
) {
151 // version field must be 0
152 // className must be pure ASCII string, non-null
153 if (__CFMaxRuntimeTypes
<= __CFRuntimeClassTableCount
) {
154 CFLog(kCFLogLevelWarning
, CFSTR("*** CoreFoundation class table full; registration failing for class '%s'. Program will crash soon."), cls
->className
);
155 return _kCFRuntimeNotATypeID
;
157 if (__CFRuntimeClassTableSize
<= __CFRuntimeClassTableCount
) {
158 int32_t old_size
= __CFRuntimeClassTableSize
;
159 int32_t new_size
= __CFRuntimeClassTableSize
* 4;
161 void *new_table1
= calloc(new_size
, sizeof(CFRuntimeClass
*));
162 memmove(new_table1
, __CFRuntimeClassTable
, old_size
* sizeof(CFRuntimeClass
*));
163 __CFRuntimeClassTable
= (CFRuntimeClass
**)new_table1
;
164 __CFRuntimeClassTableSize
= new_size
;
165 // The old value of __CFRuntimeClassTable is intentionally leaked
166 // for thread-safety reasons:
167 // other threads might have loaded the value of that, in functions here
168 // in this file executing in other threads, and may attempt to use it after
169 // this thread gets done reallocating here, so freeing is unsafe. We
170 // don't want to pay the expense of locking around all uses of these variables.
171 // The old value of __CFRuntimeObjCClassTable is intentionally leaked
172 // for thread-safety reasons:
173 // other threads might have loaded the value of that, since it is
174 // accessible via CFBridgingPriv.h, and may attempt to use it after
175 // this thread gets done reallocating here, so freeing is unsafe.
177 __CFRuntimeClassTable
[__CFRuntimeClassTableCount
++] = (CFRuntimeClass
*)cls
;
178 return __CFRuntimeClassTableCount
- 1;
181 void _CFRuntimeBridgeClasses(CFTypeID cf_typeID
, const char *objc_classname
) {
185 const CFRuntimeClass
* _CFRuntimeGetClassWithTypeID(CFTypeID typeID
) {
186 return __CFRuntimeClassTable
[typeID
];
189 void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID
) {
190 __CFRuntimeClassTable
[typeID
] = NULL
;
194 #if defined(DEBUG) || defined(ENABLE_ZOMBIES)
196 /* CFZombieLevel levels:
197 * bit 0: scribble deallocated CF object memory
198 * bit 1: do not scribble on CFRuntimeBase header (when bit 0)
199 * bit 4: do not free CF objects
200 * bit 7: use 3rd-order byte as scribble byte for dealloc (otherwise 0xFC)
203 static uint32_t __CFZombieLevel
= 0x0;
204 static uint8_t __CFZombieEnabled
= 0;
205 static uint8_t __CFDeallocateZombies
= 0;
206 static void *_original_objc_dealloc
= 0;
210 // XXX_PCB: use the class version field as a bitmask, to allow classes to opt-in for GC scanning.
212 #define CF_GET_COLLECTABLE_MEMORY_TYPE(x) (0)
214 CFTypeRef
_CFRuntimeCreateInstance(CFAllocatorRef allocator
, CFTypeID typeID
, CFIndex extraBytes
, unsigned char *category
) {
215 CFRuntimeBase
*memory
;
216 Boolean usesSystemDefaultAllocator
;
219 CFAssert1(typeID
!= _kCFRuntimeNotATypeID
, __kCFLogAssertion
, "%s(): Uninitialized type id", __PRETTY_FUNCTION__
);
221 if (NULL
== __CFRuntimeClassTable
[typeID
]) {
224 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
225 usesSystemDefaultAllocator
= (allocator
== kCFAllocatorSystemDefault
);
226 size
= sizeof(CFRuntimeBase
) + extraBytes
+ (usesSystemDefaultAllocator
? 0 : sizeof(CFAllocatorRef
));
227 size
= (size
+ 0xF) & ~0xF; // CF objects are multiples of 16 in size
228 // CFType version 0 objects are unscanned by default since they don't have write-barriers and hard retain their innards
229 // CFType version 1 objects are scanned and use hand coded write-barriers to store collectable storage within
230 memory
= (CFRuntimeBase
*)CFAllocatorAllocate(allocator
, size
, CF_GET_COLLECTABLE_MEMORY_TYPE(__CFRuntimeClassTable
[typeID
]));
231 if (NULL
== memory
) {
234 memset(memory
, 0, malloc_size(memory
));
235 if (__CFOASafe
&& category
) {
236 __CFSetLastAllocationEventName(memory
, (char *)category
);
237 } else if (__CFOASafe
) {
238 __CFSetLastAllocationEventName(memory
, (char *)__CFRuntimeClassTable
[typeID
]->className
);
240 if (!usesSystemDefaultAllocator
) {
241 // add space to hold allocator ref for non-standard allocators.
242 // (this screws up 8 byte alignment but seems to work)
243 *(CFAllocatorRef
*)((char *)memory
) = (CFAllocatorRef
)CFRetain(allocator
);
244 memory
= (CFRuntimeBase
*)((char *)memory
+ sizeof(CFAllocatorRef
));
246 memory
->_cfisa
= __CFISAForTypeID(typeID
);
248 *(uint32_t *)(memory
->_cfinfo
) = (uint32_t)((0 << 24) + ((typeID
& 0xFFFF) << 8) + (usesSystemDefaultAllocator
? 0x80 : 0x00));
251 *(uint32_t *)(memory
->_cfinfo
) = (uint32_t)((1 << 24) + ((typeID
& 0xFFFF) << 8) + (usesSystemDefaultAllocator
? 0x80 : 0x00));
253 if (NULL
!= __CFRuntimeClassTable
[typeID
]->init
) {
254 (__CFRuntimeClassTable
[typeID
]->init
)(memory
);
259 void _CFRuntimeInitStaticInstance(void *ptr
, CFTypeID typeID
) {
260 CFRuntimeBase
*memory
= (CFRuntimeBase
*)ptr
;
261 CFAssert1(typeID
!= _kCFRuntimeNotATypeID
, __kCFLogAssertion
, "%s(): Uninitialized type id", __PRETTY_FUNCTION__
);
262 if (NULL
== __CFRuntimeClassTable
[typeID
]) {
265 memory
->_cfisa
= __CFISAForTypeID(typeID
);
266 *(uint32_t *)(memory
->_cfinfo
) = (uint32_t)((0 << 24) + ((typeID
& 0xFFFF) << 8) + 0x80);
270 if (NULL
!= __CFRuntimeClassTable
[typeID
]->init
) {
271 (__CFRuntimeClassTable
[typeID
]->init
)(memory
);
275 void _CFRuntimeSetInstanceTypeID(CFTypeRef cf
, CFTypeID typeID
) {
276 *(uint16_t *)(((CFRuntimeBase
*)cf
)->_cfinfo
+ 1) = (uint16_t)(typeID
& 0xFFFF);
279 __private_extern__ Boolean
__CFRuntimeIsFreedObject(id anObject
) {
280 if (!anObject
) return false;
281 static Class freedClass
= Nil
;
282 if (!freedClass
) freedClass
= _objc_getFreedObjectClass();
283 Class cls
= object_getClass(anObject
);
284 if (cls
== freedClass
) return true;
285 // in 64-bit, a future class has nil isa, and calling class_getName() on
286 // such will crash so we do this test; zombie classes are not future classes
287 if (objc_getClass((id
)cls
) == nil
) return false;
288 const char *cname
= class_getName(cls
);
289 if (cname
&& 0 == strncmp(cname
, "_NSZombie_", 10)) return true;
293 CFTypeID
__CFGenericTypeID(const void *cf
) {
294 return (*(uint32_t *)(((CFRuntimeBase
*)cf
)->_cfinfo
) >> 8) & 0xFFFF;
297 CF_INLINE CFTypeID
__CFGenericTypeID_inline(const void *cf
) {
298 return (*(uint32_t *)(((CFRuntimeBase
*)cf
)->_cfinfo
) >> 8) & 0xFFFF;
301 CFTypeID
CFTypeGetTypeID(void) {
302 return __kCFTypeTypeID
;
305 __private_extern__
void __CFGenericValidateType_(CFTypeRef cf
, CFTypeID type
, const char *func
) {
306 if (cf
&& CF_IS_OBJC(type
, cf
)) return;
307 CFAssert2((cf
!= NULL
) && (NULL
!= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]) && (__kCFNotATypeTypeID
!= __CFGenericTypeID_inline(cf
)) && (__kCFTypeTypeID
!= __CFGenericTypeID_inline(cf
)), __kCFLogAssertion
, "%s(): pointer %p is not a CF object", func
, cf
); \
308 CFAssert3(__CFGenericTypeID_inline(cf
) == type
, __kCFLogAssertion
, "%s(): pointer %p is not a %s", func
, cf
, __CFRuntimeClassTable
[type
]->className
); \
311 #define __CFGenericAssertIsCF(cf) \
312 CFAssert2(cf != NULL && (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]) && (__kCFNotATypeTypeID != __CFGenericTypeID_inline(cf)) && (__kCFTypeTypeID != __CFGenericTypeID_inline(cf)), __kCFLogAssertion, "%s(): pointer %p is not a CF object", __PRETTY_FUNCTION__, cf);
314 #define CFTYPE_IS_OBJC(obj) (false)
315 #define CFTYPE_OBJC_FUNCDISPATCH0(rettype, obj, sel) do {} while (0)
316 #define CFTYPE_OBJC_FUNCDISPATCH1(rettype, obj, sel, a1) do {} while (0)
318 CFTypeID
CFGetTypeID(CFTypeRef cf
) {
320 if (NULL
== cf
) HALT
;
322 CFTYPE_OBJC_FUNCDISPATCH0(CFTypeID
, cf
, "_cfTypeID");
323 __CFGenericAssertIsCF(cf
);
324 return __CFGenericTypeID_inline(cf
);
327 CFStringRef
CFCopyTypeIDDescription(CFTypeID type
) {
328 CFAssert2((NULL
!= __CFRuntimeClassTable
[type
]) && __kCFNotATypeTypeID
!= type
&& __kCFTypeTypeID
!= type
, __kCFLogAssertion
, "%s(): type %d is not a CF type ID", __PRETTY_FUNCTION__
, type
);
329 return CFStringCreateWithCString(kCFAllocatorSystemDefault
, __CFRuntimeClassTable
[type
]->className
, kCFStringEncodingASCII
);
332 #define DISGUISE(object) ((void *)(((uintptr_t)object) + 1))
333 #define UNDISGUISE(disguised) ((id)(((uintptr_t)disguised) - 1))
335 // Bit 31 (highest bit) in second word of cf instance indicates external ref count
337 CF_EXPORT
void _CFRelease(CFTypeRef cf
);
338 CF_EXPORT CFTypeRef
_CFRetain(CFTypeRef cf
);
339 CF_EXPORT CFHashCode
_CFHash(CFTypeRef cf
);
341 CFTypeRef
CFRetain(CFTypeRef cf
) {
342 if (CF_IS_COLLECTABLE(cf
)) {
343 // always honor CFRetain's with a GC-visible retain.
344 auto_zone_retain(__CFCollectableZone
, (void*)cf
);
347 CFTYPE_OBJC_FUNCDISPATCH0(CFTypeRef
, cf
, "retain");
348 if (cf
) __CFGenericAssertIsCF(cf
);
349 return _CFRetain(cf
);
352 __private_extern__
void __CFAllocatorDeallocate(CFTypeRef cf
);
354 void CFRelease(CFTypeRef cf
) {
355 #if !defined(__WIN32__)
356 if (CF_IS_COLLECTABLE(cf
)) {
357 // release the GC-visible reference.
358 if (auto_zone_release(__CFCollectableZone
, (void*)cf
) == 0 && !CFTYPE_IS_OBJC(cf
)) {
359 CFRuntimeClass
*cfClass
= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)];
360 if (cfClass
->version
& _kCFRuntimeResourcefulObject
) {
361 if (cfClass
->reclaim
) cfClass
->reclaim(cf
);
367 CFTYPE_OBJC_FUNCDISPATCH0(void, cf
, "release");
368 if (cf
) __CFGenericAssertIsCF(cf
);
373 __private_extern__
const void *__CFStringCollectionCopy(CFAllocatorRef allocator
, const void *ptr
) {
374 CFStringRef theString
= (CFStringRef
)ptr
;
375 CFStringRef result
= CFStringCreateCopy(allocator
, theString
);
376 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
377 result
= (CFStringRef
)CFMakeCollectable(result
);
379 return (const void *)result
;
382 extern void CFCollection_non_gc_storage_error(void);
384 __private_extern__
const void *__CFTypeCollectionRetain(CFAllocatorRef allocator
, const void *ptr
) {
385 CFTypeRef cf
= (CFTypeRef
)ptr
;
386 // only collections allocated in the GC zone can opt-out of reference counting.
387 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
388 if (CFTYPE_IS_OBJC(cf
)) return cf
; // do nothing for OBJC objects.
389 if (auto_zone_is_valid_pointer(__CFCollectableZone
, ptr
)) {
390 CFRuntimeClass
*cfClass
= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)];
391 if (cfClass
->version
& _kCFRuntimeResourcefulObject
) {
392 // GC: If this a CF object in the GC heap that is marked resourceful, then
393 // it must be retained keep it alive in a CF collection.
394 // We're basically inlining CFRetain() here, to avoid an extra heap membership test.
395 auto_zone_retain(__CFCollectableZone
, (void*)cf
);
398 ; // don't retain normal CF objects
401 // support constant CFTypeRef objects.
403 uint32_t lowBits
= ((CFRuntimeBase
*)cf
)->_rc
;
405 uint32_t lowBits
= ((CFRuntimeBase
*)cf
)->_cfinfo
[CF_RC_BITS
];
407 if (lowBits
== 0) return cf
;
408 // complain about non-GC objects in GC containers.
409 CFLog(kCFLogLevelWarning
, CFSTR("storing a non-GC object %p in a GC collection, break on CFCollection_non_gc_storage_error to debug."), cf
);
410 CFCollection_non_gc_storage_error();
411 // XXX should halt, except Patrick is using this somewhere.
419 __private_extern__
void __CFTypeCollectionRelease(CFAllocatorRef allocator
, const void *ptr
) {
420 CFTypeRef cf
= (CFTypeRef
)ptr
;
421 // only collections allocated in the GC zone can opt-out of reference counting.
422 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
423 if (CFTYPE_IS_OBJC(cf
)) return; // do nothing for OBJC objects.
424 if (auto_zone_is_valid_pointer(__CFCollectableZone
, cf
)) {
425 #if !defined(__WIN32__)
426 // GC: If this a CF object in the GC heap that is marked uncollectable, then
427 // must balance the retain done in __CFTypeCollectionRetain().
428 // We're basically inlining CFRelease() here, to avoid an extra heap membership test.
429 CFRuntimeClass
*cfClass
= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)];
430 if (cfClass
->version
& _kCFRuntimeResourcefulObject
&& auto_zone_release(__CFCollectableZone
, (void*)cf
) == 0) {
431 // ResourceFull objects trigger 'reclaim' on transition to zero
432 if (cfClass
->reclaim
) cfClass
->reclaim(cf
);
434 else // avoid releasing normal CF objects. Like other collections, for example
439 // support constant CFTypeRef objects.
441 uint32_t lowBits
= ((CFRuntimeBase
*)cf
)->_rc
;
443 uint32_t lowBits
= ((CFRuntimeBase
*)cf
)->_cfinfo
[CF_RC_BITS
];
445 if (lowBits
== 0) return;
452 static CFSpinLock_t __CFRuntimeExternRefCountTableLock
= CFSpinLockInit
;
453 static CFMutableBagRef __CFRuntimeExternRefCountTable
= NULL
;
456 static uint64_t __CFGetFullRetainCount(CFTypeRef cf
) {
458 uint32_t lowBits
= ((CFRuntimeBase
*)cf
)->_rc
;
460 return (uint64_t)0x0fffffffffffffffULL
;
464 uint32_t lowBits
= ((CFRuntimeBase
*)cf
)->_cfinfo
[CF_RC_BITS
];
466 return (uint64_t)0x0fffffffffffffffULL
;
468 uint64_t highBits
= 0;
469 if ((lowBits
& 0x80) != 0) {
470 __CFSpinLock(&__CFRuntimeExternRefCountTableLock
);
471 highBits
= (uint64_t)CFBagGetCountOfValue(__CFRuntimeExternRefCountTable
, DISGUISE(cf
));
472 __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock
);
474 uint64_t compositeRC
= (lowBits
& 0x7f) + (highBits
<< 6);
479 CFTypeRef
_CFRetainGC(CFTypeRef cf
) {
481 if (CF_USING_COLLECTABLE_MEMORY
&& !CF_IS_COLLECTABLE(cf
)) {
482 fprintf(stderr
, "non-auto object %p passed to _CFRetainGC.\n", cf
);
486 return CF_USING_COLLECTABLE_MEMORY
? cf
: CFRetain(cf
);
489 void _CFReleaseGC(CFTypeRef cf
) {
491 if (CF_USING_COLLECTABLE_MEMORY
&& !CF_IS_COLLECTABLE(cf
)) {
492 fprintf(stderr
, "non-auto object %p passed to _CFReleaseGC.\n", cf
);
496 if (!CF_USING_COLLECTABLE_MEMORY
) CFRelease(cf
);
499 CFIndex
CFGetRetainCount(CFTypeRef cf
) {
500 if (NULL
== cf
) return 0;
501 if (CF_IS_COLLECTABLE(cf
)) {
502 return auto_zone_retain_count(__CFCollectableZone
, cf
);
504 CFTYPE_OBJC_FUNCDISPATCH0(CFIndex
, cf
, "retainCount");
505 __CFGenericAssertIsCF(cf
);
506 uint64_t rc
= __CFGetFullRetainCount(cf
);
507 return (rc
< (uint64_t)LONG_MAX
) ? (CFIndex
)rc
: (CFIndex
)LONG_MAX
;
510 CFTypeRef
CFMakeCollectable(CFTypeRef cf
) {
511 if (NULL
== cf
) return NULL
;
512 if (CF_IS_COLLECTABLE(cf
)) {
514 CFAllocatorRef allocator
= CFGetAllocator(cf
);
515 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
516 CFLog(kCFLogLevelWarning
, CFSTR("object %p with non-GC allocator %p passed to CFMakeCollectable."), cf
, allocator
);
520 if (!CFTYPE_IS_OBJC(cf
)) {
521 CFRuntimeClass
*cfClass
= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)];
522 if (cfClass
->version
& (_kCFRuntimeResourcefulObject
)) {
523 // don't allow the collector to manage uncollectable objects.
524 CFLog(kCFLogLevelWarning
, CFSTR("uncollectable object %p passed to CFMakeCollectable."), cf
);
528 if (auto_zone_retain_count(__CFCollectableZone
, cf
) == 0) {
529 CFLog(kCFLogLevelWarning
, CFSTR("object %p with 0 retain-count passed to CFMakeCollectable."), cf
);
532 auto_zone_release(__CFCollectableZone
, (void *)cf
);
537 Boolean
CFEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
539 if (NULL
== cf1
) HALT
;
540 if (NULL
== cf2
) HALT
;
542 if (cf1
== cf2
) return true;
543 CFTYPE_OBJC_FUNCDISPATCH1(Boolean
, cf1
, "isEqual:", cf2
);
544 CFTYPE_OBJC_FUNCDISPATCH1(Boolean
, cf2
, "isEqual:", cf1
);
545 __CFGenericAssertIsCF(cf1
);
546 __CFGenericAssertIsCF(cf2
);
547 if (__CFGenericTypeID_inline(cf1
) != __CFGenericTypeID_inline(cf2
)) return false;
548 if (NULL
!= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf1
)]->equal
) {
549 return __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf1
)]->equal(cf1
, cf2
);
554 CFHashCode
CFHash(CFTypeRef cf
) {
555 CFTYPE_OBJC_FUNCDISPATCH0(CFHashCode
, cf
, "hash");
556 __CFGenericAssertIsCF(cf
);
560 // definition: produces a normally non-NULL debugging description of the object
561 CFStringRef
CFCopyDescription(CFTypeRef cf
) {
563 if (NULL
== cf
) HALT
;
565 __CFGenericAssertIsCF(cf
);
566 if (NULL
!= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->copyDebugDesc
) {
568 result
= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->copyDebugDesc(cf
);
569 if (NULL
!= result
) return result
;
571 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<%s %p [%p]>"), __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->className
, cf
, CFGetAllocator(cf
));
574 // Definition: if type produces a formatting description, return that string, otherwise NULL
575 __private_extern__ CFStringRef
__CFCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
577 if (NULL
== cf
) HALT
;
579 __CFGenericAssertIsCF(cf
);
580 if (NULL
!= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->copyFormattingDesc
) {
581 return __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->copyFormattingDesc(cf
, formatOptions
);
586 extern CFAllocatorRef
__CFAllocatorGetAllocator(CFTypeRef
);
588 CFAllocatorRef
CFGetAllocator(CFTypeRef cf
) {
589 if (NULL
== cf
) return kCFAllocatorSystemDefault
;
590 if (__kCFAllocatorTypeID_CONST
== __CFGenericTypeID_inline(cf
)) {
591 return __CFAllocatorGetAllocator(cf
);
593 return __CFGetAllocator(cf
);
596 extern void __CFBaseInitialize(void);
597 extern void __CFNullInitialize(void);
598 extern void __CFAllocatorInitialize(void);
599 extern void __CFStringInitialize(void);
600 extern void __CFArrayInitialize(void);
601 extern void __CFBagInitialize(void);
602 extern void __CFBooleanInitialize(void);
603 extern void __CFCharacterSetInitialize(void);
604 extern void __CFDataInitialize(void);
605 extern void __CFDateInitialize(void);
606 extern void __CFDictionaryInitialize(void);
607 extern void __CFNumberInitialize(void);
608 extern void __CFSetInitialize(void);
609 extern void __CFStorageInitialize(void);
610 extern void __CFErrorInitialize(void);
611 extern void __CFTimeZoneInitialize(void);
612 extern void __CFTreeInitialize(void);
613 extern void __CFURLInitialize(void);
614 #if DEPLOYMENT_TARGET_MACOSX
615 extern void __CFMachPortInitialize(void);
617 #if DEPLOYMENT_TARGET_MACOSX
618 extern void __CFMessagePortInitialize(void);
620 #if DEPLOYMENT_TARGET_MACOSX || defined(__WIN32__)
621 extern void __CFRunLoopInitialize(void);
622 extern void __CFRunLoopObserverInitialize(void);
623 extern void __CFRunLoopSourceInitialize(void);
624 extern void __CFRunLoopTimerInitialize(void);
625 extern void __CFSocketInitialize(void);
627 extern void __CFBundleInitialize(void);
628 extern void __CFPlugInInitialize(void);
629 extern void __CFPlugInInstanceInitialize(void);
630 extern void __CFUUIDInitialize(void);
631 extern void __CFBinaryHeapInitialize(void);
632 extern void __CFBitVectorInitialize(void);
633 extern void __CFStreamInitialize(void);
635 static void __exceptionInit(void) {}
636 static void __collatorInit(void) {}
637 static void __forwarding_prep_0___(void) {}
638 static void __forwarding_prep_1___(void) {}
639 static void __NSFastEnumerationMutationHandler(id obj
) {}
640 const void *__CFArgStuff
= NULL
;
641 __private_extern__
void *__CFAppleLanguages
= NULL
;
643 bool kCFUseCollectableAllocator
= false;
646 #if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
647 static void __CFInitialize(void) __attribute__ ((constructor
));
650 void __CFInitialize(void) {
651 static int __done
= 0;
656 #if defined(DEBUG) || defined(ENABLE_ZOMBIES)
657 const char *value
= getenv("NSZombieEnabled");
658 if (value
&& (*value
== 'Y' || *value
== 'y')) __CFZombieEnabled
= 0xff;
659 value
= getenv("NSDeallocateZombies");
660 if (value
&& (*value
== 'Y' || *value
== 'y')) __CFDeallocateZombies
= 0xff;
662 value
= getenv("CFZombieLevel");
664 __CFZombieLevel
= (uint32_t)strtoul_l(value
, NULL
, 0, NULL
);
666 if (0x0 == __CFZombieLevel
) __CFZombieLevel
= 0x0000FC00; // default
669 __CFRuntimeClassTableSize
= 1024;
670 __CFRuntimeClassTable
= (CFRuntimeClass
**)calloc(__CFRuntimeClassTableSize
, sizeof(CFRuntimeClass
*));
671 __CFBaseInitialize();
673 /* Here so that two runtime classes get indices 0, 1. */
674 __kCFNotATypeTypeID
= _CFRuntimeRegisterClass(&__CFNotATypeClass
);
675 __kCFTypeTypeID
= _CFRuntimeRegisterClass(&__CFTypeClass
);
677 /* Here so that __kCFAllocatorTypeID gets index 2. */
678 __CFAllocatorInitialize();
680 #if DEPLOYMENT_TARGET_MACOSX
683 char **args
= *_NSGetArgv();
685 for (idx
= 1; idx
< cnt
- 1; idx
++) {
686 if (NULL
== args
[idx
]) continue;
687 if (0 == strcmp(args
[idx
], "-AppleLanguages") && args
[idx
+ 1]) {
688 CFIndex length
= strlen(args
[idx
+ 1]);
689 __CFAppleLanguages
= malloc(length
+ 1);
690 memmove(__CFAppleLanguages
, args
[idx
+ 1], length
+ 1);
698 /* CFBag needs to be up before CFString. */
702 // Creating this lazily in CFRetain causes recursive call to CFRetain
703 __CFRuntimeExternRefCountTable
= CFBagCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
);
706 /*** _CFRuntimeCreateInstance() can finally be called generally after this line. ***/
708 __CFRuntimeClassTableCount
= 7;
709 __CFStringInitialize(); // CFString's TypeID must be 0x7, now and forever
710 __CFRuntimeClassTableCount
= 16;
711 __CFDictionaryInitialize();
712 __CFArrayInitialize();
713 __CFDataInitialize();
715 __CFNullInitialize(); // See above for hard-coding of this position
716 __CFBooleanInitialize(); // See above for hard-coding of this position
717 __CFNumberInitialize(); // See above for hard-coding of this position
720 __CFDateInitialize(); // just initializes the time goo
721 // _CFRuntimeBridgeClasses(CFDateGetTypeID(), objc_lookUpClass("NSCFDate") ? "NSCFDate" : "__NSCFDate");
722 __CFTimeZoneInitialize();
723 // _CFRuntimeBridgeClasses(CFTimeZoneGetTypeID(), "NSCFTimeZone");
724 __CFBinaryHeapInitialize();
725 __CFBitVectorInitialize();
726 __CFCharacterSetInitialize();
727 __CFStorageInitialize();
728 __CFErrorInitialize();
729 __CFTreeInitialize();
731 __CFBundleInitialize();
732 #if DEPLOYMENT_TARGET_MACOSX
733 __CFPlugInInitialize();
734 __CFPlugInInstanceInitialize();
736 __CFUUIDInitialize();
737 #if DEPLOYMENT_TARGET_MACOSX
738 __CFMessagePortInitialize();
740 #if DEPLOYMENT_TARGET_MACOSX
741 __CFMachPortInitialize();
743 __CFStreamInitialize();
744 __CFPreferencesDomainInitialize();
745 #if DEPLOYMENT_TARGET_MACOSX || defined(__WIN32__)
746 __CFRunLoopInitialize();
747 __CFRunLoopObserverInitialize();
748 __CFRunLoopSourceInitialize();
749 __CFRunLoopTimerInitialize();
750 __CFSocketInitialize();
754 #if DEPLOYMENT_TARGET_MACOSX
758 args
= *_NSGetArgv();
761 CFStringRef
*list
, buffer
[256];
762 list
= (cnt
<= 256) ? buffer
: malloc(cnt
* sizeof(CFStringRef
));
763 for (idx
= 0, count
= 0; idx
< cnt
; idx
++) {
764 if (NULL
== args
[idx
]) continue;
765 list
[count
] = CFStringCreateWithCString(kCFAllocatorSystemDefault
, args
[idx
], kCFStringEncodingUTF8
);
766 if (NULL
== list
[count
]) {
767 list
[count
] = CFStringCreateWithCString(kCFAllocatorSystemDefault
, args
[idx
], kCFStringEncodingISOLatin1
);
768 // We CANNOT use the string SystemEncoding here;
769 // Do not argue: it is not initialized yet, but these
770 // arguments MUST be initialized before it is.
771 // We should just ignore the argument if the UTF-8
772 // conversion fails, but out of charity we try once
773 // more with ISO Latin1, a standard unix encoding.
775 if (NULL
!= list
[count
]) count
++;
777 __CFArgStuff
= CFArrayCreate(kCFAllocatorSystemDefault
, (const void **)list
, count
, &kCFTypeArrayCallBacks
);
780 _CFProcessPath(); // cache this early
782 if (__CFRuntimeClassTableCount
< 256) __CFRuntimeClassTableCount
= 256;
784 #if defined(DEBUG) && !defined(__WIN32__)
785 CFLog(kCFLogLevelWarning
, CFSTR("Assertions enabled"));
790 //#if defined(__WIN32__)
792 #ifdef _BUILD_NET_FOUNDATION_
796 extern void _CFFTPCleanup(void);
797 extern void _CFHTTPMessageCleanup(void);
798 extern void _CFHTTPStreamCleanup(void);
803 #endif //_BUILD_NET_FOUNDATION_
807 /* We have to call __CFInitialize when library is attached to the process.
810 #if defined(_BUILD_NET_FOUNDATION_)
812 BOOL WINAPI
CoreFoundationDllMain( HINSTANCE hInstance
, DWORD dwReason
, LPVOID pReserved
);
815 BOOL WINAPI
CoreFoundationDllMain( HINSTANCE hInstance
, DWORD dwReason
, LPVOID pReserved
) {
817 BOOL WINAPI
DllMain( HINSTANCE hInstance
, DWORD dwReason
, LPVOID pReserved
) {
819 static CFBundleRef cfBundle
= NULL
;
820 if (dwReason
== DLL_PROCESS_ATTACH
) {
822 cfBundle
= RegisterCoreFoundationBundle();
823 } else if (dwReason
== DLL_PROCESS_DETACH
) {
824 if (cfBundle
) CFRelease(cfBundle
);
829 __CFUniCharCleanup();
832 } else if (dwReason
== DLL_THREAD_DETACH
) {
833 __CFFinalizeThreadData(NULL
);
840 // Functions that avoid ObC dispatch and CF type validation, for use by NSNotifyingCFArray, etc.
841 // Hopefully all of this will just go away. 3321464. M.P. To Do - 7/9/03
843 Boolean
_CFEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
844 if (cf1
== cf2
) return true;
845 if (NULL
== cf1
) return false;
846 if (NULL
== cf2
) return false;
847 __CFGenericAssertIsCF(cf1
);
848 __CFGenericAssertIsCF(cf2
);
849 if (__CFGenericTypeID_inline(cf1
) != __CFGenericTypeID_inline(cf2
)) return false;
850 if (NULL
!= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf1
)]->equal
) {
851 return __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf1
)]->equal(cf1
, cf2
);
856 CFIndex
_CFGetRetainCount(CFTypeRef cf
) {
857 if (NULL
== cf
) return 0;
858 if (CF_IS_COLLECTABLE(cf
)) {
859 return auto_zone_retain_count(__CFCollectableZone
, cf
);
861 uint64_t rc
= __CFGetFullRetainCount(cf
);
862 return (rc
< (uint64_t)LONG_MAX
) ? (CFIndex
)rc
: (CFIndex
)LONG_MAX
;
865 CFHashCode
_CFHash(CFTypeRef cf
) {
866 if (NULL
== cf
) return 0;
867 if (NULL
!= __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->hash
) {
868 return __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->hash(cf
);
870 return (CFHashCode
)cf
;
874 static inline bool myOSAtomicCompareAndSwap32Barrier(int32_t oldValue
, int32_t newValue
, volatile int32_t *theValue
) {
875 int32_t actualOldValue
= InterlockedCompareExchange((volatile LONG
*)theValue
, newValue
, oldValue
);
876 return actualOldValue
== oldValue
? true : false;
879 static bool (*myOSAtomicCompareAndSwap32Barrier
)(int32_t __oldValue
, int32_t __newValue
, volatile int32_t *__theValue
) = OSAtomicCompareAndSwap32Barrier
;
882 CF_EXPORT CFTypeRef
_CFRetain(CFTypeRef cf
) {
883 if (NULL
== cf
) return NULL
;
887 lowBits
= ((CFRuntimeBase
*)cf
)->_rc
;
888 if (0 == lowBits
) return cf
; // Constant CFTypeRef
889 } while (!myOSAtomicCompareAndSwap32Barrier(lowBits
, lowBits
+ 1, (int32_t *)&((CFRuntimeBase
*)cf
)->_rc
));
893 volatile UInt32
*infoLocation
= (UInt32
*)&(((CFRuntimeBase
*)cf
)->_cfinfo
);
894 CFIndex rcLowBits
= __CFBitfieldGetValue(*infoLocation
, RC_END
, RC_START
);
895 if (__builtin_expect(0 == rcLowBits
, 0)) return cf
; // Constant CFTypeRef
898 UInt32 initialCheckInfo
= *infoLocation
;
899 UInt32 prospectiveNewInfo
= initialCheckInfo
; // don't want compiler to generate prospectiveNewInfo = *infoLocation. This is why infoLocation is declared as a pointer to volatile memory.
900 prospectiveNewInfo
+= (1 << RC_START
);
901 rcLowBits
= __CFBitfieldGetValue(prospectiveNewInfo
, RC_END
, RC_START
);
902 if (__builtin_expect((rcLowBits
& 0x7f) == 0, 0)) {
903 /* Roll over another bit to the external ref count
904 Real ref count = low 7 bits of info[CF_RC_BITS] + external ref count << 6
905 Bit 8 of low bits indicates that external ref count is in use.
906 External ref count is shifted by 6 rather than 7 so that we can set the low
907 bits to to 1100 0000 rather than 1000 0000.
908 This prevents needing to access the external ref count for successive retains and releases
909 when the composite retain count is right around a multiple of 1 << 7.
911 prospectiveNewInfo
= initialCheckInfo
;
912 __CFBitfieldSetValue(prospectiveNewInfo
, RC_END
, RC_START
, ((1 << 7) | (1 << 6)));
913 __CFSpinLock(&__CFRuntimeExternRefCountTableLock
);
914 success
= myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo
, *(int32_t *)&prospectiveNewInfo
, (int32_t *)infoLocation
);
915 if (__builtin_expect(success
, 1)) {
916 CFBagAddValue(__CFRuntimeExternRefCountTable
, DISGUISE(cf
));
918 __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock
);
920 success
= myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo
, *(int32_t *)&prospectiveNewInfo
, (int32_t *)infoLocation
);
922 } while (__builtin_expect(!success
, 0));
924 if (__builtin_expect(__CFOASafe
, 0)) {
925 __CFRecordAllocationEvent(__kCFRetainEvent
, (void *)cf
, 0, _CFGetRetainCount(cf
), NULL
);
930 CF_EXPORT
void _CFRelease(CFTypeRef cf
) {
931 Boolean isAllocator
= false;
935 lowBits
= ((CFRuntimeBase
*)cf
)->_rc
;
936 if (0 == lowBits
) return; // Constant CFTypeRef
938 // CANNOT WRITE ANY NEW VALUE INTO [CF_RC_BITS] UNTIL AFTER FINALIZATION
939 CFTypeID typeID
= __CFGenericTypeID_inline(cf
);
940 isAllocator
= (__kCFAllocatorTypeID_CONST
== typeID
);
941 CFRuntimeClass
*cfClass
= __CFRuntimeClassTable
[typeID
];
942 if (cfClass
->version
& _kCFRuntimeResourcefulObject
&& cfClass
->reclaim
!= NULL
) {
943 cfClass
->reclaim(cf
);
945 void (*func
)(CFTypeRef
) = __CFRuntimeClassTable
[typeID
]->finalize
;
949 // We recheck lowBits to see if the object has been retained again during
950 // the finalization process. This allows for the finalizer to resurrect,
951 // but the main point is to allow finalizers to be able to manage the
952 // removal of objects from uniquing caches, which may race with other threads
953 // which are allocating (looking up and finding) objects from those caches,
954 // which (that thread) would be the thing doing the extra retain in that case.
955 if (isAllocator
|| myOSAtomicCompareAndSwap32Barrier(1, 0, (int32_t *)&((CFRuntimeBase
*)cf
)->_rc
)) {
959 } while (!myOSAtomicCompareAndSwap32Barrier(lowBits
, lowBits
- 1, (int32_t *)&((CFRuntimeBase
*)cf
)->_rc
));
961 volatile UInt32
*infoLocation
= (UInt32
*)&(((CFRuntimeBase
*)cf
)->_cfinfo
);
962 CFIndex rcLowBits
= __CFBitfieldGetValue(*infoLocation
, RC_END
, RC_START
);
963 if (__builtin_expect(0 == rcLowBits
, 0)) return; // Constant CFTypeRef
966 UInt32 initialCheckInfo
= *infoLocation
;
967 rcLowBits
= __CFBitfieldGetValue(initialCheckInfo
, RC_END
, RC_START
);
968 if (__builtin_expect(1 == rcLowBits
, 0)) {
969 // we think cf should be deallocated
970 if (__builtin_expect(__kCFAllocatorTypeID_CONST
== __CFGenericTypeID_inline(cf
), 0)) {
971 if (__builtin_expect(__CFOASafe
, 0)) __CFRecordAllocationEvent(__kCFReleaseEvent
, (void *)cf
, 0, 0, NULL
);
972 __CFAllocatorDeallocate((void *)cf
);
975 // CANNOT WRITE ANY NEW VALUE INTO [CF_RC_BITS] UNTIL AFTER FINALIZATION
976 CFTypeID typeID
= __CFGenericTypeID_inline(cf
);
977 CFRuntimeClass
*cfClass
= __CFRuntimeClassTable
[typeID
];
978 if (cfClass
->version
& _kCFRuntimeResourcefulObject
&& cfClass
->reclaim
!= NULL
) {
979 cfClass
->reclaim(cf
);
981 if (NULL
!= __CFRuntimeClassTable
[typeID
]->finalize
) {
982 __CFRuntimeClassTable
[__CFGenericTypeID_inline(cf
)]->finalize(cf
);
984 // We recheck rcLowBits to see if the object has been retained again during
985 // the finalization process. This allows for the finalizer to resurrect,
986 // but the main point is to allow finalizers to be able to manage the
987 // removal of objects from uniquing caches, which may race with other threads
988 // which are allocating (looking up and finding) objects from those caches,
989 // which (that thread) would be the thing doing the extra retain in that case.
990 rcLowBits
= __CFBitfieldGetValue(*infoLocation
, RC_END
, RC_START
);
991 success
= (1 == rcLowBits
);
992 if (__builtin_expect(success
, 1)) {
998 UInt32 prospectiveNewInfo
= initialCheckInfo
; // don't want compiler to generate prospectiveNewInfo = *infoLocation. This is why infoLocation is declared as a pointer to volatile memory.
999 if (__builtin_expect((1 << 7) == rcLowBits
, 0)) {
1000 // Time to remove a bit from the external ref count
1001 __CFSpinLock(&__CFRuntimeExternRefCountTableLock
);
1002 CFIndex rcHighBitsCnt
= CFBagGetCountOfValue(__CFRuntimeExternRefCountTable
, DISGUISE(cf
));
1003 if (1 == rcHighBitsCnt
) {
1004 __CFBitfieldSetValue(prospectiveNewInfo
, RC_END
, RC_START
, (1 << 6) - 1);
1006 __CFBitfieldSetValue(prospectiveNewInfo
, RC_END
, RC_START
, ((1 << 6) | (1 << 7)) - 1);
1008 success
= myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo
, *(int32_t *)&prospectiveNewInfo
, (int32_t *)infoLocation
);
1009 if (__builtin_expect(success
, 1)) {
1010 CFBagRemoveValue(__CFRuntimeExternRefCountTable
, DISGUISE(cf
));
1012 __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock
);
1014 prospectiveNewInfo
-= (1 << RC_START
);
1015 success
= myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo
, *(int32_t *)&prospectiveNewInfo
, (int32_t *)infoLocation
);
1018 } while (__builtin_expect(!success
, 0));
1021 if (__builtin_expect(__CFOASafe
, 0)) {
1022 __CFRecordAllocationEvent(__kCFReleaseEvent
, (void *)cf
, 0, _CFGetRetainCount(cf
), NULL
);
1027 if (__builtin_expect(__CFOASafe
, 0)) {
1028 // do not use _CFGetRetainCount() because cf has been freed if it was an allocator
1029 __CFRecordAllocationEvent(__kCFReleaseEvent
, (void *)cf
, 0, 0, NULL
);
1031 // cannot zombify allocators, which get deallocated by __CFAllocatorDeallocate (finalize)
1033 CFAllocatorRef allocator
;
1034 Boolean usesSystemDefaultAllocator
;
1036 if (__CFBitfieldGetValue(((const CFRuntimeBase
*)cf
)->_cfinfo
[CF_INFO_BITS
], 7, 7)) {
1037 allocator
= kCFAllocatorSystemDefault
;
1039 allocator
= CFGetAllocator(cf
);
1041 usesSystemDefaultAllocator
= (allocator
== kCFAllocatorSystemDefault
);
1043 if (__CFZombieLevel
& (1 << 0)) {
1044 uint8_t *ptr
= (uint8_t *)cf
- (usesSystemDefaultAllocator
? 0 : sizeof(CFAllocatorRef
));
1045 size_t size
= malloc_size(ptr
);
1046 uint8_t byte
= 0xFC;
1047 if (__CFZombieLevel
& (1 << 1)) {
1048 ptr
= (uint8_t *)cf
+ sizeof(CFRuntimeBase
);
1049 size
= size
- sizeof(CFRuntimeBase
) - (usesSystemDefaultAllocator
? 0 : sizeof(CFAllocatorRef
));
1051 if (__CFZombieLevel
& (1 << 7)) {
1052 byte
= (__CFZombieLevel
>> 8) & 0xFF;
1054 memset(ptr
, byte
, size
);
1056 if (!(__CFZombieLevel
& (1 << 4))) {
1057 CFAllocatorDeallocate(allocator
, (uint8_t *)cf
- (usesSystemDefaultAllocator
? 0 : sizeof(CFAllocatorRef
)));
1060 if (kCFAllocatorSystemDefault
!= allocator
) {
1061 CFRelease(allocator
);
1066 #undef __kCFAllocatorTypeID_CONST
1067 #undef __CFGenericAssertIsCF