__private_extern__ CFArrayRef __CFArrayCreateCopy0(CFAllocatorRef allocator, CFArrayRef array) { CFArrayRef result; const CFArrayCallBacks *cb; struct __CFArrayBucket *buckets; CFAllocatorRef bucketsAllocator; void* bucketsBase; CFIndex numValues = CFArrayGetCount(array); CFIndex idx; if (CF_IS_OBJC(__kCFArrayTypeID, array)) { cb = &kCFTypeArrayCallBacks; } else { cb = __CFArrayGetCallBacks(array); } result = __CFArrayInit(allocator, __kCFArrayImmutable, numValues, cb); cb = __CFArrayGetCallBacks(result); // GC: use the new array's callbacks so we don't leak. buckets = __CFArrayGetBucketsPtr(result); bucketsAllocator = isStrongMemory(result) ? allocator : kCFAllocatorNull; bucketsBase = CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator) ? (void *)auto_zone_base_pointer(objc_collectableZone(), buckets) : NULL; for (idx = 0; idx < numValues; idx++) { const void *value = CFArrayGetValueAtIndex(array, idx); if (NULL != cb->retain) { value = (void *)INVOKE_CALLBACK2(cb->retain, allocator, value); } __CFAssignWithWriteBarrier((void **)&buckets->_item, (void *)value); buckets++; } __CFArraySetCount(result, numValues); return result; }
static void weak_clear_entry_no_lock(azone_t *azone, weak_entry_t *entry, uintptr_t *weak_refs_count, auto_weak_callback_block_t **head) { // clear referrers, update counters, update lists unsigned count = entry->referrers.num_allocated; unsigned index = 0; for (; index < count; ++index) { weak_referrer_t *ref = &entry->referrers.refs[index]; if (ref->referrer) { if (azone->control.log & AUTO_LOG_WEAK) malloc_printf("%s: WEAK: clearing ref to %p at %p (value was %p)\n", auto_prelude(), entry->referent, ref->referrer, *ref->referrer); if (*ref->referrer != entry->referent) { malloc_printf("__weak value %p at location %p not equal to %p and so will not be cleared\n", *ref->referrer, ref->referrer, entry->referent); void **base = (void **)auto_zone_base_pointer((auto_zone_t*)azone, ref->referrer); if (base) { auto_memory_type_t type = auto_zone_get_layout_type((auto_zone_t*)azone, base); malloc_printf("...location is %s starting at %p with first slot value %p\n", (type & AUTO_OBJECT) ? "an object" : "a data block", base, *base); } continue; } *ref->referrer = NULL; ++*weak_refs_count; if (ref->block && ref->block->callback_function && !ref->block->next) { // chain it if isn't already chained & there is a callout to call ref->block->next = *head; *head = ref->block; } } } weak_entry_remove_no_lock(azone, entry); }
__private_extern__ CFArrayRef __CFArrayCreate0(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFArrayCallBacks *callBacks) { CFArrayRef result; const CFArrayCallBacks *cb; struct __CFArrayBucket *buckets; CFAllocatorRef bucketsAllocator; void* bucketsBase; CFIndex idx; CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%d) cannot be less than zero", __PRETTY_FUNCTION__, numValues); result = __CFArrayInit(allocator, __kCFArrayImmutable, numValues, callBacks); cb = __CFArrayGetCallBacks(result); buckets = __CFArrayGetBucketsPtr(result); bucketsAllocator = isStrongMemory(result) ? allocator : kCFAllocatorNull; bucketsBase = CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator) ? (void *)auto_zone_base_pointer(objc_collectableZone(), buckets) : NULL; if (NULL != cb->retain) { for (idx = 0; idx < numValues; idx++) { __CFAssignWithWriteBarrier((void **)&buckets->_item, (void *)INVOKE_CALLBACK2(cb->retain, allocator, *values)); values++; buckets++; } } else { for (idx = 0; idx < numValues; idx++) { __CFAssignWithWriteBarrier((void **)&buckets->_item, (void *)*values); values++; buckets++; } } __CFArraySetCount(result, numValues); return result; }