mirror of https://github.com/python/cpython
bpo-40137: Optimize _PyType_GetModuleByDef() loop (GH-25505)
PyType_Ready() now ensures that a type MRO cannot be empty. _PyType_GetModuleByDef() no longer checks "i < PyTuple_GET_SIZE(mro)" at the first loop iteration to optimize the most common case, when the argument is the defining class.
This commit is contained in:
parent
d4aaa34798
commit
760da626ff
|
@ -1987,14 +1987,20 @@ mro_invoke(PyTypeObject *type)
|
||||||
|
|
||||||
new_mro = PySequence_Tuple(mro_result);
|
new_mro = PySequence_Tuple(mro_result);
|
||||||
Py_DECREF(mro_result);
|
Py_DECREF(mro_result);
|
||||||
if (new_mro == NULL)
|
if (new_mro == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyTuple_GET_SIZE(new_mro) == 0) {
|
||||||
|
Py_DECREF(new_mro);
|
||||||
|
PyErr_Format(PyExc_TypeError, "type MRO must not be empty");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (custom && mro_check(type, new_mro) < 0) {
|
if (custom && mro_check(type, new_mro) < 0) {
|
||||||
Py_DECREF(new_mro);
|
Py_DECREF(new_mro);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_mro;
|
return new_mro;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2034,8 +2040,9 @@ mro_internal(PyTypeObject *type, PyObject **p_old_mro)
|
||||||
new_mro = mro_invoke(type); /* might cause reentrance */
|
new_mro = mro_invoke(type); /* might cause reentrance */
|
||||||
reent = (type->tp_mro != old_mro);
|
reent = (type->tp_mro != old_mro);
|
||||||
Py_XDECREF(old_mro);
|
Py_XDECREF(old_mro);
|
||||||
if (new_mro == NULL)
|
if (new_mro == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (reent) {
|
if (reent) {
|
||||||
Py_DECREF(new_mro);
|
Py_DECREF(new_mro);
|
||||||
|
@ -3590,9 +3597,17 @@ PyObject *
|
||||||
_PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
|
_PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
|
||||||
{
|
{
|
||||||
assert(PyType_Check(type));
|
assert(PyType_Check(type));
|
||||||
|
|
||||||
PyObject *mro = type->tp_mro;
|
PyObject *mro = type->tp_mro;
|
||||||
|
// The type must be ready
|
||||||
assert(mro != NULL);
|
assert(mro != NULL);
|
||||||
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(mro); i++) {
|
assert(PyTuple_Check(mro));
|
||||||
|
// mro_invoke() ensures that the type MRO cannot be empty, so we don't have
|
||||||
|
// to check i < PyTuple_GET_SIZE(mro) at the first loop iteration.
|
||||||
|
assert(PyTuple_GET_SIZE(mro) >= 1);
|
||||||
|
|
||||||
|
Py_ssize_t i = 0;
|
||||||
|
do {
|
||||||
PyObject *super = PyTuple_GET_ITEM(mro, i);
|
PyObject *super = PyTuple_GET_ITEM(mro, i);
|
||||||
// _PyType_GetModuleByDef() must only be called on a heap type created
|
// _PyType_GetModuleByDef() must only be called on a heap type created
|
||||||
// by PyType_FromModuleAndSpec() or on its subclasses.
|
// by PyType_FromModuleAndSpec() or on its subclasses.
|
||||||
|
@ -3605,7 +3620,8 @@ _PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
|
||||||
if (module && PyModule_GetDef(module) == def) {
|
if (module && PyModule_GetDef(module) == def) {
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
}
|
i++;
|
||||||
|
} while (i < PyTuple_GET_SIZE(mro));
|
||||||
|
|
||||||
PyErr_Format(
|
PyErr_Format(
|
||||||
PyExc_TypeError,
|
PyExc_TypeError,
|
||||||
|
|
Loading…
Reference in New Issue