py: Split RAISE_VARARGS opcode into 3 separate ones.

From the beginning of this project the RAISE_VARARGS opcode was named and
implemented following CPython, where it has an argument (to the opcode)
counting how many args the raise takes:

    raise # 0 args (re-raise previous exception)
    raise exc # 1 arg
    raise exc from exc2 # 2 args (chained raise)

In the bytecode this operation therefore takes 2 bytes, one for
RAISE_VARARGS and one for the number of args.

This patch splits this opcode into 3, where each is now a single byte.
This reduces bytecode size by 1 byte for each use of raise.  Every byte
counts!  It also has the benefit of reducing code size (on all ports except
nanbox).
pull/1/head
Damien George 2019-08-22 12:39:07 +10:00
parent 870e900d02
commit 02db91a7a3
6 changed files with 50 additions and 43 deletions

View File

@ -46,7 +46,7 @@
#define MP_BC_BASE_VINT_O (0x30) // UUMMCCCC--------
#define MP_BC_BASE_JUMP_E (0x40) // J-JJJJJEEEEF----
#define MP_BC_BASE_BYTE_O (0x50) // LLLLSSDTTTTTEEFF
#define MP_BC_BASE_BYTE_E (0x60) // E-BRYYI---------
#define MP_BC_BASE_BYTE_E (0x60) // --BREEEYYI------
#define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // LLLLLLLLLLLLLLLL
// (0x80) // LLLLLLLLLLLLLLLL
// (0x90) // LLLLLLLLLLLLLLLL
@ -128,9 +128,11 @@
#define MP_BC_UNPACK_EX (MP_BC_BASE_VINT_O + 0x01) // uint
#define MP_BC_RETURN_VALUE (MP_BC_BASE_BYTE_E + 0x03)
#define MP_BC_RAISE_VARARGS (MP_BC_BASE_BYTE_E + 0x00) // extra byte
#define MP_BC_YIELD_VALUE (MP_BC_BASE_BYTE_E + 0x04)
#define MP_BC_YIELD_FROM (MP_BC_BASE_BYTE_E + 0x05)
#define MP_BC_RAISE_LAST (MP_BC_BASE_BYTE_E + 0x04)
#define MP_BC_RAISE_OBJ (MP_BC_BASE_BYTE_E + 0x05)
#define MP_BC_RAISE_FROM (MP_BC_BASE_BYTE_E + 0x06)
#define MP_BC_YIELD_VALUE (MP_BC_BASE_BYTE_E + 0x07)
#define MP_BC_YIELD_FROM (MP_BC_BASE_BYTE_E + 0x08)
#define MP_BC_MAKE_FUNCTION (MP_BC_BASE_VINT_O + 0x02) // uint
#define MP_BC_MAKE_FUNCTION_DEFARGS (MP_BC_BASE_VINT_O + 0x03) // uint
@ -143,6 +145,6 @@
#define MP_BC_IMPORT_NAME (MP_BC_BASE_QSTR_O + 0x0b) // qstr
#define MP_BC_IMPORT_FROM (MP_BC_BASE_QSTR_O + 0x0c) // qstr
#define MP_BC_IMPORT_STAR (MP_BC_BASE_BYTE_E + 0x06)
#define MP_BC_IMPORT_STAR (MP_BC_BASE_BYTE_E + 0x09)
#endif // MICROPY_INCLUDED_PY_BC0_H

View File

