@@ -106,7 +106,7 @@ gc_old_space(PyGC_Head *g)
106106}
107107
108108static inline int
109- flip_old_space (int space )
109+ other_space (int space )
110110{
111111 assert (space == 0 || space == 1 );
112112 return space ^ _PyGC_NEXT_MASK_OLD_SPACE_1 ;
@@ -430,18 +430,27 @@ validate_list(PyGC_Head *head, enum flagstates flags)
430430#endif
431431
432432#ifdef GC_EXTRA_DEBUG
433+
434+
433435static void
434- validate_old (GCState * gcstate )
436+ gc_list_validate_space (PyGC_Head * head , int space ) {
437+ PyGC_Head * gc = GC_NEXT (head );
438+ while (gc != head ) {
439+ assert (gc_old_space (gc ) == space );
440+ gc = GC_NEXT (gc );
441+ }
442+ }
443+
444+ static void
445+ validate_spaces (GCState * gcstate )
435446{
447+ int visited = gcstate -> visited_space ;
448+ int not_visited = other_space (visited );
449+ gc_list_validate_space (& gcstate -> young .head , not_visited );
436450 for (int space = 0 ; space < 2 ; space ++ ) {
437- PyGC_Head * head = & gcstate -> old [space ].head ;
438- PyGC_Head * gc = GC_NEXT (head );
439- while (gc != head ) {
440- PyGC_Head * next = GC_NEXT (gc );
441- assert (gc_old_space (gc ) == space );
442- gc = next ;
443- }
451+ gc_list_validate_space (& gcstate -> old [space ].head , space );
444452 }
453+ gc_list_validate_space (& gcstate -> permanent_generation .head , visited );
445454}
446455
447456static void
@@ -463,14 +472,6 @@ validate_consistent_old_space(PyGC_Head *head)
463472 assert (prev == GC_PREV (head ));
464473}
465474
466- static void
467- gc_list_validate_space (PyGC_Head * head , int space ) {
468- PyGC_Head * gc = GC_NEXT (head );
469- while (gc != head ) {
470- assert (gc_old_space (gc ) == space );
471- gc = GC_NEXT (gc );
472- }
473- }
474475
475476#else
476477#define validate_old (g ) do{}while(0)
@@ -494,7 +495,7 @@ update_refs(PyGC_Head *containers)
494495 next = GC_NEXT (gc );
495496 PyObject * op = FROM_GC (gc );
496497 if (_Py_IsImmortal (op )) {
497- gc_list_move ( gc , & get_gc_state () -> permanent_generation . head );
498+ _PyObject_GC_UNTRACK ( op );
498499 gc = next ;
499500 continue ;
500501 }
@@ -1293,6 +1294,7 @@ gc_collect_young(PyThreadState *tstate,
12931294 struct gc_collection_stats * stats )
12941295{
12951296 GCState * gcstate = & tstate -> interp -> gc ;
1297+ validate_spaces (gcstate );
12961298 PyGC_Head * young = & gcstate -> young .head ;
12971299 PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
12981300 GC_STAT_ADD (0 , collections , 1 );
@@ -1326,7 +1328,7 @@ gc_collect_young(PyThreadState *tstate,
13261328 }
13271329 (void )survivor_count ; // Silence compiler warning
13281330 gc_list_merge (& survivors , visited );
1329- validate_old (gcstate );
1331+ validate_spaces (gcstate );
13301332 gcstate -> young .count = 0 ;
13311333 gcstate -> old [gcstate -> visited_space ].count ++ ;
13321334 Py_ssize_t scale_factor = gcstate -> old [0 ].threshold ;
@@ -1335,13 +1337,14 @@ gc_collect_young(PyThreadState *tstate,
13351337 }
13361338 gcstate -> work_to_do += gcstate -> heap_size / SCAN_RATE_DIVISOR / scale_factor ;
13371339 add_stats (gcstate , 0 , stats );
1340+ validate_spaces (gcstate );
13381341}
13391342
13401343#ifndef NDEBUG
13411344static inline int
13421345IS_IN_VISITED (PyGC_Head * gc , int visited_space )
13431346{
1344- assert (visited_space == 0 || flip_old_space (visited_space ) == 0 );
1347+ assert (visited_space == 0 || other_space (visited_space ) == 0 );
13451348 return gc_old_space (gc ) == visited_space ;
13461349}
13471350#endif
@@ -1406,19 +1409,15 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
14061409static void
14071410completed_cycle (GCState * gcstate )
14081411{
1409- int not_visited = flip_old_space (gcstate -> visited_space );
1410- assert (gc_list_is_empty (& gcstate -> old [not_visited ].head ));
1411- gcstate -> visited_space = not_visited ;
1412- gcstate -> visited_space = flip_old_space (gcstate -> visited_space );
1413- /* Make sure all young objects have old space bit set correctly */
1414- PyGC_Head * young = & gcstate -> young .head ;
1415- PyGC_Head * gc = GC_NEXT (young );
1416- while (gc != young ) {
1417- PyGC_Head * next = GC_NEXT (gc );
1418- gc_set_old_space (gc , not_visited );
1419- gc = next ;
1420- }
1412+ /* Flip spaces */
1413+ int not_visited = gcstate -> visited_space ;
1414+ int visited = other_space (not_visited );
1415+ gcstate -> visited_space = visited ;
1416+ /* Make sure all objects have visited bit set correctly */
1417+ gc_list_set_space (& gcstate -> young .head , not_visited );
1418+ gc_list_set_space (& gcstate -> permanent_generation .head , visited );
14211419 gcstate -> work_to_do = 0 ;
1420+ assert (gc_list_is_empty (& gcstate -> old [visited ].head ));
14221421}
14231422
14241423static void
@@ -1461,11 +1460,11 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14611460 gcstate -> work_to_do += gcstate -> heap_size / SCAN_RATE_DIVISOR / scale_factor ;
14621461 gcstate -> work_to_do -= increment_size ;
14631462
1464- validate_old (gcstate );
14651463 add_stats (gcstate , 1 , stats );
14661464 if (gc_list_is_empty (not_visited )) {
14671465 completed_cycle (gcstate );
14681466 }
1467+ validate_spaces (gcstate );
14691468}
14701469
14711470static void
@@ -1474,7 +1473,7 @@ gc_collect_full(PyThreadState *tstate,
14741473{
14751474 GC_STAT_ADD (2 , collections , 1 );
14761475 GCState * gcstate = & tstate -> interp -> gc ;
1477- validate_old (gcstate );
1476+ validate_spaces (gcstate );
14781477 PyGC_Head * young = & gcstate -> young .head ;
14791478 PyGC_Head * pending = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
14801479 PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
@@ -1484,16 +1483,18 @@ gc_collect_full(PyThreadState *tstate,
14841483 gc_list_set_space (pending , gcstate -> visited_space );
14851484 gcstate -> young .count = 0 ;
14861485 gc_list_merge (pending , visited );
1486+ validate_spaces (gcstate );
14871487
14881488 gc_collect_region (tstate , visited , visited ,
14891489 stats );
1490+ validate_spaces (gcstate );
14901491 gcstate -> young .count = 0 ;
14911492 gcstate -> old [0 ].count = 0 ;
14921493 gcstate -> old [1 ].count = 0 ;
14931494 completed_cycle (gcstate );
14941495 gcstate -> work_to_do = - gcstate -> young .threshold * 2 ;
14951496 _PyGC_ClearAllFreeLists (tstate -> interp );
1496- validate_old (gcstate );
1497+ validate_spaces (gcstate );
14971498 add_stats (gcstate , 2 , stats );
14981499}
14991500
@@ -1735,30 +1736,32 @@ void
17351736_PyGC_Freeze (PyInterpreterState * interp )
17361737{
17371738 GCState * gcstate = & interp -> gc ;
1738- /* The permanent_generation has its old space bit set to zero */
1739- if (gcstate -> visited_space == 0 ) {
1740- gc_list_set_space (& gcstate -> young .head , 0 );
1741- }
1742- gc_list_validate_space (& gcstate -> young .head , 0 );
1739+ /* The permanent_generation must be visited */
1740+ gc_list_set_space (& gcstate -> young .head , gcstate -> visited_space );
17431741 gc_list_merge (& gcstate -> young .head , & gcstate -> permanent_generation .head );
17441742 gcstate -> young .count = 0 ;
17451743 PyGC_Head * old0 = & gcstate -> old [0 ].head ;
17461744 PyGC_Head * old1 = & gcstate -> old [1 ].head ;
1745+ if (gcstate -> visited_space ) {
1746+ gc_list_set_space (old0 , 1 );
1747+ }
1748+ else {
1749+ gc_list_set_space (old1 , 0 );
1750+ }
17471751 gc_list_merge (old0 , & gcstate -> permanent_generation .head );
17481752 gcstate -> old [0 ].count = 0 ;
1749- gc_list_set_space (old1 , 0 );
17501753 gc_list_merge (old1 , & gcstate -> permanent_generation .head );
17511754 gcstate -> old [1 ].count = 0 ;
1752- validate_old (gcstate );
1755+ validate_spaces (gcstate );
17531756}
17541757
17551758void
17561759_PyGC_Unfreeze (PyInterpreterState * interp )
17571760{
17581761 GCState * gcstate = & interp -> gc ;
17591762 gc_list_merge (& gcstate -> permanent_generation .head ,
1760- & gcstate -> old [0 ].head );
1761- validate_old (gcstate );
1763+ & gcstate -> old [gcstate -> visited_space ].head );
1764+ validate_spaces (gcstate );
17621765}
17631766
17641767Py_ssize_t
@@ -1863,7 +1866,7 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
18631866 _Py_stats -> object_stats .object_visits = 0 ;
18641867 }
18651868#endif
1866- validate_old (gcstate );
1869+ validate_spaces (gcstate );
18671870 _Py_atomic_store_int (& gcstate -> collecting , 0 );
18681871 return stats .uncollectable + stats .collected ;
18691872}
0 commit comments