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:
Damien George 2014-03-31 11:59:23 +01:00
parent 3056509e00
commit 523b575039
6 changed files with 44 additions and 130 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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
View File

@ -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: