From dbcdb9f8d8d5dd56ede1f0705355679a11b75658 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 16 Feb 2017 16:34:53 +1100 Subject: py/objfun: Convert mp_uint_t to size_t where appropriate. --- py/objfun.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'py/objfun.c') diff --git a/py/objfun.c b/py/objfun.c index 207e68a77..e5f6009dc 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -181,9 +181,9 @@ STATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t #endif #if DEBUG_PRINT -STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) { +STATIC void dump_args(const mp_obj_t *a, size_t sz) { DEBUG_printf("%p: ", a); - for (mp_uint_t i = 0; i < sz; i++) { + for (size_t i = 0; i < sz; i++) { DEBUG_printf("%p ", a[i]); } DEBUG_printf("\n"); @@ -247,15 +247,15 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const const byte *ip = self->bytecode; // bytecode prelude: state size and exception stack size - mp_uint_t n_state = mp_decode_uint(&ip); - mp_uint_t n_exc_stack = mp_decode_uint(&ip); + size_t n_state = mp_decode_uint(&ip); + size_t n_exc_stack = mp_decode_uint(&ip); #if VM_DETECT_STACK_OVERFLOW n_state += 1; #endif // allocate state for locals and stack - mp_uint_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); + size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); mp_code_state_t *code_state = NULL; if (state_size > VM_MAX_STATE_ON_STACK) { code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); @@ -288,7 +288,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && self->n_pos_args + self->n_kwonly_args == 0)) { // Just check to see that we have at least 1 null object left in the state. bool overflow = true; - for (mp_uint_t i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) { + for (size_t i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) { if (code_state->state[i] == MP_OBJ_NULL) { overflow = false; break; @@ -350,8 +350,8 @@ const mp_obj_type_t mp_type_fun_bc = { }; mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table) { - mp_uint_t n_def_args = 0; - mp_uint_t n_extra_args = 0; + size_t n_def_args = 0; + size_t n_extra_args = 0; mp_obj_tuple_t *def_args = MP_OBJ_TO_PTR(def_args_in); if (def_args_in != MP_OBJ_NULL) { assert(MP_OBJ_IS_TYPE(def_args_in, &mp_type_tuple)); @@ -409,7 +409,7 @@ mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const typedef struct _mp_obj_fun_viper_t { mp_obj_base_t base; - mp_uint_t n_args; + size_t n_args; void *fun_data; // GC must be able to trace this pointer mp_uint_t type_sig; } mp_obj_fun_viper_t; @@ -457,7 +457,7 @@ STATIC const mp_obj_type_t mp_type_fun_viper = { .unary_op = mp_generic_unary_op, }; -mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig) { +mp_obj_t mp_obj_new_fun_viper(size_t n_args, void *fun_data, mp_uint_t type_sig) { mp_obj_fun_viper_t *o = m_new_obj(mp_obj_fun_viper_t); o->base.type = &mp_type_fun_viper; o->n_args = n_args; @@ -475,7 +475,7 @@ mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_s typedef struct _mp_obj_fun_asm_t { mp_obj_base_t base; - mp_uint_t n_args; + size_t n_args; void *fun_data; // GC must be able to trace this pointer mp_uint_t type_sig; } mp_obj_fun_asm_t; @@ -573,7 +573,7 @@ STATIC const mp_obj_type_t mp_type_fun_asm = { .unary_op = mp_generic_unary_op, }; -mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig) { +mp_obj_t mp_obj_new_fun_asm(size_t n_args, void *fun_data, mp_uint_t type_sig) { mp_obj_fun_asm_t *o = m_new_obj(mp_obj_fun_asm_t); o->base.type = &mp_type_fun_asm; o->n_args = n_args; -- cgit v1.2.3 From 7e480e8a30e5e293586bd4806f02a481a08648ca Mon Sep 17 00:00:00 2001 From: Krzysztof Blazewicz Date: Sat, 4 Mar 2017 12:29:20 +0100 Subject: py: Use mp_obj_get_array where sequence may be a tuple or a list. --- py/objfun.c | 10 ++-------- py/objstr.c | 15 ++++++--------- py/runtime.c | 12 ++---------- 3 files changed, 10 insertions(+), 27 deletions(-) (limited to 'py/objfun.c') diff --git a/py/objfun.c b/py/objfun.c index e5f6009dc..a823f49e5 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -511,17 +511,11 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { // convert float to int (could also pass in float registers) return (mp_int_t)mp_obj_float_get(obj); #endif - } else if (type == &mp_type_tuple) { + } else if (type == &mp_type_tuple || type == &mp_type_list) { // pointer to start of tuple (could pass length, but then could use len(x) for that) mp_uint_t len; mp_obj_t *items; - mp_obj_tuple_get(obj, &len, &items); - return (mp_uint_t)items; - } else if (type == &mp_type_list) { - // pointer to start of list (could pass length, but then could use len(x) for that) - mp_uint_t len; - mp_obj_t *items; - mp_obj_list_get(obj, &len, &items); + mp_obj_get_array(obj, &len, &items); return (mp_uint_t)items; } else { mp_buffer_info_t bufinfo; diff --git a/py/objstr.c b/py/objstr.c index c137afe67..17d06f88e 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -430,16 +430,13 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { // process args mp_uint_t seq_len; mp_obj_t *seq_items; - if (MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) { - mp_obj_tuple_get(arg, &seq_len, &seq_items); - } else { - if (!MP_OBJ_IS_TYPE(arg, &mp_type_list)) { - // arg is not a list, try to convert it to one - // TODO: Try to optimize? - arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg); - } - mp_obj_list_get(arg, &seq_len, &seq_items); + + if (!MP_OBJ_IS_TYPE(arg, &mp_type_list) && !MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) { + // arg is not a list nor a tuple, try to convert it to a list + // TODO: Try to optimize? + arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg); } + mp_obj_get_array(arg, &seq_len, &seq_items); // count required length size_t required_len = 0; diff --git a/py/runtime.c b/py/runtime.c index 0f8044c8d..1f69290ba 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -797,11 +797,7 @@ void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) { mp_uint_t seq_len; if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) { mp_obj_t *seq_items; - if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) { - mp_obj_tuple_get(seq_in, &seq_len, &seq_items); - } else { - mp_obj_list_get(seq_in, &seq_len, &seq_items); - } + mp_obj_get_array(seq_in, &seq_len, &seq_items); if (seq_len < num) { goto too_short; } else if (seq_len > num) { @@ -851,11 +847,7 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) { mp_uint_t seq_len; if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) { mp_obj_t *seq_items; - if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) { - mp_obj_tuple_get(seq_in, &seq_len, &seq_items); - } else { - mp_obj_list_get(seq_in, &seq_len, &seq_items); - } + mp_obj_get_array(seq_in, &seq_len, &seq_items); if (seq_len < num_left + num_right) { goto too_short; } -- cgit v1.2.3 From 71a3d6ec3bd02c5bd13334537e1bd146bb643bad Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Mar 2017 14:54:53 +1100 Subject: py: Reduce size of mp_code_state_t structure. Instead of caching data that is constant (code_info, const_table and n_state), store just a pointer to the underlying function object from which this data can be derived. This helps reduce stack usage for the case when the mp_code_state_t structure is stored on the stack, as well as heap usage when it's stored on the heap. The downside is that the VM becomes a little more complex because it now needs to derive the data from the underlying function object. But this doesn't impact the performance by much (if at all) because most of the decoding of data is done outside the main opcode loop. Measurements using pystone show that little to no performance is lost. This patch also fixes a nasty bug whereby the bytecode can be reclaimed by the GC during execution. With this patch there is always a pointer to the function object held by the VM during execution, since it's stored in the mp_code_state_t structure. --- py/bc.c | 22 +++++++++++----------- py/bc.h | 12 +++++++----- py/emitnative.c | 35 ++++++++++++----------------------- py/objfun.c | 12 ++++++------ py/objgenerator.c | 15 +++++++++------ py/vm.c | 25 +++++++++++++++++-------- 6 files changed, 62 insertions(+), 59 deletions(-) (limited to 'py/objfun.c') diff --git a/py/bc.c b/py/bc.c index 07de08fc3..db5d0e686 100644 --- a/py/bc.c +++ b/py/bc.c @@ -86,25 +86,26 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) { // On entry code_state should be allocated somewhere (stack/heap) and // contain the following valid entries: -// - code_state->ip should contain the offset in bytes from the start of -// the bytecode chunk to just after n_state and n_exc_stack -// - code_state->n_state should be set to the state size (locals plus stack) -void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { +// - code_state->fun_bc should contain a pointer to the function object +// - code_state->ip should contain the offset in bytes from the pointer +// code_state->fun_bc->bytecode to the entry n_state (0 for bytecode, non-zero for native) +void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) { // This function is pretty complicated. It's main aim is to be efficient in speed and RAM // usage for the common case of positional only args. - size_t n_state = code_state->n_state; + + // get the function object that we want to set up (could be bytecode or native code) + mp_obj_fun_bc_t *self = code_state->fun_bc; // ip comes in as an offset into bytecode, so turn it into a true pointer code_state->ip = self->bytecode + (size_t)code_state->ip; - // store pointer to constant table - code_state->const_table = self->const_table; - #if MICROPY_STACKLESS code_state->prev = NULL; #endif // get params + size_t n_state = mp_decode_uint(&code_state->ip); + mp_decode_uint(&code_state->ip); // skip n_exc_stack size_t scope_flags = *code_state->ip++; size_t n_pos_args = *code_state->ip++; size_t n_kwonly_args = *code_state->ip++; @@ -168,7 +169,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, siz } // get pointer to arg_names array - const mp_obj_t *arg_names = (const mp_obj_t*)code_state->const_table; + const mp_obj_t *arg_names = (const mp_obj_t*)self->const_table; for (size_t i = 0; i < n_kw; i++) { // the keys in kwargs are expected to be qstr objects @@ -244,9 +245,8 @@ continue2:; // get the ip and skip argument names const byte *ip = code_state->ip; - // store pointer to code_info and jump over it + // jump over code info (source file and line-number mapping) { - code_state->code_info = ip; const byte *ip2 = ip; size_t code_info_size = mp_decode_uint(&ip2); ip += code_info_size; diff --git a/py/bc.h b/py/bc.h index c7dffbac5..996b1a2f3 100644 --- a/py/bc.h +++ b/py/bc.h @@ -28,6 +28,7 @@ #include "py/runtime.h" #include "py/obj.h" +#include "py/objfun.h" // bytecode layout: // @@ -70,9 +71,12 @@ typedef struct _mp_exc_stack_t { } mp_exc_stack_t; typedef struct _mp_code_state_t { - const byte *code_info; + // The fun_bc entry points to the underlying function object that is being executed. + // It is needed to access the start of bytecode and the const_table. + // It is also needed to prevent the GC from reclaiming the bytecode during execution, + // because the ip pointer below will always point to the interior of the bytecode. + mp_obj_fun_bc_t *fun_bc; const byte *ip; - const mp_uint_t *const_table; mp_obj_t *sp; // bit 0 is saved currently_in_except_block value mp_exc_stack_t *exc_sp; @@ -80,7 +84,6 @@ typedef struct _mp_code_state_t { #if MICROPY_STACKLESS struct _mp_code_state_t *prev; #endif - size_t n_state; // Variable-length mp_obj_t state[0]; // Variable-length, never accessed by name, only as (void*)(state + n_state) @@ -91,8 +94,7 @@ mp_uint_t mp_decode_uint(const byte **ptr); mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc); mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args); -struct _mp_obj_fun_bc_t; -void mp_setup_code_state(mp_code_state_t *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args); +void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args); void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table); void mp_bytecode_print2(const byte *code, size_t len, const mp_uint_t *const_table); const byte *mp_bytecode_print_str(const byte *ip); diff --git a/py/emitnative.c b/py/emitnative.c index 55eb6cadf..4af68102b 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -407,43 +407,29 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop #endif // prepare incoming arguments for call to mp_setup_code_state + #if N_X86 - asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_2); - asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_3); - asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_4); - asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_5); - #else - #if N_THUMB - ASM_MOV_REG_REG(emit->as, ASM_THUMB_REG_R4, REG_ARG_4); - #elif N_ARM - ASM_MOV_REG_REG(emit->as, ASM_ARM_REG_R4, REG_ARG_4); - #else - ASM_MOV_REG_REG(emit->as, REG_ARG_5, REG_ARG_4); - #endif - ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_ARG_3); - ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_ARG_2); - ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_ARG_1); + asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1); + asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2); + asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_3); + asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_4); #endif + // set code_state.fun_bc + ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_1, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t)); + // set code_state.ip (offset from start of this function to prelude info) // XXX this encoding may change size - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(mp_uint_t), REG_ARG_1); - - // set code_state.n_state - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state_t, n_state) / sizeof(mp_uint_t), REG_ARG_1); + ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), REG_ARG_1); // put address of code_state into first arg ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1); // call mp_setup_code_state to prepare code_state structure #if N_THUMB - asm_thumb_op16(emit->as, 0xb400 | (1 << ASM_THUMB_REG_R4)); // push 5th arg asm_thumb_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4); - asm_thumb_op16(emit->as, 0xbc00 | (1 << REG_RET)); // pop dummy (was 5th arg) #elif N_ARM - asm_arm_push(emit->as, 1 << ASM_ARM_REG_R4); // push 5th arg asm_arm_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_ARM_REG_R4); - asm_arm_pop(emit->as, 1 << REG_RET); // pop dummy (was 5th arg) #else ASM_CALL_IND(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE); #endif @@ -477,6 +463,9 @@ STATIC void emit_native_end_pass(emit_t *emit) { if (!emit->do_viper_types) { emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base); + mp_asm_base_data(&emit->as->base, 1, 0x80 | ((emit->n_state >> 7) & 0x7f)); + mp_asm_base_data(&emit->as->base, 1, emit->n_state & 0x7f); + mp_asm_base_data(&emit->as->base, 1, 0); // n_exc_stack mp_asm_base_data(&emit->as->base, 1, emit->scope->scope_flags); mp_asm_base_data(&emit->as->base, 1, emit->scope->num_pos_args); mp_asm_base_data(&emit->as->base, 1, emit->scope->num_kwonly_args); diff --git a/py/objfun.c b/py/objfun.c index a823f49e5..4670521b4 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -220,9 +220,9 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args return NULL; } - code_state->ip = (byte*)(ip - self->bytecode); // offset to after n_state/n_exc_stack - code_state->n_state = n_state; - mp_setup_code_state(code_state, self, n_args, n_kw, args); + code_state->fun_bc = self; + code_state->ip = 0; + mp_setup_code_state(code_state, n_args, n_kw, args); // execute the byte code with the correct globals context code_state->old_globals = mp_globals_get(); @@ -265,9 +265,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const state_size = 0; // indicate that we allocated using alloca } - code_state->ip = (byte*)(ip - self->bytecode); // offset to after n_state/n_exc_stack - code_state->n_state = n_state; - mp_setup_code_state(code_state, self, n_args, n_kw, args); + code_state->fun_bc = self; + code_state->ip = 0; + mp_setup_code_state(code_state, n_args, n_kw, args); // execute the byte code with the correct globals context code_state->old_globals = mp_globals_get(); diff --git a/py/objgenerator.c b/py/objgenerator.c index 654b18670..2baead231 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -67,9 +67,9 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons o->base.type = &mp_type_gen_instance; o->globals = self_fun->globals; - o->code_state.n_state = n_state; - o->code_state.ip = (byte*)(ip - self_fun->bytecode); // offset to prelude - mp_setup_code_state(&o->code_state, self_fun, n_args, n_kw, args); + o->code_state.fun_bc = self_fun; + o->code_state.ip = 0; + mp_setup_code_state(&o->code_state, n_args, n_kw, args); return MP_OBJ_FROM_PTR(o); } @@ -92,7 +92,7 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) { STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", mp_obj_code_get_name(self->code_state.code_info), self); + mp_printf(print, "", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self); } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { @@ -134,10 +134,13 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ } break; - case MP_VM_RETURN_EXCEPTION: + case MP_VM_RETURN_EXCEPTION: { + const byte *bc = self->code_state.fun_bc->bytecode; + size_t n_state = mp_decode_uint(&bc); self->code_state.ip = 0; - *ret_val = self->code_state.state[self->code_state.n_state - 1]; + *ret_val = self->code_state.state[n_state - 1]; break; + } } return ret_kind; diff --git a/py/vm.c b/py/vm.c index 7a906cd80..63a88a4fb 100644 --- a/py/vm.c +++ b/py/vm.c @@ -73,10 +73,10 @@ typedef enum { ip += 2; #define DECODE_PTR \ DECODE_UINT; \ - void *ptr = (void*)(uintptr_t)code_state->const_table[unum] + void *ptr = (void*)(uintptr_t)code_state->fun_bc->const_table[unum] #define DECODE_OBJ \ DECODE_UINT; \ - mp_obj_t obj = (mp_obj_t)code_state->const_table[unum] + mp_obj_t obj = (mp_obj_t)code_state->fun_bc->const_table[unum] #else @@ -162,8 +162,10 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp run_code_state: ; #endif // Pointers which are constant for particular invocation of mp_execute_bytecode() - mp_obj_t * /*const*/ fastn = &code_state->state[code_state->n_state - 1]; - mp_exc_stack_t * /*const*/ exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state); + const byte *temp_bc = code_state->fun_bc->bytecode; + size_t n_state = mp_decode_uint(&temp_bc); + mp_obj_t * /*const*/ fastn = &code_state->state[n_state - 1]; + mp_exc_stack_t * /*const*/ exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); // variables that are visible to the exception handler (declared volatile) volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions @@ -1327,8 +1329,16 @@ unwind_loop: // But consider how to handle nested exceptions. // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj) if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) { - const byte *ip = code_state->code_info; + const byte *ip = code_state->fun_bc->bytecode; + mp_decode_uint(&ip); // skip n_state + mp_decode_uint(&ip); // skip n_exc_stack + ip++; // skip scope_params + ip++; // skip n_pos_args + ip++; // skip n_kwonly_args + ip++; // skip n_def_pos_args + size_t bc = code_state->ip - ip; size_t code_info_size = mp_decode_uint(&ip); + bc -= code_info_size; #if MICROPY_PERSISTENT_CODE qstr block_name = ip[0] | (ip[1] << 8); qstr source_file = ip[2] | (ip[3] << 8); @@ -1337,7 +1347,6 @@ unwind_loop: qstr block_name = mp_decode_uint(&ip); qstr source_file = mp_decode_uint(&ip); #endif - size_t bc = code_state->ip - code_state->code_info - code_info_size; size_t source_line = 1; size_t c; while ((c = *ip)) { @@ -1393,8 +1402,8 @@ unwind_loop: } else if (code_state->prev != NULL) { mp_globals_set(code_state->old_globals); code_state = code_state->prev; - fastn = &code_state->state[code_state->n_state - 1]; - exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state); + fastn = &code_state->state[n_state - 1]; + exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); // variables that are visible to the exception handler (declared volatile) currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack -- cgit v1.2.3 From 6213ad7f466df12c734dc527993bbb46c9d9eb5c Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 25 Mar 2017 19:35:08 +1100 Subject: py: Convert mp_uint_t to size_t for tuple/list accessors. This patch changes mp_uint_t to size_t for the len argument of the following public facing C functions: mp_obj_tuple_get mp_obj_list_get mp_obj_get_array These functions take a pointer to the len argument (to be filled in by the function) and callers of these functions should update their code so the type of len is changed to size_t. For ports that don't use nan-boxing there should be no change in generate code because the size of the type remains the same (word sized), and in a lot of cases there won't even be a compiler warning if the type remains as mp_uint_t. The reason for this change is to standardise on the use of size_t for variables that count memory (or memory related) sizes/lengths. It helps builds that use nan-boxing. --- py/builtinimport.c | 2 +- py/modthread.c | 2 +- py/obj.c | 4 ++-- py/obj.h | 6 +++--- py/objfun.c | 2 +- py/objlist.c | 4 ++-- py/objnamedtuple.c | 2 +- py/objstr.c | 4 ++-- py/objtuple.c | 2 +- py/objtype.c | 4 ++-- py/runtime.c | 6 +++--- 11 files changed, 19 insertions(+), 19 deletions(-) (limited to 'py/objfun.c') diff --git a/py/builtinimport.c b/py/builtinimport.c index 17c1622ef..8101d633f 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -97,7 +97,7 @@ STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) { STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) { #if MICROPY_PY_SYS // extract the list of paths - mp_uint_t path_num; + size_t path_num; mp_obj_t *path_items; mp_obj_list_get(mp_sys_path, &path_num, &path_items); diff --git a/py/modthread.c b/py/modthread.c index ecf470527..d0e71dad3 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -215,7 +215,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) thread_entry_args_t *th_args; // get positional arguments - mp_uint_t pos_args_len; + size_t pos_args_len; mp_obj_t *pos_args_items; mp_obj_get_array(args[1], &pos_args_len, &pos_args_items); diff --git a/py/obj.c b/py/obj.c index 4b5fe2532..98ffa930b 100644 --- a/py/obj.c +++ b/py/obj.c @@ -321,7 +321,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { #endif // note: returned value in *items may point to the interior of a GC block -void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) { +void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) { if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) { mp_obj_tuple_get(o, len, items); } else if (MP_OBJ_IS_TYPE(o, &mp_type_list)) { @@ -338,7 +338,7 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) { // note: returned value in *items may point to the interior of a GC block void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items) { - mp_uint_t seq_len; + size_t seq_len; mp_obj_get_array(o, &seq_len, items); if (seq_len != len) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { diff --git a/py/obj.h b/py/obj.h index 71945f4f1..65543b785 100644 --- a/py/obj.h +++ b/py/obj.h @@ -676,7 +676,7 @@ mp_float_t mp_obj_get_float(mp_obj_t self_in); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); #endif //qstr mp_obj_get_qstr(mp_obj_t arg); -void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items); // *items may point inside a GC block +void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items); // *items may point inside a GC block void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items); // *items may point inside a GC block size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice); mp_obj_t mp_obj_id(mp_obj_t o_in); @@ -728,7 +728,7 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t #endif // tuple -void mp_obj_tuple_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items); +void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items); void mp_obj_tuple_del(mp_obj_t self_in); mp_int_t mp_obj_tuple_hash(mp_obj_t self_in); @@ -737,7 +737,7 @@ struct _mp_obj_list_t; void mp_obj_list_init(struct _mp_obj_list_t *o, size_t n); mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value); -void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items); +void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items); void mp_obj_list_set_len(mp_obj_t self_in, size_t len); void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); diff --git a/py/objfun.c b/py/objfun.c index 4670521b4..2ce33cb21 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -513,7 +513,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { #endif } else if (type == &mp_type_tuple || type == &mp_type_list) { // pointer to start of tuple (could pass length, but then could use len(x) for that) - mp_uint_t len; + size_t len; mp_obj_t *items; mp_obj_get_array(obj, &len, &items); return (mp_uint_t)items; diff --git a/py/objlist.c b/py/objlist.c index 312cef6d3..45e69c8bc 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -192,7 +192,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); - mp_uint_t value_len; mp_obj_t *value_items; + size_t value_len; mp_obj_t *value_items; mp_obj_get_array(value, &value_len, &value_items); mp_bound_slice_t slice_out; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { @@ -475,7 +475,7 @@ mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items) { return MP_OBJ_FROM_PTR(o); } -void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) { +void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); *len = self->len; *items = self->items; diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 2371518b9..52468747b 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -158,7 +158,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) { qstr name = mp_obj_str_get_qstr(name_in); - mp_uint_t n_fields; + size_t n_fields; mp_obj_t *fields; #if MICROPY_CPYTHON_COMPAT if (MP_OBJ_IS_STR(fields_in)) { diff --git a/py/objstr.c b/py/objstr.c index 4053efb88..682bd2693 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -284,7 +284,7 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // check for modulo if (op == MP_BINARY_OP_MODULO) { mp_obj_t *args = &rhs_in; - mp_uint_t n_args = 1; + size_t n_args = 1; mp_obj_t dict = MP_OBJ_NULL; if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple)) { // TODO: Support tuple subclasses? @@ -428,7 +428,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { GET_STR_DATA_LEN(self_in, sep_str, sep_len); // process args - mp_uint_t seq_len; + size_t seq_len; mp_obj_t *seq_items; if (!MP_OBJ_IS_TYPE(arg, &mp_type_list) && !MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) { diff --git a/py/objtuple.c b/py/objtuple.c index a8efdc7f9..fa5309aae 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -244,7 +244,7 @@ mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) { return MP_OBJ_FROM_PTR(o); } -void mp_obj_tuple_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) { +void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); *len = self->len; diff --git a/py/objtype.c b/py/objtype.c index a64832c1f..dd170b4c6 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -916,7 +916,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // TODO might need to make a copy of locals_dict; at least that's how CPython does it // Basic validation of base classes - mp_uint_t len; + size_t len; mp_obj_t *items; mp_obj_tuple_get(bases_tuple, &len, &items); for (size_t i = 0; i < len; i++) { @@ -1098,7 +1098,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { } STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { - mp_uint_t len; + size_t len; mp_obj_t *items; if (MP_OBJ_IS_TYPE(classinfo, &mp_type_type)) { len = 1; diff --git a/py/runtime.c b/py/runtime.c index 9f6c654ab..73886e10f 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -670,7 +670,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ // optimise the case of a tuple and list // get the items - mp_uint_t len; + size_t len; mp_obj_t *items; mp_obj_get_array(pos_seq, &len, &items); @@ -799,7 +799,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob // unpacked items are stored in reverse order into the array pointed to by items void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) { - mp_uint_t seq_len; + size_t seq_len; if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) { mp_obj_t *seq_items; mp_obj_get_array(seq_in, &seq_len, &seq_items); @@ -849,7 +849,7 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) { size_t num_left = num_in & 0xff; size_t num_right = (num_in >> 8) & 0xff; DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right); - mp_uint_t seq_len; + size_t seq_len; if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) { mp_obj_t *seq_items; mp_obj_get_array(seq_in, &seq_len, &seq_items); -- cgit v1.2.3 From 6b341075376705ee1fe9e003b76b09afa59778f4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 25 Mar 2017 19:48:18 +1100 Subject: py: Change mp_uint_t to size_t for mp_obj_str_get_data len arg. --- py/builtinevex.c | 4 ++-- py/builtinimport.c | 6 +++--- py/modbuiltins.c | 6 +++--- py/obj.h | 2 +- py/objcomplex.c | 2 +- py/objfloat.c | 2 +- py/objfun.c | 2 +- py/objint.c | 4 ++-- py/objstr.c | 12 ++++++------ py/repl.c | 6 +++--- py/runtime.c | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) (limited to 'py/objfun.c') diff --git a/py/builtinevex.c b/py/builtinevex.c index 89fcc2fe1..d9a3833cc 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -78,7 +78,7 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { (void)n_args; // get the source - mp_uint_t str_len; + size_t str_len; const char *str = mp_obj_str_get_data(args[0], &str_len); // get the filename @@ -128,7 +128,7 @@ STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_i } #endif - mp_uint_t str_len; + size_t str_len; const char *str = mp_obj_str_get_data(args[0], &str_len); // create the lexer diff --git a/py/builtinimport.c b/py/builtinimport.c index 8101d633f..cf17d5305 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -111,7 +111,7 @@ STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *d // go through each path looking for a directory or file for (mp_uint_t i = 0; i < path_num; i++) { vstr_reset(dest); - mp_uint_t p_len; + size_t p_len; const char *p = mp_obj_str_get_data(path_items[i], &p_len); if (p_len > 0) { vstr_add_strn(dest, p, p_len); @@ -265,7 +265,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { } } - mp_uint_t mod_len; + size_t mod_len; const char *mod_str = mp_obj_str_get_data(module_name, &mod_len); if (level != 0) { @@ -296,7 +296,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { DEBUG_printf("\n"); #endif - mp_uint_t this_name_l; + size_t this_name_l; const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l); const char *p = this_name + this_name_l; diff --git a/py/modbuiltins.c b/py/modbuiltins.c index f1d703a6d..e8119456d 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -336,7 +336,7 @@ STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct); STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { - mp_uint_t len; + size_t len; const char *str = mp_obj_str_get_data(o_in, &len); #if MICROPY_PY_BUILTINS_STR_UNICODE if (MP_OBJ_IS_STR(o_in)) { @@ -397,9 +397,9 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t * mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP); mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP); const char *sep_data = " "; - mp_uint_t sep_len = 1; + size_t sep_len = 1; const char *end_data = "\n"; - mp_uint_t end_len = 1; + size_t end_len = 1; if (sep_elem != NULL && sep_elem->value != mp_const_none) { sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len); } diff --git a/py/obj.h b/py/obj.h index 65543b785..580b814a8 100644 --- a/py/obj.h +++ b/py/obj.h @@ -712,7 +712,7 @@ void mp_init_emergency_exception_buf(void); bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2); qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated -const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len); +const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len); mp_obj_t mp_obj_str_intern(mp_obj_t str); void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes); diff --git a/py/objcomplex.c b/py/objcomplex.c index 426e76e5f..8118fb813 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -80,7 +80,7 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si case 1: if (MP_OBJ_IS_STR(args[0])) { // a string, parse it - mp_uint_t l; + size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_decimal(s, l, true, true, NULL); } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { diff --git a/py/objfloat.c b/py/objfloat.c index 9292490a9..6d80d6c0e 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -89,7 +89,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size default: if (MP_OBJ_IS_STR(args[0])) { // a string, parse it - mp_uint_t l; + size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_decimal(s, l, false, false, NULL); } else if (mp_obj_is_float(args[0])) { diff --git a/py/objfun.c b/py/objfun.c index 2ce33cb21..08d031c8d 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -501,7 +501,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { return mp_obj_int_get_truncated(obj); } else if (MP_OBJ_IS_STR(obj)) { // pointer to the string (it's probably constant though!) - mp_uint_t l; + size_t l; return (mp_uint_t)mp_obj_str_get_data(obj, &l); } else { mp_obj_type_t *type = mp_obj_get_type(obj); diff --git a/py/objint.c b/py/objint.c index ce091549d..2e8fe4f22 100644 --- a/py/objint.c +++ b/py/objint.c @@ -56,7 +56,7 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, return args[0]; } else if (MP_OBJ_IS_STR_OR_BYTES(args[0])) { // a string, parse it - mp_uint_t l; + size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, 0, NULL); #if MICROPY_PY_BUILTINS_FLOAT @@ -72,7 +72,7 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, default: { // should be a string, parse it // TODO proper error checking of argument types - mp_uint_t l; + size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL); } diff --git a/py/objstr.c b/py/objstr.c index 682bd2693..60a26d45b 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -513,7 +513,7 @@ mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) { bad_implicit_conversion(sep); } - mp_uint_t sep_len; + size_t sep_len; const char *sep_str = mp_obj_str_get_data(sep, &sep_len); if (sep_len == 0) { @@ -611,7 +611,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { if (sep == mp_const_none) { mp_not_implemented("rsplit(None,n)"); } else { - mp_uint_t sep_len; + size_t sep_len; const char *sep_str = mp_obj_str_get_data(sep, &sep_len); if (sep_len == 0) { @@ -1306,12 +1306,12 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar switch (type) { case '\0': // no explicit format type implies 's' case 's': { - mp_uint_t slen; + size_t slen; const char *s = mp_obj_str_get_data(arg, &slen); if (precision < 0) { precision = slen; } - if (slen > (mp_uint_t)precision) { + if (slen > (size_t)precision) { slen = precision; } mp_print_strn(&print, s, slen, flags, fill, width); @@ -1452,7 +1452,7 @@ not_enough_args: switch (*str) { case 'c': if (MP_OBJ_IS_STR(arg)) { - mp_uint_t slen; + size_t slen; const char *s = mp_obj_str_get_data(arg, &slen); if (slen != 1) { mp_raise_TypeError("%%c requires int or char"); @@ -2097,7 +2097,7 @@ const char *mp_obj_str_get_str(mp_obj_t self_in) { } } -const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len) { +const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len) { if (MP_OBJ_IS_STR_OR_BYTES(self_in)) { GET_STR_DATA_LEN(self_in, s, l); *len = l; diff --git a/py/repl.c b/py/repl.c index 997d80005..6d8f7cca4 100644 --- a/py/repl.c +++ b/py/repl.c @@ -153,7 +153,7 @@ mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t mp_obj_t obj = MP_OBJ_NULL; for (mp_uint_t i = 0; i < dict->map.alloc; i++) { if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { - mp_uint_t d_len; + size_t d_len; const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len); if (s_len == d_len && strncmp(s_start, d_str, d_len) == 0) { obj = dict->map.table[i].value; @@ -197,7 +197,7 @@ mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t mp_uint_t match_len = 0; for (mp_uint_t i = 0; i < dict->map.alloc; i++) { if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { - mp_uint_t d_len; + size_t d_len; const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len); if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { if (match_str == NULL) { @@ -247,7 +247,7 @@ mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t int line_len = MAX_LINE_LEN; // force a newline for first word for (mp_uint_t i = 0; i < dict->map.alloc; i++) { if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { - mp_uint_t d_len; + size_t d_len; const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len); if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len; diff --git a/py/runtime.c b/py/runtime.c index 73886e10f..1df6740b2 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1330,7 +1330,7 @@ import_error: } mp_load_method_maybe(module, MP_QSTR___name__, dest); - mp_uint_t pkg_name_len; + size_t pkg_name_len; const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len); const uint dot_name_len = pkg_name_len + 1 + qstr_len(name); -- cgit v1.2.3 From a8a5d1e8c8db3b7c64e1921005ceb5a5d47280f4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 9 Jun 2017 13:31:57 +1000 Subject: py: Provide mp_decode_uint_skip() to help reduce stack usage. Taking the address of a local variable leads to increased stack usage, so the mp_decode_uint_skip() function is added to reduce the need for taking addresses. The changes in this patch reduce stack usage of a Python call by 8 bytes on ARM Thumb, by 16 bytes on non-windowing Xtensa archs, and by 16 bytes on x86-64. Code size is also slightly reduced on most archs by around 32 bytes. --- py/bc.c | 10 +++++++++- py/bc.h | 1 + py/objfun.c | 22 ++++++++-------------- py/objgenerator.c | 7 ++----- py/vm.c | 13 ++++++++----- 5 files changed, 28 insertions(+), 25 deletions(-) (limited to 'py/objfun.c') diff --git a/py/bc.c b/py/bc.c index fc1794683..2e481bce7 100644 --- a/py/bc.c +++ b/py/bc.c @@ -64,6 +64,14 @@ mp_uint_t mp_decode_uint_value(const byte *ptr) { return mp_decode_uint(&ptr); } +// This function is used to help reduce stack usage at the caller, for the case when +// the caller doesn't need the actual value and just wants to skip over it. +const byte *mp_decode_uint_skip(const byte *ptr) { + while ((*ptr++) & 0x80) { + } + return ptr; +} + STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE // generic message, used also for other argument issues @@ -115,7 +123,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw // get params size_t n_state = mp_decode_uint(&code_state->ip); - mp_decode_uint(&code_state->ip); // skip n_exc_stack + code_state->ip = mp_decode_uint_skip(code_state->ip); // skip n_exc_stack size_t scope_flags = *code_state->ip++; size_t n_pos_args = *code_state->ip++; size_t n_kwonly_args = *code_state->ip++; diff --git a/py/bc.h b/py/bc.h index e8d428612..88045dc55 100644 --- a/py/bc.h +++ b/py/bc.h @@ -92,6 +92,7 @@ typedef struct _mp_code_state_t { mp_uint_t mp_decode_uint(const byte **ptr); mp_uint_t mp_decode_uint_value(const byte *ptr); +const byte *mp_decode_uint_skip(const byte *ptr); mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc); mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args); diff --git a/py/objfun.c b/py/objfun.c index 08d031c8d..9f3589124 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -141,11 +141,11 @@ const mp_obj_type_t mp_type_fun_builtin_var = { /* byte code functions */ qstr mp_obj_code_get_name(const byte *code_info) { - mp_decode_uint(&code_info); // skip code_info_size entry + code_info = mp_decode_uint_skip(code_info); // skip code_info_size entry #if MICROPY_PERSISTENT_CODE return code_info[0] | (code_info[1] << 8); #else - return mp_decode_uint(&code_info); + return mp_decode_uint_value(code_info); #endif } @@ -163,8 +163,8 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { #endif const byte *bc = fun->bytecode; - mp_decode_uint(&bc); // skip n_state - mp_decode_uint(&bc); // skip n_exc_stack + bc = mp_decode_uint_skip(bc); // skip n_state + bc = mp_decode_uint_skip(bc); // skip n_exc_stack bc++; // skip scope_params bc++; // skip n_pos_args bc++; // skip n_kwonly_args @@ -205,12 +205,9 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args MP_STACK_CHECK(); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); - // get start of bytecode - const byte *ip = self->bytecode; - // bytecode prelude: state size and exception stack size - size_t n_state = mp_decode_uint(&ip); - size_t n_exc_stack = mp_decode_uint(&ip); + size_t n_state = mp_decode_uint_value(self->bytecode); + size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode)); // allocate state for locals and stack size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); @@ -243,12 +240,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); DEBUG_printf("Func n_def_args: %d\n", self->n_def_args); - // get start of bytecode - const byte *ip = self->bytecode; - // bytecode prelude: state size and exception stack size - size_t n_state = mp_decode_uint(&ip); - size_t n_exc_stack = mp_decode_uint(&ip); + size_t n_state = mp_decode_uint_value(self->bytecode); + size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode)); #if VM_DETECT_STACK_OVERFLOW n_state += 1; diff --git a/py/objgenerator.c b/py/objgenerator.c index 2e57fdf4b..8cb0e60cc 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -54,12 +54,9 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t*)self->fun; assert(self_fun->base.type == &mp_type_fun_bc); - // get start of bytecode - const byte *ip = self_fun->bytecode; - // bytecode prelude: get state size and exception stack size - mp_uint_t n_state = mp_decode_uint(&ip); - mp_uint_t n_exc_stack = mp_decode_uint(&ip); + size_t n_state = mp_decode_uint_value(self_fun->bytecode); + size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self_fun->bytecode)); // allocate the generator object, with room for local stack and exception stack mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, diff --git a/py/vm.c b/py/vm.c index ad3d9e29c..404c79912 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1363,22 +1363,25 @@ unwind_loop: // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj) if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) { const byte *ip = code_state->fun_bc->bytecode; - mp_decode_uint(&ip); // skip n_state - mp_decode_uint(&ip); // skip n_exc_stack + ip = mp_decode_uint_skip(ip); // skip n_state + ip = mp_decode_uint_skip(ip); // skip n_exc_stack ip++; // skip scope_params ip++; // skip n_pos_args ip++; // skip n_kwonly_args ip++; // skip n_def_pos_args size_t bc = code_state->ip - ip; - size_t code_info_size = mp_decode_uint(&ip); + size_t code_info_size = mp_decode_uint_value(ip); + ip = mp_decode_uint_skip(ip); // skip code_info_size bc -= code_info_size; #if MICROPY_PERSISTENT_CODE qstr block_name = ip[0] | (ip[1] << 8); qstr source_file = ip[2] | (ip[3] << 8); ip += 4; #else - qstr block_name = mp_decode_uint(&ip); - qstr source_file = mp_decode_uint(&ip); + qstr block_name = mp_decode_uint_value(ip); + ip = mp_decode_uint_skip(ip); + qstr source_file = mp_decode_uint_value(ip); + ip = mp_decode_uint_skip(ip); #endif size_t source_line = 1; size_t c; -- cgit v1.2.3