@@ -109,11 +109,14 @@ static inline void _PyObject_GC_SET_SHARED_INLINE(PyObject *op) {
109109
110110/* Bit flags for _gc_prev */
111111/* Bit 0 is set when tp_finalize is called */
112- #define _PyGC_PREV_MASK_FINALIZED (1)
112+ #define _PyGC_PREV_MASK_FINALIZED 1
113113/* Bit 1 is set when the object is in generation which is GCed currently. */
114- #define _PyGC_PREV_MASK_COLLECTING (2)
115- /* The (N-2) most significant bits contain the real address. */
116- #define _PyGC_PREV_SHIFT (2)
114+ #define _PyGC_PREV_MASK_COLLECTING 2
115+
116+ /* Bit 0 is set if the object belongs to old space 1 */
117+ #define _PyGC_NEXT_MASK_OLD_SPACE_1 1
118+
119+ #define _PyGC_PREV_SHIFT 2
117120#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
118121
119122/* set for debugging information */
@@ -139,18 +142,21 @@ typedef enum {
139142// Lowest bit of _gc_next is used for flags only in GC.
140143// But it is always 0 for normal code.
141144static inline PyGC_Head * _PyGCHead_NEXT (PyGC_Head * gc ) {
142- uintptr_t next = gc -> _gc_next ;
145+ uintptr_t next = gc -> _gc_next & _PyGC_PREV_MASK ;
143146 return (PyGC_Head * )next ;
144147}
145148static inline void _PyGCHead_SET_NEXT (PyGC_Head * gc , PyGC_Head * next ) {
146- gc -> _gc_next = (uintptr_t )next ;
149+ uintptr_t unext = (uintptr_t )next ;
150+ assert ((unext & ~_PyGC_PREV_MASK ) == 0 );
151+ gc -> _gc_next = (gc -> _gc_next & ~_PyGC_PREV_MASK ) | unext ;
147152}
148153
149154// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
150155static inline PyGC_Head * _PyGCHead_PREV (PyGC_Head * gc ) {
151156 uintptr_t prev = (gc -> _gc_prev & _PyGC_PREV_MASK );
152157 return (PyGC_Head * )prev ;
153158}
159+
154160static inline void _PyGCHead_SET_PREV (PyGC_Head * gc , PyGC_Head * prev ) {
155161 uintptr_t uprev = (uintptr_t )prev ;
156162 assert ((uprev & ~_PyGC_PREV_MASK ) == 0 );
@@ -236,6 +242,13 @@ struct gc_generation {
236242 generations */
237243};
238244
245+ struct gc_collection_stats {
246+ /* number of collected objects */
247+ Py_ssize_t collected ;
248+ /* total number of uncollectable objects (put into gc.garbage) */
249+ Py_ssize_t uncollectable ;
250+ };
251+
239252/* Running stats per generation */
240253struct gc_generation_stats {
241254 /* total number of collections */
@@ -257,8 +270,8 @@ struct _gc_runtime_state {
257270 int enabled ;
258271 int debug ;
259272 /* linked lists of container objects */
260- struct gc_generation generations [ NUM_GENERATIONS ] ;
261- PyGC_Head * generation0 ;
273+ struct gc_generation young ;
274+ struct gc_generation old [ 2 ] ;
262275 /* a permanent generation which won't be collected */
263276 struct gc_generation permanent_generation ;
264277 struct gc_generation_stats generation_stats [NUM_GENERATIONS ];
@@ -268,6 +281,12 @@ struct _gc_runtime_state {
268281 PyObject * garbage ;
269282 /* a list of callbacks to be invoked when collection is performed */
270283 PyObject * callbacks ;
284+
285+ Py_ssize_t work_to_do ;
286+ /* Which of the old spaces is the visited space */
287+ int visited_space ;
288+
289+ #ifdef Py_GIL_DISABLED
271290 /* This is the number of objects that survived the last full
272291 collection. It approximates the number of long lived objects
273292 tracked by the GC.
@@ -279,6 +298,7 @@ struct _gc_runtime_state {
279298 collections, and are awaiting to undergo a full collection for
280299 the first time. */
281300 Py_ssize_t long_lived_pending ;
301+ #endif
282302};
283303
284304#ifdef Py_GIL_DISABLED
@@ -291,9 +311,8 @@ struct _gc_thread_state {
291311
292312extern void _PyGC_InitState (struct _gc_runtime_state * );
293313
294- extern Py_ssize_t _PyGC_Collect (PyThreadState * tstate , int generation ,
295- _PyGC_Reason reason );
296- extern Py_ssize_t _PyGC_CollectNoFail (PyThreadState * tstate );
314+ extern Py_ssize_t _PyGC_Collect (PyThreadState * tstate , int generation , _PyGC_Reason reason );
315+ extern void _PyGC_CollectNoFail (PyThreadState * tstate );
297316
298317/* Freeze objects tracked by the GC and ignore them in future collections. */
299318extern void _PyGC_Freeze (PyInterpreterState * interp );
0 commit comments