| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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.kernel.world_builder; | 5 library dart2js.kernel.world_builder; |
| 6 | 6 |
| 7 import 'package:kernel/ast.dart' as ir; | 7 import 'package:kernel/ast.dart' as ir; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../common/resolution.dart'; | 10 import '../common/resolution.dart'; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 | 57 |
| 58 /// List of class environments by `KClass.classIndex`. This is used for | 58 /// List of class environments by `KClass.classIndex`. This is used for |
| 59 /// fast lookup into class members. | 59 /// fast lookup into class members. |
| 60 List<KClassEnv> _classEnvs = <KClassEnv>[]; | 60 List<KClassEnv> _classEnvs = <KClassEnv>[]; |
| 61 | 61 |
| 62 Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; | 62 Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; |
| 63 Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; | 63 Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; |
| 64 Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = | 64 Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = |
| 65 <ir.TypeParameter, KTypeVariable>{}; | 65 <ir.TypeParameter, KTypeVariable>{}; |
| 66 | 66 |
| 67 // TODO(johnniwinther): Change this to a list of 'KMemberData' class if we | 67 List<_MemberData> _memberList = <_MemberData>[]; |
| 68 // need more data for members. | |
| 69 List<ir.Member> _memberList = <ir.Member>[]; | |
| 70 | 68 |
| 71 Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; | 69 Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; |
| 72 Map<KConstructor, ConstantConstructor> _constructorConstantMap = | |
| 73 <KConstructor, ConstantConstructor>{}; | |
| 74 | |
| 75 Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; | 70 Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; |
| 76 | |
| 77 Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; | 71 Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; |
| 78 Map<KField, ConstantExpression> _fieldConstantMap = | |
| 79 <KField, ConstantExpression>{}; | |
| 80 | 72 |
| 81 Map<ir.TreeNode, KLocalFunction> _localFunctionMap = | 73 Map<ir.TreeNode, KLocalFunction> _localFunctionMap = |
| 82 <ir.TreeNode, KLocalFunction>{}; | 74 <ir.TreeNode, KLocalFunction>{}; |
| 83 | 75 |
| 84 KernelWorldBuilder(this.reporter) { | 76 KernelWorldBuilder(this.reporter) { |
| 85 _elementEnvironment = new KernelElementEnvironment(this); | 77 _elementEnvironment = new KernelElementEnvironment(this); |
| 86 _commonElements = new CommonElements(_elementEnvironment); | 78 _commonElements = new CommonElements(_elementEnvironment); |
| 87 _constantEnvironment = new KernelConstantEnvironment(this); | 79 _constantEnvironment = new KernelConstantEnvironment(this); |
| 88 _nativeBehaviorBuilder = | 80 _nativeBehaviorBuilder = |
| 89 new KernelBehaviorBuilder(_commonElements, _constantEnvironment); | 81 new KernelBehaviorBuilder(_commonElements, _constantEnvironment); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 } | 235 } |
| 244 | 236 |
| 245 KConstructor _getConstructor(ir.Member node) { | 237 KConstructor _getConstructor(ir.Member node) { |
| 246 return _constructorMap.putIfAbsent(node, () { | 238 return _constructorMap.putIfAbsent(node, () { |
| 247 int memberIndex = _memberList.length; | 239 int memberIndex = _memberList.length; |
| 248 KConstructor constructor; | 240 KConstructor constructor; |
| 249 KClass enclosingClass = _getClass(node.enclosingClass); | 241 KClass enclosingClass = _getClass(node.enclosingClass); |
| 250 Name name = getName(node.name); | 242 Name name = getName(node.name); |
| 251 bool isExternal = node.isExternal; | 243 bool isExternal = node.isExternal; |
| 252 | 244 |
| 245 ir.FunctionNode functionNode; |
| 253 if (node is ir.Constructor) { | 246 if (node is ir.Constructor) { |
| 247 functionNode = node.function; |
| 254 constructor = new KGenerativeConstructor(memberIndex, enclosingClass, | 248 constructor = new KGenerativeConstructor(memberIndex, enclosingClass, |
| 255 name, _getParameterStructure(node.function), | 249 name, _getParameterStructure(functionNode), |
| 256 isExternal: isExternal, isConst: node.isConst); | 250 isExternal: isExternal, isConst: node.isConst); |
| 257 } else if (node is ir.Procedure) { | 251 } else if (node is ir.Procedure) { |
| 252 functionNode = node.function; |
| 258 constructor = new KFactoryConstructor(memberIndex, enclosingClass, name, | 253 constructor = new KFactoryConstructor(memberIndex, enclosingClass, name, |
| 259 _getParameterStructure(node.function), | 254 _getParameterStructure(functionNode), |
| 260 isExternal: isExternal, isConst: node.isConst); | 255 isExternal: isExternal, isConst: node.isConst); |
| 261 } else { | 256 } else { |
| 262 // TODO(johnniwinther): Convert `node.location` to a [SourceSpan]. | 257 // TODO(johnniwinther): Convert `node.location` to a [SourceSpan]. |
| 263 throw new SpannableAssertionFailure( | 258 throw new SpannableAssertionFailure( |
| 264 NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}."); | 259 NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}."); |
| 265 } | 260 } |
| 266 _memberList.add(node); | 261 _memberList.add(new _ConstructorData(node, functionNode)); |
| 267 return constructor; | 262 return constructor; |
| 268 }); | 263 }); |
| 269 } | 264 } |
| 270 | 265 |
| 271 KFunction _getMethod(ir.Procedure node) { | 266 KFunction _getMethod(ir.Procedure node) { |
| 272 return _methodMap.putIfAbsent(node, () { | 267 return _methodMap.putIfAbsent(node, () { |
| 273 int memberIndex = _memberList.length; | 268 int memberIndex = _memberList.length; |
| 274 KLibrary library; | 269 KLibrary library; |
| 275 KClass enclosingClass; | 270 KClass enclosingClass; |
| 276 if (node.enclosingClass != null) { | 271 if (node.enclosingClass != null) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 302 isAbstract: isAbstract); | 297 isAbstract: isAbstract); |
| 303 break; | 298 break; |
| 304 case ir.ProcedureKind.Setter: | 299 case ir.ProcedureKind.Setter: |
| 305 function = new KSetter( | 300 function = new KSetter( |
| 306 memberIndex, library, enclosingClass, getName(node.name).setter, | 301 memberIndex, library, enclosingClass, getName(node.name).setter, |
| 307 isStatic: isStatic, | 302 isStatic: isStatic, |
| 308 isExternal: isExternal, | 303 isExternal: isExternal, |
| 309 isAbstract: isAbstract); | 304 isAbstract: isAbstract); |
| 310 break; | 305 break; |
| 311 } | 306 } |
| 312 _memberList.add(node); | 307 _memberList.add(new _FunctionData(node, node.function)); |
| 313 return function; | 308 return function; |
| 314 }); | 309 }); |
| 315 } | 310 } |
| 316 | 311 |
| 317 KField _getField(ir.Field node) { | 312 KField _getField(ir.Field node) { |
| 318 return _fieldMap.putIfAbsent(node, () { | 313 return _fieldMap.putIfAbsent(node, () { |
| 319 int memberIndex = _memberList.length; | 314 int memberIndex = _memberList.length; |
| 320 KLibrary library; | 315 KLibrary library; |
| 321 KClass enclosingClass; | 316 KClass enclosingClass; |
| 322 if (node.enclosingClass != null) { | 317 if (node.enclosingClass != null) { |
| 323 enclosingClass = _getClass(node.enclosingClass); | 318 enclosingClass = _getClass(node.enclosingClass); |
| 324 library = enclosingClass.library; | 319 library = enclosingClass.library; |
| 325 } else { | 320 } else { |
| 326 library = _getLibrary(node.enclosingLibrary); | 321 library = _getLibrary(node.enclosingLibrary); |
| 327 } | 322 } |
| 328 Name name = getName(node.name); | 323 Name name = getName(node.name); |
| 329 bool isStatic = node.isStatic; | 324 bool isStatic = node.isStatic; |
| 330 _memberList.add(node); | 325 _memberList.add(new _FieldData(node)); |
| 331 return new KField(memberIndex, library, enclosingClass, name, | 326 return new KField(memberIndex, library, enclosingClass, name, |
| 332 isStatic: isStatic, | 327 isStatic: isStatic, |
| 333 isAssignable: node.isMutable, | 328 isAssignable: node.isMutable, |
| 334 isConst: node.isConst); | 329 isConst: node.isConst); |
| 335 }); | 330 }); |
| 336 } | 331 } |
| 337 | 332 |
| 338 KLocalFunction _getLocal(ir.TreeNode node) { | 333 KLocalFunction _getLocal(ir.TreeNode node) { |
| 339 return _localFunctionMap.putIfAbsent(node, () { | 334 return _localFunctionMap.putIfAbsent(node, () { |
| 340 MemberEntity memberContext; | 335 MemberEntity memberContext; |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 return _getMethod(node); | 557 return _getMethod(node); |
| 563 } | 558 } |
| 564 } | 559 } |
| 565 throw new UnsupportedError("Unexpected member: $node"); | 560 throw new UnsupportedError("Unexpected member: $node"); |
| 566 } | 561 } |
| 567 | 562 |
| 568 @override | 563 @override |
| 569 FunctionEntity getConstructor(ir.Member node) => _getConstructor(node); | 564 FunctionEntity getConstructor(ir.Member node) => _getConstructor(node); |
| 570 | 565 |
| 571 ConstantConstructor _getConstructorConstant(KConstructor constructor) { | 566 ConstantConstructor _getConstructorConstant(KConstructor constructor) { |
| 572 return _constructorConstantMap.putIfAbsent(constructor, () { | 567 _ConstructorData data = _memberList[constructor.memberIndex]; |
| 573 ir.Member node = _memberList[constructor.memberIndex]; | 568 return data.getConstructorConstant(this, constructor); |
| 574 if (node is ir.Constructor && node.isConst) { | |
| 575 return new Constantifier(this).computeConstantConstructor(node); | |
| 576 } | |
| 577 throw new SpannableAssertionFailure( | |
| 578 constructor, | |
| 579 "Unexpected constructor $constructor in " | |
| 580 "KernelWorldBuilder._getConstructorConstant"); | |
| 581 }); | |
| 582 } | 569 } |
| 583 | 570 |
| 584 ConstantExpression _getFieldConstant(KField field) { | 571 ConstantExpression _getFieldConstant(KField field) { |
| 585 return _fieldConstantMap.putIfAbsent(field, () { | 572 _FieldData data = _memberList[field.memberIndex]; |
| 586 ir.Field node = _memberList[field.memberIndex]; | 573 return data.getFieldConstant(this, field); |
| 587 if (node.isConst) { | 574 } |
| 588 return new Constantifier(this).visit(node.initializer); | 575 |
| 589 } | 576 FunctionType _getFunctionType(KFunction function) { |
| 590 throw new SpannableAssertionFailure( | 577 _FunctionData data = _memberList[function.memberIndex]; |
| 591 field, | 578 return data.getFunctionType(this); |
| 592 "Unexpected field $field in " | |
| 593 "KernelWorldBuilder._getConstructorConstant"); | |
| 594 }); | |
| 595 } | 579 } |
| 596 | 580 |
| 597 ResolutionImpact computeWorldImpact(KMember member) { | 581 ResolutionImpact computeWorldImpact(KMember member) { |
| 598 ir.Member node = _memberList[member.memberIndex]; | 582 return _memberList[member.memberIndex].getWorldImpact(this); |
| 599 return buildKernelImpact(node, this); | |
| 600 } | 583 } |
| 601 } | 584 } |
| 602 | 585 |
| 603 /// Environment for fast lookup of program libraries. | 586 /// Environment for fast lookup of program libraries. |
| 604 class KEnv { | 587 class KEnv { |
| 605 final Set<ir.Program> programs = new Set<ir.Program>(); | 588 final Set<ir.Program> programs = new Set<ir.Program>(); |
| 606 | 589 |
| 607 Map<Uri, KLibraryEnv> _libraryMap; | 590 Map<Uri, KLibraryEnv> _libraryMap; |
| 608 | 591 |
| 609 /// TODO(johnniwinther): Handle arbitrary load order if needed. | 592 /// TODO(johnniwinther): Handle arbitrary load order if needed. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 } | 758 } |
| 776 | 759 |
| 777 Iterable<ConstantExpression> getMetadata(KernelWorldBuilder worldBuilder) { | 760 Iterable<ConstantExpression> getMetadata(KernelWorldBuilder worldBuilder) { |
| 778 if (_metadata == null) { | 761 if (_metadata == null) { |
| 779 _metadata = worldBuilder.getMetadata(cls.annotations); | 762 _metadata = worldBuilder.getMetadata(cls.annotations); |
| 780 } | 763 } |
| 781 return _metadata; | 764 return _metadata; |
| 782 } | 765 } |
| 783 } | 766 } |
| 784 | 767 |
| 768 class _MemberData { |
| 769 final ir.Member node; |
| 770 |
| 771 _MemberData(this.node); |
| 772 |
| 773 ResolutionImpact getWorldImpact(KernelWorldBuilder worldBuilder) { |
| 774 return buildKernelImpact(node, worldBuilder); |
| 775 } |
| 776 } |
| 777 |
| 778 class _FunctionData extends _MemberData { |
| 779 final ir.FunctionNode functionNode; |
| 780 FunctionType _type; |
| 781 CallStructure _callStructure; |
| 782 |
| 783 _FunctionData(ir.Member node, this.functionNode) : super(node); |
| 784 |
| 785 FunctionType getFunctionType(KernelWorldBuilder worldBuilder) { |
| 786 return _type ??= worldBuilder.getFunctionType(functionNode); |
| 787 } |
| 788 |
| 789 CallStructure get callStructure { |
| 790 return _callStructure ??= new CallStructure( |
| 791 functionNode.positionalParameters.length + |
| 792 functionNode.namedParameters.length, |
| 793 functionNode.namedParameters.map((d) => d.name).toList()); |
| 794 } |
| 795 } |
| 796 |
| 797 class _ConstructorData extends _FunctionData { |
| 798 ConstantConstructor _constantConstructor; |
| 799 |
| 800 _ConstructorData(ir.Member node, ir.FunctionNode functionNode) |
| 801 : super(node, functionNode); |
| 802 |
| 803 ConstantConstructor getConstructorConstant( |
| 804 KernelWorldBuilder worldBuilder, KConstructor constructor) { |
| 805 if (_constantConstructor == null) { |
| 806 if (node is ir.Constructor && constructor.isConst) { |
| 807 _constantConstructor = |
| 808 new Constantifier(worldBuilder).computeConstantConstructor(node); |
| 809 } else { |
| 810 throw new SpannableAssertionFailure( |
| 811 constructor, |
| 812 "Unexpected constructor $constructor in " |
| 813 "KernelWorldBuilder._getConstructorConstant"); |
| 814 } |
| 815 } |
| 816 return _constantConstructor; |
| 817 } |
| 818 } |
| 819 |
| 820 class _FieldData extends _MemberData { |
| 821 ConstantExpression _constant; |
| 822 |
| 823 _FieldData(ir.Field node) : super(node); |
| 824 |
| 825 ir.Field get node => super.node; |
| 826 |
| 827 ConstantExpression getFieldConstant( |
| 828 KernelWorldBuilder worldBuilder, KField field) { |
| 829 if (_constant == null) { |
| 830 if (node.isConst) { |
| 831 _constant = new Constantifier(worldBuilder).visit(node.initializer); |
| 832 } else { |
| 833 throw new SpannableAssertionFailure( |
| 834 field, |
| 835 "Unexpected field $field in " |
| 836 "KernelWorldBuilder._getConstructorConstant"); |
| 837 } |
| 838 } |
| 839 return _constant; |
| 840 } |
| 841 } |
| 842 |
| 785 class KernelElementEnvironment implements ElementEnvironment { | 843 class KernelElementEnvironment implements ElementEnvironment { |
| 786 final KernelWorldBuilder worldBuilder; | 844 final KernelWorldBuilder worldBuilder; |
| 787 | 845 |
| 788 KernelElementEnvironment(this.worldBuilder); | 846 KernelElementEnvironment(this.worldBuilder); |
| 789 | 847 |
| 790 @override | 848 @override |
| 791 DartType get dynamicType => const DynamicType(); | 849 DartType get dynamicType => const DynamicType(); |
| 792 | 850 |
| 793 @override | 851 @override |
| 794 LibraryEntity get mainLibrary => worldBuilder._mainLibrary; | 852 LibraryEntity get mainLibrary => worldBuilder._mainLibrary; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 821 return new InterfaceType(cls, typeArguments); | 879 return new InterfaceType(cls, typeArguments); |
| 822 } | 880 } |
| 823 | 881 |
| 824 @override | 882 @override |
| 825 bool isSubtype(DartType a, DartType b) { | 883 bool isSubtype(DartType a, DartType b) { |
| 826 return worldBuilder.types.isSubtype(a, b); | 884 return worldBuilder.types.isSubtype(a, b); |
| 827 } | 885 } |
| 828 | 886 |
| 829 @override | 887 @override |
| 830 FunctionType getFunctionType(KFunction function) { | 888 FunctionType getFunctionType(KFunction function) { |
| 831 throw new UnimplementedError('KernelElementEnvironment.getFunctionType'); | 889 return worldBuilder._getFunctionType(function); |
| 832 } | 890 } |
| 833 | 891 |
| 834 @override | 892 @override |
| 835 FunctionType getLocalFunctionType(KLocalFunction function) { | 893 FunctionType getLocalFunctionType(KLocalFunction function) { |
| 836 return function.functionType; | 894 return function.functionType; |
| 837 } | 895 } |
| 838 | 896 |
| 839 @override | 897 @override |
| 840 DartType getUnaliasedType(DartType type) => type; | 898 DartType getUnaliasedType(DartType type) => type; |
| 841 | 899 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 LibraryEntity library = worldBuilder.lookupLibrary(uri); | 976 LibraryEntity library = worldBuilder.lookupLibrary(uri); |
| 919 if (library == null && required) { | 977 if (library == null && required) { |
| 920 throw new SpannableAssertionFailure( | 978 throw new SpannableAssertionFailure( |
| 921 CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found."); | 979 CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found."); |
| 922 } | 980 } |
| 923 return library; | 981 return library; |
| 924 } | 982 } |
| 925 | 983 |
| 926 @override | 984 @override |
| 927 CallStructure getCallStructure(KFunction function) { | 985 CallStructure getCallStructure(KFunction function) { |
| 928 ir.Member member = worldBuilder._memberList[function.memberIndex]; | 986 _FunctionData data = worldBuilder._memberList[function.memberIndex]; |
| 929 ir.FunctionNode functionNode; | 987 return data.callStructure; |
| 930 if (member is ir.Procedure) { | |
| 931 functionNode = member.function; | |
| 932 } else if (member is ir.Constructor) { | |
| 933 functionNode = member.function; | |
| 934 } else { | |
| 935 throw new SpannableAssertionFailure( | |
| 936 function, "Unexpected function node ${member} for $function."); | |
| 937 } | |
| 938 return new CallStructure( | |
| 939 functionNode.positionalParameters.length + | |
| 940 functionNode.namedParameters.length, | |
| 941 functionNode.namedParameters.map((d) => d.name).toList()); | |
| 942 } | 988 } |
| 943 | 989 |
| 944 @override | 990 @override |
| 945 bool isDeferredLoadLibraryGetter(KMember member) { | 991 bool isDeferredLoadLibraryGetter(KMember member) { |
| 946 // TODO(johnniwinther): Support these. | 992 // TODO(johnniwinther): Support these. |
| 947 return false; | 993 return false; |
| 948 } | 994 } |
| 949 } | 995 } |
| 950 | 996 |
| 951 /// Visitor that converts kernel dart types into [DartType]. | 997 /// Visitor that converts kernel dart types into [DartType]. |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 } | 1255 } |
| 1210 | 1256 |
| 1211 InterfaceType getMixinTypeForClass(KClass cls) { | 1257 InterfaceType getMixinTypeForClass(KClass cls) { |
| 1212 KClassEnv env = builder._classEnvs[cls.classIndex]; | 1258 KClassEnv env = builder._classEnvs[cls.classIndex]; |
| 1213 ir.Supertype mixedInType = env.cls.mixedInType; | 1259 ir.Supertype mixedInType = env.cls.mixedInType; |
| 1214 if (mixedInType == null) return null; | 1260 if (mixedInType == null) return null; |
| 1215 return builder.createInterfaceType( | 1261 return builder.createInterfaceType( |
| 1216 mixedInType.classNode, mixedInType.typeArguments); | 1262 mixedInType.classNode, mixedInType.typeArguments); |
| 1217 } | 1263 } |
| 1218 } | 1264 } |
| OLD | NEW |