From 8c6856d2e76c5865d9f30cad2c51615d4a1a1418 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Sat, 3 Sep 2016 20:44:12 +1200 Subject: py/emitglue.c: provide mp_raw_code_load_file for any unix architecture Signed-off-by: Chris Packham --- py/emitglue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/emitglue.c b/py/emitglue.c index 0b5903092..f4b59df3e 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -379,7 +379,7 @@ mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) { // here we define mp_raw_code_load_file depending on the port // TODO abstract this away properly -#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || (defined(__arm__) && (defined(__unix__))) +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || defined(__unix__) // unix file reader #include -- cgit v1.2.3 From e2ac8bb3f14b076a29244022865e3b47c6c0800a Mon Sep 17 00:00:00 2001 From: Delio Brignoli Date: Sun, 21 Aug 2016 11:33:37 +0200 Subject: py: Add MICROPY_USE_INTERNAL_PRINTF option, defaults to enabled. This new config option allows to control whether MicroPython uses its own internal printf or not (if not, an external one should be linked in). Accompanying this new option is the inclusion of lib/utils/printf.c in the core list of source files, so that ports no longer need to include it themselves. --- bare-arm/mpconfigport.h | 1 + cc3200/application.mk | 1 - esp8266/Makefile | 1 - lib/utils/printf.c | 6 ++++++ minimal/Makefile | 1 - py/mpconfig.h | 5 +++++ py/py.mk | 1 + qemu-arm/mpconfigport.h | 1 + stmhal/Makefile | 1 - teensy/Makefile | 1 - unix/Makefile | 1 - 11 files changed, 14 insertions(+), 6 deletions(-) (limited to 'py') diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h index 7c448d13c..79b2b7328 100644 --- a/bare-arm/mpconfigport.h +++ b/bare-arm/mpconfigport.h @@ -42,6 +42,7 @@ #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#define MICROPY_USE_INTERNAL_PRINTF (0) // type definitions for the specific machine diff --git a/cc3200/application.mk b/cc3200/application.mk index dca6fcbc6..300262c97 100644 --- a/cc3200/application.mk +++ b/cc3200/application.mk @@ -154,7 +154,6 @@ APP_LIB_SRC_C = $(addprefix lib/,\ timeutils/timeutils.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ ) APP_STM_SRC_C = $(addprefix stmhal/,\ diff --git a/esp8266/Makefile b/esp8266/Makefile index 521cbb472..1dfcec809 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -128,7 +128,6 @@ LIB_SRC_C = $(addprefix lib/,\ timeutils/timeutils.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ fatfs/ff.c \ fatfs/option/ccsbcs.c \ ) diff --git a/lib/utils/printf.c b/lib/utils/printf.c index 308525b6e..303edfcca 100644 --- a/lib/utils/printf.c +++ b/lib/utils/printf.c @@ -24,6 +24,10 @@ * THE SOFTWARE. */ +#include "py/mpconfig.h" + +#if MICROPY_USE_INTERNAL_PRINTF + #include #include #include @@ -127,3 +131,5 @@ int snprintf(char *str, size_t size, const char *fmt, ...) { va_end(ap); return ret; } + +#endif //MICROPY_USE_INTERNAL_PRINTF diff --git a/minimal/Makefile b/minimal/Makefile index 02096f9f0..0cecd1c0f 100644 --- a/minimal/Makefile +++ b/minimal/Makefile @@ -46,7 +46,6 @@ SRC_C = \ main.c \ uart_core.c \ lib/utils/stdout_helpers.c \ - lib/utils/printf.c \ lib/utils/pyexec.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ diff --git a/py/mpconfig.h b/py/mpconfig.h index 455f870ac..e33a41f7a 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -581,6 +581,11 @@ typedef double mp_float_t; #define MICROPY_USE_INTERNAL_ERRNO (0) #endif +// Whether to use internally defined *printf() functions (otherwise external ones) +#ifndef MICROPY_USE_INTERNAL_PRINTF +#define MICROPY_USE_INTERNAL_PRINTF (1) +#endif + // Support for user-space VFS mount (selected ports) #ifndef MICROPY_FSUSERMOUNT #define MICROPY_FSUSERMOUNT (0) diff --git a/py/py.mk b/py/py.mk index abea7215b..37b98de92 100644 --- a/py/py.mk +++ b/py/py.mk @@ -223,6 +223,7 @@ PY_O_BASENAME = \ ../extmod/vfs_fat_misc.o \ ../extmod/moduos_dupterm.o \ ../lib/embed/abort_.o \ + ../lib/utils/printf.o \ # prepend the build destination prefix to the py object files PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME)) diff --git a/qemu-arm/mpconfigport.h b/qemu-arm/mpconfigport.h index 57277b156..1f23148c2 100644 --- a/qemu-arm/mpconfigport.h +++ b/qemu-arm/mpconfigport.h @@ -23,6 +23,7 @@ #define MICROPY_PY_IO (0) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) +#define MICROPY_USE_INTERNAL_PRINTF (0) // type definitions for the specific machine diff --git a/stmhal/Makefile b/stmhal/Makefile index e06eed1cc..881c073f1 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -111,7 +111,6 @@ SRC_LIB = $(addprefix lib/,\ timeutils/timeutils.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ ) SRC_C = \ diff --git a/teensy/Makefile b/teensy/Makefile index 7b34ba90e..0ab07121c 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -110,7 +110,6 @@ LIB_SRC_C = $(addprefix lib/,\ mp-readline/readline.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ ) SRC_TEENSY = $(addprefix core/,\ diff --git a/unix/Makefile b/unix/Makefile index 3afa80dfa..49b605f12 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -157,7 +157,6 @@ endif LIB_SRC_C = $(addprefix lib/,\ $(LIB_SRC_C_EXTRA) \ - utils/printf.c \ timeutils/timeutils.c \ ) -- cgit v1.2.3 From f3b19ef6347f41b073b27c7a83a12cfc1c7267b8 Mon Sep 17 00:00:00 2001 From: Antonin ENFRUN Date: Thu, 8 Sep 2016 00:02:17 +0200 Subject: py/asmthumb: Flush D-cache, and invalidate I-cache on STM32F7. Tested on a STM32F7DISCO at 216MHz. All tests generating code (inlineasm, native, viper) now pass, except pybnative/while.py, but that's because there is no LED(2). --- py/asmthumb.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'py') diff --git a/py/asmthumb.c b/py/asmthumb.c index 8341c958e..1aae3d38e 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -90,6 +90,15 @@ void asm_thumb_start_pass(asm_thumb_t *as, uint pass) { void asm_thumb_end_pass(asm_thumb_t *as) { (void)as; // could check labels are resolved... + + #if defined(MCU_SERIES_F7) + if (as->pass == ASM_THUMB_PASS_EMIT) { + // flush D-cache, so the code emited is stored in memory + SCB_CleanDCache_by_Addr((uint32_t*)as->code_base, as->code_size); + // invalidate I-cache + SCB_InvalidateICache(); + } + #endif } // all functions must go through this one to emit bytes -- cgit v1.2.3 From a50b26e4b00ed094aa1ac74eac2fc2d8eb9ea1ed Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 8 Sep 2016 20:34:34 +1200 Subject: py/makeqstrdefs.py: Use python 2.6 syntax for set creation. py/makeqstrdefs.py declares that it works with python 2.6 however the syntax used to initialise of a set with values was only added in python 2.7. This leads to build failures when the host system doesn't have python 2.7 or newer. Instead of using the new syntax pass a list of initial values through set() to achieve the same result. This should work for python versions from at least 2.6 onwards. Helped-by: Thomas Petazzoni Signed-off-by: Chris Packham --- py/makeqstrdefs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 69aaefb3e..92a19c392 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -11,7 +11,7 @@ import os # Blacklist of qstrings that are specially handled in further # processing and should be ignored -QSTRING_BLACK_LIST = {'NULL', 'number_of', } +QSTRING_BLACK_LIST = set(['NULL', 'number_of']) def write_out(fname, output): -- cgit v1.2.3 From f84b3416187c8144fd92e52d97a655a133d725b2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 16 Sep 2016 12:30:09 +1000 Subject: py/objnone: Remove unnecessary handling of MP_UNARY_OP_BOOL. bool(None) has a fast path in mp_obj_is_true so doesn't need to be handled in none_unary_op. The only caveat is that subclassing may bypass the mp_obj_is_true function, but actually you aren't allowed to subclass classes that have singleton instances like NoneType (see https://mail.python.org/pipermail/python-dev/2002-March/020822.html for reference on this point). --- py/objnone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/objnone.c b/py/objnone.c index 69eab03fe..74c02e4d2 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -46,7 +46,7 @@ STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ STATIC mp_obj_t none_unary_op(mp_uint_t op, mp_obj_t o_in) { (void)o_in; switch (op) { - case MP_UNARY_OP_BOOL: return mp_const_false; + // MP_UNARY_OP_BOOL is handled by a fast-path in mp_obj_is_true case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); default: return MP_OBJ_NULL; // op not supported } -- cgit v1.2.3 From f28efa19713977a61395b19fec1fe501aeee4c0e Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 17 Sep 2016 20:57:43 +0300 Subject: py: Move frozen modules rules from esp8266 port for reuse across ports. A port now just needs to define FROZEN_DIR var and add $(BUILD)/frozen.c to SRC_C to support frozen modules. --- esp8266/Makefile | 4 +--- py/mkenv.mk | 2 ++ py/mkrules.mk | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'py') diff --git a/esp8266/Makefile b/esp8266/Makefile index e13082e18..26b5e8626 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -171,9 +171,7 @@ endif $(BUILD)/uart.o: $(CONFVARS_FILE) -$(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(CONFVARS_FILE) - $(ECHO) "Generating $@" - $(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@ +FROZEN_EXTRA_DEPS = $(CONFVARS_FILE) # to build .mpy files from .py files $(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py diff --git a/py/mkenv.mk b/py/mkenv.mk index b7f8c2aff..e7262907c 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -58,6 +58,8 @@ CXX += -m32 LD += -m32 endif +MAKE_FROZEN = ../tools/make-frozen.py + all: .PHONY: all diff --git a/py/mkrules.mk b/py/mkrules.mk index a3a408dc8..26e4aeab3 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -100,6 +100,12 @@ $(OBJ_DIRS): $(HEADER_BUILD): $(MKDIR) -p $@ +ifneq ($(FROZEN_DIR),) +$(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DEPS) + $(ECHO) "Generating $@" + $(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@ +endif + ifneq ($(PROG),) # Build a standalone executable (unix does this) -- cgit v1.2.3 From a5624bf3818c573611b2b7bfc755e27de97f64e4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 18 Sep 2016 23:59:47 +1000 Subject: py: Combine 3 comprehension emit functions (list/dict/set) into 1. The 3 kinds of comprehensions are similar enough that merging their emit functions reduces code size. Decreases in code size in bytes are: bare-arm:24, minimal:96, unix(NDEBUG,x86-64):328, stmhal:80, esp8266:76. --- py/compile.c | 12 +++-------- py/emit.h | 8 ++----- py/emitbc.c | 37 +++++++++++++++---------------- py/emitnative.c | 67 ++++++++++++++++++++++++++------------------------------- 4 files changed, 54 insertions(+), 70 deletions(-) (limited to 'py') diff --git a/py/compile.c b/py/compile.c index c8b4e5470..7207ac2e0 100644 --- a/py/compile.c +++ b/py/compile.c @@ -2869,17 +2869,11 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn if (MP_PARSE_NODE_IS_NULL(pn_iter)) { // no more nested if/for; compile inner expression compile_node(comp, pn_inner_expr); - if (comp->scope_cur->kind == SCOPE_LIST_COMP) { - EMIT_ARG(list_append, for_depth + 2); - } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) { - EMIT_ARG(map_add, for_depth + 2); - #if MICROPY_PY_BUILTINS_SET - } else if (comp->scope_cur->kind == SCOPE_SET_COMP) { - EMIT_ARG(set_add, for_depth + 2); - #endif - } else { + if (comp->scope_cur->kind == SCOPE_GEN_EXPR) { EMIT(yield_value); EMIT(pop_top); + } else { + EMIT_ARG(store_comp, comp->scope_cur->kind, for_depth + 2); } } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) { // if condition diff --git a/py/emit.h b/py/emit.h index 9121e719f..2b87e2c77 100644 --- a/py/emit.h +++ b/py/emit.h @@ -119,17 +119,15 @@ typedef struct _emit_method_table_t { void (*binary_op)(emit_t *emit, mp_binary_op_t op); void (*build_tuple)(emit_t *emit, mp_uint_t n_args); void (*build_list)(emit_t *emit, mp_uint_t n_args); - void (*list_append)(emit_t *emit, mp_uint_t list_stack_index); void (*build_map)(emit_t *emit, mp_uint_t n_args); void (*store_map)(emit_t *emit); - void (*map_add)(emit_t *emit, mp_uint_t map_stack_index); #if MICROPY_PY_BUILTINS_SET void (*build_set)(emit_t *emit, mp_uint_t n_args); - void (*set_add)(emit_t *emit, mp_uint_t set_stack_index); #endif #if MICROPY_PY_BUILTINS_SLICE void (*build_slice)(emit_t *emit, mp_uint_t n_args); #endif + void (*store_comp)(emit_t *emit, scope_kind_t kind, mp_uint_t set_stack_index); void (*unpack_sequence)(emit_t *emit, mp_uint_t n_args); void (*unpack_ex)(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void (*make_function)(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); @@ -240,17 +238,15 @@ void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op); void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op); void mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args); -void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index); void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_store_map(emit_t *emit); -void mp_emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index); #if MICROPY_PY_BUILTINS_SET void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args); -void mp_emit_bc_set_add(emit_t *emit, mp_uint_t set_stack_index); #endif #if MICROPY_PY_BUILTINS_SLICE void mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args); #endif +void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t list_stack_index); void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); diff --git a/py/emitbc.c b/py/emitbc.c index d871aa4ce..11d04c511 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -837,11 +837,6 @@ void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args) { emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_LIST, n_args); } -void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index); -} - void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, 1); emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args); @@ -852,21 +847,11 @@ void mp_emit_bc_store_map(emit_t *emit) { emit_write_bytecode_byte(emit, MP_BC_STORE_MAP); } -void mp_emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index) { - emit_bc_pre(emit, -2); - emit_write_bytecode_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index); -} - #if MICROPY_PY_BUILTINS_SET void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, 1 - n_args); emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_SET, n_args); } - -void mp_emit_bc_set_add(emit_t *emit, mp_uint_t set_stack_index) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_uint(emit, MP_BC_SET_ADD, set_stack_index); -} #endif #if MICROPY_PY_BUILTINS_SLICE @@ -876,6 +861,24 @@ void mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args) { } #endif +void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) { + int n; + byte opcode; + if (kind == SCOPE_LIST_COMP) { + n = -1; + opcode = MP_BC_LIST_APPEND; + } else if (MICROPY_PY_BUILTINS_SET && kind == SCOPE_SET_COMP) { + n = -1; + opcode = MP_BC_SET_ADD; + } else { + // scope == SCOPE_DICT_COMP + n = -2; + opcode = MP_BC_MAP_ADD; + } + emit_bc_pre(emit, n); + emit_write_bytecode_byte_uint(emit, opcode, collection_stack_index); +} + void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, -1 + n_args); emit_write_bytecode_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args); @@ -1028,17 +1031,15 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_binary_op, mp_emit_bc_build_tuple, mp_emit_bc_build_list, - mp_emit_bc_list_append, mp_emit_bc_build_map, mp_emit_bc_store_map, - mp_emit_bc_map_add, #if MICROPY_PY_BUILTINS_SET mp_emit_bc_build_set, - mp_emit_bc_set_add, #endif #if MICROPY_PY_BUILTINS_SLICE mp_emit_bc_build_slice, #endif + mp_emit_bc_store_comp, mp_emit_bc_unpack_sequence, mp_emit_bc_unpack_ex, mp_emit_bc_make_function, diff --git a/py/emitnative.c b/py/emitnative.c index 2cf4711fe..b54f263d6 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -2344,17 +2344,6 @@ STATIC void emit_native_build_list(emit_t *emit, mp_uint_t n_args) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list } -STATIC void emit_native_list_append(emit_t *emit, mp_uint_t list_index) { - // only used in list comprehension - vtype_kind_t vtype_list, vtype_item; - emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); - emit_access_stack(emit, list_index, &vtype_list, REG_ARG_1); - assert(vtype_list == VTYPE_PYOBJ); - assert(vtype_item == VTYPE_PYOBJ); - emit_call(emit, MP_F_LIST_APPEND); - emit_post(emit); -} - STATIC void emit_native_build_map(emit_t *emit, mp_uint_t n_args) { emit_native_pre(emit); emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, n_args, REG_ARG_1); @@ -2371,18 +2360,6 @@ STATIC void emit_native_store_map(emit_t *emit) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map } -STATIC void emit_native_map_add(emit_t *emit, mp_uint_t map_index) { - // only used in list comprehension - vtype_kind_t vtype_map, vtype_key, vtype_value; - emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3); - emit_access_stack(emit, map_index, &vtype_map, REG_ARG_1); - assert(vtype_map == VTYPE_PYOBJ); - assert(vtype_key == VTYPE_PYOBJ); - assert(vtype_value == VTYPE_PYOBJ); - emit_call(emit, MP_F_STORE_MAP); - emit_post(emit); -} - #if MICROPY_PY_BUILTINS_SET STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) { emit_native_pre(emit); @@ -2390,17 +2367,6 @@ STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) { emit_call_with_imm_arg(emit, MP_F_BUILD_SET, n_args, REG_ARG_1); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set } - -STATIC void emit_native_set_add(emit_t *emit, mp_uint_t set_index) { - // only used in set comprehension - vtype_kind_t vtype_set, vtype_item; - emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); - emit_access_stack(emit, set_index, &vtype_set, REG_ARG_1); - assert(vtype_set == VTYPE_PYOBJ); - assert(vtype_item == VTYPE_PYOBJ); - emit_call(emit, MP_F_STORE_SET); - emit_post(emit); -} #endif #if MICROPY_PY_BUILTINS_SLICE @@ -2426,6 +2392,35 @@ STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) { } #endif +STATIC void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_index) { + mp_fun_kind_t f; + if (kind == SCOPE_LIST_COMP) { + vtype_kind_t vtype_item; + emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); + assert(vtype_item == VTYPE_PYOBJ); + f = MP_F_LIST_APPEND; + #if MICROPY_PY_BUILTINS_SET + } else if (kind == SCOPE_SET_COMP) { + vtype_kind_t vtype_item; + emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); + assert(vtype_item == VTYPE_PYOBJ); + f = MP_F_STORE_SET; + #endif + } else { + // SCOPE_DICT_COMP + vtype_kind_t vtype_key, vtype_value; + emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3); + assert(vtype_key == VTYPE_PYOBJ); + assert(vtype_value == VTYPE_PYOBJ); + f = MP_F_STORE_MAP; + } + vtype_kind_t vtype_collection; + emit_access_stack(emit, collection_index, &vtype_collection, REG_ARG_1); + assert(vtype_collection == VTYPE_PYOBJ); + emit_call(emit, f); + emit_post(emit); +} + STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) { DEBUG_printf("unpack_sequence %d\n", n_args); vtype_kind_t vtype_base; @@ -2674,17 +2669,15 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_binary_op, emit_native_build_tuple, emit_native_build_list, - emit_native_list_append, emit_native_build_map, emit_native_store_map, - emit_native_map_add, #if MICROPY_PY_BUILTINS_SET emit_native_build_set, - emit_native_set_add, #endif #if MICROPY_PY_BUILTINS_SLICE emit_native_build_slice, #endif + emit_native_store_comp, emit_native_unpack_sequence, emit_native_unpack_ex, emit_native_make_function, -- cgit v1.2.3 From adaf0d865cd6c81fb352751566460506392ed55f Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Sep 2016 08:46:01 +1000 Subject: py: Combine 3 comprehension opcodes (list/dict/set) into 1. With the previous patch combining 3 emit functions into 1, it now makes sense to also combine the corresponding VM opcodes, which is what this patch does. This eliminates 2 opcodes which simplifies the VM and reduces code size, in bytes: bare-arm:44, minimal:64, unix(NDEBUG,x86-64):272, stmhal:92, esp8266:200. Profiling (with a simple script that creates many list/dict/set comprehensions) shows no measurable change in performance. --- py/bc0.h | 4 +--- py/emitbc.c | 24 ++++++++++++------------ py/showbc.c | 20 +++++--------------- py/vm.c | 46 +++++++++++++++++++--------------------------- py/vmentrytable.h | 4 +--- 5 files changed, 38 insertions(+), 60 deletions(-) (limited to 'py') diff --git a/py/bc0.h b/py/bc0.h index b0b7d5c79..5ff9e50a8 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -82,13 +82,11 @@ #define MP_BC_BUILD_TUPLE (0x50) // uint #define MP_BC_BUILD_LIST (0x51) // uint -#define MP_BC_LIST_APPEND (0x52) // uint #define MP_BC_BUILD_MAP (0x53) // uint #define MP_BC_STORE_MAP (0x54) -#define MP_BC_MAP_ADD (0x55) // uint #define MP_BC_BUILD_SET (0x56) // uint -#define MP_BC_SET_ADD (0x57) // uint #define MP_BC_BUILD_SLICE (0x58) // uint +#define MP_BC_STORE_COMP (0x57) // uint #define MP_BC_UNPACK_SEQUENCE (0x59) // uint #define MP_BC_UNPACK_EX (0x5a) // uint diff --git a/py/emitbc.c b/py/emitbc.c index 11d04c511..8c712e1fd 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -862,21 +862,21 @@ void mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args) { #endif void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) { + int t; int n; - byte opcode; if (kind == SCOPE_LIST_COMP) { - n = -1; - opcode = MP_BC_LIST_APPEND; - } else if (MICROPY_PY_BUILTINS_SET && kind == SCOPE_SET_COMP) { - n = -1; - opcode = MP_BC_SET_ADD; - } else { - // scope == SCOPE_DICT_COMP - n = -2; - opcode = MP_BC_MAP_ADD; + n = 0; + t = 0; + } else if (!MICROPY_PY_BUILTINS_SET || kind == SCOPE_DICT_COMP) { + n = 1; + t = 1; + } else if (MICROPY_PY_BUILTINS_SET) { + n = 0; + t = 2; } - emit_bc_pre(emit, n); - emit_write_bytecode_byte_uint(emit, opcode, collection_stack_index); + emit_bc_pre(emit, -1 - n); + // the lower 2 bits of the opcode argument indicate the collection type + emit_write_bytecode_byte_uint(emit, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t); } void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) { diff --git a/py/showbc.c b/py/showbc.c index dd5959f4a..0f335ffef 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -409,11 +409,6 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("BUILD_LIST " UINT_FMT, unum); break; - case MP_BC_LIST_APPEND: - DECODE_UINT; - printf("LIST_APPEND " UINT_FMT, unum); - break; - case MP_BC_BUILD_MAP: DECODE_UINT; printf("BUILD_MAP " UINT_FMT, unum); @@ -423,21 +418,11 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("STORE_MAP"); break; - case MP_BC_MAP_ADD: - DECODE_UINT; - printf("MAP_ADD " UINT_FMT, unum); - break; - case MP_BC_BUILD_SET: DECODE_UINT; printf("BUILD_SET " UINT_FMT, unum); break; - case MP_BC_SET_ADD: - DECODE_UINT; - printf("SET_ADD " UINT_FMT, unum); - break; - #if MICROPY_PY_BUILTINS_SLICE case MP_BC_BUILD_SLICE: DECODE_UINT; @@ -445,6 +430,11 @@ const byte *mp_bytecode_print_str(const byte *ip) { break; #endif + case MP_BC_STORE_COMP: + DECODE_UINT; + printf("STORE_COMP " UINT_FMT, unum); + break; + case MP_BC_UNPACK_SEQUENCE: DECODE_UINT; printf("UNPACK_SEQUENCE " UINT_FMT, unum); diff --git a/py/vm.c b/py/vm.c index f9bdedff8..da8697fad 100644 --- a/py/vm.c +++ b/py/vm.c @@ -777,15 +777,6 @@ unwind_jump:; DISPATCH(); } - ENTRY(MP_BC_LIST_APPEND): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[unum] is a list - mp_obj_list_append(sp[-unum], sp[0]); - sp--; - DISPATCH(); - } - ENTRY(MP_BC_BUILD_MAP): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; @@ -799,15 +790,6 @@ unwind_jump:; mp_obj_dict_store(sp[0], sp[2], sp[1]); DISPATCH(); - ENTRY(MP_BC_MAP_ADD): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[-unum - 1] is a map - mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]); - sp -= 2; - DISPATCH(); - } - #if MICROPY_PY_BUILTINS_SET ENTRY(MP_BC_BUILD_SET): { MARK_EXC_IP_SELECTIVE(); @@ -816,15 +798,6 @@ unwind_jump:; SET_TOP(mp_obj_new_set(unum, sp)); DISPATCH(); } - - ENTRY(MP_BC_SET_ADD): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[-unum] is a set - mp_obj_set_store(sp[-unum], sp[0]); - sp--; - DISPATCH(); - } #endif #if MICROPY_PY_BUILTINS_SLICE @@ -845,6 +818,25 @@ unwind_jump:; } #endif + ENTRY(MP_BC_STORE_COMP): { + MARK_EXC_IP_SELECTIVE(); + DECODE_UINT; + mp_obj_t obj = sp[-(unum >> 2)]; + if ((unum & 3) == 0) { + mp_obj_list_append(obj, sp[0]); + sp--; + } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) { + mp_obj_dict_store(obj, sp[0], sp[-1]); + sp -= 2; + #if MICROPY_PY_BUILTINS_SET + } else { + mp_obj_set_store(obj, sp[0]); + sp--; + #endif + } + DISPATCH(); + } + ENTRY(MP_BC_UNPACK_SEQUENCE): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; diff --git a/py/vmentrytable.h b/py/vmentrytable.h index 9df1e40a3..dd30dd7a5 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -78,17 +78,15 @@ static const void *const entry_table[256] = { [MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT, [MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE, [MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST, - [MP_BC_LIST_APPEND] = &&entry_MP_BC_LIST_APPEND, [MP_BC_BUILD_MAP] = &&entry_MP_BC_BUILD_MAP, [MP_BC_STORE_MAP] = &&entry_MP_BC_STORE_MAP, - [MP_BC_MAP_ADD] = &&entry_MP_BC_MAP_ADD, #if MICROPY_PY_BUILTINS_SET [MP_BC_BUILD_SET] = &&entry_MP_BC_BUILD_SET, - [MP_BC_SET_ADD] = &&entry_MP_BC_SET_ADD, #endif #if MICROPY_PY_BUILTINS_SLICE [MP_BC_BUILD_SLICE] = &&entry_MP_BC_BUILD_SLICE, #endif + [MP_BC_STORE_COMP] = &&entry_MP_BC_STORE_COMP, [MP_BC_UNPACK_SEQUENCE] = &&entry_MP_BC_UNPACK_SEQUENCE, [MP_BC_UNPACK_EX] = &&entry_MP_BC_UNPACK_EX, [MP_BC_MAKE_FUNCTION] = &&entry_MP_BC_MAKE_FUNCTION, -- cgit v1.2.3 From 5da0d29d3cefa6a3cac52e0db96e9ede820d6a51 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Sep 2016 11:17:02 +1000 Subject: py/vstr: Remove vstr.had_error flag and inline basic vstr functions. The vstr.had_error flag was a relic from the very early days which assumed that the malloc functions (eg m_new, m_renew) returned NULL if they failed to allocate. But that's no longer the case: these functions will raise an exception if they fail. Since it was impossible for had_error to be set, this patch introduces no change in behaviour. An alternative option would be to change the malloc calls to the _maybe variants, which return NULL instead of raising, but then a lot of code will need to explicitly check if the vstr had an error and raise if it did. The code-size savings for this patch are, in bytes: bare-arm:188, minimal:456, unix(NDEBUG,x86-64):368, stmhal:228, esp8266:360. --- py/lexer.c | 3 ++- py/misc.h | 8 +++----- py/vstr.c | 55 +++---------------------------------------------------- 3 files changed, 8 insertions(+), 58 deletions(-) (limited to 'py') diff --git a/py/lexer.c b/py/lexer.c index 820f91be7..b2c9c5ff7 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -723,7 +723,8 @@ mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_ vstr_init(&lex->vstr, 32); // check for memory allocation error - if (lex->indent_level == NULL || vstr_had_error(&lex->vstr)) { + // note: vstr_init above may fail on malloc, but so may mp_lexer_next_token_into below + if (lex->indent_level == NULL) { mp_lexer_free(lex); return NULL; } diff --git a/py/misc.h b/py/misc.h index 79a4c1c6e..3ed227a35 100644 --- a/py/misc.h +++ b/py/misc.h @@ -139,7 +139,6 @@ typedef struct _vstr_t { size_t alloc; size_t len; char *buf; - bool had_error : 1; bool fixed_buf : 1; } vstr_t; @@ -155,10 +154,9 @@ void vstr_clear(vstr_t *vstr); vstr_t *vstr_new(void); vstr_t *vstr_new_size(size_t alloc); void vstr_free(vstr_t *vstr); -void vstr_reset(vstr_t *vstr); -bool vstr_had_error(vstr_t *vstr); -char *vstr_str(vstr_t *vstr); -size_t vstr_len(vstr_t *vstr); +static inline void vstr_reset(vstr_t *vstr) { vstr->len = 0; } +static inline char *vstr_str(vstr_t *vstr) { return vstr->buf; } +static inline size_t vstr_len(vstr_t *vstr) { return vstr->len; } void vstr_hint_size(vstr_t *vstr, size_t size); char *vstr_extend(vstr_t *vstr, size_t size); char *vstr_add_len(vstr_t *vstr, size_t len); diff --git a/py/vstr.c b/py/vstr.c index cf10f8471..5096475f1 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -44,11 +44,6 @@ void vstr_init(vstr_t *vstr, size_t alloc) { vstr->alloc = alloc; vstr->len = 0; vstr->buf = m_new(char, vstr->alloc); - if (vstr->buf == NULL) { - vstr->had_error = true; - return; - } - vstr->had_error = false; vstr->fixed_buf = false; } @@ -63,7 +58,6 @@ void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) { vstr->alloc = alloc; vstr->len = 0; vstr->buf = buf; - vstr->had_error = false; vstr->fixed_buf = true; } @@ -107,39 +101,12 @@ void vstr_free(vstr_t *vstr) { } } -void vstr_reset(vstr_t *vstr) { - vstr->len = 0; - vstr->had_error = false; -} - -bool vstr_had_error(vstr_t *vstr) { - return vstr->had_error; -} - -char *vstr_str(vstr_t *vstr) { - if (vstr->had_error) { - return NULL; - } - return vstr->buf; -} - -size_t vstr_len(vstr_t *vstr) { - if (vstr->had_error) { - return 0; - } - return vstr->len; -} - // Extend vstr strictly by requested size, return pointer to newly added chunk. char *vstr_extend(vstr_t *vstr, size_t size) { if (vstr->fixed_buf) { return NULL; } char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size); - if (new_buf == NULL) { - vstr->had_error = true; - return NULL; - } char *p = new_buf + vstr->alloc; vstr->alloc += size; vstr->buf = new_buf; @@ -153,10 +120,6 @@ STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) { } size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16); char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc); - if (new_buf == NULL) { - vstr->had_error = true; - return false; - } vstr->alloc = new_alloc; vstr->buf = new_buf; } @@ -164,14 +127,11 @@ STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) { } void vstr_hint_size(vstr_t *vstr, size_t size) { - // it's not an error if we fail to allocate for the size hint - bool er = vstr->had_error; vstr_ensure_extra(vstr, size); - vstr->had_error = er; } char *vstr_add_len(vstr_t *vstr, size_t len) { - if (vstr->had_error || !vstr_ensure_extra(vstr, len)) { + if (!vstr_ensure_extra(vstr, len)) { return NULL; } char *buf = vstr->buf + vstr->len; @@ -181,9 +141,6 @@ char *vstr_add_len(vstr_t *vstr, size_t len) { // Doesn't increase len, just makes sure there is a null byte at the end char *vstr_null_terminated_str(vstr_t *vstr) { - if (vstr->had_error) { - return NULL; - } // If there's no more room, add single byte if (vstr->alloc == vstr->len) { if (vstr_extend(vstr, 1) == NULL) { @@ -248,7 +205,7 @@ void vstr_add_str(vstr_t *vstr, const char *str) { } void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) { - if (vstr->had_error || !vstr_ensure_extra(vstr, len)) { + if (!vstr_ensure_extra(vstr, len)) { // if buf is fixed, we got here because there isn't enough room left // so just try to copy as much as we can, with room for a possible null byte if (vstr->fixed_buf && vstr->len < vstr->alloc) { @@ -263,9 +220,6 @@ copy: } STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) { - if (vstr->had_error) { - return NULL; - } size_t l = vstr->len; if (byte_pos > l) { byte_pos = l; @@ -303,9 +257,6 @@ void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) { } void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) { - if (vstr->had_error) { - return; - } if (len > vstr->len) { vstr->len = 0; } else { @@ -314,7 +265,7 @@ void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) { } void vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut) { - if (vstr->had_error || byte_pos >= vstr->len) { + if (byte_pos >= vstr->len) { return; } else if (byte_pos + bytes_to_cut >= vstr->len) { vstr->len = byte_pos; -- cgit v1.2.3 From 8dd5960ac0853ca2a73dd394511f80f3dd3d38cb Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Sep 2016 12:20:41 +1000 Subject: py/objnone: Use mp_generic_unary_op instead of custom one. --- py/objnone.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'py') diff --git a/py/objnone.c b/py/objnone.c index 74c02e4d2..5d5b83540 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -43,20 +43,11 @@ STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ } } -STATIC mp_obj_t none_unary_op(mp_uint_t op, mp_obj_t o_in) { - (void)o_in; - switch (op) { - // MP_UNARY_OP_BOOL is handled by a fast-path in mp_obj_is_true - case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); - default: return MP_OBJ_NULL; // op not supported - } -} - const mp_obj_type_t mp_type_NoneType = { { &mp_type_type }, .name = MP_QSTR_NoneType, .print = none_print, - .unary_op = none_unary_op, + .unary_op = mp_generic_unary_op, }; const mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}}; -- cgit v1.2.3 From e60835bac5336c8e0123443b427c6db48b5060df Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Sep 2016 13:18:54 +1000 Subject: py/qstr: Remove a comment. qstrs are always null terminated so qstr_str will stay as part of the API. --- py/qstr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'py') diff --git a/py/qstr.c b/py/qstr.c index 079b2a8e7..28df06ca3 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -275,7 +275,6 @@ size_t qstr_len(qstr q) { return Q_GET_LENGTH(qd); } -// XXX to remove! const char *qstr_str(qstr q) { const byte *qd = find_qstr(q); return (const char*)Q_GET_DATA(qd); -- cgit v1.2.3