/
githubmirror
/
julia
Обзор
Документация
Войти
/
githubmirror
/
julia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/precompile.c
197 строк
8 KB
Sam Schweigel
Split images: write the heap image to the .ji (#61649)
06 авг 2026, 19:15
Не верифицирован
06 авг 2026, 19:15
ad84450
Код
Авторство
О чём код?
// This file is a part of Julia. License is MIT: https://julialang.org/license /* precompile.c Generating compiler output artifacts (object files, etc.) */ #include <stdlib.h> #include "julia.h" #include "julia_internal.h" #include "julia_assert.h" #include "serialize.h" #ifdef __cplusplus extern "C" { #endif JL_DLLEXPORT int jl_generating_output(void) { return jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc || jl_options.outputji || jl_options.outputasm; } static void write_srctext(ios_t *f, jl_array_t *udeps, int64_t srctextpos) JL_CANSAFEPOINT { // Write the source-text for the dependent files if (udeps) { // Go back and update the source-text position to point to the current position int64_t posfile = ios_pos(f); ios_seek(f, srctextpos); write_uint64(f, posfile); ios_seek_end(f); // Each source-text file is written as // int32: length of abspath // char*: abspath // uint64: length of src text // char*: src text // At the end we write int32(0) as a terminal sentinel. size_t len = jl_array_nrows(udeps); ios_t srctext; jl_value_t *replace_depot_func = NULL; jl_value_t *normalize_depots_func = NULL; jl_value_t *deptuple = NULL; jl_value_t *depots = NULL; jl_task_t *ct = jl_current_task; size_t last_age = ct->world_age; ct->world_age = jl_atomic_load_acquire(&jl_world_counter); JL_GC_PUSH4(&deptuple, &depots, &replace_depot_func, &normalize_depots_func); replace_depot_func = jl_eval_global_var(jl_base_module, jl_symbol("replace_depot_path"), jl_current_task->world_age); normalize_depots_func = jl_eval_global_var(jl_base_module, jl_symbol("normalize_depots_for_relocation"), jl_current_task->world_age); depots = jl_apply(&normalize_depots_func, 1); jl_datatype_t *deptuple_p[5] = {jl_module_type, jl_string_type, jl_uint64_type, jl_uint32_type, jl_float64_type}; jl_value_t *jl_deptuple_type = jl_apply_tuple_type_v((jl_value_t**)deptuple_p, 5); JL_GC_PROMISE_ROOTED(jl_deptuple_type); #define jl_is_deptuple(v) (jl_typeis((v), jl_deptuple_type)) for (size_t i = 0; i < len; i++) { deptuple = jl_array_ptr_ref(udeps, i); jl_value_t *depmod = jl_fieldref_noalloc(deptuple, 0); // module // Dependencies declared with `include_dependency` are excluded // because these may not be Julia code (and could be huge) JL_TYPECHK(write_srctext, deptuple, deptuple); if (depmod != (jl_value_t*)jl_main_module) { jl_value_t *abspath = jl_fieldref_noalloc(deptuple, 1); // file abspath const char *abspathstr = jl_string_data(abspath); if (!abspathstr[0]) continue; ios_t *srctp = ios_file(&srctext, abspathstr, 1, 0, 0, 0); if (!srctp) { jl_printf(JL_STDERR, "WARNING: could not cache source text for \"%s\".\n", abspathstr); continue; } jl_value_t *replace_depot_args[3]; replace_depot_args[0] = replace_depot_func; replace_depot_args[1] = abspath; replace_depot_args[2] = depots; jl_value_t *depalias = (jl_value_t*)jl_apply(replace_depot_args, 3); size_t slen = jl_string_len(depalias); write_int32(f, slen); ios_write(f, jl_string_data(depalias), slen); posfile = ios_pos(f); write_uint64(f, 0); // placeholder for length of this file in bytes uint64_t filelen = (uint64_t) ios_copyall(f, &srctext); ios_close(&srctext); ios_seek(f, posfile); write_uint64(f, filelen); ios_seek_end(f); } } ct->world_age = last_age; #undef jl_is_deptuple JL_GC_POP(); } write_int32(f, 0); // mark the end of the source text } JL_DLLEXPORT void jl_write_compiler_output(void) { if (!jl_generating_output()) { return; } jl_task_wait_empty(); // wait for most work to finish (except possibly finalizers) jl_gc_collect(JL_GC_FULL); jl_gc_collect(JL_GC_INCREMENTAL); // sweep finalizers jl_task_t *ct = jl_current_task; jl_gc_enable_finalizers(ct, 0); // now disable finalizers, as they could schedule more work or make other unexpected changes to reachability jl_task_wait_empty(); // then make sure we are the only thread alive that could be running user code past here jl_array_t *worklist = jl_module_init_order; if (!worklist) { jl_printf(JL_STDERR, "WARNING: --output requested, but no modules defined during run\n"); return; } jl_array_t *udeps = NULL; JL_GC_PUSH2(&worklist, &udeps); jl_module_init_order = jl_alloc_vec_any(0); int i, l = jl_array_nrows(worklist); for (i = 0; i < l; i++) { jl_value_t *m = jl_array_ptr_ref(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); } } void *native_code = NULL; bool_t emit_native = jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc || jl_options.outputasm; const char *outputji = jl_options.outputji; bool_t emit_split = outputji && emit_native; int comp = jl_options.compress_sysimage; ios_t *s = NULL; int64_t srctextpos = 0 ; uint32_t checksum = jl_create_system_image(emit_native ? &native_code : NULL, jl_options.incremental ? worklist : NULL, emit_split, comp, &s, &udeps, &srctextpos, jl_module_init_order); ios_t f; if (outputji) { if (ios_file(&f, outputji, 1, 1, 1, 1) == NULL) jl_errorf("cannot open system image file \"%s\" for writing", outputji); // It would be a waste to allocate a huge buffer only to write it all // immediately to the file. ios_bufmode(&f, bm_none); ios_write(&f, (const char *)s->buf, (size_t)s->size); ios_close(s); free(s); ios_bufmode(&f, bm_block); } if (native_code) { const char *unpack_func = emit_split ? (comp ? "jl_image_unpack_split_zstd" : "jl_image_unpack_split") : (comp ? "jl_image_unpack_zstd" : "jl_image_unpack_uncomp"); // jl_dump_native will close and free s when appropriate // this is a horrible abstraction, but // this helps reduce live memory significantly jl_dump_native(native_code, jl_options.outputbc, jl_options.outputunoptbc, jl_options.outputo, jl_options.outputasm, outputji ? NULL : s, checksum, unpack_func, NULL); jl_postoutput_hook(); } if (outputji) { if (jl_options.incremental) { write_srctext(&f, udeps, srctextpos); } ios_close(&f); } 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"); } } if (jl_options.trim) { exit(0); // Some finalizers need to run and we've blown up the bindings table // TODO: Is this still needed } JL_GC_POP(); jl_gc_enable_finalizers(ct, 1); } #ifdef __cplusplus } #endif