@@ -256,6 +256,30 @@ extern PyGC_Head *_PyGC_generation0;
256256
257257#define _Py_AS_GC (o ) ((PyGC_Head *)(o)-1)
258258
259+ /* Bit 0 is set when tp_finalize is called */
260+ #define _PyGC_REFS_MASK_FINALIZED (1 << 0)
261+ /* The (N-1) most significant bits contain the gc state / refcount */
262+ #define _PyGC_REFS_SHIFT (1)
263+ #define _PyGC_REFS_MASK (((size_t) -1) << _PyGC_REFS_SHIFT)
264+
265+ #define _PyGCHead_REFS (g ) ((g)->gc.gc_refs >> _PyGC_REFS_SHIFT)
266+ #define _PyGCHead_SET_REFS (g , v ) do { \
267+ (g)->gc.gc_refs = ((g)->gc.gc_refs & ~_PyGC_REFS_MASK) \
268+ | (v << _PyGC_REFS_SHIFT); \
269+ } while (0)
270+ #define _PyGCHead_DECREF (g ) ((g)->gc.gc_refs -= 1 << _PyGC_REFS_SHIFT)
271+
272+ #define _PyGCHead_FINALIZED (g ) (((g)->gc.gc_refs & _PyGC_REFS_MASK_FINALIZED) != 0)
273+ #define _PyGCHead_SET_FINALIZED (g , v ) do { \
274+ (g)->gc.gc_refs = ((g)->gc.gc_refs & ~_PyGC_REFS_MASK_FINALIZED) \
275+ | (v != 0); \
276+ } while (0)
277+
278+ #define _PyGC_FINALIZED (o ) _PyGCHead_FINALIZED(_Py_AS_GC(o))
279+ #define _PyGC_SET_FINALIZED (o , v ) _PyGCHead_SET_FINALIZED(_Py_AS_GC(o), v)
280+
281+ #define _PyGC_REFS (o ) _PyGCHead_REFS(_Py_AS_GC(o))
282+
259283#define _PyGC_REFS_UNTRACKED (-2)
260284#define _PyGC_REFS_REACHABLE (-3)
261285#define _PyGC_REFS_TENTATIVELY_UNREACHABLE (-4)
@@ -264,9 +288,9 @@ extern PyGC_Head *_PyGC_generation0;
264288 * collector it must be safe to call the ob_traverse method. */
265289#define _PyObject_GC_TRACK (o ) do { \
266290 PyGC_Head *g = _Py_AS_GC(o); \
267- if (g->gc.gc_refs != _PyGC_REFS_UNTRACKED) \
291+ if (_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED) \
268292 Py_FatalError("GC object already tracked"); \
269- g->gc.gc_refs = _PyGC_REFS_REACHABLE; \
293+ _PyGCHead_SET_REFS(g, _PyGC_REFS_REACHABLE) ; \
270294 g->gc.gc_next = _PyGC_generation0; \
271295 g->gc.gc_prev = _PyGC_generation0->gc.gc_prev; \
272296 g->gc.gc_prev->gc.gc_next = g; \
@@ -279,16 +303,16 @@ extern PyGC_Head *_PyGC_generation0;
279303 */
280304#define _PyObject_GC_UNTRACK (o ) do { \
281305 PyGC_Head *g = _Py_AS_GC(o); \
282- assert(g->gc.gc_refs != _PyGC_REFS_UNTRACKED); \
283- g->gc.gc_refs = _PyGC_REFS_UNTRACKED; \
306+ assert(_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED); \
307+ _PyGCHead_SET_REFS(g, _PyGC_REFS_UNTRACKED) ; \
284308 g->gc.gc_prev->gc.gc_next = g->gc.gc_next; \
285309 g->gc.gc_next->gc.gc_prev = g->gc.gc_prev; \
286310 g->gc.gc_next = NULL; \
287311 } while (0);
288312
289313/* True if the object is currently tracked by the GC. */
290314#define _PyObject_GC_IS_TRACKED (o ) \
291- ((_Py_AS_GC(o))->gc.gc_refs != _PyGC_REFS_UNTRACKED)
315+ (_PyGC_REFS(o) != _PyGC_REFS_UNTRACKED)
292316
293317/* True if the object may be tracked by the GC in the future, or already is.
294318 This can be useful to implement some optimizations. */
0 commit comments