summaryrefslogtreecommitdiffstatshomepage
path: root/py/objmodule.c
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2023-05-12 17:07:24 +1000
committerDamien George <damien@micropython.org>2023-06-01 16:21:37 +1000
commit6a8114eee8ff486d812b4efc5a94880b565640f3 (patch)
treec0fc5e7a06e05cb90db952ce59824521d5dc87fc /py/objmodule.c
parented90f30dd5d39e958ce99c041f1dc1f9dbb63bb2 (diff)
downloadmicropython-6a8114eee8ff486d812b4efc5a94880b565640f3.tar.gz
micropython-6a8114eee8ff486d812b4efc5a94880b565640f3.zip
py/objmodule: Don't use sys.modules to track a builtin __init__.
This can lead to duplicate initialisations if a module can be imported via multiple names, so the module must track this itself anyway. This reduces code size (diff is -40 bytes), and avoids special treatment of builtin-modules-with-init with respect to sys.modules. No other builtin modules get put into sys.modules. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Diffstat (limited to 'py/objmodule.c')
-rw-r--r--py/objmodule.c38
1 files changed, 9 insertions, 29 deletions
diff --git a/py/objmodule.c b/py/objmodule.c
index 6f061a9408..7326fbe2d1 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -40,10 +40,6 @@
#include "genhdr/moduledefs.h"
#endif
-#if MICROPY_MODULE_BUILTIN_INIT
-STATIC void mp_module_call_init(mp_obj_t module_name, mp_obj_t module_obj);
-#endif
-
STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
@@ -176,9 +172,8 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table);
-// Attempts to find (and initialise) a builtin, otherwise returns MP_OBJ_NULL.
-// This must only be called after first checking the loaded modules,
-// otherwise the module will be re-initialised.
+// Attempts to find (and initialise) a builtin, otherwise returns
+// MP_OBJ_NULL.
mp_obj_t mp_module_get_builtin(qstr module_name) {
mp_map_elem_t *elem = mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
if (!elem) {
@@ -186,33 +181,18 @@ mp_obj_t mp_module_get_builtin(qstr module_name) {
}
#if MICROPY_MODULE_BUILTIN_INIT
- // If found, it's a newly loaded built-in, so init it.
- mp_module_call_init(MP_OBJ_NEW_QSTR(module_name), elem->value);
- #endif
-
- return elem->value;
-}
-
-#if MICROPY_MODULE_BUILTIN_INIT
-STATIC void mp_module_register(mp_obj_t module_name, mp_obj_t module) {
- mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;
- mp_map_lookup(mp_loaded_modules_map, module_name, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;
-}
-
-STATIC void mp_module_call_init(mp_obj_t module_name, mp_obj_t module_obj) {
- // Look for __init__ and call it if it exists
+ // If found, it's a newly loaded built-in, so init it. This can run
+ // multiple times, so the module must ensure that it handles being
+ // initialised multiple times.
mp_obj_t dest[2];
- mp_load_method_maybe(module_obj, MP_QSTR___init__, dest);
+ mp_load_method_maybe(elem->value, MP_QSTR___init__, dest);
if (dest[0] != MP_OBJ_NULL) {
mp_call_method_n_kw(0, 0, dest);
- // Register module so __init__ is not called again.
- // If a module can be referenced by more than one name (eg due to weak links)
- // then __init__ will still be called for each distinct import, and it's then
- // up to the particular module to make sure it's __init__ code only runs once.
- mp_module_register(module_name, module_obj);
}
+ #endif
+
+ return elem->value;
}
-#endif
void mp_module_generic_attr(qstr attr, mp_obj_t *dest, const uint16_t *keys, mp_obj_t *values) {
for (size_t i = 0; keys[i] != MP_QSTRnull; ++i) {