summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Objects/dictobject.c35
-rw-r--r--Python/ceval.c21
2 files changed, 20 insertions, 36 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 773eda0..6ca82a7 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1439,11 +1439,8 @@ PyDict_GetItem(PyObject *op, PyObject *key)
Py_ssize_t
_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(PyDict_CheckExact((PyObject*)mp));
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);
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;
+ return (mp->ma_keys->dk_lookup)(mp, key, hash, value);
}
/* Same as PyDict_GetItemWithError() but with hash supplied by caller.
diff --git a/Python/ceval.c b/Python/ceval.c
index e2b2d21..e1a8f15 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3214,9 +3214,10 @@ main_loop:
Py_ssize_t hint = la->hint;
Py_INCREF(dict);
res = NULL;
+ assert(!_PyErr_Occurred(tstate));
la->hint = _PyDict_GetItemHint((PyDictObject*)dict, name, hint, &res);
-
if (res != NULL) {
+ assert(la->hint >= 0);
if (la->hint == hint && hint >= 0) {
// Our hint has helped -- cache hit.
OPCACHE_STAT_ATTR_HIT();
@@ -3231,18 +3232,22 @@ main_loop:
Py_DECREF(owner);
Py_DECREF(dict);
DISPATCH();
- } else {
+ }
+ else {
+ _PyErr_Clear(tstate);
// This attribute can be missing sometimes;
// we don't want to optimize this lookup.
OPCACHE_DEOPT_LOAD_ATTR();
Py_DECREF(dict);
}
- } else {
+ }
+ else {
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.
OPCACHE_DEOPT_LOAD_ATTR();
}
}
- } else {
+ }
+ else {
// The type of the object has either been updated,
// or is different. Maybe it will stabilize?
OPCACHE_MAYBE_DEOPT_LOAD_ATTR();
@@ -3298,7 +3303,8 @@ main_loop:
}
// Else it's some other kind of descriptor that we don't handle.
OPCACHE_DEOPT_LOAD_ATTR();
- } else if (type->tp_dictoffset > 0) {
+ }
+ else if (type->tp_dictoffset > 0) {
// We found an instance with a __dict__.
dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset);
dict = *dictptr;
@@ -3306,6 +3312,7 @@ main_loop:
if (dict != NULL && PyDict_CheckExact(dict)) {
Py_INCREF(dict);
res = NULL;
+ assert(!_PyErr_Occurred(tstate));
Py_ssize_t hint = _PyDict_GetItemHint((PyDictObject*)dict, name, -1, &res);
if (res != NULL) {
Py_INCREF(res);
@@ -3322,10 +3329,14 @@ main_loop:
la = &co_opcache->u.la;
la->type = type;
la->tp_version_tag = type->tp_version_tag;
+ assert(hint >= 0);
la->hint = hint;
DISPATCH();
}
+ else {
+ _PyErr_Clear(tstate);
+ }
Py_DECREF(dict);
} else {
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.