环境对象
环境对象(Env)用于维护对 Python 对象的引用,这些对象是支持对象模式和 nopython 模式编译函数所必需的。
在 nopython 模式下,Env 用于:
存储 pyobject,用于从原生值进行重建,例如:
用于打印 NumPy 数组的原生值;
用于将原生值返回或生成回解释器。
在对象模式下,Env 用于:
存储代码中引用的常量值。
存储对函数全局字典的引用,以加载全局值。
实现
Env 分两部分实现。在 _dynfunc.c
中,Env 被定义为 EnvironmentObject
,作为 Python C 扩展类型。在 lowering.py
中,EnvironmentObject`(导出为 _dynfunc.Environment
)被扩展以支持在 lowering 阶段所需的必要操作。
序列化
Env 支持被 pickle 化。编译缓存文件和提前编译的模块会序列化所有使用的 Env,以便在运行时重新创建。
用法
在函数或生成器 lowering 过程开始时,会创建一个 Env。在整个编译过程中,Env 会被修改以附加额外信息。编译后的代码通过发出的 LLVM IR 中的一个全局变量引用 Env。该全局变量以“common”链接类型进行零初始化,这是 C 全局值的默认链接类型。使用这种链接类型允许在模块链接时,将全局变量的多个定义合并为单个定义。全局变量的名称是根据函数的名称计算的(参见目标上下文的 FunctionDescriptor.env_name
和 .get_env_name()
)。
当编译函数被加载时,Env 会被初始化。JIT 引擎会找到与 Env 关联的全局变量的地址,并将 Env 的地址存储到其中。对于缓存的函数,也适用相同的过程。对于提前编译的函数,生成库中的模块初始化器负责初始化模块中所有 Env 的全局变量。