📄 alloc.c
字号:
GC_clear_marks();# ifdef SAVE_CALL_CHAIN GC_save_callers(GC_last_stack);# endif GC_is_full_gc = TRUE; if (!GC_stopped_mark(stop_func)) { if (!GC_incremental) { /* We're partially done and have no way to complete or use */ /* current work. Reestablish invariants as cheaply as */ /* possible. */ GC_invalidate_mark_state(); GC_unpromote_black_lists(); } /* else we claim the world is already still consistent. We'll */ /* finish incrementally. */ return(FALSE); } GC_finish_collection(); if (GC_print_stats) { GET_TIME(current_time); GC_log_printf("Complete collection took %lu msecs\n", MS_TIME_DIFF(current_time,start_time)); } return(TRUE);}/* * Perform n units of garbage collection work. A unit is intended to touch * roughly GC_RATE pages. Every once in a while, we do more than that. * This needs to be a fairly large number with our current incremental * GC strategy, since otherwise we allocate too much during GC, and the * cleanup gets expensive. */# define GC_RATE 10 # define MAX_PRIOR_ATTEMPTS 1 /* Maximum number of prior attempts at world stop marking */ /* A value of 1 means that we finish the second time, no matter */ /* how long it takes. Doesn't count the initial root scan */ /* for a full GC. */int GC_deficit = 0; /* The number of extra calls to GC_mark_some */ /* that we have made. */void GC_collect_a_little_inner(int n){ int i; if (GC_dont_gc) return; if (GC_incremental && GC_collection_in_progress()) { for (i = GC_deficit; i < GC_RATE*n; i++) { if (GC_mark_some((ptr_t)0)) { /* Need to finish a collection */# ifdef SAVE_CALL_CHAIN GC_save_callers(GC_last_stack);# endif# ifdef PARALLEL_MARK GC_wait_for_reclaim();# endif if (GC_n_attempts < MAX_PRIOR_ATTEMPTS && GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); if (!GC_stopped_mark(GC_timeout_stop_func)) { GC_n_attempts++; break; } } else { (void)GC_stopped_mark(GC_never_stop_func); } GC_finish_collection(); break; } } if (GC_deficit > 0) GC_deficit -= GC_RATE*n; if (GC_deficit < 0) GC_deficit = 0; } else { GC_maybe_gc(); }}int GC_collect_a_little(void){ int result; DCL_LOCK_STATE; LOCK(); GC_collect_a_little_inner(1); result = (int)GC_collection_in_progress(); UNLOCK(); if (!result && GC_debugging_started) GC_print_all_smashed(); return(result);}/* * Assumes lock is held, signals are disabled. * We stop the world. * If stop_func() ever returns TRUE, we may fail and return FALSE. * Increment GC_gc_no if we succeed. */GC_bool GC_stopped_mark(GC_stop_func stop_func){ unsigned i; int dummy; CLOCK_TYPE start_time, current_time; if (GC_print_stats) GET_TIME(start_time);# if defined(REGISTER_LIBRARIES_EARLY) GC_cond_register_dynamic_libraries();# endif STOP_WORLD(); IF_THREADS(GC_world_stopped = TRUE); if (GC_print_stats) { GC_log_printf("--> Marking for collection %lu ", (unsigned long)GC_gc_no + 1); GC_log_printf("after %lu allocd bytes\n", (unsigned long) GC_bytes_allocd); }# ifdef MAKE_BACK_GRAPH if (GC_print_back_height) { GC_build_back_graph(); }# endif /* Mark from all roots. */ /* Minimize junk left in my registers and on the stack */ GC_clear_a_few_frames(); GC_noop(0,0,0,0,0,0); GC_initiate_gc(); for(i = 0;;i++) { if ((*stop_func)()) { if (GC_print_stats) { GC_log_printf("Abandoned stopped marking after "); GC_log_printf("%u iterations\n", i); } GC_deficit = i; /* Give the mutator a chance. */ IF_THREADS(GC_world_stopped = FALSE); START_WORLD(); return(FALSE); } if (GC_mark_some((ptr_t)(&dummy))) break; } GC_gc_no++; if (GC_print_stats) { GC_log_printf("Collection %lu reclaimed %ld bytes", (unsigned long)GC_gc_no - 1, (long)GC_bytes_found); GC_log_printf(" ---> heapsize = %lu bytes\n", (unsigned long) GC_heapsize); /* Printf arguments may be pushed in funny places. Clear the */ /* space. */ GC_log_printf(""); } /* Check all debugged objects for consistency */ if (GC_debugging_started) { (*GC_check_heap)(); } IF_THREADS(GC_world_stopped = FALSE); START_WORLD(); if (GC_print_stats) { GET_TIME(current_time); GC_log_printf("World-stopped marking took %lu msecs\n", MS_TIME_DIFF(current_time,start_time)); } return(TRUE);}/* Set all mark bits for the free list whose first entry is q */void GC_set_fl_marks(ptr_t q){ ptr_t p; struct hblk * h, * last_h = 0; hdr *hhdr; /* gcc "might be uninitialized" warning is bogus. */ IF_PER_OBJ(size_t sz;) unsigned bit_no; for (p = q; p != 0; p = obj_link(p)){ h = HBLKPTR(p); if (h != last_h) { last_h = h; hhdr = HDR(h); IF_PER_OBJ(sz = hhdr->hb_sz;) } bit_no = MARK_BIT_NO((ptr_t)p - (ptr_t)h, sz); if (!mark_bit_from_hdr(hhdr, bit_no)) { set_mark_bit_from_hdr(hhdr, bit_no); ++hhdr -> hb_n_marks; } }}#ifdef GC_ASSERTIONS/* Check that all mark bits for the free list whose first entry is q *//* are set. */void GC_check_fl_marks(ptr_t q){ ptr_t p; for (p = q; p != 0; p = obj_link(p)){ if (!GC_is_marked(p)) { GC_err_printf("Unmarked object %p on list %p\n", p, q); ABORT("Unmarked local free list entry."); } }}#endif/* Clear all mark bits for the free list whose first entry is q *//* Decrement GC_bytes_found by number of bytes on free list. */void GC_clear_fl_marks(ptr_t q){ ptr_t p; struct hblk * h, * last_h = 0; hdr *hhdr; size_t sz; unsigned bit_no; for (p = q; p != 0; p = obj_link(p)){ h = HBLKPTR(p); if (h != last_h) { last_h = h; hhdr = HDR(h); sz = hhdr->hb_sz; /* Normally set only once. */ } bit_no = MARK_BIT_NO((ptr_t)p - (ptr_t)h, sz); if (mark_bit_from_hdr(hhdr, bit_no)) { size_t n_marks = hhdr -> hb_n_marks - 1; clear_mark_bit_from_hdr(hhdr, bit_no);# ifdef PARALLEL_MARK /* Appr. count, don't decrement to zero! */ if (0 != n_marks) { hhdr -> hb_n_marks = n_marks; }# else hhdr -> hb_n_marks = n_marks;# endif } GC_bytes_found -= sz; }}#if defined(GC_ASSERTIONS) && defined(THREADS) && defined(THREAD_LOCAL_ALLOC)extern void GC_check_tls(void);#endif/* Finish up a collection. Assumes lock is held, signals are disabled, *//* but the world is otherwise running. */void GC_finish_collection(){ CLOCK_TYPE start_time; CLOCK_TYPE finalize_time; CLOCK_TYPE done_time; # if defined(GC_ASSERTIONS) && defined(THREADS) \ && defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) /* Check that we marked some of our own data. */ /* FIXME: Add more checks. */ GC_check_tls();# endif if (GC_print_stats) GET_TIME(start_time); GC_bytes_found = 0;# if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) if (getenv("GC_PRINT_ADDRESS_MAP") != 0) { GC_print_address_map(); }# endif COND_DUMP; if (GC_find_leak) { /* Mark all objects on the free list. All objects should be */ /* marked when we're done. */ { word size; /* current object size */ unsigned kind; ptr_t q; for (kind = 0; kind < GC_n_kinds; kind++) { for (size = 1; size <= MAXOBJGRANULES; size++) { q = GC_obj_kinds[kind].ok_freelist[size]; if (q != 0) GC_set_fl_marks(q); } } } GC_start_reclaim(TRUE); /* The above just checks; it doesn't really reclaim anything. */ } GC_finalize();# ifdef STUBBORN_ALLOC GC_clean_changing_list();# endif if (GC_print_stats) GET_TIME(finalize_time); if (GC_print_back_height) {# ifdef MAKE_BACK_GRAPH GC_traverse_back_graph();# else# ifndef SMALL_CONFIG GC_err_printf("Back height not available: " "Rebuild collector with -DMAKE_BACK_GRAPH\n");# endif# endif } /* Clear free list mark bits, in case they got accidentally marked */ /* (or GC_find_leak is set and they were intentionally marked). */ /* Also subtract memory remaining from GC_bytes_found count. */ /* Note that composite objects on free list are cleared. */ /* Thus accidentally marking a free list is not a problem; only */ /* objects on the list itself will be marked, and that's fixed here. */ { word size; /* current object size */ ptr_t q; /* pointer to current object */ unsigned kind; for (kind = 0; kind < GC_n_kinds; kind++) { for (size = 1; size <= MAXOBJGRANULES; size++) { q = GC_obj_kinds[kind].ok_freelist[size]; if (q != 0) GC_clear_fl_marks(q); } } } if (GC_print_stats == VERBOSE) GC_log_printf("Bytes recovered before sweep - f.l. count = %ld\n", (long)GC_bytes_found); /* Reconstruct free lists to contain everything not marked */ GC_start_reclaim(FALSE); if (GC_print_stats) { GC_log_printf("Heap contains %lu pointer-containing " "+ %lu pointer-free reachable bytes\n", (unsigned long)GC_composite_in_use,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -