@@ -22,6 +22,7 @@ static struct {
2222 .mask = _Py_TYPECACHE_MINSIZE - 1 ,
2323 .available = 0 ,
2424 .used = 0 ,
25+ .version_tag = 0 ,
2526 },
2627};
2728// The empty cache is statically allocated and shared across all the types,
@@ -96,13 +97,13 @@ cache_slot(PyTypeObject *type)
9697static inline struct type_cache *
9798cache_get (PyTypeObject * type )
9899{
99- return (struct type_cache * )FT_ATOMIC_LOAD_PTR (* cache_slot (type ));
100+ return (struct type_cache * )FT_ATOMIC_LOAD_PTR_ACQUIRE (* cache_slot (type ));
100101}
101102
102103static inline void
103104cache_set (PyTypeObject * type , struct type_cache * cache )
104105{
105- FT_ATOMIC_STORE_PTR (* cache_slot (type ), cache );
106+ FT_ATOMIC_STORE_PTR_RELEASE (* cache_slot (type ), cache );
106107}
107108
108109void
@@ -124,8 +125,8 @@ cache_insert(struct type_cache *cache, PyObject *name,
124125 // On free-threading, all interned strings are immortal.
125126 Py_INCREF (name );
126127#endif
127- FT_ATOMIC_STORE_PTR ( cache -> hashtable [index ].value , value ) ;
128- FT_ATOMIC_STORE_PTR (cache -> hashtable [index ].name , name );
128+ cache -> hashtable [index ].value = value ;
129+ FT_ATOMIC_STORE_PTR_RELEASE (cache -> hashtable [index ].name , name );
129130 cache -> used ++ ;
130131 cache -> available -- ;
131132 return ;
@@ -151,17 +152,20 @@ cache_resize(PyTypeObject *type, struct type_cache *cache)
151152 // double the cache size when resizing
152153 new_size = old_size * 2 ;
153154 }
155+ if (new_size > _Py_TYPECACHE_MAXSIZE ) {
156+ // The cache is too big, don't resize and just return.
157+ return -1 ;
158+ }
154159 struct type_cache * new_cache = cache_allocate (new_size );
155160 if (new_cache == NULL ) {
156161 return -1 ;
157162 }
158163 for (uint32_t i = 0 ; i < old_size ; i ++ ) {
159164 if (cache -> hashtable [i ].name != NULL ) {
160- cache_insert (new_cache , cache -> hashtable [i ].name ,
161- cache -> hashtable [i ].value );
165+ cache_insert (new_cache , cache -> hashtable [i ].name , cache -> hashtable [i ].value );
162166 }
163167 }
164- new_cache -> version_tag = cache -> version_tag ;
168+ new_cache -> version_tag = type -> tp_version_tag ;
165169 cache_set (type , new_cache );
166170 cache_free_delayed (cache );
167171 return 0 ;
@@ -183,8 +187,8 @@ _PyTypeCache_Insert(PyTypeObject *type, PyObject *name, PyObject *value)
183187 cache = cache_get (type );
184188 assert (cache -> available > 0 );
185189 }
190+ assert (cache -> version_tag == type -> tp_version_tag );
186191 cache_insert (cache , name , value );
187- FT_ATOMIC_STORE_UINT_RELAXED (cache -> version_tag , FT_ATOMIC_LOAD_UINT_RELAXED (type -> tp_version_tag ));
188192}
189193
190194
@@ -205,10 +209,7 @@ _PyTypeCache_Lookup(PyTypeObject *type, PyObject *name)
205209 uint32_t index = hash & cache -> mask ;
206210 _PyStackRef out_ref ;
207211 for (;;) {
208- PyObject * entry_name = FT_ATOMIC_LOAD_PTR (cache -> hashtable [index ].name );
209- if (entry_name == NULL ) {
210- return miss ;
211- }
212+ PyObject * entry_name = FT_ATOMIC_LOAD_PTR_ACQUIRE (cache -> hashtable [index ].name );
212213 if (entry_name == name ) {
213214#ifdef Py_GIL_DISABLED
214215 if (!_Py_TryXGetStackRef (& cache -> hashtable [index ].value , & out_ref )) {
@@ -220,15 +221,18 @@ _PyTypeCache_Lookup(PyTypeObject *type, PyObject *name)
220221#endif
221222 break ;
222223 }
224+ else if (entry_name == NULL ) {
225+ return miss ;
226+ }
223227 index = (index + 1 ) & cache -> mask ;
224228 }
225- // to maintain consistency with find_name_in_mro and prevent stale cache reads
226- uint32_t cache_version = FT_ATOMIC_LOAD_UINT_RELAXED ( cache -> version_tag );
227- if (cache_version != FT_ATOMIC_LOAD_UINT_RELAXED (type -> tp_version_tag )) {
229+ // Check the cache version against the type version tag to maintain
230+ // consistency with find_name_in_mro and prevent stale cache reads
231+ if (cache -> version_tag != FT_ATOMIC_LOAD_UINT_RELAXED (type -> tp_version_tag )) {
228232 PyStackRef_XCLOSE (out_ref );
229233 return miss ;
230234 }
231- return (struct _PyTypeCacheLookupResult ){out_ref , 1 , cache_version };
235+ return (struct _PyTypeCacheLookupResult ){out_ref , 1 , cache -> version_tag };
232236}
233237
234238// Invalidate the type cache of the type.
0 commit comments