Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_incremental.library_updater; | 5 library dart2js_incremental.library_updater; |
| 6 | 6 |
| 7 import 'dart:async' show | 7 import 'dart:async' show |
| 8 Future; | 8 Future; |
| 9 | 9 |
| 10 import 'dart:convert' show | 10 import 'dart:convert' show |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 LibraryElementX library) { | 248 LibraryElementX library) { |
| 249 invalidateScopesAffectedBy(element, library); | 249 invalidateScopesAffectedBy(element, library); |
| 250 | 250 |
| 251 updates.add(new AddedClassUpdate(compiler, element, library)); | 251 updates.add(new AddedClassUpdate(compiler, element, library)); |
| 252 } | 252 } |
| 253 | 253 |
| 254 bool canReuseRemovedElement(PartialElement element) { | 254 bool canReuseRemovedElement(PartialElement element) { |
| 255 if (element is PartialFunctionElement) { | 255 if (element is PartialFunctionElement) { |
| 256 removeFunction(element); | 256 removeFunction(element); |
| 257 return true; | 257 return true; |
| 258 } else if (element is PartialClassElement) { | |
| 259 removeClass(element); | |
| 260 return true; | |
| 258 } | 261 } |
| 259 return cannotReuse(element, "Removed element that isn't a function."); | 262 return cannotReuse(element, "Removed element that isn't a function."); |
| 260 } | 263 } |
| 261 | 264 |
| 262 void removeFunction(PartialFunctionElement element) { | 265 void removeFunction(PartialFunctionElement element) { |
| 263 logVerbose("Removed method $element."); | 266 logVerbose("Removed method $element."); |
| 264 | 267 |
| 265 invalidateScopesAffectedBy(element, element.enclosingElement); | 268 invalidateScopesAffectedBy(element, element.enclosingElement); |
| 266 | 269 |
| 267 _removedElements.add(element); | 270 _removedElements.add(element); |
| 268 | 271 |
| 269 updates.add(new RemovedFunctionUpdate(compiler, element)); | 272 updates.add(new RemovedFunctionUpdate(compiler, element)); |
| 270 } | 273 } |
| 271 | 274 |
| 275 void removeClass(PartialClassElement element) { | |
| 276 logVerbose("Removed class $element."); | |
| 277 | |
| 278 invalidateScopesAffectedBy(element, element.enclosingElement); | |
| 279 | |
| 280 _removedElements.add(element); | |
| 281 element.forEachLocalMember((ElementX member) { | |
| 282 _removedElements.add(member); | |
| 283 }); | |
| 284 | |
| 285 updates.add(new RemovedClassUpdate(compiler, element)); | |
| 286 } | |
| 287 | |
| 272 void invalidateScopesAffectedBy( | 288 void invalidateScopesAffectedBy( |
| 273 ElementX element, | 289 ElementX element, |
| 274 ScopeContainerElement container) { | 290 ScopeContainerElement container) { |
| 275 for (ScopeContainerElement scope in scopesAffectedBy(element, container)) { | 291 for (ScopeContainerElement scope in scopesAffectedBy(element, container)) { |
| 276 scanSites(scope, (Element member, DeclarationSite site) { | 292 scanSites(scope, (Element member, DeclarationSite site) { |
| 277 // TODO(ahe): Cache qualifiedNamesIn to avoid quadratic behavior. | 293 // TODO(ahe): Cache qualifiedNamesIn to avoid quadratic behavior. |
| 278 Map<String, List<String>> names = qualifiedNamesIn(site); | 294 Map<String, List<String>> names = qualifiedNamesIn(site); |
| 279 if (canNamesResolveStaticallyTo(names, element, container)) { | 295 if (canNamesResolveStaticallyTo(names, element, container)) { |
| 280 _elementsToInvalidate.add(member); | 296 _elementsToInvalidate.add(member); |
| 281 } | 297 } |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 PartialFunctionElement get before; | 625 PartialFunctionElement get before; |
| 610 | 626 |
| 611 /// Reset various caches and remove this element from the compiler's internal | 627 /// Reset various caches and remove this element from the compiler's internal |
| 612 /// state. | 628 /// state. |
| 613 void reuseElement() { | 629 void reuseElement() { |
| 614 compiler.forgetElement(before); | 630 compiler.forgetElement(before); |
| 615 before.reuseElement(); | 631 before.reuseElement(); |
| 616 } | 632 } |
| 617 } | 633 } |
| 618 | 634 |
| 619 class RemovedFunctionUpdate extends Update with JsFeatures, ReuseFunction { | 635 class RemovalUpdate extends Update { |
| 620 final PartialFunctionElement element; | 636 ElementX get element; |
| 621 | 637 |
| 622 /// Name of property to remove using JavaScript "delete". Null for | 638 RemovalUpdate(Compiler compiler) |
| 623 /// non-instance methods. | |
| 624 String name; | |
| 625 | |
| 626 /// Name of super-alias property to remove using JavaScript "delete". Null | |
| 627 /// for methods that aren't "super aliased", and non-instance methods. | |
| 628 String superName; | |
| 629 | |
| 630 /// For instance methods, access to class object. Otherwise, access to the | |
| 631 /// method itself. | |
| 632 jsAst.Node elementAccess; | |
| 633 | |
| 634 bool wasStateCaptured = false; | |
| 635 | |
| 636 RemovedFunctionUpdate(Compiler compiler, this.element) | |
| 637 : super(compiler); | 639 : super(compiler); |
| 638 | 640 |
| 639 PartialFunctionElement get before => element; | |
| 640 | |
| 641 PartialElement get after => null; | |
| 642 | |
| 643 bool get isRemoval => true; | 641 bool get isRemoval => true; |
| 644 | 642 |
| 645 void captureState() { | 643 void writeUpdateJsOn(List<jsAst.Statement> updates); |
| 646 if (wasStateCaptured) throw "captureState was called twice."; | |
| 647 | |
| 648 if (element.isInstanceMember) { | |
| 649 elementAccess = namer.elementAccess(element.enclosingClass); | |
| 650 name = namer.getNameOfMember(element); | |
| 651 if (backend.isAliasedSuperMember(element)) { | |
| 652 superName = namer.getNameOfAliasedSuperMember(element); | |
| 653 } | |
| 654 } else { | |
| 655 elementAccess = namer.elementAccess(element); | |
| 656 } | |
| 657 | |
| 658 wasStateCaptured = true; | |
| 659 } | |
| 660 | |
| 661 PartialFunctionElement apply() { | |
| 662 if (!wasStateCaptured) throw "captureState must be called before apply."; | |
| 663 removeFromEnclosing(); | |
| 664 reuseElement(); | |
| 665 return null; | |
| 666 } | |
| 667 | 644 |
| 668 void removeFromEnclosing() { | 645 void removeFromEnclosing() { |
| 669 // TODO(ahe): Need to recompute duplicated elements logic again. Simplest | 646 // TODO(ahe): Need to recompute duplicated elements logic again. Simplest |
| 670 // solution is probably to remove all elements from enclosing scope and add | 647 // solution is probably to remove all elements from enclosing scope and add |
| 671 // them back. | 648 // them back. |
| 672 PartialClassElement cls = element.enclosingClass; | 649 PartialClassElement cls = element.enclosingClass; |
| 673 if (cls == null) { | 650 if (cls == null) { |
| 674 removeFromLibrary(element.library); | 651 removeFromLibrary(element.library); |
| 675 } else { | 652 } else { |
| 676 removeFromEnclosingClass(cls); | 653 removeFromEnclosingClass(cls); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 694 LinkBuilder copy = new LinkBuilder(); | 671 LinkBuilder copy = new LinkBuilder(); |
| 695 | 672 |
| 696 for (; !link.isEmpty; link = link.tail) { | 673 for (; !link.isEmpty; link = link.tail) { |
| 697 if (link.head != e) { | 674 if (link.head != e) { |
| 698 copy.addLast(e); | 675 copy.addLast(e); |
| 699 } | 676 } |
| 700 } | 677 } |
| 701 | 678 |
| 702 return copy.toLink(link); | 679 return copy.toLink(link); |
| 703 } | 680 } |
| 681 } | |
| 682 | |
| 683 class RemovedFunctionUpdate extends RemovalUpdate | |
| 684 with JsFeatures, ReuseFunction { | |
| 685 final PartialFunctionElement element; | |
| 686 | |
| 687 /// Name of property to remove using JavaScript "delete". Null for | |
| 688 /// non-instance methods. | |
| 689 String name; | |
| 690 | |
| 691 /// Name of super-alias property to remove using JavaScript "delete". Null | |
| 692 /// for methods that aren't "super aliased", and non-instance methods. | |
| 693 String superName; | |
| 694 | |
| 695 /// For instance methods, access to class object. Otherwise, access to the | |
| 696 /// method itself. | |
| 697 jsAst.Node elementAccess; | |
| 698 | |
| 699 bool wasStateCaptured = false; | |
| 700 | |
| 701 RemovedFunctionUpdate(Compiler compiler, this.element) | |
| 702 : super(compiler); | |
| 703 | |
| 704 PartialFunctionElement get before => element; | |
| 705 | |
| 706 PartialFunctionElement get after => null; | |
| 707 | |
| 708 void captureState() { | |
| 709 if (wasStateCaptured) throw "captureState was called twice."; | |
| 710 wasStateCaptured = true; | |
| 711 | |
| 712 if (element.isInstanceMember) { | |
| 713 elementAccess = namer.elementAccess(element.enclosingClass); | |
| 714 name = namer.getNameOfMember(element); | |
| 715 if (backend.isAliasedSuperMember(element)) { | |
| 716 superName = namer.getNameOfAliasedSuperMember(element); | |
| 717 } | |
| 718 } else { | |
| 719 elementAccess = namer.elementAccess(element); | |
| 720 } | |
| 721 } | |
| 722 | |
| 723 PartialFunctionElement apply() { | |
| 724 if (!wasStateCaptured) throw "captureState must be called before apply."; | |
| 725 removeFromEnclosing(); | |
| 726 reuseElement(); | |
| 727 return null; | |
| 728 } | |
| 704 | 729 |
| 705 void writeUpdateJsOn(List<jsAst.Statement> updates) { | 730 void writeUpdateJsOn(List<jsAst.Statement> updates) { |
| 706 if (elementAccess == null) { | 731 if (elementAccess == null) { |
| 707 compiler.internalError( | 732 compiler.internalError( |
| 708 element, 'No elementAccess for ${element.runtimeType}'); | 733 element, 'No elementAccess for ${element.runtimeType}'); |
| 709 } | 734 } |
| 710 if (element.isInstanceMember) { | 735 if (element.isInstanceMember) { |
| 711 if (name == null) { | 736 if (name == null) { |
| 712 compiler.internalError(element, 'No name for ${element.runtimeType}'); | 737 compiler.internalError(element, 'No name for ${element.runtimeType}'); |
| 713 } | 738 } |
| 714 updates.add( | 739 updates.add( |
| 715 js.statement('delete #.prototype.#', [elementAccess, name])); | 740 js.statement('delete #.prototype.#', [elementAccess, name])); |
| 716 | 741 |
| 717 if (superName != null) { | 742 if (superName != null) { |
| 718 updates.add( | 743 updates.add( |
| 719 js.statement('delete #.prototype.#', [elementAccess, superName])); | 744 js.statement('delete #.prototype.#', [elementAccess, superName])); |
| 720 } | 745 } |
| 721 } else { | 746 } else { |
| 722 updates.add(js.statement('delete #', [elementAccess])); | 747 updates.add(js.statement('delete #', [elementAccess])); |
| 723 } | 748 } |
| 724 } | 749 } |
| 725 } | 750 } |
| 726 | 751 |
| 752 class RemovedClassUpdate extends RemovalUpdate with JsFeatures { | |
| 753 final PartialClassElement element; | |
| 754 | |
| 755 bool wasStateCaptured = false; | |
| 756 | |
| 757 final List<jsAst.Node> accessToStatics = <jsAst.Node>[]; | |
| 758 | |
| 759 RemovedClassUpdate(Compiler compiler, this.element) | |
| 760 : super(compiler); | |
| 761 | |
| 762 PartialClassElement get before => element; | |
| 763 | |
| 764 PartialClassElement get after => null; | |
| 765 | |
| 766 bool get isRemoval => true; | |
|
Johnni Winther
2014/11/19 12:43:53
Not needed. Is already declared in RemovalUpdate.
ahe
2014/11/21 10:47:45
Done.
| |
| 767 | |
| 768 void captureState() { | |
| 769 if (wasStateCaptured) throw "captureState was called twice."; | |
| 770 wasStateCaptured = true; | |
| 771 | |
| 772 accessToStatics.add(namer.elementAccess(element)); | |
| 773 | |
| 774 element.forEachLocalMember((ElementX member) { | |
| 775 if (!member.isInstanceMember) { | |
| 776 accessToStatics.add(namer.elementAccess(member)); | |
| 777 } | |
| 778 }); | |
| 779 } | |
| 780 | |
| 781 PartialClassElement apply() { | |
| 782 if (!wasStateCaptured) { | |
| 783 throw new StateError("captureState must be called before apply."); | |
| 784 } | |
| 785 | |
| 786 removeFromEnclosing(); | |
| 787 | |
| 788 element.forEachLocalMember((ElementX member) { | |
| 789 compiler.forgetElement(before); | |
| 790 member.reuseElement(); | |
| 791 }); | |
| 792 | |
| 793 compiler.forgetElement(element); | |
| 794 element.reuseElement(); | |
| 795 | |
| 796 return null; | |
| 797 } | |
| 798 | |
| 799 void writeUpdateJsOn(List<jsAst.Statement> updates) { | |
| 800 if (accessToStatics.isEmpty) { | |
| 801 throw | |
| 802 new StateError("captureState must be called before writeUpdateJsOn."); | |
| 803 } | |
| 804 | |
| 805 for (jsAst.Node access in accessToStatics) { | |
| 806 updates.add(js.statement('delete #', [access])); | |
| 807 } | |
| 808 } | |
| 809 } | |
| 810 | |
| 727 class AddedFunctionUpdate extends Update with JsFeatures { | 811 class AddedFunctionUpdate extends Update with JsFeatures { |
| 728 final PartialFunctionElement element; | 812 final PartialFunctionElement element; |
| 729 | 813 |
| 730 final ScopeContainerElement container; | 814 final ScopeContainerElement container; |
| 731 | 815 |
| 732 AddedFunctionUpdate(Compiler compiler, this.element, this.container) | 816 AddedFunctionUpdate(Compiler compiler, this.element, this.container) |
| 733 : super(compiler) { | 817 : super(compiler) { |
| 734 if (container == null) { | 818 if (container == null) { |
| 735 throw "container is null"; | 819 throw "container is null"; |
| 736 } | 820 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 866 | 950 |
| 867 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; | 951 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; |
| 868 | 952 |
| 869 List<String> computeFields(ClassElement cls) { | 953 List<String> computeFields(ClassElement cls) { |
| 870 // TODO(ahe): Rewrite for new emitter. | 954 // TODO(ahe): Rewrite for new emitter. |
| 871 ClassBuilder builder = new ClassBuilder(cls, namer); | 955 ClassBuilder builder = new ClassBuilder(cls, namer); |
| 872 classEmitter.emitFields(cls, builder, ""); | 956 classEmitter.emitFields(cls, builder, ""); |
| 873 return builder.fields; | 957 return builder.fields; |
| 874 } | 958 } |
| 875 } | 959 } |
| OLD | NEW |