@@ -116,6 +116,31 @@ gc_decref(PyGC_Head *g)
116116 g -> _gc_prev -= 1 << _PyGC_PREV_SHIFT ;
117117}
118118
119+ static inline uintptr_t
120+ gc_old_space (PyGC_Head * g )
121+ {
122+ return g -> _gc_prev & _PyGC_PREV_MASK_OLD_SPACE_1 ;
123+ }
124+
125+ static inline uintptr_t
126+ flip_old_space (uintptr_t space )
127+ {
128+ return space ^ _PyGC_PREV_MASK_OLD_SPACE_1 ;
129+ }
130+
131+ static inline void
132+ gc_flip_old_space (PyGC_Head * g )
133+ {
134+ g -> _gc_prev ^= _PyGC_PREV_MASK_OLD_SPACE_1 ;
135+ }
136+
137+ static inline void
138+ gc_set_old_space (PyGC_Head * g , uintptr_t space )
139+ {
140+ g -> _gc_prev &= ~_PyGC_PREV_MASK_OLD_SPACE_1 ;
141+ g -> _gc_prev |= space ;
142+ }
143+
119144/* set for debugging information */
120145#define DEBUG_STATS (1<<0) /* print collection statistics */
121146#define DEBUG_COLLECTABLE (1<<1) /* print collectable objects */
@@ -427,16 +452,16 @@ validate_list(PyGC_Head *head, enum flagstates flags)
427452static void
428453validate_old (GCState * gcstate )
429454{
430- for (uintptr_t gen = 0 ; gen < 2 ; gen ++ ) {
431- PyGC_Head * head = & gcstate -> old [gen ].head ;
455+ for (uintptr_t space = 0 ; space < 2 ; space ++ ) {
456+ PyGC_Head * head = & gcstate -> old [space ].head ;
432457 PyGC_Head * prev = head ;
433458 PyGC_Head * gc = GC_NEXT (head );
434459 while (gc != head ) {
435460 PyGC_Head * trueprev = GC_PREV (gc );
436461 PyGC_Head * truenext = (PyGC_Head * )(gc -> _gc_next & ~NEXT_MASK_UNREACHABLE );
437462 assert (truenext != NULL );
438463 assert (trueprev == prev );
439- assert ((gc -> _gc_prev & _PyGC_PREV_MASK_OLD_SPACE_1 ) == gen );
464+ assert (gc_old_space (gc ) == space );
440465 prev = gc ;
441466 gc = truenext ;
442467 }
@@ -454,7 +479,7 @@ validate_list_is_aging(PyGC_Head *head)
454479 while (gc != head ) {
455480 PyGC_Head * truenext = (PyGC_Head * )(gc -> _gc_next & ~NEXT_MASK_UNREACHABLE );
456481 assert (truenext != NULL );
457- assert ((gc -> _gc_prev & _PyGC_PREV_MASK_OLD_SPACE_1 ) == aging_flag );
482+ assert (gc_old_space (gc ) == aging_flag );
458483 prev = gc ;
459484 gc = truenext ;
460485 }
@@ -1240,25 +1265,13 @@ gc_collect_region(PyThreadState *tstate,
12401265 int untrack ,
12411266 struct gc_collection_stats * stats );
12421267
1243- static Py_ssize_t
1244- make_space0 (PyGC_Head * list )
1245- {
1246- Py_ssize_t size = 0 ;
1247- PyGC_Head * gc ;
1248- for (gc = GC_NEXT (list ); gc != list ; gc = GC_NEXT (gc )) {
1249- gc -> _gc_prev &= ~_PyGC_PREV_MASK_OLD_SPACE_1 ;
1250- size ++ ;
1251- }
1252- return size ;
1253- }
1254-
1255- static Py_ssize_t
1256- make_space1 (PyGC_Head * list )
1268+ static inline Py_ssize_t
1269+ gc_list_set_space (PyGC_Head * list , uintptr_t space )
12571270{
12581271 Py_ssize_t size = 0 ;
12591272 PyGC_Head * gc ;
12601273 for (gc = GC_NEXT (list ); gc != list ; gc = GC_NEXT (gc )) {
1261- gc -> _gc_prev |= _PyGC_PREV_MASK_OLD_SPACE_1 ;
1274+ gc_set_old_space ( gc , space ) ;
12621275 size ++ ;
12631276 }
12641277 return size ;
@@ -1285,7 +1298,7 @@ gc_collect_young(PyThreadState *tstate,
12851298 * do that here */
12861299 PyGC_Head * gc ;
12871300 for (gc = GC_NEXT (young ); gc != young ; gc = GC_NEXT (gc )) {
1288- gc -> _gc_prev |= _PyGC_PREV_MASK_OLD_SPACE_1 ;
1301+ gc_set_old_space ( gc , 1 ) ;
12891302 }
12901303 }
12911304 validate_old (gcstate );
@@ -1296,13 +1309,13 @@ gc_collect_young(PyThreadState *tstate,
12961309 Py_ssize_t surivivor_count = 0 ;
12971310 if (gcstate -> aging_space ) {
12981311 /* objects in aging space have bit set, so we set it here */
1299- surivivor_count = make_space1 (& survivors );
1312+ surivivor_count = gc_list_set_space (& survivors , 1 );
13001313 }
13011314 else {
13021315 PyGC_Head * gc ;
13031316 for (gc = GC_NEXT (& survivors ); gc != & survivors ; gc = GC_NEXT (gc )) {
13041317#ifdef GC_DEBUG
1305- assert ((gc -> _gc_prev & _PyGC_PREV_MASK_OLD_SPACE_1 ) == 0 );
1318+ assert (gc_old_space (gc ) == 0 );
13061319#endif
13071320 surivivor_count ++ ;
13081321 }
@@ -1320,21 +1333,19 @@ static void
13201333gc_collect_aging (PyThreadState * tstate ,
13211334 struct gc_collection_stats * stats )
13221335{
1323- /* For now just collect middle generation */
13241336 GCState * gcstate = & tstate -> interp -> gc ;
1337+ uintptr_t oldest_space = flip_old_space (gcstate -> aging_space );
13251338 PyGC_Head * young = & gcstate -> young .head ;
13261339 PyGC_Head * aging = & gcstate -> old [gcstate -> aging_space ].head ;
1327- PyGC_Head * oldest = & gcstate -> old [gcstate -> aging_space ^ 1 ].head ;
1340+ PyGC_Head * oldest = & gcstate -> old [oldest_space ].head ;
13281341 /* Need to tag all objects as part of oldest generation */
1329- Py_ssize_t size ;
13301342 if (gcstate -> aging_space ) {
13311343 /* No need to tag young objects */
1332- size = make_space0 (aging );
13331344 }
13341345 else {
1335- make_space1 (young );
1336- size = make_space1 (aging );
1346+ gc_list_set_space (young , 1 );
13371347 }
1348+ Py_ssize_t size = gc_list_set_space (aging , oldest_space );
13381349 /* merge young in pending before collecting */
13391350 gc_list_merge (young , aging );
13401351 gcstate -> young .count = 0 ;
@@ -1348,10 +1359,10 @@ gc_collect_aging(PyThreadState *tstate,
13481359}
13491360
13501361static inline int
1351- IS_IN_OLDEST (PyGC_Head * head , uintptr_t aging_space )
1362+ IS_IN_OLDEST (PyGC_Head * gc , uintptr_t aging_space )
13521363{
1353- assert (aging_space == 0 || aging_space == _PyGC_PREV_MASK_OLD_SPACE_1 );
1354- return ( head -> _gc_prev & _PyGC_PREV_MASK_OLD_SPACE_1 ) == ( aging_space ^ _PyGC_PREV_MASK_OLD_SPACE_1 ) ;
1364+ assert (aging_space == 0 || flip_old_space ( aging_space ) == 0 );
1365+ return gc_old_space ( gc ) != aging_space ;
13551366}
13561367
13571368struct container_and_flag {
@@ -1365,13 +1376,13 @@ visit_add_to_container(PyObject *op, void *arg)
13651376{
13661377 OBJECT_STAT_INC (object_visits );
13671378 struct container_and_flag * cf = (struct container_and_flag * )arg ;
1368- uintptr_t oldest_flag = cf -> aging_space ^ _PyGC_PREV_MASK_OLD_SPACE_1 ;
1379+ uintptr_t aging = cf -> aging_space ;
13691380 if (_PyObject_IS_GC (op )) {
13701381 PyGC_Head * gc = AS_GC (op );
13711382 if (_PyObject_GC_IS_TRACKED (op ) &&
1372- (gc -> _gc_prev & _PyGC_PREV_MASK_OLD_SPACE_1 ) == oldest_flag ) {
1383+ gc_old_space (gc ) != aging ) {
13731384 assert (!_Py_IsImmortal (op ));
1374- gc -> _gc_prev ^= _PyGC_PREV_MASK_OLD_SPACE_1 ;
1385+ gc_flip_old_space ( gc ) ;
13751386 gc_list_move (gc , cf -> container );
13761387 }
13771388 }
@@ -1437,7 +1448,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14371448 PyGC_Head * tmp = aging ;
14381449 aging = oldest ;
14391450 oldest = tmp ;
1440- gcstate -> aging_space ^= _PyGC_PREV_MASK_OLD_SPACE_1 ;
1451+ gcstate -> aging_space = flip_old_space ( gcstate -> aging_space ) ;
14411452 }
14421453 validate_old (gcstate );
14431454 while (region_size < work_to_do ) {
@@ -1447,8 +1458,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14471458 }
14481459 PyGC_Head * gc = _PyGCHead_NEXT (oldest );
14491460 gc_list_move (gc , & increment );
1450- gc -> _gc_prev &= ~_PyGC_PREV_MASK_OLD_SPACE_1 ;
1451- gc -> _gc_prev |= gcstate -> aging_space ;
1461+ gc_set_old_space (gc , gcstate -> aging_space );
14521462 region_size += expand_region_transitively_reachable (& increment , gcstate );
14531463 }
14541464 validate_old (gcstate );
@@ -1477,7 +1487,7 @@ gc_collect_full(PyThreadState *tstate,
14771487 gcstate -> young .count = 0 ;
14781488 PyGC_Head * gc = GC_NEXT (old1 );
14791489 while (gc != old1 ) {
1480- gc -> _gc_prev &= ~ _PyGC_PREV_MASK_OLD_SPACE_1 ;
1490+ gc_set_old_space ( gc , 0 ) ;
14811491 gc = GC_NEXT (gc );
14821492 }
14831493 gc_list_merge (old1 , old0 );
@@ -2137,7 +2147,7 @@ gc_freeze_impl(PyObject *module)
21372147 PyGC_Head * old1 = & gcstate -> old [1 ].head ;
21382148 gc_list_merge (old0 , & gcstate -> permanent_generation .head );
21392149 gcstate -> old [0 ].count = 0 ;
2140- make_space0 (old1 );
2150+ gc_list_set_space (old1 , 0 );
21412151 gc_list_merge (old1 , & gcstate -> permanent_generation .head );
21422152 gcstate -> old [1 ].count = 0 ;
21432153 validate_old (gcstate );
0 commit comments