mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[python] Fixed MicroPython emscripten bug.
Micropython did not work because of two problems: - the stack in ascending order on emscripten - if optimized, some variables may be stored in local JavaScript variables, which breaks garbage collection. Change-Id: Ib454e0c4d995e9f5f85370eea758526119b35773
This commit is contained in:
@@ -67,7 +67,6 @@ py_objs = $(addprefix python/src/py/,\
|
||||
runtime_utils.o \
|
||||
scheduler.o \
|
||||
nativeglue.o \
|
||||
stackctrl.o \
|
||||
argcheck.o \
|
||||
warning.o \
|
||||
map.o \
|
||||
@@ -179,8 +178,21 @@ port_objs += $(addprefix python/port/,\
|
||||
modkandinsky.o \
|
||||
modkandinsky_impl.o \
|
||||
mphalport.o \
|
||||
stackctrl.o \
|
||||
)
|
||||
|
||||
# Reduce optimization for the emscripten platform.
|
||||
# With optimization, register and stack variables might be held in a JavaScript
|
||||
# local variable, which breaks garbage collection. Indeed, these JavaScript
|
||||
# variables cannot be marked as root during garbage collection, which means that
|
||||
# the heap objects they depend on will likely be destroyed. When the Python
|
||||
# computing resumes, if necessary heap objects have been destroyed, the Python
|
||||
# program crashes.
|
||||
|
||||
ifeq ($(PLATFORM),emscripten)
|
||||
$(py_objs): SFLAGS := $(subst -Os,-O0,$(SFLAGS))
|
||||
endif
|
||||
|
||||
# QSTR generation
|
||||
|
||||
python/port/genhdr/qstrdefs.generated.h: python/port/genhdr/qstrdefs.in.h
|
||||
|
||||
@@ -137,7 +137,9 @@ void MicroPython::registerScriptProvider(ScriptProvider * s) {
|
||||
}
|
||||
|
||||
void gc_collect(void) {
|
||||
assert(MP_STATE_THREAD(stack_top) != NULL);
|
||||
void * python_stack_top = MP_STATE_THREAD(stack_top);
|
||||
assert(python_stack_top != NULL);
|
||||
|
||||
gc_collect_start();
|
||||
|
||||
/* get the registers.
|
||||
@@ -146,18 +148,19 @@ void gc_collect(void) {
|
||||
jmp_buf regs;
|
||||
setjmp(regs);
|
||||
|
||||
void **regs_ptr = (void**)(void*)®s;
|
||||
void **regs_ptr = (void**)®s;
|
||||
|
||||
/* On the device, the stack is stored in reverse order, but it might not be
|
||||
* the case on a computer. We thus have to take the absolute value of the
|
||||
* addresses difference. */
|
||||
size_t stackLength;
|
||||
if ((uintptr_t)MP_STATE_THREAD(stack_top) > (uintptr_t)(®s)) {
|
||||
stackLength = (((uintptr_t)(MP_STATE_THREAD(stack_top)) - (uintptr_t)(®s)) / sizeof(uintptr_t));
|
||||
if ((uintptr_t)python_stack_top > (uintptr_t)®s) {
|
||||
stackLength = ((uintptr_t)python_stack_top - (uintptr_t)®s) / sizeof(uintptr_t);
|
||||
gc_collect_root(regs_ptr, stackLength);
|
||||
} else {
|
||||
stackLength = (((uintptr_t)(®s) - (uintptr_t)(MP_STATE_THREAD(stack_top))) / sizeof(uintptr_t));
|
||||
stackLength = ((uintptr_t)(®s) - (uintptr_t)python_stack_top) / sizeof(uintptr_t);
|
||||
gc_collect_root((void **)python_stack_top, stackLength);
|
||||
}
|
||||
gc_collect_root(regs_ptr, stackLength);
|
||||
|
||||
gc_collect_end();
|
||||
}
|
||||
|
||||
70
python/port/stackctrl.c
Normal file
70
python/port/stackctrl.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpstate.h"
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stackctrl.h"
|
||||
|
||||
void mp_stack_ctrl_init(void) {
|
||||
volatile int stack_dummy;
|
||||
MP_STATE_THREAD(stack_top) = (char*)&stack_dummy;
|
||||
}
|
||||
|
||||
void mp_stack_set_top(void *top) {
|
||||
MP_STATE_THREAD(stack_top) = top;
|
||||
}
|
||||
|
||||
mp_uint_t mp_stack_usage(void) {
|
||||
/* Micropython's stackctrl.c assumes that the stack is in descending order,
|
||||
* which is not always the case for us. */
|
||||
volatile int stack_dummy;
|
||||
if (MP_STATE_THREAD(stack_top) > (char*)&stack_dummy) {
|
||||
return MP_STATE_THREAD(stack_top) - (char*)&stack_dummy;
|
||||
} else {
|
||||
return (char*)&stack_dummy - MP_STATE_THREAD(stack_top);
|
||||
}
|
||||
}
|
||||
|
||||
#if MICROPY_STACK_CHECK
|
||||
|
||||
void mp_stack_set_limit(mp_uint_t limit) {
|
||||
MP_STATE_THREAD(stack_limit) = limit;
|
||||
}
|
||||
|
||||
void mp_exc_recursion_depth(void) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
|
||||
}
|
||||
|
||||
void mp_stack_check(void) {
|
||||
if (mp_stack_usage() >= MP_STATE_THREAD(stack_limit)) {
|
||||
mp_exc_recursion_depth();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MICROPY_STACK_CHECK
|
||||
Reference in New Issue
Block a user