@@ -47,27 +47,37 @@ class object "PyObject *" "&PyBaseObject_Type"
4747static  inline  unsigned int  
4848mcache_name_hash (PyTypeObject  * type , PyObject  * name )
4949{
50-     unsigned  int   name_hash ;
50+     Py_hash_t  name_hash ;
5151#if  Py_GIL_DISABLED 
5252    // Cache misses are relatively more expensive for the free-threaded build. 
5353    // So we use the unicode string hash and unicode compare for caching 
5454    // names.  This allows caching of non-interned strings. 
55-     if  (PyUnicode_CheckExact (name )) {
56-         name_hash  =  (unsigned int  )_PyObject_HashFast (name );
57-     }
58-     else  {
59-         name_hash  =  0 ;
60-     }
55+     assert (PyUnicode_CheckExact (name ));
56+     name_hash  =  _PyObject_HashFast (name );
57+     // should not fail to hash an exact unicode object 
58+     assert (name_hash  !=  -1 );
6159#else 
6260    // Use the pointer value of the string for the hash and the compare.  This 
6361    // is faster but non-interned strings can't use the cache. 
64-     name_hash  =  ((Py_ssize_t )(name )) >> 3 ;
62+     name_hash  =  ((Py_hash_t )(name )) >> 3 ;
6563#endif 
6664    unsigned int   version  =  FT_ATOMIC_LOAD_UINT32_RELAXED ((type )-> tp_version_tag );
6765    return  (((unsigned int  )(version ) ^ (unsigned int  )(name_hash )) & 
6866            ((1  << MCACHE_SIZE_EXP ) -  1 ));
6967}
7068
69+ static  inline  struct  type_cache_entry  * 
70+ mcache_get_entry (PyTypeObject  * type , PyObject  * name , struct  type_cache  * cache )
71+ {
72+ #ifdef  Py_GIL_DISABLED 
73+     if  (!PyUnicode_CheckExact (name )) {
74+         return  NULL ;
75+     }
76+ #endif 
77+     unsigned int   h  =  mcache_name_hash (type , name );
78+     return  & cache -> hashtable [h ];
79+ }
80+ 
7181static  inline  int 
7282mcache_name_eq (PyObject  * entry_name ,  PyObject  * name )
7383{
@@ -76,7 +86,7 @@ mcache_name_eq(PyObject *entry_name,  PyObject *name)
7686        return  0 ;
7787    }
7888    assert (PyUnicode_CheckExact (entry_name ));
79-     assert (PyUnicode_Check (name ));
89+     assert (PyUnicode_CheckExact (name ));
8090    return  _PyUnicode_Equal (entry_name , name );
8191#else 
8292    return  entry_name  ==  name ;
@@ -5754,12 +5764,11 @@ _PyType_LookupRefAndVersion(PyTypeObject *type, PyObject *name, unsigned int *ve
57545764unsigned int  
57555765_PyType_LookupStackRefAndVersion (PyTypeObject  * type , PyObject  * name , _PyStackRef  * out )
57565766{
5757-     unsigned int   h  =  mcache_name_hash (type , name );
57585767    struct  type_cache  * cache  =  get_type_cache ();
5759-     struct  type_cache_entry  * entry  =  & cache -> hashtable [ h ] ;
5768+     struct  type_cache_entry  * entry  =  mcache_get_entry ( type ,  name ,  cache ) ;
57605769#ifdef  Py_GIL_DISABLED 
57615770    // synchronize-with other writing threads by doing an acquire load on the sequence 
5762-     while  (1 ) {
5771+     while  (entry   !=   NULL ) {
57635772        uint32_t  sequence  =  _PySeqLock_BeginRead (& entry -> sequence );
57645773        uint32_t  entry_version  =  _Py_atomic_load_uint32_acquire (& entry -> version );
57655774        uint32_t  type_version  =  _Py_atomic_load_uint32_acquire (& type -> tp_version_tag );
@@ -5837,6 +5846,7 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef
58375846
58385847    if  (has_version ) {
58395848#if  Py_GIL_DISABLED 
5849+         assert (entry  !=  NULL );
58405850        update_cache_gil_disabled (entry , name , assigned_version , res );
58415851#else 
58425852        PyObject  * old_value  =  update_cache (entry , name , assigned_version , res );
0 commit comments