diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2023-05-31 00:13:35 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-31 00:13:35 (GMT) |
commit | 7be667dfafa2465df6342d72dca9c1f82dd830d0 (patch) | |
tree | 6fb8852fb71d0348327d0d79bf152acb4fddd03d /Objects | |
parent | 26e7bbf66e93ee7c94b6e007ec7b2d769c2ced92 (diff) | |
download | cpython-7be667dfafa2465df6342d72dca9c1f82dd830d0.zip cpython-7be667dfafa2465df6342d72dca9c1f82dd830d0.tar.gz cpython-7be667dfafa2465df6342d72dca9c1f82dd830d0.tar.bz2 |
gh-105020: Share tp_bases and tp_mro Between Interpreters For All Static Builtin Types (gh-105115)
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.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0a2e1b1..6540d4e 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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; |