Commit 224c87d6 authored by Raymond Hettinger's avatar Raymond Hettinger

Issue #18594: Fix the fallback path in collections.Counter().

parent 1a33b2f3
...@@ -79,7 +79,8 @@ Library ...@@ -79,7 +79,8 @@ Library
when necessary. Patch by Oscar Benjamin. when necessary. Patch by Oscar Benjamin.
- Issue #18594: The fast path for collections.Counter() was never taken - Issue #18594: The fast path for collections.Counter() was never taken
due to an over-restrictive type check. due to an over-restrictive type check. And the fallback path did
not implement the same algorithm as the pure python code.
- Properly initialize all fields of a SSL object after allocation. - Properly initialize all fields of a SSL object after allocation.
......
...@@ -1694,7 +1694,9 @@ _count_elements(PyObject *self, PyObject *args) ...@@ -1694,7 +1694,9 @@ _count_elements(PyObject *self, PyObject *args)
PyObject *it, *iterable, *mapping, *oldval; PyObject *it, *iterable, *mapping, *oldval;
PyObject *newval = NULL; PyObject *newval = NULL;
PyObject *key = NULL; PyObject *key = NULL;
PyObject *zero = NULL;
PyObject *one = NULL; PyObject *one = NULL;
PyObject *mapping_get = NULL;
PyObject *mapping_getitem; PyObject *mapping_getitem;
PyObject *mapping_setitem; PyObject *mapping_setitem;
PyObject *dict_getitem; PyObject *dict_getitem;
...@@ -1708,10 +1710,8 @@ _count_elements(PyObject *self, PyObject *args) ...@@ -1708,10 +1710,8 @@ _count_elements(PyObject *self, PyObject *args)
return NULL; return NULL;
one = PyLong_FromLong(1); one = PyLong_FromLong(1);
if (one == NULL) { if (one == NULL)
Py_DECREF(it); goto done;
return NULL;
}
mapping_getitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___getitem__); mapping_getitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___getitem__);
dict_getitem = _PyType_LookupId(&PyDict_Type, &PyId___getitem__); dict_getitem = _PyType_LookupId(&PyDict_Type, &PyId___getitem__);
...@@ -1741,23 +1741,25 @@ _count_elements(PyObject *self, PyObject *args) ...@@ -1741,23 +1741,25 @@ _count_elements(PyObject *self, PyObject *args)
Py_DECREF(key); Py_DECREF(key);
} }
} else { } else {
mapping_get = PyObject_GetAttrString(mapping, "get");
if (mapping_get == NULL)
goto done;
zero = PyLong_FromLong(0);
if (zero == NULL)
goto done;
while (1) { while (1) {
key = PyIter_Next(it); key = PyIter_Next(it);
if (key == NULL) if (key == NULL)
break; break;
oldval = PyObject_GetItem(mapping, key); oldval = PyObject_CallFunctionObjArgs(mapping_get, key, zero, NULL);
if (oldval == NULL) { if (oldval == NULL)
if (!PyErr_Occurred() || !PyErr_ExceptionMatches(PyExc_KeyError)) break;
break; newval = PyNumber_Add(oldval, one);
PyErr_Clear(); Py_DECREF(oldval);
Py_INCREF(one); if (newval == NULL)
newval = one; break;
} else {
newval = PyNumber_Add(oldval, one);
Py_DECREF(oldval);
if (newval == NULL)
break;
}
if (PyObject_SetItem(mapping, key, newval) == -1) if (PyObject_SetItem(mapping, key, newval) == -1)
break; break;
Py_CLEAR(newval); Py_CLEAR(newval);
...@@ -1765,10 +1767,13 @@ _count_elements(PyObject *self, PyObject *args) ...@@ -1765,10 +1767,13 @@ _count_elements(PyObject *self, PyObject *args)
} }
} }
done:
Py_DECREF(it); Py_DECREF(it);
Py_XDECREF(key); Py_XDECREF(key);
Py_XDECREF(newval); Py_XDECREF(newval);
Py_DECREF(one); Py_XDECREF(mapping_get);
Py_XDECREF(zero);
Py_XDECREF(one);
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
Py_RETURN_NONE; Py_RETURN_NONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment