diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/compile.c | 38 | ||||
-rw-r--r-- | py/emitbc.c | 9 | ||||
-rw-r--r-- | py/objgenerator.c | 29 | ||||
-rw-r--r-- | py/scope.h | 3 | ||||
-rw-r--r-- | py/vm.c | 42 |
5 files changed, 77 insertions, 44 deletions
diff --git a/py/compile.c b/py/compile.c index f18c228450..4d07f2e74b 100644 --- a/py/compile.c +++ b/py/compile.c @@ -144,11 +144,7 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) { } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1)); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) { - //pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, - // floor((mp_float_t)arg0 / arg1)); - pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, - python_floor_divide(arg0, arg1)); - + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_floor_divide(arg0, arg1)); } else { // shouldn't happen assert(0); @@ -198,12 +194,24 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) { } STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra); -void compile_node(compiler_t *comp, mp_parse_node_t pn); +STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn); STATIC int comp_next_label(compiler_t *comp) { return comp->next_label++; } +STATIC void compile_increase_except_level(compiler_t *comp) { + comp->cur_except_level += 1; + if (comp->cur_except_level > comp->scope_cur->exc_stack_size) { + comp->scope_cur->exc_stack_size = comp->cur_except_level; + } +} + +STATIC void compile_decrease_except_level(compiler_t *comp) { + assert(comp->cur_except_level > 0); + comp->cur_except_level -= 1; +} + 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, rt_get_unique_code_id(), emit_options); scope->parent = comp->scope_cur; @@ -1635,7 +1643,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, int success_label = comp_next_label(comp); EMIT_ARG(setup_except, l1); - comp->cur_except_level += 1; + compile_increase_except_level(comp); compile_node(comp, pn_body); // body EMIT(pop_block); @@ -1687,7 +1695,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, if (qstr_exception_local != 0) { l3 = comp_next_label(comp); EMIT_ARG(setup_finally, l3); - comp->cur_except_level += 1; + compile_increase_except_level(comp); } compile_node(comp, pns_except->nodes[1]); if (qstr_exception_local != 0) { @@ -1701,14 +1709,14 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, EMIT_ARG(store_id, qstr_exception_local); EMIT_ARG(delete_id, qstr_exception_local); - comp->cur_except_level -= 1; + compile_decrease_except_level(comp); EMIT(end_finally); } EMIT_ARG(jump, l2); EMIT_ARG(label_assign, end_finally_label); } - comp->cur_except_level -= 1; + compile_decrease_except_level(comp); EMIT(end_finally); EMIT_ARG(label_assign, success_label); @@ -1723,7 +1731,7 @@ void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except int l_finally_block = comp_next_label(comp); EMIT_ARG(setup_finally, l_finally_block); - comp->cur_except_level += 1; + compile_increase_except_level(comp); if (n_except == 0) { assert(MP_PARSE_NODE_IS_NULL(pn_else)); @@ -1736,7 +1744,7 @@ void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except EMIT_ARG(label_assign, l_finally_block); compile_node(comp, pn_finally); - comp->cur_except_level -= 1; + compile_decrease_except_level(comp); EMIT(end_finally); EMIT_ARG(set_stack_size, stack_size); @@ -2799,7 +2807,10 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { EMIT_ARG(start_pass, pass, scope); if (comp->pass == PASS_1) { + // reset maximum stack sizes in scope + // they will be computed in this first pass scope->stack_size = 0; + scope->exc_stack_size = 0; } #if MICROPY_EMIT_CPYTHON @@ -2939,6 +2950,9 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } EMIT(end_pass); + + // make sure we match all the exception levels + assert(comp->cur_except_level == 0); } void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) { diff --git a/py/emitbc.c b/py/emitbc.c index 653b144875..fcaa9b7fae 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -224,7 +224,14 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit_write_code_info_qstr(emit, scope->source_file); emit_write_code_info_qstr(emit, scope->simple_name); - // prelude for initialising closed over variables + // bytecode prelude: exception stack size; 16 bit uint for now + { + byte* c = emit_get_cur_to_write_byte_code(emit, 2); + c[0] = scope->exc_stack_size & 0xff; + c[1] = (scope->exc_stack_size >> 8) & 0xff; + } + + // bytecode prelude: initialise closed over variables int num_cell = 0; for (int i = 0; i < scope->id_info_len; i++) { id_info_t *id = &scope->id_info[i]; diff --git a/py/objgenerator.c b/py/objgenerator.c index 9f609ce509..29ef4e235f 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -211,8 +211,22 @@ const mp_obj_type_t gen_instance_type = { }; mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) { - // TODO: 4 is hardcoded number from vm.c, calc exc stack size instead. - mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, n_state * sizeof(mp_obj_t) + 4 * sizeof(mp_exc_stack)); + // get code info size, and skip the line number table + machine_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24); + bytecode += code_info_size; + + // bytecode prelude: get exception stack size + machine_uint_t n_exc_stack = bytecode[0] | (bytecode[1] << 8); + bytecode += 2; + + // bytecode prelude: initialise closed over variables + // TODO + // for now we just make sure there are no cells variables + // need to work out how to implement closed over variables in generators + assert(bytecode[0] == 0); + bytecode += 1; + + mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack)); o->base.type = &gen_instance_type; o->code_info = bytecode; o->ip = bytecode; @@ -225,16 +239,5 @@ mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, o->state[n_state - 1 - i] = args[i]; } - // TODO - // prelude for making cells (closed over variables) - // for now we just make sure there are no cells variables - // need to work out how to implement closed over variables in generators - - // get code info size - machine_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24); - o->ip += code_info_size; - assert(o->ip[0] == 0); - o->ip += 1; - return o; } diff --git a/py/scope.h b/py/scope.h index 660317f30b..7ecd1e19f9 100644 --- a/py/scope.h +++ b/py/scope.h @@ -36,7 +36,8 @@ typedef struct _scope_t { int num_dict_params; */ int num_locals; - int stack_size; + int stack_size; // maximum size of the locals stack + int exc_stack_size; // maximum size of the exception stack uint unique_code_id; uint emit_options; } scope_t; @@ -45,6 +45,16 @@ typedef enum { #define SET_TOP(val) *sp = (val) mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, uint n_state, mp_obj_t *ret) { + const byte *ip = code; + + // get code info size, and skip line number table + machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24); + ip += code_info_size; + + // bytecode prelude: exception stack size; 16 bit uint for now + machine_uint_t n_exc_stack = ip[0] | (ip[1] << 8); + ip += 2; + // allocate state for locals and stack mp_obj_t temp_state[10]; mp_obj_t *state = &temp_state[0]; @@ -53,6 +63,14 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, } mp_obj_t *sp = &state[0] - 1; + // allocate state for exceptions + mp_exc_stack exc_state[4]; + mp_exc_stack *exc_stack = &exc_state[0]; + if (n_exc_stack > 4) { + exc_stack = m_new(mp_exc_stack, n_exc_stack); + } + mp_exc_stack *exc_sp = &exc_stack[0] - 1; + // init args for (uint i = 0; i < n_args; i++) { state[n_state - 1 - i] = args[i]; @@ -61,26 +79,16 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, state[n_state - 1 - n_args - i] = args2[i]; } - const byte *ip = code; - - // get code info size - machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24); - ip += code_info_size; - - // execute prelude to make any cells (closed over variables) - { - for (uint n_local = *ip++; n_local > 0; n_local--) { - uint local_num = *ip++; - if (local_num < n_args + n_args2) { - state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]); - } else { - state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL); - } + // bytecode prelude: initialise closed over variables + for (uint n_local = *ip++; n_local > 0; n_local--) { + uint local_num = *ip++; + if (local_num < n_args + n_args2) { + state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]); + } else { + state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL); } } - mp_exc_stack exc_stack[4]; - mp_exc_stack *exc_sp = &exc_stack[0] - 1; // execute the byte code mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp, MP_OBJ_NULL); |