OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
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.md file. | |
4 | |
5 library fletchc_incremental.fletch_reuser; | |
6 | |
7 import 'package:compiler/compiler_new.dart' show | |
8 CompilerDiagnostics, | |
9 Diagnostic; | |
10 | |
11 import 'package:compiler/compiler.dart' as api; | |
12 | |
13 import 'package:compiler/src/compiler.dart' show | |
14 Compiler; | |
15 | |
16 import 'package:compiler/src/enqueue.dart' show | |
17 EnqueueTask; | |
18 | |
19 import 'package:compiler/src/elements/elements.dart' show | |
20 AstElement, | |
21 ClassElement, | |
22 Element, | |
23 FieldElement, | |
24 FunctionElement; | |
25 | |
26 import 'package:compiler/src/parser/partial_elements.dart' show | |
27 PartialClassElement, | |
28 PartialElement, | |
29 PartialFunctionElement; | |
30 | |
31 import 'package:compiler/src/elements/modelx.dart' show | |
32 ClassElementX, | |
33 FieldElementX, | |
34 LibraryElementX; | |
35 | |
36 import 'package:compiler/src/constants/values.dart' show | |
37 ConstantValue; | |
38 | |
39 import '../incremental_backend.dart' show | |
40 IncrementalFletchBackend; | |
41 | |
42 import '../src/fletch_class_builder.dart' show | |
43 FletchClassBuilder; | |
44 | |
45 import '../src/fletch_context.dart' show | |
46 FletchContext; | |
47 | |
48 import '../src/fletch_compiler_implementation.dart' show | |
49 FletchCompilerImplementation; | |
50 | |
51 import '../src/fletch_function_builder.dart' show | |
52 FletchFunctionBuilder; | |
53 | |
54 import '../vm_commands.dart' show | |
55 PrepareForChanges, | |
56 VmCommand; | |
57 | |
58 import '../fletch_system.dart' show | |
59 FletchDelta, | |
60 FletchSystem; | |
61 | |
62 import 'fletchc_incremental.dart' show | |
63 IncrementalCompilationFailed, | |
64 IncrementalCompiler; | |
65 | |
66 import 'reuser.dart' show | |
67 AddedClassUpdate, | |
68 AddedFieldUpdate, | |
69 AddedFunctionUpdate, | |
70 ClassUpdate, | |
71 Logger, | |
72 RemovedClassUpdate, | |
73 RemovedFieldUpdate, | |
74 RemovedFunctionUpdate, | |
75 Reuser; | |
76 | |
77 export 'reuser.dart' show | |
78 Logger; | |
79 | |
80 abstract class _IncrementalCompilerContext { | |
81 IncrementalCompiler incrementalCompiler; | |
82 } | |
83 | |
84 class IncrementalCompilerContext extends _IncrementalCompilerContext | |
85 implements CompilerDiagnostics { | |
86 final CompilerDiagnostics diagnostics; | |
87 int errorCount = 0; | |
88 int warningCount = 0; | |
89 int hintCount = 0; | |
90 | |
91 final Set<Uri> _uriWithUpdates = new Set<Uri>(); | |
92 | |
93 IncrementalCompilerContext(this.diagnostics); | |
94 | |
95 int get problemCount => errorCount + warningCount + hintCount; | |
96 | |
97 void set incrementalCompiler(IncrementalCompiler value) { | |
98 if (super.incrementalCompiler != null) { | |
99 throw new StateError("Can't set [incrementalCompiler] more than once"); | |
100 } | |
101 super.incrementalCompiler = value; | |
102 } | |
103 | |
104 void registerUriWithUpdates(Iterable<Uri> uris) { | |
105 _uriWithUpdates.addAll(uris); | |
106 } | |
107 | |
108 bool _uriHasUpdate(Uri uri) => _uriWithUpdates.contains(uri); | |
109 | |
110 void report( | |
111 var code, | |
112 Uri uri, | |
113 int begin, | |
114 int end, | |
115 String text, | |
116 Diagnostic kind) { | |
117 if (kind == Diagnostic.ERROR) { | |
118 errorCount++; | |
119 } | |
120 if (kind == Diagnostic.WARNING) { | |
121 warningCount++; | |
122 } | |
123 if (kind == Diagnostic.HINT) { | |
124 hintCount++; | |
125 } | |
126 diagnostics.report(code, uri, begin, end, text, kind); | |
127 } | |
128 } | |
129 | |
130 class FletchReuser extends Reuser with FletchFeatures { | |
131 final IncrementalCompilerContext _context; | |
132 | |
133 FletchReuser( | |
134 FletchCompilerImplementation compiler, | |
135 api.CompilerInputProvider inputProvider, | |
136 Logger logTime, | |
137 Logger logVerbose, | |
138 this._context) | |
139 : super(compiler, inputProvider, logTime, logVerbose); | |
140 | |
141 FletchDelta computeUpdateFletch(FletchSystem currentSystem) { | |
142 // TODO(ahe): Remove this when we support adding static fields. | |
143 Set<Element> existingStaticFields = | |
144 new Set<Element>.from(fletchContext.staticIndices.keys); | |
145 | |
146 backend.newSystemBuilder(currentSystem); | |
147 | |
148 List<Element> updatedElements = applyUpdates(); | |
149 | |
150 if (compiler.progress != null) { | |
151 compiler.progress.reset(); | |
152 } | |
153 | |
154 for (Element element in updatedElements) { | |
155 if (!element.isClass) { | |
156 if (element.isClassMember) { | |
157 element.enclosingClass.ensureResolved(compiler.resolution); | |
158 } | |
159 enqueuer.resolution.addToWorkList(element); | |
160 } else { | |
161 ClassElement cls = element; | |
162 cls.ensureResolved(compiler.resolution); | |
163 | |
164 // We've told the enqueuer to forget this class, now tell it that it's | |
165 // in use again. TODO(ahe): We only need to do this if [cls] was | |
166 // already instantiated. | |
167 enqueuer.codegen.registerInstantiatedType(cls.rawType); | |
168 } | |
169 } | |
170 compiler.processQueue(enqueuer.resolution, null); | |
171 | |
172 compiler.phase = Compiler.PHASE_DONE_RESOLVING; | |
173 | |
174 // TODO(ahe): Clean this up. Don't call this method in analyze-only mode. | |
175 if (compiler.analyzeOnly) { | |
176 return new FletchDelta(currentSystem, currentSystem, <VmCommand>[]); | |
177 } | |
178 | |
179 for (AstElement element in updatedElements) { | |
180 if (element.node.isErroneous) { | |
181 throw new IncrementalCompilationFailed( | |
182 "Unable to incrementally compile $element with syntax error"); | |
183 } | |
184 if (element.isField) { | |
185 backend.newElement(element); | |
186 } else if (!element.isClass) { | |
187 enqueuer.codegen.addToWorkList(element); | |
188 } | |
189 } | |
190 compiler.processQueue(enqueuer.codegen, null); | |
191 | |
192 // TODO(ahe): Remove this when we support adding static fields. | |
193 Set<Element> newStaticFields = | |
194 new Set<Element>.from(fletchContext.staticIndices.keys).difference( | |
195 existingStaticFields); | |
196 if (newStaticFields.isNotEmpty) { | |
197 throw new IncrementalCompilationFailed( | |
198 "Unable to add static fields:\n ${newStaticFields.join(',\n ')}"); | |
199 } | |
200 | |
201 List<VmCommand> commands = <VmCommand>[const PrepareForChanges()]; | |
202 FletchSystem system = | |
203 backend.systemBuilder.computeSystem(fletchContext, commands); | |
204 return new FletchDelta(system, currentSystem, commands); | |
205 } | |
206 | |
207 void addClassUpdate( | |
208 Compiler compiler, | |
209 PartialClassElement before, | |
210 PartialClassElement after) { | |
211 updates.add(new FletchClassUpdate(compiler, before, after)); | |
212 } | |
213 | |
214 void addAddedFunctionUpdate( | |
215 Compiler compiler, | |
216 PartialFunctionElement element, | |
217 /* ScopeContainerElement */ container) { | |
218 updates.add(new FletchAddedFunctionUpdate(compiler, element, container)); | |
219 } | |
220 | |
221 void addRemovedFunctionUpdate( | |
222 Compiler compiler, | |
223 PartialFunctionElement element) { | |
224 updates.add(new FletchRemovedFunctionUpdate(compiler, element)); | |
225 } | |
226 | |
227 void addRemovedFieldUpdate( | |
228 Compiler compiler, | |
229 FieldElementX element) { | |
230 updates.add(new FletchRemovedFieldUpdate(compiler, element)); | |
231 } | |
232 | |
233 void addRemovedClassUpdate( | |
234 Compiler compiler, | |
235 PartialClassElement element) { | |
236 updates.add(new FletchRemovedClassUpdate(compiler, element)); | |
237 } | |
238 | |
239 void addAddedFieldUpdate( | |
240 Compiler compiler, | |
241 FieldElementX element, | |
242 /* ScopeContainerElement */ container) { | |
243 updates.add(new FletchAddedFieldUpdate(compiler, element, container)); | |
244 } | |
245 | |
246 void addAddedClassUpdate( | |
247 Compiler compiler, | |
248 PartialClassElement element, | |
249 LibraryElementX library) { | |
250 updates.add(new FletchAddedClassUpdate(compiler, element, library)); | |
251 } | |
252 | |
253 static void forEachField(ClassElement c, void action(FieldElement field)) { | |
254 List classes = []; | |
255 while (c != null) { | |
256 if (!c.isResolved) { | |
257 throw new IncrementalCompilationFailed("Class not resolved: $c"); | |
258 } | |
259 classes.add(c); | |
260 c = c.superclass; | |
261 } | |
262 for (int i = classes.length - 1; i >= 0; i--) { | |
263 classes[i].implementation.forEachInstanceField((_, FieldElement field) { | |
264 action(field); | |
265 }); | |
266 } | |
267 } | |
268 | |
269 bool uriHasUpdate(Uri uri) => _context._uriHasUpdate(uri); | |
270 | |
271 bool allowClassHeaderModified(PartialClassElement after) { | |
272 if (!_context.incrementalCompiler.isExperimentalModeEnabled) { | |
273 return cannotReuse( | |
274 after, | |
275 "Changing a class header requires requires 'experimental' mode"); | |
276 } | |
277 return true; | |
278 } | |
279 | |
280 bool allowSignatureChanged( | |
281 PartialFunctionElement before, | |
282 PartialFunctionElement after) { | |
283 if (!_context.incrementalCompiler.isExperimentalModeEnabled) { | |
284 return cannotReuse( | |
285 after, "Signature change requires 'experimental' mode"); | |
286 } | |
287 return true; | |
288 } | |
289 | |
290 bool allowNonInstanceMemberModified(PartialFunctionElement after) { | |
291 if (!_context.incrementalCompiler.isExperimentalModeEnabled) { | |
292 return cannotReuse( | |
293 after, "Non-instance member requires 'experimental' mode"); | |
294 } | |
295 return true; | |
296 } | |
297 | |
298 bool allowRemovedElement(PartialElement element) { | |
299 if (!_context.incrementalCompiler.isExperimentalModeEnabled) { | |
300 return cannotReuse( | |
301 element, "Removing elements requires 'experimental' mode"); | |
302 } | |
303 return true; | |
304 } | |
305 | |
306 bool allowAddedElement(PartialElement element) { | |
307 if (!_context.incrementalCompiler.isExperimentalModeEnabled) { | |
308 return cannotReuse( | |
309 element, "Adding elements requires 'experimental' mode"); | |
310 } | |
311 return true; | |
312 } | |
313 } | |
314 | |
315 class FletchRemovedFunctionUpdate extends RemovedFunctionUpdate | |
316 with FletchFeatures { | |
317 FletchRemovedFunctionUpdate(Compiler compiler, PartialFunctionElement element) | |
318 : super(compiler, element); | |
319 } | |
320 | |
321 class FletchRemovedClassUpdate extends RemovedClassUpdate with FletchFeatures { | |
322 FletchRemovedClassUpdate(Compiler compiler, PartialClassElement element) | |
323 : super(compiler, element); | |
324 } | |
325 | |
326 class FletchRemovedFieldUpdate extends RemovedFieldUpdate with FletchFeatures { | |
327 // TODO(ahe): Remove? | |
328 FletchClassBuilder beforeFletchClassBuilder; | |
329 | |
330 FletchRemovedFieldUpdate(Compiler compiler, FieldElementX element) | |
331 : super(compiler, element); | |
332 } | |
333 | |
334 class FletchAddedFunctionUpdate extends AddedFunctionUpdate | |
335 with FletchFeatures { | |
336 FletchAddedFunctionUpdate( | |
337 Compiler compiler, | |
338 PartialFunctionElement element, | |
339 /* ScopeContainerElement */ container) | |
340 : super(compiler, element, container); | |
341 } | |
342 | |
343 class FletchAddedClassUpdate extends AddedClassUpdate with FletchFeatures { | |
344 FletchAddedClassUpdate( | |
345 Compiler compiler, | |
346 PartialClassElement element, | |
347 LibraryElementX library) | |
348 : super(compiler, element, library); | |
349 } | |
350 | |
351 class FletchAddedFieldUpdate extends AddedFieldUpdate with FletchFeatures { | |
352 FletchAddedFieldUpdate( | |
353 Compiler compiler, | |
354 FieldElementX element, | |
355 /* ScopeContainerElement */ container) | |
356 : super(compiler, element, container); | |
357 } | |
358 | |
359 class FletchClassUpdate extends ClassUpdate with FletchFeatures { | |
360 FletchClassUpdate( | |
361 Compiler compiler, | |
362 PartialClassElement before, | |
363 PartialClassElement after) | |
364 : super(compiler, before, after); | |
365 } | |
366 | |
367 abstract class FletchFeatures { | |
368 FletchCompilerImplementation get compiler; | |
369 | |
370 IncrementalFletchBackend get backend { | |
371 return compiler.backend as IncrementalFletchBackend; | |
372 } | |
373 | |
374 EnqueueTask get enqueuer => compiler.enqueuer; | |
375 | |
376 FletchContext get fletchContext => compiler.context; | |
377 | |
378 FletchFunctionBuilder lookupFletchFunctionBuilder(FunctionElement function) { | |
379 return backend.systemBuilder.lookupFunctionBuilderByElement(function); | |
380 } | |
381 } | |
OLD | NEW |