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 {
/// suitable for loading with `mmap`.
/// * Assembly AOT snapshot: architecture-specific ahead-of-time compile to
/// assembly suitable for compilation as a static or dynamic library.
class Snapshotter {
class ScriptSnapshotter {
/// Builds an architecture-independent snapshot of the specified script.
Future<int> buildScriptSnapshot({
Future<int> build({
@required String mainPath,
@required String snapshotPath,
@required String depfilePath,
......@@ -206,51 +206,11 @@ class Snapshotter {
await _writeFingerprint(snapshotType, outputPaths, depfilePath, mainPath, fingerprintPath);
return exitCode;
}
}
/// 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;
}
class AOTSnapshotter {
/// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script.
Future<int> buildAotSnapshot({
Future<int> build({
@required TargetPlatform platform,
@required BuildMode buildMode,
@required String mainPath,
......@@ -415,6 +375,48 @@ class Snapshotter {
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) {
if (platform == TargetPlatform.ios && buildMode == BuildMode.debug)
return false;
......@@ -428,49 +430,49 @@ class Snapshotter {
String _getPackagePath(PackageMap packageMap, String 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 {
final File fingerprintFile = fs.file(fingerprintPath);
final List<String> requiredFiles = <String>[fingerprintPath, depfilePath]..addAll(outputPaths);
if (!requiredFiles.every(fs.isFileSync))
return true;
try {
if (fingerprintFile.existsSync()) {
final Fingerprint oldFingerprint = new Fingerprint.fromJson(await fingerprintFile.readAsString());
final Set<String> inputFilePaths = await readDepfile(depfilePath)..add(mainPath)..addAll(outputPaths);
final Fingerprint newFingerprint = createFingerprint(type, mainPath, inputFilePaths);
return oldFingerprint != newFingerprint;
}
} catch (e) {
// Log exception and continue, this step is a performance improvement only.
printTrace('Rebuilding snapshot due to fingerprint check error: $e');
}
Future<bool> _isBuildRequired(SnapshotType type, Set<String> outputPaths, String depfilePath, String mainPath, String fingerprintPath) async {
final File fingerprintFile = fs.file(fingerprintPath);
final List<String> requiredFiles = <String>[fingerprintPath, depfilePath]..addAll(outputPaths);
if (!requiredFiles.every(fs.isFileSync))
return true;
}
Future<Null> _writeFingerprint(SnapshotType type, Set<String> outputPaths, String depfilePath, String mainPath, String fingerprintPath) async {
try {
final Set<String> inputFilePaths = await readDepfile(depfilePath)
..add(mainPath)
..addAll(outputPaths);
final Fingerprint fingerprint = createFingerprint(type, mainPath, inputFilePaths);
await fs.file(fingerprintPath).writeAsString(fingerprint.toJson());
} catch (e, s) {
// Log exception and continue, this step is a performance improvement only.
printStatus('Error during snapshot fingerprinting: $e\n$s');
try {
if (fingerprintFile.existsSync()) {
final Fingerprint oldFingerprint = new Fingerprint.fromJson(await fingerprintFile.readAsString());
final Set<String> inputFilePaths = await readDepfile(depfilePath)..add(mainPath)..addAll(outputPaths);
final Fingerprint newFingerprint = createFingerprint(type, mainPath, inputFilePaths);
return oldFingerprint != newFingerprint;
}
} catch (e) {
// Log exception and continue, this step is a performance improvement only.
printTrace('Rebuilding snapshot due to fingerprint check error: $e');
}
return true;
}
static Fingerprint createFingerprint(SnapshotType type, String mainPath, Iterable<String> inputFilePaths) {
final Map<String, String> properties = <String, String>{
'buildMode': type.mode.toString(),
'targetPlatform': type.platform?.toString() ?? '',
'entryPoint': mainPath,
};
final List<String> pathsWithSnapshotData = inputFilePaths.toList()
..add(artifacts.getArtifactPath(Artifact.vmSnapshotData))
..add(artifacts.getArtifactPath(Artifact.isolateSnapshotData));
return new Fingerprint.fromBuildInputs(properties, pathsWithSnapshotData);
Future<Null> _writeFingerprint(SnapshotType type, Set<String> outputPaths, String depfilePath, String mainPath, String fingerprintPath) async {
try {
final Set<String> inputFilePaths = await readDepfile(depfilePath)
..add(mainPath)
..addAll(outputPaths);
final Fingerprint fingerprint = createFingerprint(type, mainPath, inputFilePaths);
await fs.file(fingerprintPath).writeAsString(fingerprint.toJson());
} catch (e, s) {
// Log exception and continue, this step is a performance improvement only.
printStatus('Error during snapshot fingerprinting: $e\n$s');
}
}
Fingerprint createFingerprint(SnapshotType type, String mainPath, Iterable<String> inputFilePaths) {
final Map<String, String> properties = <String, String>{
'buildMode': type.mode.toString(),
'targetPlatform': type.platform?.toString() ?? '',
'entryPoint': mainPath,
};
final List<String> pathsWithSnapshotData = inputFilePaths.toList()
..add(artifacts.getArtifactPath(Artifact.vmSnapshotData))
..add(artifacts.getArtifactPath(Artifact.isolateSnapshotData));
return new Fingerprint.fromBuildInputs(properties, pathsWithSnapshotData);
}
......@@ -56,8 +56,7 @@ Future<void> build({
// In a precompiled snapshot, the instruction buffer contains script
// content equivalents
final Snapshotter snapshotter = new Snapshotter();
final int result = await snapshotter.buildScriptSnapshot(
final int result = await new ScriptSnapshotter().build(
mainPath: mainPath,
snapshotPath: snapshotPath,
depfilePath: depfilePath,
......
......@@ -72,7 +72,7 @@ class BuildAotCommand extends BuildSubCommand {
try {
final bool previewDart2 = argResults['preview-dart-2'];
String mainPath = findMainDartFile(targetFile);
final Snapshotter snapshotter = new Snapshotter();
final AOTSnapshotter snapshotter = new AOTSnapshotter();
// Compile to kernel, if Dart 2.
if (previewDart2) {
......@@ -90,7 +90,7 @@ class BuildAotCommand extends BuildSubCommand {
}
// Build AOT snapshot.
final int snapshotExitCode = await snapshotter.buildAotSnapshot(
final int snapshotExitCode = await snapshotter.build(
platform: platform,
buildMode: buildMode,
mainPath: mainPath,
......
......@@ -335,7 +335,7 @@ void main() {
_FakeGenSnapshot genSnapshot;
MemoryFileSystem fs;
MockFlutterVersion mockVersion;
Snapshotter snapshotter;
ScriptSnapshotter snapshotter;
MockArtifacts mockArtifacts;
setUp(() {
......@@ -349,7 +349,7 @@ void main() {
};
mockVersion = new MockFlutterVersion();
when(mockVersion.frameworkRevision).thenReturn(kVersion);
snapshotter = new Snapshotter();
snapshotter = new ScriptSnapshotter();
mockArtifacts = new MockArtifacts();
when(mockArtifacts.getArtifactPath(Artifact.isolateSnapshotData)).thenReturn(kIsolateSnapshotData);
when(mockArtifacts.getArtifactPath(Artifact.vmSnapshotData)).thenReturn(kVmSnapshotData);
......@@ -395,7 +395,7 @@ void main() {
await fs.file('main.dart').writeAsString('void main() {}');
await fs.file('output.snapshot').create();
await fs.file('output.snapshot.d').writeAsString('snapshot : main.dart');
await snapshotter.buildScriptSnapshot(
await snapshotter.build(
mainPath: 'main.dart',
snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d',
......@@ -429,7 +429,7 @@ void main() {
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
'output.snapshot': 'deadbeef000b204e9800998ecaaaaa',
});
await snapshotter.buildScriptSnapshot(
await snapshotter.build(
mainPath: 'main.dart',
snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d',
......@@ -450,7 +450,7 @@ void main() {
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
});
await snapshotter.buildScriptSnapshot(
await snapshotter.build(
mainPath: 'main.dart',
snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d',
......@@ -479,7 +479,7 @@ void main() {
'output.snapshot.d': 'output.snapshot : main.dart other.dart',
};
await snapshotter.buildScriptSnapshot(
await snapshotter.build(
mainPath: 'other.dart',
snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d',
......@@ -505,7 +505,7 @@ void main() {
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
});
await snapshotter.buildScriptSnapshot(
await snapshotter.build(
mainPath: 'main.dart',
snapshotPath: 'output.snapshot',
depfilePath: 'output.snapshot.d',
......@@ -529,7 +529,7 @@ void main() {
kIsolateSnapshotData,
];
testUsingContext('creates fingerprint with target platform', () {
final Fingerprint fingerprint = Snapshotter.createFingerprint(
final Fingerprint fingerprint = createFingerprint(
new SnapshotType(TargetPlatform.android_x64, BuildMode.release),
'a.dart',
<String>[],
......@@ -541,7 +541,7 @@ void main() {
}, artifactPaths));
}, overrides: contextOverrides);
testUsingContext('creates fingerprint without target platform', () {
final Fingerprint fingerprint = Snapshotter.createFingerprint(
final Fingerprint fingerprint = createFingerprint(
new SnapshotType(null, BuildMode.release),
'a.dart',
<String>[],
......@@ -555,7 +555,7 @@ void main() {
testUsingContext('creates fingerprint with file checksums', () async {
await fs.file('a.dart').create();
await fs.file('b.dart').create();
final Fingerprint fingerprint = Snapshotter.createFingerprint(
final Fingerprint fingerprint = createFingerprint(
new SnapshotType(TargetPlatform.android_x64, BuildMode.release),
'a.dart',
<String>['a.dart', 'b.dart'],
......@@ -582,7 +582,7 @@ void main() {
_FakeGenSnapshot genSnapshot;
MemoryFileSystem fs;
Snapshotter snapshotter;
AOTSnapshotter snapshotter;
MockArtifacts mockArtifacts;
MockXcode mockXcode;
......@@ -603,7 +603,7 @@ void main() {
fs.file(fs.path.join(skyEnginePath, 'sdk_ext', 'vmservice_io.dart')).createSync();
genSnapshot = new _FakeGenSnapshot();
snapshotter = new Snapshotter();
snapshotter = new AOTSnapshotter();
mockArtifacts = new MockArtifacts();
mockXcode = new MockXcode();
for (BuildMode mode in BuildMode.values) {
......@@ -624,7 +624,7 @@ void main() {
testUsingContext('iOS debug AOT snapshot is invalid', () async {
final String outputPath = fs.path.join('build', 'foo');
expect(await snapshotter.buildAotSnapshot(
expect(await snapshotter.build(
platform: TargetPlatform.ios,
buildMode: BuildMode.debug,
mainPath: 'main.dill',
......@@ -646,7 +646,7 @@ void main() {
fs.path.join(outputPath, 'snapshot.d'): '',
};
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
final int genSnapshotExitCode = await snapshotter.build(
platform: TargetPlatform.ios,
buildMode: BuildMode.profile,
mainPath: 'main.dill',
......@@ -690,7 +690,7 @@ void main() {
fs.path.join(outputPath, 'snapshot.d'): '',
};
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
final int genSnapshotExitCode = await snapshotter.build(
platform: TargetPlatform.ios,
buildMode: BuildMode.release,
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