@@ -67,6 +67,88 @@ slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value);
67
67
68
68
static inline PyTypeObject * subclass_from_ref (PyObject * ref );
69
69
70
+
71
+ /* helpers for for static builtin types */
72
+
73
+ static inline int
74
+ static_builtin_index_is_set (PyTypeObject * self )
75
+ {
76
+ return self -> tp_static_builtin_index > 0 ;
77
+ }
78
+
79
+ static inline size_t
80
+ static_builtin_index_get (PyTypeObject * self )
81
+ {
82
+ assert (static_builtin_index_is_set (self ));
83
+ /* We store a 1-based index so 0 can mean "not initialized". */
84
+ return self -> tp_static_builtin_index - 1 ;
85
+ }
86
+
87
+ static inline void
88
+ static_builtin_index_set (PyTypeObject * self , size_t index )
89
+ {
90
+ assert (index < _Py_MAX_STATIC_BUILTIN_TYPES );
91
+ /* We store a 1-based index so 0 can mean "not initialized". */
92
+ self -> tp_static_builtin_index = index + 1 ;
93
+ }
94
+
95
+ static inline void
96
+ static_builtin_index_clear (PyTypeObject * self )
97
+ {
98
+ self -> tp_static_builtin_index = 0 ;
99
+ }
100
+
101
+ static inline static_builtin_state *
102
+ static_builtin_state_get (PyInterpreterState * interp , PyTypeObject * self )
103
+ {
104
+ return & (interp -> types .builtins [static_builtin_index_get (self )]);
105
+ }
106
+
107
+ /* For static types we store some state in an array on each interpreter. */
108
+ static_builtin_state *
109
+ _PyStaticType_GetState (PyTypeObject * self )
110
+ {
111
+ assert (self -> tp_flags & _Py_TPFLAGS_STATIC_BUILTIN );
112
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
113
+ return static_builtin_state_get (interp , self );
114
+ }
115
+
116
+ static void
117
+ static_builtin_state_init (PyTypeObject * self )
118
+ {
119
+ /* Set the type's per-interpreter state. */
120
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
121
+
122
+ /* It should only be called once for each builtin type. */
123
+ assert (!static_builtin_index_is_set (self ));
124
+
125
+ static_builtin_index_set (self , interp -> types .num_builtins_initialized );
126
+ interp -> types .num_builtins_initialized ++ ;
127
+
128
+ static_builtin_state * state = static_builtin_state_get (interp , self );
129
+ state -> type = self ;
130
+ }
131
+
132
+ static void
133
+ static_builtin_state_clear (PyTypeObject * self )
134
+ {
135
+ /* Reset the type's per-interpreter state.
136
+ This basically undoes what static_builtin_state_init() did. */
137
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
138
+
139
+ static_builtin_state * state = static_builtin_state_get (interp , self );
140
+ state -> type = NULL ;
141
+ static_builtin_index_clear (self );
142
+
143
+ assert (interp -> types .num_builtins_initialized > 0 );
144
+ interp -> types .num_builtins_initialized -- ;
145
+ }
146
+
147
+ // Also see _PyStaticType_InitBuiltin() and _PyStaticType_Dealloc().
148
+
149
+ /* end static builtin helpers */
150
+
151
+
70
152
/*
71
153
* finds the beginning of the docstring's introspection signature.
72
154
* if present, returns a pointer pointing to the first '('.
@@ -206,7 +288,7 @@ static struct type_cache*
206
288
get_type_cache (void )
207
289
{
208
290
PyInterpreterState * interp = _PyInterpreterState_GET ();
209
- return & interp -> type_cache ;
291
+ return & interp -> types . type_cache ;
210
292
}
211
293
212
294
@@ -225,7 +307,7 @@ type_cache_clear(struct type_cache *cache, PyObject *value)
225
307
void
226
308
_PyType_InitCache (PyInterpreterState * interp )
227
309
{
228
- struct type_cache * cache = & interp -> type_cache ;
310
+ struct type_cache * cache = & interp -> types . type_cache ;
229
311
for (Py_ssize_t i = 0 ; i < (1 << MCACHE_SIZE_EXP ); i ++ ) {
230
312
struct type_cache_entry * entry = & cache -> hashtable [i ];
231
313
assert (entry -> name == NULL );
@@ -242,7 +324,7 @@ _PyType_InitCache(PyInterpreterState *interp)
242
324
static unsigned int
243
325
_PyType_ClearCache (PyInterpreterState * interp )
244
326
{
245
- struct type_cache * cache = & interp -> type_cache ;
327
+ struct type_cache * cache = & interp -> types . type_cache ;
246
328
#if MCACHE_STATS
247
329
size_t total = cache -> hits + cache -> collisions + cache -> misses ;
248
330
fprintf (stderr , "-- Method cache hits = %zd (%d%%)\n" ,
@@ -274,11 +356,17 @@ PyType_ClearCache(void)
274
356
void
275
357
_PyTypes_Fini (PyInterpreterState * interp )
276
358
{
277
- struct type_cache * cache = & interp -> type_cache ;
359
+ struct type_cache * cache = & interp -> types . type_cache ;
278
360
type_cache_clear (cache , NULL );
279
361
if (_Py_IsMainInterpreter (interp )) {
280
362
clear_slotdefs ();
281
363
}
364
+
365
+ assert (interp -> types .num_builtins_initialized == 0 );
366
+ // All the static builtin types should have been finalized already.
367
+ for (size_t i = 0 ; i < _Py_MAX_STATIC_BUILTIN_TYPES ; i ++ ) {
368
+ assert (interp -> types .builtins [i ].type == NULL );
369
+ }
282
370
}
283
371
284
372
@@ -4247,6 +4335,8 @@ clear_static_tp_subclasses(PyTypeObject *type)
4247
4335
void
4248
4336
_PyStaticType_Dealloc (PyTypeObject * type )
4249
4337
{
4338
+ assert (!(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ));
4339
+
4250
4340
type_dealloc_common (type );
4251
4341
4252
4342
Py_CLEAR (type -> tp_dict );
@@ -4261,6 +4351,11 @@ _PyStaticType_Dealloc(PyTypeObject *type)
4261
4351
}
4262
4352
4263
4353
type -> tp_flags &= ~Py_TPFLAGS_READY ;
4354
+
4355
+ if (type -> tp_flags & _Py_TPFLAGS_STATIC_BUILTIN ) {
4356
+ static_builtin_state_clear (type );
4357
+ /* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
4358
+ }
4264
4359
}
4265
4360
4266
4361
@@ -6679,7 +6774,13 @@ _PyStaticType_InitBuiltin(PyTypeObject *self)
6679
6774
{
6680
6775
self -> tp_flags = self -> tp_flags | _Py_TPFLAGS_STATIC_BUILTIN ;
6681
6776
6682
- return PyType_Ready (self );
6777
+ static_builtin_state_init (self );
6778
+
6779
+ int res = PyType_Ready (self );
6780
+ if (res < 0 ) {
6781
+ static_builtin_state_clear (self );
6782
+ }
6783
+ return res ;
6683
6784
}
6684
6785
6685
6786
0 commit comments