py: Calculate maximum exception stack size in compiler.
This commit is contained in:
parent
945a01c4e3
commit
8dcc0c7924
38
py/compile.c
38
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) {
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
42
py/vm.c
42
py/vm.c
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user