Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d5fc998

Browse files
authored
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.
1 parent 38b6c2a commit d5fc998

2 files changed

Lines changed: 20 additions & 36 deletions

File tree

Objects/dictobject.c

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,11 +1439,8 @@ PyDict_GetItem(PyObject *op, PyObject *key)
14391439

14401440
Py_ssize_t
14411441
_PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
1442-
Py_ssize_t hint, PyObject **value)
1442+
Py_ssize_t hint, PyObject **value)
14431443
{
1444-
Py_hash_t hash;
1445-
PyThreadState *tstate;
1446-
14471444
assert(*value == NULL);
14481445
assert(PyDict_CheckExact((PyObject*)mp));
14491446
assert(PyUnicode_CheckExact(key));
@@ -1467,39 +1464,15 @@ _PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
14671464
}
14681465
}
14691466

1470-
if ((hash = ((PyASCIIObject *) key)->hash) == -1)
1471-
{
1467+
Py_hash_t hash = ((PyASCIIObject *) key)->hash;
1468+
if (hash == -1) {
14721469
hash = PyObject_Hash(key);
14731470
if (hash == -1) {
1474-
PyErr_Clear();
1475-
return -1;
1476-
}
1477-
}
1478-
1479-
// We can arrive here with a NULL tstate during initialization: try
1480-
// running "python -Wi" for an example related to string interning
1481-
tstate = _PyThreadState_UncheckedGet();
1482-
Py_ssize_t ix = 0;
1483-
if (tstate != NULL && tstate->curexc_type != NULL) {
1484-
/* preserve the existing exception */
1485-
PyObject *err_type, *err_value, *err_tb;
1486-
PyErr_Fetch(&err_type, &err_value, &err_tb);
1487-
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value);
1488-
/* ignore errors */
1489-
PyErr_Restore(err_type, err_value, err_tb);
1490-
if (ix < 0) {
1491-
return -1;
1492-
}
1493-
}
1494-
else {
1495-
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value);
1496-
if (ix < 0) {
1497-
PyErr_Clear();
14981471
return -1;
14991472
}
15001473
}
15011474

1502-
return ix;
1475+
return (mp->ma_keys->dk_lookup)(mp, key, hash, value);
15031476
}
15041477

15051478
/* Same as PyDict_GetItemWithError() but with hash supplied by caller.

Python/ceval.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3214,9 +3214,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
32143214
Py_ssize_t hint = la->hint;
32153215
Py_INCREF(dict);
32163216
res = NULL;
3217+
assert(!_PyErr_Occurred(tstate));
32173218
la->hint = _PyDict_GetItemHint((PyDictObject*)dict, name, hint, &res);
3218-
32193219
if (res != NULL) {
3220+
assert(la->hint >= 0);
32203221
if (la->hint == hint && hint >= 0) {
32213222
// Our hint has helped -- cache hit.
32223223
OPCACHE_STAT_ATTR_HIT();
@@ -3231,18 +3232,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
32313232
Py_DECREF(owner);
32323233
Py_DECREF(dict);
32333234
DISPATCH();
3234-
} else {
3235+
}
3236+
else {
3237+
_PyErr_Clear(tstate);
32353238
// This attribute can be missing sometimes;
32363239
// we don't want to optimize this lookup.
32373240
OPCACHE_DEOPT_LOAD_ATTR();
32383241
Py_DECREF(dict);
32393242
}
3240-
} else {
3243+
}
3244+
else {
32413245
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.
32423246
OPCACHE_DEOPT_LOAD_ATTR();
32433247
}
32443248
}
3245-
} else {
3249+
}
3250+
else {
32463251
// The type of the object has either been updated,
32473252
// or is different. Maybe it will stabilize?
32483253
OPCACHE_MAYBE_DEOPT_LOAD_ATTR();
@@ -3298,14 +3303,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
32983303
}
32993304
// Else it's some other kind of descriptor that we don't handle.
33003305
OPCACHE_DEOPT_LOAD_ATTR();
3301-
} else if (type->tp_dictoffset > 0) {
3306+
}
3307+
else if (type->tp_dictoffset > 0) {
33023308
// We found an instance with a __dict__.
33033309
dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset);
33043310
dict = *dictptr;
33053311

33063312
if (dict != NULL && PyDict_CheckExact(dict)) {
33073313
Py_INCREF(dict);
33083314
res = NULL;
3315+
assert(!_PyErr_Occurred(tstate));
33093316
Py_ssize_t hint = _PyDict_GetItemHint((PyDictObject*)dict, name, -1, &res);
33103317
if (res != NULL) {
33113318
Py_INCREF(res);
@@ -3322,10 +3329,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
33223329
la = &co_opcache->u.la;
33233330
la->type = type;
33243331
la->tp_version_tag = type->tp_version_tag;
3332+
assert(hint >= 0);
33253333
la->hint = hint;
33263334

33273335
DISPATCH();
33283336
}
3337+
else {
3338+
_PyErr_Clear(tstate);
3339+
}
33293340
Py_DECREF(dict);
33303341
} else {
33313342
// There is no dict, or __dict__ doesn't satisfy PyDict_CheckExact.

0 commit comments

Comments
 (0)