2 * Copyright (c) 2014 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@
25 Copyright (c) 1998-2013, Apple Inc. All rights reserved.
26 Responsibility: Christopher Kane
29 #include <CoreFoundation/CFBase.h>
30 #include "CFInternal.h"
31 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
34 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
35 #include <malloc/malloc.h>
36 #include <mach/mach.h>
42 // -------- -------- -------- -------- -------- -------- -------- --------
44 struct __CFAllocator
{
46 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
47 // CFAllocator structure must match struct _malloc_zone_t!
48 // The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
49 size_t (*size
)(struct _malloc_zone_t
*zone
, const void *ptr
); /* returns the size of a block or 0 if not in this zone; must be fast, especially for negative answers */
50 void *(*malloc
)(struct _malloc_zone_t
*zone
, size_t size
);
51 void *(*calloc
)(struct _malloc_zone_t
*zone
, size_t num_items
, size_t size
); /* same as malloc, but block returned is set to zero */
52 void *(*valloc
)(struct _malloc_zone_t
*zone
, size_t size
); /* same as malloc, but block returned is set to zero and is guaranteed to be page aligned */
53 void (*free
)(struct _malloc_zone_t
*zone
, void *ptr
);
54 void *(*realloc
)(struct _malloc_zone_t
*zone
, void *ptr
, size_t size
);
55 void (*destroy
)(struct _malloc_zone_t
*zone
); /* zone is destroyed and all memory reclaimed */
56 const char *zone_name
;
58 /* Optional batch callbacks; these may be NULL */
59 unsigned (*batch_malloc
)(struct _malloc_zone_t
*zone
, size_t size
, void **results
, unsigned num_requested
); /* given a size, returns pointers capable of holding that size; returns the number of pointers allocated (maybe 0 or less than num_requested) */
60 void (*batch_free
)(struct _malloc_zone_t
*zone
, void **to_be_freed
, unsigned num_to_be_freed
); /* frees all the pointers in to_be_freed; note that to_be_freed may be overwritten during the process */
62 struct malloc_introspection_t
*introspect
;
65 /* aligned memory allocation. The callback may be NULL. */
66 void *(*memalign
)(struct _malloc_zone_t
*zone
, size_t alignment
, size_t size
);
68 /* free a pointer known to be in zone and known to have the given size. The callback may be NULL. */
69 void (*free_definite_size
)(struct _malloc_zone_t
*zone
, void *ptr
, size_t size
);
71 CFAllocatorRef _allocator
;
72 CFAllocatorContext _context
;
75 CF_INLINE CFAllocatorRetainCallBack
__CFAllocatorGetRetainFunction(const CFAllocatorContext
*context
) {
76 CFAllocatorRetainCallBack retval
= NULL
;
77 retval
= context
->retain
;
81 CF_INLINE CFAllocatorReleaseCallBack
__CFAllocatorGetReleaseFunction(const CFAllocatorContext
*context
) {
82 CFAllocatorReleaseCallBack retval
= NULL
;
83 retval
= context
->release
;
87 CF_INLINE CFAllocatorCopyDescriptionCallBack
__CFAllocatorGetCopyDescriptionFunction(const CFAllocatorContext
*context
) {
88 CFAllocatorCopyDescriptionCallBack retval
= NULL
;
89 retval
= context
->copyDescription
;
93 CF_INLINE CFAllocatorAllocateCallBack
__CFAllocatorGetAllocateFunction(const CFAllocatorContext
*context
) {
94 CFAllocatorAllocateCallBack retval
= NULL
;
95 retval
= context
->allocate
;
99 CF_INLINE CFAllocatorReallocateCallBack
__CFAllocatorGetReallocateFunction(const CFAllocatorContext
*context
) {
100 CFAllocatorReallocateCallBack retval
= NULL
;
101 retval
= context
->reallocate
;
105 CF_INLINE CFAllocatorDeallocateCallBack
__CFAllocatorGetDeallocateFunction(const CFAllocatorContext
*context
) {
106 CFAllocatorDeallocateCallBack retval
= NULL
;
107 retval
= context
->deallocate
;
111 CF_INLINE CFAllocatorPreferredSizeCallBack
__CFAllocatorGetPreferredSizeFunction(const CFAllocatorContext
*context
) {
112 CFAllocatorPreferredSizeCallBack retval
= NULL
;
113 retval
= context
->preferredSize
;
117 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
119 CF_PRIVATE
void __CFAllocatorDeallocate(CFTypeRef cf
);
121 static kern_return_t
__CFAllocatorZoneIntrospectNoOp(void) {
125 static boolean_t
__CFAllocatorZoneIntrospectTrue(void) {
129 static size_t __CFAllocatorCustomSize(malloc_zone_t
*zone
, const void *ptr
) {
132 // The only way to implement this with a version 0 allocator would be
133 // for CFAllocator to keep track of all blocks allocated itself, which
134 // could be done, but would be bad for performance, so we don't do it.
135 // size_t (*size)(struct _malloc_zone_t *zone, const void *ptr);
136 /* returns the size of a block or 0 if not in this zone;
137 * must be fast, especially for negative answers */
140 static void *__CFAllocatorCustomMalloc(malloc_zone_t
*zone
, size_t size
) {
141 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
142 return CFAllocatorAllocate(allocator
, size
, 0);
145 static void *__CFAllocatorCustomCalloc(malloc_zone_t
*zone
, size_t num_items
, size_t size
) {
146 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
147 void *newptr
= CFAllocatorAllocate(allocator
, size
, 0);
148 if (newptr
) memset(newptr
, 0, size
);
152 static void *__CFAllocatorCustomValloc(malloc_zone_t
*zone
, size_t size
) {
153 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
154 if (size
>= ULONG_MAX
- 2 * vm_page_size
) return NULL
; // avoid integer overflow plus don't allow all pages to be allocated either
155 void *newptr
= CFAllocatorAllocate(allocator
, size
+ vm_page_size
, 0);
156 newptr
= (void *)round_page((uintptr_t)newptr
);
160 static void __CFAllocatorCustomFree(malloc_zone_t
*zone
, void *ptr
) {
161 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
162 CFAllocatorDeallocate(allocator
, ptr
);
165 static void *__CFAllocatorCustomRealloc(malloc_zone_t
*zone
, void *ptr
, size_t size
) {
166 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
167 return CFAllocatorReallocate(allocator
, ptr
, size
, 0);
170 static void __CFAllocatorCustomDestroy(malloc_zone_t
*zone
) {
171 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
172 // !!! we do it, and caller of malloc_destroy_zone() assumes
173 // COMPLETE responsibility for the result; NO Apple library
174 // code should be modified as a result of discovering that
175 // some activity results in inconveniences to developers
176 // trying to use malloc_destroy_zone() with a CFAllocatorRef;
177 // that's just too bad for them.
178 __CFAllocatorDeallocate(allocator
);
181 static size_t __CFAllocatorCustomGoodSize(malloc_zone_t
*zone
, size_t size
) {
182 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
183 return CFAllocatorGetPreferredSizeForSize(allocator
, size
, 0);
186 static struct malloc_introspection_t __CFAllocatorZoneIntrospect
= {
187 (void *)__CFAllocatorZoneIntrospectNoOp
,
188 (void *)__CFAllocatorCustomGoodSize
,
189 (void *)__CFAllocatorZoneIntrospectTrue
,
190 (void *)__CFAllocatorZoneIntrospectNoOp
,
191 (void *)__CFAllocatorZoneIntrospectNoOp
,
192 (void *)__CFAllocatorZoneIntrospectNoOp
,
193 (void *)__CFAllocatorZoneIntrospectNoOp
,
194 (void *)__CFAllocatorZoneIntrospectNoOp
197 static size_t __CFAllocatorNullSize(malloc_zone_t
*zone
, const void *ptr
) {
201 static void * __CFAllocatorNullMalloc(malloc_zone_t
*zone
, size_t size
) {
205 static void * __CFAllocatorNullCalloc(malloc_zone_t
*zone
, size_t num_items
, size_t size
) {
209 static void * __CFAllocatorNullValloc(malloc_zone_t
*zone
, size_t size
) {
213 static void __CFAllocatorNullFree(malloc_zone_t
*zone
, void *ptr
) {
216 static void * __CFAllocatorNullRealloc(malloc_zone_t
*zone
, void *ptr
, size_t size
) {
220 static void __CFAllocatorNullDestroy(malloc_zone_t
*zone
) {
223 static size_t __CFAllocatorNullGoodSize(malloc_zone_t
*zone
, size_t size
) {
227 static struct malloc_introspection_t __CFAllocatorNullZoneIntrospect
= {
228 (void *)__CFAllocatorZoneIntrospectNoOp
,
229 (void *)__CFAllocatorNullGoodSize
,
230 (void *)__CFAllocatorZoneIntrospectTrue
,
231 (void *)__CFAllocatorZoneIntrospectNoOp
,
232 (void *)__CFAllocatorZoneIntrospectNoOp
,
233 (void *)__CFAllocatorZoneIntrospectNoOp
,
234 (void *)__CFAllocatorZoneIntrospectNoOp
,
235 (void *)__CFAllocatorZoneIntrospectNoOp
238 static void *__CFAllocatorSystemAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
239 return malloc_zone_malloc(info
, size
);
242 static void *__CFAllocatorSystemReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
243 return malloc_zone_realloc(info
, ptr
, newsize
);
246 static void __CFAllocatorSystemDeallocate(void *ptr
, void *info
) {
248 size_t size
= malloc_size(ptr
);
249 if (size
) memset(ptr
, 0xCC, size
);
251 malloc_zone_free(info
, ptr
);
256 static void *__CFAllocatorSystemAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
260 static void *__CFAllocatorSystemReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
261 return realloc(ptr
, newsize
);
264 static void __CFAllocatorSystemDeallocate(void *ptr
, void *info
) {
269 static void *__CFAllocatorNullAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
273 static void *__CFAllocatorNullReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
277 #if defined (__cplusplus)
278 static void * __CFAllocatorCPPMalloc(CFIndex allocSize
, CFOptionFlags hint
, void *info
)
280 return malloc(allocSize
);
282 static void * __CFAllocatorCPPReAlloc(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
)
284 return realloc(ptr
, newsize
);
286 static void __CFAllocatorCPPFree(void *ptr
, void *info
)
293 static struct __CFAllocator __kCFAllocatorMalloc
= {
294 INIT_CFRUNTIME_BASE(),
295 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
296 __CFAllocatorCustomSize
,
297 __CFAllocatorCustomMalloc
,
298 __CFAllocatorCustomCalloc
,
299 __CFAllocatorCustomValloc
,
300 __CFAllocatorCustomFree
,
301 __CFAllocatorCustomRealloc
,
302 __CFAllocatorNullDestroy
,
303 "kCFAllocatorMalloc",
306 &__CFAllocatorZoneIntrospect
,
312 // Using the malloc functions directly is a total cheat, but works (in C)
313 // because the function signatures match in their common prefix of arguments.
314 // This saves us one hop through an adaptor function.
315 #if !defined (__cplusplus)
316 {0, NULL
, NULL
, NULL
, NULL
, (void *)malloc
, (void *)realloc
, (void *)free
, NULL
}
318 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorCPPMalloc
,__CFAllocatorCPPReAlloc
, __CFAllocatorCPPFree
, NULL
}
319 #endif // __cplusplus
322 static struct __CFAllocator __kCFAllocatorMallocZone
= {
323 INIT_CFRUNTIME_BASE(),
324 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
325 __CFAllocatorCustomSize
,
326 __CFAllocatorCustomMalloc
,
327 __CFAllocatorCustomCalloc
,
328 __CFAllocatorCustomValloc
,
329 __CFAllocatorCustomFree
,
330 __CFAllocatorCustomRealloc
,
331 __CFAllocatorNullDestroy
,
332 "kCFAllocatorMallocZone",
335 &__CFAllocatorZoneIntrospect
,
341 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorSystemAllocate
, __CFAllocatorSystemReallocate
, __CFAllocatorSystemDeallocate
, NULL
}
344 static struct __CFAllocator __kCFAllocatorSystemDefault
= {
345 INIT_CFRUNTIME_BASE(),
346 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
347 __CFAllocatorCustomSize
,
348 __CFAllocatorCustomMalloc
,
349 __CFAllocatorCustomCalloc
,
350 __CFAllocatorCustomValloc
,
351 __CFAllocatorCustomFree
,
352 __CFAllocatorCustomRealloc
,
353 __CFAllocatorNullDestroy
,
354 "kCFAllocatorSystemDefault",
357 &__CFAllocatorZoneIntrospect
,
363 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorSystemAllocate
, __CFAllocatorSystemReallocate
, __CFAllocatorSystemDeallocate
, NULL
}
366 static struct __CFAllocator __kCFAllocatorNull
= {
367 INIT_CFRUNTIME_BASE(),
368 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
369 __CFAllocatorNullSize
,
370 __CFAllocatorNullMalloc
,
371 __CFAllocatorNullCalloc
,
372 __CFAllocatorNullValloc
,
373 __CFAllocatorNullFree
,
374 __CFAllocatorNullRealloc
,
375 __CFAllocatorNullDestroy
,
379 &__CFAllocatorNullZoneIntrospect
,
385 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorNullAllocate
, __CFAllocatorNullReallocate
, NULL
, NULL
}
388 const CFAllocatorRef kCFAllocatorDefault
= NULL
;
389 const CFAllocatorRef kCFAllocatorSystemDefault
= &__kCFAllocatorSystemDefault
;
390 const CFAllocatorRef kCFAllocatorMalloc
= &__kCFAllocatorMalloc
;
391 const CFAllocatorRef kCFAllocatorMallocZone
= &__kCFAllocatorMallocZone
;
392 const CFAllocatorRef kCFAllocatorNull
= &__kCFAllocatorNull
;
393 const CFAllocatorRef kCFAllocatorUseContext
= (CFAllocatorRef
)0x03ab;
394 #undef kCFAllocatorSystemDefaultGCRefZero
395 #undef kCFAllocatorDefaultGCRefZero
396 const CFAllocatorRef kCFAllocatorSystemDefaultGCRefZero
= (CFAllocatorRef
)0x03ad;
397 const CFAllocatorRef kCFAllocatorDefaultGCRefZero
= (CFAllocatorRef
)0x03af;
399 static CFStringRef
__CFAllocatorCopyDescription(CFTypeRef cf
) {
400 CFAllocatorRef self
= (CFAllocatorRef
)cf
;
401 CFAllocatorRef allocator
= (kCFAllocatorUseContext
== self
->_allocator
) ? self
: self
->_allocator
;
402 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("<CFAllocator %p [%p]>{info = %p}"), cf
, allocator
, self
->_context
.info
);
403 // CF: should use copyDescription function here to describe info field
404 // remember to release value returned from copydescr function when this happens
407 CF_PRIVATE CFAllocatorRef
__CFAllocatorGetAllocator(CFTypeRef cf
) {
408 CFAllocatorRef allocator
= (CFAllocatorRef
)cf
;
409 return (kCFAllocatorUseContext
== allocator
->_allocator
) ? allocator
: allocator
->_allocator
;
412 CF_PRIVATE
void __CFAllocatorDeallocate(CFTypeRef cf
) {
413 CFAllocatorRef self
= (CFAllocatorRef
)cf
;
414 CFAllocatorRef allocator
= self
->_allocator
;
415 CFAllocatorReleaseCallBack releaseFunc
= __CFAllocatorGetReleaseFunction(&self
->_context
);
416 if (kCFAllocatorUseContext
== allocator
) {
417 /* Rather a chicken and egg problem here, so we do things
418 in the reverse order from what was done at create time. */
419 CFAllocatorDeallocateCallBack deallocateFunc
= __CFAllocatorGetDeallocateFunction(&self
->_context
);
420 void *info
= self
->_context
.info
;
421 if (NULL
!= deallocateFunc
) {
422 INVOKE_CALLBACK2(deallocateFunc
, (void *)self
, info
);
424 if (NULL
!= releaseFunc
) {
425 INVOKE_CALLBACK1(releaseFunc
, info
);
428 if (NULL
!= releaseFunc
) {
429 INVOKE_CALLBACK1(releaseFunc
, self
->_context
.info
);
431 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) CFAllocatorDeallocate(allocator
, (void *)self
);
435 static CFTypeID __kCFAllocatorTypeID
= _kCFRuntimeNotATypeID
;
437 static const CFRuntimeClass __CFAllocatorClass
= {
446 __CFAllocatorCopyDescription
449 static void _CFAllocatorSetInstanceTypeIDAndIsa(struct __CFAllocator
*memory
) {
450 _CFRuntimeSetInstanceTypeID(memory
, __kCFAllocatorTypeID
);
451 memory
->_base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
454 CF_PRIVATE
void __CFAllocatorInitialize(void) {
455 __kCFAllocatorTypeID
= _CFRuntimeRegisterClass(&__CFAllocatorClass
);
457 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorSystemDefault
);
458 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
459 __kCFAllocatorSystemDefault
._context
.info
= (kCFUseCollectableAllocator
? objc_collectableZone() : malloc_default_zone());
461 __kCFAllocatorSystemDefault
._allocator
= kCFAllocatorSystemDefault
;
463 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMalloc
);
464 __kCFAllocatorMalloc
._allocator
= kCFAllocatorSystemDefault
;
466 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
467 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMallocZone
);
468 __kCFAllocatorMallocZone
._allocator
= kCFAllocatorSystemDefault
;
469 __kCFAllocatorMallocZone
._context
.info
= malloc_default_zone();
472 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorNull
);
473 __kCFAllocatorNull
._allocator
= kCFAllocatorSystemDefault
;
476 CFTypeID
CFAllocatorGetTypeID(void) {
477 return __kCFAllocatorTypeID
;
480 CFAllocatorRef
CFAllocatorGetDefault(void) {
481 return __CFGetDefaultAllocator();
484 void CFAllocatorSetDefault(CFAllocatorRef allocator
) {
485 CFAllocatorRef current
= __CFGetDefaultAllocator();
487 if (NULL
!= allocator
) {
488 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
491 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
492 if (allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
493 return; // require allocator to this function to be an allocator
496 if (NULL
!= allocator
&& allocator
!= current
) {
497 if (current
) CFRelease(current
);
499 // We retain an extra time so that anything set as the default
500 // allocator never goes away.
502 _CFSetTSD(__CFTSDKeyAllocator
, (void *)allocator
, NULL
);
506 static CFAllocatorRef
__CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
507 struct __CFAllocator
*memory
= NULL
;
508 CFAllocatorRetainCallBack retainFunc
;
509 CFAllocatorAllocateCallBack allocateFunc
;
511 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
512 if (allocator
&& kCFAllocatorUseContext
!= allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
513 return NULL
; // require allocator to this function to be an allocator
516 retainFunc
= context
->retain
;
517 FAULT_CALLBACK((void **)&retainFunc
);
518 allocateFunc
= context
->allocate
;
519 FAULT_CALLBACK((void **)&allocateFunc
);
520 if (NULL
!= retainFunc
) {
521 retainedInfo
= (void *)INVOKE_CALLBACK1(retainFunc
, context
->info
);
523 retainedInfo
= context
->info
;
525 // We don't use _CFRuntimeCreateInstance()
526 if (kCFAllocatorUseContext
== allocator
) {
529 memory
= (struct __CFAllocator
*)INVOKE_CALLBACK3(allocateFunc
, sizeof(struct __CFAllocator
), 0, retainedInfo
);
531 if (NULL
== memory
) {
535 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
536 memory
= (struct __CFAllocator
*)CFAllocatorAllocate(allocator
, sizeof(struct __CFAllocator
), __kCFAllocatorGCObjectMemory
);
537 if (NULL
== memory
) {
540 if (__CFOASafe
) __CFSetLastAllocationEventName(memory
, "CFAllocator");
542 memset(memory
, 0, sizeof(CFRuntimeBase
));
544 memory
->_base
._rc
= 1;
546 memory
->_base
._cfinfo
[CF_RC_BITS
] = 1;
548 memory
->_base
._cfinfo
[CF_INFO_BITS
] = 0;
549 _CFAllocatorSetInstanceTypeIDAndIsa(memory
);
550 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
551 memory
->size
= __CFAllocatorCustomSize
;
552 memory
->malloc
= __CFAllocatorCustomMalloc
;
553 memory
->calloc
= __CFAllocatorCustomCalloc
;
554 memory
->valloc
= __CFAllocatorCustomValloc
;
555 memory
->free
= __CFAllocatorCustomFree
;
556 memory
->realloc
= __CFAllocatorCustomRealloc
;
557 memory
->destroy
= __CFAllocatorCustomDestroy
;
558 memory
->zone_name
= "Custom CFAllocator";
559 memory
->batch_malloc
= NULL
;
560 memory
->batch_free
= NULL
;
561 memory
->introspect
= &__CFAllocatorZoneIntrospect
;
563 memory
->memalign
= NULL
;
564 memory
->free_definite_size
= NULL
;
566 memory
->_allocator
= allocator
;
567 memory
->_context
.version
= context
->version
;
568 memory
->_context
.info
= retainedInfo
;
569 memory
->_context
.retain
= retainFunc
;
570 memory
->_context
.release
= context
->release
;
571 FAULT_CALLBACK((void **)&(memory
->_context
.release
));
572 memory
->_context
.copyDescription
= context
->copyDescription
;
573 FAULT_CALLBACK((void **)&(memory
->_context
.copyDescription
));
574 memory
->_context
.allocate
= allocateFunc
;
575 memory
->_context
.reallocate
= context
->reallocate
;
576 FAULT_CALLBACK((void **)&(memory
->_context
.reallocate
));
577 memory
->_context
.deallocate
= context
->deallocate
;
578 FAULT_CALLBACK((void **)&(memory
->_context
.deallocate
));
579 memory
->_context
.preferredSize
= context
->preferredSize
;
580 FAULT_CALLBACK((void **)&(memory
->_context
.preferredSize
));
585 CFAllocatorRef
CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
586 return __CFAllocatorCreate(allocator
, context
);
589 void *CFAllocatorAllocate(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
590 CFAllocatorAllocateCallBack allocateFunc
;
593 Boolean initialRefcountOne
= true;
594 if (NULL
== allocator
) {
595 allocator
= __CFGetDefaultAllocator();
598 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
599 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
600 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
603 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
605 if (0 == size
) return NULL
;
606 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
607 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
608 return malloc_zone_malloc((malloc_zone_t
*)allocator
, size
);
611 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
612 newptr
= auto_zone_allocate_object((auto_zone_t
*)allocator
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), initialRefcountOne
, false);
615 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
617 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, size
, hint
, allocator
->_context
.info
);
623 void *CFAllocatorReallocate(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
) {
624 CFAllocatorAllocateCallBack allocateFunc
;
625 CFAllocatorReallocateCallBack reallocateFunc
;
626 CFAllocatorDeallocateCallBack deallocateFunc
;
630 allocator
= kCFAllocatorSystemDefault
;
632 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
633 } else if (NULL
== allocator
) {
634 allocator
= __CFGetDefaultAllocator();
637 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
638 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
639 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
642 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
644 if (NULL
== ptr
&& 0 < newsize
) {
645 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
646 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
647 return malloc_zone_malloc((malloc_zone_t
*)allocator
, newsize
);
651 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
653 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, newsize
, hint
, allocator
->_context
.info
);
657 if (NULL
!= ptr
&& 0 == newsize
) {
658 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
659 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
661 size_t size
= malloc_size(ptr
);
662 if (size
) memset(ptr
, 0xCC, size
);
664 malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
668 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
669 if (NULL
!= deallocateFunc
) {
670 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
674 if (NULL
== ptr
&& 0 == newsize
) return NULL
;
675 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
676 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
677 return malloc_zone_realloc((malloc_zone_t
*)allocator
, ptr
, newsize
);
680 reallocateFunc
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
681 if (NULL
== reallocateFunc
) return NULL
;
682 newptr
= (void *)INVOKE_CALLBACK4(reallocateFunc
, ptr
, newsize
, hint
, allocator
->_context
.info
);
686 void CFAllocatorDeallocate(CFAllocatorRef allocator
, void *ptr
) {
687 CFAllocatorDeallocateCallBack deallocateFunc
;
690 allocator
= kCFAllocatorSystemDefault
;
692 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
693 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) return;
694 } else if (NULL
== allocator
) {
695 allocator
= __CFGetDefaultAllocator();
698 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
699 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
700 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
703 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
705 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
706 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
708 size_t size
= malloc_size(ptr
);
709 if (size
) memset(ptr
, 0xCC, size
);
711 return malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
714 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
715 if (NULL
!= ptr
&& NULL
!= deallocateFunc
) {
716 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
720 CFIndex
CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
721 CFAllocatorPreferredSizeCallBack prefFunc
;
725 allocator
= kCFAllocatorSystemDefault
;
727 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
728 } else if (NULL
== allocator
) {
729 allocator
= __CFGetDefaultAllocator();
732 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
733 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
734 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
737 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
739 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
740 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
741 return malloc_good_size(size
);
744 prefFunc
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
745 if (0 < size
&& NULL
!= prefFunc
) {
746 newsize
= (CFIndex
)(INVOKE_CALLBACK3(prefFunc
, size
, hint
, allocator
->_context
.info
));
748 if (newsize
< size
) newsize
= size
;
752 void CFAllocatorGetContext(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
754 allocator
= kCFAllocatorSystemDefault
;
756 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
757 } else if (NULL
== allocator
) {
758 allocator
= __CFGetDefaultAllocator();
761 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
762 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
763 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
766 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
768 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
769 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
770 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
774 context
->version
= 0;
775 context
->info
= allocator
->_context
.info
;
776 context
->retain
= __CFAllocatorGetRetainFunction(&allocator
->_context
);
777 context
->release
= __CFAllocatorGetReleaseFunction(&allocator
->_context
);
778 context
->copyDescription
= __CFAllocatorGetCopyDescriptionFunction(&allocator
->_context
);
779 context
->allocate
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
780 context
->reallocate
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
781 context
->deallocate
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
782 context
->preferredSize
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
785 CF_PRIVATE
void *_CFAllocatorAllocateGC(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
)
787 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
788 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), false, false);
790 return CFAllocatorAllocate(allocator
, size
, hint
);
793 CF_PRIVATE
void *_CFAllocatorReallocateGC(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
)
795 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
796 if (ptr
&& (newsize
== 0)) {
797 return NULL
; // equivalent to _CFAllocatorDeallocateGC.
800 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, newsize
, CF_GET_GC_MEMORY_TYPE(hint
), false, false); // eq. to _CFAllocator
803 // otherwise, auto_realloc() now preserves layout type and refCount.
804 return CFAllocatorReallocate(allocator
, ptr
, newsize
, hint
);
807 CF_PRIVATE
void _CFAllocatorDeallocateGC(CFAllocatorRef allocator
, void *ptr
)
809 // when running GC, don't deallocate.
810 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) CFAllocatorDeallocate(allocator
, ptr
);
813 // -------- -------- -------- -------- -------- -------- -------- --------
816 CFRange
__CFRangeMake(CFIndex loc
, CFIndex len
) {
818 range
.location
= loc
;
828 static struct __CFNull __kCFNull
= {
829 INIT_CFRUNTIME_BASE()
831 const CFNullRef kCFNull
= &__kCFNull
;
833 static CFStringRef
__CFNullCopyDescription(CFTypeRef cf
) {
834 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFNull %p [%p]>"), cf
, CFGetAllocator(cf
));
837 static CFStringRef
__CFNullCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
838 return (CFStringRef
)CFRetain(CFSTR("null"));
841 static void __CFNullDeallocate(CFTypeRef cf
) {
842 CFAssert(false, __kCFLogAssertion
, "Deallocated CFNull!");
845 static CFTypeID __kCFNullTypeID
= _kCFRuntimeNotATypeID
;
847 static const CFRuntimeClass __CFNullClass
= {
855 __CFNullCopyFormattingDescription
,
856 __CFNullCopyDescription
859 CF_PRIVATE
void __CFNullInitialize(void) {
860 __kCFNullTypeID
= _CFRuntimeRegisterClass(&__CFNullClass
);
861 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNull
, __kCFNullTypeID
);
864 CFTypeID
CFNullGetTypeID(void) {
865 return __kCFNullTypeID
;
868 void CFCollection_non_gc_storage_error(void) { }
871 void _CFRuntimeSetCFMPresent(void *addr
) {
875 // void __HALT(void);
877 /* Keep this assembly at the bottom of the source file! */
880 extern void __HALT() {
883 #elif defined(__i386__) || defined(__x86_64__)
884 #if defined(_MSC_VER)