Skip to content

Commit dee7b3d

Browse files
authored
Update pythoncapi_compat.h (#21257)
1 parent ebaa73a commit dee7b3d

File tree

1 file changed

+154
-34
lines changed

1 file changed

+154
-34
lines changed

mypyc/lib-rt/pythoncapi_compat.h

Lines changed: 154 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ extern "C" {
2525
#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
2626
# include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
2727
#endif
28-
#if PY_VERSION_HEX < 0x030C00A3
29-
# include <structmember.h> // T_SHORT, READONLY
30-
#endif
3128

3229

3330
#ifndef _Py_CAST
@@ -1428,6 +1425,11 @@ PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
14281425
static inline int
14291426
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
14301427
{
1428+
if (obj == NULL) {
1429+
return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer,
1430+
"<NULL>", 6);
1431+
}
1432+
14311433
PyObject *str = PyObject_Repr(obj);
14321434
if (str == NULL) {
14331435
return -1;
@@ -1572,6 +1574,11 @@ static inline int PyLong_IsZero(PyObject *obj)
15721574

15731575
// gh-124502 added PyUnicode_Equal() to Python 3.14.0a0
15741576
#if PY_VERSION_HEX < 0x030E00A0
1577+
1578+
#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION)
1579+
PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2);
1580+
#endif
1581+
15751582
static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2)
15761583
{
15771584
if (!PyUnicode_Check(str1)) {
@@ -1586,8 +1593,6 @@ static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2)
15861593
}
15871594

15881595
#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION)
1589-
PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2);
1590-
15911596
return _PyUnicode_Equal(str1, str2);
15921597
#elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
15931598
return _PyUnicode_EQ(str1, str2);
@@ -1610,11 +1615,14 @@ static inline PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable)
16101615

16111616

16121617
#if PY_VERSION_HEX < 0x030E00A0
1618+
1619+
#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
1620+
PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len);
1621+
#endif
1622+
16131623
static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len)
16141624
{
16151625
#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
1616-
PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len);
1617-
16181626
return _Py_HashBytes(ptr, len);
16191627
#else
16201628
Py_hash_t hash;
@@ -1919,43 +1927,46 @@ PyLongWriter_Finish(PyLongWriter *writer)
19191927

19201928

19211929
#if PY_VERSION_HEX < 0x030C00A3
1922-
# define Py_T_SHORT T_SHORT
1923-
# define Py_T_INT T_INT
1924-
# define Py_T_LONG T_LONG
1925-
# define Py_T_FLOAT T_FLOAT
1926-
# define Py_T_DOUBLE T_DOUBLE
1927-
# define Py_T_STRING T_STRING
1928-
# define _Py_T_OBJECT T_OBJECT
1929-
# define Py_T_CHAR T_CHAR
1930-
# define Py_T_BYTE T_BYTE
1931-
# define Py_T_UBYTE T_UBYTE
1932-
# define Py_T_USHORT T_USHORT
1933-
# define Py_T_UINT T_UINT
1934-
# define Py_T_ULONG T_ULONG
1935-
# define Py_T_STRING_INPLACE T_STRING_INPLACE
1936-
# define Py_T_BOOL T_BOOL
1937-
# define Py_T_OBJECT_EX T_OBJECT_EX
1938-
# define Py_T_LONGLONG T_LONGLONG
1939-
# define Py_T_ULONGLONG T_ULONGLONG
1940-
# define Py_T_PYSSIZET T_PYSSIZET
1930+
# define Py_T_SHORT 0
1931+
# define Py_T_INT 1
1932+
# define Py_T_LONG 2
1933+
# define Py_T_FLOAT 3
1934+
# define Py_T_DOUBLE 4
1935+
# define Py_T_STRING 5
1936+
# define _Py_T_OBJECT 6
1937+
# define Py_T_CHAR 7
1938+
# define Py_T_BYTE 8
1939+
# define Py_T_UBYTE 9
1940+
# define Py_T_USHORT 10
1941+
# define Py_T_UINT 11
1942+
# define Py_T_ULONG 12
1943+
# define Py_T_STRING_INPLACE 13
1944+
# define Py_T_BOOL 14
1945+
# define Py_T_OBJECT_EX 16
1946+
# define Py_T_LONGLONG 17
1947+
# define Py_T_ULONGLONG 18
1948+
# define Py_T_PYSSIZET 19
19411949

19421950
# if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
1943-
# define _Py_T_NONE T_NONE
1951+
# define _Py_T_NONE 20
19441952
# endif
19451953

1946-
# define Py_READONLY READONLY
1947-
# define Py_AUDIT_READ READ_RESTRICTED
1948-
# define _Py_WRITE_RESTRICTED PY_WRITE_RESTRICTED
1954+
# define Py_READONLY 1
1955+
# define Py_AUDIT_READ 2
1956+
# define _Py_WRITE_RESTRICTED 4
19491957
#endif
19501958

19511959

