From 6211d979eed0a809cef03230e14b6d264f6f92ee Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 May 2018 21:43:41 +1000 Subject: [PATCH] py/emit: Combine load/store/delete attr into one emit function. Reduces code size by: bare-arm: -20 minimal x86: -140 unix x64: -408 unix nanbox: -140 stm32: -68 cc3200: -16 esp8266: -80 esp32: -32 --- py/compile.c | 14 +++++++------- py/emit.h | 13 +++++++------ py/emitbc.c | 43 ++++++++++++++++++------------------------- py/emitnative.c | 14 +++++++++++--- 4 files changed, 43 insertions(+), 41 deletions(-) diff --git a/py/compile.c b/py/compile.c index 6aba2b896e..e3735bf3dd 100644 --- a/py/compile.c +++ b/py/compile.c @@ -381,12 +381,12 @@ STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, as assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); if (assign_kind == ASSIGN_AUG_LOAD) { EMIT(dup_top); - EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); + EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_LOAD); } else { if (assign_kind == ASSIGN_AUG_STORE) { EMIT(rot_two); } - EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); + EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_STORE); } return; } @@ -820,7 +820,7 @@ STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, name_nodes[0]); for (int j = 1; j < name_len; j++) { assert(MP_PARSE_NODE_IS_ID(name_nodes[j])); // should be - EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j])); + EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j]), MP_EMIT_ATTR_LOAD); } // nodes[1] contains arguments to the decorator function, if any @@ -887,7 +887,7 @@ STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { EMIT_ARG(subscr, MP_EMIT_SUBSCR_DELETE); } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); - EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); + EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_DELETE); } else { goto cannot_delete; } @@ -1061,7 +1061,7 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) { EMIT_ARG(import_name, q_full); if (is_as) { for (int i = 1; i < n; i++) { - EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); + EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), MP_EMIT_ATTR_LOAD); } } } @@ -1811,7 +1811,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod // at this point the stack contains: ..., __aexit__, self, exc EMIT(dup_top); #if MICROPY_CPYTHON_COMPAT - EMIT_ARG(load_attr, MP_QSTR___class__); // get type(exc) + EMIT_ARG(attr, MP_QSTR___class__, MP_EMIT_ATTR_LOAD); // get type(exc) #else compile_load_id(comp, MP_QSTR_type); EMIT(rot_two); @@ -2541,7 +2541,7 @@ STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pn STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) { // object who's attribute we want is on top of stack - EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get + EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]), MP_EMIT_ATTR_LOAD); // attribute to get } #if MICROPY_PY_BUILTINS_SLICE diff --git a/py/emit.h b/py/emit.h index 6467f84e8f..c9e4f0c718 100644 --- a/py/emit.h +++ b/py/emit.h @@ -68,6 +68,11 @@ typedef enum { #define MP_EMIT_SUBSCR_STORE (1) #define MP_EMIT_SUBSCR_DELETE (2) +// Kind for emit->attr() +#define MP_EMIT_ATTR_LOAD (0) +#define MP_EMIT_ATTR_STORE (1) +#define MP_EMIT_ATTR_DELETE (2) + // Kind for emit->build() #define MP_EMIT_BUILD_TUPLE (0) #define MP_EMIT_BUILD_LIST (1) @@ -105,12 +110,10 @@ typedef struct _emit_method_table_t { void (*load_const_str)(emit_t *emit, qstr qst); 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, bool is_super); void (*load_build_class)(emit_t *emit); void (*subscr)(emit_t *emit, int kind); - void (*store_attr)(emit_t *emit, qstr qst); - void (*delete_attr)(emit_t *emit, qstr qst); + void (*attr)(emit_t *emit, qstr qst, int kind); void (*dup_top)(emit_t *emit); void (*dup_top_two)(emit_t *emit); void (*pop_top)(emit_t *emit); @@ -211,12 +214,10 @@ void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg); 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, bool is_super); void mp_emit_bc_load_build_class(emit_t *emit); void mp_emit_bc_subscr(emit_t *emit, int kind); -void mp_emit_bc_store_attr(emit_t *emit, qstr qst); -void mp_emit_bc_delete_attr(emit_t *emit, qstr qst); +void mp_emit_bc_attr(emit_t *emit, qstr qst, int kind); void mp_emit_bc_dup_top(emit_t *emit); void mp_emit_bc_dup_top_two(emit_t *emit); void mp_emit_bc_pop_top(emit_t *emit); diff --git a/py/emitbc.c b/py/emitbc.c index b342c21a41..774343f2bf 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -579,14 +579,6 @@ void mp_emit_bc_load_global(emit_t *emit, qstr qst, int kind) { } } -void mp_emit_bc_load_attr(emit_t *emit, qstr qst) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst); - if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { - emit_write_bytecode_byte(emit, 0); - } -} - 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); @@ -611,6 +603,23 @@ void mp_emit_bc_subscr(emit_t *emit, int kind) { } } +void mp_emit_bc_attr(emit_t *emit, qstr qst, int kind) { + if (kind == MP_EMIT_ATTR_LOAD) { + emit_bc_pre(emit, 0); + emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst); + } else { + if (kind == MP_EMIT_ATTR_DELETE) { + mp_emit_bc_load_null(emit); + mp_emit_bc_rot_two(emit); + } + emit_bc_pre(emit, -2); + emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_ATTR, qst); + } + if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { + emit_write_bytecode_byte(emit, 0); + } +} + void mp_emit_bc_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_STORE_FAST_N); MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_STORE_DEREF); @@ -630,14 +639,6 @@ void mp_emit_bc_store_global(emit_t *emit, qstr qst, int kind) { emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_NAME + kind, qst); } -void mp_emit_bc_store_attr(emit_t *emit, qstr qst) { - emit_bc_pre(emit, -2); - emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_ATTR, qst); - if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { - emit_write_bytecode_byte(emit, 0); - } -} - void mp_emit_bc_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_DELETE_FAST); MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_DELETE_DEREF); @@ -652,12 +653,6 @@ void mp_emit_bc_delete_global(emit_t *emit, qstr qst, int kind) { emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_NAME + kind, qst); } -void mp_emit_bc_delete_attr(emit_t *emit, qstr qst) { - mp_emit_bc_load_null(emit); - mp_emit_bc_rot_two(emit); - mp_emit_bc_store_attr(emit, qst); -} - void mp_emit_bc_dup_top(emit_t *emit) { emit_bc_pre(emit, 1); emit_write_bytecode_byte(emit, MP_BC_DUP_TOP); @@ -959,12 +954,10 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_load_const_str, mp_emit_bc_load_const_obj, mp_emit_bc_load_null, - mp_emit_bc_load_attr, mp_emit_bc_load_method, mp_emit_bc_load_build_class, mp_emit_bc_subscr, - mp_emit_bc_store_attr, - mp_emit_bc_delete_attr, + mp_emit_bc_attr, mp_emit_bc_dup_top, mp_emit_bc_dup_top_two, mp_emit_bc_pop_top, diff --git a/py/emitnative.c b/py/emitnative.c index 725ee21edb..8624680a6d 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1457,6 +1457,16 @@ STATIC void emit_native_subscr(emit_t *emit, int kind) { } } +STATIC void emit_native_attr(emit_t *emit, qstr qst, int kind) { + if (kind == MP_EMIT_ATTR_LOAD) { + emit_native_load_attr(emit, qst); + } else if (kind == MP_EMIT_ATTR_STORE) { + emit_native_store_attr(emit, qst); + } else { + emit_native_delete_attr(emit, qst); + } +} + STATIC void emit_native_dup_top(emit_t *emit) { DEBUG_printf("dup_top\n"); vtype_kind_t vtype; @@ -2226,12 +2236,10 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_load_const_str, emit_native_load_const_obj, emit_native_load_null, - emit_native_load_attr, emit_native_load_method, emit_native_load_build_class, emit_native_subscr, - emit_native_store_attr, - emit_native_delete_attr, + emit_native_attr, emit_native_dup_top, emit_native_dup_top_two, emit_native_pop_top,