diff --git a/py/compile.c b/py/compile.c index c2dd914f03..4d985a07fc 100644 --- a/py/compile.c +++ b/py/compile.c @@ -65,7 +65,7 @@ typedef enum { // we need a method table to do the lookup for the emitter functions #define EMIT(fun) (comp->emit_method_table->fun(comp->emit)) #define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__)) -#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.fast(comp->emit, qst, local_num)) +#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST)) #define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst)) #else @@ -73,7 +73,7 @@ typedef enum { // if we only have the bytecode emitter enabled then we can do a direct call to the functions #define EMIT(fun) (mp_emit_bc_##fun(comp->emit)) #define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__)) -#define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_fast(comp->emit, qst, local_num)) +#define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST)) #define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst)) #endif diff --git a/py/emit.h b/py/emit.h index 270a40633c..5fe3c3d1f6 100644 --- a/py/emit.h +++ b/py/emit.h @@ -55,11 +55,14 @@ typedef enum { #define MP_EMIT_NATIVE_TYPE_RETURN (1) #define MP_EMIT_NATIVE_TYPE_ARG (2) +// Kind for emit_id_ops->local() +#define MP_EMIT_IDOP_LOCAL_FAST (0) +#define MP_EMIT_IDOP_LOCAL_DEREF (1) + typedef struct _emit_t emit_t; typedef struct _mp_emit_method_table_id_ops_t { - void (*fast)(emit_t *emit, qstr qst, mp_uint_t local_num); - void (*deref)(emit_t *emit, qstr qst, mp_uint_t local_num); + void (*local)(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void (*name)(emit_t *emit, qstr qst); void (*global)(emit_t *emit, qstr qst); } mp_emit_method_table_id_ops_t; @@ -180,16 +183,13 @@ bool mp_emit_bc_last_emit_was_return_value(emit_t *emit); void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta); void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line); -void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num); -void mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num); +void mp_emit_bc_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void mp_emit_bc_load_name(emit_t *emit, qstr qst); void mp_emit_bc_load_global(emit_t *emit, qstr qst); -void mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num); -void mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num); +void mp_emit_bc_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void mp_emit_bc_store_name(emit_t *emit, qstr qst); void mp_emit_bc_store_global(emit_t *emit, qstr qst); -void mp_emit_bc_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num); -void mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num); +void mp_emit_bc_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void mp_emit_bc_delete_name(emit_t *emit, qstr qst); void mp_emit_bc_delete_global(emit_t *emit, qstr qst); diff --git a/py/emitbc.c b/py/emitbc.c index b1b61ba67e..28d32d4ea8 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -556,22 +556,18 @@ void mp_emit_bc_load_null(emit_t *emit) { emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL); } -void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { +void mp_emit_bc_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { + MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_LOAD_FAST_N); + MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_LOAD_DEREF); (void)qst; emit_bc_pre(emit, 1); - if (local_num <= 15) { + if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) { emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num); } else { - emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num); + emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N + kind, local_num); } } -void mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { - (void)qst; - emit_bc_pre(emit, 1); - emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_DEREF, local_num); -} - void mp_emit_bc_load_name(emit_t *emit, qstr qst) { (void)qst; emit_bc_pre(emit, 1); @@ -613,22 +609,18 @@ void mp_emit_bc_load_subscr(emit_t *emit) { emit_write_bytecode_byte(emit, MP_BC_LOAD_SUBSCR); } -void mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { +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); (void)qst; emit_bc_pre(emit, -1); - if (local_num <= 15) { + if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) { emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num); } else { - emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N, local_num); + emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N + kind, local_num); } } -void mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { - (void)qst; - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_uint(emit, MP_BC_STORE_DEREF, local_num); -} - void mp_emit_bc_store_name(emit_t *emit, qstr qst) { emit_bc_pre(emit, -1); emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_NAME, qst); @@ -652,14 +644,11 @@ void mp_emit_bc_store_subscr(emit_t *emit) { emit_write_bytecode_byte(emit, MP_BC_STORE_SUBSCR); } -void mp_emit_bc_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { - (void)qst; - emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST, local_num); -} - -void mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { +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); (void)qst; - emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_DEREF, local_num); + emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST + kind, local_num); } void mp_emit_bc_delete_name(emit_t *emit, qstr qst) { @@ -972,20 +961,17 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_set_source_line, { - mp_emit_bc_load_fast, - mp_emit_bc_load_deref, + mp_emit_bc_load_local, mp_emit_bc_load_name, mp_emit_bc_load_global, }, { - mp_emit_bc_store_fast, - mp_emit_bc_store_deref, + mp_emit_bc_store_local, mp_emit_bc_store_name, mp_emit_bc_store_global, }, { - mp_emit_bc_delete_fast, - mp_emit_bc_delete_deref, + mp_emit_bc_delete_local, mp_emit_bc_delete_name, mp_emit_bc_delete_global, }, @@ -1056,22 +1042,19 @@ const emit_method_table_t emit_bc_method_table = { }; #else const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops = { - mp_emit_bc_load_fast, - mp_emit_bc_load_deref, + mp_emit_bc_load_local, mp_emit_bc_load_name, mp_emit_bc_load_global, }; const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops = { - mp_emit_bc_store_fast, - mp_emit_bc_store_deref, + mp_emit_bc_store_local, mp_emit_bc_store_name, mp_emit_bc_store_global, }; const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops = { - mp_emit_bc_delete_fast, - mp_emit_bc_delete_deref, + mp_emit_bc_delete_local, mp_emit_bc_delete_name, mp_emit_bc_delete_global, }; diff --git a/py/emitcommon.c b/py/emitcommon.c index 07b1dbb4ce..47fd41ef2e 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -67,10 +67,10 @@ void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emi } else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) { emit_method_table->global(emit, qst); } else if (id->kind == ID_INFO_KIND_LOCAL) { - emit_method_table->fast(emit, qst, id->local_num); + emit_method_table->local(emit, qst, id->local_num, MP_EMIT_IDOP_LOCAL_FAST); } else { assert(id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE); - emit_method_table->deref(emit, qst, id->local_num); + emit_method_table->local(emit, qst, id->local_num, MP_EMIT_IDOP_LOCAL_DEREF); } } diff --git a/py/emitnative.c b/py/emitnative.c index 7e017ba39f..9e16ef4bd9 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -938,6 +938,14 @@ STATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } +STATIC void emit_native_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { + if (kind == MP_EMIT_IDOP_LOCAL_FAST) { + emit_native_load_fast(emit, qst, local_num); + } else { + emit_native_load_deref(emit, qst, local_num); + } +} + STATIC void emit_native_load_name(emit_t *emit, qstr qst) { DEBUG_printf("load_name(%s)\n", qstr_str(qst)); emit_native_pre(emit); @@ -1178,6 +1186,14 @@ STATIC void emit_native_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) emit_post(emit); } +STATIC void emit_native_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { + if (kind == MP_EMIT_IDOP_LOCAL_FAST) { + emit_native_store_fast(emit, qst, local_num); + } else { + emit_native_store_deref(emit, qst, local_num); + } +} + STATIC void emit_native_store_name(emit_t *emit, qstr qst) { // mp_store_name, but needs conversion of object (maybe have mp_viper_store_name(obj, type)) vtype_kind_t vtype; @@ -1389,19 +1405,16 @@ STATIC void emit_native_store_subscr(emit_t *emit) { } } -STATIC void emit_native_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { - // TODO: This is not compliant implementation. We could use MP_OBJ_SENTINEL - // to mark deleted vars but then every var would need to be checked on - // each access. Very inefficient, so just set value to None to enable GC. - emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE); - emit_native_store_fast(emit, qst, local_num); -} - -STATIC void emit_native_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { - // TODO implement me! - (void)emit; - (void)qst; - (void)local_num; +STATIC void emit_native_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { + if (kind == MP_EMIT_IDOP_LOCAL_FAST) { + // TODO: This is not compliant implementation. We could use MP_OBJ_SENTINEL + // to mark deleted vars but then every var would need to be checked on + // each access. Very inefficient, so just set value to None to enable GC. + emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE); + emit_native_store_fast(emit, qst, local_num); + } else { + // TODO implement me! + } } STATIC void emit_native_delete_name(emit_t *emit, qstr qst) { @@ -2192,20 +2205,17 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_set_source_line, { - emit_native_load_fast, - emit_native_load_deref, + emit_native_load_local, emit_native_load_name, emit_native_load_global, }, { - emit_native_store_fast, - emit_native_store_deref, + emit_native_store_local, emit_native_store_name, emit_native_store_global, }, { - emit_native_delete_fast, - emit_native_delete_deref, + emit_native_delete_local, emit_native_delete_name, emit_native_delete_global, },