| 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 |