Skip to content

Commit a57ea4e

Browse files
Add PyUnstable_SetImmortal
1 parent 11cb80f commit a57ea4e

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

pythoncapi_compat.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2659,6 +2659,19 @@ PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op)
26592659
}
26602660
#endif
26612661

2662+
#if 0x030C0000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030F00A7 && !defined(PYPY_VERSION)
2663+
extern void _Py_SetImmortal(PyObject *op);
2664+
static inline int
2665+
PyUnstable_SetImmortal(PyObject *op)
2666+
{
2667+
assert(op != NULL);
2668+
if (!PyUnstable_Object_IsUniquelyReferenced(op) || PyUnicode_Check(op)) {
2669+
return 0;
2670+
}
2671+
_Py_SetImmortal(op);
2672+
return 1;
2673+
}
2674+
#endif
26622675

26632676
#ifdef __cplusplus
26642677
}

tests/test_pythoncapi_compat_cext.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,6 +2489,39 @@ test_try_incref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
24892489
Py_RETURN_NONE;
24902490
}
24912491

2492+
#if 0x030C0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
2493+
static PyObject *
2494+
test_set_immortal(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
2495+
{
2496+
PyObject object;
2497+
memset(&object, 0, sizeof(PyObject));
2498+
#ifdef Py_GIL_DISABLED
2499+
object.ob_tid = _Py_ThreadId();
2500+
object.ob_gc_bits = 0;
2501+
object.ob_ref_local = 1;
2502+
object.ob_ref_shared = 0;
2503+
#else
2504+
object.ob_refcnt = 1;
2505+
#endif
2506+
object.ob_type = &PyBaseObject_Type;
2507+
2508+
int rc = PyUnstable_SetImmortal(&object);
2509+
assert(rc == 1);
2510+
Py_DECREF(&object); // should not dealloc
2511+
2512+
// Check already immortal object
2513+
rc = PyUnstable_SetImmortal(&object);
2514+
assert(rc == 0);
2515+
2516+
// Check unicode objects
2517+
PyObject *unicode = PyUnicode_FromString("test");
2518+
rc = PyUnstable_SetImmortal(unicode);
2519+
assert(rc == 0);
2520+
Py_DECREF(unicode);
2521+
Py_RETURN_NONE;
2522+
}
2523+
#endif
2524+
24922525

24932526
static struct PyMethodDef methods[] = {
24942527
{"test_object", test_object, METH_NOARGS, _Py_NULL},
@@ -2546,6 +2579,9 @@ static struct PyMethodDef methods[] = {
25462579
{"test_byteswriter", test_byteswriter, METH_NOARGS, _Py_NULL},
25472580
{"test_tuple", test_tuple, METH_NOARGS, _Py_NULL},
25482581
{"test_try_incref", test_try_incref, METH_NOARGS, _Py_NULL},
2582+
#if 0x030C0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
2583+
{"test_set_immortal", test_set_immortal, METH_NOARGS, _Py_NULL},
2584+
#endif
25492585
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
25502586
};
25512587

0 commit comments

Comments
 (0)