@@ -45,7 +45,7 @@ class object "PyObject *" "&PyBaseObject_Type"
45
45
46
46
// bpo-42745: next_version_tag remains shared by all interpreters because of static types
47
47
// Used to set PyTypeObject.tp_version_tag
48
- static unsigned int next_version_tag = 0 ;
48
+ static unsigned int next_version_tag = 1 ;
49
49
50
50
typedef struct PySlot_Offset {
51
51
short subslot_offset ;
@@ -233,24 +233,14 @@ get_type_cache(void)
233
233
234
234
235
235
static void
236
- type_cache_clear (struct type_cache * cache , int use_none )
236
+ type_cache_clear (struct type_cache * cache , PyObject * value )
237
237
{
238
238
for (Py_ssize_t i = 0 ; i < (1 << MCACHE_SIZE_EXP ); i ++ ) {
239
239
struct type_cache_entry * entry = & cache -> hashtable [i ];
240
240
entry -> version = 0 ;
241
- if (use_none ) {
242
- // Set to None so _PyType_Lookup() can use Py_SETREF(),
243
- // rather than using slower Py_XSETREF().
244
- Py_XSETREF (entry -> name , Py_NewRef (Py_None ));
245
- }
246
- else {
247
- Py_CLEAR (entry -> name );
248
- }
241
+ Py_XSETREF (entry -> name , _Py_XNewRef (value ));
249
242
entry -> value = NULL ;
250
243
}
251
-
252
- // Mark all version tags as invalid
253
- PyType_Modified (& PyBaseObject_Type );
254
244
}
255
245
256
246
@@ -287,14 +277,11 @@ _PyType_ClearCache(PyInterpreterState *interp)
287
277
sizeof (cache -> hashtable ) / 1024 );
288
278
#endif
289
279
290
- unsigned int cur_version_tag = next_version_tag - 1 ;
291
- if (_Py_IsMainInterpreter (interp )) {
292
- next_version_tag = 0 ;
293
- }
280
+ // Set to None, rather than NULL, so _PyType_Lookup() can
281
+ // use Py_SETREF() rather than using slower Py_XSETREF().
282
+ type_cache_clear (cache , Py_None );
294
283
295
- type_cache_clear (cache , 0 );
296
-
297
- return cur_version_tag ;
284
+ return next_version_tag - 1 ;
298
285
}
299
286
300
287
@@ -309,7 +296,8 @@ PyType_ClearCache(void)
309
296
void
310
297
_PyType_Fini (PyInterpreterState * interp )
311
298
{
312
- _PyType_ClearCache (interp );
299
+ struct type_cache * cache = & interp -> type_cache ;
300
+ type_cache_clear (cache , NULL );
313
301
if (_Py_IsMainInterpreter (interp )) {
314
302
clear_slotdefs ();
315
303
}
@@ -426,14 +414,12 @@ assign_version_tag(struct type_cache *cache, PyTypeObject *type)
426
414
if (!_PyType_HasFeature (type , Py_TPFLAGS_READY ))
427
415
return 0 ;
428
416
429
- type -> tp_version_tag = next_version_tag ++ ;
430
- /* for stress-testing: next_version_tag &= 0xFF; */
431
-
432
- if (type -> tp_version_tag == 0 ) {
433
- // Wrap-around or just starting Python - clear the whole cache
434
- type_cache_clear (cache , 1 );
417
+ if (next_version_tag == 0 ) {
418
+ /* We have run out of version numbers */
435
419
return 0 ;
436
420
}
421
+ type -> tp_version_tag = next_version_tag ++ ;
422
+ assert (type -> tp_version_tag != 0 );
437
423
438
424
bases = type -> tp_bases ;
439
425
n = PyTuple_GET_SIZE (bases );
0 commit comments