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