一、概述
书接上文源码解读Flutter run机制的第四节 flutter build aot命令将dart源码编译成AOT产物,其主要工作为前端编译器frontend_server和机器码生成,本文先介绍前端编译器frontend_server的工作原理。
1.1 frontend_server命令
KernelCompiler.compile()过程等价于如下命令:
// 该frontend_server命令 同时适用于Android和iOS
flutter/bin/cache/dart-sdk/bin/dart \
flutter/bin/cache/artifacts/engine/darwin-x64/frontend_server.dart.snapshot \
--sdk-root flutter/bin/cache/artifacts/engine/common/flutter_patched_sdk/ \
--strong \
--target=flutter \
--aot --tfa \
-Ddart.vm.product=true \
--packages .packages \
--output-dill /build/app/intermediates/flutter/release/app.dill \
--depfile /build/app/intermediates/flutter/release/kernel_compile.d \
--"package" /lib/main.dart
可见,通过dart虚拟机启动frontend_server.dart.snapshot,将dart代码转换成app.dill形式的kernel文件。frontend_server.dart.snapshot入口位于Flutter引擎中的 flutter/frontend_server/bin/starter.dart。
1.2 frontend参数表
前端编译器的可选参数:
参数 | 说明 | 默认值 | |
---|---|---|---|
aot | 在AOT模式下运行编译器(启用整个程序转换) | false | |
tfa | 在AOT模式下启用全局类型流分析和相关转换 | false | |
train | 通过示例命令行运行以生成快照 | false | |
incremental | 以增量模式运行编译器 | flase | |
link-platform | 批处理模式,平台kernel文件链接到结果的内核文件 | true | |
embed-source-text | 源码加入到生成的dill文件,便于得到用于调试的堆栈信息 | true | |
track-widget-creation | 运行内核转换器来跟踪widgets创建的位置 | false | |
strong | 已过时flags | true | |
import-dill | 从已存在的dill文件中引入库 | null | |
output-dill | 将生成的dill文件输出路径 | null | |
output-incremental-dill | 将生成的增量dill文件输出路径 | null | |
depfile | 仅用于批量,输出Ninja的depfile | ||
packages | 用于编译的.packages文件 | null | |
sdk-root | SDK根目录的路径 | ../../out/android_debug/flutter_patched_sdk | |
target | 确定哪些核心库可用,可取值vm、flutter、flutter_runner、dart_runner | vm |
- 增量模式运行编译器应该能加快编译速度
- track-widget-creation、aot、tfa参数的使用场景
1.3 frontend_server执行流程图
(1)点击查看大图
frontend_server前端编译器将dart代码转换为AST,并生成app.dill文件,其中bytecode生成过程默认是关闭的。
(2)点击查看大图
Component的成员变量:
- uriToSource的类型为Map<Uri, Source> ,用于从源文件URI映射到行开始表和源代码。给定一个源文件URI和该文件中的偏移量,就可以转换为该文件中line:column的位置。
二、 源码解读frontend_server
BuildAotCommand.runCommand
AOTSnapshotter.compileKernel
KernelCompiler.compile
frontend_server命令
2.1 starter.main
[-> flutter/frontend_server/bin/starter.dart]
void main(List<String> args) async {
final int exitCode = await starter(args);
...
}
2.2 server.starter
[-> flutter/frontend_server/lib/server.dart]
Future<int> starter(
List<String> args, {
frontend.CompilerInterface compiler,
Stream<List<int>> input,
StringSink output,
}) async {
...
//解析参数 [见小节2.2.1]
ArgResults options = frontend.argParser.parse(args);
//创建前端编译器实例对象
compiler ??= new _FlutterFrontendCompiler(output,
trackWidgetCreation: options['track-widget-creation'],
unsafePackageSerialization: options['unsafe-package-serialization']);
if (options.rest.isNotEmpty) {
//解析命令行的剩余参数 [见小节2.3]
return await compiler.compile(options.rest[0], options) ? 0 : 254;
}
...
}
该方法主要工作:
- 解析KernelCompiler.compile()方法中传递过来的参数,参数表小节[1.2]
- 创建前端编译器实例对象_FlutterFrontendCompiler;
- 执行编译操作;
2.3 _FlutterFrontendCompiler.compile
[-> flutter/frontend_server/lib/server.dart]
class _FlutterFrontendCompiler implements frontend.CompilerInterface{
final frontend.CompilerInterface _compiler;
_FlutterFrontendCompiler(StringSink output,
{bool trackWidgetCreation: false, bool unsafePackageSerialization}) :
//创建编译器对象
_compiler = new frontend.FrontendCompiler(output,
transformer: trackWidgetCreation ? new WidgetCreatorTracker() : null,
unsafePackageSerialization: unsafePackageSerialization);
Future<bool> compile(String filename, ArgResults options, {IncrementalCompiler generator}) async {
// filename是入口文件名 [见小节2.4]
return _compiler.compile(filename, options, generator: generator);
}
}
创建前端编译器实例对象_FlutterFrontendCompiler,其内部有一个重要的成员变量frontend.FrontendCompiler,该对象主要是在FrontendCompile功能的基础之上编译中添加了一个widgetCreatorTracker的内核转换器,所以核心工作都是交由FrontendCompiler来执行。
2.4 FrontendCompiler.compile
[-> third_party/dart/pkg/vm/lib/frontend_server.dart]
class FrontendCompiler implements CompilerInterface {
Future<bool> compile(String entryPoint, ArgResults options, {IncrementalCompiler generator,}) async {
_options = options;
_fileSystem = createFrontEndFileSystem(options['filesystem-scheme'], options['filesystem-root']);
//源码入口函数名,也就是lib/main.dart
_mainSource = _getFileOrUri(entryPoint);
_kernelBinaryFilenameFull = _options['output-dill'] ?? '$entryPoint.dill';
_kernelBinaryFilenameIncremental = _options['output-incremental-dill'] ??
(_options['output-dill'] != null
? '${_options['output-dill']}.incremental.dill'
: '$entryPoint.incremental.dill');
_kernelBinaryFilename = _kernelBinaryFilenameFull;
_initializeFromDill = _options['initialize-from-dill'] ?? _kernelBinaryFilenameFull;
final String boundaryKey = new Uuid().generateV4();
_outputStream.writeln('result $boundaryKey');
final Uri sdkRoot = _ensureFolderPath(options['sdk-root']);
final String platformKernelDill = options['platform'] ?? 'platform_strong.dill';
...
Component component;
if (options['incremental']) {
_compilerOptions = compilerOptions;
setVMEnvironmentDefines(environmentDefines, _compilerOptions);
_compilerOptions.omitPlatform = false;
_generator = generator ?? _createGenerator(new Uri.file(_initializeFromDill));
await invalidateIfInitializingFromDill();
component = await _runWithPrintRedirection(() => _generator.compile());
} else {
...
// [见小节2.5]
component = await _runWithPrintRedirection(() => compileToKernel(
_mainSource, compilerOptions,
aot: options['aot'],
useGlobalTypeFlowAnalysis: options['tfa'],
environmentDefines: environmentDefines));
}
if (component != null) {
if (transformer != null) {
transformer.transform(component);
}
//[见小节2.10] 写入dill文件
await writeDillFile(component, _kernelBinaryFilename,
filterExternal: importDill != null);
await _outputDependenciesDelta(component);
final String depfile = options['depfile'];
if (depfile != null) {
await writeDepfile(compilerOptions.fileSystem, component,
_kernelBinaryFilename, depfile);
}
_kernelBinaryFilename = _kernelBinaryFilenameIncremental;
}
return errors.isEmpty;
}
}
该方法主要功能:
- 执行compileToKernel,将dart转换为kernel文件,也就是中间语言文件;
- 再将中间数据写入app.dill文件
2.5 compileToKernel
[-> third_party/dart/pkg/vm/lib/kernel_front_end.dart]
Future<Component> compileToKernel(Uri source, CompilerOptions options,
{bool aot: false,
bool useGlobalTypeFlowAnalysis: false,
Map<String, String> environmentDefines,
bool genBytecode: false,
bool emitBytecodeSourcePositions: false,
bool emitBytecodeAnnotations: false,
bool dropAST: false,
bool useFutureBytecodeFormat: false,
bool enableAsserts: false,
bool enableConstantEvaluation: true,
bool useProtobufTreeShaker: false}) async {
//替代错误处理程序以检测是否存在编译错误
final errorDetector = new ErrorDetector(previousErrorHandler: options.onDiagnostic);
options.onDiagnostic = errorDetector;
setVMEnvironmentDefines(environmentDefines, options);
//将dart代码转换为component对象 [见小节2.6]
final component = await kernelForProgram(source, options);
if (aot && component != null) {
// 执行全局转换器 [见小节2.7]
await _runGlobalTransformations(
source,
options,
component,
useGlobalTypeFlowAnalysis,
environmentDefines,
enableAsserts,
enableConstantEvaluation,
useProtobufTreeShaker,
errorDetector);
}
if (genBytecode && !errorDetector.hasCompilationErrors && component != null) {
//生成字节码,genBytecode默认为false,不执行该操作 [见小节2.8]
await runWithFrontEndCompilerContext(source, options, component, () {
generateBytecode(component,
emitSourcePositions: emitBytecodeSourcePositions,
emitAnnotations: emitBytecodeAnnotations,
useFutureBytecodeFormat: useFutureBytecodeFormat,
environmentDefines: environmentDefines);
});
if (dropAST) {
new ASTRemover(component).visitComponent(component);
}
}
//恢复错误处理程序
options.onDiagnostic = errorDetector.previousErrorHandler;
return component;
}
该方法主要功能:
- kernelForProgram:将dart代码转换为component对象;
- _runGlobalTransformations:执行全局转换器;
- generateBytecode:默认genBytecode为false,AST不生成kernel字节码
2.6 kernelForProgram
[-> third_party/dart/pkg/front_end/lib/src/api_prototype/kernel_generator.dart]
Future<CompilerResult> kernelForProgram(
Uri source, CompilerOptions options) async {
return (await kernelForProgramInternal(source, options));
}
Future<CompilerResult> kernelForProgramInternal(
Uri source, CompilerOptions options,
{bool retainDataForTesting: false}) async {
var pOptions = new ProcessedOptions(options: options, inputs: [source]);
return await CompilerContext.runWithOptions(pOptions, (context) async {
//生成component [见小节2.6.1]
var component = (await generateKernelInternal())?.component;
if (component == null) return null;
// 输入source应该是包含main方法的脚步,否则将报告错误
if (component.mainMethod == null) {
context.options.report(
messageMissingMain.withLocation(source, -1, noLength),
Severity.error);
return null;
}
return component;
});
}
该方法的主要功能是将整个dart程序代码生成component对象。编译整个程序,生成程序的内核表示,该程序的主库位于给定的源码。 给定包含main方法的文件的Uri,通过该函数的import, export, part声明来发现整个程序,并将结果转换为Dart Kernel格式。 需要注意的是,当[options]中的compileSdk=true,则生成的组件将包含SDK代码。
Component的成员变量libraries,记录所有的lib库,包括app源文件、package以及三方库。每个Library对象会有Class、Field、procedure等组成。
2.6.1 generateKernelInternal
[-> third_party/dart/pkg/front_end/lib/src/kernel_generator_impl.dart]
Future<CompilerResult> generateKernelInternal(
{bool buildSummary: false,
bool buildComponent: true,
bool truncateSummary: false}) async {
var options = CompilerContext.current.options;
var fs = options.fileSystem;
Loader sourceLoader;
return withCrashReporting<CompilerResult>(() async {
UriTranslator uriTranslator = await options.getUriTranslator();
var dillTarget = new DillTarget(options.ticker, uriTranslator, options.target);
...
await dillTarget.buildOutlines();
//创建KernelTarget
var kernelTarget = new KernelTarget(fs, false, dillTarget, uriTranslator);
sourceLoader = kernelTarget.loader;
kernelTarget.setEntryPoints(options.inputs);
Component summaryComponent = await kernelTarget.buildOutlines(nameRoot: nameRoot);
if (buildSummary) {
...
}
Component component;
if (buildComponent) {
//[见小节2.6.2]
component = await kernelTarget.buildComponent(verify: options.verify);
}
...
return new InternalCompilerResult(
summary: summary,
component: component,
classHierarchy:
includeHierarchyAndCoreTypes ? kernelTarget.loader.hierarchy : null,
coreTypes:
includeHierarchyAndCoreTypes ? kernelTarget.loader.coreTypes : null,
deps: new List<Uri>.from(CompilerContext.current.dependencies),
kernelTargetForTesting: retainDataForTesting ? kernelTarget : null);
}, () => sourceLoader?.currentUriForCrashReporting ?? options.inputs.first);
}
2.6.2 buildComponent
[-> third_party/dart/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart]
class KernelTarget extends TargetImplementation {
Component component; //成员变量--组件
Future<Component> buildComponent({bool verify: false}) async {
if (loader.first == null) return null;
return withCrashReporting<Component>(() async {
//[见小节2.6.3]
await loader.buildBodies();
finishClonedParameters();
loader.finishDeferredLoadTearoffs();
loader.finishNoSuchMethodForwarders();
List<SourceClassBuilder> myClasses = collectMyClasses();
loader.finishNativeMethods();
loader.finishPatchMethods();
finishAllConstructors(myClasses);
runBuildTransformations();
if (verify) this.verify();
installAllComponentProblems(loader.allComponentProblems);
return component;
}, () => loader?.currentUriForCrashReporting);
}
}
KernelTarget的component记录整个dart代码的各种信息。
2.6.3 buildBodies
[-> third_party/dart/pkg/front_end/lib/src/fasta/loader.dart]
Future<Null> buildBodies() async {
for (LibraryBuilder library in builders.values) {
if (library.loader == this) {
currentUriForCrashReporting = library.uri;
//[见小节2.6.4]
await buildBody(library);
}
}
currentUriForCrashReporting = null;
logSummary(templateSourceBodySummary);
}
此处的loader为SourceLoader,是在KernelTarget对象创建过程初始化的。
2.6.4 buildBody
[-> third_party/dart/pkg/front_end/lib/src/fasta/source/source_loader.dart]
class SourceLoader extends Loader<Library> {
Future<Null> buildBody(LibraryBuilder library) async {
if (library is SourceLibraryBuilder) {
//词法分析
Token tokens = await tokenize(library, suppressLexicalErrors: true);
DietListener listener = createDietListener(library);
DietParser parser = new DietParser(listener);
//语法分析
parser.parseUnit(tokens);
for (SourceLibraryBuilder part in library.parts) {
if (part.partOfLibrary != library) {
// part部分包含在多个库中,此处跳过
continue;
}
Token tokens = await tokenize(part);
if (tokens != null) {
listener.uri = part.fileUri;
listener.partDirectiveIndex = 0;
parser.parseUnit(tokens);
}
}
}
}
}
该方法主要工作:
- 词法分析tokenize:对库中dart源码,根据一定的词法规则解析成词法单元tokens;
- 语法分析parser:对tokens根据Dart语法规则解析成抽象语法树;
说明,这个过程采用两次标记源文件,以保持较低的内存使用率。 这是第二次,第一次是在上面的[buildOutline]中,所以这抑制词法错误。
2.7 _runGlobalTransformations
[-> third_party/dart/pkg/vm/lib/kernel_front_end.dart]
Future _runGlobalTransformations(
Uri source,
CompilerOptions compilerOptions,
Component component,
bool useGlobalTypeFlowAnalysis,
Map<String, String> environmentDefines,
bool enableAsserts,
bool enableConstantEvaluation,
bool useProtobufTreeShaker,
ErrorDetector errorDetector) async {
if (errorDetector.hasCompilationErrors) return;
final coreTypes = new CoreTypes(component);
_patchVmConstants(coreTypes);
//mixin应用在前端创建mixin应用时,所有后端(以及从一开始就进行的所有转换)能都受益于mixin重复数据删除。
//AOT除外, JIT构建情况下,都需要运行此转换
mixin_deduplication.transformComponent(component);
if (enableConstantEvaluation) {
await _performConstantEvaluation(source, compilerOptions, component,
coreTypes, environmentDefines, enableAsserts);
if (errorDetector.hasCompilationErrors) return;
}
if (useGlobalTypeFlowAnalysis) {
globalTypeFlow.transformComponent(
compilerOptions.target, coreTypes, component);
} else {
devirtualization.transformComponent(coreTypes, component);
no_dynamic_invocations_annotator.transformComponent(component);
}
if (useProtobufTreeShaker) {
if (!useGlobalTypeFlowAnalysis) {
throw 'Protobuf tree shaker requires type flow analysis (--tfa)';
}
protobuf_tree_shaker.removeUnusedProtoReferences(
component, coreTypes, null);
globalTypeFlow.transformComponent(
compilerOptions.target, coreTypes, component);
}
// 避免通过从平台文件读取重新计算CSA
void ignoreAmbiguousSupertypes(cls, a, b) {}
final hierarchy = new ClassHierarchy(component,
onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
call_site_annotator.transformLibraries(
component, component.libraries, coreTypes, hierarchy);
// 不确定gen_snapshot是否要进行混淆处理,但是如果这样做,则需要混淆处理禁止。
obfuscationProhibitions.transformComponent(component, coreTypes);
}
执行混淆等转换工作
2.8 runWithFrontEndCompilerContext
[-> third_party/dart/pkg/vm/lib/kernel_front_end.dart]
Future<T> runWithFrontEndCompilerContext<T>(Uri source,
CompilerOptions compilerOptions, Component component, T action()) async {
final processedOptions =
new ProcessedOptions(options: compilerOptions, inputs: [source]);
//在上下文中运行,则可以获取uri源的tokens
return await CompilerContext.runWithOptions(processedOptions,
(CompilerContext context) async {
// 为了使fileUri / fileOffset->行/列映射,则需要预填充映射。
context.uriToSource.addAll(component.uriToSource);
//此处action对应的是generateBytecode()方法 [见小节2.8.1]
return action();
});
}
generateBytecode
BytecodeGenerator.visitLibrary(Library node)
visitList(node.procedures, BytecodeGenerator);
Procedure.accept(BytecodeGenerator);
BytecodeGenerator.visitProcedure(Procedure);
BytecodeGenerator.defaultMember(Procedure)
_genxxx
asm.emitPush
third_party/dart/pkg/vm/lib/bytecode/dbc.dart 中定义很多指令
2.8.1 generateBytecode
[-> third_party/dart/pkg/vm/lib/bytecode/gen_bytecode.dart]
void generateBytecode(
ast.Component component, {
bool emitSourcePositions: false,
bool emitAnnotations: false,
bool omitAssertSourcePositions: false,
bool useFutureBytecodeFormat: false,
Map<String, String> environmentDefines: const <String, String>{},
ErrorReporter errorReporter,
List<Library> libraries,
}) {
final coreTypes = new CoreTypes(component);
void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
final hierarchy = new ClassHierarchy(component,
onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
final constantsBackend = new VmConstantsBackend(coreTypes);
final errorReporter = new ForwardConstantEvaluationErrors();
//从component获取libraries
libraries ??= component.libraries;
//创建字节码生成器对象
final bytecodeGenerator = new BytecodeGenerator(
component,
coreTypes,
hierarchy,
typeEnvironment,
constantsBackend,
environmentDefines,
emitSourcePositions,
emitAnnotations,
omitAssertSourcePositions,
useFutureBytecodeFormat,
errorReporter);
for (var library in libraries) {
//[见小节2.8.2]
bytecodeGenerator.visitLibrary(library);
}
}
遍历component中的所有libraries。
2.8.2 visitLibrary
[-> third_party/dart/pkg/vm/lib/bytecode/gen_bytecode.dart]
class BytecodeGenerator extends RecursiveVisitor<Null> {
visitLibrary(Library node) {
if (node.isExternal) {
return;
}
//对于class的visit会调用到下方的visitClass
visitList(node.classes, this);
//初始化fieldDeclarations和functionDeclarations来记录类的字段和方法
startMembers();
// [见小节2.8.3]
visitList(node.procedures, this);
visitList(node.fields, this);
endMembers(node);
}
visitClass(Class node) {
startMembers();
visitList(node.constructors, this);
visitList(node.procedures, this);
visitList(node.fields, this);
endMembers(node);
}
}
该方法主要功能:
- 通过visitList来访问库中的classes,procedures,fields。
- 先访问类中的构造函数constructors、方法procedures以及字段fields;
- 再访问库中不属于任何类的一些方法和字段;
- fieldDeclarations和functionDeclarations来记录类的字段和方法,最终保存在bytecodeComponent的成员变量members;
2.8.3 visitList
[-> third_party/dart/pkg/kernel/lib/ast.dart]
void visitList(List<Node> nodes, Visitor visitor) {
for (int i = 0; i < nodes.length; ++i) {
// [见小节2.8.4]
nodes[i].accept(visitor);
}
}
该方法说明:
- 此处的nodes,可以是classes,constructors,procedures或者fields
- 此处的visitor,便是BytecodeGenerator
2.8.4 accept
[-> third_party/dart/pkg/kernel/lib/ast.dart]
class Procedure extends Member {
accept(MemberVisitor v) => v.visitProcedure(this);
}
class Field extends Member {
R accept<R>(MemberVisitor<R> v) => v.visitField(this);
}
class Constructor extends Member {
R accept<R>(MemberVisitor<R> v) => v.visitConstructor(this);
}
此处的v是BytecodeGenerator,而BytecodeGenerator间接继承于TreeVisitor,在TreeVisitor由大量的visitXXX()方法,最终都是调用到defaultMember(),如下所示。
class TreeVisitor<R> {
// [见小节2.8.5]
R visitConstructor(Constructor node) => defaultMember(node);
R visitProcedure(Procedure node) => defaultMember(node);
R visitField(Field node) => defaultMember(node);
}
2.8.5 defaultMember
[-> third_party/dart/pkg/vm/lib/bytecode/gen_bytecode.dart]
defaultMember(Member node) {
// 当该方法表示重定向工厂构造函数,并且没有可运行的主体,则直接返回
if (node is Procedure && node.isRedirectingFactoryConstructor) {
return;
}
try {
bool hasCode = false;
start(node);
//字段类型
if (node is Field) {
if (hasInitializerCode(node)) {
hasCode = true;
if (node.isConst) {
_genPushConstExpr(node.initializer);
} else {
_generateNode(node.initializer);
}
_genReturnTOS();
}
//方法类型
} else if ((node is Procedure && !node.isRedirectingFactoryConstructor) ||
(node is Constructor)) {
if (!node.isAbstract) {
hasCode = true;
if (node is Constructor) {
_genConstructorInitializers(node);
}
if (node.isExternal) {
final String nativeName = getExternalName(node);
if (nativeName != null) {
_genNativeCall(nativeName);
} else {
asm.emitPushNull();
}
} else {
_generateNode(node.function?.body);
// 如果无法访问此字节码,则BytecodeAssembler会将其消除。
asm.emitPushNull();
}
_genReturnTOS();
}
} else {
throw 'Unexpected member ${node.runtimeType} $node';
}
end(node, hasCode);
} on BytecodeLimitExceededException {
// 不生成字节码,回滚到内核语法树AST
hasErrors = true;
end(node, false);
}
}
该方法主要功能是 根据node类型:字段、方法或者构造方法,则生成相应的汇编指令。 这里会有很多_genXXX()方法,最终是调用asm.emitXXX()方法, 此处的asm的数据类型为BytecodeAssembler。 接下来以emitPushNull为例子,继续往下说。
2.8.6 emitPushNull
[-> third_party/dart/pkg/vm/lib/bytecode/assembler.dart]
class BytecodeAssembler {
final List<int> bytecode = new List<int>();
final Uint32List _encodeBufferIn;
final Uint8List _encodeBufferOut;
void emitPushNull() {
emitWord(_encode0(Opcode.kPushNull));
}
void emitWord(int word) {
if (isUnreachable) {
return;
}
_encodeBufferIn[0] = word; //opcode写入_encodeBufferIn
bytecode.addAll(_encodeBufferOut);
}
//将操作码转换整型
int _encode0(Opcode opcode) => _uint8(opcode.index);
...
}
可见,所有的字节码信息最终都写入到BytecodeAssembler的bytecode列表。另外,Opcode操作码位于dbc.dart,里面定义了各种操作码。
2.9 writeDillFile
[-> third_party/dart/pkg/vm/lib/frontend_server.dart]
writeDillFile(Component component, String filename,
{bool filterExternal: false}) async {
final IOSink sink = new File(filename).openWrite();
final BinaryPrinter printer = filterExternal
? new LimitedBinaryPrinter(
sink, (lib) => !lib.isExternal, true /* excludeUriToSource */)
: printerFactory.newBinaryPrinter(sink);
component.libraries.sort((Library l1, Library l2) {
return "${l1.fileUri}".compareTo("${l2.fileUri}");
});
component.computeCanonicalNames();
for (Library library in component.libraries) {
library.additionalExports.sort((Reference r1, Reference r2) {
return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
});
}
if (unsafePackageSerialization == true) {
writePackagesToSinkAndTrimComponent(component, sink);
}
//[见小节2.9.1]
printer.writeComponentFile(component);
await sink.close();
}
再回到[小节2.4],执行完compileToKernel()后开始执行writeDillFile,该方法主要功能便是将component内容写入app.dill文件。
- component:是指compileToKernel()方法执行后得到的,记录dart代码中类、方法、字段等所有相关信息
- filename:是指前面传递–output-dill参数值,也就是app.dill
2.9.1 writeComponentFile
[-> third_party/dart/pkg/kernel/lib/binary/ast_to_binary.dart]
void writeComponentFile(Component component) {
computeCanonicalNames(component);
final componentOffset = getBufferOffset();
writeUInt32(Tag.ComponentFile);
writeUInt32(Tag.BinaryFormatVersion);
writeListOfStrings(component.problemsAsJson);
indexLinkTable(component);
_collectMetadata(component);
if (_metadataSubsections != null) {
// 将asm.bytecode写入文件
_writeNodeMetadataImpl(component, componentOffset);
}
libraryOffsets = <int>[];
CanonicalName main = getCanonicalNameOfMember(component.mainMethod);
if (main != null) {
checkCanonicalName(main);
}
writeLibraries(component);
writeUriToSource(component.uriToSource);
writeLinkTable(component);
_writeMetadataSection(component);
writeStringTable(stringIndexer);
writeConstantTable(_constantIndexer);
writeComponentIndex(component, component.libraries);
_flush();
}
这便完成的kernel编译以及文件生成过程。
附录
本文相关源码flutter engine
flutter/frontend_server/
- bin/starter.dart
- lib/server.dart
third_party/dart/pkg/
- vm/lib/
- frontend_server.dart
- kernel_front_end.dart
- bytecode/gen_bytecode.dart
- bytecode/assembler.dart
- front_end/lib/
- src/api_prototype/kernel_generator.dart
- src/kernel_generator_impl.dart
- src/fasta/kernel/kernel_target.dart
- src/fasta/loader.dart
- src/fasta/source/source_loader.dart
- kernel/lib/
- ast.dart
- binary/ast_to_binary.dart
微信公众号 Gityuan | 微博 weibo.com/gityuan | 博客 留言区交流