| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:front_end/file_system.dart'; | 7 import 'package:front_end/file_system.dart'; |
| 8 import 'package:front_end/src/base/api_signature.dart'; | 8 import 'package:front_end/src/base/api_signature.dart'; |
| 9 import 'package:front_end/src/base/performace_logger.dart'; | 9 import 'package:front_end/src/base/performace_logger.dart'; |
| 10 import 'package:front_end/src/base/processed_options.dart'; | 10 import 'package:front_end/src/base/processed_options.dart'; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 /// A call to [invalidate] removes the specified file from the current file | 44 /// A call to [invalidate] removes the specified file from the current file |
| 45 /// state, so that it will be reread before any following [getKernel] will | 45 /// state, so that it will be reread before any following [getKernel] will |
| 46 /// return a result. | 46 /// return a result. |
| 47 class KernelDriver { | 47 class KernelDriver { |
| 48 /// The version of data format, should be incremented on every format change. | 48 /// The version of data format, should be incremented on every format change. |
| 49 static const int DATA_VERSION = 1; | 49 static const int DATA_VERSION = 1; |
| 50 | 50 |
| 51 /// Options used by the kernel compiler. | 51 /// Options used by the kernel compiler. |
| 52 final ProcessedOptions _options; | 52 final ProcessedOptions _options; |
| 53 | 53 |
| 54 /// The optional SDK outline as a serialized program. |
| 55 /// If provided, the driver will not attempt to read SDK files. |
| 56 final List<int> _sdkOutlineBytes; |
| 57 |
| 54 /// The logger to report compilation progress. | 58 /// The logger to report compilation progress. |
| 55 final PerformanceLog _logger; | 59 final PerformanceLog _logger; |
| 56 | 60 |
| 57 /// The [FileSystem] which should be used by the front end to access files. | 61 /// The [FileSystem] which should be used by the front end to access files. |
| 58 final FileSystem _fileSystem; | 62 final FileSystem _fileSystem; |
| 59 | 63 |
| 60 /// The byte storage to get and put serialized data. | 64 /// The byte storage to get and put serialized data. |
| 61 final ByteStore _byteStore; | 65 final ByteStore _byteStore; |
| 62 | 66 |
| 63 /// The object that knows how to resolve "package:" and "dart:" URIs. | 67 /// The object that knows how to resolve "package:" and "dart:" URIs. |
| 64 final UriTranslator _uriTranslator; | 68 final UriTranslator _uriTranslator; |
| 65 | 69 |
| 66 /// The function that is invoked when a new file is about to be added to | 70 /// The function that is invoked when a new file is about to be added to |
| 67 /// the current file state. The [Future] that it returns is awaited before | 71 /// the current file state. The [Future] that it returns is awaited before |
| 68 /// reading the file contents. | 72 /// reading the file contents. |
| 69 final KernelDriverFileAddedFn _fileAddedFn; | 73 final KernelDriverFileAddedFn _fileAddedFn; |
| 70 | 74 |
| 75 /// The optional SDK outline loaded from [_sdkOutlineBytes]. |
| 76 /// Might be `null` if the bytes are not provided, or if not loaded yet. |
| 77 Program _sdkOutline; |
| 78 |
| 71 /// The salt to mix into all hashes used as keys for serialized data. | 79 /// The salt to mix into all hashes used as keys for serialized data. |
| 72 List<int> _salt; | 80 List<int> _salt; |
| 73 | 81 |
| 74 /// The current file system state. | 82 /// The current file system state. |
| 75 FileSystemState _fsState; | 83 FileSystemState _fsState; |
| 76 | 84 |
| 77 /// The set of absolute file URIs that were reported through [invalidate] | 85 /// The set of absolute file URIs that were reported through [invalidate] |
| 78 /// and not checked for actual changes yet. | 86 /// and not checked for actual changes yet. |
| 79 final Set<Uri> _invalidatedFiles = new Set<Uri>(); | 87 final Set<Uri> _invalidatedFiles = new Set<Uri>(); |
| 80 | 88 |
| 81 /// The object that provides additional information for tests. | 89 /// The object that provides additional information for tests. |
| 82 final _TestView _testView = new _TestView(); | 90 final _TestView _testView = new _TestView(); |
| 83 | 91 |
| 84 KernelDriver(this._options, this._uriTranslator, | 92 KernelDriver(this._options, this._uriTranslator, |
| 85 {KernelDriverFileAddedFn fileAddedFn}) | 93 {List<int> sdkOutlineBytes, KernelDriverFileAddedFn fileAddedFn}) |
| 86 : _logger = _options.logger, | 94 : _logger = _options.logger, |
| 87 _fileSystem = _options.fileSystem, | 95 _fileSystem = _options.fileSystem, |
| 88 _byteStore = _options.byteStore, | 96 _byteStore = _options.byteStore, |
| 97 _sdkOutlineBytes = sdkOutlineBytes, |
| 89 _fileAddedFn = fileAddedFn { | 98 _fileAddedFn = fileAddedFn { |
| 90 _computeSalt(); | 99 _computeSalt(); |
| 91 | 100 |
| 92 Future<Null> onFileAdded(Uri uri) { | 101 Future<Null> onFileAdded(Uri uri) { |
| 93 if (_fileAddedFn != null) { | 102 if (_fileAddedFn != null) { |
| 94 return _fileAddedFn(uri); | 103 return _fileAddedFn(uri); |
| 95 } | 104 } |
| 96 return new Future.value(); | 105 return new Future.value(); |
| 97 } | 106 } |
| 98 | 107 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 115 /// reported using [invalidate]. | 124 /// reported using [invalidate]. |
| 116 /// | 125 /// |
| 117 /// If the driver has the cached result for the file with the current file | 126 /// If the driver has the cached result for the file with the current file |
| 118 /// state, it is returned. | 127 /// state, it is returned. |
| 119 /// | 128 /// |
| 120 /// Otherwise the driver will compute new kernel files and return them. | 129 /// Otherwise the driver will compute new kernel files and return them. |
| 121 Future<KernelResult> getKernel(Uri uri) async { | 130 Future<KernelResult> getKernel(Uri uri) async { |
| 122 return await runWithFrontEndContext('Compute delta', () async { | 131 return await runWithFrontEndContext('Compute delta', () async { |
| 123 await _refreshInvalidatedFiles(); | 132 await _refreshInvalidatedFiles(); |
| 124 | 133 |
| 134 // Load the SDK outline before building the graph, so that the file |
| 135 // system state is configured to skip SDK libraries. |
| 136 await _loadSdkOutline(); |
| 137 |
| 125 // Ensure that the graph starting at the entry point is ready. | 138 // Ensure that the graph starting at the entry point is ready. |
| 126 FileState entryLibrary = | 139 FileState entryLibrary = |
| 127 await _logger.runAsync('Build graph of files', () async { | 140 await _logger.runAsync('Build graph of files', () async { |
| 128 return await _fsState.getFile(uri); | 141 return await _fsState.getFile(uri); |
| 129 }); | 142 }); |
| 130 | 143 |
| 131 List<LibraryCycle> cycles = _logger.run('Compute library cycles', () { | 144 List<LibraryCycle> cycles = _logger.run('Compute library cycles', () { |
| 132 List<LibraryCycle> cycles = entryLibrary.topologicalOrder; | 145 List<LibraryCycle> cycles = entryLibrary.topologicalOrder; |
| 133 _logger.writeln('Computed ${cycles.length} cycles.'); | 146 _logger.writeln('Computed ${cycles.length} cycles.'); |
| 134 return cycles; | 147 return cycles; |
| 135 }); | 148 }); |
| 136 | 149 |
| 137 CanonicalName nameRoot = new CanonicalName.root(); | 150 CanonicalName nameRoot = new CanonicalName.root(); |
| 138 DillTarget dillTarget = new DillTarget( | 151 DillTarget dillTarget = new DillTarget( |
| 139 new Ticker(isVerbose: false), _uriTranslator, _options.target); | 152 new Ticker(isVerbose: false), _uriTranslator, _options.target); |
| 140 | 153 |
| 154 // If there is SDK outline, load it. |
| 155 if (_sdkOutline != null) { |
| 156 dillTarget.loader.appendLibraries(_sdkOutline); |
| 157 await dillTarget.buildOutlines(); |
| 158 } |
| 159 |
| 141 List<LibraryCycleResult> results = []; | 160 List<LibraryCycleResult> results = []; |
| 142 _testView.compiledCycles.clear(); | 161 _testView.compiledCycles.clear(); |
| 143 await _logger.runAsync('Compute results for cycles', () async { | 162 await _logger.runAsync('Compute results for cycles', () async { |
| 144 for (LibraryCycle cycle in cycles) { | 163 for (LibraryCycle cycle in cycles) { |
| 145 LibraryCycleResult result = | 164 LibraryCycleResult result = |
| 146 await _compileCycle(nameRoot, dillTarget, cycle); | 165 await _compileCycle(nameRoot, dillTarget, cycle); |
| 147 results.add(result); | 166 results.add(result); |
| 148 } | 167 } |
| 149 }); | 168 }); |
| 150 | 169 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 } | 309 } |
| 291 } | 310 } |
| 292 } while (wasChanged); | 311 } while (wasChanged); |
| 293 } | 312 } |
| 294 | 313 |
| 295 /// Compute salt and put into [_salt]. | 314 /// Compute salt and put into [_salt]. |
| 296 void _computeSalt() { | 315 void _computeSalt() { |
| 297 var saltBuilder = new ApiSignature(); | 316 var saltBuilder = new ApiSignature(); |
| 298 saltBuilder.addInt(DATA_VERSION); | 317 saltBuilder.addInt(DATA_VERSION); |
| 299 saltBuilder.addBool(_options.strongMode); | 318 saltBuilder.addBool(_options.strongMode); |
| 319 if (_sdkOutlineBytes != null) { |
| 320 saltBuilder.addBytes(_sdkOutlineBytes); |
| 321 } |
| 300 _salt = saltBuilder.toByteList(); | 322 _salt = saltBuilder.toByteList(); |
| 301 } | 323 } |
| 302 | 324 |
| 303 String _getCycleSignature(LibraryCycle cycle) { | 325 String _getCycleSignature(LibraryCycle cycle) { |
| 304 bool hasMixinApplication = | 326 bool hasMixinApplication = |
| 305 cycle.libraries.any((library) => library.hasMixinApplicationLibrary); | 327 cycle.libraries.any((library) => library.hasMixinApplicationLibrary); |
| 306 var signatureBuilder = new ApiSignature(); | 328 var signatureBuilder = new ApiSignature(); |
| 307 signatureBuilder.addBytes(_salt); | 329 signatureBuilder.addBytes(_salt); |
| 308 Set<FileState> transitiveFiles = cycle.libraries | 330 Set<FileState> transitiveFiles = cycle.libraries |
| 309 .map((library) => library.transitiveFiles) | 331 .map((library) => library.transitiveFiles) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 328 for (var library in cycle.libraries) { | 350 for (var library in cycle.libraries) { |
| 329 signatureBuilder.addBytes(library.contentHash); | 351 signatureBuilder.addBytes(library.contentHash); |
| 330 for (var part in library.partFiles) { | 352 for (var part in library.partFiles) { |
| 331 signatureBuilder.addBytes(part.contentHash); | 353 signatureBuilder.addBytes(part.contentHash); |
| 332 } | 354 } |
| 333 } | 355 } |
| 334 | 356 |
| 335 return signatureBuilder.toHex(); | 357 return signatureBuilder.toHex(); |
| 336 } | 358 } |
| 337 | 359 |
| 360 /// Load the SDK outline if its bytes are provided, and configure the file |
| 361 /// system state to skip SDK library files. |
| 362 Future<Null> _loadSdkOutline() async { |
| 363 if (_sdkOutlineBytes != null) { |
| 364 if (_sdkOutline == null) { |
| 365 await _logger.runAsync('Load SDK outline from bytes.', () async { |
| 366 _sdkOutline = new Program(); |
| 367 new BinaryBuilder(_sdkOutlineBytes).readProgram(_sdkOutline); |
| 368 // Configure the file system state to skip the outline libraries. |
| 369 for (var outlineLibrary in _sdkOutline.libraries) { |
| 370 _fsState.skipSdkLibraries.add(outlineLibrary.importUri); |
| 371 } |
| 372 }); |
| 373 } |
| 374 } |
| 375 } |
| 376 |
| 338 /// Refresh all the invalidated files and update dependencies. | 377 /// Refresh all the invalidated files and update dependencies. |
| 339 Future<Null> _refreshInvalidatedFiles() async { | 378 Future<Null> _refreshInvalidatedFiles() async { |
| 340 await _logger.runAsync('Refresh invalidated files', () async { | 379 await _logger.runAsync('Refresh invalidated files', () async { |
| 341 // Create a copy to avoid concurrent modifications. | 380 // Create a copy to avoid concurrent modifications. |
| 342 var invalidatedFiles = _invalidatedFiles.toList(); | 381 var invalidatedFiles = _invalidatedFiles.toList(); |
| 343 _invalidatedFiles.clear(); | 382 _invalidatedFiles.clear(); |
| 344 | 383 |
| 345 // Refresh the files. | 384 // Refresh the files. |
| 346 for (var fileUri in invalidatedFiles) { | 385 for (var fileUri in invalidatedFiles) { |
| 347 var file = _fsState.getFileByFileUri(fileUri); | 386 var file = _fsState.getFileByFileUri(fileUri); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 | 420 |
| 382 LibraryCycleResult(this.cycle, this.signature, this.kernelLibraries); | 421 LibraryCycleResult(this.cycle, this.signature, this.kernelLibraries); |
| 383 } | 422 } |
| 384 | 423 |
| 385 @visibleForTesting | 424 @visibleForTesting |
| 386 class _TestView { | 425 class _TestView { |
| 387 /// The list of [LibraryCycle]s compiled for the last delta. | 426 /// The list of [LibraryCycle]s compiled for the last delta. |
| 388 /// It does not include libraries which were read from the cache. | 427 /// It does not include libraries which were read from the cache. |
| 389 final List<LibraryCycle> compiledCycles = []; | 428 final List<LibraryCycle> compiledCycles = []; |
| 390 } | 429 } |
| OLD | NEW |