环境对象

环境对象(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 的全局变量。