void Init_PreGC(void) { auto_collection_control_t *control; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 __auto_zone = objc_collectableZone(); #else __auto_zone = auto_zone(); #endif if (__auto_zone == NULL) { rb_objc_no_gc_error(); } __nsobject = (void *)objc_getClass("NSObject"); control = auto_collection_parameters(__auto_zone); if (getenv("GC_DEBUG")) { control->log = AUTO_LOG_COLLECTIONS | AUTO_LOG_REGIONS | AUTO_LOG_UNUSUAL; } if (getenv("GC_DISABLE")) { gc_disabled = true; auto_collector_disable(__auto_zone); } }
static VALUE id2ref(VALUE obj, SEL sel, VALUE objid) { #if SIZEOF_LONG == SIZEOF_VOIDP #define NUM2PTR(x) NUM2ULONG(x) #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP #define NUM2PTR(x) NUM2ULL(x) #endif VALUE ptr; void *p0; rb_secure(4); ptr = NUM2PTR(objid); p0 = (void *)ptr; if (ptr == Qtrue) return Qtrue; if (ptr == Qfalse) return Qfalse; if (ptr == Qnil) return Qnil; if (FIXNUM_P(ptr) || SYMBOL_P(ptr)) return ptr; if (auto_zone_is_valid_pointer(auto_zone(), p0)) { auto_memory_type_t type = auto_zone_get_layout_type(__auto_zone, p0); if ((type == AUTO_OBJECT_SCANNED || type == AUTO_OBJECT_UNSCANNED) && !rb_objc_is_placeholder(p0) && (NATIVE((VALUE)p0) || (BUILTIN_TYPE(p0) < T_FIXNUM && BUILTIN_TYPE(p0) != T_ICLASS))) return (VALUE)p0; } rb_raise(rb_eRangeError, "%p is not id value", p0); }
void Init_PreGC(void) { auto_collection_control_t *control; __auto_zone = auto_zone(); if (__auto_zone == NULL) { rb_objc_no_gc_error(); } __nsobject = (void *)objc_getClass("NSObject"); control = auto_collection_parameters(__auto_zone); if (getenv("GC_DEBUG")) { control->log = AUTO_LOG_COLLECTIONS | AUTO_LOG_REGIONS | AUTO_LOG_UNUSUAL; } if (getenv("GC_DISABLE")) { gc_disabled = true; } Method m = class_getInstanceMethod((Class)objc_getClass("NSObject"), sel_registerName("finalize")); assert(m != NULL); method_setImplementation(m, (IMP)rb_obj_imp_finalize); auto_collector_disable(__auto_zone); }
__private_extern__ void weak_print_stats(void) { azone_t *azone = (azone_t *)auto_zone(); if (!azone) { fprintf(stderr, "weak table empty (GC off)\n"); return; } weak_entry_t *table = azone->weak_refs_table; if (!table) { fprintf(stderr, "weak table empty\n"); return; } unsigned chainlen = 0; unsigned chaincount = 0; unsigned chain = 0; unsigned chainmax = 0; unsigned table_size = azone->max_weak_refs; unsigned start; unsigned i; // find the start of some chain for (start = 0; start < azone->max_weak_refs; start++) { weak_entry_t *entry = table + start; if (! entry->referent) break; } for ( ; start < azone->max_weak_refs; start++) { weak_entry_t *entry = table + start; if (entry->referent) break; } if (start == azone->max_weak_refs) { fprintf(stderr, "weak table empty\n"); return; } // add up all chains i = start; do { weak_entry_t *entry = table + i; if (entry->referent) chain++; else if (chain) { if (chain > chainmax) chainmax = chain; chainlen += chain; chaincount++; chain = 0; } i++; if (i == table_size) i = 0; } while (i != start); fprintf(stderr, "weak table %u/%u used, %.1g avg / %u max chain\n", chainlen, azone->max_weak_refs, chaincount ? chainlen/(double)chaincount : 0.0, chainmax); }