| 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 class EnqueueTask extends CompilerTask { | 7 class EnqueueTask extends CompilerTask { |
| 8 final ResolutionEnqueuer resolution; | 8 final ResolutionEnqueuer resolution; |
| 9 final CodegenEnqueuer codegen; | 9 final CodegenEnqueuer codegen; |
| 10 | 10 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 bool get isResolutionQueue => false; | 103 bool get isResolutionQueue => false; |
| 104 | 104 |
| 105 /// Returns [:true:] if [member] has been processed by this enqueuer. | 105 /// Returns [:true:] if [member] has been processed by this enqueuer. |
| 106 bool isProcessed(Element member); | 106 bool isProcessed(Element member); |
| 107 | 107 |
| 108 /** | 108 /** |
| 109 * Documentation wanted -- johnniwinther | 109 * Documentation wanted -- johnniwinther |
| 110 * | 110 * |
| 111 * Invariant: [element] must be a declaration element. | 111 * Invariant: [element] must be a declaration element. |
| 112 */ | 112 */ |
| 113 void addToWorkList(Element element, [TreeElements elements]) { | 113 void addToWorkList(Element element) { |
| 114 assert(invariant(element, element.isDeclaration)); | 114 assert(invariant(element, element.isDeclaration)); |
| 115 if (element.isForeign(compiler)) return; | 115 if (element.isForeign(compiler)) return; |
| 116 | 116 |
| 117 if (element.isForwardingConstructor) { | 117 if (element.isForwardingConstructor) { |
| 118 addToWorkList(element.targetConstructor, elements); | 118 addToWorkList(element.targetConstructor); |
| 119 return; | 119 return; |
| 120 } | 120 } |
| 121 | 121 |
| 122 if (!addElementToWorkList(element, elements)) return; | 122 internalAddToWorkList(element); |
| 123 | |
| 124 // Enable runtime type support if we discover a getter called runtimeType. | |
| 125 // We have to enable runtime type before hitting the codegen, so | |
| 126 // that constructors know whether they need to generate code for | |
| 127 // runtime type. | |
| 128 if (element.isGetter() && element.name == Compiler.RUNTIME_TYPE) { | |
| 129 compiler.enabledRuntimeType = true; | |
| 130 // TODO(ahe): Record precise dependency here. | |
| 131 compiler.backend.registerRuntimeType(compiler.globalDependencies); | |
| 132 } else if (element == compiler.functionApplyMethod) { | |
| 133 compiler.enabledFunctionApply = true; | |
| 134 } else if (element == compiler.invokeOnMethod) { | |
| 135 compiler.enabledInvokeOn = true; | |
| 136 } | |
| 137 | |
| 138 nativeEnqueuer.registerElement(element); | |
| 139 } | 123 } |
| 140 | 124 |
| 141 /** | 125 /** |
| 142 * Adds [element] to the work list if it has not already been processed. | 126 * Adds [element] to the work list if it has not already been processed. |
| 143 * | |
| 144 * Returns [:true:] if the [element] should be processed. | |
| 145 */ | 127 */ |
| 146 // TODO(johnniwinther): Change to 'Returns true if the element was added to | 128 void internalAddToWorkList(Element element); |
| 147 // the work list'? | |
| 148 bool addElementToWorkList(Element element, [TreeElements elements]); | |
| 149 | 129 |
| 150 void registerInstantiatedType(InterfaceType type, TreeElements elements) { | 130 void registerInstantiatedType(InterfaceType type, TreeElements elements) { |
| 151 ClassElement cls = type.element; | 131 ClassElement cls = type.element; |
| 152 elements.registerDependency(cls); | 132 elements.registerDependency(cls); |
| 153 cls.ensureResolved(compiler); | 133 cls.ensureResolved(compiler); |
| 154 universe.instantiatedTypes.add(type); | 134 universe.instantiatedTypes.add(type); |
| 155 if (universe.instantiatedClasses.contains(cls)) return; | 135 if (universe.instantiatedClasses.contains(cls)) return; |
| 156 if (!cls.isAbstract(compiler)) { | 136 if (!cls.isAbstract(compiler)) { |
| 157 universe.instantiatedClasses.add(cls); | 137 universe.instantiatedClasses.add(cls); |
| 158 } | 138 } |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 | 584 |
| 605 bool get isResolutionQueue => true; | 585 bool get isResolutionQueue => true; |
| 606 | 586 |
| 607 bool isProcessed(Element member) => resolvedElements.containsKey(member); | 587 bool isProcessed(Element member) => resolvedElements.containsKey(member); |
| 608 | 588 |
| 609 TreeElements getCachedElements(Element element) { | 589 TreeElements getCachedElements(Element element) { |
| 610 // TODO(ngeoffray): Get rid of this check. | 590 // TODO(ngeoffray): Get rid of this check. |
| 611 if (element.enclosingElement.isClosure()) { | 591 if (element.enclosingElement.isClosure()) { |
| 612 closureMapping.ClosureClassElement cls = element.enclosingElement; | 592 closureMapping.ClosureClassElement cls = element.enclosingElement; |
| 613 element = cls.methodElement; | 593 element = cls.methodElement; |
| 594 } else if (element.isGenerativeConstructorBody()) { |
| 595 ConstructorBodyElement body = element; |
| 596 element = body.constructor; |
| 614 } | 597 } |
| 615 Element owner = element.getOutermostEnclosingMemberOrTopLevel(); | 598 Element owner = element.getOutermostEnclosingMemberOrTopLevel(); |
| 616 if (owner == null) { | 599 if (owner == null) { |
| 617 owner = element; | 600 owner = element; |
| 618 } | 601 } |
| 619 return resolvedElements[owner.declaration]; | 602 return resolvedElements[owner.declaration]; |
| 620 } | 603 } |
| 621 | 604 |
| 622 /** | 605 void internalAddToWorkList(Element element) { |
| 623 * Sets the resolved elements of [element] to [elements], or if [elements] is | 606 if (getCachedElements(element) != null) return; |
| 624 * [:null:], to the elements found through [getCachedElements]. | |
| 625 * | |
| 626 * Returns the resolved elements. | |
| 627 */ | |
| 628 TreeElements ensureCachedElements(Element element, TreeElements elements) { | |
| 629 if (elements == null) { | |
| 630 elements = getCachedElements(element); | |
| 631 } | |
| 632 resolvedElements[element] = elements; | |
| 633 return elements; | |
| 634 } | |
| 635 | |
| 636 bool addElementToWorkList(Element element, [TreeElements elements]) { | |
| 637 if (queueIsClosed) { | 607 if (queueIsClosed) { |
| 638 if (getCachedElements(element) != null) return false; | |
| 639 throw new SpannableAssertionFailure(element, | 608 throw new SpannableAssertionFailure(element, |
| 640 "Resolution work list is closed."); | 609 "Resolution work list is closed."); |
| 641 } | 610 } |
| 642 if (elements == null) { | |
| 643 elements = getCachedElements(element); | |
| 644 } | |
| 645 compiler.world.registerUsedElement(element); | 611 compiler.world.registerUsedElement(element); |
| 646 | 612 |
| 647 if (elements == null) { | 613 queue.add(new ResolutionWorkItem(element, itemCompilationContextCreator())); |
| 648 queue.add( | |
| 649 new ResolutionWorkItem(element, itemCompilationContextCreator())); | |
| 650 } | |
| 651 | 614 |
| 652 // Enable isolate support if we start using something from the | 615 // Enable isolate support if we start using something from the |
| 653 // isolate library, or timers for the async library. | 616 // isolate library, or timers for the async library. |
| 654 LibraryElement library = element.getLibrary(); | 617 LibraryElement library = element.getLibrary(); |
| 655 if (!compiler.hasIsolateSupport()) { | 618 if (!compiler.hasIsolateSupport()) { |
| 656 String uri = library.canonicalUri.toString(); | 619 String uri = library.canonicalUri.toString(); |
| 657 if (uri == 'dart:isolate') { | 620 if (uri == 'dart:isolate') { |
| 658 enableIsolateSupport(library); | 621 enableIsolateSupport(library); |
| 659 } else if (uri == 'dart:async') { | 622 } else if (uri == 'dart:async') { |
| 660 ClassElement cls = element.getEnclosingClass(); | 623 ClassElement cls = element.getEnclosingClass(); |
| 661 if (cls != null && cls.name == const SourceString('Timer')) { | 624 if (cls != null && cls.name == const SourceString('Timer')) { |
| 662 // The [:Timer:] class uses the event queue of the isolate | 625 // The [:Timer:] class uses the event queue of the isolate |
| 663 // library, so we make sure that event queue is generated. | 626 // library, so we make sure that event queue is generated. |
| 664 enableIsolateSupport(library); | 627 enableIsolateSupport(library); |
| 665 } | 628 } |
| 666 } | 629 } |
| 667 } | 630 } |
| 668 | 631 |
| 669 return true; | 632 if (element.isGetter() && element.name == Compiler.RUNTIME_TYPE) { |
| 633 // Enable runtime type support if we discover a getter called runtimeType. |
| 634 // We have to enable runtime type before hitting the codegen, so |
| 635 // that constructors know whether they need to generate code for |
| 636 // runtime type. |
| 637 compiler.enabledRuntimeType = true; |
| 638 // TODO(ahe): Record precise dependency here. |
| 639 compiler.backend.registerRuntimeType(compiler.globalDependencies); |
| 640 } else if (element == compiler.functionApplyMethod) { |
| 641 compiler.enabledFunctionApply = true; |
| 642 } else if (element == compiler.invokeOnMethod) { |
| 643 compiler.enabledInvokeOn = true; |
| 644 } |
| 645 |
| 646 nativeEnqueuer.registerElement(element); |
| 670 } | 647 } |
| 671 | 648 |
| 672 void enableIsolateSupport(LibraryElement element) { | 649 void enableIsolateSupport(LibraryElement element) { |
| 673 compiler.isolateLibrary = element.patch; | 650 compiler.isolateLibrary = element.patch; |
| 674 var startRootIsolate = | 651 var startRootIsolate = |
| 675 compiler.isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE); | 652 compiler.isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE); |
| 676 addToWorkList(startRootIsolate); | 653 addToWorkList(startRootIsolate); |
| 677 compiler.globalDependencies.registerDependency(startRootIsolate); | 654 compiler.globalDependencies.registerDependency(startRootIsolate); |
| 678 addToWorkList(compiler.isolateHelperLibrary.find( | 655 addToWorkList(compiler.isolateHelperLibrary.find( |
| 679 const SourceString('_currentIsolate'))); | 656 const SourceString('_currentIsolate'))); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 new Map<Element, js.Expression>(); | 715 new Map<Element, js.Expression>(); |
| 739 | 716 |
| 740 CodegenEnqueuer(Compiler compiler, | 717 CodegenEnqueuer(Compiler compiler, |
| 741 ItemCompilationContext itemCompilationContextCreator()) | 718 ItemCompilationContext itemCompilationContextCreator()) |
| 742 : super('codegen enqueuer', compiler, itemCompilationContextCreator), | 719 : super('codegen enqueuer', compiler, itemCompilationContextCreator), |
| 743 queue = new Queue<CodegenWorkItem>(); | 720 queue = new Queue<CodegenWorkItem>(); |
| 744 | 721 |
| 745 bool isProcessed(Element member) => | 722 bool isProcessed(Element member) => |
| 746 member.isAbstract(compiler) || generatedCode.containsKey(member); | 723 member.isAbstract(compiler) || generatedCode.containsKey(member); |
| 747 | 724 |
| 748 bool addElementToWorkList(Element element, [TreeElements elements]) { | 725 void internalAddToWorkList(Element element) { |
| 749 // Codegen inlines field initializers, so it does not need to add | 726 // Codegen inlines field initializers, so it does not need to add |
| 750 // individual fields in the work list. | 727 // individual fields in the work list. |
| 751 if (element.isField() && element.isInstanceMember()) return true; | 728 if (element.isField() && element.isInstanceMember()) return; |
| 752 | 729 |
| 753 if (queueIsClosed) { | 730 if (queueIsClosed) { |
| 754 throw new SpannableAssertionFailure(element, | 731 throw new SpannableAssertionFailure(element, |
| 755 "Codegen work list is closed."); | 732 "Codegen work list is closed."); |
| 756 } | 733 } |
| 757 elements = | |
| 758 compiler.enqueuer.resolution.ensureCachedElements(element, elements); | |
| 759 | |
| 760 CodegenWorkItem workItem = new CodegenWorkItem( | 734 CodegenWorkItem workItem = new CodegenWorkItem( |
| 761 element, elements, itemCompilationContextCreator()); | 735 element, itemCompilationContextCreator()); |
| 762 queue.add(workItem); | 736 queue.add(workItem); |
| 763 | |
| 764 return true; | |
| 765 } | 737 } |
| 766 | 738 |
| 767 void forEach(f(WorkItem work)) { | 739 void forEach(f(WorkItem work)) { |
| 768 while(!queue.isEmpty) { | 740 while(!queue.isEmpty) { |
| 769 // TODO(johnniwinther): Find an optimal process order for codegen. | 741 // TODO(johnniwinther): Find an optimal process order for codegen. |
| 770 f(queue.removeLast()); | 742 f(queue.removeLast()); |
| 771 } | 743 } |
| 772 } | 744 } |
| 773 | 745 |
| 774 void _logSpecificSummary(log(message)) { | 746 void _logSpecificSummary(log(message)) { |
| 775 log('Compiled ${generatedCode.length} methods.'); | 747 log('Compiled ${generatedCode.length} methods.'); |
| 776 } | 748 } |
| 777 } | 749 } |
| OLD | NEW |