@@ -19,6 +19,13 @@ extern "C" {
1919#include <stdbool.h> // bool
2020
2121
22+ #ifdef Py_TRACE_REFS
23+ extern void _Py_AddToAllObjects (PyObject * op );
24+ extern void _Py_PrintReferences (PyInterpreterState * , FILE * );
25+ extern void _Py_PrintReferenceAddresses (PyInterpreterState * , FILE * );
26+ #endif
27+
28+
2229// This value is added to `ob_ref_shared` for objects that use deferred
2330// reference counting so that they are not immediately deallocated when the
2431// non-deferred reference count drops to zero.
@@ -468,6 +475,52 @@ static inline void Py_DECREF_MORTAL_SPECIALIZED(PyObject *op, destructor destruc
468475# define Py_DECREF_MORTAL_SPECIALIZED (op , destruct ) Py_DECREF(op)
469476#endif
470477
478+ static inline void
479+ _Py_NewReferenceNoTotalInline (PyObject * op )
480+ {
481+ // Skip the immortal object check in Py_SET_REFCNT; always set refcnt to 1
482+ #if !defined(Py_GIL_DISABLED )
483+ // With GIL
484+ #if SIZEOF_VOID_P > 4
485+ op -> ob_refcnt_full = 1 ;
486+ assert (op -> ob_refcnt == 1 );
487+ assert (op -> ob_flags == 0 );
488+ #else
489+ op -> ob_refcnt = 1 ;
490+ #endif
491+ #else
492+ // Free Threading
493+ op -> ob_flags = 0 ;
494+ op -> ob_mutex = (PyMutex ){ 0 };
495+ #ifdef _Py_THREAD_SANITIZER
496+ _Py_atomic_store_uintptr_relaxed (& op -> ob_tid , _Py_ThreadId ());
497+ _Py_atomic_store_uint8_relaxed (& op -> ob_gc_bits , 0 );
498+ _Py_atomic_store_uint32_relaxed (& op -> ob_ref_local , 1 );
499+ _Py_atomic_store_ssize_relaxed (& op -> ob_ref_shared , 0 );
500+ #else
501+ op -> ob_tid = _Py_ThreadId ();
502+ op -> ob_gc_bits = 0 ;
503+ op -> ob_ref_local = 1 ;
504+ op -> ob_ref_shared = 0 ;
505+ #endif
506+ #endif
507+
508+ #ifdef Py_TRACE_REFS
509+ _Py_AddToAllObjects (op );
510+ #endif
511+
512+ _PyReftracerTrack (op , PyRefTracer_CREATE );
513+ }
514+
515+ static inline void
516+ _Py_NewReferenceInline (PyObject * op )
517+ {
518+ #ifdef Py_REF_DEBUG
519+ _Py_IncRefTotal (_PyThreadState_GET ());
520+ #endif
521+ _Py_NewReferenceNoTotalInline (op );
522+ }
523+
471524/* Inline functions trading binary compatibility for speed:
472525 _PyObject_Init() is the fast version of PyObject_Init(), and
473526 _PyObject_InitVar() is the fast version of PyObject_InitVar().
@@ -480,7 +533,7 @@ _PyObject_Init(PyObject *op, PyTypeObject *typeobj)
480533 Py_SET_TYPE (op , typeobj );
481534 assert (_PyType_HasFeature (typeobj , Py_TPFLAGS_HEAPTYPE ) || _Py_IsImmortal (typeobj ));
482535 _Py_INCREF_TYPE (typeobj );
483- _Py_NewReference (op );
536+ _Py_NewReferenceInline (op );
484537}
485538
486539static inline void
@@ -764,12 +817,6 @@ extern void _Py_FinalizeRefTotal(_PyRuntimeState *);
764817extern void _PyDebug_PrintTotalRefs (void );
765818#endif
766819
767- #ifdef Py_TRACE_REFS
768- extern void _Py_AddToAllObjects (PyObject * op );
769- extern void _Py_PrintReferences (PyInterpreterState * , FILE * );
770- extern void _Py_PrintReferenceAddresses (PyInterpreterState * , FILE * );
771- #endif
772-
773820
774821/* Return the *address* of the object's weaklist. The address may be
775822 * dereferenced to get the current head of the weaklist. This is useful
0 commit comments