OLD | NEW |
---|---|
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'; | 23 import 'dart:async' show Future; |
24 import 'dart:io' hide FileSystemEntity; | 24 import 'dart:io' show File, Platform hide FileSystemEntity; |
25 import 'dart:isolate'; | 25 import 'dart:isolate'; |
26 import 'dart:typed_data' show Uint8List; | |
26 | 27 |
27 import 'package:front_end/file_system.dart'; | 28 import 'package:front_end/file_system.dart'; |
29 import 'package:front_end/front_end.dart'; | |
28 import 'package:front_end/memory_file_system.dart'; | 30 import 'package:front_end/memory_file_system.dart'; |
29 import 'package:front_end/physical_file_system.dart'; | 31 import 'package:front_end/physical_file_system.dart'; |
30 import 'package:front_end/src/fasta/vm.dart' | 32 import 'package:front_end/src/fasta/kernel/utils.dart'; |
31 show CompilationResult, Status, parseScriptInFileSystem; | |
32 import 'package:front_end/src/testing/hybrid_file_system.dart'; | 33 import 'package:front_end/src/testing/hybrid_file_system.dart'; |
34 import 'package:kernel/kernel.dart' show Program; | |
35 import 'package:kernel/target/targets.dart' show TargetFlags; | |
36 import 'package:kernel/target/vm_fasta.dart' show VmFastaTarget; | |
33 | 37 |
34 const bool verbose = const bool.fromEnvironment('DFE_VERBOSE'); | 38 const bool verbose = const bool.fromEnvironment('DFE_VERBOSE'); |
35 | 39 |
36 const bool strongMode = const bool.fromEnvironment('DFE_STRONG_MODE'); | 40 const bool strongMode = const bool.fromEnvironment('DFE_STRONG_MODE'); |
37 | 41 |
42 /// CODE REVIEW NOTE: this came from fasta.dart, moved here because it is | |
43 /// specific to the kernel-service and nothing else. | |
ahe
2017/07/06 13:12:22
I'm not at all excited about moving stuff from pkg
Siggi Cherem (dart-lang)
2017/07/06 19:05:28
I hear you. Given that the code below is modified
ahe
2017/07/11 09:34:26
We need to do something about this. This is way to
| |
44 Future<CompilationResult> _parseScriptInFileSystem( | |
45 Uri script, FileSystem fileSystem, | |
46 {bool verbose: false, bool strongMode: false}) async { | |
47 final Uri packagesUri = (Platform.packageConfig != null) | |
48 ? Uri.parse(Platform.packageConfig) | |
49 : await _findPackagesFile(fileSystem, script); | |
50 if (packagesUri == null) { | |
51 throw "Could not find .packages"; | |
52 } | |
53 | |
54 final Uri patchedSdk = Uri.base | |
55 .resolveUri(new Uri.file(Platform.resolvedExecutable)) | |
56 .resolveUri(new Uri.directory("patched_sdk")); | |
57 | |
58 if (verbose) { | |
59 print("""DFE: Requesting compilation { | |
60 scriptUri: ${script} | |
61 packagesUri: ${packagesUri} | |
62 patchedSdk: ${patchedSdk} | |
63 }"""); | |
64 } | |
65 | |
66 try { | |
67 var errors = <String>[]; | |
68 var options = new CompilerOptions() | |
69 ..strongMode = strongMode | |
70 ..fileSystem = fileSystem | |
71 ..target = new VmFastaTarget(new TargetFlags(strongMode: strongMode)) | |
72 ..packagesFileUri = packagesUri | |
73 // TODO(sigmund): use outline.dill when the mixin transformer is modular. | |
74 ..sdkSummary = patchedSdk.resolve('platform.dill') | |
75 ..verbose = verbose | |
76 ..onError = (CompilationError e) => errors.add(e.message); | |
77 | |
78 Program program = await kernelForProgram(script, options); | |
79 if (errors.isNotEmpty) return new CompilationResult.errors(errors); | |
80 | |
81 // We serialize the program excluding platform.dill because the VM has these | |
82 // sources built-in. Everything loaded as a summary in [kernelForProgram] is | |
83 // marked `external`, so we can use that bit to decide what to excluce. | |
84 return new CompilationResult.ok( | |
85 | |
86 /// CODE REVIEW NOTE: this is a change: we used to call the | |
87 /// LibraryFilteringBinaryBuilder. [serializeProgram] uses | |
88 /// LimitedBinaryBuilder instead (which not only excludes code, but also | |
89 /// string tables from excluded libraries). | |
90 serializeProgram(program, filter: (lib) => !lib.isExternal)); | |
91 } catch (err, stack) { | |
92 return new CompilationResult.crash(err, stack); | |
93 } | |
94 } | |
95 | |
96 /// This duplicates functionality from the Loader which we can't easily | |
97 /// access from here. | |
98 // TODO(sigmund): delete, this should be supported by the default options in | |
99 // package:front_end. | |
100 Future<Uri> _findPackagesFile(FileSystem fileSystem, Uri base) async { | |
101 var dir = new File.fromUri(base).parent; | |
102 while (true) { | |
103 final packagesFile = dir.uri.resolve(".packages"); | |
104 if (await fileSystem.entityForUri(packagesFile).exists()) { | |
105 return packagesFile; | |
106 } | |
107 if (dir.parent.path == dir.path) { | |
108 break; | |
109 } | |
110 dir = dir.parent; | |
111 } | |
112 return null; | |
113 } | |
114 | |
38 Future<CompilationResult> _processLoadRequestImpl( | 115 Future<CompilationResult> _processLoadRequestImpl( |
39 String inputFilePathOrUri, FileSystem fileSystem) { | 116 String inputFilePathOrUri, FileSystem fileSystem) { |
40 Uri scriptUri = Uri.parse(inputFilePathOrUri); | 117 Uri scriptUri = Uri.parse(inputFilePathOrUri); |
41 | 118 |
42 // Because we serve both Loader and bootstrapping requests we need to | 119 // Because we serve both Loader and bootstrapping requests we need to |
43 // duplicate the logic from _resolveScriptUri(...) here and attempt to | 120 // duplicate the logic from _resolveScriptUri(...) here and attempt to |
44 // resolve schemaless uris using current working directory. | 121 // resolve schemaless uris using current working directory. |
45 if (!scriptUri.hasScheme) { | 122 if (!scriptUri.hasScheme) { |
46 // Script does not have a scheme, assume that it is a path, | 123 // Script does not have a scheme, assume that it is a path, |
47 // resolve it against the working directory. | 124 // resolve it against the working directory. |
48 scriptUri = Uri.base.resolveUri(new Uri.file(inputFilePathOrUri)); | 125 scriptUri = Uri.base.resolveUri(new Uri.file(inputFilePathOrUri)); |
49 } | 126 } |
50 | 127 |
51 if (!scriptUri.isScheme('file')) { | 128 if (!scriptUri.isScheme('file')) { |
52 // TODO(vegorov): Reuse loader code to support other schemes. | 129 // TODO(vegorov): Reuse loader code to support other schemes. |
53 return new Future<CompilationResult>.value(new CompilationResult.error( | 130 return new Future<CompilationResult>.value(new CompilationResult.errors( |
54 "Expected 'file' scheme for a script uri: got ${scriptUri.scheme}")); | 131 ["Expected 'file' scheme for a script uri: got ${scriptUri.scheme}"])); |
55 } | 132 } |
56 return parseScriptInFileSystem(scriptUri, fileSystem, | 133 return _parseScriptInFileSystem(scriptUri, fileSystem, |
57 verbose: verbose, strongMode: strongMode); | 134 verbose: verbose, strongMode: strongMode); |
58 } | 135 } |
59 | 136 |
60 // Process a request from the runtime. See KernelIsolate::CompileToKernel in | 137 // Process a request from the runtime. See KernelIsolate::CompileToKernel in |
61 // kernel_isolate.cc and Loader::SendKernelRequest in loader.cc. | 138 // kernel_isolate.cc and Loader::SendKernelRequest in loader.cc. |
62 Future _processLoadRequest(request) async { | 139 Future _processLoadRequest(request) async { |
63 if (verbose) { | 140 if (verbose) { |
64 print("DFE: request: $request"); | 141 print("DFE: request: $request"); |
65 print("DFE: Platform.packageConfig: ${Platform.packageConfig}"); | 142 print("DFE: Platform.packageConfig: ${Platform.packageConfig}"); |
66 print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}"); | 143 print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}"); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 main([args]) { | 216 main([args]) { |
140 if (args?.length == 2 && args[0] == '--train') { | 217 if (args?.length == 2 && args[0] == '--train') { |
141 // This entry point is used when creating an app snapshot. The argument | 218 // This entry point is used when creating an app snapshot. The argument |
142 // provides a script to compile to warm-up generated code. | 219 // provides a script to compile to warm-up generated code. |
143 train(args[1]); | 220 train(args[1]); |
144 } else { | 221 } else { |
145 // Entry point for the Kernel isolate. | 222 // Entry point for the Kernel isolate. |
146 return new RawReceivePort()..handler = _processLoadRequest; | 223 return new RawReceivePort()..handler = _processLoadRequest; |
147 } | 224 } |
148 } | 225 } |
226 | |
227 /// CODE REVIEW NOTE: this came from fasta/vm.dart, also moved here because it | |
228 /// is specific to the kernel-service and nothing else. | |
229 | |
230 /// Compilation status codes. | |
231 /// | |
232 /// Note: The [index] property of these constants must match | |
233 /// `Dart_KernelCompilationStatus` in | |
234 /// [dart_api.h](../../../../runtime/include/dart_api.h). | |
235 enum Status { | |
236 /// Compilation was successful. | |
237 ok, | |
238 | |
239 /// Compilation failed with a compile time error. | |
240 error, | |
241 | |
242 /// Compiler crashed. | |
243 crash, | |
244 } | |
245 | |
246 abstract class CompilationResult { | |
247 CompilationResult._(); | |
248 | |
249 factory CompilationResult.ok(Uint8List bytes) = _CompilationOk; | |
250 | |
251 factory CompilationResult.errors(List<String> errors) = _CompilationError; | |
252 | |
253 factory CompilationResult.crash(Object exception, StackTrace stack) = | |
254 _CompilationCrash; | |
255 | |
256 Status get status; | |
257 | |
258 get payload; | |
259 | |
260 List toResponse() => [status.index, payload]; | |
261 } | |
262 | |
263 class _CompilationOk extends CompilationResult { | |
264 final Uint8List bytes; | |
265 | |
266 _CompilationOk(this.bytes) : super._(); | |
267 | |
268 @override | |
269 Status get status => Status.ok; | |
270 | |
271 @override | |
272 get payload => bytes; | |
273 | |
274 String toString() => "_CompilationOk(${bytes.length} bytes)"; | |
275 } | |
276 | |
277 abstract class _CompilationFail extends CompilationResult { | |
278 _CompilationFail() : super._(); | |
279 | |
280 String get errorString; | |
281 | |
282 @override | |
283 get payload => errorString; | |
284 } | |
285 | |
286 class _CompilationError extends _CompilationFail { | |
287 final List<String> errors; | |
288 | |
289 _CompilationError(this.errors); | |
290 | |
291 @override | |
292 Status get status => Status.error; | |
293 | |
294 @override | |
295 String get errorString => errors.take(10).join('\n'); | |
296 | |
297 String toString() => "_CompilationError(${errorString})"; | |
298 } | |
299 | |
300 class _CompilationCrash extends _CompilationFail { | |
301 final Object exception; | |
302 final StackTrace stack; | |
303 | |
304 _CompilationCrash(this.exception, this.stack); | |
305 | |
306 @override | |
307 Status get status => Status.crash; | |
308 | |
309 @override | |
310 String get errorString => "${exception}\n${stack}"; | |
311 | |
312 String toString() => "_CompilationCrash(${errorString})"; | |
313 } | |
OLD | NEW |