diff options
author | Damien George <damien.p.george@gmail.com> | 2016-09-27 12:37:21 +1000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2016-09-27 12:37:21 +1000 |
commit | f040685b0cbec18feb981fdad96389a3b28b676d (patch) | |
tree | d79a7e70eba6a56092a950c70c7992ad1b47a7cf /py/emitbc.c | |
parent | 67d52d8cb9f7894a8d50251a67ece3c7a6178270 (diff) |
py: Only store the exception instance on Py stack in bytecode try block.
When an exception is raised and is to be handled by the VM, it is stored
on the Python value stack so the bytecode can access it. CPython stores
3 objects on the stack for each exception: exc type, exc instance and
traceback. uPy followed this approach, but it turns out not to be
necessary. Instead, it is enough to store just the exception instance on
the Python value stack. The only place where the 3 values are needed
explicitly is for the __exit__ handler of a with-statement context, but
for these cases the 3 values can be extracted from the single exception
instance.
This patch removes the need to store 3 values on the stack, and instead
just stores the exception instance.
Code size is reduced by about 50-100 bytes, the compiler and VM are
slightly simpler, generate bytecode is smaller (by 2 bytes for each try
block), and the Python value stack is reduced in size for functions that
handle exceptions.
Diffstat (limited to 'py/emitbc.c')
-rw-r--r-- | py/emitbc.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/py/emitbc.c b/py/emitbc.c index 8c712e1fd..40485108d 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -751,10 +751,9 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept } void mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label) { - // TODO We can probably optimise the amount of needed stack space, since - // we don't actually need 4 slots during the entire with block, only in - // the cleanup handler in certain cases. It needs some thinking. - emit_bc_pre(emit, 4); + // The SETUP_WITH opcode pops ctx_mgr from the top of the stack + // and then pushes 3 entries: __exit__, ctx_mgr, as_value. + emit_bc_pre(emit, 2); emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label); } @@ -762,8 +761,9 @@ void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) { mp_emit_bc_pop_block(emit); mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE); mp_emit_bc_label_assign(emit, label); - emit_bc_pre(emit, -4); + emit_bc_pre(emit, 2); // ensure we have enough stack space to call the __exit__ method emit_write_bytecode_byte(emit, MP_BC_WITH_CLEANUP); + emit_bc_pre(emit, -4); // cancel the 2 above, plus the 2 from mp_emit_bc_setup_with } void mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label) { @@ -955,11 +955,11 @@ void mp_emit_bc_yield_from(emit_t *emit) { } void mp_emit_bc_start_except_handler(emit_t *emit) { - mp_emit_bc_adjust_stack_size(emit, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state + mp_emit_bc_adjust_stack_size(emit, 4); // stack adjust for the exception instance, +3 for possible UNWIND_JUMP state } void mp_emit_bc_end_except_handler(emit_t *emit) { - mp_emit_bc_adjust_stack_size(emit, -5); // stack adjust + mp_emit_bc_adjust_stack_size(emit, -3); // stack adjust } #if MICROPY_EMIT_NATIVE |