From cc4c1adf6e05dcda54393fe512e47463fc45414e Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Jan 2017 12:34:09 +1100 Subject: py/showbc: Make sure to set the const_table before printing bytecode. --- py/showbc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'py/showbc.c') diff --git a/py/showbc.c b/py/showbc.c index 684d9af0c..9d20decdc 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -82,7 +82,6 @@ const mp_uint_t *mp_showbc_const_table; void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const mp_uint_t *const_table) { mp_showbc_code_start = ip; - mp_showbc_const_table = const_table; // get bytecode parameters mp_uint_t n_state = mp_decode_uint(&ip); @@ -159,7 +158,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); } } - mp_bytecode_print2(ip, len - 0); + mp_bytecode_print2(ip, len - 0, const_table); } const byte *mp_bytecode_print_str(const byte *ip) { @@ -547,8 +546,9 @@ const byte *mp_bytecode_print_str(const byte *ip) { return ip; } -void mp_bytecode_print2(const byte *ip, mp_uint_t len) { +void mp_bytecode_print2(const byte *ip, size_t len, const mp_uint_t *const_table) { mp_showbc_code_start = ip; + mp_showbc_const_table = const_table; while (ip < len + mp_showbc_code_start) { printf("%02u ", (uint)(ip - mp_showbc_code_start)); ip = mp_bytecode_print_str(ip); -- cgit v1.2.3 From f4df3aaa72a0460614b1ab8b7b8a7927a1165e31 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 9 Jan 2016 23:59:52 +0000 Subject: py: Allow bytecode/native to put iter_buf on stack for simple for loops. So that the "for x in it: ..." statement can now work without using the heap (so long as the iterator argument fits in an iter_buf structure). --- py/bc0.h | 1 + py/compile.c | 12 ++++++------ py/emit.h | 8 ++++---- py/emitbc.c | 17 +++++++++++++---- py/emitnative.c | 14 +++++++++++--- py/showbc.c | 4 ++++ py/vm.c | 11 +++++++++++ py/vmentrytable.h | 1 + tests/cmdline/cmd_showbc.py.exp | 8 ++++++-- 9 files changed, 57 insertions(+), 19 deletions(-) (limited to 'py/showbc.c') diff --git a/py/bc0.h b/py/bc0.h index 5ff9e50a8..c2b019f1a 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -79,6 +79,7 @@ #define MP_BC_POP_BLOCK (0x44) #define MP_BC_POP_EXCEPT (0x45) #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) #define MP_BC_BUILD_TUPLE (0x50) // uint #define MP_BC_BUILD_LIST (0x51) // uint diff --git a/py/compile.c b/py/compile.c index b84793d10..d2fa03f01 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1475,7 +1475,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { uint pop_label = comp_next_label(comp); compile_node(comp, pns->nodes[1]); // iterator - EMIT(get_iter); + EMIT_ARG(get_iter, true); EMIT_ARG(label_assign, continue_label); EMIT_ARG(for_iter, pop_label); c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable @@ -1484,7 +1484,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(jump, continue_label); } EMIT_ARG(label_assign, pop_label); - EMIT(for_iter_end); + EMIT_ARG(for_iter_end, true); // break/continue apply to outer loop (if any) in the else block END_BREAK_CONTINUE_BLOCK @@ -1680,7 +1680,7 @@ STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } STATIC void compile_yield_from(compiler_t *comp) { - EMIT(get_iter); + EMIT_ARG(get_iter, false); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT(yield_from); } @@ -2372,7 +2372,7 @@ STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, close_over_variables_etc(comp, this_scope, 0, 0); compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator - EMIT(get_iter); + EMIT_ARG(get_iter, false); EMIT_ARG(call_function, 1, 0, 0); } @@ -2900,13 +2900,13 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn // for loop mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter; compile_node(comp, pns_comp_for2->nodes[1]); - EMIT(get_iter); + EMIT_ARG(get_iter, false); compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1); } EMIT_ARG(jump, l_top); EMIT_ARG(label_assign, l_end); - EMIT(for_iter_end); + EMIT_ARG(for_iter_end, false); } STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { diff --git a/py/emit.h b/py/emit.h index 7d00f11f9..6acae9e80 100644 --- a/py/emit.h +++ b/py/emit.h @@ -110,9 +110,9 @@ typedef struct _emit_method_table_t { void (*setup_except)(emit_t *emit, mp_uint_t label); void (*setup_finally)(emit_t *emit, mp_uint_t label); void (*end_finally)(emit_t *emit); - void (*get_iter)(emit_t *emit); + 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 (*for_iter_end)(emit_t *emit, bool use_stack); void (*pop_block)(emit_t *emit); void (*pop_except)(emit_t *emit); void (*unary_op)(emit_t *emit, mp_unary_op_t op); @@ -228,9 +228,9 @@ void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label); void mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label); void mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label); void mp_emit_bc_end_finally(emit_t *emit); -void mp_emit_bc_get_iter(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_for_iter_end(emit_t *emit, bool use_stack); void mp_emit_bc_pop_block(emit_t *emit); void mp_emit_bc_pop_except(emit_t *emit); void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op); diff --git a/py/emitbc.c b/py/emitbc.c index e3a047f27..3e0c0b397 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -734,6 +734,10 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept if (label & MP_EMIT_BREAK_FROM_FOR) { // need to pop the iterator if we are breaking out of a for loop emit_write_bytecode_byte(emit, MP_BC_POP_TOP); + // also pop the iter_buf + for (size_t i = 0; i < sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t); ++i) { + emit_write_bytecode_byte(emit, MP_BC_POP_TOP); + } } emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); } else { @@ -773,9 +777,9 @@ void mp_emit_bc_end_finally(emit_t *emit) { emit_write_bytecode_byte(emit, MP_BC_END_FINALLY); } -void mp_emit_bc_get_iter(emit_t *emit) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte(emit, MP_BC_GET_ITER); +void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) { + emit_bc_pre(emit, use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) : 0); + emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER); } void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) { @@ -783,8 +787,13 @@ void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) { emit_write_bytecode_byte_unsigned_label(emit, MP_BC_FOR_ITER, label); } -void mp_emit_bc_for_iter_end(emit_t *emit) { +void mp_emit_bc_for_iter_end(emit_t *emit, bool use_stack) { emit_bc_pre(emit, -1); + if (use_stack) { + for (size_t i = 0; i < sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t); ++i) { + mp_emit_bc_pop_top(emit); + } + } } void mp_emit_bc_pop_block(emit_t *emit) { diff --git a/py/emitnative.c b/py/emitnative.c index e8e3754e1..6e8a37bde 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1799,14 +1799,19 @@ STATIC void emit_native_end_finally(emit_t *emit) { emit_post(emit); } -STATIC void emit_native_get_iter(emit_t *emit) { +STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) { // perhaps the difficult one, as we want to rewrite for loops using native code // in cases where we iterate over a Python object, can we use normal runtime calls? vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_1); assert(vtype == VTYPE_PYOBJ); - assert(0); // TODO allocate memory for iter_buf + if (use_stack) { + emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)); + } else { + // mp_getiter will allocate the iter_buf on the heap + ASM_MOV_IMM_TO_REG(emit->as, 0, REG_ARG_2); + } emit_call(emit, MP_F_GETITER); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } @@ -1822,10 +1827,13 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_for_iter_end(emit_t *emit) { +STATIC void emit_native_for_iter_end(emit_t *emit, bool use_stack) { // adjust stack counter (we get here from for_iter ending, which popped the value for us) emit_native_pre(emit); adjust_stack(emit, -1); + if (use_stack) { + adjust_stack(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t))); + } emit_post(emit); } diff --git a/py/showbc.c b/py/showbc.c index 9d20decdc..b52905f67 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -387,6 +387,10 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("GET_ITER"); break; + case MP_BC_GET_ITER_STACK: + printf("GET_ITER_STACK"); + break; + case MP_BC_FOR_ITER: DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward printf("FOR_ITER " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); diff --git a/py/vm.c b/py/vm.c index 917d41a11..848a77a45 100644 --- a/py/vm.c +++ b/py/vm.c @@ -681,7 +681,9 @@ unwind_jump:; } ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump if (unum != 0) { + // pop iter and iter_buf sp--; + sp -= sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t); } DISPATCH_WITH_PEND_EXC_CHECK(); } @@ -726,6 +728,15 @@ unwind_jump:; SET_TOP(mp_getiter(TOP(), NULL)); DISPATCH(); + ENTRY(MP_BC_GET_ITER_STACK): { + MARK_EXC_IP_SELECTIVE(); + mp_obj_t obj = TOP(); + mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp; + sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t); + SET_TOP(mp_getiter(obj, iter_buf)); + DISPATCH(); + } + ENTRY(MP_BC_FOR_ITER): { MARK_EXC_IP_SELECTIVE(); DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward diff --git a/py/vmentrytable.h b/py/vmentrytable.h index dd30dd7a5..8731c3d4c 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -73,6 +73,7 @@ static const void *const entry_table[256] = { [MP_BC_SETUP_FINALLY] = &&entry_MP_BC_SETUP_FINALLY, [MP_BC_END_FINALLY] = &&entry_MP_BC_END_FINALLY, [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, diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 1f0c054cf..8ee47eab6 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -31,7 +31,7 @@ File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ byt Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+rg names: -(N_STATE 22) +(N_STATE 23) (N_EXC_STACK 2) (INIT_CELL 14) (INIT_CELL 15) @@ -245,12 +245,16 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ LOAD_FAST 0 \\d\+ STORE_FAST 0 \\d\+ LOAD_DEREF 14 -\\d\+ GET_ITER +\\d\+ GET_ITER_STACK \\d\+ FOR_ITER \\d\+ \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 1 \\d\+ POP_TOP \\d\+ JUMP \\d\+ +\\d\+ POP_TOP +\\d\+ POP_TOP +\\d\+ POP_TOP +\\d\+ POP_TOP \\d\+ SETUP_FINALLY \\d\+ \\d\+ SETUP_EXCEPT \\d\+ \\d\+ JUMP \\d\+ -- cgit v1.2.3 From dd11af209d226b7d18d5148b239662e30ed60bad Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 19 Apr 2017 09:45:59 +1000 Subject: py: Add LOAD_SUPER_METHOD bytecode to allow heap-free super meth calls. This patch allows the following code to run without allocating on the heap: super().foo(...) Before this patch such a call would allocate a super object on the heap and then load the foo method and call it right away. The super object is only needed to perform the lookup of the method and not needed after that. This patch makes an optimisation to allocate the super object on the C stack and discard it right after use. Changes in code size due to this patch are: bare-arm: +128 minimal: +232 unix x64: +416 unix nanbox: +364 stmhal: +184 esp8266: +340 cc3200: +128 --- minimal/frozentest.mpy | Bin 255 -> 255 bytes py/bc.c | 2 +- py/bc0.h | 13 +++++++------ py/compile.c | 23 +++++++++++++++++------ py/emit.h | 4 ++-- py/emitbc.c | 6 +++--- py/emitnative.c | 19 +++++++++++++------ py/nativeglue.c | 1 + py/objtype.c | 5 +++++ py/persistentcode.c | 2 +- py/runtime.h | 1 + py/runtime0.h | 1 + py/showbc.c | 5 +++++ py/vm.c | 8 ++++++++ py/vmentrytable.h | 1 + tools/mpy-tool.py | 4 ++-- 16 files changed, 68 insertions(+), 27 deletions(-) (limited to 'py/showbc.c') diff --git a/minimal/frozentest.mpy b/minimal/frozentest.mpy index 5cb356d61..87f9581bf 100644 Binary files a/minimal/frozentest.mpy and b/minimal/frozentest.mpy differ diff --git a/py/bc.c b/py/bc.c index 4c0eb5391..fc1794683 100644 --- a/py/bc.c +++ b/py/bc.c @@ -304,7 +304,7 @@ STATIC const byte opcode_format_table[64] = { OC4(U, U, U, U), // 0x0c-0x0f OC4(B, B, B, U), // 0x10-0x13 OC4(V, U, Q, V), // 0x14-0x17 - OC4(B, U, V, V), // 0x18-0x1b + OC4(B, V, V, Q), // 0x18-0x1b OC4(Q, Q, Q, Q), // 0x1c-0x1f OC4(B, B, V, V), // 0x20-0x23 OC4(Q, Q, Q, B), // 0x24-0x27 diff --git a/py/bc0.h b/py/bc0.h index c2b019f1a..b5650abe4 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -37,12 +37,13 @@ #define MP_BC_LOAD_CONST_OBJ (0x17) // ptr #define MP_BC_LOAD_NULL (0x18) -#define MP_BC_LOAD_FAST_N (0x1a) // uint -#define MP_BC_LOAD_DEREF (0x1b) // uint -#define MP_BC_LOAD_NAME (0x1c) // qstr -#define MP_BC_LOAD_GLOBAL (0x1d) // qstr -#define MP_BC_LOAD_ATTR (0x1e) // qstr -#define MP_BC_LOAD_METHOD (0x1f) // qstr +#define MP_BC_LOAD_FAST_N (0x19) // uint +#define MP_BC_LOAD_DEREF (0x1a) // uint +#define MP_BC_LOAD_NAME (0x1b) // qstr +#define MP_BC_LOAD_GLOBAL (0x1c) // qstr +#define MP_BC_LOAD_ATTR (0x1d) // qstr +#define MP_BC_LOAD_METHOD (0x1e) // qstr +#define MP_BC_LOAD_SUPER_METHOD (0x1f) // qstr #define MP_BC_LOAD_BUILD_CLASS (0x20) #define MP_BC_LOAD_SUBSCR (0x21) diff --git a/py/compile.c b/py/compile.c index 42c2cc3a2..8533e0528 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1694,7 +1694,7 @@ STATIC void compile_yield_from(compiler_t *comp) { #if MICROPY_PY_ASYNC_AWAIT STATIC void compile_await_object_method(compiler_t *comp, qstr method) { - EMIT_ARG(load_method, method); + EMIT_ARG(load_method, method, false); EMIT_ARG(call_method, 0, 0, 0); compile_yield_from(comp); } @@ -1785,7 +1785,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod } compile_load_id(comp, context); - EMIT_ARG(load_method, MP_QSTR___aexit__); + EMIT_ARG(load_method, MP_QSTR___aexit__, false); EMIT_ARG(setup_except, try_exception_label); compile_increase_except_level(comp); @@ -2219,9 +2219,20 @@ STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *p return; } - // a super() call - EMIT_ARG(call_function, 2, 0, 0); - i = 1; + if (num_trail >= 3 + && MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period + && MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) { + // optimisation for method calls super().f(...), to eliminate heap allocation + mp_parse_node_struct_t *pns_period = pns_trail[1]; + mp_parse_node_struct_t *pns_paren = pns_trail[2]; + EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true); + compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0); + i = 3; + } else { + // a super() call + EMIT_ARG(call_function, 2, 0, 0); + i = 1; + } } // compile the remaining trailers @@ -2232,7 +2243,7 @@ STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *p // optimisation for method calls a.f(...), following PyPy mp_parse_node_struct_t *pns_period = pns_trail[i]; mp_parse_node_struct_t *pns_paren = pns_trail[i + 1]; - EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); + EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false); compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0); i += 1; } else { diff --git a/py/emit.h b/py/emit.h index 64bb957f6..0236a9b8d 100644 --- a/py/emit.h +++ b/py/emit.h @@ -88,7 +88,7 @@ typedef struct _emit_method_table_t { void (*load_const_obj)(emit_t *emit, mp_obj_t obj); void (*load_null)(emit_t *emit); void (*load_attr)(emit_t *emit, qstr qst); - void (*load_method)(emit_t *emit, qstr qst); + void (*load_method)(emit_t *emit, qstr qst, bool is_super); void (*load_build_class)(emit_t *emit); void (*load_subscr)(emit_t *emit); void (*store_attr)(emit_t *emit, qstr qst); @@ -205,7 +205,7 @@ void mp_emit_bc_load_const_str(emit_t *emit, qstr qst); void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj); void mp_emit_bc_load_null(emit_t *emit); void mp_emit_bc_load_attr(emit_t *emit, qstr qst); -void mp_emit_bc_load_method(emit_t *emit, qstr qst); +void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super); void mp_emit_bc_load_build_class(emit_t *emit); void mp_emit_bc_load_subscr(emit_t *emit); void mp_emit_bc_store_attr(emit_t *emit, qstr qst); diff --git a/py/emitbc.c b/py/emitbc.c index 673cd405f..6d8db81bc 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -594,9 +594,9 @@ void mp_emit_bc_load_attr(emit_t *emit, qstr qst) { } } -void mp_emit_bc_load_method(emit_t *emit, qstr qst) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_METHOD, qst); +void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super) { + emit_bc_pre(emit, 1 - 2 * is_super); + emit_write_bytecode_byte_qstr(emit, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst); } void mp_emit_bc_load_build_class(emit_t *emit) { diff --git a/py/emitnative.c b/py/emitnative.c index 3ab001f8d..99adc809c 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -85,6 +85,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_LOAD_BUILD_CLASS] = 0, [MP_F_LOAD_ATTR] = 2, [MP_F_LOAD_METHOD] = 3, + [MP_F_LOAD_SUPER_METHOD] = 2, [MP_F_STORE_NAME] = 2, [MP_F_STORE_GLOBAL] = 2, [MP_F_STORE_ATTR] = 3, @@ -1065,12 +1066,18 @@ STATIC void emit_native_load_attr(emit_t *emit, qstr qst) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_load_method(emit_t *emit, qstr qst) { - vtype_kind_t vtype_base; - emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base - assert(vtype_base == VTYPE_PYOBJ); - emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr - emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name +STATIC void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) { + if (is_super) { + emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, 3); // arg2 = dest ptr + emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, 2); // arg2 = dest ptr + emit_call_with_imm_arg(emit, MP_F_LOAD_SUPER_METHOD, qst, REG_ARG_1); // arg1 = method name + } else { + vtype_kind_t vtype_base; + emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base + assert(vtype_base == VTYPE_PYOBJ); + emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr + emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name + } } STATIC void emit_native_load_build_class(emit_t *emit) { diff --git a/py/nativeglue.c b/py/nativeglue.c index 694dfca74..c75e5ec04 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -133,6 +133,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_load_build_class, mp_load_attr, mp_load_method, + mp_load_super_method, mp_store_name, mp_store_global, mp_store_attr, diff --git a/py/objtype.c b/py/objtype.c index de1ee8c42..2a119e40f 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1070,6 +1070,11 @@ const mp_obj_type_t mp_type_super = { .attr = super_attr, }; +void mp_load_super_method(qstr attr, mp_obj_t *dest) { + mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]}; + mp_load_method(MP_OBJ_FROM_PTR(&super), attr, dest); +} + /******************************************************************************/ // subclassing and built-ins specific to types diff --git a/py/persistentcode.c b/py/persistentcode.c index 2a9a5b7cc..a71045a29 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -39,7 +39,7 @@ #include "py/smallint.h" // The current version of .mpy files -#define MPY_VERSION (1) +#define MPY_VERSION (2) // The feature flags byte encodes the compile-time config options that // affect the generate bytecode. diff --git a/py/runtime.h b/py/runtime.h index 177869145..d75d23ff1 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -131,6 +131,7 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr); void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest); void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest); void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest); +void mp_load_super_method(qstr attr, mp_obj_t *dest); void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val); mp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf); diff --git a/py/runtime0.h b/py/runtime0.h index b1ed71026..720fe6a23 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -107,6 +107,7 @@ typedef enum { MP_F_LOAD_BUILD_CLASS, MP_F_LOAD_ATTR, MP_F_LOAD_METHOD, + MP_F_LOAD_SUPER_METHOD, MP_F_STORE_NAME, MP_F_STORE_GLOBAL, MP_F_STORE_ATTR, diff --git a/py/showbc.c b/py/showbc.c index b52905f67..0bccf8427 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -245,6 +245,11 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("LOAD_METHOD %s", qstr_str(qst)); break; + case MP_BC_LOAD_SUPER_METHOD: + DECODE_QSTR; + printf("LOAD_SUPER_METHOD %s", qstr_str(qst)); + break; + case MP_BC_LOAD_BUILD_CLASS: printf("LOAD_BUILD_CLASS"); break; diff --git a/py/vm.c b/py/vm.c index 8ce635ca8..469528df4 100644 --- a/py/vm.c +++ b/py/vm.c @@ -376,6 +376,14 @@ dispatch_loop: DISPATCH(); } + ENTRY(MP_BC_LOAD_SUPER_METHOD): { + MARK_EXC_IP_SELECTIVE(); + DECODE_QSTR; + sp -= 1; + mp_load_super_method(qst, sp - 1); + DISPATCH(); + } + ENTRY(MP_BC_LOAD_BUILD_CLASS): MARK_EXC_IP_SELECTIVE(); PUSH(mp_load_build_class()); diff --git a/py/vmentrytable.h b/py/vmentrytable.h index 8731c3d4c..dd9789e34 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -44,6 +44,7 @@ static const void *const entry_table[256] = { [MP_BC_LOAD_GLOBAL] = &&entry_MP_BC_LOAD_GLOBAL, [MP_BC_LOAD_ATTR] = &&entry_MP_BC_LOAD_ATTR, [MP_BC_LOAD_METHOD] = &&entry_MP_BC_LOAD_METHOD, + [MP_BC_LOAD_SUPER_METHOD] = &&entry_MP_BC_LOAD_SUPER_METHOD, [MP_BC_LOAD_BUILD_CLASS] = &&entry_MP_BC_LOAD_BUILD_CLASS, [MP_BC_LOAD_SUBSCR] = &&entry_MP_BC_LOAD_SUBSCR, [MP_BC_STORE_FAST_N] = &&entry_MP_BC_STORE_FAST_N, diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index d14e0f4ea..d2a1c67ad 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -57,7 +57,7 @@ class FreezeError(Exception): return 'error while freezing %s: %s' % (self.rawcode.source_file, self.msg) class Config: - MPY_VERSION = 1 + MPY_VERSION = 2 MICROPY_LONGINT_IMPL_NONE = 0 MICROPY_LONGINT_IMPL_LONGLONG = 1 MICROPY_LONGINT_IMPL_MPZ = 2 @@ -94,7 +94,7 @@ def make_opcode_format(): OC4(U, U, U, U), # 0x0c-0x0f OC4(B, B, B, U), # 0x10-0x13 OC4(V, U, Q, V), # 0x14-0x17 - OC4(B, U, V, V), # 0x18-0x1b + OC4(B, V, V, Q), # 0x18-0x1b OC4(Q, Q, Q, Q), # 0x1c-0x1f OC4(B, B, V, V), # 0x20-0x23 OC4(Q, Q, Q, B), # 0x24-0x27 -- cgit v1.2.3