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

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

Issue 2993013002: Introduce IKG into kernel-service to support incremental compilation. (Closed)
Patch Set: Add TODO to add assert that isolate exists. 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
« no previous file with comments | « 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 final FileSystem fileSystem;
45 final List<String> errors = new List<String>();
46
47 CompilerOptions options;
48
49 Compiler(this.fileSystem) {
50 Uri packagesUri = (Platform.packageConfig != null)
51 ? Uri.parse(Platform.packageConfig)
52 : null;
53
54 Uri sdkSummary = Uri.base
55 .resolveUri(new Uri.file(Platform.resolvedExecutable))
56 .resolveUri(new Uri.directory("patched_sdk"))
57 // TODO(sigmund): use outline.dill when the mixin transformer is
58 // modular.
59 .resolve('platform.dill');
60
61 if (verbose) {
62 print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
63 print("DFE: packagesUri: ${packagesUri}");
64 print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
65 print("DFE: sdkSummary: ${sdkSummary}");
66 }
67
68 options = new CompilerOptions()
69 ..strongMode = strongMode
70 ..fileSystem = fileSystem
71 ..target = new VmFastaTarget(new TargetFlags(strongMode: strongMode))
72 ..packagesFileUri = packagesUri
73 ..sdkSummary = sdkSummary
74 ..verbose = verbose
75 ..throwOnErrors = false
76 ..reportMessages = true
77 ..onError = (CompilationMessage e) {
78 if (e.severity == Severity.error) {
79 // TODO(sigmund): support emitting code with errors as long as they
80 // are handled in the generated code (issue #30194).
81 errors.add(e.message);
82 }
83 };
84 }
85
86 Future<Program> compile(Uri script);
87 }
88
89 class IncrementalCompiler extends Compiler {
90 IncrementalKernelGenerator generator;
91
92 IncrementalCompiler(FileSystem fileSystem) : super(fileSystem);
93
94 @override
95 Future<Program> compile(Uri script) async {
96 if (generator == null) {
97 generator = await IncrementalKernelGenerator.newInstance(options, script);
98 }
99 DeltaProgram deltaProgram = await generator.computeDelta();
100 // TODO(aam): Accepting/rejecting should be done based on VM response.
101 generator.acceptLastDelta();
102 return deltaProgram.newProgram;
103 }
104
105 void invalidate(Uri uri) {
106 generator.invalidate(uri);
107 }
108 }
109
110 class SingleShotCompiler extends Compiler {
111 final bool requireMain;
112
113 SingleShotCompiler(FileSystem fileSystem, this.requireMain)
114 : super(fileSystem);
115
116 @override
117 Future<Program> compile(Uri script) async {
118 return requireMain
119 ? kernelForProgram(script, options)
120 : kernelForBuildUnit([script], options..chaseDependencies = true);
121 }
122 }
123
124 final Map<int, Compiler> isolateCompilers = new Map<int, Compiler>();
125
126 Future<Compiler> lookupOrBuildNewIncrementalCompiler(
127 int isolateId, List sourceFiles) async {
128 IncrementalCompiler compiler;
129 if (isolateCompilers.containsKey(isolateId)) {
130 compiler = isolateCompilers[isolateId];
131 final HybridFileSystem fileSystem = compiler.fileSystem;
132 if (sourceFiles != null) {
133 for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
134 Uri uri = Uri.parse(sourceFiles[i * 2]);
135 fileSystem.memory
136 .entityForUri(uri)
137 .writeAsBytesSync(sourceFiles[i * 2 + 1]);
138 compiler.invalidate(uri);
139 }
140 }
141 } else {
142 final FileSystem fileSystem = sourceFiles == null
143 ? PhysicalFileSystem.instance
144 : _buildFileSystem(sourceFiles);
145
146 // TODO(aam): IncrementalCompiler instance created below have to be
147 // destroyed when corresponding isolate is shut down. To achieve that kernel
148 // isolate needs to receive a message indicating that particular
149 // isolate was shut down. Message should be handled here in this script.
150 compiler = new IncrementalCompiler(fileSystem);
151 isolateCompilers[isolateId] = compiler;
152 }
153 return compiler;
154 }
155
41 // Process a request from the runtime. See KernelIsolate::CompileToKernel in 156 // Process a request from the runtime. See KernelIsolate::CompileToKernel in
42 // kernel_isolate.cc and Loader::SendKernelRequest in loader.cc. 157 // kernel_isolate.cc and Loader::SendKernelRequest in loader.cc.
43 Future _processLoadRequest(request) async { 158 Future _processLoadRequest(request) async {
44 if (verbose) print("DFE: request: $request"); 159 if (verbose) print("DFE: request: $request");
45 160
46 int tag = request[0]; 161 int tag = request[0];
47 final SendPort port = request[1]; 162 final SendPort port = request[1];
48 final String inputFileUri = request[2]; 163 final String inputFileUri = request[2];
49 final Uri script = Uri.base.resolve(inputFileUri); 164 final Uri script = Uri.base.resolve(inputFileUri);
165 final bool incremental = request[3];
50 166
51 FileSystem fileSystem = PhysicalFileSystem.instance; 167 final List sourceFiles = request.length > 5 ? request[5] : null;
52 bool requireMain = true;
53 168
54 if (request.length > 3) { 169 Compiler compiler;
55 fileSystem = _buildFileSystem(request[3]); 170 // TODO(aam): There should be no need to have an option to choose
56 requireMain = false; 171 // one compiler or another. We should always use an incremental
172 // compiler as its functionality is a super set of the other one. We need to
173 // watch the performance though.
174 if (incremental) {
175 final int isolateId = request[4];
176 compiler =
177 await lookupOrBuildNewIncrementalCompiler(isolateId, sourceFiles);
178 } else {
179 final FileSystem fileSystem = sourceFiles == null
180 ? PhysicalFileSystem.instance
181 : _buildFileSystem(sourceFiles);
182 compiler = new SingleShotCompiler(
183 fileSystem, sourceFiles == null /* requireMain */);
57 } 184 }
58 185
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; 186 CompilationResult result;
96 try { 187 try {
97 Program program = requireMain 188 if (verbose) {
98 ? await kernelForProgram(script, options) 189 print("DFE: scriptUri: ${script}");
99 : await kernelForBuildUnit([script], options..chaseDependencies = true); 190 }
100 191
101 if (errors.isNotEmpty) { 192 Program program = await compiler.compile(script);
193
194 if (compiler.errors.isNotEmpty) {
102 // TODO(sigmund): the compiler prints errors to the console, so we 195 // TODO(sigmund): the compiler prints errors to the console, so we
103 // shouldn't print those messages again here. 196 // shouldn't print those messages again here.
104 result = new CompilationResult.errors(errors); 197 result = new CompilationResult.errors(compiler.errors);
105 } else { 198 } else {
106 // We serialize the program excluding platform.dill because the VM has 199 // We serialize the program excluding platform.dill because the VM has
107 // these sources built-in. Everything loaded as a summary in 200 // these sources built-in. Everything loaded as a summary in
108 // [kernelForProgram] is marked `external`, so we can use that bit to 201 // [kernelForProgram] is marked `external`, so we can use that bit to
109 // decide what to excluce. 202 // decide what to exclude.
110 // TODO(sigmund): remove the following line (Issue #30111) 203 // TODO(sigmund): remove the following line (Issue #30111)
111 program.libraries.forEach((e) => e.isExternal = false); 204 program.libraries.forEach((e) => e.isExternal = false);
112 result = new CompilationResult.ok( 205 result = new CompilationResult.ok(
113 serializeProgram(program, filter: (lib) => !lib.isExternal)); 206 serializeProgram(program, filter: (lib) => !lib.isExternal));
114 } 207 }
115 } catch (error, stack) { 208 } catch (error, stack) {
116 result = new CompilationResult.crash(error, stack); 209 result = new CompilationResult.crash(error, stack);
117 } 210 }
118 211
119 if (verbose) print("DFE:> ${result}"); 212 if (verbose) print("DFE:> ${result}");
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 if (response[0] == tag) { 252 if (response[0] == tag) {
160 // Success. 253 // Success.
161 responsePort.close(); 254 responsePort.close();
162 } else if (response[0] == -tag) { 255 } else if (response[0] == -tag) {
163 // Compilation error. 256 // Compilation error.
164 throw response[4]; 257 throw response[4];
165 } else { 258 } else {
166 throw "Unexpected response: $response"; 259 throw "Unexpected response: $response";
167 } 260 }
168 }; 261 };
169 var request = [tag, responsePort.sendPort, scriptUri]; 262 var request = [
263 tag,
264 responsePort.sendPort,
265 scriptUri,
266 1 /* isolateId chosen randomly */,
267 false /* incremental */
268 ];
170 _processLoadRequest(request); 269 _processLoadRequest(request);
171 } 270 }
172 271
173 main([args]) { 272 main([args]) {
174 if (args?.length == 2 && args[0] == '--train') { 273 if (args?.length == 2 && args[0] == '--train') {
175 // This entry point is used when creating an app snapshot. The argument 274 // This entry point is used when creating an app snapshot. The argument
176 // provides a script to compile to warm-up generated code. 275 // provides a script to compile to warm-up generated code.
177 train(args[1]); 276 train(args[1]);
178 } else { 277 } else {
179 // Entry point for the Kernel isolate. 278 // Entry point for the Kernel isolate.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 _CompilationCrash(this.exception, this.stack); 357 _CompilationCrash(this.exception, this.stack);
259 358
260 @override 359 @override
261 Status get status => Status.crash; 360 Status get status => Status.crash;
262 361
263 @override 362 @override
264 String get errorString => "${exception}\n${stack}"; 363 String get errorString => "${exception}\n${stack}";
265 364
266 String toString() => "_CompilationCrash(${errorString})"; 365 String toString() => "_CompilationCrash(${errorString})";
267 } 366 }
OLDNEW
« no previous file with comments | « runtime/vm/unit_test.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698