summaryrefslogtreecommitdiffstatshomepage
path: root/py/objmodule.c
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2023-05-10 13:02:09 +1000
committerDamien George <damien@micropython.org>2023-06-01 16:21:21 +1000
commit525557738cccb73d7b00d2048b9fd47e4caeeec6 (patch)
tree7bdcfc552a57d1fffe6bd207759f36bd566e1f09 /py/objmodule.c
parent42f3f66431bb3131f5ee78f3e121491e9d0fb91d (diff)
downloadmicropython-525557738cccb73d7b00d2048b9fd47e4caeeec6.tar.gz
micropython-525557738cccb73d7b00d2048b9fd47e4caeeec6.zip
py/builtinimport: Optimise sub-package loading.
This makes it so that sub-packages are resolved relative to their parent's `__path__`, rather than re-resolving each parent's filesystem path. The previous behavior was that `import foo.bar` would first re-search `sys.path` for `foo`, then use the resulting path to find `bar`. For already-loaded and u-prefixed modules, because we no longer need to build the path from level to level, we no longer unnecessarily search the filesystem. This should improve startup time. Explicitly makes the resolving process clear: - Loaded modules are returned immediately without touching the filesystem. - Exact-match of builtins are also returned immediately. - Then the filesystem search happens. - If that fails, then the weak-link handling is applied. This maintains the existing behavior: if a user writes `import time` they will get time.py if it exits, otherwise the built-in utime. Whereas `import utime` will always return the built-in. This also fixes a regression from a7fa18c203a241f670f12ab507aa8b349fcd45a1 where we search the filesystem for built-ins. It is now only possible to override u-prefixed builtins. This will remove a lot of filesystem stats at startup, as micropython-specific modules (e.g. `pyb`) will no longer attempt to look at the filesystem. Added several improvements to the comments and some minor renaming and refactoring to make it clearer how the import mechanism works. Overall code size diff is +56 bytes on STM32. 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.c32
1 files changed, 3 insertions, 29 deletions
diff --git a/py/objmodule.c b/py/objmodule.c
index 63e9fa4757..6f061a9408 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -176,35 +176,10 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table);
-// Tries to find a loaded module, otherwise attempts to load a builtin, otherwise MP_OBJ_NULL.
-mp_obj_t mp_module_get_loaded_or_builtin(qstr module_name) {
- // First try loaded modules.
- mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_loaded_modules_dict).map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
-
- if (!elem) {
- #if MICROPY_MODULE_WEAK_LINKS
- return mp_module_get_builtin(module_name);
- #else
- // Otherwise try builtin.
- elem = mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
- if (!elem) {
- return MP_OBJ_NULL;
- }
-
- #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
- #endif
- }
-
- return elem->value;
-}
-
-#if MICROPY_MODULE_WEAK_LINKS
-// Tries to find a loaded module, otherwise attempts to load a builtin, otherwise MP_OBJ_NULL.
+// 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.
mp_obj_t mp_module_get_builtin(qstr module_name) {
- // Try builtin.
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) {
return MP_OBJ_NULL;
@@ -217,7 +192,6 @@ mp_obj_t mp_module_get_builtin(qstr module_name) {
return elem->value;
}
-#endif
#if MICROPY_MODULE_BUILTIN_INIT
STATIC void mp_module_register(mp_obj_t module_name, mp_obj_t module) {