mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
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.
This commit is contained in:
parent
c50ec007ff
commit
b4efc963d6
2 changed files with 38 additions and 28 deletions
|
@ -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) {
|
{
|
||||||
|
hash = PyObject_Hash(key);
|
||||||
|
if (hash == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
x = *value_addr;
|
|
||||||
if (x != NULL)
|
/* namespace 1: globals */
|
||||||
return x;
|
entry = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr);
|
||||||
e = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr);
|
if (entry == NULL)
|
||||||
if (e == NULL) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
value = *value_addr;
|
||||||
x = *value_addr;
|
if (value != NULL)
|
||||||
return x;
|
return value;
|
||||||
}
|
|
||||||
}
|
/* namespace 2: builtins */
|
||||||
x = PyDict_GetItemWithError((PyObject *)globals, key);
|
entry = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr);
|
||||||
if (x != NULL)
|
if (entry == NULL)
|
||||||
return x;
|
|
||||||
if (PyErr_Occurred())
|
|
||||||
return NULL;
|
return NULL;
|
||||||
return PyDict_GetItemWithError((PyObject *)builtins, key);
|
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)
|
||||||
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))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue