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/backend_api.dart'; | 10 import '../common/backend_api.dart'; |
11 import '../compile_time_constants.dart'; | 11 import '../compile_time_constants.dart'; |
12 import '../constants/constant_system.dart'; | 12 import '../constants/constant_system.dart'; |
13 import '../constants/constructors.dart'; | 13 import '../constants/constructors.dart'; |
14 import '../constants/evaluation.dart'; | 14 import '../constants/evaluation.dart'; |
15 import '../constants/expressions.dart'; | 15 import '../constants/expressions.dart'; |
16 import '../constants/values.dart'; | 16 import '../constants/values.dart'; |
17 import '../common_elements.dart'; | 17 import '../common_elements.dart'; |
18 import '../elements/elements.dart'; | 18 import '../elements/elements.dart'; |
19 import '../elements/entities.dart'; | 19 import '../elements/entities.dart'; |
20 import '../elements/types.dart'; | 20 import '../elements/types.dart'; |
21 import '../js_backend/backend_helpers.dart'; | 21 import '../js_backend/backend_helpers.dart'; |
22 import '../js_backend/constant_system_javascript.dart'; | 22 import '../js_backend/constant_system_javascript.dart'; |
23 import '../js_backend/no_such_method_registry.dart'; | 23 import '../js_backend/no_such_method_registry.dart'; |
24 import '../native/native.dart' as native; | 24 import '../native/native.dart' as native; |
25 import '../native/resolver.dart'; | 25 import '../native/resolver.dart'; |
| 26 import '../universe/call_structure.dart'; |
26 import 'element_adapter.dart'; | 27 import 'element_adapter.dart'; |
27 import 'elements.dart'; | 28 import 'elements.dart'; |
28 | 29 |
29 part 'native_class_resolver.dart'; | 30 part 'native_class_resolver.dart'; |
30 part 'no_such_method_resolver.dart'; | 31 part 'no_such_method_resolver.dart'; |
31 | 32 |
32 /// World builder used for creating elements and types corresponding to Kernel | 33 /// World builder used for creating elements and types corresponding to Kernel |
33 /// IR nodes. | 34 /// IR nodes. |
34 // TODO(johnniwinther): Implement [ResolutionWorldBuilder]. | 35 // TODO(johnniwinther): Implement [ResolutionWorldBuilder]. |
35 class KernelWorldBuilder extends KernelElementAdapterMixin { | 36 class KernelWorldBuilder extends KernelElementAdapterMixin { |
(...skipping 12 matching lines...) Expand all Loading... |
48 | 49 |
49 /// List of class environments by `KClass.classIndex`. This is used for | 50 /// List of class environments by `KClass.classIndex`. This is used for |
50 /// fast lookup into class members. | 51 /// fast lookup into class members. |
51 List<KClassEnv> _classEnvs = <KClassEnv>[]; | 52 List<KClassEnv> _classEnvs = <KClassEnv>[]; |
52 | 53 |
53 Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; | 54 Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; |
54 Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; | 55 Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; |
55 Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = | 56 Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = |
56 <ir.TypeParameter, KTypeVariable>{}; | 57 <ir.TypeParameter, KTypeVariable>{}; |
57 | 58 |
| 59 // TODO(johnniwinther): Change this to a list of 'KMemberData' class if we |
| 60 // need more data for members. |
| 61 List<ir.Member> _memberList = <ir.Member>[]; |
| 62 |
58 Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; | 63 Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; |
59 // TODO(johnniwinther): Change this to a list of 'KConstructorData' class | |
60 // holding the [ConstantConstructor] if we need more data for constructors. | |
61 List<ir.Member> _constructorList = <ir.Member>[]; | |
62 Map<KConstructor, ConstantConstructor> _constructorConstantMap = | 64 Map<KConstructor, ConstantConstructor> _constructorConstantMap = |
63 <KConstructor, ConstantConstructor>{}; | 65 <KConstructor, ConstantConstructor>{}; |
64 | 66 |
65 Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; | 67 Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; |
66 | 68 |
67 Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; | 69 Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; |
68 // TODO(johnniwinther): Change this to a list of 'KFieldData' class | |
69 // holding the [ConstantExpression] if we need more data for fields. | |
70 List<ir.Field> _fieldList = <ir.Field>[]; | |
71 Map<KField, ConstantExpression> _fieldConstantMap = | 70 Map<KField, ConstantExpression> _fieldConstantMap = |
72 <KField, ConstantExpression>{}; | 71 <KField, ConstantExpression>{}; |
73 | 72 |
74 Map<ir.TreeNode, KLocalFunction> _localFunctionMap = | 73 Map<ir.TreeNode, KLocalFunction> _localFunctionMap = |
75 <ir.TreeNode, KLocalFunction>{}; | 74 <ir.TreeNode, KLocalFunction>{}; |
76 | 75 |
77 KernelWorldBuilder(this.reporter, ir.Program program) | 76 KernelWorldBuilder(this.reporter, ir.Program program) |
78 : _env = new KEnv(program) { | 77 : _env = new KEnv(program) { |
79 _elementEnvironment = new KernelElementEnvironment(this); | 78 _elementEnvironment = new KernelElementEnvironment(this); |
80 _commonElements = new CommonElementsImpl(_elementEnvironment); | 79 _commonElements = new CommonElementsImpl(_elementEnvironment); |
(...skipping 24 matching lines...) Expand all Loading... |
105 @override | 104 @override |
106 native.BehaviorBuilder get nativeBehaviorBuilder => _nativeBehaviorBuilder; | 105 native.BehaviorBuilder get nativeBehaviorBuilder => _nativeBehaviorBuilder; |
107 | 106 |
108 LibraryEntity lookupLibrary(Uri uri) { | 107 LibraryEntity lookupLibrary(Uri uri) { |
109 KLibraryEnv libraryEnv = _env.lookupLibrary(uri); | 108 KLibraryEnv libraryEnv = _env.lookupLibrary(uri); |
110 return _getLibrary(libraryEnv.library, libraryEnv); | 109 return _getLibrary(libraryEnv.library, libraryEnv); |
111 } | 110 } |
112 | 111 |
113 KLibrary _getLibrary(ir.Library node, [KLibraryEnv libraryEnv]) { | 112 KLibrary _getLibrary(ir.Library node, [KLibraryEnv libraryEnv]) { |
114 return _libraryMap.putIfAbsent(node, () { | 113 return _libraryMap.putIfAbsent(node, () { |
115 _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(node.importUri)); | 114 Uri canonicalUri = node.importUri; |
| 115 _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(canonicalUri)); |
116 String name = node.name; | 116 String name = node.name; |
117 if (name == null) { | 117 if (name == null) { |
118 // Use the file name as script name. | 118 // Use the file name as script name. |
119 String path = node.importUri.path; | 119 String path = canonicalUri.path; |
120 name = path.substring(path.lastIndexOf('/') + 1); | 120 name = path.substring(path.lastIndexOf('/') + 1); |
121 } | 121 } |
122 return new KLibrary(_libraryMap.length, name); | 122 return new KLibrary(_libraryMap.length, name, canonicalUri); |
123 }); | 123 }); |
124 } | 124 } |
125 | 125 |
126 MemberEntity lookupLibraryMember(KLibrary library, String name, | 126 MemberEntity lookupLibraryMember(KLibrary library, String name, |
127 {bool setter: false}) { | 127 {bool setter: false}) { |
128 KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; | 128 KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
129 ir.Member member = libraryEnv.lookupMember(name, setter: setter); | 129 ir.Member member = libraryEnv.lookupMember(name, setter: setter); |
130 return member != null ? getMember(member) : null; | 130 return member != null ? getMember(member) : null; |
131 } | 131 } |
132 | 132 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 return new KTypeVariable(_getMethod(procedure), node.name, index); | 187 return new KTypeVariable(_getMethod(procedure), node.name, index); |
188 } | 188 } |
189 } | 189 } |
190 } | 190 } |
191 throw new UnsupportedError('Unsupported type parameter type node $node.'); | 191 throw new UnsupportedError('Unsupported type parameter type node $node.'); |
192 }); | 192 }); |
193 } | 193 } |
194 | 194 |
195 KConstructor _getConstructor(ir.Member node) { | 195 KConstructor _getConstructor(ir.Member node) { |
196 return _constructorMap.putIfAbsent(node, () { | 196 return _constructorMap.putIfAbsent(node, () { |
197 int constructorIndex = _constructorList.length; | 197 int memberIndex = _memberList.length; |
198 KConstructor constructor; | 198 KConstructor constructor; |
199 KClass enclosingClass = _getClass(node.enclosingClass); | 199 KClass enclosingClass = _getClass(node.enclosingClass); |
200 Name name = getName(node.name); | 200 Name name = getName(node.name); |
201 bool isExternal = node.isExternal; | 201 bool isExternal = node.isExternal; |
202 if (node is ir.Constructor) { | 202 if (node is ir.Constructor) { |
203 constructor = new KGenerativeConstructor( | 203 constructor = new KGenerativeConstructor( |
204 constructorIndex, enclosingClass, name, | 204 memberIndex, enclosingClass, name, |
205 isExternal: isExternal); | 205 isExternal: isExternal, isConst: node.isConst); |
| 206 } else if (node is ir.Procedure) { |
| 207 constructor = new KFactoryConstructor(memberIndex, enclosingClass, name, |
| 208 isExternal: isExternal, isConst: node.isConst); |
206 } else { | 209 } else { |
207 constructor = new KFactoryConstructor( | 210 // TODO(johnniwinther): Convert `node.location` to a [SourceSpan]. |
208 constructorIndex, enclosingClass, name, | 211 throw new SpannableAssertionFailure( |
209 isExternal: isExternal); | 212 NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}."); |
210 } | 213 } |
211 _constructorList.add(node); | 214 _memberList.add(node); |
212 return constructor; | 215 return constructor; |
213 }); | 216 }); |
214 } | 217 } |
215 | 218 |
216 KFunction _getMethod(ir.Procedure node) { | 219 KFunction _getMethod(ir.Procedure node) { |
217 return _methodMap.putIfAbsent(node, () { | 220 return _methodMap.putIfAbsent(node, () { |
| 221 int memberIndex = _memberList.length; |
218 KLibrary library; | 222 KLibrary library; |
219 KClass enclosingClass; | 223 KClass enclosingClass; |
220 if (node.enclosingClass != null) { | 224 if (node.enclosingClass != null) { |
221 enclosingClass = _getClass(node.enclosingClass); | 225 enclosingClass = _getClass(node.enclosingClass); |
222 library = enclosingClass.library; | 226 library = enclosingClass.library; |
223 } else { | 227 } else { |
224 library = _getLibrary(node.enclosingLibrary); | 228 library = _getLibrary(node.enclosingLibrary); |
225 } | 229 } |
226 Name name = getName(node.name); | 230 Name name = getName(node.name); |
227 bool isStatic = node.isStatic; | 231 bool isStatic = node.isStatic; |
228 bool isExternal = node.isExternal; | 232 bool isExternal = node.isExternal; |
| 233 KFunction function; |
229 switch (node.kind) { | 234 switch (node.kind) { |
230 case ir.ProcedureKind.Factory: | 235 case ir.ProcedureKind.Factory: |
231 throw new UnsupportedError("Cannot create method from factory."); | 236 throw new UnsupportedError("Cannot create method from factory."); |
232 case ir.ProcedureKind.Getter: | 237 case ir.ProcedureKind.Getter: |
233 return new KGetter(library, enclosingClass, name, | 238 function = new KGetter(memberIndex, library, enclosingClass, name, |
234 isStatic: isStatic, isExternal: isExternal); | 239 isStatic: isStatic, isExternal: isExternal); |
| 240 break; |
235 case ir.ProcedureKind.Method: | 241 case ir.ProcedureKind.Method: |
236 case ir.ProcedureKind.Operator: | 242 case ir.ProcedureKind.Operator: |
237 return new KMethod(library, enclosingClass, name, | 243 function = new KMethod(memberIndex, library, enclosingClass, name, |
238 isStatic: isStatic, isExternal: isExternal); | 244 isStatic: isStatic, isExternal: isExternal); |
| 245 break; |
239 case ir.ProcedureKind.Setter: | 246 case ir.ProcedureKind.Setter: |
240 return new KSetter(library, enclosingClass, getName(node.name).setter, | 247 function = new KSetter( |
| 248 memberIndex, library, enclosingClass, getName(node.name).setter, |
241 isStatic: isStatic, isExternal: isExternal); | 249 isStatic: isStatic, isExternal: isExternal); |
| 250 break; |
242 } | 251 } |
| 252 _memberList.add(node); |
| 253 return function; |
243 }); | 254 }); |
244 } | 255 } |
245 | 256 |
246 KField _getField(ir.Field node) { | 257 KField _getField(ir.Field node) { |
247 return _fieldMap.putIfAbsent(node, () { | 258 return _fieldMap.putIfAbsent(node, () { |
248 int fieldIndex = _fieldList.length; | 259 int memberIndex = _memberList.length; |
249 KLibrary library; | 260 KLibrary library; |
250 KClass enclosingClass; | 261 KClass enclosingClass; |
251 if (node.enclosingClass != null) { | 262 if (node.enclosingClass != null) { |
252 enclosingClass = _getClass(node.enclosingClass); | 263 enclosingClass = _getClass(node.enclosingClass); |
253 library = enclosingClass.library; | 264 library = enclosingClass.library; |
254 } else { | 265 } else { |
255 library = _getLibrary(node.enclosingLibrary); | 266 library = _getLibrary(node.enclosingLibrary); |
256 } | 267 } |
257 Name name = getName(node.name); | 268 Name name = getName(node.name); |
258 bool isStatic = node.isStatic; | 269 bool isStatic = node.isStatic; |
259 _fieldList.add(node); | 270 _memberList.add(node); |
260 return new KField(fieldIndex, library, enclosingClass, name, | 271 return new KField(memberIndex, library, enclosingClass, name, |
261 isStatic: isStatic, isAssignable: node.isMutable); | 272 isStatic: isStatic, |
| 273 isAssignable: node.isMutable, |
| 274 isConst: node.isConst); |
262 }); | 275 }); |
263 } | 276 } |
264 | 277 |
265 KLocalFunction _getLocal(ir.TreeNode node) { | 278 KLocalFunction _getLocal(ir.TreeNode node) { |
266 return _localFunctionMap.putIfAbsent(node, () { | 279 return _localFunctionMap.putIfAbsent(node, () { |
267 MemberEntity memberContext; | 280 MemberEntity memberContext; |
268 Entity executableContext; | 281 Entity executableContext; |
269 ir.TreeNode parent = node.parent; | 282 ir.TreeNode parent = node.parent; |
270 while (parent != null) { | 283 while (parent != null) { |
271 if (parent is ir.Member) { | 284 if (parent is ir.Member) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 } | 406 } |
394 } | 407 } |
395 throw new UnsupportedError("Unexpected member: $node"); | 408 throw new UnsupportedError("Unexpected member: $node"); |
396 } | 409 } |
397 | 410 |
398 @override | 411 @override |
399 FunctionEntity getConstructor(ir.Member node) => _getConstructor(node); | 412 FunctionEntity getConstructor(ir.Member node) => _getConstructor(node); |
400 | 413 |
401 ConstantConstructor _getConstructorConstant(KConstructor constructor) { | 414 ConstantConstructor _getConstructorConstant(KConstructor constructor) { |
402 return _constructorConstantMap.putIfAbsent(constructor, () { | 415 return _constructorConstantMap.putIfAbsent(constructor, () { |
403 ir.Member node = _constructorList[constructor.constructorIndex]; | 416 ir.Member node = _memberList[constructor.memberIndex]; |
404 if (node is ir.Constructor && node.isConst) { | 417 if (node is ir.Constructor && node.isConst) { |
405 return new Constantifier(this).computeConstantConstructor(node); | 418 return new Constantifier(this).computeConstantConstructor(node); |
406 } | 419 } |
407 throw new SpannableAssertionFailure( | 420 throw new SpannableAssertionFailure( |
408 constructor, | 421 constructor, |
409 "Unexpected constructor $constructor in " | 422 "Unexpected constructor $constructor in " |
410 "KernelWorldBuilder._getConstructorConstant"); | 423 "KernelWorldBuilder._getConstructorConstant"); |
411 }); | 424 }); |
412 } | 425 } |
413 | 426 |
414 ConstantExpression _getFieldConstant(KField field) { | 427 ConstantExpression _getFieldConstant(KField field) { |
415 return _fieldConstantMap.putIfAbsent(field, () { | 428 return _fieldConstantMap.putIfAbsent(field, () { |
416 ir.Field node = _fieldList[field.fieldIndex]; | 429 ir.Field node = _memberList[field.memberIndex]; |
417 if (node.isConst) { | 430 if (node.isConst) { |
418 return new Constantifier(this).visit(node.initializer); | 431 return new Constantifier(this).visit(node.initializer); |
419 } | 432 } |
420 throw new SpannableAssertionFailure( | 433 throw new SpannableAssertionFailure( |
421 field, | 434 field, |
422 "Unexpected field $field in " | 435 "Unexpected field $field in " |
423 "KernelWorldBuilder._getConstructorConstant"); | 436 "KernelWorldBuilder._getConstructorConstant"); |
424 }); | 437 }); |
425 } | 438 } |
426 } | 439 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 ClassEntity cls, List<DartType> typeArguments) { | 562 ClassEntity cls, List<DartType> typeArguments) { |
550 return new InterfaceType(cls, typeArguments); | 563 return new InterfaceType(cls, typeArguments); |
551 } | 564 } |
552 | 565 |
553 @override | 566 @override |
554 bool isSubtype(DartType a, DartType b) { | 567 bool isSubtype(DartType a, DartType b) { |
555 throw new UnimplementedError('KernelElementEnvironment.isSubtype'); | 568 throw new UnimplementedError('KernelElementEnvironment.isSubtype'); |
556 } | 569 } |
557 | 570 |
558 @override | 571 @override |
| 572 FunctionType getFunctionType(KFunction function) { |
| 573 throw new UnimplementedError('KernelElementEnvironment.getFunctionType'); |
| 574 } |
| 575 |
| 576 @override |
559 ConstructorEntity lookupConstructor(ClassEntity cls, String name, | 577 ConstructorEntity lookupConstructor(ClassEntity cls, String name, |
560 {bool required: false}) { | 578 {bool required: false}) { |
561 ConstructorEntity constructor = worldBuilder.lookupConstructor(cls, name); | 579 ConstructorEntity constructor = worldBuilder.lookupConstructor(cls, name); |
562 if (constructor == null && required) { | 580 if (constructor == null && required) { |
563 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, | 581 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, |
564 "The constructor $name was not found in class '${cls.name}'."); | 582 "The constructor $name was not found in class '${cls.name}'."); |
565 } | 583 } |
566 return constructor; | 584 return constructor; |
567 } | 585 } |
568 | 586 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 | 638 |
621 @override | 639 @override |
622 LibraryEntity lookupLibrary(Uri uri, {bool required: false}) { | 640 LibraryEntity lookupLibrary(Uri uri, {bool required: false}) { |
623 LibraryEntity library = worldBuilder.lookupLibrary(uri); | 641 LibraryEntity library = worldBuilder.lookupLibrary(uri); |
624 if (library == null && required) { | 642 if (library == null && required) { |
625 throw new SpannableAssertionFailure( | 643 throw new SpannableAssertionFailure( |
626 CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found."); | 644 CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found."); |
627 } | 645 } |
628 return library; | 646 return library; |
629 } | 647 } |
| 648 |
| 649 @override |
| 650 CallStructure getCallStructure(KFunction function) { |
| 651 ir.Member member = worldBuilder._memberList[function.memberIndex]; |
| 652 ir.FunctionNode functionNode; |
| 653 if (member is ir.Procedure) { |
| 654 functionNode = member.function; |
| 655 } else if (member is ir.Constructor) { |
| 656 functionNode = member.function; |
| 657 } else { |
| 658 throw new SpannableAssertionFailure( |
| 659 function, "Unexpected function node ${member} for $function."); |
| 660 } |
| 661 return new CallStructure( |
| 662 functionNode.positionalParameters.length + |
| 663 functionNode.namedParameters.length, |
| 664 functionNode.namedParameters.map((d) => d.name).toList()); |
| 665 } |
| 666 |
| 667 @override |
| 668 bool isDeferredLoadLibraryGetter(KMember member) { |
| 669 // TODO(johnniwinther): Support these. |
| 670 return false; |
| 671 } |
630 } | 672 } |
631 | 673 |
632 /// Visitor that converts kernel dart types into [DartType]. | 674 /// Visitor that converts kernel dart types into [DartType]. |
633 class DartTypeConverter extends ir.DartTypeVisitor<DartType> { | 675 class DartTypeConverter extends ir.DartTypeVisitor<DartType> { |
634 final KernelWorldBuilder elementAdapter; | 676 final KernelWorldBuilder elementAdapter; |
635 bool topLevel = true; | 677 bool topLevel = true; |
636 | 678 |
637 DartTypeConverter(this.elementAdapter); | 679 DartTypeConverter(this.elementAdapter); |
638 | 680 |
639 DartType convert(ir.DartType type) { | 681 DartType convert(ir.DartType type) { |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 } | 886 } |
845 | 887 |
846 InterfaceType getMixinTypeForClass(KClass cls) { | 888 InterfaceType getMixinTypeForClass(KClass cls) { |
847 KClassEnv env = builder._classEnvs[cls.classIndex]; | 889 KClassEnv env = builder._classEnvs[cls.classIndex]; |
848 ir.Supertype mixedInType = env.cls.mixedInType; | 890 ir.Supertype mixedInType = env.cls.mixedInType; |
849 if (mixedInType == null) return null; | 891 if (mixedInType == null) return null; |
850 return builder.createInterfaceType( | 892 return builder.createInterfaceType( |
851 mixedInType.classNode, mixedInType.typeArguments); | 893 mixedInType.classNode, mixedInType.typeArguments); |
852 } | 894 } |
853 } | 895 } |
OLD | NEW |