@@ -1419,28 +1419,28 @@ completed_cycle(GCState *gcstate)
14191419}
14201420
14211421void
1422- _PyGC_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space )
1422+ _PyGC_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space )
14231423{
14241424 if (op != NULL && !_Py_IsImmortal (op ) && _PyObject_IS_GC (op )) {
14251425 PyGC_Head * gc = AS_GC (op );
14261426 if (_PyObject_GC_IS_TRACKED (op ) &&
14271427 gc_old_space (gc ) != visited_space ) {
14281428 gc_flip_old_space (gc );
1429- gc_list_move (gc , reachable );
1429+ gc_list_move (gc , to );
14301430 }
14311431 }
14321432}
14331433
14341434/* TO DO -- Move this into pycore_stackref.h */
14351435
14361436void
1437- _PyFrame_MoveToReachable (_PyInterpreterFrame * frame , PyGC_Head * reachable , int visited_space )
1437+ _PyFrame_MoveUnvisited (_PyInterpreterFrame * frame , PyGC_Head * to , int visited_space )
14381438{
14391439 _PyStackRef * locals = frame -> localsplus ;
14401440 _PyStackRef * sp = frame -> stackpointer ;
1441- _PyGC_MoveToReachable (frame -> f_locals , reachable , visited_space );
1441+ _PyGC_MoveUnvisited (frame -> f_locals , to , visited_space );
14421442 PyObject * func = PyStackRef_AsPyObjectBorrow (frame -> f_funcobj );
1443- _PyGC_MoveToReachable (func , reachable , visited_space );
1443+ _PyGC_MoveUnvisited (func , to , visited_space );
14441444 while (sp > locals ) {
14451445 sp -- ;
14461446 _PyStackRef ref = * sp ;
@@ -1451,25 +1451,25 @@ _PyFrame_MoveToReachable(_PyInterpreterFrame *frame, PyGC_Head *reachable, int v
14511451 if (_PyObject_GC_IS_TRACKED (op ) &&
14521452 gc_old_space (gc ) != visited_space ) {
14531453 gc_flip_old_space (gc );
1454- gc_list_move (gc , reachable );
1454+ gc_list_move (gc , to );
14551455 }
14561456 }
14571457 }
14581458 }
14591459}
14601460
1461- extern void _PySet_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1462- extern void _PyDict_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1463- extern void _PyGen_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1464- extern void _PyAsyncGen_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1465- extern void _PyAsyncAsend_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1466- extern void _PyList_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1467- extern void _PyTuple_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1468- extern void _PyType_MoveToReachable (PyObject * op , PyGC_Head * reachable , int visited_space );
1461+ extern void _PySet_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
1462+ extern void _PyDict_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
1463+ extern void _PyGen_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
1464+ extern void _PyAsyncGen_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
1465+ extern void _PyAsyncAsend_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
1466+ extern void _PyList_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
1467+ extern void _PyTuple_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
1468+ extern void _PyType_MoveUnvisited (PyObject * op , PyGC_Head * to , int visited_space );
14691469
14701470
14711471static Py_ssize_t
1472- mark_all_reachable (PyGC_Head * reachable , PyGC_Head * visited , int visited_space )
1472+ move_all_transitively_reachable (PyGC_Head * reachable , PyGC_Head * visited , int visited_space )
14731473{
14741474 // Transitively traverse all objects from reachable, until empty
14751475 struct container_and_flag arg = {
@@ -1486,12 +1486,19 @@ mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space)
14861486 objects_marked ++ ;
14871487 PyObject * op = FROM_GC (gc );
14881488 assert (PyObject_IS_GC (op ));
1489+ assert (_PyObject_GC_IS_TRACKED (op ));
1490+ if (_Py_IsImmortal (op )) {
1491+ PyGC_Head * prev = _PyGCHead_PREV (gc );
1492+ gc_list_move (gc , & get_gc_state ()-> permanent_generation .head );
1493+ gc = prev ;
1494+ continue ;
1495+ }
14891496 switch (Py_TYPE (op )-> tp_version_tag ) {
14901497 case _Py_TYPE_VERSION_LIST :
1491- _PyList_MoveToReachable (op , reachable , visited_space );
1498+ _PyList_MoveUnvisited (op , reachable , visited_space );
14921499 break ;
14931500 case _Py_TYPE_VERSION_TUPLE :
1494- _PyTuple_MoveToReachable (op , reachable , visited_space );
1501+ _PyTuple_MoveUnvisited (op , reachable , visited_space );
14951502 break ;
14961503 case _Py_TYPE_VERSION_MODULE :
14971504 {
@@ -1507,24 +1514,24 @@ mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space)
15071514 }
15081515 /* fall through */
15091516 case _Py_TYPE_VERSION_DICT :
1510- _PyDict_MoveToReachable (op , reachable , visited_space );
1517+ _PyDict_MoveUnvisited (op , reachable , visited_space );
15111518 break ;
15121519 case _Py_TYPE_VERSION_SET :
15131520 case _Py_TYPE_VERSION_FROZEN_SET :
1514- _PySet_MoveToReachable (op , reachable , visited_space );
1521+ _PySet_MoveUnvisited (op , reachable , visited_space );
15151522 break ;
15161523 case _Py_TYPE_VERSION_ASYNC_GENERATOR :
1517- _PyAsyncGen_MoveToReachable (op , reachable , visited_space );
1524+ _PyAsyncGen_MoveUnvisited (op , reachable , visited_space );
15181525 break ;
15191526 case _Py_TYPE_VERSION_ASYNC_ASEND :
1520- _PyAsyncAsend_MoveToReachable (op , reachable , visited_space );
1527+ _PyAsyncAsend_MoveUnvisited (op , reachable , visited_space );
15211528 break ;
15221529 case _Py_TYPE_VERSION_COROUTINE :
15231530 case _Py_TYPE_VERSION_GENERATOR :
1524- _PyGen_MoveToReachable (op , reachable , visited_space );
1531+ _PyGen_MoveUnvisited (op , reachable , visited_space );
15251532 break ;
15261533 case _Py_TYPE_VERSION_TYPE :
1527- _PyType_MoveToReachable (op , reachable , visited_space );
1534+ _PyType_MoveUnvisited (op , reachable , visited_space );
15281535 break ;
15291536 default :
15301537 {
@@ -1543,19 +1550,19 @@ mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_sp
15431550 PyGC_Head reachable ;
15441551 gc_list_init (& reachable );
15451552 Py_ssize_t objects_marked = 0 ;
1546- _PyGC_MoveToReachable (interp -> sysdict , & reachable , visited_space );
1547- _PyGC_MoveToReachable (interp -> builtins , & reachable , visited_space );
1548- _PyGC_MoveToReachable (interp -> dict , & reachable , visited_space );
1553+ _PyGC_MoveUnvisited (interp -> sysdict , & reachable , visited_space );
1554+ _PyGC_MoveUnvisited (interp -> builtins , & reachable , visited_space );
1555+ _PyGC_MoveUnvisited (interp -> dict , & reachable , visited_space );
15491556 struct types_state * types = & interp -> types ;
15501557 for (int i = 0 ; i < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ; i ++ ) {
1551- _PyGC_MoveToReachable (types -> builtins .initialized [i ].tp_dict , & reachable , visited_space );
1552- _PyGC_MoveToReachable (types -> builtins .initialized [i ].tp_subclasses , & reachable , visited_space );
1558+ _PyGC_MoveUnvisited (types -> builtins .initialized [i ].tp_dict , & reachable , visited_space );
1559+ _PyGC_MoveUnvisited (types -> builtins .initialized [i ].tp_subclasses , & reachable , visited_space );
15531560 }
15541561 for (int i = 0 ; i < _Py_MAX_MANAGED_STATIC_EXT_TYPES ; i ++ ) {
1555- _PyGC_MoveToReachable (types -> for_extensions .initialized [i ].tp_dict , & reachable , visited_space );
1556- _PyGC_MoveToReachable (types -> for_extensions .initialized [i ].tp_subclasses , & reachable , visited_space );
1562+ _PyGC_MoveUnvisited (types -> for_extensions .initialized [i ].tp_dict , & reachable , visited_space );
1563+ _PyGC_MoveUnvisited (types -> for_extensions .initialized [i ].tp_subclasses , & reachable , visited_space );
15571564 }
1558- objects_marked += mark_all_reachable (& reachable , visited , visited_space );
1565+ objects_marked += move_all_transitively_reachable (& reachable , visited , visited_space );
15591566 assert (gc_list_is_empty (& reachable ));
15601567 return objects_marked + 20 ;
15611568}
@@ -1577,7 +1584,7 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b
15771584 frame = frame -> previous ;
15781585 continue ;
15791586 }
1580- _PyFrame_MoveToReachable (frame , & reachable , visited_space );
1587+ _PyFrame_MoveUnvisited (frame , & reachable , visited_space );
15811588 if (!start && frame -> visited ) {
15821589 // If this frame has already been visited, then the lower frames
15831590 // will have already been visited and will not have changed
@@ -1590,7 +1597,7 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b
15901597 ts = PyThreadState_Next (ts );
15911598 HEAD_UNLOCK (runtime );
15921599 }
1593- Py_ssize_t objects_marked = mark_all_reachable (& reachable , visited , visited_space );
1600+ Py_ssize_t objects_marked = move_all_transitively_reachable (& reachable , visited , visited_space );
15941601 assert (gc_list_is_empty (& reachable ));
15951602 return objects_marked ;
15961603}
@@ -1662,12 +1669,12 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
16621669 }
16631670 PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
16641671 PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
1665- PyGC_Head increment ;
1666- gc_list_init (& increment );
16671672 Py_ssize_t objects_marked = mark_stacks (tstate -> interp , visited , gcstate -> visited_space , false);
16681673 GC_STAT_ADD (1 , objects_transitively_reachable , objects_marked );
16691674 gcstate -> work_to_do -= objects_marked ;
16701675 gc_list_set_space (& gcstate -> young .head , gcstate -> visited_space );
1676+ PyGC_Head increment ;
1677+ gc_list_init (& increment );
16711678 gc_list_merge (& gcstate -> young .head , & increment );
16721679 gc_list_validate_space (& increment , gcstate -> visited_space );
16731680 Py_ssize_t increment_size = 0 ;
0 commit comments