__private_extern__ const void *__CFTypeCollectionRetain(CFAllocatorRef allocator, const void *ptr) { CFTypeRef cf = (CFTypeRef)ptr; // only collections allocated in the GC zone can opt-out of reference counting. if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { if (CFTYPE_IS_OBJC(cf)) return cf; // do nothing for OBJC objects. if (auto_zone_is_valid_pointer(__CFCollectableZone, ptr)) { CFRuntimeClass *cfClass = __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]; if (cfClass->version & _kCFRuntimeResourcefulObject) { // GC: If this a CF object in the GC heap that is marked resourceful, then // it must be retained keep it alive in a CF collection. // We're basically inlining CFRetain() here, to avoid an extra heap membership test. auto_zone_retain(__CFCollectableZone, (void*)cf); } else ; // don't retain normal CF objects return cf; } else { // support constant CFTypeRef objects. #if __LP64__ uint32_t lowBits = ((CFRuntimeBase *)cf)->_rc; #else uint32_t lowBits = ((CFRuntimeBase *)cf)->_cfinfo[CF_RC_BITS]; #endif if (lowBits == 0) return cf; // complain about non-GC objects in GC containers. CFLog(kCFLogLevelWarning, CFSTR("storing a non-GC object %p in a GC collection, break on CFCollection_non_gc_storage_error to debug."), cf); CFCollection_non_gc_storage_error(); // XXX should halt, except Patrick is using this somewhere. // HALT; } } return CFRetain(cf); }
void ruby_xfree(void *ptr) { if (ptr != NULL) { auto_zone_retain(__auto_zone, ptr); malloc_zone_free(__auto_zone, ptr); } }
CFTypeRef CFRetain(CFTypeRef cf) { if (CF_IS_COLLECTABLE(cf)) { // always honor CFRetain's with a GC-visible retain. auto_zone_retain(__CFCollectableZone, (void*)cf); return cf; } CFTYPE_OBJC_FUNCDISPATCH0(CFTypeRef, cf, "retain"); if (cf) __CFGenericAssertIsCF(cf); return _CFRetain(cf); }
uint32_t CFClass::cleanupObject(intptr_t op, CFTypeRef cf, bool &zap) { // the default is to not throw away the object zap = false; bool isGC = CF_IS_COLLECTABLE(cf); uint32_t currentCount; SecCFObject *obj = SecCFObject::optional(cf); uint32_t oldCount; currentCount = obj->updateRetainCount(op, &oldCount); if (isGC) { auto_zone_t* zone = objc_collectableZone(); if (op == -1 && oldCount == 0) { auto_zone_release(zone, (void*) cf); } else if (op == 1 && oldCount == 0 && currentCount == 1) { auto_zone_retain(zone, (void*) cf); } else if (op == -1 && oldCount == 1 && currentCount == 0) { /* To prevent accidental resurrection, just pull it out of the cache. */ obj->aboutToDestruct(); auto_zone_release(zone, (void*) cf); } else if (op == 0) { return currentCount; } return 0; } if (op == 0) { return currentCount; } else if (currentCount == 0) { // we may not be able to delete if the caller has active children if (obj->mayDelete()) { finalizeType(cf); zap = true; // ask the caller to release the mutex and zap the object return 0; } else { return currentCount; } } else { return 0; } }