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 library dart2js.enqueue; | 5 library dart2js.enqueue; |
6 | 6 |
7 import 'dart:collection' show | 7 import 'dart:collection' show |
8 Queue; | 8 Queue; |
9 | 9 |
10 import 'common.dart'; | 10 import 'common.dart'; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 Name, | 44 Name, |
45 TypedElement, | 45 TypedElement, |
46 TypedefElement; | 46 TypedefElement; |
47 import 'js/js.dart' as js; | 47 import 'js/js.dart' as js; |
48 import 'native/native.dart' as native; | 48 import 'native/native.dart' as native; |
49 import 'types/types.dart' show | 49 import 'types/types.dart' show |
50 TypeMaskStrategy; | 50 TypeMaskStrategy; |
51 import 'universe/selector.dart' show | 51 import 'universe/selector.dart' show |
52 Selector; | 52 Selector; |
53 import 'universe/universe.dart'; | 53 import 'universe/universe.dart'; |
| 54 import 'universe/use.dart' show |
| 55 StaticUse, |
| 56 StaticUseKind; |
54 import 'universe/world_impact.dart' show | 57 import 'universe/world_impact.dart' show |
55 WorldImpact; | 58 WorldImpact; |
56 import 'util/util.dart' show | 59 import 'util/util.dart' show |
57 Link, | 60 Link, |
58 Setlet; | 61 Setlet; |
59 | 62 |
60 typedef ItemCompilationContext ItemCompilationContextCreator(); | 63 typedef ItemCompilationContext ItemCompilationContextCreator(); |
61 | 64 |
62 class EnqueueTask extends CompilerTask { | 65 class EnqueueTask extends CompilerTask { |
63 final ResolutionEnqueuer resolution; | 66 final ResolutionEnqueuer resolution; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 /** | 157 /** |
155 * Adds [element] to the work list if it has not already been processed. | 158 * Adds [element] to the work list if it has not already been processed. |
156 * | 159 * |
157 * Returns [true] if the element was actually added to the queue. | 160 * Returns [true] if the element was actually added to the queue. |
158 */ | 161 */ |
159 bool internalAddToWorkList(Element element); | 162 bool internalAddToWorkList(Element element); |
160 | 163 |
161 /// Apply the [worldImpact] of processing [element] to this enqueuer. | 164 /// Apply the [worldImpact] of processing [element] to this enqueuer. |
162 void applyImpact(Element element, WorldImpact worldImpact) { | 165 void applyImpact(Element element, WorldImpact worldImpact) { |
163 // TODO(johnniwinther): Optimize the application of the world impact. | 166 // TODO(johnniwinther): Optimize the application of the world impact. |
164 worldImpact.dynamicInvocations.forEach(registerDynamicInvocation); | 167 worldImpact.dynamicUses.forEach(registerDynamicUse); |
165 worldImpact.dynamicGetters.forEach(registerDynamicGetter); | |
166 worldImpact.dynamicSetters.forEach(registerDynamicSetter); | |
167 worldImpact.staticUses.forEach(registerStaticUse); | 168 worldImpact.staticUses.forEach(registerStaticUse); |
168 worldImpact.instantiatedTypes.forEach(registerInstantiatedType); | 169 worldImpact.instantiatedTypes.forEach(registerInstantiatedType); |
169 worldImpact.isChecks.forEach(registerIsCheck); | 170 worldImpact.isChecks.forEach(registerIsCheck); |
170 worldImpact.asCasts.forEach(registerIsCheck); | 171 worldImpact.asCasts.forEach(registerIsCheck); |
171 if (compiler.enableTypeAssertions) { | 172 if (compiler.enableTypeAssertions) { |
172 worldImpact.checkedModeChecks.forEach(registerIsCheck); | 173 worldImpact.checkedModeChecks.forEach(registerIsCheck); |
173 } | 174 } |
174 worldImpact.onCatchTypes.forEach(registerIsCheck); | 175 worldImpact.onCatchTypes.forEach(registerIsCheck); |
175 worldImpact.closurizedFunctions.forEach(registerGetOfStaticFunction); | |
176 worldImpact.closures.forEach(registerClosure); | 176 worldImpact.closures.forEach(registerClosure); |
177 } | 177 } |
178 | 178 |
179 // TODO(johnniwinther): Remove the need for passing the [registry]. | |
180 void registerInstantiatedType(InterfaceType type, | 179 void registerInstantiatedType(InterfaceType type, |
181 {bool mirrorUsage: false}) { | 180 {bool mirrorUsage: false}) { |
182 task.measure(() { | 181 task.measure(() { |
183 ClassElement cls = type.element; | 182 ClassElement cls = type.element; |
184 cls.ensureResolved(resolution); | 183 cls.ensureResolved(resolution); |
185 universe.registerTypeInstantiation( | 184 universe.registerTypeInstantiation( |
186 type, | 185 type, |
187 isNative: compiler.backend.isNative(cls), | 186 isNative: compiler.backend.isNative(cls), |
188 byMirrors: mirrorUsage, | 187 byMirrors: mirrorUsage, |
189 onImplemented: (ClassElement cls) { | 188 onImplemented: (ClassElement cls) { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 superclass, this, compiler.globalDependencies); | 338 superclass, this, compiler.globalDependencies); |
340 } | 339 } |
341 | 340 |
342 while (cls != null) { | 341 while (cls != null) { |
343 processClass(cls); | 342 processClass(cls); |
344 cls = cls.superclass; | 343 cls = cls.superclass; |
345 } | 344 } |
346 }); | 345 }); |
347 } | 346 } |
348 | 347 |
349 void registerInvocation(UniverseSelector selector) { | 348 void registerDynamicUse(UniverseSelector selector) { |
350 task.measure(() { | 349 task.measure(() { |
351 if (universe.registerInvocation(selector)) { | 350 if (universe.registerDynamicUse(selector)) { |
352 handleUnseenSelector(selector); | 351 handleUnseenSelector(selector); |
353 } | 352 } |
354 }); | 353 }); |
355 } | |
356 | |
357 void registerInvokedGetter(UniverseSelector selector) { | |
358 task.measure(() { | |
359 if (universe.registerInvokedGetter(selector)) { | |
360 handleUnseenSelector(selector); | |
361 } | |
362 }); | |
363 } | |
364 | |
365 void registerInvokedSetter(UniverseSelector selector) { | |
366 task.measure(() { | |
367 if (universe.registerInvokedSetter(selector)) { | |
368 handleUnseenSelector(selector); | |
369 } | |
370 }); | |
371 } | 354 } |
372 | 355 |
373 /** | 356 /** |
374 * Decides whether an element should be included to satisfy requirements | 357 * Decides whether an element should be included to satisfy requirements |
375 * of the mirror system. [includedEnclosing] provides a hint whether the | 358 * of the mirror system. [includedEnclosing] provides a hint whether the |
376 * enclosing element was included. | 359 * enclosing element was included. |
377 * | 360 * |
378 * The actual implementation depends on the current compiler phase. | 361 * The actual implementation depends on the current compiler phase. |
379 */ | 362 */ |
380 bool shouldIncludeElementDueToMirrors(Element element, | 363 bool shouldIncludeElementDueToMirrors(Element element, |
(...skipping 13 matching lines...) Expand all Loading... |
394 bool enclosingWasIncluded) { | 377 bool enclosingWasIncluded) { |
395 if (shouldIncludeElementDueToMirrors(ctor, | 378 if (shouldIncludeElementDueToMirrors(ctor, |
396 includedEnclosing: enclosingWasIncluded)) { | 379 includedEnclosing: enclosingWasIncluded)) { |
397 logEnqueueReflectiveAction(ctor); | 380 logEnqueueReflectiveAction(ctor); |
398 ClassElement cls = ctor.declaration.enclosingClass; | 381 ClassElement cls = ctor.declaration.enclosingClass; |
399 compiler.backend.registerInstantiatedType( | 382 compiler.backend.registerInstantiatedType( |
400 cls.rawType, | 383 cls.rawType, |
401 this, | 384 this, |
402 compiler.mirrorDependencies, | 385 compiler.mirrorDependencies, |
403 mirrorUsage: true); | 386 mirrorUsage: true); |
404 registerStaticUse(ctor.declaration); | 387 registerStaticUse(new StaticUse.foreignUse(ctor.declaration)); |
405 } | 388 } |
406 } | 389 } |
407 | 390 |
408 /// Enqeue the member [element] if it is required for reflection. | 391 /// Enqeue the member [element] if it is required for reflection. |
409 /// | 392 /// |
410 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 393 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
411 /// needed for reflection. | 394 /// needed for reflection. |
412 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { | 395 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { |
413 if (shouldIncludeElementDueToMirrors(element, | 396 if (shouldIncludeElementDueToMirrors(element, |
414 includedEnclosing: enclosingWasIncluded)) { | 397 includedEnclosing: enclosingWasIncluded)) { |
415 logEnqueueReflectiveAction(element); | 398 logEnqueueReflectiveAction(element); |
416 if (element.isTypedef) { | 399 if (element.isTypedef) { |
417 TypedefElement typedef = element; | 400 TypedefElement typedef = element; |
418 typedef.ensureResolved(resolution); | 401 typedef.ensureResolved(resolution); |
419 compiler.world.allTypedefs.add(element); | 402 compiler.world.allTypedefs.add(element); |
420 } else if (Elements.isStaticOrTopLevel(element)) { | 403 } else if (Elements.isStaticOrTopLevel(element)) { |
421 registerStaticUse(element.declaration); | 404 registerStaticUse(new StaticUse.foreignUse(element.declaration)); |
422 } else if (element.isInstanceMember) { | 405 } else if (element.isInstanceMember) { |
423 // We need to enqueue all members matching this one in subclasses, as | 406 // We need to enqueue all members matching this one in subclasses, as |
424 // well. | 407 // well. |
425 // TODO(herhut): Use TypedSelector.subtype for enqueueing | 408 // TODO(herhut): Use TypedSelector.subtype for enqueueing |
426 UniverseSelector selector = new UniverseSelector( | 409 UniverseSelector selector = new UniverseSelector( |
427 new Selector.fromElement(element), null); | 410 new Selector.fromElement(element), null); |
428 registerSelectorUse(selector); | 411 registerDynamicUse(selector); |
429 if (element.isField) { | 412 if (element.isField) { |
430 UniverseSelector selector = new UniverseSelector( | 413 UniverseSelector selector = new UniverseSelector( |
431 new Selector.setter(new Name( | 414 new Selector.setter(new Name( |
432 element.name, element.library, isSetter: true)), null); | 415 element.name, element.library, isSetter: true)), null); |
433 registerInvokedSetter(selector); | 416 registerDynamicUse(selector); |
434 } | 417 } |
435 } | 418 } |
436 } | 419 } |
437 } | 420 } |
438 | 421 |
439 /// Enqeue the member [element] if it is required for reflection. | 422 /// Enqeue the member [element] if it is required for reflection. |
440 /// | 423 /// |
441 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 424 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
442 /// needed for reflection. | 425 /// needed for reflection. |
443 void enqueueReflectiveElementsInClass(ClassElement cls, | 426 void enqueueReflectiveElementsInClass(ClassElement cls, |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 | 552 |
570 processInstanceMembers(String n, bool f(Element e)) { | 553 processInstanceMembers(String n, bool f(Element e)) { |
571 processSet(instanceMembersByName, n, f); | 554 processSet(instanceMembersByName, n, f); |
572 } | 555 } |
573 | 556 |
574 processInstanceFunctions(String n, bool f(Element e)) { | 557 processInstanceFunctions(String n, bool f(Element e)) { |
575 processSet(instanceFunctionsByName, n, f); | 558 processSet(instanceFunctionsByName, n, f); |
576 } | 559 } |
577 | 560 |
578 void handleUnseenSelector(UniverseSelector universeSelector) { | 561 void handleUnseenSelector(UniverseSelector universeSelector) { |
579 strategy.processSelector(this, universeSelector); | 562 strategy.processDynamicUse(this, universeSelector); |
580 } | 563 } |
581 | 564 |
582 void handleUnseenSelectorInternal(UniverseSelector universeSelector) { | 565 void handleUnseenSelectorInternal(UniverseSelector universeSelector) { |
583 Selector selector = universeSelector.selector; | 566 Selector selector = universeSelector.selector; |
584 String methodName = selector.name; | 567 String methodName = selector.name; |
585 processInstanceMembers(methodName, (Element member) { | 568 processInstanceMembers(methodName, (Element member) { |
586 if (universeSelector.appliesUnnamed(member, compiler.world)) { | 569 if (universeSelector.appliesUnnamed(member, compiler.world)) { |
587 if (member.isFunction && selector.isGetter) { | 570 if (member.isFunction && selector.isGetter) { |
588 registerClosurizedMember(member); | 571 registerClosurizedMember(member); |
589 } | 572 } |
(...skipping 29 matching lines...) Expand all Loading... |
619 return false; | 602 return false; |
620 }); | 603 }); |
621 } | 604 } |
622 } | 605 } |
623 | 606 |
624 /** | 607 /** |
625 * Documentation wanted -- johnniwinther | 608 * Documentation wanted -- johnniwinther |
626 * | 609 * |
627 * Invariant: [element] must be a declaration element. | 610 * Invariant: [element] must be a declaration element. |
628 */ | 611 */ |
629 void registerStaticUse(Element element) { | 612 void registerStaticUse(StaticUse staticUse) { |
630 if (element == null) return; | 613 strategy.processStaticUse(this, staticUse); |
631 strategy.processStaticUse(this, element); | |
632 } | 614 } |
633 | 615 |
634 void registerStaticUseInternal(Element element) { | 616 void registerStaticUseInternal(StaticUse staticUse) { |
| 617 Element element = staticUse.element; |
635 assert(invariant(element, element.isDeclaration, | 618 assert(invariant(element, element.isDeclaration, |
636 message: "Element ${element} is not the declaration.")); | 619 message: "Element ${element} is not the declaration.")); |
637 if (Elements.isStaticOrTopLevel(element) && element.isField) { | 620 universe.registerStaticUse(staticUse); |
638 universe.registerStaticFieldUse(element); | 621 compiler.backend.registerStaticUse(element, this); |
| 622 bool addElement = true; |
| 623 switch (staticUse.kind) { |
| 624 case StaticUseKind.STATIC_TEAR_OFF: |
| 625 compiler.backend.registerGetOfStaticFunction(this); |
| 626 break; |
| 627 case StaticUseKind.FIELD_GET: |
| 628 case StaticUseKind.FIELD_SET: |
| 629 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and |
| 630 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
| 631 addElement = false; |
| 632 break; |
| 633 case StaticUseKind.SUPER_TEAR_OFF: |
| 634 case StaticUseKind.GENERAL: |
| 635 break; |
639 } | 636 } |
640 addToWorkList(element); | 637 if (addElement) { |
641 compiler.backend.registerStaticUse(element, this); | 638 addToWorkList(element); |
642 } | |
643 | |
644 void registerGetOfStaticFunction(FunctionElement element) { | |
645 registerStaticUse(element); | |
646 compiler.backend.registerGetOfStaticFunction(this); | |
647 universe.staticFunctionsNeedingGetter.add(element); | |
648 } | |
649 | |
650 void registerDynamicInvocation(UniverseSelector selector) { | |
651 assert(selector != null); | |
652 registerInvocation(selector); | |
653 } | |
654 | |
655 void registerSelectorUse(UniverseSelector universeSelector) { | |
656 if (universeSelector.selector.isGetter) { | |
657 registerInvokedGetter(universeSelector); | |
658 } else if (universeSelector.selector.isSetter) { | |
659 registerInvokedSetter(universeSelector); | |
660 } else { | |
661 registerInvocation(universeSelector); | |
662 } | 639 } |
663 } | 640 } |
664 | 641 |
665 void registerDynamicGetter(UniverseSelector selector) { | |
666 registerInvokedGetter(selector); | |
667 } | |
668 | |
669 void registerDynamicSetter(UniverseSelector selector) { | |
670 registerInvokedSetter(selector); | |
671 } | |
672 | |
673 void registerGetterForSuperMethod(Element element) { | |
674 universe.methodsNeedingSuperGetter.add(element); | |
675 } | |
676 | |
677 void registerFieldGetter(Element element) { | |
678 universe.fieldGetters.add(element); | |
679 } | |
680 | |
681 void registerFieldSetter(Element element) { | |
682 universe.fieldSetters.add(element); | |
683 } | |
684 | |
685 void registerIsCheck(DartType type) { | 642 void registerIsCheck(DartType type) { |
686 type = universe.registerIsCheck(type, compiler); | 643 type = universe.registerIsCheck(type, compiler); |
687 // Even in checked mode, type annotations for return type and argument | 644 // Even in checked mode, type annotations for return type and argument |
688 // types do not imply type checks, so there should never be a check | 645 // types do not imply type checks, so there should never be a check |
689 // against the type variable of a typedef. | 646 // against the type variable of a typedef. |
690 assert(!type.isTypeVariable || | 647 assert(!type.isTypeVariable || |
691 !type.element.enclosingElement.isTypedef); | 648 !type.element.enclosingElement.isTypedef); |
692 } | 649 } |
693 | 650 |
694 void registerCallMethodWithFreeTypeVariables(Element element) { | 651 void registerCallMethodWithFreeTypeVariables(Element element) { |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 } | 986 } |
1030 | 987 |
1031 /// Strategy used by the enqueuer to populate the world. | 988 /// Strategy used by the enqueuer to populate the world. |
1032 // TODO(johnniwinther): Merge this interface with [QueueFilter]. | 989 // TODO(johnniwinther): Merge this interface with [QueueFilter]. |
1033 class EnqueuerStrategy { | 990 class EnqueuerStrategy { |
1034 const EnqueuerStrategy(); | 991 const EnqueuerStrategy(); |
1035 | 992 |
1036 /// Process a class instantiated in live code. | 993 /// Process a class instantiated in live code. |
1037 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) {} | 994 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) {} |
1038 | 995 |
1039 /// Process an element statically accessed in live code. | 996 /// Process a static use of and element in live code. |
1040 void processStaticUse(Enqueuer enqueuer, Element element) {} | 997 void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) {} |
1041 | 998 |
1042 /// Process a selector for a call site in live code. | 999 /// Process a selector for a call site in live code. |
1043 void processSelector(Enqueuer enqueuer, UniverseSelector selector) {} | 1000 void processDynamicUse(Enqueuer enqueuer, UniverseSelector dynamicUse) {} |
1044 } | 1001 } |
1045 | 1002 |
1046 class TreeShakingEnqueuerStrategy implements EnqueuerStrategy { | 1003 class TreeShakingEnqueuerStrategy implements EnqueuerStrategy { |
1047 const TreeShakingEnqueuerStrategy(); | 1004 const TreeShakingEnqueuerStrategy(); |
1048 | 1005 |
1049 @override | 1006 @override |
1050 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) { | 1007 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) { |
1051 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); | 1008 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); |
1052 } | 1009 } |
1053 | 1010 |
1054 @override | 1011 @override |
1055 void processStaticUse(Enqueuer enqueuer, Element element) { | 1012 void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) { |
1056 enqueuer.registerStaticUseInternal(element); | 1013 enqueuer.registerStaticUseInternal(staticUse); |
1057 } | 1014 } |
1058 | 1015 |
1059 @override | 1016 @override |
1060 void processSelector(Enqueuer enqueuer, UniverseSelector selector) { | 1017 void processDynamicUse(Enqueuer enqueuer, UniverseSelector dynamicUse) { |
1061 enqueuer.handleUnseenSelectorInternal(selector); | 1018 enqueuer.handleUnseenSelectorInternal(dynamicUse); |
1062 } | 1019 } |
1063 } | 1020 } |
OLD | NEW |