mirror of
https://github.com/python/cpython.git
synced 2025-08-15 22:30:42 +00:00
[3.12] gh-105020: Share tp_bases and tp_mro Between Interpreters For All Static Builtin Types (gh-105115) (gh-105124)
In gh-103912 we added tp_bases and tp_mro to each PyInterpreterState.types.builtins entry. However, doing so ignored the fact that both PyTypeObject fields are public API, and not documented as internal (as opposed to tp_subclasses). We address that here by reverting back to shared objects, making them immortal in the process.
(cherry picked from commit 7be667d
)
Co-authored-by: Eric Snow ericsnowcurrently@gmail.com
This commit is contained in:
parent
83c7386cee
commit
c38ceb032d
7 changed files with 26544 additions and 26462 deletions
|
@ -268,12 +268,6 @@ clear_tp_dict(PyTypeObject *self)
|
|||
static inline PyObject *
|
||||
lookup_tp_bases(PyTypeObject *self)
|
||||
{
|
||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
||||
assert(state != NULL);
|
||||
return state->tp_bases;
|
||||
}
|
||||
return self->tp_bases;
|
||||
}
|
||||
|
||||
|
@ -287,12 +281,22 @@ _PyType_GetBases(PyTypeObject *self)
|
|||
static inline void
|
||||
set_tp_bases(PyTypeObject *self, PyObject *bases)
|
||||
{
|
||||
assert(PyTuple_CheckExact(bases));
|
||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
||||
assert(state != NULL);
|
||||
state->tp_bases = bases;
|
||||
return;
|
||||
// XXX tp_bases can probably be statically allocated for each
|
||||
// static builtin type.
|
||||
assert(_Py_IsMainInterpreter(_PyInterpreterState_GET()));
|
||||
assert(self->tp_bases == NULL);
|
||||
if (PyTuple_GET_SIZE(bases) == 0) {
|
||||
assert(self->tp_base == NULL);
|
||||
}
|
||||
else {
|
||||
assert(PyTuple_GET_SIZE(bases) == 1);
|
||||
assert(PyTuple_GET_ITEM(bases, 0) == (PyObject *)self->tp_base);
|
||||
assert(self->tp_base->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
|
||||
assert(_Py_IsImmortal(self->tp_base));
|
||||
}
|
||||
_Py_SetImmortal(bases);
|
||||
}
|
||||
self->tp_bases = bases;
|
||||
}
|
||||
|
@ -301,10 +305,14 @@ static inline void
|
|||
clear_tp_bases(PyTypeObject *self)
|
||||
{
|
||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
||||
assert(state != NULL);
|
||||
Py_CLEAR(state->tp_bases);
|
||||
if (_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
|
||||
if (self->tp_bases != NULL
|
||||
&& PyTuple_GET_SIZE(self->tp_bases) > 0)
|
||||
{
|
||||
assert(_Py_IsImmortal(self->tp_bases));
|
||||
_Py_ClearImmortal(self->tp_bases);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Py_CLEAR(self->tp_bases);
|
||||
|
@ -314,12 +322,6 @@ clear_tp_bases(PyTypeObject *self)
|
|||
static inline PyObject *
|
||||
lookup_tp_mro(PyTypeObject *self)
|
||||
{
|
||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
||||
assert(state != NULL);
|
||||
return state->tp_mro;
|
||||
}
|
||||
return self->tp_mro;
|
||||
}
|
||||
|
||||
|
@ -333,12 +335,14 @@ _PyType_GetMRO(PyTypeObject *self)
|
|||
static inline void
|
||||
set_tp_mro(PyTypeObject *self, PyObject *mro)
|
||||
{
|
||||
assert(PyTuple_CheckExact(mro));
|
||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
||||
assert(state != NULL);
|
||||
state->tp_mro = mro;
|
||||
return;
|
||||
// XXX tp_mro can probably be statically allocated for each
|
||||
// static builtin type.
|
||||
assert(_Py_IsMainInterpreter(_PyInterpreterState_GET()));
|
||||
assert(self->tp_mro == NULL);
|
||||
/* Other checks are done via set_tp_bases. */
|
||||
_Py_SetImmortal(mro);
|
||||
}
|
||||
self->tp_mro = mro;
|
||||
}
|
||||
|
@ -347,10 +351,14 @@ static inline void
|
|||
clear_tp_mro(PyTypeObject *self)
|
||||
{
|
||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
||||
assert(state != NULL);
|
||||
Py_CLEAR(state->tp_mro);
|
||||
if (_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
|
||||
if (self->tp_mro != NULL
|
||||
&& PyTuple_GET_SIZE(self->tp_mro) > 0)
|
||||
{
|
||||
assert(_Py_IsImmortal(self->tp_mro));
|
||||
_Py_ClearImmortal(self->tp_mro);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Py_CLEAR(self->tp_mro);
|
||||
|
@ -7153,6 +7161,14 @@ type_ready_preheader(PyTypeObject *type)
|
|||
static int
|
||||
type_ready_mro(PyTypeObject *type)
|
||||
{
|
||||
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||
if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
|
||||
assert(lookup_tp_mro(type) != NULL);
|
||||
return 0;
|
||||
}
|
||||
assert(lookup_tp_mro(type) == NULL);
|
||||
}
|
||||
|
||||
/* Calculate method resolution order */
|
||||
if (mro_internal(type, NULL) < 0) {
|
||||
return -1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue