@@ -1370,14 +1370,7 @@ static int
13701370visit_add_to_container (PyObject  * op , void  * arg )
13711371{
13721372    struct  container_and_flag  * cf  =  (struct  container_and_flag  * )arg ;
1373- #ifdef  Py_STATS 
1374-     if  (cf -> mark ) {
1375-         GC_STAT_ADD (1 , mark_visits , 1 );
1376-     }
1377-     else  {
1378-         OBJECT_STAT_INC (object_visits );
1379-     }
1380- #endif 
1373+     OBJECT_STAT_INC (object_visits );
13811374    int  visited  =  cf -> visited_space ;
13821375    assert (visited  ==  get_gc_state ()-> visited_space );
13831376    if  (!_Py_IsImmortal (op ) &&  _PyObject_IS_GC (op )) {
@@ -1482,7 +1475,7 @@ mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space)
14821475    return  arg .size ;
14831476}
14841477
1485- static  int 
1478+ static  Py_ssize_t 
14861479mark_global_roots (PyInterpreterState  * interp , PyGC_Head  * visited , int  visited_space )
14871480{
14881481    PyGC_Head  reachable ;
@@ -1491,12 +1484,21 @@ mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_sp
14911484    objects_marked  +=  move_to_reachable (interp -> sysdict , & reachable , visited_space );
14921485    objects_marked  +=  move_to_reachable (interp -> builtins , & reachable , visited_space );
14931486    objects_marked  +=  move_to_reachable (interp -> dict , & reachable , visited_space );
1487+     struct  types_state  * types  =  & interp -> types ;
1488+     for  (int  i  =  0 ; i  <  _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ; i ++ ) {
1489+         objects_marked  +=  move_to_reachable (types -> builtins .initialized [i ].tp_dict , & reachable , visited_space );
1490+         objects_marked  +=  move_to_reachable (types -> builtins .initialized [i ].tp_subclasses , & reachable , visited_space );
1491+     }
1492+     for  (int  i  =  0 ; i  <  _Py_MAX_MANAGED_STATIC_EXT_TYPES ; i ++ ) {
1493+         objects_marked  +=  move_to_reachable (types -> for_extensions .initialized [i ].tp_dict , & reachable , visited_space );
1494+         objects_marked  +=  move_to_reachable (types -> for_extensions .initialized [i ].tp_subclasses , & reachable , visited_space );
1495+     }
14941496    objects_marked  +=  mark_all_reachable (& reachable , visited , visited_space );
14951497    assert (gc_list_is_empty (& reachable ));
14961498    return  objects_marked ;
14971499}
14981500
1499- static  int 
1501+ static  Py_ssize_t 
15001502mark_stacks (PyInterpreterState  * interp , PyGC_Head  * visited , int  visited_space , bool  start )
15011503{
15021504    PyGC_Head  reachable ;
@@ -1550,7 +1552,7 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b
15501552    return  objects_marked ;
15511553}
15521554
1553- static  void 
1555+ static  Py_ssize_t 
15541556mark_at_start (PyThreadState  * tstate )
15551557{
15561558    // TO DO -- Make this incremental 
@@ -1560,12 +1562,8 @@ mark_at_start(PyThreadState *tstate)
15601562    Py_ssize_t  objects_marked  =  mark_global_roots (tstate -> interp , visited , gcstate -> visited_space );
15611563    objects_marked  +=  mark_stacks (tstate -> interp , visited , gcstate -> visited_space , true);
15621564    gcstate -> work_to_do  -=  objects_marked ;
1563- #ifdef  Py_STATS 
1564-     if  (_Py_stats ) {
1565-         GC_STAT_ADD (1 , objects_marked , objects_marked );
1566-     }
1567- #endif 
15681565    gcstate -> phase  =  GC_PHASE_COLLECT ;
1566+     return  objects_marked ;
15691567}
15701568
15711569static  void 
@@ -1575,7 +1573,9 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
15751573    GCState  * gcstate  =  & tstate -> interp -> gc ;
15761574    gcstate -> work_to_do  +=  gcstate -> young .count ;
15771575    if  (gcstate -> phase  ==  GC_PHASE_MARK ) {
1578-         mark_at_start (tstate );
1576+         Py_ssize_t  objects_marked  =  mark_at_start (tstate );
1577+         GC_STAT_ADD (1 , objects_transitively_reachable , objects_marked );
1578+         gcstate -> work_to_do  -=  objects_marked ;
15791579        return ;
15801580    }
15811581    PyGC_Head  * not_visited  =  & gcstate -> old [gcstate -> visited_space ^1 ].head ;
@@ -1586,7 +1586,9 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
15861586    if  (scale_factor  <  1 ) {
15871587        scale_factor  =  1 ;
15881588    }
1589-     gcstate -> work_to_do  -=  mark_stacks (tstate -> interp , visited , gcstate -> visited_space , false);
1589+     Py_ssize_t  objects_marked  =  mark_stacks (tstate -> interp , visited , gcstate -> visited_space , false);
1590+     GC_STAT_ADD (1 , objects_transitively_reachable , objects_marked );
1591+     gcstate -> work_to_do  -=  objects_marked ;
15901592    gc_list_set_space (& gcstate -> young .head , gcstate -> visited_space );
15911593    gc_list_merge (& gcstate -> young .head , & increment );
15921594    gcstate -> young .count  =  0 ;
@@ -1603,6 +1605,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
16031605        gc_set_old_space (gc , gcstate -> visited_space );
16041606        increment_size  +=  expand_region_transitively_reachable (& increment , gc , gcstate );
16051607    }
1608+     GC_STAT_ADD (1 , objects_not_transitively_reachable , increment_size );
16061609    gc_list_validate_space (& increment , gcstate -> visited_space );
16071610    PyGC_Head  survivors ;
16081611    gc_list_init (& survivors );
@@ -1631,16 +1634,17 @@ gc_collect_full(PyThreadState *tstate,
16311634    PyGC_Head  * young  =  & gcstate -> young .head ;
16321635    PyGC_Head  * pending  =  & gcstate -> old [gcstate -> visited_space ^1 ].head ;
16331636    PyGC_Head  * visited  =  & gcstate -> old [gcstate -> visited_space ].head ;
1634-     mark_global_roots (tstate -> interp , visited , gcstate -> visited_space );
1635-     mark_stacks (tstate -> interp , visited , gcstate -> visited_space , true);
16361637    /* merge all generations into pending */ 
16371638    gc_list_validate_space (young , 1 - gcstate -> visited_space );
16381639    gc_list_merge (young , pending );
16391640    gc_list_set_space (visited , 1 - gcstate -> visited_space );
16401641    gc_list_merge (visited , pending );
16411642    /* Mark reachable */ 
1642-     mark_global_roots (tstate -> interp , visited , gcstate -> visited_space );
1643-     mark_stacks (tstate -> interp , visited , gcstate -> visited_space , true);
1643+     Py_ssize_t  reachable  =  mark_global_roots (tstate -> interp , visited , gcstate -> visited_space );
1644+     reachable  +=  mark_stacks (tstate -> interp , visited , gcstate -> visited_space , true);
1645+     (void )reachable ;
1646+     GC_STAT_ADD (2 , objects_transitively_reachable , reachable );
1647+     GC_STAT_ADD (2 , objects_not_transitively_reachable , gc_list_size (pending ));
16441648    gcstate -> young .count  =  0 ;
16451649    gc_list_set_space (pending , gcstate -> visited_space );
16461650    gc_collect_region (tstate , pending , visited ,
0 commit comments