Skip to main content

Include/internal/pycore_object.h

Source:

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_object.h

pycore_object.h provides the internal macros and inline functions for reference counting and object initialization that are not part of the stable ABI.

Map

LinesSymbolRole
1-50_PyObject_InitInitialize ob_refcnt and ob_type for a new object
51-100_Py_NewReferenceTrack new objects in debug builds
101-150_Py_DECREF_SPECIALIZEDSpecialized DECREF for known types (avoids virtual dispatch)
151-180Immortal objects_Py_IsImmortal, immortality threshold
181-220_PyObject_IS_GCCheck if a type participates in cyclic GC
221-250Debug-mode extras_Py_INC_REFTOTAL, _Py_DEC_REFTOTAL

Reading

_PyObject_Init

// CPython: Include/internal/pycore_object.h:28 _PyObject_Init
static inline void
_PyObject_Init(PyObject *op, PyTypeObject *typeobj)
{
Py_SET_REFCNT(op, 1);
Py_SET_TYPE(op, typeobj);
if (_PyType_HasFeature(typeobj, Py_TPFLAGS_HEAPTYPE)) {
Py_INCREF(typeobj);
}
_Py_NewReference(op);
}

All allocations call _PyObject_Init (or the _PyObject_VAR_Init variant for variable-size objects).

_Py_NewReference

// CPython: Include/internal/pycore_object.h:62 _Py_NewReference
static inline void
_Py_NewReference(PyObject *op)
{
#ifdef Py_REF_DEBUG
_Py_INC_REFTOTAL();
/* Add to linked list of all objects (for sys.getobjects()) */
_Py_AddToAllObjects(op);
#endif
}

Only active in debug builds (Py_REF_DEBUG). Production builds compile this away.

Immortal objects (3.12+)

// CPython: Include/internal/pycore_object.h:158 _Py_IsImmortal
#define _Py_IMMORTAL_REFCNT (UINT_MAX >> 2)

static inline int
_Py_IsImmortal(PyObject *op)
{
return (op->ob_refcnt >= _Py_IMMORTAL_REFCNT);
}

Immortal objects (None, True, False, small integers, interned strings) have a reference count at the saturating maximum. Py_DECREF on an immortal object is a no-op, avoiding cache-line contention in multi-threaded code.

Py_DECREF fast path

// CPython: Include/internal/pycore_object.h:105 Py_DECREF
static inline void
Py_DECREF(PyObject *op)
{
if (_Py_IsImmortal(op)) return; /* immortal: skip */
if (--op->ob_refcnt != 0) return; /* still referenced */
_Py_Dealloc(op); /* refcount hit 0: deallocate */
}

_Py_Dealloc calls tp_finalize (if present) then tp_free (usually PyObject_Free).

_PyObject_IS_GC

// CPython: Include/internal/pycore_object.h:200 _PyObject_IS_GC
static inline int
_PyObject_IS_GC(PyObject *obj)
{
return _PyType_IS_GC(Py_TYPE(obj));
}
#define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)

list, dict, tuple, function objects, class objects have Py_TPFLAGS_HAVE_GC. int, str, float do not — they cannot form reference cycles.

gopy notes

In gopy, Go's GC manages memory; there is no reference counting. However, the reference-counting API is emulated for C extension compatibility. _Py_IsImmortal maps to a isImmortal bool flag on objects.Object. Py_DECREF calls runtime.KeepAlive to prevent premature GC of objects still referenced by C code. Py_TPFLAGS_HAVE_GC tracks which types can form cycles.