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.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 import 'dart:io'; | 7 import 'dart:io'; |
| 8 import 'dart:convert' show JSON; | 8 import 'dart:convert' show JSON; |
| 9 | 9 |
| 10 import '../../closure.dart' show ClosureTask, ClosureFieldElement; | 10 import '../../closure.dart' show ClosureTask, ClosureFieldElement; |
| 11 import '../../common.dart'; | 11 import '../../common.dart'; |
| 12 import '../../common/names.dart' show Names, Selectors; | 12 import '../../common/names.dart' show Names, Selectors; |
| 13 import '../../constants/values.dart' | 13 import '../../constants/values.dart' |
| 14 show ConstantValue, InterceptorConstantValue; | 14 show ConstantValue, InterceptorConstantValue; |
| 15 import '../../common_elements.dart' show CommonElements, ElementEnvironment; | 15 import '../../common_elements.dart' show CommonElements, ElementEnvironment; |
| 16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
| 17 import '../../elements/elements.dart' | 17 import '../../elements/elements.dart' |
| 18 show | 18 show |
| 19 ClassElement, | 19 ClassElement, |
| 20 ConstructorBodyElement, | |
| 20 Element, | 21 Element, |
| 21 Elements, | 22 Elements, |
| 22 FieldElement, | 23 FieldElement, |
| 23 FunctionElement, | 24 FunctionElement, |
| 24 FunctionSignature, | 25 FunctionSignature, |
| 25 GetterElement, | 26 GetterElement, |
| 26 LibraryElement, | 27 LibraryElement, |
| 27 MemberElement, | 28 MemberElement, |
| 28 MethodElement, | 29 MethodElement, |
| 29 ParameterElement, | 30 ParameterElement, |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 if (superclass != null) { | 230 if (superclass != null) { |
| 230 c.setSuperclass(_classes[superclass]); | 231 c.setSuperclass(_classes[superclass]); |
| 231 assert( | 232 assert( |
| 232 c.superclass != null, | 233 c.superclass != null, |
| 233 failedAt( | 234 failedAt( |
| 234 cls, | 235 cls, |
| 235 "No Class for has been created for superclass " | 236 "No Class for has been created for superclass " |
| 236 "${superclass} of $c.")); | 237 "${superclass} of $c.")); |
| 237 } | 238 } |
| 238 if (c is MixinApplication) { | 239 if (c is MixinApplication) { |
| 239 c.setMixinClass(_classes[computeMixinClass(cls)]); | 240 c.setMixinClass(_classes[computeMixinClass(cls)]); |
|
Siggi Cherem (dart-lang)
2017/06/08 18:01:46
should we do here the same fix you did in the othe
Johnni Winther
2017/06/09 09:28:49
ElementEnvironment.forEachMixin returns all mixins
Siggi Cherem (dart-lang)
2017/06/14 18:13:24
are you saying that the code in program_builder/co
Johnni Winther
2017/06/15 07:44:11
It wasn't - just weird: computeMixinClass didn't m
| |
| 240 assert(c.mixinClass != null); | 241 assert(c.mixinClass != null); |
| 241 } | 242 } |
| 242 }); | 243 }); |
| 243 | 244 |
| 244 List<Class> nativeClasses = collector.nativeClassesAndSubclasses | 245 List<Class> nativeClasses = collector.nativeClassesAndSubclasses |
| 245 .map((ClassEntity classElement) => _classes[classElement]) | 246 .map((ClassEntity classElement) => _classes[classElement]) |
| 246 .toList(); | 247 .toList(); |
| 247 | 248 |
| 248 Set<ClassEntity> interceptorClassesNeededByConstants = | 249 Set<ClassEntity> interceptorClassesNeededByConstants = |
| 249 collector.computeInterceptorsReferencedFromConstants(); | 250 collector.computeInterceptorsReferencedFromConstants(); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 // Interceptor class with implementations that directly call the | 511 // Interceptor class with implementations that directly call the |
| 511 // corresponding JavaScript member. We do not attempt to bind this when | 512 // corresponding JavaScript member. We do not attempt to bind this when |
| 512 // tearing off JavaScript methods as we cannot distinguish between calling | 513 // tearing off JavaScript methods as we cannot distinguish between calling |
| 513 // a regular getter that returns a JavaScript function and tearing off | 514 // a regular getter that returns a JavaScript function and tearing off |
| 514 // a method in the case where there exist multiple JavaScript classes | 515 // a method in the case where there exist multiple JavaScript classes |
| 515 // that conflict on whether the member is a getter or a method. | 516 // that conflict on whether the member is a getter or a method. |
| 516 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; | 517 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; |
| 517 var stubNames = new Set<String>(); | 518 var stubNames = new Set<String>(); |
| 518 librariesMap | 519 librariesMap |
| 519 .forEach((LibraryEntity library, List<ClassEntity> classElements, _) { | 520 .forEach((LibraryEntity library, List<ClassEntity> classElements, _) { |
| 520 for (ClassElement e in classElements) { | 521 for (ClassEntity cls in classElements) { |
| 521 if (_nativeData.isJsInteropClass(e)) { | 522 if (_nativeData.isJsInteropClass(cls)) { |
| 523 // TODO(johnniwinther): Handle class entities. | |
| 524 ClassElement e = cls; | |
| 522 e.declaration.forEachMember((_, Element member) { | 525 e.declaration.forEachMember((_, Element member) { |
| 523 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); | 526 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); |
| 524 if (!member.isInstanceMember) return; | 527 if (!member.isInstanceMember) return; |
| 525 if (member.isGetter || member.isField || member.isFunction) { | 528 if (member.isGetter || member.isField || member.isFunction) { |
| 526 var selectors = | 529 var selectors = |
| 527 _worldBuilder.getterInvocationsByName(member.name); | 530 _worldBuilder.getterInvocationsByName(member.name); |
| 528 if (selectors != null && !selectors.isEmpty) { | 531 if (selectors != null && !selectors.isEmpty) { |
| 529 for (var selector in selectors.keys) { | 532 for (var selector in selectors.keys) { |
| 530 var stubName = _namer.invocationName(selector); | 533 var stubName = _namer.invocationName(selector); |
| 531 if (stubNames.add(stubName.key)) { | 534 if (stubNames.add(stubName.key)) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 .toList(growable: false); | 659 .toList(growable: false); |
| 657 | 660 |
| 658 bool visitStatics = true; | 661 bool visitStatics = true; |
| 659 List<Field> staticFieldsForReflection = | 662 List<Field> staticFieldsForReflection = |
| 660 _buildFields(library: library, visitStatics: visitStatics); | 663 _buildFields(library: library, visitStatics: visitStatics); |
| 661 | 664 |
| 662 return new Library( | 665 return new Library( |
| 663 library, uri, statics, classes, staticFieldsForReflection); | 666 library, uri, statics, classes, staticFieldsForReflection); |
| 664 } | 667 } |
| 665 | 668 |
| 666 bool _isSoftDeferred(ClassElement element) { | 669 bool _isSoftDeferred(ClassEntity element) { |
| 667 return _notSoftDeferred != null && !_notSoftDeferred.contains(element); | 670 return _notSoftDeferred != null && !_notSoftDeferred.contains(element); |
| 668 } | 671 } |
| 669 | 672 |
| 670 Class _buildClass(ClassElement element) { | 673 Class _buildClass(ClassEntity cls) { |
| 671 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element); | 674 bool onlyForRti = collector.classesOnlyNeededForRti.contains(cls); |
| 672 bool hasRtiField = _rtiNeed.classNeedsRtiField(element); | 675 bool hasRtiField = _rtiNeed.classNeedsRtiField(cls); |
| 673 if (_nativeData.isJsInteropClass(element)) { | 676 if (_nativeData.isJsInteropClass(cls)) { |
| 674 // TODO(jacobr): check whether the class has any active static fields | 677 // TODO(jacobr): check whether the class has any active static fields |
| 675 // if it does not we can suppress it completely. | 678 // if it does not we can suppress it completely. |
| 676 onlyForRti = true; | 679 onlyForRti = true; |
| 677 } | 680 } |
| 678 bool isClosureBaseClass = element == _commonElements.closureClass; | 681 bool isClosureBaseClass = cls == _commonElements.closureClass; |
| 679 | 682 |
| 680 List<Method> methods = []; | 683 List<Method> methods = []; |
| 681 List<StubMethod> callStubs = <StubMethod>[]; | 684 List<StubMethod> callStubs = <StubMethod>[]; |
| 682 | 685 |
| 683 ClassStubGenerator classStubGenerator = new ClassStubGenerator( | 686 ClassStubGenerator classStubGenerator = new ClassStubGenerator( |
| 684 _task.emitter, _commonElements, _namer, _worldBuilder, _closedWorld, | 687 _task.emitter, _commonElements, _namer, _worldBuilder, _closedWorld, |
| 685 enableMinification: _options.enableMinification); | 688 enableMinification: _options.enableMinification); |
| 686 RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator( | 689 RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator( |
| 687 _commonElements, | 690 _commonElements, |
| 688 _closureToClassMapper, | 691 _closureToClassMapper, |
| 689 _task, | 692 _task, |
| 690 _namer, | 693 _namer, |
| 691 _nativeData, | 694 _nativeData, |
| 692 _rtiChecks, | 695 _rtiChecks, |
| 693 _rtiEncoder, | 696 _rtiEncoder, |
| 694 _rtiNeed, | 697 _rtiNeed, |
| 695 _rtiSubstitutions, | 698 _rtiSubstitutions, |
| 696 _jsInteropAnalysis); | 699 _jsInteropAnalysis); |
| 697 | 700 |
| 698 void visitMember(ClassElement enclosing, MemberElement member) { | 701 void visitMember(ClassEntity declarer, MemberEntity member) { |
| 699 assert(member.isDeclaration, failedAt(element)); | 702 if (cls != declarer) return; |
| 700 assert(element == enclosing, failedAt(element)); | |
| 701 | 703 |
| 702 if (Elements.isNonAbstractInstanceMember(member)) { | 704 if (member.isInstanceMember && !member.isAbstract && !member.isField) { |
| 703 // TODO(herhut): Remove once _buildMethod can no longer return null. | 705 // TODO(herhut): Remove once _buildMethod can no longer return null. |
| 704 Method method = _buildMethod(member); | 706 Method method = _buildMethod(member); |
| 705 if (method != null) methods.add(method); | 707 if (method != null) methods.add(method); |
| 706 } | 708 } |
| 707 if (member.isGetter || member.isField) { | 709 if (member.isGetter || member.isField) { |
| 708 Map<Selector, SelectorConstraints> selectors = | 710 Map<Selector, SelectorConstraints> selectors = |
| 709 _worldBuilder.invocationsByName(member.name); | 711 _worldBuilder.invocationsByName(member.name); |
| 710 if (selectors != null && !selectors.isEmpty) { | 712 if (selectors != null && !selectors.isEmpty) { |
| 711 Map<js.Name, js.Expression> callStubsForMember = | 713 Map<js.Name, js.Expression> callStubsForMember = |
| 712 classStubGenerator.generateCallStubsForGetter(member, selectors); | 714 classStubGenerator.generateCallStubsForGetter(member, selectors); |
| 713 callStubsForMember.forEach((js.Name name, js.Expression code) { | 715 callStubsForMember.forEach((js.Name name, js.Expression code) { |
| 714 callStubs.add(_buildStubMethod(name, code, element: member)); | 716 callStubs.add(_buildStubMethod(name, code, element: member)); |
| 715 }); | 717 }); |
| 716 } | 718 } |
| 717 } | 719 } |
| 718 } | 720 } |
| 719 | 721 |
| 720 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; | 722 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; |
| 721 | 723 |
| 722 if (_backendUsage.isNoSuchMethodUsed && element.isObject) { | 724 if (_backendUsage.isNoSuchMethodUsed && |
| 725 cls == _commonElements.objectClass) { | |
| 723 Map<js.Name, Selector> selectors = | 726 Map<js.Name, Selector> selectors = |
| 724 classStubGenerator.computeSelectorsForNsmHandlers(); | 727 classStubGenerator.computeSelectorsForNsmHandlers(); |
| 725 selectors.forEach((js.Name name, Selector selector) { | 728 selectors.forEach((js.Name name, Selector selector) { |
| 726 // If the program contains `const Symbol` names we have to retain them. | 729 // If the program contains `const Symbol` names we have to retain them. |
| 727 String selectorName = selector.name; | 730 String selectorName = selector.name; |
| 728 if (selector.isSetter) selectorName = "$selectorName="; | 731 if (selector.isSetter) selectorName = "$selectorName="; |
| 729 if (_mirrorsData.symbolsUsed.contains(selectorName)) { | 732 if (_mirrorsData.symbolsUsed.contains(selectorName)) { |
| 730 _symbolsMap[name] = selectorName; | 733 _symbolsMap[name] = selectorName; |
| 731 } | 734 } |
| 732 noSuchMethodStubs.add( | 735 noSuchMethodStubs.add( |
| 733 classStubGenerator.generateStubForNoSuchMethod(name, selector)); | 736 classStubGenerator.generateStubForNoSuchMethod(name, selector)); |
| 734 }); | 737 }); |
| 735 } | 738 } |
| 736 | 739 |
| 737 if (isClosureBaseClass) { | 740 if (isClosureBaseClass) { |
| 738 // We add a special getter to allow for tearing off a closure from itself. | 741 // We add a special getter to allow for tearing off a closure from itself. |
| 739 js.Name name = _namer.getterForMember(Names.call); | 742 js.Name name = _namer.getterForMember(Names.call); |
| 740 js.Fun function = js.js('function() { return this; }'); | 743 js.Fun function = js.js('function() { return this; }'); |
| 741 callStubs.add(_buildStubMethod(name, function)); | 744 callStubs.add(_buildStubMethod(name, function)); |
| 742 } | 745 } |
| 743 | 746 |
| 744 ClassElement implementation = element.implementation; | |
| 745 | |
| 746 // MixinApplications run through the members of their mixin. Here, we are | 747 // MixinApplications run through the members of their mixin. Here, we are |
| 747 // only interested in direct members. | 748 // only interested in direct members. |
| 748 if (!onlyForRti && !element.isMixinApplication) { | 749 if (!onlyForRti && !_elementEnvironment.isUnnamedMixinApplication(cls)) { |
| 749 implementation.forEachMember(visitMember, includeBackendMembers: true); | 750 _elementEnvironment.forEachClassMember(cls, visitMember); |
| 751 if (cls is ClassElement) { | |
| 752 // TODO(johnniwinther): Support constructor bodies for entities. | |
| 753 cls.forEachBackendMember((ConstructorBodyElement constructorBody) => | |
| 754 visitMember(cls, constructorBody)); | |
| 755 } | |
| 750 } | 756 } |
| 751 bool isInterceptedClass = _interceptorData.isInterceptedClass(element); | 757 bool isInterceptedClass = _interceptorData.isInterceptedClass(cls); |
| 752 List<Field> instanceFields = onlyForRti | 758 List<Field> instanceFields = onlyForRti |
| 753 ? const <Field>[] | 759 ? const <Field>[] |
| 754 : _buildFields( | 760 : _buildFields( |
| 755 cls: element, | 761 cls: cls, |
| 756 visitStatics: false, | 762 visitStatics: false, |
| 757 isHolderInterceptedClass: isInterceptedClass); | 763 isHolderInterceptedClass: isInterceptedClass); |
| 758 List<Field> staticFieldsForReflection = onlyForRti | 764 List<Field> staticFieldsForReflection = onlyForRti |
| 759 ? const <Field>[] | 765 ? const <Field>[] |
| 760 : _buildFields( | 766 : _buildFields( |
| 761 cls: element, | 767 cls: cls, |
| 762 visitStatics: true, | 768 visitStatics: true, |
| 763 isHolderInterceptedClass: isInterceptedClass); | 769 isHolderInterceptedClass: isInterceptedClass); |
| 764 | 770 |
| 765 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, | 771 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(cls, |
| 766 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 772 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
| 767 | 773 |
| 768 List<StubMethod> checkedSetters = <StubMethod>[]; | 774 List<StubMethod> checkedSetters = <StubMethod>[]; |
| 769 List<StubMethod> isChecks = <StubMethod>[]; | 775 List<StubMethod> isChecks = <StubMethod>[]; |
| 770 if (_nativeData.isJsInteropClass(element)) { | 776 if (_nativeData.isJsInteropClass(cls)) { |
| 771 typeTests.properties.forEach((js.Name name, js.Node code) { | 777 typeTests.properties.forEach((js.Name name, js.Node code) { |
| 772 _classes[_commonElements.jsInterceptorClass] | 778 _classes[_commonElements.jsInterceptorClass] |
| 773 .isChecks | 779 .isChecks |
| 774 .add(_buildStubMethod(name, code)); | 780 .add(_buildStubMethod(name, code)); |
| 775 }); | 781 }); |
| 776 } else { | 782 } else { |
| 777 for (Field field in instanceFields) { | 783 for (Field field in instanceFields) { |
| 778 if (field.needsCheckedSetter) { | 784 if (field.needsCheckedSetter) { |
| 779 assert(!field.needsUncheckedSetter); | 785 assert(!field.needsUncheckedSetter); |
| 780 FieldElement element = field.element; | 786 FieldElement element = field.element; |
| 781 js.Expression code = _generatedCode[element]; | 787 js.Expression code = _generatedCode[element]; |
| 782 assert(code != null); | 788 assert(code != null); |
| 783 js.Name name = _namer.deriveSetterName(field.accessorName); | 789 js.Name name = _namer.deriveSetterName(field.accessorName); |
| 784 checkedSetters.add(_buildStubMethod(name, code, element: element)); | 790 checkedSetters.add(_buildStubMethod(name, code, element: element)); |
| 785 } | 791 } |
| 786 } | 792 } |
| 787 | 793 |
| 788 typeTests.properties.forEach((js.Name name, js.Node code) { | 794 typeTests.properties.forEach((js.Name name, js.Node code) { |
| 789 isChecks.add(_buildStubMethod(name, code)); | 795 isChecks.add(_buildStubMethod(name, code)); |
| 790 }); | 796 }); |
| 791 } | 797 } |
| 792 | 798 |
| 793 js.Name name = _namer.className(element); | 799 js.Name name = _namer.className(cls); |
| 794 String holderName = _namer.globalObjectForClass(element); | 800 String holderName = _namer.globalObjectForClass(cls); |
| 795 // TODO(floitsch): we shouldn't update the registry in the middle of | 801 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 796 // building a class. | 802 // building a class. |
| 797 Holder holder = _registry.registerHolder(holderName); | 803 Holder holder = _registry.registerHolder(holderName); |
| 798 bool isInstantiated = !_nativeData.isJsInteropClass(element) && | 804 bool isInstantiated = !_nativeData.isJsInteropClass(cls) && |
| 799 _worldBuilder.directlyInstantiatedClasses.contains(element); | 805 _worldBuilder.directlyInstantiatedClasses.contains(cls); |
| 800 | 806 |
| 801 Class result; | 807 Class result; |
| 802 if (element.isMixinApplication && !onlyForRti) { | 808 if (_elementEnvironment.isUnnamedMixinApplication(cls) && !onlyForRti) { |
| 803 assert(!_nativeData.isNativeClass(element)); | 809 assert(!_nativeData.isNativeClass(cls)); |
| 804 assert(methods.isEmpty); | 810 assert(methods.isEmpty); |
| 805 assert(!isClosureBaseClass); | 811 assert(!isClosureBaseClass); |
| 806 | 812 |
| 807 result = new MixinApplication( | 813 result = new MixinApplication( |
| 808 element, | 814 cls, |
| 809 name, | 815 name, |
| 810 holder, | 816 holder, |
| 811 instanceFields, | 817 instanceFields, |
| 812 staticFieldsForReflection, | 818 staticFieldsForReflection, |
| 813 callStubs, | 819 callStubs, |
| 814 checkedSetters, | 820 checkedSetters, |
| 815 isChecks, | 821 isChecks, |
| 816 typeTests.functionTypeIndex, | 822 typeTests.functionTypeIndex, |
| 817 isDirectlyInstantiated: isInstantiated, | 823 isDirectlyInstantiated: isInstantiated, |
| 818 hasRtiField: hasRtiField, | 824 hasRtiField: hasRtiField, |
| 819 onlyForRti: onlyForRti); | 825 onlyForRti: onlyForRti); |
| 820 } else { | 826 } else { |
| 821 result = new Class( | 827 result = new Class( |
| 822 element, | 828 cls, |
| 823 name, | 829 name, |
| 824 holder, | 830 holder, |
| 825 methods, | 831 methods, |
| 826 instanceFields, | 832 instanceFields, |
| 827 staticFieldsForReflection, | 833 staticFieldsForReflection, |
| 828 callStubs, | 834 callStubs, |
| 829 noSuchMethodStubs, | 835 noSuchMethodStubs, |
| 830 checkedSetters, | 836 checkedSetters, |
| 831 isChecks, | 837 isChecks, |
| 832 typeTests.functionTypeIndex, | 838 typeTests.functionTypeIndex, |
| 833 isDirectlyInstantiated: isInstantiated, | 839 isDirectlyInstantiated: isInstantiated, |
| 834 hasRtiField: hasRtiField, | 840 hasRtiField: hasRtiField, |
| 835 onlyForRti: onlyForRti, | 841 onlyForRti: onlyForRti, |
| 836 isNative: _nativeData.isNativeClass(element), | 842 isNative: _nativeData.isNativeClass(cls), |
| 837 isClosureBaseClass: isClosureBaseClass, | 843 isClosureBaseClass: isClosureBaseClass, |
| 838 isSoftDeferred: _isSoftDeferred(element)); | 844 isSoftDeferred: _isSoftDeferred(cls)); |
| 839 } | 845 } |
| 840 _classes[element] = result; | 846 _classes[cls] = result; |
| 841 return result; | 847 return result; |
| 842 } | 848 } |
| 843 | 849 |
| 844 bool _methodNeedsStubs(FunctionEntity method) { | 850 bool _methodNeedsStubs(FunctionEntity method) { |
| 845 return method.parameterStructure.optionalParameters != 0; | 851 return method.parameterStructure.optionalParameters != 0; |
| 846 } | 852 } |
| 847 | 853 |
| 848 bool _methodCanBeReflected(FunctionEntity method) { | 854 bool _methodCanBeReflected(FunctionEntity method) { |
| 849 return _mirrorsData.isMemberAccessibleByReflection(method); | 855 return _mirrorsData.isMemberAccessibleByReflection(method); |
| 850 } | 856 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 867 optionalParameterDefaultValues = <ConstantValue>[]; | 873 optionalParameterDefaultValues = <ConstantValue>[]; |
| 868 signature.forEachOptionalParameter((ParameterElement parameter) { | 874 signature.forEachOptionalParameter((ParameterElement parameter) { |
| 869 ConstantValue def = | 875 ConstantValue def = |
| 870 _constantHandler.getConstantValue(parameter.constant); | 876 _constantHandler.getConstantValue(parameter.constant); |
| 871 optionalParameterDefaultValues.add(def); | 877 optionalParameterDefaultValues.add(def); |
| 872 }); | 878 }); |
| 873 } | 879 } |
| 874 return optionalParameterDefaultValues; | 880 return optionalParameterDefaultValues; |
| 875 } | 881 } |
| 876 | 882 |
| 877 DartMethod _buildMethod(MethodElement element) { | 883 DartMethod _buildMethod(FunctionEntity element) { |
| 878 assert(element.isDeclaration); | 884 assert(!(element is MethodElement && !element.isDeclaration)); |
| 879 js.Name name = _namer.methodPropertyName(element); | 885 js.Name name = _namer.methodPropertyName(element); |
| 880 js.Expression code = _generatedCode[element]; | 886 js.Expression code = _generatedCode[element]; |
| 881 | 887 |
| 882 // TODO(kasperl): Figure out under which conditions code is null. | 888 // TODO(kasperl): Figure out under which conditions code is null. |
| 883 if (code == null) return null; | 889 if (code == null) return null; |
| 884 | 890 |
| 885 bool canTearOff = false; | 891 bool canTearOff = false; |
| 886 js.Name tearOffName; | 892 js.Name tearOffName; |
| 887 bool isClosureCallMethod = false; | 893 bool isClosureCallMethod = false; |
| 888 bool isNotApplyTarget = !element.isFunction || element.isAccessor; | 894 bool isNotApplyTarget = |
| 895 !element.isFunction || element.isGetter || element.isSetter; | |
| 889 | 896 |
| 890 bool canBeReflected = _methodCanBeReflected(element); | 897 bool canBeReflected = _methodCanBeReflected(element); |
| 891 bool canBeApplied = _methodCanBeApplied(element); | 898 bool canBeApplied = _methodCanBeApplied(element); |
| 892 | 899 |
| 893 js.Name aliasName = _superMemberData.isAliasedSuperMember(element) | 900 js.Name aliasName = _superMemberData.isAliasedSuperMember(element) |
| 894 ? _namer.aliasedSuperMemberPropertyName(element) | 901 ? _namer.aliasedSuperMemberPropertyName(element) |
| 895 : null; | 902 : null; |
| 896 | 903 |
| 897 if (isNotApplyTarget) { | 904 if (isNotApplyTarget) { |
| 898 canTearOff = false; | 905 canTearOff = false; |
| 899 } else { | 906 } else { |
| 900 if (element.enclosingClass.isClosure) { | 907 if (element.enclosingClass.isClosure) { |
| 901 canTearOff = false; | 908 canTearOff = false; |
| 902 isClosureCallMethod = true; | 909 isClosureCallMethod = true; |
| 903 } else { | 910 } else { |
| 904 // Careful with operators. | 911 // Careful with operators. |
| 905 canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld) || | 912 canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld) || |
| 906 (canBeReflected && !element.isOperator); | 913 (canBeReflected && !Selector.isOperatorName(element.name)); |
| 907 assert(canTearOff || | 914 assert(canTearOff || |
| 908 !_worldBuilder.methodsNeedingSuperGetter.contains(element)); | 915 !_worldBuilder.methodsNeedingSuperGetter.contains(element)); |
| 909 tearOffName = _namer.getterForElement(element); | 916 tearOffName = _namer.getterForElement(element); |
| 910 } | 917 } |
| 911 } | 918 } |
| 912 | 919 |
| 913 if (canTearOff) { | 920 if (canTearOff) { |
| 914 assert(!element.isGenerativeConstructor, failedAt(element)); | 921 assert(element is! ConstructorEntity, failedAt(element)); |
| 915 assert(!element.isGenerativeConstructorBody, failedAt(element)); | 922 assert(element is! ConstructorBodyElement, failedAt(element)); |
| 916 assert(!element.isConstructor, failedAt(element)); | |
| 917 } | 923 } |
| 918 | 924 |
| 919 js.Name callName = null; | 925 js.Name callName = null; |
| 920 if (canTearOff) { | 926 if (canTearOff) { |
| 921 Selector callSelector = | 927 Selector callSelector = |
| 922 new Selector.fromElement(element).toCallSelector(); | 928 new Selector.fromElement(element).toCallSelector(); |
| 923 callName = _namer.invocationName(callSelector); | 929 callName = _namer.invocationName(callSelector); |
| 924 } | 930 } |
| 925 | 931 |
| 926 ResolutionDartType memberType; | 932 DartType memberType = _elementEnvironment.getFunctionType(element); |
| 927 if (element.isGenerativeConstructorBody) { | |
| 928 // TODO(herhut): Why does this need to be normalized away? We never need | |
| 929 // this information anyway as they cannot be torn off or | |
| 930 // reflected. | |
| 931 var body = element; | |
| 932 memberType = body.constructor.type; | |
| 933 } else { | |
| 934 memberType = element.type; | |
| 935 } | |
| 936 | |
| 937 js.Expression functionType; | 933 js.Expression functionType; |
| 938 if (canTearOff || canBeReflected) { | 934 if (canTearOff || canBeReflected) { |
| 939 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element); | 935 OutputUnit outputUnit = _deferredLoadTask.outputUnitForMember(element); |
| 940 functionType = _generateFunctionType(memberType, outputUnit); | 936 functionType = _generateFunctionType(memberType, outputUnit); |
| 941 } | 937 } |
| 942 | 938 |
| 943 int requiredParameterCount; | 939 int requiredParameterCount; |
| 944 var /* List | Map */ optionalParameterDefaultValues; | 940 var /* List | Map */ optionalParameterDefaultValues; |
| 945 if (canBeApplied || canBeReflected) { | 941 if (canBeApplied || canBeReflected) { |
| 946 FunctionSignature signature = element.functionSignature; | 942 // TODO(johnniwinther): Handle function entities. |
| 943 MethodElement method = element; | |
| 944 FunctionSignature signature = method.functionSignature; | |
| 947 requiredParameterCount = signature.requiredParameterCount; | 945 requiredParameterCount = signature.requiredParameterCount; |
| 948 optionalParameterDefaultValues = | 946 optionalParameterDefaultValues = |
| 949 _computeParameterDefaultValues(signature); | 947 _computeParameterDefaultValues(signature); |
| 950 } | 948 } |
| 951 | 949 |
| 952 return new InstanceMethod(element, name, code, | 950 return new InstanceMethod(element, name, code, |
| 953 _generateParameterStubs(element, canTearOff), callName, | 951 _generateParameterStubs(element, canTearOff), callName, |
| 954 needsTearOff: canTearOff, | 952 needsTearOff: canTearOff, |
| 955 tearOffName: tearOffName, | 953 tearOffName: tearOffName, |
| 956 isClosureCallMethod: isClosureCallMethod, | 954 isClosureCallMethod: isClosureCallMethod, |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1185 Constant constant = new Constant(name, holder, constantValue); | 1183 Constant constant = new Constant(name, holder, constantValue); |
| 1186 _constants[constantValue] = constant; | 1184 _constants[constantValue] = constant; |
| 1187 } | 1185 } |
| 1188 } | 1186 } |
| 1189 | 1187 |
| 1190 Holder _registerStaticStateHolder() { | 1188 Holder _registerStaticStateHolder() { |
| 1191 return _registry.registerHolder(_namer.staticStateHolder, | 1189 return _registry.registerHolder(_namer.staticStateHolder, |
| 1192 isStaticStateHolder: true); | 1190 isStaticStateHolder: true); |
| 1193 } | 1191 } |
| 1194 } | 1192 } |
| OLD | NEW |