@@ -251,9 +251,8 @@ PyAPI_FUNC(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, Py_ssize_t);
251
251
#ifndef Py_LIMITED_API
252
252
typedef union _gc_head {
253
253
struct {
254
- union _gc_head * gc_next ;
255
- union _gc_head * gc_prev ;
256
- Py_ssize_t gc_refs ;
254
+ union _gc_head * gc_next ; // NULL means the object is not tracked
255
+ uintptr_t gc_prev ;
257
256
} gc ;
258
257
double dummy ; /* force worst-case alignment */
259
258
} PyGC_Head ;
@@ -263,44 +262,39 @@ extern PyGC_Head *_PyGC_generation0;
263
262
#define _Py_AS_GC (o ) ((PyGC_Head *)(o)-1)
264
263
265
264
/* Bit 0 is set when tp_finalize is called */
266
- #define _PyGC_REFS_MASK_FINALIZED (1 << 0)
267
- /* The (N-1) most significant bits contain the gc state / refcount */
268
- #define _PyGC_REFS_SHIFT (1)
269
- #define _PyGC_REFS_MASK (((size_t) -1) << _PyGC_REFS_SHIFT)
270
-
271
- #define _PyGCHead_REFS (g ) ((g)->gc.gc_refs >> _PyGC_REFS_SHIFT)
272
- #define _PyGCHead_SET_REFS (g , v ) do { \
273
- (g)->gc.gc_refs = ((g)->gc.gc_refs & ~_PyGC_REFS_MASK) \
274
- | (((size_t)(v)) << _PyGC_REFS_SHIFT); \
265
+ #define _PyGC_PREV_MASK_FINALIZED (1 << 0)
266
+ /* Bit 1 and 2 is used in gcmodule.c */
267
+ /* The (N-3) most significant bits contain the real address. */
268
+ #define _PyGC_PREV_SHIFT (3)
269
+ #define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
270
+
271
+ #define _PyGCHead_PREV (g ) ((PyGC_Head*)((g)->gc.gc_prev & _PyGC_PREV_MASK))
272
+ #define _PyGCHead_SET_PREV (g , p ) do { \
273
+ assert(((uintptr_t)p & ~_PyGC_PREV_MASK) == 0); \
274
+ (g)->gc.gc_prev = ((g)->gc.gc_prev & ~_PyGC_PREV_MASK) \
275
+ | ((uintptr_t)(p)); \
275
276
} while (0)
276
- #define _PyGCHead_DECREF (g ) ((g)->gc.gc_refs -= 1 << _PyGC_REFS_SHIFT)
277
277
278
- #define _PyGCHead_FINALIZED (g ) (((g)->gc.gc_refs & _PyGC_REFS_MASK_FINALIZED ) != 0)
278
+ #define _PyGCHead_FINALIZED (g ) (((g)->gc.gc_prev & _PyGC_PREV_MASK_FINALIZED ) != 0)
279
279
#define _PyGCHead_SET_FINALIZED (g , v ) do { \
280
- (g)->gc.gc_refs = ((g)->gc.gc_refs & ~_PyGC_REFS_MASK_FINALIZED ) \
280
+ (g)->gc.gc_prev = ((g)->gc.gc_prev & ~_PyGC_PREV_MASK_FINALIZED ) \
281
281
| (v != 0); \
282
282
} while (0)
283
283
284
284
#define _PyGC_FINALIZED (o ) _PyGCHead_FINALIZED(_Py_AS_GC(o))
285
285
#define _PyGC_SET_FINALIZED (o , v ) _PyGCHead_SET_FINALIZED(_Py_AS_GC(o), v)
286
286
287
- #define _PyGC_REFS (o ) _PyGCHead_REFS(_Py_AS_GC(o))
288
-
289
- #define _PyGC_REFS_UNTRACKED (-2)
290
- #define _PyGC_REFS_REACHABLE (-3)
291
- #define _PyGC_REFS_TENTATIVELY_UNREACHABLE (-4)
292
-
293
287
/* Tell the GC to track this object. NB: While the object is tracked the
294
288
* collector it must be safe to call the ob_traverse method. */
295
289
#define _PyObject_GC_TRACK (o ) do { \
296
290
PyGC_Head *g = _Py_AS_GC(o); \
297
- if (_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED ) \
291
+ if (g->gc.gc_next != NULL ) \
298
292
Py_FatalError("GC object already tracked"); \
299
- _PyGCHead_SET_REFS(g, _PyGC_REFS_REACHABLE ); \
293
+ assert((g->gc.gc_prev & 6) == 0 ); \
300
294
g->gc.gc_next = _PyGC_generation0; \
301
- g->gc.gc_prev = _PyGC_generation0->gc.gc_prev; \
302
- g->gc.gc_prev ->gc.gc_next = g; \
303
- _PyGC_generation0->gc.gc_prev = g; \
295
+ _PyGCHead_SET_PREV(g, _PyGC_generation0->gc.gc_prev) ; \
296
+ _PyGCHead_PREV(_PyGC_generation0) ->gc.gc_next = g; \
297
+ _PyGC_generation0->gc.gc_prev = (uintptr_t) g; \
304
298
} while (0);
305
299
306
300
/* Tell the GC to stop tracking this object.
@@ -309,16 +303,15 @@ extern PyGC_Head *_PyGC_generation0;
309
303
*/
310
304
#define _PyObject_GC_UNTRACK (o ) do { \
311
305
PyGC_Head *g = _Py_AS_GC(o); \
312
- assert(_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED); \
313
- _PyGCHead_SET_REFS(g, _PyGC_REFS_UNTRACKED); \
314
- g->gc.gc_prev->gc.gc_next = g->gc.gc_next; \
315
- g->gc.gc_next->gc.gc_prev = g->gc.gc_prev; \
306
+ assert(g->gc.gc_next != NULL); \
307
+ _PyGCHead_PREV(g)->gc.gc_next = g->gc.gc_next; \
308
+ _PyGCHead_SET_PREV(g->gc.gc_next, _PyGCHead_PREV(g)); \
316
309
g->gc.gc_next = NULL; \
310
+ g->gc.gc_prev &= _PyGC_PREV_MASK_FINALIZED; \
317
311
} while (0);
318
312
319
313
/* True if the object is currently tracked by the GC. */
320
- #define _PyObject_GC_IS_TRACKED (o ) \
321
- (_PyGC_REFS(o) != _PyGC_REFS_UNTRACKED)
314
+ #define _PyObject_GC_IS_TRACKED (o ) (_Py_AS_GC(o)->gc.gc_next != NULL)
322
315
323
316
/* True if the object may be tracked by the GC in the future, or already is.
324
317
This can be useful to implement some optimizations. */
0 commit comments