|
1 | 1 | #include "Python.h" |
2 | 2 | #include "pycore_call.h" // _PyObject_CallNoArgs() |
3 | | -#include "pycore_dict.h" // _PyDict_GetItem_KnownHash() |
| 3 | +#include "pycore_dict.h" // _PyDict_GetItemRef_KnownHash_LockHeld() |
4 | 4 | #include "pycore_long.h" // _PyLong_GetZero() |
5 | 5 | #include "pycore_moduleobject.h" // _PyModule_GetState() |
6 | 6 | #include "pycore_pyatomic_ft_wrappers.h" |
@@ -2595,24 +2595,36 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping, |
2595 | 2595 | goto done; |
2596 | 2596 | } |
2597 | 2597 |
|
2598 | | - oldval = _PyDict_GetItem_KnownHash(mapping, key, hash); |
2599 | | - if (oldval == NULL) { |
2600 | | - if (PyErr_Occurred()) |
2601 | | - goto done; |
2602 | | - if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) < 0) |
2603 | | - goto done; |
2604 | | - } else { |
2605 | | - /* oldval is a borrowed reference. Keep it alive across |
2606 | | - PyNumber_Add(), which can execute arbitrary user code and |
2607 | | - mutate (or even clear) the underlying dict. */ |
2608 | | - Py_INCREF(oldval); |
| 2598 | + int found; |
| 2599 | + int cs_err = 0; |
| 2600 | + Py_BEGIN_CRITICAL_SECTION(mapping); |
| 2601 | + found = _PyDict_GetItemRef_KnownHash_LockHeld( |
| 2602 | + (PyDictObject *)mapping, key, hash, &oldval); |
| 2603 | + if (found < 0) { |
| 2604 | + cs_err = -1; |
| 2605 | + } |
| 2606 | + else if (found == 0) { |
| 2607 | + if (_PyDict_SetItem_KnownHash_LockHeld( |
| 2608 | + (PyDictObject *)mapping, key, one, hash) < 0) { |
| 2609 | + cs_err = -1; |
| 2610 | + } |
| 2611 | + } |
| 2612 | + else { |
2609 | 2613 | newval = PyNumber_Add(oldval, one); |
2610 | 2614 | Py_DECREF(oldval); |
2611 | | - if (newval == NULL) |
2612 | | - goto done; |
2613 | | - if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) < 0) |
2614 | | - goto done; |
2615 | | - Py_CLEAR(newval); |
| 2615 | + oldval = NULL; |
| 2616 | + if (newval == NULL) { |
| 2617 | + cs_err = -1; |
| 2618 | + } |
| 2619 | + else if (_PyDict_SetItem_KnownHash_LockHeld( |
| 2620 | + (PyDictObject *)mapping, key, newval, hash) < 0) { |
| 2621 | + cs_err = -1; |
| 2622 | + } |
| 2623 | + } |
| 2624 | + Py_END_CRITICAL_SECTION(); |
| 2625 | + Py_CLEAR(newval); |
| 2626 | + if (cs_err < 0) { |
| 2627 | + goto done; |
2616 | 2628 | } |
2617 | 2629 | Py_DECREF(key); |
2618 | 2630 | } |
|
0 commit comments