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

Side by Side Diff: pkg/front_end/lib/src/incremental_kernel_generator_impl.dart

Issue 2877193003: Start actually adding incrementality into incremental kernel generator. (Closed)
Patch Set: Created 3 years, 7 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
OLDNEW
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 import 'dart:io';
6 7
7 import 'package:front_end/file_system.dart'; 8 import 'package:front_end/file_system.dart';
8 import 'package:front_end/incremental_kernel_generator.dart'; 9 import 'package:front_end/incremental_kernel_generator.dart';
9 import 'package:front_end/incremental_resolved_ast_generator.dart'; 10 import 'package:front_end/incremental_resolved_ast_generator.dart';
11 import 'package:front_end/src/base/api_signature.dart';
12 import 'package:front_end/src/base/performace_logger.dart';
10 import 'package:front_end/src/base/processed_options.dart'; 13 import 'package:front_end/src/base/processed_options.dart';
11 import 'package:front_end/src/fasta/dill/dill_target.dart'; 14 import 'package:front_end/src/fasta/dill/dill_target.dart';
12 import 'package:front_end/src/fasta/kernel/kernel_target.dart'; 15 import 'package:front_end/src/fasta/kernel/kernel_target.dart';
13 import 'package:front_end/src/fasta/ticker.dart'; 16 import 'package:front_end/src/fasta/ticker.dart';
14 import 'package:front_end/src/fasta/translate_uri.dart'; 17 import 'package:front_end/src/fasta/translate_uri.dart';
18 import 'package:front_end/src/incremental/byte_store.dart';
15 import 'package:front_end/src/incremental/file_state.dart'; 19 import 'package:front_end/src/incremental/file_state.dart';
20 import 'package:kernel/binary/ast_from_binary.dart';
21 import 'package:kernel/binary/ast_to_binary.dart';
16 import 'package:kernel/kernel.dart' hide Source; 22 import 'package:kernel/kernel.dart' hide Source;
17 import 'package:kernel/target/vm.dart';
18 23
19 dynamic unimplemented() { 24 dynamic unimplemented() {
20 // TODO(paulberry): get rid of this. 25 // TODO(paulberry): get rid of this.
21 throw new UnimplementedError(); 26 throw new UnimplementedError();
22 } 27 }
23 28
29 class ByteSink implements Sink<List<int>> {
30 final BytesBuilder builder = new BytesBuilder();
31
32 void add(List<int> data) {
33 builder.add(data);
34 }
35
36 void close() {}
37 }
38
24 /// Implementation of [IncrementalKernelGenerator]. 39 /// Implementation of [IncrementalKernelGenerator].
25 /// 40 ///
26 /// TODO(scheglov) Update the documentation. 41 /// TODO(scheglov) Update the documentation.
27 /// 42 ///
28 /// Theory of operation: an instance of [IncrementalResolvedAstGenerator] is 43 /// Theory of operation: an instance of [IncrementalResolvedAstGenerator] is
29 /// used to obtain resolved ASTs, and these are fed into kernel code generation 44 /// used to obtain resolved ASTs, and these are fed into kernel code generation
30 /// logic. 45 /// logic.
31 class IncrementalKernelGeneratorImpl implements IncrementalKernelGenerator { 46 class IncrementalKernelGeneratorImpl implements IncrementalKernelGenerator {
32 /// The compiler options, such as the [FileSystem], the SDK dill location, 47 /// The compiler options, such as the [FileSystem], the SDK dill location,
33 /// etc. 48 /// etc.
34 final ProcessedOptions _options; 49 final ProcessedOptions _options;
35 50
36 /// The object that knows how to resolve "package:" and "dart:" URIs. 51 /// The object that knows how to resolve "package:" and "dart:" URIs.
37 final TranslateUri _uriTranslator; 52 final TranslateUri _uriTranslator;
38 53
54 /// The logger to report compilation progress.
55 final PerformanceLog _logger;
56
39 /// The current file system state. 57 /// The current file system state.
40 final FileSystemState _fsState; 58 final FileSystemState _fsState;
41 59
60 /// The byte storage to get and put serialized data.
61 final ByteStore _byteStore;
62
42 /// The URI of the program entry point. 63 /// The URI of the program entry point.
43 final Uri _entryPoint; 64 final Uri _entryPoint;
44 65
45 /// The set of absolute file URIs that were reported through [invalidate] 66 /// The set of absolute file URIs that were reported through [invalidate]
46 /// and not checked for actual changes yet. 67 /// and not checked for actual changes yet.
47 final Set<Uri> _invalidatedFiles = new Set<Uri>(); 68 final Set<Uri> _invalidatedFiles = new Set<Uri>();
48 69
49 /// The cached SDK kernel.
50 DillTarget _sdkDillTarget;
51
52 IncrementalKernelGeneratorImpl( 70 IncrementalKernelGeneratorImpl(
53 this._options, this._uriTranslator, this._entryPoint) 71 this._options, this._uriTranslator, this._entryPoint)
54 : _fsState = new FileSystemState(_options.fileSystem, _uriTranslator); 72 : _logger = _options.logger,
73 _fsState = new FileSystemState(_options.fileSystem, _uriTranslator),
74 _byteStore = _options.byteStore;
55 75
56 @override 76 @override
57 Future<DeltaProgram> computeDelta( 77 Future<DeltaProgram> computeDelta(
58 {Future<Null> watch(Uri uri, bool used)}) async { 78 {Future<Null> watch(Uri uri, bool used)}) async {
59 await _ensureVmLibrariesLoaded(); 79 return await _logger.runAsync('Compute delta', () async {
60 await _refreshInvalidatedFiles(); 80 await _refreshInvalidatedFiles();
61 81
62 // Ensure that the graph starting at the entry point is ready. 82 // Ensure that the graph starting at the entry point is ready.
63 await _fsState.getFile(_entryPoint); 83 FileState entryLibrary = await _fsState.getFile(_entryPoint);
64 84
65 DillTarget sdkTarget = await _getSdkDillTarget(); 85 List<LibraryCycle> cycles = _logger.run('Compute library cycles', () {
66 // TODO(scheglov) Use it to also serve other package kernels. 86 List<LibraryCycle> cycles = entryLibrary.topologicalOrder;
87 _logger.writeln('Computed ${cycles.length} cycles.');
88 return cycles;
89 });
67 90
68 KernelTarget kernelTarget = new KernelTarget(_fsState.fileSystemView, 91 CanonicalName nameRoot = new CanonicalName.root();
69 sdkTarget, _uriTranslator, _options.strongMode, null); 92 DillTarget dillTarget =
70 kernelTarget.read(_entryPoint); 93 new DillTarget(new Ticker(isVerbose: false), _uriTranslator);
71 94
72 // TODO(scheglov) Replace with a better API. 95 List<_LibraryCycleResult> results = [];
73 // Firstly, we don't "write" anything here. 96 await _logger.runAsync('Compute results for cycles', () async {
74 // Secondly, it catches all the exceptions and write them to `stderr`. 97 for (LibraryCycle cycle in cycles) {
75 // This is too interactive and not API-clients friendly. 98 _LibraryCycleResult result =
76 await kernelTarget.writeOutline(null); 99 await _compileCycle(nameRoot, dillTarget, cycle);
100 results.add(result);
101 }
102 });
77 103
78 // TODO(scheglov) Replace with a better API. 104 Program program = new Program(nameRoot: nameRoot);
79 Program program = await kernelTarget.writeProgram(null); 105 for (_LibraryCycleResult result in results) {
80 return new DeltaProgram(program); 106 program.libraries.addAll(result.kernelLibraries);
107 }
108
109 return new DeltaProgram(program);
110 });
81 } 111 }
82 112
83 @override 113 @override
84 void invalidate(Uri uri) { 114 void invalidate(Uri uri) {
85 _invalidatedFiles.add(uri); 115 _invalidatedFiles.add(uri);
86 } 116 }
87 117
88 @override 118 @override
89 void invalidateAll() => unimplemented(); 119 void invalidateAll() => unimplemented();
90 120
91 /// Fasta unconditionally loads all VM libraries. In order to be able to 121 /// Ensure that [dillTarget] includes the [cycle] libraries. It already
92 /// serve them using the file system view, we need to ask [_fsState] for 122 /// contains all the libraries that sorted before the given [cycle] in
93 /// the corresponding files. 123 /// topological order. Return the result with the cycle libraries.
94 Future<Null> _ensureVmLibrariesLoaded() async { 124 Future<_LibraryCycleResult> _compileCycle(
95 List<String> extraLibraries = new VmTarget(null).extraRequiredLibraries; 125 CanonicalName nameRoot, DillTarget dillTarget, LibraryCycle cycle) async {
96 for (String absoluteUriStr in extraLibraries) { 126 return _logger.runAsync('Compile cycle $cycle', () async {
97 Uri absoluteUri = Uri.parse(absoluteUriStr); 127 String signature;
98 Uri fileUri = _uriTranslator.translate(absoluteUri); 128 {
99 await _fsState.getFile(fileUri); 129 var signatureBuilder = new ApiSignature();
100 } 130 // TODO(scheglov) add salt
101 } 131 // signature.addUint32List(_fsState._salt);
132 Set<FileState> transitiveFiles = cycle.libraries
133 .map((library) => library.transitiveFiles)
134 .expand((files) => files)
135 .toSet();
136 signatureBuilder.addInt(transitiveFiles.length);
137 for (FileState file in transitiveFiles) {
138 signatureBuilder.addString(file.uri.toString());
139 // TODO(scheglov) use API signature
140 signatureBuilder.addBytes(file.contentHash);
141 }
142 signature = signatureBuilder.toHex();
143 }
102 144
103 /// Return the [DillTarget] that is used inside of [KernelTarget] to 145 _logger.writeln('Signature: $signature.');
104 /// resynthesize SDK libraries. 146 String kernelKey = '$signature.kernel';
105 Future<DillTarget> _getSdkDillTarget() async { 147
106 if (_sdkDillTarget == null) { 148 /// We need kernel libraries for these URIs.
107 _sdkDillTarget = 149 Set<Uri> libraryUris = new Set<Uri>();
108 new DillTarget(new Ticker(isVerbose: false), _uriTranslator); 150 for (FileState library in cycle.libraries) {
109 // TODO(scheglov) Read the SDK kernel. 151 libraryUris.add(library.uri);
110 // _sdkDillTarget.read(options.sdkSummary); 152 }
111 // await _sdkDillTarget.writeOutline(null); 153
112 } else { 154 /// Check if there is already a bundle with these libraries.
113 // Program sdkProgram = _sdkDillTarget.loader.program; 155 List<int> bytes = _byteStore.get(kernelKey);
114 // sdkProgram.visitChildren(new _ClearCanonicalNamesVisitor()); 156 if (bytes != null) {
115 } 157 return _logger.run('Read serialized libraries', () {
116 return _sdkDillTarget; 158 var program = new Program(nameRoot: nameRoot);
159 var reader = new BinaryBuilder(bytes);
160 reader.readProgram(program);
161 dillTarget.loader
162 .appendLibraries(program, (uri) => libraryUris.contains(uri));
163 return new _LibraryCycleResult(cycle, signature, program.libraries);
164 });
165 }
166
167 // Ask DILL to fill outlines using loaded libraries.
168 await dillTarget.writeOutline(null);
169
170 // Create KernelTarget and configure it for compiling the cycle URIs.
171 KernelTarget kernelTarget = new KernelTarget(_fsState.fileSystemView,
172 dillTarget, _uriTranslator, _options.strongMode);
173 for (FileState library in cycle.libraries) {
174 kernelTarget.read(library.uri);
175 }
176
177 // Compile the cycle libraries into a new full program.
178 Program program = await _logger.runAsync(
179 'Compile ${cycle.libraries.length} cycle libraries', () async {
180 await kernelTarget.writeOutline(null, nameRoot: nameRoot);
181 return await kernelTarget.writeProgram(null);
182 });
183
184 // Add newly compiled libraries into DILL.
185 List<Library> kernelLibraries = program.libraries
186 .where((library) => libraryUris.contains(library.importUri))
187 .toList();
188 dillTarget.loader
189 .appendLibraries(program, (uri) => libraryUris.contains(uri));
190
191 _logger.run('Serialize ${kernelLibraries.length} libraries', () {
192 program.unbindCanonicalNames();
193 List<int> bytes = _writeProgramBytes(program, kernelLibraries.contains);
194 _byteStore.put(kernelKey, bytes);
195 _logger.writeln('Stored ${bytes.length} bytes.');
196 });
197
198 return new _LibraryCycleResult(cycle, signature, kernelLibraries);
199 });
117 } 200 }
118 201
119 /// Refresh all the invalidated files and update dependencies. 202 /// Refresh all the invalidated files and update dependencies.
120 Future<Null> _refreshInvalidatedFiles() async { 203 Future<Null> _refreshInvalidatedFiles() async {
121 for (Uri fileUri in _invalidatedFiles) { 204 await _logger.runAsync('Refresh invalidated files', () async {
122 FileState file = await _fsState.getFile(fileUri); 205 for (Uri fileUri in _invalidatedFiles) {
123 await file.refresh(); 206 FileState file = await _fsState.getFile(fileUri);
124 } 207 await file.refresh();
125 _invalidatedFiles.clear(); 208 }
209 _invalidatedFiles.clear();
210 });
211 }
212
213 List<int> _writeProgramBytes(Program program, bool filter(Library library)) {
214 ByteSink byteSink = new ByteSink();
215 new LibraryFilteringBinaryPrinter(byteSink, filter)
216 .writeProgramFile(program);
217 return byteSink.builder.takeBytes();
126 } 218 }
127 } 219 }
220
221 /// TODO(scheglov) document
Paul Berry 2017/05/12 22:24:57 Please document this before committing.
scheglov 2017/05/13 02:32:59 Done.
222 class _LibraryCycleResult {
223 final LibraryCycle cycle;
224 final String signature;
225 final List<Library> kernelLibraries;
226
227 _LibraryCycleResult(this.cycle, this.signature, this.kernelLibraries);
228 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698