Dart VM是运行dart的虚拟机,由多个isolate组成,每个isolate提供dart的运行环境,类似Android/ART中Zygote提供的Java运行环境,Dart VM包含下面几个重要的isolate

一、Dart VM概述

Dart VM是运行dart的虚拟机,由多个isolate组成,每个isolate提供dart的运行环境,类似Android/ART中Zygote提供的Java运行环境,Dart VM包含下面几个重要的isolate

  • vm isolate

    负责维持系统中基础的heap object如null,class_, true, false,供各个isolate共享

  • kernel isolate

    主要用于执行CFE代码,CFE使用dart语言开发,实现了dart的语法分析,词法分析和语义分析,生成kernel AST

  • service isolate

    主要用于执行其他isolate发起的service请求,service包括debug相关,compile相关等,具体列表: https://github.com/dart-lang/sdk/blob/main/runtime/vm/service.cc#L5254

  • dartdev isolate

    主要用于执行用户命令,如dart run/compile等命令,最终会转换为后端命令。

    用户命令: dart compile kernel hello.dart 
     后端命令: dart --snapshot-kind=kernel --snapshot=hello.dill --verbosity=all hello.dart
    
  • main isolate

    主要用来执行用户开发的dart code。

更多关于Dart VM的基础原理可参见dart作者的blog,网上很多blog来自这篇文章,这篇文章还在持续完善中

https://mrale.ph/dartvm/

二、Dart VM各个isolate在main函数中的启动和初始化过程

  • 5个isolate在main中的初始化和启动过程

    int main(int argc, char* argv[]) {
        Dart_Initialize(&init_params) {
            Dart::Init(..) {
               Dart::DartInit(...) {
                  //各种初始化,线程池,heap,zone,object(null_,class_),stub code等
    
                  // create_group_ = CreateIsolateGroupAndSetup();
                  Isolate::SetCreateGroupCallback(create_group);
                  // 创建"vm-isolate" isolate
                  vm_isolate_ = Isolate::InitIsolate("vm-isolate", ....);
    
                  // 创建"vm-service" isolate
                  if (!is_dart2_aot_precompiler || !kDartPrecompiledRuntime) {
                      ServiceIsolate::Run(); {
                          CreateIsolateGroupAndSetup("vm-service", ...)
                             CreateAndSetupServiceIsolate("vm-service");
                      }
                  }
    
                  // 初始化"kernel-service" isolate
                  if (not dart precoompiled runtime) {
                      KernelIsolate::InitializeState();
                  }
    
                  // 按需创建kernel-service isolate
                  // KernelIsolate::Start()
               }
            }
        }
    
        // "dartdev isolate"
        bool should_run_user_program = true;
        if (...) {
            result = DartDevIsolate::RunDartDev(CreateIsolateGroupAndSetup,...)
               DartDevIsolate::DartDevRunner::Run(CreateIsolateGroupAndSetup,..)
                 ThreadStart --> DartDevRunner::RunCallback {
                     CreateIsolateGroupAndSetup("dartdev");
                        CreateAndSetupDartDevIsolate("dartdev")
    
                     // dartdev isolate入口:
                     isolate_args[0] = "dartdev.dart::main" // entrypoint
                     isolate_args[1] = args                 // args
                     isolate_args[2] = send_port;           // message back
                     isolate_args[4] = ...
                     ...
    
                     Dart_Invoke(isolate_lib="dart::isolate", "_startIsolate", 4,
                                   isolate_args);
                     Dart_RunLoop();
                 }
            // 如果dartdev命令结果是继续执行编译结果,则在main isolate中执行。
            should_run_user_program =
                  (dartdev_result == DartDevIsolate::DartDev_Result_Run);
            if (should_run_user_program) {
                // 加载编译后dill文件的data和instructions,包含app和vm的data和instruction
                // vm_snapshot_data
                // vm_snapshot_instructions
                // app_isolate_snapshot_data
                // app_isolate_snapshot_instructions
                try_load_snapshots_lambda();
            }
        }
    
        // main isolate
        if (should_run_user_program) {
            RunMainIsolate(script_name, ...)
              CreateIsolateGroupAndSetupHelper(true, "hello.dart", "main",...);
    
            // 向kernel isolate发起编译dill binary请求
            if (Options::gen_snapshot_kind) == kKernel) {
               Snapshot::GenerateKernel(Options::snapshot_filename(), script_name..)
            }
            // load dill binary(try_load_snapshots_lambda),并执行
            else {
                isolate_args[0] = "hello.dart::main";   // entrypoint
                isolate_args[1] =  args                 // args
    
                Dart_Invoke(isolate_lib="dart::isolate", 2, isolate_args);
                Dart_RunLoop();
                // Generate an app snapshot after execution if specified.
                if (Options::gen_snapshot_kind() == kAppJIT) {
                    Snapshot::GenerateAppJIT(Options::snapshot_filename());
                }
            }
    
        }
    }
    

