kopia lustrzana https://github.com/micropython/micropython
py: Calculate maximum exception stack size in compiler.
rodzic
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)) {
|
} 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));
|
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)) {
|
} 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,
|
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_floor_divide(arg0, arg1));
|
||||||
// floor((mp_float_t)arg0 / arg1));
|
|
||||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT,
|
|
||||||
python_floor_divide(arg0, arg1));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
assert(0);
|
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);
|
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) {
|
STATIC int comp_next_label(compiler_t *comp) {
|
||||||
return comp->next_label++;
|
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) {
|
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_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
|
||||||
scope->parent = comp->scope_cur;
|
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);
|
int success_label = comp_next_label(comp);
|
||||||
|
|
||||||
EMIT_ARG(setup_except, l1);
|
EMIT_ARG(setup_except, l1);
|
||||||
comp->cur_except_level += 1;
|
compile_increase_except_level(comp);
|
||||||
|
|
||||||
compile_node(comp, pn_body); // body
|
compile_node(comp, pn_body); // body
|
||||||
EMIT(pop_block);
|
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) {
|
if (qstr_exception_local != 0) {
|
||||||
l3 = comp_next_label(comp);
|
l3 = comp_next_label(comp);
|
||||||
EMIT_ARG(setup_finally, l3);
|
EMIT_ARG(setup_finally, l3);
|
||||||
comp->cur_except_level += 1;
|
compile_increase_except_level(comp);
|
||||||
}
|
}
|
||||||
compile_node(comp, pns_except->nodes[1]);
|
compile_node(comp, pns_except->nodes[1]);
|
||||||
if (qstr_exception_local != 0) {
|
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(store_id, qstr_exception_local);
|
||||||
EMIT_ARG(delete_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(end_finally);
|
||||||
}
|
}
|
||||||
EMIT_ARG(jump, l2);
|
EMIT_ARG(jump, l2);
|
||||||
EMIT_ARG(label_assign, end_finally_label);
|
EMIT_ARG(label_assign, end_finally_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
comp->cur_except_level -= 1;
|
compile_decrease_except_level(comp);
|
||||||
EMIT(end_finally);
|
EMIT(end_finally);
|
||||||
|
|
||||||
EMIT_ARG(label_assign, success_label);
|
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);
|
int l_finally_block = comp_next_label(comp);
|
||||||
|
|
||||||
EMIT_ARG(setup_finally, l_finally_block);
|
EMIT_ARG(setup_finally, l_finally_block);
|
||||||
comp->cur_except_level += 1;
|
compile_increase_except_level(comp);
|
||||||
|
|
||||||
if (n_except == 0) {
|
if (n_except == 0) {
|
||||||
assert(MP_PARSE_NODE_IS_NULL(pn_else));
|
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);
|
EMIT_ARG(label_assign, l_finally_block);
|
||||||
compile_node(comp, pn_finally);
|
compile_node(comp, pn_finally);
|
||||||
|
|
||||||
comp->cur_except_level -= 1;
|
compile_decrease_except_level(comp);
|
||||||
EMIT(end_finally);
|
EMIT(end_finally);
|
||||||
|
|
||||||
EMIT_ARG(set_stack_size, stack_size);
|
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);
|
EMIT_ARG(start_pass, pass, scope);
|
||||||
|
|
||||||
if (comp->pass == PASS_1) {
|
if (comp->pass == PASS_1) {
|
||||||
|
// reset maximum stack sizes in scope
|
||||||
|
// they will be computed in this first pass
|
||||||
scope->stack_size = 0;
|
scope->stack_size = 0;
|
||||||
|
scope->exc_stack_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MICROPY_EMIT_CPYTHON
|
#if MICROPY_EMIT_CPYTHON
|
||||||
|
@ -2939,6 +2950,9 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT(end_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) {
|
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->source_file);
|
||||||
emit_write_code_info_qstr(emit, scope->simple_name);
|
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;
|
int num_cell = 0;
|
||||||
for (int i = 0; i < scope->id_info_len; i++) {
|
for (int i = 0; i < scope->id_info_len; i++) {
|
||||||
id_info_t *id = &scope->id_info[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) {
|
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.
|
// get code info size, and skip the line number table
|
||||||
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));
|
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->base.type = &gen_instance_type;
|
||||||
o->code_info = bytecode;
|
o->code_info = bytecode;
|
||||||
o->ip = 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];
|
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;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ typedef struct _scope_t {
|
||||||
int num_dict_params;
|
int num_dict_params;
|
||||||
*/
|
*/
|
||||||
int num_locals;
|
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 unique_code_id;
|
||||||
uint emit_options;
|
uint emit_options;
|
||||||
} scope_t;
|
} scope_t;
|
||||||
|
|
42
py/vm.c
42
py/vm.c
|
@ -45,6 +45,16 @@ typedef enum {
|
||||||
#define SET_TOP(val) *sp = (val)
|
#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) {
|
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
|
// allocate state for locals and stack
|
||||||
mp_obj_t temp_state[10];
|
mp_obj_t temp_state[10];
|
||||||
mp_obj_t *state = &temp_state[0];
|
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;
|
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
|
// init args
|
||||||
for (uint i = 0; i < n_args; i++) {
|
for (uint i = 0; i < n_args; i++) {
|
||||||
state[n_state - 1 - i] = 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];
|
state[n_state - 1 - n_args - i] = args2[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
const byte *ip = code;
|
// bytecode prelude: initialise closed over variables
|
||||||
|
for (uint n_local = *ip++; n_local > 0; n_local--) {
|
||||||
// get code info size
|
uint local_num = *ip++;
|
||||||
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
|
if (local_num < n_args + n_args2) {
|
||||||
ip += code_info_size;
|
state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]);
|
||||||
|
} else {
|
||||||
// execute prelude to make any cells (closed over variables)
|
state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL);
|
||||||
{
|
|
||||||
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
|
// 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);
|
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);
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue