Skip to content

Commit 3c4000c

Browse files
Move Py_TPFLAGS_READYING to each interpreter for static builtin types.
1 parent cd1dd10 commit 3c4000c

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed

Include/internal/pycore_typeobject.h

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct type_cache {
4444

4545
typedef struct {
4646
PyTypeObject *type;
47+
int readying;
48+
int ready;
4749
// XXX tp_dict, tp_bases, and tp_mro can probably be statically
4850
// allocated, instead of dynamically and stored on the interpreter.
4951
PyObject *tp_dict;

Objects/typeobject.c

+50-7
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,49 @@ static_builtin_state_clear(PyInterpreterState *interp, PyTypeObject *self)
167167
/* end static builtin helpers */
168168

169169

170+
static inline void
171+
start_readying(PyTypeObject *type)
172+
{
173+
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
174+
PyInterpreterState *interp = _PyInterpreterState_GET();
175+
static_builtin_state *state = static_builtin_state_get(interp, type);
176+
assert(state != NULL);
177+
assert(!state->readying);
178+
state->readying = 1;
179+
return;
180+
}
181+
assert((type->tp_flags & Py_TPFLAGS_READYING) == 0);
182+
type->tp_flags |= Py_TPFLAGS_READYING;
183+
}
184+
185+
static inline void
186+
stop_readying(PyTypeObject *type)
187+
{
188+
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
189+
PyInterpreterState *interp = _PyInterpreterState_GET();
190+
static_builtin_state *state = static_builtin_state_get(interp, type);
191+
assert(state != NULL);
192+
assert(state->readying);
193+
state->readying = 0;
194+
return;
195+
}
196+
assert(type->tp_flags & Py_TPFLAGS_READYING);
197+
type->tp_flags &= ~Py_TPFLAGS_READYING;
198+
}
199+
200+
static inline int
201+
is_readying(PyTypeObject *type)
202+
{
203+
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
204+
PyInterpreterState *interp = _PyInterpreterState_GET();
205+
static_builtin_state *state = static_builtin_state_get(interp, type);
206+
assert(state != NULL);
207+
return state->readying;
208+
}
209+
return (type->tp_flags & Py_TPFLAGS_READYING);
210+
}
211+
212+
170213
/* accessors for objects stored on PyTypeObject */
171214

172215
static inline PyObject *
@@ -471,7 +514,7 @@ _PyType_CheckConsistency(PyTypeObject *type)
471514
CHECK(Py_REFCNT(type) >= 1);
472515
CHECK(PyType_Check(type));
473516

474-
CHECK(!(type->tp_flags & Py_TPFLAGS_READYING));
517+
CHECK(!is_readying(type));
475518
CHECK(lookup_tp_dict(type) != NULL);
476519

477520
if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
@@ -4419,7 +4462,7 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error)
44194462
/* Look in tp_dict of types in MRO */
44204463
PyObject *mro = lookup_tp_mro(type);
44214464
if (mro == NULL) {
4422-
if ((type->tp_flags & Py_TPFLAGS_READYING) == 0) {
4465+
if (is_readying(type)) {
44234466
if (PyType_Ready(type) < 0) {
44244467
*error = -1;
44254468
return NULL;
@@ -7181,9 +7224,8 @@ type_ready_post_checks(PyTypeObject *type)
71817224
static int
71827225
type_ready(PyTypeObject *type, int rerunbuiltin)
71837226
{
7184-
_PyObject_ASSERT((PyObject *)type,
7185-
(type->tp_flags & Py_TPFLAGS_READYING) == 0);
7186-
type->tp_flags |= Py_TPFLAGS_READYING;
7227+
_PyObject_ASSERT((PyObject *)type, !is_readying(type));
7228+
start_readying(type);
71877229

71887230
if (type_ready_pre_checks(type) < 0) {
71897231
goto error;
@@ -7238,13 +7280,14 @@ type_ready(PyTypeObject *type, int rerunbuiltin)
72387280
}
72397281

72407282
/* All done -- set the ready flag */
7241-
type->tp_flags = (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;
7283+
type->tp_flags = type->tp_flags | Py_TPFLAGS_READY;
7284+
stop_readying(type);
72427285

72437286
assert(_PyType_CheckConsistency(type));
72447287
return 0;
72457288

72467289
error:
7247-
type->tp_flags &= ~Py_TPFLAGS_READYING;
7290+
stop_readying(type);
72487291
return -1;
72497292
}
72507293

0 commit comments

Comments
 (0)