static void zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero) { GC_Weak_Box *wb; wb = gc->weak_boxes[is_late]; while (wb) { if (force_zero || !is_marked(gc, wb->val)) { wb->val = NULL; if (wb->secondary_erase) { void **p; mpage *page; /* it's possible for the secondary to be in an old generation and therefore on an mprotected page: */ page = pagemap_find_page(gc->page_maps, wb->secondary_erase); if (page->mprotected) { page->mprotected = 0; mmu_write_unprotect_page(gc->mmu, page->addr, APAGE_SIZE); GC_MP_CNT_INC(mp_mark_cnt); } p = (void **)GC_resolve2(wb->secondary_erase, gc); *(p + wb->soffset) = NULL; wb->secondary_erase = NULL; } } wb = wb->next; } /* reset, in case we have a second round */ gc->weak_boxes[is_late] = NULL; }
static int mark_ready_ephemerons(GCTYPE *gc, int inc_gen1) { GC_Ephemeron *waiting, *next, *eph; int did_one = 0, j; GC_mark_no_recur(gc, 1); for (j = 0; j < (inc_gen1 ? 1 : 2); j++) { if (inc_gen1) eph = gc->inc_ephemerons; else if (j == 0) eph = gc->ephemerons; else eph = gc->bp_ephemerons; waiting = NULL; for (; eph; eph = next) { if (inc_gen1) next = eph->inc_next; else next = eph->next; if (is_marked(gc, eph->key)) { if (!inc_gen1) eph->key = GC_resolve2(eph->key, gc); gcMARK2(eph->val, gc); gc->num_last_seen_ephemerons++; did_one = 1; if (!inc_gen1 && (j == 0) && !gc->gc_full && gc->started_incremental) { /* Need to preserve the ephemeron in the incremental list, unless it's kept in generation 1/2 nistead of promoted to generation 1. */ if (!is_in_generation_half(gc, eph)) { eph->inc_next = gc->inc_ephemerons; gc->inc_ephemerons = eph; } } } else { if (inc_gen1) { /* Ensure that we can write to the page containing the emphemeron: */ check_incremental_unprotect(gc, pagemap_find_page(gc->page_maps, eph)); eph->inc_next = waiting; } else eph->next = waiting; waiting = eph; } } if (inc_gen1) gc->inc_ephemerons = waiting; else if (j == 0) gc->ephemerons = waiting; else gc->bp_ephemerons = waiting; } GC_mark_no_recur(gc, 0); return did_one; }
static int zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc, int fuel) { GC_Weak_Array *wa; int i, num_gen0; if (from_inc) { wa = gc->inc_weak_arrays; num_gen0 = 0; } else wa = append_weak_arrays(gc->weak_arrays, gc->bp_weak_arrays, &num_gen0); if (gc->gc_full || !gc->started_incremental) num_gen0 = 0; while (wa) { void **data; data = wa->data; for (i = wa->count; i--; ) { void *p = data[i]; if (p && (force_zero || !is_marked(gc, p))) data[i] = wa->replace_val; else data[i] = GC_resolve2(p, gc); } if (fuel > 0) fuel = ((fuel > wa->count) ? (fuel - wa->count) : 0); if (num_gen0 > 0) { if (!is_in_generation_half(gc, wa)) { /* For incremental mode, preserve this weak box in the incremental list for re-checking later. */ wa->data[wa->count] = gc->inc_weak_arrays; gc->inc_weak_arrays = wa; } } if (from_inc) { GC_Weak_Array *next; next = (GC_Weak_Array *)wa->data[wa->count]; wa->data[wa->count] = gc->weak_incremental_done; wa = next; } else wa = wa->next; num_gen0--; } if (from_inc) gc->inc_weak_arrays = NULL; else { gc->weak_arrays = NULL; gc->bp_weak_arrays = NULL; } return fuel; }
inline static void clean_up_account_hooks(NewGC *gc) { AccountHook *work = gc->hooks; AccountHook *prev = NULL; while(work) { if((!work->c1 || marked(gc, work->c1)) && marked(gc, work->c2)) { work->c1 = GC_resolve2(work->c1, gc); work->c2 = GC_resolve2(work->c2, gc); prev = work; work = work->next; } else { /* remove work hook */ AccountHook *next = work->next; if(prev) prev->next = next; if(!prev) gc->hooks = next; ofm_free(work, sizeof(AccountHook)); work = next; } } }
inline static void clean_up_thread_list(NewGC *gc) { GC_Thread_Info *work = gc->thread_infos; GC_Thread_Info *prev = NULL; while(work) { if(!pagemap_find_page(gc->page_maps, work->thread) || marked(gc, work->thread)) { work->thread = GC_resolve2(work->thread, gc); prev = work; work = work->next; } else { GC_Thread_Info *next = work->next; if(prev) prev->next = next; if(!prev) gc->thread_infos = next; ofm_free(work, sizeof(GC_Thread_Info)); work = next; } } }
inline static void clean_up_owner_table(NewGC *gc) { OTEntry **owner_table = gc->owner_table; const int table_size = gc->owner_table_size; int i; for(i = 1; i < table_size; i++) if(owner_table[i]) { /* repair or delete the originator */ if(!marked(gc, owner_table[i]->originator)) { owner_table[i]->originator = NULL; } else owner_table[i]->originator = GC_resolve2(owner_table[i]->originator, gc); /* potential delete */ if(i != 1) if((owner_table[i]->memory_use == 0) && !owner_table[i]->originator) free_owner_set(gc, i); } }
static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc, int fuel) { GC_Weak_Box *wb; int num_gen0; if (from_inc) { wb = gc->inc_weak_boxes[is_late]; num_gen0 = 0; } else { wb = append_weak_boxes(gc->weak_boxes[is_late], gc->bp_weak_boxes[is_late], &num_gen0); if (gc->gc_full || !gc->started_incremental) num_gen0 = 0; } while (wb) { GC_ASSERT(is_marked(gc, wb)); if (!wb->val) { /* nothing to do */ } else if (force_zero || !is_marked(gc, wb->val)) { wb->val = NULL; if (wb->secondary_erase) { void **p; mpage *page; /* it's possible for the secondary to be in an old generation and therefore on an mprotected page: */ page = pagemap_find_page(gc->page_maps, wb->secondary_erase); if (page->mprotected) { page->mprotected = 0; mmu_write_unprotect_page(gc->mmu, page->addr, APAGE_SIZE, page_mmu_type(page), &page->mmu_src_block); page->reprotect_next = gc->reprotect_next; gc->reprotect_next = page; page->reprotect = 1; } p = (void **)GC_resolve2(wb->secondary_erase, gc); *(p + wb->soffset) = NULL; wb->secondary_erase = NULL; } } else { wb->val = GC_resolve2(wb->val, gc); } if (num_gen0 > 0) { if (!is_in_generation_half(gc, wb)) { /* For incremental mode, preserve this weak box in the incremental list for re-checking later. */ check_weak_box_not_already_in_inc_chain(wb, gc->inc_weak_boxes[wb->is_late]); wb->inc_next = gc->inc_weak_boxes[is_late]; gc->inc_weak_boxes[is_late] = wb; } } if (from_inc) { GC_Weak_Box *next; next = wb->inc_next; wb->inc_next = gc->weak_incremental_done; wb = next; } else wb = wb->next; num_gen0--; if (fuel >= 0) { if (fuel > 0) fuel--; else { GC_ASSERT(from_inc); gc->inc_weak_boxes[is_late] = wb; return 0; } } } /* reset, in case we have a second round */ if (from_inc) { gc->inc_weak_boxes[is_late] = NULL; } else { gc->weak_boxes[is_late] = NULL; gc->bp_weak_boxes[is_late] = NULL; } return fuel; }