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

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

Issue 2993393002: Enforce single computeDelta() invocation. (Closed)
Patch Set: Fixes for review comments. Created 3 years, 4 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
« no previous file with comments | « no previous file | pkg/front_end/test/incremental_kernel_generator_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 6
7 import 'package:front_end/incremental_kernel_generator.dart'; 7 import 'package:front_end/incremental_kernel_generator.dart';
8 import 'package:front_end/src/base/performace_logger.dart'; 8 import 'package:front_end/src/base/performace_logger.dart';
9 import 'package:front_end/src/base/processed_options.dart'; 9 import 'package:front_end/src/base/processed_options.dart';
10 import 'package:front_end/src/fasta/uri_translator.dart'; 10 import 'package:front_end/src/fasta/uri_translator.dart';
11 import 'package:front_end/src/incremental/file_state.dart'; 11 import 'package:front_end/src/incremental/file_state.dart';
12 import 'package:front_end/src/incremental/kernel_driver.dart'; 12 import 'package:front_end/src/incremental/kernel_driver.dart';
13 import 'package:kernel/kernel.dart' hide Source; 13 import 'package:kernel/kernel.dart' hide Source;
14 import 'package:meta/meta.dart'; 14 import 'package:meta/meta.dart';
15 15
16 /// Implementation of [IncrementalKernelGenerator]. 16 /// Implementation of [IncrementalKernelGenerator].
17 /// 17 ///
18 /// TODO(scheglov) Update the documentation. 18 /// TODO(scheglov) Update the documentation.
19 /// 19 ///
20 /// Theory of operation: an instance of [IncrementalResolvedAstGenerator] is 20 /// Theory of operation: an instance of [IncrementalResolvedAstGenerator] is
21 /// used to obtain resolved ASTs, and these are fed into kernel code generation 21 /// used to obtain resolved ASTs, and these are fed into kernel code generation
22 /// logic. 22 /// logic.
23 class IncrementalKernelGeneratorImpl implements IncrementalKernelGenerator { 23 class IncrementalKernelGeneratorImpl implements IncrementalKernelGenerator {
24 /// The version of data format, should be incremented on every format change. 24 static const MSG_PENDING_COMPUTE =
Siggi Cherem (dart-lang) 2017/08/11 00:44:52 not for this CL: even if we don't report them on t
scheglov 2017/08/11 04:50:40 Yes, is seems like it might be useful to put into
25 static const int DATA_VERSION = 1; 25 'Another computeDelta() invocation is still executing.';
Siggi Cherem (dart-lang) 2017/08/11 00:44:52 Consider: Another => A (since now this message is
scheglov 2017/08/11 04:50:40 Done.
26
27 static const MSG_NO_LAST_DELTA =
28 'The last delta has been already accepted or rejected.';
29
30 static const MSG_HAS_LAST_DELTA =
31 'The last delta must be either accepted or rejected.';
26 32
27 /// The logger to report compilation progress. 33 /// The logger to report compilation progress.
28 final PerformanceLog _logger; 34 final PerformanceLog _logger;
29 35
30 /// The URI of the program entry point. 36 /// The URI of the program entry point.
31 final Uri _entryPoint; 37 final Uri _entryPoint;
32 38
33 /// The function to notify when files become used or unused, or `null`. 39 /// The function to notify when files become used or unused, or `null`.
34 final WatchUsedFilesFn _watchFn; 40 final WatchUsedFilesFn _watchFn;
35 41
36 /// The [KernelDriver] that is used to compute kernels. 42 /// The [KernelDriver] that is used to compute kernels.
37 KernelDriver _driver; 43 KernelDriver _driver;
38 44
45 /// Whether [computeDelta] is executing.
46 bool _isComputeDeltaExecuting = false;
47
39 /// The current signatures for libraries. 48 /// The current signatures for libraries.
40 final Map<Uri, String> _currentSignatures = {}; 49 final Map<Uri, String> _currentSignatures = {};
41 50
42 /// The signatures for libraries produced by the last [computeDelta], or 51 /// The signatures for libraries produced by the last [computeDelta], or
43 /// `null` if the last delta was either accepted or rejected. 52 /// `null` if the last delta was either accepted or rejected.
44 Map<Uri, String> _lastSignatures; 53 Map<Uri, String> _lastSignatures;
45 54
46 /// The object that provides additional information for tests. 55 /// The object that provides additional information for tests.
47 _TestView _testView; 56 _TestView _testView;
48 57
(...skipping 20 matching lines...) Expand all
69 _TestView get test => _testView; 78 _TestView get test => _testView;
70 79
71 @override 80 @override
72 void acceptLastDelta() { 81 void acceptLastDelta() {
73 _throwIfNoLastDelta(); 82 _throwIfNoLastDelta();
74 _currentSignatures.addAll(_lastSignatures); 83 _currentSignatures.addAll(_lastSignatures);
75 _lastSignatures = null; 84 _lastSignatures = null;
76 } 85 }
77 86
78 @override 87 @override
79 Future<DeltaProgram> computeDelta() async { 88 Future<DeltaProgram> computeDelta() {
89 if (_isComputeDeltaExecuting) {
90 throw new StateError(MSG_PENDING_COMPUTE);
91 }
92
80 if (_lastSignatures != null) { 93 if (_lastSignatures != null) {
81 throw new StateError( 94 throw new StateError(MSG_HAS_LAST_DELTA);
82 'The last delta must be either accepted or rejected.');
83 } 95 }
84 _lastSignatures = {}; 96 _lastSignatures = {};
85 97
86 return await _logger.runAsync('Compute delta', () async { 98 _isComputeDeltaExecuting = true;
87 KernelResult kernelResult = await _driver.getKernel(_entryPoint);
88 List<LibraryCycleResult> results = kernelResult.results;
89 99
90 // The file graph might have changed, perform GC. 100 return _logger.runAsync('Compute delta', () async {
91 await _gc(); 101 try {
102 KernelResult kernelResult = await _driver.getKernel(_entryPoint);
103 List<LibraryCycleResult> results = kernelResult.results;
92 104
93 // The set of affected library cycles (have different signatures). 105 // The file graph might have changed, perform GC.
94 final affectedLibraryCycles = new Set<LibraryCycle>(); 106 await _gc();
95 for (LibraryCycleResult result in results) { 107
96 for (Library library in result.kernelLibraries) { 108 // The set of affected library cycles (have different signatures).
97 Uri uri = library.importUri; 109 final affectedLibraryCycles = new Set<LibraryCycle>();
98 if (_currentSignatures[uri] != result.signature) { 110 for (LibraryCycleResult result in results) {
99 _lastSignatures[uri] = result.signature; 111 for (Library library in result.kernelLibraries) {
100 affectedLibraryCycles.add(result.cycle); 112 Uri uri = library.importUri;
113 if (_currentSignatures[uri] != result.signature) {
114 _lastSignatures[uri] = result.signature;
115 affectedLibraryCycles.add(result.cycle);
116 }
101 } 117 }
102 } 118 }
103 }
104 119
105 // The set of affected library cycles (have different signatures), 120 // The set of affected library cycles (have different signatures),
106 // or libraries that import or export affected libraries (so VM might 121 // or libraries that import or export affected libraries (so VM might
107 // have inlined some code from affected libraries into them). 122 // have inlined some code from affected libraries into them).
108 final vmRequiredLibraryCycles = new Set<LibraryCycle>(); 123 final vmRequiredLibraryCycles = new Set<LibraryCycle>();
109 124
110 void gatherVmRequiredLibraryCycles(LibraryCycle cycle) { 125 void gatherVmRequiredLibraryCycles(LibraryCycle cycle) {
111 if (vmRequiredLibraryCycles.add(cycle)) { 126 if (vmRequiredLibraryCycles.add(cycle)) {
112 cycle.directUsers.forEach(gatherVmRequiredLibraryCycles); 127 cycle.directUsers.forEach(gatherVmRequiredLibraryCycles);
113 }
114 }
115
116 affectedLibraryCycles.forEach(gatherVmRequiredLibraryCycles);
117
118 // Add required libraries.
119 Program program = new Program(nameRoot: kernelResult.nameRoot);
120 for (LibraryCycleResult result in results) {
121 if (vmRequiredLibraryCycles.contains(result.cycle)) {
122 for (Library library in result.kernelLibraries) {
123 program.libraries.add(library);
124 library.parent = program;
125 } 128 }
126 } 129 }
127 }
128 130
129 // Set the main method. 131 affectedLibraryCycles.forEach(gatherVmRequiredLibraryCycles);
130 if (program.libraries.isNotEmpty) { 132
131 for (Library library in results.last.kernelLibraries) { 133 // Add required libraries.
132 if (library.importUri == _entryPoint) { 134 Program program = new Program(nameRoot: kernelResult.nameRoot);
133 program.mainMethod = library.procedures.firstWhere( 135 for (LibraryCycleResult result in results) {
134 (procedure) => procedure.name.name == 'main', 136 if (vmRequiredLibraryCycles.contains(result.cycle)) {
135 orElse: () => null); 137 for (Library library in result.kernelLibraries) {
136 break; 138 program.libraries.add(library);
139 library.parent = program;
140 }
137 } 141 }
138 } 142 }
143
144 // Set the main method.
145 if (program.libraries.isNotEmpty) {
146 for (Library library in results.last.kernelLibraries) {
147 if (library.importUri == _entryPoint) {
148 program.mainMethod = library.procedures.firstWhere(
149 (procedure) => procedure.name.name == 'main',
150 orElse: () => null);
151 break;
152 }
153 }
154 }
155
156 return new DeltaProgram(program);
157 } finally {
158 _isComputeDeltaExecuting = false;
139 } 159 }
140
141 return new DeltaProgram(program);
142 }); 160 });
143 } 161 }
144 162
145 @override 163 @override
146 void invalidate(Uri uri) { 164 void invalidate(Uri uri) {
147 _driver.invalidate(uri); 165 _driver.invalidate(uri);
148 } 166 }
149 167
150 @override 168 @override
151 void rejectLastDelta() { 169 void rejectLastDelta() {
152 _throwIfNoLastDelta(); 170 _throwIfNoLastDelta();
153 _lastSignatures = null; 171 _lastSignatures = null;
154 } 172 }
155 173
156 /// TODO(scheglov) document 174 /// Find files which are not referenced from the entry point and report
175 /// them to the watch function.
157 Future<Null> _gc() async { 176 Future<Null> _gc() async {
158 var removedFiles = _driver.fsState.gc(_entryPoint); 177 var removedFiles = _driver.fsState.gc(_entryPoint);
159 if (removedFiles.isNotEmpty && _watchFn != null) { 178 if (removedFiles.isNotEmpty && _watchFn != null) {
160 for (var removedFile in removedFiles) { 179 for (var removedFile in removedFiles) {
161 await _watchFn(removedFile.fileUri, false); 180 await _watchFn(removedFile.fileUri, false);
162 } 181 }
163 } 182 }
164 } 183 }
165 184
166 /// Throw [StateError] if [_lastSignatures] is `null`, i.e. there is no 185 /// Throw [StateError] if [_lastSignatures] is `null`, i.e. there is no
167 /// last delta - it either has not been computed yet, or has been already 186 /// last delta - it either has not been computed yet, or has been already
168 /// accepted or rejected. 187 /// accepted or rejected.
169 void _throwIfNoLastDelta() { 188 void _throwIfNoLastDelta() {
189 if (_isComputeDeltaExecuting) {
190 throw new StateError(MSG_PENDING_COMPUTE);
191 }
170 if (_lastSignatures == null) { 192 if (_lastSignatures == null) {
171 throw new StateError( 193 throw new StateError(MSG_NO_LAST_DELTA);
172 'The last delta has been already accepted or rejected.');
173 } 194 }
174 } 195 }
175 } 196 }
176 197
177 @visibleForTesting 198 @visibleForTesting
178 class _TestView { 199 class _TestView {
179 final IncrementalKernelGeneratorImpl _generator; 200 final IncrementalKernelGeneratorImpl _generator;
180 201
181 _TestView(this._generator); 202 _TestView(this._generator);
182 203
183 /// The [KernelDriver] that is used to actually compile. 204 /// The [KernelDriver] that is used to actually compile.
184 KernelDriver get driver => _generator._driver; 205 KernelDriver get driver => _generator._driver;
185 } 206 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/test/incremental_kernel_generator_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698