]> granicus.if.org Git - python/commitdiff
Issue #18594: Fix the fast path for collections.Counter().
authorRaymond Hettinger <python@rcn.com>
Tue, 1 Oct 2013 07:55:43 +0000 (00:55 -0700)
committerRaymond Hettinger <python@rcn.com>
Tue, 1 Oct 2013 07:55:43 +0000 (00:55 -0700)
The path wasn't being taken due to an over-restrictive type check.

Include/object.h
Misc/NEWS
Modules/_collectionsmodule.c
Objects/typeobject.c

index 387cadb4e4793be677bb6808d04f3af5b7750b10..20c4780e0c9faca34ab89707ce9ec66e216e3c05 100644 (file)
@@ -482,6 +482,7 @@ PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *,
                                                PyObject *, PyObject *);
 #ifndef Py_LIMITED_API
 PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
+PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *);
 PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *);
 PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
 #endif
index c787537857ada29baf04c0fb02eea24af77406d9..7898b9b592c59be6c8eb3bb1b8123438e7c6e050 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -74,6 +74,9 @@ Library
 - Issue #12641: Avoid passing "-mno-cygwin" to the mingw32 compiler, except
   when necessary.  Patch by Oscar Benjamin.
 
+- Issue #18594: The fast path for collections.Counter() was never taken
+  due to an over-restrictive type check.
+
 - Properly initialize all fields of a SSL object after allocation.
 
 - Issue #4366: Fix building extensions on all platforms when --enable-shared
index 34a1a903afa9ecafc8198f6f3772f9aa4bc2dc8f..cb1674898b3358fd8222d60dea0768db104e2637 100644 (file)
@@ -1689,10 +1689,16 @@ Count elements in the iterable, updating the mappping");
 static PyObject *
 _count_elements(PyObject *self, PyObject *args)
 {
+    _Py_IDENTIFIER(__getitem__);
+    _Py_IDENTIFIER(__setitem__);
     PyObject *it, *iterable, *mapping, *oldval;
     PyObject *newval = NULL;
     PyObject *key = NULL;
     PyObject *one = NULL;
+    PyObject *mapping_getitem;
+    PyObject *mapping_setitem;
+    PyObject *dict_getitem;
+    PyObject *dict_setitem;
 
     if (!PyArg_UnpackTuple(args, "_count_elements", 2, 2, &mapping, &iterable))
         return NULL;
@@ -1707,7 +1713,15 @@ _count_elements(PyObject *self, PyObject *args)
         return NULL;
     }
 
-    if (PyDict_CheckExact(mapping)) {
+    mapping_getitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___getitem__);
+    dict_getitem = _PyType_LookupId(&PyDict_Type, &PyId___getitem__);
+    mapping_setitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___setitem__);
+    dict_setitem = _PyType_LookupId(&PyDict_Type, &PyId___setitem__);
+
+    if (mapping_getitem != NULL &&
+        mapping_getitem == dict_getitem &&
+        mapping_setitem != NULL &&
+        mapping_setitem == dict_setitem) {
         while (1) {
             key = PyIter_Next(it);
             if (key == NULL)
index a55d9775ded5be389fa71147d21bd2e67f961629..3dcbc86080a98e8c7d7795af55031deaaaba748b 100644 (file)
@@ -49,9 +49,6 @@ _Py_IDENTIFIER(__module__);
 _Py_IDENTIFIER(__name__);
 _Py_IDENTIFIER(__new__);
 
-static PyObject *
-_PyType_LookupId(PyTypeObject *type, struct _Py_Identifier *name);
-
 static PyObject *
 slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
 
@@ -2589,7 +2586,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
     return res;
 }
 
-static PyObject *
+PyObject *
 _PyType_LookupId(PyTypeObject *type, struct _Py_Identifier *name)
 {
     PyObject *oname;