Chromium Code Reviews| 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' 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |