Skip to content

Commit 74b5ade

Browse files
committed
Change the GC type flag since the API has changed. Allow types using
the old flag to still compile. Remove the PyType_BASICSIZE and PyType_SET_BASICSIZE macros. Add PyObject_GC_New, PyObject_GC_NewVar, PyObject_GC_Resize, PyObject_GC_Del, PyObject_GC_Track, PyObject_GC_UnTrack. Part of SF patch #421893.
1 parent 31ec142 commit 74b5ade

File tree

1 file changed

+66
-50
lines changed

1 file changed

+66
-50
lines changed

Include/objimpl.h

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -219,70 +219,86 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
219219
* ==========================
220220
*/
221221

222-
/* To make a new object participate in garbage collection use
223-
PyObject_{New, VarNew, Del} to manage the memory. Set the type flag
224-
Py_TPFLAGS_GC and define the type method tp_traverse. You should also
225-
add the method tp_clear if your object is mutable. Include
226-
PyGC_HEAD_SIZE in the calculation of tp_basicsize. Call
227-
PyObject_GC_Init after the pointers followed by tp_traverse become
228-
valid (usually just before returning the object from the allocation
229-
method. Call PyObject_GC_Fini before those pointers become invalid
230-
(usually at the top of the deallocation method). */
231-
232-
#ifndef WITH_CYCLE_GC
222+
/* Test if a type has a GC head */
223+
#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
233224

234-
#define PyGC_HEAD_SIZE 0
235-
#define PyObject_GC_Init(op)
236-
#define PyObject_GC_Fini(op)
237-
#define PyObject_AS_GC(op) (op)
238-
#define PyObject_FROM_GC(op) (op)
239-
#define PyType_IS_GC(t) 0
240-
#define PyObject_IS_GC(o) 0
241-
#define PyType_BASICSIZE(t) ((t)->tp_basicsize)
242-
#define PyType_SET_BASICSIZE(t, s) ((t)->tp_basicsize = (s))
225+
/* Test if an object has a GC head */
226+
#define PyObject_IS_GC(o) PyType_IS_GC((o)->ob_type)
243227

244-
#else
228+
extern DL_IMPORT(PyObject *) _PyObject_GC_Malloc(PyTypeObject *, int);
229+
extern DL_IMPORT(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, int);
245230

246-
/* Add the object into the container set */
247-
extern DL_IMPORT(void) _PyGC_Insert(PyObject *);
231+
#define PyObject_GC_Resize(type, op, n) \
232+
( (type *) _PyObject_GC_Resize((PyVarObject *)(op), (n)) )
248233

249-
/* Remove the object from the container set */
250-
extern DL_IMPORT(void) _PyGC_Remove(PyObject *);
234+
#ifdef WITH_CYCLE_GC
251235

252-
#define PyObject_GC_Init(op) _PyGC_Insert((PyObject *)op)
253-
#define PyObject_GC_Fini(op) _PyGC_Remove((PyObject *)op)
236+
extern DL_IMPORT(PyObject *) _PyObject_GC_New(PyTypeObject *);
237+
extern DL_IMPORT(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, int);
238+
extern DL_IMPORT(void) _PyObject_GC_Del(PyObject *);
239+
extern DL_IMPORT(void) _PyObject_GC_Track(PyObject *);
240+
extern DL_IMPORT(void) _PyObject_GC_UnTrack(PyObject *);
254241

255-
/* Structure *prefixed* to container objects participating in GC */
242+
/* GC information is stored BEFORE the object structure */
256243
typedef struct _gc_head {
257-
struct _gc_head *gc_next;
244+
struct _gc_head *gc_next; /* not NULL if object is tracked */
258245
struct _gc_head *gc_prev;
259246
int gc_refs;
260247
} PyGC_Head;
261248

