bpo-42093: Add opcode cache for LOAD_ATTR (GH-22803)

This commit is contained in:
Pablo Galindo 2020-10-20 06:22:44 +01:00 committed by GitHub
parent 871934d4cf
commit 109826c850
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 296 additions and 7 deletions

View file

@ -1437,6 +1437,71 @@ PyDict_GetItem(PyObject *op, PyObject *key)
return value;
}
Py_ssize_t
_PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
Py_ssize_t hint, PyObject **value)
{
Py_hash_t hash;
PyThreadState *tstate;
assert(*value == NULL);
assert(PyDict_CheckExact((PyObject*)mp));
assert(PyUnicode_CheckExact(key));
if (hint >= 0 && hint < _PyDict_KeysSize(mp->ma_keys)) {
PyObject *res = NULL;
PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys) + (size_t)hint;
if (ep->me_key == key) {
if (mp->ma_keys->dk_lookup == lookdict_split) {
assert(mp->ma_values != NULL);
res = mp->ma_values[(size_t)hint];
}
else {
res = ep->me_value;
}
if (res != NULL) {
*value = res;
return hint;
}
}
}
if ((hash = ((PyASCIIObject *) key)->hash) == -1)
{
hash = PyObject_Hash(key);
if (hash == -1) {
PyErr_Clear();
return -1;
}
}
// We can arrive here with a NULL tstate during initialization: try
// running "python -Wi" for an example related to string interning
tstate = _PyThreadState_UncheckedGet();
Py_ssize_t ix = 0;
if (tstate != NULL && tstate->curexc_type != NULL) {
/* preserve the existing exception */
PyObject *err_type, *err_value, *err_tb;
PyErr_Fetch(&err_type, &err_value, &err_tb);
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value);
/* ignore errors */
PyErr_Restore(err_type, err_value, err_tb);
if (ix < 0) {
return -1;
}
}
else {
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value);
if (ix < 0) {
PyErr_Clear();
return -1;
}
}
return ix;
}
/* Same as PyDict_GetItemWithError() but with hash supplied by caller.
This returns NULL *with* an exception set if an exception occurred.
It returns NULL *without* an exception set if the key wasn't present.