https://github.com/python/cpython/commit/eca53620e3ff1f2e7d621360a513ac34a1b35aa3
commit: eca53620e3ff1f2e7d621360a513ac34a1b35aa3
branch: main
author: Eric Snow <[email protected]>
committer: ericsnowcurrently <[email protected]>
date: 2024-04-12T16:39:27-06:00
summary:
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
files:
M Include/internal/pycore_typeobject.h
M Objects/typeobject.c
diff --git a/Include/internal/pycore_typeobject.h
b/Include/internal/pycore_typeobject.h
index 1693119ffece03..09c4501c38c935 100644
--- a/Include/internal/pycore_typeobject.h
+++ b/Include/internal/pycore_typeobject.h
@@ -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;
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index a3c137536a4d87..1cb53516a9ae76 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -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. */
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]