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

Skip to content

Commit 2ff2190

Browse files
committed
Issue #18594: Fix the fast path for collections.Counter().
The path wasn't being taken due to an over-restrictive type check.
1 parent 21b2933 commit 2ff2190

4 files changed

Lines changed: 20 additions & 5 deletions

File tree

Include/object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *,
482482
PyObject *, PyObject *);
483483
#ifndef Py_LIMITED_API
484484
PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
485+
PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *);
485486
PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *);
486487
PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
487488
#endif

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ Library
7474
- Issue #12641: Avoid passing "-mno-cygwin" to the mingw32 compiler, except
7575
when necessary. Patch by Oscar Benjamin.
7676

77+
- Issue #18594: The fast path for collections.Counter() was never taken
78+
due to an over-restrictive type check.
79+
7780
- Properly initialize all fields of a SSL object after allocation.
7881

7982
- Issue #4366: Fix building extensions on all platforms when --enable-shared

Modules/_collectionsmodule.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,10 +1689,16 @@ Count elements in the iterable, updating the mappping");
16891689
static PyObject *
16901690
_count_elements(PyObject *self, PyObject *args)
16911691
{
1692+
_Py_IDENTIFIER(__getitem__);
1693+
_Py_IDENTIFIER(__setitem__);
16921694
PyObject *it, *iterable, *mapping, *oldval;
16931695
PyObject *newval = NULL;
16941696
PyObject *key = NULL;
16951697
PyObject *one = NULL;
1698+
PyObject *mapping_getitem;
1699+
PyObject *mapping_setitem;
1700+
PyObject *dict_getitem;
1701+
PyObject *dict_setitem;
16961702

16971703
if (!PyArg_UnpackTuple(args, "_count_elements", 2, 2, &mapping, &iterable))
16981704
return NULL;
@@ -1707,7 +1713,15 @@ _count_elements(PyObject *self, PyObject *args)
17071713
return NULL;
17081714
}
17091715

1710-
if (PyDict_CheckExact(mapping)) {
1716+
mapping_getitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___getitem__);
1717+
dict_getitem = _PyType_LookupId(&PyDict_Type, &PyId___getitem__);
1718+
mapping_setitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___setitem__);
1719+
dict_setitem = _PyType_LookupId(&PyDict_Type, &PyId___setitem__);
1720+
1721+
if (mapping_getitem != NULL &&
1722+
mapping_getitem == dict_getitem &&
1723+
mapping_setitem != NULL &&
1724+
mapping_setitem == dict_setitem) {
17111725
while (1) {
17121726
key = PyIter_Next(it);
17131727
if (key == NULL)

Objects/typeobject.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ _Py_IDENTIFIER(__module__);
4949
_Py_IDENTIFIER(__name__);
5050
_Py_IDENTIFIER(__new__);
5151

52-
static PyObject *
53-
_PyType_LookupId(PyTypeObject *type, struct _Py_Identifier *name);
54-
5552
static PyObject *
5653
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
5754

@@ -2589,7 +2586,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
25892586
return res;
25902587
}
25912588

2592-
static PyObject *
2589+
PyObject *
25932590
_PyType_LookupId(PyTypeObject *type, struct _Py_Identifier *name)
25942591
{
25952592
PyObject *oname;

0 commit comments

Comments
 (0)