jl_module_t *jl_new_main_module(void) { if (jl_generating_output() && jl_options.incremental) jl_error("cannot call workspace() in incremental compile mode"); // switch to a new top-level module if (jl_current_module != jl_main_module && jl_current_module != NULL) jl_error("Main can only be replaced from the top level"); jl_module_t *old_main = jl_main_module; jl_main_module = jl_new_module(jl_symbol("Main")); jl_main_module->parent = jl_main_module; if (old_main) // don't block continued loading of incremental caches jl_main_module->uuid = old_main->uuid; jl_current_module = jl_main_module; jl_core_module->parent = jl_main_module; jl_set_const(jl_main_module, jl_symbol("Core"), (jl_value_t*)jl_core_module); jl_set_global(jl_core_module, jl_symbol("Main"), (jl_value_t*)jl_main_module); jl_current_task->current_module = jl_main_module; jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval")); return old_main; }
JL_DLLEXPORT jl_module_t *jl_new_main_module(void) { jl_ptls_t ptls = jl_get_ptls_states(); if (jl_generating_output() && jl_options.incremental) jl_error("cannot call workspace() in incremental compile mode"); // switch to a new top-level module if (ptls->current_module != jl_main_module && ptls->current_module != NULL && jl_main_module != NULL) jl_error("Main can only be replaced from the top level"); jl_module_t *old_main = jl_main_module; jl_main_module = jl_new_module(jl_symbol("Main")); jl_main_module->parent = jl_main_module; if (old_main) { // don't block continued loading of incremental caches jl_main_module->primary_world = old_main->primary_world; jl_main_module->build_id = old_main->build_id; jl_main_module->uuid = old_main->uuid; } ptls->current_module = jl_main_module; jl_core_module->parent = jl_main_module; jl_set_const(jl_main_module, jl_symbol("Core"), (jl_value_t*)jl_core_module); jl_set_global(jl_core_module, jl_symbol("Main"), (jl_value_t*)jl_main_module); ptls->current_task->current_module = jl_main_module; return old_main; }
void jl_write_compiler_output(void) { if (!jl_generating_output()) return; if (!jl_options.incremental) jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL); if (!jl_module_init_order) { jl_printf(JL_STDERR, "WARNING: --output requested, but no modules defined during run\n"); return; } jl_array_t *worklist = jl_module_init_order; JL_GC_PUSH1(&worklist); jl_module_init_order = jl_alloc_vec_any(0); int i, l = jl_array_len(worklist); for (i = 0; i < l; i++) { jl_value_t *m = jl_arrayref(worklist, i); if (jl_get_global((jl_module_t*)m, jl_symbol("__init__"))) { jl_array_ptr_1d_push(jl_module_init_order, m); } } if (jl_options.incremental) { if (jl_options.outputji) if (jl_save_incremental(jl_options.outputji, worklist)) jl_exit(1); if (jl_options.outputbc || jl_options.outputunoptbc) jl_printf(JL_STDERR, "WARNING: incremental output to a .bc file is not implemented\n"); if (jl_options.outputo) jl_printf(JL_STDERR, "WARNING: incremental output to a .o file is not implemented\n"); } else { ios_t *s = NULL; if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) s = jl_create_system_image(); if (jl_options.outputji) { if (s == NULL) { jl_save_system_image(jl_options.outputji); } else { ios_t f; if (ios_file(&f, jl_options.outputji, 1, 1, 1, 1) == NULL) jl_errorf("cannot open system image file \"%s\" for writing", jl_options.outputji); ios_write(&f, (const char*)s->buf, (size_t)s->size); ios_close(&f); } } if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) jl_dump_native(jl_options.outputbc, jl_options.outputunoptbc, jl_options.outputo, (const char*)s->buf, (size_t)s->size); } JL_GC_POP(); }
// load time init procedure: in build mode, only record order void jl_module_load_time_initialize(jl_module_t *m) { int build_mode = jl_generating_output(); if (build_mode) { if (jl_module_init_order == NULL) jl_module_init_order = jl_alloc_cell_1d(0); jl_cell_1d_push(jl_module_init_order, (jl_value_t*)m); jl_function_t *f = jl_module_get_initializer(m); if (f) jl_get_specialization(f, (jl_tupletype_t*)jl_typeof(jl_emptytuple)); } else { jl_module_run_initializer(m); } }
// load time init procedure: in build mode, only record order static void jl_module_load_time_initialize(jl_module_t *m) { int build_mode = jl_generating_output(); if (build_mode) { if (jl_module_init_order == NULL) jl_module_init_order = jl_alloc_vec_any(0); jl_array_ptr_1d_push(jl_module_init_order, (jl_value_t*)m); jl_function_t *f = jl_module_get_initializer(m); if (f != NULL) { jl_value_t *tt = jl_is_type(f) ? (jl_value_t*)jl_wrap_Type(f) : jl_typeof(f); JL_GC_PUSH1(&tt); tt = (jl_value_t*)jl_apply_tuple_type_v(&tt, 1); jl_compile_hint((jl_tupletype_t*)tt); JL_GC_POP(); } } else { jl_module_run_initializer(m); } }
jl_value_t *jl_eval_module_expr(jl_expr_t *ex) { static arraylist_t module_stack; static int initialized=0; static jl_module_t *outermost = NULL; if (!initialized) { arraylist_new(&module_stack, 0); initialized = 1; } assert(ex->head == module_sym); jl_module_t *last_module = jl_current_module; if (jl_array_len(ex->args) != 3 || !jl_is_expr(jl_exprarg(ex,2))) { jl_error("syntax: malformed module expression"); } int std_imports = (jl_exprarg(ex,0)==jl_true); jl_sym_t *name = (jl_sym_t*)jl_exprarg(ex, 1); if (!jl_is_symbol(name)) { jl_type_error("module", (jl_value_t*)jl_sym_type, (jl_value_t*)name); } jl_module_t *parent_module = jl_current_module; jl_binding_t *b = jl_get_binding_wr(parent_module, name); jl_declare_constant(b); if (b->value != NULL) { if (!jl_is_module(b->value)) { jl_errorf("invalid redefinition of constant %s", name->name); } if (jl_generating_output() && jl_options.incremental) { jl_errorf("cannot replace module %s during incremental compile", name->name); } if (!jl_generating_output()) { // suppress warning "replacing module Core.Inference" during bootstrapping jl_printf(JL_STDERR, "WARNING: replacing module %s\n", name->name); } } jl_module_t *newm = jl_new_module(name); newm->parent = parent_module; b->value = (jl_value_t*)newm; jl_gc_wb_binding(b, newm); if (parent_module == jl_main_module && name == jl_symbol("Base")) { // pick up Base module during bootstrap jl_old_base_module = jl_base_module; jl_base_module = newm; // reinitialize global variables // to pick up new types from Base jl_errorexception_type = NULL; jl_argumenterror_type = NULL; jl_methoderror_type = NULL; jl_loaderror_type = NULL; jl_current_task->tls = jl_nothing; // may contain an entry for :SOURCE_FILE that is not valid in the new base } // export all modules from Main if (parent_module == jl_main_module) jl_module_export(jl_main_module, name); // add standard imports unless baremodule if (std_imports) { if (jl_base_module != NULL) { jl_add_standard_imports(newm); } } JL_GC_PUSH1(&last_module); jl_module_t *task_last_m = jl_current_task->current_module; jl_current_task->current_module = jl_current_module = newm; jl_module_t *prev_outermost = outermost; size_t stackidx = module_stack.len; if (outermost == NULL) outermost = newm; jl_array_t *exprs = ((jl_expr_t*)jl_exprarg(ex, 2))->args; JL_TRY { for(int i=0; i < jl_array_len(exprs); i++) { // process toplevel form jl_value_t *form = jl_cellref(exprs, i); (void)jl_toplevel_eval_flex(form, 1); } } JL_CATCH { jl_current_module = last_module; jl_current_task->current_module = task_last_m; outermost = prev_outermost; module_stack.len = stackidx; jl_rethrow(); } JL_GC_POP(); jl_current_module = last_module; jl_current_task->current_module = task_last_m; outermost = prev_outermost; #if 0 // some optional post-processing steps size_t i; void **table = newm->bindings.table; for(i=1; i < newm->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; // remove non-exported macros if (b->name->name[0]=='@' && !b->exportp && b->owner==newm) b->value = NULL; // error for unassigned exports /* if (b->exportp && b->owner==newm && b->value==NULL) jl_errorf("identifier %s exported from %s is not initialized", b->name->name, newm->name->name); */ } } #endif arraylist_push(&module_stack, newm); if (outermost == NULL || jl_current_module == jl_main_module) { size_t i, l=module_stack.len; for(i = stackidx; i < l; i++) { jl_module_load_time_initialize((jl_module_t*)module_stack.items[i]); } assert(module_stack.len == l); module_stack.len = stackidx; } return (jl_value_t*)newm; }
jl_value_t *jl_eval_module_expr(jl_expr_t *ex) { jl_ptls_t ptls = jl_get_ptls_states(); static arraylist_t module_stack; static int initialized=0; static jl_module_t *outermost = NULL; if (!initialized) { arraylist_new(&module_stack, 0); initialized = 1; } assert(ex->head == module_sym); jl_module_t *last_module = ptls->current_module; if (jl_array_len(ex->args) != 3 || !jl_is_expr(jl_exprarg(ex,2))) { jl_error("syntax: malformed module expression"); } int std_imports = (jl_exprarg(ex,0)==jl_true); jl_sym_t *name = (jl_sym_t*)jl_exprarg(ex, 1); if (!jl_is_symbol(name)) { jl_type_error("module", (jl_value_t*)jl_sym_type, (jl_value_t*)name); } jl_module_t *parent_module = ptls->current_module; jl_binding_t *b = jl_get_binding_wr(parent_module, name); jl_declare_constant(b); if (b->value != NULL) { if (!jl_is_module(b->value)) { jl_errorf("invalid redefinition of constant %s", jl_symbol_name(name)); } if (jl_generating_output()) { jl_errorf("cannot replace module %s during compilation", jl_symbol_name(name)); } jl_printf(JL_STDERR, "WARNING: replacing module %s\n", jl_symbol_name(name)); } jl_module_t *newm = jl_new_module(name); newm->parent = parent_module; b->value = (jl_value_t*)newm; jl_gc_wb_binding(b, newm); if (parent_module == jl_main_module && name == jl_symbol("Base")) { // pick up Base module during bootstrap jl_base_module = newm; } // export all modules from Main if (parent_module == jl_main_module) jl_module_export(jl_main_module, name); // add standard imports unless baremodule if (std_imports) { if (jl_base_module != NULL) { jl_add_standard_imports(newm); } } jl_value_t *defaultdefs = NULL, *form = NULL; JL_GC_PUSH3(&last_module, &defaultdefs, &form); jl_module_t *task_last_m = ptls->current_task->current_module; ptls->current_task->current_module = ptls->current_module = newm; jl_module_t *prev_outermost = outermost; size_t stackidx = module_stack.len; if (outermost == NULL) outermost = newm; if (std_imports) { // add `eval` function defaultdefs = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex); jl_toplevel_eval_flex(defaultdefs, 0, 1); defaultdefs = NULL; } jl_array_t *exprs = ((jl_expr_t*)jl_exprarg(ex, 2))->args; JL_TRY { for(int i=0; i < jl_array_len(exprs); i++) { // process toplevel form form = jl_expand(jl_array_ptr_ref(exprs, i)); (void)jl_toplevel_eval_flex(form, 1, 1); } } JL_CATCH { ptls->current_module = last_module; ptls->current_task->current_module = task_last_m; outermost = prev_outermost; module_stack.len = stackidx; jl_rethrow(); } JL_GC_POP(); ptls->current_module = last_module; ptls->current_task->current_module = task_last_m; outermost = prev_outermost; #if 0 // some optional post-processing steps size_t i; void **table = newm->bindings.table; for(i=1; i < newm->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; // remove non-exported macros if (jl_symbol_name(b->name)[0]=='@' && !b->exportp && b->owner == newm) b->value = NULL; // error for unassigned exports /* if (b->exportp && b->owner==newm && b->value==NULL) jl_errorf("identifier %s exported from %s is not initialized", jl_symbol_name(b->name), jl_symbol_name(newm->name)); */ } } #endif arraylist_push(&module_stack, newm); if (outermost == NULL || ptls->current_module == jl_main_module) { JL_TRY { size_t i, l=module_stack.len; for(i = stackidx; i < l; i++) { jl_module_load_time_initialize((jl_module_t*)module_stack.items[i]); } assert(module_stack.len == l); module_stack.len = stackidx; } JL_CATCH { module_stack.len = stackidx; jl_rethrow(); } }
void jl_write_compiler_output(void) { if (!jl_generating_output()) { if (jl_options.outputjitbc) jl_dump_native(NULL, jl_options.outputjitbc, NULL, NULL, 0); return; } if (!jl_options.incremental) jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL); if (!jl_module_init_order) { jl_printf(JL_STDERR, "WARNING: --output requested, but no modules defined during run\n"); return; } if (jl_options.outputjitbc) { jl_printf(JL_STDERR, "WARNING: --output-jit-bc is meaningless with options for dumping sysimage data\n"); } jl_array_t *worklist = jl_module_init_order; JL_GC_PUSH1(&worklist); jl_module_init_order = jl_alloc_vec_any(0); int i, l = jl_array_len(worklist); for (i = 0; i < l; i++) { jl_value_t *m = jl_ptrarrayref(worklist, i); jl_value_t *f = jl_get_global((jl_module_t*)m, jl_symbol("__init__")); if (f) { jl_array_ptr_1d_push(jl_module_init_order, m); // TODO: this would be better handled if moved entirely to jl_precompile // since it's a slightly duplication of effort jl_value_t *tt = jl_is_type(f) ? (jl_value_t*)jl_wrap_Type(f) : jl_typeof(f); JL_GC_PUSH1(&tt); tt = (jl_value_t*)jl_apply_tuple_type_v(&tt, 1); jl_compile_hint((jl_tupletype_t*)tt); JL_GC_POP(); } } if (jl_options.incremental) { if (jl_options.outputji) if (jl_save_incremental(jl_options.outputji, worklist)) jl_exit(1); if (jl_options.outputbc || jl_options.outputunoptbc) jl_printf(JL_STDERR, "WARNING: incremental output to a .bc file is not implemented\n"); if (jl_options.outputo) jl_printf(JL_STDERR, "WARNING: incremental output to a .o file is not implemented\n"); } else { ios_t *s = NULL; if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) s = jl_create_system_image(); if (jl_options.outputji) { if (s == NULL) { jl_save_system_image(jl_options.outputji); } else { ios_t f; if (ios_file(&f, jl_options.outputji, 1, 1, 1, 1) == NULL) jl_errorf("cannot open system image file \"%s\" for writing", jl_options.outputji); ios_write(&f, (const char*)s->buf, (size_t)s->size); ios_close(&f); } } if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) { assert(s); jl_dump_native(jl_options.outputbc, jl_options.outputunoptbc, jl_options.outputo, (const char*)s->buf, (size_t)s->size); } } for (size_t i = 0; i < jl_current_modules.size; i += 2) { if (jl_current_modules.table[i + 1] != HT_NOTFOUND) { jl_printf(JL_STDERR, "\nWARNING: detected unclosed module: "); jl_static_show(JL_STDERR, (jl_value_t*)jl_current_modules.table[i]); jl_printf(JL_STDERR, "\n ** incremental compilation may be broken for this module **\n\n"); } } JL_GC_POP(); }
// TODO: add locks around global state mutation operations jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) { jl_ptls_t ptls = jl_get_ptls_states(); assert(ex->head == module_sym); if (jl_array_len(ex->args) != 3 || !jl_is_expr(jl_exprarg(ex, 2))) { jl_error("syntax: malformed module expression"); } int std_imports = (jl_exprarg(ex, 0) == jl_true); jl_sym_t *name = (jl_sym_t*)jl_exprarg(ex, 1); if (!jl_is_symbol(name)) { jl_type_error("module", (jl_value_t*)jl_sym_type, (jl_value_t*)name); } jl_module_t *newm = jl_new_module(name); jl_value_t *form = (jl_value_t*)newm; JL_GC_PUSH1(&form); ptrhash_put(&jl_current_modules, (void*)newm, (void*)((uintptr_t)HT_NOTFOUND + 1)); // copy parent environment info into submodule newm->uuid = parent_module->uuid; if (jl_base_module && (jl_value_t*)parent_module == jl_get_global(jl_base_module, jl_symbol("__toplevel__"))) { newm->parent = newm; jl_register_root_module(newm); } else { jl_binding_t *b = jl_get_binding_wr(parent_module, name, 1); jl_declare_constant(b); if (b->value != NULL) { if (!jl_is_module(b->value)) { jl_errorf("invalid redefinition of constant %s", jl_symbol_name(name)); } if (jl_generating_output()) { jl_errorf("cannot replace module %s during compilation", jl_symbol_name(name)); } jl_printf(JL_STDERR, "WARNING: replacing module %s.\n", jl_symbol_name(name)); // create a hidden gc root for the old module uintptr_t *refcnt = (uintptr_t*)ptrhash_bp(&jl_current_modules, (void*)b->value); *refcnt += 1; } newm->parent = parent_module; b->value = (jl_value_t*)newm; jl_gc_wb_binding(b, newm); } if (parent_module == jl_main_module && name == jl_symbol("Base")) { // pick up Base module during bootstrap jl_base_module = newm; } size_t last_age = ptls->world_age; // add standard imports unless baremodule if (std_imports) { if (jl_base_module != NULL) { jl_add_standard_imports(newm); } // add `eval` function form = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex, newm); ptls->world_age = jl_world_counter; jl_toplevel_eval_flex(newm, form, 0, 1); form = NULL; } jl_array_t *exprs = ((jl_expr_t*)jl_exprarg(ex, 2))->args; for (int i = 0; i < jl_array_len(exprs); i++) { // process toplevel form ptls->world_age = jl_world_counter; form = jl_expand_stmt(jl_array_ptr_ref(exprs, i), newm); ptls->world_age = jl_world_counter; (void)jl_toplevel_eval_flex(newm, form, 1, 1); } ptls->world_age = last_age; #if 0 // some optional post-processing steps size_t i; void **table = newm->bindings.table; for(i=1; i < newm->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; // remove non-exported macros if (jl_symbol_name(b->name)[0]=='@' && !b->exportp && b->owner == newm) b->value = NULL; // error for unassigned exports /* if (b->exportp && b->owner==newm && b->value==NULL) jl_errorf("identifier %s exported from %s is not initialized", jl_symbol_name(b->name), jl_symbol_name(newm->name)); */ } } #endif uintptr_t *refcnt = (uintptr_t*)ptrhash_bp(&jl_current_modules, (void*)newm); assert(*refcnt > (uintptr_t)HT_NOTFOUND); *refcnt -= 1; // newm should be reachable from somewhere else by now if (jl_module_init_order == NULL) jl_module_init_order = jl_alloc_vec_any(0); jl_array_ptr_1d_push(jl_module_init_order, (jl_value_t*)newm); // defer init of children until parent is done being defined // then initialize all in definition-finished order // at build time, don't run them at all (defer for runtime) if (!jl_generating_output()) { if (!ptrhash_has(&jl_current_modules, (void*)newm->parent)) { size_t i, l = jl_array_len(jl_module_init_order); size_t ns = 0; form = (jl_value_t*)jl_alloc_vec_any(0); for (i = 0; i < l; i++) { jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(jl_module_init_order, i); if (jl_is_submodule(m, newm)) { jl_array_ptr_1d_push((jl_array_t*)form, (jl_value_t*)m); } else if (ns++ != i) { jl_array_ptr_set(jl_module_init_order, ns - 1, (jl_value_t*)m); } } if (ns < l) jl_array_del_end(jl_module_init_order, l - ns); l = jl_array_len(form); for (i = 0; i < l; i++) { jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(form, i); JL_GC_PROMISE_ROOTED(m); jl_module_run_initializer(m); } } } JL_GC_POP(); return (jl_value_t*)newm; }