Skip to content

Commit 58b73a1

Browse files
Add PyUnstable_SetImmortal
1 parent 11cb80f commit 58b73a1

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

pythoncapi_compat.h

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

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

26632675
#ifdef __cplusplus
26642676
}

tests/test_pythoncapi_compat_cext.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,6 +2489,43 @@ 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 = {0};
2497+
#ifdef Py_GIL_DISABLED
2498+
object.ob_tid = _Py_ThreadId();
2499+
object.ob_gc_bits = 0;
2500+
object.ob_ref_local = 1;
2501+
object.ob_ref_shared = 0;
2502+
#else
2503+
object.ob_refcnt = 1;
2504+
#endif
2505+
object.ob_type = &PyBaseObject_Type;
2506+
2507+
assert(!PyUnstable_IsImmortal(&object));
2508+
int rc = PyUnstable_SetImmortal(&object);
2509+
assert(rc == 1);
2510+
assert(PyUnstable_IsImmortal(&object));
2511+
Py_DECREF(&object); // should not dealloc
2512+
assert(PyUnstable_IsImmortal(&object));
2513+
2514+
// Check already immortal object
2515+
rc = PyUnstable_SetImmortal(&object);
2516+
assert(rc == 0);
2517+
2518+
// Check unicode objects
2519+
PyObject *unicode = PyUnicode_FromString("test");
2520+
assert(!PyUnstable_IsImmortal(unicode));
2521+
rc = PyUnstable_SetImmortal(unicode);
2522+
assert(rc == 0);
2523+
assert(!PyUnstable_IsImmortal(unicode));
2524+
Py_DECREF(unicode);
2525+
Py_RETURN_NONE;
2526+
}
2527+
#endif
2528+
24922529

24932530
static struct PyMethodDef methods[] = {
24942531
{"test_object", test_object, METH_NOARGS, _Py_NULL},
@@ -2546,6 +2583,9 @@ static struct PyMethodDef methods[] = {
25462583
{"test_byteswriter", test_byteswriter, METH_NOARGS, _Py_NULL},
25472584
{"test_tuple", test_tuple, METH_NOARGS, _Py_NULL},
25482585
{"test_try_incref", test_try_incref, METH_NOARGS, _Py_NULL},
2586+
#ifdef 0x030C0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
2587+
{"test_set_immortal", test_set_immortal, METH_NOARGS, _Py_NULL},
2588+
#endif
25492589
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
25502590
};
25512591

0 commit comments

Comments
 (0)