@@ -474,7 +474,8 @@ update_refs(PyGC_Head *containers)
474474
475475 while (gc != containers ) {
476476 next = GC_NEXT (gc );
477- assert (!_Py_IsImmortal (FROM_GC (gc )));
477+ PyObject * op = FROM_GC (gc );
478+ assert (!_Py_IsImmortal (op ));
478479 gc_reset_refs (gc , Py_REFCNT (op ));
479480 /* Python's cyclic gc should never see an incoming refcount
480481 * of 0: if something decref'ed to 0, it should have been
@@ -1369,7 +1370,6 @@ completed_cycle(GCState *gcstate)
13691370{
13701371 PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
13711372 assert (gc_list_is_empty (not_visited ));
1372- assert (gc_list_is_empty (& gcstate -> young .head ));
13731373 gcstate -> visited_space = flip_old_space (gcstate -> visited_space );
13741374 if (gcstate -> work_to_do > 0 ) {
13751375 gcstate -> work_to_do = 0 ;
@@ -1380,20 +1380,26 @@ static void
13801380gc_collect_increment (PyThreadState * tstate , struct gc_collection_stats * stats )
13811381{
13821382 GCState * gcstate = & tstate -> interp -> gc ;
1383- assert (gc_list_is_empty (& gcstate -> young .head ));
1384- if (gcstate -> work_to_do <= 0 ) {
1385- /* No work to do */
1386- return ;
1387- }
13881383 PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
13891384 PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
13901385 PyGC_Head increment ;
13911386 gc_list_init (& increment );
1392- if (gc_list_is_empty (not_visited )) {
1393- completed_cycle (gcstate );
1394- return ;
1395- }
13961387 Py_ssize_t region_size = 0 ;
1388+ gc_list_merge (& gcstate -> young .head , & increment );
1389+ gcstate -> young .count = 0 ;
1390+ if (gcstate -> visited_space ) {
1391+ /* objects in visited space have bit set, so we set it here */
1392+ region_size = gc_list_set_space (& increment , 1 );
1393+ }
1394+ else {
1395+ PyGC_Head * gc ;
1396+ for (gc = GC_NEXT (& increment ); gc != & increment ; gc = GC_NEXT (gc )) {
1397+ #ifdef GC_DEBUG
1398+ assert (gc_old_space (gc ) == 0 );
1399+ #endif
1400+ region_size ++ ;
1401+ }
1402+ }
13971403 while (region_size < gcstate -> work_to_do ) {
13981404 if (gc_list_is_empty (not_visited )) {
13991405 break ;
@@ -1403,13 +1409,19 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14031409 gc_set_old_space (gc , gcstate -> visited_space );
14041410 region_size += expand_region_transitively_reachable (& increment , gc , gcstate );
14051411 }
1406- assert (region_size = gc_list_size (& increment ));
1412+ assert (region_size == gc_list_size (& increment ));
14071413 GC_STAT_ADD (1 , objects_queued , region_size );
14081414 PyGC_Head survivors ;
14091415 gc_list_init (& survivors );
14101416 gc_collect_region (tstate , & increment , & survivors , UNTRACK_TUPLES , stats );
14111417 gc_list_merge (& survivors , visited );
14121418 assert (gc_list_is_empty (& increment ));
1419+ Py_ssize_t survivor_count = gc_list_size (& survivors );
1420+ Py_ssize_t scale_factor = gcstate -> old [0 ].threshold ;
1421+ if (scale_factor < 1 ) {
1422+ scale_factor = 1 ;
1423+ }
1424+ gcstate -> work_to_do += survivor_count + survivor_count * SCAN_RATE_MULTIPLIER / scale_factor ;
14131425 gcstate -> work_to_do -= region_size ;
14141426 validate_old (gcstate );
14151427 add_stats (gcstate , 1 , stats );
@@ -1448,7 +1460,7 @@ gc_collect_full(PyThreadState *tstate,
14481460 gcstate -> old [1 ].count = 0 ;
14491461
14501462 gcstate -> work_to_do = - gcstate -> young .threshold * 2 ;
1451- clear_freelists (tstate -> interp );
1463+ _PyGC_ClearAllFreeLists (tstate -> interp );
14521464 validate_old (gcstate );
14531465 add_stats (gcstate , 2 , stats );
14541466}
@@ -1768,7 +1780,6 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
17681780 gc_collect_young (tstate , & stats );
17691781 break ;
17701782 case 1 :
1771- gc_collect_young (tstate , & stats );
17721783 gc_collect_increment (tstate , & stats );
17731784 break ;
17741785 case 2 :
0 commit comments