Julia运行时的初始化
Julia运行时如何执行 julia-e’println("你好世界!")' ?
主要()
执行开始于https://github.com/JuliaLang/julia/blob/master/cli/loader_exe.c[脧锚脧赂`主要()` 在 cli/loader_exe。c],其中调用 jl_load_repl() 在https://github.com/JuliaLang/julia/blob/master/cli/loader_lib.c[脧锚脧赂`cli/loader_lib。c`]其中加载了几个库,最终调用https://github.com/JuliaLang/julia/blob/master/src/jlapi.c[脧锚脧赂`jl_repl_entrypoint()` 在 src/jlapi。c].
jl_repl_entrypoint() 电话https://github.com/JuliaLang/julia/blob/master/src/support/libsupportinit.c[脧锚脧赂`libsupport_init()]设置C库区域设置并初始化"ios"库(请参阅https://github.com/JuliaLang/julia/blob/master/src/support/ios.c[脧锚脧赂`ios_init_stdstreams()]和 遗产 的ios。c 库)。
下一个https://github.com/JuliaLang/julia/blob/master/src/jloptions.c[脧锚脧赂`jl_parse_opts()]被调用来处理命令行选项。 请注意 `jl_parse_opts() 仅处理影响代码生成或早期初始化的选项。 其他选项稍后由https://github.com/JuliaLang/julia/blob/master/base/client.jl[脧锚脧赂`执行_操作()` 在 基地/客户端。jl].
jl_parse_opts() 将命令行选项存储在https://github.com/JuliaLang/julia/blob/master/src/julia.h[全球 jl_选项 结构]。
朱莉亚*尼特()
脧锚脧赂`朱莉亚*尼特()` 在 初始化。c被称为 主要() 和电话https://github.com/JuliaLang/julia/blob/master/src/init.c[脧锚脧赂`_朱利亚_init()` 在 初始化。c].
_朱利亚_init() 从打电话开始 libsupport_init() 再次(第二次什么也不做)。
脧锚脧赂`restore_signals()`被调用以将信号处理程序掩码归零。
脧锚脧赂`jl_resolve_sysimg_location()`搜索基本系统映像的已配置路径。 见 构建Julia系统映像。
脧锚脧赂`jl_gc_init()`为弱引用、保留值和最终确定设置分配池和列表。
脧锚脧赂`jl_init_frontend()`加载并初始化包含扫描仪/解析器的预编译femtolisp图像。
脧锚脧赂`jl_init_types()创建 `jl_datatype_t 类型描述对象的https://github.com/JuliaLang/julia/blob/master/src/julia.h[内置类型定义于 朱莉娅。h]. 例如
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 对象;初始化全局 jl_root_task 结构;以及集合 jl_current_task 到根任务。
脧锚脧赂`jl_init_codegen()`初始化https://llvm.org[LLVM库]。
脧锚脧赂`jl_init_serializer()为内建初始化8位序列化标记 `jl_value_t 价值观。
如果没有sysimg文件(!jl_options。图像文件)然后 核心 和 主要 模块被创建和 靴子。jl 被评估:
jl_core_module=jl_new_module(jl_symbol("Core"),NULL) 创建朱莉娅 核心 模块。
脧锚脧赂`jl_init_intrinsic_functions()创建一个新的Julia模块 `内在函数 包含常量 jl_intrinsic_type 符号。 这些为每个定义一个整数代码https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp[内在功能]。 脧锚脧赂`emit_intrinsic()`在代码生成期间将这些符号转换为LLVM指令。
脧锚脧赂`jl_init_primitives()将C函数与Julia函数符号挂钩。 例如符号 `核心。:(===)() 绑定到c函数指针 jl_f_is() 通过调用 add_builtin_func("===",jl_f_is).
脧锚脧赂`jl_new_main_module()创建全局"主"模块并设置 `+jl_current_task→current_module=jl_main_module+.
注: _朱利亚_init() 然后设置 jl_root_task->current_module=jl_core_module. jl_root_task 是一个别名 jl_current_task 在这一点上,所以 当前_module 设置 jl_new_main_module() 以上被复盖。
脧锚脧赂`jl_load("引导。jl",sizeof("boot.jl"))电话https://github.com/JuliaLang/julia/blob/master/src/ast.c[脧锚脧赂`jl_parse_eval_all[重复调用https://github.com/JuliaLang/julia/blob/master/src/toplevel.c[脧锚脧赂`jl_toplevel_eval_flex()]执行https://github.com/JuliaLang/julia/blob/master/base/boot.jl[脧锚脧赂`靴子。jl]. <!--TODO-深入到eval? -→
脧锚脧赂`jl_get_builtin_hooks()初始化全局c指针到Julia全局变量 `靴子。jl.
脧锚脧赂`jl_init_box_caches()`为最多1024个值预分配全局盒装整数值对象。 这加快了以后盒装ints的分配。 例如:
jl_value_t *jl_box_uint8(uint32_t x)
{
return boxed_uint8_cache[(uint8_t)x];
}
脧锚脧赂`_朱利亚_init()` 迭代在 jl_core_module->绑定。表 寻找 jl_datatype_t 值并将类型名称的模块前缀设置为 jl_core_module的.
脧锚脧赂`jl_add_standard_imports(jl_main_module)`在"主"模块中"使用Base"。
注: _朱利亚_init() 现在恢复到 jl_root_task->current_module=jl_main_module 就像之前被设定的那样 jl_core_module的 以上。
平台特定的信号处理程序被初始化为 [医]乙状结肠 (OSX,Linux),以及 [医]SIGFPE (窗户)。
其他信号(SIGINFO,SIGBUS,SIGILL,SIGTERM,SIGABRT,SIGQUIT,SIGSYS 和 [医]乙状结肠)被连接到https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c[脧锚脧赂`sigdie_handler()`]它打印了一条后路。
脧锚脧赂`jl_init_restored_module()电话https://github.com/JuliaLang/julia/blob/master/src/module.c[脧锚脧赂`jl_module_run_initializer()]对于每个反序列化模块运行 __init__() 函数。
最后https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c[脧锚脧赂`sigint_handler()]被连接到 `西金特 和电话 jl_throw(jl_interrupt_exception).
_朱利亚_init() 然后返回https://github.com/JuliaLang/julia/blob/master/cli/loader_exe.c[返回 主要() 在 cli/loader_exe。c]和 主要() 电话 repl_entrypoint(argc,(char**)argv).
|
sysimg如果有一个sysimg文件,它包含一个预先煮熟的图像 脧锚脧赂`jl_restore_system_image() 注:https://github.com/JuliaLang/julia/blob/master/src/staticdata.c[脧锚脧赂`jl_restore_system_image()` (和 |
重放点()
脧锚脧赂`重放点()加载的内容 `argv[] 进入 基地。阿格斯.
如果一个 .jl 在命令行上提供了"程序"文件,然后https://github.com/JuliaLang/julia/blob/master/src/jlapi.c[脧锚脧赂`exec_program()]电话https://github.com/JuliaLang/julia/blob/master/src/toplevel.c[脧锚脧赂`jl_load(程序,len)]哪些调用https://github.com/JuliaLang/julia/blob/master/src/ast.c[脧锚脧赂`jl_parse_eval_all`[重复调用https://github.com/JuliaLang/julia/blob/master/src/toplevel.c[脧锚脧赂`jl_toplevel_eval_flex()`]来执行程序。
但是,在我们的例子中(julia-e’println("你好世界!")'),https://github.com/JuliaLang/julia/blob/master/src/module.c[脧锚脧赂`jl_get_global(jl_base_module,jl_symbol("_start"))]向上看https://github.com/JuliaLang/julia/blob/master/base/client.jl[脧锚脧赂`基地。_启动]和https://github.com/JuliaLang/julia/blob/master/src/julia.h[脧锚脧赂`jl_应用()`]执行它。
基地。_启动
脧锚脧赂`基地。_启动`电话https://github.com/JuliaLang/julia/blob/master/base/client.jl[脧锚脧赂`基地。执行_操作`]哪些调用https://github.com/JuliaLang/julia/blob/master/src/ast.c[脧锚脧赂`jl_parse_input_line("println("Hello World!")")]创建表达式对象和 `核心。eval(主要,ex)执行解析后的表达式 前 在模块上下文中 主要.
核心。埃瓦尔
核心。eval(主要,ex)电话https://github.com/JuliaLang/julia/blob/master/src/toplevel.c[脧锚脧赂`jl_toplevel_eval_in(m,ex)],其中调用https://github.com/JuliaLang/julia/blob/master/src/toplevel.c[脧锚脧赂`jl_toplevel_eval_flex]. jl_toplevel_eval_flex 实现一个简单的启发式来决定是编译给定的代码thunk还是由解释器运行它。 当给予 println("你好世界!"),它通常会决定通过解释器运行代码,在这种情况下,它会调用https://github.com/JuliaLang/julia/blob/master/src/interpreter.c[脧锚脧赂`jl_interpret_toplevel_thunk`],然后调用https://github.com/JuliaLang/julia/blob/master/src/interpreter.c[脧锚脧赂`eval_body`].
下面的堆栈转储显示了解释器如何通过 基地。打印()和 基地。印刷()抵达前https://github.com/JuliaLang/julia/blob/master/base/stream.jl[脧锚脧赂`写(s::IO,A::数组{T})其中T]哪个 `ccall(jl_uv_write()).
脧锚脧赂`jl_uv_write()电话 `uv_write() 要写"你好世界!"到 JL_STDOUT. 见 Libuv包装为stdio。:
Hello World!
| 堆栈帧 | 源代码 | 注意事项 |
|---|---|---|
|
|
虽然叫 |
|
|
功能 |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
由于我们的例子只有一个函数调用,它已经完成了打印"Hello World!",堆栈现在迅速解开回到 主要().
jl_atexit_hook()
主要() 电话https://github.com/JuliaLang/julia/blob/master/src/init.c[脧锚脧赂`jl_atexit_hook()]. 这就要求 `基地。_atexit,然后调用https://github.com/JuliaLang/julia/blob/master/src/gc.c[脧锚脧赂`jl_gc_run_all_finalizers()`]并清理libuv句柄。
julia_save()
最后, 主要() 电话https://github.com/JuliaLang/julia/blob/master/src/init.c[脧锚脧赂`julia_save()],如果在命令行上请求,则将运行时状态保存到新的系统映像。 见https://github.com/JuliaLang/julia/blob/master/src/gf.c[脧锚脧赂`jl_compile_all()]和https://github.com/JuliaLang/julia/blob/master/src/staticdata.c[脧锚脧赂`jl_save_system_image()`].