Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 typedef ItemCompilationContext ItemCompilationContextCreator(); | 7 typedef ItemCompilationContext ItemCompilationContextCreator(); |
| 8 | 8 |
| 9 class EnqueueTask extends CompilerTask { | 9 class EnqueueTask extends CompilerTask { |
| 10 final ResolutionEnqueuer resolution; | 10 final ResolutionEnqueuer resolution; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 | 66 |
| 67 abstract class Enqueuer { | 67 abstract class Enqueuer { |
| 68 final String name; | 68 final String name; |
| 69 final Compiler compiler; // TODO(ahe): Remove this dependency. | 69 final Compiler compiler; // TODO(ahe): Remove this dependency. |
| 70 final ItemCompilationContextCreator itemCompilationContextCreator; | 70 final ItemCompilationContextCreator itemCompilationContextCreator; |
| 71 final Map<String, Link<Element>> instanceMembersByName | 71 final Map<String, Link<Element>> instanceMembersByName |
| 72 = new Map<String, Link<Element>>(); | 72 = new Map<String, Link<Element>>(); |
| 73 final Map<String, Link<Element>> instanceFunctionsByName | 73 final Map<String, Link<Element>> instanceFunctionsByName |
| 74 = new Map<String, Link<Element>>(); | 74 = new Map<String, Link<Element>>(); |
| 75 final Set<ClassElement> seenClasses = new Set<ClassElement>(); | 75 final Set<ClassElement> seenClasses = new Set<ClassElement>(); |
| 76 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | |
| 76 final Universe universe = new Universe(); | 77 final Universe universe = new Universe(); |
| 77 | 78 |
| 79 static final TRACE_MIRROR_ENQUEUING = false; | |
|
floitsch
2014/06/27 08:59:15
should we start making these things const X.fromEn
herhut
2014/06/27 12:34:35
I did not know it was that easy to read an environ
| |
| 80 | |
| 78 bool queueIsClosed = false; | 81 bool queueIsClosed = false; |
| 79 EnqueueTask task; | 82 EnqueueTask task; |
| 80 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 83 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 81 | 84 |
| 82 bool hasEnqueuedEverything = false; | 85 bool hasEnqueuedReflectiveElements = false; |
| 83 bool hasEnqueuedReflectiveStaticFields = false; | 86 bool hasEnqueuedReflectiveStaticFields = false; |
| 84 | 87 |
| 85 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); | 88 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); |
| 86 | 89 |
| 87 Queue<WorkItem> get queue; | 90 Queue<WorkItem> get queue; |
| 88 bool get queueIsEmpty => queue.isEmpty; | 91 bool get queueIsEmpty => queue.isEmpty; |
| 89 | 92 |
| 90 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 93 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 91 bool get isResolutionQueue => false; | 94 bool get isResolutionQueue => false; |
| 92 | 95 |
| 93 /// Returns [:true:] if [member] has been processed by this enqueuer. | 96 /// Returns [:true:] if [member] has been processed by this enqueuer. |
| 94 bool isProcessed(Element member); | 97 bool isProcessed(Element member); |
| 95 | 98 |
| 96 /** | 99 /** |
| 97 * Documentation wanted -- johnniwinther | 100 * Documentation wanted -- johnniwinther |
| 98 * | 101 * |
| 99 * Invariant: [element] must be a declaration element. | 102 * Invariant: [element] must be a declaration element. |
| 100 */ | 103 */ |
| 101 void addToWorkList(Element element) { | 104 void addToWorkList(Element element) { |
| 102 assert(invariant(element, element.isDeclaration)); | 105 assert(invariant(element, element.isDeclaration)); |
| 103 internalAddToWorkList(element); | 106 internalAddToWorkList(element); |
| 104 } | 107 } |
| 105 | 108 |
| 106 /** | 109 /** |
| 107 * Adds [element] to the work list if it has not already been processed. | 110 * Adds [element] to the work list if it has not already been processed. |
| 108 */ | 111 */ |
| 109 void internalAddToWorkList(Element element); | 112 void internalAddToWorkList(Element element); |
| 110 | 113 |
| 111 void registerInstantiatedType(InterfaceType type, Registry registry) { | 114 void registerInstantiatedType(InterfaceType type, Registry registry, |
| 115 {mirrorUsage: false}) { | |
|
karlklose
2014/06/27 07:45:57
Only use registerInstantiatedType for types that a
herhut
2014/06/27 12:34:35
This only replicated what the original implementat
| |
| 112 task.measure(() { | 116 task.measure(() { |
| 113 ClassElement cls = type.element; | 117 ClassElement cls = type.element; |
| 114 registry.registerDependency(cls); | 118 registry.registerDependency(cls); |
| 115 cls.ensureResolved(compiler); | 119 cls.ensureResolved(compiler); |
| 116 universe.instantiatedTypes.add(type); | 120 universe.instantiatedTypes.add(type); |
| 117 if (!cls.isAbstract | 121 if (!cls.isAbstract |
| 118 // We can't use the closed-world assumption with native abstract | 122 // We can't use the closed-world assumption with native abstract |
| 119 // classes; a native abstract class may have non-abstract subclasses | 123 // classes; a native abstract class may have non-abstract subclasses |
| 120 // not declared to the program. Instances of these classes are | 124 // not declared to the program. Instances of these classes are |
| 121 // indistinguishable from the abstract class. | 125 // indistinguishable from the abstract class. |
| 122 || cls.isNative) { | 126 || cls.isNative |
| 127 // Likewise, if this registration comes from the mirror system, | |
| 128 // all bets are off. | |
| 129 || mirrorUsage) { | |
| 123 universe.instantiatedClasses.add(cls); | 130 universe.instantiatedClasses.add(cls); |
| 124 } | 131 } |
| 125 onRegisterInstantiatedClass(cls); | 132 onRegisterInstantiatedClass(cls); |
| 126 }); | 133 }); |
| 127 } | 134 } |
| 128 | 135 |
| 129 void registerInstantiatedClass(ClassElement cls, Registry registry) { | 136 void registerInstantiatedClass(ClassElement cls, Registry registry, |
| 137 {mirrorUsage: false}) { | |
| 130 cls.ensureResolved(compiler); | 138 cls.ensureResolved(compiler); |
| 131 registerInstantiatedType(cls.rawType, registry); | 139 registerInstantiatedType(cls.rawType, registry, mirrorUsage: mirrorUsage); |
| 132 } | 140 } |
| 133 | 141 |
| 134 bool checkNoEnqueuedInvokedInstanceMethods() { | 142 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 135 task.measure(() { | 143 task.measure(() { |
| 136 // Run through the classes and see if we need to compile methods. | 144 // Run through the classes and see if we need to compile methods. |
| 137 for (ClassElement classElement in universe.instantiatedClasses) { | 145 for (ClassElement classElement in universe.instantiatedClasses) { |
| 138 for (ClassElement currentClass = classElement; | 146 for (ClassElement currentClass = classElement; |
| 139 currentClass != null; | 147 currentClass != null; |
| 140 currentClass = currentClass.superclass) { | 148 currentClass = currentClass.superclass) { |
| 141 processInstantiatedClass(currentClass); | 149 processInstantiatedClass(currentClass); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 task.measure(() { | 261 task.measure(() { |
| 254 if (seenClasses.contains(cls)) return; | 262 if (seenClasses.contains(cls)) return; |
| 255 // The class must be resolved to compute the set of all | 263 // The class must be resolved to compute the set of all |
| 256 // supertypes. | 264 // supertypes. |
| 257 cls.ensureResolved(compiler); | 265 cls.ensureResolved(compiler); |
| 258 | 266 |
| 259 void processClass(ClassElement cls) { | 267 void processClass(ClassElement cls) { |
| 260 if (seenClasses.contains(cls)) return; | 268 if (seenClasses.contains(cls)) return; |
| 261 | 269 |
| 262 seenClasses.add(cls); | 270 seenClasses.add(cls); |
| 271 recentClasses.add(cls); | |
| 263 cls.ensureResolved(compiler); | 272 cls.ensureResolved(compiler); |
| 264 cls.implementation.forEachMember(processInstantiatedClassMember); | 273 cls.implementation.forEachMember(processInstantiatedClassMember); |
| 265 if (isResolutionQueue) { | 274 if (isResolutionQueue) { |
| 266 compiler.resolver.checkClass(cls); | 275 compiler.resolver.checkClass(cls); |
| 267 } | 276 } |
| 268 // We only tell the backend once that [cls] was instantiated, so | 277 // We only tell the backend once that [cls] was instantiated, so |
| 269 // any additional dependencies must be treated as global | 278 // any additional dependencies must be treated as global |
| 270 // dependencies. | 279 // dependencies. |
| 271 compiler.backend.registerInstantiatedClass( | 280 compiler.backend.registerInstantiatedClass( |
| 272 cls, this, compiler.globalDependencies); | 281 cls, this, compiler.globalDependencies); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 301 registerNewSelector(selector, universe.invokedGetters); | 310 registerNewSelector(selector, universe.invokedGetters); |
| 302 }); | 311 }); |
| 303 } | 312 } |
| 304 | 313 |
| 305 void registerInvokedSetter(Selector selector) { | 314 void registerInvokedSetter(Selector selector) { |
| 306 task.measure(() { | 315 task.measure(() { |
| 307 registerNewSelector(selector, universe.invokedSetters); | 316 registerNewSelector(selector, universe.invokedSetters); |
| 308 }); | 317 }); |
| 309 } | 318 } |
| 310 | 319 |
| 311 void pretendElementWasUsed(Element element, Registry registry) { | 320 /** |
| 312 if (!compiler.backend.isNeededForReflection(element)) return; | 321 * Decides whether an element should be included to satisfy requirements |
| 313 if (Elements.isUnresolved(element)) { | 322 * of the mirror system. |
| 314 // Ignore. | 323 * |
| 315 } else if (element.isSynthesized | 324 * The actual implementation depends on the current compiler phase. |
| 316 && element.library.isPlatformLibrary) { | 325 */ |
| 317 // TODO(ahe): Work-around for http://dartbug.com/11205. | 326 bool includeElementDueToMirrors(bool includeEnclosing, Element element); |
|
Johnni Winther
2014/06/27 07:43:01
Rename to [shouldIncludeElementDueToMirror] to ind
Johnni Winther
2014/06/27 07:43:01
Make [includeEnclosing] a named parameter.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:36
Done.
| |
| 318 } else if (element.isConstructor) { | 327 |
| 319 ClassElement cls = element.declaration.enclosingClass; | 328 void logEnqueueReflectiveAction(action, [msg = ""]) { |
| 320 registerInstantiatedType(cls.rawType, registry); | 329 if (TRACE_MIRROR_ENQUEUING) { |
| 321 registerStaticUse(element.declaration); | 330 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "B"}): $action $msg"); |
|
karlklose
2014/06/27 07:45:57
'R' -> 'resolution'?
What is 'B'?
herhut
2014/06/27 12:34:36
Backend. Probably C for codegen is better. I have
| |
| 322 } else if (element.isClass) { | 331 } |
| 323 ClassElement cls = element.declaration; | 332 } |
| 324 registerInstantiatedClass(cls, registry); | 333 |
| 325 // Make sure that even abstract classes are considered instantiated. | 334 void enqueueReflectiveConstructor(ConstructorElement ctor, bool add) { |
|
Johnni Winther
2014/06/27 07:43:00
Add comment. I guess it is a helper method for [en
Johnni Winther
2014/06/27 07:43:01
Make [add] named.
karlklose
2014/06/27 07:45:57
Could you add a comment about the semantics of 'ad
floitsch
2014/06/27 08:59:15
nit: s/add/forceAdd/
I'm guessing that's the mean
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:37
Done.
| |
| 326 universe.instantiatedClasses.add(cls); | 335 if (includeElementDueToMirrors(add, ctor)) { |
| 327 } else if (element.impliesType) { | 336 logEnqueueReflectiveAction(ctor); |
| 328 // Don't enqueue typedefs, and type variables. | 337 ClassElement cls = ctor.declaration.enclosingClass; |
| 329 } else if (Elements.isStaticOrTopLevel(element)) { | 338 registerInstantiatedType(cls.rawType, compiler.mirrorDependencies); |
|
Johnni Winther
2014/06/27 07:43:01
Shouldn't this call have `mirrorUsage: true` ?
karlklose
2014/06/27 07:45:57
I am not sure we should register this type here.
herhut
2014/06/27 12:34:35
It will not have an effect currently but it is mor
herhut
2014/06/27 12:34:36
This implements what was done before. I will redo
| |
| 330 registerStaticUse(element.declaration); | 339 registerStaticUse(ctor.declaration); |
| 331 } else if (element.isInstanceMember) { | 340 } |
| 332 Selector selector = new Selector.fromElement(element, compiler); | 341 } |
| 333 registerSelectorUse(selector); | 342 |
| 334 if (element.isField) { | 343 void enqueueReflectiveMember(Element element, bool add) { |
|
Johnni Winther
2014/06/27 07:43:00
Make [add] named.
Johnni Winther
2014/06/27 07:43:01
Add comment.
herhut
2014/06/27 12:34:35
Done.
herhut
2014/06/27 12:34:36
Done.
| |
| 335 Selector selector = | 344 add = includeElementDueToMirrors(add, element); |
|
karlklose
2014/06/27 07:45:57
Inline call to includeElementsDueToMirrors? (Also
herhut
2014/06/27 12:34:36
Below I have to pass the result on to the processi
| |
| 336 new Selector.setter(element.name, element.library); | 345 if (add && !element.impliesType) { |
|
floitsch
2014/06/27 08:59:15
Keep comment exlpaining what "impliesType" means.
herhut
2014/06/27 12:34:36
Done.
| |
| 337 registerInvokedSetter(selector); | 346 logEnqueueReflectiveAction(element); |
| 347 if (Elements.isStaticOrTopLevel(element)) { | |
| 348 registerStaticUse(element.declaration); | |
| 349 } else if (element.isInstanceMember) { | |
| 350 // We need to enqueue all members matching this one in subclasses, as | |
| 351 // well. | |
| 352 // TODO(herhut): Use TypedSelector.subtype for enqueueing | |
| 353 Selector selector = new Selector.fromElement(element, compiler); | |
| 354 registerSelectorUse(selector); | |
| 355 if (element.isField) { | |
| 356 Selector selector = | |
| 357 new Selector.setter(element.name, element.library); | |
| 358 registerInvokedSetter(selector); | |
| 359 } | |
| 338 } | 360 } |
| 339 } | 361 } |
| 340 } | 362 } |
| 341 | 363 |
| 342 void enqueueEverything() { | 364 void enqueueReflectiveElementsInClass(ClassElement cls, |
|
Johnni Winther
2014/06/27 07:43:00
Add comment.
herhut
2014/06/27 12:34:36
Done.
| |
| 343 if (hasEnqueuedEverything) return; | 365 Iterable<ClassElement> recents, |
| 344 compiler.log('Enqueuing everything'); | 366 bool add) { |
|
Johnni Winther
2014/06/27 07:43:00
Make [add] named.
herhut
2014/06/27 12:34:37
Done.
| |
| 345 task.ensureAllElementsByName(); | 367 if (cls.library.isInternalLibrary) return; |
| 346 for (Link link in task.allElementsByName.values) { | 368 if (cls.isInjected) return; |
|
Johnni Winther
2014/06/27 07:43:00
Merge conditions.
herhut
2014/06/27 12:34:36
Done.
| |
| 347 for (Element element in link) { | 369 add = includeElementDueToMirrors(add, cls); |
| 348 pretendElementWasUsed(element, compiler.mirrorDependencies); | 370 if (add) { |
| 371 logEnqueueReflectiveAction(cls, "register"); | |
| 372 ClassElement decl = cls.declaration; | |
| 373 registerInstantiatedClass(decl, compiler.mirrorDependencies, | |
| 374 mirrorUsage: true); | |
| 375 } | |
| 376 // If the class is never instantiated, we know nothing of it can possibly | |
| 377 // be reflected upon. | |
| 378 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. | |
| 379 if (recents.contains(cls.declaration)) { | |
| 380 logEnqueueReflectiveAction(cls, "members"); | |
| 381 cls.constructors.forEach((Element element) { | |
| 382 enqueueReflectiveConstructor(element, add); | |
| 383 }); | |
| 384 cls.forEachClassMember((Member member) { | |
| 385 enqueueReflectiveMember(member.element, add); | |
| 386 }); | |
| 387 } | |
| 388 } | |
| 389 | |
| 390 void enqueueReflectiveSpecialClasses() { | |
|
Johnni Winther
2014/06/27 07:43:00
Add comment.
herhut
2014/06/27 12:34:36
Done.
| |
| 391 // [Closure] is treated specially as it is the superclass of all closures. | |
| 392 // Although it is in an internal library, we mark it as reflectable. Note | |
| 393 // that none of its methods are reflectable, unless reflectable by | |
| 394 // inheritance. | |
| 395 ClassElement closureClass = compiler.closureClass; | |
| 396 if (compiler.backend.referencedFromMirrorSystem(closureClass)) { | |
| 397 logEnqueueReflectiveAction(closureClass); | |
| 398 registerInstantiatedClass(closureClass, compiler.mirrorDependencies, | |
| 399 mirrorUsage: true); | |
| 400 } | |
| 401 } | |
| 402 | |
| 403 void enqueueReflectiveElementsInLibrary(LibraryElement lib, | |
|
Johnni Winther
2014/06/27 07:43:00
Add comment.
herhut
2014/06/27 12:34:36
Done.
| |
| 404 Iterable<ClassElement> recents, | |
| 405 bool add) { | |
| 406 add = includeElementDueToMirrors(add, lib); | |
| 407 lib.forEachLocalMember((Element member) { | |
| 408 if (member.isClass) { | |
| 409 enqueueReflectiveElementsInClass(member, recents, add); | |
| 410 } else { | |
| 411 enqueueReflectiveMember(member, add); | |
| 349 } | 412 } |
| 413 }); | |
| 414 } | |
| 415 | |
| 416 /// Enqueue all elements that are matched by the mirrors used | |
| 417 /// annotation or, in lack thereof, all elements. | |
| 418 void enqueueReflectiveElements(Iterable<ClassElement> recents) { | |
| 419 if (!hasEnqueuedReflectiveElements) { | |
| 420 logEnqueueReflectiveAction("!START enqueueAll"); | |
| 421 // First round of enqueuing, visit everything that is visible to | |
| 422 // also pick up static top levels, etc. | |
| 423 // Also, during the first round, consider all classes that have been seen | |
| 424 // as recently seen, as a couple of rounds of resolution might have run | |
|
floitsch
2014/06/27 08:59:15
maybe?
... as treeshaking might only be disabled
herhut
2014/06/27 12:34:35
Rephrased:
Also, during the first round, consider
| |
| 425 // before treeshaking is disabled and we thus enqueue everything. | |
| 426 recents = seenClasses.toSet(); | |
| 427 compiler.log('Enqueuing everything'); | |
| 428 for (LibraryElement lib in compiler.libraries.values) { | |
| 429 enqueueReflectiveElementsInLibrary(lib, recents, false); | |
| 430 } | |
| 431 enqueueReflectiveSpecialClasses(); | |
| 432 hasEnqueuedReflectiveElements = true; | |
| 433 hasEnqueuedReflectiveStaticFields = true; | |
| 434 logEnqueueReflectiveAction("!DONE enqueueAll"); | |
| 435 } else if (recents.isNotEmpty) { | |
| 436 // Keep looking at new classes until fixpoint is reached. | |
| 437 logEnqueueReflectiveAction("!START enqueueRecents"); | |
| 438 recents.forEach((ClassElement cls) { | |
| 439 enqueueReflectiveElementsInClass(cls, recents, | |
| 440 includeElementDueToMirrors(false, cls.library)); | |
| 441 }); | |
| 442 logEnqueueReflectiveAction("!DONE enqueueRecents"); | |
| 350 } | 443 } |
| 351 hasEnqueuedEverything = true; | |
| 352 hasEnqueuedReflectiveStaticFields = true; | |
| 353 } | 444 } |
| 354 | 445 |
| 355 /// Enqueue the static fields that have been marked as used by reflective | 446 /// Enqueue the static fields that have been marked as used by reflective |
| 356 /// usage through `MirrorsUsed`. | 447 /// usage through `MirrorsUsed`. |
| 357 void enqueueReflectiveStaticFields(Iterable<Element> elements) { | 448 void enqueueReflectiveStaticFields(Iterable<Element> elements) { |
| 358 if (hasEnqueuedReflectiveStaticFields) return; | 449 if (hasEnqueuedReflectiveStaticFields) return; |
| 359 hasEnqueuedReflectiveStaticFields = true; | 450 hasEnqueuedReflectiveStaticFields = true; |
| 360 for (Element element in elements) { | 451 for (Element element in elements) { |
| 361 pretendElementWasUsed(element, compiler.mirrorDependencies); | 452 enqueueReflectiveMember(element, true); |
| 362 } | 453 } |
| 363 } | 454 } |
| 364 | 455 |
| 365 processLink(Map<String, Link<Element>> map, | 456 processLink(Map<String, Link<Element>> map, |
| 366 String memberName, | 457 String memberName, |
| 367 bool f(Element e)) { | 458 bool f(Element e)) { |
| 368 Link<Element> members = map[memberName]; | 459 Link<Element> members = map[memberName]; |
| 369 if (members != null) { | 460 if (members != null) { |
| 370 // [f] might add elements to [: map[memberName] :] during the loop below | 461 // [f] might add elements to [: map[memberName] :] during the loop below |
| 371 // so we create a new list for [: map[memberName] :] and prepend the | 462 // so we create a new list for [: map[memberName] :] and prepend the |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 } | 612 } |
| 522 | 613 |
| 523 | 614 |
| 524 void registerIfGeneric(Element element, Registry registry) { | 615 void registerIfGeneric(Element element, Registry registry) { |
| 525 if (element.computeType(compiler).containsTypeVariables) { | 616 if (element.computeType(compiler).containsTypeVariables) { |
| 526 compiler.backend.registerGenericClosure(element, this, registry); | 617 compiler.backend.registerGenericClosure(element, this, registry); |
| 527 universe.genericClosures.add(element); | 618 universe.genericClosures.add(element); |
| 528 } | 619 } |
| 529 } | 620 } |
| 530 | 621 |
| 531 void registerClosure(Element element, Registry registry) { | 622 void registerClosure(Element element, Registry registry) { |
|
Johnni Winther
2014/06/27 07:43:00
Change [Element] to [FunctionElement].
herhut
2014/06/27 12:34:36
Done.
| |
| 623 universe.allClosures.add(element); | |
| 532 registerIfGeneric(element, registry); | 624 registerIfGeneric(element, registry); |
| 533 } | 625 } |
| 534 | 626 |
| 535 void forEach(f(WorkItem work)) { | 627 void forEach(f(WorkItem work)) { |
| 536 do { | 628 do { |
| 537 while (!queue.isEmpty) { | 629 while (queue.isNotEmpty) { |
| 538 // TODO(johnniwinther): Find an optimal process order. | 630 // TODO(johnniwinther): Find an optimal process order. |
| 539 f(queue.removeLast()); | 631 f(queue.removeLast()); |
| 540 } | 632 } |
| 541 onQueueEmpty(); | 633 List recents = recentClasses.toList(growable: false); |
| 542 } while (!queue.isEmpty); | 634 recentClasses.clear(); |
| 635 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); | |
| 636 } while (queue.isNotEmpty || recentClasses.isNotEmpty); | |
| 543 } | 637 } |
| 544 | 638 |
| 545 void onQueueEmpty() { | 639 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
| 546 compiler.backend.onQueueEmpty(this); | 640 /// contains the set of all classes seen for the first time since |
| 641 /// [onQueueEmpty] was called last. A return value of [true] indicates that | |
| 642 /// the [recentClasses] have been processed and may be cleared. If [false] is | |
| 643 /// returned, [onQueueEmpty] will be called once the queue is empty again (or | |
| 644 /// still empty) and [recentClasses] will be a superset of the current value. | |
| 645 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | |
| 646 return compiler.backend.onQueueEmpty(this, recentClasses); | |
| 547 } | 647 } |
| 548 | 648 |
| 549 void logSummary(log(message)) { | 649 void logSummary(log(message)) { |
| 550 _logSpecificSummary(log); | 650 _logSpecificSummary(log); |
| 551 nativeEnqueuer.logSummary(log); | 651 nativeEnqueuer.logSummary(log); |
| 552 } | 652 } |
| 553 | 653 |
| 554 /// Log summary specific to the concrete enqueuer. | 654 /// Log summary specific to the concrete enqueuer. |
| 555 void _logSpecificSummary(log(message)); | 655 void _logSpecificSummary(log(message)); |
| 556 | 656 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 596 resolvedElements.add(element); | 696 resolvedElements.add(element); |
| 597 } | 697 } |
| 598 | 698 |
| 599 /// Returns [:true:] if [element] has actually been used. | 699 /// Returns [:true:] if [element] has actually been used. |
| 600 bool isLive(Element element) { | 700 bool isLive(Element element) { |
| 601 if (seenClasses.contains(element)) return true; | 701 if (seenClasses.contains(element)) return true; |
| 602 if (hasBeenResolved(element)) return true; | 702 if (hasBeenResolved(element)) return true; |
| 603 return false; | 703 return false; |
| 604 } | 704 } |
| 605 | 705 |
| 706 /** | |
| 707 * Decides whether an element should be included to satisfy requirements | |
| 708 * of the mirror system. | |
| 709 * | |
| 710 * During resoltion, we have to resort to matching elements against the | |
|
Johnni Winther
2014/06/27 07:43:01
'resoltion' -> 'resolution'.
karlklose
2014/06/27 07:45:57
'resoltion' -> 'resolution'.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:37
Done.
| |
| 711 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | |
| 712 * yet. | |
| 713 */ | |
| 714 bool includeElementDueToMirrors(bool includeEnclosing, Element element) { | |
|
karlklose
2014/06/27 07:45:57
Does it make sense to move functionality like this
herhut
2014/06/27 12:34:36
Yes, this is also on the list of further refactori
| |
| 715 return includeEnclosing || compiler.backend.requiredByMirrorSystem(element); | |
| 716 } | |
| 717 | |
| 606 void internalAddToWorkList(Element element) { | 718 void internalAddToWorkList(Element element) { |
| 607 assert(invariant(element, element is AnalyzableElement, | 719 assert(invariant(element, element is AnalyzableElement, |
| 608 message: 'Element $element is not analyzable.')); | 720 message: 'Element $element is not analyzable.')); |
| 609 if (hasBeenResolved(element)) return; | 721 if (hasBeenResolved(element)) return; |
| 610 if (queueIsClosed) { | 722 if (queueIsClosed) { |
| 611 throw new SpannableAssertionFailure(element, | 723 throw new SpannableAssertionFailure(element, |
| 612 "Resolution work list is closed. Trying to add $element."); | 724 "Resolution work list is closed. Trying to add $element."); |
| 613 } | 725 } |
| 614 | 726 |
| 615 compiler.world.registerUsedElement(element); | 727 compiler.world.registerUsedElement(element); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 682 */ | 794 */ |
| 683 void addDeferredAction(Element element, DeferredAction action) { | 795 void addDeferredAction(Element element, DeferredAction action) { |
| 684 if (queueIsClosed) { | 796 if (queueIsClosed) { |
| 685 throw new SpannableAssertionFailure(element, | 797 throw new SpannableAssertionFailure(element, |
| 686 "Resolution work list is closed. " | 798 "Resolution work list is closed. " |
| 687 "Trying to add deferred action for $element"); | 799 "Trying to add deferred action for $element"); |
| 688 } | 800 } |
| 689 deferredTaskQueue.add(new DeferredTask(element, action)); | 801 deferredTaskQueue.add(new DeferredTask(element, action)); |
| 690 } | 802 } |
| 691 | 803 |
| 692 void onQueueEmpty() { | 804 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
| 693 emptyDeferredTaskQueue(); | 805 emptyDeferredTaskQueue(); |
| 694 super.onQueueEmpty(); | 806 return super.onQueueEmpty(recentClasses); |
| 695 } | 807 } |
| 696 | 808 |
| 697 void emptyDeferredTaskQueue() { | 809 void emptyDeferredTaskQueue() { |
| 698 while (!deferredTaskQueue.isEmpty) { | 810 while (!deferredTaskQueue.isEmpty) { |
| 699 DeferredTask task = deferredTaskQueue.removeFirst(); | 811 DeferredTask task = deferredTaskQueue.removeFirst(); |
| 700 compiler.withCurrentElement(task.element, task.action); | 812 compiler.withCurrentElement(task.element, task.action); |
| 701 } | 813 } |
| 702 } | 814 } |
| 703 | 815 |
| 704 void registerJsCall(Send node, ResolverVisitor resolver) { | 816 void registerJsCall(Send node, ResolverVisitor resolver) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 720 | 832 |
| 721 CodegenEnqueuer(Compiler compiler, | 833 CodegenEnqueuer(Compiler compiler, |
| 722 ItemCompilationContext itemCompilationContextCreator()) | 834 ItemCompilationContext itemCompilationContextCreator()) |
| 723 : queue = new Queue<CodegenWorkItem>(), | 835 : queue = new Queue<CodegenWorkItem>(), |
| 724 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 836 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
| 725 super('codegen enqueuer', compiler, itemCompilationContextCreator); | 837 super('codegen enqueuer', compiler, itemCompilationContextCreator); |
| 726 | 838 |
| 727 bool isProcessed(Element member) => | 839 bool isProcessed(Element member) => |
| 728 member.isAbstract || generatedCode.containsKey(member); | 840 member.isAbstract || generatedCode.containsKey(member); |
| 729 | 841 |
| 842 /** | |
| 843 * Decides whether an element should be included to satisfy requirements | |
| 844 * of the mirror system. | |
| 845 * | |
| 846 * For code generation, we rely on the precomputed set of elements that takes | |
| 847 * subtyping constraints into account. | |
| 848 */ | |
| 849 bool includeElementDueToMirrors(bool includeEnclosing, Element element) { | |
| 850 return compiler.backend.isAccessibleByReflection(element); | |
| 851 } | |
| 852 | |
| 730 void internalAddToWorkList(Element element) { | 853 void internalAddToWorkList(Element element) { |
| 731 if (compiler.hasIncrementalSupport) { | 854 if (compiler.hasIncrementalSupport) { |
| 732 newlyEnqueuedElements.add(element); | 855 newlyEnqueuedElements.add(element); |
| 733 } | 856 } |
| 734 // Don't generate code for foreign elements. | 857 // Don't generate code for foreign elements. |
| 735 if (element.isForeign(compiler)) return; | 858 if (element.isForeign(compiler)) return; |
| 736 | 859 |
| 737 // Codegen inlines field initializers. It only needs to generate | 860 // Codegen inlines field initializers. It only needs to generate |
| 738 // code for checked setters. | 861 // code for checked setters. |
| 739 if (element.isField && element.isInstanceMember) { | 862 if (element.isField && element.isInstanceMember) { |
| 740 if (!compiler.enableTypeAssertions | 863 if (!compiler.enableTypeAssertions |
| 741 || element.enclosingElement.isClosure) { | 864 || element.enclosingElement.isClosure) { |
| 742 return; | 865 return; |
| 743 } | 866 } |
| 744 } | 867 } |
| 745 | 868 |
| 746 if (queueIsClosed) { | 869 if (queueIsClosed) { |
| 747 throw new SpannableAssertionFailure(element, | 870 throw new SpannableAssertionFailure(element, |
| 748 "Codegen work list is closed. Trying to add $element"); | 871 "Codegen work list is closed. Trying to add $element"); |
| 749 } | 872 } |
| 750 CodegenWorkItem workItem = new CodegenWorkItem( | 873 CodegenWorkItem workItem = new CodegenWorkItem( |
| 751 element, itemCompilationContextCreator()); | 874 element, itemCompilationContextCreator()); |
| 752 queue.add(workItem); | 875 queue.add(workItem); |
| 753 } | 876 } |
| 754 | 877 |
| 755 void _logSpecificSummary(log(message)) { | 878 void _logSpecificSummary(log(message)) { |
| 756 log('Compiled ${generatedCode.length} methods.'); | 879 log('Compiled ${generatedCode.length} methods.'); |
| 757 } | 880 } |
| 758 } | 881 } |
| OLD | NEW |