summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-03-31 11:59:23 +0100
committerDamien George <damien.p.george@gmail.com>2014-03-31 11:59:23 +0100
commit523b575039d96d63669ad8c1fa318ba4db046aca (patch)
treebc191c86845b3c5714d11f24e8848f22020308e5
parent3056509e00c02e4faef44d90bf3953dcf0b0d4a0 (diff)
downloadmicropython-523b575039d96d63669ad8c1fa318ba4db046aca.tar.gz
micropython-523b575039d96d63669ad8c1fa318ba4db046aca.zip
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.
-rw-r--r--py/bc0.h21
-rw-r--r--py/emitbc.c67
-rw-r--r--py/runtime.c4
-rw-r--r--py/runtime.h2
-rw-r--r--py/showbc.c20
-rw-r--r--py/vm.c60
6 files changed, 44 insertions, 130 deletions
diff --git a/py/bc0.h b/py/bc0.h
index 3d4b106d32..80a8248de7 100644
--- a/py/bc0.h
+++ b/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
diff --git a/py/emitbc.c b/py/emitbc.c
index a149582c0d..595c7ac196 100644
--- a/py/emitbc.c
+++ b/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) {
diff --git a/py/runtime.c b/py/runtime.c
index 4898864962..7e02879455 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -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);
diff --git a/py/runtime.h b/py/runtime.h
index f79cb2e306..d71e045b01 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -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);
diff --git a/py/showbc.c b/py/showbc.c
index 10b3e7490d..823769c0ef 100644
--- a/py/showbc.c
+++ b/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);
diff --git a/py/vm.c b/py/vm.c
index edcad39565..599a1d862e 100644
--- a/py/vm.c
+++ b/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: