mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
bpo-42093: Cleanup _PyDict_GetItemHint() (GH-24582)
* No longer save/restore the current exception. It is no longer used with an exception raised. * No longer clear the current exception on error: it's now up to the caller.
This commit is contained in:
parent
38b6c2acd4
commit
d5fc998737
2 changed files with 20 additions and 36 deletions
|
@ -1439,11 +1439,8 @@ PyDict_GetItem(PyObject *op, PyObject *key)
|
||||||
|
|
||||||
Py_ssize_t
|
Py_ssize_t
|
||||||
_PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
|
_PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
|
||||||
Py_ssize_t hint, PyObject **value)
|
Py_ssize_t hint, PyObject **value)
|
||||||
{
|
{
|
||||||
Py_hash_t hash;
|
|
||||||
PyThreadState *tstate;
|
|
||||||
|
|
||||||
assert(*value == NULL);
|
assert(*value == NULL);
|
||||||
assert(PyDict_CheckExact((PyObject*)mp));
|
assert(PyDict_CheckExact((PyObject*)mp));
|
||||||
assert(PyUnicode_CheckExact(key));
|
assert(PyUnicode_CheckExact(key));
|
||||||
|
@ -1467,39 +1464,15 @@ _PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hash = ((PyASCIIObject *) key)->hash) == -1)
|
Py_hash_t hash = ((PyASCIIObject *) key)->hash;
|
||||||
{
|
if (hash == -1) {
|
||||||
hash = PyObject_Hash(key);
|
hash = PyObject_Hash(key);
|
||||||
if (hash == -1) {
|
if (hash == -1) {
|
||||||
PyErr_Clear();
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can arrive here with a NULL tstate during initialization: try
|
return (mp->ma_keys->dk_lookup)(mp, key, hash, value);
|
||||||
// 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.
|
/* Same as PyDict_GetItemWithError() but with hash supplied by caller.
|
||||||
|
|
|
@ -3214,9 +3214,10 @@ main_loop:
|
||||||
Py_ssize_t hint = la->hint;
|
Py_ssize_t hint = la->hint;
|
||||||
Py_INCREF(dict);
|
Py_INCREF(dict);
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
assert(!_PyErr_Occurred(tstate));
|
||||||
la->hint = _PyDict_GetItemHint((PyDictObject*)dict, name, hint, &res);
|
la->hint = _PyDict_GetItemHint((PyDictObject*)dict, name, hint, &res);
|
||||||
|
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
|
assert(la->hint >= 0);
|
||||||
if (la->hint == hint && hint >= 0) {
|
if (la->hint == hint && hint >= 0) {
|
||||||
// Our hint has helped -- cache hit.
|
// Our hint has helped -- cache hit.
|
||||||
OPCACHE_STAT_ATTR_HIT();
|
OPCACHE_STAT_ATTR_HIT();
|
||||||
|
@ -3231,18 +3232,22 @@ main_loop:
|
||||||
Py_DECREF(owner);
|
Py_DECREF(owner);
|
||||||
Py_DECREF(dict);
|
Py_DECREF(dict);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
// This attribute can be missing sometimes;
|
// This attribute can be missing sometimes;
|
||||||
// we don't want to optimize this lookup.
|
// we don't want to optimize this lookup.
|
||||||
OPCACHE_DEOPT_LOAD_ATTR();
|
OPCACHE_DEOPT_LOAD_ATTR();
|
||||||
Py_DECREF(dict);
|
Py_DECREF(dict);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.
|
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.
|
||||||
OPCACHE_DEOPT_LOAD_ATTR();
|
OPCACHE_DEOPT_LOAD_ATTR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// The type of the object has either been updated,
|
// The type of the object has either been updated,
|
||||||
// or is different. Maybe it will stabilize?
|
// or is different. Maybe it will stabilize?
|
||||||
OPCACHE_MAYBE_DEOPT_LOAD_ATTR();
|
OPCACHE_MAYBE_DEOPT_LOAD_ATTR();
|
||||||
|
@ -3298,7 +3303,8 @@ main_loop:
|
||||||
}
|
}
|
||||||
// Else it's some other kind of descriptor that we don't handle.
|
// Else it's some other kind of descriptor that we don't handle.
|
||||||
OPCACHE_DEOPT_LOAD_ATTR();
|
OPCACHE_DEOPT_LOAD_ATTR();
|
||||||
} else if (type->tp_dictoffset > 0) {
|
}
|
||||||
|
else if (type->tp_dictoffset > 0) {
|
||||||
// We found an instance with a __dict__.
|
// We found an instance with a __dict__.
|
||||||
dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset);
|
dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset);
|
||||||
dict = *dictptr;
|
dict = *dictptr;
|
||||||
|
@ -3306,6 +3312,7 @@ main_loop:
|
||||||
if (dict != NULL && PyDict_CheckExact(dict)) {
|
if (dict != NULL && PyDict_CheckExact(dict)) {
|
||||||
Py_INCREF(dict);
|
Py_INCREF(dict);
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
assert(!_PyErr_Occurred(tstate));
|
||||||
Py_ssize_t hint = _PyDict_GetItemHint((PyDictObject*)dict, name, -1, &res);
|
Py_ssize_t hint = _PyDict_GetItemHint((PyDictObject*)dict, name, -1, &res);
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
Py_INCREF(res);
|
Py_INCREF(res);
|
||||||
|
@ -3322,10 +3329,14 @@ main_loop:
|
||||||
la = &co_opcache->u.la;
|
la = &co_opcache->u.la;
|
||||||
la->type = type;
|
la->type = type;
|
||||||
la->tp_version_tag = type->tp_version_tag;
|
la->tp_version_tag = type->tp_version_tag;
|
||||||
|
assert(hint >= 0);
|
||||||
la->hint = hint;
|
la->hint = hint;
|
||||||
|
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
|
}
|
||||||
Py_DECREF(dict);
|
Py_DECREF(dict);
|
||||||
} else {
|
} else {
|
||||||
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.
|
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue