From 4e3bac2e42788aa9312a6145aef18da083eac2df Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 16 Feb 2017 15:32:34 +1100 Subject: py/runtime: Convert mp_uint_t to size_t where appropriate. --- py/nativeglue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py/nativeglue.c') diff --git a/py/nativeglue.c b/py/nativeglue.c index 5f2164ee0..5db63080b 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -86,7 +86,7 @@ mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) { // wrapper that accepts n_args and n_kw in one argument // (native emitter can only pass at most 3 arguments to a function) -mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args) { +mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) { return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args); } -- cgit v1.2.3 From 088740ecc40476fd0796a3ef6a68ee7c677eae64 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 17 Jan 2017 15:27:37 +1100 Subject: py: Optimise storage of iterator so it takes only 4 slots on Py stack. --- py/compile.c | 8 ++++---- py/emitbc.c | 6 +++--- py/emitnative.c | 21 +++++++++------------ py/nativeglue.c | 30 ++++++++++++++++++++++++++++-- py/runtime0.h | 4 ++-- py/vm.c | 25 +++++++++++++++++++------ 6 files changed, 65 insertions(+), 29 deletions(-) (limited to 'py/nativeglue.c') diff --git a/py/compile.c b/py/compile.c index 4fde278d0..5ea7bb4b2 100644 --- a/py/compile.c +++ b/py/compile.c @@ -2887,7 +2887,7 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn EMIT(yield_value); EMIT(pop_top); } else { - EMIT_ARG(store_comp, comp->scope_cur->kind, 5 * for_depth + 6); + EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5); } } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) { // if condition @@ -3070,13 +3070,13 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { #endif } - // dummy 4 objects - EMIT(load_null); + // There are 4 slots on the stack for the iterator, and the first one is + // NULL to indicate that the second one points to the iterator object. EMIT(load_null); + compile_load_id(comp, qstr_arg); EMIT(load_null); EMIT(load_null); - compile_load_id(comp, qstr_arg); compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0); if (scope->kind == SCOPE_GEN_EXPR) { diff --git a/py/emitbc.c b/py/emitbc.c index 0d7e6519b..caa6761fe 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -735,7 +735,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept // 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) { + for (size_t i = 0; i < sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1; ++i) { emit_write_bytecode_byte(emit, MP_BC_POP_TOP); } } @@ -778,7 +778,7 @@ void mp_emit_bc_end_finally(emit_t *emit) { } 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_bc_pre(emit, use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1 : 0); emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER); } @@ -788,7 +788,7 @@ void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) { } void mp_emit_bc_for_iter_end(emit_t *emit, bool use_stack) { - emit_bc_pre(emit, use_stack ? -1 - sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) : -1); + emit_bc_pre(emit, -(use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) : 1)); } void mp_emit_bc_pop_block(emit_t *emit) { diff --git a/py/emitnative.c b/py/emitnative.c index 6e8a37bde..ffc4d9187 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -105,8 +105,8 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3, [MP_F_CALL_METHOD_N_KW] = 3, [MP_F_CALL_METHOD_N_KW_VAR] = 3, - [MP_F_GETITER] = 1, - [MP_F_ITERNEXT] = 1, + [MP_F_NATIVE_GETITER] = 2, + [MP_F_NATIVE_ITERNEXT] = 1, [MP_F_NLR_PUSH] = 1, [MP_F_NLR_POP] = 0, [MP_F_NATIVE_RAISE] = 1, @@ -1808,20 +1808,20 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) { assert(vtype == VTYPE_PYOBJ); 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)); + emit_call(emit, MP_F_NATIVE_GETITER); } 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_NATIVE_GETITER); + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } - emit_call(emit, MP_F_GETITER); - emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) { emit_native_pre(emit); - vtype_kind_t vtype; - emit_access_stack(emit, 1, &vtype, REG_ARG_1); - assert(vtype == VTYPE_PYOBJ); - emit_call(emit, MP_F_ITERNEXT); + emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)); + adjust_stack(emit, 4); + emit_call(emit, MP_F_NATIVE_ITERNEXT); ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1); ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); @@ -1830,10 +1830,7 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) { 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))); - } + adjust_stack(emit, -(use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) : 1)); emit_post(emit); } diff --git a/py/nativeglue.c b/py/nativeglue.c index 5db63080b..694dfca74 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -98,6 +98,32 @@ void mp_native_raise(mp_obj_t o) { } } +// wrapper that handles iterator buffer +STATIC mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) { + if (iter == NULL) { + return mp_getiter(obj, NULL); + } else { + obj = mp_getiter(obj, iter); + if (obj != MP_OBJ_FROM_PTR(iter)) { + // Iterator didn't use the stack so indicate that with MP_OBJ_NULL. + iter->base.type = MP_OBJ_NULL; + iter->buf[0] = obj; + } + return NULL; + } +} + +// wrapper that handles iterator buffer +STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) { + mp_obj_t obj; + if (iter->base.type == MP_OBJ_NULL) { + obj = iter->buf[0]; + } else { + obj = MP_OBJ_FROM_PTR(iter); + } + return mp_iternext(obj); +} + // these must correspond to the respective enum in runtime0.h void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_convert_obj_to_native, @@ -127,8 +153,8 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_native_call_function_n_kw, mp_call_method_n_kw, mp_call_method_n_kw_var, - mp_getiter, - mp_iternext, + mp_native_getiter, + mp_native_iternext, nlr_push, nlr_pop, mp_native_raise, diff --git a/py/runtime0.h b/py/runtime0.h index 8d62403a7..b1ed71026 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -127,8 +127,8 @@ typedef enum { MP_F_NATIVE_CALL_FUNCTION_N_KW, MP_F_CALL_METHOD_N_KW, MP_F_CALL_METHOD_N_KW_VAR, - MP_F_GETITER, - MP_F_ITERNEXT, + MP_F_NATIVE_GETITER, + MP_F_NATIVE_ITERNEXT, MP_F_NLR_PUSH, MP_F_NLR_POP, MP_F_NATIVE_RAISE, diff --git a/py/vm.c b/py/vm.c index f9eb2692d..7a906cd80 100644 --- a/py/vm.c +++ b/py/vm.c @@ -728,12 +728,20 @@ unwind_jump:; SET_TOP(mp_getiter(TOP(), NULL)); DISPATCH(); + // An iterator for a for-loop takes 4 slots on the stack. They are either + // used to store the iterator object itself, or the first slot is NULL and + // the second slot holds a reference to the iterator object. 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)); + sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1; + obj = mp_getiter(obj, iter_buf); + if (obj != MP_OBJ_FROM_PTR(iter_buf)) { + // Iterator didn't use the stack so indicate that with MP_OBJ_NULL. + sp[-3] = MP_OBJ_NULL; + sp[-2] = obj; + } DISPATCH(); } @@ -741,10 +749,15 @@ unwind_jump:; MARK_EXC_IP_SELECTIVE(); DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward code_state->sp = sp; - assert(TOP()); - mp_obj_t value = mp_iternext_allow_raise(TOP()); + mp_obj_t obj; + if (sp[-3] == MP_OBJ_NULL) { + obj = sp[-2]; + } else { + obj = MP_OBJ_FROM_PTR(&sp[-3]); + } + mp_obj_t value = mp_iternext_allow_raise(obj); if (value == MP_OBJ_STOP_ITERATION) { - sp -= 5; // pop the exhausted iterator + sp -= 4; // pop the exhausted iterator ip += ulab; // jump to after for-block } else { PUSH(value); // push the next iteration value @@ -1294,7 +1307,7 @@ exception_handler: const byte *ip = code_state->ip + 1; DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward code_state->ip = ip + ulab; // jump to after for-block - code_state->sp -= 5; // pop the exhausted iterator + code_state->sp -= 4; // pop the exhausted iterator goto outer_dispatch_loop; // continue with dispatch loop } else if (*code_state->ip == MP_BC_YIELD_FROM) { // StopIteration inside yield from call means return a value of -- 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/nativeglue.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