Initialization of the Julia runtime
Julia runtime, julia -e 'println("Hello World!")', executes the command as follows:
main()
Yürütme main() in cli/loader_exe.c ile başlar, bu da jl_load_repl() çağrısını cli/loader_lib.c içinde yapar, birkaç kütüphaneyi yükler ve nihayetinde jl_repl_entrypoint() in src/jlapi.c çağrısını yapar.
jl_repl_entrypoint() libsupport_init() C kütüphanesi yerel ayarını ayarlamak ve "ios" kütüphanesini başlatmak için çağrılır (bkz. ios_init_stdstreams() ve Legacy ios.c library).
Son jl_parse_opts() komut satırı seçeneklerini işlemek için çağrılır. jl_parse_opts() yalnızca kod üretimi veya erken başlatmayı etkileyen seçeneklerle ilgilenir. Diğer seçenekler daha sonra exec_options() in base/client.jl tarafından işlenir.
jl_parse_opts() komut satırı seçeneklerini global jl_options struct içinde saklar.
julia_init()
julia_init() in init.c main() tarafından çağrılır ve _julia_init() in init.c çağrılır.
_julia_init() önce libsupport_init() çağrısı yapar (ikinci kez hiçbir şey yapmaz).
restore_signals() sinyal işleyici maskesini sıfırlamak için çağrılır.
jl_resolve_sysimg_location() temel sistem görüntüsü için yapılandırılmış yolları arar. Building the Julia system image için.
jl_gc_init() zayıf referanslar, korunmuş değerler ve sonlandırma için tahsis havuzları ve listeleri kurar.
jl_init_frontend() bir tarayıcı/parsing içeren önceden derlenmiş bir femtolisp görüntüsünü yükler ve başlatır.
jl_init_types() jl_datatype_t türü tanım nesneleri oluşturur built-in types defined in julia.h. örneğin.
jl_any_type = jl_new_abstracttype(jl_symbol("Any"), core, NULL, jl_emptysvec);
jl_any_type->super = jl_any_type;
jl_type_type = jl_new_abstracttype(jl_symbol("Type"), core, jl_any_type, jl_emptysvec);
jl_int32_type = jl_new_primitivetype(jl_symbol("Int32"), core,
jl_any_type, jl_emptysvec, 32);jl_init_tasks() jl_datatype_t* jl_task_type nesnesini oluşturur; global jl_root_task yapısını başlatır; ve jl_current_task'ı kök göreve ayarlar.
jl_init_codegen() LLVM library olarak başlatır.
jl_init_serializer() 8-bit serileştirme etiketlerini yerleşik jl_value_t değerleri için başlatır.
Eğer bir sysimg dosyası yoksa (!jl_options.image_file), o zaman Core ve Main modülleri oluşturulur ve boot.jl değerlendirilir:
jl_core_module = jl_new_module(jl_symbol("Core")) Julia Core modülünü oluşturur.
jl_init_intrinsic_functions() yeni bir Julia modülü Intrinsics oluşturur ve jl_intrinsic_type sabitlerini içerir. Bu sabitler, her bir intrinsic function için bir tamsayı kodu tanımlar. emit_intrinsic() bu sembolleri kod üretimi sırasında LLVM talimatlarına çevirir.
jl_init_primitives() C fonksiyonlarını Julia fonksiyon sembollerine bağlar. Örneğin, Core.:(===)() sembolü, add_builtin_func("===", jl_f_is) çağrısı ile C fonksiyon işaretçisi jl_f_is()'e bağlanır.
jl_new_main_module() global "Main" modülünü oluşturur ve jl_current_task->current_module = jl_main_module olarak ayarlar.
Not: _julia_init() then sets jl_root_task->current_module = jl_core_module. jl_root_task bu noktada jl_current_task'ın bir takma adıdır, bu nedenle yukarıda jl_new_main_module() tarafından ayarlanan current_module üzerine yazılır.
jl_load("boot.jl", sizeof("boot.jl")) çağrılır jl_parse_eval_all bu da sürekli olarak çağrılır jl_toplevel_eval_flex() çalıştırmak için boot.jl. <!– TODO – eval içine in? –>
jl_get_builtin_hooks() Julia globals'ı boot.jl dosyasında tanımlanan global C işaretçilerini başlatır.
jl_init_box_caches() global kutulu tam sayılar için 1024'e kadar değerler için önceden tahsis eder. Bu, daha sonra kutulu int'lerin tahsisatını hızlandırır. örn.:
jl_value_t *jl_box_uint8(uint32_t x)
{
return boxed_uint8_cache[(uint8_t)x];
}_julia_init() iterates jl_core_module->bindings.table üzerinde jl_datatype_t değerlerini arar ve tür adının modül ön ekini jl_core_module olarak ayarlar.
jl_add_standard_imports(jl_main_module) "Ana Modül" içinde "Base" kullanıyor.
Not: _julia_init() artık yukarıda jl_core_module olarak ayarlandığı gibi değil, jl_root_task->current_module = jl_main_module olarak geri dönmektedir.
Platform spesifik sinyal işleyicileri SIGSEGV (OSX, Linux) ve SIGFPE (Windows) için başlatılır.
Diğer sinyaller (SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS ve SIGPIPE), sigdie_handler() ile bağlanmıştır ve bir geri izleme (backtrace) yazdırır.
jl_init_restored_module() her jl_module_run_initializer() her her deserialized modül için __init__() fonksiyonunu çalıştırmak üzere çağrılır.
Sonunda sigint_handler() SIGINT ile bağlandı ve jl_throw(jl_interrupt_exception) çağrısı yapıyor.
_julia_init() ardından back to main() in cli/loader_exe.c ve main() repl_entrypoint(argc, (char**)argv) çağrısını yapar.
repl_entrypoint()
repl_entrypoint() argv[]'in içeriklerini Base.ARGS'ya yükler.
Eğer bir .jl "program" dosyası komut satırında sağlandıysa, o zaman exec_program() jl_load(program,len) çağırır, bu da jl_parse_eval_all çağırır, bu da sürekli olarak jl_toplevel_eval_flex() çağırarak programı çalıştırır.
However, in our example (julia -e 'println("Hello World!")'), jl_get_global(jl_base_module, jl_symbol("_start")) looks up Base._start and jl_apply() executes it.
Base._start
Base._start Base.exec_options jl_parse_input_line("println("Hello World!")") Core.eval(Main, ex)
Core.eval
Core.eval(Main, ex) çağrıları jl_toplevel_eval_in(m, ex), bu da jl_toplevel_eval_flex çağrısını yapar. jl_toplevel_eval_flex, verilen bir kod thunk'unu derleyip derlemeyeceğine veya yorumlayıcı tarafından çalıştırıp çalıştırmayacağına karar vermek için basit bir sezgi uygular. println("Hello World!") verildiğinde, genellikle kodu yorumlayıcı tarafından çalıştırmaya karar verir; bu durumda jl_interpret_toplevel_thunk çağrısını yapar, bu da eval_body çağrısını yapar.
Aşağıdaki yığın dökümü, yorumlayıcının Base.println() ve Base.print() çeşitli yöntemleri aracılığıyla nasıl ilerlediğini göstermektedir ve write(s::IO, a::Array{T}) where T ile sonuçlanır ve ccall(jl_uv_write()) işlemini gerçekleştirir.
jl_uv_write() uv_write()'i JL_STDOUT'a "Hello World!" yazmak için çağrılır. Libuv wrappers for stdio.
Hello World!| Stack frame | Source code | Notes |
|---|---|---|
jl_uv_write() | jl_uv.c | called though ccall |
julia_write_282942 | stream.jl | function write!(s::IO, a::Array{T}) where T |
julia_print_284639 | ascii.jl | print(io::IO, s::String) = (write(io, s); nothing) |
jlcall_print_284639 | ||
jl_apply() | julia.h | |
jl_trampoline() | builtins.c | |
jl_apply() | julia.h | |
jl_apply_generic() | gf.c | Base.print(Base.TTY, String) |
jl_apply() | julia.h | |
jl_trampoline() | builtins.c | |
jl_apply() | julia.h | |
jl_apply_generic() | gf.c | Base.print(Base.TTY, String, Char, Char...) |
jl_apply() | julia.h | |
jl_f_apply() | builtins.c | |
jl_apply() | julia.h | |
jl_trampoline() | builtins.c | |
jl_apply() | julia.h | |
jl_apply_generic() | gf.c | Base.println(Base.TTY, String, String...) |
jl_apply() | julia.h | |
jl_trampoline() | builtins.c | |
jl_apply() | julia.h | |
jl_apply_generic() | gf.c | Base.println(String,) |
jl_apply() | julia.h | |
do_call() | interpreter.c | |
eval_body() | interpreter.c | |
jl_interpret_toplevel_thunk | interpreter.c | |
jl_toplevel_eval_flex | toplevel.c | |
jl_toplevel_eval_in | toplevel.c | |
Core.eval | boot.jl |
Örneğimizde sadece bir fonksiyon çağrısı olduğu için, "Hello World!" yazdırma işini yaptıktan sonra, yığın hızla main()'e geri sarılır.
jl_atexit_hook()
main() jl_atexit_hook() çağrısını yapar. Bu Base._atexit çağrısını yapar, ardından jl_gc_run_all_finalizers() çağrısını yapar ve libuv handle'larını temizler.
julia_save()
Sonunda, main() julia_save() çağrısını yapar; bu, komut satırında istendiğinde çalışma durumunu yeni bir sistem görüntüsüne kaydeder. jl_compile_all() ve jl_save_system_image()'e bakın.