二、 用户命令dart compile kernel hello.dart执行过程

  • 用户命令在dartdev isolate中执行

    dartdev isolate入口在dartdev.dart,dartdev.dart是一个dart开发工具包,可以处理各种用户命令,包括analyzer, create, compile, run等命令

    https://github.com/dart-lang/sdk/blob/main/pkg/dartdev/bin/dartdev.dart

    // 支持的命令 
    addCommand(AnalyzeCommand(verbose: verbose));
    addCommand(CreateCommand(verbose: verbose));
    addCommand(CompileCommand(verbose: verbose));
    addCommand(FixCommand(verbose: verbose));
    addCommand(FormatCommand(verbose: verbose));
    addCommand(LanguageServerCommand(verbose: verbose));
    addCommand(MigrateCommand(verbose: verbose));
    addCommand(pubCommand());
    addCommand(RunCommand(verbose: verbose));
    addCommand(TestCommand())
    
  • dartdev入口,以及调用流程

    1. The entry point for dartdev
    Future<void> main(List<String>args, SendPort )
        runDartdev(args, port)
           DartdevRunner.run(args)
              DartdevRunner::runCommand(args)
                 super.runCommand(args)
                    CompileCommand.runCommand(..)
    
    1. CompileComand有四个子命令进行js,aot,exe,jit编译,最终会调用native函数执行dart后端编译命令
    CompileCommand.runCommand(..)
        CompileSnapshotCommand.run {
           // Compiling hello.dart to kernel file hello.dill
           log.stdout('Compiling $sourcePath to $commandName file $outputFile.');
           await startDartProcess(sdk, args);
              external Process.start(sdk.dart, arguments, workingDirectory: cwd);
              //调用native函数dart::bin::Builtin_Process_Start()
              //最终会fork出一个子进程,执行dart编译命令
        }
    
       .dart::bin::Builtin_Process_Start调用栈如下
    
    #0  dart::bin::ProcessStarter::ProcessStarter (this=0x7ffff39fde38, namespc=0x555558973740,
        path=0x5555589ed180 "/data/chunbo/aosp/dart-sdk/sdk/out/DebugX64/dart-sdk/bin/dartdebug", arguments=0x5555589ed210,
        arguments_length=4, working_directory=0x0, environment=0x5555589ed3c0, environment_length=31, mode=dart::bin::kNormal,
        in=0x7ffff39fe068, out=0x7ffff39fe070, err=0x7ffff39fe060, id=0x7ffff39fdfc0, exit_event=0x7ffff39fe058,
        os_error_message=0x7ffff39fdfb8) at ../../runtime/bin/process_linux.cc:270
    #1  0x000055555748a5b9 in dart::bin::Process::Start (namespc=0x555558973740,
        path=0x5555589ed180 "/data/chunbo/aosp/dart-sdk/sdk/out/DebugX64/dart-sdk/bin/dartdebug", arguments=0x5555589ed210,
        arguments_length=4, working_directory=0x0, environment=0x5555589ed3c0, environment_length=31, mode=dart::bin::kNormal,
        in=0x7ffff39fe068, out=0x7ffff39fe070, err=0x7ffff39fe060, id=0x7ffff39fdfc0, exit_event=0x7ffff39fe058,
        os_error_message=0x7ffff39fdfb8) at ../../runtime/bin/process_linux.cc:809
    #2  0x0000555557489688 in dart::bin::Builtin_Process_Start (args=0x7ffff39fe1a0) at ../../runtime/bin/process.cc:144
    #3  0x00005555577dd42c in dart::NativeEntry::AutoScopeNativeCallWrapperNoStackCheck (args=0x7ffff39fe1a0,
        func=0x555557489300 <dart::bin::Builtin_Process_Start(_Dart_NativeArguments*)>) at ../../runtime/vm/native_entry.cc:217
    #4  0x00005555577dd309 in dart::NativeEntry::AutoScopeNativeCallWrapper (args=0x7ffff39fe1a0,
        func=0x555557489300 <dart::bin::Builtin_Process_Start(_Dart_NativeArguments*)>) at ../../runtime/vm/native_entry.cc:198
    #5  0x00007ffff7682a44 in ?? ()
    #6  0x00005555589b1000 in ?? ()
    #7  0x000000000100000c in ?? ()
    #8  0x00007ffff39fe240 in ?? ()
    #9  0x00007ffff39fe1e0 in ?? ()
    #10 0x00007ffff3472c21 in ?? ()
    #11 0x00007ffff778d501 in ?? ()
    #12 0x00007ffff39fe268 in ?? ()
    #13 0x00007ffff3b2b164 in ?? ()
    #14 0x00007ffff7788041 in ?? ()
    #15 0x00007ffff3af1639 in ?? ()
    #16 0x00007ffff3aed079 in ?? ()
    #17 0x00007ffff3aec7d9 in ?? ()
    #18 0x00007ffff3aebf59 in ?? ()
    #19 0x00007ffff3aea2b9 in ?? ()
    #20 0x0000000000000000 in ?? ()
    
    1. fork的子进程会实际执行编译动作
    CMD="$DART_BIN/dart --snapshot-kind=kernel --snapshot=hello.dill --verbosity=all $DART_SOURCE/hello.dart
    dart::bin::Builtin_Process_Start(...)
      ....
      dart::bin::ProcessStarter starter(namespc, path, arguments, arguments_length,...)
      starter.Start() {
          pid_t pid = fork();
          if (pid == 0) {
              NewProcess()
                 ExecProcess(){
                    // CMD="$DART_BIN/dart --snapshot-kind=kernel --snapshot=hello.dill ....
                    execvp(realpath, const_cast<char* const*>(program_arguments_));
                 }
    
          }
      }
    

