static void jl_compile_specializations(void) { // this "found" array will contain function // type signatures that were inferred but haven't been compiled jl_array_t *m = jl_alloc_vec_any(0); JL_GC_PUSH1(&m); jl_foreach_mtable_in_module(jl_main_module, precompile_enq_all_specializations_, m); size_t i, l; for (i = 0, l = jl_array_len(m); i < l; i++) { jl_compile_hint((jl_tupletype_t*)jl_array_ptr_ref(m, i)); } JL_GC_POP(); }
// 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); } }
// f{<:Union{...}}(...) is a common pattern // and expanding the Union may give a leaf function static void _compile_all_tvar_union(jl_value_t *methsig) { if (!jl_is_unionall(methsig) && jl_is_leaf_type(methsig)) { // usually can create a specialized version of the function, // if the signature is already a leaftype if (jl_compile_hint((jl_tupletype_t*)methsig)) return; } int tvarslen = jl_subtype_env_size(methsig); jl_value_t *sigbody = methsig; jl_value_t **env; JL_GC_PUSHARGS(env, 2 * tvarslen); int *idx = (int*)alloca(sizeof(int) * tvarslen); int i; for (i = 0; i < tvarslen; i++) { assert(jl_is_unionall(sigbody)); idx[i] = 0; env[2 * i] = (jl_value_t*)((jl_unionall_t*)sigbody)->var; env[2 * i + 1] = jl_bottom_type; // initialize the list with Union{}, since T<:Union{} is always a valid option sigbody = ((jl_unionall_t*)sigbody)->body; } for (i = 0; i < tvarslen; /* incremented by inner loop */) { jl_value_t *sig; JL_TRY { // TODO: wrap in UnionAll for each tvar in env[2*i + 1] ? // currently doesn't matter much, since jl_compile_hint doesn't work on abstract types sig = (jl_value_t*)jl_instantiate_type_with(sigbody, env, tvarslen); } JL_CATCH { goto getnext; // sigh, we found an invalid type signature. should we warn the user? } assert(jl_is_tuple_type(sig)); if (sig == jl_bottom_type || tupletype_any_bottom(sig)) goto getnext; // signature wouldn't be callable / is invalid -- skip it if (jl_is_leaf_type(sig)) { if (jl_compile_hint((jl_tupletype_t*)sig)) goto getnext; // success } getnext: for (i = 0; i < tvarslen; i++) { jl_tvar_t *tv = (jl_tvar_t*)env[2 * i]; if (jl_is_uniontype(tv->ub)) { size_t l = jl_count_union_components(tv->ub); size_t j = idx[i]; if (j == l) { env[2 * i + 1] = jl_bottom_type; idx[i] = 0; } else { jl_value_t *ty = jl_nth_union_component(tv->ub, j); if (!jl_is_leaf_type(ty)) ty = (jl_value_t*)jl_new_typevar(tv->name, tv->lb, ty); env[2 * i + 1] = ty; idx[i] = j + 1; break; } } else { env[2 * i + 1] = (jl_value_t*)tv; } } } JL_GC_POP(); }
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(); }