aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python
diff options
context:
space:
mode:
authorEddie Elizondo <eduardo.elizondorueda@gmail.com>2023-04-22 15:39:37 -0400
committerGitHub <noreply@github.com>2023-04-22 13:39:37 -0600
commitea2c0016502472aa8baa3149050ada776d17a009 (patch)
treee9e3935a9b71a1f88ac18c24fe512d199880ff90 /Python
parent916de04fd1838530096336aadb3b94b774ed6c90 (diff)
downloadcpython-ea2c0016502472aa8baa3149050ada776d17a009.tar.gz
cpython-ea2c0016502472aa8baa3149050ada776d17a009.zip
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.
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c10
-rw-r--r--Python/clinic/sysmodule.c.h30
-rw-r--r--Python/instrumentation.c4
-rw-r--r--Python/legacy_tracing.c2
-rw-r--r--Python/pylifecycle.c5
-rw-r--r--Python/sysmodule.c13
6 files changed, 53 insertions, 11 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index d8495da81e9..358835024fd 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -53,8 +53,11 @@
#undef Py_DECREF
#define Py_DECREF(arg) \
do { \
- _Py_DECREF_STAT_INC(); \
PyObject *op = _PyObject_CAST(arg); \
+ if (_Py_IsImmortal(op)) { \
+ break; \
+ } \
+ _Py_DECREF_STAT_INC(); \
if (--op->ob_refcnt == 0) { \
destructor dealloc = Py_TYPE(op)->tp_dealloc; \
(*dealloc)(op); \
@@ -77,8 +80,11 @@
#undef _Py_DECREF_SPECIALIZED
#define _Py_DECREF_SPECIALIZED(arg, dealloc) \
do { \
- _Py_DECREF_STAT_INC(); \
PyObject *op = _PyObject_CAST(arg); \
+ if (_Py_IsImmortal(op)) { \
+ break; \
+ } \
+ _Py_DECREF_STAT_INC(); \
if (--op->ob_refcnt == 0) { \
destructor d = (destructor)(dealloc); \
d(op); \
diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h
index 46252dd4043..7a7c188bccc 100644
--- a/Python/clinic/sysmodule.c.h
+++ b/Python/clinic/sysmodule.c.h
@@ -912,6 +912,34 @@ exit:
return return_value;
}
+PyDoc_STRVAR(sys_getunicodeinternedsize__doc__,
+"getunicodeinternedsize($module, /)\n"
+"--\n"
+"\n"
+"Return the number of elements of the unicode interned dictionary");
+
+#define SYS_GETUNICODEINTERNEDSIZE_METHODDEF \
+ {"getunicodeinternedsize", (PyCFunction)sys_getunicodeinternedsize, METH_NOARGS, sys_getunicodeinternedsize__doc__},
+
+static Py_ssize_t
+sys_getunicodeinternedsize_impl(PyObject *module);
+
+static PyObject *
+sys_getunicodeinternedsize(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t _return_value;
+
+ _return_value = sys_getunicodeinternedsize_impl(module);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyLong_FromSsize_t(_return_value);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(sys__getframe__doc__,
"_getframe($module, depth=0, /)\n"
"--\n"
@@ -1387,4 +1415,4 @@ exit:
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
#define SYS_GETANDROIDAPILEVEL_METHODDEF
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
-/*[clinic end generated code: output=5c761f14326ced54 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6d598acc26237fbe input=a9049054013a1b77]*/
diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index 2a3b2b8ebee..8334f596eb3 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -16,13 +16,13 @@
static PyObject DISABLE =
{
- .ob_refcnt = _PyObject_IMMORTAL_REFCNT,
+ .ob_refcnt = _Py_IMMORTAL_REFCNT,
.ob_type = &PyBaseObject_Type
};
PyObject _PyInstrumentation_MISSING =
{
- .ob_refcnt = _PyObject_IMMORTAL_REFCNT,
+ .ob_refcnt = _Py_IMMORTAL_REFCNT,
.ob_type = &PyBaseObject_Type
};
diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c
index cf345bddda7..e509e63a087 100644
--- a/Python/legacy_tracing.c
+++ b/Python/legacy_tracing.c
@@ -324,7 +324,7 @@ sys_trace_exception_handled(
PyTypeObject _PyLegacyEventHandler_Type = {
- _PyVarObject_IMMORTAL_INIT(&PyType_Type, 0),
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
"sys.legacy_event_handler",
sizeof(_PyLegacyEventHandler),
.tp_dealloc = (destructor)PyObject_Free,
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index d6627bc6b7e..a510c9b2216 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -808,11 +808,6 @@ pycore_interp_init(PyThreadState *tstate)
PyStatus status;
PyObject *sysmod = NULL;
- // This is a temporary fix until we have immortal objects.
- // (See _PyType_InitCache() in typeobject.c.)
- extern void _PyType_FixCacheRefcounts(void);
- _PyType_FixCacheRefcounts();
-
// Create singletons before the first PyType_Ready() call, since
// PyType_Ready() uses singletons like the Unicode empty string (tp_doc)
// and the empty tuple singletons (tp_bases).
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 4d693a1be1f..1e42e8dfceb 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1874,6 +1874,18 @@ sys_getallocatedblocks_impl(PyObject *module)
return _Py_GetAllocatedBlocks();
}
+/*[clinic input]
+sys.getunicodeinternedsize -> Py_ssize_t
+
+Return the number of elements of the unicode interned dictionary
+[clinic start generated code]*/
+
+static Py_ssize_t
+sys_getunicodeinternedsize_impl(PyObject *module)
+/*[clinic end generated code: output=ad0e4c9738ed4129 input=726298eaa063347a]*/
+{
+ return _PyUnicode_InternedSize();
+}
/*[clinic input]
sys._getframe
@@ -2243,6 +2255,7 @@ static PyMethodDef sys_methods[] = {
SYS_GETDEFAULTENCODING_METHODDEF
SYS_GETDLOPENFLAGS_METHODDEF
SYS_GETALLOCATEDBLOCKS_METHODDEF
+ SYS_GETUNICODEINTERNEDSIZE_METHODDEF
SYS_GETFILESYSTEMENCODING_METHODDEF
SYS_GETFILESYSTEMENCODEERRORS_METHODDEF
#ifdef Py_TRACE_REFS