131131#endif
132132
133133#ifndef MAJOR_GC_DIAG
134- #define MAJOR_GC_DIAG 0
134+ #define MAJOR_GC_DIAG 1
135135#endif
136136#if MAJOR_GC_DIAG
137137#define major_gc_diag (...) fprintf(stderr, __VA_ARGS__)
143143 * so a serial vs. parallel-sweep run can be diffed. Compile with
144144 * -DGROWTH_DIAG=1 to enable. */
145145#ifndef GROWTH_DIAG
146- #define GROWTH_DIAG 0
146+ #define GROWTH_DIAG 1
147147#endif
148148#if GROWTH_DIAG
149149#define growth_diag (...) fprintf(stderr, __VA_ARGS__)
@@ -5495,10 +5495,9 @@ gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
54955495#endif
54965496
54975497#if GROWTH_DIAG
5498- const char * gd_decision = "no_growth_gate" ;
54995498 size_t gd_swept_initial = swept_slots ;
55005499 size_t gd_alloc_before = objspace -> heap_pages .allocatable_bytes ;
5501- size_t gd_resurrected = 0 ;
5500+ unsigned int gd_needmajor_before = gc_needs_major_flags ;
55025501#endif
55035502
55045503 if (swept_slots < min_free_slots &&
@@ -5515,10 +5514,6 @@ gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
55155514 heap_add_freepage (heap , resurrected_page , "gc_sweep_finish_heap" );
55165515
55175516 swept_slots += resurrected_page -> free_slots ;
5518- #if GROWTH_DIAG
5519- gd_resurrected ++ ;
5520- gd_decision = "resurrect" ;
5521- #endif
55225517 }
55235518
55245519 if (swept_slots < min_free_slots ) {
@@ -5528,32 +5523,31 @@ gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
55285523 objspace -> profile .count - objspace -> rgengc .last_major_gc < RVALUE_OLD_AGE ) {
55295524 if (objspace -> heap_pages .allocatable_bytes < min_free_slots * heap -> slot_size ) {
55305525 heap_allocatable_bytes_expand (objspace , heap , swept_slots , heap -> total_slots , heap -> slot_size );
5531- #if GROWTH_DIAG
5532- gd_decision = "expand" ;
5533- #endif
55345526 }
55355527 }
55365528 else if (swept_slots < min_free_slots * 7 / 8 &&
55375529 objspace -> heap_pages .allocatable_bytes < (min_free_slots * 7 / 8 - swept_slots ) * heap -> slot_size ) {
55385530 gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE ;
55395531 heap -> force_major_gc_count ++ ;
5540- #if GROWTH_DIAG
5541- gd_decision = "force_major_nofree" ;
5542- #endif
55435532 }
55445533 }
55455534 }
55465535
5536+ /* Decision is read off the observable deltas: total_slots A->B (B>A) = resurrected
5537+ * empty pages, alloc_bytes A->B (B>A) = expanded, nofree_set = scheduled forced major.
5538+ * The macro drops all args when GROWTH_DIAG is off, so the live branches stay untouched. */
55475539 growth_diag ("[growth_diag] site=sweep_finish_heap psweep=%d heap=%d reason=0x%x count=%zu "
5548- "since_major=%zd full_mark=%d total_slots=%zu swept=%zu(freed=%zu+empty=%zu) "
5549- "min_free =%zu alloc_bytes=%zu->%zu resurrected=%zu decision=%s \n" ,
5540+ "since_major=%zd full_mark=%d swept=%zu(freed=%zu+empty=%zu) min_free=%zu "
5541+ "total_slots =%zu->%zu alloc_bytes=%zu->%zu nofree_set=%d \n" ,
55505542 USE_PARALLEL_SWEEP , (int )(heap - heaps ), objspace -> profile .latest_gc_info ,
55515543 objspace -> profile .count ,
55525544 (ssize_t )(objspace -> profile .count - objspace -> rgengc .last_major_gc ),
5553- is_full_marking (objspace ), total_slots , gd_swept_initial ,
5545+ is_full_marking (objspace ), gd_swept_initial ,
55545546 heap -> freed_slots , heap -> empty_slots , min_free_slots ,
5547+ total_slots , heap -> total_slots ,
55555548 gd_alloc_before , objspace -> heap_pages .allocatable_bytes ,
5556- gd_resurrected , gd_decision );
5549+ (int )((gc_needs_major_flags & GPR_FLAG_MAJOR_BY_NOFREE ) &&
5550+ !(gd_needmajor_before & GPR_FLAG_MAJOR_BY_NOFREE )));
55575551}
55585552
55595553static void
@@ -7583,34 +7577,19 @@ gc_marks_finish(rb_objspace_t *objspace)
75837577 }
75847578
75857579#if GROWTH_DIAG
7586- const char * gd_decision ;
75877580 int gd_full_entry = full_marking ;
75887581 size_t gd_alloc_before = objspace -> heap_pages .allocatable_bytes ;
7589- if (objspace -> heap_pages .allocatable_bytes != 0 ) {
7590- gd_decision = "closed:alloc_bytes_nonzero" ;
7591- }
7592- else if (sweep_slots >= min_free_slots ) {
7593- gd_decision = "closed:enough_free" ;
7594- }
7595- else {
7596- gd_decision = "open:noop" ;
7597- }
7582+ unsigned int gd_needmajor_before = gc_needs_major_flags ;
75987583#endif
75997584
76007585 if (objspace -> heap_pages .allocatable_bytes == 0 && sweep_slots < min_free_slots ) {
76017586 if (!full_marking && sweep_slots < min_free_slots * 7 / 8 ) {
76027587 if (objspace -> profile .count - objspace -> rgengc .last_major_gc < RVALUE_OLD_AGE ) {
76037588 full_marking = TRUE;
7604- #if GROWTH_DIAG
7605- gd_decision = "promote_to_full" ;
7606- #endif
76077589 }
76087590 else {
76097591 gc_report (1 , objspace , "gc_marks_finish: next is full GC!!)\n" );
76107592 gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE ;
7611- #if GROWTH_DIAG
7612- gd_decision = "force_major_nofree" ;
7613- #endif
76147593 }
76157594 }
76167595
@@ -7623,20 +7602,21 @@ gc_marks_finish(rb_objspace_t *objspace)
76237602 /*size_t avg_slot_size = total_slots > 0 ? total_heap_bytes / total_slots : (size_t)heaps[0].slot_size;*/
76247603 /*heap_allocatable_bytes_expand(objspace, NULL, sweep_slots, total_slots, avg_slot_size);*/
76257604 heap_allocatable_bytes_expand (objspace , NULL , sweep_slots , total_slots , heaps [0 ].slot_size );
7626- #if GROWTH_DIAG
7627- if (gd_full_entry ) gd_decision = "expand" ;
7628- #endif
76297605 }
76307606 }
76317607
7608+ /* Decision is read off the observable deltas: full_mark 0->1 = promoted to major,
7609+ * alloc_bytes A->B (B>A) = expanded, nofree_set = scheduled forced major. The macro
7610+ * drops all args when GROWTH_DIAG is off, so the live branches above stay untouched. */
76327611 growth_diag ("[growth_diag] site=marks_finish psweep=%d reason=0x%x count=%zu since_major=%zd "
7633- "full_mark=%d total_slots=%zu sweep_slots=%zu min_free=%zu max_free=%zu "
7634- "freeable_pages=%zu alloc_bytes=%zu->%zu decision=%s \n" ,
7612+ "full_mark=%d->%d total_slots=%zu sweep_slots=%zu min_free=%zu max_free=%zu "
7613+ "freeable_pages=%zu alloc_bytes=%zu->%zu nofree_set=%d \n" ,
76357614 USE_PARALLEL_SWEEP , objspace -> profile .latest_gc_info , objspace -> profile .count ,
76367615 (ssize_t )(objspace -> profile .count - objspace -> rgengc .last_major_gc ),
7637- gd_full_entry , total_slots , sweep_slots , min_free_slots , max_free_slots ,
7616+ gd_full_entry , full_marking , total_slots , sweep_slots , min_free_slots , max_free_slots ,
76387617 heap_pages_freeable_pages , gd_alloc_before , objspace -> heap_pages .allocatable_bytes ,
7639- gd_decision );
7618+ (int )((gc_needs_major_flags & GPR_FLAG_MAJOR_BY_NOFREE ) &&
7619+ !(gd_needmajor_before & GPR_FLAG_MAJOR_BY_NOFREE )));
76407620
76417621 if (full_marking ) {
76427622 /* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
0 commit comments