py: Calculate maximum exception stack size in compiler.

This commit is contained in:
Damien George 2014-03-27 10:55:21 +00:00
parent 945a01c4e3
commit 8dcc0c7924
5 changed files with 77 additions and 44 deletions

View File

@ -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) {

View File

@ -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];

View File

@ -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;
}

View File

@ -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
View File

@ -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);