@@ -14,7 +14,7 @@ extern "C" {
1414#include "pycore_interp.h" // PyInterpreterState.gc
1515#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_PTR_RELAXED
1616#include "pycore_pystate.h" // _PyInterpreterState_GET()
17- #include "pycore_uniqueid.h" // _PyType_IncrefSlow
17+ #include "pycore_uniqueid.h" // _PyObject_ThreadIncrefSlow()
1818
1919// This value is added to `ob_ref_shared` for objects that use deferred
2020// reference counting so that they are not immediately deallocated when the
@@ -291,7 +291,31 @@ extern bool _PyRefchain_IsTraced(PyInterpreterState *interp, PyObject *obj);
291291#ifndef Py_GIL_DISABLED
292292# define _Py_INCREF_TYPE Py_INCREF
293293# define _Py_DECREF_TYPE Py_DECREF
294+ # define _Py_INCREF_CODE Py_INCREF
295+ # define _Py_DECREF_CODE Py_DECREF
294296#else
297+ static inline void
298+ _Py_THREAD_INCREF_OBJECT (PyObject * obj , Py_ssize_t unique_id )
299+ {
300+ _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
301+
302+ // Unsigned comparison so that `unique_id=-1`, which indicates that
303+ // per-thread refcounting has been disabled on this object, is handled by
304+ // the "else".
305+ if ((size_t )unique_id < (size_t )tstate -> refcounts .size ) {
306+ # ifdef Py_REF_DEBUG
307+ _Py_INCREF_IncRefTotal ();
308+ # endif
309+ _Py_INCREF_STAT_INC ();
310+ tstate -> refcounts .values [unique_id ]++ ;
311+ }
312+ else {
313+ // The slow path resizes the per-thread refcount array if necessary.
314+ // It handles the unique_id=-1 case to keep the inlinable function smaller.
315+ _PyObject_ThreadIncrefSlow (obj , unique_id );
316+ }
317+ }
318+
295319static inline void
296320_Py_INCREF_TYPE (PyTypeObject * type )
297321{
@@ -308,29 +332,38 @@ _Py_INCREF_TYPE(PyTypeObject *type)
308332# pragma GCC diagnostic push
309333# pragma GCC diagnostic ignored "-Warray-bounds"
310334#endif
335+ _Py_THREAD_INCREF_OBJECT ((PyObject * )type , ((PyHeapTypeObject * )type )-> unique_id );
336+ #if defined(__GNUC__ ) && __GNUC__ >= 11
337+ # pragma GCC diagnostic pop
338+ #endif
339+ }
340+
341+ static inline void
342+ _Py_INCREF_CODE (PyCodeObject * co )
343+ {
344+ _Py_THREAD_INCREF_OBJECT ((PyObject * )co , co -> _co_unique_id );
345+ }
311346
347+ static inline void
348+ _Py_THREAD_DECREF_OBJECT (PyObject * obj , Py_ssize_t unique_id )
349+ {
312350 _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
313- PyHeapTypeObject * ht = (PyHeapTypeObject * )type ;
314351
315352 // Unsigned comparison so that `unique_id=-1`, which indicates that
316- // per-thread refcounting has been disabled on this type , is handled by
353+ // per-thread refcounting has been disabled on this object , is handled by
317354 // the "else".
318- if ((size_t )ht -> unique_id < (size_t )tstate -> refcounts .size ) {
355+ if ((size_t )unique_id < (size_t )tstate -> refcounts .size ) {
319356# ifdef Py_REF_DEBUG
320- _Py_INCREF_IncRefTotal ();
357+ _Py_DECREF_DecRefTotal ();
321358# endif
322- _Py_INCREF_STAT_INC ();
323- tstate -> refcounts .values [ht -> unique_id ]++ ;
359+ _Py_DECREF_STAT_INC ();
360+ tstate -> refcounts .values [unique_id ]-- ;
324361 }
325362 else {
326- // The slow path resizes the thread-local refcount array if necessary.
327- // It handles the unique_id=-1 case to keep the inlinable function smaller .
328- _PyType_IncrefSlow ( ht );
363+ // Directly decref the object if the id is not assigned or if
364+ // per-thread refcounting has been disabled on this object .
365+ Py_DECREF ( obj );
329366 }
330-
331- #if defined(__GNUC__ ) && __GNUC__ >= 11
332- # pragma GCC diagnostic pop
333- #endif
334367}
335368
336369static inline void
@@ -341,25 +374,14 @@ _Py_DECREF_TYPE(PyTypeObject *type)
341374 _Py_DECREF_IMMORTAL_STAT_INC ();
342375 return ;
343376 }
344-
345- _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
346377 PyHeapTypeObject * ht = (PyHeapTypeObject * )type ;
378+ _Py_THREAD_DECREF_OBJECT ((PyObject * )type , ht -> unique_id );
379+ }
347380
348- // Unsigned comparison so that `unique_id=-1`, which indicates that
349- // per-thread refcounting has been disabled on this type, is handled by
350- // the "else".
351- if ((size_t )ht -> unique_id < (size_t )tstate -> refcounts .size ) {
352- # ifdef Py_REF_DEBUG
353- _Py_DECREF_DecRefTotal ();
354- # endif
355- _Py_DECREF_STAT_INC ();
356- tstate -> refcounts .values [ht -> unique_id ]-- ;
357- }
358- else {
359- // Directly decref the type if the type id is not assigned or if
360- // per-thread refcounting has been disabled on this type.
361- Py_DECREF (type );
362- }
381+ static inline void
382+ _Py_DECREF_CODE (PyCodeObject * co )
383+ {
384+ _Py_THREAD_DECREF_OBJECT ((PyObject * )co , co -> _co_unique_id );
363385}
364386#endif
365387
0 commit comments