@@ -67,6 +67,88 @@ slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value);
6767
6868static inline PyTypeObject * subclass_from_ref (PyObject * ref );
6969
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+
70152/*
71153 * finds the beginning of the docstring's introspection signature.
72154 * if present, returns a pointer pointing to the first '('.
@@ -206,7 +288,7 @@ static struct type_cache*
206288get_type_cache (void )
207289{
208290 PyInterpreterState * interp = _PyInterpreterState_GET ();
209- return & interp -> type_cache ;
291+ return & interp -> types . type_cache ;
210292}
211293
212294
@@ -225,7 +307,7 @@ type_cache_clear(struct type_cache *cache, PyObject *value)
225307void
226308_PyType_InitCache (PyInterpreterState * interp )
227309{
228- struct type_cache * cache = & interp -> type_cache ;
310+ struct type_cache * cache = & interp -> types . type_cache ;
229311 for (Py_ssize_t i = 0 ; i < (1 << MCACHE_SIZE_EXP ); i ++ ) {
230312 struct type_cache_entry * entry = & cache -> hashtable [i ];
231313 assert (entry -> name == NULL );
@@ -242,7 +324,7 @@ _PyType_InitCache(PyInterpreterState *interp)
242324static unsigned int
243325_PyType_ClearCache (PyInterpreterState * interp )
244326{
245- struct type_cache * cache = & interp -> type_cache ;
327+ struct type_cache * cache = & interp -> types . type_cache ;
246328#if MCACHE_STATS
247329 size_t total = cache -> hits + cache -> collisions + cache -> misses ;
248330 fprintf (stderr , "-- Method cache hits = %zd (%d%%)\n" ,
@@ -274,11 +356,17 @@ PyType_ClearCache(void)
274356void
275357_PyTypes_Fini (PyInterpreterState * interp )
276358{
277- struct type_cache * cache = & interp -> type_cache ;
359+ struct type_cache * cache = & interp -> types . type_cache ;
278360 type_cache_clear (cache , NULL );
279361 if (_Py_IsMainInterpreter (interp )) {
280362 clear_slotdefs ();
281363 }
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+ }
282370}
283371
284372
@@ -4247,6 +4335,8 @@ clear_static_tp_subclasses(PyTypeObject *type)
42474335void
42484336_PyStaticType_Dealloc (PyTypeObject * type )
42494337{
4338+ assert (!(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ));
4339+
42504340 type_dealloc_common (type );
42514341
42524342 Py_CLEAR (type -> tp_dict );
@@ -4261,6 +4351,11 @@ _PyStaticType_Dealloc(PyTypeObject *type)
42614351 }
42624352
42634353 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+ }
42644359}
42654360
42664361
@@ -6679,7 +6774,13 @@ _PyStaticType_InitBuiltin(PyTypeObject *self)
66796774{
66806775 self -> tp_flags = self -> tp_flags | _Py_TPFLAGS_STATIC_BUILTIN ;
66816776
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 ;
66836784}
66846785
66856786
0 commit comments