Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: utils/kernel-service/kernel-service.dart

Issue 2993013002: Introduce IKG into kernel-service to support incremental compilation. (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« runtime/vm/unit_test.cc ('K') | « runtime/vm/unit_test.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// This is an interface to the Dart Kernel parser and Kernel binary generator. 5 /// This is an interface to the Dart Kernel parser and Kernel binary generator.
6 /// 6 ///
7 /// It is used by the kernel-isolate to load Dart source code and generate 7 /// It is used by the kernel-isolate to load Dart source code and generate
8 /// Kernel binary format. 8 /// Kernel binary format.
9 /// 9 ///
10 /// This is either invoked as the root script of the Kernel isolate when used 10 /// This is either invoked as the root script of the Kernel isolate when used
11 /// as a part of 11 /// as a part of
12 /// 12 ///
13 /// dart --dfe=utils/kernel-service/kernel-service.dart ... 13 /// dart --dfe=utils/kernel-service/kernel-service.dart ...
14 /// 14 ///
15 /// invocation or it is invoked as a standalone script to perform training for 15 /// invocation or it is invoked as a standalone script to perform training for
16 /// the app-jit snapshot 16 /// the app-jit snapshot
17 /// 17 ///
18 /// dart utils/kernel-service/kernel-service.dart --train <source-file> 18 /// dart utils/kernel-service/kernel-service.dart --train <source-file>
19 /// 19 ///
20 /// 20 ///
21 library runtime.tools.kernel_service; 21 library runtime.tools.kernel_service;
22 22
23 import 'dart:async' show Future; 23 import 'dart:async' show Future;
24 import 'dart:convert' show JSON;
24 import 'dart:io' show Platform hide FileSystemEntity; 25 import 'dart:io' show Platform hide FileSystemEntity;
25 import 'dart:isolate'; 26 import 'dart:isolate';
26 import 'dart:typed_data' show Uint8List; 27 import 'dart:typed_data' show Uint8List;
27 28
28 import 'package:front_end/file_system.dart'; 29 import 'package:front_end/file_system.dart';
29 import 'package:front_end/front_end.dart'; 30 import 'package:front_end/front_end.dart';
31 import 'package:front_end/incremental_kernel_generator.dart';
30 import 'package:front_end/memory_file_system.dart'; 32 import 'package:front_end/memory_file_system.dart';
31 import 'package:front_end/physical_file_system.dart'; 33 import 'package:front_end/physical_file_system.dart';
32 import 'package:front_end/src/fasta/kernel/utils.dart'; 34 import 'package:front_end/src/fasta/kernel/utils.dart';
33 import 'package:front_end/src/testing/hybrid_file_system.dart'; 35 import 'package:front_end/src/testing/hybrid_file_system.dart';
34 import 'package:kernel/kernel.dart' show Program; 36 import 'package:kernel/kernel.dart' show Program;
35 import 'package:kernel/target/targets.dart' show TargetFlags; 37 import 'package:kernel/target/targets.dart' show TargetFlags;
36 import 'package:kernel/target/vm_fasta.dart' show VmFastaTarget; 38 import 'package:kernel/target/vm_fasta.dart' show VmFastaTarget;
37 39
38 const bool verbose = const bool.fromEnvironment('DFE_VERBOSE'); 40 const bool verbose = const bool.fromEnvironment('DFE_VERBOSE');
39 const bool strongMode = const bool.fromEnvironment('DFE_STRONG_MODE'); 41 const bool strongMode = const bool.fromEnvironment('DFE_STRONG_MODE');
40 42
43 abstract class Compiler {
44 FileSystem fs;
Siggi Cherem (dart-lang) 2017/08/08 00:08:07 - make final - dart style nit: for fields, try to
aam 2017/08/08 16:27:33 Done.
45 CompilerOptions options;
Siggi Cherem (dart-lang) 2017/08/08 00:08:07 might be nice to make this final too. To do that,
Siggi Cherem (dart-lang) 2017/08/09 15:57:58 Another idea for this: if you move the entire body
aam 2017/08/09 16:17:04 Yeah, I looked at that. What stopped me then was r
46 List<String> errors = new List<String>();
47
48 Compiler(this.fs) {
49 Uri packagesUri = (Platform.packageConfig != null)
50 ? Uri.parse(Platform.packageConfig)
51 : null;
52
53 Uri sdkSummary = Uri.base
54 .resolveUri(new Uri.file(Platform.resolvedExecutable))
55 .resolveUri(new Uri.directory("patched_sdk"))
56 // TODO(sigmund): use outline.dill when the mixin transformer is modular .
Siggi Cherem (dart-lang) 2017/08/08 00:08:07 nit: rewrap comments to 80 col (here and below)
aam 2017/08/08 16:27:33 Hmm... With formatting I prefer to rely on automat
Siggi Cherem (dart-lang) 2017/08/09 15:57:58 thanks, they are off limits unfortunately
57 .resolve('platform.dill');
58
59 if (verbose) {
60 print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
61 print("DFE: packagesUri: ${packagesUri}");
62 print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
63 print("DFE: sdkSummary: ${sdkSummary}");
64 }
65
66 options = new CompilerOptions()
67 ..strongMode = strongMode
68 ..fileSystem = fs
69 ..target = new VmFastaTarget(new TargetFlags(strongMode: strongMode))
70 ..packagesFileUri = packagesUri
71 ..sdkSummary = sdkSummary
72 ..verbose = verbose
73 ..throwOnErrors = false
74 ..reportMessages = true
75 ..onError = (CompilationMessage e) {
76 if (e.severity == Severity.error) {
77 // TODO(sigmund): support emitting code with errors as long as they ar e
78 // handled in the generated code (issue #30194).
79 errors.add(e.message);
80 }
81 };
82 }
83
84 Future<Program> compile(Uri script);
85 }
86
87 class IncrementalCompiler extends Compiler {
88 Map<String, Uri> loadDartLibraries(Uri libraries, dynamic librariesJson) {
89 final dynamic map = JSON.decode(librariesJson)['libraries'];
Siggi Cherem (dart-lang) 2017/08/08 00:08:07 Instead of loadingDartLibraries explicitly, simply
aam 2017/08/08 16:27:33 Done.
Siggi Cherem (dart-lang) 2017/08/09 15:57:58 I see - it would mean we would create and discard
90 final Map<String, Uri> dartLibraries = <String, Uri>{};
91 map.forEach(
92 (String k, String v) => dartLibraries[k] = libraries.resolve(v));
93 return dartLibraries;
94 }
95
96 IncrementalCompiler(FileSystem fs, Uri libraries, dynamic librariesJson)
97 : super(fs) {
98 options..dartLibraries = loadDartLibraries(libraries, librariesJson);
Siggi Cherem (dart-lang) 2017/08/08 00:08:07 nit: no need to use cascades here.
aam 2017/08/08 16:27:33 Acknowledged.
99 }
100
101 IncrementalKernelGenerator generator;
102 @override
103 Future<Program> compile(Uri script) async {
104 if (generator == null) {
105 generator = await IncrementalKernelGenerator.newInstance(options, script);
106 }
107 DeltaProgram deltaProgram = await generator.computeDelta();
108 return deltaProgram.newProgram;
109 }
110
111 void invalidate(Uri uri) {
112 generator.invalidate(uri);
113 }
114 }
115
116 class SingleShotCompiler extends Compiler {
117 bool requireMain;
118
119 SingleShotCompiler(FileSystem fs, this.requireMain) : super(fs);
120
121 @override
122 Future<Program> compile(Uri script) async {
123 return requireMain
124 ? kernelForProgram(script, options)
125 : kernelForBuildUnit([script], options..chaseDependencies = true);
126 }
127 }
128
129 final Map<int, Compiler> isolateCompilers = new Map<int, Compiler>();
130
131 Future<Compiler> lookupOrBuildNewIncrementalCompiler(
132 int isolateId, List sourceFiles) async {
133 IncrementalCompiler compiler;
134 if (isolateCompilers.containsKey(isolateId)) {
135 compiler = isolateCompilers[isolateId];
136 if (sourceFiles != null) {
137 for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
138 Uri uri = Uri.parse(sourceFiles[i * 2]);
139 (compiler.fs as HybridFileSystem)
Siggi Cherem (dart-lang) 2017/08/08 00:08:07 possibly the VM can be smart about removing this c
aam 2017/08/08 16:27:33 Done.
140 .memory
141 .entityForUri(uri)
142 .writeAsBytesSync(sourceFiles[i * 2 + 1]);
143 compiler.invalidate(uri);
144 }
145 }
146 } else {
147 Uri librariesUri = Uri.base
148 .resolveUri(new Uri.file(Platform.resolvedExecutable))
149 .resolveUri(new Uri.directory("patched_sdk"))
150 .resolveUri(new Uri.directory("lib"))
151 .resolve("libraries.json");
152 final librariesJson = await PhysicalFileSystem.instance
153 .entityForUri(librariesUri)
154 .readAsString();
155
156 final FileSystem fs = sourceFiles == null
157 ? PhysicalFileSystem.instance
158 : _buildFileSystem(sourceFiles);
159
160 compiler = new IncrementalCompiler(fs, librariesUri, librariesJson);
161 isolateCompilers[isolateId] = compiler;
siva 2017/08/07 23:59:29 When is the incremental compiler object deleted? I
aam 2017/08/08 16:27:33 Before we enable IKG flow for anything besides vm
162 }
163 return compiler;
164 }
165
41 // Process a request from the runtime. See KernelIsolate::CompileToKernel in 166 // Process a request from the runtime. See KernelIsolate::CompileToKernel in
42 // kernel_isolate.cc and Loader::SendKernelRequest in loader.cc. 167 // kernel_isolate.cc and Loader::SendKernelRequest in loader.cc.
43 Future _processLoadRequest(request) async { 168 Future _processLoadRequest(request) async {
44 if (verbose) print("DFE: request: $request"); 169 if (verbose) print("DFE: request: $request");
45 170
46 int tag = request[0]; 171 int tag = request[0];
47 final SendPort port = request[1]; 172 final SendPort port = request[1];
48 final String inputFileUri = request[2]; 173 final String inputFileUri = request[2];
49 final Uri script = Uri.base.resolve(inputFileUri); 174 final Uri script = Uri.base.resolve(inputFileUri);
175 final bool incremental = request[3];
50 176
51 FileSystem fileSystem = PhysicalFileSystem.instance; 177 final List sourceFiles = request.length > 5 ? request[5] : null;
52 bool requireMain = true;
53 178
54 if (request.length > 3) { 179 Compiler compiler;
55 fileSystem = _buildFileSystem(request[3]); 180 if (incremental) {
56 requireMain = false; 181 final int isolateId = request[4];
182 compiler =
183 await lookupOrBuildNewIncrementalCompiler(isolateId, sourceFiles);
184 } else {
185 final FileSystem fs = sourceFiles == null
186 ? PhysicalFileSystem.instance
187 : _buildFileSystem(sourceFiles);
188 compiler =
189 new SingleShotCompiler(fs, sourceFiles == null /* requireMain */);
57 } 190 }
siva 2017/08/07 23:59:29 Do you plan on switching this to always use the in
aam 2017/08/08 16:27:33 Yeah, currently incremental compilers are not clea
58 191
59 Uri packagesUri = (Platform.packageConfig != null)
60 ? Uri.parse(Platform.packageConfig)
61 : null;
62
63 Uri sdkSummary = Uri.base
64 .resolveUri(new Uri.file(Platform.resolvedExecutable))
65 .resolveUri(new Uri.directory("patched_sdk"))
66 // TODO(sigmund): use outline.dill when the mixin transformer is modular.
67 .resolve('platform.dill');
68
69 if (verbose) {
70 print("DFE: scriptUri: ${script}");
71 print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
72 print("DFE: packagesUri: ${packagesUri}");
73 print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
74 print("DFE: sdkSummary: ${sdkSummary}");
75 }
76
77 var errors = <String>[];
78 var options = new CompilerOptions()
79 ..strongMode = strongMode
80 ..fileSystem = fileSystem
81 ..target = new VmFastaTarget(new TargetFlags(strongMode: strongMode))
82 ..packagesFileUri = packagesUri
83 ..sdkSummary = sdkSummary
84 ..verbose = verbose
85 ..throwOnErrors = false
86 ..reportMessages = true
87 ..onError = (CompilationMessage e) {
88 if (e.severity == Severity.error) {
89 // TODO(sigmund): support emitting code with errors as long as they are
90 // handled in the generated code (issue #30194).
91 errors.add(e.message);
92 }
93 };
94
95 CompilationResult result; 192 CompilationResult result;
96 try { 193 try {
97 Program program = requireMain 194 if (verbose) {
98 ? await kernelForProgram(script, options) 195 print("DFE: scriptUri: ${script}");
99 : await kernelForBuildUnit([script], options..chaseDependencies = true); 196 }
100 197
101 if (errors.isNotEmpty) { 198 Program program = await compiler.compile(script);
199
200 if (compiler.errors.isNotEmpty) {
102 // TODO(sigmund): the compiler prints errors to the console, so we 201 // TODO(sigmund): the compiler prints errors to the console, so we
103 // shouldn't print those messages again here. 202 // shouldn't print those messages again here.
104 result = new CompilationResult.errors(errors); 203 result = new CompilationResult.errors(compiler.errors);
105 } else { 204 } else {
106 // We serialize the program excluding platform.dill because the VM has 205 // We serialize the program excluding platform.dill because the VM has
107 // these sources built-in. Everything loaded as a summary in 206 // these sources built-in. Everything loaded as a summary in
108 // [kernelForProgram] is marked `external`, so we can use that bit to 207 // [kernelForProgram] is marked `external`, so we can use that bit to
109 // decide what to excluce. 208 // decide what to exclude.
110 // TODO(sigmund): remove the following line (Issue #30111) 209 // TODO(sigmund): remove the following line (Issue #30111)
111 program.libraries.forEach((e) => e.isExternal = false); 210 program.libraries.forEach((e) => e.isExternal = false);
112 result = new CompilationResult.ok( 211 result = new CompilationResult.ok(
113 serializeProgram(program, filter: (lib) => !lib.isExternal)); 212 serializeProgram(program, filter: (lib) => !lib.isExternal));
114 } 213 }
115 } catch (error, stack) { 214 } catch (error, stack) {
116 result = new CompilationResult.crash(error, stack); 215 result = new CompilationResult.crash(error, stack);
117 } 216 }
118 217
119 if (verbose) print("DFE:> ${result}"); 218 if (verbose) print("DFE:> ${result}");
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 if (response[0] == tag) { 258 if (response[0] == tag) {
160 // Success. 259 // Success.
161 responsePort.close(); 260 responsePort.close();
162 } else if (response[0] == -tag) { 261 } else if (response[0] == -tag) {
163 // Compilation error. 262 // Compilation error.
164 throw response[4]; 263 throw response[4];
165 } else { 264 } else {
166 throw "Unexpected response: $response"; 265 throw "Unexpected response: $response";
167 } 266 }
168 }; 267 };
169 var request = [tag, responsePort.sendPort, scriptUri]; 268 var request = [
269 tag,
270 responsePort.sendPort,
271 scriptUri,
272 1 /* isolateId chosen randomly */,
273 false /* incremental */
274 ];
170 _processLoadRequest(request); 275 _processLoadRequest(request);
171 } 276 }
172 277
173 main([args]) { 278 main([args]) {
174 if (args?.length == 2 && args[0] == '--train') { 279 if (args?.length == 2 && args[0] == '--train') {
175 // This entry point is used when creating an app snapshot. The argument 280 // This entry point is used when creating an app snapshot. The argument
176 // provides a script to compile to warm-up generated code. 281 // provides a script to compile to warm-up generated code.
177 train(args[1]); 282 train(args[1]);
178 } else { 283 } else {
179 // Entry point for the Kernel isolate. 284 // Entry point for the Kernel isolate.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 _CompilationCrash(this.exception, this.stack); 363 _CompilationCrash(this.exception, this.stack);
259 364
260 @override 365 @override
261 Status get status => Status.crash; 366 Status get status => Status.crash;
262 367
263 @override 368 @override
264 String get errorString => "${exception}\n${stack}"; 369 String get errorString => "${exception}\n${stack}";
265 370
266 String toString() => "_CompilationCrash(${errorString})"; 371 String toString() => "_CompilationCrash(${errorString})";
267 } 372 }
OLDNEW
« runtime/vm/unit_test.cc ('K') | « runtime/vm/unit_test.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698