@@ -68,7 +68,7 @@ module gc
6868// move_legacy_finalizers() removes this flag instead.
6969// Between them, unreachable list is not normal list and we can not use
7070// most gc_list_* functions for it.
71- #define NEXT_MASK_UNREACHABLE (1 )
71+ #define NEXT_MASK_UNREACHABLE (2 )
7272
7373#define AS_GC (op ) _Py_AS_GC(op)
7474#define FROM_GC (gc ) _Py_FROM_GC(gc)
@@ -102,7 +102,7 @@ gc_set_refs(PyGC_Head *g, Py_ssize_t refs)
102102static inline void
103103gc_reset_refs (PyGC_Head * g , Py_ssize_t refs )
104104{
105- g -> _gc_prev = (g -> _gc_prev & ~ _PyGC_PREV_MASK )
105+ g -> _gc_prev = (g -> _gc_prev & _PyGC_PREV_MASK_FINALIZED )
106106 | PREV_MASK_COLLECTING
107107 | ((uintptr_t )(refs ) << _PyGC_PREV_SHIFT );
108108}
@@ -119,26 +119,27 @@ gc_decref(PyGC_Head *g)
119119static inline uintptr_t
120120gc_old_space (PyGC_Head * g )
121121{
122- return g -> _gc_prev & _PyGC_PREV_MASK_OLD_SPACE_1 ;
122+ return g -> _gc_next & _PyGC_NEXT_MASK_OLD_SPACE_1 ;
123123}
124124
125125static inline uintptr_t
126126flip_old_space (uintptr_t space )
127127{
128- return space ^ _PyGC_PREV_MASK_OLD_SPACE_1 ;
128+ return space ^ _PyGC_NEXT_MASK_OLD_SPACE_1 ;
129129}
130130
131131static inline void
132132gc_flip_old_space (PyGC_Head * g )
133133{
134- g -> _gc_prev ^= _PyGC_PREV_MASK_OLD_SPACE_1 ;
134+ g -> _gc_next ^= _PyGC_NEXT_MASK_OLD_SPACE_1 ;
135135}
136136
137137static inline void
138138gc_set_old_space (PyGC_Head * g , uintptr_t space )
139139{
140- g -> _gc_prev &= ~_PyGC_PREV_MASK_OLD_SPACE_1 ;
141- g -> _gc_prev |= space ;
140+ assert (space == 0 || space == _PyGC_NEXT_MASK_OLD_SPACE_1 );
141+ g -> _gc_next &= ~_PyGC_NEXT_MASK_OLD_SPACE_1 ;
142+ g -> _gc_next |= space ;
142143}
143144
144145/* set for debugging information */
@@ -286,6 +287,7 @@ gc_list_is_empty(PyGC_Head *list)
286287static inline void
287288gc_list_append (PyGC_Head * node , PyGC_Head * list )
288289{
290+ assert ((list -> _gc_prev & ~_PyGC_PREV_MASK ) == 0 );
289291 PyGC_Head * last = (PyGC_Head * )list -> _gc_prev ;
290292
291293 // last <-> node
@@ -434,7 +436,7 @@ validate_list(PyGC_Head *head, enum flagstates flags)
434436 PyGC_Head * gc = GC_NEXT (head );
435437 while (gc != head ) {
436438 PyGC_Head * trueprev = GC_PREV (gc );
437- PyGC_Head * truenext = ( PyGC_Head * )( gc -> _gc_next & ~ NEXT_MASK_UNREACHABLE );
439+ PyGC_Head * truenext = GC_NEXT ( gc );
438440 assert (truenext != NULL );
439441 assert (trueprev == prev );
440442 assert ((gc -> _gc_prev & PREV_MASK_COLLECTING ) == prev_value );
@@ -458,7 +460,7 @@ validate_old(GCState *gcstate)
458460 PyGC_Head * gc = GC_NEXT (head );
459461 while (gc != head ) {
460462 PyGC_Head * trueprev = GC_PREV (gc );
461- PyGC_Head * truenext = ( PyGC_Head * )( gc -> _gc_next & ~ NEXT_MASK_UNREACHABLE );
463+ PyGC_Head * truenext = GC_NEXT ( gc );
462464 assert (truenext != NULL );
463465 assert (trueprev == prev );
464466 assert (gc_old_space (gc ) == space );
@@ -477,7 +479,7 @@ validate_list_is_aging(PyGC_Head *head)
477479 PyGC_Head * gc = GC_NEXT (head );
478480 uintptr_t aging_flag = gcstate -> aging_space ;
479481 while (gc != head ) {
480- PyGC_Head * truenext = ( PyGC_Head * )( gc -> _gc_next & ~ NEXT_MASK_UNREACHABLE );
482+ PyGC_Head * truenext = GC_NEXT ( gc );
481483 assert (truenext != NULL );
482484 assert (gc_old_space (gc ) == aging_flag );
483485 prev = gc ;
@@ -611,12 +613,13 @@ visit_reachable(PyObject *op, PyGC_Head *reachable)
611613 // Manually unlink gc from unreachable list because the list functions
612614 // don't work right in the presence of NEXT_MASK_UNREACHABLE flags.
613615 PyGC_Head * prev = GC_PREV (gc );
614- PyGC_Head * next = ( PyGC_Head * )( gc -> _gc_next & ~ NEXT_MASK_UNREACHABLE );
616+ PyGC_Head * next = GC_NEXT ( gc );
615617 _PyObject_ASSERT (FROM_GC (prev ),
616618 prev -> _gc_next & NEXT_MASK_UNREACHABLE );
617619 _PyObject_ASSERT (FROM_GC (next ),
618620 next -> _gc_next & NEXT_MASK_UNREACHABLE );
619621 prev -> _gc_next = gc -> _gc_next ; // copy NEXT_MASK_UNREACHABLE
622+ gc -> _gc_next &= ~NEXT_MASK_UNREACHABLE ;
620623 _PyGCHead_SET_PREV (next , prev );
621624
622625 gc_list_append (gc , reachable );
@@ -658,7 +661,6 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable)
658661 // previous elem in the young list, used for restore gc_prev.
659662 PyGC_Head * prev = young ;
660663 PyGC_Head * gc = GC_NEXT (young );
661-
662664 /* Invariants: all objects "to the left" of us in young are reachable
663665 * (directly or indirectly) from outside the young list as it was at entry.
664666 *
@@ -718,12 +720,12 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable)
718720 gc -> _gc_next = (NEXT_MASK_UNREACHABLE | (uintptr_t )unreachable );
719721 unreachable -> _gc_prev = (uintptr_t )gc ;
720722 }
721- gc = ( PyGC_Head * ) prev -> _gc_next ;
723+ gc = _PyGCHead_NEXT ( prev ) ;
722724 }
723725 // young->_gc_prev must be last element remained in the list.
724726 young -> _gc_prev = (uintptr_t )prev ;
725727 // don't let the pollution of the list head's next pointer leak
726- unreachable -> _gc_next &= ~ NEXT_MASK_UNREACHABLE ;
728+ unreachable -> _gc_next &= _PyGC_PREV_MASK ;
727729}
728730
729731static void
@@ -780,7 +782,7 @@ move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
780782 PyObject * op = FROM_GC (gc );
781783
782784 _PyObject_ASSERT (op , gc -> _gc_next & NEXT_MASK_UNREACHABLE );
783- gc -> _gc_next &= ~ NEXT_MASK_UNREACHABLE ;
785+ gc -> _gc_next &= _PyGC_PREV_MASK ;
784786 next = (PyGC_Head * )gc -> _gc_next ;
785787
786788 if (has_legacy_finalizer (op )) {
@@ -800,7 +802,7 @@ clear_unreachable_mask(PyGC_Head *unreachable)
800802 assert ((unreachable -> _gc_next & NEXT_MASK_UNREACHABLE ) == 0 );
801803 for (gc = GC_NEXT (unreachable ); gc != unreachable ; gc = next ) {
802804 _PyObject_ASSERT ((PyObject * )FROM_GC (gc ), gc -> _gc_next & NEXT_MASK_UNREACHABLE );
803- gc -> _gc_next &= ~ NEXT_MASK_UNREACHABLE ;
805+ gc -> _gc_next &= _PyGC_PREV_MASK ;
804806 next = (PyGC_Head * )gc -> _gc_next ;
805807 }
806808 validate_list (unreachable , collecting_set_unreachable_clear );
@@ -1525,6 +1527,7 @@ gc_collect_region(PyThreadState *tstate,
15251527 assert (gcstate -> garbage != NULL );
15261528 assert (!_PyErr_Occurred (tstate ));
15271529
1530+ validate_list (from , collecting_clear_unreachable_clear );
15281531 validate_list (to , collecting_clear_unreachable_clear );
15291532
15301533 deduce_unreachable (from , & unreachable );
0 commit comments