Skip to content

Commit 8dcc0c7

Browse files
committed
py: Calculate maximum exception stack size in compiler.
1 parent 945a01c commit 8dcc0c7

5 files changed

Lines changed: 77 additions & 44 deletions

File tree

py/compile.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,7 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
144144
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
145145
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1));
146146
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
147-
//pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT,
148-
// floor((mp_float_t)arg0 / arg1));
149-
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT,
150-
python_floor_divide(arg0, arg1));
151-
147+
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_floor_divide(arg0, arg1));
152148
} else {
153149
// shouldn't happen
154150
assert(0);
@@ -198,12 +194,24 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
198194
}
199195

200196
STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
201-
void compile_node(compiler_t *comp, mp_parse_node_t pn);
197+
STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);
202198

203199
STATIC int comp_next_label(compiler_t *comp) {
204200
return comp->next_label++;
205201
}
206202

203+
STATIC void compile_increase_except_level(compiler_t *comp) {
204+
comp->cur_except_level += 1;
205+
if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
206+
comp->scope_cur->exc_stack_size = comp->cur_except_level;
207+
}
208+
}
209+
210+
STATIC void compile_decrease_except_level(compiler_t *comp) {
211+
assert(comp->cur_except_level > 0);
212+
comp->cur_except_level -= 1;
213+
}
214+
207215
STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
208216
scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
209217
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,
16351643
int success_label = comp_next_label(comp);
16361644

16371645
EMIT_ARG(setup_except, l1);
1638-
comp->cur_except_level += 1;
1646+
compile_increase_except_level(comp);
16391647

16401648
compile_node(comp, pn_body); // body
16411649
EMIT(pop_block);
@@ -1687,7 +1695,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
16871695
if (qstr_exception_local != 0) {
16881696
l3 = comp_next_label(comp);
16891697
EMIT_ARG(setup_finally, l3);
1690-
comp->cur_except_level += 1;
1698+
compile_increase_except_level(comp);
16911699
}
16921700
compile_node(comp, pns_except->nodes[1]);
16931701
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,
17011709
EMIT_ARG(store_id, qstr_exception_local);
17021710
EMIT_ARG(delete_id, qstr_exception_local);
17031711

1704-
comp->cur_except_level -= 1;
1712+
compile_decrease_except_level(comp);
17051713
EMIT(end_finally);
17061714
}
17071715
EMIT_ARG(jump, l2);
17081716
EMIT_ARG(label_assign, end_finally_label);
17091717
}
17101718

1711-
comp->cur_except_level -= 1;
1719+
compile_decrease_except_level(comp);
17121720
EMIT(end_finally);
17131721

17141722
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
17231731
int l_finally_block = comp_next_label(comp);
17241732

17251733
EMIT_ARG(setup_finally, l_finally_block);
1726-
comp->cur_except_level += 1;
1734+
compile_increase_except_level(comp);
17271735

17281736
if (n_except == 0) {
17291737
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
17361744
EMIT_ARG(label_assign, l_finally_block);
17371745
compile_node(comp, pn_finally);
17381746

1739-
comp->cur_except_level -= 1;
1747+
compile_decrease_except_level(comp);
17401748
EMIT(end_finally);
17411749

17421750
EMIT_ARG(set_stack_size, stack_size);
@@ -2799,7 +2807,10 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
27992807
EMIT_ARG(start_pass, pass, scope);
28002808

28012809
if (comp->pass == PASS_1) {
2810+
// reset maximum stack sizes in scope
2811+
// they will be computed in this first pass
28022812
scope->stack_size = 0;
2813+
scope->exc_stack_size = 0;
28032814
}
28042815

28052816
#if MICROPY_EMIT_CPYTHON
@@ -2939,6 +2950,9 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
29392950
}
29402951

29412952
EMIT(end_pass);
2953+
2954+
// make sure we match all the exception levels
2955+
assert(comp->cur_except_level == 0);
29422956
}
29432957

