本文主要介绍本地执行 Dart 代码的组件集合Dart VM

PS:内容比较繁杂,请酌情观看

Dart VM 是用于本地执行 Dart 代码的组件集合,它主要包括以下内容:

  • 运行时系统
  • 对象模型
  • 垃圾收集
  • 快照
  • 核心库的 native 方法
  • 可以通过 service protocol 访问的组件:调试 * 分析 * 热重载
  • 即时 (JIT) 和提前 (AOT) 编译管道
  • Interpreter
  • ARM模拟器

Dart VM 从某种意义上说是一个虚拟机,它为高级编程语言提供了一个执行环境,「但这并不意味着 Dart 在 Dart VM 上执行时总是需要被解释或 JIT 编译的」

例如可以使用 Dart VM AOT 将 Dart 代码编译成机器代码,然后在 Dart VM 的裁剪版本中执行,这被称为预编译运行时,它不包含任何编译器组件,无法动态加载 Dart 源代码。

Dart VM 如何运行你的代码?

Dart VM 有多种执行代码的方式,例如:

  • 使用源代码或内核二进制文件的 JIT 模式;
  • 使用快照:
  • 来自 AOT 快照;
  • 来自 AppJIT 快照;

然而它们之间的主要区别在于: 「VM “何时”以及“如何”将 Dart 源代码转换为可执行代码」,然后保证执行的运行时环境保持不变。

Dart 代码的组件集合Dart VM_事件循环

VM 中的任何 Dart 代码都在某个 ​​isolate​​ 中运行,可以将其描述为:「具有自己的内存(堆)并且通常具有自己的控制线程(mutator 线程)的 Dart 隔离宇宙」

VM 可以有许多 ​​isolate​​ 同时执行 Dart 代码,但它们不能直接共享任何状态,只能通过端口传递消息进行通信(不要与网络端口混淆!)。

这里的 OS 线程和 ​​isolate​​ 之间的关系有点模糊,并且高度依赖于虚拟机嵌入到应用程序的方式,但是主要需要保证以下内容:

  • 一个 OS 线程一次只能进入一个 ​​isolate​​​ ,如果它想进入另一个 ​​isolate​​​,它必须离开当前 ​​isolate​​;
  • 一次只能有一个与 ​​isolate​​ 相关联的 Mutator 线程,Mutator 线程是执行 Dart 代码并使用 VM 的公共 C API 的线程。

然而同一个 OS 线程可以先进入一个 ​​isolate​​​ 执行 Dart 代码,然后离开这个 ​​isolate​​​ 并进入另一个 ​​isolate​​​ 继续执行;或者有许多不同的 OS 线程进入一个 ​​isolate​​ 并在其中执行 Dart 代码,只是不会同时发生。

当然,除了单个 Mutator 线程之外,​​isolate​​ 还可以关联多个辅助线程,例如:

  • 一个后台 JIT 编译器线程;
  • GC sweeper 现场;
  • 并发 GC marker 线程;

VM 在内部使用线程池 (​​dart::ThreadPool​​​) 来管理 OS 线程,并且代码是围绕 ​​dart::ThreadPool::Task​​ 概念而不是围绕 OS 线程的概念构建的。

例如在 GC VM 中将 ​​dart::ConcurrentSweeperTask​​ 发布到全局 VM 的线程池,而不是生成专用线程来执行后台清除,「并且线程池实现要么选择空闲线程,要么在没有可用线程时生成新线程」;类似地,「用于 ​​isolate​​ 来消息处理事件循环的默认实现实际上,并没有产生专用的事件循环线程,而是在新消息到达时将​​dart::MessageHandlerTask​​ 发布到线程池」

​dart::Isolate​​​ 类相当于一个 ​​isolate​​​ ,​​dart::Heap​​​ 类相当于 ​​isolate​​​ 的堆,​​dart::Thread​​​ 类描述了线程连接到 ​​isolate​​ 相关的状态。

请注意,该名称 ​​Thread​​​可能会让人有些困惑,因为所有 OS 线程都附加到与 Mutator 相同的 ​​isolate​​​,将重用相同的 Thread 实例。有关 ​​isolate​​​ 消息处理的默认实现,请参阅 ​​Dart_RunLoop​​​ 和 ​​dart::MessageHandler​​。