Skip to content

Commit f73abf8

Browse files
gh-94673: Hide Objects in PyTypeObject Behind Accessors (gh-104074)
This makes it much cleaner to move more PyTypeObject fields to PyInterpreterState.
1 parent fdd8786 commit f73abf8

File tree

6 files changed

+352
-244
lines changed

6 files changed

+352
-244
lines changed

Include/internal/pycore_object.h

-6
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,6 @@ extern int _Py_CheckSlotResult(
331331
const char *slot_name,
332332
int success);
333333

334-
// PyType_Ready() must be called if _PyType_IsReady() is false.
335-
// See also the Py_TPFLAGS_READY flag.
336-
#define _PyType_IsReady(type) ((type)->tp_dict != NULL)
337-
338334
// Test if a type supports weak references
339335
static inline int _PyType_SUPPORTS_WEAKREFS(PyTypeObject *type) {
340336
return (type->tp_weaklistoffset != 0);
@@ -392,8 +388,6 @@ _PyDictOrValues_SetValues(PyDictOrValues *ptr, PyDictValues *values)
392388
extern PyObject ** _PyObject_ComputedDictPointer(PyObject *);
393389
extern void _PyObject_FreeInstanceAttributes(PyObject *obj);
394390
extern int _PyObject_IsInstanceDictEmpty(PyObject *);
395-
extern int _PyType_HasSubclasses(PyTypeObject *);
396-
extern PyObject* _PyType_GetSubclasses(PyTypeObject *);
397391

398392
// Access macro to the members which are floating "behind" the object
399393
static inline PyMemberDef* _PyHeapType_GET_MEMBERS(PyHeapTypeObject *etype) {

Include/internal/pycore_typeobject.h

+14
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ extern static_builtin_state * _PyStaticType_GetState(PyInterpreterState *, PyTyp
109109
extern void _PyStaticType_ClearWeakRefs(PyInterpreterState *, PyTypeObject *type);
110110
extern void _PyStaticType_Dealloc(PyInterpreterState *, PyTypeObject *);
111111

112+
PyAPI_FUNC(PyObject *) _PyType_GetDict(PyTypeObject *);
113+
extern PyObject * _PyType_GetBases(PyTypeObject *type);
114+
extern PyObject * _PyType_GetMRO(PyTypeObject *type);
115+
extern PyObject* _PyType_GetSubclasses(PyTypeObject *);
116+
extern int _PyType_HasSubclasses(PyTypeObject *);
117+
118+
// PyType_Ready() must be called if _PyType_IsReady() is false.
119+
// See also the Py_TPFLAGS_READY flag.
120+
static inline int
121+
_PyType_IsReady(PyTypeObject *type)
122+
{
123+
return _PyType_GetDict(type) != NULL;
124+
}
125+
112126
PyObject *
113127
_Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int *suppress_missing_attribute);
114128
PyObject *

Modules/_abc.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,8 @@ _abc__abc_init(PyObject *module, PyObject *self)
452452
* their special status w.r.t. pattern matching. */
453453
if (PyType_Check(self)) {
454454
PyTypeObject *cls = (PyTypeObject *)self;
455-
PyObject *flags = PyDict_GetItemWithError(cls->tp_dict,
455+
PyObject *dict = _PyType_GetDict(cls);
456+
PyObject *flags = PyDict_GetItemWithError(dict,
456457
&_Py_ID(__abc_tpflags__));
457458
if (flags == NULL) {
458459
if (PyErr_Occurred()) {
@@ -471,7 +472,7 @@ _abc__abc_init(PyObject *module, PyObject *self)
471472
}
472473
((PyTypeObject *)self)->tp_flags |= (val & COLLECTION_FLAGS);
473474
}
474-
if (PyDict_DelItem(cls->tp_dict, &_Py_ID(__abc_tpflags__)) < 0) {
475+
if (PyDict_DelItem(dict, &_Py_ID(__abc_tpflags__)) < 0) {
475476
return NULL;
476477
}
477478
}
@@ -742,7 +743,7 @@ _abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
742743
Py_DECREF(ok);
743744

744745
/* 4. Check if it's a direct subclass. */
745-
PyObject *mro = ((PyTypeObject *)subclass)->tp_mro;
746+
PyObject *mro = _PyType_GetMRO((PyTypeObject *)subclass);
746747
assert(PyTuple_Check(mro));
747748
for (pos = 0; pos < PyTuple_GET_SIZE(mro); pos++) {
748749
PyObject *mro_item = PyTuple_GET_ITEM(mro, pos);

Objects/structseq.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const char * const PyStructSequence_UnnamedField = "unnamed field";
2626
static Py_ssize_t
2727
get_type_attr_as_size(PyTypeObject *tp, PyObject *name)
2828
{
29-
PyObject *v = PyDict_GetItemWithError(tp->tp_dict, name);
29+
PyObject *v = PyDict_GetItemWithError(_PyType_GetDict(tp), name);
3030
if (v == NULL && !PyErr_Occurred()) {
3131
PyErr_Format(PyExc_TypeError,
3232
"Missed attribute '%U' of type %s",
@@ -493,7 +493,7 @@ initialize_static_type(PyTypeObject *type, PyStructSequence_Desc *desc,
493493
Py_INCREF(type);
494494

495495
if (initialize_structseq_dict(
496-
desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
496+
desc, _PyType_GetDict(type), n_members, n_unnamed_members) < 0) {
497497
Py_DECREF(type);
498498
return -1;
499499
}
@@ -549,7 +549,7 @@ _PyStructSequence_InitBuiltinWithFlags(PyInterpreterState *interp,
549549
}
550550

551551
if (initialize_structseq_dict(
552-
desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
552+
desc, _PyType_GetDict(type), n_members, n_unnamed_members) < 0) {
553553
goto error;
554554
}
555555

@@ -675,7 +675,7 @@ _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags)
675675
}
676676

677677
if (initialize_structseq_dict(
678-
desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
678+
desc, _PyType_GetDict(type), n_members, n_unnamed_members) < 0) {
679679
Py_DECREF(type);
680680
return NULL;
681681
}

0 commit comments

Comments
 (0)