29442958
void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {

py/emitbc.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,14 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
224224
emit_write_code_info_qstr(emit, scope->source_file);
225225
emit_write_code_info_qstr(emit, scope->simple_name);
226226

227-
// prelude for initialising closed over variables
227+
// bytecode prelude: exception stack size; 16 bit uint for now
228+
{
229+
byte* c = emit_get_cur_to_write_byte_code(emit, 2);
230+
c[0] = scope->exc_stack_size & 0xff;
231+
c[1] = (scope->exc_stack_size >> 8) & 0xff;
232+
}
233+
234+
// bytecode prelude: initialise closed over variables
228235
int num_cell = 0;
229236
for (int i = 0; i < scope->id_info_len; i++) {
230237
id_info_t *id = &scope->id_info[i];

py/objgenerator.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,22 @@ const mp_obj_type_t gen_instance_type = {
211211
};
212212

213213
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {
214-
// TODO: 4 is hardcoded number from vm.c, calc exc stack size instead.
215-
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));
214+
// get code info size, and skip the line number table
215+
machine_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24);
216+
bytecode += code_info_size;
217+
218+
// bytecode prelude: get exception stack size
219+
machine_uint_t n_exc_stack = bytecode[0] | (bytecode[1] << 8);
220+
bytecode += 2;
221+
222+
// bytecode prelude: initialise closed over variables
223+
// TODO
224+
// for now we just make sure there are no cells variables
225+
// need to work out how to implement closed over variables in generators
226+
assert(bytecode[0] == 0);
227+
bytecode += 1;
228+
229+
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));
216230
o->base.type = &gen_instance_type;
217231
o->code_info = bytecode;
218232
o->ip = bytecode;
@@ -225,16 +239,5 @@ mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args,
225239
o->state[n_state - 1 - i] = args[i];
226240
}
227241

228-
// TODO
229-
// prelude for making cells (closed over variables)
230-
// for now we just make sure there are no cells variables
231-
// need to work out how to implement closed over variables in generators
232-
233-
// get code info size
234-
machine_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24);
235-
o->ip += code_info_size;
236-
assert(o->ip[0] == 0);
237-
o->ip += 1;
238-
239242
return o;
240243
}

py/scope.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ typedef struct _scope_t {
3636
int num_dict_params;
3737
*/
3838
int num_locals;
39-
int stack_size;
39+
int stack_size; // maximum size of the locals stack
40+
int exc_stack_size; // maximum size of the exception stack
4041
uint unique_code_id;
4142
uint emit_options;
4243
} scope_t;

py/vm.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ typedef enum {
4545
#define SET_TOP(val) *sp = (val)
4646

4747
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) {
48+
const byte *ip = code;
49+
50+
// get code info size, and skip line number table
51+
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
52+
ip += code_info_size;
53+
54+
// bytecode prelude: exception stack size; 16 bit uint for now
55+
machine_uint_t n_exc_stack = ip[0] | (ip[1] << 8);
56+
ip += 2;
57+
4858
// allocate state for locals and stack
4959
mp_obj_t temp_state[10];
5060
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,
5363
}
5464
mp_obj_t *sp = &state[0] - 1;
5565

66+
// allocate state for exceptions
67+
mp_exc_stack exc_state[4];
68+
mp_exc_stack *exc_stack = &exc_state[0];
69+
if (n_exc_stack > 4) {
70+
exc_stack = m_new(mp_exc_stack, n_exc_stack);
71+
}
72+
mp_exc_stack *exc_sp = &exc_stack[0] - 1;
73+
5674
// init args
5775
for (uint i = 0; i < n_args; i++) {
5876
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,
6179
state[n_state - 1 - n_args - i] = args2[i];
6280
}
6381

64-
const byte *ip = code;
65-
66-
// get code info size
67-
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
68-
ip += code_info_size;
69-
70-
// execute prelude to make any cells (closed over variables)
71-
{
72-
for (uint n_local = *ip++; n_local > 0; n_local--) {
73-
uint local_num = *ip++;
74-
if (local_num < n_args + n_args2) {
75-
state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]);
76-
} else {
77-
state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL);
78-
}
82+
// bytecode prelude: initialise closed over variables
83+
for (uint n_local = *ip++; n_local > 0; n_local--) {
84+
uint local_num = *ip++;
85+
if (local_num < n_args + n_args2) {
86+
state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]);
87+
} else {
88+
state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL);
7989
}
8090
}
8191

82-
mp_exc_stack exc_stack[4];
83-
mp_exc_stack *exc_sp = &exc_stack[0] - 1;
8492
// execute the byte code
8593
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);
8694

0 commit comments

Comments
 (0)