After analyzing execute_from_str, it seems that it is not allowed to create some helper threads and then exit the script, because the entire bytecode (or whatever you call the output of the compilation process) will be cleaned up by the garbage collector as there is no longer a reference to it. As long as the script is running, the reference is on the stack of thread calling execute_from_str in the 'module_fun' variable, but as soon as you exit the script mp_call_function_0 will return and you will leave the scope where module_fun exists, hence the memory allocated in mp_obj_new_fun_bc (see code below) will be up for freeing (?)
Or is this module_fun object added to the root pointers via some other mechanism ?
Code: Select all
mp_obj_t execute_from_str(const char *str) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(0/*MP_QSTR_*/, str, strlen(str), false);
mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT);
mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, false);
mp_call_function_0(module_fun);
nlr_pop();
return 0;
} else
...
}
mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {
...
return mp_make_function_from_raw_code(...)
}
mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) {
{
...
fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->data.u_byte.bytecode, rc->data.u_byte.const_table);
...
return fun;
}