三、 转换后的dart命令执行流程

  • dart --snapshot-kind=kernel --snapshot=hello.dill --verbosity=all hello.dart
    
  • 在main isolate中启动kernel isolate(CFE)并初始化,同时向kernel isolate发起编译请求,把生成的AST写入dill文件。

    int main(int argc, char* argv[]) {
        ...
        RunMainIsolate(script_name, package_config_override, &dart_options) {
            if (Options::gen_snapshot_kind() == kKernel) {
                Snapshot::GenerateKernel(Options::snapshot_filename(), script_name, ..) {
                    dfe.ReadScript(script_name, kernel_buffer,..);
                    if (kernel_buffer != nullptr) {
                        WriteSnapshotFile(snapshot_filename, kernel_buffer,..);
                    } else {
                        // 向kernel isolate(CFE)发起dart编译请求
                        Dart_KernelCompilationResult result =
                             dfe.CompileScript(script_name, false, package_config, true);
    
                        // 请求成功后把编译结果写入dill文件
                        WriteSnapshotFile(snapshot_filename, result.kernel, result.kernel_size);
                    }
                }
            }
        }
    }
    
  • 启动kernel isolate,向kernel isolate CFE模块发起dart编译请求

     dfe.CompileScript(script_name, false, package_config, true);
       Dart_CompileToKernel(sanitized_uri, platform_strong_dill,platform_strong_dill_size,...);
          KernelIsolate::CompileToKernel(script_uri, platform_kernel, platform_kernel_size,..) {
              // Start the kernel Isolate if it is not already running.
              if (!KernelIsolate::Start()) {
              }
    
              // This must be the main script to be loaded. Wait for Kernel isolate
              // to finish initialization.
              Dart_Port kernel_port = WaitForKernelPort();  // kernel_service.dart
    
              KernelCompilationRequest request;
              // 向kernel isolate发起编译请求
              return request.SendAndWaitForResponse(
                  kCompileTag, kernel_port, script_uri, platform_kernel,
                  platform_kernel_size, source_file_count, source_files,
                  incremental_compile, snapshot_compile, package_config,
                  multiroot_filepaths, multiroot_scheme, experimental_flags_, NULL,
                  verbosity);
    
          }
    
  • kernel isolate启动和初始化

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
     KernelIsolate::Start() {
          Dart::thread_pool()->Run<RunKernelTask>();
             new thread::RunKernelTask::run() {
                  create_group_callback = KernelIsolate::create_group_callback() // CreateIsolateGroupAndSetup;
                  CreateIsolateGroupAndSetup("kernel-service", ..)
                    CreateAndSetupKernelIsolate("kernel-service", ..)
                      IsolateSetupHelper(...)
                          // 加载kernel-service的dart code
                          // 332	  if (isolate_run_app_snapshot) {
                          // (gdb) n
                          // 333	    Dart_Handle result = Loader::InitForSnapshot(script_uri, isolate_data);
                          // (gdb) p script_uri
                          // $2 = 0x55555896e3c0 "/data/chunbo/aosp/dart-sdk/sdk/out/DebugX64/dart-sdk/bin/snapshots/kernel-service.dart.snapshot"
                          if (isolate_run_app_snapshot) {
                             Dart_Handle result = Loader::InitForSnapshot(script_uri, isolate_data)
                          }
          // 执行kernel isolate的入口函数
          RunMain(isolate);
             DartEntry::InvokeFunction("kernel_service.dart::main", empty args);
             // kernel_service.dart
               main([args]) {
                   if ((args?.length ?? 0) > 1 && args[0]....) {
                   } else {
                  // Entry point for the Kernel isolate.
                       return new RawReceivePort()..handler = _processLoadRequest;    
                   }
               }
    
      }
    
  • kernel isolate接收来自的main isolate的编译请求

    // kernel_service.dart
    main([args]) {
      if ((args?.length ?? 0) > 1 && args[0] == '--train') {
        // This entry point is used when creating an app snapshot.
        // It takes the following extra arguments:
        // 1) Script to compile.
        // 2) Optional platform kernel path.
        train(script, platform);
           trainInternal(scriptUri, platformKernelPath);
              _processLoadRequest(request)
      } else {
        // Entry point for the Kernel isolate.
        return new RawReceivePort()..handler = _processLoadRequest;
      }
    }
    
  • 编译dart code,词法分析,语法分析和语义分析并返回结果给main isolate

    _processLoadRequest(request) {
        Compiler? compiler;
        if (incremental) {
           compiler = await lookupOrBuildNewIncrementalCompiler(..)
        } else {
           compiler = new SingleShotCompilerWrapper(..);
        }
        CompilerResult compilerResult = await compiler.compile(script!);
           SingleShotCompilerWrapper::compileInternal(Uri script) async 
              kernelForProgram(Uri source, ..)
                kernelForProgramInternal(source, ...);
                ....
    }
    
  • main isolate收到编译好的Kernel AST写入dill文件

    int main(int argc, char* argv[]) {
        ...
        RunMainIsolate(script_name, package_config_override, &dart_options) {
            if (Options::gen_snapshot_kind() == kKernel) {
                Snapshot::GenerateKernel(Options::snapshot_filename(), script_name, ..) {
                    dfe.ReadScript(script_name, kernel_buffer,..);
                    if (kernel_buffer != nullptr) {
                        WriteSnapshotFile(snapshot_filename, kernel_buffer,..);
                    } else {
                        // 向kernel isolate(CFE)发起dart编译请求
                        Dart_KernelCompilationResult result =
                             dfe.CompileScript(script_name, false, package_config, true);
    
                        // 请求成功后把编译结果写入dill文件
                        WriteSnapshotFile(snapshot_filename, result.kernel, result.kernel_size);
                    }
                }
            }
        }
    }
    

    至此dill的编译流程结束,下篇会介绍下CFE的编译过程