mirror of https://github.com/python/cpython
gh-117398: Use Per-Interpreter State for the _datetime Static Types (gh-119929)
We make use of the same mechanism that we use for the static builtin types. This required a few tweaks. The relevant code could use some cleanup but I opted to avoid the significant churn in this change. I'll tackle that separately. This change is the final piece needed to make _datetime support multiple interpreters. I've updated the module slot accordingly.
This commit is contained in:
parent
dba7a167db
commit
105f22ea46
|
@ -589,7 +589,7 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
|
||||||
if (PyType_Check(op) &&
|
if (PyType_Check(op) &&
|
||||||
((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = _PyStaticType_GetState(
|
managed_static_type_state *state = _PyStaticType_GetState(
|
||||||
interp, (PyTypeObject *)op);
|
interp, (PyTypeObject *)op);
|
||||||
return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
|
return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,12 @@ struct type_cache {
|
||||||
|
|
||||||
/* For now we hard-code this to a value for which we are confident
|
/* For now we hard-code this to a value for which we are confident
|
||||||
all the static builtin types will fit (for all builds). */
|
all the static builtin types will fit (for all builds). */
|
||||||
#define _Py_MAX_STATIC_BUILTIN_TYPES 200
|
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 200
|
||||||
|
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyTypeObject *type;
|
PyTypeObject *type;
|
||||||
|
int isbuiltin;
|
||||||
int readying;
|
int readying;
|
||||||
int ready;
|
int ready;
|
||||||
// XXX tp_dict can probably be statically allocated,
|
// XXX tp_dict can probably be statically allocated,
|
||||||
|
@ -59,7 +61,7 @@ typedef struct {
|
||||||
are also some diagnostic uses for the list of weakrefs,
|
are also some diagnostic uses for the list of weakrefs,
|
||||||
so we still keep it. */
|
so we still keep it. */
|
||||||
PyObject *tp_weaklist;
|
PyObject *tp_weaklist;
|
||||||
} static_builtin_state;
|
} managed_static_type_state;
|
||||||
|
|
||||||
struct types_state {
|
struct types_state {
|
||||||
/* Used to set PyTypeObject.tp_version_tag.
|
/* Used to set PyTypeObject.tp_version_tag.
|
||||||
|
@ -105,8 +107,16 @@ struct types_state {
|
||||||
num_builtins_initialized is incremented once for each static
|
num_builtins_initialized is incremented once for each static
|
||||||
builtin type. Once initialization is over for a subinterpreter,
|
builtin type. Once initialization is over for a subinterpreter,
|
||||||
the value will be the same as for all other interpreters. */
|
the value will be the same as for all other interpreters. */
|
||||||
size_t num_builtins_initialized;
|
struct {
|
||||||
static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
|
size_t num_initialized;
|
||||||
|
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES];
|
||||||
|
} builtins;
|
||||||
|
/* We apply a similar strategy for managed extension modules. */
|
||||||
|
struct {
|
||||||
|
size_t num_initialized;
|
||||||
|
size_t next_index;
|
||||||
|
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_EXT_TYPES];
|
||||||
|
} for_extensions;
|
||||||
PyMutex mutex;
|
PyMutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,12 +140,35 @@ typedef struct wrapperbase pytype_slotdef;
|
||||||
|
|
||||||
|
|
||||||
static inline PyObject **
|
static inline PyObject **
|
||||||
_PyStaticType_GET_WEAKREFS_LISTPTR(static_builtin_state *state)
|
_PyStaticType_GET_WEAKREFS_LISTPTR(managed_static_type_state *state)
|
||||||
{
|
{
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
return &state->tp_weaklist;
|
return &state->tp_weaklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int _PyStaticType_InitBuiltin(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyTypeObject *type);
|
||||||
|
extern void _PyStaticType_FiniBuiltin(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyTypeObject *type);
|
||||||
|
extern void _PyStaticType_ClearWeakRefs(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyTypeObject *type);
|
||||||
|
extern managed_static_type_state * _PyStaticType_GetState(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyTypeObject *type);
|
||||||
|
|
||||||
|
// Export for '_datetime' shared extension.
|
||||||
|
PyAPI_FUNC(int) _PyStaticType_InitForExtension(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyTypeObject *self);
|
||||||
|
PyAPI_FUNC(void) _PyStaticType_FiniForExtension(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyTypeObject *self,
|
||||||
|
int final);
|
||||||
|
|
||||||
|
|
||||||
/* Like PyType_GetModuleState, but skips verification
|
/* Like PyType_GetModuleState, but skips verification
|
||||||
* that type is a heap type with an associated module */
|
* that type is a heap type with an associated module */
|
||||||
static inline void *
|
static inline void *
|
||||||
|
@ -151,11 +184,6 @@ _PyType_GetModuleState(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 *);
|
|
||||||
|
|
||||||
// Export for 'math' shared extension, used via _PyType_IsReady() static inline
|
// Export for 'math' shared extension, used via _PyType_IsReady() static inline
|
||||||
// function
|
// function
|
||||||
PyAPI_FUNC(PyObject *) _PyType_GetDict(PyTypeObject *);
|
PyAPI_FUNC(PyObject *) _PyType_GetDict(PyTypeObject *);
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
The ``_datetime`` module (C implementation for :mod:`datetime`) now supports
|
||||||
|
being imported in multiple interpreters.
|
|
@ -111,26 +111,37 @@ get_module_state(PyObject *module)
|
||||||
#define INTERP_KEY ((PyObject *)&_Py_ID(cached_datetime_module))
|
#define INTERP_KEY ((PyObject *)&_Py_ID(cached_datetime_module))
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_current_module(PyInterpreterState *interp)
|
get_current_module(PyInterpreterState *interp, int *p_reloading)
|
||||||
{
|
{
|
||||||
|
PyObject *mod = NULL;
|
||||||
|
int reloading = 0;
|
||||||
|
|
||||||
PyObject *dict = PyInterpreterState_GetDict(interp);
|
PyObject *dict = PyInterpreterState_GetDict(interp);
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
PyObject *ref = NULL;
|
PyObject *ref = NULL;
|
||||||
if (PyDict_GetItemRef(dict, INTERP_KEY, &ref) < 0) {
|
if (PyDict_GetItemRef(dict, INTERP_KEY, &ref) < 0) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
if (ref == NULL) {
|
if (ref != NULL) {
|
||||||
return NULL;
|
reloading = 1;
|
||||||
|
if (ref != Py_None) {
|
||||||
|
(void)PyWeakref_GetRef(ref, &mod);
|
||||||
|
if (mod == Py_None) {
|
||||||
|
Py_CLEAR(mod);
|
||||||
|
}
|
||||||
|
Py_DECREF(ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PyObject *mod = NULL;
|
if (p_reloading != NULL) {
|
||||||
(void)PyWeakref_GetRef(ref, &mod);
|
*p_reloading = reloading;
|
||||||
if (mod == Py_None) {
|
|
||||||
Py_CLEAR(mod);
|
|
||||||
}
|
}
|
||||||
Py_DECREF(ref);
|
|
||||||
return mod;
|
return mod;
|
||||||
|
|
||||||
|
error:
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyModuleDef datetimemodule;
|
static PyModuleDef datetimemodule;
|
||||||
|
@ -139,7 +150,7 @@ static datetime_state *
|
||||||
_get_current_state(PyObject **p_mod)
|
_get_current_state(PyObject **p_mod)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyInterpreterState *interp = PyInterpreterState_Get();
|
||||||
PyObject *mod = get_current_module(interp);
|
PyObject *mod = get_current_module(interp, NULL);
|
||||||
if (mod == NULL) {
|
if (mod == NULL) {
|
||||||
assert(!PyErr_Occurred());
|
assert(!PyErr_Occurred());
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
|
@ -184,8 +195,6 @@ clear_current_module(PyInterpreterState *interp, PyObject *expected)
|
||||||
{
|
{
|
||||||
PyObject *exc = PyErr_GetRaisedException();
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
|
|
||||||
PyObject *current = NULL;
|
|
||||||
|
|
||||||
PyObject *dict = PyInterpreterState_GetDict(interp);
|
PyObject *dict = PyInterpreterState_GetDict(interp);
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -197,7 +206,10 @@ clear_current_module(PyInterpreterState *interp, PyObject *expected)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (ref != NULL) {
|
if (ref != NULL) {
|
||||||
|
PyObject *current = NULL;
|
||||||
int rc = PyWeakref_GetRef(ref, ¤t);
|
int rc = PyWeakref_GetRef(ref, ¤t);
|
||||||
|
/* We only need "current" for pointer comparison. */
|
||||||
|
Py_XDECREF(current);
|
||||||
Py_DECREF(ref);
|
Py_DECREF(ref);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -208,19 +220,17 @@ clear_current_module(PyInterpreterState *interp, PyObject *expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyDict_DelItem(dict, INTERP_KEY) < 0) {
|
/* We use None to identify that the module was previously loaded. */
|
||||||
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
|
if (PyDict_SetItem(dict, INTERP_KEY, Py_None) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
goto finally;
|
goto finally;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
PyErr_Print();
|
PyErr_WriteUnraisable(NULL);
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
Py_XDECREF(current);
|
|
||||||
PyErr_SetRaisedException(exc);
|
PyErr_SetRaisedException(exc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6947,14 +6957,19 @@ static PyTypeObject PyDateTime_DateTimeType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
* Module methods and initialization.
|
* datetime C-API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyTypeObject * const capi_types[] = {
|
||||||
{NULL, NULL}
|
&PyDateTime_DateType,
|
||||||
|
&PyDateTime_DateTimeType,
|
||||||
|
&PyDateTime_TimeType,
|
||||||
|
&PyDateTime_DeltaType,
|
||||||
|
&PyDateTime_TZInfoType,
|
||||||
|
/* Indirectly, via the utc object. */
|
||||||
|
&PyDateTime_TimeZoneType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The C-API is process-global. This violates interpreter isolation
|
/* The C-API is process-global. This violates interpreter isolation
|
||||||
* due to the objects stored here. Thus each of those objects must
|
* due to the objects stored here. Thus each of those objects must
|
||||||
* be managed carefully. */
|
* be managed carefully. */
|
||||||
|
@ -7004,6 +7019,11 @@ create_timezone_from_delta(int days, int sec, int ms, int normalize)
|
||||||
return tz;
|
return tz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
* Module state lifecycle.
|
||||||
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_state(datetime_state *st, PyObject *module, PyObject *old_module)
|
init_state(datetime_state *st, PyObject *module, PyObject *old_module)
|
||||||
{
|
{
|
||||||
|
@ -7105,19 +7125,44 @@ clear_state(datetime_state *st)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
_datetime_exec(PyObject *module)
|
|
||||||
{
|
|
||||||
int rc = -1;
|
|
||||||
datetime_state *st = get_module_state(module);
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
* Global module state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If we make _PyStaticType_*ForExtension() public
|
||||||
|
// then all this should be managed by the runtime.
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
PyMutex mutex;
|
||||||
|
int64_t interp_count;
|
||||||
|
} _globals = {0};
|
||||||
|
|
||||||
|
static void
|
||||||
|
callback_for_interp_exit(void *Py_UNUSED(data))
|
||||||
|
{
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyInterpreterState *interp = PyInterpreterState_Get();
|
||||||
PyObject *old_module = get_current_module(interp);
|
|
||||||
if (PyErr_Occurred()) {
|
assert(_globals.interp_count > 0);
|
||||||
assert(old_module == NULL);
|
PyMutex_Lock(&_globals.mutex);
|
||||||
goto error;
|
_globals.interp_count -= 1;
|
||||||
|
int final = !_globals.interp_count;
|
||||||
|
PyMutex_Unlock(&_globals.mutex);
|
||||||
|
|
||||||
|
/* They must be done in reverse order so subclasses are finalized
|
||||||
|
* before base classes. */
|
||||||
|
for (size_t i = Py_ARRAY_LENGTH(capi_types); i > 0; i--) {
|
||||||
|
PyTypeObject *type = capi_types[i-1];
|
||||||
|
_PyStaticType_FiniForExtension(interp, type, final);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_static_types(PyInterpreterState *interp, int reloading)
|
||||||
|
{
|
||||||
|
if (reloading) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
/* We actually set the "current" module right before a successful return. */
|
|
||||||
|
|
||||||
// `&...` is not a constant expression according to a strict reading
|
// `&...` is not a constant expression according to a strict reading
|
||||||
// of C standards. Fill tp_base at run-time rather than statically.
|
// of C standards. Fill tp_base at run-time rather than statically.
|
||||||
|
@ -7125,18 +7170,65 @@ _datetime_exec(PyObject *module)
|
||||||
PyDateTime_TimeZoneType.tp_base = &PyDateTime_TZInfoType;
|
PyDateTime_TimeZoneType.tp_base = &PyDateTime_TZInfoType;
|
||||||
PyDateTime_DateTimeType.tp_base = &PyDateTime_DateType;
|
PyDateTime_DateTimeType.tp_base = &PyDateTime_DateType;
|
||||||
|
|
||||||
PyTypeObject *capi_types[] = {
|
/* Bases classes must be initialized before subclasses,
|
||||||
&PyDateTime_DateType,
|
* so capi_types must have the types in the appropriate order. */
|
||||||
&PyDateTime_DateTimeType,
|
for (size_t i = 0; i < Py_ARRAY_LENGTH(capi_types); i++) {
|
||||||
&PyDateTime_TimeType,
|
PyTypeObject *type = capi_types[i];
|
||||||
&PyDateTime_DeltaType,
|
if (_PyStaticType_InitForExtension(interp, type) < 0) {
|
||||||
&PyDateTime_TZInfoType,
|
return -1;
|
||||||
/* Indirectly, via the utc object. */
|
}
|
||||||
&PyDateTime_TimeZoneType,
|
}
|
||||||
};
|
|
||||||
|
PyMutex_Lock(&_globals.mutex);
|
||||||
|
assert(_globals.interp_count >= 0);
|
||||||
|
_globals.interp_count += 1;
|
||||||
|
PyMutex_Unlock(&_globals.mutex);
|
||||||
|
|
||||||
|
/* It could make sense to add a separate callback
|
||||||
|
* for each of the types. However, for now we can take the simpler
|
||||||
|
* approach of a single callback. */
|
||||||
|
if (PyUnstable_AtExit(interp, callback_for_interp_exit, NULL) < 0) {
|
||||||
|
callback_for_interp_exit(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
* Module methods and initialization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static PyMethodDef module_methods[] = {
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
_datetime_exec(PyObject *module)
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
datetime_state *st = get_module_state(module);
|
||||||
|
int reloading = 0;
|
||||||
|
|
||||||
|
PyInterpreterState *interp = PyInterpreterState_Get();
|
||||||
|
PyObject *old_module = get_current_module(interp, &reloading);
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
assert(old_module == NULL);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/* We actually set the "current" module right before a successful return. */
|
||||||
|
|
||||||
|
if (init_static_types(interp, reloading) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < Py_ARRAY_LENGTH(capi_types); i++) {
|
for (size_t i = 0; i < Py_ARRAY_LENGTH(capi_types); i++) {
|
||||||
if (PyModule_AddType(module, capi_types[i]) < 0) {
|
PyTypeObject *type = capi_types[i];
|
||||||
|
const char *name = _PyType_Name(type);
|
||||||
|
assert(name != NULL);
|
||||||
|
if (PyModule_AddObjectRef(module, name, (PyObject *)type) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7145,11 +7237,8 @@ _datetime_exec(PyObject *module)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For now we only set the objects on the static types once.
|
|
||||||
* We will relax that once each types __dict__ is per-interpreter. */
|
|
||||||
#define DATETIME_ADD_MACRO(dict, c, value_expr) \
|
#define DATETIME_ADD_MACRO(dict, c, value_expr) \
|
||||||
do { \
|
do { \
|
||||||
if (PyDict_GetItemString(dict, c) == NULL) { \
|
|
||||||
assert(!PyErr_Occurred()); \
|
assert(!PyErr_Occurred()); \
|
||||||
PyObject *value = (value_expr); \
|
PyObject *value = (value_expr); \
|
||||||
if (value == NULL) { \
|
if (value == NULL) { \
|
||||||
|
@ -7160,30 +7249,29 @@ _datetime_exec(PyObject *module)
|
||||||
goto error; \
|
goto error; \
|
||||||
} \
|
} \
|
||||||
Py_DECREF(value); \
|
Py_DECREF(value); \
|
||||||
} \
|
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* timedelta values */
|
/* timedelta values */
|
||||||
PyObject *d = PyDateTime_DeltaType.tp_dict;
|
PyObject *d = _PyType_GetDict(&PyDateTime_DeltaType);
|
||||||
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
|
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
|
||||||
DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0));
|
DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0));
|
||||||
DATETIME_ADD_MACRO(d, "max",
|
DATETIME_ADD_MACRO(d, "max",
|
||||||
new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0));
|
new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0));
|
||||||
|
|
||||||
/* date values */
|
/* date values */
|
||||||
d = PyDateTime_DateType.tp_dict;
|
d = _PyType_GetDict(&PyDateTime_DateType);
|
||||||
DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1));
|
DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1));
|
||||||
DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31));
|
DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31));
|
||||||
DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0));
|
DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0));
|
||||||
|
|
||||||
/* time values */
|
/* time values */
|
||||||
d = PyDateTime_TimeType.tp_dict;
|
d = _PyType_GetDict(&PyDateTime_TimeType);
|
||||||
DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0));
|
DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0));
|
||||||
DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0));
|
DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0));
|
||||||
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
|
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
|
||||||
|
|
||||||
/* datetime values */
|
/* datetime values */
|
||||||
d = PyDateTime_DateTimeType.tp_dict;
|
d = _PyType_GetDict(&PyDateTime_DateTimeType);
|
||||||
DATETIME_ADD_MACRO(d, "min",
|
DATETIME_ADD_MACRO(d, "min",
|
||||||
new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0));
|
new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0));
|
||||||
DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59,
|
DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59,
|
||||||
|
@ -7191,7 +7279,7 @@ _datetime_exec(PyObject *module)
|
||||||
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
|
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
|
||||||
|
|
||||||
/* timezone values */
|
/* timezone values */
|
||||||
d = PyDateTime_TimeZoneType.tp_dict;
|
d = _PyType_GetDict(&PyDateTime_TimeZoneType);
|
||||||
if (PyDict_SetItemString(d, "utc", (PyObject *)&utc_timezone) < 0) {
|
if (PyDict_SetItemString(d, "utc", (PyObject *)&utc_timezone) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -7266,7 +7354,7 @@ finally:
|
||||||
|
|
||||||
static PyModuleDef_Slot module_slots[] = {
|
static PyModuleDef_Slot module_slots[] = {
|
||||||
{Py_mod_exec, _datetime_exec},
|
{Py_mod_exec, _datetime_exec},
|
||||||
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
|
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
|
||||||
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
|
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
|
||||||
{0, NULL},
|
{0, NULL},
|
||||||
};
|
};
|
||||||
|
@ -7288,17 +7376,16 @@ module_clear(PyObject *mod)
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyInterpreterState *interp = PyInterpreterState_Get();
|
||||||
clear_current_module(interp, mod);
|
clear_current_module(interp, mod);
|
||||||
|
|
||||||
|
// We take care of the static types via an interpreter atexit hook.
|
||||||
|
// See callback_for_interp_exit() above.
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
module_free(void *mod)
|
module_free(void *mod)
|
||||||
{
|
{
|
||||||
datetime_state *st = get_module_state((PyObject *)mod);
|
(void)module_clear((PyObject *)mod);
|
||||||
clear_state(st);
|
|
||||||
|
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
|
||||||
clear_current_module(interp, (PyObject *)mod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyModuleDef datetimemodule = {
|
static PyModuleDef datetimemodule = {
|
||||||
|
|
|
@ -3725,7 +3725,7 @@ _PyExc_FiniTypes(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) {
|
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) {
|
||||||
PyTypeObject *exc = static_exceptions[i].exc;
|
PyTypeObject *exc = static_exceptions[i].exc;
|
||||||
_PyStaticType_Dealloc(interp, exc);
|
_PyStaticType_FiniBuiltin(interp, exc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2355,7 +2355,7 @@ _PyTypes_FiniTypes(PyInterpreterState *interp)
|
||||||
// their base classes.
|
// their base classes.
|
||||||
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) {
|
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) {
|
||||||
PyTypeObject *type = static_types[i];
|
PyTypeObject *type = static_types[i];
|
||||||
_PyStaticType_Dealloc(interp, type);
|
_PyStaticType_FiniBuiltin(interp, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -718,7 +718,7 @@ _PyStructSequence_FiniBuiltin(PyInterpreterState *interp, PyTypeObject *type)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyStaticType_Dealloc(interp, type);
|
_PyStaticType_FiniBuiltin(interp, type);
|
||||||
|
|
||||||
if (_Py_IsMainInterpreter(interp)) {
|
if (_Py_IsMainInterpreter(interp)) {
|
||||||
// Undo _PyStructSequence_InitBuiltinWithFlags().
|
// Undo _PyStructSequence_InitBuiltinWithFlags().
|
||||||
|
|
|
@ -131,93 +131,159 @@ type_from_ref(PyObject *ref)
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static inline int
|
static inline int
|
||||||
static_builtin_index_is_set(PyTypeObject *self)
|
managed_static_type_index_is_set(PyTypeObject *self)
|
||||||
{
|
{
|
||||||
return self->tp_subclasses != NULL;
|
return self->tp_subclasses != NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
static_builtin_index_get(PyTypeObject *self)
|
managed_static_type_index_get(PyTypeObject *self)
|
||||||
{
|
{
|
||||||
assert(static_builtin_index_is_set(self));
|
assert(managed_static_type_index_is_set(self));
|
||||||
/* We store a 1-based index so 0 can mean "not initialized". */
|
/* We store a 1-based index so 0 can mean "not initialized". */
|
||||||
return (size_t)self->tp_subclasses - 1;
|
return (size_t)self->tp_subclasses - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
static_builtin_index_set(PyTypeObject *self, size_t index)
|
managed_static_type_index_set(PyTypeObject *self, size_t index)
|
||||||
{
|
{
|
||||||
assert(index < _Py_MAX_STATIC_BUILTIN_TYPES);
|
assert(index < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES);
|
||||||
/* We store a 1-based index so 0 can mean "not initialized". */
|
/* We store a 1-based index so 0 can mean "not initialized". */
|
||||||
self->tp_subclasses = (PyObject *)(index + 1);
|
self->tp_subclasses = (PyObject *)(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
static_builtin_index_clear(PyTypeObject *self)
|
managed_static_type_index_clear(PyTypeObject *self)
|
||||||
{
|
{
|
||||||
self->tp_subclasses = NULL;
|
self->tp_subclasses = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline static_builtin_state *
|
static inline managed_static_type_state *
|
||||||
static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self)
|
static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
{
|
{
|
||||||
return &(interp->types.builtins[static_builtin_index_get(self)]);
|
return &(interp->types.builtins.initialized[
|
||||||
|
managed_static_type_index_get(self)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline managed_static_type_state *
|
||||||
|
static_ext_type_state_get(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
|
{
|
||||||
|
return &(interp->types.for_extensions.initialized[
|
||||||
|
managed_static_type_index_get(self)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static managed_static_type_state *
|
||||||
|
managed_static_type_state_get(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
|
{
|
||||||
|
// It's probably a builtin type.
|
||||||
|
size_t index = managed_static_type_index_get(self);
|
||||||
|
managed_static_type_state *state =
|
||||||
|
&(interp->types.builtins.initialized[index]);
|
||||||
|
if (state->type == self) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
if (index > _Py_MAX_MANAGED_STATIC_EXT_TYPES) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
return &(interp->types.for_extensions.initialized[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For static types we store some state in an array on each interpreter. */
|
/* For static types we store some state in an array on each interpreter. */
|
||||||
static_builtin_state *
|
managed_static_type_state *
|
||||||
_PyStaticType_GetState(PyInterpreterState *interp, PyTypeObject *self)
|
_PyStaticType_GetState(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
{
|
{
|
||||||
assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
|
assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
|
||||||
return static_builtin_state_get(interp, self);
|
return managed_static_type_state_get(interp, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the type's per-interpreter state. */
|
/* Set the type's per-interpreter state. */
|
||||||
static void
|
static void
|
||||||
static_builtin_state_init(PyInterpreterState *interp, PyTypeObject *self)
|
managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
|
||||||
|
int isbuiltin, int initial)
|
||||||
{
|
{
|
||||||
if (_Py_IsMainInterpreter(interp)) {
|
size_t index;
|
||||||
assert(!static_builtin_index_is_set(self));
|
if (initial) {
|
||||||
static_builtin_index_set(self, interp->types.num_builtins_initialized);
|
assert(!managed_static_type_index_is_set(self));
|
||||||
|
if (isbuiltin) {
|
||||||
|
index = interp->types.builtins.num_initialized;
|
||||||
|
assert(index < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyMutex_Lock(&interp->types.mutex);
|
||||||
|
index = interp->types.for_extensions.next_index;
|
||||||
|
interp->types.for_extensions.next_index++;
|
||||||
|
PyMutex_Unlock(&interp->types.mutex);
|
||||||
|
assert(index < _Py_MAX_MANAGED_STATIC_EXT_TYPES);
|
||||||
|
}
|
||||||
|
managed_static_type_index_set(self, index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(static_builtin_index_get(self) ==
|
index = managed_static_type_index_get(self);
|
||||||
interp->types.num_builtins_initialized);
|
if (isbuiltin) {
|
||||||
|
assert(index == interp->types.builtins.num_initialized);
|
||||||
|
assert(index < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(index < _Py_MAX_MANAGED_STATIC_EXT_TYPES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static_builtin_state *state = static_builtin_state_get(interp, self);
|
|
||||||
|
|
||||||
/* It should only be called once for each builtin type. */
|
managed_static_type_state *state = isbuiltin
|
||||||
|
? &(interp->types.builtins.initialized[index])
|
||||||
|
: &(interp->types.for_extensions.initialized[index]);
|
||||||
|
|
||||||
|
/* It should only be called once for each builtin type per interpreter. */
|
||||||
assert(state->type == NULL);
|
assert(state->type == NULL);
|
||||||
state->type = self;
|
state->type = self;
|
||||||
|
state->isbuiltin = isbuiltin;
|
||||||
|
|
||||||
/* state->tp_subclasses is left NULL until init_subclasses() sets it. */
|
/* state->tp_subclasses is left NULL until init_subclasses() sets it. */
|
||||||
/* state->tp_weaklist is left NULL until insert_head() or insert_after()
|
/* state->tp_weaklist is left NULL until insert_head() or insert_after()
|
||||||
(in weakrefobject.c) sets it. */
|
(in weakrefobject.c) sets it. */
|
||||||
|
|
||||||
interp->types.num_builtins_initialized++;
|
if (isbuiltin) {
|
||||||
|
interp->types.builtins.num_initialized++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interp->types.for_extensions.num_initialized++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the type's per-interpreter state.
|
/* Reset the type's per-interpreter state.
|
||||||
This basically undoes what static_builtin_state_init() did. */
|
This basically undoes what managed_static_type_state_init() did. */
|
||||||
static void
|
static void
|
||||||
static_builtin_state_clear(PyInterpreterState *interp, PyTypeObject *self)
|
managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
|
||||||
|
int isbuiltin, int final)
|
||||||
{
|
{
|
||||||
static_builtin_state *state = static_builtin_state_get(interp, self);
|
managed_static_type_state *state = isbuiltin
|
||||||
|
? static_builtin_state_get(interp, self)
|
||||||
|
: static_ext_type_state_get(interp, self);
|
||||||
|
|
||||||
assert(state->type != NULL);
|
assert(state->type != NULL);
|
||||||
state->type = NULL;
|
state->type = NULL;
|
||||||
assert(state->tp_weaklist == NULL); // It was already cleared out.
|
assert(state->tp_weaklist == NULL); // It was already cleared out.
|
||||||
|
|
||||||
if (_Py_IsMainInterpreter(interp)) {
|
if (final) {
|
||||||
static_builtin_index_clear(self);
|
managed_static_type_index_clear(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(interp->types.num_builtins_initialized > 0);
|
if (isbuiltin) {
|
||||||
interp->types.num_builtins_initialized--;
|
assert(interp->types.builtins.num_initialized > 0);
|
||||||
|
interp->types.builtins.num_initialized--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyMutex_Lock(&interp->types.mutex);
|
||||||
|
assert(interp->types.for_extensions.num_initialized > 0);
|
||||||
|
interp->types.for_extensions.num_initialized--;
|
||||||
|
if (interp->types.for_extensions.num_initialized == 0) {
|
||||||
|
interp->types.for_extensions.next_index = 0;
|
||||||
|
}
|
||||||
|
PyMutex_Unlock(&interp->types.mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also see _PyStaticType_InitBuiltin() and _PyStaticType_Dealloc().
|
// Also see _PyStaticType_InitBuiltin() and _PyStaticType_FiniBuiltin().
|
||||||
|
|
||||||
/* end static builtin helpers */
|
/* end static builtin helpers */
|
||||||
|
|
||||||
|
@ -227,7 +293,7 @@ start_readying(PyTypeObject *type)
|
||||||
{
|
{
|
||||||
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = static_builtin_state_get(interp, type);
|
managed_static_type_state *state = managed_static_type_state_get(interp, type);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
assert(!state->readying);
|
assert(!state->readying);
|
||||||
state->readying = 1;
|
state->readying = 1;
|
||||||
|
@ -242,7 +308,7 @@ stop_readying(PyTypeObject *type)
|
||||||
{
|
{
|
||||||
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = static_builtin_state_get(interp, type);
|
managed_static_type_state *state = managed_static_type_state_get(interp, type);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
assert(state->readying);
|
assert(state->readying);
|
||||||
state->readying = 0;
|
state->readying = 0;
|
||||||
|
@ -257,7 +323,7 @@ is_readying(PyTypeObject *type)
|
||||||
{
|
{
|
||||||
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = static_builtin_state_get(interp, type);
|
managed_static_type_state *state = managed_static_type_state_get(interp, type);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
return state->readying;
|
return state->readying;
|
||||||
}
|
}
|
||||||
|
@ -272,7 +338,7 @@ lookup_tp_dict(PyTypeObject *self)
|
||||||
{
|
{
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
managed_static_type_state *state = _PyStaticType_GetState(interp, self);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
return state->tp_dict;
|
return state->tp_dict;
|
||||||
}
|
}
|
||||||
|
@ -298,7 +364,7 @@ set_tp_dict(PyTypeObject *self, PyObject *dict)
|
||||||
{
|
{
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
managed_static_type_state *state = _PyStaticType_GetState(interp, self);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
state->tp_dict = dict;
|
state->tp_dict = dict;
|
||||||
return;
|
return;
|
||||||
|
@ -311,7 +377,7 @@ clear_tp_dict(PyTypeObject *self)
|
||||||
{
|
{
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
managed_static_type_state *state = _PyStaticType_GetState(interp, self);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
Py_CLEAR(state->tp_dict);
|
Py_CLEAR(state->tp_dict);
|
||||||
return;
|
return;
|
||||||
|
@ -340,13 +406,13 @@ _PyType_GetBases(PyTypeObject *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
set_tp_bases(PyTypeObject *self, PyObject *bases)
|
set_tp_bases(PyTypeObject *self, PyObject *bases, int initial)
|
||||||
{
|
{
|
||||||
assert(PyTuple_CheckExact(bases));
|
assert(PyTuple_CheckExact(bases));
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
// XXX tp_bases can probably be statically allocated for each
|
// XXX tp_bases can probably be statically allocated for each
|
||||||
// static builtin type.
|
// static builtin type.
|
||||||
assert(_Py_IsMainInterpreter(_PyInterpreterState_GET()));
|
assert(initial);
|
||||||
assert(self->tp_bases == NULL);
|
assert(self->tp_bases == NULL);
|
||||||
if (PyTuple_GET_SIZE(bases) == 0) {
|
if (PyTuple_GET_SIZE(bases) == 0) {
|
||||||
assert(self->tp_base == NULL);
|
assert(self->tp_base == NULL);
|
||||||
|
@ -363,10 +429,10 @@ set_tp_bases(PyTypeObject *self, PyObject *bases)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
clear_tp_bases(PyTypeObject *self)
|
clear_tp_bases(PyTypeObject *self, int final)
|
||||||
{
|
{
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
if (_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
|
if (final) {
|
||||||
if (self->tp_bases != NULL) {
|
if (self->tp_bases != NULL) {
|
||||||
if (PyTuple_GET_SIZE(self->tp_bases) == 0) {
|
if (PyTuple_GET_SIZE(self->tp_bases) == 0) {
|
||||||
Py_CLEAR(self->tp_bases);
|
Py_CLEAR(self->tp_bases);
|
||||||
|
@ -413,13 +479,13 @@ _PyType_GetMRO(PyTypeObject *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
set_tp_mro(PyTypeObject *self, PyObject *mro)
|
set_tp_mro(PyTypeObject *self, PyObject *mro, int initial)
|
||||||
{
|
{
|
||||||
assert(PyTuple_CheckExact(mro));
|
assert(PyTuple_CheckExact(mro));
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
// XXX tp_mro can probably be statically allocated for each
|
// XXX tp_mro can probably be statically allocated for each
|
||||||
// static builtin type.
|
// static builtin type.
|
||||||
assert(_Py_IsMainInterpreter(_PyInterpreterState_GET()));
|
assert(initial);
|
||||||
assert(self->tp_mro == NULL);
|
assert(self->tp_mro == NULL);
|
||||||
/* Other checks are done via set_tp_bases. */
|
/* Other checks are done via set_tp_bases. */
|
||||||
_Py_SetImmortal(mro);
|
_Py_SetImmortal(mro);
|
||||||
|
@ -428,10 +494,10 @@ set_tp_mro(PyTypeObject *self, PyObject *mro)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
clear_tp_mro(PyTypeObject *self)
|
clear_tp_mro(PyTypeObject *self, int final)
|
||||||
{
|
{
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
if (_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
|
if (final) {
|
||||||
if (self->tp_mro != NULL) {
|
if (self->tp_mro != NULL) {
|
||||||
if (PyTuple_GET_SIZE(self->tp_mro) == 0) {
|
if (PyTuple_GET_SIZE(self->tp_mro) == 0) {
|
||||||
Py_CLEAR(self->tp_mro);
|
Py_CLEAR(self->tp_mro);
|
||||||
|
@ -457,7 +523,7 @@ init_tp_subclasses(PyTypeObject *self)
|
||||||
}
|
}
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
managed_static_type_state *state = _PyStaticType_GetState(interp, self);
|
||||||
state->tp_subclasses = subclasses;
|
state->tp_subclasses = subclasses;
|
||||||
return subclasses;
|
return subclasses;
|
||||||
}
|
}
|
||||||
|
@ -473,7 +539,7 @@ clear_tp_subclasses(PyTypeObject *self)
|
||||||
has no subclass. */
|
has no subclass. */
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
managed_static_type_state *state = _PyStaticType_GetState(interp, self);
|
||||||
Py_CLEAR(state->tp_subclasses);
|
Py_CLEAR(state->tp_subclasses);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +551,7 @@ lookup_tp_subclasses(PyTypeObject *self)
|
||||||
{
|
{
|
||||||
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
static_builtin_state *state = _PyStaticType_GetState(interp, self);
|
managed_static_type_state *state = _PyStaticType_GetState(interp, self);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
return state->tp_subclasses;
|
return state->tp_subclasses;
|
||||||
}
|
}
|
||||||
|
@ -774,10 +840,10 @@ _PyTypes_Fini(PyInterpreterState *interp)
|
||||||
struct type_cache *cache = &interp->types.type_cache;
|
struct type_cache *cache = &interp->types.type_cache;
|
||||||
type_cache_clear(cache, NULL);
|
type_cache_clear(cache, NULL);
|
||||||
|
|
||||||
assert(interp->types.num_builtins_initialized == 0);
|
assert(interp->types.builtins.num_initialized == 0);
|
||||||
// All the static builtin types should have been finalized already.
|
// All the static builtin types should have been finalized already.
|
||||||
for (size_t i = 0; i < _Py_MAX_STATIC_BUILTIN_TYPES; i++) {
|
for (size_t i = 0; i < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; i++) {
|
||||||
assert(interp->types.builtins[i].type == NULL);
|
assert(interp->types.builtins.initialized[i].type == NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1444,7 +1510,7 @@ mro_hierarchy(PyTypeObject *type, PyObject *temp)
|
||||||
Py_XDECREF(tuple);
|
Py_XDECREF(tuple);
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
set_tp_mro(type, old_mro);
|
set_tp_mro(type, old_mro, 0);
|
||||||
Py_DECREF(new_mro);
|
Py_DECREF(new_mro);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1545,7 +1611,7 @@ type_set_bases_unlocked(PyTypeObject *type, PyObject *new_bases, void *context)
|
||||||
assert(old_bases != NULL);
|
assert(old_bases != NULL);
|
||||||
PyTypeObject *old_base = type->tp_base;
|
PyTypeObject *old_base = type->tp_base;
|
||||||
|
|
||||||
set_tp_bases(type, Py_NewRef(new_bases));
|
set_tp_bases(type, Py_NewRef(new_bases), 0);
|
||||||
type->tp_base = (PyTypeObject *)Py_NewRef(new_base);
|
type->tp_base = (PyTypeObject *)Py_NewRef(new_base);
|
||||||
|
|
||||||
PyObject *temp = PyList_New(0);
|
PyObject *temp = PyList_New(0);
|
||||||
|
@ -1593,7 +1659,7 @@ type_set_bases_unlocked(PyTypeObject *type, PyObject *new_bases, void *context)
|
||||||
"", 2, 3, &cls, &new_mro, &old_mro);
|
"", 2, 3, &cls, &new_mro, &old_mro);
|
||||||
/* Do not rollback if cls has a newer version of MRO. */
|
/* Do not rollback if cls has a newer version of MRO. */
|
||||||
if (lookup_tp_mro(cls) == new_mro) {
|
if (lookup_tp_mro(cls) == new_mro) {
|
||||||
set_tp_mro(cls, Py_XNewRef(old_mro));
|
set_tp_mro(cls, Py_XNewRef(old_mro), 0);
|
||||||
Py_DECREF(new_mro);
|
Py_DECREF(new_mro);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1603,7 +1669,7 @@ type_set_bases_unlocked(PyTypeObject *type, PyObject *new_bases, void *context)
|
||||||
if (lookup_tp_bases(type) == new_bases) {
|
if (lookup_tp_bases(type) == new_bases) {
|
||||||
assert(type->tp_base == new_base);
|
assert(type->tp_base == new_base);
|
||||||
|
|
||||||
set_tp_bases(type, old_bases);
|
set_tp_bases(type, old_bases, 0);
|
||||||
type->tp_base = old_base;
|
type->tp_base = old_base;
|
||||||
|
|
||||||
Py_DECREF(new_bases);
|
Py_DECREF(new_bases);
|
||||||
|
@ -3084,7 +3150,7 @@ mro_invoke(PyTypeObject *type)
|
||||||
- Returns -1 in case of an error.
|
- Returns -1 in case of an error.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
mro_internal_unlocked(PyTypeObject *type, PyObject **p_old_mro)
|
mro_internal_unlocked(PyTypeObject *type, int initial, PyObject **p_old_mro)
|
||||||
{
|
{
|
||||||
ASSERT_TYPE_LOCK_HELD();
|
ASSERT_TYPE_LOCK_HELD();
|
||||||
|
|
||||||
|
@ -3107,7 +3173,7 @@ mro_internal_unlocked(PyTypeObject *type, PyObject **p_old_mro)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_tp_mro(type, new_mro);
|
set_tp_mro(type, new_mro, initial);
|
||||||
|
|
||||||
type_mro_modified(type, new_mro);
|
type_mro_modified(type, new_mro);
|
||||||
/* corner case: the super class might have been hidden
|
/* corner case: the super class might have been hidden
|
||||||
|
@ -3137,7 +3203,7 @@ mro_internal(PyTypeObject *type, PyObject **p_old_mro)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
BEGIN_TYPE_LOCK()
|
BEGIN_TYPE_LOCK()
|
||||||
res = mro_internal_unlocked(type, p_old_mro);
|
res = mro_internal_unlocked(type, 0, p_old_mro);
|
||||||
END_TYPE_LOCK()
|
END_TYPE_LOCK()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -3732,7 +3798,7 @@ type_new_alloc(type_new_ctx *ctx)
|
||||||
type->tp_as_mapping = &et->as_mapping;
|
type->tp_as_mapping = &et->as_mapping;
|
||||||
type->tp_as_buffer = &et->as_buffer;
|
type->tp_as_buffer = &et->as_buffer;
|
||||||
|
|
||||||
set_tp_bases(type, Py_NewRef(ctx->bases));
|
set_tp_bases(type, Py_NewRef(ctx->bases), 1);
|
||||||
type->tp_base = (PyTypeObject *)Py_NewRef(ctx->base);
|
type->tp_base = (PyTypeObject *)Py_NewRef(ctx->base);
|
||||||
|
|
||||||
type->tp_dealloc = subtype_dealloc;
|
type->tp_dealloc = subtype_dealloc;
|
||||||
|
@ -4722,7 +4788,7 @@ _PyType_FromMetaclass_impl(
|
||||||
/* Set slots we have prepared */
|
/* Set slots we have prepared */
|
||||||
|
|
||||||
type->tp_base = (PyTypeObject *)Py_NewRef(base);
|
type->tp_base = (PyTypeObject *)Py_NewRef(base);
|
||||||
set_tp_bases(type, bases);
|
set_tp_bases(type, bases, 1);
|
||||||
bases = NULL; // We give our reference to bases to the type
|
bases = NULL; // We give our reference to bases to the type
|
||||||
|
|
||||||
type->tp_doc = tp_doc;
|
type->tp_doc = tp_doc;
|
||||||
|
@ -5627,7 +5693,7 @@ type_dealloc_common(PyTypeObject *type)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clear_static_tp_subclasses(PyTypeObject *type)
|
clear_static_tp_subclasses(PyTypeObject *type, int isbuiltin)
|
||||||
{
|
{
|
||||||
PyObject *subclasses = lookup_tp_subclasses(type);
|
PyObject *subclasses = lookup_tp_subclasses(type);
|
||||||
if (subclasses == NULL) {
|
if (subclasses == NULL) {
|
||||||
|
@ -5664,47 +5730,64 @@ clear_static_tp_subclasses(PyTypeObject *type)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// All static builtin subtypes should have been finalized already.
|
// All static builtin subtypes should have been finalized already.
|
||||||
assert(!(subclass->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
|
assert(!isbuiltin || !(subclass->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
|
||||||
Py_DECREF(subclass);
|
Py_DECREF(subclass);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
(void)isbuiltin;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
clear_tp_subclasses(type);
|
clear_tp_subclasses(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clear_static_type_objects(PyInterpreterState *interp, PyTypeObject *type)
|
clear_static_type_objects(PyInterpreterState *interp, PyTypeObject *type,
|
||||||
|
int isbuiltin, int final)
|
||||||
{
|
{
|
||||||
if (_Py_IsMainInterpreter(interp)) {
|
if (final) {
|
||||||
Py_CLEAR(type->tp_cache);
|
Py_CLEAR(type->tp_cache);
|
||||||
}
|
}
|
||||||
clear_tp_dict(type);
|
clear_tp_dict(type);
|
||||||
clear_tp_bases(type);
|
clear_tp_bases(type, final);
|
||||||
clear_tp_mro(type);
|
clear_tp_mro(type, final);
|
||||||
clear_static_tp_subclasses(type);
|
clear_static_tp_subclasses(type, isbuiltin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_PyStaticType_Dealloc(PyInterpreterState *interp, PyTypeObject *type)
|
static void
|
||||||
|
fini_static_type(PyInterpreterState *interp, PyTypeObject *type,
|
||||||
|
int isbuiltin, int final)
|
||||||
{
|
{
|
||||||
assert(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
|
assert(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
|
||||||
assert(_Py_IsImmortal((PyObject *)type));
|
assert(_Py_IsImmortal((PyObject *)type));
|
||||||
|
|
||||||
type_dealloc_common(type);
|
type_dealloc_common(type);
|
||||||
|
|
||||||
clear_static_type_objects(interp, type);
|
clear_static_type_objects(interp, type, isbuiltin, final);
|
||||||
|
|
||||||
if (_Py_IsMainInterpreter(interp)) {
|
if (final) {
|
||||||
type->tp_flags &= ~Py_TPFLAGS_READY;
|
type->tp_flags &= ~Py_TPFLAGS_READY;
|
||||||
type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
|
type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
|
||||||
type->tp_version_tag = 0;
|
type->tp_version_tag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyStaticType_ClearWeakRefs(interp, type);
|
_PyStaticType_ClearWeakRefs(interp, type);
|
||||||
static_builtin_state_clear(interp, type);
|
managed_static_type_state_clear(interp, type, isbuiltin, final);
|
||||||
/* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
|
/* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyStaticType_FiniForExtension(PyInterpreterState *interp, PyTypeObject *type, int final)
|
||||||
|
{
|
||||||
|
fini_static_type(interp, type, 0, final);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyStaticType_FiniBuiltin(PyInterpreterState *interp, PyTypeObject *type)
|
||||||
|
{
|
||||||
|
fini_static_type(interp, type, 1, _Py_IsMainInterpreter(interp));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
type_dealloc(PyObject *self)
|
type_dealloc(PyObject *self)
|
||||||
|
@ -7758,10 +7841,10 @@ type_ready_set_type(PyTypeObject *type)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
type_ready_set_bases(PyTypeObject *type)
|
type_ready_set_bases(PyTypeObject *type, int initial)
|
||||||
{
|
{
|
||||||
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
|
if (!initial) {
|
||||||
assert(lookup_tp_bases(type) != NULL);
|
assert(lookup_tp_bases(type) != NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7780,7 +7863,7 @@ type_ready_set_bases(PyTypeObject *type)
|
||||||
if (bases == NULL) {
|
if (bases == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
set_tp_bases(type, bases);
|
set_tp_bases(type, bases, 1);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7890,12 +7973,12 @@ type_ready_preheader(PyTypeObject *type)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
type_ready_mro(PyTypeObject *type)
|
type_ready_mro(PyTypeObject *type, int initial)
|
||||||
{
|
{
|
||||||
ASSERT_TYPE_LOCK_HELD();
|
ASSERT_TYPE_LOCK_HELD();
|
||||||
|
|
||||||
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
|
||||||
if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
|
if (!initial) {
|
||||||
assert(lookup_tp_mro(type) != NULL);
|
assert(lookup_tp_mro(type) != NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7903,7 +7986,7 @@ type_ready_mro(PyTypeObject *type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate method resolution order */
|
/* Calculate method resolution order */
|
||||||
if (mro_internal_unlocked(type, NULL) < 0) {
|
if (mro_internal_unlocked(type, initial, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
PyObject *mro = lookup_tp_mro(type);
|
PyObject *mro = lookup_tp_mro(type);
|
||||||
|
@ -8058,7 +8141,7 @@ type_ready_add_subclasses(PyTypeObject *type)
|
||||||
// Set tp_new and the "__new__" key in the type dictionary.
|
// Set tp_new and the "__new__" key in the type dictionary.
|
||||||
// Use the Py_TPFLAGS_DISALLOW_INSTANTIATION flag.
|
// Use the Py_TPFLAGS_DISALLOW_INSTANTIATION flag.
|
||||||
static int
|
static int
|
||||||
type_ready_set_new(PyTypeObject *type, int rerunbuiltin)
|
type_ready_set_new(PyTypeObject *type, int initial)
|
||||||
{
|
{
|
||||||
PyTypeObject *base = type->tp_base;
|
PyTypeObject *base = type->tp_base;
|
||||||
/* The condition below could use some explanation.
|
/* The condition below could use some explanation.
|
||||||
|
@ -8080,7 +8163,7 @@ type_ready_set_new(PyTypeObject *type, int rerunbuiltin)
|
||||||
|
|
||||||
if (!(type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION)) {
|
if (!(type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION)) {
|
||||||
if (type->tp_new != NULL) {
|
if (type->tp_new != NULL) {
|
||||||
if (!rerunbuiltin || base == NULL || type->tp_new != base->tp_new) {
|
if (initial || base == NULL || type->tp_new != base->tp_new) {
|
||||||
// If "__new__" key does not exists in the type dictionary,
|
// If "__new__" key does not exists in the type dictionary,
|
||||||
// set it to tp_new_wrapper().
|
// set it to tp_new_wrapper().
|
||||||
if (add_tp_new_wrapper(type) < 0) {
|
if (add_tp_new_wrapper(type) < 0) {
|
||||||
|
@ -8162,7 +8245,7 @@ type_ready_post_checks(PyTypeObject *type)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
type_ready(PyTypeObject *type, int rerunbuiltin)
|
type_ready(PyTypeObject *type, int initial)
|
||||||
{
|
{
|
||||||
ASSERT_TYPE_LOCK_HELD();
|
ASSERT_TYPE_LOCK_HELD();
|
||||||
|
|
||||||
|
@ -8192,19 +8275,19 @@ type_ready(PyTypeObject *type, int rerunbuiltin)
|
||||||
if (type_ready_set_type(type) < 0) {
|
if (type_ready_set_type(type) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (type_ready_set_bases(type) < 0) {
|
if (type_ready_set_bases(type, initial) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (type_ready_mro(type) < 0) {
|
if (type_ready_mro(type, initial) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (type_ready_set_new(type, rerunbuiltin) < 0) {
|
if (type_ready_set_new(type, initial) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (type_ready_fill_dict(type) < 0) {
|
if (type_ready_fill_dict(type) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!rerunbuiltin) {
|
if (initial) {
|
||||||
if (type_ready_inherit(type) < 0) {
|
if (type_ready_inherit(type) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -8218,7 +8301,7 @@ type_ready(PyTypeObject *type, int rerunbuiltin)
|
||||||
if (type_ready_add_subclasses(type) < 0) {
|
if (type_ready_add_subclasses(type) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!rerunbuiltin) {
|
if (initial) {
|
||||||
if (type_ready_managed_dict(type) < 0) {
|
if (type_ready_managed_dict(type) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -8258,7 +8341,7 @@ PyType_Ready(PyTypeObject *type)
|
||||||
int res;
|
int res;
|
||||||
BEGIN_TYPE_LOCK()
|
BEGIN_TYPE_LOCK()
|
||||||
if (!(type->tp_flags & Py_TPFLAGS_READY)) {
|
if (!(type->tp_flags & Py_TPFLAGS_READY)) {
|
||||||
res = type_ready(type, 0);
|
res = type_ready(type, 1);
|
||||||
} else {
|
} else {
|
||||||
res = 0;
|
res = 0;
|
||||||
assert(_PyType_CheckConsistency(type));
|
assert(_PyType_CheckConsistency(type));
|
||||||
|
@ -8267,17 +8350,18 @@ PyType_Ready(PyTypeObject *type)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
_PyStaticType_InitBuiltin(PyInterpreterState *interp, PyTypeObject *self)
|
static int
|
||||||
|
init_static_type(PyInterpreterState *interp, PyTypeObject *self,
|
||||||
|
int isbuiltin, int initial)
|
||||||
{
|
{
|
||||||
assert(_Py_IsImmortal((PyObject *)self));
|
assert(_Py_IsImmortal((PyObject *)self));
|
||||||
assert(!(self->tp_flags & Py_TPFLAGS_HEAPTYPE));
|
assert(!(self->tp_flags & Py_TPFLAGS_HEAPTYPE));
|
||||||
assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_DICT));
|
assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_DICT));
|
||||||
assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF));
|
assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF));
|
||||||
|
|
||||||
int ismain = _Py_IsMainInterpreter(interp);
|
|
||||||
if ((self->tp_flags & Py_TPFLAGS_READY) == 0) {
|
if ((self->tp_flags & Py_TPFLAGS_READY) == 0) {
|
||||||
assert(ismain);
|
assert(initial);
|
||||||
|
|
||||||
self->tp_flags |= _Py_TPFLAGS_STATIC_BUILTIN;
|
self->tp_flags |= _Py_TPFLAGS_STATIC_BUILTIN;
|
||||||
self->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
|
self->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
|
||||||
|
@ -8287,24 +8371,36 @@ _PyStaticType_InitBuiltin(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
self->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
|
self->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(!ismain);
|
assert(!initial);
|
||||||
assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
|
assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
|
||||||
assert(self->tp_flags & Py_TPFLAGS_VALID_VERSION_TAG);
|
assert(self->tp_flags & Py_TPFLAGS_VALID_VERSION_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_builtin_state_init(interp, self);
|
managed_static_type_state_init(interp, self, isbuiltin, initial);
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
BEGIN_TYPE_LOCK();
|
BEGIN_TYPE_LOCK();
|
||||||
res = type_ready(self, !ismain);
|
res = type_ready(self, initial);
|
||||||
END_TYPE_LOCK()
|
END_TYPE_LOCK()
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
_PyStaticType_ClearWeakRefs(interp, self);
|
_PyStaticType_ClearWeakRefs(interp, self);
|
||||||
static_builtin_state_clear(interp, self);
|
managed_static_type_state_clear(interp, self, isbuiltin, initial);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyStaticType_InitForExtension(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
|
{
|
||||||
|
return init_static_type(interp, self, 0, ((self->tp_flags & Py_TPFLAGS_READY) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyStaticType_InitBuiltin(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
|
{
|
||||||
|
return init_static_type(interp, self, 1, _Py_IsMainInterpreter(interp));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
add_subclass(PyTypeObject *base, PyTypeObject *type)
|
add_subclass(PyTypeObject *base, PyTypeObject *type)
|
||||||
|
|
|
@ -15522,9 +15522,9 @@ unicode_is_finalizing(void)
|
||||||
void
|
void
|
||||||
_PyUnicode_FiniTypes(PyInterpreterState *interp)
|
_PyUnicode_FiniTypes(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
_PyStaticType_Dealloc(interp, &EncodingMapType);
|
_PyStaticType_FiniBuiltin(interp, &EncodingMapType);
|
||||||
_PyStaticType_Dealloc(interp, &PyFieldNameIter_Type);
|
_PyStaticType_FiniBuiltin(interp, &PyFieldNameIter_Type);
|
||||||
_PyStaticType_Dealloc(interp, &PyFormatterIter_Type);
|
_PyStaticType_FiniBuiltin(interp, &PyFormatterIter_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1066,7 +1066,7 @@ PyObject_ClearWeakRefs(PyObject *object)
|
||||||
void
|
void
|
||||||
_PyStaticType_ClearWeakRefs(PyInterpreterState *interp, PyTypeObject *type)
|
_PyStaticType_ClearWeakRefs(PyInterpreterState *interp, PyTypeObject *type)
|
||||||
{
|
{
|
||||||
static_builtin_state *state = _PyStaticType_GetState(interp, type);
|
managed_static_type_state *state = _PyStaticType_GetState(interp, type);
|
||||||
PyObject **list = _PyStaticType_GET_WEAKREFS_LISTPTR(state);
|
PyObject **list = _PyStaticType_GET_WEAKREFS_LISTPTR(state);
|
||||||
// This is safe to do without holding the lock in free-threaded builds;
|
// This is safe to do without holding the lock in free-threaded builds;
|
||||||
// there is only one thread running and no new threads can be created.
|
// there is only one thread running and no new threads can be created.
|
||||||
|
|
|
@ -90,6 +90,6 @@ static void
|
||||||
fini_exceptions(PyInterpreterState *interp)
|
fini_exceptions(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
// Likewise with _fini_not_shareable_error_type().
|
// Likewise with _fini_not_shareable_error_type().
|
||||||
_PyStaticType_Dealloc(interp, &_PyExc_InterpreterNotFoundError);
|
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterNotFoundError);
|
||||||
_PyStaticType_Dealloc(interp, &_PyExc_InterpreterError);
|
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,6 +307,7 @@ Python/crossinterp_exceptions.h - PyExc_InterpreterNotFoundError -
|
||||||
Modules/_datetimemodule.c - zero_delta -
|
Modules/_datetimemodule.c - zero_delta -
|
||||||
Modules/_datetimemodule.c - utc_timezone -
|
Modules/_datetimemodule.c - utc_timezone -
|
||||||
Modules/_datetimemodule.c - capi -
|
Modules/_datetimemodule.c - capi -
|
||||||
|
Modules/_datetimemodule.c - _globals -
|
||||||
Objects/boolobject.c - _Py_FalseStruct -
|
Objects/boolobject.c - _Py_FalseStruct -
|
||||||
Objects/boolobject.c - _Py_TrueStruct -
|
Objects/boolobject.c - _Py_TrueStruct -
|
||||||
Objects/dictobject.c - empty_keys_struct -
|
Objects/dictobject.c - empty_keys_struct -
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
|
@ -217,6 +217,7 @@ Modules/_datetimemodule.c - max_fold_seconds -
|
||||||
Modules/_datetimemodule.c datetime_isoformat specs -
|
Modules/_datetimemodule.c datetime_isoformat specs -
|
||||||
Modules/_datetimemodule.c parse_hh_mm_ss_ff correction -
|
Modules/_datetimemodule.c parse_hh_mm_ss_ff correction -
|
||||||
Modules/_datetimemodule.c time_isoformat specs -
|
Modules/_datetimemodule.c time_isoformat specs -
|
||||||
|
Modules/_datetimemodule.c - capi_types -
|
||||||
Modules/_decimal/_decimal.c - cond_map_template -
|
Modules/_decimal/_decimal.c - cond_map_template -
|
||||||
Modules/_decimal/_decimal.c - dec_signal_string -
|
Modules/_decimal/_decimal.c - dec_signal_string -
|
||||||
Modules/_decimal/_decimal.c - dflt_ctx -
|
Modules/_decimal/_decimal.c - dflt_ctx -
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
Loading…
Reference in New Issue