@@ -71,11 +71,15 @@ static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) {
71
71
72
72
/* Bit flags for _gc_prev */
73
73
/* Bit 0 is set when tp_finalize is called */
74
- #define _PyGC_PREV_MASK_FINALIZED (1)
74
+ #define _PyGC_PREV_MASK_FINALIZED 1
75
75
/* Bit 1 is set when the object is in generation which is GCed currently. */
76
- #define _PyGC_PREV_MASK_COLLECTING (2)
76
+ #define _PyGC_PREV_MASK_COLLECTING 2
77
+
78
+ /* Bit 0 is set if the object belongs to old space 1 */
79
+ #define _PyGC_NEXT_MASK_OLD_SPACE_1 1
80
+
77
81
/* The (N-2) most significant bits contain the real address. */
78
- #define _PyGC_PREV_SHIFT (2)
82
+ #define _PyGC_PREV_SHIFT 2
79
83
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
80
84
81
85
/* set for debugging information */
@@ -101,18 +105,21 @@ typedef enum {
101
105
// Lowest bit of _gc_next is used for flags only in GC.
102
106
// But it is always 0 for normal code.
103
107
static inline PyGC_Head * _PyGCHead_NEXT (PyGC_Head * gc ) {
104
- uintptr_t next = gc -> _gc_next ;
108
+ uintptr_t next = gc -> _gc_next & _PyGC_PREV_MASK ;
105
109
return (PyGC_Head * )next ;
106
110
}
107
111
static inline void _PyGCHead_SET_NEXT (PyGC_Head * gc , PyGC_Head * next ) {
108
- gc -> _gc_next = (uintptr_t )next ;
112
+ uintptr_t unext = (uintptr_t )next ;
113
+ assert ((unext & ~_PyGC_PREV_MASK ) == 0 );
114
+ gc -> _gc_next = (gc -> _gc_next & ~_PyGC_PREV_MASK ) | unext ;
109
115
}
110
116
111
117
// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
112
118
static inline PyGC_Head * _PyGCHead_PREV (PyGC_Head * gc ) {
113
119
uintptr_t prev = (gc -> _gc_prev & _PyGC_PREV_MASK );
114
120
return (PyGC_Head * )prev ;
115
121
}
122
+
116
123
static inline void _PyGCHead_SET_PREV (PyGC_Head * gc , PyGC_Head * prev ) {
117
124
uintptr_t uprev = (uintptr_t )prev ;
118
125
assert ((uprev & ~_PyGC_PREV_MASK ) == 0 );
@@ -198,6 +205,13 @@ struct gc_generation {
198
205
generations */
199
206
};
200
207
208
+ struct gc_collection_stats {
209
+ /* number of collected objects */
210
+ Py_ssize_t collected ;
211
+ /* total number of uncollectable objects (put into gc.garbage) */
212
+ Py_ssize_t uncollectable ;
213
+ };
214
+
201
215
/* Running stats per generation */
202
216
struct gc_generation_stats {
203
217
/* total number of collections */
@@ -219,8 +233,8 @@ struct _gc_runtime_state {
219
233
int enabled ;
220
234
int debug ;
221
235
/* linked lists of container objects */
222
- struct gc_generation generations [ NUM_GENERATIONS ] ;
223
- PyGC_Head * generation0 ;
236
+ struct gc_generation young ;
237
+ struct gc_generation old [ 2 ] ;
224
238
/* a permanent generation which won't be collected */
225
239
struct gc_generation permanent_generation ;
226
240
struct gc_generation_stats generation_stats [NUM_GENERATIONS ];
@@ -233,22 +247,20 @@ struct _gc_runtime_state {
233
247
/* This is the number of objects that survived the last full
234
248
collection. It approximates the number of long lived objects
235
249
tracked by the GC.
236
-
237
250
(by "full collection", we mean a collection of the oldest
238
251
generation). */
239
252
Py_ssize_t long_lived_total ;
240
- /* This is the number of objects that survived all "non-full"
241
- collections, and are awaiting to undergo a full collection for
242
- the first time. */
243
- Py_ssize_t long_lived_pending ;
253
+
254
+ Py_ssize_t work_to_do ;
255
+ /* Which of the old spaces is the visited space */
256
+ int visited_space ;
244
257
};
245
258
246
259
247
260
extern void _PyGC_InitState (struct _gc_runtime_state * );
248
261
249
- extern Py_ssize_t _PyGC_Collect (PyThreadState * tstate , int generation ,
250
- _PyGC_Reason reason );
251
- extern Py_ssize_t _PyGC_CollectNoFail (PyThreadState * tstate );
262
+ extern Py_ssize_t _PyGC_Collect (PyThreadState * tstate , int generation , _PyGC_Reason reason );
263
+ extern void _PyGC_CollectNoFail (PyThreadState * tstate );
252
264
253
265
/* Freeze objects tracked by the GC and ignore them in future collections. */
254
266
extern void _PyGC_Freeze (PyInterpreterState * interp );
0 commit comments