Skip to content

Commit 2b0a2c5

Browse files
committed
Change the young generation to 'not visited'. WIP
1 parent 1629d2c commit 2b0a2c5

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

Include/internal/pycore_object.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,8 @@ static inline void _PyObject_GC_TRACK(
470470
PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
471471
_PyGCHead_SET_NEXT(last, gc);
472472
_PyGCHead_SET_PREV(gc, last);
473-
/* Young objects will be moved into the visited space during GC, so set the bit here */
474-
gc->_gc_next = ((uintptr_t)generation0) | (uintptr_t)interp->gc.visited_space;
473+
uintptr_t not_visited = 1 ^ interp->gc.visited_space;
474+
gc->_gc_next = ((uintptr_t)generation0) | not_visited;
475475
generation0->_gc_prev = (uintptr_t)gc;
476476
#endif
477477
}

Python/gc.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ typedef struct _gc_runtime_state GCState;
2424
#endif
2525

2626
// Define this when debugging the GC
27-
// #define GC_EXTRA_DEBUG
27+
#define GC_EXTRA_DEBUG
2828

2929

3030
#define GC_NEXT _PyGCHead_NEXT
@@ -1308,6 +1308,7 @@ gc_collect_young(PyThreadState *tstate,
13081308

13091309
PyGC_Head survivors;
13101310
gc_list_init(&survivors);
1311+
gc_list_set_space(young, gcstate->visited_space);
13111312
gc_collect_region(tstate, young, &survivors, stats);
13121313
Py_ssize_t survivor_count = 0;
13131314
if (gcstate->visited_space) {
@@ -1385,6 +1386,7 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
13851386
* have been marked as visited */
13861387
assert(IS_IN_VISITED(gc, gcstate->visited_space));
13871388
PyObject *op = FROM_GC(gc);
1389+
assert(_PyObject_GC_IS_TRACKED(op));
13881390
if (_Py_IsImmortal(op)) {
13891391
PyGC_Head *next = GC_NEXT(gc);
13901392
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
14041406
static void
14051407
completed_cycle(GCState *gcstate)
14061408
{
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;
14111412
gcstate->visited_space = flip_old_space(gcstate->visited_space);
14121413
/* Make sure all young objects have old space bit set correctly */
14131414
PyGC_Head *young = &gcstate->young.head;
14141415
PyGC_Head *gc = GC_NEXT(young);
14151416
while (gc != young) {
14161417
PyGC_Head *next = GC_NEXT(gc);
1417-
gc_set_old_space(gc, gcstate->visited_space);
1418+
gc_set_old_space(gc, not_visited);
14181419
gc = next;
14191420
}
14201421
gcstate->work_to_do = 0;
@@ -1433,6 +1434,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14331434
if (scale_factor < 1) {
14341435
scale_factor = 1;
14351436
}
1437+
gc_list_set_space(&gcstate->young.head, gcstate->visited_space);
14361438
gc_list_merge(&gcstate->young.head, &increment);
14371439
gcstate->young.count = 0;
14381440
gc_list_validate_space(&increment, gcstate->visited_space);
@@ -1444,6 +1446,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14441446
PyGC_Head *gc = _PyGCHead_NEXT(not_visited);
14451447
gc_list_move(gc, &increment);
14461448
increment_size++;
1449+
assert(!_Py_IsImmortal(FROM_GC(gc)));
14471450
gc_set_old_space(gc, gcstate->visited_space);
14481451
increment_size += expand_region_transitively_reachable(&increment, gc, gcstate);
14491452
}
@@ -1465,7 +1468,6 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14651468
}
14661469
}
14671470

1468-
14691471
static void
14701472
gc_collect_full(PyThreadState *tstate,
14711473
struct gc_collection_stats *stats)
@@ -1477,9 +1479,9 @@ gc_collect_full(PyThreadState *tstate,
14771479
PyGC_Head *pending = &gcstate->old[gcstate->visited_space^1].head;
14781480
PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head;
14791481
/* merge all generations into visited */
1480-
gc_list_validate_space(young, gcstate->visited_space);
1481-
gc_list_set_space(pending, gcstate->visited_space);
14821482
gc_list_merge(young, pending);
1483+
gc_list_validate_space(pending, 1-gcstate->visited_space);
1484+
gc_list_set_space(pending, gcstate->visited_space);
14831485
gcstate->young.count = 0;
14841486
gc_list_merge(pending, visited);
14851487

@@ -1488,7 +1490,7 @@ gc_collect_full(PyThreadState *tstate,
14881490
gcstate->young.count = 0;
14891491
gcstate->old[0].count = 0;
14901492
gcstate->old[1].count = 0;
1491-
1493+
completed_cycle(gcstate);
14921494
gcstate->work_to_do = - gcstate->young.threshold * 2;
14931495
_PyGC_ClearAllFreeLists(tstate->interp);
14941496
validate_old(gcstate);
@@ -1734,9 +1736,10 @@ _PyGC_Freeze(PyInterpreterState *interp)
17341736
{
17351737
GCState *gcstate = &interp->gc;
17361738
/* The permanent_generation has its old space bit set to zero */
1737-
if (gcstate->visited_space) {
1739+
if (gcstate->visited_space == 0) {
17381740
gc_list_set_space(&gcstate->young.head, 0);
17391741
}
1742+
gc_list_validate_space(&gcstate->young.head, 0);
17401743
gc_list_merge(&gcstate->young.head, &gcstate->permanent_generation.head);
17411744
gcstate->young.count = 0;
17421745
PyGC_Head*old0 = &gcstate->old[0].head;

0 commit comments

Comments
 (0)