Unverified Commit 42ed0152 authored by Chris Bracken's avatar Chris Bracken Committed by GitHub

Split Snapshotter into AOT and Script classes (#17159)

There's very little code-sharing between the two, and what little there
is is concentrated in the GenSnapshotClass and the fingerprint
reading/writing utility methods.
parent 28c19733
...@@ -166,9 +166,9 @@ Future<Set<String>> readDepfile(String depfilePath) async { ...@@ -166,9 +166,9 @@ Future<Set<String>> readDepfile(String depfilePath) async {
/// suitable for loading with `mmap`. /// suitable for loading with `mmap`.
/// * Assembly AOT snapshot: architecture-specific ahead-of-time compile to /// * Assembly AOT snapshot: architecture-specific ahead-of-time compile to
/// assembly suitable for compilation as a static or dynamic library. /// assembly suitable for compilation as a static or dynamic library.
class Snapshotter { class ScriptSnapshotter {
/// Builds an architecture-independent snapshot of the specified script. /// Builds an architecture-independent snapshot of the specified script.
Future<int> buildScriptSnapshot({ Future<int> build({
@required String mainPath, @required String mainPath,
@required String snapshotPath, @required String snapshotPath,
@required String depfilePath, @required String depfilePath,
...@@ -206,51 +206,11 @@ class Snapshotter { ...@@ -206,51 +206,11 @@ class Snapshotter {
await _writeFingerprint(snapshotType, outputPaths, depfilePath, mainPath, fingerprintPath); await _writeFingerprint(snapshotType, outputPaths, depfilePath, mainPath, fingerprintPath);
return exitCode; return exitCode;
} }
}
/// Compiles a Dart file to kernel. class AOTSnapshotter {
///
/// Returns the output kernel file path, or null on failure.
Future<String> compileKernel({
@required TargetPlatform platform,
@required BuildMode buildMode,
@required String mainPath,
@required String outputPath,
List<String> extraFrontEndOptions: const <String>[],
}) async {
final Directory outputDir = fs.directory(outputPath);
outputDir.createSync(recursive: true);
printTrace('Compiling Dart to kernel: $mainPath');
final List<String> entryPointsJsonFiles = <String>[
artifacts.getArtifactPath(Artifact.entryPointsJson, platform, buildMode),
artifacts.getArtifactPath(Artifact.entryPointsExtraJson, platform, buildMode),
];
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
printTrace('Extra front-end options: $extraFrontEndOptions');
final String depfilePath = fs.path.join(outputPath, 'kernel_compile.d');
final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
mainPath: mainPath,
outputFilePath: fs.path.join(outputPath, 'app.dill'),
depFilePath: depfilePath,
extraFrontEndOptions: extraFrontEndOptions,
linkPlatformKernelIn: true,
aot: true,
entryPointsJsonFiles: entryPointsJsonFiles,
trackWidgetCreation: false,
);
// Write path to frontend_server, since things need to be re-generated when that changes.
final String frontendPath = artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk);
await fs.directory(outputPath).childFile('frontend_server.d').writeAsString('frontend_server.d: $frontendPath\n');
return compilerOutput?.outputFilename;
}
/// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script. /// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script.
Future<int> buildAotSnapshot({ Future<int> build({
@required TargetPlatform platform, @required TargetPlatform platform,
@required BuildMode buildMode, @required BuildMode buildMode,
@required String mainPath, @required String mainPath,
...@@ -415,6 +375,48 @@ class Snapshotter { ...@@ -415,6 +375,48 @@ class Snapshotter {
return 0; return 0;
} }
/// Compiles a Dart file to kernel.
///
/// Returns the output kernel file path, or null on failure.
Future<String> compileKernel({
@required TargetPlatform platform,
@required BuildMode buildMode,
@required String mainPath,
@required String outputPath,
List<String> extraFrontEndOptions: const <String>[],
}) async {
final Directory outputDir = fs.directory(outputPath);
outputDir.createSync(recursive: true);
printTrace('Compiling Dart to kernel: $mainPath');
final List<String> entryPointsJsonFiles = <String>[
artifacts.getArtifactPath(Artifact.entryPointsJson, platform, buildMode),
artifacts.getArtifactPath(Artifact.entryPointsExtraJson, platform, buildMode),
];
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
printTrace('Extra front-end options: $extraFrontEndOptions');
final String depfilePath = fs.path.join(outputPath, 'kernel_compile.d');
final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
mainPath: mainPath,
outputFilePath: fs.path.join(outputPath, 'app.dill'),
depFilePath: depfilePath,
extraFrontEndOptions: extraFrontEndOptions,
linkPlatformKernelIn: true,
aot: true,
entryPointsJsonFiles: entryPointsJsonFiles,
trackWidgetCreation: false,
);
// Write path to frontend_server, since things need to be re-generated when that changes.
final String frontendPath = artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk);
await fs.directory(outputPath).childFile('frontend_server.d').writeAsString('frontend_server.d: $frontendPath\n');
return compilerOutput?.outputFilename;
}
bool _isValidAotPlatform(TargetPlatform platform, BuildMode buildMode) { bool _isValidAotPlatform(TargetPlatform platform, BuildMode buildMode) {
if (platform == TargetPlatform.ios && buildMode == BuildMode.debug) if (platform == TargetPlatform.ios && buildMode == BuildMode.debug)
return false; return false;
...@@ -428,8 +430,9 @@ class Snapshotter { ...@@ -428,8 +430,9 @@ class Snapshotter {
String _getPackagePath(PackageMap packageMap, String package) { String _getPackagePath(PackageMap packageMap, String package) {
return fs.path.dirname(fs.path.fromUri(packageMap.map[package])); return fs.path.dirname(fs.path.fromUri(packageMap.map[package]));
} }
}
Future<bool> _isBuildRequired(SnapshotType type, Set<String> outputPaths, String depfilePath, String mainPath, String fingerprintPath) async { Future<bool> _isBuildRequired(SnapshotType type, Set<String> outputPaths, String depfilePath, String mainPath, String fingerprintPath) async {
final File fingerprintFile = fs.file(fingerprintPath); final File fingerprintFile = fs.file(fingerprintPath);
final List<String> requiredFiles = <String>[fingerprintPath, depfilePath]..addAll(outputPaths); final List<String> requiredFiles = <String>[fingerprintPath, depfilePath]..addAll(outputPaths);
if (!requiredFiles.every(fs.isFileSync)) if (!requiredFiles.every(fs.isFileSync))
...@@ -447,9 +450,9 @@ class Snapshotter { ...@@ -447,9 +450,9 @@ class Snapshotter {
printTrace('Rebuilding snapshot due to fingerprint check error: $e'); printTrace('Rebuilding snapshot due to fingerprint check error: $e');
} }
return true; return true;
} }
Future<Null> _writeFingerprint(SnapshotType type, Set<String> outputPaths, String depfilePath, String mainPath, String fingerprintPath) async { Future<Null> _writeFingerprint(SnapshotType type, Set<String> outputPaths, String depfilePath, String mainPath, String fingerprintPath) async {
try { try {
final Set<String> inputFilePaths = await readDepfile(depfilePath) final Set<String> inputFilePaths = await readDepfile(depfilePath)
..add(mainPath) ..add(mainPath)
...@@ -460,9 +463,9 @@ class Snapshotter { ...@@ -460,9 +463,9 @@ class Snapshotter {
// Log exception and continue, this step is a performance improvement only. // Log exception and continue, this step is a performance improvement only.
printStatus('Error during snapshot fingerprinting: $e\n$s'); printStatus('Error during snapshot fingerprinting: $e\n$s');
} }
} }
static Fingerprint createFingerprint(SnapshotType type, String mainPath, Iterable<String> inputFilePaths) { Fingerprint createFingerprint(SnapshotType type, String mainPath, Iterable<String> inputFilePaths) {
final Map<String, String> properties = <String, String>{ final Map<String, String> properties = <String, String>{
'buildMode': type.mode.toString(), 'buildMode': type.mode.toString(),
'targetPlatform': type.platform?.toString() ?? '', 'targetPlatform': type.platform?.toString() ?? '',
...@@ -472,5 +475,4 @@ class Snapshotter { ...@@ -472,5 +475,4 @@ class Snapshotter {
..add(artifacts.getArtifactPath(Artifact.vmSnapshotData)) ..add(artifacts.getArtifactPath(Artifact.vmSnapshotData))
..add(artifacts.getArtifactPath(Artifact.isolateSnapshotData)); ..add(artifacts.getArtifactPath(Artifact.isolateSnapshotData));
return new Fingerprint.fromBuildInputs(properties, pathsWithSnapshotData); return new Fingerprint.fromBuildInputs(properties, pathsWithSnapshotData);
}
} }
...@@ -56,8 +56,7 @@ Future<void> build({ ...@@ -56,8 +56,7 @@ Future<void> build({
// In a precompiled snapshot, the instruction buffer contains script // In a precompiled snapshot, the instruction buffer contains script
// content equivalents // content equivalents
final Snapshotter snapshotter = new Snapshotter(); final int result = await new ScriptSnapshotter().build(
final int result = await snapshotter.buildScriptSnapshot(
mainPath: mainPath, mainPath: mainPath,
snapshotPath: snapshotPath, snapshotPath: snapshotPath,
depfilePath: depfilePath, depfilePath: depfilePath,
......
...@@ -72,7 +72,7 @@ class BuildAotCommand extends BuildSubCommand { ...@@ -72,7 +72,7 @@ class BuildAotCommand extends BuildSubCommand {
try { try {
final bool previewDart2 = argResults['preview-dart-2']; final bool previewDart2 = argResults['preview-dart-2'];
String mainPath = findMainDartFile(targetFile); String mainPath = findMainDartFile(targetFile);
final Snapshotter snapshotter = new Snapshotter(); final AOTSnapshotter snapshotter = new AOTSnapshotter();
// Compile to kernel, if Dart 2. // Compile to kernel, if Dart 2.
if (previewDart2) { if (previewDart2) {
...@@ -90,7 +90,7 @@ class BuildAotCommand extends BuildSubCommand { ...@@ -90,7 +90,7 @@ class BuildAotCommand extends BuildSubCommand {
} }
// Build AOT snapshot. // Build AOT snapshot.
final int snapshotExitCode = await snapshotter.buildAotSnapshot( final int snapshotExitCode = await snapshotter.build(
platform: platform, platform: platform,
buildMode: buildMode, buildMode: buildMode,
mainPath: mainPath, mainPath: mainPath,
......
...@@ -335,7 +335,7 @@ void main() { ...@@ -335,7 +335,7 @@ void main() {
_FakeGenSnapshot genSnapshot; _FakeGenSnapshot genSnapshot;
MemoryFileSystem fs; MemoryFileSystem fs;
MockFlutterVersion mockVersion; MockFlutterVersion mockVersion;
Snapshotter snapshotter; ScriptSnapshotter snapshotter;
MockArtifacts mockArtifacts; MockArtifacts mockArtifacts;
setUp(() { setUp(() {
...@@ -349,7 +349,7 @@ void main() { ...@@ -349,7 +349,7 @@ void main() {
}; };
mockVersion = new MockFlutterVersion(); mockVersion = new MockFlutterVersion();
when(mockVersion.frameworkRevision).thenReturn(kVersion); when(mockVersion.frameworkRevision).thenReturn(kVersion);
snapshotter = new Snapshotter(); snapshotter = new ScriptSnapshotter();
mockArtifacts = new MockArtifacts(); mockArtifacts = new MockArtifacts();
when(mockArtifacts.getArtifactPath(Artifact.isolateSnapshotData)).thenReturn(kIsolateSnapshotData); when(mockArtifacts.getArtifactPath(Artifact.isolateSnapshotData)).thenReturn(kIsolateSnapshotData);
when(mockArtifacts.getArtifactPath(Artifact.vmSnapshotData)).thenReturn(kVmSnapshotData); when(mockArtifacts.getArtifactPath(Artifact.vmSnapshotData)).thenReturn(kVmSnapshotData);
...@@ -395,7 +395,7 @@ void main() { ...@@ -395,7 +395,7 @@ void main() {
await fs.file('main.dart').writeAsString('void main() {}'); await fs.file('main.dart').writeAsString('void main() {}');
await fs.file('output.snapshot').create(); await fs.file('output.snapshot').create();
await fs.file('output.snapshot.d').writeAsString('snapshot : main.dart'); await fs.file('output.snapshot.d').writeAsString('snapshot : main.dart');
await snapshotter.buildScriptSnapshot( await snapshotter.build(
mainPath: 'main.dart', mainPath: 'main.dart',
snapshotPath: 'output.snapshot', snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d', depfilePath: 'output.snapshot.d',
...@@ -429,7 +429,7 @@ void main() { ...@@ -429,7 +429,7 @@ void main() {
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
'output.snapshot': 'deadbeef000b204e9800998ecaaaaa', 'output.snapshot': 'deadbeef000b204e9800998ecaaaaa',
}); });
await snapshotter.buildScriptSnapshot( await snapshotter.build(
mainPath: 'main.dart', mainPath: 'main.dart',
snapshotPath: 'output.snapshot', snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d', depfilePath: 'output.snapshot.d',
...@@ -450,7 +450,7 @@ void main() { ...@@ -450,7 +450,7 @@ void main() {
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
}); });
await snapshotter.buildScriptSnapshot( await snapshotter.build(
mainPath: 'main.dart', mainPath: 'main.dart',
snapshotPath: 'output.snapshot', snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d', depfilePath: 'output.snapshot.d',
...@@ -479,7 +479,7 @@ void main() { ...@@ -479,7 +479,7 @@ void main() {
'output.snapshot.d': 'output.snapshot : main.dart other.dart', 'output.snapshot.d': 'output.snapshot : main.dart other.dart',
}; };
await snapshotter.buildScriptSnapshot( await snapshotter.build(
mainPath: 'other.dart', mainPath: 'other.dart',
snapshotPath: 'output.snapshot', snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d', depfilePath: 'output.snapshot.d',
...@@ -505,7 +505,7 @@ void main() { ...@@ -505,7 +505,7 @@ void main() {
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
}); });
await snapshotter.buildScriptSnapshot( await snapshotter.build(
mainPath: 'main.dart', mainPath: 'main.dart',
snapshotPath: 'output.snapshot', snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d', depfilePath: 'output.snapshot.d',
...@@ -529,7 +529,7 @@ void main() { ...@@ -529,7 +529,7 @@ void main() {
kIsolateSnapshotData, kIsolateSnapshotData,
]; ];
testUsingContext('creates fingerprint with target platform', () { testUsingContext('creates fingerprint with target platform', () {
final Fingerprint fingerprint = Snapshotter.createFingerprint( final Fingerprint fingerprint = createFingerprint(
new SnapshotType(TargetPlatform.android_x64, BuildMode.release), new SnapshotType(TargetPlatform.android_x64, BuildMode.release),
'a.dart', 'a.dart',
<String>[], <String>[],
...@@ -541,7 +541,7 @@ void main() { ...@@ -541,7 +541,7 @@ void main() {
}, artifactPaths)); }, artifactPaths));
}, overrides: contextOverrides); }, overrides: contextOverrides);
testUsingContext('creates fingerprint without target platform', () { testUsingContext('creates fingerprint without target platform', () {
final Fingerprint fingerprint = Snapshotter.createFingerprint( final Fingerprint fingerprint = createFingerprint(
new SnapshotType(null, BuildMode.release), new SnapshotType(null, BuildMode.release),
'a.dart', 'a.dart',
<String>[], <String>[],
...@@ -555,7 +555,7 @@ void main() { ...@@ -555,7 +555,7 @@ void main() {
testUsingContext('creates fingerprint with file checksums', () async { testUsingContext('creates fingerprint with file checksums', () async {
await fs.file('a.dart').create(); await fs.file('a.dart').create();
await fs.file('b.dart').create(); await fs.file('b.dart').create();
final Fingerprint fingerprint = Snapshotter.createFingerprint( final Fingerprint fingerprint = createFingerprint(
new SnapshotType(TargetPlatform.android_x64, BuildMode.release), new SnapshotType(TargetPlatform.android_x64, BuildMode.release),
'a.dart', 'a.dart',
<String>['a.dart', 'b.dart'], <String>['a.dart', 'b.dart'],
...@@ -582,7 +582,7 @@ void main() { ...@@ -582,7 +582,7 @@ void main() {
_FakeGenSnapshot genSnapshot; _FakeGenSnapshot genSnapshot;
MemoryFileSystem fs; MemoryFileSystem fs;
Snapshotter snapshotter; AOTSnapshotter snapshotter;
MockArtifacts mockArtifacts; MockArtifacts mockArtifacts;
MockXcode mockXcode; MockXcode mockXcode;
...@@ -603,7 +603,7 @@ void main() { ...@@ -603,7 +603,7 @@ void main() {
fs.file(fs.path.join(skyEnginePath, 'sdk_ext', 'vmservice_io.dart')).createSync(); fs.file(fs.path.join(skyEnginePath, 'sdk_ext', 'vmservice_io.dart')).createSync();
genSnapshot = new _FakeGenSnapshot(); genSnapshot = new _FakeGenSnapshot();
snapshotter = new Snapshotter(); snapshotter = new AOTSnapshotter();
mockArtifacts = new MockArtifacts(); mockArtifacts = new MockArtifacts();
mockXcode = new MockXcode(); mockXcode = new MockXcode();
for (BuildMode mode in BuildMode.values) { for (BuildMode mode in BuildMode.values) {
...@@ -624,7 +624,7 @@ void main() { ...@@ -624,7 +624,7 @@ void main() {
testUsingContext('iOS debug AOT snapshot is invalid', () async { testUsingContext('iOS debug AOT snapshot is invalid', () async {
final String outputPath = fs.path.join('build', 'foo'); final String outputPath = fs.path.join('build', 'foo');
expect(await snapshotter.buildAotSnapshot( expect(await snapshotter.build(
platform: TargetPlatform.ios, platform: TargetPlatform.ios,
buildMode: BuildMode.debug, buildMode: BuildMode.debug,
mainPath: 'main.dill', mainPath: 'main.dill',
...@@ -646,7 +646,7 @@ void main() { ...@@ -646,7 +646,7 @@ void main() {
fs.path.join(outputPath, 'snapshot.d'): '', fs.path.join(outputPath, 'snapshot.d'): '',
}; };
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot( final int genSnapshotExitCode = await snapshotter.build(
platform: TargetPlatform.ios, platform: TargetPlatform.ios,
buildMode: BuildMode.profile, buildMode: BuildMode.profile,
mainPath: 'main.dill', mainPath: 'main.dill',
...@@ -690,7 +690,7 @@ void main() { ...@@ -690,7 +690,7 @@ void main() {
fs.path.join(outputPath, 'snapshot.d'): '', fs.path.join(outputPath, 'snapshot.d'): '',
}; };
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot( final int genSnapshotExitCode = await snapshotter.build(
platform: TargetPlatform.ios, platform: TargetPlatform.ios,
buildMode: BuildMode.release, buildMode: BuildMode.release,
mainPath: 'main.dill', mainPath: 'main.dill',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment