@@ -474,7 +474,8 @@ update_refs(PyGC_Head *containers)
474
474
475
475
while (gc != containers ) {
476
476
next = GC_NEXT (gc );
477
- assert (!_Py_IsImmortal (FROM_GC (gc )));
477
+ PyObject * op = FROM_GC (gc );
478
+ assert (!_Py_IsImmortal (op ));
478
479
gc_reset_refs (gc , Py_REFCNT (op ));
479
480
/* Python's cyclic gc should never see an incoming refcount
480
481
* of 0: if something decref'ed to 0, it should have been
@@ -1369,7 +1370,6 @@ completed_cycle(GCState *gcstate)
1369
1370
{
1370
1371
PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
1371
1372
assert (gc_list_is_empty (not_visited ));
1372
- assert (gc_list_is_empty (& gcstate -> young .head ));
1373
1373
gcstate -> visited_space = flip_old_space (gcstate -> visited_space );
1374
1374
if (gcstate -> work_to_do > 0 ) {
1375
1375
gcstate -> work_to_do = 0 ;
@@ -1380,20 +1380,26 @@ static void
1380
1380
gc_collect_increment (PyThreadState * tstate , struct gc_collection_stats * stats )
1381
1381
{
1382
1382
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
- }
1388
1383
PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
1389
1384
PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
1390
1385
PyGC_Head increment ;
1391
1386
gc_list_init (& increment );
1392
- if (gc_list_is_empty (not_visited )) {
1393
- completed_cycle (gcstate );
1394
- return ;
1395
- }
1396
1387
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
+ }
1397
1403
while (region_size < gcstate -> work_to_do ) {
1398
1404
if (gc_list_is_empty (not_visited )) {
1399
1405
break ;
@@ -1403,13 +1409,19 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
1403
1409
gc_set_old_space (gc , gcstate -> visited_space );
1404
1410
region_size += expand_region_transitively_reachable (& increment , gc , gcstate );
1405
1411
}
1406
- assert (region_size = gc_list_size (& increment ));
1412
+ assert (region_size == gc_list_size (& increment ));
1407
1413
GC_STAT_ADD (1 , objects_queued , region_size );
1408
1414
PyGC_Head survivors ;
1409
1415
gc_list_init (& survivors );
1410
1416
gc_collect_region (tstate , & increment , & survivors , UNTRACK_TUPLES , stats );
1411
1417
gc_list_merge (& survivors , visited );
1412
1418
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 ;
1413
1425
gcstate -> work_to_do -= region_size ;
1414
1426
validate_old (gcstate );
1415
1427
add_stats (gcstate , 1 , stats );
@@ -1448,7 +1460,7 @@ gc_collect_full(PyThreadState *tstate,
1448
1460
gcstate -> old [1 ].count = 0 ;
1449
1461
1450
1462
gcstate -> work_to_do = - gcstate -> young .threshold * 2 ;
1451
- clear_freelists (tstate -> interp );
1463
+ _PyGC_ClearAllFreeLists (tstate -> interp );
1452
1464
validate_old (gcstate );
1453
1465
add_stats (gcstate , 2 , stats );
1454
1466
}
@@ -1768,7 +1780,6 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
1768
1780
gc_collect_young (tstate , & stats );
1769
1781
break ;
1770
1782
case 1 :
1771
- gc_collect_young (tstate , & stats );
1772
1783
gc_collect_increment (tstate , & stats );
1773
1784
break ;
1774
1785
case 2 :
0 commit comments