CFTypeRef CFMakeCollectable(CFTypeRef cf) { if (NULL == cf) return NULL; if (CF_IS_COLLECTABLE(cf)) { #if defined(DEBUG) CFAllocatorRef allocator = CFGetAllocator(cf); if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { CFLog(kCFLogLevelWarning, CFSTR("object %p with non-GC allocator %p passed to CFMakeCollectable."), cf, allocator); HALT; } #endif if (!CFTYPE_IS_OBJC(cf)) { CFRuntimeClass *cfClass = __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]; if (cfClass->version & (_kCFRuntimeResourcefulObject)) { // don't allow the collector to manage uncollectable objects. CFLog(kCFLogLevelWarning, CFSTR("uncollectable object %p passed to CFMakeCollectable."), cf); HALT; } } if (auto_zone_retain_count(__CFCollectableZone, cf) == 0) { CFLog(kCFLogLevelWarning, CFSTR("object %p with 0 retain-count passed to CFMakeCollectable."), cf); return cf; } auto_zone_release(__CFCollectableZone, (void *)cf); } return cf; }
CFIndex _CFGetRetainCount(CFTypeRef cf) { if (NULL == cf) return 0; if (CF_IS_COLLECTABLE(cf)) { return auto_zone_retain_count(__CFCollectableZone, cf); } uint64_t rc = __CFGetFullRetainCount(cf); return (rc < (uint64_t)LONG_MAX) ? (CFIndex)rc : (CFIndex)LONG_MAX; }
CFIndex CFGetRetainCount(CFTypeRef cf) { if (NULL == cf) return 0; if (CF_IS_COLLECTABLE(cf)) { return auto_zone_retain_count(__CFCollectableZone, cf); } CFTYPE_OBJC_FUNCDISPATCH0(CFIndex, cf, "retainCount"); __CFGenericAssertIsCF(cf); uint64_t rc = __CFGetFullRetainCount(cf); return (rc < (uint64_t)LONG_MAX) ? (CFIndex)rc : (CFIndex)LONG_MAX; }
static void print_memory_object(task_t task, void *context, unsigned type_mask, vm_range_t *ranges, unsigned range_count) { const size_t min_size = *(size_t *)context; for (vm_range_t *r = ranges, *end = ranges + range_count; r < end; r++) { const size_t size = auto_zone_size(__auto_zone, (void *)r->address); if (size >= min_size) { printf("address %p size %ld rc %d layout type ", (void *)r->address, size, auto_zone_retain_count(__auto_zone, (void *)r->address)); switch (auto_zone_get_layout_type(__auto_zone, (void *)r->address)) { case AUTO_OBJECT: printf("object (class %s)\n", class_getName(object_getClass((void *)r->address))); break; default: printf("memory\n"); break; } } } }
void rb_node_release(NODE *node) { if (node == NULL || node == (NODE *)-1) { return; } // static int c = 0; // printf("%d RELEASE %s %p\n", ++c, ruby_node_name(nd_type(node)), node); switch (nd_type(node)) { case NODE_IF: /* 1,2,3 */ case NODE_FOR: case NODE_ITER: case NODE_WHEN: case NODE_MASGN: case NODE_RESCUE: case NODE_RESBODY: case NODE_CLASS: case NODE_BLOCK_PASS: rb_node_release(node->u2.node); /* fall through */ case NODE_BLOCK: /* 1,3 */ case NODE_OPTBLOCK: case NODE_ARRAY: case NODE_ENSURE: case NODE_CALL: case NODE_DEFS: case NODE_OP_ASGN1: case NODE_ARGS: rb_node_release(node->u1.node); /* fall through */ case NODE_SUPER: /* 3 */ case NODE_FCALL: case NODE_DEFN: case NODE_ARGS_AUX: rb_node_release(node->u3.node); break; case NODE_WHILE: /* 1,2 */ case NODE_UNTIL: case NODE_AND: case NODE_OR: case NODE_CASE: case NODE_SCLASS: case NODE_DOT2: case NODE_DOT3: case NODE_FLIP2: case NODE_FLIP3: case NODE_MATCH2: case NODE_MATCH3: case NODE_OP_ASGN_OR: case NODE_OP_ASGN_AND: case NODE_MODULE: case NODE_ARGSCAT: rb_node_release(node->u1.node); /* fall through */ case NODE_FBODY: /* 2 */ case NODE_GASGN: case NODE_LASGN: case NODE_DASGN: case NODE_DASGN_CURR: case NODE_IASGN: case NODE_IASGN2: case NODE_CVASGN: case NODE_OPT_N: case NODE_EVSTR: case NODE_UNDEF: case NODE_POSTEXE: rb_node_release(node->u2.node); break; case NODE_HASH: /* 1 */ case NODE_DEFINED: case NODE_RETURN: case NODE_BREAK: case NODE_NEXT: case NODE_YIELD: case NODE_COLON2: case NODE_SPLAT: case NODE_TO_ARY: rb_node_release(node->u1.node); break; case NODE_SCOPE: /* 2,3 */ case NODE_CDECL: case NODE_OPT_ARG: rb_node_release(node->u3.node); rb_node_release(node->u2.node); break; } // c--; // Some NODE structures are apparently reused somewhere in parserland. const int count = auto_zone_retain_count(__auto_zone, node); if (count > 0) { node->u1.node = node->u2.node = node->u3.node = NULL; GC_RELEASE(node); } }