py: Add LOAD_NULL bytecode and use it to simplify function calls.
Adding this bytecode allows to remove 4 others related to function/method calls with * and ** support. Will also help with bytecodes that make functions/closures with default positional and keyword args.
This commit is contained in:
parent
3056509e00
commit
523b575039
21
py/bc0.h
21
py/bc0.h
|
@ -11,6 +11,7 @@
|
|||
#define MP_BC_LOAD_CONST_ID (0x17) // qstr
|
||||
#define MP_BC_LOAD_CONST_BYTES (0x18) // qstr
|
||||
#define MP_BC_LOAD_CONST_STRING (0x19) // qstr
|
||||
#define MP_BC_LOAD_NULL (0x1a)
|
||||
|
||||
#define MP_BC_LOAD_FAST_0 (0x20)
|
||||
#define MP_BC_LOAD_FAST_1 (0x21)
|
||||
|
@ -84,18 +85,14 @@
|
|||
#define MP_BC_YIELD_VALUE (0x82)
|
||||
#define MP_BC_YIELD_FROM (0x83)
|
||||
|
||||
#define MP_BC_MAKE_FUNCTION (0x90) // uint
|
||||
#define MP_BC_MAKE_CLOSURE (0x91) // uint
|
||||
#define MP_BC_CALL_FUNCTION (0x92) // uint
|
||||
#define MP_BC_CALL_FUNCTION_VAR (0x93) // uint
|
||||
#define MP_BC_CALL_FUNCTION_KW (0x94) // uint
|
||||
#define MP_BC_CALL_FUNCTION_VAR_KW (0x95) // uint
|
||||
#define MP_BC_CALL_METHOD (0x96) // uint
|
||||
#define MP_BC_CALL_METHOD_VAR (0x97) // uint
|
||||
#define MP_BC_CALL_METHOD_KW (0x98) // uint
|
||||
#define MP_BC_CALL_METHOD_VAR_KW (0x99) // uint
|
||||
#define MP_BC_MAKE_FUNCTION_DEFARGS (0x9a) // uint
|
||||
#define MP_BC_MAKE_CLOSURE_DEFARGS (0x9b) // uint
|
||||
#define MP_BC_MAKE_FUNCTION (0x90) // uint
|
||||
#define MP_BC_MAKE_FUNCTION_DEFARGS (0x91) // uint
|
||||
#define MP_BC_MAKE_CLOSURE (0x92) // uint
|
||||
#define MP_BC_MAKE_CLOSURE_DEFARGS (0x93) // uint
|
||||
#define MP_BC_CALL_FUNCTION (0x94) // uint
|
||||
#define MP_BC_CALL_FUNCTION_VAR_KW (0x95) // uint
|
||||
#define MP_BC_CALL_METHOD (0x96) // uint
|
||||
#define MP_BC_CALL_METHOD_VAR_KW (0x97) // uint
|
||||
|
||||
#define MP_BC_IMPORT_NAME (0xe0) // qstr
|
||||
#define MP_BC_IMPORT_FROM (0xe1) // qstr
|
||||
|
|
67
py/emitbc.c
67
py/emitbc.c
|
@ -399,6 +399,11 @@ STATIC void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) {
|
|||
assert(0);
|
||||
}
|
||||
|
||||
STATIC void emit_bc_load_null(emit_t *emit) {
|
||||
emit_bc_pre(emit, 1);
|
||||
emit_write_byte_code_byte(emit, MP_BC_LOAD_NULL);
|
||||
};
|
||||
|
||||
STATIC void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
|
||||
assert(local_num >= 0);
|
||||
emit_bc_pre(emit, 1);
|
||||
|
@ -748,56 +753,30 @@ STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaul
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
|
||||
int s = 0;
|
||||
if (have_star_arg) {
|
||||
s += 1;
|
||||
}
|
||||
if (have_dbl_star_arg) {
|
||||
s += 1;
|
||||
}
|
||||
emit_bc_pre(emit, -n_positional - 2 * n_keyword - s);
|
||||
int op;
|
||||
if (have_star_arg) {
|
||||
if (have_dbl_star_arg) {
|
||||
op = MP_BC_CALL_FUNCTION_VAR_KW;
|
||||
} else {
|
||||
op = MP_BC_CALL_FUNCTION_VAR;
|
||||
STATIC void emit_bc_call_function_method_helper(emit_t *emit, int stack_adj, uint bytecode_base, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
|
||||
if (have_star_arg || have_dbl_star_arg) {
|
||||
if (!have_star_arg) {
|
||||
// load dummy entry for non-existent pos_seq
|
||||
emit_bc_load_null(emit);
|
||||
emit_bc_rot_two(emit);
|
||||
} else if (!have_dbl_star_arg) {
|
||||
// load dummy entry for non-existent kw_dict
|
||||
emit_bc_load_null(emit);
|
||||
}
|
||||
emit_bc_pre(emit, stack_adj - n_positional - 2 * n_keyword - 2);
|
||||
emit_write_byte_code_byte_uint(emit, bytecode_base + 1, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints?
|
||||
} else {
|
||||
if (have_dbl_star_arg) {
|
||||
op = MP_BC_CALL_FUNCTION_KW;
|
||||
} else {
|
||||
op = MP_BC_CALL_FUNCTION;
|
||||
}
|
||||
emit_bc_pre(emit, stack_adj - n_positional - 2 * n_keyword);
|
||||
emit_write_byte_code_byte_uint(emit, bytecode_base, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints?
|
||||
}
|
||||
emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
|
||||
}
|
||||
|
||||
STATIC void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
|
||||
emit_bc_call_function_method_helper(emit, 0, MP_BC_CALL_FUNCTION, n_positional, n_keyword, have_star_arg, have_dbl_star_arg);
|
||||
}
|
||||
|
||||
STATIC void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
|
||||
int s = 0;
|
||||
if (have_star_arg) {
|
||||
s += 1;
|
||||
}
|
||||
if (have_dbl_star_arg) {
|
||||
s += 1;
|
||||
}
|
||||
emit_bc_pre(emit, -1 - n_positional - 2 * n_keyword - s);
|
||||
int op;
|
||||
if (have_star_arg) {
|
||||
if (have_dbl_star_arg) {
|
||||
op = MP_BC_CALL_METHOD_VAR_KW;
|
||||
} else {
|
||||
op = MP_BC_CALL_METHOD_VAR;
|
||||
}
|
||||
} else {
|
||||
if (have_dbl_star_arg) {
|
||||
op = MP_BC_CALL_METHOD_KW;
|
||||
} else {
|
||||
op = MP_BC_CALL_METHOD;
|
||||
}
|
||||
}
|
||||
emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
|
||||
emit_bc_call_function_method_helper(emit, -1, MP_BC_CALL_METHOD, n_positional, n_keyword, have_star_arg, have_dbl_star_arg);
|
||||
}
|
||||
|
||||
STATIC void emit_bc_return_value(emit_t *emit) {
|
||||
|
|
|
@ -505,7 +505,7 @@ mp_obj_t mp_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args) {
|
|||
return mp_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust);
|
||||
}
|
||||
|
||||
mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_t *args, mp_obj_t pos_seq, mp_obj_t kw_dict) {
|
||||
mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_t *args) {
|
||||
mp_obj_t fun = *args++;
|
||||
mp_obj_t self = MP_OBJ_NULL;
|
||||
if (have_self) {
|
||||
|
@ -513,6 +513,8 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_
|
|||
}
|
||||
uint n_args = n_args_n_kw & 0xff;
|
||||
uint n_kw = (n_args_n_kw >> 8) & 0xff;
|
||||
mp_obj_t pos_seq = args[n_args + 2 * n_kw]; // map be MP_OBJ_NULL
|
||||
mp_obj_t kw_dict = args[n_args + 2 * n_kw + 1]; // map be MP_OBJ_NULL
|
||||
|
||||
DEBUG_OP_printf("call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, seq=%p, dict=%p)\n", fun, self, n_args, n_kw, args, pos_seq, kw_dict);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
|
|||
mp_obj_t mp_call_function_n_kw_for_native(mp_obj_t fun_in, uint n_args_kw, const mp_obj_t *args);
|
||||
mp_obj_t mp_call_function_n_kw(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args);
|
||||
mp_obj_t mp_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args);
|
||||
mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_t *args, mp_obj_t pos_seq, mp_obj_t kw_dict);
|
||||
mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_t *args);
|
||||
|
||||
mp_obj_t mp_build_tuple(int n_args, mp_obj_t *items);
|
||||
mp_obj_t mp_build_list(int n_args, mp_obj_t *items);
|
||||
|
|
20
py/showbc.c
20
py/showbc.c
|
@ -399,16 +399,6 @@ void mp_byte_code_print(const byte *ip, int len) {
|
|||
printf("CALL_FUNCTION n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_FUNCTION_VAR:
|
||||
DECODE_UINT;
|
||||
printf("CALL_FUNCTION_VAR n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_FUNCTION_KW:
|
||||
DECODE_UINT;
|
||||
printf("CALL_FUNCTION_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_FUNCTION_VAR_KW:
|
||||
DECODE_UINT;
|
||||
printf("CALL_FUNCTION_VAR_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
|
@ -419,16 +409,6 @@ void mp_byte_code_print(const byte *ip, int len) {
|
|||
printf("CALL_METHOD n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_METHOD_VAR:
|
||||
DECODE_UINT;
|
||||
printf("CALL_METHOD_VAR n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_METHOD_KW:
|
||||
DECODE_UINT;
|
||||
printf("CALL_METHOD_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_METHOD_VAR_KW:
|
||||
DECODE_UINT;
|
||||
printf("CALL_METHOD_VAR_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
|
||||
|
|
60
py/vm.c
60
py/vm.c
|
@ -220,6 +220,10 @@ dispatch_loop:
|
|||
PUSH(mp_load_const_str(qst));
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_NULL:
|
||||
PUSH(MP_OBJ_NULL);
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_0:
|
||||
PUSH(fastn[0]);
|
||||
break;
|
||||
|
@ -671,38 +675,14 @@ unwind_jump:
|
|||
SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_FUNCTION_VAR:
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
// (unum >> 8) & 0xff == n_keyword
|
||||
// We have folowing stack layout here:
|
||||
// fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq <- TOS
|
||||
obj1 = POP();
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
|
||||
SET_TOP(mp_call_method_n_kw_var(false, unum, sp, obj1, MP_OBJ_NULL));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_FUNCTION_KW:
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
// (unum >> 8) & 0xff == n_keyword
|
||||
// We have folowing stack layout here:
|
||||
// fun arg0 arg1 ... kw0 val0 kw1 val1 ... dict <- TOS
|
||||
obj1 = POP();
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
|
||||
SET_TOP(mp_call_method_n_kw_var(false, unum, sp, MP_OBJ_NULL, obj1));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_FUNCTION_VAR_KW:
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
// (unum >> 8) & 0xff == n_keyword
|
||||
// We have folowing stack layout here:
|
||||
// fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
|
||||
obj2 = POP();
|
||||
obj1 = POP();
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
|
||||
SET_TOP(mp_call_method_n_kw_var(false, unum, sp, obj1, obj2));
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
|
||||
SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_METHOD:
|
||||
|
@ -713,38 +693,14 @@ unwind_jump:
|
|||
SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_METHOD_VAR:
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
// (unum >> 8) & 0xff == n_keyword
|
||||
// We have folowing stack layout here:
|
||||
// fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq <- TOS
|
||||
obj1 = POP();
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
|
||||
SET_TOP(mp_call_method_n_kw_var(true, unum, sp, obj1, MP_OBJ_NULL));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_METHOD_KW:
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
// (unum >> 8) & 0xff == n_keyword
|
||||
// We have folowing stack layout here:
|
||||
// fun self arg0 arg1 ... kw0 val0 kw1 val1 ... dict <- TOS
|
||||
obj1 = POP();
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
|
||||
SET_TOP(mp_call_method_n_kw_var(true, unum, sp, MP_OBJ_NULL, obj1));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_METHOD_VAR_KW:
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
// (unum >> 8) & 0xff == n_keyword
|
||||
// We have folowing stack layout here:
|
||||
// fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
|
||||
obj2 = POP();
|
||||
obj1 = POP();
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
|
||||
SET_TOP(mp_call_method_n_kw_var(true, unum, sp, obj1, obj2));
|
||||
sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
|
||||
SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
|
||||
break;
|
||||
|
||||
case MP_BC_RETURN_VALUE:
|
||||
|
|
Loading…
Reference in New Issue