diff --git a/Include/object.h b/Include/object.h index dfeb43bda7d841..dd73da54ea73de 100644 --- a/Include/object.h +++ b/Include/object.h @@ -290,8 +290,14 @@ _Py_IsOwnedByCurrentThread(PyObject *ob) } #endif +PyAPI_FUNC(Py_ssize_t) _Py_GetRefcnt(PyObject *ob); + static inline Py_ssize_t Py_REFCNT(PyObject *ob) { -#if !defined(Py_GIL_DISABLED) +#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000 + // Stable ABI implements Py_SET_REFCNT() as a function call + // on limited C API version 3.13 and newer. + return _Py_GetRefcnt(ob); +#elif !defined(Py_GIL_DISABLED) return ob->ob_refcnt; #else uint32_t local = _Py_atomic_load_uint32_relaxed(&ob->ob_ref_local); diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 4976ac3642bbe4..94ac9ef344102b 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -903,6 +903,7 @@ def test_windows_feature_macros(self): "_Py_DecRef", "_Py_EllipsisObject", "_Py_FalseStruct", + "_Py_GetRefcnt", "_Py_IncRef", "_Py_NoneStruct", "_Py_NotImplementedStruct", diff --git a/Misc/NEWS.d/next/C API/2023-12-05-10-39-06.gh-issue-111506.gz90Ft.rst b/Misc/NEWS.d/next/C API/2023-12-05-10-39-06.gh-issue-111506.gz90Ft.rst new file mode 100644 index 00000000000000..9a9706c2b339f1 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-12-05-10-39-06.gh-issue-111506.gz90Ft.rst @@ -0,0 +1,2 @@ +In the limited C API version 3.13, the :c:func:`Py_REFCNT` function is now +implemented as an opaque function call. Patch by Victor Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 22b25dd0ec141f..ea5c87e635e4f3 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2478,6 +2478,9 @@ added = '3.13' [function.PySys_AuditTuple] added = '3.13' +[function._Py_GetRefcnt] + added = '3.13' + abi_only = true [function._Py_SetRefcnt] added = '3.13' abi_only = true diff --git a/Objects/object.c b/Objects/object.c index d145674cb3ba34..2d9eb92f092ac3 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2932,6 +2932,14 @@ int Py_IsFalse(PyObject *x) } +// Py_REFCNT() implementation for stable ABI +Py_ssize_t +_Py_GetRefcnt(PyObject *ob) +{ + return Py_REFCNT(ob); +} + + // Py_SET_REFCNT() implementation for stable ABI void _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt) diff --git a/PC/python3dll.c b/PC/python3dll.c index 07aa84c91f9fc7..db2822bd41d17f 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -17,6 +17,7 @@ EXPORT_FUNC(_Py_BuildValue_SizeT) EXPORT_FUNC(_Py_CheckRecursiveCall) EXPORT_FUNC(_Py_Dealloc) EXPORT_FUNC(_Py_DecRef) +EXPORT_FUNC(_Py_GetRefcnt) EXPORT_FUNC(_Py_IncRef) EXPORT_FUNC(_Py_NegativeRefcount) EXPORT_FUNC(_Py_SetRefcnt)