2.2 DartVM 初始化
runtime/vm/dart.cc
的 DartInit 方法负责 DartVM 的初始化。
方法签名:
char* Dart::DartInit(const Dart_InitializeParams* params) {
这个方法接受一个 Dart_InitializeParams
结构体指针作为参数,返回一个字符串指针(用于返回错误信息)。
VM 标志初始化检查
检查 VM 标志是否已初始化,以及 VM isolate 是否已经存在。这两个条件都会导致初始化失败。
if Initialized() {
return Utils::StrDup("VM initialization failed-VM Flags not initialized.");
}
if (vm_isolate_ != nullptr) {
return Utils::StrDup("VM initialization is in an inconsistent state.");
}
snapshot_data 按需加载
如果提供了 VM snapshot 数据,则设置 snapshot。
const Snapshot* snapshot = nullptr;
if (params->vm_snapshot_data != nullptr) {
snapshot = Snapshot::SetupFromBuffer(params->vm_snapshot_data);
if (snapshot == nullptr) {
return Utils::StrDup("Invalid vm isolate snapshot seen");
}
}
如果有 snapshot,则从 snapshot 中初始化全局 VM 标志。
if (snapshot != nullptr) {
char* error =
SnapshotHeaderReader::InitializeGlobalVMFlagsFromSnapshot(snapshot);
if (error != nullptr) {
return error;
}
}
初始化帧布局
初始化帧布局,设置线程启动和退出回调,设置文件操作回调,设置熵源回调,初始化操作系统相关功能。
FrameLayout::Init();
set_thread_start_callback(params->thread_start);
set_thread_exit_callback(params->thread_exit);
SetFileCallbacks(params->file_open,
params->file_read,
params->file_write,
params->file_close);
set_entropy_source_callback(params->entropy_source);
OS::Init();
代码观察器
在非产品模式下初始化代码观察器,记录启动时间。
NOT_IN_PRODUCTInit();
if (params->code_observer != nullptr) {
NOT_IN_PRODUCTRegisterExternal(*params->code_observer);
}
start_time_micros_ = OS::GetCurrentMonotonicMicros();
虚拟内存
初始化虚拟内存系统,对于 Fuchsia 操作系统有特殊处理。
#if defined(DART_HOST_OS_FUCHSIA)
VirtualMemory::Init(params->vmex_resource);
#else
VirtualMemory::Init();
#endif
DartVM 子系统初始化
这一大段代码初始化了 DartVM 的各个子系统,包括操作系统线程、随机数生成器、内存分配器(Zone)、时间线、Isolate 组、Isolate、用户标签、端口映射、服务、自由列表元素、ForwardingCorpse、API、本地符号解析器、展开记录平台、页面、存储缓冲区、标记栈、目标 CPU 特性、FFI 回调元数据等。
OSThread::Init();
Random::Init();
Zone::Init();
#if defined(SUPPORT_TIMELINE)
Timeline::Init();
TimelineBeginEndScope tbesGetVMStream(), "Dart::Init";
#endif
IsolateGroup::Init();
Isolate::InitVM();
UserTags::Init();
PortMap::Init();
Service::Init();
FreeListElement::Init();
ForwardingCorpse::Init();
Api::Init();
NativeSymbolResolver::Init();
UnwindingRecordsPlatform::Init();
Page::Init();
StoreBuffer::Init();
MarkingStack::Init();
TargetCPUFeatures::Init();
FfiCallbackMetadata::Init();
模拟器
如果使用模拟器,则初始化模拟器。
#if defined(USING_SIMULATOR)
Simulator::Init();
#endif
线程池
创建预定义句柄和线程池。
predefined_handles_ = new ReadOnlyHandles();
thread_pool_ = new ThreadPool();
VM isolate
这一大段代码是初始化 VM isolate 的核心逻辑。它创建了 VM isolate,设置了它的标志,创建了堆,注册了 isolate 组,初始化了对象系统,读取了 VM snapshot(如果有的话),并完成了最后的初始化和验证步骤。
{
// 确保 VM isolate 还未被创建
ASSERT(vm_isolate_ == nullptr);
// 确保 VM 标志已经被初始化
ASSERTInitialized();
// 标记这是 VM isolate
const bool is_vm_isolate = true;
// 初始化 isolate 标志
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
// 设置为系统 isolate
api_flags.is_system_isolate = true;
// 创建 IsolateGroupSource,包含 VM isolate 的基本信息
std::unique_ptr<IsolateGroupSource> source(
new IsolateGroupSource(
kVmIsolateName,
kVmIsolateName,
params->vm_snapshot_data,
params->vm_snapshot_instructions,
nullptr,
-1,
api_flags));
// 创建 IsolateGroup,这是 VM isolate 所属的组
auto group = new IsolateGroup(
std::move(source),
/*embedder_data=*/nullptr,
/*object_store=*/nullptr,
api_flags);
// 为 VM isolate 创建堆
group->CreateHeap(
/*is_vm_isolate=*/true,
/*is_service_or_kernel_isolate=*/false);
// 注册 IsolateGroup
IsolateGroup::RegisterIsolateGroup(group);
// 初始化 VM isolate
vm_isolate_ =
Isolate::InitIsolate(
kVmIsolateName,
group,
api_flags,
is_vm_isolate);
// 标记初始化成功
group->set_initial_spawn_successful();
// 验证当前执行环境确实是 VM isolate
ASSERT(vm_isolate_ == Isolate::Current());
ASSERT(vm_isolate_ == Thread::Current()->isolate());
// 获取当前线程
Thread* T = Thread::Current();
ASSERT(T != nullptr);
// 创建栈区域和句柄作用域
StackZone zone(T);
HandleScope handle_scope(T);
// 初始化 null 和 bool 对象
Object::InitNullAndBool(vm_isolate_->group());
// 设置对象存储
vm_isolate_->isolate_group_->set_object_store(new ObjectStore());
vm_isolate_->isolate_object_store()->Init();
// 初始化终结器
vm_isolate_->finalizers_ = GrowableObjectArray::null();
// 初始化对象系统
Object::Init(vm_isolate_->group());
// 初始化偏移表、参数描述符和 IC 数据
OffsetsTable::Init();
ArgumentsDescriptor::Init();
ICData::Init();
// 如果提供了 VM snapshot 数据
if (params->vm_snapshot_data != nullptr) {
// 开始读取 VM snapshot 的时间记录(仅在支持时间线的情况下)
#if defined(SUPPORT_TIMELINE)
TimelineBeginEndScope tbesGetVMStream(), "ReadVMSnapshot";
#endif
ASSERT(snapshot != nullptr);
// 记录 snapshot 类型
vm_snapshot_kind_ = snapshot->kind();
// 如果 snapshot 包含代码
if IncludesCode(vm_snapshot_kind_) {
// 对于 AOT 编译的 snapshot,JIT 运行时无法处理
if (vm_snapshot_kind_ == Snapshot::kFullAOT) {
#if !defined(DART_PRECOMPILED_RUNTIME)
return Utils::StrDup("JIT runtime cannot run a precompiled snapshot");
#endif
}
// 确保提供了指令 snapshot
if (params->vm_snapshot_instructions == nullptr) {
return Utils::StrDup("Missing instructions snapshot");
}
} else if IsFull(vm_snapshot_kind_) {
// 预编译运行时需要预编译的 snapshot
#if defined(DART_PRECOMPILED_RUNTIME)
return Utils::StrDup(
"Precompiled runtime requires a precompiled snapshot");
#else
// 初始化存根代码和完成对象初始化
StubCode::Init();
Object::FinishInit(vm_isolate_->group());
#endif
} else {
return Utils::StrDup("Invalid vm isolate snapshot seen");
}
// 读取 VM snapshot
FullSnapshotReader reader(snapshot, params->vm_snapshot_instructions, T);
const Error& error = Error::Handle(reader.ReadVMSnapshot());
if (!error.IsNull()) {
return Utils::StrDup(error.ToErrorCString());
}
// 完成对象初始化
Object::FinishInit(vm_isolate_->group());
// 记录 snapshot 大小和堆大小(仅在支持时间线的情况下)
#if defined(SUPPORT_TIMELINE)
if (tbes.enabled()) {
tbes.SetNumArguments(2);
tbes.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
tbes.FormatArgument(
1, "heapSize", "%" Pd,
vm_isolate_groupkOld) * kWordSize;
}
#endif // !defined(PRODUCT)
// 如果开启了 isolate 跟踪,打印相关信息
if (FLAG_trace_isolates) {
OS::PrintErr("Size of vm isolate snapshot = %" Pd "\n",
snapshot->length());
vm_isolate_group()->heap()->PrintSizes();
MegamorphicCacheTable::PrintSizes(T);
intptr_t size;
intptr_t capacity;
Symbols::GetStats(vm_isolate_->group(), &size, &capacity);
OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
}
} else {
// 如果没有提供 VM snapshot 数据
#if defined(DART_PRECOMPILED_RUNTIME)
return Utils::StrDup(
"Precompiled runtime requires a precompiled snapshot");
#else
// 设置 snapshot 类型为 None,初始化存根代码和符号
vm_snapshot_kind_ = Snapshot::kNone;
StubCode::Init();
Object::FinishInit(vm_isolate_->group());
Symbols::Init(vm_isolate_->group());
#endif
}
// 初始化 VM 常量
T->InitVMConstants();
// 对于 IA32 或 X64 架构,检查是否支持 SSE2
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
if sse2_supported() {
return Utils::StrDup("SSE2 is required.");
}
#endif
// 完成 VM isolate 的最终初始化
{
#if defined(SUPPORT_TIMELINE)
TimelineBeginEndScope tbesGetVMStream(), "FinalizeVMIsolate";
#endif
Object::FinalizeVMIsolate(vm_isolate_->group());
}
// 在调试模式下验证堆
#if defined(DEBUG)
vm_isolate_groupDartInit", kRequireMarked;
#endif
}
Snapshot 类型校验
在 DartVM 的初始化过程中,对 snapshot 类型的判断是非常重要的,因为它决定了 VM 如何加载和执行代码。
Snapshot 概念:Snapshot 是 Dart 程序状态的序列化表示。它可以包含对象图、代码等,用于快速启动和执行 Dart 程序。
Snapshot 类型:
主要有以下几种类型:
- Full: 完整的程序状态
- FullJIT: 包含 JIT 编译的代码
- FullAOT: 包含 AOT 编译的代码
在上一节的 Snapshot 校验环节中,代码的逻辑如下:
a. 检查 snapshot 是否包含代码:
- 如果包含,进一步检查是否是 AOT 编译的 snapshot
- 如果是 AOT snapshot,但当前运行时不是预编译运行时,则报错
- 检查是否提供了指令 snapshot
b. 如果 snapshot 是完整的(Full),但不包含代码:
- 如果是预编译运行时,报错(因为预编译运行时需要预编译的 snapshot)
- 否则,初始化存根代码和对象
c. 如果既不包含代码也不是完整的 snapshot,报错
JIT vs AOT:
- JIT (Just-In-Time): 在运行时编译代码。适用于开发环境,可以动态优化热点代码。
- AOT (Ahead-Of-Time): 在运行前预编译代码。适用于生产环境,启动更快,但失去了动态优化的能力。
为什么需要这些判断:
- 兼容性: 确保运行时环境与 snapshot 类型匹配
- 性能: 不同类型的 snapshot 需要不同的加载和执行策略
- 安全性: 防止在不适合的环境中运行某些类型的 snapshot
收尾工作
最后的这段代码完成了一些收尾工作:
- 在非产品模式下初始化分析器。
- 初始化 API 句柄。
- 退出 VM isolate。
- 设置各种回调函数。
- 在非产品模式下设置服务相关的回调。
- 如果不是 AOT 预编译器且需要支持服务或者不是预编译运行时,则运行服务 isolate。
- 在非预编译运行时模式下,如果需要启动内核 isolate,则初始化内核 isolate 的状态。
最后,如果一切正常,返回 nullptr 表示初始化成功。
NOT_IN_PRODUCTInit();
Api::InitHandles();
Thread::ExitIsolate();
Isolate::SetCreateGroupCallback(params->create_group);
Isolate::SetInitializeCallback_(params->initialize_isolate);
Isolate::SetShutdownCallback(params->shutdown_isolate);
Isolate::SetCleanupCallback(params->cleanup_isolate);
Isolate::SetGroupCleanupCallback(params->cleanup_group);
Isolate::SetRegisterKernelBlobCallback(params->register_kernel_blob);
Isolate::SetUnregisterKernelBlobCallback(params->unregister_kernel_blob);
#ifndef PRODUCT
const bool support_service = true;
Service::SetGetServiceAssetsCallback(params->get_service_assets);
#else
const bool support_service = false;
#endif
const bool is_dart2_aot_precompiler =
FLAG_precompiled_mode && !kDartPrecompiledRuntime;
if (!is_dart2_aot_precompiler &&
(support_service || !kDartPrecompiledRuntime)) {
ServiceIsolate::Run();
}
#ifndef DART_PRECOMPILED_RUNTIME
if (params->start_kernel_isolate) {
KernelIsolate::InitializeState();
}
#endif // DART_PRECOMPILED_RUNTIME
return nullptr;
本文作者:Maeiee
本文链接:2.2 DartVM 初始化
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!