py: Replace POP_BLOCK and POP_EXCEPT opcodes with POP_EXCEPT_JUMP.
POP_BLOCK and POP_EXCEPT are now the same, and are always followed by a JUMP. So this optimisation reduces code size, and RAM usage of bytecode by two bytes for each try-except handler.
This commit is contained in:
parent
6f9e3ff719
commit
5a2599d962
2
py/bc.c
2
py/bc.c
@ -321,7 +321,7 @@ STATIC const byte opcode_format_table[64] = {
|
||||
OC4(O, O, U, U), // 0x38-0x3b
|
||||
OC4(U, O, B, O), // 0x3c-0x3f
|
||||
OC4(O, B, B, O), // 0x40-0x43
|
||||
OC4(B, B, O, B), // 0x44-0x47
|
||||
OC4(O, U, O, B), // 0x44-0x47
|
||||
OC4(U, U, U, U), // 0x48-0x4b
|
||||
OC4(U, U, U, U), // 0x4c-0x4f
|
||||
OC4(V, V, U, V), // 0x50-0x53
|
||||
|
3
py/bc0.h
3
py/bc0.h
@ -77,8 +77,7 @@
|
||||
#define MP_BC_END_FINALLY (0x41)
|
||||
#define MP_BC_GET_ITER (0x42)
|
||||
#define MP_BC_FOR_ITER (0x43) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_POP_BLOCK (0x44)
|
||||
#define MP_BC_POP_EXCEPT (0x45)
|
||||
#define MP_BC_POP_EXCEPT_JUMP (0x44) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_UNWIND_JUMP (0x46) // rel byte code offset, 16-bit signed, in excess; then a byte
|
||||
#define MP_BC_GET_ITER_STACK (0x47)
|
||||
|
||||
|
12
py/compile.c
12
py/compile.c
@ -1535,8 +1535,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
||||
compile_increase_except_level(comp, l1, MP_EMIT_SETUP_BLOCK_EXCEPT);
|
||||
|
||||
compile_node(comp, pn_body); // body
|
||||
EMIT(pop_block);
|
||||
EMIT_ARG(jump, success_label); // jump over exception handler
|
||||
EMIT_ARG(pop_except_jump, success_label, false); // jump over exception handler
|
||||
|
||||
EMIT_ARG(label_assign, l1); // start of exception handler
|
||||
EMIT(start_except_handler);
|
||||
@ -1607,8 +1606,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
||||
compile_decrease_except_level(comp);
|
||||
}
|
||||
|
||||
EMIT(pop_except);
|
||||
EMIT_ARG(jump, l2);
|
||||
EMIT_ARG(pop_except_jump, l2, true);
|
||||
EMIT_ARG(label_assign, end_finally_label);
|
||||
EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance
|
||||
}
|
||||
@ -1741,8 +1739,7 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
|
||||
compile_load_id(comp, context);
|
||||
compile_await_object_method(comp, MP_QSTR___anext__);
|
||||
c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
|
||||
EMIT(pop_block);
|
||||
EMIT_ARG(jump, try_else_label);
|
||||
EMIT_ARG(pop_except_jump, try_else_label, false);
|
||||
|
||||
EMIT_ARG(label_assign, try_exception_label);
|
||||
EMIT(start_except_handler);
|
||||
@ -1751,8 +1748,7 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
|
||||
EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
|
||||
EMIT_ARG(pop_jump_if, false, try_finally_label);
|
||||
EMIT(pop_top); // pop exception instance
|
||||
EMIT(pop_except);
|
||||
EMIT_ARG(jump, while_else_label);
|
||||
EMIT_ARG(pop_except_jump, while_else_label, true);
|
||||
|
||||
EMIT_ARG(label_assign, try_finally_label);
|
||||
EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack
|
||||
|
@ -134,8 +134,7 @@ typedef struct _emit_method_table_t {
|
||||
void (*get_iter)(emit_t *emit, bool use_stack);
|
||||
void (*for_iter)(emit_t *emit, mp_uint_t label);
|
||||
void (*for_iter_end)(emit_t *emit);
|
||||
void (*pop_block)(emit_t *emit);
|
||||
void (*pop_except)(emit_t *emit);
|
||||
void (*pop_except_jump)(emit_t *emit, mp_uint_t label, bool within_exc_handler);
|
||||
void (*unary_op)(emit_t *emit, mp_unary_op_t op);
|
||||
void (*binary_op)(emit_t *emit, mp_binary_op_t op);
|
||||
void (*build)(emit_t *emit, mp_uint_t n_args, int kind);
|
||||
@ -232,8 +231,7 @@ 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);
|
||||
void mp_emit_bc_for_iter_end(emit_t *emit);
|
||||
void mp_emit_bc_pop_block(emit_t *emit);
|
||||
void mp_emit_bc_pop_except(emit_t *emit);
|
||||
void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler);
|
||||
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op);
|
||||
void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op);
|
||||
void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind);
|
||||
|
13
py/emitbc.c
13
py/emitbc.c
@ -764,14 +764,10 @@ void mp_emit_bc_for_iter_end(emit_t *emit) {
|
||||
emit_bc_pre(emit, -MP_OBJ_ITER_BUF_NSLOTS);
|
||||
}
|
||||
|
||||
void mp_emit_bc_pop_block(emit_t *emit) {
|
||||
void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
|
||||
(void)within_exc_handler;
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte(emit, MP_BC_POP_BLOCK);
|
||||
}
|
||||
|
||||
void mp_emit_bc_pop_except(emit_t *emit) {
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte(emit, MP_BC_POP_EXCEPT);
|
||||
emit_write_bytecode_byte_unsigned_label(emit, MP_BC_POP_EXCEPT_JUMP, label);
|
||||
}
|
||||
|
||||
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
|
||||
@ -958,8 +954,7 @@ const emit_method_table_t emit_bc_method_table = {
|
||||
mp_emit_bc_get_iter,
|
||||
mp_emit_bc_for_iter,
|
||||
mp_emit_bc_for_iter_end,
|
||||
mp_emit_bc_pop_block,
|
||||
mp_emit_bc_pop_except,
|
||||
mp_emit_bc_pop_except_jump,
|
||||
mp_emit_bc_unary_op,
|
||||
mp_emit_bc_binary_op,
|
||||
mp_emit_bc_build,
|
||||
|
@ -1916,7 +1916,7 @@ STATIC void emit_native_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t exc
|
||||
prev_finally->unwind_label = UNWIND_LABEL_DO_FINAL_UNWIND;
|
||||
ASM_MOV_REG_PCREL(emit->as, REG_RET, label & ~MP_EMIT_BREAK_FROM_FOR);
|
||||
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_RET);
|
||||
// Cancel any active exception (see also emit_native_pop_except)
|
||||
// Cancel any active exception (see also emit_native_pop_except_jump)
|
||||
emit_native_mov_reg_const(emit, REG_RET, MP_F_CONST_NONE_OBJ);
|
||||
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_RET);
|
||||
// Jump to the innermost active finally
|
||||
@ -2111,18 +2111,15 @@ STATIC void emit_native_for_iter_end(emit_t *emit) {
|
||||
emit_post(emit);
|
||||
}
|
||||
|
||||
STATIC void emit_native_pop_block(emit_t *emit) {
|
||||
emit_native_pre(emit);
|
||||
if (!emit->exc_stack[emit->exc_stack_size - 1].is_finally) {
|
||||
STATIC void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
|
||||
if (within_exc_handler) {
|
||||
// Cancel any active exception so subsequent handlers don't see it
|
||||
emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ);
|
||||
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
|
||||
} else {
|
||||
emit_native_leave_exc_stack(emit, false);
|
||||
}
|
||||
emit_post(emit);
|
||||
}
|
||||
|
||||
STATIC void emit_native_pop_except(emit_t *emit) {
|
||||
// Cancel any active exception so subsequent handlers don't see it
|
||||
emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ);
|
||||
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
|
||||
emit_native_jump(emit, label);
|
||||
}
|
||||
|
||||
STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
|
||||
@ -2726,8 +2723,7 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
|
||||
emit_native_get_iter,
|
||||
emit_native_for_iter,
|
||||
emit_native_for_iter_end,
|
||||
emit_native_pop_block,
|
||||
emit_native_pop_except,
|
||||
emit_native_pop_except_jump,
|
||||
emit_native_unary_op,
|
||||
emit_native_binary_op,
|
||||
emit_native_build,
|
||||
|
11
py/showbc.c
11
py/showbc.c
@ -401,14 +401,9 @@ const byte *mp_bytecode_print_str(const byte *ip) {
|
||||
printf("FOR_ITER " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
|
||||
break;
|
||||
|
||||
case MP_BC_POP_BLOCK:
|
||||
// pops block and restores the stack
|
||||
printf("POP_BLOCK");
|
||||
break;
|
||||
|
||||
case MP_BC_POP_EXCEPT:
|
||||
// pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
|
||||
printf("POP_EXCEPT");
|
||||
case MP_BC_POP_EXCEPT_JUMP:
|
||||
DECODE_ULABEL; // these labels are always forward
|
||||
printf("POP_EXCEPT_JUMP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
|
||||
break;
|
||||
|
||||
case MP_BC_BUILD_TUPLE:
|
||||
|
14
py/vm.c
14
py/vm.c
@ -759,17 +759,13 @@ unwind_jump:;
|
||||
}
|
||||
|
||||
// matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
|
||||
ENTRY(MP_BC_POP_BLOCK):
|
||||
// we are exiting an exception handler, so pop the last one of the exception-stack
|
||||
ENTRY(MP_BC_POP_EXCEPT_JUMP): {
|
||||
assert(exc_sp >= exc_stack);
|
||||
POP_EXC_BLOCK();
|
||||
DISPATCH();
|
||||
|
||||
// matched against: SETUP_EXCEPT
|
||||
ENTRY(MP_BC_POP_EXCEPT):
|
||||
assert(exc_sp >= exc_stack);
|
||||
POP_EXC_BLOCK();
|
||||
DISPATCH();
|
||||
DECODE_ULABEL;
|
||||
ip += ulab;
|
||||
DISPATCH_WITH_PEND_EXC_CHECK();
|
||||
}
|
||||
|
||||
ENTRY(MP_BC_BUILD_TUPLE): {
|
||||
MARK_EXC_IP_SELECTIVE();
|
||||
|
@ -76,8 +76,7 @@ static const void *const entry_table[256] = {
|
||||
[MP_BC_GET_ITER] = &&entry_MP_BC_GET_ITER,
|
||||
[MP_BC_GET_ITER_STACK] = &&entry_MP_BC_GET_ITER_STACK,
|
||||
[MP_BC_FOR_ITER] = &&entry_MP_BC_FOR_ITER,
|
||||
[MP_BC_POP_BLOCK] = &&entry_MP_BC_POP_BLOCK,
|
||||
[MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT,
|
||||
[MP_BC_POP_EXCEPT_JUMP] = &&entry_MP_BC_POP_EXCEPT_JUMP,
|
||||
[MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE,
|
||||
[MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST,
|
||||
[MP_BC_BUILD_MAP] = &&entry_MP_BC_BUILD_MAP,
|
||||
|
@ -257,13 +257,11 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||
\\d\+ JUMP \\d\+
|
||||
\\d\+ LOAD_FAST 0
|
||||
\\d\+ POP_JUMP_IF_TRUE \\d\+
|
||||
\\d\+ POP_BLOCK
|
||||
\\d\+ JUMP \\d\+
|
||||
\\d\+ POP_EXCEPT_JUMP \\d\+
|
||||
\\d\+ POP_TOP
|
||||
\\d\+ LOAD_DEREF 14
|
||||
\\d\+ POP_TOP
|
||||
\\d\+ POP_EXCEPT
|
||||
\\d\+ JUMP \\d\+
|
||||
\\d\+ POP_EXCEPT_JUMP \\d\+
|
||||
\\d\+ END_FINALLY
|
||||
\\d\+ LOAD_CONST_NONE
|
||||
\\d\+ LOAD_FAST 1
|
||||
@ -272,11 +270,9 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||
\\d\+ JUMP \\d\+
|
||||
\\d\+ SETUP_EXCEPT \\d\+
|
||||
\\d\+ UNWIND_JUMP \\d\+ 1
|
||||
\\d\+ POP_BLOCK
|
||||
\\d\+ JUMP \\d\+
|
||||
\\d\+ POP_EXCEPT_JUMP \\d\+
|
||||
\\d\+ POP_TOP
|
||||
\\d\+ POP_EXCEPT
|
||||
\\d\+ JUMP \\d\+
|
||||
\\d\+ POP_EXCEPT_JUMP \\d\+
|
||||
\\d\+ END_FINALLY
|
||||
\\d\+ LOAD_FAST 0
|
||||
\\d\+ POP_JUMP_IF_TRUE \\d\+
|
||||
|
@ -105,7 +105,7 @@ def make_opcode_format():
|
||||
OC4(O, O, U, U), # 0x38-0x3b
|
||||
OC4(U, O, B, O), # 0x3c-0x3f
|
||||
OC4(O, B, B, O), # 0x40-0x43
|
||||
OC4(B, B, O, B), # 0x44-0x47
|
||||
OC4(O, U, O, B), # 0x44-0x47
|
||||
OC4(U, U, U, U), # 0x48-0x4b
|
||||
OC4(U, U, U, U), # 0x4c-0x4f
|
||||
OC4(V, V, U, V), # 0x50-0x53
|
||||
|
Loading…
Reference in New Issue
Block a user