diff --git a/Include/internal/pycore_structseq.h b/Include/internal/pycore_structseq.h index 0199c790e24..d10a921c55f 100644 --- a/Include/internal/pycore_structseq.h +++ b/Include/internal/pycore_structseq.h @@ -15,11 +15,18 @@ PyAPI_FUNC(PyTypeObject *) _PyStructSequence_NewType( PyStructSequence_Desc *desc, unsigned long tp_flags); -PyAPI_FUNC(int) _PyStructSequence_InitType( +PyAPI_FUNC(int) _PyStructSequence_InitBuiltinWithFlags( PyTypeObject *type, PyStructSequence_Desc *desc, unsigned long tp_flags); +static inline int +_PyStructSequence_InitBuiltin(PyTypeObject *type, + PyStructSequence_Desc *desc) +{ + return _PyStructSequence_InitBuiltinWithFlags(type, desc, 0); +} + extern void _PyStructSequence_FiniType(PyTypeObject *type); #ifdef __cplusplus diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index c480a3a57b4..46f3bf78b13 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -41,6 +41,7 @@ struct type_cache { extern PyStatus _PyTypes_InitSlotDefs(void); +extern int _PyStaticType_InitBuiltin(PyTypeObject *type); extern void _PyStaticType_Dealloc(PyTypeObject *type); diff --git a/Include/object.h b/Include/object.h index a12b754c8ed..c00b9eb5834 100644 --- a/Include/object.h +++ b/Include/object.h @@ -352,6 +352,9 @@ given type object has a specified feature. #ifndef Py_LIMITED_API +/* Track types initialized using _PyStaticType_InitBuiltin(). */ +#define _Py_TPFLAGS_STATIC_BUILTIN (1 << 1) + /* Placement of dict (and values) pointers are managed by the VM, not by the type. * The VM will automatically set tp_dictoffset. Should not be used for variable sized * classes, such as classes that extend tuple. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 9aab683fd1c..e06a8f4173c 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -3556,8 +3556,7 @@ _PyExc_InitTypes(PyInterpreterState *interp) for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { PyTypeObject *exc = static_exceptions[i].exc; - - if (PyType_Ready(exc) < 0) { + if (_PyStaticType_InitBuiltin(exc) < 0) { return -1; } } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 47d308b8eb3..4b1b24f2e70 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1992,7 +1992,8 @@ _PyFloat_InitTypes(PyInterpreterState *interp) /* Init float info */ if (FloatInfoType.tp_name == NULL) { - if (PyStructSequence_InitType2(&FloatInfoType, &floatinfo_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&FloatInfoType, + &floatinfo_desc) < 0) { return _PyStatus_ERR("can't init float info type"); } } diff --git a/Objects/longobject.c b/Objects/longobject.c index 4a1e5caf5a2..90ed02b8c27 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -6135,7 +6135,7 @@ _PyLong_InitTypes(PyInterpreterState *interp) /* initialize int_info */ if (Int_InfoType.tp_name == NULL) { - if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&Int_InfoType, &int_info_desc) < 0) { return _PyStatus_ERR("can't init int info type"); } } diff --git a/Objects/object.c b/Objects/object.c index 75aee909a3b..758b79eff5b 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1975,8 +1975,8 @@ _PyTypes_InitTypes(PyInterpreterState *interp) // All other static types (unless initialized elsewhere) for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { PyTypeObject *type = static_types[i]; - if (PyType_Ready(type) < 0) { - return _PyStatus_ERR("Can't initialize types"); + if (_PyStaticType_InitBuiltin(type) < 0) { + return _PyStatus_ERR("Can't initialize builtin type"); } if (type == &PyType_Type) { // Sanitify checks of the two most important types diff --git a/Objects/structseq.c b/Objects/structseq.c index 229e3d893ff..24cd0e70596 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -432,11 +432,21 @@ error: return -1; } -static void -initialize_members(PyStructSequence_Desc *desc, PyMemberDef* members, - Py_ssize_t n_members) { - Py_ssize_t i, k; +static PyMemberDef * +initialize_members(PyStructSequence_Desc *desc, + Py_ssize_t *pn_members, Py_ssize_t *pn_unnamed_members) +{ + PyMemberDef *members; + Py_ssize_t n_members, n_unnamed_members; + n_members = count_members(desc, &n_unnamed_members); + members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); + if (members == NULL) { + PyErr_NoMemory(); + return NULL; + } + + Py_ssize_t i, k; for (i = k = 0; i < n_members; ++i) { if (desc->fields[i].name == PyStructSequence_UnnamedField) { continue; @@ -453,12 +463,78 @@ initialize_members(PyStructSequence_Desc *desc, PyMemberDef* members, k++; } members[k].name = NULL; + + *pn_members = n_members; + *pn_unnamed_members = n_unnamed_members; + return members; } +static void +initialize_static_fields(PyTypeObject *type, PyStructSequence_Desc *desc, + PyMemberDef *tp_members, unsigned long tp_flags) +{ + type->tp_name = desc->name; + type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *); + type->tp_itemsize = sizeof(PyObject *); + type->tp_dealloc = (destructor)structseq_dealloc; + type->tp_repr = (reprfunc)structseq_repr; + type->tp_doc = desc->doc; + type->tp_base = &PyTuple_Type; + type->tp_methods = structseq_methods; + type->tp_new = structseq_new; + type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags; + type->tp_traverse = (traverseproc) structseq_traverse; + type->tp_members = tp_members; +} + +static int +initialize_static_type(PyTypeObject *type, PyStructSequence_Desc *desc, + Py_ssize_t n_members, Py_ssize_t n_unnamed_members) { + /* initialize_static_fields() should have been called already. */ + if (PyType_Ready(type) < 0) { + return -1; + } + Py_INCREF(type); + + if (initialize_structseq_dict( + desc, type->tp_dict, n_members, n_unnamed_members) < 0) { + Py_DECREF(type); + return -1; + } + + return 0; +} + int -_PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc, - unsigned long tp_flags) +_PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type, + PyStructSequence_Desc *desc, + unsigned long tp_flags) +{ + PyMemberDef *members; + Py_ssize_t n_members, n_unnamed_members; + + members = initialize_members(desc, &n_members, &n_unnamed_members); + if (members == NULL) { + return -1; + } + initialize_static_fields(type, desc, members, tp_flags); + if (_PyStaticType_InitBuiltin(type) < 0) { + PyMem_Free(members); + PyErr_Format(PyExc_RuntimeError, + "Can't initialize builtin type %s", + desc->name); + return -1; + } + if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) { + PyMem_Free(members); + return -1; + } + return 0; +} + +int +PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) { PyMemberDef *members; Py_ssize_t n_members, n_unnamed_members; @@ -477,49 +553,18 @@ _PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc, return -1; } - type->tp_name = desc->name; - type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *); - type->tp_itemsize = sizeof(PyObject *); - type->tp_dealloc = (destructor)structseq_dealloc; - type->tp_repr = (reprfunc)structseq_repr; - type->tp_doc = desc->doc; - type->tp_base = &PyTuple_Type; - type->tp_methods = structseq_methods; - type->tp_new = structseq_new; - type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags; - type->tp_traverse = (traverseproc) structseq_traverse; - - n_members = count_members(desc, &n_unnamed_members); - members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); + members = initialize_members(desc, &n_members, &n_unnamed_members); if (members == NULL) { - PyErr_NoMemory(); return -1; } - initialize_members(desc, members, n_members); - type->tp_members = members; - - if (PyType_Ready(type) < 0) { + initialize_static_fields(type, desc, members, 0); + if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) { PyMem_Free(members); return -1; } - Py_INCREF(type); - - if (initialize_structseq_dict( - desc, type->tp_dict, n_members, n_unnamed_members) < 0) { - PyMem_Free(members); - Py_DECREF(type); - return -1; - } - return 0; } -int -PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) -{ - return _PyStructSequence_InitType(type, desc, 0); -} - void PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc) { @@ -569,13 +614,10 @@ _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags) Py_ssize_t n_members, n_unnamed_members; /* Initialize MemberDefs */ - n_members = count_members(desc, &n_unnamed_members); - members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); + members = initialize_members(desc, &n_members, &n_unnamed_members); if (members == NULL) { - PyErr_NoMemory(); return NULL; } - initialize_members(desc, members, n_members); /* Initialize Slots */ slots[0] = (PyType_Slot){Py_tp_dealloc, (destructor)structseq_dealloc}; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5ebff6084f4..8510196b612 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6650,6 +6650,14 @@ PyType_Ready(PyTypeObject *type) return 0; } +int +_PyStaticType_InitBuiltin(PyTypeObject *self) +{ + self->tp_flags = self->tp_flags | _Py_TPFLAGS_STATIC_BUILTIN; + + return PyType_Ready(self); +} + static int add_subclass(PyTypeObject *base, PyTypeObject *type) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 669ffe70727..7e3caf1af14 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -14604,13 +14604,13 @@ _PyUnicode_InitTypes(PyInterpreterState *interp) return _PyStatus_OK(); } - if (PyType_Ready(&EncodingMapType) < 0) { + if (_PyStaticType_InitBuiltin(&EncodingMapType) < 0) { goto error; } - if (PyType_Ready(&PyFieldNameIter_Type) < 0) { + if (_PyStaticType_InitBuiltin(&PyFieldNameIter_Type) < 0) { goto error; } - if (PyType_Ready(&PyFormatterIter_Type) < 0) { + if (_PyStaticType_InitBuiltin(&PyFormatterIter_Type) < 0) { goto error; } return _PyStatus_OK(); diff --git a/Python/errors.c b/Python/errors.c index b6b5d9b046c..2aa748c60c3 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1229,8 +1229,8 @@ _PyErr_InitTypes(PyInterpreterState *interp) } if (UnraisableHookArgsType.tp_name == NULL) { - if (PyStructSequence_InitType2(&UnraisableHookArgsType, - &UnraisableHookArgs_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&UnraisableHookArgsType, + &UnraisableHookArgs_desc) < 0) { return _PyStatus_ERR("failed to initialize UnraisableHookArgs type"); } } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index a5fa551b957..e861d9cbce4 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -28,7 +28,7 @@ Data members: #include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_structseq.h" // _PyStructSequence_InitType() +#include "pycore_structseq.h" // _PyStructSequence_InitBuiltinWithFlags() #include "pycore_tuple.h" // _PyTuple_FromArray() #include "frameobject.h" // PyFrame_FastToLocalsWithError() @@ -2921,7 +2921,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) SET_SYS("int_info", PyLong_GetInfo()); /* initialize hash_info */ if (Hash_InfoType.tp_name == NULL) { - if (PyStructSequence_InitType2(&Hash_InfoType, &hash_info_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&Hash_InfoType, &hash_info_desc) < 0) { goto type_init_failed; } } @@ -2943,14 +2943,18 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) SET_SYS_FROM_STRING("abiflags", ABIFLAGS); #endif +#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; \ + } \ + } \ + } while (0) + /* version_info */ - if (VersionInfoType.tp_name == NULL) { - if (_PyStructSequence_InitType(&VersionInfoType, - &version_info_desc, - Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { - goto type_init_failed; - } - } + ENSURE_INFO_TYPE(VersionInfoType, version_info_desc); version_info = make_version_info(tstate); SET_SYS("version_info", version_info); @@ -2958,27 +2962,18 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) SET_SYS("implementation", make_impl_info(version_info)); // sys.flags: updated in-place later by _PySys_UpdateConfig() - if (FlagsType.tp_name == 0) { - if (_PyStructSequence_InitType(&FlagsType, &flags_desc, - Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { - goto type_init_failed; - } - } + ENSURE_INFO_TYPE(FlagsType, flags_desc); SET_SYS("flags", make_flags(tstate->interp)); #if defined(MS_WINDOWS) /* getwindowsversion */ - if (WindowsVersionType.tp_name == 0) { - if (_PyStructSequence_InitType(&WindowsVersionType, - &windows_version_desc, - Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { - goto type_init_failed; - } - } + ENSURE_INFO_TYPE(WindowsVersionType, windows_version_desc); SET_SYS_FROM_STRING("_vpath", VPATH); #endif +#undef ENSURE_INFO_TYPE + /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */ #if _PY_SHORT_FLOAT_REPR == 1 SET_SYS_FROM_STRING("float_repr_style", "short"); @@ -2990,7 +2985,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) /* initialize asyncgen_hooks */ if (AsyncGenHooksType.tp_name == NULL) { - if (PyStructSequence_InitType2( + if (_PyStructSequence_InitBuiltin( &AsyncGenHooksType, &asyncgen_hooks_desc) < 0) { goto type_init_failed; } diff --git a/Python/thread.c b/Python/thread.c index 846f0254527..d3211219dff 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -155,7 +155,8 @@ PyThread_GetInfo(void) #endif if (ThreadInfoType.tp_name == 0) { - if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0) + if (_PyStructSequence_InitBuiltin(&ThreadInfoType, + &threadinfo_desc) < 0) return NULL; }