@@ -68,6 +68,9 @@ static PyObject _dummy_struct;
6868#define  SET_LOOKKEY_CHANGED  (-2)
6969#define  SET_LOOKKEY_EMPTY  (-3)
7070
71+ typedef  int  (* compare_func )(PySetObject  * so , setentry  * table , setentry  * ep ,
72+                             PyObject  * key , Py_hash_t  hash );
73+ 
7174#ifdef  Py_GIL_DISABLED 
7275
7376#define  SET_IS_SHARED (so ) _PyObject_GC_IS_SHARED(so)
@@ -159,6 +162,36 @@ set_compare_entry(PySetObject *so, setentry *table, setentry *entry,
159162    return  SET_LOOKKEY_NO_MATCH ;
160163}
161164
165+ // This is similar to set_compare_entry() but we don't need to incref startkey 
166+ // before comparing and we don't need to check if the set has changed. 
167+ static  inline  Py_ALWAYS_INLINE  int 
168+ set_compare_frozenset (PySetObject  * so , setentry  * table , setentry  * ep ,
169+                                  PyObject  * key , Py_hash_t  hash )
170+ {
171+     assert (PyFrozenSet_CheckExact (so ));
172+     PyObject  * startkey  =  ep -> key ;
173+     if  (startkey  ==  NULL ) {
174+         return  SET_LOOKKEY_EMPTY ;
175+     }
176+     if  (startkey  ==  key ) {
177+         return  SET_LOOKKEY_FOUND ;
178+     }
179+     Py_ssize_t  ep_hash  =  ep -> hash ;
180+     if  (ep_hash  ==  hash ) {
181+         if  (PyUnicode_CheckExact (startkey )
182+             &&  PyUnicode_CheckExact (key )
183+             &&  unicode_eq (startkey , key ))
184+             return  SET_LOOKKEY_FOUND ;
185+         int  cmp  =  PyObject_RichCompareBool (startkey , key , Py_EQ );
186+         if  (cmp  <  0 ) {
187+             return  SET_LOOKKEY_ERROR ;
188+         }
189+         assert (cmp  ==  SET_LOOKKEY_FOUND  ||  cmp  ==  SET_LOOKKEY_NO_MATCH );
190+         return  cmp ;
191+     }
192+     return  SET_LOOKKEY_NO_MATCH ;
193+ }
194+ 
162195static  void 
163196set_zero_table (setentry  * table , size_t  size )
164197{
@@ -186,9 +219,7 @@ set_zero_table(setentry *table, size_t size)
186219
187220static  int 
188221set_do_lookup (PySetObject  * so , setentry  * table , size_t  mask , PyObject  * key ,
189-               Py_hash_t  hash , setentry  * * epp ,
190-               int  (* compare_entry )(PySetObject  * so , setentry  * table , setentry  * ep ,
191-                                    PyObject  * key , Py_hash_t  hash ))
222+               Py_hash_t  hash , setentry  * * epp , compare_func  compare_entry )
192223{
193224    setentry  * entry ;
194225    size_t  perturb  =  hash ;
@@ -363,11 +394,18 @@ static int
363394set_lookkey (PySetObject  * so , PyObject  * key , Py_hash_t  hash , setentry  * * epp )
364395{
365396    int  status ;
366-     Py_BEGIN_CRITICAL_SECTION (so );
367-     do  {
368-         status  =  set_do_lookup (so , so -> table , so -> mask , key , hash , epp , set_compare_entry );
369-     } while  (status  ==  SET_LOOKKEY_CHANGED );
370-     Py_END_CRITICAL_SECTION ();
397+     if  (PyFrozenSet_CheckExact (so )) {
398+         status  =  set_do_lookup (so , so -> table , so -> mask , key , hash , epp ,
399+                                set_compare_frozenset );
400+     }
401+     else  {
402+         Py_BEGIN_CRITICAL_SECTION (so );
403+         do  {
404+             status  =  set_do_lookup (so , so -> table , so -> mask , key , hash , epp ,
405+                                    set_compare_entry );
406+         } while  (status  ==  SET_LOOKKEY_CHANGED );
407+         Py_END_CRITICAL_SECTION ();
408+     }
371409    assert (status  ==  SET_LOOKKEY_FOUND  || 
372410           status  ==  SET_LOOKKEY_NO_MATCH  || 
373411           status  ==  SET_LOOKKEY_ERROR );
@@ -380,13 +418,22 @@ set_lookkey_threadsafe(PySetObject *so, PyObject *key, Py_hash_t hash)
380418{
381419    int  status ;
382420    setentry  * entry ;
421+     if  (PyFrozenSet_CheckExact (so )) {
422+         status  =  set_do_lookup (so , so -> table , so -> mask , key , hash , & entry ,
423+                                set_compare_frozenset );
424+         assert (status  ==  SET_LOOKKEY_FOUND  || 
425+                status  ==  SET_LOOKKEY_NO_MATCH  || 
426+                status  ==  SET_LOOKKEY_ERROR );
427+         return  status ;
428+     }
383429    ensure_shared_on_read (so );
384430    setentry  * table  =  FT_ATOMIC_LOAD_PTR_ACQUIRE (so -> table );
385431    size_t  mask  =  FT_ATOMIC_LOAD_SSIZE_RELAXED (so -> mask );
386432    if  (table  ==  NULL  ||  table  !=  FT_ATOMIC_LOAD_PTR_ACQUIRE (so -> table )) {
387433        return  set_lookkey (so , key , hash , & entry );
388434    }
389-     status  =  set_do_lookup (so , table , mask , key , hash , & entry , set_compare_threadsafe );
435+     status  =  set_do_lookup (so , table , mask , key , hash , & entry ,
436+                            set_compare_threadsafe );
390437    if  (status  ==  SET_LOOKKEY_CHANGED ) {
391438        return  set_lookkey (so , key , hash , & entry );
392439    }
0 commit comments