diff --git a/py/compile.c b/py/compile.c index f397501f17..7a3d810f9d 100644 --- a/py/compile.c +++ b/py/compile.c @@ -10,11 +10,11 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" -#include "scope.h" #include "runtime0.h" -#include "emit.h" -#include "emitglue.h" #include "obj.h" +#include "emitglue.h" +#include "scope.h" +#include "emit.h" #include "compile.h" #include "runtime.h" #include "builtin.h" @@ -283,7 +283,7 @@ STATIC void compile_decrease_except_level(compiler_t *comp) { } STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) { - scope_t *scope = scope_new(kind, pn, comp->source_file, mp_emit_glue_get_unique_code_id(), emit_options); + scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options); scope->parent = comp->scope_cur; scope->next = NULL; if (comp->scope_head == NULL) { @@ -3454,7 +3454,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is #endif // !MICROPY_EMIT_CPYTHON // free the scopes - uint unique_code_id = module_scope->unique_code_id; + mp_raw_code_t *outer_raw_code = module_scope->raw_code; for (scope_t *s = module_scope; s;) { scope_t *next = s->next; scope_free(s); @@ -3471,12 +3471,11 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is } else { #if MICROPY_EMIT_CPYTHON // can't create code, so just return true - (void)unique_code_id; // to suppress warning that unique_code_id is unused + (void)outer_raw_code; // to suppress warning that outer_raw_code is unused return mp_const_true; #else // return function that executes the outer module - // we can free the unique_code slot because no-one has reference to this unique_code_id anymore - return mp_make_function_from_id_and_free(unique_code_id, MP_OBJ_NULL, MP_OBJ_NULL); + return mp_make_function_from_raw_code(outer_raw_code, MP_OBJ_NULL, MP_OBJ_NULL); #endif } } diff --git a/py/emitbc.c b/py/emitbc.c index d1d59ef4a5..2d71d86855 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -9,10 +9,11 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" -#include "emitglue.h" #include "bc0.h" struct _emit_t { @@ -65,6 +66,10 @@ STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_writ } } +STATIC void emit_align_code_info_to_machine_word(emit_t* emit) { + emit->code_info_offset = (emit->code_info_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1)); +} + STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) { byte* c = emit_get_cur_to_write_code_info(emit, 4); // TODO variable length encoding for qstr @@ -98,6 +103,10 @@ STATIC byte* emit_get_cur_to_write_byte_code(emit_t* emit, int num_bytes_to_writ } } +STATIC void emit_align_byte_code_to_machine_word(emit_t* emit) { + emit->byte_code_offset = (emit->byte_code_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1)); +} + STATIC void emit_write_byte_code_byte(emit_t* emit, byte b1) { byte* c = emit_get_cur_to_write_byte_code(emit, 1); c[0] = b1; @@ -158,6 +167,14 @@ STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) { emit_write_byte_code_uint(emit, num); } +// aligns the pointer so it is friendly to GC +STATIC void emit_write_byte_code_byte_ptr(emit_t* emit, byte b, void *ptr) { + emit_write_byte_code_byte(emit, b); + emit_align_byte_code_to_machine_word(emit); + machine_uint_t *c = (machine_uint_t*)emit_get_cur_to_write_byte_code(emit, sizeof(machine_uint_t)); + *c = (machine_uint_t)ptr; +} + /* currently unused STATIC void emit_write_byte_code_byte_uint_uint(emit_t* emit, byte b, uint num1, uint num2) { emit_write_byte_code_byte(emit, b); @@ -178,7 +195,7 @@ STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, uint } else { byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3; } - byte* c = emit_get_cur_to_write_byte_code(emit, 3); + byte *c = emit_get_cur_to_write_byte_code(emit, 3); c[0] = b1; c[1] = byte_code_offset; c[2] = byte_code_offset >> 8; @@ -269,19 +286,20 @@ STATIC void emit_bc_end_pass(emit_t *emit) { } emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info + emit_align_code_info_to_machine_word(emit); // align so that following byte_code is aligned if (emit->pass == PASS_2) { // calculate size of code in bytes emit->code_info_size = emit->code_info_offset; emit->byte_code_size = emit->byte_code_offset; - emit->code_base = m_new(byte, emit->code_info_size + emit->byte_code_size); + emit->code_base = m_new0(byte, emit->code_info_size + emit->byte_code_size); } else if (emit->pass == PASS_3) { qstr *arg_names = m_new(qstr, emit->scope->num_params); for (int i = 0; i < emit->scope->num_params; i++) { arg_names[i] = emit->scope->id_info[i].qstr; } - mp_emit_glue_assign_byte_code(emit->scope->unique_code_id, emit->code_base, + mp_emit_glue_assign_byte_code(emit->scope->raw_code, emit->code_base, emit->code_info_size + emit->byte_code_size, emit->scope->num_params, emit->scope->num_locals, emit->scope->scope_flags, arg_names); @@ -733,7 +751,7 @@ STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) { STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { emit_bc_pre(emit, 1); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION, scope->raw_code); } else { if (n_pos_defaults == 0) { // load dummy entry for non-existent positional default tuple @@ -744,14 +762,14 @@ STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defau emit_bc_load_null(emit); } emit_bc_pre(emit, -1); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code); } } STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { emit_bc_pre(emit, 0); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE, scope->raw_code); } else { if (n_pos_defaults == 0) { // load dummy entry for non-existent positional default tuple @@ -763,7 +781,7 @@ STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaul emit_bc_rot_two(emit); } emit_bc_pre(emit, -2); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code); } } diff --git a/py/emitcommon.c b/py/emitcommon.c index 30f5ace923..454ec9c5e5 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -7,8 +7,10 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" -#include "scope.h" #include "runtime0.h" +#include "obj.h" +#include "emitglue.h" +#include "scope.h" #include "emit.h" #define EMIT(fun, ...) (emit_method_table->fun(emit, __VA_ARGS__)) diff --git a/py/emitcpy.c b/py/emitcpy.c index 5866d474e9..010219d12f 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -9,6 +9,8 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" diff --git a/py/emitglue.c b/py/emitglue.c index bcc9b2cca1..ce296f4321 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -23,46 +23,11 @@ #define DEBUG_OP_printf(...) (void)0 #endif -typedef enum { - MP_CODE_UNUSED, - MP_CODE_RESERVED, - MP_CODE_BYTE, - MP_CODE_NATIVE, - MP_CODE_INLINE_ASM, -} mp_code_kind_t; - -typedef struct _mp_code_t { - mp_code_kind_t kind : 8; - uint scope_flags : 8; - uint n_args : 16; - union { - struct { - byte *code; - uint len; - } u_byte; - struct { - mp_fun_t fun; - } u_native; - struct { - void *fun; - } u_inline_asm; - }; - qstr *arg_names; -} mp_code_t; - -STATIC machine_uint_t unique_codes_alloc = 0; -STATIC machine_uint_t unique_codes_total = 0; // always >= unique_codes_alloc -STATIC mp_code_t *unique_codes = NULL; - #ifdef WRITE_CODE FILE *fp_write_code = NULL; #endif void mp_emit_glue_init(void) { - unique_codes_alloc = 0; - unique_codes_total = 0; - unique_codes = NULL; - #ifdef WRITE_CODE fp_write_code = fopen("out-code", "wb"); #endif @@ -74,50 +39,24 @@ void mp_emit_glue_deinit(void) { fclose(fp_write_code); } #endif - - m_del(mp_code_t, unique_codes, unique_codes_alloc); } -uint mp_emit_glue_get_unique_code_id(void) { - // look for an existing unused slot - for (uint i = 0; i < unique_codes_alloc; i++) { - if (unique_codes[i].kind == MP_CODE_UNUSED) { - unique_codes[i].kind = MP_CODE_RESERVED; - return i; - } - } - // no existing slot - // return next available id, memory will be allocated later - return unique_codes_total++; +mp_raw_code_t *mp_emit_glue_new_raw_code(void) { + mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1); + rc->kind = MP_CODE_RESERVED; + return rc; } -STATIC void mp_emit_glue_alloc_unique_codes(void) { - if (unique_codes_total > unique_codes_alloc) { - DEBUG_printf("allocate more unique codes: " UINT_FMT " -> %u\n", unique_codes_alloc, unique_codes_total); - // increase size of unique_codes table (all new entries are already reserved) - unique_codes = m_renew(mp_code_t, unique_codes, unique_codes_alloc, unique_codes_total); - for (uint i = unique_codes_alloc; i < unique_codes_total; i++) { - unique_codes[i].kind = MP_CODE_RESERVED; - } - unique_codes_alloc = unique_codes_total; - } -} - -void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) { - mp_emit_glue_alloc_unique_codes(); - - assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED); - unique_codes[unique_code_id].kind = MP_CODE_BYTE; - unique_codes[unique_code_id].scope_flags = scope_flags; - unique_codes[unique_code_id].n_args = n_args; - unique_codes[unique_code_id].u_byte.code = code; - unique_codes[unique_code_id].u_byte.len = len; - unique_codes[unique_code_id].arg_names = arg_names; - - //printf("byte code: %d bytes\n", len); +void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) { + rc->kind = MP_CODE_BYTE; + rc->scope_flags = scope_flags; + rc->n_args = n_args; + rc->u_byte.code = code; + rc->u_byte.len = len; + rc->arg_names = arg_names; #ifdef DEBUG_PRINT - DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d n_locals=%d\n", unique_code_id, code, len, n_args, n_locals); + DEBUG_printf("assign byte code: code=%p len=%u n_args=%d n_locals=%d\n", code, len, n_args, n_locals); for (int i = 0; i < 128 && i < len; i++) { if (i > 0 && i % 16 == 0) { DEBUG_printf("\n"); @@ -131,19 +70,14 @@ void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, in #endif } -void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, int n_args) { - mp_emit_glue_alloc_unique_codes(); - - assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED); - unique_codes[unique_code_id].kind = MP_CODE_NATIVE; - unique_codes[unique_code_id].scope_flags = 0; - unique_codes[unique_code_id].n_args = n_args; - unique_codes[unique_code_id].u_native.fun = fun; - - //printf("native code: %d bytes\n", len); +void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) { + rc->kind = MP_CODE_NATIVE; + rc->scope_flags = 0; + rc->n_args = n_args; + rc->u_native.fun = fun; #ifdef DEBUG_PRINT - DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args); + DEBUG_printf("assign native code: fun=%p len=%u n_args=%d\n", fun, len, n_args); byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code for (int i = 0; i < 128 && i < len; i++) { if (i > 0 && i % 16 == 0) { @@ -162,17 +96,14 @@ void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, i #endif } -void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint len, int n_args) { - mp_emit_glue_alloc_unique_codes(); - - assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED); - unique_codes[unique_code_id].kind = MP_CODE_INLINE_ASM; - unique_codes[unique_code_id].scope_flags = 0; - unique_codes[unique_code_id].n_args = n_args; - unique_codes[unique_code_id].u_inline_asm.fun = fun; +void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) { + rc->kind = MP_CODE_INLINE_ASM; + rc->scope_flags = 0; + rc->n_args = n_args; + rc->u_inline_asm.fun = fun; #ifdef DEBUG_PRINT - DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args); + DEBUG_printf("assign inline asm code: fun=%p len=%u n_args=%d\n", fun, len, n_args); byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code for (int i = 0; i < 128 && i < len; i++) { if (i > 0 && i % 16 == 0) { @@ -191,12 +122,9 @@ void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint le #endif } -mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) { - DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id); - if (unique_code_id >= unique_codes_total) { - // illegal code id - return mp_const_none; - } +mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) { + DEBUG_OP_printf("make_function_from_raw_code %p\n", rc); + assert(rc != NULL); // def_args must be MP_OBJ_NULL or a tuple assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple)); @@ -204,49 +132,36 @@ mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj // TODO implement default kw args assert(def_kw_args == MP_OBJ_NULL); - // make the function, depending on the code kind - mp_code_t *c = &unique_codes[unique_code_id]; + // make the function, depending on the raw code kind mp_obj_t fun; - switch (c->kind) { + switch (rc->kind) { case MP_CODE_BYTE: - fun = mp_obj_new_fun_bc(c->scope_flags, c->arg_names, c->n_args, def_args, c->u_byte.code); + fun = mp_obj_new_fun_bc(rc->scope_flags, rc->arg_names, rc->n_args, def_args, rc->u_byte.code); break; case MP_CODE_NATIVE: - fun = mp_make_function_n(c->n_args, c->u_native.fun); + fun = mp_make_function_n(rc->n_args, rc->u_native.fun); break; case MP_CODE_INLINE_ASM: - fun = mp_obj_new_fun_asm(c->n_args, c->u_inline_asm.fun); + fun = mp_obj_new_fun_asm(rc->n_args, rc->u_inline_asm.fun); break; default: - // code id was never assigned (this should not happen) + // raw code was never set (this should not happen) assert(0); return mp_const_none; } // check for generator functions and if so wrap in generator object - if ((c->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { + if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { fun = mp_obj_new_gen_wrap(fun); } return fun; } -mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) { - mp_obj_t f = mp_make_function_from_id(unique_code_id, def_args, def_kw_args); - - // in some cases we can free the unique_code slot - // any dynamically allocated memory is now owned by the fun object - mp_code_t *c = &unique_codes[unique_code_id]; - memset(c, 0, sizeof *c); // make sure all pointers are zeroed - c->kind = MP_CODE_UNUSED; - - return f; -} - -mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) { - DEBUG_OP_printf("make_closure_from_id %d\n", unique_code_id); +mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) { + DEBUG_OP_printf("make_closure_from_raw_code %p\n", rc); // make function object - mp_obj_t ffun = mp_make_function_from_id(unique_code_id, def_args, def_kw_args); + mp_obj_t ffun = mp_make_function_from_raw_code(rc, def_args, def_kw_args); // wrap function in closure object return mp_obj_new_closure(ffun, closure_tuple); } diff --git a/py/emitglue.h b/py/emitglue.h index 8f69951c21..2f9960bfa1 100644 --- a/py/emitglue.h +++ b/py/emitglue.h @@ -1,8 +1,40 @@ // These variables and functions glue the code emitters to the runtime. +typedef enum { + MP_CODE_UNUSED, + MP_CODE_RESERVED, + MP_CODE_BYTE, + MP_CODE_NATIVE, + MP_CODE_INLINE_ASM, +} mp_raw_code_kind_t; + +typedef struct _mp_code_t { + mp_raw_code_kind_t kind : 8; + uint scope_flags : 8; + uint n_args : 16; + union { + struct { + byte *code; + uint len; + } u_byte; + struct { + mp_fun_t fun; + } u_native; + struct { + void *fun; + } u_inline_asm; + }; + qstr *arg_names; +} mp_raw_code_t; + void mp_emit_glue_init(void); void mp_emit_glue_deinit(void); -uint mp_emit_glue_get_unique_code_id(void); -void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names); -void mp_emit_glue_assign_native_code(uint unique_code_id, void *f, uint len, int n_args); -void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *f, uint len, int n_args); + +mp_raw_code_t *mp_emit_glue_new_raw_code(void); + +void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names); +void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *f, uint len, int n_args); +void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *f, uint len, int n_args); + +mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args); +mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args); diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index fc881f3d18..812e702af6 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -9,10 +9,11 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" -#include "emitglue.h" #include "asmthumb.h" #if MICROPY_EMIT_INLINE_THUMB @@ -72,7 +73,7 @@ STATIC bool emit_inline_thumb_end_pass(emit_inline_asm_t *emit) { if (emit->pass == PASS_3) { void *f = asm_thumb_get_code(emit->as); - mp_emit_glue_assign_inline_asm_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); + mp_emit_glue_assign_inline_asm_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); } return emit->success; diff --git a/py/emitnative.c b/py/emitnative.c index b5a3acc231..3046aef4d6 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -27,11 +27,11 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" -#include "emitglue.h" -#include "obj.h" #include "runtime.h" #if 0 // print debugging info @@ -283,10 +283,10 @@ STATIC void emit_native_end_pass(emit_t *emit) { if (emit->pass == PASS_3) { #if N_X64 void *f = asm_x64_get_code(emit->as); - mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_x64_get_code_size(emit->as), emit->scope->num_params); + mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_x64_get_code_size(emit->as), emit->scope->num_params); #elif N_THUMB void *f = asm_thumb_get_code(emit->as); - mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); + mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); #endif } } @@ -1188,7 +1188,9 @@ STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_d // call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them assert(n_pos_defaults == 0 && n_kw_defaults == 0); emit_native_pre(emit); - emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_ID, mp_make_function_from_id, scope->unique_code_id, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); + assert(0); + // TODO we need to store the raw_code ptr aligned within the code for the GC + emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } diff --git a/py/emitpass1.c b/py/emitpass1.c index ad86588e20..01156bfbe6 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -7,6 +7,8 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" diff --git a/py/runtime.c b/py/runtime.c index 053367e3f7..51190f233c 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1143,7 +1143,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_obj_dict_store, mp_obj_new_set, mp_obj_set_store, - mp_make_function_from_id, + mp_make_function_from_raw_code, mp_call_function_n_kw_for_native, mp_call_method_n_kw, mp_getiter, diff --git a/py/runtime.h b/py/runtime.h index 867d633520..a3c6119838 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -29,12 +29,9 @@ mp_obj_t mp_load_const_dec(qstr qstr); mp_obj_t mp_load_const_str(qstr qstr); mp_obj_t mp_load_const_bytes(qstr qstr); -mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args); -mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args); mp_obj_t mp_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments mp_obj_t mp_make_function_var(int n_args_min, mp_fun_var_t fun); mp_obj_t mp_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive -mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args); mp_obj_t mp_call_function_0(mp_obj_t fun); mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg); diff --git a/py/runtime0.h b/py/runtime0.h index 6ee70aa01d..eef3706794 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -86,7 +86,7 @@ typedef enum { MP_F_STORE_MAP, MP_F_BUILD_SET, MP_F_STORE_SET, - MP_F_MAKE_FUNCTION_FROM_ID, + MP_F_MAKE_FUNCTION_FROM_RAW_CODE, MP_F_CALL_FUNCTION_N_KW_FOR_NATIVE, MP_F_CALL_METHOD_N_KW, MP_F_GETITER, diff --git a/py/scope.c b/py/scope.c index 51701727e6..391ad5da87 100644 --- a/py/scope.c +++ b/py/scope.c @@ -6,10 +6,12 @@ #include "misc.h" #include "mpconfig.h" #include "qstr.h" +#include "obj.h" #include "parse.h" +#include "emitglue.h" #include "scope.h" -scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options) { +scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options) { scope_t *scope = m_new0(scope_t, 1); scope->kind = kind; scope->pn = pn; @@ -41,7 +43,7 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint default: assert(0); } - scope->unique_code_id = unique_code_id; + scope->raw_code = mp_emit_glue_new_raw_code(); scope->emit_options = emit_options; scope->id_info_alloc = 8; scope->id_info = m_new(id_info_t, scope->id_info_alloc); diff --git a/py/scope.h b/py/scope.h index 07b41fe721..6e0990ea9c 100644 --- a/py/scope.h +++ b/py/scope.h @@ -29,7 +29,7 @@ typedef struct _scope_t { mp_parse_node_t pn; qstr source_file; qstr simple_name; - uint unique_code_id; + mp_raw_code_t *raw_code; uint8_t scope_flags; // see runtime0.h uint8_t emit_options; // see compile.h uint16_t num_params; @@ -41,7 +41,7 @@ typedef struct _scope_t { id_info_t *id_info; } scope_t; -scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options); +scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options); void scope_free(scope_t *scope); id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added); id_info_t *scope_find(scope_t *scope, qstr qstr); diff --git a/py/vm.c b/py/vm.c index f62cb2d7b1..be7cf01f00 100644 --- a/py/vm.c +++ b/py/vm.c @@ -7,6 +7,7 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "emitglue.h" #include "runtime.h" #include "bc0.h" #include "bc.h" @@ -29,20 +30,25 @@ typedef enum { UNWIND_JUMP, } mp_unwind_reason_t; -#define DECODE_UINT { \ +#define DECODE_UINT do { \ unum = 0; \ do { \ unum = (unum << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ -} +} while (0) #define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0) #define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0) -#define DECODE_QSTR { \ +#define DECODE_QSTR do { \ qst = 0; \ do { \ qst = (qst << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ -} +} while (0) +#define DECODE_PTR do { \ + ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \ + unum = *(machine_uint_t*)ip; \ + ip += sizeof(machine_uint_t); \ +} while (0) #define PUSH(val) *++sp = (val) #define POP() (*sp--) #define TOP() (*sp) @@ -704,29 +710,29 @@ unwind_jump: break; case MP_BC_MAKE_FUNCTION: - DECODE_UINT; - PUSH(mp_make_function_from_id(unum, MP_OBJ_NULL, MP_OBJ_NULL)); + DECODE_PTR; + PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL)); break; case MP_BC_MAKE_FUNCTION_DEFARGS: - DECODE_UINT; + DECODE_PTR; // Stack layout: def_tuple def_dict <- TOS obj1 = POP(); - SET_TOP(mp_make_function_from_id(unum, TOP(), obj1)); + SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), obj1)); break; case MP_BC_MAKE_CLOSURE: - DECODE_UINT; + DECODE_PTR; // Stack layout: closure_tuple <- TOS - SET_TOP(mp_make_closure_from_id(unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL)); + SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL)); break; case MP_BC_MAKE_CLOSURE_DEFARGS: - DECODE_UINT; + DECODE_PTR; // Stack layout: def_tuple def_dict closure_tuple <- TOS obj1 = POP(); obj2 = POP(); - SET_TOP(mp_make_closure_from_id(unum, obj1, TOP(), obj2)); + SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, obj1, TOP(), obj2)); break; case MP_BC_CALL_FUNCTION: