From 99c57468d9bdbcb3a7dffcb6cbfcf782bbb4ca56 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 13:55:02 -0600 Subject: [PATCH 1/9] Restore the finalization code. --- Objects/typeobject.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7d01b680605a38..dee6e9927e4a21 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -269,7 +269,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self, /* Reset the type's per-interpreter state. This basically undoes what managed_static_type_state_init() did. */ -static void +static PyTypeObject * managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, int isbuiltin, int final) { @@ -277,6 +277,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, size_t full_index = isbuiltin ? index : index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; + PyTypeObject *def = &_PyRuntime.types.managed_static.types[full_index].def; managed_static_type_state *state = isbuiltin ? &(interp->types.builtins.initialized[index]) @@ -312,6 +313,8 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, } PyMutex_Unlock(&interp->types.mutex); } + + return def; } static PyTypeObject * @@ -5849,7 +5852,15 @@ fini_static_type(PyInterpreterState *interp, PyTypeObject *type, } _PyStaticType_ClearWeakRefs(interp, type); - managed_static_type_state_clear(interp, type, isbuiltin, final); + PyTypeObject *def = + managed_static_type_state_clear(interp, type, isbuiltin, final); + /* For now we exclude extension module types. */ + if (final && isbuiltin) { + /* Restore the static type to it's (mostly) original values. */ + destructor dealloc = type->tp_dealloc; + memcpy(type, def, sizeof(PyTypeObject)); + type->tp_dealloc = dealloc; + } } void @@ -8481,6 +8492,9 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self, PyTypeObject *def = managed_static_type_get_def(self, isbuiltin); if (initial) { memcpy(def, self, sizeof(PyTypeObject)); + /* For now we do not worry about preserving the index + at finalization. */ + managed_static_type_index_clear(def); } int res; @@ -8492,6 +8506,10 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self, managed_static_type_state_clear(interp, self, isbuiltin, initial); } + if (initial) { + Py_SET_TYPE(def, Py_TYPE(self)); + } + return res; } From 853c7d2dde7046bb9e7097b71ae2a47c62c02958 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 15:12:12 -0600 Subject: [PATCH 2/9] Factor out static type def helpers. --- Objects/typeobject.c | 105 +++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 23 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index dee6e9927e4a21..bcc00d35e54322 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -148,6 +148,78 @@ managed_static_type_index_clear(PyTypeObject *self) self->tp_subclasses = NULL; } + +typedef PyTypeObject *static_type_def; + +static inline static_type_def +managed_static_type_get_def(static_type_def type, int isbuiltin) +{ + size_t index = managed_static_type_index_get(type); + size_t full_index = isbuiltin + ? index + : index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; + return &_PyRuntime.types.managed_static.types[full_index].def; +} + +static void +managed_static_type_init_def(static_type_def def, PyTypeObject *type) +{ + assert(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN); + assert(type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE); + /* It must be the initial case. */ + assert(!(type->tp_flags & Py_TPFLAGS_READY) + && !(type->tp_flags & Py_TPFLAGS_READYING)); + + /* We preserve the original type struct value to restore during + finalization. This will also preserve (thus restore) any extra + values set on the struct before this. */ + memcpy(def, type, sizeof(PyTypeObject)); + + /* For now we do not worry about preserving the index + at finalization. Ideally, we would keep it, + but the related change should wait until 3.13 is ready. */ + managed_static_type_index_clear(def); +} + +static void +managed_static_type_fini_def(PyTypeObject *def, PyTypeObject *type, + int isbuiltin) +{ + /* It must be the final case. */ + assert(!(type->tp_flags & Py_TPFLAGS_READY)); + + if (!isbuiltin) { + /* For now we exclude extension module types, + since currently some of their instances are getting cleaned up + after the types, rather than before. */ + return; + } + + /* Preserve specific data before potentially wiping it. */ + destructor dealloc = type->tp_dealloc; + + /* Restore the static type to it's (mostly) original values. + We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */ + memcpy(type, def, sizeof(PyTypeObject)); + assert(!managed_static_type_index_is_set(type)); + + /* Currently, there is a small set of cases where a static type + might be used after it has been finalized. For example, some + instances are cleaned up after the static types are finalized. + Similarly, MemoryError could be raised even after it is finalized. + + Ideally, none of the cases would ever happen and types would be + finalized only after all other objects have been destroyed + (or are themselves static). + + However, fixing that isn't simple and not something we're doing + yet. Thankfully, those exceptional cases only require a small + subset of the type, all of which is static data. Thus, in the + meantime, we preserve those parts. */ + type->tp_dealloc = dealloc; +} + + static PyTypeObject * static_ext_type_lookup(PyInterpreterState *interp, size_t index, int64_t *p_interp_count) @@ -269,7 +341,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self, /* Reset the type's per-interpreter state. This basically undoes what managed_static_type_state_init() did. */ -static PyTypeObject * +static static_type_def managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, int isbuiltin, int final) { @@ -317,16 +389,6 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, return def; } -static PyTypeObject * -managed_static_type_get_def(PyTypeObject *self, int isbuiltin) -{ - size_t index = managed_static_type_index_get(self); - size_t full_index = isbuiltin - ? index - : index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; - return &_PyRuntime.types.managed_static.types[full_index].def; -} - // Also see _PyStaticType_InitBuiltin() and _PyStaticType_FiniBuiltin(). /* end static builtin helpers */ @@ -5852,14 +5914,12 @@ fini_static_type(PyInterpreterState *interp, PyTypeObject *type, } _PyStaticType_ClearWeakRefs(interp, type); - PyTypeObject *def = + static_type_def def = managed_static_type_state_clear(interp, type, isbuiltin, final); - /* For now we exclude extension module types. */ - if (final && isbuiltin) { - /* Restore the static type to it's (mostly) original values. */ - destructor dealloc = type->tp_dealloc; - memcpy(type, def, sizeof(PyTypeObject)); - type->tp_dealloc = dealloc; + + if (final) { + /* We need to restore the copy of the original static type struct, */ + managed_static_type_fini_def(def, type, isbuiltin); } } @@ -8489,12 +8549,11 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self, managed_static_type_state_init(interp, self, isbuiltin, initial); - PyTypeObject *def = managed_static_type_get_def(self, isbuiltin); + static_type_def def = managed_static_type_get_def(self, isbuiltin); if (initial) { - memcpy(def, self, sizeof(PyTypeObject)); - /* For now we do not worry about preserving the index - at finalization. */ - managed_static_type_index_clear(def); + /* We need to save a copy of the original static type struct, + to use when readying the type. */ + managed_static_type_init_def(def, self); } int res; From 753be4d9869bc4eb85c9c32e03447675ceb62cb7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 15:22:32 -0600 Subject: [PATCH 3/9] Do not preserve the metaclass on the def. --- Objects/typeobject.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index bcc00d35e54322..b4b950b620ac57 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -196,6 +196,7 @@ managed_static_type_fini_def(PyTypeObject *def, PyTypeObject *type, } /* Preserve specific data before potentially wiping it. */ + PyTypeObject *metaclass = Py_TYPE(type); destructor dealloc = type->tp_dealloc; /* Restore the static type to it's (mostly) original values. @@ -216,6 +217,7 @@ managed_static_type_fini_def(PyTypeObject *def, PyTypeObject *type, yet. Thankfully, those exceptional cases only require a small subset of the type, all of which is static data. Thus, in the meantime, we preserve those parts. */ + Py_SET_TYPE(type, metaclass); type->tp_dealloc = dealloc; } @@ -8565,10 +8567,6 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self, managed_static_type_state_clear(interp, self, isbuiltin, initial); } - if (initial) { - Py_SET_TYPE(def, Py_TYPE(self)); - } - return res; } From 5c422f4d949c500f27ae6d9d138fc18afe2b224d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 13:43:07 -0600 Subject: [PATCH 4/9] Do not return the def from managed_static_type_state_clear(). --- Objects/typeobject.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index b4b950b620ac57..237aa0796161d7 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -192,6 +192,7 @@ managed_static_type_fini_def(PyTypeObject *def, PyTypeObject *type, /* For now we exclude extension module types, since currently some of their instances are getting cleaned up after the types, rather than before. */ + managed_static_type_index_clear(type); return; } @@ -343,7 +344,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self, /* Reset the type's per-interpreter state. This basically undoes what managed_static_type_state_init() did. */ -static static_type_def +static void managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, int isbuiltin, int final) { @@ -351,7 +352,6 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, size_t full_index = isbuiltin ? index : index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; - PyTypeObject *def = &_PyRuntime.types.managed_static.types[full_index].def; managed_static_type_state *state = isbuiltin ? &(interp->types.builtins.initialized[index]) @@ -371,7 +371,9 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, assert(!_PyRuntime.types.managed_static.types[full_index].interp_count); _PyRuntime.types.managed_static.types[full_index].type = NULL; - managed_static_type_index_clear(self); + /* It could make sense to call managed_static_type_index_clear(self) + here. However, we need to know the index to finalize the preserved + def and that must happen only after we've cleared the state here. */ } if (isbuiltin) { @@ -387,8 +389,6 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self, } PyMutex_Unlock(&interp->types.mutex); } - - return def; } // Also see _PyStaticType_InitBuiltin() and _PyStaticType_FiniBuiltin(). @@ -5916,11 +5916,11 @@ fini_static_type(PyInterpreterState *interp, PyTypeObject *type, } _PyStaticType_ClearWeakRefs(interp, type); - static_type_def def = - managed_static_type_state_clear(interp, type, isbuiltin, final); + managed_static_type_state_clear(interp, type, isbuiltin, final); if (final) { /* We need to restore the copy of the original static type struct, */ + static_type_def def = managed_static_type_get_def(type, isbuiltin); managed_static_type_fini_def(def, type, isbuiltin); } } From eba8751f2941f5e9dea27aa57be5cfed3dc2475f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 16:56:57 -0600 Subject: [PATCH 5/9] Factor out struct static_type_def. --- Include/internal/pycore_typeobject.h | 6 +++++- Objects/typeobject.c | 31 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index df6bfef715dd34..d27a606b29e456 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -24,6 +24,10 @@ extern "C" { #define _Py_MAX_MANAGED_STATIC_TYPES \ (_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES + _Py_MAX_MANAGED_STATIC_EXT_TYPES) +struct static_type_def { + PyTypeObject type; +}; + struct _types_runtime_state { /* Used to set PyTypeObject.tp_version_tag for core static types. */ // bpo-42745: next_version_tag remains shared by all interpreters @@ -33,7 +37,7 @@ struct _types_runtime_state { struct { struct { PyTypeObject *type; - PyTypeObject def; + struct static_type_def def; int64_t interp_count; } types[_Py_MAX_MANAGED_STATIC_TYPES]; } managed_static; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 237aa0796161d7..96ae891d89f052 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -149,10 +149,10 @@ managed_static_type_index_clear(PyTypeObject *self) } -typedef PyTypeObject *static_type_def; +typedef struct static_type_def *static_type_def; static inline static_type_def -managed_static_type_get_def(static_type_def type, int isbuiltin) +managed_static_type_get_def(PyTypeObject *type, int isbuiltin) { size_t index = managed_static_type_index_get(type); size_t full_index = isbuiltin @@ -173,16 +173,17 @@ managed_static_type_init_def(static_type_def def, PyTypeObject *type) /* We preserve the original type struct value to restore during finalization. This will also preserve (thus restore) any extra values set on the struct before this. */ - memcpy(def, type, sizeof(PyTypeObject)); + PyTypeObject *deftype = &def->type; + memcpy(deftype, type, sizeof(PyTypeObject)); /* For now we do not worry about preserving the index at finalization. Ideally, we would keep it, but the related change should wait until 3.13 is ready. */ - managed_static_type_index_clear(def); + managed_static_type_index_clear(deftype); } static void -managed_static_type_fini_def(PyTypeObject *def, PyTypeObject *type, +managed_static_type_fini_def(static_type_def def, PyTypeObject *type, int isbuiltin) { /* It must be the final case. */ @@ -202,8 +203,8 @@ managed_static_type_fini_def(PyTypeObject *def, PyTypeObject *type, /* Restore the static type to it's (mostly) original values. We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */ - memcpy(type, def, sizeof(PyTypeObject)); - assert(!managed_static_type_index_is_set(type)); + PyTypeObject *deftype = &def->type; + memcpy(type, deftype, sizeof(PyTypeObject)); /* Currently, there is a small set of cases where a static type might be used after it has been finalized. For example, some @@ -7932,7 +7933,7 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) return 0; } -static int add_operators(PyTypeObject *, PyTypeObject *); +static int add_operators(PyTypeObject *, static_type_def); static int add_tp_new_wrapper(PyTypeObject *type); #define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING) @@ -8097,7 +8098,7 @@ type_dict_set_doc(PyTypeObject *type) static int -type_ready_fill_dict(PyTypeObject *type, PyTypeObject *def) +type_ready_fill_dict(PyTypeObject *type, static_type_def def) { /* Add type-specific descriptors to tp_dict */ if (add_operators(type, def) < 0) { @@ -8419,7 +8420,7 @@ type_ready_post_checks(PyTypeObject *type) static int -type_ready(PyTypeObject *type, PyTypeObject *def, int initial) +type_ready(PyTypeObject *type, static_type_def def, int initial) { ASSERT_TYPE_LOCK_HELD(); @@ -11154,7 +11155,7 @@ recurse_down_subclasses(PyTypeObject *type, PyObject *attr_name, infinite recursion here.) */ static int -add_operators(PyTypeObject *type, PyTypeObject *def) +add_operators(PyTypeObject *type, static_type_def def) { PyObject *dict = lookup_tp_dict(type); pytype_slotdef *p; @@ -11162,14 +11163,14 @@ add_operators(PyTypeObject *type, PyTypeObject *def) void **ptr; assert(def == NULL || (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN)); - if (def == NULL) { - def = type; - } + PyTypeObject *deftype = def == NULL + ? type + : &def->type; for (p = slotdefs; p->name; p++) { if (p->wrapper == NULL) continue; - ptr = slotptr(def, p->offset); + ptr = slotptr(deftype, p->offset); if (!ptr || !*ptr) continue; int r = PyDict_Contains(dict, p->name_strobj); From 8000ab314182bb2ebb14fdbbe2f600cc499b7d69 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 16:58:18 -0600 Subject: [PATCH 6/9] Clear the index after getting the def. --- Objects/typeobject.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 96ae891d89f052..b8b518946f65f6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -175,11 +175,6 @@ managed_static_type_init_def(static_type_def def, PyTypeObject *type) values set on the struct before this. */ PyTypeObject *deftype = &def->type; memcpy(deftype, type, sizeof(PyTypeObject)); - - /* For now we do not worry about preserving the index - at finalization. Ideally, we would keep it, - but the related change should wait until 3.13 is ready. */ - managed_static_type_index_clear(deftype); } static void @@ -193,7 +188,6 @@ managed_static_type_fini_def(static_type_def def, PyTypeObject *type, /* For now we exclude extension module types, since currently some of their instances are getting cleaned up after the types, rather than before. */ - managed_static_type_index_clear(type); return; } @@ -5923,6 +5917,7 @@ fini_static_type(PyInterpreterState *interp, PyTypeObject *type, /* We need to restore the copy of the original static type struct, */ static_type_def def = managed_static_type_get_def(type, isbuiltin); managed_static_type_fini_def(def, type, isbuiltin); + managed_static_type_index_clear(type); } } From 6b17676e566fa1e1099f2718e3f250c8f654cc02 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 16:58:34 -0600 Subject: [PATCH 7/9] Do not overwrite the entire type struct; only the tp slot operators. --- Objects/typeobject.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index b8b518946f65f6..a36d6edb05ac25 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -149,6 +149,9 @@ managed_static_type_index_clear(PyTypeObject *self) } +static pytype_slotdef slotdefs[]; +static void ** slotptr(PyTypeObject *, int); + typedef struct static_type_def *static_type_def; static inline static_type_def @@ -171,8 +174,9 @@ managed_static_type_init_def(static_type_def def, PyTypeObject *type) && !(type->tp_flags & Py_TPFLAGS_READYING)); /* We preserve the original type struct value to restore during - finalization. This will also preserve (thus restore) any extra - values set on the struct before this. */ + finalization. This will also preserve any extra values set on + the struct before this. Technically, we only need the operator + "tp" slots, but it's simpler to copy the whole struct. */ PyTypeObject *deftype = &def->type; memcpy(deftype, type, sizeof(PyTypeObject)); } @@ -192,13 +196,23 @@ managed_static_type_fini_def(static_type_def def, PyTypeObject *type, } /* Preserve specific data before potentially wiping it. */ - PyTypeObject *metaclass = Py_TYPE(type); destructor dealloc = type->tp_dealloc; - /* Restore the static type to it's (mostly) original values. - We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */ + /* Restore the static type's original operator "tp" slot values. + We do not bother restoring any of the other preserved data, + nor do we even overwrite any of it. */ PyTypeObject *deftype = &def->type; - memcpy(type, deftype, sizeof(PyTypeObject)); + for (pytype_slotdef *p = slotdefs; p->name; p++) { + void **defptr = slotptr(deftype, p->offset); + if (defptr == NULL) { + continue; + } + if (defptr == (void **)&def->type.tp_call) { + continue; + } + void **typeptr = slotptr(type, p->offset); + *typeptr = *defptr; + } /* Currently, there is a small set of cases where a static type might be used after it has been finalized. For example, some @@ -213,7 +227,6 @@ managed_static_type_fini_def(static_type_def def, PyTypeObject *type, yet. Thankfully, those exceptional cases only require a small subset of the type, all of which is static data. Thus, in the meantime, we preserve those parts. */ - Py_SET_TYPE(type, metaclass); type->tp_dealloc = dealloc; } From e777250b761da5fd65518d2a40e3a1e25d084b44 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 17:25:00 -0600 Subject: [PATCH 8/9] Preserve the type substructs too. --- Include/internal/pycore_typeobject.h | 5 ++++ Objects/typeobject.c | 35 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index d27a606b29e456..783c4f8a9fc43f 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -26,6 +26,11 @@ extern "C" { struct static_type_def { PyTypeObject type; + PyNumberMethods as_number; + PySequenceMethods as_sequence; + PyMappingMethods as_mapping; + PyBufferProcs as_buffer; + PyAsyncMethods as_async; }; struct _types_runtime_state { diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a36d6edb05ac25..91f8e16c35e65e 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -179,6 +179,26 @@ managed_static_type_init_def(static_type_def def, PyTypeObject *type) "tp" slots, but it's simpler to copy the whole struct. */ PyTypeObject *deftype = &def->type; memcpy(deftype, type, sizeof(PyTypeObject)); + if (deftype->tp_as_buffer != NULL) { + memcpy(&def->as_buffer, type->tp_as_buffer, sizeof(PyBufferProcs)); + deftype->tp_as_buffer = &def->as_buffer; + } + if (deftype->tp_as_sequence != NULL) { + memcpy(&def->as_sequence, type->tp_as_sequence, sizeof(PySequenceMethods)); + deftype->tp_as_sequence = &def->as_sequence; + } + if (deftype->tp_as_mapping != NULL) { + memcpy(&def->as_mapping, type->tp_as_mapping, sizeof(PyMappingMethods)); + deftype->tp_as_mapping = &def->as_mapping; + } + if (deftype->tp_as_number != NULL) { + memcpy(&def->as_number, type->tp_as_number, sizeof(PyNumberMethods)); + deftype->tp_as_number = &def->as_number; + } + if (deftype->tp_as_async != NULL) { + memcpy(&def->as_async, type->tp_as_async, sizeof(PyAsyncMethods)); + deftype->tp_as_async = &def->as_async; + } } static void @@ -213,6 +233,21 @@ managed_static_type_fini_def(static_type_def def, PyTypeObject *type, void **typeptr = slotptr(type, p->offset); *typeptr = *defptr; } + if (deftype->tp_as_buffer == NULL) { + type->tp_as_buffer = NULL; + } + if (deftype->tp_as_sequence== NULL) { + type->tp_as_sequence = NULL; + } + if (deftype->tp_as_mapping == NULL) { + type->tp_as_mapping = NULL; + } + if (deftype->tp_as_number == NULL) { + type->tp_as_number = NULL; + } + if (deftype->tp_as_async == NULL) { + type->tp_as_async = NULL; + } /* Currently, there is a small set of cases where a static type might be used after it has been finalized. For example, some From 8520cfcdf67219216eb11df92ce4708bb60ed92d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 11 Jul 2024 17:40:13 -0600 Subject: [PATCH 9/9] Fix a compiler error on Windows. --- Objects/typeobject.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 91f8e16c35e65e..1cd047fbd631ac 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -149,7 +149,11 @@ managed_static_type_index_clear(PyTypeObject *self) } +#ifdef MS_WINDOWS +static pytype_slotdef slotdefs[100]; +#else static pytype_slotdef slotdefs[]; +#endif static void ** slotptr(PyTypeObject *, int); typedef struct static_type_def *static_type_def;