diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/argcheck.c | 3 | ||||
-rw-r--r-- | py/bc0.h | 1 | ||||
-rw-r--r-- | py/binary.c | 16 | ||||
-rw-r--r-- | py/builtinimport.c | 4 | ||||
-rw-r--r-- | py/compile.c | 6 | ||||
-rw-r--r-- | py/emit.h | 14 | ||||
-rw-r--r-- | py/emitbc.c | 49 | ||||
-rw-r--r-- | py/emitcpy.c | 55 | ||||
-rw-r--r-- | py/emitglue.c | 15 | ||||
-rw-r--r-- | py/emitglue.h | 2 | ||||
-rw-r--r-- | py/emitnative.c | 22 | ||||
-rw-r--r-- | py/emitpass1.c | 3 | ||||
-rw-r--r-- | py/gc.c | 142 | ||||
-rw-r--r-- | py/nlrx86.S | 4 | ||||
-rw-r--r-- | py/obj.h | 2 | ||||
-rw-r--r-- | py/objarray.c | 8 | ||||
-rw-r--r-- | py/objcell.c | 15 | ||||
-rw-r--r-- | py/objclosure.c | 29 | ||||
-rw-r--r-- | py/objfun.c | 4 | ||||
-rw-r--r-- | py/showbc.c | 5 | ||||
-rw-r--r-- | py/vm.c | 27 | ||||
-rw-r--r-- | py/vmentrytable.h | 1 |
22 files changed, 247 insertions, 180 deletions
diff --git a/py/argcheck.c b/py/argcheck.c index 5c5ea1bf80..aea71d0bd8 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -40,7 +40,7 @@ void mp_arg_parse_all(uint n_pos, const mp_obj_t *pos, mp_map_t *kws, uint n_all mp_obj_t given_arg; if (i < n_pos) { if (allowed[i].flags & MP_ARG_PARSE_KW_ONLY) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' argument must be given by a keyword", qstr_str(allowed[i].qstr))); + goto extra_positional; } pos_found++; given_arg = pos[i]; @@ -69,6 +69,7 @@ void mp_arg_parse_all(uint n_pos, const mp_obj_t *pos, mp_map_t *kws, uint n_all } if (pos_found < n_pos) { // TODO better error message + extra_positional: nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "extra positional arguments given")); } if (kws_found < kws->used) { @@ -51,7 +51,6 @@ #define MP_BC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess #define MP_BC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess #define MP_BC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess -#define MP_BC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned #define MP_BC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned #define MP_BC_WITH_CLEANUP (0x4e) #define MP_BC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned diff --git a/py/binary.c b/py/binary.c index ee95d56e44..e57766b41c 100644 --- a/py/binary.c +++ b/py/binary.c @@ -49,6 +49,8 @@ int mp_binary_get_size(char struct_type, char val_type, uint *palign) { case 'q': case 'Q': // TODO: This is for x86 align = sizeof(int); size = sizeof(long long); break; + case 'P': case 'O': + align = size = sizeof(void*); break; } } } @@ -131,7 +133,9 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) { } *ptr += size; - if (is_signed(val_type)) { + if (val_type == 'O') { + return (mp_obj_t)val; + } else if (is_signed(val_type)) { return mp_obj_new_int(val); } else { return mp_obj_new_int_from_uint(val); @@ -156,8 +160,16 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte ** #if MP_ENDIANNESS_BIG #error Not implemented #endif - machine_int_t val = mp_obj_int_get_checked(val_in); + machine_int_t val; byte *in = (byte*)&val; + switch (val_type) { + case 'O': + in = (byte*)&val_in; + break; + default: + val = mp_obj_get_int(val_in); + } + int in_delta, out_delta; uint val_sz = MIN(size, sizeof(val)); if (struct_type == '>') { diff --git a/py/builtinimport.c b/py/builtinimport.c index 262ee04a53..4a2f6510c3 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -3,6 +3,10 @@ #include <stdio.h> #include <string.h> #include <assert.h> +#ifdef __MINGW32__ +// For alloca() +#include <malloc.h> +#endif #include "nlr.h" #include "misc.h" diff --git a/py/compile.c b/py/compile.c index b0f1f9e00d..57f6f1546f 100644 --- a/py/compile.c +++ b/py/compile.c @@ -889,8 +889,7 @@ void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_d if (nfree == 0) { EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults); } else { - EMIT_ARG(build_tuple, nfree); - EMIT_ARG(make_closure, this_scope, n_pos_defaults, n_kw_defaults); + EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults); } } @@ -957,6 +956,8 @@ void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) { // we need to do this here before we start building the map for the default keywords if (comp->num_default_params > 0) { EMIT_ARG(build_tuple, comp->num_default_params); + } else { + EMIT(load_null); // sentinel indicating empty default positional args } // first default dict param, so make the map EMIT_ARG(build_map, 0); @@ -1009,6 +1010,7 @@ qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint // the default keywords args may have already made the tuple; if not, do it now if (comp->num_default_params > 0 && comp->num_dict_params == 0) { EMIT_ARG(build_tuple, comp->num_default_params); + EMIT(load_null); // sentinel indicating empty default keyword args } #endif @@ -41,10 +41,9 @@ typedef struct _emit_method_table_t { void (*load_const_dec)(emit_t *emit, qstr qstr); void (*load_const_id)(emit_t *emit, qstr qstr); void (*load_const_str)(emit_t *emit, qstr qstr, bool bytes); - void (*load_const_verbatim_str)(emit_t *emit, const char *str); // only needed for emitcpy + void (*load_null)(emit_t *emit); void (*load_fast)(emit_t *emit, qstr qstr, uint id_flags, int local_num); void (*load_deref)(emit_t *emit, qstr qstr, int local_num); - void (*load_closure)(emit_t *emit, qstr qstr, int local_num); // only needed for emitcpy void (*load_name)(emit_t *emit, qstr qstr); void (*load_global)(emit_t *emit, qstr qstr); void (*load_attr)(emit_t *emit, qstr qstr); @@ -73,7 +72,6 @@ typedef struct _emit_method_table_t { void (*pop_jump_if_false)(emit_t *emit, uint label); void (*jump_if_true_or_pop)(emit_t *emit, uint label); void (*jump_if_false_or_pop)(emit_t *emit, uint label); - void (*setup_loop)(emit_t *emit, uint label); void (*break_loop)(emit_t *emit, uint label, int except_depth); void (*continue_loop)(emit_t *emit, uint label, int except_depth); void (*setup_with)(emit_t *emit, uint label); @@ -100,13 +98,21 @@ typedef struct _emit_method_table_t { void (*unpack_sequence)(emit_t *emit, int n_args); void (*unpack_ex)(emit_t *emit, int n_left, int n_right); void (*make_function)(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults); - void (*make_closure)(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults); + void (*make_closure)(emit_t *emit, scope_t *scope, uint n_closed_over, uint n_pos_defaults, uint n_kw_defaults); void (*call_function)(emit_t *emit, int n_positional, int n_keyword, uint star_flags); void (*call_method)(emit_t *emit, int n_positional, int n_keyword, uint star_flags); void (*return_value)(emit_t *emit); void (*raise_varargs)(emit_t *emit, int n_args); void (*yield_value)(emit_t *emit); void (*yield_from)(emit_t *emit); + +#if MICROPY_EMIT_CPYTHON + // these methods are only needed for emitcpy + void (*load_const_verbatim_str)(emit_t *emit, const char *str); + void (*load_closure)(emit_t *emit, qstr qstr, int local_num); + void (*setup_loop)(emit_t *emit, uint label); +#endif + } emit_method_table_t; void emit_common_load_id(emit_t *emit, const emit_method_table_t *emit_method_table, scope_t *scope, qstr qstr); diff --git a/py/emitbc.c b/py/emitbc.c index d7b309a37f..f58cec1f1f 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -16,6 +16,8 @@ #include "emit.h" #include "bc0.h" +#if !MICROPY_EMIT_CPYTHON + struct _emit_t { pass_kind_t pass; int stack_size; @@ -421,11 +423,6 @@ STATIC void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) { } } -STATIC void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) { - // not needed/supported for BC - assert(0); -} - STATIC void emit_bc_load_null(emit_t *emit) { emit_bc_pre(emit, 1); emit_write_byte_code_byte(emit, MP_BC_LOAD_NULL); @@ -447,11 +444,6 @@ STATIC void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) { emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_DEREF, local_num); } -STATIC void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) { - // not needed/supported for BC - assert(0); -} - STATIC void emit_bc_load_name(emit_t *emit, qstr qstr) { emit_bc_pre(emit, 1); emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_NAME, qstr); @@ -598,11 +590,6 @@ STATIC void emit_bc_jump_if_false_or_pop(emit_t *emit, uint label) { emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label); } -STATIC void emit_bc_setup_loop(emit_t *emit, uint label) { - emit_bc_pre(emit, 0); - emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_LOOP, label); -} - STATIC void emit_bc_unwind_jump(emit_t *emit, uint label, int except_depth) { if (except_depth == 0) { emit_bc_jump(emit, label); @@ -761,35 +748,21 @@ STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defau emit_bc_pre(emit, 1); 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 - emit_bc_load_null(emit); - emit_bc_rot_two(emit); - } else if (n_kw_defaults == 0) { - // load dummy entry for non-existent keyword default dict - emit_bc_load_null(emit); - } emit_bc_pre(emit, -1); 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) { +STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_closed_over, uint n_pos_defaults, uint n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { - emit_bc_pre(emit, 0); + emit_bc_pre(emit, -n_closed_over + 1); emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE, scope->raw_code); + emit_write_byte_code_byte(emit, n_closed_over); } else { - if (n_pos_defaults == 0) { - // load dummy entry for non-existent positional default tuple - emit_bc_load_null(emit); - emit_bc_rot_three(emit); - } else if (n_kw_defaults == 0) { - // load dummy entry for non-existent keyword default dict - emit_bc_load_null(emit); - emit_bc_rot_two(emit); - } - emit_bc_pre(emit, -2); + assert(n_closed_over <= 255); + emit_bc_pre(emit, -2 - n_closed_over + 1); emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code); + emit_write_byte_code_byte(emit, n_closed_over); } } @@ -869,10 +842,9 @@ const emit_method_table_t emit_bc_method_table = { emit_bc_load_const_dec, emit_bc_load_const_id, emit_bc_load_const_str, - emit_bc_load_const_verbatim_str, + emit_bc_load_null, emit_bc_load_fast, emit_bc_load_deref, - emit_bc_load_closure, emit_bc_load_name, emit_bc_load_global, emit_bc_load_attr, @@ -901,7 +873,6 @@ const emit_method_table_t emit_bc_method_table = { emit_bc_pop_jump_if_false, emit_bc_jump_if_true_or_pop, emit_bc_jump_if_false_or_pop, - emit_bc_setup_loop, emit_bc_unwind_jump, emit_bc_unwind_jump, emit_bc_setup_with, @@ -936,3 +907,5 @@ const emit_method_table_t emit_bc_method_table = { emit_bc_yield_value, emit_bc_yield_from, }; + +#endif // !MICROPY_EMIT_CPYTHON diff --git a/py/emitcpy.c b/py/emitcpy.c index 119cf818cf..a041c4f1e0 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -221,11 +221,9 @@ STATIC void emit_cpy_load_const_str(emit_t *emit, qstr qstr, bool bytes) { } } -STATIC void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) { - emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { - printf("LOAD_CONST %s\n", str); - } +STATIC void emit_cpy_load_null(emit_t *emit) { + // unused for cpy + assert(0); } STATIC void emit_cpy_load_fast(emit_t *emit, qstr qstr, uint id_flags, int local_num) { @@ -242,13 +240,6 @@ STATIC void emit_cpy_load_deref(emit_t *emit, qstr qstr, int local_num) { } } -STATIC void emit_cpy_load_closure(emit_t *emit, qstr qstr, int local_num) { - emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { - printf("LOAD_CLOSURE %d %s\n", local_num, qstr_str(qstr)); - } -} - STATIC void emit_cpy_load_name(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); if (emit->pass == PASS_3) { @@ -447,13 +438,6 @@ STATIC void emit_cpy_jump_if_false_or_pop(emit_t *emit, uint label) { } } -STATIC void emit_cpy_setup_loop(emit_t *emit, uint label) { - emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { - printf("SETUP_LOOP %d\n", emit->label_offsets[label]); - } -} - STATIC void emit_cpy_break_loop(emit_t *emit, uint label, int except_depth) { emit_pre(emit, 0, 1); if (emit->pass == PASS_3) { @@ -764,7 +748,8 @@ STATIC void emit_cpy_make_function(emit_t *emit, scope_t *scope, uint n_pos_defa } } -STATIC void emit_cpy_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) { +STATIC void emit_cpy_make_closure(emit_t *emit, scope_t *scope, uint n_closed_over, uint n_pos_defaults, uint n_kw_defaults) { + emit_cpy_build_tuple(emit, n_closed_over); load_cpy_const_code_and_name(emit, scope->simple_name); emit_pre(emit, -2 - n_pos_defaults - 2 * n_kw_defaults, 3); if (emit->pass == PASS_3) { @@ -792,6 +777,27 @@ STATIC void emit_cpy_yield_from(emit_t *emit) { } } +STATIC void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) { + emit_pre(emit, 1, 3); + if (emit->pass == PASS_3) { + printf("LOAD_CONST %s\n", str); + } +} + +STATIC void emit_cpy_load_closure(emit_t *emit, qstr qstr, int local_num) { + emit_pre(emit, 1, 3); + if (emit->pass == PASS_3) { + printf("LOAD_CLOSURE %d %s\n", local_num, qstr_str(qstr)); + } +} + +STATIC void emit_cpy_setup_loop(emit_t *emit, uint label) { + emit_pre(emit, 0, 3); + if (emit->pass == PASS_3) { + printf("SETUP_LOOP %d\n", emit->label_offsets[label]); + } +} + const emit_method_table_t emit_cpython_method_table = { emit_cpy_set_native_types, emit_cpy_start_pass, @@ -814,10 +820,9 @@ const emit_method_table_t emit_cpython_method_table = { emit_cpy_load_const_dec, emit_cpy_load_const_id, emit_cpy_load_const_str, - emit_cpy_load_const_verbatim_str, + emit_cpy_load_null, emit_cpy_load_fast, emit_cpy_load_deref, - emit_cpy_load_closure, emit_cpy_load_name, emit_cpy_load_global, emit_cpy_load_attr, @@ -846,7 +851,6 @@ const emit_method_table_t emit_cpython_method_table = { emit_cpy_pop_jump_if_false, emit_cpy_jump_if_true_or_pop, emit_cpy_jump_if_false_or_pop, - emit_cpy_setup_loop, emit_cpy_break_loop, emit_cpy_continue_loop, emit_cpy_setup_with, @@ -880,6 +884,11 @@ const emit_method_table_t emit_cpython_method_table = { emit_cpy_raise_varargs, emit_cpy_yield_value, emit_cpy_yield_from, + + // emitcpy specific functions + emit_cpy_load_const_verbatim_str, + emit_cpy_load_closure, + emit_cpy_setup_loop, }; #endif // MICROPY_EMIT_CPYTHON diff --git a/py/emitglue.c b/py/emitglue.c index ce296f4321..8b1fd97021 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -158,10 +158,17 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp return fun; } -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); +mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, uint n_closed_over, const mp_obj_t *args) { + DEBUG_OP_printf("make_closure_from_raw_code %p %u %p\n", rc, n_closed_over, argrs); // make function object - mp_obj_t ffun = mp_make_function_from_raw_code(rc, def_args, def_kw_args); + mp_obj_t ffun; + if (n_closed_over & 0x100) { + // default positional and keyword args given + ffun = mp_make_function_from_raw_code(rc, args[0], args[1]); + } else { + // default positional and keyword args not given + ffun = mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL); + } // wrap function in closure object - return mp_obj_new_closure(ffun, closure_tuple); + return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2)); } diff --git a/py/emitglue.h b/py/emitglue.h index 2f9960bfa1..9aea2e4d45 100644 --- a/py/emitglue.h +++ b/py/emitglue.h @@ -37,4 +37,4 @@ void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *f, uint len, int n 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); +mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, uint n_closed_over, const mp_obj_t *args); diff --git a/py/emitnative.c b/py/emitnative.c index d86456244a..79d6da67c1 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -695,9 +695,9 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qstr, bool bytes) { } } -STATIC void emit_native_load_const_verbatim_str(emit_t *emit, const char *str) { - // not supported/needed for viper - assert(0); +STATIC void emit_native_load_null(emit_t *emit) { + emit_native_pre(emit); + emit_post_push_imm(emit, VTYPE_PYOBJ, 0); } STATIC void emit_native_load_fast(emit_t *emit, qstr qstr, uint id_flags, int local_num) { @@ -735,11 +735,6 @@ STATIC void emit_native_load_deref(emit_t *emit, qstr qstr, int local_num) { assert(0); } -STATIC void emit_native_load_closure(emit_t *emit, qstr qstr, int local_num) { - // not implemented - assert(0); -} - STATIC void emit_native_load_name(emit_t *emit, qstr qstr) { emit_native_pre(emit); emit_call_with_imm_arg(emit, MP_F_LOAD_NAME, mp_load_name, qstr, REG_ARG_1); @@ -985,11 +980,6 @@ STATIC void emit_native_jump_if_false_or_pop(emit_t *emit, uint label) { assert(0); } -STATIC void emit_native_setup_loop(emit_t *emit, uint label) { - emit_native_pre(emit); - emit_post(emit); -} - STATIC void emit_native_break_loop(emit_t *emit, uint label, int except_depth) { emit_native_jump(emit, label); // TODO properly } @@ -1209,7 +1199,7 @@ STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_d emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) { +STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, uint n_closed_over, uint n_pos_defaults, uint n_kw_defaults) { assert(0); } @@ -1334,10 +1324,9 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_load_const_dec, emit_native_load_const_id, emit_native_load_const_str, - emit_native_load_const_verbatim_str, + emit_native_load_null, emit_native_load_fast, emit_native_load_deref, - emit_native_load_closure, emit_native_load_name, emit_native_load_global, emit_native_load_attr, @@ -1366,7 +1355,6 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_pop_jump_if_false, emit_native_jump_if_true_or_pop, emit_native_jump_if_false_or_pop, - emit_native_setup_loop, emit_native_break_loop, emit_native_continue_loop, emit_native_setup_with, diff --git a/py/emitpass1.c b/py/emitpass1.c index ca34f220eb..64b58c4757 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -189,6 +189,9 @@ const emit_method_table_t emit_pass1_method_table = { (void*)emit_pass1_dummy, (void*)emit_pass1_dummy, (void*)emit_pass1_dummy, +#if MICROPY_EMIT_CPYTHON + (void*)emit_pass1_dummy, (void*)emit_pass1_dummy, (void*)emit_pass1_dummy, +#endif }; @@ -1,3 +1,4 @@ +#include <assert.h> #include <stdio.h> #include <string.h> #include <stdbool.h> @@ -434,8 +435,14 @@ void *gc_realloc(void *ptr, machine_uint_t n_bytes) { if (n_bytes <= n_existing) { return ptr; } else { - // TODO check if we can grow inplace - void *ptr2 = gc_alloc(n_bytes); + // TODO false is incorrect! Should get value from current block! + void *ptr2 = gc_alloc(n_bytes, +#if MICROPY_ENABLE_FINALISER + FTB_GET(BLOCK_FROM_PTR((machine_uint_t)ptr)) +#else + false +#endif + ); if (ptr2 == NULL) { return ptr2; } @@ -444,86 +451,101 @@ void *gc_realloc(void *ptr, machine_uint_t n_bytes) { return ptr2; } } -#endif + +#else // Alternative gc_realloc impl void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) { if (gc_lock_depth > 0) { return NULL; } - void *ptr_out = NULL; - machine_uint_t block = 0; - machine_uint_t ptr = (machine_uint_t)ptr_in; - + // check for pure allocation if (ptr_in == NULL) { return gc_alloc(n_bytes, false); } - if (VERIFY_PTR(ptr) // verify pointer - && (block = BLOCK_FROM_PTR(ptr)) // get first block - && ATB_GET_KIND(block) == AT_HEAD) { // make sure it's a HEAD block - - byte block_type; - machine_uint_t n_free = 0; - machine_uint_t n_blocks = 1; // counting HEAD block - machine_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB; - - // get the number of consecutive tail blocks and - // the number of free blocks after last tail block - // stop if we reach (or are at) end of heap - while ((block + n_blocks + n_free) < max_block - // stop as soon as we find enough blocks for n_bytes - && (n_bytes > ((n_blocks+n_free) * BYTES_PER_BLOCK)) - // stop if block is HEAD - && (block_type = ATB_GET_KIND(block + n_blocks + n_free)) != AT_HEAD) { - switch (block_type) { - case AT_FREE: n_free++; break; - case AT_TAIL: n_blocks++; break; - default: break; - } + machine_uint_t ptr = (machine_uint_t)ptr_in; + + // sanity check the ptr + if (!VERIFY_PTR(ptr)) { + return NULL; + } + + // get first block + machine_uint_t block = BLOCK_FROM_PTR(ptr); + + // sanity check the ptr is pointing to the head of a block + if (ATB_GET_KIND(block) != AT_HEAD) { + return NULL; + } + + // compute number of new blocks that are requested + machine_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; + + // get the number of consecutive tail blocks and + // the number of free blocks after last tail block + // stop if we reach (or are at) end of heap + machine_uint_t n_free = 0; + machine_uint_t n_blocks = 1; // counting HEAD block + machine_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB; + while (block + n_blocks + n_free < max_block) { + if (n_blocks + n_free >= new_blocks) { + // stop as soon as we find enough blocks for n_bytes + break; } - // number of allocated bytes - machine_uint_t n_existing = n_blocks * BYTES_PER_BLOCK; - - // check if realloc'ing to a smaller size - if (n_bytes <= n_existing) { - ptr_out = ptr_in; - // free unneeded tail blocks - for (machine_uint_t bl = block + n_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) { - ATB_ANY_TO_FREE(bl); - } + byte block_type = ATB_GET_KIND(block + n_blocks + n_free); + switch (block_type) { + case AT_FREE: n_free++; continue; + case AT_TAIL: n_blocks++; continue; + case AT_MARK: assert(0); + } + break; + } - // check if we can expand in place - } else if (n_bytes <= (n_existing + (n_free * BYTES_PER_BLOCK))) { - // number of blocks needed to expand +1 if there's a remainder - machine_uint_t n_diff = ( n_bytes - n_existing)/BYTES_PER_BLOCK+ - ((n_bytes - n_existing)%BYTES_PER_BLOCK!=0); + // return original ptr if it already has the requested number of blocks + if (new_blocks == n_blocks) { + return ptr_in; + } - DEBUG_printf("gc_realloc: expanding " UINT_FMT " blocks (" UINT_FMT " bytes) to " UINT_FMT " blocks (" UINT_FMT " bytes)\n", - n_existing/BYTES_PER_BLOCK, n_existing, n_existing/BYTES_PER_BLOCK+n_diff, n_existing + n_diff*BYTES_PER_BLOCK); + // check if we can shrink the allocated area + if (new_blocks < n_blocks) { + // free unneeded tail blocks + for (machine_uint_t bl = block + new_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) { + ATB_ANY_TO_FREE(bl); + } + return ptr_in; + } - // mark rest of blocks as used tail - for (machine_uint_t bl = block + n_blocks; bl < (block + n_blocks + n_diff); bl++) { - ATB_FREE_TO_TAIL(bl); - } - ptr_out = ptr_in; + // check if we can expand in place + if (new_blocks <= n_blocks + n_free) { + // mark few more blocks as used tail + for (machine_uint_t bl = block + n_blocks; bl < block + new_blocks; bl++) { + assert(ATB_GET_KIND(bl) == AT_FREE); + ATB_FREE_TO_TAIL(bl); + } + return ptr_in; + } - // try to find a new contiguous chain - } else if ((ptr_out = gc_alloc(n_bytes, + // can't resize inplace; try to find a new contiguous chain + void *ptr_out = gc_alloc(n_bytes, #if MICROPY_ENABLE_FINALISER - FTB_GET(block) + FTB_GET(block) #else - false + false #endif - )) != NULL) { - DEBUG_printf("gc_realloc: allocating new block\n"); - memcpy(ptr_out, ptr_in, n_existing); - gc_free(ptr_in); - } + ); + + // check that the alloc succeeded + if (ptr_out == NULL) { + return NULL; } + DEBUG_printf("gc_realloc: allocating new block\n"); + memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK); + gc_free(ptr_in); return ptr_out; } +#endif // Alternative gc_realloc impl void gc_dump_info() { gc_info_t info; diff --git a/py/nlrx86.S b/py/nlrx86.S index 003de5095f..145bdb9da0 100644 --- a/py/nlrx86.S +++ b/py/nlrx86.S @@ -61,7 +61,11 @@ nlr_jump: #endif mov nlr_top, %edx # load nlr_top test %edx, %edx # check for nlr_top being NULL +#ifdef _WIN32 + je _nlr_jump_fail # fail if nlr_top is NULL +#else je nlr_jump_fail # fail if nlr_top is NULL +#endif mov 4(%esp), %eax # load return value mov %eax, 4(%edx) # store return value mov (%edx), %eax # load prev nlr_top @@ -357,7 +357,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char mp_obj_t mp_obj_new_fun_bc(uint scope_flags, qstr *args, uint n_args, mp_obj_t def_args, const byte *code); mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun); mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun); -mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple); +mp_obj_t mp_obj_new_closure(mp_obj_t fun, uint n_closed, const mp_obj_t *closed); mp_obj_t mp_obj_new_tuple(uint n, const mp_obj_t *items); mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items); mp_obj_t mp_obj_new_dict(int n_args); diff --git a/py/objarray.c b/py/objarray.c index b7a84ba4cf..ce107ddf25 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -136,10 +136,18 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value if (value == MP_OBJ_NULL) { // delete item // TODO implement + // TODO: confirmed that both bytearray and array.array support + // slice deletion return MP_OBJ_NOT_SUPPORTED; } else { mp_obj_array_t *o = self_in; if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { + if (value != MP_OBJ_SENTINEL) { + // Only getting a slice is suported so far, not assignment + // TODO: confirmed that both bytearray and array.array support + // slice assignment (incl. of different size) + return MP_OBJ_NOT_SUPPORTED; + } machine_uint_t start, stop; if (!m_seq_get_fast_slice_indexes(o->len, index_in, &start, &stop)) { assert(0); diff --git a/py/objcell.c b/py/objcell.c index d8517587df..7fdf07b046 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -20,9 +20,24 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { self->obj = obj; } +#if 0 +STATIC void cell_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { + mp_obj_cell_t *o = o_in; + print(env, "<cell "); + if (o->obj == MP_OBJ_NULL) { + print(env, "(nil)"); + } else { + //print(env, "%p", o->obj); + mp_obj_print_helper(print, env, o->obj, PRINT_REPR); + } + print(env, ">"); +} +#endif + const mp_obj_type_t cell_type = { { &mp_type_type }, .name = MP_QSTR_, // should never need to print cell type + //.print = cell_print, }; mp_obj_t mp_obj_new_cell(mp_obj_t obj) { diff --git a/py/objclosure.c b/py/objclosure.c index 9b4a3f8933..09371b0348 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -5,13 +5,14 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "objtuple.h" #include "runtime.h" typedef struct _mp_obj_closure_t { mp_obj_base_t base; mp_obj_t fun; - uint n_closed; - mp_obj_t *closed; + machine_uint_t n_closed; + mp_obj_t closed[]; } mp_obj_closure_t; mp_obj_t closure_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { @@ -37,16 +38,34 @@ mp_obj_t closure_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t * } } +#if 0 +STATIC void closure_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { + mp_obj_closure_t *o = o_in; + print(env, "<closure %p, n_closed=%u ", o, o->n_closed); + for (int i = 0; i < o->n_closed; i++) { + if (o->closed[i] == MP_OBJ_NULL) { + print(env, "(nil)"); + } else { + mp_obj_print_helper(print, env, o->closed[i], PRINT_REPR); + } + print(env, " "); + } + print(env, ">"); +} +#endif + const mp_obj_type_t closure_type = { { &mp_type_type }, .name = MP_QSTR_closure, + //.print = closure_print, .call = closure_call, }; -mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple) { - mp_obj_closure_t *o = m_new_obj(mp_obj_closure_t); +mp_obj_t mp_obj_new_closure(mp_obj_t fun, uint n_closed_over, const mp_obj_t *closed) { + mp_obj_closure_t *o = m_new_obj_var(mp_obj_closure_t, mp_obj_t, n_closed_over); o->base.type = &closure_type; o->fun = fun; - mp_obj_tuple_get(closure_tuple, &o->n_closed, &o->closed); + o->n_closed = n_closed_over; + memcpy(o->closed, closed, n_closed_over * sizeof(mp_obj_t)); return o; } diff --git a/py/objfun.c b/py/objfun.c index c7144f3078..940b64a66e 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -2,6 +2,10 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#ifdef __MINGW32__ +// For alloca() +#include <malloc.h> +#endif #include "nlr.h" #include "misc.h" diff --git a/py/showbc.c b/py/showbc.c index bf25966e97..4a8e12e68b 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -287,11 +287,6 @@ void mp_byte_code_print(const byte *ip, int len) { printf("JUMP_IF_FALSE_OR_POP " UINT_FMT, ip + unum - ip_start); break; - case MP_BC_SETUP_LOOP: - DECODE_ULABEL; // loop labels are always forward - printf("SETUP_LOOP " UINT_FMT, ip + unum - ip_start); - break; - case MP_BC_SETUP_WITH: DECODE_ULABEL; // loop-like labels are always forward printf("SETUP_WITH " UINT_FMT, ip + unum - ip_start); @@ -481,13 +481,6 @@ dispatch_loop: } DISPATCH(); - /* we are trying to get away without using this opcode - ENTRY(MP_BC_SETUP_LOOP): - DECODE_UINT; - // push_block(MP_BC_SETUP_LOOP, ip + unum, sp) - DISPATCH(); - */ - ENTRY(MP_BC_SETUP_WITH): obj1 = TOP(); SET_TOP(mp_load_attr(obj1, MP_QSTR___exit__)); @@ -759,19 +752,23 @@ unwind_jump: SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), obj1)); DISPATCH(); - ENTRY(MP_BC_MAKE_CLOSURE): + ENTRY(MP_BC_MAKE_CLOSURE): { DECODE_PTR; - // Stack layout: closure_tuple <- TOS - SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL)); + machine_uint_t n_closed_over = *ip++; + // Stack layout: closed_overs <- TOS + sp -= n_closed_over - 1; + SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, n_closed_over, sp)); DISPATCH(); + } - ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): + ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): { DECODE_PTR; - // Stack layout: def_tuple def_dict closure_tuple <- TOS - obj1 = POP(); - obj2 = POP(); - SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, obj1, TOP(), obj2)); + machine_uint_t n_closed_over = *ip++; + // Stack layout: def_tuple def_dict closed_overs <- TOS + sp -= 2 + n_closed_over - 1; + SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, 0x100 | n_closed_over, sp)); DISPATCH(); + } ENTRY(MP_BC_CALL_FUNCTION): DECODE_UINT; diff --git a/py/vmentrytable.h b/py/vmentrytable.h index 2e1d1fb04f..c4d15427d7 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -45,7 +45,6 @@ static void* entry_table[256] = { [MP_BC_POP_JUMP_IF_FALSE] = &&entry_MP_BC_POP_JUMP_IF_FALSE, [MP_BC_JUMP_IF_TRUE_OR_POP] = &&entry_MP_BC_JUMP_IF_TRUE_OR_POP, [MP_BC_JUMP_IF_FALSE_OR_POP] = &&entry_MP_BC_JUMP_IF_FALSE_OR_POP, -// [MP_BC_SETUP_LOOP] = &&entry_MP_BC_SETUP_LOOP, [MP_BC_SETUP_WITH] = &&entry_MP_BC_SETUP_WITH, [MP_BC_WITH_CLEANUP] = &&entry_MP_BC_WITH_CLEANUP, [MP_BC_UNWIND_JUMP] = &&entry_MP_BC_UNWIND_JUMP, |