gh-111506: Implement Py_SET_REFCNT() as opaque function in limited C API (#111508)

In the limited C API version 3.13, Py_SET_REFCNT() function is now
implemented as an opaque function call.

Add _Py_SetRefcnt() to the stable ABI.
This commit is contained in:
Victor Stinner 2023-11-03 18:18:57 +01:00 committed by GitHub
parent e0afed7e27
commit 20cfab903d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 26 additions and 2 deletions

View file

@ -327,7 +327,15 @@ static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
#endif #endif
// Py_SET_REFCNT() implementation for stable ABI
PyAPI_FUNC(void) _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt);
static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
#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.
_Py_SetRefcnt(ob, refcnt);
#else
// This immortal check is for code that is unaware of immortal objects. // This immortal check is for code that is unaware of immortal objects.
// The runtime tracks these objects and we should avoid as much // The runtime tracks these objects and we should avoid as much
// as possible having extensions inadvertently change the refcnt // as possible having extensions inadvertently change the refcnt
@ -335,7 +343,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
if (_Py_IsImmortal(ob)) { if (_Py_IsImmortal(ob)) {
return; return;
} }
#if !defined(Py_NOGIL) #ifndef Py_NOGIL
ob->ob_refcnt = refcnt; ob->ob_refcnt = refcnt;
#else #else
if (_Py_IsOwnedByCurrentThread(ob)) { if (_Py_IsOwnedByCurrentThread(ob)) {
@ -352,7 +360,8 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
ob->ob_ref_local = 0; ob->ob_ref_local = 0;
ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED); ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED);
} }
#endif #endif // Py_NOGIL
#endif // Py_LIMITED_API+0 < 0x030d0000
} }
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
# define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt)) # define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt))

View file

@ -907,6 +907,7 @@ SYMBOL_NAMES = (
"_Py_IncRef", "_Py_IncRef",
"_Py_NoneStruct", "_Py_NoneStruct",
"_Py_NotImplementedStruct", "_Py_NotImplementedStruct",
"_Py_SetRefcnt",
"_Py_SwappedOp", "_Py_SwappedOp",
"_Py_TrueStruct", "_Py_TrueStruct",
"_Py_VaBuildValue_SizeT", "_Py_VaBuildValue_SizeT",

View file

@ -0,0 +1,2 @@
In the limited C API version 3.13, :c:func:`Py_SET_REFCNT` function is now
implemented as an opaque function call. Patch by Victor Stinner.

View file

@ -2480,3 +2480,6 @@
added = '3.13' added = '3.13'
[function.PyUnicode_AsUTF8] [function.PyUnicode_AsUTF8]
added = '3.13' added = '3.13'
[function._Py_SetRefcnt]
added = '3.13'
abi_only = true

View file

@ -2931,3 +2931,11 @@ int Py_IsFalse(PyObject *x)
{ {
return Py_Is(x, Py_False); return Py_Is(x, Py_False);
} }
// Py_SET_REFCNT() implementation for stable ABI
void
_Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
{
Py_SET_REFCNT(ob, refcnt);
}

1
PC/python3dll.c generated
View file

@ -19,6 +19,7 @@ EXPORT_FUNC(_Py_Dealloc)
EXPORT_FUNC(_Py_DecRef) EXPORT_FUNC(_Py_DecRef)
EXPORT_FUNC(_Py_IncRef) EXPORT_FUNC(_Py_IncRef)
EXPORT_FUNC(_Py_NegativeRefcount) EXPORT_FUNC(_Py_NegativeRefcount)
EXPORT_FUNC(_Py_SetRefcnt)
EXPORT_FUNC(_Py_VaBuildValue_SizeT) EXPORT_FUNC(_Py_VaBuildValue_SizeT)
EXPORT_FUNC(_PyArg_Parse_SizeT) EXPORT_FUNC(_PyArg_Parse_SizeT)
EXPORT_FUNC(_PyArg_ParseTuple_SizeT) EXPORT_FUNC(_PyArg_ParseTuple_SizeT)