From bbcea3f62b08f3166b87a86e9c2c5ac9cc61b578 Mon Sep 17 00:00:00 2001 From: stijn Date: Mon, 16 Jun 2014 10:44:29 +0200 Subject: [PATCH 01/30] gc: More verbose debugging Add more DEBUG_printf statements to trace gc behaviour --- py/gc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/py/gc.c b/py/gc.c index 30bae5054..2f60ce50d 100644 --- a/py/gc.c +++ b/py/gc.c @@ -113,7 +113,6 @@ STATIC machine_uint_t gc_lock_depth; void gc_init(void *start, void *end) { // align end pointer on block boundary end = (void*)((machine_uint_t)end & (~(BYTES_PER_BLOCK - 1))); - DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, end - start); // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): // T = A + F + P @@ -121,6 +120,7 @@ void gc_init(void *start, void *end) { // P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) machine_uint_t total_byte_len = (byte*)end - (byte*)start; + DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, total_byte_len); #if MICROPY_ENABLE_FINALISER gc_alloc_table_byte_len = total_byte_len * BITS_PER_BYTE / (BITS_PER_BYTE + BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); #else @@ -268,6 +268,7 @@ STATIC void gc_sweep(void) { case AT_TAIL: if (free_tail) { + DEBUG_printf("gc_sweep(%p)\n",PTR_FROM_BLOCK(block)); ATB_ANY_TO_FREE(block); } break; @@ -347,7 +348,6 @@ void gc_info(gc_info_t *info) { void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser) { machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK; - DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks); // check if GC is locked if (gc_lock_depth > 0) { @@ -401,6 +401,7 @@ found: // get pointer to first block void *ret_ptr = (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK); + DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks ptr %p)\n", n_bytes, n_blocks, ret_ptr); // zero out the additional bytes of the newly allocated blocks // This is needed because the blocks may have previously held pointers @@ -439,6 +440,7 @@ void gc_free(void *ptr_in) { } machine_uint_t ptr = (machine_uint_t)ptr_in; + DEBUG_printf("gc_free(%p)\n", ptr); if (VERIFY_PTR(ptr)) { machine_uint_t block = BLOCK_FROM_PTR(ptr); @@ -590,7 +592,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) { return NULL; } - DEBUG_printf("gc_realloc: allocating new block\n"); + DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out); memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK); gc_free(ptr_in); return ptr_out; From def10cecd18bc41418a41d8130aab31c84874361 Mon Sep 17 00:00:00 2001 From: stijn Date: Wed, 18 Jun 2014 10:20:41 +0200 Subject: [PATCH 02/30] gc: Keep debug statements at beginning of scope where possible --- py/gc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/py/gc.c b/py/gc.c index 2f60ce50d..d78b70a9c 100644 --- a/py/gc.c +++ b/py/gc.c @@ -40,7 +40,7 @@ #if MICROPY_ENABLE_GC -#if 0 // print debugging info +#if 1 // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #else // don't print debugging info @@ -113,6 +113,7 @@ STATIC machine_uint_t gc_lock_depth; void gc_init(void *start, void *end) { // align end pointer on block boundary end = (void*)((machine_uint_t)end & (~(BYTES_PER_BLOCK - 1))); + DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start); // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): // T = A + F + P @@ -120,7 +121,6 @@ void gc_init(void *start, void *end) { // P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) machine_uint_t total_byte_len = (byte*)end - (byte*)start; - DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, total_byte_len); #if MICROPY_ENABLE_FINALISER gc_alloc_table_byte_len = total_byte_len * BITS_PER_BYTE / (BITS_PER_BYTE + BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); #else @@ -348,6 +348,7 @@ void gc_info(gc_info_t *info) { void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser) { machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK; + DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks); // check if GC is locked if (gc_lock_depth > 0) { @@ -401,7 +402,7 @@ found: // get pointer to first block void *ret_ptr = (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK); - DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks ptr %p)\n", n_bytes, n_blocks, ret_ptr); + DEBUG_printf("gc_alloc(%p)\n", ret_ptr); // zero out the additional bytes of the newly allocated blocks // This is needed because the blocks may have previously held pointers From 9acb5e4cf00c752f16a9606572ad440e2f545dbf Mon Sep 17 00:00:00 2001 From: stijn Date: Wed, 18 Jun 2014 12:29:03 +0200 Subject: [PATCH 03/30] gc: Turn off debugging info again --- py/gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/gc.c b/py/gc.c index d78b70a9c..90b7b89e5 100644 --- a/py/gc.c +++ b/py/gc.c @@ -40,7 +40,7 @@ #if MICROPY_ENABLE_GC -#if 1 // print debugging info +#if 0 // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #else // don't print debugging info From afc67c6dc5c66f671efd6d1ebb2ed725ced8cb3e Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Sat, 14 Jun 2014 17:41:13 +0200 Subject: [PATCH 04/30] bare-arm, stmhal: Fix --nostdlib to -nostdlib -nostdlib is the correct option, gcc recognizes the double dash version when in link-only mode, but not when compiling. Signed-off-by: Sven Wegener --- bare-arm/Makefile | 2 +- stmhal/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bare-arm/Makefile b/bare-arm/Makefile index 745945deb..82312cd85 100644 --- a/bare-arm/Makefile +++ b/bare-arm/Makefile @@ -22,7 +22,7 @@ else CFLAGS += -Os -DNDEBUG endif -LDFLAGS = --nostdlib -T stm32f405.ld +LDFLAGS = -nostdlib -T stm32f405.ld LIBS = SRC_C = \ diff --git a/stmhal/Makefile b/stmhal/Makefile index e27dd7b6c..5a801ced2 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -53,7 +53,7 @@ else COPT += -Os -DNDEBUG endif -LDFLAGS = --nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref +LDFLAGS = -nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref LIBS = # uncomment this if you want libgcc From c3cabf4e336c104542bb248730094747b13977b1 Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Sat, 14 Jun 2014 17:41:13 +0200 Subject: [PATCH 05/30] bare-arm, stmhal, teensy: Duplicate -nostdlib to CFLAGS As we are building with -nostdlib gcc features like the stack protector will fail linking, because the failure handlers are in gcc's internal libs. Such features are implicitly disabled during compilation when -nostdlib is used in CFLAGS too. Signed-off-by: Sven Wegener --- bare-arm/Makefile | 2 +- stmhal/Makefile | 2 +- teensy/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bare-arm/Makefile b/bare-arm/Makefile index 82312cd85..ed8c00482 100644 --- a/bare-arm/Makefile +++ b/bare-arm/Makefile @@ -13,7 +13,7 @@ INC += -I$(PY_SRC) INC += -I$(BUILD) CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion -CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT) +CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) #Debugging/Optimization ifeq ($(DEBUG), 1) diff --git a/stmhal/Makefile b/stmhal/Makefile index 5a801ced2..3cc98d7be 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -41,7 +41,7 @@ INC += -I$(FATFS_DIR)/src INC += -I$(CC3K_DIR) CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion -CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT) +CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) CFLAGS += -Iboards/$(BOARD) diff --git a/teensy/Makefile b/teensy/Makefile index 00f351472..8244d52d3 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -23,7 +23,7 @@ INC += -I$(PY_SRC) INC += -I$(BUILD) INC += -I$(CORE_PATH) -CFLAGS = $(INC) -Wall -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) +CFLAGS = $(INC) -Wall -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) LDFLAGS = -nostdlib -T mk20dx256.ld LIBS = -L $(COMPILER_PATH)/../lib/gcc/arm-none-eabi/4.7.2/thumb2 -lgcc From bf3366a48bca2808ae04ac49e5f5737481d28b57 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 19 Jun 2014 18:47:38 +0200 Subject: [PATCH 06/30] =?UTF-8?q?Add=20missing=20=E2=80=9Cassert.h?= =?UTF-8?q?=E2=80=9D=20file=20header=20inclusion=20from=20=E2=80=9Cnlr.h?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- py/nlr.h | 1 + 1 file changed, 1 insertion(+) diff --git a/py/nlr.h b/py/nlr.h index 43a0c4f6a..83ab25134 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -29,6 +29,7 @@ #include #include +#include typedef struct _nlr_buf_t nlr_buf_t; struct _nlr_buf_t { From f6932d650620d3753b5a18df5131227276260f74 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 19 Jun 2014 18:54:34 +0200 Subject: [PATCH 07/30] Prefix ARRAY_SIZE with micropython prefix MP_ --- py/builtin.c | 2 +- py/builtintables.c | 8 ++++---- py/compile.c | 4 ++-- py/emitinlinethumb.c | 4 ++-- py/lexer.c | 6 +++--- py/misc.h | 2 +- py/modarray.c | 4 ++-- py/modcmath.c | 4 ++-- py/modcollections.c | 4 ++-- py/modgc.c | 4 ++-- py/modio.c | 4 ++-- py/modmath.c | 4 ++-- py/modmicropython.c | 4 ++-- py/modstruct.c | 4 ++-- py/modsys.c | 4 ++-- py/objenumerate.c | 2 +- stmhal/dac.c | 2 +- stmhal/extint.c | 2 +- stmhal/i2c.c | 10 +++++----- stmhal/led.c | 2 +- stmhal/main.c | 2 +- stmhal/modos.c | 4 ++-- stmhal/modpyb.c | 4 ++-- stmhal/modstm.c | 4 ++-- stmhal/modtime.c | 4 ++-- stmhal/spi.c | 10 +++++----- stmhal/timer.c | 4 ++-- stmhal/uart.c | 6 +++--- unix/modffi.c | 4 ++-- unix/modos.c | 4 ++-- unix/modsocket.c | 4 ++-- unix/modtime.c | 4 ++-- 32 files changed, 67 insertions(+), 67 deletions(-) diff --git a/py/builtin.c b/py/builtin.c index 834108f1b..b25ca42a1 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -154,7 +154,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any); STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) { mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in }; - return mp_obj_str_format(ARRAY_SIZE(args), args); + return mp_obj_str_format(MP_ARRAY_SIZE(args), args); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin); diff --git a/py/builtintables.c b/py/builtintables.c index 857a581de..af9a9bc25 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -150,8 +150,8 @@ const mp_obj_dict_t mp_builtin_object_dict_obj = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_builtin_object_table), - .alloc = ARRAY_SIZE(mp_builtin_object_table), + .used = MP_ARRAY_SIZE(mp_builtin_object_table), + .alloc = MP_ARRAY_SIZE(mp_builtin_object_table), .table = (mp_map_elem_t*)mp_builtin_object_table, }, }; @@ -195,8 +195,8 @@ const mp_obj_dict_t mp_builtin_module_dict_obj = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_builtin_module_table), - .alloc = ARRAY_SIZE(mp_builtin_module_table), + .used = MP_ARRAY_SIZE(mp_builtin_module_table), + .alloc = MP_ARRAY_SIZE(mp_builtin_module_table), .table = (mp_map_elem_t*)mp_builtin_module_table, }, }; diff --git a/py/compile.c b/py/compile.c index 946c8924b..b9979af14 100644 --- a/py/compile.c +++ b/py/compile.c @@ -111,8 +111,8 @@ STATIC const mp_map_elem_t mp_constants_table[] = { STATIC const mp_map_t mp_constants_map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_constants_table), - .alloc = ARRAY_SIZE(mp_constants_table), + .used = MP_ARRAY_SIZE(mp_constants_table), + .alloc = MP_ARRAY_SIZE(mp_constants_table), .table = (mp_map_elem_t*)mp_constants_table, }; diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 79ed1c4a0..8acee6c3e 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -167,7 +167,7 @@ STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t if (MP_PARSE_NODE_IS_ID(pn)) { qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn); const char *reg_str = qstr_str(reg_qstr); - for (uint i = 0; i < ARRAY_SIZE(reg_name_table); i++) { + for (uint i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) { const reg_name_t *r = ®_name_table[i]; if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) { if (r->reg > max_reg) { @@ -286,7 +286,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m asm_thumb_b_n(emit->as, label_num); } else if (op_str[0] == 'b' && op_len == 3) { uint cc = -1; - for (uint i = 0; i < ARRAY_SIZE(cc_name_table); i++) { + for (uint i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) { if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) { cc = cc_name_table[i].cc; } diff --git a/py/lexer.c b/py/lexer.c index a65df54ba..f69c395e7 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -694,10 +694,10 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs // need to check for this special token in many places in the compiler. // TODO improve speed of these string comparisons //for (int i = 0; tok_kw[i] != NULL; i++) { - for (int i = 0; i < ARRAY_SIZE(tok_kw); i++) { + for (int i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) { if (str_strn_equal(tok_kw[i], tok->str, tok->len)) { - if (i == ARRAY_SIZE(tok_kw) - 1) { - // tok_kw[ARRAY_SIZE(tok_kw) - 1] == "__debug__" + if (i == MP_ARRAY_SIZE(tok_kw) - 1) { + // tok_kw[MP_ARRAY_SIZE(tok_kw) - 1] == "__debug__" tok->kind = (mp_optimise_value == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE); } else { tok->kind = MP_TOKEN_KW_FALSE + i; diff --git a/py/misc.h b/py/misc.h index 044fef623..3f62e3198 100644 --- a/py/misc.h +++ b/py/misc.h @@ -82,7 +82,7 @@ int m_get_peak_bytes_allocated(void); /** array helpers ***********************************************/ // get the number of elements in a fixed-size array -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) /** unichar / UTF-8 *********************************************/ diff --git a/py/modarray.c b/py/modarray.c index a741a0ecb..2b9f531f9 100644 --- a/py/modarray.c +++ b/py/modarray.c @@ -40,8 +40,8 @@ STATIC const mp_obj_dict_t mp_module_array_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_array_globals_table), - .alloc = ARRAY_SIZE(mp_module_array_globals_table), + .used = MP_ARRAY_SIZE(mp_module_array_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_array_globals_table), .table = (mp_map_elem_t*)mp_module_array_globals_table, }, }; diff --git a/py/modcmath.c b/py/modcmath.c index 3bc3055dc..14f204b8b 100644 --- a/py/modcmath.c +++ b/py/modcmath.c @@ -142,8 +142,8 @@ STATIC const mp_obj_dict_t mp_module_cmath_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_cmath_globals_table), - .alloc = ARRAY_SIZE(mp_module_cmath_globals_table), + .used = MP_ARRAY_SIZE(mp_module_cmath_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_cmath_globals_table), .table = (mp_map_elem_t*)mp_module_cmath_globals_table, }, }; diff --git a/py/modcollections.c b/py/modcollections.c index 9e3da7e66..2f732085f 100644 --- a/py/modcollections.c +++ b/py/modcollections.c @@ -42,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_collections_globals_table), - .alloc = ARRAY_SIZE(mp_module_collections_globals_table), + .used = MP_ARRAY_SIZE(mp_module_collections_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_collections_globals_table), .table = (mp_map_elem_t*)mp_module_collections_globals_table, }, }; diff --git a/py/modgc.c b/py/modgc.c index c53eed235..a82a7a0eb 100644 --- a/py/modgc.c +++ b/py/modgc.c @@ -73,8 +73,8 @@ STATIC const mp_obj_dict_t mp_module_gc_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_gc_globals_table), - .alloc = ARRAY_SIZE(mp_module_gc_globals_table), + .used = MP_ARRAY_SIZE(mp_module_gc_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_gc_globals_table), .table = (mp_map_elem_t*)mp_module_gc_globals_table, }, }; diff --git a/py/modio.c b/py/modio.c index 08c6c59dd..e2ebc990b 100644 --- a/py/modio.c +++ b/py/modio.c @@ -57,8 +57,8 @@ STATIC const mp_obj_dict_t mp_module_io_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_io_globals_table), - .alloc = ARRAY_SIZE(mp_module_io_globals_table), + .used = MP_ARRAY_SIZE(mp_module_io_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_io_globals_table), .table = (mp_map_elem_t*)mp_module_io_globals_table, }, }; diff --git a/py/modmath.c b/py/modmath.c index 0fd583c2f..ff6129c5b 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -172,8 +172,8 @@ STATIC const mp_obj_dict_t mp_module_math_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_math_globals_table), - .alloc = ARRAY_SIZE(mp_module_math_globals_table), + .used = MP_ARRAY_SIZE(mp_module_math_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_math_globals_table), .table = (mp_map_elem_t*)mp_module_math_globals_table, }, }; diff --git a/py/modmicropython.c b/py/modmicropython.c index 40d749da2..c1a293a53 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -65,8 +65,8 @@ STATIC const mp_obj_dict_t mp_module_micropython_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_micropython_globals_table), - .alloc = ARRAY_SIZE(mp_module_micropython_globals_table), + .used = MP_ARRAY_SIZE(mp_module_micropython_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_micropython_globals_table), .table = (mp_map_elem_t*)mp_module_micropython_globals_table, }, }; diff --git a/py/modstruct.c b/py/modstruct.c index a45181852..ae6cb9eb9 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -210,8 +210,8 @@ STATIC const mp_obj_dict_t mp_module_struct_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_struct_globals_table), - .alloc = ARRAY_SIZE(mp_module_struct_globals_table), + .used = MP_ARRAY_SIZE(mp_module_struct_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_struct_globals_table), .table = (mp_map_elem_t*)mp_module_struct_globals_table, }, }; diff --git a/py/modsys.c b/py/modsys.c index a99db1b7f..519d470b0 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -87,8 +87,8 @@ STATIC const mp_obj_dict_t mp_module_sys_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_sys_globals_table), - .alloc = ARRAY_SIZE(mp_module_sys_globals_table), + .used = MP_ARRAY_SIZE(mp_module_sys_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_sys_globals_table), .table = (mp_map_elem_t*)mp_module_sys_globals_table, }, }; diff --git a/py/objenumerate.c b/py/objenumerate.c index 7d9ea9915..2fdf30b23 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -45,7 +45,7 @@ STATIC const mp_arg_t enumerate_make_new_args[] = { { MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_start, MP_ARG_INT, {.u_int = 0} }, }; -#define ENUMERATE_MAKE_NEW_NUM_ARGS ARRAY_SIZE(enumerate_make_new_args) +#define ENUMERATE_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(enumerate_make_new_args) STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { #if MICROPY_CPYTHON_COMPAT diff --git a/stmhal/dac.c b/stmhal/dac.c index 81ce993a8..725e14e90 100644 --- a/stmhal/dac.c +++ b/stmhal/dac.c @@ -237,7 +237,7 @@ STATIC const mp_arg_t pyb_dac_write_timed_args[] = { { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DMA_NORMAL} }, }; -#define PYB_DAC_WRITE_TIMED_NUM_ARGS ARRAY_SIZE(pyb_dac_write_timed_args) +#define PYB_DAC_WRITE_TIMED_NUM_ARGS MP_ARRAY_SIZE(pyb_dac_write_timed_args) mp_obj_t pyb_dac_write_timed(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_dac_obj_t *self = args[0]; diff --git a/stmhal/extint.c b/stmhal/extint.c index 24d51ffb8..591246cdd 100644 --- a/stmhal/extint.c +++ b/stmhal/extint.c @@ -296,7 +296,7 @@ STATIC const mp_arg_t pyb_extint_make_new_args[] = { { MP_QSTR_pull, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; -#define PYB_EXTINT_MAKE_NEW_NUM_ARGS ARRAY_SIZE(pyb_extint_make_new_args) +#define PYB_EXTINT_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(pyb_extint_make_new_args) STATIC mp_obj_t extint_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { // type_in == extint_obj_type diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 00501a57d..b6ab53129 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -220,7 +220,7 @@ STATIC const mp_arg_t pyb_i2c_init_args[] = { { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, { MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; -#define PYB_I2C_INIT_NUM_ARGS ARRAY_SIZE(pyb_i2c_init_args) +#define PYB_I2C_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_init_args) STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args @@ -271,7 +271,7 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const machine_int_t i2c_id = mp_obj_get_int(args[0]) - 1; // check i2c number - if (!(0 <= i2c_id && i2c_id < ARRAY_SIZE(pyb_i2c_obj) && pyb_i2c_obj[i2c_id].i2c != NULL)) { + if (!(0 <= i2c_id && i2c_id < MP_ARRAY_SIZE(pyb_i2c_obj) && pyb_i2c_obj[i2c_id].i2c != NULL)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1)); } @@ -363,7 +363,7 @@ STATIC const mp_arg_t pyb_i2c_send_args[] = { { MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_I2C_SEND_NUM_ARGS ARRAY_SIZE(pyb_i2c_send_args) +#define PYB_I2C_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_send_args) STATIC mp_obj_t pyb_i2c_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_i2c_obj_t *self = args[0]; @@ -414,7 +414,7 @@ STATIC const mp_arg_t pyb_i2c_recv_args[] = { { MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_I2C_RECV_NUM_ARGS ARRAY_SIZE(pyb_i2c_recv_args) +#define PYB_I2C_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_recv_args) STATIC mp_obj_t pyb_i2c_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_i2c_obj_t *self = args[0]; @@ -470,7 +470,7 @@ STATIC const mp_arg_t pyb_i2c_mem_read_args[] = { { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_I2C_MEM_READ_NUM_ARGS ARRAY_SIZE(pyb_i2c_mem_read_args) +#define PYB_I2C_MEM_READ_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_mem_read_args) STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_i2c_obj_t *self = args[0]; diff --git a/stmhal/led.c b/stmhal/led.c index 8cef02425..95b6feb28 100644 --- a/stmhal/led.c +++ b/stmhal/led.c @@ -61,7 +61,7 @@ STATIC const pyb_led_obj_t pyb_led_obj[] = { #endif #endif }; -#define NUM_LEDS ARRAY_SIZE(pyb_led_obj) +#define NUM_LEDS MP_ARRAY_SIZE(pyb_led_obj) void led_init(void) { /* GPIO structure */ diff --git a/stmhal/main.c b/stmhal/main.c index 9751dcac2..e264fdf4b 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -308,7 +308,7 @@ soft_reset: MP_OBJ_NEW_SMALL_INT(115200), }; pyb_uart_global_debug = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, - ARRAY_SIZE(args), + MP_ARRAY_SIZE(args), 0, args); } #else diff --git a/stmhal/modos.c b/stmhal/modos.c index 4a6949a84..e0df05ca6 100644 --- a/stmhal/modos.c +++ b/stmhal/modos.c @@ -194,8 +194,8 @@ STATIC const mp_obj_dict_t os_module_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(os_module_globals_table), - .alloc = ARRAY_SIZE(os_module_globals_table), + .used = MP_ARRAY_SIZE(os_module_globals_table), + .alloc = MP_ARRAY_SIZE(os_module_globals_table), .table = (mp_map_elem_t*)os_module_globals_table, }, }; diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index 6879a2c1b..9dcd0e76c 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -426,8 +426,8 @@ STATIC const mp_obj_dict_t pyb_module_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(pyb_module_globals_table), - .alloc = ARRAY_SIZE(pyb_module_globals_table), + .used = MP_ARRAY_SIZE(pyb_module_globals_table), + .alloc = MP_ARRAY_SIZE(pyb_module_globals_table), .table = (mp_map_elem_t*)pyb_module_globals_table, }, }; diff --git a/stmhal/modstm.c b/stmhal/modstm.c index 520c8e51b..1196ff82f 100644 --- a/stmhal/modstm.c +++ b/stmhal/modstm.c @@ -131,8 +131,8 @@ STATIC const mp_obj_dict_t stm_module_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(stm_module_globals_table), - .alloc = ARRAY_SIZE(stm_module_globals_table), + .used = MP_ARRAY_SIZE(stm_module_globals_table), + .alloc = MP_ARRAY_SIZE(stm_module_globals_table), .table = (mp_map_elem_t*)stm_module_globals_table, }, }; diff --git a/stmhal/modtime.c b/stmhal/modtime.c index 4fbee3129..ea4e3210a 100644 --- a/stmhal/modtime.c +++ b/stmhal/modtime.c @@ -122,8 +122,8 @@ STATIC const mp_obj_dict_t time_module_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(time_module_globals_table), - .alloc = ARRAY_SIZE(time_module_globals_table), + .used = MP_ARRAY_SIZE(time_module_globals_table), + .alloc = MP_ARRAY_SIZE(time_module_globals_table), .table = (mp_map_elem_t*)time_module_globals_table, }, }; diff --git a/stmhal/spi.c b/stmhal/spi.c index 10ecf7ec8..448b8696e 100644 --- a/stmhal/spi.c +++ b/stmhal/spi.c @@ -188,7 +188,7 @@ STATIC const pyb_spi_obj_t pyb_spi_obj[] = { {{&pyb_spi_type}, NULL}, #endif }; -#define PYB_NUM_SPI ARRAY_SIZE(pyb_spi_obj) +#define PYB_NUM_SPI MP_ARRAY_SIZE(pyb_spi_obj) STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { pyb_spi_obj_t *self = self_in; @@ -242,7 +242,7 @@ STATIC const mp_arg_t pyb_spi_init_args[] = { { MP_QSTR_ti, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_crc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; -#define PYB_SPI_INIT_NUM_ARGS ARRAY_SIZE(pyb_spi_init_args) +#define PYB_SPI_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_init_args) STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args @@ -359,7 +359,7 @@ STATIC const mp_arg_t pyb_spi_send_args[] = { { MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_SPI_SEND_NUM_ARGS ARRAY_SIZE(pyb_spi_send_args) +#define PYB_SPI_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_send_args) STATIC mp_obj_t pyb_spi_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide @@ -401,7 +401,7 @@ STATIC const mp_arg_t pyb_spi_recv_args[] = { { MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_SPI_RECV_NUM_ARGS ARRAY_SIZE(pyb_spi_recv_args) +#define PYB_SPI_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_recv_args) STATIC mp_obj_t pyb_spi_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide @@ -449,7 +449,7 @@ STATIC const mp_arg_t pyb_spi_send_recv_args[] = { { MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_SPI_SEND_RECV_NUM_ARGS ARRAY_SIZE(pyb_spi_send_recv_args) +#define PYB_SPI_SEND_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_send_recv_args) STATIC mp_obj_t pyb_spi_send_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide diff --git a/stmhal/timer.c b/stmhal/timer.c index 0ba24754b..ec0c4dec4 100644 --- a/stmhal/timer.c +++ b/stmhal/timer.c @@ -105,7 +105,7 @@ static uint32_t tim3_counter = 0; // Used to do callbacks to Python code on interrupt STATIC pyb_timer_obj_t *pyb_timer_obj_all[14]; -#define PYB_TIMER_OBJ_ALL_NUM ARRAY_SIZE(pyb_timer_obj_all) +#define PYB_TIMER_OBJ_ALL_NUM MP_ARRAY_SIZE(pyb_timer_obj_all) void timer_init0(void) { tim3_counter = 0; @@ -234,7 +234,7 @@ STATIC const mp_arg_t pyb_timer_init_args[] = { { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_COUNTERMODE_UP} }, { MP_QSTR_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_CLOCKDIVISION_DIV1} }, }; -#define PYB_TIMER_INIT_NUM_ARGS ARRAY_SIZE(pyb_timer_init_args) +#define PYB_TIMER_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_timer_init_args) STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args diff --git a/stmhal/uart.c b/stmhal/uart.c index 5bbd9f299..a85f7f9e3 100644 --- a/stmhal/uart.c +++ b/stmhal/uart.c @@ -270,7 +270,7 @@ STATIC const mp_arg_t pyb_uart_init_args[] = { { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; -#define PYB_UART_INIT_NUM_ARGS ARRAY_SIZE(pyb_uart_init_args) +#define PYB_UART_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_init_args) STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args @@ -396,7 +396,7 @@ STATIC const mp_arg_t pyb_uart_send_args[] = { { MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_UART_SEND_NUM_ARGS ARRAY_SIZE(pyb_uart_send_args) +#define PYB_UART_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_send_args) STATIC mp_obj_t pyb_uart_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide @@ -438,7 +438,7 @@ STATIC const mp_arg_t pyb_uart_recv_args[] = { { MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; -#define PYB_UART_RECV_NUM_ARGS ARRAY_SIZE(pyb_uart_recv_args) +#define PYB_UART_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_recv_args) STATIC mp_obj_t pyb_uart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide diff --git a/unix/modffi.c b/unix/modffi.c index bfc840cef..f1b219987 100644 --- a/unix/modffi.c +++ b/unix/modffi.c @@ -421,8 +421,8 @@ STATIC const mp_obj_dict_t mp_module_ffi_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_ffi_globals_table), - .alloc = ARRAY_SIZE(mp_module_ffi_globals_table), + .used = MP_ARRAY_SIZE(mp_module_ffi_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_ffi_globals_table), .table = (mp_map_elem_t*)mp_module_ffi_globals_table, }, }; diff --git a/unix/modos.c b/unix/modos.c index 657958d04..2e02ef0aa 100644 --- a/unix/modos.c +++ b/unix/modos.c @@ -75,8 +75,8 @@ STATIC const mp_obj_dict_t mp_module_os_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_os_globals_table), - .alloc = ARRAY_SIZE(mp_module_os_globals_table), + .used = MP_ARRAY_SIZE(mp_module_os_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_os_globals_table), .table = (mp_map_elem_t*)mp_module_os_globals_table, }, }; diff --git a/unix/modsocket.c b/unix/modsocket.c index b1a34a39b..8c5c9706c 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -436,8 +436,8 @@ STATIC const mp_obj_dict_t mp_module_socket_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_socket_globals_table), - .alloc = ARRAY_SIZE(mp_module_socket_globals_table), + .used = MP_ARRAY_SIZE(mp_module_socket_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_socket_globals_table), .table = (mp_map_elem_t*)mp_module_socket_globals_table, }, }; diff --git a/unix/modtime.c b/unix/modtime.c index 3cc09e3cd..006fd0ebd 100644 --- a/unix/modtime.c +++ b/unix/modtime.c @@ -113,8 +113,8 @@ STATIC const mp_obj_dict_t mp_module_time_globals = { .map = { .all_keys_are_qstrs = 1, .table_is_fixed_array = 1, - .used = ARRAY_SIZE(mp_module_time_globals_table), - .alloc = ARRAY_SIZE(mp_module_time_globals_table), + .used = MP_ARRAY_SIZE(mp_module_time_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_time_globals_table), .table = (mp_map_elem_t*)mp_module_time_globals_table, }, }; From e53d2197e4a749b2e2265c7b42f9b9834128799f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 19 Jun 2014 03:20:34 +0300 Subject: [PATCH 08/30] bench: Add test for function call overhead. For a trivial operation, calling a function is 5 times slower than doing operation inline. --- tests/bench/funcall-1-inline.py | 9 +++++++++ tests/bench/funcall-2-funcall.py | 12 ++++++++++++ tests/bench/funcall-3-funcall-local.py | 16 ++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 tests/bench/funcall-1-inline.py create mode 100644 tests/bench/funcall-2-funcall.py create mode 100644 tests/bench/funcall-3-funcall-local.py diff --git a/tests/bench/funcall-1-inline.py b/tests/bench/funcall-1-inline.py new file mode 100644 index 000000000..fbeb79630 --- /dev/null +++ b/tests/bench/funcall-1-inline.py @@ -0,0 +1,9 @@ +# Function call overhead test +# Establish a baseline for performing a trivial operation inline +import bench + +def test(num): + for i in iter(range(num)): + a = i + 1 + +bench.run(test) diff --git a/tests/bench/funcall-2-funcall.py b/tests/bench/funcall-2-funcall.py new file mode 100644 index 000000000..d5c36c60a --- /dev/null +++ b/tests/bench/funcall-2-funcall.py @@ -0,0 +1,12 @@ +# Function call overhead test +# Perform the same trivial operation as global function call +import bench + +def f(x): + return x + 1 + +def test(num): + for i in iter(range(num)): + a = f(i) + +bench.run(test) diff --git a/tests/bench/funcall-3-funcall-local.py b/tests/bench/funcall-3-funcall-local.py new file mode 100644 index 000000000..1a6d728c6 --- /dev/null +++ b/tests/bench/funcall-3-funcall-local.py @@ -0,0 +1,16 @@ +# Function call overhead test +# Perform the same trivial operation as calling function, cached in a +# local variable. This is commonly known optimization for overly dynamic +# languages (the idea is to cut on symbolic look up overhead, as local +# variables are accessed by offset, not by name) +import bench + +def f(x): + return x + 1 + +def test(num): + f_ = f + for i in iter(range(num)): + a = f_(i) + +bench.run(test) From 17db09650569609793061e83aded7039e39e81a7 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 19 Jun 2014 21:44:33 +0300 Subject: [PATCH 09/30] bench: Add tests for constructing various containers from iterator. Both "bound" (like, length known) and "unbound" (length unknown) are tested. All of list, tuple, bytes, bytesarray offer approximately the same performance, with "unbound" case being 30 times slower. --- tests/bench/from_iter-1-list_bound.py | 8 ++++++++ tests/bench/from_iter-2-list_unbound.py | 8 ++++++++ tests/bench/from_iter-3-tuple_bound.py | 8 ++++++++ tests/bench/from_iter-4-tuple_unbound.py | 8 ++++++++ tests/bench/from_iter-5-bytes_bound.py | 8 ++++++++ tests/bench/from_iter-6-bytes_unbound.py | 8 ++++++++ tests/bench/from_iter-7-bytearray_bound.py | 8 ++++++++ tests/bench/from_iter-8-bytearray_unbound.py | 8 ++++++++ 8 files changed, 64 insertions(+) create mode 100644 tests/bench/from_iter-1-list_bound.py create mode 100644 tests/bench/from_iter-2-list_unbound.py create mode 100644 tests/bench/from_iter-3-tuple_bound.py create mode 100644 tests/bench/from_iter-4-tuple_unbound.py create mode 100644 tests/bench/from_iter-5-bytes_bound.py create mode 100644 tests/bench/from_iter-6-bytes_unbound.py create mode 100644 tests/bench/from_iter-7-bytearray_bound.py create mode 100644 tests/bench/from_iter-8-bytearray_unbound.py diff --git a/tests/bench/from_iter-1-list_bound.py b/tests/bench/from_iter-1-list_bound.py new file mode 100644 index 000000000..d209daecc --- /dev/null +++ b/tests/bench/from_iter-1-list_bound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = list(l) + +bench.run(test) diff --git a/tests/bench/from_iter-2-list_unbound.py b/tests/bench/from_iter-2-list_unbound.py new file mode 100644 index 000000000..be019c52f --- /dev/null +++ b/tests/bench/from_iter-2-list_unbound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = list(map(lambda x: x, l)) + +bench.run(test) diff --git a/tests/bench/from_iter-3-tuple_bound.py b/tests/bench/from_iter-3-tuple_bound.py new file mode 100644 index 000000000..7b7fa36c6 --- /dev/null +++ b/tests/bench/from_iter-3-tuple_bound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = tuple(l) + +bench.run(test) diff --git a/tests/bench/from_iter-4-tuple_unbound.py b/tests/bench/from_iter-4-tuple_unbound.py new file mode 100644 index 000000000..7c7f134c8 --- /dev/null +++ b/tests/bench/from_iter-4-tuple_unbound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = tuple(map(lambda x: x, l)) + +bench.run(test) diff --git a/tests/bench/from_iter-5-bytes_bound.py b/tests/bench/from_iter-5-bytes_bound.py new file mode 100644 index 000000000..b793a3207 --- /dev/null +++ b/tests/bench/from_iter-5-bytes_bound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = bytes(l) + +bench.run(test) diff --git a/tests/bench/from_iter-6-bytes_unbound.py b/tests/bench/from_iter-6-bytes_unbound.py new file mode 100644 index 000000000..20aa55627 --- /dev/null +++ b/tests/bench/from_iter-6-bytes_unbound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = bytes(map(lambda x: x, l)) + +bench.run(test) diff --git a/tests/bench/from_iter-7-bytearray_bound.py b/tests/bench/from_iter-7-bytearray_bound.py new file mode 100644 index 000000000..72001a05c --- /dev/null +++ b/tests/bench/from_iter-7-bytearray_bound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = bytearray(l) + +bench.run(test) diff --git a/tests/bench/from_iter-8-bytearray_unbound.py b/tests/bench/from_iter-8-bytearray_unbound.py new file mode 100644 index 000000000..e2263b8ef --- /dev/null +++ b/tests/bench/from_iter-8-bytearray_unbound.py @@ -0,0 +1,8 @@ +import bench + +def test(num): + for i in iter(range(num//10000)): + l = [0] * 1000 + l2 = bytearray(map(lambda x: x, l)) + +bench.run(test) From 59ced651b542941f893293099a932252e498eb7c Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 19 Jun 2014 21:54:51 +0300 Subject: [PATCH 10/30] bench: Add test for map() vs inplace operations in array-likes. map() is 5 times slower. That's mostly because of inefficiency of creating containers from iterables of unknown length (like map()). --- tests/bench/arrayop-1-list_inplace.py | 12 ++++++++++++ tests/bench/arrayop-2-list_map.py | 12 ++++++++++++ tests/bench/arrayop-3-bytearray_inplace.py | 12 ++++++++++++ tests/bench/arrayop-4-bytearray_map.py | 12 ++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 tests/bench/arrayop-1-list_inplace.py create mode 100644 tests/bench/arrayop-2-list_map.py create mode 100644 tests/bench/arrayop-3-bytearray_inplace.py create mode 100644 tests/bench/arrayop-4-bytearray_map.py diff --git a/tests/bench/arrayop-1-list_inplace.py b/tests/bench/arrayop-1-list_inplace.py new file mode 100644 index 000000000..0ee1ef2ec --- /dev/null +++ b/tests/bench/arrayop-1-list_inplace.py @@ -0,0 +1,12 @@ +# Array operation +# Type: list, inplace operation using for. What's good about this +# method is that it doesn't require any extra memory allocation. +import bench + +def test(num): + for i in iter(range(num//10000)): + arr = [0] * 1000 + for i in range(len(arr)): + arr[i] += 1 + +bench.run(test) diff --git a/tests/bench/arrayop-2-list_map.py b/tests/bench/arrayop-2-list_map.py new file mode 100644 index 000000000..9d5095c53 --- /dev/null +++ b/tests/bench/arrayop-2-list_map.py @@ -0,0 +1,12 @@ +# Array operation +# Type: list, map() call. This method requires allocation of +# the same amount of memory as original array (to hold result +# array). On the other hand, input array stays intact. +import bench + +def test(num): + for i in iter(range(num//10000)): + arr = [0] * 1000 + arr2 = list(map(lambda x: x + 1, arr)) + +bench.run(test) diff --git a/tests/bench/arrayop-3-bytearray_inplace.py b/tests/bench/arrayop-3-bytearray_inplace.py new file mode 100644 index 000000000..a6d628070 --- /dev/null +++ b/tests/bench/arrayop-3-bytearray_inplace.py @@ -0,0 +1,12 @@ +# Array operation +# Type: bytearray, inplace operation using for. What's good about this +# method is that it doesn't require any extra memory allocation. +import bench + +def test(num): + for i in iter(range(num//10000)): + arr = bytearray(b"\0" * 1000) + for i in range(len(arr)): + arr[i] += 1 + +bench.run(test) diff --git a/tests/bench/arrayop-4-bytearray_map.py b/tests/bench/arrayop-4-bytearray_map.py new file mode 100644 index 000000000..1b92a4096 --- /dev/null +++ b/tests/bench/arrayop-4-bytearray_map.py @@ -0,0 +1,12 @@ +# Array operation +# Type: list, map() call. This method requires allocation of +# the same amount of memory as original array (to hold result +# array). On the other hand, input array stays intact. +import bench + +def test(num): + for i in iter(range(num//10000)): + arr = bytearray(b"\0" * 1000) + arr2 = bytearray(map(lambda x: x + 1, arr)) + +bench.run(test) From 74c710187c77ebd5ab8c5a44b07087f2c2ca786e Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 19 Jun 2014 22:27:13 +0300 Subject: [PATCH 11/30] bench: Three ways to process a byte buffer. --- tests/bench/bytebuf-1-inplace.py | 11 +++++++++++ tests/bench/bytebuf-2-join_map_bytes.py | 12 ++++++++++++ tests/bench/bytebuf-3-bytarray_map.py | 10 ++++++++++ 3 files changed, 33 insertions(+) create mode 100644 tests/bench/bytebuf-1-inplace.py create mode 100644 tests/bench/bytebuf-2-join_map_bytes.py create mode 100644 tests/bench/bytebuf-3-bytarray_map.py diff --git a/tests/bench/bytebuf-1-inplace.py b/tests/bench/bytebuf-1-inplace.py new file mode 100644 index 000000000..7e7d9391c --- /dev/null +++ b/tests/bench/bytebuf-1-inplace.py @@ -0,0 +1,11 @@ +# Doing some operation on bytearray +# Inplace - the most memory efficient way +import bench + +def test(num): + for i in iter(range(num//10000)): + ba = bytearray(b"\0" * 1000) + for i in range(len(ba)): + ba[i] += 1 + +bench.run(test) diff --git a/tests/bench/bytebuf-2-join_map_bytes.py b/tests/bench/bytebuf-2-join_map_bytes.py new file mode 100644 index 000000000..daa622991 --- /dev/null +++ b/tests/bench/bytebuf-2-join_map_bytes.py @@ -0,0 +1,12 @@ +# Doing some operation on bytearray +# Pretty weird way - map bytearray thru function, but make sure that +# function return bytes of size 1, then join them together. Surely, +# this is slowest way to do it. +import bench + +def test(num): + for i in iter(range(num//10000)): + ba = bytearray(b"\0" * 1000) + ba2 = b''.join(map(lambda x:bytes([x + 1]), ba)) + +bench.run(test) diff --git a/tests/bench/bytebuf-3-bytarray_map.py b/tests/bench/bytebuf-3-bytarray_map.py new file mode 100644 index 000000000..078d08e99 --- /dev/null +++ b/tests/bench/bytebuf-3-bytarray_map.py @@ -0,0 +1,10 @@ +# Doing some operation on bytearray +# No joins, but still map(). +import bench + +def test(num): + for i in iter(range(num//10000)): + ba = bytearray(b"\0" * 1000) + ba2 = bytearray(map(lambda x: x + 1, ba)) + +bench.run(test) From 3b6f7b95eb487fc927a3bc4644b1941cfbe2612b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 01:48:35 +0300 Subject: [PATCH 12/30] py: Separate MICROPY_PY_BUILTINS_COMPLEX from MICROPY_PY_BUILTINS_FLOAT. One thing is wanting to do 1 / 2 and get something else but 0, and quite another - doing rocket science ;-). --- py/builtin.c | 2 ++ py/builtintables.c | 2 +- py/mpconfig.h | 4 ++++ py/obj.c | 2 ++ py/objcomplex.c | 2 +- py/objfloat.c | 5 ++++- py/objint_mpz.c | 2 ++ py/parsenum.c | 6 ++++++ py/runtime.c | 2 ++ 9 files changed, 24 insertions(+), 3 deletions(-) diff --git a/py/builtin.c b/py/builtin.c index b25ca42a1..d4b77d37a 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -113,10 +113,12 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) { } else { return o_in; } +#if MICROPY_PY_BUILTINS_COMPLEX } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) { mp_float_t real, imag; mp_obj_complex_get(o_in, &real, &imag); return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)); +#endif #endif } else { assert(0); diff --git a/py/builtintables.c b/py/builtintables.c index af9a9bc25..66ea4ea44 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -44,7 +44,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool }, { MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes }, { MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray }, -#if MICROPY_PY_BUILTINS_FLOAT +#if MICROPY_PY_BUILTINS_COMPLEX { MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict }, diff --git a/py/mpconfig.h b/py/mpconfig.h index 93e98c25b..4a3288a3d 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -223,6 +223,10 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_FLOAT (0) #endif +#ifndef MICROPY_PY_BUILTINS_COMPLEX +#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT) +#endif + // Enable features which improve CPython compatibility // but may lead to more code size/memory usage. // TODO: Originally intended as generic category to not diff --git a/py/obj.c b/py/obj.c index 6d0966db2..a0f55d65d 100644 --- a/py/obj.c +++ b/py/obj.c @@ -274,6 +274,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { } } +#if MICROPY_PY_BUILTINS_COMPLEX void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { if (arg == mp_const_false) { *real = 0; @@ -297,6 +298,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { } } #endif +#endif void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) { if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) { diff --git a/py/objcomplex.c b/py/objcomplex.c index d58b53463..20e7c97d3 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -36,7 +36,7 @@ #include "runtime0.h" #include "runtime.h" -#if MICROPY_PY_BUILTINS_FLOAT +#if MICROPY_PY_BUILTINS_COMPLEX #include diff --git a/py/objfloat.c b/py/objfloat.c index b608b1a3d..e3fefad8d 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -102,9 +102,12 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) { STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_float_t *lhs = lhs_in; +#if MICROPY_PY_BUILTINS_COMPLEX if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) { return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in); - } else { + } else +#endif + { return mp_obj_float_binary_op(op, lhs->value, rhs_in); } } diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 516fb5274..cf7896f9e 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -121,8 +121,10 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { #if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_float)) { return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in); +#if MICROPY_PY_BUILTINS_COMPLEX } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) { return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in); +#endif #endif } else { // delegate to generic function to check for extra cases diff --git a/py/parsenum.c b/py/parsenum.c index 1c1868ae0..36b069050 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -35,6 +35,7 @@ #include "parsenumbase.h" #include "parsenum.h" #include "smallint.h" +#include "runtime.h" #if MICROPY_PY_BUILTINS_FLOAT #include @@ -252,10 +253,15 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f } // return the object +#if MICROPY_PY_BUILTINS_COMPLEX if (imag) { return mp_obj_new_complex(0, dec_val); } else if (force_complex) { return mp_obj_new_complex(dec_val, 0); +#else + if (imag || force_complex) { + mp_not_implemented("complex values not supported"); +#endif } else { return mp_obj_new_float(dec_val); } diff --git a/py/runtime.c b/py/runtime.c index d57bb686d..b539984c0 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -426,6 +426,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } else { return res; } +#if MICROPY_PY_BUILTINS_COMPLEX } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) { mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs); if (res == MP_OBJ_NULL) { @@ -433,6 +434,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } else { return res; } +#endif #endif } } From f605172d2b595fc42cf55a5f7d4819abb0396fd2 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 01:50:49 +0300 Subject: [PATCH 13/30] tests/float/: Skip tests if "math" module is not available. --- tests/float/math-fun-bool.py | 7 ++++++- tests/float/math-fun.py | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/float/math-fun-bool.py b/tests/float/math-fun-bool.py index cf718d4b8..57232857a 100644 --- a/tests/float/math-fun-bool.py +++ b/tests/float/math-fun-bool.py @@ -1,6 +1,11 @@ # Test the bool functions from math -from math import isfinite, isnan, isinf +try: + from math import isfinite, isnan, isinf +except ImportError: + print("SKIP") + import sys + sys.exit() test_values = [1, 0, -1, 1.0, 0.0, -1.0, float('NaN'), float('Inf'), -float('NaN'), -float('Inf')] diff --git a/tests/float/math-fun.py b/tests/float/math-fun.py index 7a37c5845..fa111e33e 100644 --- a/tests/float/math-fun.py +++ b/tests/float/math-fun.py @@ -1,6 +1,11 @@ # Tests the functions imported from math -from math import * +try: + from math import * +except ImportError: + print("SKIP") + import sys + sys.exit() test_values = [-100., -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 100.] p_test_values = [0.1, 0.5, 1.23456] From 2099b6897fb6f2a375f0fb176883c7099b6e0af9 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 19:17:35 +0300 Subject: [PATCH 14/30] unix: Allow to override compiler warning options without touching the rest. Some people want to enable even more warnings. Let them do it without putting burden on everyone. Some people vice versa think that current settings should be relaxed. In this regard, -Werror is the most problematic, it disallows to use #warning directive, and disallows to pass configuration settings on make command lines. Again, until decided how to deal with these globally, allow to work around these problems locally. --- unix/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unix/Makefile b/unix/Makefile index 485009135..2f30f92c0 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -15,7 +15,8 @@ INC += -I$(PY_SRC) INC += -I$(BUILD) # compiler settings -CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) +CWARN = -Wall -Werror +CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Darwin) From eecf3e90c638af886226ba652132d679db8a43fd Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 19:19:06 +0300 Subject: [PATCH 15/30] unix: Group CFLAGS related stuff together. --- unix/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/unix/Makefile b/unix/Makefile index 2f30f92c0..80495315f 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -18,6 +18,14 @@ INC += -I$(BUILD) CWARN = -Wall -Werror CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) +# Debugging/Optimization +ifdef DEBUG +CFLAGS += -g +COPT = -O0 +else +COPT = -Os #-DNDEBUG +endif + UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Darwin) LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-map,$@.map,-order_file,$(BUILD)/order.def @@ -57,14 +65,6 @@ SRC_MOD += modffi.c endif -# Debugging/Optimization -ifdef DEBUG -CFLAGS += -g -COPT = -O0 -else -COPT = -Os #-DNDEBUG -endif - # source files SRC_C = \ main.c \ From 7e56e552523d9fec09003243f2f3c0dd6afc9b4d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 19:25:54 +0300 Subject: [PATCH 16/30] unix: Refactor order file munging fo MacOSX. --- unix/Makefile | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/unix/Makefile b/unix/Makefile index 80495315f..90a043a1b 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -7,6 +7,9 @@ PROG = micropython # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h +# OS name, for simple autoconfig +UNAME_S := $(shell uname -s) + # include py core make definitions include ../py/py.mk @@ -26,12 +29,7 @@ else COPT = -Os #-DNDEBUG endif -UNAME_S := $(shell uname -s) - ifeq ($(UNAME_S),Darwin) - LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-map,$@.map,-order_file,$(BUILD)/order.def - else - LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref - endif +LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref ifeq ($(MICROPY_FORCE_32BIT),1) CFLAGS += -m32 @@ -76,6 +74,9 @@ SRC_C = \ $(SRC_MOD) ifeq ($(UNAME_S),Darwin) + +LDFLAGS+ = -Wl,-order_file,$(BUILD)/order.def + # Must be the last file in list of sources SRC_C += seg_helpers.c From 7cd46a12aef7931614ad6b8aa10ffb2a28fa73e8 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 19:27:51 +0300 Subject: [PATCH 17/30] unix: Add CFLAGS_EXTRA & LDFLAGS_EXTRA for command line usage. The idea is that it should be possible to pass any additional params for experimentation without need to patch sources (and without need to deviate from or repeat baseline options). --- unix/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unix/Makefile b/unix/Makefile index 90a043a1b..9a85f59e1 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -19,7 +19,7 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror -CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) +CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG @@ -29,7 +29,7 @@ else COPT = -Os #-DNDEBUG endif -LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref +LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref $(LDFLAGS_EXTRA) ifeq ($(MICROPY_FORCE_32BIT),1) CFLAGS += -m32 From 17a49431d484fd1ea9b08056b10881fd975f7ae1 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 20:17:43 +0300 Subject: [PATCH 18/30] unix: Allow to override MICROPY_GCREGS_SETJMP from cmdline. --- unix/mpconfigport.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index 3426ae44f..1559bdb35 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -53,7 +53,9 @@ #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) // Define to 1 to use untested inefficient GC helper implementation // (if more efficient arch-specific one is not available). +#ifndef MICROPY_GCREGS_SETJMP #define MICROPY_GCREGS_SETJMP (0) +#endif extern const struct _mp_obj_module_t mp_module_os; extern const struct _mp_obj_module_t mp_module_time; From 0fc7efb663e7b6c4cbc452ccb359e3f35f13953f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 20:25:35 +0300 Subject: [PATCH 19/30] makefile: Pass STRIPFLAGS_EXTRA to strip. Expected to be set on command line, with the idea being that for different targets, there're different smartass ABIs which strive to put unneeded sections into executables, etc., so let people have flexible way to strip that. The option name is similar to previously introduced CLFAGS_EXTRA & LDFLAGS_EXTRA. --- py/mkrules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 9592d6c59..ab8948ade 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -75,7 +75,7 @@ $(PROG): $(OBJ) $(ECHO) "LINK $@" $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) ifndef DEBUG - $(Q)$(STRIP) $(PROG) + $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG) endif $(Q)$(SIZE) $(PROG) From 4c4b9d15ab94dfe31ec34559ab70bafc0ef11f02 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 20 Jun 2014 20:33:20 +0300 Subject: [PATCH 20/30] mkrules.mk: Pass $(COPT) to link stage. In generalize case, optimization options should be passed to all stages of the build process. --- py/mkrules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index ab8948ade..6153618fa 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -73,7 +73,7 @@ all: $(PROG) $(PROG): $(OBJ) $(ECHO) "LINK $@" - $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) + $(Q)$(CC) $(COPT) -o $@ $(OBJ) $(LIB) $(LDFLAGS) ifndef DEBUG $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG) endif From 59c675a64c1d9757d50ad4627da67a6f996a99fb Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 21 Jun 2014 22:43:22 +0300 Subject: [PATCH 21/30] py: Include mpconfig.h before all other includes. It defines types used by all other headers. Fixes #691. --- py/asmthumb.c | 2 +- py/asmx64.c | 2 +- py/binary.c | 2 +- py/builtintables.c | 2 +- py/compile.c | 2 +- py/emitbc.c | 2 +- py/emitcommon.c | 2 +- py/emitcpy.c | 2 +- py/emitglue.c | 2 +- py/emitinlinethumb.c | 2 +- py/emitnative.c | 2 +- py/emitpass1.c | 2 +- py/gc.c | 1 - py/lexer.c | 2 +- py/lexerstr.c | 2 +- py/lexerunix.c | 2 +- py/malloc.c | 2 +- py/map.c | 2 +- py/modarray.c | 2 +- py/modcmath.c | 2 +- py/modcollections.c | 2 +- py/modgc.c | 2 +- py/modio.c | 2 +- py/modmath.c | 2 +- py/modmicropython.c | 2 +- py/modstruct.c | 2 +- py/modsys.c | 2 +- py/mpz.c | 2 +- py/objenumerate.c | 2 +- py/parse.c | 2 +- py/parsehelper.c | 2 +- py/parsenum.c | 2 +- py/parsenumbase.c | 2 +- py/pfenv.c | 2 +- py/qstr.c | 2 +- py/repl.c | 2 +- py/scope.c | 2 +- py/smallint.c | 2 +- py/unicode.c | 2 +- py/vstr.c | 2 +- 40 files changed, 39 insertions(+), 40 deletions(-) diff --git a/py/asmthumb.c b/py/asmthumb.c index 891947567..03752ed93 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -28,8 +28,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "asmthumb.h" // wrapper around everything in this file diff --git a/py/asmx64.c b/py/asmx64.c index 6c22ea25d..4695bdc73 100644 --- a/py/asmx64.c +++ b/py/asmx64.c @@ -29,8 +29,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" // wrapper around everything in this file #if MICROPY_EMIT_X64 diff --git a/py/binary.c b/py/binary.c index 833d9c85a..9eab01c4e 100644 --- a/py/binary.c +++ b/py/binary.c @@ -29,8 +29,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "binary.h" diff --git a/py/builtintables.c b/py/builtintables.c index 66ea4ea44..8b4df9317 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -26,8 +26,8 @@ #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/compile.c b/py/compile.c index b9979af14..d49edd6ef 100644 --- a/py/compile.c +++ b/py/compile.c @@ -31,8 +31,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/emitbc.c b/py/emitbc.c index 841dd4aab..3eb0d575b 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -30,8 +30,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/emitcommon.c b/py/emitcommon.c index ea6518362..464979313 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -28,8 +28,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/emitcpy.c b/py/emitcpy.c index a8a6265b8..fbca3805b 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -30,8 +30,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/emitglue.c b/py/emitglue.c index f9b946083..17dc8f867 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -30,8 +30,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "runtime0.h" diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 8acee6c3e..435e1b64d 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -30,8 +30,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/emitnative.c b/py/emitnative.c index 4dac5ffb0..49acc0bb1 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -48,8 +48,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/emitpass1.c b/py/emitpass1.c index 2e76420a2..bea1af4db 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -28,8 +28,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/gc.c b/py/gc.c index 90b7b89e5..65bfea0b3 100644 --- a/py/gc.c +++ b/py/gc.c @@ -33,7 +33,6 @@ #include "misc.h" #include "gc.h" -#include "misc.h" #include "qstr.h" #include "obj.h" #include "runtime.h" diff --git a/py/lexer.c b/py/lexer.c index f69c395e7..5d1113fb3 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -32,8 +32,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" diff --git a/py/lexerstr.c b/py/lexerstr.c index 76e90671b..666dbfa37 100644 --- a/py/lexerstr.c +++ b/py/lexerstr.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" diff --git a/py/lexerunix.c b/py/lexerunix.c index 89dc80b00..51bc915b2 100644 --- a/py/lexerunix.c +++ b/py/lexerunix.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #if MICROPY_HELPER_LEXER_UNIX diff --git a/py/malloc.c b/py/malloc.c index b180ddf6b..8e90849e9 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -28,8 +28,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #if 0 // print debugging info #define DEBUG_printf DEBUG_printf diff --git a/py/map.c b/py/map.c index 402040162..dcc13c52c 100644 --- a/py/map.c +++ b/py/map.c @@ -27,8 +27,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "runtime0.h" diff --git a/py/modarray.c b/py/modarray.c index 2b9f531f9..3ff567f1d 100644 --- a/py/modarray.c +++ b/py/modarray.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modcmath.c b/py/modcmath.c index 14f204b8b..ddd8abf71 100644 --- a/py/modcmath.c +++ b/py/modcmath.c @@ -26,8 +26,8 @@ #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modcollections.c b/py/modcollections.c index 2f732085f..5cd0b317a 100644 --- a/py/modcollections.c +++ b/py/modcollections.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modgc.c b/py/modgc.c index a82a7a0eb..f136ce733 100644 --- a/py/modgc.c +++ b/py/modgc.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modio.c b/py/modio.c index e2ebc990b..ef3b29b53 100644 --- a/py/modio.c +++ b/py/modio.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modmath.c b/py/modmath.c index ff6129c5b..0d0d13b4e 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -26,8 +26,8 @@ #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modmicropython.c b/py/modmicropython.c index c1a293a53..bbb315189 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modstruct.c b/py/modstruct.c index ae6cb9eb9..2e40264e8 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -27,8 +27,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/modsys.c b/py/modsys.c index 519d470b0..1e7f7eff7 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "builtin.h" diff --git a/py/mpz.c b/py/mpz.c index ab300b91d..3f1e859fc 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -30,8 +30,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "mpz.h" #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ diff --git a/py/objenumerate.c b/py/objenumerate.c index 2fdf30b23..37414464d 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -27,8 +27,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "runtime.h" diff --git a/py/parse.c b/py/parse.c index af09c335f..492c1678b 100644 --- a/py/parse.c +++ b/py/parse.c @@ -30,8 +30,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parsenumbase.h" diff --git a/py/parsehelper.c b/py/parsehelper.c index 3ead5a303..105afe711 100644 --- a/py/parsehelper.c +++ b/py/parsehelper.c @@ -29,8 +29,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "lexer.h" #include "parse.h" diff --git a/py/parsenum.c b/py/parsenum.c index 36b069050..b9801ab6a 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -27,8 +27,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "nlr.h" #include "obj.h" diff --git a/py/parsenumbase.c b/py/parsenumbase.c index ce140655b..4fddac9c3 100644 --- a/py/parsenumbase.c +++ b/py/parsenumbase.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "parsenumbase.h" // find real radix base, and strip preceding '0x', '0o' and '0b' diff --git a/py/pfenv.c b/py/pfenv.c index e631f8654..ca1e3e919 100644 --- a/py/pfenv.c +++ b/py/pfenv.c @@ -27,8 +27,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "mpz.h" diff --git a/py/qstr.c b/py/qstr.c index 7ccb34f1c..10bc20ecb 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -27,8 +27,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" // NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings) diff --git a/py/repl.c b/py/repl.c index 457ce165b..2c3dfbd4d 100644 --- a/py/repl.c +++ b/py/repl.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "repl.h" #if MICROPY_HELPER_REPL diff --git a/py/scope.c b/py/scope.c index 839e8216c..83c2b6e07 100644 --- a/py/scope.c +++ b/py/scope.c @@ -29,8 +29,8 @@ #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "parse.h" diff --git a/py/smallint.c b/py/smallint.c index 5543f126c..c57f364e3 100644 --- a/py/smallint.c +++ b/py/smallint.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "misc.h" #include "mpconfig.h" +#include "misc.h" #include "qstr.h" #include "obj.h" #include "smallint.h" diff --git a/py/unicode.c b/py/unicode.c index c8faa5700..88f835131 100644 --- a/py/unicode.c +++ b/py/unicode.c @@ -26,8 +26,8 @@ #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" // attribute flags #define FL_PRINT (0x01) diff --git a/py/vstr.c b/py/vstr.c index ea6a1c937..f8b7e4dab 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -29,8 +29,8 @@ #include #include #include -#include "misc.h" #include "mpconfig.h" +#include "misc.h" // returned value is always at least 1 greater than argument #define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8) From a96cc824bdacb34ced0edef523181c215fba313b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 22 Jun 2014 01:14:28 +0300 Subject: [PATCH 22/30] py: Support arm and thumb ARM ISAs, in addition to thumb2. These changes were tested with QEMU, and by few people of real hardware. --- py/nlr.h | 2 +- py/nlrthumb.S | 12 +++++++++--- unix/gccollect.c | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/py/nlr.h b/py/nlr.h index 83ab25134..cb2b53b85 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -45,7 +45,7 @@ struct _nlr_buf_t { #else void *regs[8]; #endif -#elif defined(__thumb2__) +#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) void *regs[10]; #else #define MICROPY_NLR_SETJMP (1) diff --git a/py/nlrthumb.S b/py/nlrthumb.S index b306c0175..dabf57cf8 100644 --- a/py/nlrthumb.S +++ b/py/nlrthumb.S @@ -24,19 +24,21 @@ * THE SOFTWARE. */ -#if defined(__thumb2__) && !MICROPY_NLR_SETJMP -/* thumb callee save: bx, bp, sp, r12, r14, r14, r15 */ +#if !MICROPY_NLR_SETJMP && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) +/* arm callee save: bx, bp, sp, r12, r14, r14, r15 */ .syntax unified /*.cpu cortex-m4*/ - .thumb + /*.thumb*/ .text .align 2 /* uint nlr_push(r0=nlr_buf_t *nlr) */ .global nlr_push +#if defined(__thumb2__) .thumb .thumb_func +#endif .type nlr_push, %function nlr_push: str lr, [r0, #8] @ store lr into nlr_buf @@ -64,8 +66,10 @@ nlr_push: @ void nlr_pop() .global nlr_pop +#if defined(__thumb2__) .thumb .thumb_func +#endif .type nlr_pop, %function nlr_pop: ldr r3, .L5 @ load addr of nlr_top @@ -80,8 +84,10 @@ nlr_pop: /* void nlr_jump(r0=uint val) */ .global nlr_jump +#if defined(__thumb2__) .thumb .thumb_func +#endif .type nlr_jump, %function nlr_jump: ldr r3, .L2 @ load addr of nlr_top diff --git a/unix/gccollect.c b/unix/gccollect.c index 4f3b786e7..1014a2629 100644 --- a/unix/gccollect.c +++ b/unix/gccollect.c @@ -97,7 +97,7 @@ void gc_helper_get_regs(regs_t arr) { } #endif -#ifdef __thumb2__ +#if defined(__thumb2__) || defined(__thumb__) || defined(__arm__) typedef machine_uint_t regs_t[10]; void gc_helper_get_regs(regs_t arr) { From 8abcf666cb638152634790a882875f52f7f0432b Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 12 Jun 2014 17:45:41 +0200 Subject: [PATCH 23/30] windows: Enable GC and implement bss start and end symbols The pointers to the bss section are acquired in init.c() by inspecting the PE header. Works for msvc and mingw. --- unix/gccollect.c | 16 +++++++-- windows/Makefile | 2 ++ windows/bss.c | 74 ++++++++++++++++++++++++++++++++++++++ windows/init.c | 3 ++ windows/mpconfigport.h | 19 ++++++++++ windows/msvc/common.props | 3 +- windows/msvc/sources.props | 2 +- 7 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 windows/bss.c diff --git a/unix/gccollect.c b/unix/gccollect.c index 1014a2629..792913821 100644 --- a/unix/gccollect.c +++ b/unix/gccollect.c @@ -130,8 +130,11 @@ void gc_collect(void) { gc_collect_start(); // this traces the .bss section -#ifdef __CYGWIN__ +#if defined( __CYGWIN__ ) #define BSS_START __bss_start__ +#elif defined( _MSC_VER ) || defined( __MINGW32__ ) +#define BSS_START *bss_start +#define _end *bss_end #else #define BSS_START __bss_start #endif @@ -141,7 +144,16 @@ void gc_collect(void) { regs_t regs; gc_helper_get_regs(regs); // GC stack (and regs because we captured them) - gc_collect_root((void**)®s, ((machine_uint_t)stack_top - (machine_uint_t)®s) / sizeof(machine_uint_t)); +#ifdef __MINGW32__ + // The Mingw cross-compiler on Travis complains + // 'warning: dereferencing type-punned pointer will break strict-aliasing rules' + // when casting ®s to void** directly so use a union. + union { regs_t *r; void **ptr; } cast_regs = { ®s }; + void **regs_ptr = cast_regs.ptr; +#else + void **regs_ptr = (void**)®s; +#endif + gc_collect_root(regs_ptr, ((machine_uint_t)stack_top - (machine_uint_t)®s) / sizeof(machine_uint_t)); gc_collect_end(); //printf("-----\n"); diff --git a/windows/Makefile b/windows/Makefile index a188979bd..e3085ff23 100644 --- a/windows/Makefile +++ b/windows/Makefile @@ -35,9 +35,11 @@ SRC_C = \ unix/file.c \ unix/input.c \ unix/modtime.c \ + unix/gccollect.c \ realpath.c \ init.c \ sleep.c \ + bss.c \ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) diff --git a/windows/bss.c b/windows/bss.c new file mode 100644 index 000000000..b860c4ee8 --- /dev/null +++ b/windows/bss.c @@ -0,0 +1,74 @@ +/* +* This file is part of the Micro Python project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2013, 2014 Damien P. George +* +* 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 "mpconfig.h" +#include "misc.h" +#include "nlr.h" +#include "qstr.h" +#include "obj.h" +#include + +IMAGE_NT_HEADERS *header_from_memory(const char *module) { + BYTE *base_addr = (BYTE*)GetModuleHandleA(module); + IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER*)base_addr; + return (IMAGE_NT_HEADERS*)(base_addr + dos_header->e_lfanew); +} + +IMAGE_SECTION_HEADER *find_section(IMAGE_NT_HEADERS *nt_header, const char *name) { + int i; + IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION(nt_header); + for (i = 0; i < nt_header->FileHeader.NumberOfSections; ++i) { + if (strcmp((const char *)section->Name, name) == 0) { + return section; + } + ++section; + } + return NULL; +} + +void section_boundaries(IMAGE_NT_HEADERS *nt_header, IMAGE_SECTION_HEADER *section, char **start, char **end) { + if (section == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Could not lookup section boundaries")); + } + *start = (char*)(nt_header->OptionalHeader.ImageBase + section->VirtualAddress); + *end = *start + section->Misc.VirtualSize; +} + +void section_boundaries_from_module(const char *module, const char *section, char **start, char **end) { + IMAGE_NT_HEADERS *nt_header = header_from_memory(module); + IMAGE_SECTION_HEADER *dsection = find_section(nt_header, section); + section_boundaries(nt_header, dsection, start, end); +} + +char *bss_start = 0; +char *bss_end = 0; + +//MSVC has no __bss_start and _end but we can get accurate section info from the PE header. +//The standard .bss section is appended to the standard .data section however so it cannot +//be looked up by name. To deal with that we put all uPy static variables in a named section. +void getbss() { + section_boundaries_from_module(NULL, MICROPY_PORT_BSSSECTION, &bss_start, &bss_end); +} diff --git a/windows/init.c b/windows/init.c index a370c464e..57f349ef8 100644 --- a/windows/init.c +++ b/windows/init.c @@ -28,9 +28,12 @@ #include #include +extern void getbss(); + HANDLE hSleepEvent = NULL; void init() { + getbss(); hSleepEvent = CreateEvent(NULL, TRUE, FALSE, FALSE); #ifdef __MINGW32__ putenv("PRINTF_EXPONENT_DIGITS=2"); diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h index b9a50b084..c930fe95e 100644 --- a/windows/mpconfigport.h +++ b/windows/mpconfigport.h @@ -43,6 +43,12 @@ #define MICROPY_PY_CMATH (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_EXIT (1) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_PY_GC_COLLECT_RETVAL (1) +#ifdef _MSC_VER +#define MICROPY_GCREGS_SETJMP (1) +#endif #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_PORT_INIT_FUNC init() @@ -113,6 +119,14 @@ void msec_sleep(double msec); #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +// Put static/global variables in sections with a known name we can lookup for the GC +// For this to work this header must be included by all sources, which is the case normally +#define MICROPY_PORT_DATASECTION "upydata" +#define MICROPY_PORT_BSSSECTION "upybss" +#pragma data_seg(MICROPY_PORT_DATASECTION) +#pragma bss_seg(MICROPY_PORT_BSSSECTION) + + // System headers (needed e.g. for nlr.h) #include //for NULL @@ -122,3 +136,8 @@ void msec_sleep(double msec); int snprintf(char *dest, size_t count, const char *format, ...); #endif + +// MingW specifics +#ifdef __MINGW32__ +#define MICROPY_PORT_BSSSECTION ".bss" +#endif diff --git a/windows/msvc/common.props b/windows/msvc/common.props index 300de46a5..b6f22c615 100644 --- a/windows/msvc/common.props +++ b/windows/msvc/common.props @@ -16,7 +16,8 @@ true + true - \ No newline at end of file + diff --git a/windows/msvc/sources.props b/windows/msvc/sources.props index 8af03e756..6fd3306b9 100644 --- a/windows/msvc/sources.props +++ b/windows/msvc/sources.props @@ -5,7 +5,7 @@ - + From de5ce6d4613093f06de34746e865b32bcc243dd9 Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 19 Jun 2014 13:53:15 +0200 Subject: [PATCH 24/30] gc: Use simple cast instead of union to silence compiler --- unix/gccollect.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/unix/gccollect.c b/unix/gccollect.c index 792913821..f24cc5249 100644 --- a/unix/gccollect.c +++ b/unix/gccollect.c @@ -144,15 +144,7 @@ void gc_collect(void) { regs_t regs; gc_helper_get_regs(regs); // GC stack (and regs because we captured them) -#ifdef __MINGW32__ - // The Mingw cross-compiler on Travis complains - // 'warning: dereferencing type-punned pointer will break strict-aliasing rules' - // when casting ®s to void** directly so use a union. - union { regs_t *r; void **ptr; } cast_regs = { ®s }; - void **regs_ptr = cast_regs.ptr; -#else - void **regs_ptr = (void**)®s; -#endif + void **regs_ptr = (void**)(void*)®s; gc_collect_root(regs_ptr, ((machine_uint_t)stack_top - (machine_uint_t)®s) / sizeof(machine_uint_t)); gc_collect_end(); From 69d0a1c540da569e0a70d2102ed8463debfe3ccf Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 22 Jun 2014 19:08:32 +0300 Subject: [PATCH 25/30] unix: uClibc doesn't like NULL as a buffer arg to realpath(). So, allocate one explicitly. --- unix/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/unix/main.c b/unix/main.c index 26736e431..c04045a3a 100644 --- a/unix/main.c +++ b/unix/main.c @@ -365,7 +365,8 @@ int main(int argc, char **argv) { return usage(argv); } } else { - char *basedir = realpath(argv[a], NULL); + char *pathbuf = malloc(PATH_MAX); + char *basedir = realpath(argv[a], pathbuf); if (basedir == NULL) { fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[a], errno); perror(""); @@ -377,7 +378,7 @@ int main(int argc, char **argv) { // Set base dir of the script as first entry in sys.path char *p = strrchr(basedir, '/'); path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir)); - free(basedir); + free(pathbuf); for (int i = a; i < argc; i++) { mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); From 949a49c9da9f8adb64bdddbd8f0258eaa881df2f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 22 Jun 2014 19:11:34 +0300 Subject: [PATCH 26/30] modsocket: Add call to freeaddrinfo(). --- unix/modsocket.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/unix/modsocket.c b/unix/modsocket.c index 8c5c9706c..457dc8167 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -368,18 +368,18 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { } struct addrinfo hints; - struct addrinfo *addr; + struct addrinfo *addr_list; memset(&hints, 0, sizeof(hints)); - int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr); + int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr_list); if (res != 0) { // CPython: socket.gaierror nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res)); } - assert(addr); + assert(addr_list); mp_obj_t list = mp_obj_new_list(0, NULL); - for (; addr; addr = addr->ai_next) { + for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) { mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL); t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_family); t->items[1] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_socktype); @@ -394,6 +394,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr); mp_obj_list_append(list, t); } + freeaddrinfo(addr_list); return list; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 6, mod_socket_getaddrinfo); From ff5932a8d8d61351b2a9593ab407cc29c094109d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 22 Jun 2014 19:14:12 +0300 Subject: [PATCH 27/30] modsocket: Workaround uClibc issue with numeric port for getaddrinfo(). It sucks to workaround this on uPy side, but upgrading not upgradable embedded systems sucks even more. --- unix/modsocket.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/unix/modsocket.c b/unix/modsocket.c index 457dc8167..5dce46b2e 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -356,6 +356,8 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { const char *host = mp_obj_str_get_str(args[0]); const char *serv = NULL; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); // getaddrinfo accepts port in string notation, so however // it may seem stupid, we need to convert int to str if (MP_OBJ_IS_SMALL_INT(args[1])) { @@ -363,14 +365,24 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { char buf[6]; sprintf(buf, "%d", port); serv = buf; + hints.ai_flags = AI_NUMERICSERV; +#if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32)) +#warning Working around uClibc bug with numeric service name + // Older versions og uClibc have bugs when numeric ports in service + // arg require also hints.ai_socktype (or hints.ai_protocol) != 0 + // This actually was fixed in 0.9.32.1, but uClibc doesn't allow to + // test for that. + // http://git.uclibc.org/uClibc/commit/libc/inet/getaddrinfo.c?id=bc3be18145e4d5 + // Note that this is crude workaround, precluding UDP socket addresses + // to be returned. TODO: set only if not set by Python args. + hints.ai_socktype = SOCK_STREAM; +#endif } else { serv = mp_obj_str_get_str(args[1]); } - struct addrinfo hints; struct addrinfo *addr_list; - memset(&hints, 0, sizeof(hints)); - int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr_list); + int res = getaddrinfo(host, serv, &hints, &addr_list); if (res != 0) { // CPython: socket.gaierror From cd590cbfaaaabadb79a15fea7b974c6b85c9f077 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 22 Jun 2014 19:20:27 +0300 Subject: [PATCH 28/30] unix: Don't error out on #warning directive. --- unix/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/Makefile b/unix/Makefile index 9a85f59e1..afe268ae4 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -18,7 +18,7 @@ INC += -I$(PY_SRC) INC += -I$(BUILD) # compiler settings -CWARN = -Wall -Werror +CWARN = -Wall -Werror -Wno-error=cpp CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) # Debugging/Optimization From 141df2d35043feaefe895e0e96f030264f0bfd40 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 24 Jun 2014 16:58:00 +0300 Subject: [PATCH 29/30] unix: Dump default heap size in usage message. --- unix/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unix/main.c b/unix/main.c index c04045a3a..552df9b80 100644 --- a/unix/main.c +++ b/unix/main.c @@ -201,8 +201,8 @@ int usage(char **argv) { impl_opts_cnt++; #if MICROPY_ENABLE_GC printf( -" heapsize= -- set the heap size for the GC\n" -); +" heapsize= -- set the heap size for the GC (default %ld)\n" +, heap_size); impl_opts_cnt++; #endif From 3c9b24bebeb573d10c1187fcf40ec1e1bb1bd7f2 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 24 Jun 2014 21:20:38 +0300 Subject: [PATCH 30/30] modsocket: Fix uClibc detection. --- unix/modsocket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unix/modsocket.c b/unix/modsocket.c index 5dce46b2e..5b3fb0187 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -366,6 +366,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { sprintf(buf, "%d", port); serv = buf; hints.ai_flags = AI_NUMERICSERV; +#ifdef __UCLIBC_MAJOR__ #if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32)) #warning Working around uClibc bug with numeric service name // Older versions og uClibc have bugs when numeric ports in service @@ -376,6 +377,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { // Note that this is crude workaround, precluding UDP socket addresses // to be returned. TODO: set only if not set by Python args. hints.ai_socktype = SOCK_STREAM; +#endif #endif } else { serv = mp_obj_str_get_str(args[1]);