Skip to content

Commit b5d1583

Browse files
committed
bricks/_common/micropython: Share mpy execution.
bricks/_common/micropython: Share mpy execution. - Replaces `do_execute_raw_code` (which came from MicroPython but was changed upstream) with `do_execute_proto_fun` so we don't fall too far behind. - Create shared implementation that main and imported modules can both use to deduplicate code.
1 parent 3a159a5 commit b5d1583

File tree

1 file changed

+59
-62
lines changed

1 file changed

+59
-62
lines changed

bricks/_common/micropython.c

Lines changed: 59 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -144,36 +144,6 @@ static void run_repl(void) {
144144
}
145145
#endif // PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL
146146

147-
// From micropython/py/builtinimport.c, but copied because it is static.
148-
static void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_t *rc, const mp_module_context_t *mc) {
149-
150-
// execute the module in its context
151-
mp_obj_dict_t *mod_globals = context->module.globals;
152-
153-
// save context
154-
mp_obj_dict_t *volatile old_globals = mp_globals_get();
155-
mp_obj_dict_t *volatile old_locals = mp_locals_get();
156-
157-
// set new context
158-
mp_globals_set(mod_globals);
159-
mp_locals_set(mod_globals);
160-
161-
nlr_buf_t nlr;
162-
if (nlr_push(&nlr) == 0) {
163-
mp_obj_t module_fun = mp_make_function_from_proto_fun(rc, mc, NULL);
164-
mp_call_function_0(module_fun);
165-
166-
// finish nlr block, restore context
167-
nlr_pop();
168-
mp_globals_set(old_globals);
169-
mp_locals_set(old_locals);
170-
} else {
171-
// exception; restore context and re-raise same exception
172-
mp_globals_set(old_globals);
173-
mp_locals_set(old_locals);
174-
nlr_jump(nlr.ret_val);
175-
}
176-
}
177147

178148
/** mpy info and data for one script or module. */
179149
typedef struct {
@@ -222,6 +192,44 @@ static mpy_info_t *mpy_data_find(qstr name) {
222192
return NULL;
223193
}
224194

195+
// From micropython/py/builtinimport.c, but copied because it is static.
196+
static void do_execute_proto_fun(const mp_module_context_t *context, mp_proto_fun_t proto_fun) {
197+
198+
// execute the module in its context
199+
mp_obj_dict_t *mod_globals = context->module.globals;
200+
201+
// save context
202+
nlr_jump_callback_node_globals_locals_t ctx;
203+
ctx.globals = mp_globals_get();
204+
ctx.locals = mp_locals_get();
205+
206+
// set new context
207+
mp_globals_set(mod_globals);
208+
mp_locals_set(mod_globals);
209+
210+
// set exception handler to restore context if an exception is raised
211+
nlr_push_jump_callback(&ctx.callback, mp_globals_locals_set_from_nlr_jump_callback);
212+
213+
// make and execute the function
214+
mp_obj_t module_fun = mp_make_function_from_proto_fun(proto_fun, context, NULL);
215+
mp_call_function_0(module_fun);
216+
217+
// deregister exception handler and restore context
218+
nlr_pop_jump_callback(true);
219+
}
220+
221+
static void execute_rom_mpy_in_context(mp_module_context_t *module_context, mpy_info_t *mpy_info) {
222+
// Prepare to execute in its own context.
223+
mp_compiled_module_t compiled_module;
224+
compiled_module.context = module_context;
225+
226+
// Execute the MPY file in the new module context.
227+
mp_reader_t reader;
228+
mp_reader_new_mem(&reader, mpy_data_get_buf(mpy_info), pbio_get_uint32_le(mpy_info->mpy_size), MP_READER_IS_ROM);
229+
mp_raw_code_load(&reader, &compiled_module);
230+
do_execute_proto_fun(compiled_module.context, compiled_module.rc);
231+
}
232+
225233
/**
226234
* Runs the __main__ module from user RAM.
227235
*/
@@ -234,22 +242,15 @@ static void run_user_program(void) {
234242
if (nlr_push(&nlr) == 0) {
235243
nlr_set_abort(&nlr);
236244

237-
// Main program is in the first mpy file.
238-
mpy_info_t *info = mpy_first;
239-
240-
// This is similar to __import__ except we don't push/pop globals
241-
mp_reader_t reader;
242-
mp_reader_new_mem(&reader, mpy_data_get_buf(info), pbio_get_uint32_le(info->mpy_size), MP_READER_IS_ROM);
243-
mp_module_context_t *context = m_new_obj(mp_module_context_t);
244-
context->module.globals = mp_globals_get();
245-
mp_compiled_module_t compiled_module;
246-
compiled_module.context = context;
247-
mp_raw_code_load(&reader, &compiled_module);
248-
mp_obj_t module_fun = mp_make_function_from_proto_fun(compiled_module.rc, context, NULL);
249-
250245
// Run the script while letting CTRL-C interrupt it.
251246
mp_hal_set_interrupt_char(CHAR_CTRL_C);
252-
mp_call_function_0(module_fun);
247+
248+
// Main program runs in __main__ module which is already initialized.
249+
mp_module_context_t main_context = {
250+
.module = mp_module___main__
251+
};
252+
execute_rom_mpy_in_context(&main_context, mpy_first);
253+
253254
mp_hal_set_interrupt_char(-1);
254255

255256
// Handle any pending exceptions (and any callbacks)
@@ -438,20 +439,14 @@ mp_obj_t pb_builtin_import(size_t n_args, const mp_obj_t *args) {
438439

439440
// If a downloaded module was found but not yet loaded, load it.
440441
if (info) {
441-
// Parse the static script data.
442-
mp_reader_t reader;
443-
mp_reader_new_mem(&reader, mpy_data_get_buf(info), pbio_get_uint32_le(info->mpy_size), MP_READER_IS_ROM);
444-
445-
// Create new module and execute in its own context.
446-
mp_obj_t module_obj = mp_obj_new_module(module_name_qstr);
447-
mp_module_context_t *context = MP_OBJ_TO_PTR(module_obj);
448-
mp_compiled_module_t compiled_module;
449-
compiled_module.context = context;
450-
mp_raw_code_load(&reader, &compiled_module);
451-
do_execute_raw_code(context, compiled_module.rc, compiled_module.context);
442+
// Create new module.
443+
mp_module_context_t *module_context = mp_obj_new_module(module_name_qstr);
444+
445+
// Execute the module in that context.
446+
execute_rom_mpy_in_context(module_context, info);
452447

453448
// Return the newly imported module.
454-
return module_obj;
449+
return MP_OBJ_FROM_PTR(module_context);
455450
}
456451

457452
// Allow importing of frozen modules if any were included in the firmware.
@@ -462,13 +457,15 @@ mp_obj_t pb_builtin_import(size_t n_args, const mp_obj_t *args) {
462457
char module_path[(1 << (8 * MICROPY_QSTR_BYTES_IN_LEN)) + sizeof(ext)] = { 0 };
463458
strcpy(module_path, mp_obj_str_get_str(args[0]));
464459
strcpy(module_path + qstr_len(module_name_qstr), ext);
465-
if (mp_find_frozen_module(module_path, &frozen_type, &modref) == MP_IMPORT_STAT_FILE) {
466-
// Create new module and execute in its own context, then return it.
467-
mp_obj_t module_obj = mp_obj_new_module(module_name_qstr);
468-
mp_module_context_t *context = MP_OBJ_TO_PTR(module_obj);
460+
if (mp_find_frozen_module(module_path, &frozen_type, &modref) == MP_IMPORT_STAT_FILE && frozen_type == MP_FROZEN_MPY) {
461+
// Create new module to be returned.
462+
mp_module_context_t *module_context = mp_obj_new_module(module_name_qstr);
463+
mp_obj_t module_obj = MP_OBJ_FROM_PTR(module_context);
464+
465+
// Execute frozen code in the new module context.
469466
const mp_frozen_module_t *frozen = modref;
470-
context->constants = frozen->constants;
471-
do_execute_raw_code(context, frozen->proto_fun, context);
467+
module_context->constants = frozen->constants;
468+
do_execute_proto_fun(module_context, frozen->proto_fun);
472469
return module_obj;
473470
}
474471
#endif

0 commit comments

Comments
 (0)