@@ -256,18 +256,18 @@ PyAPI_FUNC(Py_ssize_t) _PyGC_CollectIfEnabled(void);
256256/* Test if a type has a GC head */
257257#define PyType_IS_GC (t ) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
258258
259- /* Test if an object has a GC head */
260- #ifndef Py_LIMITED_API
261- #define PyObject_IS_GC (o ) (PyType_IS_GC(Py_TYPE(o)) && \
262- (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o)))
263- #endif
264-
265259PyAPI_FUNC (PyVarObject * ) _PyObject_GC_Resize (PyVarObject * , Py_ssize_t );
266260#define PyObject_GC_Resize (type , op , n ) \
267261 ( (type *) _PyObject_GC_Resize((PyVarObject *)(op), (n)) )
268262
269- /* GC information is stored BEFORE the object structure. */
263+
270264#ifndef Py_LIMITED_API
265+ /* Test if an object has a GC head */
266+ #define PyObject_IS_GC (o ) \
267+ (PyType_IS_GC(Py_TYPE(o)) \
268+ && (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o)))
269+
270+ /* GC information is stored BEFORE the object structure. */
271271typedef struct {
272272 // Pointer to next object in the list.
273273 // 0 means the object is not tracked
@@ -278,10 +278,21 @@ typedef struct {
278278 uintptr_t _gc_prev ;
279279} PyGC_Head ;
280280
281- extern PyGC_Head * _PyGC_generation0 ;
282-
283281#define _Py_AS_GC (o ) ((PyGC_Head *)(o)-1)
284282
283+ /* True if the object is currently tracked by the GC. */
284+ #define _PyObject_GC_IS_TRACKED (o ) (_Py_AS_GC(o)->_gc_next != 0)
285+
286+ /* True if the object may be tracked by the GC in the future, or already is.
287+ This can be useful to implement some optimizations. */
288+ #define _PyObject_GC_MAY_BE_TRACKED (obj ) \
289+ (PyObject_IS_GC(obj) && \
290+ (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
291+ #endif
292+
293+
294+ #if defined(Py_BUILD_CORE ) || defined(Py_BUILD_CORE_BUILTIN )
295+
285296/* Bit flags for _gc_prev */
286297/* Bit 0 is set when tp_finalize is called */
287298#define _PyGC_PREV_MASK_FINALIZED (1)
@@ -304,38 +315,46 @@ extern PyGC_Head *_PyGC_generation0;
304315 | ((uintptr_t)(p)); \
305316 } while (0)
306317
307- #define _PyGCHead_FINALIZED (g ) (((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0)
308- #define _PyGCHead_SET_FINALIZED (g ) ((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED)
318+ #define _PyGCHead_FINALIZED (g ) \
319+ (((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0)
320+ #define _PyGCHead_SET_FINALIZED (g ) \
321+ ((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED)
309322
310- #define _PyGC_FINALIZED (o ) _PyGCHead_FINALIZED(_Py_AS_GC(o))
311- #define _PyGC_SET_FINALIZED (o ) _PyGCHead_SET_FINALIZED(_Py_AS_GC(o))
323+ #define _PyGC_FINALIZED (o ) \
324+ _PyGCHead_FINALIZED(_Py_AS_GC(o))
325+ #define _PyGC_SET_FINALIZED (o ) \
326+ _PyGCHead_SET_FINALIZED(_Py_AS_GC(o))
312327
313328/* Tell the GC to track this object.
314329 *
315330 * NB: While the object is tracked by the collector, it must be safe to call the
316331 * ob_traverse method.
317332 *
318- * Internal note: _PyGC_generation0 ->_gc_prev doesn't have any bit flags
333+ * Internal note: _PyRuntime.gc.generation0 ->_gc_prev doesn't have any bit flags
319334 * because it's not object header. So we don't use _PyGCHead_PREV() and
320335 * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations.
336+ *
337+ * The PyObject_GC_Track() function is the public version of this macro.
321338 */
322339#define _PyObject_GC_TRACK (o ) do { \
323340 PyGC_Head *g = _Py_AS_GC(o); \
324341 if (g->_gc_next != 0) { \
325342 Py_FatalError("GC object already tracked"); \
326343 } \
327344 assert((g->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0); \
328- PyGC_Head *last = (PyGC_Head*)(_PyGC_generation0 ->_gc_prev); \
345+ PyGC_Head *last = (PyGC_Head*)(_PyRuntime.gc.generation0 ->_gc_prev); \
329346 _PyGCHead_SET_NEXT(last, g); \
330347 _PyGCHead_SET_PREV(g, last); \
331- _PyGCHead_SET_NEXT(g, _PyGC_generation0 ); \
332- _PyGC_generation0 ->_gc_prev = (uintptr_t)g; \
348+ _PyGCHead_SET_NEXT(g, _PyRuntime.gc.generation0 ); \
349+ _PyRuntime.gc.generation0 ->_gc_prev = (uintptr_t)g; \
333350 } while (0);
334351
335352/* Tell the GC to stop tracking this object.
336353 *
337354 * Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING must
338355 * be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept.
356+ *
357+ * The PyObject_GC_UnTrack() function is the public version of this macro.
339358 */
340359#define _PyObject_GC_UNTRACK (o ) do { \
341360 PyGC_Head *g = _Py_AS_GC(o); \
@@ -347,25 +366,25 @@ extern PyGC_Head *_PyGC_generation0;
347366 g->_gc_next = 0; \
348367 g->_gc_prev &= _PyGC_PREV_MASK_FINALIZED; \
349368 } while (0);
350-
351- /* True if the object is currently tracked by the GC. */
352- #define _PyObject_GC_IS_TRACKED (o ) (_Py_AS_GC(o)->_gc_next != 0)
353-
354- /* True if the object may be tracked by the GC in the future, or already is.
355- This can be useful to implement some optimizations. */
356- #define _PyObject_GC_MAY_BE_TRACKED (obj ) \
357- (PyObject_IS_GC(obj) && \
358- (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
359- #endif /* Py_LIMITED_API */
369+ #endif /* defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) */
360370
361371#ifndef Py_LIMITED_API
362372PyAPI_FUNC (PyObject * ) _PyObject_GC_Malloc (size_t size );
363373PyAPI_FUNC (PyObject * ) _PyObject_GC_Calloc (size_t size );
364374#endif /* !Py_LIMITED_API */
365375PyAPI_FUNC (PyObject * ) _PyObject_GC_New (PyTypeObject * );
366376PyAPI_FUNC (PyVarObject * ) _PyObject_GC_NewVar (PyTypeObject * , Py_ssize_t );
377+
378+ /* Tell the GC to track this object.
379+ *
380+ * See also private _PyObject_GC_TRACK() macro. */
367381PyAPI_FUNC (void ) PyObject_GC_Track (void * );
382+
383+ /* Tell the GC to stop tracking this object.
384+ *
385+ * See also private _PyObject_GC_UNTRACK() macro. */
368386PyAPI_FUNC (void ) PyObject_GC_UnTrack (void * );
387+
369388PyAPI_FUNC (void ) PyObject_GC_Del (void * );
370389
371390#define PyObject_GC_New (type , typeobj ) \
0 commit comments