gh-124127: Make Py_REFCNT() opaque in limited C API 3.14 (#124128)

This commit is contained in:
Victor Stinner 2024-09-24 08:42:58 +02:00 committed by GitHub
parent b82f07653e
commit 9d344fafc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 44 additions and 17 deletions

View File

@ -881,6 +881,7 @@ func,Py_Main,3.2,,
func,Py_MakePendingCalls,3.2,, func,Py_MakePendingCalls,3.2,,
func,Py_NewInterpreter,3.2,, func,Py_NewInterpreter,3.2,,
func,Py_NewRef,3.10,, func,Py_NewRef,3.10,,
func,Py_REFCNT,3.14,,
func,Py_ReprEnter,3.2,, func,Py_ReprEnter,3.2,,
func,Py_ReprLeave,3.2,, func,Py_ReprLeave,3.2,,
func,Py_SetProgramName,3.2,, func,Py_SetProgramName,3.2,,

View File

@ -650,9 +650,10 @@ New Features
Porting to Python 3.14 Porting to Python 3.14
---------------------- ----------------------
* In the limited C API 3.14 and newer, :c:func:`Py_TYPE` is now implemented as * In the limited C API 3.14 and newer, :c:func:`Py_TYPE` and
an opaque function call to hide implementation details. :c:func:`Py_REFCNT` are now implemented as an opaque function call to hide
(Contributed by Victor Stinner in :gh:`120600`.) implementation details.
(Contributed by Victor Stinner in :gh:`120600` and :gh:`124127`.)
Deprecated Deprecated

View File

@ -77,21 +77,29 @@ check by comparing the reference count field to the immortality reference count.
#endif // Py_GIL_DISABLED #endif // Py_GIL_DISABLED
static inline Py_ssize_t Py_REFCNT(PyObject *ob) { // Py_REFCNT() implementation for the stable ABI
#if !defined(Py_GIL_DISABLED) PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob);
return ob->ob_refcnt;
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030e0000
// Stable ABI implements Py_REFCNT() as a function call
// on limited C API version 3.14 and newer.
#else #else
uint32_t local = _Py_atomic_load_uint32_relaxed(&ob->ob_ref_local); static inline Py_ssize_t _Py_REFCNT(PyObject *ob) {
if (local == _Py_IMMORTAL_REFCNT_LOCAL) { #if !defined(Py_GIL_DISABLED)
return _Py_IMMORTAL_REFCNT; return ob->ob_refcnt;
#else
uint32_t local = _Py_atomic_load_uint32_relaxed(&ob->ob_ref_local);
if (local == _Py_IMMORTAL_REFCNT_LOCAL) {
return _Py_IMMORTAL_REFCNT;
}
Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&ob->ob_ref_shared);
return _Py_STATIC_CAST(Py_ssize_t, local) +
Py_ARITHMETIC_RIGHT_SHIFT(Py_ssize_t, shared, _Py_REF_SHARED_SHIFT);
#endif
} }
Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&ob->ob_ref_shared); #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
return _Py_STATIC_CAST(Py_ssize_t, local) + # define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST(ob))
Py_ARITHMETIC_RIGHT_SHIFT(Py_ssize_t, shared, _Py_REF_SHARED_SHIFT); #endif
#endif
}
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
# define Py_REFCNT(ob) Py_REFCNT(_PyObject_CAST(ob))
#endif #endif

View File

@ -899,6 +899,7 @@ SYMBOL_NAMES = (
"Py_MakePendingCalls", "Py_MakePendingCalls",
"Py_NewInterpreter", "Py_NewInterpreter",
"Py_NewRef", "Py_NewRef",
"Py_REFCNT",
"Py_ReprEnter", "Py_ReprEnter",
"Py_ReprLeave", "Py_ReprLeave",
"Py_SetPath", "Py_SetPath",

View File

@ -0,0 +1,3 @@
In the limited C API 3.14 and newer, :c:func:`Py_REFCNT` is now implemented
as an opaque function call to hide implementation details. Patch by Victor
Stinner.

View File

@ -2508,6 +2508,8 @@
[function.Py_TYPE] [function.Py_TYPE]
added = '3.14' added = '3.14'
[function.Py_REFCNT]
added = '3.14'
[function.PyIter_NextItem] [function.PyIter_NextItem]
added = '3.14' added = '3.14'
[function.PyLong_FromInt32] [function.PyLong_FromInt32]

View File

@ -3039,7 +3039,17 @@ Py_GetConstantBorrowed(unsigned int constant_id)
// Py_TYPE() implementation for the stable ABI // Py_TYPE() implementation for the stable ABI
#undef Py_TYPE #undef Py_TYPE
PyTypeObject* Py_TYPE(PyObject *ob) PyTypeObject*
Py_TYPE(PyObject *ob)
{ {
return _Py_TYPE(ob); return _Py_TYPE(ob);
} }
// Py_REFCNT() implementation for the stable ABI
#undef Py_REFCNT
Py_ssize_t
Py_REFCNT(PyObject *ob)
{
return _Py_REFCNT(ob);
}

1
PC/python3dll.c generated
View File

@ -81,6 +81,7 @@ EXPORT_FUNC(Py_Main)
EXPORT_FUNC(Py_MakePendingCalls) EXPORT_FUNC(Py_MakePendingCalls)
EXPORT_FUNC(Py_NewInterpreter) EXPORT_FUNC(Py_NewInterpreter)
EXPORT_FUNC(Py_NewRef) EXPORT_FUNC(Py_NewRef)
EXPORT_FUNC(Py_REFCNT)
EXPORT_FUNC(Py_ReprEnter) EXPORT_FUNC(Py_ReprEnter)
EXPORT_FUNC(Py_ReprLeave) EXPORT_FUNC(Py_ReprLeave)
EXPORT_FUNC(Py_SetPath) EXPORT_FUNC(Py_SetPath)