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

Side by Side Diff: pkg/compiler/lib/src/world.dart

Issue 1304083008: Add ClassSet to support ClassWorld.strictSubtypesOf (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years, 3 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
« no previous file with comments | « pkg/compiler/lib/src/use_unused_api.dart ('k') | tests/compiler/dart2js/class_set_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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.world; 5 library dart2js.world;
6 6
7 import 'closure.dart' show 7 import 'closure.dart' show
8 SynthesizedCallMethodElementX; 8 SynthesizedCallMethodElementX;
9 import 'common/backend_api.dart' show 9 import 'common/backend_api.dart' show
10 Backend; 10 Backend;
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 /// Returns `true` if [cls] is instantiated. 178 /// Returns `true` if [cls] is instantiated.
179 bool isInstantiated(ClassElement cls) { 179 bool isInstantiated(ClassElement cls) {
180 return compiler.resolverWorld.isInstantiated(cls); 180 return compiler.resolverWorld.isInstantiated(cls);
181 } 181 }
182 182
183 /// Returns an iterable over the directly instantiated classes that extend 183 /// Returns an iterable over the directly instantiated classes that extend
184 /// [cls] possibly including [cls] itself, if it is live. 184 /// [cls] possibly including [cls] itself, if it is live.
185 Iterable<ClassElement> subclassesOf(ClassElement cls) { 185 Iterable<ClassElement> subclassesOf(ClassElement cls) {
186 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; 186 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
187 if (hierarchy == null) return const <ClassElement>[]; 187 if (hierarchy == null) return const <ClassElement>[];
188 assert(invariant(cls, isInstantiated(cls.declaration), 188 return hierarchy.subclasses(
189 message: 'Class $cls has not been instantiated.')); 189 includeIndirectlyInstantiated: false,
190 return hierarchy.subclasses(); 190 includeUninstantiated: false);
191 } 191 }
192 192
193 /// Returns an iterable over the directly instantiated classes that extend 193 /// Returns an iterable over the directly instantiated classes that extend
194 /// [cls] _not_ including [cls] itself. 194 /// [cls] _not_ including [cls] itself.
195 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { 195 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
196 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 196 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
197 if (subclasses == null) return const <ClassElement>[]; 197 if (subclasses == null) return const <ClassElement>[];
198 assert(invariant(cls, isInstantiated(cls.declaration), 198 return subclasses.subclasses(
199 message: 'Class $cls has not been instantiated.')); 199 strict: true,
200 return subclasses.strictSubclasses(); 200 includeIndirectlyInstantiated: false,
201 includeUninstantiated: false);
201 } 202 }
202 203
203 /// Returns an iterable over the directly instantiated that implement [cls] 204 /// Returns an iterable over the directly instantiated that implement [cls]
204 /// _not_ including [cls]. 205 /// _not_ including [cls].
205 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { 206 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
206 Set<ClassElement> subtypes = _subtypes[cls.declaration]; 207 ClassSet classSet = _classSets[cls.declaration];
207 return subtypes != null ? subtypes : const <ClassElement>[]; 208 if (classSet == null) {
209 return const <ClassElement>[];
210 } else {
211 return classSet.subtypes(
212 strict: true,
213 includeIndirectlyInstantiated: false,
214 includeUninstantiated: false);
215 }
208 } 216 }
209 217
210 /// Returns `true` if any directly instantiated class other than [cls] extends 218 /// Returns `true` if any directly instantiated class other than [cls] extends
211 /// [cls]. 219 /// [cls].
212 bool hasAnyStrictSubclass(ClassElement cls) { 220 bool hasAnyStrictSubclass(ClassElement cls) {
213 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 221 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
214 if (subclasses == null) return false; 222 if (subclasses == null) return false;
215 assert(invariant(cls, isInstantiated(cls.declaration),
216 message: 'Class $cls has not been instantiated.'));
217 return subclasses.isIndirectlyInstantiated; 223 return subclasses.isIndirectlyInstantiated;
218 } 224 }
219 225
220 /// Returns `true` if any directly instantiated class other than [cls] 226 /// Returns `true` if any directly instantiated class other than [cls]
221 /// implements [cls]. 227 /// implements [cls].
222 bool hasAnyStrictSubtype(ClassElement cls) { 228 bool hasAnyStrictSubtype(ClassElement cls) {
223 return !strictSubtypesOf(cls).isEmpty; 229 return !strictSubtypesOf(cls).isEmpty;
224 } 230 }
225 231
226 /// Returns `true` if all directly instantiated classes that implement [cls] 232 /// Returns `true` if all directly instantiated classes that implement [cls]
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 new Map<ClassElement, List<MixinApplicationElement>>(); 337 new Map<ClassElement, List<MixinApplicationElement>>();
332 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; 338 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses;
333 339
334 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = 340 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses =
335 new Map<ClassElement, Set<ClassElement>>(); 341 new Map<ClassElement, Set<ClassElement>>();
336 342
337 // We keep track of subtype and subclass relationships in four 343 // We keep track of subtype and subclass relationships in four
338 // distinct sets to make class hierarchy analysis faster. 344 // distinct sets to make class hierarchy analysis faster.
339 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = 345 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes =
340 <ClassElement, ClassHierarchyNode>{}; 346 <ClassElement, ClassHierarchyNode>{};
341 final Map<ClassElement, Set<ClassElement>> _subtypes = 347 final Map<ClassElement, ClassSet> _classSets =
342 new Map<ClassElement, Set<ClassElement>>(); 348 <ClassElement, ClassSet>{};
343 349
344 final Set<Element> sideEffectsFreeElements = new Set<Element>(); 350 final Set<Element> sideEffectsFreeElements = new Set<Element>();
345 351
346 final Set<Element> elementsThatCannotThrow = new Set<Element>(); 352 final Set<Element> elementsThatCannotThrow = new Set<Element>();
347 353
348 final Set<Element> functionsThatMightBePassedToApply = 354 final Set<Element> functionsThatMightBePassedToApply =
349 new Set<FunctionElement>(); 355 new Set<FunctionElement>();
350 356
351 final Set<Element> alreadyPopulated; 357 final Set<Element> alreadyPopulated;
352 358
(...skipping 11 matching lines...) Expand all
364 370
365 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) { 371 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) {
366 return _typesImplementedBySubclasses[cls.declaration]; 372 return _typesImplementedBySubclasses[cls.declaration];
367 } 373 }
368 374
369 World(Compiler compiler) 375 World(Compiler compiler)
370 : allFunctions = new FunctionSet(compiler), 376 : allFunctions = new FunctionSet(compiler),
371 this.compiler = compiler, 377 this.compiler = compiler,
372 alreadyPopulated = compiler.cacheStrategy.newSet(); 378 alreadyPopulated = compiler.cacheStrategy.newSet();
373 379
374 ClassHierarchyNode classHierarchyNode(ClassElement cls) { 380 /// Called to add [cls] to the set of known classes.
375 return _classHierarchyNodes[cls]; 381 ///
382 /// This ensures that class hierarchy queries can be performed on [cls] and
383 /// classes that extend or implement it.
384 void registerClass(ClassElement cls) {
385 _ensureClassSet(cls);
386 }
387
388 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
389 /// of known classes.
390 ///
391 /// This method is only provided for testing. For queries on classes, use the
392 /// methods defined in [ClassWorld].
393 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) {
394 return _classHierarchyNodes[cls.declaration];
395 }
396
397 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
398 cls = cls.declaration;
399 return _classHierarchyNodes.putIfAbsent(cls, () {
400 ClassHierarchyNode node = new ClassHierarchyNode(cls);
401 if (cls.superclass != null) {
402 _ensureClassHierarchyNode(cls.superclass).addDirectSubclass(node);
403 }
404 return node;
405 });
406 }
407
408 /// Returns [ClassSet] for [cls] used to model the extends and implements
409 /// relations of known classes.
410 ///
411 /// This method is only provided for testing. For queries on classes, use the
412 /// methods defined in [ClassWorld].
413 ClassSet getClassSet(ClassElement cls) {
414 return _classSets[cls.declaration];
415 }
416
417 ClassSet _ensureClassSet(ClassElement cls) {
418 cls = cls.declaration;
419 return _classSets.putIfAbsent(cls, () {
420 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
421 ClassSet classSet = new ClassSet(node);
422
423 for (InterfaceType type in cls.allSupertypes) {
424 // TODO(johnniwinther): Optimization: Avoid adding [cls] to
425 // superclasses.
426 ClassSet subtypeSet = _ensureClassSet(type.element);
427 subtypeSet.addSubtype(node);
428 }
429 return classSet;
430 });
376 } 431 }
377 432
378 void populate() { 433 void populate() {
379 434 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
380 /// Ensure that a [ClassHierarchyNode] exists for [cls]. Updates the 435 /// properties of the [ClassHierarchyNode] for [cls].
381 /// `isDirectlyInstantiated` and `isIndirectlyInstantiated` property of the 436 void updateClassHierarchyNodeForClass(
382 /// node according the provided arguments and returns the node.
383 ClassHierarchyNode createClassHierarchyNodeForClass(
384 ClassElement cls, 437 ClassElement cls,
385 {bool directlyInstantiated: false, 438 {bool directlyInstantiated: false,
386 bool indirectlyInstantiated: false}) { 439 bool indirectlyInstantiated: false}) {
387 assert(isInstantiated(cls)); 440 assert(!directlyInstantiated || isInstantiated(cls));
388 441 ClassHierarchyNode node = getClassHierarchyNode(cls);
389 ClassHierarchyNode node = _classHierarchyNodes.putIfAbsent(cls, () { 442 bool changed = false;
390 ClassHierarchyNode node = new ClassHierarchyNode(cls); 443 if (directlyInstantiated && !node.isDirectlyInstantiated) {
391 if (cls.superclass != null) {
392 createClassHierarchyNodeForClass(cls.superclass,
393 indirectlyInstantiated:
394 directlyInstantiated || indirectlyInstantiated)
395 .addDirectSubclass(node);
396 }
397 return node;
398 });
399 if (directlyInstantiated) {
400 node.isDirectlyInstantiated = true; 444 node.isDirectlyInstantiated = true;
445 changed = true;
401 } 446 }
402 if (indirectlyInstantiated) { 447 if (indirectlyInstantiated && !node.isIndirectlyInstantiated) {
403 node.isIndirectlyInstantiated = true; 448 node.isIndirectlyInstantiated = true;
449 changed = true;
404 } 450 }
405 return node; 451 if (changed && cls.superclass != null) {
452 updateClassHierarchyNodeForClass(
453 cls.superclass, indirectlyInstantiated: true);
454 }
406 } 455 }
407 456
408 void addSubtypes(ClassElement cls) { 457 void addSubtypes(ClassElement cls) {
409 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { 458 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
410 return; 459 return;
411 } 460 }
412 assert(cls.isDeclaration); 461 assert(cls.isDeclaration);
413 if (!cls.isResolved) { 462 if (!cls.isResolved) {
414 compiler.internalError(cls, 'Class "${cls.name}" is not resolved.'); 463 compiler.internalError(cls, 'Class "${cls.name}" is not resolved.');
415 } 464 }
416 465
417 createClassHierarchyNodeForClass(cls, directlyInstantiated: true); 466 updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
418
419 for (DartType type in cls.allSupertypes) {
420 Set<Element> subtypesOfSupertype =
421 _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>());
422 subtypesOfSupertype.add(cls);
423 }
424 467
425 // Walk through the superclasses, and record the types 468 // Walk through the superclasses, and record the types
426 // implemented by that type on the superclasses. 469 // implemented by that type on the superclasses.
427 ClassElement superclass = cls.superclass; 470 ClassElement superclass = cls.superclass;
428 while (superclass != null) { 471 while (superclass != null) {
429 Set<Element> typesImplementedBySubclassesOfCls = 472 Set<Element> typesImplementedBySubclassesOfCls =
430 _typesImplementedBySubclasses.putIfAbsent( 473 _typesImplementedBySubclasses.putIfAbsent(
431 superclass, () => new Set<ClassElement>()); 474 superclass, () => new Set<ClassElement>());
432 for (DartType current in cls.allSupertypes) { 475 for (DartType current in cls.allSupertypes) {
433 typesImplementedBySubclassesOfCls.add(current.element); 476 typesImplementedBySubclassesOfCls.add(current.element);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 // function expressions's element. 626 // function expressions's element.
584 // TODO(herhut): Generate classes for function expressions earlier. 627 // TODO(herhut): Generate classes for function expressions earlier.
585 if (element is SynthesizedCallMethodElementX) { 628 if (element is SynthesizedCallMethodElementX) {
586 return getMightBePassedToApply(element.expression); 629 return getMightBePassedToApply(element.expression);
587 } 630 }
588 return functionsThatMightBePassedToApply.contains(element); 631 return functionsThatMightBePassedToApply.contains(element);
589 } 632 }
590 633
591 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; 634 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport;
592 } 635 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/use_unused_api.dart ('k') | tests/compiler/dart2js/class_set_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698