@@ -14,10 +14,19 @@ extern "C" {
14
14
#include "pycore_interp.h" // PyInterpreterState.gc
15
15
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_PTR_RELAXED
16
16
#include "pycore_pystate.h" // _PyInterpreterState_GET()
17
+ #include "pycore_typeid.h" // _PyType_IncrefSlow
17
18
18
19
19
20
#define _Py_IMMORTAL_REFCNT_LOOSE ((_Py_IMMORTAL_REFCNT >> 1) + 1)
20
21
22
+ // This value is added to `ob_ref_shared` for objects that use deferred
23
+ // reference counting so that they are not immediately deallocated when the
24
+ // non-deferred reference count drops to zero.
25
+ //
26
+ // The value is half the maximum shared refcount because the low two bits of
27
+ // `ob_ref_shared` are used for flags.
28
+ #define _Py_REF_DEFERRED (PY_SSIZE_T_MAX / 8)
29
+
21
30
// gh-121528, gh-118997: Similar to _Py_IsImmortal() but be more loose when
22
31
// comparing the reference count to stay compatible with C extensions built
23
32
// with the stable ABI 3.11 or older. Such extensions implement INCREF/DECREF
@@ -280,6 +289,62 @@ extern PyStatus _PyObject_InitState(PyInterpreterState *interp);
280
289
extern void _PyObject_FiniState (PyInterpreterState * interp );
281
290
extern bool _PyRefchain_IsTraced (PyInterpreterState * interp , PyObject * obj );
282
291
292
+ static inline void
293
+ _Py_INCREF_TYPE (PyTypeObject * type )
294
+ {
295
+ #ifndef Py_GIL_DISABLED
296
+ Py_INCREF (type );
297
+ #else
298
+ if (!_PyType_HasFeature (type , Py_TPFLAGS_HEAPTYPE )) {
299
+ assert (_Py_IsImmortal (type ));
300
+ return ;
301
+ }
302
+
303
+ _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
304
+ PyHeapTypeObject * ht = (PyHeapTypeObject * )type ;
305
+
306
+ Py_ssize_t ht_id = ht -> _ht_id ;
307
+ if ((size_t )ht_id >= (size_t )tstate -> types .size ) {
308
+ _PyType_IncrefSlow (ht );
309
+ }
310
+ else {
311
+ # ifdef Py_REF_DEBUG
312
+ _Py_INCREF_IncRefTotal ();
313
+ # endif
314
+ _Py_INCREF_STAT_INC ();
315
+ tstate -> types .refcounts [ht_id ]++ ;
316
+ }
317
+ #endif
318
+ }
319
+
320
+ static inline void
321
+ _Py_DECREF_TYPE (PyTypeObject * type )
322
+ {
323
+ #ifndef Py_GIL_DISABLED
324
+ Py_DECREF (type );
325
+ #else
326
+ if (!_PyType_HasFeature (type , Py_TPFLAGS_HEAPTYPE )) {
327
+ assert (_Py_IsImmortal (type ));
328
+ return ;
329
+ }
330
+
331
+ _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
332
+ PyHeapTypeObject * ht = (PyHeapTypeObject * )type ;
333
+
334
+ Py_ssize_t ht_id = ht -> _ht_id ;
335
+ if ((size_t )ht_id >= (size_t )tstate -> types .size ) {
336
+ Py_DECREF (type );
337
+ }
338
+ else {
339
+ # ifdef Py_REF_DEBUG
340
+ _Py_DECREF_DecRefTotal ();
341
+ # endif
342
+ _Py_DECREF_STAT_INC ();
343
+ tstate -> types .refcounts [ht_id ]-- ;
344
+ }
345
+ #endif
346
+ }
347
+
283
348
/* Inline functions trading binary compatibility for speed:
284
349
_PyObject_Init() is the fast version of PyObject_Init(), and
285
350
_PyObject_InitVar() is the fast version of PyObject_InitVar().
@@ -291,7 +356,7 @@ _PyObject_Init(PyObject *op, PyTypeObject *typeobj)
291
356
assert (op != NULL );
292
357
Py_SET_TYPE (op , typeobj );
293
358
assert (_PyType_HasFeature (typeobj , Py_TPFLAGS_HEAPTYPE ) || _Py_IsImmortalLoose (typeobj ));
294
- Py_INCREF (typeobj );
359
+ _Py_INCREF_TYPE (typeobj );
295
360
_Py_NewReference (op );
296
361
}
297
362
0 commit comments