void mrb_garbage_collect(mrb_state *mrb) { size_t max_limit = ~0; if (mrb->gc_disabled) return; GC_INVOKE_TIME_REPORT("mrb_garbage_collect()"); GC_TIME_START; if (mrb->gc_state == GC_STATE_SWEEP) { /* finish sweep phase */ while (mrb->gc_state != GC_STATE_NONE) { incremental_gc(mrb, max_limit); } } /* clean all black object as old */ if (is_generational(mrb)) { clear_all_old(mrb); mrb->gc_full = TRUE; } do { incremental_gc(mrb, max_limit); } while (mrb->gc_state != GC_STATE_NONE); mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio; if (is_generational(mrb)) { mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; mrb->gc_full = FALSE; } GC_TIME_STOP_AND_REPORT; }
void test_incremental_gc(void) { mrb_state *mrb = mrb_open(); size_t max = ~0, live = 0, total = 0, freed = 0; RVALUE *free; struct heap_page *page; puts("test_incremental_gc"); mrb_garbage_collect(mrb); gc_assert(mrb->gc_state == GC_STATE_NONE); incremental_gc(mrb, max); gc_assert(mrb->gc_state == GC_STATE_MARK); incremental_gc(mrb, max); gc_assert(mrb->gc_state == GC_STATE_MARK); incremental_gc(mrb, max); gc_assert(mrb->gc_state == GC_STATE_SWEEP); page = mrb->heaps; while (page) { RVALUE *p = page->objects; RVALUE *e = p + MRB_HEAP_PAGE_SIZE; while (p<e) { if (is_black(&p->as.basic)) { live++; } if (is_gray(&p->as.basic) && !is_dead(mrb, &p->as.basic)) { printf("%p\n", &p->as.basic); } p++; } page = page->next; total += MRB_HEAP_PAGE_SIZE; } gc_assert(mrb->gray_list == NULL); incremental_gc(mrb, max); gc_assert(mrb->gc_state == GC_STATE_SWEEP); incremental_gc(mrb, max); gc_assert(mrb->gc_state == GC_STATE_NONE); free = (RVALUE*)mrb->heaps->freelist; while (free) { freed++; free = (RVALUE*)free->as.free.next; } gc_assert(mrb->live == live); gc_assert(mrb->live == total-freed); mrb_close(mrb); }
static void incremental_gc_until(mrb_state *mrb, enum gc_state to_state) { do { incremental_gc(mrb, ~0); } while (mrb->gc_state != to_state); }
void mrb_incremental_gc(mrb_state *mrb) { size_t limit = 0, result = 0; if (mrb->gc_disabled) return; GC_INVOKE_TIME_REPORT; GC_TIME_START; limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio; while (result < limit) { result += incremental_gc(mrb, limit); if (mrb->gc_state == GC_STATE_NONE) break; } if (mrb->gc_state == GC_STATE_NONE) { gc_assert(mrb->live >= mrb->gc_live_after_mark); mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio; if (mrb->gc_threshold < GC_STEP_SIZE) { mrb->gc_threshold = GC_STEP_SIZE; } } else { mrb->gc_threshold = mrb->live + GC_STEP_SIZE; } GC_TIME_STOP_AND_REPORT; }
static void incremental_gc_until(mrb_state *mrb, mrb_gc *gc, mrb_gc_state to_state) { do { incremental_gc(mrb, gc, SIZE_MAX); } while (gc->state != to_state); }
static void advance_phase(mrb_state *mrb, enum gc_state to_state) { while (mrb->gc_state != to_state) { incremental_gc(mrb, ~0); } }
void mrb_incremental_gc(mrb_state *mrb) { if (mrb->gc_disabled) return; GC_INVOKE_TIME_REPORT("mrb_incremental_gc()"); GC_TIME_START; if (is_minor_gc(mrb)) { do { incremental_gc(mrb, ~0); } while (mrb->gc_state != GC_STATE_NONE); } else { size_t limit = 0, result = 0; limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio; while (result < limit) { result += incremental_gc(mrb, limit); if (mrb->gc_state == GC_STATE_NONE) break; } } if (mrb->gc_state == GC_STATE_NONE) { gc_assert(mrb->live >= mrb->gc_live_after_mark); mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio; if (mrb->gc_threshold < GC_STEP_SIZE) { mrb->gc_threshold = GC_STEP_SIZE; } if (is_major_gc(mrb)) { mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; mrb->gc_full = FALSE; } else if (is_minor_gc(mrb)) { if (mrb->live > mrb->majorgc_old_threshold) { clear_all_old(mrb); mrb->gc_full = TRUE; } } } else { mrb->gc_threshold = mrb->live + GC_STEP_SIZE; } GC_TIME_STOP_AND_REPORT; }
static void incremental_gc_step(mrb_state *mrb) { size_t limit = 0, result = 0; limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio; while (result < limit) { result += incremental_gc(mrb, limit); if (mrb->gc_state == GC_STATE_NONE) break; } mrb->gc_threshold = mrb->live + GC_STEP_SIZE; }
static void incremental_gc_step(mrb_state *mrb, mrb_gc *gc) { size_t limit = 0, result = 0; limit = (GC_STEP_SIZE/100) * gc->step_ratio; while (result < limit) { result += incremental_gc(mrb, gc, limit); if (gc->state == MRB_GC_STATE_ROOT) break; } gc->threshold = gc->live + GC_STEP_SIZE; }
void mrb_garbage_collect(mrb_state *mrb) { size_t max_limit = ~0; GC_INVOKE_TIME_REPORT; GC_TIME_START; if (mrb->gc_state == GC_STATE_SWEEP) { /* finish sweep phase */ while (mrb->gc_state != GC_STATE_NONE) { incremental_gc(mrb, max_limit); } } do { incremental_gc(mrb, max_limit); } while (mrb->gc_state != GC_STATE_NONE); mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio; GC_TIME_STOP_AND_REPORT; }
void test_incremental_gc(void) { mrb_state *mrb = mrb_open(); size_t max = ~0, live = 0, total = 0, freed = 0; RVALUE *free; struct heap_page *page; puts("test_incremental_gc"); change_gen_gc_mode(mrb, FALSE); puts(" in mrb_full_gc"); mrb_full_gc(mrb); mrb_assert(mrb->gc_state == GC_STATE_NONE); puts(" in GC_STATE_NONE"); incremental_gc(mrb, max); mrb_assert(mrb->gc_state == GC_STATE_MARK); puts(" in GC_STATE_MARK"); incremental_gc_until(mrb, GC_STATE_SWEEP); mrb_assert(mrb->gc_state == GC_STATE_SWEEP); puts(" in GC_STATE_SWEEP"); page = mrb->heaps; while (page) { RVALUE *p = page->objects; RVALUE *e = p + MRB_HEAP_PAGE_SIZE; while (p<e) { if (is_black(&p->as.basic)) { live++; } if (is_gray(&p->as.basic) && !is_dead(mrb, &p->as.basic)) { printf("%p\n", &p->as.basic); } p++; } page = page->next; total += MRB_HEAP_PAGE_SIZE; } mrb_assert(mrb->gray_list == NULL); incremental_gc(mrb, max); mrb_assert(mrb->gc_state == GC_STATE_SWEEP); incremental_gc(mrb, max); mrb_assert(mrb->gc_state == GC_STATE_NONE); free = (RVALUE*)mrb->heaps->freelist; while (free) { freed++; free = (RVALUE*)free->as.free.next; } mrb_assert(mrb->live == live); mrb_assert(mrb->live == total-freed); puts("test_incremental_gc(gen)"); incremental_gc_until(mrb, GC_STATE_SWEEP); change_gen_gc_mode(mrb, TRUE); mrb_assert(mrb->gc_full == FALSE); mrb_assert(mrb->gc_state == GC_STATE_NONE); puts(" in minor"); mrb_assert(is_minor_gc(mrb)); mrb_assert(mrb->majorgc_old_threshold > 0); mrb->majorgc_old_threshold = 0; mrb_incremental_gc(mrb); mrb_assert(mrb->gc_full == TRUE); mrb_assert(mrb->gc_state == GC_STATE_NONE); puts(" in major"); mrb_assert(is_major_gc(mrb)); do { mrb_incremental_gc(mrb); } while (mrb->gc_state != GC_STATE_NONE); mrb_assert(mrb->gc_full == FALSE); mrb_close(mrb); }