@@ -1433,6 +1433,7 @@ move_to_reachable(PyObject *op, PyGC_Head *reachable, int visited_space)
14331433 return 0 ;
14341434}
14351435
1436+
14361437static Py_ssize_t
14371438mark_all_reachable (PyGC_Head * reachable , PyGC_Head * visited , int visited_space )
14381439{
@@ -1442,18 +1443,77 @@ mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space)
14421443 .visited_space = visited_space ,
14431444 .size = 0
14441445 };
1446+ Py_ssize_t objects_marked = 0 ;
14451447 while (!gc_list_is_empty (reachable )) {
14461448 PyGC_Head * gc = _PyGCHead_NEXT (reachable );
14471449 assert (gc_old_space (gc ) == visited_space );
14481450 gc_list_move (gc , visited );
14491451 PyObject * op = FROM_GC (gc );
1450- traverseproc traverse = Py_TYPE (op )-> tp_traverse ;
1451- (void ) traverse (op ,
1452- visit_add_to_container ,
1453- & arg );
1452+ assert (PyObject_IS_GC (op ));
1453+ switch (Py_TYPE (op )-> tp_version_tag ) {
1454+ case _Py_TYPE_VERSION_LIST :
1455+ {
1456+ PyListObject * o = (PyListObject * )op ;
1457+ Py_ssize_t i ;
1458+ for (i = Py_SIZE (o ); -- i >= 0 ; ) {
1459+ PyObject * item = o -> ob_item [i ];
1460+ objects_marked += move_to_reachable (item , reachable , visited_space );
1461+ }
1462+ break ;
1463+ }
1464+ case _Py_TYPE_VERSION_TUPLE :
1465+ {
1466+ PyTupleObject * o = (PyTupleObject * )op ;
1467+ for (Py_ssize_t i = Py_SIZE (o ); -- i >= 0 ; ) {
1468+ PyObject * item = o -> ob_item [i ];
1469+ objects_marked += move_to_reachable (item , reachable , visited_space );
1470+ }
1471+ break ;
1472+ }
1473+ case _Py_TYPE_VERSION_DICT :
1474+ {
1475+ PyDictObject * mp = (PyDictObject * )op ;
1476+ PyDictKeysObject * keys = mp -> ma_keys ;
1477+ Py_ssize_t i , n = keys -> dk_nentries ;
1478+ if (DK_IS_UNICODE (keys )) {
1479+ if (_PyDict_HasSplitTable (mp )) {
1480+ if (!mp -> ma_values -> embedded ) {
1481+ for (i = 0 ; i < n ; i ++ ) {
1482+ PyObject * value = mp -> ma_values -> values [i ];
1483+ objects_marked += move_to_reachable (value , reachable , visited_space );
1484+ }
1485+ }
1486+ }
1487+ else {
1488+ PyDictUnicodeEntry * entries = DK_UNICODE_ENTRIES (keys );
1489+ for (i = 0 ; i < n ; i ++ ) {
1490+ PyObject * value = entries [i ].me_value ;
1491+ objects_marked += move_to_reachable (value , reachable , visited_space );
1492+ }
1493+ }
1494+ }
1495+ else {
1496+ PyDictKeyEntry * entries = DK_ENTRIES (keys );
1497+ for (i = 0 ; i < n ; i ++ ) {
1498+ if (entries [i ].me_value != NULL ) {
1499+ PyObject * key = entries [i ].me_key ;
1500+ objects_marked += move_to_reachable (key , reachable , visited_space );
1501+ PyObject * value = entries [i ].me_value ;
1502+ objects_marked += move_to_reachable (value , reachable , visited_space );
1503+ }
1504+ }
1505+ }
1506+ break ;
1507+ }
1508+ default :
1509+ {
1510+ traverseproc traverse = Py_TYPE (op )-> tp_traverse ;
1511+ (void ) traverse (op , visit_add_to_container , & arg );
1512+ }
1513+ }
14541514 }
14551515 gc_list_validate_space (visited , visited_space );
1456- return arg .size ;
1516+ return objects_marked + arg .size ;
14571517}
14581518
14591519static Py_ssize_t
0 commit comments