@@ -1400,15 +1400,28 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
14001400
14011401/* Do bookkeeping for a completed GC cycle */
14021402static 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+ }
14121425 assert (gc_list_is_empty (& gcstate -> old [visited ].head ));
14131426 gcstate -> work_to_do = 0 ;
14141427 gcstate -> phase = GC_PHASE_MARK ;
@@ -1627,7 +1640,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
16271640
16281641 add_stats (gcstate , 1 , stats );
16291642 if (gc_list_is_empty (not_visited )) {
1630- completed_cycle (gcstate );
1643+ completed_scavenge (gcstate );
16311644 }
16321645 validate_spaces (gcstate );
16331646}
@@ -1657,7 +1670,7 @@ gc_collect_full(PyThreadState *tstate,
16571670 gcstate -> young .count = 0 ;
16581671 gcstate -> old [0 ].count = 0 ;
16591672 gcstate -> old [1 ].count = 0 ;
1660- completed_cycle (gcstate );
1673+ completed_scavenge (gcstate );
16611674 _PyGC_ClearAllFreeLists (tstate -> interp );
16621675 validate_spaces (gcstate );
16631676 add_stats (gcstate , 2 , stats );
0 commit comments