通过 JIT 运行源代码

本节将介绍当从命令行执行 Dart 时会发生什么:

// hello.dartmain() => print('Hello, World!');$ dart hello.dartHello, World!复制代码

「Dart 2 VM 开始不再具有从原始代码直接执行 Dart 的能力,相反 VM 希望获得包含序列化内核 AST 的内核二进制文件(也称为 dill 文件)」。将 Dart 源代码翻译成 Kernel AST 的任务是由通用前端 (CFE)处理的,CFE 是用 Dart 编写并在不同 Dart 工具上共享(例如 VM、dart2js、Dart Dev Compiler)。

Dart 代码的组件集合Dart VM3_flutter

为了保持直接从源代码执行 Dart ,这里托管一个名为 kernel service 的辅助 ​​isolate​​,它处理将 Dart 源代码编译到内核中,然后 VM 运行生成的内核二进制文件。

Dart 代码的组件集合Dart VM3_前端_02

然而这种设置并不是 CFE 和 VM 运行 Dart 代码的唯一方法,例如 「Flutter 是将编译到 Kernel 的过程和从 Kernel 执行的过程完全分离」,并将它们放在不同的设备上实现:编译发生在开发者机器(主机)上,执行在目标移动设备上处理,目标移动设备接收由 flutter 工具发送给它的内核二进制文件。

Dart 代码的组件集合Dart VM3_Dart_03

这里需要注意,该 Flutter 工具不处理 Dart 本身的解析, 相反它会生成另一个持久进程 ​​frontend_server​​,它本质上是围绕 CFE 和一些 Flutter 特定的 Kernel-to-Kernel 换的封装。

​frontend_server​​​ 将 Dart 源代码编译为内核文件, 然后 flutter 将其发送到设备, 当开发人员请求热重载时 ​​frontend_server​​​ 开始发挥作用:在这种情况下 ​​frontend_server​​ 可以重用先前编译中的 CFE 状态,并重新编译实际更改的库。

「一旦内核二进制文件加载到 VM 中,它就会被解析以创建代表各种程序实体的对象,然而这个过程是惰性完成的」:首先只加载关于库和类的基本信息,源自内核二进制文件的每个实体都保留一个指向二进制文件的指针,以便以后可以根据需要加载更多信息。

Dart 代码的组件集合Dart VM3_flutter_04

每当我们引用 VM 内部分配的对象时,我们都会使用 Untagged 前缀,因为这遵循了 VM 自己的命名约定:内部 VM 对象的布局由 C++ 类定义,名称以 Untagged头文件 ​​runtime/vm/raw_object.h​​​ 开头。例如 ​​dart::UntaggedClass​​​ 是描述一个 Dart 类 VM 对象, ​​dart::UntaggedField​​ 是一个 VM 对象

「只有在运行时需要它时(例如查找类成员、分配实例等),有关类的信息才会完全反序列化」,在这个阶段,类成员会从内核二进制文件中读取,然而在此阶段不会反序列化完整的函数体,只会反序列化它们的签名。

Dart 代码的组件集合Dart VM3_Dart_05

此时 methods 在运行时可以被成功解析和调用,因为已经从内核二进制文件加载了足够的信息,例如它可以解析和调用 ​​main​​ 库中的函数。

​package:kernel/ast.dart​​​ 定义了描述内核 AST 的类; ​​package:front_end​​​处理解析 Dart 源代码并从中构建内核 AST。​​dart::kernel::KernelLoader::LoadEntireProgram是​​​ 将内核 AST 反序列化为相应 VM 对象的入口点;​​pkg/vm/bin/kernel_service.dart​​​ 实现了内核服务隔离,​​runtime/vm/kernel_isolate.cc​​​ 将 Dart 实现粘合到 VM 的其余部分; ​​package:vm​​​ 承载大多数基于内核的 VM 特定功能,例如各种内核到内核的换;由于历史原因一些特定于 VM 的转换仍然存在于 ​​package:kernel​​ 中。

最初所有的函数都会有一个占位符,而不是它们的主体的实际可执行代码:它们指向 ​​LazyCompileStub​​​,它只是要求运行时系统为当前函数生成可执行代码,然后 ​​tail-calls​​ 这个新生成的代码。

Dart 代码的组件集合Dart VM3_二进制文件_06

第一次编译函数时,是通过未优化编译器完成的。

Dart 代码的组件集合Dart VM3_flutter_07