Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: pkg/compiler/lib/src/universe/element_world_builder.dart

Issue 2804993002: Extract ResolutionWorldBuilderBase from ElementResolutionWorldBuilder (Closed)
Patch Set: Fix. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of world_builder;
6
7 /// [ResolutionEnqueuerWorldBuilder] based on the [Element] model.
8 class ElementResolutionWorldBuilder extends ResolutionWorldBuilderBase {
9 /// Used for testing the new more precise computation of instantiated types
10 /// and classes.
11 static bool useInstantiationMap = false;
12
13 final JavaScriptBackend _backend;
14 final Resolution _resolution;
15
16 ElementResolutionWorldBuilder(this._backend, this._resolution,
17 SelectorConstraintsStrategy selectorConstraintsStrategy)
18 : super(_backend.compiler.elementEnvironment, _resolution.commonElements,
19 _backend.nativeBasicData, selectorConstraintsStrategy);
20
21 bool isImplemented(ClassElement cls) {
22 return super.isImplemented(cls.declaration);
23 }
24
25 void registerTypeInstantiation(
26 InterfaceType type, ClassUsedCallback classUsed,
27 {ConstructorEntity constructor,
28 bool byMirrors: false,
29 bool isRedirection: false}) {
30 ClassElement cls = type.element;
31 cls.ensureResolved(_resolution);
32 super.registerTypeInstantiation(type, classUsed,
33 constructor: constructor,
34 byMirrors: byMirrors,
35 isRedirection: isRedirection);
36 }
37
38 /// Returns the instantiation map used for computing the closed world.
39 ///
40 /// If [useInstantiationMap] is `true`, redirections are removed and
41 /// redirecting factories are converted to their effective target and type.
42 Map<ClassEntity, InstantiationInfo> getInstantiationMap() {
43 if (!useInstantiationMap) return _instantiationInfo;
44
45 Map<ClassEntity, InstantiationInfo> instantiationMap =
46 <ClassEntity, InstantiationInfo>{};
47
48 InstantiationInfo infoFor(ClassEntity cls) {
49 return instantiationMap.putIfAbsent(cls, () => new InstantiationInfo());
50 }
51
52 _instantiationInfo.forEach((cls, info) {
53 if (info.instantiationMap != null) {
54 info.instantiationMap
55 .forEach((ConstructorElement constructor, Set<Instance> set) {
56 for (Instance instance in set) {
57 if (instance.isRedirection) {
58 continue;
59 }
60 if (constructor == null || !constructor.isRedirectingFactory) {
61 infoFor(cls)
62 .addInstantiation(constructor, instance.type, instance.kind);
63 } else {
64 ConstructorElement target = constructor.effectiveTarget;
65 ResolutionInterfaceType targetType =
66 constructor.computeEffectiveTargetType(instance.type);
67 Instantiation kind = Instantiation.DIRECTLY_INSTANTIATED;
68 if (target.enclosingClass.isAbstract) {
69 // If target is a factory constructor on an abstract class.
70 kind = Instantiation.UNINSTANTIATED;
71 }
72 infoFor(targetType.element)
73 .addInstantiation(target, targetType, kind);
74 }
75 }
76 });
77 }
78 });
79 return instantiationMap;
80 }
81
82 void registerIsCheck(ResolutionDartType type) {
83 type.computeUnaliased(_resolution);
84 type = type.unaliased;
85 // Even in checked mode, type annotations for return type and argument
86 // types do not imply type checks, so there should never be a check
87 // against the type variable of a typedef.
88 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
89 super.registerIsCheck(type);
90 }
91
92 void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
93 if (staticUse.kind == StaticUseKind.CLOSURE) {
94 LocalFunctionElement localFunction = staticUse.element;
95 if (localFunction.type.containsTypeVariables) {
96 localFunctionsWithFreeTypeVariables.add(localFunction);
97 }
98 localFunctions.add(staticUse.element);
99 return;
100 }
101 MemberElement element = staticUse.element;
102 assert(invariant(element, element.isDeclaration,
103 message: "Element ${element} is not the declaration."));
104 super.registerStaticUse(staticUse, memberUsed);
105 }
106
107 _ClassUsage _createClassUsage(ClassElement cls) {
108 cls.ensureResolved(_resolution);
109 _resolution.ensureClassMembers(cls);
110 return super._createClassUsage(cls);
111 }
112
113 /// Called to add [cls] to the set of known classes.
114 ///
115 /// This ensures that class hierarchy queries can be performed on [cls] and
116 /// classes that extend or implement it.
117 void registerClass(ClassEntity cls) => _registerClass(cls);
118
119 void _registerClass(ClassEntity cls, {bool isDirectlyInstantiated: false}) {
120 _ensureClassSet(cls);
121 if (isDirectlyInstantiated) {
122 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
123 }
124 }
125
126 void _processInstantiatedClassMember(
127 ClassEntity cls, MemberElement member, MemberUsedCallback memberUsed) {
128 assert(invariant(member, member.isDeclaration));
129 member.computeType(_resolution);
130 super._processInstantiatedClassMember(cls, member, memberUsed);
131 }
132
133 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
134 cls = cls.declaration;
135 return _classHierarchyNodes.putIfAbsent(cls, () {
136 ClassHierarchyNode parentNode;
137 if (cls.superclass != null) {
138 parentNode = _ensureClassHierarchyNode(cls.superclass);
139 }
140 return new ClassHierarchyNode(parentNode, cls);
141 });
142 }
143
144 ClassSet _ensureClassSet(ClassElement cls) {
145 cls = cls.declaration;
146 return _classSets.putIfAbsent(cls, () {
147 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
148 ClassSet classSet = new ClassSet(node);
149
150 for (ResolutionInterfaceType type in cls.allSupertypes) {
151 // TODO(johnniwinther): Optimization: Avoid adding [cls] to
152 // superclasses.
153 ClassSet subtypeSet = _ensureClassSet(type.element);
154 subtypeSet.addSubtype(node);
155 }
156 if (cls.isMixinApplication) {
157 // TODO(johnniwinther): Store this in the [ClassSet].
158 MixinApplicationElement mixinApplication = cls;
159 if (mixinApplication.mixin != null) {
160 // If [mixinApplication] is malformed [mixin] is `null`.
161 registerMixinUse(mixinApplication, mixinApplication.mixin);
162 }
163 }
164
165 return classSet;
166 });
167 }
168
169 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) {
170 // Ensure that classes implicitly implementing `Function` are in its
171 // subtype set.
172 ClassElement cls = node.cls;
173 if (cls != _commonElements.functionClass &&
174 cls.implementsFunction(_commonElements)) {
175 ClassSet subtypeSet = _ensureClassSet(_commonElements.functionClass);
176 subtypeSet.addSubtype(node);
177 }
178 if (!node.isInstantiated && node.parentNode != null) {
179 _updateSuperClassHierarchyNodeForClass(node.parentNode);
180 }
181 }
182
183 void _updateClassHierarchyNodeForClass(ClassElement cls,
184 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) {
185 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
186 _updateSuperClassHierarchyNodeForClass(node);
187 if (directlyInstantiated) {
188 node.isDirectlyInstantiated = true;
189 }
190 if (abstractlyInstantiated) {
191 node.isAbstractlyInstantiated = true;
192 }
193 }
194
195 ClosedWorld closeWorld(DiagnosticReporter reporter) {
196 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
197 new Map<ClassEntity, Set<ClassEntity>>();
198
199 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
200 /// properties of the [ClassHierarchyNode] for [cls].
201
202 void addSubtypes(ClassElement cls, InstantiationInfo info) {
203 if (!info.hasInstantiation) {
204 return;
205 }
206 assert(cls.isDeclaration);
207 if (!cls.isResolved) {
208 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.');
209 }
210
211 _updateClassHierarchyNodeForClass(cls,
212 directlyInstantiated: info.isDirectlyInstantiated,
213 abstractlyInstantiated: info.isAbstractlyInstantiated);
214
215 // Walk through the superclasses, and record the types
216 // implemented by that type on the superclasses.
217 ClassElement superclass = cls.superclass;
218 while (superclass != null) {
219 Set<ClassEntity> typesImplementedBySubclassesOfCls =
220 typesImplementedBySubclasses.putIfAbsent(
221 superclass, () => new Set<ClassEntity>());
222 for (ResolutionInterfaceType current in cls.allSupertypes) {
223 typesImplementedBySubclassesOfCls.add(current.element);
224 }
225 superclass = superclass.superclass;
226 }
227 }
228
229 // Use the [:seenClasses:] set to include non-instantiated
230 // classes: if the superclass of these classes require RTI, then
231 // they also need RTI, so that a constructor passes the type
232 // variables to the super constructor.
233 forEachInstantiatedClass(addSubtypes);
234
235 _closed = true;
236 return _closedWorldCache = new ClosedWorldImpl(
237 backend: _backend,
238 commonElements: _commonElements,
239 resolutionWorldBuilder: this,
240 functionSetBuilder: _allFunctions,
241 allTypedefs: _allTypedefs,
242 mixinUses: _mixinUses,
243 typesImplementedBySubclasses: typesImplementedBySubclasses,
244 classHierarchyNodes: _classHierarchyNodes,
245 classSets: _classSets);
246 }
247
248 void registerUsedElement(MemberElement element) {
249 if (element.isInstanceMember && !element.isAbstract) {
250 _allFunctions.add(element);
251 }
252 }
253
254 @override
255 void registerMixinUse(
256 MixinApplicationElement mixinApplication, ClassElement mixin) {
257 assert(mixin.isDeclaration);
258 super.registerMixinUse(mixinApplication, mixin);
259 }
260 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/resolution.dart ('k') | pkg/compiler/lib/src/universe/resolution_world_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698