From 83e16d5fb7221a94ce765d07d2b6fe654354e3f0 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 28 Feb 2023 14:51:05 -0700 Subject: [PATCH 1/7] Move types.next_version_tag to PyInterpreterState for non-core-static types. --- Include/internal/pycore_runtime.h | 9 +--- Include/internal/pycore_runtime_init.h | 3 ++ Include/internal/pycore_typeobject.h | 58 +++++++++++++++++--------- Objects/typeobject.c | 26 +++++++----- 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 2350eaab5976ca..51850b65569ce9 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -25,6 +25,7 @@ extern "C" { #include "pycore_signal.h" // struct _signals_runtime_state #include "pycore_time.h" // struct _time_runtime_state #include "pycore_tracemalloc.h" // struct _tracemalloc_runtime_state +#include "pycore_typeobject.h" // struct types_runtime_state #include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids struct _getargs_runtime_state { @@ -156,13 +157,7 @@ typedef struct pyruntimestate { struct _Py_unicode_runtime_state unicode_state; struct _Py_dict_runtime_state dict_state; struct _py_func_runtime_state func_state; - - struct { - /* Used to set PyTypeObject.tp_version_tag */ - // bpo-42745: next_version_tag remains shared by all interpreters - // because of static types. - unsigned int next_version_tag; - } types; + struct _types_runtime_state types; /* All the objects that are shared by the runtime's interpreters. */ struct _Py_cached_objects cached_objects; diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index b54adf04761d4e..2e3de187a29e4b 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -113,6 +113,9 @@ extern "C" { }, \ }, \ .dtoa = _dtoa_state_INIT(&(INTERP)), \ + .types = { \ + .next_version_tag = _Py_MAX_GLOBAL_TYPE_VERSION_TAG + 1, \ + }, \ .static_objects = { \ .singletons = { \ ._not_used = 1, \ diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index cc5ce2875101ea..8a10bbe7082b5a 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -11,22 +11,16 @@ extern "C" { #endif -/* runtime lifecycle */ - -extern PyStatus _PyTypes_InitTypes(PyInterpreterState *); -extern void _PyTypes_FiniTypes(PyInterpreterState *); -extern void _PyTypes_Fini(PyInterpreterState *); - +/* state */ -/* other API */ - -/* Length of array of slotdef pointers used to store slots with the - same __name__. There should be at most MAX_EQUIV-1 slotdef entries with - the same __name__, for any __name__. Since that's a static property, it is - appropriate to declare fixed-size arrays for this. */ -#define MAX_EQUIV 10 +#define _Py_MAX_GLOBAL_TYPE_VERSION_TAG ((2<<16) - 1) -typedef struct wrapperbase pytype_slotdef; +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 + // because of static types. + unsigned int next_version_tag; +}; // Type attribute lookup cache: speed up attribute and method lookups, @@ -57,6 +51,36 @@ typedef struct { PyObject *tp_weaklist; } static_builtin_state; +struct types_state { + /* Used to set PyTypeObject.tp_version_tag. + It starts at _Py_MAX_GLOBAL_TYPE_VERSION_TAG + 1, + where all those lower numbers are used for core static types. */ + unsigned int next_version_tag; + + struct type_cache type_cache; + size_t num_builtins_initialized; + static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES]; +}; + + +/* runtime lifecycle */ + +extern PyStatus _PyTypes_InitTypes(PyInterpreterState *); +extern void _PyTypes_FiniTypes(PyInterpreterState *); +extern void _PyTypes_Fini(PyInterpreterState *); + + +/* other API */ + +/* Length of array of slotdef pointers used to store slots with the + same __name__. There should be at most MAX_EQUIV-1 slotdef entries with + the same __name__, for any __name__. Since that's a static property, it is + appropriate to declare fixed-size arrays for this. */ +#define MAX_EQUIV 10 + +typedef struct wrapperbase pytype_slotdef; + + static inline PyObject ** _PyStaticType_GET_WEAKREFS_LISTPTR(static_builtin_state *state) { @@ -78,12 +102,6 @@ _PyType_GetModuleState(PyTypeObject *type) return mod->md_state; } -struct types_state { - struct type_cache type_cache; - size_t num_builtins_initialized; - static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES]; -}; - extern int _PyStaticType_InitBuiltin(PyTypeObject *type); extern static_builtin_state * _PyStaticType_GetState(PyTypeObject *); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index b3f1429debc58b..349dcf6f03a4ee 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -44,7 +44,8 @@ class object "PyObject *" "&PyBaseObject_Type" PyUnicode_IS_READY(name) && \ (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE) -#define next_version_tag (_PyRuntime.types.next_version_tag) +#define next_version_tag(interp) \ + (interp)->types.next_version_tag typedef struct PySlot_Offset { short subslot_offset; @@ -331,7 +332,7 @@ _PyType_ClearCache(PyInterpreterState *interp) // use Py_SETREF() rather than using slower Py_XSETREF(). type_cache_clear(cache, Py_None); - return next_version_tag - 1; + return next_version_tag(interp) - 1; } @@ -400,7 +401,7 @@ PyType_ClearWatcher(int watcher_id) return 0; } -static int assign_version_tag(PyTypeObject *type); +static int assign_version_tag(PyInterpreterState *interp, PyTypeObject *type); int PyType_Watch(int watcher_id, PyObject* obj) @@ -415,7 +416,7 @@ PyType_Watch(int watcher_id, PyObject* obj) return -1; } // ensure we will get a callback on the next modification - assign_version_tag(type); + assign_version_tag(interp, type); type->tp_watched |= (1 << watcher_id); return 0; } @@ -549,7 +550,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { } static int -assign_version_tag(PyTypeObject *type) +assign_version_tag(PyInterpreterState *interp, PyTypeObject *type) { /* Ensure that the tp_version_tag is valid and set Py_TPFLAGS_VALID_VERSION_TAG. To respect the invariant, this @@ -563,18 +564,18 @@ assign_version_tag(PyTypeObject *type) return 0; } - if (next_version_tag == 0) { + if (next_version_tag(interp) == 0) { /* We have run out of version numbers */ return 0; } - type->tp_version_tag = next_version_tag++; + type->tp_version_tag = next_version_tag(interp)++; assert (type->tp_version_tag != 0); PyObject *bases = type->tp_bases; Py_ssize_t n = PyTuple_GET_SIZE(bases); for (Py_ssize_t i = 0; i < n; i++) { PyObject *b = PyTuple_GET_ITEM(bases, i); - if (!assign_version_tag(_PyType_CAST(b))) + if (!assign_version_tag(interp, _PyType_CAST(b))) return 0; } type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG; @@ -4165,6 +4166,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) { PyObject *res; int error; + PyInterpreterState *interp = _PyInterpreterState_GET(); unsigned int h = MCACHE_HASH_METHOD(type, name); struct type_cache *cache = get_type_cache(); @@ -4199,7 +4201,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) return NULL; } - if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(type)) { + if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(interp, type)) { h = MCACHE_HASH_METHOD(type, name); struct type_cache_entry *entry = &cache->hashtable[h]; entry->version = type->tp_version_tag; @@ -6985,7 +6987,11 @@ PyType_Ready(PyTypeObject *type) int _PyStaticType_InitBuiltin(PyTypeObject *self) { - self->tp_flags = self->tp_flags | _Py_TPFLAGS_STATIC_BUILTIN; + self->tp_flags |= _Py_TPFLAGS_STATIC_BUILTIN; + + assert(_PyRuntime.types.next_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG); + self->tp_version_tag = _PyRuntime.types.next_version_tag++; + self->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG; static_builtin_state_init(self); From c9281e4f706b91014f78bde1318b10d291ad75c5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 3 Mar 2023 11:56:29 -0700 Subject: [PATCH 2/7] Add NEXT_GLOBAL_VERSION_TAG. --- Objects/typeobject.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 349dcf6f03a4ee..96106ad9939436 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -44,7 +44,8 @@ class object "PyObject *" "&PyBaseObject_Type" PyUnicode_IS_READY(name) && \ (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE) -#define next_version_tag(interp) \ +#define NEXT_GLOBAL_VERSION_TAG _PyRuntime.types.next_version_tag +#define NEXT_VERSION_TAG(interp) \ (interp)->types.next_version_tag typedef struct PySlot_Offset { @@ -332,7 +333,7 @@ _PyType_ClearCache(PyInterpreterState *interp) // use Py_SETREF() rather than using slower Py_XSETREF(). type_cache_clear(cache, Py_None); - return next_version_tag(interp) - 1; + return NEXT_VERSION_TAG(interp) - 1; } @@ -564,11 +565,11 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type) return 0; } - if (next_version_tag(interp) == 0) { + if (NEXT_VERSION_TAG(interp) == 0) { /* We have run out of version numbers */ return 0; } - type->tp_version_tag = next_version_tag(interp)++; + type->tp_version_tag = NEXT_VERSION_TAG(interp)++; assert (type->tp_version_tag != 0); PyObject *bases = type->tp_bases; @@ -6989,8 +6990,8 @@ _PyStaticType_InitBuiltin(PyTypeObject *self) { self->tp_flags |= _Py_TPFLAGS_STATIC_BUILTIN; - assert(_PyRuntime.types.next_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG); - self->tp_version_tag = _PyRuntime.types.next_version_tag++; + assert(NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG); + self->tp_version_tag = NEXT_GLOBAL_VERSION_TAG++; self->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG; static_builtin_state_init(self); From 95ffcd12be8d2a31c40667b3c7f79d79413746e9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 3 Mar 2023 13:52:29 -0700 Subject: [PATCH 3/7] Handle static types correctly in assign_version_tag(). --- Include/internal/pycore_runtime_init.h | 2 +- Include/internal/pycore_typeobject.h | 3 ++- Objects/typeobject.c | 22 +++++++++++++++++----- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index 2e3de187a29e4b..c80d15680115f0 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -114,7 +114,7 @@ extern "C" { }, \ .dtoa = _dtoa_state_INIT(&(INTERP)), \ .types = { \ - .next_version_tag = _Py_MAX_GLOBAL_TYPE_VERSION_TAG + 1, \ + .next_version_tag = _Py_TYPE_BASE_VERSION_TAG, \ }, \ .static_objects = { \ .singletons = { \ diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index 8a10bbe7082b5a..0025d4903adf8b 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -13,7 +13,8 @@ extern "C" { /* state */ -#define _Py_MAX_GLOBAL_TYPE_VERSION_TAG ((2<<16) - 1) +#define _Py_TYPE_BASE_VERSION_TAG (2<<16) +#define _Py_MAX_GLOBAL_TYPE_VERSION_TAG (_Py_TYPE_BASE_VERSION_TAG - 1) struct _types_runtime_state { /* Used to set PyTypeObject.tp_version_tag for core static types. */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 96106ad9939436..44ecdacb043a38 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -565,12 +565,24 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type) return 0; } - if (NEXT_VERSION_TAG(interp) == 0) { - /* We have run out of version numbers */ - return 0; + if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { + /* static types */ + if (NEXT_GLOBAL_VERSION_TAG > _Py_MAX_GLOBAL_TYPE_VERSION_TAG) { + /* We have run out of version numbers */ + return 0; + } + type->tp_version_tag = NEXT_GLOBAL_VERSION_TAG++; + assert (type->tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG); + } + else { + /* heap types */ + if (NEXT_VERSION_TAG(interp) == 0) { + /* We have run out of version numbers */ + return 0; + } + type->tp_version_tag = NEXT_VERSION_TAG(interp)++; + assert (type->tp_version_tag != 0); } - type->tp_version_tag = NEXT_VERSION_TAG(interp)++; - assert (type->tp_version_tag != 0); PyObject *bases = type->tp_bases; Py_ssize_t n = PyTuple_GET_SIZE(bases); From f3b707d7f88e6ff96e7f0408c7ff5431925d25a7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 3 Mar 2023 14:09:05 -0700 Subject: [PATCH 4/7] Verify that builtin types have builtin bases. --- Objects/typeobject.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 44ecdacb043a38..8f35d656aa9007 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6676,8 +6676,11 @@ type_ready_mro(PyTypeObject *type) assert(type->tp_mro != NULL); assert(PyTuple_Check(type->tp_mro)); - /* All bases of statically allocated type should be statically allocated */ + /* All bases of statically allocated type should be statically allocated, + and static builtin types must have static builtin bases. */ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + assert(type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE); + int isbuiltin = type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN; PyObject *mro = type->tp_mro; Py_ssize_t n = PyTuple_GET_SIZE(mro); for (Py_ssize_t i = 0; i < n; i++) { @@ -6689,6 +6692,7 @@ type_ready_mro(PyTypeObject *type) type->tp_name, base->tp_name); return -1; } + assert(!isbuiltin || (base->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN)); } } return 0; From c32b834c8135ae7f78137309d2cd0d78d22be30b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 3 Mar 2023 14:17:32 -0700 Subject: [PATCH 5/7] Add an assert. --- Objects/typeobject.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8f35d656aa9007..4b86591840a218 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -545,7 +545,9 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { } } return; + clear: + assert(!(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN)); type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; type->tp_version_tag = 0; /* 0 is not a valid version tag */ } From 6362a368c72d497500cd14f755df7406fe194f4d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 3 Mar 2023 14:32:08 -0700 Subject: [PATCH 6/7] Do not invalidate the method cache for static builtin types. --- Objects/typeobject.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 4b86591840a218..2e0fa8ffb81ec8 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2346,7 +2346,15 @@ mro_internal(PyTypeObject *type, PyObject **p_old_mro) from the custom MRO */ type_mro_modified(type, type->tp_bases); - PyType_Modified(type); + // XXX Expand this to Py_TPFLAGS_IMMUTABLETYPE? + if (!(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN)) { + PyType_Modified(type); + } + else { + /* For static builtin types, this is only called during init + before the method cache has been populated. */ + assert(_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)); + } if (p_old_mro != NULL) *p_old_mro = old_mro; /* transfer the ownership */ From 0d78c1b9403df66042d3ef8273e51e9e5b8282d9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 24 Apr 2023 14:37:02 -0600 Subject: [PATCH 7/7] Only use deepfreeze in the main interpreter. --- Makefile.pre.in | 2 +- Python/frozen.c | 81 +++++++++++++++++++++++++++++++------------------ Python/import.c | 9 +++--- 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index 582310807d05ba..d5a0f501e984b6 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1194,7 +1194,7 @@ Tools/build/freeze_modules.py: $(FREEZE_MODULE) .PHONY: regen-frozen regen-frozen: Tools/build/freeze_modules.py $(FROZEN_FILES_IN) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/freeze_modules.py + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/freeze_modules.py --frozen-modules @echo "The Makefile was updated, you may need to re-run make." ############################################################################ diff --git a/Python/frozen.c b/Python/frozen.c index 48b429519b6606..6b977710e6e342 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -41,6 +41,29 @@ #include /* Includes for frozen modules: */ +#include "frozen_modules/importlib._bootstrap.h" +#include "frozen_modules/importlib._bootstrap_external.h" +#include "frozen_modules/zipimport.h" +#include "frozen_modules/abc.h" +#include "frozen_modules/codecs.h" +#include "frozen_modules/io.h" +#include "frozen_modules/_collections_abc.h" +#include "frozen_modules/_sitebuiltins.h" +#include "frozen_modules/genericpath.h" +#include "frozen_modules/ntpath.h" +#include "frozen_modules/posixpath.h" +#include "frozen_modules/os.h" +#include "frozen_modules/site.h" +#include "frozen_modules/stat.h" +#include "frozen_modules/importlib.util.h" +#include "frozen_modules/importlib.machinery.h" +#include "frozen_modules/runpy.h" +#include "frozen_modules/__hello__.h" +#include "frozen_modules/__phello__.h" +#include "frozen_modules/__phello__.ham.h" +#include "frozen_modules/__phello__.ham.eggs.h" +#include "frozen_modules/__phello__.spam.h" +#include "frozen_modules/frozen_only.h" /* End includes */ #define GET_CODE(name) _Py_get_##name##_toplevel @@ -78,46 +101,46 @@ extern PyObject *_Py_get_frozen_only_toplevel(void); /* End extern declarations */ static const struct _frozen bootstrap_modules[] = { - {"_frozen_importlib", NULL, 0, false, GET_CODE(importlib__bootstrap)}, - {"_frozen_importlib_external", NULL, 0, false, GET_CODE(importlib__bootstrap_external)}, - {"zipimport", NULL, 0, false, GET_CODE(zipimport)}, + {"_frozen_importlib", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap), false, GET_CODE(importlib__bootstrap)}, + {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external), false, GET_CODE(importlib__bootstrap_external)}, + {"zipimport", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport), false, GET_CODE(zipimport)}, {0, 0, 0} /* bootstrap sentinel */ }; static const struct _frozen stdlib_modules[] = { /* stdlib - startup, without site (python -S) */ - {"abc", NULL, 0, false, GET_CODE(abc)}, - {"codecs", NULL, 0, false, GET_CODE(codecs)}, - {"io", NULL, 0, false, GET_CODE(io)}, + {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false, GET_CODE(abc)}, + {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false, GET_CODE(codecs)}, + {"io", _Py_M__io, (int)sizeof(_Py_M__io), false, GET_CODE(io)}, /* stdlib - startup, with site */ - {"_collections_abc", NULL, 0, false, GET_CODE(_collections_abc)}, - {"_sitebuiltins", NULL, 0, false, GET_CODE(_sitebuiltins)}, - {"genericpath", NULL, 0, false, GET_CODE(genericpath)}, - {"ntpath", NULL, 0, false, GET_CODE(ntpath)}, - {"posixpath", NULL, 0, false, GET_CODE(posixpath)}, - {"os.path", NULL, 0, false, GET_CODE(posixpath)}, - {"os", NULL, 0, false, GET_CODE(os)}, - {"site", NULL, 0, false, GET_CODE(site)}, - {"stat", NULL, 0, false, GET_CODE(stat)}, + {"_collections_abc", _Py_M___collections_abc, (int)sizeof(_Py_M___collections_abc), false, GET_CODE(_collections_abc)}, + {"_sitebuiltins", _Py_M___sitebuiltins, (int)sizeof(_Py_M___sitebuiltins), false, GET_CODE(_sitebuiltins)}, + {"genericpath", _Py_M__genericpath, (int)sizeof(_Py_M__genericpath), false, GET_CODE(genericpath)}, + {"ntpath", _Py_M__ntpath, (int)sizeof(_Py_M__ntpath), false, GET_CODE(ntpath)}, + {"posixpath", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false, GET_CODE(posixpath)}, + {"os.path", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false, GET_CODE(posixpath)}, + {"os", _Py_M__os, (int)sizeof(_Py_M__os), false, GET_CODE(os)}, + {"site", _Py_M__site, (int)sizeof(_Py_M__site), false, GET_CODE(site)}, + {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false, GET_CODE(stat)}, /* runpy - run module with -m */ - {"importlib.util", NULL, 0, false, GET_CODE(importlib_util)}, - {"importlib.machinery", NULL, 0, false, GET_CODE(importlib_machinery)}, - {"runpy", NULL, 0, false, GET_CODE(runpy)}, + {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false, GET_CODE(importlib_util)}, + {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false, GET_CODE(importlib_machinery)}, + {"runpy", _Py_M__runpy, (int)sizeof(_Py_M__runpy), false, GET_CODE(runpy)}, {0, 0, 0} /* stdlib sentinel */ }; static const struct _frozen test_modules[] = { - {"__hello__", NULL, 0, false, GET_CODE(__hello__)}, - {"__hello_alias__", NULL, 0, false, GET_CODE(__hello__)}, - {"__phello_alias__", NULL, 0, true, GET_CODE(__hello__)}, - {"__phello_alias__.spam", NULL, 0, false, GET_CODE(__hello__)}, - {"__phello__", NULL, 0, true, GET_CODE(__phello__)}, - {"__phello__.__init__", NULL, 0, false, GET_CODE(__phello__)}, - {"__phello__.ham", NULL, 0, true, GET_CODE(__phello___ham)}, - {"__phello__.ham.__init__", NULL, 0, false, GET_CODE(__phello___ham)}, - {"__phello__.ham.eggs", NULL, 0, false, GET_CODE(__phello___ham_eggs)}, - {"__phello__.spam", NULL, 0, false, GET_CODE(__phello___spam)}, - {"__hello_only__", NULL, 0, false, GET_CODE(frozen_only)}, + {"__hello__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)}, + {"__hello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)}, + {"__phello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), true, GET_CODE(__hello__)}, + {"__phello_alias__.spam", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)}, + {"__phello__", _Py_M____phello__, (int)sizeof(_Py_M____phello__), true, GET_CODE(__phello__)}, + {"__phello__.__init__", _Py_M____phello__, (int)sizeof(_Py_M____phello__), false, GET_CODE(__phello__)}, + {"__phello__.ham", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), true, GET_CODE(__phello___ham)}, + {"__phello__.ham.__init__", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), false, GET_CODE(__phello___ham)}, + {"__phello__.ham.eggs", _Py_M____phello___ham_eggs, (int)sizeof(_Py_M____phello___ham_eggs), false, GET_CODE(__phello___ham_eggs)}, + {"__phello__.spam", _Py_M____phello___spam, (int)sizeof(_Py_M____phello___spam), false, GET_CODE(__phello___spam)}, + {"__hello_only__", _Py_M__frozen_only, (int)sizeof(_Py_M__frozen_only), false, GET_CODE(frozen_only)}, {0, 0, 0} /* test sentinel */ }; const struct _frozen *_PyImport_FrozenBootstrap = bootstrap_modules; diff --git a/Python/import.c b/Python/import.c index 1db5b9333bbba1..df577800528d27 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2021,9 +2021,9 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) } static PyObject * -unmarshal_frozen_code(struct frozen_info *info) +unmarshal_frozen_code(PyInterpreterState *interp, struct frozen_info *info) { - if (info->get_code) { + if (info->get_code && _Py_IsMainInterpreter(interp)) { PyObject *code = info->get_code(); assert(code != NULL); return code; @@ -2070,7 +2070,7 @@ PyImport_ImportFrozenModuleObject(PyObject *name) set_frozen_error(status, name); return -1; } - co = unmarshal_frozen_code(&info); + co = unmarshal_frozen_code(tstate->interp, &info); if (co == NULL) { return -1; } @@ -3528,7 +3528,8 @@ _imp_get_frozen_object_impl(PyObject *module, PyObject *name, return NULL; } - PyObject *codeobj = unmarshal_frozen_code(&info); + PyInterpreterState *interp = _PyInterpreterState_GET(); + PyObject *codeobj = unmarshal_frozen_code(interp, &info); if (dataobj != Py_None) { PyBuffer_Release(&buf); }