@ -193,13 +193,6 @@ STATIC void emit_write_bytecode_byte(emit_t *emit, int stack_adj, byte b1) {
c[0] = b1;
}
STATIC void emit_write_bytecode_byte_byte(emit_t* emit, int stack_adj, byte b1, byte b2) {
mp_emit_bc_adjust_stack_size(emit, stack_adj);
byte *c = emit_get_cur_to_write_bytecode(emit, 2);
c[0] = b1;
c[1] = b2;
}
// Similar to emit_write_bytecode_uint(), just some extra handling to encode sign
STATIC void emit_write_bytecode_byte_int(emit_t *emit, int stack_adj, byte b1, mp_int_t num) {
emit_write_bytecode_byte(emit, stack_adj, b1);
@ -848,8 +841,10 @@ void mp_emit_bc_return_value(emit_t *emit) {
}
void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {
MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 1 == MP_BC_RAISE_OBJ);
MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM);
assert(n_args <= 2);
emit_write_bytecode_byte_byte(emit, -n_args, MP_BC_RAISE_VARARGS, n_args);
emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args);
}
void mp_emit_bc_yield(emit_t *emit, int kind) {

View File

@ -500,9 +500,16 @@ const byte *mp_bytecode_print_str(const byte *ip) {
printf("RETURN_VALUE");
break;
case MP_BC_RAISE_VARARGS:
unum = *ip++;
printf("RAISE_VARARGS " UINT_FMT, unum);
case MP_BC_RAISE_LAST:
printf("RAISE_LAST");
break;
case MP_BC_RAISE_OBJ:
printf("RAISE_OBJ");
break;
case MP_BC_RAISE_FROM:
printf("RAISE_FROM");
break;
case MP_BC_YIELD_VALUE:

49
py/vm.c
View File

@ -1162,32 +1162,33 @@ unwind_return:
FRAME_LEAVE();
return MP_VM_RETURN_NORMAL;
ENTRY(MP_BC_RAISE_VARARGS): {
ENTRY(MP_BC_RAISE_LAST): {
MARK_EXC_IP_SELECTIVE();
mp_uint_t unum = *ip;
mp_obj_t obj;
if (unum == 2) {
mp_warning(NULL, "exception chaining not supported");
// ignore (pop) "from" argument
sp--;
}
if (unum == 0) {
// search for the inner-most previous exception, to reraise it
obj = MP_OBJ_NULL;
for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
if (e->prev_exc != NULL) {
obj = MP_OBJ_FROM_PTR(e->prev_exc);
break;
}
// search for the inner-most previous exception, to reraise it
mp_obj_t obj = MP_OBJ_NULL;
for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; --e) {
if (e->prev_exc != NULL) {
obj = MP_OBJ_FROM_PTR(e->prev_exc);
break;
}
if (obj == MP_OBJ_NULL) {
obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "no active exception to reraise");
RAISE(obj);
}
} else {
obj = TOP();
}
obj = mp_make_raise_obj(obj);
if (obj == MP_OBJ_NULL) {
obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "no active exception to reraise");
}
RAISE(obj);
}
ENTRY(MP_BC_RAISE_OBJ): {
MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = mp_make_raise_obj(TOP());
RAISE(obj);
}
ENTRY(MP_BC_RAISE_FROM): {
MARK_EXC_IP_SELECTIVE();
mp_warning(NULL, "exception chaining not supported");
sp--; // ignore (pop) "from" argument
mp_obj_t obj = mp_make_raise_obj(TOP());
RAISE(obj);
}
@ -1437,7 +1438,7 @@ unwind_loop:
// - exceptions re-raised explicitly by "raise"
if (nlr.ret_val != &mp_const_GeneratorExit_obj
&& *code_state->ip != MP_BC_END_FINALLY
&& !(*code_state->ip == MP_BC_RAISE_VARARGS && code_state->ip[1] == 0)) {
&& *code_state->ip != MP_BC_RAISE_LAST) {
const byte *ip = code_state->fun_bc->bytecode;
ip = mp_decode_uint_skip(ip); // skip n_state
ip = mp_decode_uint_skip(ip); // skip n_exc_stack

View File

@ -99,7 +99,9 @@ static const void *const entry_table[256] = {
[MP_BC_CALL_METHOD] = &&entry_MP_BC_CALL_METHOD,
[MP_BC_CALL_METHOD_VAR_KW] = &&entry_MP_BC_CALL_METHOD_VAR_KW,
[MP_BC_RETURN_VALUE] = &&entry_MP_BC_RETURN_VALUE,
[MP_BC_RAISE_VARARGS] = &&entry_MP_BC_RAISE_VARARGS,
[MP_BC_RAISE_LAST] = &&entry_MP_BC_RAISE_LAST,
[MP_BC_RAISE_OBJ] = &&entry_MP_BC_RAISE_OBJ,
[MP_BC_RAISE_FROM] = &&entry_MP_BC_RAISE_FROM,
[MP_BC_YIELD_VALUE] = &&entry_MP_BC_YIELD_VALUE,
[MP_BC_YIELD_FROM] = &&entry_MP_BC_YIELD_FROM,
[MP_BC_IMPORT_NAME] = &&entry_MP_BC_IMPORT_NAME,

View File

@ -305,9 +305,9 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
\\d\+ BUILD_TUPLE 1
\\d\+ IMPORT_NAME 'a'
\\d\+ IMPORT_STAR
\\d\+ RAISE_VARARGS 0
\\d\+ RAISE_LAST
\\d\+ LOAD_CONST_SMALL_INT 1
\\d\+ RAISE_VARARGS 1
\\d\+ RAISE_OBJ
\\d\+ LOAD_CONST_NONE
\\d\+ RETURN_VALUE
\\d\+ LOAD_CONST_SMALL_INT 1