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/compile.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/compile.c')
-rw-r--r-- | py/compile.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/py/compile.c b/py/compile.c index 7207ac2e0..2fae5c9f6 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1495,6 +1495,8 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ EMIT_ARG(label_assign, l1); // start of exception handler EMIT(start_except_handler); + // at this point the top of the stack contains the exception instance that was raised + uint l2 = comp_next_label(comp); for (int i = 0; i < n_except; i++) { @@ -1528,16 +1530,13 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ EMIT_ARG(pop_jump_if, false, end_finally_label); } - EMIT(pop_top); - + // either discard or store the exception instance if (qstr_exception_local == 0) { EMIT(pop_top); } else { compile_store_id(comp, qstr_exception_local); } - EMIT(pop_top); - uint l3 = 0; if (qstr_exception_local != 0) { l3 = comp_next_label(comp); @@ -1561,7 +1560,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ } EMIT_ARG(jump, l2); EMIT_ARG(label_assign, end_finally_label); - EMIT_ARG(adjust_stack_size, 3); // stack adjust for the 3 exception items + EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance } compile_decrease_except_level(comp); |