262-
#define PyGC_HEAD_SIZE sizeof(PyGC_Head)
249+
extern PyGC_Head _PyGC_generation0;
250+
251+
/* Tell the GC to track this object. NB: While the object is tracked the
252+
* collector it must be safe to call the ob_traverse method. */
253+
#define _PyObject_GC_TRACK(o) do { \
254+
PyGC_Head *g = (PyGC_Head *)(o)-1; \
255+
if (g->gc_next != NULL) \
256+
Py_FatalError("GC object already in linked list"); \
257+
g->gc_next = &_PyGC_generation0; \
258+
g->gc_prev = _PyGC_generation0.gc_prev; \
259+
g->gc_prev->gc_next = g; \
260+
_PyGC_generation0.gc_prev = g; \
261+
} while (0);
262+
263+
/* Tell the GC to stop tracking this object. */
264+
#define _PyObject_GC_UNTRACK(o) do { \
265+
PyGC_Head *g = (PyGC_Head *)(o)-1; \
266+
g->gc_prev->gc_next = g->gc_next; \
267+
g->gc_next->gc_prev = g->gc_prev; \
268+
g->gc_next = NULL; \
269+
} while (0);
270+
271+
#define PyObject_GC_Track(op) _PyObject_GC_Track((PyObject *)op)
272+
#define PyObject_GC_UnTrack(op) _PyObject_GC_UnTrack((PyObject *)op)
273+
274+
275+
#define PyObject_GC_New(type, typeobj) \
276+
( (type *) _PyObject_GC_New(typeobj) )
277+
#define PyObject_GC_NewVar(type, typeobj, n) \
278+
( (type *) _PyObject_GC_NewVar((typeobj), (n)) )
279+
#define PyObject_GC_Del(op) _PyObject_GC_Del((PyObject *)(op))
280+
281+
#else /* !WITH_CYCLE_GC */
282+
283+
#define PyObject_GC_New PyObject_New
284+
#define PyObject_GC_NewVar PyObject_NewVar
285+
#define PyObject_GC_Del PyObject_Del
286+
#define PyObject_GC_TRACK(op)
287+
#define PyObject_GC_UNTRACK(op)
288+
#define PyObject_GC_Track(op)
289+
#define PyObject_GC_UnTrack(op)
263290

264-
/* Test if a type has a GC head */
265-
#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_GC)
266-
267-
/* Test if an object has a GC head */
268-
#define PyObject_IS_GC(o) PyType_IS_GC((o)->ob_type)
269-
270-
/* Get an object's GC head */
271-
#define PyObject_AS_GC(o) ((PyGC_Head *)(o)-1)
272-
273-
/* Get the object given the PyGC_Head */
274-
#define PyObject_FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))
275-
276-
/* Calculate tp_basicsize excluding PyGC_HEAD_SIZE if applicable */
277-
#define PyType_BASICSIZE(t) (!PyType_IS_GC(t) ? (t)->tp_basicsize : \
278-
(t)->tp_basicsize - PyGC_HEAD_SIZE)
279-
#define PyType_SET_BASICSIZE(t, s) (!PyType_IS_GC(t) ? \
280-
((t)->tp_basicsize = (s)) : \
281-
((t)->tp_basicsize = (s) + PyGC_HEAD_SIZE))
291+
#endif
282292

283-
extern DL_IMPORT(void) _PyGC_Dump(PyGC_Head *);
293+
/* This is here for the sake of backwards compatibility. Extensions that
294+
* use the old GC API will still compile but the objects will not be
295+
* tracked by the GC. */
296+
#define PyGC_HEAD_SIZE 0
297+
#define PyObject_GC_Init(op)
298+
#define PyObject_GC_Fini(op)
299+
#define PyObject_AS_GC(op) (op)
300+
#define PyObject_FROM_GC(op) (op)
284301

285-
#endif /* WITH_CYCLE_GC */
286302

287303
/* Test if a type supports weak references */
288304
#define PyType_SUPPORTS_WEAKREFS(t) \

0 commit comments

Comments
 (0)