py/emit: Combine fast and deref into one function for load/store/delete.

Reduces code size by:

   bare-arm:   -16
minimal x86:  -208
   unix x64:  -408
unix nanbox:  -248
      stm32:   -12
     cc3200:   -24
    esp8266:   -96
      esp32:   -44
This commit is contained in:
Damien George 2018-05-19 00:11:04 +10:00
parent 400273a799
commit 0a25fff956
5 changed files with 61 additions and 68 deletions

View File

@ -65,7 +65,7 @@ typedef enum {
// we need a method table to do the lookup for the emitter functions // 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(fun) (comp->emit_method_table->fun(comp->emit))
#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__)) #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)) #define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst))
#else #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 // 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(fun) (mp_emit_bc_##fun(comp->emit))
#define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__)) #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)) #define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst))
#endif #endif

View File

@ -55,11 +55,14 @@ typedef enum {
#define MP_EMIT_NATIVE_TYPE_RETURN (1) #define MP_EMIT_NATIVE_TYPE_RETURN (1)
#define MP_EMIT_NATIVE_TYPE_ARG (2) #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 _emit_t emit_t;
typedef struct _mp_emit_method_table_id_ops_t { typedef struct _mp_emit_method_table_id_ops_t {
void (*fast)(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 (*deref)(emit_t *emit, qstr qst, mp_uint_t local_num);
void (*name)(emit_t *emit, qstr qst); void (*name)(emit_t *emit, qstr qst);
void (*global)(emit_t *emit, qstr qst); void (*global)(emit_t *emit, qstr qst);
} mp_emit_method_table_id_ops_t; } 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_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_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_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind);
void mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num);
void mp_emit_bc_load_name(emit_t *emit, qstr qst); 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_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_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind);
void mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num);
void mp_emit_bc_store_name(emit_t *emit, qstr qst); 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_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_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind);
void mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num);
void mp_emit_bc_delete_name(emit_t *emit, qstr qst); void mp_emit_bc_delete_name(emit_t *emit, qstr qst);
void mp_emit_bc_delete_global(emit_t *emit, qstr qst); void mp_emit_bc_delete_global(emit_t *emit, qstr qst);

View File

@ -556,22 +556,18 @@ void mp_emit_bc_load_null(emit_t *emit) {
emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL); 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; (void)qst;
emit_bc_pre(emit, 1); 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); emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num);
} else { } 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 mp_emit_bc_load_name(emit_t *emit, qstr qst) {
(void)qst; (void)qst;
emit_bc_pre(emit, 1); 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); 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; (void)qst;
emit_bc_pre(emit, -1); 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); emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num);
} else { } 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) { void mp_emit_bc_store_name(emit_t *emit, qstr qst) {
emit_bc_pre(emit, -1); emit_bc_pre(emit, -1);
emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_NAME, qst); 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); 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 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; (void)qst;
emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST, local_num); emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST + kind, local_num);
}
void mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
(void)qst;
emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_DEREF, local_num);
} }
void mp_emit_bc_delete_name(emit_t *emit, qstr qst) { 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_set_source_line,
{ {
mp_emit_bc_load_fast, mp_emit_bc_load_local,
mp_emit_bc_load_deref,
mp_emit_bc_load_name, mp_emit_bc_load_name,
mp_emit_bc_load_global, mp_emit_bc_load_global,
}, },
{ {
mp_emit_bc_store_fast, mp_emit_bc_store_local,
mp_emit_bc_store_deref,
mp_emit_bc_store_name, mp_emit_bc_store_name,
mp_emit_bc_store_global, mp_emit_bc_store_global,
}, },
{ {
mp_emit_bc_delete_fast, mp_emit_bc_delete_local,
mp_emit_bc_delete_deref,
mp_emit_bc_delete_name, mp_emit_bc_delete_name,
mp_emit_bc_delete_global, mp_emit_bc_delete_global,
}, },
@ -1056,22 +1042,19 @@ const emit_method_table_t emit_bc_method_table = {
}; };
#else #else
const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops = { 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_local,
mp_emit_bc_load_deref,
mp_emit_bc_load_name, mp_emit_bc_load_name,
mp_emit_bc_load_global, mp_emit_bc_load_global,
}; };
const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops = { 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_local,
mp_emit_bc_store_deref,
mp_emit_bc_store_name, mp_emit_bc_store_name,
mp_emit_bc_store_global, mp_emit_bc_store_global,
}; };
const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops = { 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_local,
mp_emit_bc_delete_deref,
mp_emit_bc_delete_name, mp_emit_bc_delete_name,
mp_emit_bc_delete_global, mp_emit_bc_delete_global,
}; };

View File

@ -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) { } else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {
emit_method_table->global(emit, qst); emit_method_table->global(emit, qst);
} else if (id->kind == ID_INFO_KIND_LOCAL) { } 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 { } else {
assert(id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE); 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);
} }
} }

View File

@ -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); 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) { STATIC void emit_native_load_name(emit_t *emit, qstr qst) {
DEBUG_printf("load_name(%s)\n", qstr_str(qst)); DEBUG_printf("load_name(%s)\n", qstr_str(qst));
emit_native_pre(emit); 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); 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) { 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)) // mp_store_name, but needs conversion of object (maybe have mp_viper_store_name(obj, type))
vtype_kind_t vtype; 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) { STATIC void emit_native_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) {
// TODO: This is not compliant implementation. We could use MP_OBJ_SENTINEL if (kind == MP_EMIT_IDOP_LOCAL_FAST) {
// to mark deleted vars but then every var would need to be checked on // TODO: This is not compliant implementation. We could use MP_OBJ_SENTINEL
// each access. Very inefficient, so just set value to None to enable GC. // to mark deleted vars but then every var would need to be checked on
emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE); // each access. Very inefficient, so just set value to None to enable GC.
emit_native_store_fast(emit, qst, local_num); emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE);
} emit_native_store_fast(emit, qst, local_num);
} else {
STATIC void emit_native_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { // TODO implement me!
// TODO implement me! }
(void)emit;
(void)qst;
(void)local_num;
} }
STATIC void emit_native_delete_name(emit_t *emit, qstr qst) { 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_set_source_line,
{ {
emit_native_load_fast, emit_native_load_local,
emit_native_load_deref,
emit_native_load_name, emit_native_load_name,
emit_native_load_global, emit_native_load_global,
}, },
{ {
emit_native_store_fast, emit_native_store_local,
emit_native_store_deref,
emit_native_store_name, emit_native_store_name,
emit_native_store_global, emit_native_store_global,
}, },
{ {
emit_native_delete_fast, emit_native_delete_local,
emit_native_delete_deref,
emit_native_delete_name, emit_native_delete_name,
emit_native_delete_global, emit_native_delete_global,
}, },