Skip to content
This repository was archived by the owner on Oct 28, 2023. It is now read-only.

Commit a8a5d1e

Browse files
committed
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.
1 parent 4352b94 commit a8a5d1e

File tree

5 files changed

+28
-25
lines changed

5 files changed

+28
-25
lines changed

py/bc.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ mp_uint_t mp_decode_uint_value(const byte *ptr) {
6464
return mp_decode_uint(&ptr);
6565
}
6666

67+
// This function is used to help reduce stack usage at the caller, for the case when
68+
// the caller doesn't need the actual value and just wants to skip over it.
69+
const byte *mp_decode_uint_skip(const byte *ptr) {
70+
while ((*ptr++) & 0x80) {
71+
}
72+
return ptr;
73+
}
74+
6775
STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) {
6876
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
6977
// 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
115123

116124
// get params
117125
size_t n_state = mp_decode_uint(&code_state->ip);
118-
mp_decode_uint(&code_state->ip); // skip n_exc_stack
126+
code_state->ip = mp_decode_uint_skip(code_state->ip); // skip n_exc_stack
119127
size_t scope_flags = *code_state->ip++;
120128
size_t n_pos_args = *code_state->ip++;
121129
size_t n_kwonly_args = *code_state->ip++;

py/bc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ typedef struct _mp_code_state_t {
9292

9393
mp_uint_t mp_decode_uint(const byte **ptr);
9494
mp_uint_t mp_decode_uint_value(const byte *ptr);
95+
const byte *mp_decode_uint_skip(const byte *ptr);
9596

9697
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc);
9798
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);

py/objfun.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ const mp_obj_type_t mp_type_fun_builtin_var = {
141141
/* byte code functions */
142142

143143
qstr mp_obj_code_get_name(const byte *code_info) {
144-
mp_decode_uint(&code_info); // skip code_info_size entry
144+
code_info = mp_decode_uint_skip(code_info); // skip code_info_size entry
145145
#if MICROPY_PERSISTENT_CODE
146146
return code_info[0] | (code_info[1] << 8);
147147
#else
148-
return mp_decode_uint(&code_info);
148+
return mp_decode_uint_value(code_info);
149149
#endif
150150
}
151151

@@ -163,8 +163,8 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
163163
#endif
164164

165165
const byte *bc = fun->bytecode;
166-
mp_decode_uint(&bc); // skip n_state
167-
mp_decode_uint(&bc); // skip n_exc_stack
166+
bc = mp_decode_uint_skip(bc); // skip n_state
167+
bc = mp_decode_uint_skip(bc); // skip n_exc_stack
168168
bc++; // skip scope_params
169169
bc++; // skip n_pos_args
170170
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
205205
MP_STACK_CHECK();
206206
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
207207

208-
// get start of bytecode
209-
const byte *ip = self->bytecode;
210-
211208
// bytecode prelude: state size and exception stack size
212-
size_t n_state = mp_decode_uint(&ip);
213-
size_t n_exc_stack = mp_decode_uint(&ip);
209+
size_t n_state = mp_decode_uint_value(self->bytecode);
210+
size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));
214211

215212
// allocate state for locals and stack
216213
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
243240
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
244241
DEBUG_printf("Func n_def_args: %d\n", self->n_def_args);
245242

246-
// get start of bytecode
247-
const byte *ip = self->bytecode;
248-
249243
// bytecode prelude: state size and exception stack size
250-
size_t n_state = mp_decode_uint(&ip);
251-
size_t n_exc_stack = mp_decode_uint(&ip);
244+
size_t n_state = mp_decode_uint_value(self->bytecode);
245+
size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));
252246

253247
#if VM_DETECT_STACK_OVERFLOW
254248
n_state += 1;

py/objgenerator.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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
5454
mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t*)self->fun;
5555
assert(self_fun->base.type == &mp_type_fun_bc);
5656

57-
// get start of bytecode
58-
const byte *ip = self_fun->bytecode;
59-
6057
// bytecode prelude: get state size and exception stack size
61-
mp_uint_t n_state = mp_decode_uint(&ip);
62-
mp_uint_t n_exc_stack = mp_decode_uint(&ip);
58+
size_t n_state = mp_decode_uint_value(self_fun->bytecode);
59+
size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self_fun->bytecode));
6360

6461
// allocate the generator object, with room for local stack and exception stack
6562
mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte,

py/vm.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,22 +1363,25 @@ unwind_jump:;
13631363
// TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
13641364
if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
13651365
const byte *ip = code_state->fun_bc->bytecode;
1366-
mp_decode_uint(&ip); // skip n_state
1367-
mp_decode_uint(&ip); // skip n_exc_stack
1366+
ip = mp_decode_uint_skip(ip); // skip n_state
1367+
ip = mp_decode_uint_skip(ip); // skip n_exc_stack
13681368
ip++; // skip scope_params
13691369
ip++; // skip n_pos_args
13701370
ip++; // skip n_kwonly_args
13711371
ip++; // skip n_def_pos_args
13721372
size_t bc = code_state->ip - ip;
1373-
size_t code_info_size = mp_decode_uint(&ip);
1373+
size_t code_info_size = mp_decode_uint_value(ip);
1374+
ip = mp_decode_uint_skip(ip); // skip code_info_size
13741375
bc -= code_info_size;
13751376
#if MICROPY_PERSISTENT_CODE
13761377
qstr block_name = ip[0] | (ip[1] << 8);
13771378
qstr source_file = ip[2] | (ip[3] << 8);
13781379
ip += 4;
13791380
#else
1380-
qstr block_name = mp_decode_uint(&ip);
1381-
qstr source_file = mp_decode_uint(&ip);
1381+
qstr block_name = mp_decode_uint_value(ip);
1382+
ip = mp_decode_uint_skip(ip);
1383+
qstr source_file = mp_decode_uint_value(ip);
1384+
ip = mp_decode_uint_skip(ip);
13821385
#endif
13831386
size_t source_line = 1;
13841387
size_t c;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy