diff options
author | Damien George <damien@micropython.org> | 2021-06-24 10:04:15 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2021-06-25 11:29:39 +1000 |
commit | c13853f4dab9c65ee6d1af99b25f999b16ef2827 (patch) | |
tree | 7d7dd91c9da886439b97779c43b1b6a1f3e43c70 | |
parent | cfd08448a1cba0040ad3c62bce02b5f8bd76dd1d (diff) | |
download | micropython-c13853f4dab9c65ee6d1af99b25f999b16ef2827.tar.gz micropython-c13853f4dab9c65ee6d1af99b25f999b16ef2827.zip |
javascript: Rework Makefile and GC so it works with latest Emscripten.
The GC now works correctly using asyncify and the functions
emscripten_scan_stack() and emscripten_scan_registers(). Stack/call depth
is monitored via the use of the pystack option.
Fixes issue #6738.
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r-- | ports/javascript/JSBackend.patch | 10 | ||||
-rw-r--r-- | ports/javascript/Makefile | 26 | ||||
-rw-r--r-- | ports/javascript/README.md | 22 | ||||
-rw-r--r-- | ports/javascript/main.c | 21 |
4 files changed, 23 insertions, 56 deletions
diff --git a/ports/javascript/JSBackend.patch b/ports/javascript/JSBackend.patch deleted file mode 100644 index a5fd41a3fb..0000000000 --- a/ports/javascript/JSBackend.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- JSBackend.cpp 2018-01-10 16:35:07.331418145 +1100 -+++ JSBackend_mp_js.cpp 2018-01-10 16:40:04.804633134 +1100 -@@ -4280,6 +4280,7 @@ - - void JSWriter::calculateNativizedVars(const Function *F) { - NativizedVars.clear(); -+ return; - - for (Function::const_iterator I = F->begin(), BE = F->end(); I != BE; ++I) { - auto BI = &*I; diff --git a/ports/javascript/Makefile b/ports/javascript/Makefile index 9723675546..171f53b952 100644 --- a/ports/javascript/Makefile +++ b/ports/javascript/Makefile @@ -6,24 +6,16 @@ QSTR_DEFS = qstrdefsport.h include $(TOP)/py/py.mk -CC = emcc -g4 -LD = emcc -g4 +CC = emcc +LD = emcc INC += -I. INC += -I$(TOP) INC += -I$(BUILD) -CPP = clang -E - -ifdef EMSCRIPTEN - CPP += -isystem $(EMSCRIPTEN)/system/include/libc -cxx-isystem $(EMSCRIPTEN)/system/include/libcxx -endif - -CFLAGS = -m32 -Wall -Werror -Wdouble-promotion -Wfloat-conversion $(INC) -std=c99 $(COPT) -LDFLAGS = -m32 -Wl,-Map=$@.map,--cref -Wl,--gc-sections - -CFLAGS += -O0 -DNDEBUG -CFLAGS += -fdata-sections -ffunction-sections +CFLAGS += -std=c99 -Wall -Werror -Wdouble-promotion -Wfloat-conversion +CFLAGS += -O3 -DNDEBUG +CFLAGS += $(INC) ifneq ($(FROZEN_MPY_DIR),) # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and @@ -46,12 +38,12 @@ SRC_C = \ SRC_QSTR += $(SRC_C) -OBJ = -OBJ = $(PY_O) +OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -JSFLAGS = -O0 -s EXPORTED_FUNCTIONS="['_mp_js_init', '_mp_js_init_repl', '_mp_js_do_str', '_mp_js_process_char', '_mp_hal_get_interrupt_char', '_mp_sched_keyboard_interrupt']" -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" -s "BINARYEN_TRAP_MODE='clamp'" --memory-init-file 0 --js-library library.js +JSFLAGS += -s ASYNCIFY +JSFLAGS += -s EXPORTED_FUNCTIONS="['_mp_js_init', '_mp_js_init_repl', '_mp_js_do_str', '_mp_js_process_char', '_mp_hal_get_interrupt_char', '_mp_sched_keyboard_interrupt']" -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" -s --memory-init-file 0 --js-library library.js all: $(BUILD)/micropython.js @@ -65,6 +57,6 @@ min: $(BUILD)/micropython.js test: $(BUILD)/micropython.js $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py + cd $(TOP)/tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py -j1 include $(TOP)/py/mkrules.mk diff --git a/ports/javascript/README.md b/ports/javascript/README.md index ac268bb3bf..39808943b1 100644 --- a/ports/javascript/README.md +++ b/ports/javascript/README.md @@ -7,17 +7,7 @@ Dependencies ------------ Building micropython.js bears the same requirements as the standard MicroPython -ports with the addition of Emscripten (and uglify-js for the minified file). - -A standard installation of Emscripten should provide functional code, however -if memory errors are encountered it may be worthwhile to modify the tool. -`emscripten-fastcomp/lib/Target/JSBackend.cpp` may require the minor fix -found in JSBackend.patch. This patch attempts to address situations where -C code running through Emscripten is denied access to Javascript variables -leading to false-positives in the MicroPython garbage collector as variables -with pointers exclusively in Javascript will be erased prematurely. -Refer to Emscripten documentation for instructions on building Emscripten -from source. +ports with the addition of Emscripten (and uglify-js for the minified file). Build instructions ------------------ @@ -39,15 +29,15 @@ Access the repl with: Stack size may be modified using: - $ node build/micropython.js -X stack=64K + $ node build/micropython.js -X stack=64K Where stack size may be represented in Bytes, KiB or MiB. MicroPython scripts may be executed using: - $ node build/micropython.js hello.py + $ node build/micropython.js hello.py -Alternatively micropython.js may by accessed by other javascript programs in node +Alternatively micropython.js may by accessed by other javascript programs in node using the require command and the general API outlined below. For example: ```javascript @@ -85,7 +75,7 @@ demonstrates basic functionality: ``` MicroPython code execution will suspend the browser so be sure to atomize usage -within this environment. Unfortunately interrupts have not been implemented for the +within this environment. Unfortunately interrupts have not been implemented for the browser. Testing @@ -124,5 +114,5 @@ the repl. mp_js_process_char(char) ``` -Input character into MicroPython repl. `char` must be of type `number`. This +Input character into MicroPython repl. `char` must be of type `number`. This will execute MicroPython code when necessary. diff --git a/ports/javascript/main.c b/ports/javascript/main.c index 5d295f9295..c56f1a2cba 100644 --- a/ports/javascript/main.c +++ b/ports/javascript/main.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George and 2017, 2018 Rami Ali + * Copyright (c) 2013-2021 Damien P. George and 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,6 +36,7 @@ #include "py/mperrno.h" #include "lib/utils/pyexec.h" +#include "emscripten.h" #include "library.h" #if MICROPY_ENABLE_COMPILER @@ -70,8 +71,6 @@ int do_str(const char *src, mp_parse_input_kind_t input_kind) { } #endif -static char *stack_top; - int mp_js_do_str(const char *code) { return do_str(code, MP_PARSE_FILE_INPUT); } @@ -81,9 +80,6 @@ int mp_js_process_char(int c) { } void mp_js_init(int heap_size) { - int stack_dummy; - stack_top = (char *)&stack_dummy; - #if MICROPY_ENABLE_GC char *heap = (char *)malloc(heap_size * sizeof(char)); gc_init(heap, heap + heap_size); @@ -105,15 +101,14 @@ void mp_js_init_repl() { pyexec_event_repl_init(); } +STATIC void gc_scan_func(void *begin, void *end) { + gc_collect_root((void **)begin, (void **)end - (void **)begin + 1); +} + void gc_collect(void) { - // WARNING: This gc_collect implementation doesn't try to get root - // pointers from CPU registers, and thus may function incorrectly. - jmp_buf dummy; - if (setjmp(dummy) == 0) { - longjmp(dummy, 1); - } gc_collect_start(); - gc_collect_root((void *)stack_top, ((mp_uint_t)(void *)(&dummy + 1) - (mp_uint_t)stack_top) / sizeof(mp_uint_t)); + emscripten_scan_stack(gc_scan_func); + emscripten_scan_registers(gc_scan_func); gc_collect_end(); } |