[Python-checkins] bpo-42093: Cleanup _PyDict_GetItemHint() (GH-24582)

vstinner webhook-mailer at python.org
Sun Feb 21 06:02:18 EST 2021


https://github.com/python/cpython/commit/d5fc99873769f0d0d5c5d5d99059177a75a4e46e
commit: d5fc99873769f0d0d5c5d5d99059177a75a4e46e
branch: master
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2021-02-21T12:02:04+01:00
summary:

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.

files:
M Objects/dictobject.c
M Python/ceval.c

diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 773eda0d75a9c..6ca82a7601654 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 e2b2d211fb340..e1a8f15b51746 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3214,9 +3214,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
                                 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 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
                                     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 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
                         }
                         // 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 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
                         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 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
                                 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.



More information about the Python-checkins mailing list