From 18e6358480e640fd94a9383d5fa7d9b8cc2b9f73 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 May 2018 22:33:26 +1000 Subject: [PATCH] py/emit: Combine setup with/except/finally into one emit function. This patch reduces code size by: bare-arm: -16 minimal x86: -156 unix x64: -288 unix nanbox: -184 stm32: -48 cc3200: -16 esp8266: -96 esp32: -16 The last 10 patches combined reduce code size by: bare-arm: -164 minimal x86: -1260 unix x64: -3416 unix nanbox: -1616 stm32: -676 cc3200: -232 esp8266: -1144 esp32: -268 --- py/compile.c | 14 +++++++------- py/emit.h | 13 +++++++------ py/emitbc.c | 29 ++++++++++++----------------- py/emitnative.c | 33 ++++++++++++++++----------------- 4 files changed, 42 insertions(+), 47 deletions(-) diff --git a/py/compile.c b/py/compile.c index be1fd8b1f9..c62ed057dd 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1516,7 +1516,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ uint l1 = comp_next_label(comp); uint success_label = comp_next_label(comp); - EMIT_ARG(setup_except, l1); + EMIT_ARG(setup_block, l1, MP_EMIT_SETUP_BLOCK_EXCEPT); compile_increase_except_level(comp); compile_node(comp, pn_body); // body @@ -1571,7 +1571,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ uint l3 = 0; if (qstr_exception_local != 0) { l3 = comp_next_label(comp); - EMIT_ARG(setup_finally, l3); + EMIT_ARG(setup_block, l3, MP_EMIT_SETUP_BLOCK_FINALLY); compile_increase_except_level(comp); } compile_node(comp, pns_except->nodes[1]); @@ -1606,7 +1606,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) { uint l_finally_block = comp_next_label(comp); - EMIT_ARG(setup_finally, l_finally_block); + EMIT_ARG(setup_block, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY); compile_increase_except_level(comp); if (n_except == 0) { @@ -1668,12 +1668,12 @@ STATIC void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *n // this pre-bit is of the form "a as b" mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0]; compile_node(comp, pns->nodes[0]); - EMIT_ARG(setup_with, l_end); + EMIT_ARG(setup_block, l_end, MP_EMIT_SETUP_BLOCK_WITH); c_assign(comp, pns->nodes[1], ASSIGN_STORE); } else { // this pre-bit is just an expression compile_node(comp, nodes[0]); - EMIT_ARG(setup_with, l_end); + EMIT_ARG(setup_block, l_end, MP_EMIT_SETUP_BLOCK_WITH); EMIT(pop_top); } compile_increase_except_level(comp); @@ -1726,7 +1726,7 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns EMIT_ARG(label_assign, continue_label); - EMIT_ARG(setup_except, try_exception_label); + EMIT_ARG(setup_block, try_exception_label, MP_EMIT_SETUP_BLOCK_EXCEPT); compile_increase_except_level(comp); compile_load_id(comp, context); @@ -1797,7 +1797,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod compile_load_id(comp, context); EMIT_ARG(load_method, MP_QSTR___aexit__, false); - EMIT_ARG(setup_except, try_exception_label); + EMIT_ARG(setup_block, try_exception_label, MP_EMIT_SETUP_BLOCK_EXCEPT); compile_increase_except_level(comp); // compile additional pre-bits and the body compile_async_with_stmt_helper(comp, n - 1, nodes + 1, body); diff --git a/py/emit.h b/py/emit.h index 7f0d8c0f72..aa98efa774 100644 --- a/py/emit.h +++ b/py/emit.h @@ -78,6 +78,11 @@ typedef enum { #define MP_EMIT_ATTR_STORE (1) #define MP_EMIT_ATTR_DELETE (2) +// Kind for emit->setup_block() +#define MP_EMIT_SETUP_BLOCK_WITH (0) +#define MP_EMIT_SETUP_BLOCK_EXCEPT (2) +#define MP_EMIT_SETUP_BLOCK_FINALLY (3) + // Kind for emit->build() #define MP_EMIT_BUILD_TUPLE (0) #define MP_EMIT_BUILD_LIST (1) @@ -128,10 +133,8 @@ typedef struct _emit_method_table_t { void (*pop_jump_if)(emit_t *emit, bool cond, mp_uint_t label); void (*jump_if_or_pop)(emit_t *emit, bool cond, mp_uint_t label); void (*unwind_jump)(emit_t *emit, mp_uint_t label, mp_uint_t except_depth); - void (*setup_with)(emit_t *emit, mp_uint_t label); + void (*setup_block)(emit_t *emit, mp_uint_t label, int kind); void (*with_cleanup)(emit_t *emit, mp_uint_t label); - void (*setup_except)(emit_t *emit, mp_uint_t label); - void (*setup_finally)(emit_t *emit, mp_uint_t label); void (*end_finally)(emit_t *emit); void (*get_iter)(emit_t *emit, bool use_stack); void (*for_iter)(emit_t *emit, mp_uint_t label); @@ -223,10 +226,8 @@ void mp_emit_bc_jump(emit_t *emit, mp_uint_t label); void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label); void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label); void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth); -void mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label); +void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind); void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label); -void mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label); -void mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label); void mp_emit_bc_end_finally(emit_t *emit); void mp_emit_bc_get_iter(emit_t *emit, bool use_stack); void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label); diff --git a/py/emitbc.c b/py/emitbc.c index 4c587c72e3..f3951e9cb5 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -719,11 +719,18 @@ 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) { +void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) { + MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_WITH == MP_BC_SETUP_WITH); + MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_EXCEPT == MP_BC_SETUP_EXCEPT); + MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_FINALLY == MP_BC_SETUP_FINALLY); + if (kind == MP_EMIT_SETUP_BLOCK_WITH) { // 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); + emit_bc_pre(emit, 2); + } else { + emit_bc_pre(emit, 0); + } + emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH + kind, label); } void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) { @@ -732,17 +739,7 @@ void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) { mp_emit_bc_label_assign(emit, label); 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) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label); -} - -void mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label); + emit_bc_pre(emit, -4); // cancel the 2 above, plus the 2 from mp_emit_bc_setup_block(MP_EMIT_SETUP_BLOCK_WITH) } void mp_emit_bc_end_finally(emit_t *emit) { @@ -953,10 +950,8 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_pop_jump_if, mp_emit_bc_jump_if_or_pop, mp_emit_bc_unwind_jump, - mp_emit_bc_setup_with, + mp_emit_bc_setup_block, mp_emit_bc_with_cleanup, - mp_emit_bc_setup_except, - mp_emit_bc_setup_finally, mp_emit_bc_end_finally, mp_emit_bc_get_iter, mp_emit_bc_for_iter, diff --git a/py/emitnative.c b/py/emitnative.c index 331e4cf18e..ad8f04aac7 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1617,6 +1617,21 @@ STATIC void emit_native_setup_with(emit_t *emit, mp_uint_t label) { // stack: (..., __exit__, self, as_value, nlr_buf, as_value) } +STATIC void emit_native_setup_block(emit_t *emit, mp_uint_t label, int kind) { + if (kind == MP_EMIT_SETUP_BLOCK_WITH) { + emit_native_setup_with(emit, label); + } else { + // Set up except and finally + emit_native_pre(emit); + // need to commit stack because we may jump elsewhere + need_stack_settled(emit); + emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(mp_uint_t)); // arg1 = pointer to nlr buf + emit_call(emit, MP_F_NLR_PUSH); + ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label); + emit_post(emit); + } +} + STATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { // note: label+1 is available as an auxiliary label @@ -1686,20 +1701,6 @@ STATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { emit_native_label_assign(emit, label + 1); } -STATIC void emit_native_setup_except(emit_t *emit, mp_uint_t label) { - emit_native_pre(emit); - // need to commit stack because we may jump elsewhere - need_stack_settled(emit); - emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(mp_uint_t)); // arg1 = pointer to nlr buf - emit_call(emit, MP_F_NLR_PUSH); - ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label); - emit_post(emit); -} - -STATIC void emit_native_setup_finally(emit_t *emit, mp_uint_t label) { - emit_native_setup_except(emit, label); -} - STATIC void emit_native_end_finally(emit_t *emit) { // logic: // exc = pop_stack @@ -2254,10 +2255,8 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_pop_jump_if, emit_native_jump_if_or_pop, emit_native_unwind_jump, - emit_native_setup_with, + emit_native_setup_block, emit_native_with_cleanup, - emit_native_setup_except, - emit_native_setup_finally, emit_native_end_finally, emit_native_get_iter, emit_native_for_iter,