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

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
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 node for the direct subclasses of [cls].
karlklose 2015/07/21 12:47:21 'node' -> 'nodes'.
Johnni Winther 2015/07/21 14:22:00 Done.
39 Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>();
karlklose 2015/07/21 12:47:21 Is this a performance optimization?
Johnni Winther 2015/07/21 14:22:00 To use Link, yes. May not be worthwhile. Will chan
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 /// The nodes for the direct subclasses of [cls].
51 Link<ClassHierarchyNode> get directSubclasses => _directSubclasses;
52
53 /// `true` if [cls] has any direct subclasses.
54 bool get hasDirectSubclasses => !_directSubclasses.isEmpty;
karlklose 2015/07/21 12:47:21 Are these two getters still used?
Johnni Winther 2015/07/21 14:22:00 No, removing them.
55
56 /// `true` if [cls] has been directly or indirectly instantiated.
57 bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated;
58
59 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
60 /// If [directlyInstantiated] is `true`, the iterable only returns the
61 /// directly instantiated subclasses of [cls].
62 Iterable<ClassElement> subclasses({bool directlyInstantiated: true}) {
63 return new ClassHierarchyNodeIterable(
64 this, directlyInstantiatedOnly: directlyInstantiated);
65 }
66
67 /// Returns an [Iterable] of the strict subclasses of [cls] _not_ including
68 /// [cls] itself. If [directlyInstantiated] is `true`, the iterable only
69 /// returns the directly instantiated subclasses of [cls].
70 Iterable<ClassElement> strictSubclasses(
71 {bool directlyInstantiated: true}) {
72 return new ClassHierarchyNodeIterable(this,
73 includeRoot: false, directlyInstantiatedOnly: directlyInstantiated);
74 }
75
76 String toString() => cls.toString();
77 }
78
79 /// Iterable for subclasses of a [ClassHierarchyNode].
80 class ClassHierarchyNodeIterable extends IterableBase<ClassElement> {
81 final ClassHierarchyNode root;
82 final bool includeRoot;
83 final bool directlyInstantiatedOnly;
84
85 ClassHierarchyNodeIterable(
86 this.root,
87 {this.includeRoot: true,
88 this.directlyInstantiatedOnly: false});
89
90 @override
91 Iterator<ClassElement> get iterator {
92 return new ClassHierarchyNodeIterator(this);
93 }
94 }
95
96 /// Iterator for subclasses of a [ClassHierarchyNode].
97 ///
98 /// Classes are returned in pre-order DFS fashion.
99 class ClassHierarchyNodeIterator implements Iterator<ClassElement> {
100 final ClassHierarchyNodeIterable iterable;
101
102 /// The class node holding the [current] class.
103 ///
104 /// This is `null` before the first call to [moveNext] and at the end of
105 /// iteration, i.e. after [moveNext] has returned `false`.
106 ClassHierarchyNode currentNode;
107
108 /// Stack of pending class nodes.
109 ///
110 /// This is `null` before the first call to [moveNext].
111 Link<ClassHierarchyNode> stack;
112
113 ClassHierarchyNodeIterator(this.iterable);
114
115 ClassHierarchyNode get root => iterable.root;
116
117 bool get includeRoot => iterable.includeRoot;
118
119 bool get directlyInstantiatedOnly => iterable.directlyInstantiatedOnly;
120
121 @override
122 ClassElement get current {
123 return currentNode != null ? currentNode.cls : null;
124 }
125
126 @override
127 bool moveNext() {
128 if (stack == null) {
129 // First call to moveNext
130 stack = const Link<ClassHierarchyNode>();
131 if (root == null) return false;
karlklose 2015/07/21 12:47:21 How about letting the ClassHierarchyNodeIterable c
Johnni Winther 2015/07/21 14:22:00 Throwing instead.
132 stack = stack.prepend(root);
133 return _findNext();
134 } else {
135 // Initialized state.
136 if (currentNode == null) return false;
137 return _findNext();
138 }
139 }
140
141 /// Find the next class using the [stack].
142 bool _findNext() {
143 while (true) {
144 if (stack.isEmpty) {
145 // No more classes. Set [currentNode] to `null` to signal the end of
146 // iteration.
147 currentNode = null;
148 return false;
149 }
150 currentNode = stack.head;
151 stack = stack.tail;
152 for (Link<ClassHierarchyNode> link = currentNode.directSubclasses;
153 !link.isEmpty;
154 link = link.tail) {
155 stack = stack.prepend(link.head);
156 }
157 if (_isValid(currentNode)) {
158 return true;
159 }
160 }
161 }
162
163 /// Returns `true` if the class of [node] is a valid result for this iterator.
164 bool _isValid(ClassHierarchyNode node) {
165 if (!includeRoot && node == root) return false;
166 if (directlyInstantiatedOnly && !node.isDirectlyInstantiated) return false;
167 return true;
168 }
169 }
170
171
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698