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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 static final TRACE_MIRROR_ENQUEUING = | 42 static final TRACE_MIRROR_ENQUEUING = |
43 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 43 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
44 | 44 |
45 bool queueIsClosed = false; | 45 bool queueIsClosed = false; |
46 EnqueueTask task; | 46 EnqueueTask task; |
47 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 47 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
48 | 48 |
49 bool hasEnqueuedReflectiveElements = false; | 49 bool hasEnqueuedReflectiveElements = false; |
50 bool hasEnqueuedReflectiveStaticFields = false; | 50 bool hasEnqueuedReflectiveStaticFields = false; |
51 | 51 |
| 52 CompilationInformation get compilationInfo; |
| 53 |
52 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); | 54 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); |
53 | 55 |
54 Queue<WorkItem> get queue; | 56 Queue<WorkItem> get queue; |
55 bool get queueIsEmpty => queue.isEmpty; | 57 bool get queueIsEmpty => queue.isEmpty; |
56 | 58 |
57 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 59 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
58 bool get isResolutionQueue => false; | 60 bool get isResolutionQueue => false; |
59 | 61 |
60 QueueFilter get filter => compiler.enqueuerFilter; | 62 QueueFilter get filter => compiler.enqueuerFilter; |
61 | 63 |
62 /// Returns [:true:] if [member] has been processed by this enqueuer. | 64 /// Returns [:true:] if [member] has been processed by this enqueuer. |
63 bool isProcessed(Element member); | 65 bool isProcessed(Element member); |
64 | 66 |
65 /** | 67 /** |
66 * Documentation wanted -- johnniwinther | 68 * Documentation wanted -- johnniwinther |
67 * | 69 * |
68 * Invariant: [element] must be a declaration element. | 70 * Invariant: [element] must be a declaration element. |
69 */ | 71 */ |
70 void addToWorkList(Element element) { | 72 void addToWorkList(Element element) { |
71 assert(invariant(element, element.isDeclaration)); | 73 assert(invariant(element, element.isDeclaration)); |
72 internalAddToWorkList(element); | 74 if (internalAddToWorkList(element)) { |
| 75 compilationInfo.addsToWorkList(compiler.currentElement, element); |
| 76 } |
73 } | 77 } |
74 | 78 |
75 /** | 79 /** |
76 * Adds [element] to the work list if it has not already been processed. | 80 * Adds [element] to the work list if it has not already been processed. |
| 81 * |
| 82 * Returns [true] if the element was actually added to the queue. |
77 */ | 83 */ |
78 void internalAddToWorkList(Element element); | 84 bool internalAddToWorkList(Element element); |
79 | 85 |
80 void registerInstantiatedType(InterfaceType type, Registry registry, | 86 void registerInstantiatedType(InterfaceType type, Registry registry, |
81 {mirrorUsage: false}) { | 87 {mirrorUsage: false}) { |
82 task.measure(() { | 88 task.measure(() { |
83 ClassElement cls = type.element; | 89 ClassElement cls = type.element; |
84 registry.registerDependency(cls); | 90 registry.registerDependency(cls); |
85 cls.ensureResolved(compiler); | 91 cls.ensureResolved(compiler); |
86 universe.instantiatedTypes.add(type); | 92 universe.instantiatedTypes.add(type); |
87 if (!cls.isAbstract | 93 if (!cls.isAbstract |
88 // We can't use the closed-world assumption with native abstract | 94 // We can't use the closed-world assumption with native abstract |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 registerClosurizedMember(member, compiler.globalDependencies); | 182 registerClosurizedMember(member, compiler.globalDependencies); |
177 addToWorkList(member); | 183 addToWorkList(member); |
178 return; | 184 return; |
179 } | 185 } |
180 // Store the member in [instanceFunctionsByName] to catch | 186 // Store the member in [instanceFunctionsByName] to catch |
181 // getters on the function. | 187 // getters on the function. |
182 Link<Element> members = instanceFunctionsByName.putIfAbsent( | 188 Link<Element> members = instanceFunctionsByName.putIfAbsent( |
183 memberName, () => const Link<Element>()); | 189 memberName, () => const Link<Element>()); |
184 instanceFunctionsByName[memberName] = members.prepend(member); | 190 instanceFunctionsByName[memberName] = members.prepend(member); |
185 if (universe.hasInvocation(member, compiler)) { | 191 if (universe.hasInvocation(member, compiler)) { |
| 192 compilationInfo.enqueues(getContext(), member); |
186 addToWorkList(member); | 193 addToWorkList(member); |
187 return; | 194 return; |
188 } | 195 } |
189 } else if (member.kind == ElementKind.GETTER) { | 196 } else if (member.kind == ElementKind.GETTER) { |
190 if (universe.hasInvokedGetter(member, compiler)) { | 197 if (universe.hasInvokedGetter(member, compiler)) { |
191 addToWorkList(member); | 198 addToWorkList(member); |
192 return; | 199 return; |
193 } | 200 } |
194 // We don't know what selectors the returned closure accepts. If | 201 // We don't know what selectors the returned closure accepts. If |
195 // the set contains any selector we have to assume that it matches. | 202 // the set contains any selector we have to assume that it matches. |
(...skipping 11 matching lines...) Expand all Loading... |
207 // The element is not yet used. Add it to the list of instance | 214 // The element is not yet used. Add it to the list of instance |
208 // members to still be processed. | 215 // members to still be processed. |
209 Link<Element> members = instanceMembersByName.putIfAbsent( | 216 Link<Element> members = instanceMembersByName.putIfAbsent( |
210 memberName, () => const Link<Element>()); | 217 memberName, () => const Link<Element>()); |
211 instanceMembersByName[memberName] = members.prepend(member); | 218 instanceMembersByName[memberName] = members.prepend(member); |
212 } | 219 } |
213 | 220 |
214 void enableNoSuchMethod(Element element) {} | 221 void enableNoSuchMethod(Element element) {} |
215 void enableIsolateSupport() {} | 222 void enableIsolateSupport() {} |
216 | 223 |
| 224 Element getContext() => compiler.currentElement; |
| 225 |
217 void onRegisterInstantiatedClass(ClassElement cls) { | 226 void onRegisterInstantiatedClass(ClassElement cls) { |
218 task.measure(() { | 227 task.measure(() { |
219 if (seenClasses.contains(cls)) return; | 228 if (seenClasses.contains(cls)) return; |
220 // The class must be resolved to compute the set of all | 229 // The class must be resolved to compute the set of all |
221 // supertypes. | 230 // supertypes. |
222 cls.ensureResolved(compiler); | 231 cls.ensureResolved(compiler); |
223 | 232 |
224 void processClass(ClassElement cls) { | 233 void processClass(ClassElement cls) { |
225 if (seenClasses.contains(cls)) return; | 234 if (seenClasses.contains(cls)) return; |
226 | 235 |
(...skipping 11 matching lines...) Expand all Loading... |
238 cls, this, compiler.globalDependencies); | 247 cls, this, compiler.globalDependencies); |
239 } | 248 } |
240 processClass(cls); | 249 processClass(cls); |
241 for (Link<DartType> supertypes = cls.allSupertypes; | 250 for (Link<DartType> supertypes = cls.allSupertypes; |
242 !supertypes.isEmpty; supertypes = supertypes.tail) { | 251 !supertypes.isEmpty; supertypes = supertypes.tail) { |
243 processClass(supertypes.head.element); | 252 processClass(supertypes.head.element); |
244 } | 253 } |
245 }); | 254 }); |
246 } | 255 } |
247 | 256 |
248 void registerNewSelector(Selector selector, | 257 void registerNewSelector(Element context, |
| 258 Selector selector, |
249 Map<String, Set<Selector>> selectorsMap) { | 259 Map<String, Set<Selector>> selectorsMap) { |
250 String name = selector.name; | 260 String name = selector.name; |
251 Set<Selector> selectors = | 261 Set<Selector> selectors = |
252 selectorsMap.putIfAbsent(name, () => new Setlet<Selector>()); | 262 selectorsMap.putIfAbsent(name, () => new Setlet<Selector>()); |
253 if (!selectors.contains(selector)) { | 263 if (!selectors.contains(selector)) { |
254 selectors.add(selector); | 264 selectors.add(selector); |
255 handleUnseenSelector(name, selector); | 265 handleUnseenSelector(context, name, selector); |
256 } | 266 } |
257 } | 267 } |
258 | 268 |
259 void registerInvocation(Selector selector) { | 269 void registerInvocation(Element context, Selector selector) { |
260 task.measure(() { | 270 task.measure(() { |
261 registerNewSelector(selector, universe.invokedNames); | 271 registerNewSelector(context, selector, universe.invokedNames); |
262 }); | 272 }); |
263 } | 273 } |
264 | 274 |
265 void registerInvokedGetter(Selector selector) { | 275 void registerInvokedGetter(Element context, Selector selector) { |
266 task.measure(() { | 276 task.measure(() { |
267 registerNewSelector(selector, universe.invokedGetters); | 277 registerNewSelector(context, selector, universe.invokedGetters); |
268 }); | 278 }); |
269 } | 279 } |
270 | 280 |
271 void registerInvokedSetter(Selector selector) { | 281 void registerInvokedSetter(Element context, Selector selector) { |
272 task.measure(() { | 282 task.measure(() { |
273 registerNewSelector(selector, universe.invokedSetters); | 283 registerNewSelector(context, selector, universe.invokedSetters); |
274 }); | 284 }); |
275 } | 285 } |
276 | 286 |
277 /** | 287 /** |
278 * Decides whether an element should be included to satisfy requirements | 288 * Decides whether an element should be included to satisfy requirements |
279 * of the mirror system. [includedEnclosing] provides a hint whether the | 289 * of the mirror system. [includedEnclosing] provides a hint whether the |
280 * enclosing element was included. | 290 * enclosing element was included. |
281 * | 291 * |
282 * The actual implementation depends on the current compiler phase. | 292 * The actual implementation depends on the current compiler phase. |
283 */ | 293 */ |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 // Do not enqueue typedefs. | 326 // Do not enqueue typedefs. |
317 && !element.impliesType) { | 327 && !element.impliesType) { |
318 logEnqueueReflectiveAction(element); | 328 logEnqueueReflectiveAction(element); |
319 if (Elements.isStaticOrTopLevel(element)) { | 329 if (Elements.isStaticOrTopLevel(element)) { |
320 registerStaticUse(element.declaration); | 330 registerStaticUse(element.declaration); |
321 } else if (element.isInstanceMember) { | 331 } else if (element.isInstanceMember) { |
322 // We need to enqueue all members matching this one in subclasses, as | 332 // We need to enqueue all members matching this one in subclasses, as |
323 // well. | 333 // well. |
324 // TODO(herhut): Use TypedSelector.subtype for enqueueing | 334 // TODO(herhut): Use TypedSelector.subtype for enqueueing |
325 Selector selector = new Selector.fromElement(element, compiler); | 335 Selector selector = new Selector.fromElement(element, compiler); |
326 registerSelectorUse(selector); | 336 registerSelectorUse(element, selector); |
327 if (element.isField) { | 337 if (element.isField) { |
328 Selector selector = | 338 Selector selector = |
329 new Selector.setter(element.name, element.library); | 339 new Selector.setter(element.name, element.library); |
330 registerInvokedSetter(selector); | 340 registerInvokedSetter(element, selector); |
331 } | 341 } |
332 } | 342 } |
333 } | 343 } |
334 } | 344 } |
335 | 345 |
336 /// Enqeue the member [element] if it is required for reflection. | 346 /// Enqeue the member [element] if it is required for reflection. |
337 /// | 347 /// |
338 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 348 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
339 /// needed for reflection. | 349 /// needed for reflection. |
340 void enqueueReflectiveElementsInClass(ClassElement cls, | 350 void enqueueReflectiveElementsInClass(ClassElement cls, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 } | 467 } |
458 | 468 |
459 processInstanceMembers(String n, bool f(Element e)) { | 469 processInstanceMembers(String n, bool f(Element e)) { |
460 processLink(instanceMembersByName, n, f); | 470 processLink(instanceMembersByName, n, f); |
461 } | 471 } |
462 | 472 |
463 processInstanceFunctions(String n, bool f(Element e)) { | 473 processInstanceFunctions(String n, bool f(Element e)) { |
464 processLink(instanceFunctionsByName, n, f); | 474 processLink(instanceFunctionsByName, n, f); |
465 } | 475 } |
466 | 476 |
467 void handleUnseenSelector(String methodName, Selector selector) { | 477 void handleUnseenSelector(Element context, |
| 478 String methodName, |
| 479 Selector selector) { |
468 processInstanceMembers(methodName, (Element member) { | 480 processInstanceMembers(methodName, (Element member) { |
| 481 compilationInfo.enqueues(context, member); |
469 if (selector.appliesUnnamed(member, compiler)) { | 482 if (selector.appliesUnnamed(member, compiler)) { |
470 if (member.isFunction && selector.isGetter) { | 483 if (member.isFunction && selector.isGetter) { |
471 registerClosurizedMember(member, compiler.globalDependencies); | 484 registerClosurizedMember(member, compiler.globalDependencies); |
472 } | 485 } |
473 if (member.isField && member.enclosingClass.isNative) { | 486 if (member.isField && member.enclosingClass.isNative) { |
474 if (selector.isGetter || selector.isCall) { | 487 if (selector.isGetter || selector.isCall) { |
475 nativeEnqueuer.registerFieldLoad(member); | 488 nativeEnqueuer.registerFieldLoad(member); |
476 // We have to also handle storing to the field because we only get | 489 // We have to also handle storing to the field because we only get |
477 // one look at each member and there might be a store we have not | 490 // one look at each member and there might be a store we have not |
478 // seen yet. | 491 // seen yet. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 addToWorkList(element); | 528 addToWorkList(element); |
516 compiler.backend.registerStaticUse(element, this); | 529 compiler.backend.registerStaticUse(element, this); |
517 } | 530 } |
518 | 531 |
519 void registerGetOfStaticFunction(FunctionElement element) { | 532 void registerGetOfStaticFunction(FunctionElement element) { |
520 registerStaticUse(element); | 533 registerStaticUse(element); |
521 compiler.backend.registerGetOfStaticFunction(this); | 534 compiler.backend.registerGetOfStaticFunction(this); |
522 universe.staticFunctionsNeedingGetter.add(element); | 535 universe.staticFunctionsNeedingGetter.add(element); |
523 } | 536 } |
524 | 537 |
525 void registerDynamicInvocation(Selector selector) { | 538 void registerDynamicInvocation(Element context, Selector selector) { |
526 assert(selector != null); | 539 assert(selector != null); |
527 registerInvocation(selector); | 540 registerInvocation(context, selector); |
528 } | 541 } |
529 | 542 |
530 void registerSelectorUse(Selector selector) { | 543 void registerSelectorUse(Element context, Selector selector) { |
531 if (selector.isGetter) { | 544 if (selector.isGetter) { |
532 registerInvokedGetter(selector); | 545 registerInvokedGetter(context, selector); |
533 } else if (selector.isSetter) { | 546 } else if (selector.isSetter) { |
534 registerInvokedSetter(selector); | 547 registerInvokedSetter(context, selector); |
535 } else { | 548 } else { |
536 registerInvocation(selector); | 549 registerInvocation(context, selector); |
537 } | 550 } |
538 } | 551 } |
539 | 552 |
540 void registerDynamicGetter(Selector selector) { | 553 void registerDynamicGetter(Element context, Selector selector) { |
541 registerInvokedGetter(selector); | 554 registerInvokedGetter(context, selector); |
542 } | 555 } |
543 | 556 |
544 void registerDynamicSetter(Selector selector) { | 557 void registerDynamicSetter(Element context, Selector selector) { |
545 registerInvokedSetter(selector); | 558 registerInvokedSetter(context, selector); |
546 } | 559 } |
547 | 560 |
548 void registerGetterForSuperMethod(Element element) { | 561 void registerGetterForSuperMethod(Element element) { |
549 universe.methodsNeedingSuperGetter.add(element); | 562 universe.methodsNeedingSuperGetter.add(element); |
550 } | 563 } |
551 | 564 |
552 void registerFieldGetter(Element element) { | 565 void registerFieldGetter(Element element) { |
553 universe.fieldGetters.add(element); | 566 universe.fieldGetters.add(element); |
554 } | 567 } |
555 | 568 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 final Set<AstElement> resolvedElements; | 656 final Set<AstElement> resolvedElements; |
644 | 657 |
645 final Queue<ResolutionWorkItem> queue; | 658 final Queue<ResolutionWorkItem> queue; |
646 | 659 |
647 /** | 660 /** |
648 * A deferred task queue for the resolution phase which is processed | 661 * A deferred task queue for the resolution phase which is processed |
649 * when the resolution queue has been emptied. | 662 * when the resolution queue has been emptied. |
650 */ | 663 */ |
651 final Queue<DeferredTask> deferredTaskQueue; | 664 final Queue<DeferredTask> deferredTaskQueue; |
652 | 665 |
| 666 CompilationInformation compilationInfo; |
| 667 |
653 ResolutionEnqueuer(Compiler compiler, | 668 ResolutionEnqueuer(Compiler compiler, |
654 ItemCompilationContext itemCompilationContextCreator()) | 669 ItemCompilationContext itemCompilationContextCreator()) |
655 : super('resolution enqueuer', compiler, itemCompilationContextCreator), | 670 : super('resolution enqueuer', compiler, itemCompilationContextCreator), |
656 resolvedElements = new Set<AstElement>(), | 671 resolvedElements = new Set<AstElement>(), |
657 queue = new Queue<ResolutionWorkItem>(), | 672 queue = new Queue<ResolutionWorkItem>(), |
658 deferredTaskQueue = new Queue<DeferredTask>(); | 673 deferredTaskQueue = new Queue<DeferredTask>() { |
| 674 compilationInfo = new CompilationInformation(this); |
| 675 } |
659 | 676 |
660 bool get isResolutionQueue => true; | 677 bool get isResolutionQueue => true; |
661 | 678 |
662 bool isProcessed(Element member) => resolvedElements.contains(member); | 679 bool isProcessed(Element member) => resolvedElements.contains(member); |
663 | 680 |
664 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 681 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
665 bool hasBeenResolved(Element element) { | 682 bool hasBeenResolved(Element element) { |
666 return resolvedElements.contains(element.analyzableElement.declaration); | 683 return resolvedElements.contains(element.analyzableElement.declaration); |
667 } | 684 } |
668 | 685 |
(...skipping 15 matching lines...) Expand all Loading... |
684 * | 701 * |
685 * During resolution, we have to resort to matching elements against the | 702 * During resolution, we have to resort to matching elements against the |
686 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | 703 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, |
687 * yet. | 704 * yet. |
688 */ | 705 */ |
689 bool shouldIncludeElementDueToMirrors(Element element, | 706 bool shouldIncludeElementDueToMirrors(Element element, |
690 {bool includedEnclosing}) { | 707 {bool includedEnclosing}) { |
691 return includedEnclosing || compiler.backend.requiredByMirrorSystem(element)
; | 708 return includedEnclosing || compiler.backend.requiredByMirrorSystem(element)
; |
692 } | 709 } |
693 | 710 |
694 void internalAddToWorkList(Element element) { | 711 bool internalAddToWorkList(Element element) { |
695 assert(invariant(element, element is AnalyzableElement, | 712 assert(invariant(element, element is AnalyzableElement, |
696 message: 'Element $element is not analyzable.')); | 713 message: 'Element $element is not analyzable.')); |
697 if (hasBeenResolved(element)) return; | 714 if (hasBeenResolved(element)) return false; |
698 if (queueIsClosed) { | 715 if (queueIsClosed) { |
699 throw new SpannableAssertionFailure(element, | 716 throw new SpannableAssertionFailure(element, |
700 "Resolution work list is closed. Trying to add $element."); | 717 "Resolution work list is closed. Trying to add $element."); |
701 } | 718 } |
702 | 719 |
703 compiler.world.registerUsedElement(element); | 720 compiler.world.registerUsedElement(element); |
704 | 721 |
705 queue.add(new ResolutionWorkItem(element, itemCompilationContextCreator())); | 722 queue.add(new ResolutionWorkItem(element, itemCompilationContextCreator())); |
706 | 723 |
707 // Enable isolate support if we start using something from the isolate | 724 // Enable isolate support if we start using something from the isolate |
(...skipping 21 matching lines...) Expand all Loading... |
729 // that constructors know whether they need to generate code for | 746 // that constructors know whether they need to generate code for |
730 // runtime type. | 747 // runtime type. |
731 compiler.enabledRuntimeType = true; | 748 compiler.enabledRuntimeType = true; |
732 // TODO(ahe): Record precise dependency here. | 749 // TODO(ahe): Record precise dependency here. |
733 compiler.backend.registerRuntimeType(this, compiler.globalDependencies); | 750 compiler.backend.registerRuntimeType(this, compiler.globalDependencies); |
734 } else if (element == compiler.functionApplyMethod) { | 751 } else if (element == compiler.functionApplyMethod) { |
735 compiler.enabledFunctionApply = true; | 752 compiler.enabledFunctionApply = true; |
736 } | 753 } |
737 | 754 |
738 nativeEnqueuer.registerElement(element); | 755 nativeEnqueuer.registerElement(element); |
| 756 return true; |
739 } | 757 } |
740 | 758 |
741 void enableIsolateSupport() { | 759 void enableIsolateSupport() { |
742 compiler.hasIsolateSupport = true; | 760 compiler.hasIsolateSupport = true; |
743 compiler.backend.enableIsolateSupport(this); | 761 compiler.backend.enableIsolateSupport(this); |
744 } | 762 } |
745 | 763 |
746 void enableNoSuchMethod(Element element) { | 764 void enableNoSuchMethod(Element element) { |
747 if (compiler.enabledNoSuchMethod) return; | 765 if (compiler.enabledNoSuchMethod) return; |
748 if (compiler.backend.isDefaultNoSuchMethodImplementation(element)) return; | 766 if (compiler.backend.isDefaultNoSuchMethodImplementation(element)) return; |
749 | 767 |
750 Selector selector = compiler.noSuchMethodSelector; | 768 Selector selector = compiler.noSuchMethodSelector; |
751 compiler.enabledNoSuchMethod = true; | 769 compiler.enabledNoSuchMethod = true; |
752 compiler.backend.enableNoSuchMethod(this); | 770 compiler.backend.enableNoSuchMethod(element, this); |
753 } | 771 } |
754 | 772 |
755 /** | 773 /** |
756 * Adds an action to the deferred task queue. | 774 * Adds an action to the deferred task queue. |
757 * | 775 * |
758 * The action is performed the next time the resolution queue has been | 776 * The action is performed the next time the resolution queue has been |
759 * emptied. | 777 * emptied. |
760 * | 778 * |
761 * The queue is processed in FIFO order. | 779 * The queue is processed in FIFO order. |
762 */ | 780 */ |
(...skipping 28 matching lines...) Expand all Loading... |
791 } | 809 } |
792 | 810 |
793 /// [Enqueuer] which is specific to code generation. | 811 /// [Enqueuer] which is specific to code generation. |
794 class CodegenEnqueuer extends Enqueuer { | 812 class CodegenEnqueuer extends Enqueuer { |
795 final Queue<CodegenWorkItem> queue; | 813 final Queue<CodegenWorkItem> queue; |
796 final Map<Element, js.Expression> generatedCode = | 814 final Map<Element, js.Expression> generatedCode = |
797 new Map<Element, js.Expression>(); | 815 new Map<Element, js.Expression>(); |
798 | 816 |
799 final Set<Element> newlyEnqueuedElements; | 817 final Set<Element> newlyEnqueuedElements; |
800 | 818 |
| 819 CompilationInformation compilationInfo; |
| 820 |
801 CodegenEnqueuer(Compiler compiler, | 821 CodegenEnqueuer(Compiler compiler, |
802 ItemCompilationContext itemCompilationContextCreator()) | 822 ItemCompilationContext itemCompilationContextCreator()) |
803 : queue = new Queue<CodegenWorkItem>(), | 823 : queue = new Queue<CodegenWorkItem>(), |
804 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 824 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
805 super('codegen enqueuer', compiler, itemCompilationContextCreator); | 825 super('codegen enqueuer', compiler, itemCompilationContextCreator) { |
| 826 compilationInfo = new CompilationInformation(this); |
| 827 } |
806 | 828 |
807 bool isProcessed(Element member) => | 829 bool isProcessed(Element member) => |
808 member.isAbstract || generatedCode.containsKey(member); | 830 member.isAbstract || generatedCode.containsKey(member); |
809 | 831 |
810 /** | 832 /** |
811 * Decides whether an element should be included to satisfy requirements | 833 * Decides whether an element should be included to satisfy requirements |
812 * of the mirror system. | 834 * of the mirror system. |
813 * | 835 * |
814 * For code generation, we rely on the precomputed set of elements that takes | 836 * For code generation, we rely on the precomputed set of elements that takes |
815 * subtyping constraints into account. | 837 * subtyping constraints into account. |
816 */ | 838 */ |
817 bool shouldIncludeElementDueToMirrors(Element element, | 839 bool shouldIncludeElementDueToMirrors(Element element, |
818 {bool includedEnclosing}) { | 840 {bool includedEnclosing}) { |
819 return compiler.backend.isAccessibleByReflection(element); | 841 return compiler.backend.isAccessibleByReflection(element); |
820 } | 842 } |
821 | 843 |
822 void internalAddToWorkList(Element element) { | 844 bool internalAddToWorkList(Element element) { |
823 if (compiler.hasIncrementalSupport) { | 845 if (compiler.hasIncrementalSupport) { |
824 newlyEnqueuedElements.add(element); | 846 newlyEnqueuedElements.add(element); |
825 } | 847 } |
826 // Don't generate code for foreign elements. | 848 // Don't generate code for foreign elements. |
827 if (element.isForeign(compiler)) return; | 849 if (element.isForeign(compiler)) return false; |
828 | 850 |
829 // Codegen inlines field initializers. It only needs to generate | 851 // Codegen inlines field initializers. It only needs to generate |
830 // code for checked setters. | 852 // code for checked setters. |
831 if (element.isField && element.isInstanceMember) { | 853 if (element.isField && element.isInstanceMember) { |
832 if (!compiler.enableTypeAssertions | 854 if (!compiler.enableTypeAssertions |
833 || element.enclosingElement.isClosure) { | 855 || element.enclosingElement.isClosure) { |
834 return; | 856 return false; |
835 } | 857 } |
836 } | 858 } |
837 | 859 |
838 if (queueIsClosed) { | 860 if (queueIsClosed) { |
839 throw new SpannableAssertionFailure(element, | 861 throw new SpannableAssertionFailure(element, |
840 "Codegen work list is closed. Trying to add $element"); | 862 "Codegen work list is closed. Trying to add $element"); |
841 } | 863 } |
842 CodegenWorkItem workItem = new CodegenWorkItem( | 864 CodegenWorkItem workItem = new CodegenWorkItem( |
843 element, itemCompilationContextCreator()); | 865 element, itemCompilationContextCreator()); |
844 queue.add(workItem); | 866 queue.add(workItem); |
| 867 return true; |
845 } | 868 } |
846 | 869 |
847 void _logSpecificSummary(log(message)) { | 870 void _logSpecificSummary(log(message)) { |
848 log('Compiled ${generatedCode.length} methods.'); | 871 log('Compiled ${generatedCode.length} methods.'); |
849 } | 872 } |
850 } | 873 } |
851 | 874 |
852 /// Parameterizes filtering of which work items are enqueued. | 875 /// Parameterizes filtering of which work items are enqueued. |
853 class QueueFilter { | 876 class QueueFilter { |
854 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { | 877 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { |
855 enqueuer.task.measure(() { | 878 enqueuer.task.measure(() { |
856 // Run through the classes and see if we need to compile methods. | 879 // Run through the classes and see if we need to compile methods. |
857 for (ClassElement classElement in enqueuer.universe.instantiatedClasses) { | 880 for (ClassElement classElement in enqueuer.universe.instantiatedClasses) { |
858 for (ClassElement currentClass = classElement; | 881 for (ClassElement currentClass = classElement; |
859 currentClass != null; | 882 currentClass != null; |
860 currentClass = currentClass.superclass) { | 883 currentClass = currentClass.superclass) { |
861 enqueuer.processInstantiatedClass(currentClass); | 884 enqueuer.processInstantiatedClass(currentClass); |
862 } | 885 } |
863 } | 886 } |
864 }); | 887 }); |
865 return true; | 888 return true; |
866 } | 889 } |
867 | 890 |
868 void processWorkItem(void f(WorkItem work), WorkItem work) { | 891 void processWorkItem(void f(WorkItem work), WorkItem work) { |
869 f(work); | 892 f(work); |
870 } | 893 } |
871 } | 894 } |
OLD | NEW |