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.js_model.elements; | 5 library dart2js.js_model.elements; |
6 | 6 |
7 import '../common_elements.dart'; | |
8 import '../constants/constant_system.dart'; | |
9 import '../elements/elements.dart'; | |
10 import '../elements/entities.dart'; | 7 import '../elements/entities.dart'; |
11 import '../elements/names.dart'; | 8 import '../elements/names.dart'; |
12 import '../elements/types.dart'; | 9 import '../elements/types.dart'; |
13 import '../js_backend/backend_usage.dart'; | |
14 import '../js_backend/interceptor_data.dart'; | |
15 import '../js_backend/native_data.dart'; | |
16 import '../js_backend/runtime_types.dart'; | |
17 import '../kernel/elements.dart'; | 10 import '../kernel/elements.dart'; |
18 import '../kernel/element_map_impl.dart'; | 11 import '../kernel/element_map_impl.dart'; |
19 import '../native/behavior.dart'; | |
20 import '../universe/class_set.dart'; | |
21 import '../world.dart'; | |
22 | 12 |
23 /// Bidirectional map between 'frontend' and 'backend' elements. | 13 /// Map from 'frontend' to 'backend' elements. |
24 /// | 14 /// |
25 /// Frontend elements are what we read in, these typically represents concepts | 15 /// Frontend elements are what we read in, these typically represents concepts |
26 /// in Dart. Backend elements are what we generate, these may include elements | 16 /// in Dart. Backend elements are what we generate, these may include elements |
27 /// that do not correspond to a Dart concept, such as closure classes. | 17 /// that do not correspond to a Dart concept, such as closure classes. |
28 /// | 18 /// |
29 /// Querying for the frontend element for a backend-only element throws an | 19 /// Querying for the frontend element for a backend-only element throws an |
30 /// exception. | 20 /// exception. |
31 class JsToFrontendMap { | 21 class JsToFrontendMap { |
32 LibraryEntity toBackendLibrary(LibraryEntity library) => library; | 22 LibraryEntity toBackendLibrary(LibraryEntity library) => library; |
33 LibraryEntity toFrontendLibrary(LibraryEntity library) => library; | |
34 | 23 |
35 ClassEntity toBackendClass(ClassEntity cls) => cls; | 24 ClassEntity toBackendClass(ClassEntity cls) => cls; |
36 ClassEntity toFrontendClass(ClassEntity cls) => cls; | |
37 | 25 |
38 MemberEntity toBackendMember(MemberEntity member) => member; | 26 MemberEntity toBackendMember(MemberEntity member) => member; |
39 MemberEntity toFrontendMember(MemberEntity member) => member; | |
40 | 27 |
41 DartType toBackendType(DartType type) => type; | 28 DartType toBackendType(DartType type) => type; |
42 DartType toFrontendType(DartType type) => type; | 29 |
| 30 Set<LibraryEntity> toBackendLibrarySet(Iterable<LibraryEntity> set) { |
| 31 return set.map(toBackendLibrary).toSet(); |
| 32 } |
| 33 |
| 34 Set<ClassEntity> toBackendClassSet(Iterable<ClassEntity> set) { |
| 35 return set.map(toBackendClass).toSet(); |
| 36 } |
| 37 |
| 38 Set<MemberEntity> toBackendMemberSet(Iterable<MemberEntity> set) { |
| 39 return set.map(toBackendMember).toSet(); |
| 40 } |
| 41 |
| 42 Set<FunctionEntity> toBackendFunctionSet(Iterable<FunctionEntity> set) { |
| 43 Set<FunctionEntity> newSet = new Set<FunctionEntity>(); |
| 44 for (FunctionEntity element in set) { |
| 45 newSet.add(toBackendMember(element)); |
| 46 } |
| 47 return newSet; |
| 48 } |
| 49 |
| 50 Map<LibraryEntity, V> toBackendLibraryMap<V>( |
| 51 Map<LibraryEntity, V> map, V convert(V value)) { |
| 52 return convertMap(map, toBackendLibrary, convert); |
| 53 } |
| 54 |
| 55 Map<ClassEntity, V> toBackendClassMap<V>( |
| 56 Map<ClassEntity, V> map, V convert(V value)) { |
| 57 return convertMap(map, toBackendClass, convert); |
| 58 } |
| 59 |
| 60 Map<MemberEntity, V> toBackendMemberMap<V>( |
| 61 Map<MemberEntity, V> map, V convert(V value)) { |
| 62 return convertMap(map, toBackendMember, convert); |
| 63 } |
43 } | 64 } |
44 | 65 |
45 abstract class JsToFrontendMapBase implements JsToFrontendMap { | 66 E identity<E>(E element) => element; |
| 67 |
| 68 Map<K, V> convertMap<K, V>( |
| 69 Map<K, V> map, K convertKey(K key), V convertValue(V value)) { |
| 70 Map<K, V> newMap = <K, V>{}; |
| 71 map.forEach((K key, V value) { |
| 72 newMap[convertKey(key)] = convertValue(value); |
| 73 }); |
| 74 return newMap; |
| 75 } |
| 76 |
| 77 abstract class JsToFrontendMapBase extends JsToFrontendMap { |
46 DartType toBackendType(DartType type) => | 78 DartType toBackendType(DartType type) => |
47 const TypeConverter().visit(type, _toBackendEntity); | 79 const TypeConverter().visit(type, _toBackendEntity); |
48 DartType toFrontendType(DartType type) => | |
49 const TypeConverter().visit(type, _toFrontendEntity); | |
50 | 80 |
51 Entity _toBackendEntity(Entity entity) { | 81 Entity _toBackendEntity(Entity entity) { |
52 if (entity is ClassEntity) return toBackendClass(entity); | 82 if (entity is ClassEntity) return toBackendClass(entity); |
53 assert(entity is TypeVariableEntity); | 83 assert(entity is TypeVariableEntity); |
54 return toBackendTypeVariable(entity); | 84 return toBackendTypeVariable(entity); |
55 } | 85 } |
56 | 86 |
57 Entity _toFrontendEntity(Entity entity) { | |
58 if (entity is ClassEntity) return toFrontendClass(entity); | |
59 assert(entity is TypeVariableEntity); | |
60 TypeVariableEntity typeVariable = toFrontendTypeVariable(entity); | |
61 assert(typeVariable != null, "No front end type variable for $entity"); | |
62 return typeVariable; | |
63 } | |
64 | |
65 TypeVariableEntity toBackendTypeVariable(TypeVariableEntity typeVariable); | 87 TypeVariableEntity toBackendTypeVariable(TypeVariableEntity typeVariable); |
66 TypeVariableEntity toFrontendTypeVariable(TypeVariableEntity typeVariable); | |
67 } | 88 } |
68 | 89 |
69 // TODO(johnniwinther): Merge this with [JsKernelToElementMap]. | 90 // TODO(johnniwinther): Merge this with [JsKernelToElementMap]. |
70 class JsElementCreatorMixin { | 91 class JsElementCreatorMixin { |
71 IndexedLibrary createLibrary( | 92 IndexedLibrary createLibrary( |
72 int libraryIndex, String name, Uri canonicalUri) { | 93 int libraryIndex, String name, Uri canonicalUri) { |
73 return new JLibrary(libraryIndex, name, canonicalUri); | 94 return new JLibrary(libraryIndex, name, canonicalUri); |
74 } | 95 } |
75 | 96 |
76 IndexedClass createClass(LibraryEntity library, int classIndex, String name, | 97 IndexedClass createClass(LibraryEntity library, int classIndex, String name, |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 final MemberEntity memberContext; | 548 final MemberEntity memberContext; |
528 final Entity executableContext; | 549 final Entity executableContext; |
529 final FunctionType functionType; | 550 final FunctionType functionType; |
530 | 551 |
531 JLocalFunction( | 552 JLocalFunction( |
532 this.name, this.memberContext, this.executableContext, this.functionType); | 553 this.name, this.memberContext, this.executableContext, this.functionType); |
533 | 554 |
534 String toString() => '${jsElementPrefix}local_function' | 555 String toString() => '${jsElementPrefix}local_function' |
535 '(${memberContext.name}.${name ?? '<anonymous>'})'; | 556 '(${memberContext.name}.${name ?? '<anonymous>'})'; |
536 } | 557 } |
537 | |
538 class JsClosedWorld extends ClosedWorldBase with KernelClosedWorldMixin { | |
539 final JsKernelToElementMap elementMap; | |
540 final RuntimeTypesNeed rtiNeed; | |
541 | |
542 JsClosedWorld(this.elementMap, | |
543 {ElementEnvironment elementEnvironment, | |
544 DartTypes dartTypes, | |
545 CommonElements commonElements, | |
546 ConstantSystem constantSystem, | |
547 NativeData nativeData, | |
548 InterceptorData interceptorData, | |
549 BackendUsage backendUsage, | |
550 this.rtiNeed, | |
551 Set<ClassEntity> implementedClasses, | |
552 Iterable<ClassEntity> liveNativeClasses, | |
553 Iterable<MemberEntity> liveInstanceMembers, | |
554 Iterable<MemberEntity> assignedInstanceMembers, | |
555 Set<TypedefElement> allTypedefs, | |
556 Map<ClassEntity, Set<ClassEntity>> mixinUses, | |
557 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, | |
558 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, | |
559 Map<ClassEntity, ClassSet> classSets}) | |
560 : super( | |
561 elementEnvironment, | |
562 dartTypes, | |
563 commonElements, | |
564 constantSystem, | |
565 nativeData, | |
566 interceptorData, | |
567 backendUsage, | |
568 implementedClasses, | |
569 liveNativeClasses, | |
570 liveInstanceMembers, | |
571 assignedInstanceMembers, | |
572 allTypedefs, | |
573 mixinUses, | |
574 typesImplementedBySubclasses, | |
575 classHierarchyNodes, | |
576 classSets); | |
577 | |
578 @override | |
579 void registerClosureClass(ClassElement cls) { | |
580 throw new UnimplementedError('JsClosedWorld.registerClosureClass'); | |
581 } | |
582 } | |
583 | |
584 class JsNativeData implements NativeData { | |
585 final JsToFrontendMap _map; | |
586 final NativeData _nativeData; | |
587 | |
588 JsNativeData(this._map, this._nativeData); | |
589 | |
590 @override | |
591 bool isNativeClass(ClassEntity element) { | |
592 return _nativeData.isNativeClass(_map.toFrontendClass(element)); | |
593 } | |
594 | |
595 @override | |
596 String computeUnescapedJSInteropName(String name) { | |
597 return _nativeData.computeUnescapedJSInteropName(name); | |
598 } | |
599 | |
600 @override | |
601 String getJsInteropMemberName(MemberEntity element) { | |
602 return _nativeData.getJsInteropMemberName(_map.toFrontendMember(element)); | |
603 } | |
604 | |
605 @override | |
606 String getJsInteropClassName(ClassEntity element) { | |
607 return _nativeData.getJsInteropClassName(_map.toFrontendClass(element)); | |
608 } | |
609 | |
610 @override | |
611 bool isAnonymousJsInteropClass(ClassEntity element) { | |
612 return _nativeData.isAnonymousJsInteropClass(_map.toFrontendClass(element)); | |
613 } | |
614 | |
615 @override | |
616 String getJsInteropLibraryName(LibraryEntity element) { | |
617 return _nativeData.getJsInteropLibraryName(_map.toFrontendLibrary(element)); | |
618 } | |
619 | |
620 @override | |
621 bool isJsInteropMember(MemberEntity element) { | |
622 return _nativeData.isJsInteropMember(_map.toFrontendMember(element)); | |
623 } | |
624 | |
625 @override | |
626 String getFixedBackendMethodPath(FunctionEntity element) { | |
627 return _nativeData | |
628 .getFixedBackendMethodPath(_map.toFrontendMember(element)); | |
629 } | |
630 | |
631 @override | |
632 String getFixedBackendName(MemberEntity element) { | |
633 return _nativeData.getFixedBackendName(_map.toFrontendMember(element)); | |
634 } | |
635 | |
636 @override | |
637 bool hasFixedBackendName(MemberEntity element) { | |
638 return _nativeData.hasFixedBackendName(_map.toFrontendMember(element)); | |
639 } | |
640 | |
641 @override | |
642 NativeBehavior getNativeFieldStoreBehavior(FieldEntity field) { | |
643 return _nativeData | |
644 .getNativeFieldStoreBehavior(_map.toFrontendMember(field)); | |
645 } | |
646 | |
647 @override | |
648 NativeBehavior getNativeFieldLoadBehavior(FieldEntity field) { | |
649 return _nativeData.getNativeFieldLoadBehavior(_map.toFrontendMember(field)); | |
650 } | |
651 | |
652 @override | |
653 NativeBehavior getNativeMethodBehavior(FunctionEntity method) { | |
654 return _nativeData.getNativeMethodBehavior(_map.toFrontendMember(method)); | |
655 } | |
656 | |
657 @override | |
658 bool isNativeMember(MemberEntity element) { | |
659 return _nativeData.isNativeMember(_map.toFrontendMember(element)); | |
660 } | |
661 | |
662 @override | |
663 bool isJsInteropClass(ClassEntity element) { | |
664 return _nativeData.isJsInteropClass(_map.toFrontendClass(element)); | |
665 } | |
666 | |
667 @override | |
668 bool isJsInteropLibrary(LibraryEntity element) { | |
669 return _nativeData.isJsInteropLibrary(_map.toFrontendLibrary(element)); | |
670 } | |
671 | |
672 @override | |
673 bool get isJsInteropUsed { | |
674 return _nativeData.isJsInteropUsed; | |
675 } | |
676 | |
677 @override | |
678 bool isNativeOrExtendsNative(ClassEntity element) { | |
679 return _nativeData.isNativeOrExtendsNative(_map.toFrontendClass(element)); | |
680 } | |
681 | |
682 @override | |
683 bool hasNativeTagsForcedNonLeaf(ClassEntity cls) { | |
684 return _nativeData.hasNativeTagsForcedNonLeaf(_map.toFrontendClass(cls)); | |
685 } | |
686 | |
687 @override | |
688 List<String> getNativeTagsOfClass(ClassEntity cls) { | |
689 return _nativeData.getNativeTagsOfClass(_map.toFrontendClass(cls)); | |
690 } | |
691 } | |
692 | |
693 class JsBackendUsage implements BackendUsage { | |
694 final JsToFrontendMap _map; | |
695 final BackendUsage _backendUsage; | |
696 | |
697 @override | |
698 bool needToInitializeIsolateAffinityTag; | |
699 @override | |
700 bool needToInitializeDispatchProperty; | |
701 | |
702 JsBackendUsage(this._map, this._backendUsage) { | |
703 needToInitializeIsolateAffinityTag = | |
704 _backendUsage.needToInitializeIsolateAffinityTag; | |
705 needToInitializeDispatchProperty = | |
706 _backendUsage.needToInitializeDispatchProperty; | |
707 } | |
708 | |
709 @override | |
710 bool isFunctionUsedByBackend(FunctionEntity element) { | |
711 return _backendUsage | |
712 .isFunctionUsedByBackend(_map.toFrontendMember(element)); | |
713 } | |
714 | |
715 @override | |
716 bool isFieldUsedByBackend(FieldEntity element) { | |
717 return _backendUsage.isFieldUsedByBackend(_map.toFrontendMember(element)); | |
718 } | |
719 | |
720 @override | |
721 Iterable<FunctionEntity> get globalFunctionDependencies { | |
722 FunctionEntity f(FunctionEntity e) => _map.toBackendMember(e); | |
723 return _backendUsage.globalFunctionDependencies.map(f); | |
724 } | |
725 | |
726 @override | |
727 Iterable<ClassEntity> get globalClassDependencies { | |
728 return _backendUsage.globalClassDependencies.map(_map.toBackendClass); | |
729 } | |
730 | |
731 @override | |
732 bool get requiresPreamble => _backendUsage.requiresPreamble; | |
733 | |
734 @override | |
735 bool get isInvokeOnUsed => _backendUsage.isInvokeOnUsed; | |
736 | |
737 @override | |
738 bool get isRuntimeTypeUsed => _backendUsage.isRuntimeTypeUsed; | |
739 | |
740 @override | |
741 bool get isIsolateInUse => _backendUsage.isIsolateInUse; | |
742 | |
743 @override | |
744 bool get isFunctionApplyUsed => _backendUsage.isFunctionApplyUsed; | |
745 | |
746 @override | |
747 bool get isMirrorsUsed => _backendUsage.isMirrorsUsed; | |
748 | |
749 @override | |
750 bool get isNoSuchMethodUsed => _backendUsage.isNoSuchMethodUsed; | |
751 } | |
OLD | NEW |