diff options
Diffstat (limited to 'byterun/major_gc.c')
-rw-r--r-- | byterun/major_gc.c | 112 |
1 files changed, 70 insertions, 42 deletions
diff --git a/byterun/major_gc.c b/byterun/major_gc.c index 54759b26f5..c6feeee293 100644 --- a/byterun/major_gc.c +++ b/byterun/major_gc.c @@ -50,12 +50,13 @@ extern char *caml_fl_merge; /* Defined in freelist.c. */ static char *markhp, *chunk, *limit; -static int gc_subphase; /* Subphase_main, Subphase_weak, Subphase_final */ -#define Subphase_main 10 -#define Subphase_weak 11 -#define Subphase_final 12 +int caml_gc_subphase; /* Subphase_{main,weak1,weak2,final} */ static value *weak_prev; +#ifdef DEBUG +static unsigned long major_gc_counter = 0; +#endif + static void realloc_gray_vals (void) { value *new; @@ -113,9 +114,10 @@ static void start_cycle (void) caml_gc_message (0x01, "Starting new major GC cycle\n", 0); caml_darken_all_roots(); caml_gc_phase = Phase_mark; - gc_subphase = Subphase_main; + caml_gc_subphase = Subphase_main; markhp = NULL; #ifdef DEBUG + ++ major_gc_counter; caml_heap_check (); #endif } @@ -128,6 +130,7 @@ static void mark_slice (intnat work) mlsize_t size, i; caml_gc_message (0x40, "Marking %ld words\n", work); + caml_gc_message (0x40, "Subphase = %ld\n", caml_gc_subphase); gray_vals_ptr = gray_vals_cur; while (work > 0){ if (gray_vals_ptr > gray_vals){ @@ -189,27 +192,27 @@ static void mark_slice (intnat work) chunk = caml_heap_start; markhp = chunk; limit = chunk + Chunk_size (chunk); - }else if (gc_subphase == Subphase_main){ - /* The main marking phase is over. Start removing weak pointers to - dead values. */ - gc_subphase = Subphase_weak; - weak_prev = &caml_weak_list_head; - }else if (gc_subphase == Subphase_weak){ - value cur, curfield; - mlsize_t sz, i; - header_t hd; - - cur = *weak_prev; - if (cur != (value) NULL){ - hd = Hd_val (cur); - if (Color_hd (hd) == Caml_white){ - /* The whole array is dead, remove it from the list. */ - *weak_prev = Field (cur, 0); - }else{ + }else{ + switch (caml_gc_subphase){ + case Subphase_main: { + /* The main marking phase is over. Start removing weak pointers to + dead values. */ + caml_gc_subphase = Subphase_weak1; + weak_prev = &caml_weak_list_head; + } + break; + case Subphase_weak1: { + value cur, curfield; + mlsize_t sz, i; + header_t hd; + + cur = *weak_prev; + if (cur != (value) NULL){ + hd = Hd_val (cur); sz = Wosize_hd (hd); for (i = 1; i < sz; i++){ curfield = Field (cur, i); - weak_again: + weak_again: if (curfield != caml_weak_none && Is_block (curfield) && Is_in_heap (curfield)){ if (Tag_val (curfield) == Forward_tag){ @@ -230,27 +233,52 @@ static void mark_slice (intnat work) } } weak_prev = &Field (cur, 0); + work -= Whsize_hd (hd); + }else{ + /* Subphase_weak1 is done. Start removing dead weak arrays. */ + caml_gc_subphase = Subphase_weak2; + weak_prev = &caml_weak_list_head; } - work -= Whsize_hd (hd); - }else{ - /* Subphase_weak is done. Handle finalised values. */ + } + break; + case Subphase_weak2: { + value cur; + header_t hd; + + cur = *weak_prev; + if (cur != (value) NULL){ + hd = Hd_val (cur); + if (Color_hd (hd) == Caml_white){ + /* The whole array is dead, remove it from the list. */ + *weak_prev = Field (cur, 0); + }else{ + weak_prev = &Field (cur, 0); + } + work -= 1; + }else{ + /* Subphase_weak2 is done. Handle finalised values. */ + gray_vals_cur = gray_vals_ptr; + caml_final_update (); + gray_vals_ptr = gray_vals_cur; + caml_gc_subphase = Subphase_final; + } + } + break; + case Subphase_final: { + /* Initialise the sweep phase. */ gray_vals_cur = gray_vals_ptr; - caml_final_update (); - gray_vals_ptr = gray_vals_cur; - gc_subphase = Subphase_final; + caml_gc_sweep_hp = caml_heap_start; + caml_fl_init_merge (); + caml_gc_phase = Phase_sweep; + chunk = caml_heap_start; + caml_gc_sweep_hp = chunk; + limit = chunk + Chunk_size (chunk); + work = 0; + caml_fl_size_at_phase_change = caml_fl_cur_size; + } + break; + default: Assert (0); } - }else{ - Assert (gc_subphase == Subphase_final); - /* Initialise the sweep phase. */ - gray_vals_cur = gray_vals_ptr; - caml_gc_sweep_hp = caml_heap_start; - caml_fl_init_merge (); - caml_gc_phase = Phase_sweep; - chunk = caml_heap_start; - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - work = 0; - caml_fl_size_at_phase_change = caml_fl_cur_size; } } gray_vals_cur = gray_vals_ptr; @@ -354,7 +382,7 @@ intnat caml_major_collection_slice (intnat howmuch) if (p < dp) p = dp; if (p < caml_extra_heap_resources) p = caml_extra_heap_resources; - caml_gc_message (0x40, "allocated_words = %" + caml_gc_message (0x40, "allocated_words = %" ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocated_words); caml_gc_message (0x40, "extra_heap_resources = %" |