Skip to content

Commit 1d52082

Browse files
author
Stefan Behnel
committed
Lazily calculate name hash in find_name_in_mro() to avoid potential re-calculation if the mapping is not exactly a dict.
1 parent 09e716a commit 1d52082

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

Objects/typeobject.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,17 +2950,7 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error)
29502950
{
29512951
Py_ssize_t i, n;
29522952
PyObject *mro, *res, *base, *dict;
2953-
Py_hash_t hash;
2954-
2955-
if (!PyUnicode_CheckExact(name) ||
2956-
(hash = ((PyASCIIObject *) name)->hash) == -1)
2957-
{
2958-
hash = PyObject_Hash(name);
2959-
if (hash == -1) {
2960-
*error = -1;
2961-
return NULL;
2962-
}
2963-
}
2953+
Py_hash_t hash = -1;
29642954

29652955
/* Look in tp_dict of types in MRO */
29662956
mro = type->tp_mro;
@@ -2990,9 +2980,22 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error)
29902980
assert(PyType_Check(base));
29912981
dict = ((PyTypeObject *)base)->tp_dict;
29922982
assert(dict);
2983+
/* Optimise for the extremely common case: dict for lookup, unicode name. */
29932984
if (PyDict_CheckExact(dict)) {
2985+
if (hash == -1) {
2986+
if (!PyUnicode_CheckExact(name) ||
2987+
(hash = ((PyASCIIObject *) name)->hash) == -1)
2988+
{
2989+
hash = PyObject_Hash(name);
2990+
if (hash == -1) {
2991+
*error = -1;
2992+
goto done;
2993+
}
2994+
}
2995+
}
29942996
res = _PyDict_GetItem_KnownHash(dict, name, hash);
29952997
} else {
2998+
/* Every other combination is much less safe, so be conservative. */
29962999
res = PyObject_GetItem(dict, name);
29973000
}
29983001
if (res != NULL)

0 commit comments

Comments
 (0)