@@ -24,7 +24,7 @@ typedef struct _gc_runtime_state GCState;
24
24
#endif
25
25
26
26
// Define this when debugging the GC
27
- // #define GC_EXTRA_DEBUG
27
+ #define GC_EXTRA_DEBUG
28
28
29
29
30
30
#define GC_NEXT _PyGCHead_NEXT
@@ -1308,6 +1308,7 @@ gc_collect_young(PyThreadState *tstate,
1308
1308
1309
1309
PyGC_Head survivors ;
1310
1310
gc_list_init (& survivors );
1311
+ gc_list_set_space (young , gcstate -> visited_space );
1311
1312
gc_collect_region (tstate , young , & survivors , stats );
1312
1313
Py_ssize_t survivor_count = 0 ;
1313
1314
if (gcstate -> visited_space ) {
@@ -1385,6 +1386,7 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
1385
1386
* have been marked as visited */
1386
1387
assert (IS_IN_VISITED (gc , gcstate -> visited_space ));
1387
1388
PyObject * op = FROM_GC (gc );
1389
+ assert (_PyObject_GC_IS_TRACKED (op ));
1388
1390
if (_Py_IsImmortal (op )) {
1389
1391
PyGC_Head * next = GC_NEXT (gc );
1390
1392
gc_list_move (gc , & get_gc_state ()-> permanent_generation .head );
@@ -1404,17 +1406,16 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
1404
1406
static void
1405
1407
completed_cycle (GCState * gcstate )
1406
1408
{
1407
- #ifdef Py_DEBUG
1408
- PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
1409
- assert (gc_list_is_empty (not_visited ));
1410
- #endif
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 ;
1411
1412
gcstate -> visited_space = flip_old_space (gcstate -> visited_space );
1412
1413
/* Make sure all young objects have old space bit set correctly */
1413
1414
PyGC_Head * young = & gcstate -> young .head ;
1414
1415
PyGC_Head * gc = GC_NEXT (young );
1415
1416
while (gc != young ) {
1416
1417
PyGC_Head * next = GC_NEXT (gc );
1417
- gc_set_old_space (gc , gcstate -> visited_space );
1418
+ gc_set_old_space (gc , not_visited );
1418
1419
gc = next ;
1419
1420
}
1420
1421
gcstate -> work_to_do = 0 ;
@@ -1433,6 +1434,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
1433
1434
if (scale_factor < 1 ) {
1434
1435
scale_factor = 1 ;
1435
1436
}
1437
+ gc_list_set_space (& gcstate -> young .head , gcstate -> visited_space );
1436
1438
gc_list_merge (& gcstate -> young .head , & increment );
1437
1439
gcstate -> young .count = 0 ;
1438
1440
gc_list_validate_space (& increment , gcstate -> visited_space );
@@ -1444,6 +1446,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
1444
1446
PyGC_Head * gc = _PyGCHead_NEXT (not_visited );
1445
1447
gc_list_move (gc , & increment );
1446
1448
increment_size ++ ;
1449
+ assert (!_Py_IsImmortal (FROM_GC (gc )));
1447
1450
gc_set_old_space (gc , gcstate -> visited_space );
1448
1451
increment_size += expand_region_transitively_reachable (& increment , gc , gcstate );
1449
1452
}
@@ -1465,7 +1468,6 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
1465
1468
}
1466
1469
}
1467
1470
1468
-
1469
1471
static void
1470
1472
gc_collect_full (PyThreadState * tstate ,
1471
1473
struct gc_collection_stats * stats )
@@ -1477,9 +1479,9 @@ gc_collect_full(PyThreadState *tstate,
1477
1479
PyGC_Head * pending = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
1478
1480
PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
1479
1481
/* merge all generations into visited */
1480
- gc_list_validate_space (young , gcstate -> visited_space );
1481
- gc_list_set_space (pending , gcstate -> visited_space );
1482
1482
gc_list_merge (young , pending );
1483
+ gc_list_validate_space (pending , 1 - gcstate -> visited_space );
1484
+ gc_list_set_space (pending , gcstate -> visited_space );
1483
1485
gcstate -> young .count = 0 ;
1484
1486
gc_list_merge (pending , visited );
1485
1487
@@ -1488,7 +1490,7 @@ gc_collect_full(PyThreadState *tstate,
1488
1490
gcstate -> young .count = 0 ;
1489
1491
gcstate -> old [0 ].count = 0 ;
1490
1492
gcstate -> old [1 ].count = 0 ;
1491
-
1493
+ completed_cycle ( gcstate );
1492
1494
gcstate -> work_to_do = - gcstate -> young .threshold * 2 ;
1493
1495
_PyGC_ClearAllFreeLists (tstate -> interp );
1494
1496
validate_old (gcstate );
@@ -1734,9 +1736,10 @@ _PyGC_Freeze(PyInterpreterState *interp)
1734
1736
{
1735
1737
GCState * gcstate = & interp -> gc ;
1736
1738
/* The permanent_generation has its old space bit set to zero */
1737
- if (gcstate -> visited_space ) {
1739
+ if (gcstate -> visited_space == 0 ) {
1738
1740
gc_list_set_space (& gcstate -> young .head , 0 );
1739
1741
}
1742
+ gc_list_validate_space (& gcstate -> young .head , 0 );
1740
1743
gc_list_merge (& gcstate -> young .head , & gcstate -> permanent_generation .head );
1741
1744
gcstate -> young .count = 0 ;
1742
1745
PyGC_Head * old0 = & gcstate -> old [0 ].head ;
0 commit comments