Skip to content

Commit 24796ba

Browse files
markshannonseehwan80
authored andcommitted
pythonGH-125174: Make immortality "sticky" (pythonGH-131184)
1 parent 52a328d commit 24796ba

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

Include/refcount.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ having all the lower 32 bits set, which will avoid the reference count to go
4141
beyond the refcount limit. Immortality checks for reference count decreases will
4242
be done by checking the bit sign flag in the lower 32 bits.
4343
44+
To ensure that once an object becomes immortal, it remains immortal, the threshold
45+
for omitting increfs is much higher than for omitting decrefs. Consequently, once
46+
the refcount for an object exceeds _Py_IMMORTAL_MINIMUM_REFCNT it will gradually
47+
increase over time until it reaches _Py_IMMORTAL_INITIAL_REFCNT.
4448
*/
4549
#define _Py_IMMORTAL_INITIAL_REFCNT (3ULL << 30)
4650
#define _Py_IMMORTAL_MINIMUM_REFCNT (1ULL << 31)
@@ -288,7 +292,7 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
288292
}
289293
#elif SIZEOF_VOID_P > 4
290294
PY_UINT32_T cur_refcnt = op->ob_refcnt;
291-
if (((int32_t)cur_refcnt) < 0) {
295+
if (cur_refcnt >= _Py_IMMORTAL_INITIAL_REFCNT) {
292296
// the object is immortal
293297
_Py_INCREF_IMMORTAL_STAT_INC();
294298
return;

Lib/test/test_bigmem.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"""
1010

1111
from test import support
12-
from test.support import bigmemtest, _1G, _2G, _4G
12+
from test.support import bigmemtest, _1G, _2G, _4G, import_helper
13+
_testcapi = import_helper.import_module('_testcapi')
1314

1415
import unittest
1516
import operator
@@ -1257,6 +1258,27 @@ def test_dict(self, size):
12571258
d[size] = 1
12581259

12591260

1261+
class ImmortalityTest(unittest.TestCase):
1262+
1263+
@bigmemtest(size=_2G, memuse=pointer_size * 9/8)
1264+
def test_stickiness(self, size):
1265+
"""Check that immortality is "sticky", so that
1266+
once an object is immortal it remains so."""
1267+
if size < _2G:
1268+
# Not enough memory to cause immortality on overflow
1269+
return
1270+
o1 = o2 = o3 = o4 = o5 = o6 = o7 = o8 = object()
1271+
l = [o1] * (size-20)
1272+
self.assertFalse(_testcapi.is_immortal(o1))
1273+
for _ in range(30):
1274+
l.append(l[0])
1275+
self.assertTrue(_testcapi.is_immortal(o1))
1276+
del o2, o3, o4, o5, o6, o7, o8
1277+
self.assertTrue(_testcapi.is_immortal(o1))
1278+
del l
1279+
self.assertTrue(_testcapi.is_immortal(o1))
1280+
1281+
12601282
if __name__ == '__main__':
12611283
if len(sys.argv) > 1:
12621284
support.set_memlimit(sys.argv[1])

0 commit comments

Comments
 (0)