From 5640e6dacd39d97adffce8490991c457f457b1cd Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Mar 2017 16:38:46 +1100 Subject: [PATCH] py: Provide mp_decode_uint_value to help optimise stack usage. This has a noticeable improvement on x86-64 and Thumb2 archs, where stack usage is reduced by 2 machine words in the VM. --- py/bc.c | 16 +++++++++++----- py/bc.h | 1 + py/objgenerator.c | 3 +-- py/vm.c | 3 +-- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/py/bc.c b/py/bc.c index db5d0e6869..e7a1a333f7 100644 --- a/py/bc.c +++ b/py/bc.c @@ -54,6 +54,16 @@ mp_uint_t mp_decode_uint(const byte **ptr) { return unum; } +// This function is used to help reduce stack usage at the caller, for the case when +// the caller doesn't need to increase the ptr argument. If ptr is a local variable +// and the caller uses mp_decode_uint(&ptr) instead of this function, then the compiler +// must allocate a slot on the stack for ptr, and this slot cannot be reused for +// anything else in the function because the pointer may have been stored in a global +// and reused later in the function. +mp_uint_t mp_decode_uint_value(const byte *ptr) { + return mp_decode_uint(&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 @@ -246,11 +256,7 @@ continue2:; const byte *ip = code_state->ip; // jump over code info (source file and line-number mapping) - { - const byte *ip2 = ip; - size_t code_info_size = mp_decode_uint(&ip2); - ip += code_info_size; - } + ip += mp_decode_uint_value(ip); // bytecode prelude: initialise closed over variables size_t local_num; diff --git a/py/bc.h b/py/bc.h index 996b1a2f32..e8d4286125 100644 --- a/py/bc.h +++ b/py/bc.h @@ -91,6 +91,7 @@ typedef struct _mp_code_state_t { } mp_code_state_t; mp_uint_t mp_decode_uint(const byte **ptr); +mp_uint_t mp_decode_uint_value(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/objgenerator.c b/py/objgenerator.c index 2baead2315..e59ff3a9ce 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -135,8 +135,7 @@ 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: { - const byte *bc = self->code_state.fun_bc->bytecode; - size_t n_state = mp_decode_uint(&bc); + size_t n_state = mp_decode_uint_value(self->code_state.fun_bc->bytecode); self->code_state.ip = 0; *ret_val = self->code_state.state[n_state - 1]; break; diff --git a/py/vm.c b/py/vm.c index 63a88a4fb5..4ec1ea9066 100644 --- a/py/vm.c +++ b/py/vm.c @@ -162,8 +162,7 @@ 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() - const byte *temp_bc = code_state->fun_bc->bytecode; - size_t n_state = mp_decode_uint(&temp_bc); + size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode); 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);