2 * Copyright (c) 2015 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-2014, 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 static dispatch_once_t initOnce
;
456 dispatch_once(&initOnce
, ^{
457 __kCFAllocatorTypeID
= _CFRuntimeRegisterClass(&__CFAllocatorClass
); // initOnce covered
459 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorSystemDefault
);
460 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
461 __kCFAllocatorSystemDefault
._context
.info
= (kCFUseCollectableAllocator
? objc_collectableZone() : malloc_default_zone());
463 __kCFAllocatorSystemDefault
._allocator
= kCFAllocatorSystemDefault
;
465 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMalloc
);
466 __kCFAllocatorMalloc
._allocator
= kCFAllocatorSystemDefault
;
468 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
469 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMallocZone
);
470 __kCFAllocatorMallocZone
._allocator
= kCFAllocatorSystemDefault
;
471 __kCFAllocatorMallocZone
._context
.info
= malloc_default_zone();
474 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorNull
);
475 __kCFAllocatorNull
._allocator
= kCFAllocatorSystemDefault
;
479 CFTypeID
CFAllocatorGetTypeID(void) {
480 return __kCFAllocatorTypeID
;
483 CFAllocatorRef
CFAllocatorGetDefault(void) {
484 return __CFGetDefaultAllocator();
487 void CFAllocatorSetDefault(CFAllocatorRef allocator
) {
488 CFAllocatorRef current
= __CFGetDefaultAllocator();
490 if (NULL
!= allocator
) {
491 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
494 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
495 if (allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
496 return; // require allocator to this function to be an allocator
499 if (NULL
!= allocator
&& allocator
!= current
) {
500 if (current
) CFRelease(current
);
502 // We retain an extra time so that anything set as the default
503 // allocator never goes away.
505 _CFSetTSD(__CFTSDKeyAllocator
, (void *)allocator
, NULL
);
509 static CFAllocatorRef
__CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
510 struct __CFAllocator
*memory
= NULL
;
511 CFAllocatorRetainCallBack retainFunc
;
512 CFAllocatorAllocateCallBack allocateFunc
;
514 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
515 if (allocator
&& kCFAllocatorUseContext
!= allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
516 return NULL
; // require allocator to this function to be an allocator
519 retainFunc
= context
->retain
;
520 FAULT_CALLBACK((void **)&retainFunc
);
521 allocateFunc
= context
->allocate
;
522 FAULT_CALLBACK((void **)&allocateFunc
);
523 if (NULL
!= retainFunc
) {
524 retainedInfo
= (void *)INVOKE_CALLBACK1(retainFunc
, context
->info
);
526 retainedInfo
= context
->info
;
528 // We don't use _CFRuntimeCreateInstance()
529 if (kCFAllocatorUseContext
== allocator
) {
532 memory
= (struct __CFAllocator
*)INVOKE_CALLBACK3(allocateFunc
, sizeof(struct __CFAllocator
), 0, retainedInfo
);
534 if (NULL
== memory
) {
538 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
539 memory
= (struct __CFAllocator
*)CFAllocatorAllocate(allocator
, sizeof(struct __CFAllocator
), __kCFAllocatorGCObjectMemory
);
540 if (NULL
== memory
) {
543 if (__CFOASafe
) __CFSetLastAllocationEventName(memory
, "CFAllocator");
545 memset(memory
, 0, sizeof(CFRuntimeBase
));
547 memory
->_base
._rc
= 1;
549 memory
->_base
._cfinfo
[CF_RC_BITS
] = 1;
551 memory
->_base
._cfinfo
[CF_INFO_BITS
] = 0;
552 _CFAllocatorSetInstanceTypeIDAndIsa(memory
);
553 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
554 memory
->size
= __CFAllocatorCustomSize
;
555 memory
->malloc
= __CFAllocatorCustomMalloc
;
556 memory
->calloc
= __CFAllocatorCustomCalloc
;
557 memory
->valloc
= __CFAllocatorCustomValloc
;
558 memory
->free
= __CFAllocatorCustomFree
;
559 memory
->realloc
= __CFAllocatorCustomRealloc
;
560 memory
->destroy
= __CFAllocatorCustomDestroy
;
561 memory
->zone_name
= "Custom CFAllocator";
562 memory
->batch_malloc
= NULL
;
563 memory
->batch_free
= NULL
;
564 memory
->introspect
= &__CFAllocatorZoneIntrospect
;
566 memory
->memalign
= NULL
;
567 memory
->free_definite_size
= NULL
;
569 memory
->_allocator
= allocator
;
570 memory
->_context
.version
= context
->version
;
571 memory
->_context
.info
= retainedInfo
;
572 memory
->_context
.retain
= retainFunc
;
573 memory
->_context
.release
= context
->release
;
574 FAULT_CALLBACK((void **)&(memory
->_context
.release
));
575 memory
->_context
.copyDescription
= context
->copyDescription
;
576 FAULT_CALLBACK((void **)&(memory
->_context
.copyDescription
));
577 memory
->_context
.allocate
= allocateFunc
;
578 memory
->_context
.reallocate
= context
->reallocate
;
579 FAULT_CALLBACK((void **)&(memory
->_context
.reallocate
));
580 memory
->_context
.deallocate
= context
->deallocate
;
581 FAULT_CALLBACK((void **)&(memory
->_context
.deallocate
));
582 memory
->_context
.preferredSize
= context
->preferredSize
;
583 FAULT_CALLBACK((void **)&(memory
->_context
.preferredSize
));
588 CFAllocatorRef
CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
589 return __CFAllocatorCreate(allocator
, context
);
592 void *CFAllocatorAllocate(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
593 CFAllocatorAllocateCallBack allocateFunc
;
596 Boolean initialRefcountOne
= true;
597 if (NULL
== allocator
) {
598 allocator
= __CFGetDefaultAllocator();
601 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
602 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
603 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
606 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
608 if (0 == size
) return NULL
;
609 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
610 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
611 return malloc_zone_malloc((malloc_zone_t
*)allocator
, size
);
614 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
615 newptr
= auto_zone_allocate_object((auto_zone_t
*)allocator
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), initialRefcountOne
, false);
618 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
620 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, size
, hint
, allocator
->_context
.info
);
626 void *CFAllocatorReallocate(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
) {
627 CFAllocatorAllocateCallBack allocateFunc
;
628 CFAllocatorReallocateCallBack reallocateFunc
;
629 CFAllocatorDeallocateCallBack deallocateFunc
;
633 allocator
= kCFAllocatorSystemDefault
;
635 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
636 } else if (NULL
== allocator
) {
637 allocator
= __CFGetDefaultAllocator();
640 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
641 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
642 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
645 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
647 if (NULL
== ptr
&& 0 < newsize
) {
648 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
649 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
650 return malloc_zone_malloc((malloc_zone_t
*)allocator
, newsize
);
654 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
656 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, newsize
, hint
, allocator
->_context
.info
);
660 if (NULL
!= ptr
&& 0 == newsize
) {
661 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
662 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
664 size_t size
= malloc_size(ptr
);
665 if (size
) memset(ptr
, 0xCC, size
);
667 malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
671 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
672 if (NULL
!= deallocateFunc
) {
673 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
677 if (NULL
== ptr
&& 0 == newsize
) return NULL
;
678 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
679 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
680 return malloc_zone_realloc((malloc_zone_t
*)allocator
, ptr
, newsize
);
683 reallocateFunc
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
684 if (NULL
== reallocateFunc
) return NULL
;
685 newptr
= (void *)INVOKE_CALLBACK4(reallocateFunc
, ptr
, newsize
, hint
, allocator
->_context
.info
);
689 void CFAllocatorDeallocate(CFAllocatorRef allocator
, void *ptr
) {
690 CFAllocatorDeallocateCallBack deallocateFunc
;
693 allocator
= kCFAllocatorSystemDefault
;
695 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
696 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) return;
697 } else if (NULL
== allocator
) {
698 allocator
= __CFGetDefaultAllocator();
701 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
702 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
703 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
706 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
708 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
709 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
711 size_t size
= malloc_size(ptr
);
712 if (size
) memset(ptr
, 0xCC, size
);
714 return malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
717 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
718 if (NULL
!= ptr
&& NULL
!= deallocateFunc
) {
719 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
723 CFIndex
CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
724 CFAllocatorPreferredSizeCallBack prefFunc
;
728 allocator
= kCFAllocatorSystemDefault
;
730 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
731 } else if (NULL
== allocator
) {
732 allocator
= __CFGetDefaultAllocator();
735 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
736 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
737 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
740 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
742 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
743 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
744 return malloc_good_size(size
);
747 prefFunc
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
748 if (0 < size
&& NULL
!= prefFunc
) {
749 newsize
= (CFIndex
)(INVOKE_CALLBACK3(prefFunc
, size
, hint
, allocator
->_context
.info
));
751 if (newsize
< size
) newsize
= size
;
755 void CFAllocatorGetContext(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
757 allocator
= kCFAllocatorSystemDefault
;
759 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
760 } else if (NULL
== allocator
) {
761 allocator
= __CFGetDefaultAllocator();
764 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
765 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
766 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
769 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
771 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
772 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
773 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
777 context
->version
= 0;
778 context
->info
= allocator
->_context
.info
;
779 context
->retain
= __CFAllocatorGetRetainFunction(&allocator
->_context
);
780 context
->release
= __CFAllocatorGetReleaseFunction(&allocator
->_context
);
781 context
->copyDescription
= __CFAllocatorGetCopyDescriptionFunction(&allocator
->_context
);
782 context
->allocate
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
783 context
->reallocate
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
784 context
->deallocate
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
785 context
->preferredSize
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
788 CF_PRIVATE
void *_CFAllocatorAllocateGC(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
)
790 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
791 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), false, false);
793 return CFAllocatorAllocate(allocator
, size
, hint
);
796 CF_PRIVATE
void *_CFAllocatorReallocateGC(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
)
798 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
799 if (ptr
&& (newsize
== 0)) {
800 return NULL
; // equivalent to _CFAllocatorDeallocateGC.
803 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, newsize
, CF_GET_GC_MEMORY_TYPE(hint
), false, false); // eq. to _CFAllocator
806 // otherwise, auto_realloc() now preserves layout type and refCount.
807 return CFAllocatorReallocate(allocator
, ptr
, newsize
, hint
);
810 CF_PRIVATE
void _CFAllocatorDeallocateGC(CFAllocatorRef allocator
, void *ptr
)
812 // when running GC, don't deallocate.
813 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) CFAllocatorDeallocate(allocator
, ptr
);
816 // -------- -------- -------- -------- -------- -------- -------- --------
819 CFRange
__CFRangeMake(CFIndex loc
, CFIndex len
) {
821 range
.location
= loc
;
831 static struct __CFNull __kCFNull
= {
832 INIT_CFRUNTIME_BASE()
834 const CFNullRef kCFNull
= &__kCFNull
;
836 static CFStringRef
__CFNullCopyDescription(CFTypeRef cf
) {
837 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFNull %p [%p]>"), cf
, CFGetAllocator(cf
));
840 static CFStringRef
__CFNullCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
841 return (CFStringRef
)CFRetain(CFSTR("null"));
844 static void __CFNullDeallocate(CFTypeRef cf
) {
845 CFAssert(false, __kCFLogAssertion
, "Deallocated CFNull!");
848 static CFTypeID __kCFNullTypeID
= _kCFRuntimeNotATypeID
;
850 static const CFRuntimeClass __CFNullClass
= {
858 __CFNullCopyFormattingDescription
,
859 __CFNullCopyDescription
862 CFTypeID
CFNullGetTypeID(void) {
863 static dispatch_once_t initOnce
;
864 dispatch_once(&initOnce
, ^{
865 __kCFNullTypeID
= _CFRuntimeRegisterClass(&__CFNullClass
); // initOnce covered
866 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNull
, __kCFNullTypeID
);
868 return __kCFNullTypeID
;
871 void CFCollection_non_gc_storage_error(void) { }
874 void _CFRuntimeSetCFMPresent(void *addr
) {
878 // void __HALT(void);
880 /* Keep this assembly at the bottom of the source file! */
883 extern void __HALT() {
886 #elif defined(__i386__) || defined(__x86_64__)
887 #if defined(_MSC_VER)