summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-05-31 00:13:35 (GMT)
committerGitHub <noreply@github.com>2023-05-31 00:13:35 (GMT)
commit7be667dfafa2465df6342d72dca9c1f82dd830d0 (patch)
tree6fb8852fb71d0348327d0d79bf152acb4fddd03d /Objects
parent26e7bbf66e93ee7c94b6e007ec7b2d769c2ced92 (diff)
downloadcpython-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.c76
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;