]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-94673: Ensure Builtin Static Types are Readied Properly (gh-103940)
authorEric Snow <ericsnowcurrently@gmail.com>
Thu, 27 Apr 2023 22:19:43 +0000 (16:19 -0600)
committerGitHub <noreply@github.com>
Thu, 27 Apr 2023 22:19:43 +0000 (16:19 -0600)
There were cases where we do unnecessary work for builtin static types. This also simplifies some work necessary for a per-interpreter GIL.

21 files changed:
Include/internal/pycore_bytesobject.h
Include/internal/pycore_tuple.h
Modules/_io/_iomodule.c
Modules/mathmodule.c
Modules/symtablemodule.c
Objects/bytesobject.c
Objects/classobject.c
Objects/exceptions.c
Objects/floatobject.c
Objects/longobject.c
Objects/object.c
Objects/structseq.c
Objects/tupleobject.c
Objects/typeobject.c
Objects/unicodeobject.c
Python/bltinmodule.c
Python/errors.c
Python/modsupport.c
Python/pylifecycle.c
Python/sysmodule.c
Python/thread.c

index 9173a4f105f80084d3b8572d2277a7a44c1c3a5e..d36fa9569d64a56567660395491f438a5e5feab9 100644 (file)
@@ -9,11 +9,6 @@ extern "C" {
 #endif
 
 
-/* runtime lifecycle */
-
-extern PyStatus _PyBytes_InitTypes(PyInterpreterState *);
-
-
 /* Substring Search.
 
    Returns the index of the first occurrence of
index edc70843b5753173de0a17bd01123429d79b4e5c..335edad89792c3257d8bfa64dd2ee338ff934a61 100644 (file)
@@ -14,7 +14,6 @@ extern "C" {
 /* runtime lifecycle */
 
 extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
-extern PyStatus _PyTuple_InitTypes(PyInterpreterState *);
 extern void _PyTuple_Fini(PyInterpreterState *);
 
 
index 7f4f1d939fb7e9da555f22b7f6ff6cfd6a51da00..a3bfbc9ac5a1b1c3288cff7cc0ba39c46865aeb0 100644 (file)
@@ -671,13 +671,11 @@ static PyTypeObject* static_types[] = {
 PyStatus
 _PyIO_InitTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return _PyStatus_OK();
-    }
-
-    // Set type base classes
 #ifdef HAVE_WINDOWS_CONSOLE_IO
-    PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type;
+    if (_Py_IsMainInterpreter(interp)) {
+        // Set type base classes
+        PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type;
+    }
 #endif
 
     for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
index eddc1a33a953e6fd74c0caf9fca0fdb07be07a34..a5e82d571ada6ecfdf5c5336a694fb628d4fa084 100644 (file)
@@ -2096,7 +2096,7 @@ math_trunc(PyObject *module, PyObject *x)
         return PyFloat_Type.tp_as_number->nb_int(x);
     }
 
-    if (Py_TYPE(x)->tp_dict == NULL) {
+    if (_PyType_IsReady(Py_TYPE(x))) {
         if (PyType_Ready(Py_TYPE(x)) < 0)
             return NULL;
     }
index 4ef1d8cde07db6e162d4038063325b3725b2a5c0..91538b4fb15cbd0be05783128e6dc526b1ada956 100644 (file)
@@ -66,12 +66,6 @@ static PyMethodDef symtable_methods[] = {
     {NULL,              NULL}           /* sentinel */
 };
 
-static int
-symtable_init_stentry_type(PyObject *m)
-{
-    return PyType_Ready(&PySTEntry_Type);
-}
-
 static int
 symtable_init_constants(PyObject *m)
 {
@@ -105,7 +99,6 @@ symtable_init_constants(PyObject *m)
 }
 
 static PyModuleDef_Slot symtable_slots[] = {
-    {Py_mod_exec, symtable_init_stentry_type},
     {Py_mod_exec, symtable_init_constants},
     {0, NULL}
 };
index 2d8dab6f3780060203348b4b5b9bbefcbeca15c4..27b2ad4f2cb38f215709a172d52333404cfa9e25 100644 (file)
@@ -3090,25 +3090,6 @@ error:
 }
 
 
