1616#include "pycore_stackref.h" // _Py_TryIncrefCompareStackRef()
1717#include "pycore_tuple.h" // _PyTuple_FromArraySteal()
1818#include "pycore_typeobject.h" // _Py_TYPE_VERSION_LIST
19+ #include "pycore_unicodeobject.h" // _PyUnicode_Equal()
1920#include <stddef.h>
2021
2122/*[clinic input]
@@ -707,17 +708,55 @@ list_length(PyObject *a)
707708 return PyList_GET_SIZE (a );
708709}
709710
711+ static inline PyTypeObject *
712+ list_fast_eq_type (PyObject * value )
713+ {
714+ if (value != NULL ) {
715+ PyTypeObject * type = Py_TYPE (value );
716+ if (type == & PyLong_Type || type == & PyFloat_Type ||
717+ type == & PyUnicode_Type ) {
718+ return type ;
719+ }
720+ }
721+ return NULL ;
722+ }
723+
724+ static inline int
725+ list_item_eq (PyObject * item , PyObject * value , PyTypeObject * fast_type )
726+ {
727+ if (fast_type != NULL && Py_TYPE (item ) == fast_type ) {
728+ if (item == value ) {
729+ return 1 ;
730+ }
731+ if (fast_type == & PyLong_Type ) {
732+ PyLongObject * v = (PyLongObject * )item ;
733+ PyLongObject * w = (PyLongObject * )value ;
734+ if (_PyLong_BothAreCompact (v , w )) {
735+ return _PyLong_CompactValue (v ) == _PyLong_CompactValue (w );
736+ }
737+ }
738+ else if (fast_type == & PyFloat_Type ) {
739+ return PyFloat_AS_DOUBLE (item ) == PyFloat_AS_DOUBLE (value );
740+ }
741+ else {
742+ assert (fast_type == & PyUnicode_Type );
743+ return _PyUnicode_Equal (item , value );
744+ }
745+ }
746+ return PyObject_RichCompareBool (item , value , Py_EQ );
747+ }
748+
710749static int
711750list_contains (PyObject * aa , PyObject * el )
712751{
713-
752+ PyTypeObject * fast_type = list_fast_eq_type ( el );
714753 for (Py_ssize_t i = 0 ; ; i ++ ) {
715754 PyObject * item = list_get_item_ref ((PyListObject * )aa , i );
716755 if (item == NULL ) {
717756 // out-of-bounds
718757 return 0 ;
719758 }
720- int cmp = PyObject_RichCompareBool (item , el , Py_EQ );
759+ int cmp = list_item_eq (item , el , fast_type );
721760 Py_DECREF (item );
722761 if (cmp != 0 ) {
723762 return cmp ;
@@ -3391,13 +3430,14 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start,
33913430 if (stop < 0 )
33923431 stop = 0 ;
33933432 }
3433+ PyTypeObject * fast_type = list_fast_eq_type (value );
33943434 for (Py_ssize_t i = start ; i < stop ; i ++ ) {
33953435 PyObject * obj = list_get_item_ref (self , i );
33963436 if (obj == NULL ) {
33973437 // out-of-bounds
33983438 break ;
33993439 }
3400- int cmp = PyObject_RichCompareBool (obj , value , Py_EQ );
3440+ int cmp = list_item_eq (obj , value , fast_type );
34013441 Py_DECREF (obj );
34023442 if (cmp > 0 )
34033443 return PyLong_FromSsize_t (i );
@@ -3422,6 +3462,7 @@ list_count_impl(PyListObject *self, PyObject *value)
34223462/*[clinic end generated code: output=eff66f14aef2df86 input=3bdc3a5e6f749565]*/
34233463{
34243464 Py_ssize_t count = 0 ;
3465+ PyTypeObject * fast_type = list_fast_eq_type (value );
34253466 for (Py_ssize_t i = 0 ; ; i ++ ) {
34263467 PyObject * obj = list_get_item_ref (self , i );
34273468 if (obj == NULL ) {
@@ -3433,7 +3474,7 @@ list_count_impl(PyListObject *self, PyObject *value)
34333474 Py_DECREF (obj );
34343475 continue ;
34353476 }
3436- int cmp = PyObject_RichCompareBool (obj , value , Py_EQ );
3477+ int cmp = list_item_eq (obj , value , fast_type );
34373478 Py_DECREF (obj );
34383479 if (cmp > 0 )
34393480 count ++ ;
@@ -3460,11 +3501,12 @@ list_remove_impl(PyListObject *self, PyObject *value)
34603501/*[clinic end generated code: output=b9b76a6633b18778 input=26c813dbb95aa93b]*/
34613502{
34623503 Py_ssize_t i ;
3504+ PyTypeObject * fast_type = list_fast_eq_type (value );
34633505
34643506 for (i = 0 ; i < Py_SIZE (self ); i ++ ) {
34653507 PyObject * obj = self -> ob_item [i ];
34663508 Py_INCREF (obj );
3467- int cmp = PyObject_RichCompareBool (obj , value , Py_EQ );
3509+ int cmp = list_item_eq (obj , value , fast_type );
34683510 Py_DECREF (obj );
34693511 if (cmp > 0 ) {
34703512 if (list_ass_slice_lock_held (self , i , i + 1 , NULL ) == 0 )
@@ -3522,7 +3564,7 @@ list_richcompare_impl(PyObject *v, PyObject *w, int op)
35223564
35233565 Py_INCREF (vitem );
35243566 Py_INCREF (witem );
3525- int k = PyObject_RichCompareBool (vitem , witem , Py_EQ );
3567+ int k = list_item_eq (vitem , witem , list_fast_eq_type ( witem ) );
35263568 if (k < 0 ) {
35273569 Py_DECREF (vitem );
35283570 Py_DECREF (witem );
0 commit comments