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 |