📄 alloc.c
字号:
&& !GC_reclaim_all(stop_func, FALSE)) { /* Aborted. So far everything is still consistent. */ return(FALSE); } GC_invalidate_mark_state(); /* Flush mark stack. */ GC_clear_marks();# ifdef SAVE_CALL_CHAIN_IN_GC 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 defined(CONDPRINT) if (GC_print_stats) { GET_TIME(current_time); GC_printf1("Complete collection took %lu msecs\n", MS_TIME_DIFF(current_time,start_time)); }# endif 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 needa 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(n)int n;{ register 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_IN_GC 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 GC_PROTO(()){ int result; DCL_LOCK_STATE; DISABLE_SIGNALS(); LOCK(); GC_collect_a_little_inner(1); result = (int)GC_collection_in_progress(); UNLOCK(); ENABLE_SIGNALS(); 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(stop_func)GC_stop_func stop_func;{ register int i; int dummy;# if defined(PRINTTIMES) || defined(CONDPRINT) CLOCK_TYPE start_time, current_time;# endif # ifdef PRINTTIMES GET_TIME(start_time);# endif# if defined(CONDPRINT) && !defined(PRINTTIMES) if (GC_print_stats) GET_TIME(start_time);# endif# if defined(REGISTER_LIBRARIES_EARLY) GC_cond_register_dynamic_libraries();# endif STOP_WORLD(); IF_THREADS(GC_world_stopped = TRUE);# ifdef CONDPRINT if (GC_print_stats) { GC_printf1("--> Marking for collection %lu ", (unsigned long) GC_gc_no + 1); GC_printf2("after %lu allocd bytes + %lu wasted bytes\n", (unsigned long) WORDS_TO_BYTES(GC_words_allocd), (unsigned long) WORDS_TO_BYTES(GC_words_wasted)); }# endif# 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)()) {# ifdef CONDPRINT if (GC_print_stats) { GC_printf0("Abandoned stopped marking after "); GC_printf1("%lu iterations\n", (unsigned long)i); }# endif 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++;# ifdef PRINTSTATS GC_printf2("Collection %lu reclaimed %ld bytes", (unsigned long) GC_gc_no - 1, (long)WORDS_TO_BYTES(GC_mem_found));# else# ifdef CONDPRINT if (GC_print_stats) { GC_printf1("Collection %lu finished", (unsigned long) GC_gc_no - 1); }# endif# endif /* !PRINTSTATS */# ifdef CONDPRINT if (GC_print_stats) { GC_printf1(" ---> heapsize = %lu bytes\n", (unsigned long) GC_heapsize); /* Printf arguments may be pushed in funny places. Clear the */ /* space. */ GC_printf0(""); }# endif /* CONDPRINT */ /* Check all debugged objects for consistency */ if (GC_debugging_started) { (*GC_check_heap)(); } IF_THREADS(GC_world_stopped = FALSE); START_WORLD();# ifdef PRINTTIMES GET_TIME(current_time); GC_printf1("World-stopped marking took %lu msecs\n", MS_TIME_DIFF(current_time,start_time));# else# ifdef CONDPRINT if (GC_print_stats) { GET_TIME(current_time); GC_printf1("World-stopped marking took %lu msecs\n", MS_TIME_DIFF(current_time,start_time)); }# endif# endif return(TRUE);}/* Set all mark bits for the free list whose first entry is q */#ifdef __STDC__ void GC_set_fl_marks(ptr_t q)#else void GC_set_fl_marks(q) ptr_t q;#endif{ ptr_t p; struct hblk * h, * last_h = 0; hdr *hhdr; int word_no; for (p = q; p != 0; p = obj_link(p)){ h = HBLKPTR(p); if (h != last_h) { last_h = h; hhdr = HDR(h); } word_no = (((word *)p) - ((word *)h)); set_mark_bit_from_hdr(hhdr, word_no); }}/* Clear all mark bits for the free list whose first entry is q *//* Decrement GC_mem_found by number of words on free list. */#ifdef __STDC__ void GC_clear_fl_marks(ptr_t q)#else void GC_clear_fl_marks(q) ptr_t q;#endif{ ptr_t p; struct hblk * h, * last_h = 0; hdr *hhdr; int word_no; for (p = q; p != 0; p = obj_link(p)){ h = HBLKPTR(p); if (h != last_h) { last_h = h; hhdr = HDR(h); } word_no = (((word *)p) - ((word *)h)); clear_mark_bit_from_hdr(hhdr, word_no);# ifdef GATHERSTATS GC_mem_found -= hhdr -> hb_sz;# endif }}/* Finish up a collection. Assumes lock is held, signals are disabled, *//* but the world is otherwise running. */void GC_finish_collection(){# ifdef PRINTTIMES CLOCK_TYPE start_time; CLOCK_TYPE finalize_time; CLOCK_TYPE done_time; GET_TIME(start_time); finalize_time = start_time;# endif# ifdef GATHERSTATS GC_mem_found = 0;# endif# 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. */ { register word size; /* current object size */ int kind; ptr_t q; for (kind = 0; kind < GC_n_kinds; kind++) { for (size = 1; size <= MAXOBJSZ; 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# ifdef PRINTTIMES GET_TIME(finalize_time);# endif if (GC_print_back_height) {# ifdef MAKE_BACK_GRAPH GC_traverse_back_graph();# else# ifndef SMALL_CONFIG GC_err_printf0("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_mem_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. */ { register word size; /* current object size */ register ptr_t q; /* pointer to current object */ int kind; for (kind = 0; kind < GC_n_kinds; kind++) { for (size = 1; size <= MAXOBJSZ; size++) { q = GC_obj_kinds[kind].ok_freelist[size]; if (q != 0) GC_clear_fl_marks(q); } } }# ifdef PRINTSTATS GC_printf1("Bytes recovered before sweep - f.l. count = %ld\n", (long)WORDS_TO_BYTES(GC_mem_found));# endif /* Reconstruct free lists to contain everything not marked */ GC_start_reclaim(FALSE); if (GC_is_full_gc) { GC_used_heap_size_after_full = USED_HEAP_SIZE; GC_need_full_gc = FALSE; } else { GC_need_full_gc = BYTES_TO_WORDS(USED_HEAP_SIZE - GC_used_heap_size_after_full) > min_words_allocd(); }# ifdef PRINTSTATS GC_printf2( "Immediately reclaimed %ld bytes in heap of size %lu bytes", (long)WORDS_TO_BYTES(GC_mem_found), (unsigned long)GC_heapsize);# ifdef USE_MUNMAP GC_printf1("(%lu unmapped)", GC_unmapped_bytes);# endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -