From 789384f0b76b0e9daab1af589e240eb810dd647d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Oct 2018 18:39:30 +1100 Subject: [PATCH] microbit: Enable loading of .mpy files. Code size is increased by about 1k bytes. Heap usage is similar to before this commit: on a test suite of large example programs, those that could run before can still run, and those that couldn't run still can't run. But all those that couldn't run before can now run if they are precompiled to a .mpy. --- inc/microbit/mpconfigport.h | 1 + source/microbit/filesystem.c | 17 +++++++++++++---- source/microbit/main.cpp | 27 ++++++++++++++++++++------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/inc/microbit/mpconfigport.h b/inc/microbit/mpconfigport.h index 22a7db70c..e2215f7d3 100644 --- a/inc/microbit/mpconfigport.h +++ b/inc/microbit/mpconfigport.h @@ -39,6 +39,7 @@ #define MICROPY_QSTR_BYTES_IN_HASH (1) // emitters +#define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB_ARMV7M (0) #define MICROPY_EMIT_INLINE_THUMB_FLOAT (0) diff --git a/source/microbit/filesystem.c b/source/microbit/filesystem.c index 480596cd0..e3618b789 100644 --- a/source/microbit/filesystem.c +++ b/source/microbit/filesystem.c @@ -456,9 +456,18 @@ mp_lexer_t *microbit_file_lexer(qstr src_name, file_descriptor_obj *fd) { return mp_lexer_new(src_name, reader); } -mp_lexer_t *mp_lexer_new_from_file(const char *filename) { +void mp_reader_new_file(mp_reader_t *reader, const char *filename) { file_descriptor_obj *fd = microbit_file_open(filename, strlen(filename), false, false); - if (fd == NULL) - return NULL; - return microbit_file_lexer(qstr_from_str(filename), fd); + if (fd == NULL) { + mp_raise_OSError(MP_ENOENT); + } + reader->data = fd; + reader->readbyte = file_read_byte; + reader->close = (void(*)(void*))microbit_file_close; +} + +mp_lexer_t *mp_lexer_new_from_file(const char *filename) { + mp_reader_t reader; + mp_reader_new_file(&reader, filename); + return mp_lexer_new(qstr_from_str(filename), reader); } diff --git a/source/microbit/main.cpp b/source/microbit/main.cpp index 83748c738..0adc97c5e 100644 --- a/source/microbit/main.cpp +++ b/source/microbit/main.cpp @@ -22,6 +22,7 @@ extern "C" { #include "py/stackctrl.h" #include "py/gc.h" #include "py/compile.h" +#include "py/persistentcode.h" #include "py/runtime.h" #include "py/mphal.h" #include "lib/mp-readline/readline.h" @@ -90,17 +91,27 @@ static void microbit_display_exception(mp_obj_t exc_in) { } } -static void do_lexer(mp_lexer_t *lex) { - if (lex == NULL) { +#define SOURCE_KIND_LEXER (0) +#define SOURCE_KIND_MPY_FILE (1) + +static void do_exec(int source_kind, const void *source) { + if (source == NULL) { printf("MemoryError: lexer could not allocate memory\n"); return; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - qstr source_name = lex->source_name; - mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); + mp_obj_t module_fun; + if (source_kind == SOURCE_KIND_LEXER) { + mp_lexer_t *lex = (mp_lexer_t*)source; + qstr source_name = lex->source_name; + mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); + module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); + } else { + mp_raw_code_t *raw_code = mp_raw_code_load_file((const char *)source); + module_fun = mp_make_function_from_raw_code(raw_code, MP_OBJ_NULL, MP_OBJ_NULL); + } mp_hal_set_interrupt_char(3); // allow ctrl-C to interrupt us mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt @@ -123,12 +134,12 @@ static void do_lexer(mp_lexer_t *lex) { static void do_strn(const char *src, size_t len) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR___main__, src, len, 0); - do_lexer(lex); + do_exec(SOURCE_KIND_LEXER, lex); } static void do_file(file_descriptor_obj *fd) { mp_lexer_t *lex = microbit_file_lexer(MP_QSTR___main__, fd); - do_lexer(lex); + do_exec(SOURCE_KIND_LEXER, lex); } typedef struct _appended_script_t { @@ -187,6 +198,8 @@ int main(void) { file_descriptor_obj *main_module; if ((main_module = microbit_file_open("main.py", 7, false, false))) { do_file(main_module); + } else if (microbit_find_file("main.mpy", strlen("main.mpy")) != FILE_NOT_FOUND) { + do_exec(SOURCE_KIND_MPY_FILE, "main.mpy"); } else if (APPENDED_SCRIPT->header[0] == 'M' && APPENDED_SCRIPT->header[1] == 'P') { // run appended script do_strn(APPENDED_SCRIPT->str, APPENDED_SCRIPT->len);