int main(int argc, char **argv) { int i = 0; int ncollect = 2; int alloc_id = 0; int alloc_n = 100; my_cons *x = 0, *y = 0; my_cons *xp = 0, *yp = 0; smal_type *my_cons_type_mu; /* mostly_unchanging */ smal_roots_4(x, y, xp, yp); smal_debug_set_level(smal_debug_mprotect, 9); smal_debug_set_level(smal_debug_mmap, 9); my_cons_type = smal_type_for(sizeof(my_cons), my_cons_mark, 0); { smal_type_descriptor desc; memset(&desc, 0, sizeof(desc)); desc.object_size = sizeof(my_cons); desc.mark_func = my_cons_mark; desc.mostly_unchanging = 1; my_cons_type_mu = smal_type_for_desc(&desc); } fprintf(stderr, "allocing for x list\n"); for ( alloc_id = 0; alloc_id < alloc_n; ++ alloc_id ) { my_cons *c = smal_alloc(my_cons_type); c->car = (void*) 1; c->cdr = x; x = c; } my_print_stats(); { smal_stats stats = { 0 }; smal_global_stats(&stats); assert(stats.buffer_mutations == 0); } fprintf(stderr, "collecting x after list\n"); smal_collect(); my_print_stats(); { smal_stats stats = { 0 }; smal_global_stats(&stats); assert(stats.buffer_mutations == 0); } fprintf(stderr, "allocing for y list (mostly_unchanging)\n"); for ( alloc_id = 0; alloc_id < alloc_n; ++ alloc_id ) { my_cons *c = smal_alloc(my_cons_type_mu); fprintf(stderr, " c = %p\n", c); c->car = (void*) 2; c->cdr = y; y = c; } my_print_stats(); fprintf(stderr, "collecting after x and y list\n"); smal_collect(); my_print_stats(); fprintf(stderr, "mutating y list\n"); xp = x; yp = y; while ( yp ) { yp->car = xp; yp = yp->cdr; xp = xp->cdr; } { smal_stats stats = { 0 }; smal_global_stats(&stats); assert(stats.buffer_mutations == 1); } fprintf(stderr, "collecting after mutating y list\n"); smal_collect(); my_print_stats(); { smal_stats stats = { 0 }; smal_global_stats(&stats); assert(stats.buffer_mutations == 1); } fprintf(stderr, "mutating y list, again\n"); xp = x; yp = y; while ( yp ) { yp->car = xp; yp = yp->cdr; xp = xp->cdr; } { smal_stats stats = { 0 }; smal_global_stats(&stats); assert(stats.buffer_mutations == 2); } fprintf(stderr, "collecting after mutating y list, again\n"); smal_collect(); my_print_stats(); { smal_stats stats = { 0 }; smal_global_stats(&stats); assert(stats.buffer_mutations == 2); } #if 0 fprintf(stderr, "dropping some of x\n"); { my_cons *c; for ( c = x; c; c = c->cdr ) { if ( rand() % 10 > 5 ) { c->cdr = c->cdr ? ((my_cons*) c->cdr)->cdr : 0; } } } smal_collect(); my_print_stats(); fprintf(stderr, "allocing more for y list\n"); for ( alloc_id = 0; alloc_id < alloc_n; ++ alloc_id ) { my_cons *c = smal_alloc(my_cons_type); c->car = (void*) 2; c->cdr = y; y = c; } smal_collect(); my_print_stats(); #endif x = y = 0; // smal_debug_level = 9; for ( i = 0; i < ncollect; ++ i ) { smal_collect(); fprintf(stderr, "dereference all %d\n", i); } my_print_stats(); { smal_stats stats = { 0 }; smal_global_stats(&stats); assert(stats.alloc_id == alloc_n * 2); assert(stats.free_id == stats.alloc_id); assert(stats.capacity_n == 0); assert(stats.buffer_n == 0); assert(stats.buffer_mutations == 2); } smal_roots_end(); fprintf(stderr, "\n%s OK\n", argv[0]); return 0; }
tort_v _tort_m_initializer__malloc(tort_tp tort_v init) { const char *var; _tort_gc_disabled ++; // temporarily disabled till boot is finished. (void) _tort_finalization_proc; // avoid warning. var = getenv("TORT_GC"); if ( ! var || ! *var || ! strcmp(var, "0") ) var = "bdw"; #if TORT_GC_BDW if ( ! strcmp(var, "bdw") ) { GC_set_all_interior_pointers(1); GC_set_finalize_on_demand(0); GC_INIT(); _tort_gc_mode = "bdw"; _tort_malloc = GC_malloc; _tort_malloc_atomic = GC_malloc_atomic; _tort_free = GC_free; _tort_free_atomic = GC_free; /* ??? */ _tort_realloc = GC_realloc; _tort_realloc_atomic = GC_realloc; /* ??? */ _tort_gc_collect = GC_gcollect; _tort_gc_register_finalizer = _tort_gc_register_finalizer_bdw; _tort_gc_invoke_finalizers = (void*) GC_invoke_finalizers; _tort_gc_stats = _tort_gc_stats_bdw; } #endif #if TORT_GC_SMAL if ( ! strcmp(var, "smal") ) { _tort_gc_mode = "smal"; smal_debug_set_level(smal_debug_all, 1); smal_init(); _tort_gc_collect = _tort_gc_collect_smal; _tort_object_alloc = _tort_object_alloc_smal; _tort_gc_stats = _tort_gc_stats_smal; { const char *s = getenv("TORT_GC_ALLOCS_PER_GC"); allocs_per_gc = s && *s ? atoi(s) : 10000; } } #endif if ( ! strcmp(var, "malloc") ) _tort_gc_mode = "malloc"; if ( ! _tort_gc_mode ) { _tort_gc_mode = "malloc"; fprintf(stderr, " tort: WARNING: defaulting to TORT_GC=%s\n", _tort_gc_mode); } if ( ! strcmp(_tort_gc_mode, "malloc") ) fprintf(stderr, " tort: WARNING: using malloc(), NO GC!\n"); { /* assert alignments. */ void *p; assert((size_t) (p = tort_malloc(sizeof(tort_header))) % sizeof(tort_v) == 0); tort_free(p); assert((size_t) (p = tort_malloc_atomic(sizeof(tort_header))) % sizeof(tort_v) == 0); tort_free_atomic(p); } return init; }