@@ -157,6 +157,17 @@ static inline Py_ALWAYS_INLINE void _Py_CLEAR_IMMUTABLE(PyObject *op)
157157#endif
158158}
159159
160+ /** Currently, only cowns require atomic reference counting.
161+ * Immutable objects are handled separately.
162+ */
163+ static inline int _PyRegion_NeedsAtomicRc (PyObject * obj ) {
164+ // Cown objects always have their region set to `_Py_COWN_REGION`
165+ // directly. It's not possible to merge regions into the cown
166+ // region, therefore, we don't need to check if the region field
167+ // is part of a union find.
168+ return obj -> ob_region == _Py_COWN_REGION ;
169+ }
170+
160171// Py_REFCNT() implementation for the stable ABI
161172PyAPI_FUNC (Py_ssize_t ) Py_REFCNT (PyObject * ob );
162173
@@ -166,6 +177,10 @@ PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob);
166177#else
167178 static inline Py_ssize_t _Py_REFCNT (PyObject * ob ) {
168179 #if !defined(Py_GIL_DISABLED )
180+ // FIXME: This for some reason doesn't compile
181+ // if (_PyRegion_NeedsAtomicRc(ob)) {
182+ // return _Py_atomic_load_uint32_relaxed(&ob->ob_refcnt);
183+ // }
169184 return _Py_IMMUTABLE_FLAG_CLEAR (ob -> ob_refcnt );
170185 #else
171186 uint32_t local = _Py_atomic_load_uint32_relaxed (& ob -> ob_ref_local );
@@ -257,6 +272,9 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
257272 // TODO(Immutable): Care should be taken to make the whole SCC mutable
258273 // again if needed.
259274 }
275+ // FIXME: Setting the ref count for cowns is dangerous
276+ // investigate if this is really needed.
277+ assert (!_PyRegion_NeedsAtomicRc (ob ));
260278#ifndef Py_GIL_DISABLED
261279#if SIZEOF_VOID_P > 4
262280 ob -> ob_refcnt = (PY_UINT32_T )refcnt ;
@@ -403,7 +421,11 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
403421 return ;
404422#endif
405423 }
406- op -> ob_refcnt = (uint32_t )cur_refcnt + 1 ;
424+ if (_PyRegion_NeedsAtomicRc (op )) {
425+ _Py_atomic_add_uint32 (& op -> ob_refcnt , 1 );
426+ } else {
427+ op -> ob_refcnt = (uint32_t )cur_refcnt + 1 ;
428+ }
407429#else
408430 if (_Py_IsImmortalOrImmutable (op )) {
409431 if (_Py_IsImmortal (op )) {
@@ -576,7 +598,14 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
576598#endif
577599 }
578600 _Py_DECREF_STAT_INC ();
579- if (-- op -> ob_refcnt == 0 ) {
601+ uint32_t rc ;
602+ if (_PyRegion_NeedsAtomicRc (ob )) {
603+ rc = _Py_atomic_sub_uint32 (& ob -> ob_refcnt , 1 );
604+ } else {
605+ rc = -- op -> ob_refcnt ;
606+ }
607+
608+ if (rc == 0 ) {
580609 _Py_Dealloc (op );
581610 }
582611}
0 commit comments