@@ -1400,15 +1400,28 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
1400
1400
1401
1401
/* Do bookkeeping for a completed GC cycle */
1402
1402
static void
1403
- completed_cycle (GCState * gcstate )
1404
- {
1405
- /* Flip spaces */
1406
- int not_visited = gcstate -> visited_space ;
1407
- int visited = other_space (not_visited );
1408
- gcstate -> visited_space = visited ;
1409
- /* Make sure all objects have visited bit set correctly */
1410
- gc_list_set_space (& gcstate -> young .head , not_visited );
1411
- gc_list_set_space (& gcstate -> permanent_generation .head , visited );
1403
+ completed_scavenge (GCState * gcstate )
1404
+ {
1405
+ /* We must observe two invariants:
1406
+ * 1. Members of the permanent generation must be marked visited.
1407
+ * 2. We cannot touch members of the permanent generation. */
1408
+ int visited ;
1409
+ if (gc_list_is_empty (& gcstate -> permanent_generation .head )) {
1410
+ /* Permanent generation is empty so we can flip spaces bit */
1411
+ int not_visited = gcstate -> visited_space ;
1412
+ visited = other_space (not_visited );
1413
+ gcstate -> visited_space = visited ;
1414
+ /* Make sure all objects have visited bit set correctly */
1415
+ gc_list_set_space (& gcstate -> young .head , not_visited );
1416
+ }
1417
+ else {
1418
+ /* We must move the objects from visited to pending space. */
1419
+ visited = gcstate -> visited_space ;
1420
+ int not_visited = other_space (visited );
1421
+ assert (gc_list_is_empty (& gcstate -> old [not_visited ].head ));
1422
+ gc_list_merge (& gcstate -> old [visited ].head , & gcstate -> old [not_visited ].head );
1423
+ gc_list_set_space (& gcstate -> old [not_visited ].head , not_visited );
1424
+ }
1412
1425
assert (gc_list_is_empty (& gcstate -> old [visited ].head ));
1413
1426
gcstate -> work_to_do = 0 ;
1414
1427
gcstate -> phase = GC_PHASE_MARK ;
@@ -1627,7 +1640,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
1627
1640
1628
1641
add_stats (gcstate , 1 , stats );
1629
1642
if (gc_list_is_empty (not_visited )) {
1630
- completed_cycle (gcstate );
1643
+ completed_scavenge (gcstate );
1631
1644
}
1632
1645
validate_spaces (gcstate );
1633
1646
}
@@ -1657,7 +1670,7 @@ gc_collect_full(PyThreadState *tstate,
1657
1670
gcstate -> young .count = 0 ;
1658
1671
gcstate -> old [0 ].count = 0 ;
1659
1672
gcstate -> old [1 ].count = 0 ;
1660
- completed_cycle (gcstate );
1673
+ completed_scavenge (gcstate );
1661
1674
_PyGC_ClearAllFreeLists (tstate -> interp );
1662
1675
validate_spaces (gcstate );
1663
1676
add_stats (gcstate , 2 , stats );
0 commit comments