19521960
// gh-127350 added Py_fopen() and Py_fclose() to Python 3.14a4
19531961
#if PY_VERSION_HEX < 0x030E00A4
1962+
1963+
#if 0x030400A2 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
1964+
PyAPI_FUNC(FILE*) _Py_fopen_obj(PyObject *path, const char *mode);
1965+
#endif
1966+
19541967
static inline FILE* Py_fopen(PyObject *path, const char *mode)
19551968
{
19561969
#if 0x030400A2 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
1957-
PyAPI_FUNC(FILE*) _Py_fopen_obj(PyObject *path, const char *mode);
1958-
19591970
return _Py_fopen_obj(path, mode);
19601971
#else
19611972
FILE *f;
@@ -1992,6 +2003,8 @@ static inline int Py_fclose(FILE *file)
19922003

19932004

19942005
#if 0x03080000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION)
2006+
PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
2007+
19952008
static inline PyObject*
19962009
PyConfig_Get(const char *name)
19972010
{
@@ -2127,8 +2140,6 @@ PyConfig_Get(const char *name)
21272140
return Py_NewRef(value);
21282141
}
21292142

2130-
PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
2131-
21322143
const PyConfig *config = _Py_GetConfig();
21332144
void *member = (char *)config + spec->offset;
21342145
switch (spec->type) {
@@ -2231,6 +2242,81 @@ static inline int PyUnstable_Object_IsUniquelyReferenced(PyObject *obj)
22312242
}
22322243
#endif
22332244

2245+
// gh-128926 added PyUnstable_TryIncRef() and PyUnstable_EnableTryIncRef() to
2246+
// Python 3.14.0a5. Adapted from _Py_TryIncref() and _PyObject_SetMaybeWeakref().
2247+
#if PY_VERSION_HEX < 0x030E00A5
2248+
static inline int PyUnstable_TryIncRef(PyObject *op)
2249+
{
2250+
#ifndef Py_GIL_DISABLED
2251+
if (Py_REFCNT(op) > 0) {
2252+
Py_INCREF(op);
2253+
return 1;
2254+
}
2255+
return 0;
2256+
#else
2257+
// _Py_TryIncrefFast()
2258+
uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local);
2259+
local += 1;
2260+
if (local == 0) {
2261+
// immortal
2262+
return 1;
2263+
}
2264+
if (_Py_IsOwnedByCurrentThread(op)) {
2265+
_Py_INCREF_STAT_INC();
2266+
_Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local);
2267+
#ifdef Py_REF_DEBUG
2268+
_Py_INCREF_IncRefTotal();
2269+
#endif
2270+
return 1;
2271+
}
2272+
2273+
// _Py_TryIncRefShared()
2274+
Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared);
2275+
for (;;) {
2276+
// If the shared refcount is zero and the object is either merged
2277+
// or may not have weak references, then we cannot incref it.
2278+
if (shared == 0 || shared == _Py_REF_MERGED) {
2279+
return 0;
2280+
}
2281+
2282+
if (_Py_atomic_compare_exchange_ssize(
2283+
&op->ob_ref_shared,
2284+
&shared,
2285+
shared + (1 << _Py_REF_SHARED_SHIFT))) {
2286+
#ifdef Py_REF_DEBUG
2287+
_Py_INCREF_IncRefTotal();
2288+
#endif
2289+
_Py_INCREF_STAT_INC();
2290+
return 1;
2291+
}
2292+
}
2293+
#endif
2294+
}
2295+
2296+
static inline void PyUnstable_EnableTryIncRef(PyObject *op)
2297+
{
2298+
#ifdef Py_GIL_DISABLED
2299+
// _PyObject_SetMaybeWeakref()
2300+
if (_Py_IsImmortal(op)) {
2301+
return;
2302+
}
2303+
for (;;) {
2304+
Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared);
2305+
if ((shared & _Py_REF_SHARED_FLAG_MASK) != 0) {
2306+
// Nothing to do if it's in WEAKREFS, QUEUED, or MERGED states.
2307+
return;
2308+
}
2309+
if (_Py_atomic_compare_exchange_ssize(
2310+
&op->ob_ref_shared, &shared, shared | _Py_REF_MAYBE_WEAKREF)) {
2311+
return;
2312+
}
2313+
}
2314+
#else
2315+
(void)op; // unused argument
2316+
#endif
2317+
}
2318+
#endif
2319+
22342320

22352321
#if PY_VERSION_HEX < 0x030F0000
22362322
static inline PyObject*
@@ -2587,6 +2673,40 @@ PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op)
25872673
}
25882674
#endif
25892675

2676+
#if 0x030D0000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030F00A7 && !defined(PYPY_VERSION)
2677+
// Immortal objects were implemented in Python 3.12, however there is no easy API
2678+
// to make objects immortal until 3.14 which has _Py_SetImmortal(). Since
2679+
// immortal objects are primarily needed for free-threading, this API is implemented
2680+
// for 3.14 using _Py_SetImmortal() and uses private macros on 3.13.
2681+
#if 0x030E0000 <= PY_VERSION_HEX
2682+
PyAPI_FUNC(void) _Py_SetImmortal(PyObject *op);
2683+
#endif
2684+
2685+
static inline int
2686+
PyUnstable_SetImmortal(PyObject *op)
2687+
{
2688+
assert(op != NULL);
2689+
if (!PyUnstable_Object_IsUniquelyReferenced(op) || PyUnicode_Check(op)) {
2690+
return 0;
2691+
}
2692+
#if 0x030E0000 <= PY_VERSION_HEX
2693+
_Py_SetImmortal(op);
2694+
#else
2695+
// Python 3.13 doesn't export _Py_SetImmortal() function
2696+
if (PyObject_GC_IsTracked(op)) {
2697+
PyObject_GC_UnTrack(op);
2698+
}
2699+
#ifdef Py_GIL_DISABLED
2700+
op->ob_tid = _Py_UNOWNED_TID;
2701+
op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL;
2702+
op->ob_ref_shared = 0;
2703+
#else
2704+
op->ob_refcnt = _Py_IMMORTAL_REFCNT;
2705+
#endif
2706+
#endif
2707+
return 1;
2708+
}
2709+
#endif
25902710

25912711
#ifdef __cplusplus
25922712
}

0 commit comments

Comments
 (0)