
On Wed, Feb 16, 2022 at 12:14 PM Kevin Modzelewski <kevmod@gmail.com> wrote:
fwiw Pyston has immortal objects, though with a slightly different goal and thus design [1]. I'm not necessarily advocating for our design (it makes most sense if there is a JIT involved), but just writing to report our experience of making a change like this and the compatibility effects.
Thanks!
Importantly, our system allows for the reference count of immortal objects to change, as long as it doesn't go below half of the original very-high value. So extension code with no concept of immortality will still update the reference counts of immortal objects, but this is fine. Because of this we haven't seen any issues with extension modules.
As Guido noted, we are taking a similar approach for the sake of older extensions built with the limited API. As a precaution, we start the refcount for immortal objects basically at _Py_IMMORTAL_REFCNT * 1.5. Then we only need to check the high bit of _Py_IMMORTAL_REFCNT to see if an object is immortal.
The small amount of compatibility challenges we've run into have been in testing code that checks for memory leaks. For example this code breaks on Pyston: [snip] This might work with this PEP, but we've also seen code that asserts that the refcount increases by a specific value, which I believe wouldn't.
Right, this is less of an issue for us since normally we do not change the refcount of immortal objects. Also, CPython's test suite keeps us honest about leaking references and memory blocks. :)
For Pyston we've simply disabled these tests, figuring that our users still have CPython to test on. Personally I consider this breakage to be small, but I hadn't seen anyone mention the potential usage of sys.getrefcount() so I thought I'd bring it up.
Thanks again for that.
[1] Our goal is to entirely remove refcounting operations when we can prove we are operating on an immortal object. We can prove it in a couple cases: sometimes simply, such as in Py_RETURN_NONE, but mostly our JIT will often know the immortality of objects it embeds into the code. So if we can prove statically that an object is immortal then we elide the incref/decrefs, and if we can't then we use an unmodified Py_INCREF/Py_DECREF. This means that our reference counts on immortal objects will change, so we detect immortality by checking if the reference count is at least half of the original very-high value.
FWIW, we anticipate that we can take a similar approach in CPython's eval loop, specializing for immortal objects. We are also updating Py_RETURN_NONE, etc. to stop incref'ing. -eric