From dfe232d0003b9f381643050c06c547fc3093e9e1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 17 Aug 2022 16:21:03 +1000 Subject: [PATCH] py/builtinimport: Remove weak links. In order to keep "import umodule" working, the existing mechanism is replaced with a simple fallback to drop the "u". This makes importing of built-ins no longer touch the filesystem, which makes a typical built-in import take ~0.15ms rather than 3-5ms. (Weak links were added in c14a81662c1df812c0c6b4299f97966302f16477) This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- docs/develop/porting.rst | 3 --- ports/cc3200/mpconfigport.h | 1 - ports/nrf/mpconfigport.h | 1 - ports/samd/mpconfigport.h | 1 - ports/windows/mpconfigport.h | 1 - ports/zephyr/mpconfigport.h | 1 - py/builtinimport.c | 50 ++++-------------------------------- py/mpconfig.h | 5 ---- py/objmodule.c | 1 - 9 files changed, 5 insertions(+), 59 deletions(-) diff --git a/docs/develop/porting.rst b/docs/develop/porting.rst index fab8a751b8..63919b97a6 100644 --- a/docs/develop/porting.rst +++ b/docs/develop/porting.rst @@ -151,9 +151,6 @@ The following is an example of an ``mpconfigport.h`` file: #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) - // Enable u-modules to be imported with their standard name, like sys. - #define MICROPY_MODULE_WEAK_LINKS (1) - // Fine control over Python builtins, classes, modules, etc. #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_SET (0) diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index 6bdaa9b553..aa78005d68 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -71,7 +71,6 @@ #define MICROPY_FATFS_SYNC_T SemaphoreHandle_t #define MICROPY_STREAMS_NON_BLOCK (1) -#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_VFS (1) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 23f7e560dc..3d482f4fe1 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -137,7 +137,6 @@ #define MICROPY_PY_UOS (0) #define MICROPY_STREAMS_NON_BLOCK (1) -#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #if MICROPY_HW_USB_CDC_1200BPS_TOUCH diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 7392b03059..a0a58a2fd7 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -59,7 +59,6 @@ #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_STATIC_NODES (1) -#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_HW_ENABLE_USBDEV (1) #define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1) diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index fd3a76408c..5e56923d93 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -72,7 +72,6 @@ #endif #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_OPT_COMPUTED_GOTO (0) -#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_MODULE_OVERRIDE_MAIN_IMPORT (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #ifndef MICROPY_ENABLE_SCHEDULER diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index d3ef4375c7..30ccccb627 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -69,7 +69,6 @@ #define MICROPY_PY_MACHINE_SPI_MSB (SPI_TRANSFER_MSB) #define MICROPY_PY_MACHINE_SPI_LSB (SPI_TRANSFER_LSB) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new -#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_PY_STRUCT (0) #ifdef CONFIG_NETWORKING // If we have networking, we likely want errno comfort diff --git a/py/builtinimport.c b/py/builtinimport.c index 8827be6123..299877de63 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -45,15 +45,6 @@ #define DEBUG_printf(...) (void)0 #endif -#if MICROPY_MODULE_WEAK_LINKS -STATIC qstr make_weak_link_name(vstr_t *buffer, qstr name) { - vstr_reset(buffer); - vstr_add_char(buffer, 'u'); - vstr_add_str(buffer, qstr_str(name)); - return qstr_from_strn(buffer->buf, buffer->len); -} -#endif - #if MICROPY_ENABLE_EXTERNAL_IMPORT // Must be a string of one byte. @@ -391,13 +382,8 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, if (outer_module_obj == MP_OBJ_NULL) { DEBUG_printf("Searching for top-level module\n"); - // An exact match of a built-in will always bypass the filesystem. - // Note that CPython-compatible built-ins are named e.g. utime, so this - // means that an exact match is only for `import utime`, so `import - // time` will search the filesystem and failing that hit the weak - // link handling below. Whereas micropython-specific built-ins like - // `micropython`, `pyb`, `network`, etc will match exactly and cannot - // be overridden by the filesystem. + // An import of a non-extensible built-in will always bypass the + // filesystem. e.g. `import micropython` or `import pyb`. module_obj = mp_module_get_builtin(level_mod_name); if (module_obj != MP_OBJ_NULL) { return module_obj; @@ -417,20 +403,9 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, // relative to all the locations in sys.path. stat = stat_top_level(level_mod_name, &path); - #if MICROPY_MODULE_WEAK_LINKS - if (stat == MP_IMPORT_STAT_NO_EXIST) { - // No match on the filesystem. (And not a built-in either). - // If "foo" was requested, then try "ufoo" as a built-in. This - // allows `import time` to use built-in `utime`, unless `time` - // exists on the filesystem. This feature was formerly known - // as "weak links". - qstr umodule_name = make_weak_link_name(&path, level_mod_name); - module_obj = mp_module_get_builtin(umodule_name); - if (module_obj != MP_OBJ_NULL) { - return module_obj; - } - } - #endif + // TODO: If stat failed, now try extensible built-in modules. + + // TODO: If importing `ufoo`, try `foo`. } else { DEBUG_printf("Searching for sub-module\n"); @@ -667,21 +642,6 @@ mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { return module_obj; } - #if MICROPY_MODULE_WEAK_LINKS - // Check if the u-prefixed name is a built-in. - VSTR_FIXED(umodule_path, MICROPY_ALLOC_PATH_MAX); - qstr umodule_name_qstr = make_weak_link_name(&umodule_path, module_name_qstr); - module_obj = mp_module_get_builtin(umodule_name_qstr); - if (module_obj != MP_OBJ_NULL) { - return module_obj; - } - #elif MICROPY_PY_SYS - // Special handling to make `import sys` work even if weak links aren't enabled. - if (module_name_qstr == MP_QSTR_sys) { - return MP_OBJ_FROM_PTR(&mp_module_sys); - } - #endif - // Couldn't find the module, so fail #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("module not found")); diff --git a/py/mpconfig.h b/py/mpconfig.h index afef744ab5..9f4d88ec09 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -871,11 +871,6 @@ typedef double mp_float_t; #define MICROPY_MODULE_GETATTR (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif -// Whether module weak links are supported -#ifndef MICROPY_MODULE_WEAK_LINKS -#define MICROPY_MODULE_WEAK_LINKS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) -#endif - // Whether to enable importing foo.py with __name__ set to '__main__' // Used by the unix port for the -m flag. #ifndef MICROPY_MODULE_OVERRIDE_MAIN_IMPORT diff --git a/py/objmodule.c b/py/objmodule.c index 7326fbe2d1..e63fb18a1e 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -169,7 +169,6 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = { // builtin modules declared with MP_REGISTER_MODULE() MICROPY_REGISTERED_MODULES }; - MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table); // Attempts to find (and initialise) a builtin, otherwise returns