mirror of https://github.com/python/cpython
gh-94673: Clarify About Runtime State Related to Static Builtin Types (gh-117761)
Guido pointed out to me that some details about the per-interpreter state for the builtin types aren't especially clear. I'm addressing that by: * adding a comment explaining that state * adding some asserts to point out the relationship between each index and the interp/global runtime state
This commit is contained in:
parent
30f0643e36
commit
eca53620e3
|
@ -68,6 +68,43 @@ struct types_state {
|
|||
unsigned int next_version_tag;
|
||||
|
||||
struct type_cache type_cache;
|
||||
|
||||
/* Every static builtin type is initialized for each interpreter
|
||||
during its own initialization, including for the main interpreter
|
||||
during global runtime initialization. This is done by calling
|
||||
_PyStaticType_InitBuiltin().
|
||||
|
||||
The first time a static builtin type is initialized, all the
|
||||
normal PyType_Ready() stuff happens. The only difference from
|
||||
normal is that there are three PyTypeObject fields holding
|
||||
objects which are stored here (on PyInterpreterState) rather
|
||||
than in the corresponding PyTypeObject fields. Those are:
|
||||
tp_dict (cls.__dict__), tp_subclasses (cls.__subclasses__),
|
||||
and tp_weaklist.
|
||||
|
||||
When a subinterpreter is initialized, each static builtin type
|
||||
is still initialized, but only the interpreter-specific portion,
|
||||
namely those three objects.
|
||||
|
||||
Those objects are stored in the PyInterpreterState.types.builtins
|
||||
array, at the index corresponding to each specific static builtin
|
||||
type. That index (a size_t value) is stored in the tp_subclasses
|
||||
field. For static builtin types, we re-purposed the now-unused
|
||||
tp_subclasses to avoid adding another field to PyTypeObject.
|
||||
In all other cases tp_subclasses holds a dict like before.
|
||||
(The field was previously defined as PyObject*, but is now void*
|
||||
to reflect its dual use.)
|
||||
|
||||
The index for each static builtin type isn't statically assigned.
|
||||
Instead it is calculated the first time a type is initialized
|
||||
(by the main interpreter). The index matches the order in which
|
||||
the type was initialized relative to the others. The actual
|
||||
value comes from the current value of num_builtins_initialized,
|
||||
as each type is initialized for the main interpreter.
|
||||
|
||||
num_builtins_initialized is incremented once for each static
|
||||
builtin type. Once initialization is over for a subinterpreter,
|
||||
the value will be the same as for all other interpreters. */
|
||||
size_t num_builtins_initialized;
|
||||
static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
|
||||
PyMutex mutex;
|
||||
|
|
|
@ -162,9 +162,14 @@ _PyStaticType_GetState(PyInterpreterState *interp, PyTypeObject *self)
|
|||
static void
|
||||
static_builtin_state_init(PyInterpreterState *interp, PyTypeObject *self)
|
||||
{
|
||||
if (!static_builtin_index_is_set(self)) {
|
||||
if (_Py_IsMainInterpreter(interp)) {
|
||||
assert(!static_builtin_index_is_set(self));
|
||||
static_builtin_index_set(self, interp->types.num_builtins_initialized);
|
||||
}
|
||||
else {
|
||||
assert(static_builtin_index_get(self) ==
|
||||
interp->types.num_builtins_initialized);
|
||||
}
|
||||
static_builtin_state *state = static_builtin_state_get(interp, self);
|
||||
|
||||
/* It should only be called once for each builtin type. */
|
||||
|
|
Loading…
Reference in New Issue