mirror of
https://github.com/python/cpython.git
synced 2025-11-25 21:11:09 +00:00
gh-84436: Implement Immortal Objects (gh-19474)
This is the implementation of PEP683 Motivation: The PR introduces the ability to immortalize instances in CPython which bypasses reference counting. Tagging objects as immortal allows up to skip certain operations when we know that the object will be around for the entire execution of the runtime. Note that this by itself will bring a performance regression to the runtime due to the extra reference count checks. However, this brings the ability of having truly immutable objects that are useful in other contexts such as immutable data sharing between sub-interpreters.
This commit is contained in:
parent
916de04fd1
commit
ea2c001650
35 changed files with 483 additions and 171 deletions
|
|
@ -1754,10 +1754,14 @@ none_repr(PyObject *op)
|
|||
return PyUnicode_FromString("None");
|
||||
}
|
||||
|
||||
static void _Py_NO_RETURN
|
||||
none_dealloc(PyObject* Py_UNUSED(ignore))
|
||||
static void
|
||||
none_dealloc(PyObject* none)
|
||||
{
|
||||
_Py_FatalRefcountError("deallocating None");
|
||||
/* This should never get called, but we also don't want to SEGV if
|
||||
* we accidentally decref None out of existence. Instead,
|
||||
* since None is an immortal object, re-set the reference count.
|
||||
*/
|
||||
_Py_SetImmortal(none);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
@ -1823,7 +1827,7 @@ PyTypeObject _PyNone_Type = {
|
|||
"NoneType",
|
||||
0,
|
||||
0,
|
||||
none_dealloc, /*tp_dealloc*/ /*never called*/
|
||||
none_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_vectorcall_offset*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
|
|
@ -1860,8 +1864,9 @@ PyTypeObject _PyNone_Type = {
|
|||
};
|
||||
|
||||
PyObject _Py_NoneStruct = {
|
||||
_PyObject_EXTRA_INIT
|
||||
1, &_PyNone_Type
|
||||
_PyObject_EXTRA_INIT
|
||||
{ _Py_IMMORTAL_REFCNT },
|
||||
&_PyNone_Type
|
||||
};
|
||||
|
||||
/* NotImplemented is an object that can be used to signal that an
|
||||
|
|
@ -1894,13 +1899,14 @@ notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||
Py_RETURN_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
static void _Py_NO_RETURN
|
||||
notimplemented_dealloc(PyObject* ignore)
|
||||
static void
|
||||
notimplemented_dealloc(PyObject *notimplemented)
|
||||
{
|
||||
/* This should never get called, but we also don't want to SEGV if
|
||||
* we accidentally decref NotImplemented out of existence.
|
||||
* we accidentally decref NotImplemented out of existence. Instead,
|
||||
* since Notimplemented is an immortal object, re-set the reference count.
|
||||
*/
|
||||
Py_FatalError("deallocating NotImplemented");
|
||||
_Py_SetImmortal(notimplemented);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1962,7 +1968,8 @@ PyTypeObject _PyNotImplemented_Type = {
|
|||
|
||||
PyObject _Py_NotImplementedStruct = {
|
||||
_PyObject_EXTRA_INIT
|
||||
1, &_PyNotImplemented_Type
|
||||
{ _Py_IMMORTAL_REFCNT },
|
||||
&_PyNotImplemented_Type
|
||||
};
|
||||
|
||||
extern PyTypeObject _Py_GenericAliasIterType;
|
||||
|
|
@ -2143,7 +2150,8 @@ new_reference(PyObject *op)
|
|||
if (_PyRuntime.tracemalloc.config.tracing) {
|
||||
_PyTraceMalloc_NewReference(op);
|
||||
}
|
||||
Py_SET_REFCNT(op, 1);
|
||||
// Skip the immortal object check in Py_SET_REFCNT; always set refcnt to 1
|
||||
op->ob_refcnt = 1;
|
||||
#ifdef Py_TRACE_REFS
|
||||
_Py_AddToAllObjects(op, 1);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue