Commit b4efc963 authored by Victor Stinner's avatar Victor Stinner

Issue #25557: Refactor _PyDict_LoadGlobal()

Don't fallback to PyDict_GetItemWithError() if the hash is unknown: compute the
hash instead. Add also comments to explain the optimization a little bit.
parent c50ec007
...@@ -1165,39 +1165,42 @@ _PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key) ...@@ -1165,39 +1165,42 @@ _PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key)
return PyDict_GetItemWithError(dp, kv); return PyDict_GetItemWithError(dp, kv);
} }
/* Fast version of global value lookup. /* Fast version of global value lookup (LOAD_GLOBAL).
* Lookup in globals, then builtins. * Lookup in globals, then builtins.
*
* Raise an exception and return NULL if an error occurred (ex: computing the
* key hash failed, key comparison failed, ...). Return NULL if the key doesn't
* exist. Return the value if the key exists.
*/ */
PyObject * PyObject *
_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key) _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
{ {
PyObject *x; Py_hash_t hash;
if (PyUnicode_CheckExact(key)) { PyDictKeyEntry *entry;
PyObject **value_addr; PyObject **value_addr;
Py_hash_t hash = ((PyASCIIObject *)key)->hash; PyObject *value;
if (hash != -1) {
PyDictKeyEntry *e; if (!PyUnicode_CheckExact(key) ||
e = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr); (hash = ((PyASCIIObject *) key)->hash) == -1)
if (e == NULL) { {
return NULL; hash = PyObject_Hash(key);
} if (hash == -1)
x = *value_addr; return NULL;
if (x != NULL)
return x;
e = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr);
if (e == NULL) {
return NULL;
}
x = *value_addr;
return x;
}
} }
x = PyDict_GetItemWithError((PyObject *)globals, key);
if (x != NULL) /* namespace 1: globals */
return x; entry = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr);
if (PyErr_Occurred()) if (entry == NULL)
return NULL; return NULL;
return PyDict_GetItemWithError((PyObject *)builtins, key); value = *value_addr;
if (value != NULL)
return value;
/* namespace 2: builtins */
entry = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr);
if (entry == NULL)
return NULL;
return *value_addr;
} }
/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
......
...@@ -2347,26 +2347,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) ...@@ -2347,26 +2347,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PyObject *name = GETITEM(names, oparg); PyObject *name = GETITEM(names, oparg);
PyObject *v; PyObject *v;
if (PyDict_CheckExact(f->f_globals) if (PyDict_CheckExact(f->f_globals)
&& PyDict_CheckExact(f->f_builtins)) { && PyDict_CheckExact(f->f_builtins))
{
v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals, v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,
(PyDictObject *)f->f_builtins, (PyDictObject *)f->f_builtins,
name); name);
if (v == NULL) { if (v == NULL) {
if (!_PyErr_OCCURRED()) if (!_PyErr_OCCURRED()) {
/* _PyDict_LoadGlobal() returns NULL without raising
* an exception if the key doesn't exist */
format_exc_check_arg(PyExc_NameError, format_exc_check_arg(PyExc_NameError,
NAME_ERROR_MSG, name); NAME_ERROR_MSG, name);
}
goto error; goto error;
} }
Py_INCREF(v); Py_INCREF(v);
} }
else { else {
/* Slow-path if globals or builtins is not a dict */ /* Slow-path if globals or builtins is not a dict */
/* namespace 1: globals */
v = PyObject_GetItem(f->f_globals, name); v = PyObject_GetItem(f->f_globals, name);
if (v == NULL) { if (v == NULL) {
if (!PyErr_ExceptionMatches(PyExc_KeyError)) if (!PyErr_ExceptionMatches(PyExc_KeyError))
goto error; goto error;
PyErr_Clear(); PyErr_Clear();
/* namespace 2: builtins */
v = PyObject_GetItem(f->f_builtins, name); v = PyObject_GetItem(f->f_builtins, name);
if (v == NULL) { if (v == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError)) if (PyErr_ExceptionMatches(PyExc_KeyError))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment