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

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

Issue 1234053002: Add SubclassNode to prepare for optimized queries on ClassWorld. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years, 5 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/dart2jslib.dart ('k') | pkg/compiler/lib/src/use_unused_api.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, 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 library dart2js.world.class_set;
6
7 import 'dart:collection' show IterableBase;
8 import '../elements/elements.dart' show ClassElement;
9 import '../util/util.dart' show Link;
10
11 /// Node for [cls] in a tree forming the subclass relation of [ClassElement]s.
12 ///
13 /// This is used by the [ClassWorld] to perform queries on subclass and subtype
14 /// relations.
15 // TODO(johnniwinther): Use this for `ClassWorld.subtypesOf`.
16 class ClassHierarchyNode {
17 final ClassElement cls;
18
19 /// `true` if [cls] has been directly instantiated.
20 ///
21 /// For instance `C` but _not_ `B` in:
22 /// class B {}
23 /// class C extends B {}
24 /// main() => new C();
25 ///
26 bool isDirectlyInstantiated = false;
27
28 /// `true` if [cls] has been instantiated through subclasses.
29 ///
30 /// For instance `A` and `B` but _not_ `C` in:
31 /// class A {}
32 /// class B extends A {}
33 /// class C extends B {}
34 /// main() => [new B(), new C()];
35 ///
36 bool isIndirectlyInstantiated = false;
37
38 /// The nodes for the direct subclasses of [cls].
39 Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>();
40
41 ClassHierarchyNode(this.cls);
42
43 /// Adds [subclass] as a direct subclass of [cls].
44 void addDirectSubclass(ClassHierarchyNode subclass) {
45 assert(subclass.cls.superclass == cls);
46 assert(!_directSubclasses.contains(subclass));
47 _directSubclasses = _directSubclasses.prepend(subclass);
48 }
49
50 /// `true` if [cls] has been directly or indirectly instantiated.
51 bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated;
52
53 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
54 /// If [directlyInstantiated] is `true`, the iterable only returns the
55 /// directly instantiated subclasses of [cls].
56 Iterable<ClassElement> subclasses({bool directlyInstantiated: true}) {
57 return new ClassHierarchyNodeIterable(
58 this, directlyInstantiatedOnly: directlyInstantiated);
59 }
60
61 /// Returns an [Iterable] of the strict subclasses of [cls] _not_ including
62 /// [cls] itself. If [directlyInstantiated] is `true`, the iterable only
63 /// returns the directly instantiated subclasses of [cls].
64 Iterable<ClassElement> strictSubclasses(
65 {bool directlyInstantiated: true}) {
66 return new ClassHierarchyNodeIterable(this,
67 includeRoot: false, directlyInstantiatedOnly: directlyInstantiated);
68 }
69
70 String toString() => cls.toString();
71 }
72
73 /// Iterable for subclasses of a [ClassHierarchyNode].
74 class ClassHierarchyNodeIterable extends IterableBase<ClassElement> {
75 final ClassHierarchyNode root;
76 final bool includeRoot;
77 final bool directlyInstantiatedOnly;
78
79 ClassHierarchyNodeIterable(
80 this.root,
81 {this.includeRoot: true,
82 this.directlyInstantiatedOnly: false}) {
83 if (root == null) throw new StateError("No root for iterable.");
84 }
85
86 @override
87 Iterator<ClassElement> get iterator {
88 return new ClassHierarchyNodeIterator(this);
89 }
90 }
91
92 /// Iterator for subclasses of a [ClassHierarchyNode].
93 ///
94 /// Classes are returned in pre-order DFS fashion.
95 class ClassHierarchyNodeIterator implements Iterator<ClassElement> {
96 final ClassHierarchyNodeIterable iterable;
97
98 /// The class node holding the [current] class.
99 ///
100 /// This is `null` before the first call to [moveNext] and at the end of
101 /// iteration, i.e. after [moveNext] has returned `false`.
102 ClassHierarchyNode currentNode;
103
104 /// Stack of pending class nodes.
105 ///
106 /// This is `null` before the first call to [moveNext].
107 Link<ClassHierarchyNode> stack;
108
109 ClassHierarchyNodeIterator(this.iterable);
110
111 ClassHierarchyNode get root => iterable.root;
112
113 bool get includeRoot => iterable.includeRoot;
114
115 bool get directlyInstantiatedOnly => iterable.directlyInstantiatedOnly;
116
117 @override
118 ClassElement get current {
119 return currentNode != null ? currentNode.cls : null;
120 }
121
122 @override
123 bool moveNext() {
124 if (stack == null) {
125 // First call to moveNext
126 stack = const Link<ClassHierarchyNode>().prepend(root);
127 return _findNext();
128 } else {
129 // Initialized state.
130 if (currentNode == null) return false;
131 return _findNext();
132 }
133 }
134
135 /// Find the next class using the [stack].
136 bool _findNext() {
137 while (true) {
138 if (stack.isEmpty) {
139 // No more classes. Set [currentNode] to `null` to signal the end of
140 // iteration.
141 currentNode = null;
142 return false;
143 }
144 currentNode = stack.head;
145 stack = stack.tail;
146 for (Link<ClassHierarchyNode> link = currentNode._directSubclasses;
147 !link.isEmpty;
148 link = link.tail) {
149 stack = stack.prepend(link.head);
150 }
151 if (_isValid(currentNode)) {
152 return true;
153 }
154 }
155 }
156
157 /// Returns `true` if the class of [node] is a valid result for this iterator.
158 bool _isValid(ClassHierarchyNode node) {
159 if (!includeRoot && node == root) return false;
160 if (directlyInstantiatedOnly && !node.isDirectlyInstantiated) return false;
161 return true;
162 }
163 }
164
165
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart2jslib.dart ('k') | pkg/compiler/lib/src/use_unused_api.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698