Until now, we haven't been initializing nor finalizing the per-interpreter state properly.
{
if (PyType_Check(op) &&
((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
+ PyInterpreterState *interp = _PyInterpreterState_GET();
static_builtin_state *state = _PyStaticType_GetState(
- (PyTypeObject *)op);
+ interp, (PyTypeObject *)op);
return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
}
// Essentially _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET():
extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
extern int _PySys_UpdateConfig(PyThreadState *tstate);
-extern void _PySys_Fini(PyInterpreterState *interp);
+extern void _PySys_FiniTypes(PyInterpreterState *interp);
extern int _PyBuiltins_AddExceptions(PyObject * bltinmod);
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
unsigned long tp_flags);
extern int _PyStructSequence_InitBuiltinWithFlags(
+ PyInterpreterState *interp,
PyTypeObject *type,
PyStructSequence_Desc *desc,
unsigned long tp_flags);
static inline int
-_PyStructSequence_InitBuiltin(PyTypeObject *type,
+_PyStructSequence_InitBuiltin(PyInterpreterState *interp,
+ PyTypeObject *type,
PyStructSequence_Desc *desc)
{
- return _PyStructSequence_InitBuiltinWithFlags(type, desc, 0);
+ return _PyStructSequence_InitBuiltinWithFlags(interp, type, desc, 0);
}
-extern void _PyStructSequence_FiniBuiltin(PyTypeObject *type);
+extern void _PyStructSequence_FiniBuiltin(
+ PyInterpreterState *interp,
+ PyTypeObject *type);
#ifdef __cplusplus
}
}
-extern int _PyStaticType_InitBuiltin(PyTypeObject *type);
-extern static_builtin_state * _PyStaticType_GetState(PyTypeObject *);
-extern void _PyStaticType_ClearWeakRefs(PyTypeObject *type);
-extern void _PyStaticType_Dealloc(PyTypeObject *type);
+extern int _PyStaticType_InitBuiltin(PyInterpreterState *, PyTypeObject *type);
+extern static_builtin_state * _PyStaticType_GetState(PyInterpreterState *, PyTypeObject *);
+extern void _PyStaticType_ClearWeakRefs(PyInterpreterState *, PyTypeObject *type);
+extern void _PyStaticType_Dealloc(PyInterpreterState *, PyTypeObject *);
PyObject *
_Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int *suppress_missing_attribute);
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
PyTypeObject *type = static_types[i];
- if (_PyStaticType_InitBuiltin(type) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, type) < 0) {
return _PyStatus_ERR("Can't initialize builtin type");
}
}
void
_PyIO_FiniTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
// Deallocate types in the reverse order to deallocate subclasses before
// their base classes.
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types) - 1; i >= 0; i--) {
PyTypeObject *type = static_types[i];
- _PyStaticType_Dealloc(type);
+ _PyStaticType_Dealloc(interp, type);
}
}
{
for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
PyTypeObject *exc = static_exceptions[i].exc;
- if (_PyStaticType_InitBuiltin(exc) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, exc) < 0) {
return -1;
}
}
static void
_PyExc_FiniTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) {
PyTypeObject *exc = static_exceptions[i].exc;
- _PyStaticType_Dealloc(exc);
+ _PyStaticType_Dealloc(interp, exc);
}
}
_PyFloat_InitTypes(PyInterpreterState *interp)
{
/* Init float info */
- if (_PyStructSequence_InitBuiltin(&FloatInfoType,
- &floatinfo_desc) < 0) {
+ if (_PyStructSequence_InitBuiltin(interp, &FloatInfoType,
+ &floatinfo_desc) < 0)
+ {
return _PyStatus_ERR("can't init float info type");
}
void
_PyFloat_FiniType(PyInterpreterState *interp)
{
- if (_Py_IsMainInterpreter(interp)) {
- _PyStructSequence_FiniBuiltin(&FloatInfoType);
- }
+ _PyStructSequence_FiniBuiltin(interp, &FloatInfoType);
}
/* Print summary info about the state of the optimized allocator */
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_long.h" // _Py_SmallInts
#include "pycore_object.h" // _PyObject_Init()
-#include "pycore_pystate.h" // _Py_IsMainInterpreter()
#include "pycore_runtime.h" // _PY_NSMALLPOSINTS
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
_PyLong_InitTypes(PyInterpreterState *interp)
{
/* initialize int_info */
- if (_PyStructSequence_InitBuiltin(&Int_InfoType, &int_info_desc) < 0) {
+ if (_PyStructSequence_InitBuiltin(interp, &Int_InfoType,
+ &int_info_desc) < 0)
+ {
return _PyStatus_ERR("can't init int info type");
}
void
_PyLong_FiniTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
- _PyStructSequence_FiniBuiltin(&Int_InfoType);
+ _PyStructSequence_FiniBuiltin(interp, &Int_InfoType);
}
// All other static types (unless initialized elsewhere)
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
PyTypeObject *type = static_types[i];
- if (_PyStaticType_InitBuiltin(type) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, type) < 0) {
return _PyStatus_ERR("Can't initialize builtin type");
}
if (type == &PyType_Type) {
void
_PyTypes_FiniTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
// Deallocate types in the reverse order to deallocate subclasses before
// their base classes.
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) {
PyTypeObject *type = static_types[i];
- _PyStaticType_Dealloc(type);
+ _PyStaticType_Dealloc(interp, type);
}
}
}
int
-_PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type,
+_PyStructSequence_InitBuiltinWithFlags(PyInterpreterState *interp,
+ PyTypeObject *type,
PyStructSequence_Desc *desc,
unsigned long tp_flags)
{
}
#endif
- if (_PyStaticType_InitBuiltin(type) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, type) < 0) {
PyErr_Format(PyExc_RuntimeError,
"Can't initialize builtin type %s",
desc->name);
initialized via _PyStructSequence_InitBuiltinWithFlags(). */
void
-_PyStructSequence_FiniBuiltin(PyTypeObject *type)
+_PyStructSequence_FiniBuiltin(PyInterpreterState *interp, PyTypeObject *type)
{
// Ensure that the type is initialized
assert(type->tp_name != NULL);
return;
}
- _PyStaticType_Dealloc(type);
+ _PyStaticType_Dealloc(interp, type);
- // Undo _PyStructSequence_InitBuiltinWithFlags().
- type->tp_name = NULL;
- PyMem_Free(type->tp_members);
- type->tp_members = NULL;
- type->tp_base = NULL;
+ if (_Py_IsMainInterpreter(interp)) {
+ // Undo _PyStructSequence_InitBuiltinWithFlags().
+ type->tp_name = NULL;
+ PyMem_Free(type->tp_members);
+ type->tp_members = NULL;
+ type->tp_base = NULL;
+ }
}
/* helpers for for static builtin types */
-#ifndef NDEBUG
static inline int
static_builtin_index_is_set(PyTypeObject *self)
{
return self->tp_subclasses != NULL;
}
-#endif
static inline size_t
static_builtin_index_get(PyTypeObject *self)
/* For static types we store some state in an array on each interpreter. */
static_builtin_state *
-_PyStaticType_GetState(PyTypeObject *self)
+_PyStaticType_GetState(PyInterpreterState *interp, PyTypeObject *self)
{
assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
- PyInterpreterState *interp = _PyInterpreterState_GET();
return static_builtin_state_get(interp, self);
}
+/* Set the type's per-interpreter state. */
static void
-static_builtin_state_init(PyTypeObject *self)
+static_builtin_state_init(PyInterpreterState *interp, PyTypeObject *self)
{
- /* Set the type's per-interpreter state. */
- PyInterpreterState *interp = _PyInterpreterState_GET();
+ if (!static_builtin_index_is_set(self)) {
+ static_builtin_index_set(self, interp->types.num_builtins_initialized);
+ }
+ static_builtin_state *state = static_builtin_state_get(interp, self);
/* It should only be called once for each builtin type. */
- assert(!static_builtin_index_is_set(self));
-
- static_builtin_index_set(self, interp->types.num_builtins_initialized);
- interp->types.num_builtins_initialized++;
-
- static_builtin_state *state = static_builtin_state_get(interp, self);
+ assert(state->type == NULL);
state->type = self;
+
/* state->tp_subclasses is left NULL until init_subclasses() sets it. */
/* state->tp_weaklist is left NULL until insert_head() or insert_after()
(in weakrefobject.c) sets it. */
+
+ interp->types.num_builtins_initialized++;
}
+/* Reset the type's per-interpreter state.
+ This basically undoes what static_builtin_state_init() did. */
static void
-static_builtin_state_clear(PyTypeObject *self)
+static_builtin_state_clear(PyInterpreterState *interp, PyTypeObject *self)
{
- /* Reset the type's per-interpreter state.
- This basically undoes what static_builtin_state_init() did. */
- PyInterpreterState *interp = _PyInterpreterState_GET();
-
static_builtin_state *state = static_builtin_state_get(interp, self);
+
+ assert(state->type != NULL);
state->type = NULL;
assert(state->tp_weaklist == NULL); // It was already cleared out.
- static_builtin_index_clear(self);
+
+ if (_Py_IsMainInterpreter(interp)) {
+ static_builtin_index_clear(self);
+ }
assert(interp->types.num_builtins_initialized > 0);
interp->types.num_builtins_initialized--;
clear_subclasses(type);
}
+static void
+clear_static_type_objects(PyInterpreterState *interp, PyTypeObject *type)
+{
+ if (_Py_IsMainInterpreter(interp)) {
+ Py_CLEAR(type->tp_dict);
+ Py_CLEAR(type->tp_bases);
+ Py_CLEAR(type->tp_mro);
+ Py_CLEAR(type->tp_cache);
+ }
+ clear_static_tp_subclasses(type);
+}
+
void
-_PyStaticType_Dealloc(PyTypeObject *type)
+_PyStaticType_Dealloc(PyInterpreterState *interp, PyTypeObject *type)
{
- assert(!(type->tp_flags & Py_TPFLAGS_HEAPTYPE));
+ assert(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
+ assert(_Py_IsImmortal((PyObject *)type));
type_dealloc_common(type);
- Py_CLEAR(type->tp_dict);
- Py_CLEAR(type->tp_bases);
- Py_CLEAR(type->tp_mro);
- Py_CLEAR(type->tp_cache);
- clear_static_tp_subclasses(type);
+ clear_static_type_objects(interp, type);
- // PyObject_ClearWeakRefs() raises an exception if Py_REFCNT() != 0
- if (Py_REFCNT(type) == 0) {
- PyObject_ClearWeakRefs((PyObject *)type);
+ if (_Py_IsMainInterpreter(interp)) {
+ type->tp_flags &= ~Py_TPFLAGS_READY;
+ type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+ type->tp_version_tag = 0;
}
- type->tp_flags &= ~Py_TPFLAGS_READY;
- type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
- type->tp_version_tag = 0;
-
- if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
- _PyStaticType_ClearWeakRefs(type);
- static_builtin_state_clear(type);
- /* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
- }
+ _PyStaticType_ClearWeakRefs(interp, type);
+ static_builtin_state_clear(interp, type);
+ /* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
}
lookup_subclasses(PyTypeObject *self)
{
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
- static_builtin_state *state = _PyStaticType_GetState(self);
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ static_builtin_state *state = _PyStaticType_GetState(interp, self);
assert(state != NULL);
return state->tp_subclasses;
}
int
_PyType_HasSubclasses(PyTypeObject *self)
{
+ PyInterpreterState *interp = _PyInterpreterState_GET();
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN &&
- _PyStaticType_GetState(self) == NULL) {
+ _PyStaticType_GetState(interp, self) == NULL) {
return 0;
}
if (lookup_subclasses(self) == NULL) {
else if (type->tp_dictoffset < (Py_ssize_t)sizeof(PyObject)) {
if (type->tp_dictoffset + type->tp_basicsize <= 0) {
PyErr_Format(PyExc_SystemError,
- "type %s has a tp_dictoffset that is too small");
+ "type %s has a tp_dictoffset that is too small",
+ type->tp_name);
}
}
return 0;
}
int
-_PyStaticType_InitBuiltin(PyTypeObject *self)
+_PyStaticType_InitBuiltin(PyInterpreterState *interp, PyTypeObject *self)
{
assert(_Py_IsImmortal((PyObject *)self));
assert(!(self->tp_flags & Py_TPFLAGS_HEAPTYPE));
+ assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_DICT));
+ assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF));
+#ifndef NDEBUG
+ int ismain = _Py_IsMainInterpreter(interp);
+#endif
if (self->tp_flags & Py_TPFLAGS_READY) {
+ assert(!ismain);
assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
+ assert(self->tp_flags & Py_TPFLAGS_VALID_VERSION_TAG);
+
+ static_builtin_state_init(interp, self);
+
+ /* Per-interpreter tp_subclasses is done lazily.
+ Otherwise we would initialize it here. */
+
assert(_PyType_CheckConsistency(self));
return 0;
}
+ assert(ismain);
+
self->tp_flags |= _Py_TPFLAGS_STATIC_BUILTIN;
self->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
self->tp_version_tag = NEXT_GLOBAL_VERSION_TAG++;
self->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
- static_builtin_state_init(self);
+ static_builtin_state_init(interp, self);
int res = type_ready(self);
if (res < 0) {
- static_builtin_state_clear(self);
+ static_builtin_state_clear(interp, self);
}
return res;
}
return NULL;
}
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
- static_builtin_state *state = _PyStaticType_GetState(self);
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ static_builtin_state *state = _PyStaticType_GetState(interp, self);
state->tp_subclasses = subclasses;
return subclasses;
}
callers also test if tp_subclasses is NULL to check if a static type
has no subclass. */
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
- static_builtin_state *state = _PyStaticType_GetState(self);
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ static_builtin_state *state = _PyStaticType_GetState(interp, self);
Py_CLEAR(state->tp_subclasses);
return;
}
PyStatus
_PyUnicode_InitTypes(PyInterpreterState *interp)
{
- if (_PyStaticType_InitBuiltin(&EncodingMapType) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, &EncodingMapType) < 0) {
goto error;
}
- if (_PyStaticType_InitBuiltin(&PyFieldNameIter_Type) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, &PyFieldNameIter_Type) < 0) {
goto error;
}
- if (_PyStaticType_InitBuiltin(&PyFormatterIter_Type) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, &PyFormatterIter_Type) < 0) {
goto error;
}
return _PyStatus_OK();
void
_PyUnicode_FiniTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
- _PyStaticType_Dealloc(&EncodingMapType);
- _PyStaticType_Dealloc(&PyFieldNameIter_Type);
- _PyStaticType_Dealloc(&PyFormatterIter_Type);
+ _PyStaticType_Dealloc(interp, &EncodingMapType);
+ _PyStaticType_Dealloc(interp, &PyFieldNameIter_Type);
+ _PyStaticType_Dealloc(interp, &PyFormatterIter_Type);
}
* or anything else.
*/
void
-_PyStaticType_ClearWeakRefs(PyTypeObject *type)
+_PyStaticType_ClearWeakRefs(PyInterpreterState *interp, PyTypeObject *type)
{
- static_builtin_state *state = _PyStaticType_GetState(type);
+ static_builtin_state *state = _PyStaticType_GetState(interp, type);
PyObject **list = _PyStaticType_GET_WEAKREFS_LISTPTR(state);
while (*list != NULL) {
/* Note that clear_weakref() pops the first ref off the type's
PyStatus
_PyErr_InitTypes(PyInterpreterState *interp)
{
- if (_PyStructSequence_InitBuiltin(&UnraisableHookArgsType,
- &UnraisableHookArgs_desc) < 0) {
+ if (_PyStructSequence_InitBuiltin(interp, &UnraisableHookArgsType,
+ &UnraisableHookArgs_desc) < 0)
+ {
return _PyStatus_ERR("failed to initialize UnraisableHookArgs type");
}
return _PyStatus_OK();
void
_PyErr_FiniTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
- _PyStructSequence_FiniBuiltin(&UnraisableHookArgsType);
+ _PyStructSequence_FiniBuiltin(interp, &UnraisableHookArgsType);
}
static void
finalize_interp_types(PyInterpreterState *interp)
{
+ _PyIO_FiniTypes(interp);
+
_PyUnicode_FiniTypes(interp);
- _PySys_Fini(interp);
+ _PySys_FiniTypes(interp);
_PyExc_Fini(interp);
_PyAsyncGen_Fini(interp);
_PyContext_Fini(interp);
/* Clear interpreter state and all thread states */
_PyInterpreterState_Clear(tstate);
- _PyIO_FiniTypes(tstate->interp);
-
/* Clear all loghooks */
/* Both _PySys_Audit function and users still need PyObject, such as tuple.
Call _PySys_ClearAuditHooks when PyObject available. */
{
PyObject *version_info;
int res;
+ PyInterpreterState *interp = tstate->interp;
/* stdin/stdout/stderr are set in pylifecycle.c */
SET_SYS("float_info", PyFloat_GetInfo());
SET_SYS("int_info", PyLong_GetInfo());
/* initialize hash_info */
- if (_PyStructSequence_InitBuiltin(&Hash_InfoType, &hash_info_desc) < 0) {
+ if (_PyStructSequence_InitBuiltin(interp, &Hash_InfoType,
+ &hash_info_desc) < 0)
+ {
goto type_init_failed;
}
SET_SYS("hash_info", get_hash_info(tstate));
#define ENSURE_INFO_TYPE(TYPE, DESC) \
do { \
if (_PyStructSequence_InitBuiltinWithFlags( \
- &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \
+ interp, &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \
goto type_init_failed; \
} \
} while (0)
SET_SYS("thread_info", PyThread_GetInfo());
/* initialize asyncgen_hooks */
- if (_PyStructSequence_InitBuiltin(
- &AsyncGenHooksType, &asyncgen_hooks_desc) < 0) {
+ if (_PyStructSequence_InitBuiltin(interp, &AsyncGenHooksType,
+ &asyncgen_hooks_desc) < 0)
+ {
goto type_init_failed;
}
void
-_PySys_Fini(PyInterpreterState *interp)
+_PySys_FiniTypes(PyInterpreterState *interp)
{
- if (_Py_IsMainInterpreter(interp)) {
- _PyStructSequence_FiniBuiltin(&VersionInfoType);
- _PyStructSequence_FiniBuiltin(&FlagsType);
+ _PyStructSequence_FiniBuiltin(interp, &VersionInfoType);
+ _PyStructSequence_FiniBuiltin(interp, &FlagsType);
#if defined(MS_WINDOWS)
- _PyStructSequence_FiniBuiltin(&WindowsVersionType);
+ _PyStructSequence_FiniBuiltin(interp, &WindowsVersionType);
#endif
- _PyStructSequence_FiniBuiltin(&Hash_InfoType);
- _PyStructSequence_FiniBuiltin(&AsyncGenHooksType);
+ _PyStructSequence_FiniBuiltin(interp, &Hash_InfoType);
+ _PyStructSequence_FiniBuiltin(interp, &AsyncGenHooksType);
#ifdef __EMSCRIPTEN__
+ if (_Py_IsMainInterpreter(interp)) {
Py_CLEAR(EmscriptenInfoType);
-#endif
}
+#endif
}
int len;
#endif
- if (_PyStructSequence_InitBuiltin(&ThreadInfoType, &threadinfo_desc) < 0) {
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ if (_PyStructSequence_InitBuiltin(interp, &ThreadInfoType, &threadinfo_desc) < 0) {
return NULL;
}
void
_PyThread_FiniType(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
- _PyStructSequence_FiniBuiltin(&ThreadInfoType);
+ _PyStructSequence_FiniBuiltin(interp, &ThreadInfoType);
}