-PyStatus
-_PyBytes_InitTypes(PyInterpreterState *interp)
-{
-    if (!_Py_IsMainInterpreter(interp)) {
-        return _PyStatus_OK();
-    }
-
-    if (PyType_Ready(&PyBytes_Type) < 0) {
-        return _PyStatus_ERR("Can't initialize bytes type");
-    }
-
-    if (PyType_Ready(&PyBytesIter_Type) < 0) {
-        return _PyStatus_ERR("Can't initialize bytes iterator type");
-    }
-
-    return _PyStatus_OK();
-}
-
-
 /*********************** Bytes Iterator ****************************/
 
 typedef struct {
index 2cb192e725d40d076832f4c68e85053adb09923f..71c4a4e5d0f8ab03ccd38ff6299616f011b089a6 100644 (file)
@@ -181,7 +181,7 @@ method_getattro(PyObject *obj, PyObject *name)
     PyObject *descr = NULL;
 
     {
-        if (tp->tp_dict == NULL) {
+        if (!_PyType_IsReady(tp)) {
             if (PyType_Ready(tp) < 0)
                 return NULL;
         }
@@ -395,7 +395,7 @@ instancemethod_getattro(PyObject *self, PyObject *name)
     PyTypeObject *tp = Py_TYPE(self);
     PyObject *descr = NULL;
 
-    if (tp->tp_dict == NULL) {
+    if (!_PyType_IsReady(tp)) {
         if (PyType_Ready(tp) < 0)
             return NULL;
     }
index 55a6768a3aacf213ca2369fa8d177b4282ba64bc..6c9dfbd9b415cf1fc0eba3db45dccb8356ddaf6f 100644 (file)
@@ -3596,10 +3596,6 @@ static struct static_exception static_exceptions[] = {
 int
 _PyExc_InitTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return 0;
-    }
-
     for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
         PyTypeObject *exc = static_exceptions[i].exc;
         if (_PyStaticType_InitBuiltin(exc) < 0) {
index d641311f1126cd25ed4deae9f130b937cc2a35cd..9c2315781bed36ae795dbb0b8416ba60db3cd7bb 100644 (file)
@@ -1990,20 +1990,10 @@ _PyFloat_InitState(PyInterpreterState *interp)
 PyStatus
 _PyFloat_InitTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return _PyStatus_OK();
-    }
-
-    if (PyType_Ready(&PyFloat_Type) < 0) {
-        return _PyStatus_ERR("Can't initialize float type");
-    }
-
     /* Init float info */
-    if (FloatInfoType.tp_name == NULL) {
-        if (_PyStructSequence_InitBuiltin(&FloatInfoType,
-                                          &floatinfo_desc) < 0) {
-            return _PyStatus_ERR("can't init float info type");
-        }
+    if (_PyStructSequence_InitBuiltin(&FloatInfoType,
+                                      &floatinfo_desc) < 0) {
+        return _PyStatus_ERR("can't init float info type");
     }
 
     return _PyStatus_OK();
index d98bbbb6d6ff464f625548b073f13544593249ed..f84809b8a8986a3cfe3dcdb2e1901984a2a07ba2 100644 (file)
@@ -6351,19 +6351,9 @@ PyLong_GetInfo(void)
 PyStatus
 _PyLong_InitTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return _PyStatus_OK();
-    }
-
-    if (PyType_Ready(&PyLong_Type) < 0) {
-        return _PyStatus_ERR("Can't initialize int type");
-    }
-
     /* initialize int_info */
-    if (Int_InfoType.tp_name == NULL) {
-        if (_PyStructSequence_InitBuiltin(&Int_InfoType, &int_info_desc) < 0) {
-            return _PyStatus_ERR("can't init int info type");
-        }
+    if (_PyStructSequence_InitBuiltin(&Int_InfoType, &int_info_desc) < 0) {
+        return _PyStatus_ERR("can't init int info type");
     }
 
     return _PyStatus_OK();
index 65c296e9340601e7e798b803ec44fe6f74d6d685..cd610297aacba07dd029d8c3220c427cf9814643 100644 (file)
@@ -890,7 +890,7 @@ PyObject_Hash(PyObject *v)
      * an explicit call to PyType_Ready, we implicitly call
      * PyType_Ready here and then check the tp_hash slot again
      */
-    if (tp->tp_dict == NULL) {
+    if (!_PyType_IsReady(tp)) {
         if (PyType_Ready(tp) < 0)
             return -1;
         if (tp->tp_hash != NULL)
@@ -1385,7 +1385,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name,
     }
     Py_INCREF(name);
 
-    if (tp->tp_dict == NULL) {
+    if (!_PyType_IsReady(tp)) {
         if (PyType_Ready(tp) < 0)
             goto done;
     }
@@ -1507,8 +1507,9 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
         return -1;
     }
 
-    if (tp->tp_dict == NULL && PyType_Ready(tp) < 0)
+    if (!_PyType_IsReady(tp) && PyType_Ready(tp) < 0) {
         return -1;
+    }
 
     Py_INCREF(name);
     Py_INCREF(tp);
index 2a5343815866d3c95d7d35f5732fc8e1503cd305..727d72865e3bb34c627d0e6cd75a613d6c6fedc9 100644 (file)
@@ -509,6 +509,13 @@ _PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type,
                                        PyStructSequence_Desc *desc,
                                        unsigned long tp_flags)
 {
+    if (type->tp_flags & Py_TPFLAGS_READY) {
+        if (_PyStaticType_InitBuiltin(type) < 0) {
+            goto failed_init_builtin;
+        }
+        return 0;
+    }
+
     PyMemberDef *members;
     Py_ssize_t n_members, n_unnamed_members;
 
@@ -517,18 +524,25 @@ _PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type,
         return -1;
     }
     initialize_static_fields(type, desc, members, tp_flags);
+
+    Py_INCREF(type);  // XXX It should be immortal.
     if (_PyStaticType_InitBuiltin(type) < 0) {
         PyMem_Free(members);
-        PyErr_Format(PyExc_RuntimeError,
-                     "Can't initialize builtin type %s",
-                     desc->name);
-        return -1;
+        goto failed_init_builtin;
     }
-    if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) {
+
+    if (initialize_structseq_dict(
+            desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
         PyMem_Free(members);
         return -1;
     }
     return 0;
+
+failed_init_builtin:
+    PyErr_Format(PyExc_RuntimeError,
+                 "Can't initialize builtin type %s",
+                 desc->name);
+    return -1;
 }
 
 int
index 61fab4078d66ba1d3b1a5354a1906a4d388165d5..991edcc86677de9376c0a94c1ac966c1b44a74cf 100644 (file)
@@ -960,24 +960,6 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
 }
 
 
-PyStatus
-_PyTuple_InitTypes(PyInterpreterState *interp)
-{
-    if (!_Py_IsMainInterpreter(interp)) {
-        return _PyStatus_OK();
-    }
-
-    if (PyType_Ready(&PyTuple_Type) < 0) {
-        return _PyStatus_ERR("Can't initialize tuple type");
-    }
-
-    if (PyType_Ready(&PyTupleIter_Type) < 0) {
-        return _PyStatus_ERR("Can't initialize tuple iterator type");
-    }
-
-    return _PyStatus_OK();
-}
-
 static void maybe_freelist_clear(PyInterpreterState *, int);
 
 void
index 9194eba0eae15ce81686197a9ea4efafb7daa944..38b99315457a58d7900e853f69f9cde4a5c594d3 100644 (file)
@@ -6948,8 +6948,12 @@ type_ready_post_checks(PyTypeObject *type)
 static int
 type_ready(PyTypeObject *type)
 {
+    _PyObject_ASSERT((PyObject *)type,
+                     (type->tp_flags & Py_TPFLAGS_READYING) == 0);
+    type->tp_flags |= Py_TPFLAGS_READYING;
+
     if (type_ready_pre_checks(type) < 0) {
-        return -1;
+        goto error;
     }
 
 #ifdef Py_TRACE_REFS
@@ -6963,41 +6967,49 @@ type_ready(PyTypeObject *type)
 
     /* Initialize tp_dict: _PyType_IsReady() tests if tp_dict != NULL */
     if (type_ready_set_dict(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_set_bases(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_mro(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_set_new(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_fill_dict(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_inherit(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_preheader(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_set_hash(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_add_subclasses(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_managed_dict(type) < 0) {
-        return -1;
+        goto error;
     }
     if (type_ready_post_checks(type) < 0) {
-        return -1;
+        goto error;
     }
+
+    /* All done -- set the ready flag */
+    type->tp_flags = (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;
+
+    assert(_PyType_CheckConsistency(type));
     return 0;
-}
 
+error:
+    type->tp_flags &= ~Py_TPFLAGS_READYING;
+    return -1;
+}
 
 int
 PyType_Ready(PyTypeObject *type)
@@ -7006,31 +7018,29 @@ PyType_Ready(PyTypeObject *type)
         assert(_PyType_CheckConsistency(type));
         return 0;
     }
-    _PyObject_ASSERT((PyObject *)type,
-                     (type->tp_flags & Py_TPFLAGS_READYING) == 0);
-
-    type->tp_flags |= Py_TPFLAGS_READYING;
+    assert(!(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
 
     /* Historically, all static types were immutable. See bpo-43908 */
     if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
         type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
     }
 
-    if (type_ready(type) < 0) {
-        type->tp_flags &= ~Py_TPFLAGS_READYING;
-        return -1;
-    }
-
-    /* All done -- set the ready flag */
-    type->tp_flags = (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;
-    assert(_PyType_CheckConsistency(type));
-    return 0;
+    return type_ready(type);
 }
 
 int
 _PyStaticType_InitBuiltin(PyTypeObject *self)
 {
+    assert(!(self->tp_flags & Py_TPFLAGS_HEAPTYPE));
+
+    if (self->tp_flags & Py_TPFLAGS_READY) {
+        assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
+        assert(_PyType_CheckConsistency(self));
+        return 0;
+    }
+
     self->tp_flags |= _Py_TPFLAGS_STATIC_BUILTIN;
+    self->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
 
     assert(NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG);
     self->tp_version_tag = NEXT_GLOBAL_VERSION_TAG++;
@@ -7038,7 +7048,7 @@ _PyStaticType_InitBuiltin(PyTypeObject *self)
 
     static_builtin_state_init(self);
 
-    int res = PyType_Ready(self);
+    int res = type_ready(self);
     if (res < 0) {
         static_builtin_state_clear(self);
     }
index fd056e38f3f86b03cb6e3cf73b452bcc6ca76731..7537c12e92680c4b28b8a07bbf3efc3e308dde0c 100644 (file)
@@ -14573,10 +14573,6 @@ _PyUnicode_InitGlobalObjects(PyInterpreterState *interp)
 PyStatus
 _PyUnicode_InitTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return _PyStatus_OK();
-    }
-
     if (_PyStaticType_InitBuiltin(&EncodingMapType) < 0) {
         goto error;
     }
index fcb4d7a9a975c6d64e340672cd1834c0ef2692cc..8840bbabe4b584706f0fc2fc2b220745de4a9f1f 100644 (file)
@@ -2316,7 +2316,7 @@ builtin_round_impl(PyObject *module, PyObject *number, PyObject *ndigits)
 {
     PyObject *round, *result;
 
-    if (Py_TYPE(number)->tp_dict == NULL) {
+    if (!_PyType_IsReady(Py_TYPE(number))) {
         if (PyType_Ready(Py_TYPE(number)) < 0)
             return NULL;
     }
index 0ff6a0d5985f0f2edcaf84f760205f5a092e15e1..7fc267385c569bc0ec41b3ff3644fbd5d3022fba 100644 (file)
@@ -1342,15 +1342,9 @@ static PyStructSequence_Desc UnraisableHookArgs_desc = {
 PyStatus
 _PyErr_InitTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return _PyStatus_OK();
-    }
-
-    if (UnraisableHookArgsType.tp_name == NULL) {
-        if (_PyStructSequence_InitBuiltin(&UnraisableHookArgsType,
-                                          &UnraisableHookArgs_desc) < 0) {
-            return _PyStatus_ERR("failed to initialize UnraisableHookArgs type");
-        }
+    if (_PyStructSequence_InitBuiltin(&UnraisableHookArgsType,
+                                      &UnraisableHookArgs_desc) < 0) {
+        return _PyStatus_ERR("failed to initialize UnraisableHookArgs type");
     }
     return _PyStatus_OK();
 }
index 75698455c88166e0d757f8e6bc78e87e5a3e4a36..be229c987b8a78b715e090c374f8d53de4abc5c7 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "Python.h"
 #include "pycore_abstract.h"   // _PyIndex_Check()
+#include "pycore_object.h"     // _PyType_IsReady()
 
 #define FLAG_SIZE_T 1
 typedef double va_double;
@@ -693,7 +694,7 @@ PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
 int
 PyModule_AddType(PyObject *module, PyTypeObject *type)
 {
-    if (PyType_Ready(type) < 0) {
+    if (!_PyType_IsReady(type) && PyType_Ready(type) < 0) {
         return -1;
     }
 
index ebf1a0bff54eb0fef6d7b5fa13137809858b89fa..d525fb1075c4664ae6b96df0c90310d0be7bfe60 100644 (file)
@@ -2,7 +2,6 @@
 
 #include "Python.h"
 
-#include "pycore_bytesobject.h"   // _PyBytes_InitTypes()
 #include "pycore_ceval.h"         // _PyEval_FiniGIL()
 #include "pycore_context.h"       // _PyContext_Init()
 #include "pycore_exceptions.h"    // _PyExc_InitTypes()
@@ -26,7 +25,6 @@
 #include "pycore_sliceobject.h"   // _PySlice_Fini()
 #include "pycore_sysmodule.h"     // _PySys_ClearAuditHooks()
 #include "pycore_traceback.h"     // _Py_DumpTracebackThreads()
-#include "pycore_tuple.h"         // _PyTuple_InitTypes()
 #include "pycore_typeobject.h"    // _PyTypes_InitTypes()
 #include "pycore_unicodeobject.h" // _PyUnicode_InitTypes()
 #include "opcode.h"
@@ -684,11 +682,6 @@ pycore_init_types(PyInterpreterState *interp)
         return status;
     }
 
-    status = _PyBytes_InitTypes(interp);
-    if (_PyStatus_EXCEPTION(status)) {
-        return status;
-    }
-
     status = _PyLong_InitTypes(interp);
     if (_PyStatus_EXCEPTION(status)) {
         return status;
@@ -704,11 +697,6 @@ pycore_init_types(PyInterpreterState *interp)
         return status;
     }
 
-    status = _PyTuple_InitTypes(interp);
-    if (_PyStatus_EXCEPTION(status)) {
-        return status;
-    }
-
     if (_PyExc_InitTypes(interp) < 0) {
         return _PyStatus_ERR("failed to initialize an exception type");
     }
index 58ed48859b5f3acde89e7edeb7273dae1cdf4a1d..d673e40af5e1defa517aca48bc43a9362cd25af0 100644 (file)
@@ -3166,10 +3166,8 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
     SET_SYS("float_info", PyFloat_GetInfo());
     SET_SYS("int_info", PyLong_GetInfo());
     /* initialize hash_info */
-    if (Hash_InfoType.tp_name == NULL) {
-        if (_PyStructSequence_InitBuiltin(&Hash_InfoType, &hash_info_desc) < 0) {
-            goto type_init_failed;
-        }
+    if (_PyStructSequence_InitBuiltin(&Hash_InfoType, &hash_info_desc) < 0) {
+        goto type_init_failed;
     }
     SET_SYS("hash_info", get_hash_info(tstate));
     SET_SYS("maxunicode", PyLong_FromLong(0x10FFFF));
@@ -3191,11 +3189,9 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
 
 #define ENSURE_INFO_TYPE(TYPE, DESC) \
     do { \
-        if (TYPE.tp_name == NULL) { \
-            if (_PyStructSequence_InitBuiltinWithFlags( \
-                    &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \
-                goto type_init_failed; \
-            } \
+        if (_PyStructSequence_InitBuiltinWithFlags( \
+                &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \
+            goto type_init_failed; \
         } \
     } while (0)
 
@@ -3230,11 +3226,9 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
     SET_SYS("thread_info", PyThread_GetInfo());
 
     /* initialize asyncgen_hooks */
-    if (AsyncGenHooksType.tp_name == NULL) {
-        if (_PyStructSequence_InitBuiltin(
-                &AsyncGenHooksType, &asyncgen_hooks_desc) < 0) {
-            goto type_init_failed;
-        }
+    if (_PyStructSequence_InitBuiltin(
+            &AsyncGenHooksType, &asyncgen_hooks_desc) < 0) {
+        goto type_init_failed;
     }
 
 #ifdef __EMSCRIPTEN__
index 4581f1af043a37f16833aa08820b78fa449818f5..7fdedb0b9b7e265e6c4a545ddb7895bc292ffe68 100644 (file)
@@ -137,10 +137,8 @@ PyThread_GetInfo(void)
     int len;
 #endif
 
-    if (ThreadInfoType.tp_name == 0) {
-        if (_PyStructSequence_InitBuiltin(&ThreadInfoType,
-                                          &threadinfo_desc) < 0)
-            return NULL;
+    if (_PyStructSequence_InitBuiltin(&ThreadInfoType, &threadinfo_desc) < 0) {
+        return NULL;
     }
 
     threadinfo = PyStructSequence_New(&ThreadInfoType);