summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/argcheck.c3
-rw-r--r--py/bc0.h1
-rw-r--r--py/binary.c16
-rw-r--r--py/builtinimport.c4
-rw-r--r--py/compile.c6
-rw-r--r--py/emit.h14
-rw-r--r--py/emitbc.c49
-rw-r--r--py/emitcpy.c55
-rw-r--r--py/emitglue.c15
-rw-r--r--py/emitglue.h2
-rw-r--r--py/emitnative.c22
-rw-r--r--py/emitpass1.c3
-rw-r--r--py/gc.c142
-rw-r--r--py/nlrx86.S4
-rw-r--r--py/obj.h2
-rw-r--r--py/objarray.c8
-rw-r--r--py/objcell.c15
-rw-r--r--py/objclosure.c29
-rw-r--r--py/objfun.c4
-rw-r--r--py/showbc.c5
-rw-r--r--py/vm.c27
-rw-r--r--py/vmentrytable.h1
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) {
diff --git a/py/bc0.h b/py/bc0.h
index 57c2d2ea64..37bd904147 100644
--- a/py/bc0.h
+++ b/py/bc0.h
@@ -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
diff --git a/py/emit.h b/py/emit.h
index 74cc5baa4a..5fca153163 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -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
};
diff --git a/py/gc.c b/py/gc.c
index d39307464b..9a5f9d89bf 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -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
diff --git a/py/obj.h b/py/obj.h
index 44d9bf6a6d..d62d376ab4 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -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);
diff --git a/py/vm.c b/py/vm.c
index c8e4ba9f48..b1c1719b72 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -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,