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.
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 @@ _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.