diff options
| author | Scott Shawcroft <scott@tannewt.org> | 2019-04-16 10:32:38 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-16 10:32:38 -0700 |
| commit | f58446e937ede4735a7ecb0852f2d2739f147cdd (patch) | |
| tree | 72185232547d424dfe0b61fb7f98ce11378d1e6d /py | |
| parent | 2d303213ed4ee058c0fc4c541dd7a7181f59d50f (diff) | |
| parent | 7822d013cd6d379c777f95c73a803b749d1bebe4 (diff) | |
Merge branch 'master' into master
Diffstat (limited to 'py')
| -rw-r--r-- | py/circuitpy_defns.mk | 1 | ||||
| -rw-r--r-- | py/circuitpy_mpconfig.h | 41 | ||||
| -rw-r--r-- | py/circuitpy_mpconfig.mk | 2 | ||||
| -rwxr-xr-x | py/gc.c | 36 | ||||
| -rw-r--r-- | py/gc.h | 4 | ||||
| -rw-r--r-- | py/mpstate.h | 2 | ||||
| -rw-r--r-- | py/objtype.c | 40 | ||||
| -rw-r--r-- | py/runtime.c | 8 | ||||
| -rw-r--r-- | py/runtime.h | 1 |
9 files changed, 112 insertions, 23 deletions
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 7a369817a..342c0ab0c 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -302,6 +302,7 @@ $(filter $(SRC_PATTERNS), \ bitbangio/OneWire.c \ bitbangio/SPI.c \ bitbangio/__init__.c \ + board/__init__.c \ busio/OneWire.c \ displayio/Bitmap.c \ displayio/ColorConverter.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index e96d811ac..441dd5bad 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -88,6 +88,7 @@ #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) +#define MICROPY_PY_BUILTINS_REVERSED (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) @@ -182,7 +183,6 @@ typedef long mp_off_t; #define MICROPY_PY_ALL_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_BUILTINS_COMPLEX (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_BUILTINS_FROZENSET (CIRCUITPY_FULL_BUILD) -#define MICROPY_PY_BUILTINS_REVERSED (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_BUILTINS_STR_CENTER (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_BUILTINS_STR_PARTITION (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (CIRCUITPY_FULL_BUILD) @@ -252,8 +252,29 @@ extern const struct _mp_obj_module_t bleio_module; #if CIRCUITPY_BOARD #define BOARD_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, extern const struct _mp_obj_module_t board_module; + +#define BOARD_I2C (defined(DEFAULT_I2C_BUS_SDA) && defined(DEFAULT_I2C_BUS_SCL)) +#define BOARD_SPI (defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MISO) && defined(DEFAULT_SPI_BUS_MOSI)) +#define BOARD_UART (defined(DEFAULT_UART_BUS_RX) && defined(DEFAULT_UART_BUS_TX)) + +#if BOARD_I2C +#define BOARD_I2C_ROOT_POINTER mp_obj_t shared_i2c_bus; +#else +#define BOARD_I2C_ROOT_POINTER +#endif + +// SPI is always allocated off the heap. + +#if BOARD_UART +#define BOARD_UART_ROOT_POINTER mp_obj_t shared_uart_bus; +#else +#define BOARD_UART_ROOT_POINTER +#endif + #else #define BOARD_MODULE +#define BOARD_I2C_ROOT_POINTER +#define BOARD_UART_ROOT_POINTER #endif #if CIRCUITPY_BUSIO @@ -360,6 +381,13 @@ extern const struct _mp_obj_module_t os_module; #define OS_MODULE_ALT_NAME #endif +#if CIRCUITPY_PEW +extern const struct _mp_obj_module_t pew_module; +#define PEW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pew),(mp_obj_t)&pew_module }, +#else +#define PEW_MODULE +#endif + #if CIRCUITPY_PIXELBUF extern const struct _mp_obj_module_t pixelbuf_module; #define PIXELBUF_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pixelbuf),(mp_obj_t)&pixelbuf_module }, @@ -474,13 +502,6 @@ extern const struct _mp_obj_module_t ustack_module; #define USTACK_MODULE #endif -#if CIRCUITPY_PEW -extern const struct _mp_obj_module_t pew_module; -#define PEW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pew),(mp_obj_t)&pew_module }, -#else -#define PEW_MODULE -#endif - // These modules are not yet in shared-bindings, but we prefer the non-uxxx names. #if MICROPY_PY_UERRNO #define ERRNO_MODULE { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, @@ -546,6 +567,7 @@ extern const struct _mp_obj_module_t pew_module; PULSEIO_MODULE \ RANDOM_MODULE \ RE_MODULE \ + ROTARYIO_MODULE \ RTC_MODULE \ SAMD_MODULE \ STAGE_MODULE \ @@ -585,6 +607,8 @@ extern const struct _mp_obj_module_t pew_module; mp_obj_t gamepad_singleton; \ mp_obj_t pew_singleton; \ mp_obj_t terminal_tilegrid_tiles; \ + BOARD_I2C_ROOT_POINTER \ + BOARD_UART_ROOT_POINTER \ FLASH_ROOT_POINTERS \ NETWORK_ROOT_POINTERS \ @@ -597,6 +621,7 @@ void run_background_tasks(void); #define MICROPY_VM_HOOK_RETURN run_background_tasks(); #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 +#define CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS 1000 #define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt" #endif // __INCLUDED_MPCONFIG_CIRCUITPY_H diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 0df6fff06..8ea72f0bf 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -93,7 +93,7 @@ endif CFLAGS += -DCIRCUITPY_DISPLAYIO=$(CIRCUITPY_DISPLAYIO) ifndef CIRCUITPY_FREQUENCYIO -CIRCUITPY_FREQUENCYIO = 1 +CIRCUITPY_FREQUENCYIO = $(CIRCUITPY_FULL_BUILD) endif CFLAGS += -DCIRCUITPY_FREQUENCYIO=$(CIRCUITPY_FREQUENCYIO) @@ -176,6 +176,8 @@ void gc_init(void *start, void *end) { mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex)); #endif + MP_STATE_MEM(permanent_pointers) = NULL; + DEBUG_printf("GC layout:\n"); DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(gc_alloc_table_start), MP_STATE_MEM(gc_alloc_table_byte_len), MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB); #if MICROPY_ENABLE_FINALISER @@ -359,6 +361,10 @@ void gc_collect_start(void) { size_t root_end = offsetof(mp_state_ctx_t, vm.qstr_last_chunk); gc_collect_root(ptrs + root_start / sizeof(void*), (root_end - root_start) / sizeof(void*)); + if (MP_STATE_MEM(permanent_pointers) != NULL) { + gc_collect_root(MP_STATE_MEM(permanent_pointers), BYTES_PER_BLOCK / sizeof(void*)); + } + #if MICROPY_ENABLE_PYSTACK // Trace root pointers from the Python stack. ptrs = (void**)(void*)MP_STATE_THREAD(pystack_start); @@ -938,6 +944,36 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { } #endif // Alternative gc_realloc impl +bool gc_never_free(void *ptr) { + // Check to make sure the pointer is on the heap in the first place. + if (gc_nbytes(ptr) == 0) { + return false; + } + // Pointers are stored in a linked list where each block is BYTES_PER_BLOCK long and the first + // pointer is the next block of pointers. + void ** current_reference_block = MP_STATE_MEM(permanent_pointers); + while (current_reference_block != NULL) { + for (size_t i = 1; i < BYTES_PER_BLOCK / sizeof(void*); i++) { + if (current_reference_block[i] == NULL) { + current_reference_block[i] = ptr; + return true; + } + } + current_reference_block = current_reference_block[0]; + } + void** next_block = gc_alloc(BYTES_PER_BLOCK, false, true); + if (next_block == NULL) { + return false; + } + if (MP_STATE_MEM(permanent_pointers) == NULL) { + MP_STATE_MEM(permanent_pointers) = next_block; + } else { + current_reference_block[0] = next_block; + } + next_block[1] = ptr; + return true; +} + void gc_dump_info(void) { gc_info_t info; gc_info(&info); @@ -57,6 +57,10 @@ bool gc_has_finaliser(const void *ptr); void *gc_make_long_lived(void *old_ptr); void *gc_realloc(void *ptr, size_t n_bytes, bool allow_move); +// Prevents a pointer from ever being freed because it establishes a permanent reference to it. Use +// very sparingly because it can leak memory. +bool gc_never_free(void *ptr); + typedef struct _gc_info_t { size_t total; size_t used; diff --git a/py/mpstate.h b/py/mpstate.h index eef8696d3..a3d7e5dcc 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -103,6 +103,8 @@ typedef struct _mp_state_mem_t { // This is a global mutex used to make the GC thread-safe. mp_thread_mutex_t gc_mutex; #endif + + void** permanent_pointers; } mp_state_mem_t; // This structure hold runtime and VM information. It includes a section diff --git a/py/objtype.c b/py/objtype.c index f205c224e..88e918827 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -964,6 +964,21 @@ STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { #endif return false; } + +STATIC bool map_has_special_accessors(const mp_map_t *map) { + if (map == NULL) { + return false; + } + for (size_t i = 0; i < map->alloc; i++) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + const mp_map_elem_t *elem = &map->table[i]; + if (check_for_special_accessors(elem->key, elem->value)) { + return true; + } + } + } + return false; +} #endif STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -1158,20 +1173,6 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) o->locals_dict = make_dict_long_lived(locals_dict, 10); - #if ENABLE_SPECIAL_ACCESSORS - // Check if the class has any special accessor methods - if (!(o->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { - for (size_t i = 0; i < o->locals_dict->map.alloc; i++) { - if (MP_MAP_SLOT_IS_FILLED(&o->locals_dict->map, i)) { - const mp_map_elem_t *elem = &o->locals_dict->map.table[i]; - if (check_for_special_accessors(elem->key, elem->value)) { - o->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS; - break; - } - } - } - } - #endif const mp_obj_type_t *native_base; size_t num_native_bases = instance_count_native_bases(o, &native_base); @@ -1180,6 +1181,17 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } mp_map_t *locals_map = &o->locals_dict->map; + #if ENABLE_SPECIAL_ACCESSORS + // Check if the class has any special accessor methods + if (!(o->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS) && + (map_has_special_accessors(locals_map) || + (num_native_bases == 1 && + native_base->locals_dict != NULL && + map_has_special_accessors(&native_base->locals_dict->map)))) { + o->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS; + } + #endif + mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); if (elem != NULL) { // __new__ slot exists; check if it is a function diff --git a/py/runtime.c b/py/runtime.c index 060748f1b..1e0100337 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1590,6 +1590,14 @@ NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg) { mp_raise_msg(&mp_type_NotImplementedError, msg); } +NORETURN void mp_raise_NotImplementedError_varg(const compressed_string_t *fmt, ...) { + va_list argptr; + va_start(argptr,fmt); + mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_NotImplementedError, fmt, argptr); + va_end(argptr); + nlr_raise(exception); +} + #if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK NORETURN void mp_raise_recursion_depth(void) { mp_raise_RuntimeError(translate("maximum recursion depth exceeded")); diff --git a/py/runtime.h b/py/runtime.h index e52d3232e..2577c9dd5 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -162,6 +162,7 @@ NORETURN void mp_raise_OSError(int errno_); NORETURN void mp_raise_OSError_msg(const compressed_string_t *msg); NORETURN void mp_raise_OSError_msg_varg(const compressed_string_t *fmt, ...); NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg); +NORETURN void mp_raise_NotImplementedError_varg(const compressed_string_t *fmt, ...); NORETURN void mp_raise_recursion_depth(void); #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG |
