在Flutter之Engine启动流程一文中叙述了Engine
是如何建立并调用入口函数——main
的。因为篇幅缘由,在该文中并无具体讲解Dart VM的建立。因此本文就来看看Dart VM是如何建立的。html
直接来看Shell
的Create
函数(关因而如何调用该函数的,能够去阅读Flutter之Engine启动流程一文),代码以下。android
std::unique_ptr<Shell> Shell::Create(
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
PerformInitializationTasks(settings);
PersistentCache::SetCacheSkSL(settings.cache_sksl);
//Dart VM的建立
auto vm = DartVMRef::Create(settings);
auto vm_data = vm->GetVMData();
//继续进行Shell对象的建立
return Shell::Create(std::move(task_runners), //
std::move(window_data), //
std::move(settings), //
vm_data->GetIsolateSnapshot(), // isolate snapshot
on_create_platform_view, //
on_create_rasterizer, //
std::move(vm) //
);
}
复制代码
在Create
主要是进行Dart VM的建立,经过DartVMRef
中的Create
函数。代码以下。c++
DartVMRef DartVMRef::Create(Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot) {
std::scoped_lock lifecycle_lock(gVMMutex);
//若是进程中存在正在运行的Dart VM,那么直接使用这个Dart VM。也就是在同一进程中,只会存在一个Dart VM
if (auto vm = gVM.lock()) {
//直接返回进程中已存在的Dart VM
return DartVMRef{std::move(vm)};
}
std::scoped_lock dependents_lock(gVMDependentsMutex);
gVMData.reset();
gVMServiceProtocol.reset();
gVMIsolateNameServer.reset();
gVM.reset();
//若是进程中没有Dart VM,就建立并初始化一个Dart VM
auto isolate_name_server = std::make_shared<IsolateNameServer>();
auto vm = DartVM::Create(std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
isolate_name_server //
);
if (!vm) {//建立DartVM实例失败
return {nullptr};
}
//将Dart VM的引用设为全局引用,保证进程内惟一性。
gVMData = vm->GetVMData();
gVMServiceProtocol = vm->GetServiceProtocol();
gVMIsolateNameServer = isolate_name_server;
gVM = vm;
if (settings.leak_vm) {
gVMLeak = new std::shared_ptr<DartVM>(vm);
}
return DartVMRef{std::move(vm)};
}
复制代码
在DartVMRef
中的Create
函数中主要是返回一个Dart VM引用,这个Dart VM是进程内惟一的,也就是进程中若是不存在Dart VM,那么就建立并初始化一个Dart VM,不然直接使用已存在的Dart VM。下面再来看Dart VM的建立流程。git
std::shared_ptr<DartVM> DartVM::Create(
Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
std::shared_ptr<IsolateNameServer> isolate_name_server) {
auto vm_data = DartVMData::Create(settings, //
std::move(vm_snapshot), //
std::move(isolate_snapshot) //
);
if (!vm_data) {
return {};
}
//建立Dart VM
return std::shared_ptr<DartVM>(
new DartVM(std::move(vm_data), std::move(isolate_name_server)));
}
复制代码
上面代码就是简单的建立一个DartVM
对象,来看该对象的构造函数。bootstrap
DartVM::DartVM(std::shared_ptr<const DartVMData> vm_data,
std::shared_ptr<IsolateNameServer> isolate_name_server)
: settings_(vm_data->GetSettings()),
concurrent_message_loop_(fml::ConcurrentMessageLoop::Create()),
skia_concurrent_executor_(
[runner = concurrent_message_loop_->GetTaskRunner()](
fml::closure work) { runner->PostTask(work); }),
vm_data_(vm_data),
isolate_name_server_(std::move(isolate_name_server)),
service_protocol_(std::make_shared<ServiceProtocol>()) {
gVMLaunchCount++;
//因为Dart VM初始化是线程安全的,所以这里的调用也是线程安全的
SkExecutor::SetDefault(&skia_concurrent_executor_);
{
//EventHandler的建立
dart::bin::BootstrapDartIo();
if (!settings_.temp_directory_path.empty()) {
dart::bin::SetSystemTempDirectory(settings_.temp_directory_path.c_str());
}
}
...
//UI相关类的注册,如Canvas、Picture、Window等。
DartUI::InitForGlobal();
{
//Dart VM初始化参数
Dart_InitializeParams params = {};
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
params.vm_snapshot_data = vm_data_->GetVMSnapshot().GetDataMapping();
params.vm_snapshot_instructions =
vm_data_->GetVMSnapshot().GetInstructionsMapping();
params.create_group = reinterpret_cast<decltype(params.create_group)>(
DartIsolate::DartIsolateGroupCreateCallback);
params.initialize_isolate =
reinterpret_cast<decltype(params.initialize_isolate)>(
DartIsolate::DartIsolateInitializeCallback);
params.shutdown_isolate =
reinterpret_cast<decltype(params.shutdown_isolate)>(
DartIsolate::DartIsolateShutdownCallback);
params.cleanup_isolate = reinterpret_cast<decltype(params.cleanup_isolate)>(
DartIsolate::DartIsolateCleanupCallback);
params.cleanup_group = reinterpret_cast<decltype(params.cleanup_group)>(
DartIsolate::DartIsolateGroupCleanupCallback);
params.thread_exit = ThreadExitCallback;
params.get_service_assets = GetVMServiceAssetsArchiveCallback;
params.entropy_source = dart::bin::GetEntropy;
//Dart VM初始化
char* init_error = Dart_Initialize(¶ms);
...
}
...
}
复制代码
在DartVM
对象的构造函数中主要作了如下几件事。api
EventHandler
的建立。Engine
层的注册。先来看EventHandler
的建立。安全
EventHandler
是经过BootstrapDartIo
函数来建立的,实现代码以下。app
void BootstrapDartIo() {
// Bootstrap 'dart:io' event handler.
TimerUtils::InitOnce();
EventHandler::Start();
}
复制代码
在EventHandler
的Start
函数中,会建立一个全局socket(globalTcpListeningSocketRegistry
)、一个Monitor
对象及EventHandler
对象。异步
EventHandler
的具体实现因系统而已,这里以Android
系统为例。EventHandler
的delegate_
是一个EventHandlerImplementation
对象,他的具体实如今eventhandler_android.cc
中。socket
void EventHandler::Start() {
//初始化一个全局socket(globalTcpListeningSocketRegistry)
ListeningSocketRegistry::Initialize();
shutdown_monitor = new Monitor();
//建立EventHandler对象
event_handler = new EventHandler();
event_handler->delegate_.Start(event_handler);
...
}
复制代码
在delegate_
的构造函数中,会建立一个epoll
句柄,并注册一个interrupt_fd
到epoll
中。
再来看delegate_
的start
函数,在该函数中会建立一个名为dart:io EventHandler
的新线程。Java中,建立一个新线程,都会传递一个回调方法。这里也不例外。其对应的回调函数就是Poll
函数,在该函数中会经过epoll
来等待事件并执行。
经过epoll
拿到执行完毕的任务后,直接调用HandleEvents
函数来进一步处理,并经过isolate
的MessageHandler
来执行对应的回调。
//建立epoll句柄
EventHandlerImplementation::EventHandlerImplementation()
: socket_map_(&SimpleHashMap::SamePointerValue, 16) {
intptr_t result;
result = NO_RETRY_EXPECTED(pipe(interrupt_fds_));
shutdown_ = false;
//传递给epoll_create的初始大小,当Linux版本>=2.6.8时,该值将被忽略
static const int kEpollInitialSize = 64;
//建立epoll句柄
epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize));
//注册interrupt_fd到epoll中。
struct epoll_event event;
event.events = EPOLLIN;
event.data.ptr = NULL;
int status = NO_RETRY_EXPECTED(
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupt_fds_[0], &event));
}
void EventHandlerImplementation::Start(EventHandler* handler) {
//建立线程名为dart:io EventHandler的新线程
int result =
Thread::Start("dart:io EventHandler", &EventHandlerImplementation::Poll,
reinterpret_cast<uword>(handler));
}
//新线程的具体执行函数
void EventHandlerImplementation::Poll(uword args) {
ThreadSignalBlocker signal_blocker(SIGPROF);
static const intptr_t kMaxEvents = 16;
struct epoll_event events[kMaxEvents];
EventHandler* handler = reinterpret_cast<EventHandler*>(args);
EventHandlerImplementation* handler_impl = &handler->delegate_;
while (!handler_impl->shutdown_) {
int64_t millis = handler_impl->GetTimeout();
if (millis > kMaxInt32) {
millis = kMaxInt32;
}
//阻塞等待
intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis));
if (result == -1) {
...
} else {
handler_impl->HandleTimeout();
//在子线程调用HandleEvents函数,会处理拿到的全部任务
handler_impl->HandleEvents(events, result);
}
}
handler->NotifyShutdownDone();
}
//处理拿到的全部事件
void EventHandlerImplementation::HandleEvents(struct epoll_event* events,
int size) {
bool interrupt_seen = false;
for (int i = 0; i < size; i++) {
if (events[i].data.ptr == NULL) {
interrupt_seen = true;
} else {
DescriptorInfo* di =
reinterpret_cast<DescriptorInfo*>(events[i].data.ptr);
const intptr_t old_mask = di->Mask();
const intptr_t event_mask = GetPollEvents(events[i].events, di);
if ((event_mask & (1 << kErrorEvent)) != 0) {
di->NotifyAllDartPorts(event_mask);
UpdateEpollInstance(old_mask, di);
} else if (event_mask != 0) {
Dart_Port port = di->NextNotifyDartPort(event_mask);
UpdateEpollInstance(old_mask, di);
//发送消息给isolate中MessageHandler
DartUtils::PostInt32(port, event_mask);
}
}
}
if (interrupt_seen) {
// Handle after socket events, so we avoid closing a socket before we handle
// the current events.
HandleInterruptFd();
}
}
复制代码
在EventHandler
的建立中,主要是建立新线程及epoll
的使用。在上层使用中,socket
及Timer
定时任务的执行就是经过EventHandler
来实现的。
在IOS
中,则是采用的kqueue
来实现异步IO。
EventHandler
建立成功后,还会进行UI相关类在C/C++层的注册,从而使framework层能顺利的调用native方法。在Java中,若是想要调用native方法,也会进行相似的注册。
void DartUI::InitForGlobal() {
if (!g_natives) {
g_natives = new tonic::DartLibraryNatives();
Canvas::RegisterNatives(g_natives);
CanvasGradient::RegisterNatives(g_natives);
CanvasImage::RegisterNatives(g_natives);
CanvasPath::RegisterNatives(g_natives);
CanvasPathMeasure::RegisterNatives(g_natives);
Codec::RegisterNatives(g_natives);
ColorFilter::RegisterNatives(g_natives);
DartRuntimeHooks::RegisterNatives(g_natives);
EngineLayer::RegisterNatives(g_natives);
FontCollection::RegisterNatives(g_natives);
FrameInfo::RegisterNatives(g_natives);
ImageFilter::RegisterNatives(g_natives);
ImageShader::RegisterNatives(g_natives);
IsolateNameServerNatives::RegisterNatives(g_natives);
Paragraph::RegisterNatives(g_natives);
ParagraphBuilder::RegisterNatives(g_natives);
Picture::RegisterNatives(g_natives);
PictureRecorder::RegisterNatives(g_natives);
Scene::RegisterNatives(g_natives);
SceneBuilder::RegisterNatives(g_natives);
SemanticsUpdate::RegisterNatives(g_natives);
SemanticsUpdateBuilder::RegisterNatives(g_natives);
Vertices::RegisterNatives(g_natives);
Window::RegisterNatives(g_natives);
#if defined(OS_FUCHSIA)
SceneHost::RegisterNatives(g_natives);
#endif
// Secondary isolates do not provide UI-related APIs.
g_natives_secondary = new tonic::DartLibraryNatives();
DartRuntimeHooks::RegisterNatives(g_natives_secondary);
IsolateNameServerNatives::RegisterNatives(g_natives_secondary);
}
}
复制代码
能够看到不少与UI相关的native方法都是在InitForGlobal
函数中注册的。
最后再来看Dart VM的初始化。
char* Dart::Init(const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
Dart_IsolateGroupCreateCallback create_group,
Dart_InitializeIsolateCallback initialize_isolate,
Dart_IsolateShutdownCallback shutdown,
Dart_IsolateCleanupCallback cleanup,
Dart_IsolateGroupCleanupCallback cleanup_group,
Dart_ThreadExitCallback thread_exit,
Dart_FileOpenCallback file_open,
Dart_FileReadCallback file_read,
Dart_FileWriteCallback file_write,
Dart_FileCloseCallback file_close,
Dart_EntropySource entropy_source,
Dart_GetVMServiceAssetsArchive get_service_assets,
bool start_kernel_isolate,
Dart_CodeObserver* observer) {
...
//栈帧布局的初始化
FrameLayout::Init();
set_thread_exit_callback(thread_exit);
SetFileCallbacks(file_open, file_read, file_write, file_close);
set_entropy_source_callback(entropy_source);
//系统相关初始化,针对不一样系统作的适配
OS::Init();
...
start_time_micros_ = OS::GetCurrentMonotonicMicros();
//虚拟内存初始化,默认是获取一页的大小
VirtualMemory::Init();
//OSThread线程初始化,建立一个名为Dart_Initialize的OSThread并将其设置为TLS
OSThread::Init();
//zone初始化
Zone::Init();
...
//将isolate的一些回调重置为null,如create_group_callback_、initialize_callback_等
Isolate::InitVM();
//IsolateGroup初始化
IsolateGroup::Init();
//PortMap初始化,建立一个初始化容量为8的map
PortMap::Init();
//FreeListElement初始化,主要是作一些assert判断
FreeListElement::Init();
//ForwardingCorpse初始化,主要是作一些assert判断
ForwardingCorpse::Init();
//Api初始化
Api::Init();
//与具体操做系统相关,目前都是空实现
NativeSymbolResolver::Init();
//SemiSpace初始化,SemiSpace主要是用于对内存的管理,新生代就由两个SemiSpace组成
SemiSpace::Init();
NOT_IN_PRODUCT(Metric::Init());
StoreBuffer::Init();
MarkingStack::Init();
...
// Create the read-only handles area.
predefined_handles_ = new ReadOnlyHandles();
// Create the VM isolate and finish the VM initialization.
//建立一个线程池
thread_pool_ = new ThreadPool();
{
//即将建立的isolate是vm isolate
const bool is_vm_isolate = true;
// Cache value of "non-nullable" experimental flag.
set_non_nullable_flag(KernelIsolate::GetExperimentalFlag("non-nullable"));
// Setup default flags for the VM isolate.
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
//这里建立一个伪IsolateGroupSource对象,由于即将建立的vm-isolate不是一个真正的isolate对象。它更多充当的是一个包含VM全局对象的容器。
std::unique_ptr<IsolateGroupSource> source(
new IsolateGroupSource(nullptr, kVmIsolateName, vm_isolate_snapshot,
instructions_snapshot, nullptr, -1, api_flags));
auto group = new IsolateGroup(std::move(source), /*embedder_data=*/nullptr);
IsolateGroup::RegisterIsolateGroup(group);
//建立一个名为vm-isolate的isolate对象
vm_isolate_ =
Isolate::InitIsolate(kVmIsolateName, group, api_flags, is_vm_isolate);
group->set_initial_spawn_successful();
Thread* T = Thread::Current();
StackZone zone(T);
HandleScope handle_scope(T);
//建立null对象,null是Dart VM建立的第一个对象
Object::InitNull(vm_isolate_);
//建立一个ObjectStore对象,该对象主要是来存储每一个isolate对于Dart VM中对象的引用
ObjectStore::Init(vm_isolate_);
//初始化CPU相关信息
TargetCPUFeatures::Init();
//初始化对象。
Object::Init(vm_isolate_);
ArgumentsDescriptor::Init();
ICData::Init();
SubtypeTestCache::Init();
if (vm_isolate_snapshot != NULL) {...} else {...}
//因为bootstrapping问题,这里须要在vm isolate所在线程来初始化常量
T->InitVMConstants();
{
Object::FinalizeVMIsolate(vm_isolate_);
}
}
Api::InitHandles();
//取消注册该线程中的VM isolate
Thread::ExitIsolate();
Isolate::SetCreateGroupCallback(create_group);
Isolate::SetInitializeCallback_(initialize_isolate);
Isolate::SetShutdownCallback(shutdown);
Isolate::SetCleanupCallback(cleanup);
Isolate::SetGroupCleanupCallback(cleanup_group);
...
return NULL;
}
复制代码
上面代码中作了详细的注释。能够发如今Dart VM初始化时,须要作的操做仍是蛮多的,好比栈帧布局的初始化、虚拟内存初始化、OSThread初始化、null对象及其余共享对象的初始化、PortMap
的初始化、线程池的建立、名为vm-isolate
的isolate
对象建立等。
这里重点来看vm-isolate
,它是一个isolate
,但与普通isolate
有很大的区别,因此不是一个真正的isolate
,是一个伪isolate
。主要区别以下:
isolate
堆中都会分为新生代与老年代,而且新生代中from
与to
的比例是1:1,新建立的对象也基本上都会分配在to
中。而vm-isolate
的堆中,新生代的空间大小为0,也就是不存在新生代。也所以,全部对象都直接分配在老年代中。isolate
相似进程,之间的对象是没法相互引用的。但对于vm-isolate
倒是例外,它的堆中包含一些不可变对象,如null,true,false,而且其余isolate
能够引用vm-isolate
中堆的对象。关于vm-isolate
的具体建立能够参考深刻理解Isolate原理这篇文章。
Dart VM启动流程图以下,是从Flutter之引擎启动流程的基础上开始的
Dart VM初始化成功后,也就意味着在同一进程中,Dart虚拟机已经启动成功并使用它了。不管engine
建立多少次,在同一进程中,Dart VM仅会建立一次。
【参考资料】