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

Side by Side Diff: pkg/compiler/lib/src/universe/resolution_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
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 part of world_builder; 5 part of world_builder;
6 6
7 abstract class ResolutionWorldBuilder implements WorldBuilder, OpenWorld { 7 abstract class ResolutionWorldBuilder implements WorldBuilder, OpenWorld {
8 /// Set of all local functions in the program. Used by the mirror tracking 8 /// Set of all local functions in the program. Used by the mirror tracking
9 /// system to find all live closure instances. 9 /// system to find all live closure instances.
10 Iterable<LocalFunctionElement> get localFunctions; 10 Iterable<Local> get localFunctions;
11 11
12 /// Set of (live) local functions (closures) whose signatures reference type 12 /// Set of (live) local functions (closures) whose signatures reference type
13 /// variables. 13 /// variables.
14 /// 14 ///
15 /// A live function is one whose enclosing member function has been enqueued. 15 /// A live function is one whose enclosing member function has been enqueued.
16 Iterable<LocalFunctionElement> get localFunctionsWithFreeTypeVariables; 16 Iterable<Local> get localFunctionsWithFreeTypeVariables;
17 17
18 /// Set of methods in instantiated classes that are potentially closurized. 18 /// Set of methods in instantiated classes that are potentially closurized.
19 Iterable<MethodElement> get closurizedMembers; 19 Iterable<FunctionEntity> get closurizedMembers;
20 20
21 /// Set of live closurized members whose signatures reference type variables. 21 /// Set of live closurized members whose signatures reference type variables.
22 /// 22 ///
23 /// A closurized method is considered live if the enclosing class has been 23 /// A closurized method is considered live if the enclosing class has been
24 /// instantiated. 24 /// instantiated.
25 Iterable<MethodElement> get closurizedMembersWithFreeTypeVariables; 25 Iterable<FunctionEntity> get closurizedMembersWithFreeTypeVariables;
26 26
27 /// Returns `true` if [cls] is considered to be implemented by an 27 /// Returns `true` if [cls] is considered to be implemented by an
28 /// instantiated class, either directly, through subclasses or through 28 /// instantiated class, either directly, through subclasses or through
29 /// subtypes. The latter case only contains spurious information from 29 /// subtypes. The latter case only contains spurious information from
30 /// instantiations through factory constructors and mixins. 30 /// instantiations through factory constructors and mixins.
31 bool isImplemented(ClassElement cls); 31 // TODO(johnniwinther): Improve semantic precision.
32 bool isImplemented(ClassEntity cls);
32 33
33 /// Set of all fields that are statically known to be written to. 34 /// Set of all fields that are statically known to be written to.
34 Iterable<Element> get fieldSetters; 35 Iterable<FieldEntity> get fieldSetters;
35 36
36 /// Call [f] for all classes with instantiated types. This includes the 37 /// Call [f] for all classes with instantiated types. This includes the
37 /// directly and abstractly instantiated classes but also classes whose type 38 /// directly and abstractly instantiated classes but also classes whose type
38 /// arguments are used in live factory constructors. 39 /// arguments are used in live factory constructors.
39 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)); 40 void forEachInstantiatedClass(f(ClassEntity cls, InstantiationInfo info));
40 41
41 /// Returns `true` if [member] is invoked as a setter. 42 /// Returns `true` if [member] is invoked as a setter.
42 bool hasInvokedSetter(Element member); 43 bool hasInvokedSetter(MemberEntity member);
43 44
44 /// Returns `true` if [member] has been marked as used (called, read, etc.) in 45 /// Returns `true` if [member] has been marked as used (called, read, etc.) in
45 /// this world builder. 46 /// this world builder.
46 // TODO(johnniwinther): Maybe this should be part of [ClosedWorld] (instead). 47 // TODO(johnniwinther): Maybe this should be part of [ClosedWorld] (instead).
47 bool isMemberUsed(MemberEntity member); 48 bool isMemberUsed(MemberEntity member);
48 49
49 /// The closed world computed by this world builder. 50 /// The closed world computed by this world builder.
50 /// 51 ///
51 /// This is only available after the world builder has been closed. 52 /// This is only available after the world builder has been closed.
52 ClosedWorld get closedWorldForTesting; 53 ClosedWorld get closedWorldForTesting;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed); 87 void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed);
87 88
88 /// Register the constant [use] with this world builder. Returns `true` if 89 /// Register the constant [use] with this world builder. Returns `true` if
89 /// the constant use was new to the world. 90 /// the constant use was new to the world.
90 bool registerConstantUse(ConstantUse use); 91 bool registerConstantUse(ConstantUse use);
91 } 92 }
92 93
93 /// The type and kind of an instantiation registered through 94 /// The type and kind of an instantiation registered through
94 /// `ResolutionWorldBuilder.registerTypeInstantiation`. 95 /// `ResolutionWorldBuilder.registerTypeInstantiation`.
95 class Instance { 96 class Instance {
96 final ResolutionInterfaceType type; 97 final InterfaceType type;
97 final Instantiation kind; 98 final Instantiation kind;
98 final bool isRedirection; 99 final bool isRedirection;
99 100
100 Instance(this.type, this.kind, {this.isRedirection: false}); 101 Instance(this.type, this.kind, {this.isRedirection: false});
101 102
102 int get hashCode { 103 int get hashCode {
103 return Hashing.objectHash( 104 return Hashing.objectHash(
104 type, Hashing.objectHash(kind, Hashing.objectHash(isRedirection))); 105 type, Hashing.objectHash(kind, Hashing.objectHash(isRedirection)));
105 } 106 }
106 107
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 /// }, 185 /// },
185 /// }, 186 /// },
186 /// DivElement: { 187 /// DivElement: {
187 /// DivElement: { 188 /// DivElement: {
188 /// DivElement abstractly, // from `new DivElement()` 189 /// DivElement abstractly, // from `new DivElement()`
189 /// }, 190 /// },
190 /// } 191 /// }
191 /// 192 ///
192 /// If the constructor is unknown, for instance for native or mirror usage, 193 /// If the constructor is unknown, for instance for native or mirror usage,
193 /// `null` is used as key. 194 /// `null` is used as key.
194 Map<ConstructorElement, Set<Instance>> instantiationMap; 195 Map<ConstructorEntity, Set<Instance>> instantiationMap;
195 196
196 /// Register [type] as the instantiation [kind] using [constructor]. 197 /// Register [type] as the instantiation [kind] using [constructor].
197 void addInstantiation(ConstructorElement constructor, 198 void addInstantiation(
198 ResolutionInterfaceType type, Instantiation kind, 199 ConstructorEntity constructor, InterfaceType type, Instantiation kind,
199 {bool isRedirection: false}) { 200 {bool isRedirection: false}) {
200 instantiationMap ??= <ConstructorElement, Set<Instance>>{}; 201 instantiationMap ??= <ConstructorEntity, Set<Instance>>{};
201 instantiationMap 202 instantiationMap
202 .putIfAbsent(constructor, () => new Set<Instance>()) 203 .putIfAbsent(constructor, () => new Set<Instance>())
203 .add(new Instance(type, kind, isRedirection: isRedirection)); 204 .add(new Instance(type, kind, isRedirection: isRedirection));
204 switch (kind) { 205 switch (kind) {
205 case Instantiation.DIRECTLY_INSTANTIATED: 206 case Instantiation.DIRECTLY_INSTANTIATED:
206 isDirectlyInstantiated = true; 207 isDirectlyInstantiated = true;
207 break; 208 break;
208 case Instantiation.ABSTRACTLY_INSTANTIATED: 209 case Instantiation.ABSTRACTLY_INSTANTIATED:
209 isAbstractlyInstantiated = true; 210 isAbstractlyInstantiated = true;
210 break; 211 break;
(...skipping 13 matching lines...) Expand all
224 225
225 /// `true` if the class is abstractly instantiated. 226 /// `true` if the class is abstractly instantiated.
226 bool isAbstractlyInstantiated = false; 227 bool isAbstractlyInstantiated = false;
227 228
228 String toString() { 229 String toString() {
229 StringBuffer sb = new StringBuffer(); 230 StringBuffer sb = new StringBuffer();
230 sb.write('InstantiationInfo['); 231 sb.write('InstantiationInfo[');
231 if (instantiationMap != null) { 232 if (instantiationMap != null) {
232 bool needsComma = false; 233 bool needsComma = false;
233 instantiationMap 234 instantiationMap
234 .forEach((ConstructorElement constructor, Set<Instance> set) { 235 .forEach((ConstructorEntity constructor, Set<Instance> set) {
235 if (needsComma) { 236 if (needsComma) {
236 sb.write(', '); 237 sb.write(', ');
237 } 238 }
238 if (constructor != null) { 239 if (constructor != null) {
239 sb.write(constructor); 240 sb.write(constructor);
240 } else { 241 } else {
241 sb.write('<unknown>'); 242 sb.write('<unknown>');
242 } 243 }
243 sb.write(': '); 244 sb.write(': ');
244 sb.write(set); 245 sb.write(set);
245 needsComma = true; 246 needsComma = true;
246 }); 247 });
247 } 248 }
248 sb.write(']'); 249 sb.write(']');
249 return sb.toString(); 250 return sb.toString();
250 } 251 }
251 } 252 }
252 253
253 /// [ResolutionEnqueuerWorldBuilder] based on the [Element] model. 254 /// Base implementation of [ResolutionEnqueuerWorldBuilder].
254 class ElementResolutionWorldBuilder implements ResolutionEnqueuerWorldBuilder { 255 abstract class ResolutionWorldBuilderBase
256 implements ResolutionEnqueuerWorldBuilder {
255 /// Instantiation information for all classes with instantiated types. 257 /// Instantiation information for all classes with instantiated types.
256 /// 258 ///
257 /// Invariant: Elements are declaration elements. 259 /// Invariant: Elements are declaration elements.
258 final Map<ClassElement, InstantiationInfo> _instantiationInfo = 260 final Map<ClassEntity, InstantiationInfo> _instantiationInfo =
259 <ClassElement, InstantiationInfo>{}; 261 <ClassEntity, InstantiationInfo>{};
260 262
261 /// Classes implemented by directly instantiated classes. 263 /// Classes implemented by directly instantiated classes.
262 final Set<ClassElement> _implementedClasses = new Set<ClassElement>(); 264 final Set<ClassEntity> _implementedClasses = new Set<ClassEntity>();
263 265
264 /// The set of all referenced static fields. 266 /// The set of all referenced static fields.
265 /// 267 ///
266 /// Invariant: Elements are declaration elements. 268 /// Invariant: Elements are declaration elements.
267 final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>(); 269 final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
268 270
269 /** 271 /**
270 * Documentation wanted -- johnniwinther 272 * Documentation wanted -- johnniwinther
271 * 273 *
272 * Invariant: Elements are declaration elements. 274 * Invariant: Elements are declaration elements.
273 */ 275 */
274 final Set<FunctionElement> methodsNeedingSuperGetter = 276 final Set<FunctionEntity> methodsNeedingSuperGetter =
275 new Set<FunctionElement>(); 277 new Set<FunctionEntity>();
276 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = 278 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
277 <String, Map<Selector, SelectorConstraints>>{}; 279 <String, Map<Selector, SelectorConstraints>>{};
278 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = 280 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters =
279 <String, Map<Selector, SelectorConstraints>>{}; 281 <String, Map<Selector, SelectorConstraints>>{};
280 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = 282 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
281 <String, Map<Selector, SelectorConstraints>>{}; 283 <String, Map<Selector, SelectorConstraints>>{};
282 284
283 final Map<ClassElement, _ClassUsage> _processedClasses = 285 final Map<ClassEntity, _ClassUsage> _processedClasses =
284 <ClassElement, _ClassUsage>{}; 286 <ClassEntity, _ClassUsage>{};
285 287
286 /// Map of registered usage of static members of live classes. 288 /// Map of registered usage of static members of live classes.
287 final Map<Entity, _StaticMemberUsage> _staticMemberUsage = 289 final Map<Entity, _StaticMemberUsage> _staticMemberUsage =
288 <Entity, _StaticMemberUsage>{}; 290 <Entity, _StaticMemberUsage>{};
289 291
290 /// Map of registered usage of instance members of live classes. 292 /// Map of registered usage of instance members of live classes.
291 final Map<MemberEntity, _MemberUsage> _instanceMemberUsage = 293 final Map<MemberEntity, _MemberUsage> _instanceMemberUsage =
292 <MemberEntity, _MemberUsage>{}; 294 <MemberEntity, _MemberUsage>{};
293 295
294 /// Map containing instance members of live classes that are not yet live 296 /// Map containing instance members of live classes that are not yet live
295 /// themselves. 297 /// themselves.
296 final Map<String, Set<_MemberUsage>> _instanceMembersByName = 298 final Map<String, Set<_MemberUsage>> _instanceMembersByName =
297 <String, Set<_MemberUsage>>{}; 299 <String, Set<_MemberUsage>>{};
298 300
299 /// Map containing instance methods of live classes that are not yet 301 /// Map containing instance methods of live classes that are not yet
300 /// closurized. 302 /// closurized.
301 final Map<String, Set<_MemberUsage>> _instanceFunctionsByName = 303 final Map<String, Set<_MemberUsage>> _instanceFunctionsByName =
302 <String, Set<_MemberUsage>>{}; 304 <String, Set<_MemberUsage>>{};
303 305
304 /// Fields set. 306 /// Fields set.
305 final Set<Element> fieldSetters = new Set<Element>(); 307 final Set<FieldEntity> fieldSetters = new Set<FieldEntity>();
306 final Set<ResolutionDartType> isChecks = new Set<ResolutionDartType>(); 308 final Set<DartType> isChecks = new Set<DartType>();
307 309
308 /// Set of all closures in the program. Used by the mirror tracking system 310 /// Set of all closures in the program. Used by the mirror tracking system
309 /// to find all live closure instances. 311 /// to find all live closure instances.
310 final Set<LocalFunctionElement> localFunctions = 312 final Set<Local> localFunctions = new Set<Local>();
311 new Set<LocalFunctionElement>();
312 313
313 /// Set of live local functions (closures) whose signatures reference type 314 /// Set of live local functions (closures) whose signatures reference type
314 /// variables. 315 /// variables.
315 /// 316 ///
316 /// A local function is considered live if the enclosing member function is 317 /// A local function is considered live if the enclosing member function is
317 /// live. 318 /// live.
318 final Set<LocalFunctionElement> localFunctionsWithFreeTypeVariables = 319 final Set<Local> localFunctionsWithFreeTypeVariables = new Set<Local>();
319 new Set<LocalFunctionElement>();
320 320
321 /// Set of methods in instantiated classes that are potentially closurized. 321 /// Set of methods in instantiated classes that are potentially closurized.
322 final Set<MethodElement> closurizedMembers = new Set<MethodElement>(); 322 final Set<FunctionEntity> closurizedMembers = new Set<FunctionEntity>();
323 323
324 /// Set of live closurized members whose signatures reference type variables. 324 /// Set of live closurized members whose signatures reference type variables.
325 /// 325 ///
326 /// A closurized method is considered live if the enclosing class has been 326 /// A closurized method is considered live if the enclosing class has been
327 /// instantiated. 327 /// instantiated.
328 final Set<MethodElement> closurizedMembersWithFreeTypeVariables = 328 final Set<FunctionEntity> closurizedMembersWithFreeTypeVariables =
329 new Set<MethodElement>(); 329 new Set<FunctionEntity>();
330
331 final ElementEnvironment _elementEnvironment;
332
333 final CommonElements _commonElements;
334
335 final NativeBasicData _nativeBasicData;
330 336
331 final SelectorConstraintsStrategy selectorConstraintsStrategy; 337 final SelectorConstraintsStrategy selectorConstraintsStrategy;
332 338
333 bool hasRuntimeTypeSupport = false; 339 bool hasRuntimeTypeSupport = false;
334 bool hasIsolateSupport = false; 340 bool hasIsolateSupport = false;
335 bool hasFunctionApplySupport = false; 341 bool hasFunctionApplySupport = false;
336 342
337 /// Used for testing the new more precise computation of instantiated types
338 /// and classes.
339 static bool useInstantiationMap = false;
340
341 final JavaScriptBackend _backend;
342 final Resolution _resolution;
343 bool _closed = false; 343 bool _closed = false;
344 ClosedWorld _closedWorldCache; 344 ClosedWorld _closedWorldCache;
345 FunctionSetBuilder _allFunctions; 345 FunctionSetBuilder _allFunctions;
346 346
347 final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>(); 347 final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>();
348 348
349 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = 349 final Map<ClassEntity, Set<ClassEntity>> _mixinUses =
350 new Map<ClassElement, Set<MixinApplicationElement>>(); 350 new Map<ClassEntity, Set<ClassEntity>>();
351 351
352 // We keep track of subtype and subclass relationships in four 352 // We keep track of subtype and subclass relationships in four
353 // distinct sets to make class hierarchy analysis faster. 353 // distinct sets to make class hierarchy analysis faster.
354 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = 354 final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes =
355 <ClassElement, ClassHierarchyNode>{}; 355 <ClassEntity, ClassHierarchyNode>{};
356 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{}; 356 final Map<ClassEntity, ClassSet> _classSets = <ClassEntity, ClassSet>{};
357 357
358 final Set<ConstantValue> _constantValues = new Set<ConstantValue>(); 358 final Set<ConstantValue> _constantValues = new Set<ConstantValue>();
359 359
360 bool get isClosed => _closed; 360 bool get isClosed => _closed;
361 361
362 ElementResolutionWorldBuilder( 362 ResolutionWorldBuilderBase(this._elementEnvironment, this._commonElements,
363 this._backend, this._resolution, this.selectorConstraintsStrategy) { 363 this._nativeBasicData, this.selectorConstraintsStrategy) {
364 _allFunctions = new FunctionSetBuilder(); 364 _allFunctions = new FunctionSetBuilder();
365 } 365 }
366 366
367 Iterable<ClassElement> get processedClasses => _processedClasses.keys 367 Iterable<ClassEntity> get processedClasses => _processedClasses.keys
368 .where((cls) => _processedClasses[cls].isInstantiated); 368 .where((cls) => _processedClasses[cls].isInstantiated);
369 369
370 CommonElements get commonElements => _resolution.commonElements;
371
372 ClosedWorld get closedWorldForTesting { 370 ClosedWorld get closedWorldForTesting {
373 if (!_closed) { 371 if (!_closed) {
374 throw new SpannableAssertionFailure( 372 throw new SpannableAssertionFailure(
375 NO_LOCATION_SPANNABLE, "The world builder has not yet been closed."); 373 NO_LOCATION_SPANNABLE, "The world builder has not yet been closed.");
376 } 374 }
377 return _closedWorldCache; 375 return _closedWorldCache;
378 } 376 }
379 377
380 /// All directly instantiated classes, that is, classes with a generative 378 /// All directly instantiated classes, that is, classes with a generative
381 /// constructor that has been called directly and not only through a 379 /// constructor that has been called directly and not only through a
382 /// super-call. 380 /// super-call.
383 // TODO(johnniwinther): Improve semantic precision. 381 // TODO(johnniwinther): Improve semantic precision.
384 Iterable<ClassElement> get directlyInstantiatedClasses { 382 Iterable<ClassEntity> get directlyInstantiatedClasses {
385 Set<ClassElement> classes = new Set<ClassElement>(); 383 Set<ClassEntity> classes = new Set<ClassEntity>();
386 getInstantiationMap().forEach((ClassElement cls, InstantiationInfo info) { 384 getInstantiationMap().forEach((ClassEntity cls, InstantiationInfo info) {
387 if (info.hasInstantiation) { 385 if (info.hasInstantiation) {
388 classes.add(cls); 386 classes.add(cls);
389 } 387 }
390 }); 388 });
391 return classes; 389 return classes;
392 } 390 }
393 391
394 /// All directly instantiated types, that is, the types of the directly 392 /// All directly instantiated types, that is, the types of the directly
395 /// instantiated classes. 393 /// instantiated classes.
396 /// 394 ///
397 /// See [directlyInstantiatedClasses]. 395 /// See [directlyInstantiatedClasses].
398 // TODO(johnniwinther): Improve semantic precision. 396 // TODO(johnniwinther): Improve semantic precision.
399 Iterable<InterfaceType> get instantiatedTypes { 397 Iterable<InterfaceType> get instantiatedTypes {
400 Set<ResolutionInterfaceType> types = new Set<ResolutionInterfaceType>(); 398 Set<InterfaceType> types = new Set<InterfaceType>();
401 getInstantiationMap().forEach((_, InstantiationInfo info) { 399 getInstantiationMap().forEach((_, InstantiationInfo info) {
402 if (info.instantiationMap != null) { 400 if (info.instantiationMap != null) {
403 for (Set<Instance> instances in info.instantiationMap.values) { 401 for (Set<Instance> instances in info.instantiationMap.values) {
404 for (Instance instance in instances) { 402 for (Instance instance in instances) {
405 types.add(instance.type); 403 types.add(instance.type);
406 } 404 }
407 } 405 }
408 } 406 }
409 }); 407 });
410 return types; 408 return types;
411 } 409 }
412 410
413 /// Returns `true` if [cls] is considered to be implemented by an 411 bool isImplemented(ClassEntity cls) {
414 /// instantiated class, either directly, through subclasses or through 412 return _implementedClasses.contains(cls);
415 /// subtypes. The latter case only contains spurious information from
416 /// instantiations through factory constructors and mixins.
417 // TODO(johnniwinther): Improve semantic precision.
418 bool isImplemented(ClassElement cls) {
419 return _implementedClasses.contains(cls.declaration);
420 } 413 }
421 414
422 void registerClosurizedMember(MemberElement element) { 415 void registerClosurizedMember(FunctionEntity element) {
423 closurizedMembers.add(element); 416 closurizedMembers.add(element);
424 if (element.type.containsTypeVariables) { 417 FunctionType type = _elementEnvironment.getFunctionType(element);
418 if (type.containsTypeVariables) {
425 closurizedMembersWithFreeTypeVariables.add(element); 419 closurizedMembersWithFreeTypeVariables.add(element);
426 } 420 }
427 } 421 }
428 422
429 /// Register [type] as (directly) instantiated. 423 /// Register [type] as (directly) instantiated.
430 /// 424 ///
431 /// If [byMirrors] is `true`, the instantiation is through mirrors. 425 /// If [byMirrors] is `true`, the instantiation is through mirrors.
432 // TODO(johnniwinther): Fully enforce the separation between exact, through 426 // TODO(johnniwinther): Fully enforce the separation between exact, through
433 // subclass and through subtype instantiated types/classes. 427 // subclass and through subtype instantiated types/classes.
434 // TODO(johnniwinther): Support unknown type arguments for generic types. 428 // TODO(johnniwinther): Support unknown type arguments for generic types.
435 void registerTypeInstantiation( 429 void registerTypeInstantiation(
436 ResolutionInterfaceType type, ClassUsedCallback classUsed, 430 InterfaceType type, ClassUsedCallback classUsed,
437 {ConstructorElement constructor, 431 {ConstructorEntity constructor,
438 bool byMirrors: false, 432 bool byMirrors: false,
439 bool isRedirection: false}) { 433 bool isRedirection: false}) {
440 ClassElement cls = type.element; 434 ClassEntity cls = type.element;
441 cls.ensureResolved(_resolution);
442 InstantiationInfo info = 435 InstantiationInfo info =
443 _instantiationInfo.putIfAbsent(cls, () => new InstantiationInfo()); 436 _instantiationInfo.putIfAbsent(cls, () => new InstantiationInfo());
444 Instantiation kind = Instantiation.UNINSTANTIATED; 437 Instantiation kind = Instantiation.UNINSTANTIATED;
445 bool isNative = _backend.nativeBasicData.isNativeClass(cls); 438 bool isNative = _nativeBasicData.isNativeClass(cls);
446 if (!cls.isAbstract || 439 if (!cls.isAbstract ||
447 // We can't use the closed-world assumption with native abstract 440 // We can't use the closed-world assumption with native abstract
448 // classes; a native abstract class may have non-abstract subclasses 441 // classes; a native abstract class may have non-abstract subclasses
449 // not declared to the program. Instances of these classes are 442 // not declared to the program. Instances of these classes are
450 // indistinguishable from the abstract class. 443 // indistinguishable from the abstract class.
451 isNative || 444 isNative ||
452 // Likewise, if this registration comes from the mirror system, 445 // Likewise, if this registration comes from the mirror system,
453 // all bets are off. 446 // all bets are off.
454 // TODO(herhut): Track classes required by mirrors seperately. 447 // TODO(herhut): Track classes required by mirrors seperately.
455 byMirrors) { 448 byMirrors) {
456 if (isNative || byMirrors) { 449 if (isNative || byMirrors) {
457 kind = Instantiation.ABSTRACTLY_INSTANTIATED; 450 kind = Instantiation.ABSTRACTLY_INSTANTIATED;
458 } else { 451 } else {
459 kind = Instantiation.DIRECTLY_INSTANTIATED; 452 kind = Instantiation.DIRECTLY_INSTANTIATED;
460 } 453 }
461 _processInstantiatedClass(cls, classUsed); 454 _processInstantiatedClass(cls, classUsed);
462 } 455 }
463 info.addInstantiation(constructor, type, kind, 456 info.addInstantiation(constructor, type, kind,
464 isRedirection: isRedirection); 457 isRedirection: isRedirection);
465 458
466 // TODO(johnniwinther): Use [_instantiationInfo] to compute this information 459 // TODO(johnniwinther): Use [_instantiationInfo] to compute this information
467 // instead. 460 // instead.
468 if (_implementedClasses.add(cls)) { 461 if (_implementedClasses.add(cls)) {
469 classUsed(cls, _getClassUsage(cls).implement()); 462 classUsed(cls, _getClassUsage(cls).implement());
470 cls.allSupertypes.forEach((ResolutionInterfaceType supertype) { 463 _elementEnvironment.forEachSupertype(cls, (InterfaceType supertype) {
471 if (_implementedClasses.add(supertype.element)) { 464 if (_implementedClasses.add(supertype.element)) {
472 classUsed( 465 classUsed(
473 supertype.element, _getClassUsage(supertype.element).implement()); 466 supertype.element, _getClassUsage(supertype.element).implement());
474 } 467 }
475 }); 468 });
476 } 469 }
477 } 470 }
478 471
479 @override 472 @override
480 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { 473 void forEachInstantiatedClass(f(ClassEntity cls, InstantiationInfo info)) {
481 getInstantiationMap().forEach(f); 474 getInstantiationMap().forEach(f);
482 } 475 }
483 476
484 bool _hasMatchingSelector( 477 bool _hasMatchingSelector(
485 Map<Selector, SelectorConstraints> selectors, Element member) { 478 Map<Selector, SelectorConstraints> selectors, MemberEntity member) {
486 if (selectors == null) return false; 479 if (selectors == null) return false;
487 for (Selector selector in selectors.keys) { 480 for (Selector selector in selectors.keys) {
488 if (selector.appliesUnnamed(member)) { 481 if (selector.appliesUnnamed(member)) {
489 SelectorConstraints masks = selectors[selector]; 482 SelectorConstraints masks = selectors[selector];
490 if (masks.applies(member, selector, this)) { 483 if (masks.applies(member, selector, this)) {
491 return true; 484 return true;
492 } 485 }
493 } 486 }
494 } 487 }
495 return false; 488 return false;
496 } 489 }
497 490
498 /// Returns the instantiation map used for computing the closed world. 491 /// Returns the instantiation map used for computing the closed world.
499 /// 492 Map<ClassEntity, InstantiationInfo> getInstantiationMap() {
500 /// If [useInstantiationMap] is `true`, redirections are removed and 493 return _instantiationInfo;
501 /// redirecting factories are converted to their effective target and type.
502 Map<ClassElement, InstantiationInfo> getInstantiationMap() {
503 if (!useInstantiationMap) return _instantiationInfo;
504
505 Map<ClassElement, InstantiationInfo> instantiationMap =
506 <ClassElement, InstantiationInfo>{};
507
508 InstantiationInfo infoFor(ClassElement cls) {
509 return instantiationMap.putIfAbsent(cls, () => new InstantiationInfo());
510 }
511
512 _instantiationInfo.forEach((cls, info) {
513 if (info.instantiationMap != null) {
514 info.instantiationMap
515 .forEach((ConstructorElement constructor, Set<Instance> set) {
516 for (Instance instance in set) {
517 if (instance.isRedirection) {
518 continue;
519 }
520 if (constructor == null || !constructor.isRedirectingFactory) {
521 infoFor(cls)
522 .addInstantiation(constructor, instance.type, instance.kind);
523 } else {
524 ConstructorElement target = constructor.effectiveTarget;
525 ResolutionInterfaceType targetType =
526 constructor.computeEffectiveTargetType(instance.type);
527 Instantiation kind = Instantiation.DIRECTLY_INSTANTIATED;
528 if (target.enclosingClass.isAbstract) {
529 // If target is a factory constructor on an abstract class.
530 kind = Instantiation.UNINSTANTIATED;
531 }
532 infoFor(targetType.element)
533 .addInstantiation(target, targetType, kind);
534 }
535 }
536 });
537 }
538 });
539 return instantiationMap;
540 } 494 }
541 495
542 bool _hasInvocation(Element member) { 496 bool _hasInvocation(MemberEntity member) {
543 return _hasMatchingSelector(_invokedNames[member.name], member); 497 return _hasMatchingSelector(_invokedNames[member.name], member);
544 } 498 }
545 499
546 bool _hasInvokedGetter(Element member) { 500 bool _hasInvokedGetter(MemberEntity member) {
547 return _hasMatchingSelector(_invokedGetters[member.name], member) || 501 return _hasMatchingSelector(_invokedGetters[member.name], member) ||
548 member.isFunction && methodsNeedingSuperGetter.contains(member); 502 member.isFunction && methodsNeedingSuperGetter.contains(member);
549 } 503 }
550 504
551 bool hasInvokedSetter(Element member) { 505 bool hasInvokedSetter(MemberEntity member) {
552 return _hasMatchingSelector(_invokedSetters[member.name], member); 506 return _hasMatchingSelector(_invokedSetters[member.name], member);
553 } 507 }
554 508
555 void registerDynamicUse( 509 void registerDynamicUse(
556 DynamicUse dynamicUse, MemberUsedCallback memberUsed) { 510 DynamicUse dynamicUse, MemberUsedCallback memberUsed) {
557 Selector selector = dynamicUse.selector; 511 Selector selector = dynamicUse.selector;
558 String methodName = selector.name; 512 String methodName = selector.name;
559 513
560 void _process(Map<String, Set<_MemberUsage>> memberMap, 514 void _process(Map<String, Set<_MemberUsage>> memberMap,
561 EnumSet<MemberUse> action(_MemberUsage usage)) { 515 EnumSet<MemberUse> action(_MemberUsage usage)) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 ReceiverConstraint mask = dynamicUse.mask; 549 ReceiverConstraint mask = dynamicUse.mask;
596 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent( 550 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent(
597 name, () => new Maplet<Selector, SelectorConstraints>()); 551 name, () => new Maplet<Selector, SelectorConstraints>());
598 UniverseSelectorConstraints constraints = 552 UniverseSelectorConstraints constraints =
599 selectors.putIfAbsent(selector, () { 553 selectors.putIfAbsent(selector, () {
600 return selectorConstraintsStrategy.createSelectorConstraints(selector); 554 return selectorConstraintsStrategy.createSelectorConstraints(selector);
601 }); 555 });
602 return constraints.addReceiverConstraint(mask); 556 return constraints.addReceiverConstraint(mask);
603 } 557 }
604 558
605 void registerIsCheck(ResolutionDartType type) { 559 void registerIsCheck(DartType type) {
606 type.computeUnaliased(_resolution);
607 type = type.unaliased;
608 // Even in checked mode, type annotations for return type and argument
609 // types do not imply type checks, so there should never be a check
610 // against the type variable of a typedef.
611 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
612 isChecks.add(type); 560 isChecks.add(type);
613 } 561 }
614 562
615 bool registerConstantUse(ConstantUse use) { 563 bool registerConstantUse(ConstantUse use) {
616 return _constantValues.add(use.value); 564 return _constantValues.add(use.value);
617 } 565 }
618 566
619 void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) { 567 void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
620 Element element = staticUse.element; 568 MemberEntity element = staticUse.element;
621 assert(invariant(element, element.isDeclaration,
622 message: "Element ${element} is not the declaration."));
623 _StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () { 569 _StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () {
624 if ((element.isStatic || element.isTopLevel) && element.isFunction) { 570 if ((element.isStatic || element.isTopLevel) && element.isFunction) {
625 return new _StaticFunctionUsage(element); 571 return new _StaticFunctionUsage(element);
626 } else { 572 } else {
627 return new _GeneralStaticMemberUsage(element); 573 return new _GeneralStaticMemberUsage(element);
628 } 574 }
629 }); 575 });
630 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); 576 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
631 577
632 if (Elements.isStaticOrTopLevel(element) && element.isField) { 578 if ((element.isStatic || element.isTopLevel) && element.isField) {
633 allReferencedStaticFields.add(element); 579 allReferencedStaticFields.add(staticUse.element);
634 } 580 }
635 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and 581 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
636 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. 582 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
637 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot 583 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot
638 // enqueue. 584 // enqueue.
639 switch (staticUse.kind) { 585 switch (staticUse.kind) {
640 case StaticUseKind.FIELD_GET: 586 case StaticUseKind.FIELD_GET:
641 break; 587 break;
642 case StaticUseKind.FIELD_SET: 588 case StaticUseKind.FIELD_SET:
643 fieldSetters.add(element); 589 fieldSetters.add(staticUse.element);
644 break; 590 break;
645 case StaticUseKind.CLOSURE: 591 case StaticUseKind.CLOSURE:
646 LocalFunctionElement localFunction = staticUse.element; 592 throw new UnimplementedError(
647 if (localFunction.type.containsTypeVariables) { 593 "registerStaticUse not implemented for StaticUseKind.CLOSURE.");
648 localFunctionsWithFreeTypeVariables.add(localFunction);
649 }
650 localFunctions.add(element);
651 break;
652 case StaticUseKind.SUPER_TEAR_OFF: 594 case StaticUseKind.SUPER_TEAR_OFF:
653 useSet.addAll(usage.tearOff()); 595 useSet.addAll(usage.tearOff());
654 methodsNeedingSuperGetter.add(element); 596 methodsNeedingSuperGetter.add(staticUse.element);
655 break; 597 break;
656 case StaticUseKind.SUPER_FIELD_SET: 598 case StaticUseKind.SUPER_FIELD_SET:
657 fieldSetters.add(element); 599 fieldSetters.add(staticUse.element);
658 useSet.addAll(usage.normalUse()); 600 useSet.addAll(usage.normalUse());
659 break; 601 break;
660 case StaticUseKind.STATIC_TEAR_OFF: 602 case StaticUseKind.STATIC_TEAR_OFF:
661 useSet.addAll(usage.tearOff()); 603 useSet.addAll(usage.tearOff());
662 break; 604 break;
663 case StaticUseKind.GENERAL: 605 case StaticUseKind.GENERAL:
664 case StaticUseKind.DIRECT_USE: 606 case StaticUseKind.DIRECT_USE:
665 case StaticUseKind.CONSTRUCTOR_INVOKE: 607 case StaticUseKind.CONSTRUCTOR_INVOKE:
666 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: 608 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
667 case StaticUseKind.REDIRECTION: 609 case StaticUseKind.REDIRECTION:
668 useSet.addAll(usage.normalUse()); 610 useSet.addAll(usage.normalUse());
669 break; 611 break;
670 case StaticUseKind.DIRECT_INVOKE: 612 case StaticUseKind.DIRECT_INVOKE:
671 invariant( 613 invariant(
672 element, 'Direct static use is not supported for resolution.'); 614 element, 'Direct static use is not supported for resolution.');
673 break; 615 break;
674 case StaticUseKind.INLINING: 616 case StaticUseKind.INLINING:
675 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, 617 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
676 "Static use ${staticUse.kind} is not supported during resolution."); 618 "Static use ${staticUse.kind} is not supported during resolution.");
677 } 619 }
678 if (useSet.isNotEmpty) { 620 if (useSet.isNotEmpty) {
679 memberUsed(usage.entity, useSet); 621 memberUsed(usage.entity, useSet);
680 } 622 }
681 } 623 }
682 624
625 /// Called to create a [_ClassUsage] for [cls].
626 ///
627 /// Subclasses override this to ensure needed invariants on [cls].
628 _ClassUsage _createClassUsage(ClassEntity cls) => new _ClassUsage(cls);
629
683 /// Return the canonical [_ClassUsage] for [cls]. 630 /// Return the canonical [_ClassUsage] for [cls].
684 _ClassUsage _getClassUsage(ClassElement cls) { 631 _ClassUsage _getClassUsage(ClassEntity cls) {
685 return _processedClasses.putIfAbsent(cls, () { 632 return _processedClasses.putIfAbsent(cls, () {
686 cls.ensureResolved(_resolution); 633 return _createClassUsage(cls);
687 _ClassUsage usage = new _ClassUsage(cls);
688 _resolution.ensureClassMembers(cls);
689 return usage;
690 }); 634 });
691 } 635 }
692 636
693 /// Register [cls] and all its superclasses as instantiated. 637 /// Register [cls] and all its superclasses as instantiated.
694 void _processInstantiatedClass( 638 void _processInstantiatedClass(ClassEntity cls, ClassUsedCallback classUsed) {
695 ClassElement cls, ClassUsedCallback classUsed) {
696 // Registers [superclass] as instantiated. Returns `true` if it wasn't 639 // Registers [superclass] as instantiated. Returns `true` if it wasn't
697 // already instantiated and we therefore have to process its superclass as 640 // already instantiated and we therefore have to process its superclass as
698 // well. 641 // well.
699 bool processClass(ClassElement superclass) { 642 bool processClass(ClassEntity superclass) {
700 _ClassUsage usage = _getClassUsage(superclass); 643 _ClassUsage usage = _getClassUsage(superclass);
701 if (!usage.isInstantiated) { 644 if (!usage.isInstantiated) {
702 classUsed(usage.cls, usage.instantiate()); 645 classUsed(usage.cls, usage.instantiate());
703 return true; 646 return true;
704 } 647 }
705 return false; 648 return false;
706 } 649 }
707 650
708 while (cls != null && processClass(cls)) { 651 while (cls != null && processClass(cls)) {
709 cls = cls.superclass; 652 cls = _elementEnvironment.getSuperClass(cls);
710 } 653 }
711 } 654 }
712 655
713 /// Computes usage for all members declared by [cls]. Calls [membersUsed] with 656 /// Computes usage for all members declared by [cls]. Calls [membersUsed] with
714 /// the usage changes for each member. 657 /// the usage changes for each member.
715 void processClassMembers(ClassElement cls, MemberUsedCallback memberUsed) { 658 void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed) {
716 cls.implementation.forEachMember((ClassElement cls, MemberElement member) { 659 _elementEnvironment.forEachClassMember(cls,
660 (ClassEntity cls, MemberEntity member) {
717 _processInstantiatedClassMember(cls, member, memberUsed); 661 _processInstantiatedClassMember(cls, member, memberUsed);
718 }); 662 });
719 } 663 }
720 664
721 /// Call [updateUsage] on all [_MemberUsage]s in the set in [map] for 665 /// Call [updateUsage] on all [_MemberUsage]s in the set in [map] for
722 /// [memberName]. If [updateUsage] returns `true` the usage is removed from 666 /// [memberName]. If [updateUsage] returns `true` the usage is removed from
723 /// the set. 667 /// the set.
724 void _processSet(Map<String, Set<_MemberUsage>> map, String memberName, 668 void _processSet(Map<String, Set<_MemberUsage>> map, String memberName,
725 bool updateUsage(_MemberUsage e)) { 669 bool updateUsage(_MemberUsage e)) {
726 Set<_MemberUsage> members = map[memberName]; 670 Set<_MemberUsage> members = map[memberName];
727 if (members == null) return; 671 if (members == null) return;
728 // [f] might add elements to [: map[memberName] :] during the loop below 672 // [f] might add elements to [: map[memberName] :] during the loop below
729 // so we create a new list for [: map[memberName] :] and prepend the 673 // so we create a new list for [: map[memberName] :] and prepend the
730 // [remaining] members after the loop. 674 // [remaining] members after the loop.
731 map[memberName] = new Set<_MemberUsage>(); 675 map[memberName] = new Set<_MemberUsage>();
732 Set<_MemberUsage> remaining = new Set<_MemberUsage>(); 676 Set<_MemberUsage> remaining = new Set<_MemberUsage>();
733 for (_MemberUsage usage in members) { 677 for (_MemberUsage usage in members) {
734 if (!updateUsage(usage)) remaining.add(usage); 678 if (!updateUsage(usage)) remaining.add(usage);
735 } 679 }
736 map[memberName].addAll(remaining); 680 map[memberName].addAll(remaining);
737 } 681 }
738 682
739 void _processInstantiatedClassMember( 683 void _processInstantiatedClassMember(
740 ClassElement cls, MemberElement member, MemberUsedCallback memberUsed) { 684 ClassEntity cls, MemberEntity member, MemberUsedCallback memberUsed) {
741 assert(invariant(member, member.isDeclaration));
742 if (!member.isInstanceMember) return; 685 if (!member.isInstanceMember) return;
743 String memberName = member.name; 686 String memberName = member.name;
744 member.computeType(_resolution);
745 // The obvious thing to test here would be "member.isNative", 687 // The obvious thing to test here would be "member.isNative",
746 // however, that only works after metadata has been parsed/analyzed, 688 // however, that only works after metadata has been parsed/analyzed,
747 // and that may not have happened yet. 689 // and that may not have happened yet.
748 // So instead we use the enclosing class, which we know have had 690 // So instead we use the enclosing class, which we know have had
749 // its metadata parsed and analyzed. 691 // its metadata parsed and analyzed.
750 // Note: this assumes that there are no non-native fields on native 692 // Note: this assumes that there are no non-native fields on native
751 // classes, which may not be the case when a native class is subclassed. 693 // classes, which may not be the case when a native class is subclassed.
752 _instanceMemberUsage.putIfAbsent(member, () { 694 _instanceMemberUsage.putIfAbsent(member, () {
753 bool isNative = _backend.nativeBasicData.isNativeClass(cls); 695 bool isNative = _nativeBasicData.isNativeClass(cls);
754 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); 696 _MemberUsage usage = new _MemberUsage(member, isNative: isNative);
755 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); 697 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
756 useSet.addAll(usage.appliedUse); 698 useSet.addAll(usage.appliedUse);
757 if (member.isField && isNative) { 699 if (member.isField && isNative) {
758 registerUsedElement(member); 700 registerUsedElement(member);
759 } 701 }
760 if (member.isFunction && 702 if (member.isFunction &&
761 member.name == Identifiers.call && 703 member.name == Identifiers.call &&
762 !cls.typeVariables.isEmpty) { 704 _elementEnvironment.getThisType(cls).typeArguments.isNotEmpty) {
763 closurizedMembersWithFreeTypeVariables.add(member); 705 closurizedMembersWithFreeTypeVariables.add(member);
764 } 706 }
765 707
766 if (_hasInvokedGetter(member)) { 708 if (_hasInvokedGetter(member)) {
767 useSet.addAll(usage.read()); 709 useSet.addAll(usage.read());
768 } 710 }
769 if (_hasInvocation(member)) { 711 if (_hasInvocation(member)) {
770 useSet.addAll(usage.invoke()); 712 useSet.addAll(usage.invoke());
771 } 713 }
772 if (hasInvokedSetter(member)) { 714 if (hasInvokedSetter(member)) {
(...skipping 14 matching lines...) Expand all
787 .putIfAbsent(memberName, () => new Set<_MemberUsage>()) 729 .putIfAbsent(memberName, () => new Set<_MemberUsage>())
788 .add(usage); 730 .add(usage);
789 } 731 }
790 732
791 memberUsed(usage.entity, useSet); 733 memberUsed(usage.entity, useSet);
792 return usage; 734 return usage;
793 }); 735 });
794 } 736 }
795 737
796 /// Returns an iterable over all mixin applications that mixin [cls]. 738 /// Returns an iterable over all mixin applications that mixin [cls].
797 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls) { 739 Iterable<ClassEntity> allMixinUsesOf(ClassEntity cls) {
798 Iterable<MixinApplicationElement> uses = _mixinUses[cls]; 740 Iterable<ClassEntity> uses = _mixinUses[cls];
799 return uses != null ? uses : const <MixinApplicationElement>[]; 741 return uses != null ? uses : const <ClassEntity>[];
800 }
801
802 /// Called to add [cls] to the set of known classes.
803 ///
804 /// This ensures that class hierarchy queries can be performed on [cls] and
805 /// classes that extend or implement it.
806 void registerClass(ClassElement cls) => _registerClass(cls);
807
808 void _registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) {
809 _ensureClassSet(cls);
810 if (isDirectlyInstantiated) {
811 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
812 }
813 } 742 }
814 743
815 void registerTypedef(TypedefElement typdef) { 744 void registerTypedef(TypedefElement typdef) {
816 _allTypedefs.add(typdef); 745 _allTypedefs.add(typdef);
817 } 746 }
818 747
819 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { 748 void registerMixinUse(ClassEntity mixinApplication, ClassEntity mixin) {
820 cls = cls.declaration;
821 return _classHierarchyNodes.putIfAbsent(cls, () {
822 ClassHierarchyNode parentNode;
823 if (cls.superclass != null) {
824 parentNode = _ensureClassHierarchyNode(cls.superclass);
825 }
826 return new ClassHierarchyNode(parentNode, cls);
827 });
828 }
829
830 ClassSet _ensureClassSet(ClassElement cls) {
831 cls = cls.declaration;
832 return _classSets.putIfAbsent(cls, () {
833 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
834 ClassSet classSet = new ClassSet(node);
835
836 for (ResolutionInterfaceType type in cls.allSupertypes) {
837 // TODO(johnniwinther): Optimization: Avoid adding [cls] to
838 // superclasses.
839 ClassSet subtypeSet = _ensureClassSet(type.element);
840 subtypeSet.addSubtype(node);
841 }
842 if (cls.isMixinApplication) {
843 // TODO(johnniwinther): Store this in the [ClassSet].
844 MixinApplicationElement mixinApplication = cls;
845 if (mixinApplication.mixin != null) {
846 // If [mixinApplication] is malformed [mixin] is `null`.
847 registerMixinUse(mixinApplication, mixinApplication.mixin);
848 }
849 }
850
851 return classSet;
852 });
853 }
854
855 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) {
856 // Ensure that classes implicitly implementing `Function` are in its
857 // subtype set.
858 ClassElement cls = node.cls;
859 if (cls != commonElements.functionClass &&
860 cls.implementsFunction(commonElements)) {
861 ClassSet subtypeSet = _ensureClassSet(commonElements.functionClass);
862 subtypeSet.addSubtype(node);
863 }
864 if (!node.isInstantiated && node.parentNode != null) {
865 _updateSuperClassHierarchyNodeForClass(node.parentNode);
866 }
867 }
868
869 void _updateClassHierarchyNodeForClass(ClassElement cls,
870 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) {
871 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
872 _updateSuperClassHierarchyNodeForClass(node);
873 if (directlyInstantiated) {
874 node.isDirectlyInstantiated = true;
875 }
876 if (abstractlyInstantiated) {
877 node.isAbstractlyInstantiated = true;
878 }
879 }
880
881 ClosedWorld closeWorld(DiagnosticReporter reporter) {
882 Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses =
883 new Map<ClassElement, Set<ClassElement>>();
884
885 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
886 /// properties of the [ClassHierarchyNode] for [cls].
887
888 void addSubtypes(ClassElement cls, InstantiationInfo info) {
889 if (!info.hasInstantiation) {
890 return;
891 }
892 assert(cls.isDeclaration);
893 if (!cls.isResolved) {
894 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.');
895 }
896
897 _updateClassHierarchyNodeForClass(cls,
898 directlyInstantiated: info.isDirectlyInstantiated,
899 abstractlyInstantiated: info.isAbstractlyInstantiated);
900
901 // Walk through the superclasses, and record the types
902 // implemented by that type on the superclasses.
903 ClassElement superclass = cls.superclass;
904 while (superclass != null) {
905 Set<Element> typesImplementedBySubclassesOfCls =
906 typesImplementedBySubclasses.putIfAbsent(
907 superclass, () => new Set<ClassElement>());
908 for (ResolutionDartType current in cls.allSupertypes) {
909 typesImplementedBySubclassesOfCls.add(current.element);
910 }
911 superclass = superclass.superclass;
912 }
913 }
914
915 // Use the [:seenClasses:] set to include non-instantiated
916 // classes: if the superclass of these classes require RTI, then
917 // they also need RTI, so that a constructor passes the type
918 // variables to the super constructor.
919 forEachInstantiatedClass(addSubtypes);
920
921 _closed = true;
922 return _closedWorldCache = new ClosedWorldImpl(
923 backend: _backend,
924 commonElements: commonElements,
925 resolutionWorldBuilder: this,
926 functionSetBuilder: _allFunctions,
927 allTypedefs: _allTypedefs,
928 mixinUses: _mixinUses,
929 typesImplementedBySubclasses: typesImplementedBySubclasses,
930 classHierarchyNodes: _classHierarchyNodes,
931 classSets: _classSets);
932 }
933
934 void registerMixinUse(
935 MixinApplicationElement mixinApplication, ClassElement mixin) {
936 // TODO(johnniwinther): Add map restricted to live classes. 749 // TODO(johnniwinther): Add map restricted to live classes.
937 // We don't support patch classes as mixin. 750 // We don't support patch classes as mixin.
938 assert(mixin.isDeclaration); 751 Set<ClassEntity> users =
939 Set<MixinApplicationElement> users = 752 _mixinUses.putIfAbsent(mixin, () => new Set<ClassEntity>());
940 _mixinUses.putIfAbsent(mixin, () => new Set<MixinApplicationElement>());
941 users.add(mixinApplication); 753 users.add(mixinApplication);
942 } 754 }
943 755
944 void registerUsedElement(MemberElement element) {
945 if (element.isInstanceMember && !element.isAbstract) {
946 _allFunctions.add(element);
947 }
948 }
949
950 ClosedWorld get closedWorldCache { 756 ClosedWorld get closedWorldCache {
951 assert(isClosed); 757 assert(isClosed);
952 return _closedWorldCache; 758 return _closedWorldCache;
953 } 759 }
954 760
955 @override 761 @override
956 bool isMemberUsed(MemberEntity member) { 762 bool isMemberUsed(MemberEntity member) {
957 if (member.isInstanceMember) { 763 if (member.isInstanceMember) {
958 _MemberUsage usage = _instanceMemberUsage[member]; 764 _MemberUsage usage = _instanceMemberUsage[member];
959 if (usage != null && usage.hasUse) return true; 765 if (usage != null && usage.hasUse) return true;
960 } 766 }
961 _StaticMemberUsage usage = _staticMemberUsage[member]; 767 _StaticMemberUsage usage = _staticMemberUsage[member];
962 return usage != null && usage.hasUse; 768 return usage != null && usage.hasUse;
963 } 769 }
964 } 770 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/universe/element_world_builder.dart ('k') | pkg/compiler/lib/src/universe/world_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698