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

Side by Side Diff: lib/compiler/implementation/universe.dart

Issue 10191016: Introduce typed selectors for getters and setters also for better tree shaking. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « lib/compiler/implementation/ssa/codegen.dart ('k') | no next file » | 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 class Universe { 5 class Universe {
6 Map<Element, String> generatedCode; 6 Map<Element, String> generatedCode;
7 Map<Element, String> generatedBailoutCode; 7 Map<Element, String> generatedBailoutCode;
8 final Set<ClassElement> instantiatedClasses; 8 final Set<ClassElement> instantiatedClasses;
9 final Set<SourceString> instantiatedClassInstanceFields; 9 final Set<SourceString> instantiatedClassInstanceFields;
10 final Set<FunctionElement> staticFunctionsNeedingGetter; 10 final Set<FunctionElement> staticFunctionsNeedingGetter;
11 final Map<SourceString, Set<Selector>> invokedNames; 11 final Map<SourceString, Set<Selector>> invokedNames;
12 final Set<SourceString> invokedGetters; 12 final Map<SourceString, Set<Selector>> invokedGetters;
13 final Set<SourceString> invokedSetters; 13 final Map<SourceString, Set<Selector>> invokedSetters;
14 final Map<String, LibraryElement> libraries; 14 final Map<String, LibraryElement> libraries;
15 // TODO(ngeoffray): This should be a Set<Type>. 15 // TODO(ngeoffray): This should be a Set<Type>.
16 final Set<Element> isChecks; 16 final Set<Element> isChecks;
17 17
18 Universe() : generatedCode = new Map<Element, String>(), 18 Universe() : generatedCode = new Map<Element, String>(),
19 generatedBailoutCode = new Map<Element, String>(), 19 generatedBailoutCode = new Map<Element, String>(),
20 libraries = new Map<String, LibraryElement>(), 20 libraries = new Map<String, LibraryElement>(),
21 instantiatedClasses = new Set<ClassElement>(), 21 instantiatedClasses = new Set<ClassElement>(),
22 instantiatedClassInstanceFields = new Set<SourceString>(), 22 instantiatedClassInstanceFields = new Set<SourceString>(),
23 staticFunctionsNeedingGetter = new Set<FunctionElement>(), 23 staticFunctionsNeedingGetter = new Set<FunctionElement>(),
24 invokedNames = new Map<SourceString, Set<Selector>>(), 24 invokedNames = new Map<SourceString, Set<Selector>>(),
25 invokedGetters = new Set<SourceString>(), 25 invokedGetters = new Map<SourceString, Set<Selector>>(),
26 invokedSetters = new Set<SourceString>(), 26 invokedSetters = new Map<SourceString, Set<Selector>>(),
27 isChecks = new Set<Element>(); 27 isChecks = new Set<Element>();
28 28
29 void addGeneratedCode(WorkItem work, String code) { 29 void addGeneratedCode(WorkItem work, String code) {
30 generatedCode[work.element] = code; 30 generatedCode[work.element] = code;
31 } 31 }
32 32
33 void addBailoutCode(WorkItem work, String code) { 33 void addBailoutCode(WorkItem work, String code) {
34 generatedBailoutCode[work.element] = code; 34 generatedBailoutCode[work.element] = code;
35 } 35 }
36
37 bool hasMatchingSelector(Set<Selector> selectors,
38 Element member,
39 Compiler compiler) {
40 if (selectors === null) return false;
41 for (Selector selector in selectors) {
42 if (selector.applies(member, compiler)) return true;
43 }
44 return false;
45 }
46
47 bool hasInvocation(Element member, Compiler compiler) {
48 return hasMatchingSelector(
49 compiler.universe.invokedNames[member.name], member, compiler);
50 }
51
52 bool hasGetter(Element member, Compiler compiler) {
53 return hasMatchingSelector(
54 compiler.universe.invokedGetters[member.name], member, compiler);
55 }
56
57 bool hasSetter(Element member, Compiler compiler) {
58 return hasMatchingSelector(
59 compiler.universe.invokedSetters[member.name], member, compiler);
60 }
36 } 61 }
37 62
38 class SelectorKind { 63 class SelectorKind {
39 final String name; 64 final String name;
40 const SelectorKind(this.name); 65 const SelectorKind(this.name);
41 66
42 static final SelectorKind GETTER = const SelectorKind('getter'); 67 static final SelectorKind GETTER = const SelectorKind('getter');
43 static final SelectorKind SETTER = const SelectorKind('setter'); 68 static final SelectorKind SETTER = const SelectorKind('setter');
44 static final SelectorKind INVOCATION = const SelectorKind('invocation'); 69 static final SelectorKind INVOCATION = const SelectorKind('invocation');
45 static final SelectorKind OPERATOR = const SelectorKind('operator'); 70 static final SelectorKind OPERATOR = const SelectorKind('operator');
46 static final SelectorKind INDEX = const SelectorKind('index'); 71 static final SelectorKind INDEX = const SelectorKind('index');
47 72
48 toString() => name; 73 toString() => name;
49 } 74 }
50 75
51 class Selector implements Hashable { 76 class Selector implements Hashable {
52 // The numbers of arguments of the selector. Includes named arguments. 77 // The numbers of arguments of the selector. Includes named arguments.
53 final int argumentCount; 78 final int argumentCount;
54 final SelectorKind kind; 79 final SelectorKind kind;
55 const Selector(this.kind, this.argumentCount); 80 final List<SourceString> namedArguments = const <SourceString>[];
81 final List<SourceString> orderedNamedArguments = const <SourceString>[];
82
83 // The const constructor.
84 const Selector.constant(this.kind, this.argumentCount);
85
86 Selector(
87 this.kind,
88 this.argumentCount,
89 [List<SourceString> namedArguments = const <SourceString>[]])
90 : this.namedArguments = namedArguments,
91 this.orderedNamedArguments = namedArguments.isEmpty()
92 ? namedArguments
93 : <SourceString>[];
94
95 Selector.invocation(
96 int argumentCount,
97 [List<SourceString> namedArguments = const <SourceString>[]])
98 : this(SelectorKind.INVOCATION, argumentCount, namedArguments);
56 99
57 int hashCode() => argumentCount + 1000 * namedArguments.length; 100 int hashCode() => argumentCount + 1000 * namedArguments.length;
58 List<SourceString> get namedArguments() => const <SourceString>[]; 101 int get namedArgumentCount() => namedArguments.length;
59 int get namedArgumentCount() => 0; 102 int get positionalArgumentCount() => argumentCount - namedArgumentCount;
60 int get positionalArgumentCount() => argumentCount;
61 103
62 static final Selector GETTER = const Selector(SelectorKind.GETTER, 0); 104 static final Selector GETTER =
63 static final Selector SETTER = const Selector(SelectorKind.SETTER, 1); 105 const Selector.constant(SelectorKind.GETTER, 0);
106 static final Selector SETTER =
107 const Selector.constant(SelectorKind.SETTER, 1);
64 static final Selector UNARY_OPERATOR = 108 static final Selector UNARY_OPERATOR =
65 const Selector(SelectorKind.OPERATOR, 0); 109 const Selector.constant(SelectorKind.OPERATOR, 0);
66 static final Selector BINARY_OPERATOR = 110 static final Selector BINARY_OPERATOR =
67 const Selector(SelectorKind.OPERATOR, 1); 111 const Selector.constant(SelectorKind.OPERATOR, 1);
68 static final Selector INDEX = const Selector(SelectorKind.INDEX, 1); 112 static final Selector INDEX =
69 static final Selector INDEX_SET = const Selector(SelectorKind.INDEX, 2); 113 const Selector.constant(SelectorKind.INDEX, 1);
114 static final Selector INDEX_SET =
115 const Selector.constant(SelectorKind.INDEX, 2);
70 static final Selector INDEX_AND_INDEX_SET = 116 static final Selector INDEX_AND_INDEX_SET =
71 const Selector(SelectorKind.INDEX, 2); 117 const Selector.constant(SelectorKind.INDEX, 2);
72 static final Selector GETTER_AND_SETTER = 118 static final Selector GETTER_AND_SETTER =
73 const Selector(SelectorKind.SETTER, 1); 119 const Selector.constant(SelectorKind.SETTER, 1);
74 static final Selector INVOCATION_0 = 120 static final Selector INVOCATION_0 =
75 const Selector(SelectorKind.INVOCATION, 0); 121 const Selector.constant(SelectorKind.INVOCATION, 0);
76 static final Selector INVOCATION_1 = 122 static final Selector INVOCATION_1 =
77 const Selector(SelectorKind.INVOCATION, 1); 123 const Selector.constant(SelectorKind.INVOCATION, 1);
78 static final Selector INVOCATION_2 = 124 static final Selector INVOCATION_2 =
79 const Selector(SelectorKind.INVOCATION, 2); 125 const Selector.constant(SelectorKind.INVOCATION, 2);
80 126
81 bool applies(FunctionElement element, Compiler compiler) { 127 bool applies(Element element, Compiler compiler) {
82 FunctionParameters parameters = element.computeParameters(compiler); 128 if (element.isSetter()) return kind === SelectorKind.SETTER;
129 if (element.isGetter()) {
130 return kind === SelectorKind.GETTER || kind === SelectorKind.INVOCATION;
131 }
132 if (element.isField()) {
133 return kind === SelectorKind.GETTER
134 || kind === SelectorKind.INVOCATION
135 || kind === SelectorKind.SETTER;
136 }
137 if (kind === SelectorKind.GETTER) return true;
138
139 FunctionElement function = element;
140 FunctionParameters parameters = function.computeParameters(compiler);
83 if (argumentCount > parameters.parameterCount) return false; 141 if (argumentCount > parameters.parameterCount) return false;
84 int requiredParameterCount = parameters.requiredParameterCount; 142 int requiredParameterCount = parameters.requiredParameterCount;
85 int optionalParameterCount = parameters.optionalParameterCount; 143 int optionalParameterCount = parameters.optionalParameterCount;
86 if (positionalArgumentCount < requiredParameterCount) return false; 144 if (positionalArgumentCount < requiredParameterCount) return false;
87 145
88 bool hasOptionalParameters = !parameters.optionalParameters.isEmpty(); 146 bool hasOptionalParameters = !parameters.optionalParameters.isEmpty();
89 if (namedArguments.isEmpty()) { 147 if (namedArguments.isEmpty()) {
90 if (!hasOptionalParameters) { 148 if (!hasOptionalParameters) {
91 return requiredParameterCount == argumentCount; 149 return requiredParameterCount == argumentCount;
92 } else { 150 } else {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 return true; 254 return true;
197 } 255 }
198 256
199 bool operator ==(other) { 257 bool operator ==(other) {
200 if (other is !Selector) return false; 258 if (other is !Selector) return false;
201 return argumentCount == other.argumentCount 259 return argumentCount == other.argumentCount
202 && namedArguments.length == other.namedArguments.length 260 && namedArguments.length == other.namedArguments.length
203 && sameNames(namedArguments, other.namedArguments); 261 && sameNames(namedArguments, other.namedArguments);
204 } 262 }
205 263
206 List<SourceString> getOrderedNamedArguments() => namedArguments; 264 List<SourceString> getOrderedNamedArguments() {
265 if (namedArguments.isEmpty()) return namedArguments;
266 if (!orderedNamedArguments.isEmpty()) return orderedNamedArguments;
267
268 orderedNamedArguments.addAll(namedArguments);
269 orderedNamedArguments.sort((SourceString first, SourceString second) {
270 return first.slowToString().compareTo(second.slowToString());
271 });
272 return orderedNamedArguments;
273 }
207 274
208 toString() => '$kind $argumentCount'; 275 toString() => '$kind $argumentCount';
209 } 276 }
210 277
211 class Invocation extends Selector { 278 class TypedSelector extends Selector {
212 final List<SourceString> namedArguments;
213 List<SourceString> orderedNamedArguments;
214 int get namedArgumentCount() => namedArguments.length;
215 int get positionalArgumentCount() => argumentCount - namedArgumentCount;
216
217 Invocation(int argumentCount,
218 [List<SourceString> names = const <SourceString>[]])
219 : super(SelectorKind.INVOCATION, argumentCount),
220 namedArguments = names,
221 orderedNamedArguments = const <SourceString>[];
222
223 List<SourceString> getOrderedNamedArguments() {
224 if (namedArguments.isEmpty()) return namedArguments;
225 // We use the empty const List as a sentinel.
226 if (!orderedNamedArguments.isEmpty()) return orderedNamedArguments;
227
228 List<SourceString> list = new List<SourceString>.from(namedArguments);
229 list.sort((SourceString first, SourceString second) {
230 return first.slowToString().compareTo(second.slowToString());
231 });
232 orderedNamedArguments = list;
233 return orderedNamedArguments;
234 }
235 }
236
237 /**
238 * A [TypedInvocation] is an invocation where we have information on
239 * the type of the receiver.
240 */
241 class TypedInvocation extends Invocation {
242 /** 279 /**
243 * The type of the receiver. Any subtype of that type can be the 280 * The type of the receiver. Any subtype of that type can be the
244 * target of the invocation. 281 * target of the invocation.
245 */ 282 */
246 final Type receiverType; 283 final Type receiverType;
247 284
248 TypedInvocation(this.receiverType, Selector selector) 285 TypedSelector(this.receiverType, Selector selector)
249 : super(selector.argumentCount, selector.namedArguments); 286 : super(selector.kind,
287 selector.argumentCount,
288 selector.namedArguments);
250 289
251 bool applies(FunctionElement element, Compiler compiler) { 290 bool applies(Element element, Compiler compiler) {
252 if (!element.enclosingElement.isClass()) return false; 291 if (!element.enclosingElement.isClass()) return false;
253 292
293 // A closure can be called through any typed selector:
294 // class A {
295 // get foo() => () => 42;
296 // bar() => foo(); // The call to 'foo' is a typed selector.
297 // }
298 if (element.enclosingElement.superclass === compiler.closureClass) {
299 return super.applies(element, compiler);
300 }
301
254 ClassElement other = element.enclosingElement; 302 ClassElement other = element.enclosingElement;
255 ClassElement self = receiverType.element; 303 ClassElement self = receiverType.element;
256 if (!other.isSubclassOf(self)) return false; 304
257 return super.applies(element, compiler); 305 // If the class of the element is a subclass of this selector's
306 // class, it is a candidate.
307 if (other.isSubclassOf(self)) {
308 return super.applies(element, compiler);
309 }
310
311 if (self.isSubclassOf(other)) {
312 // Resolve an invocation of [element.name] on [self]. If the
313 // found element is [element], or is an abstract field whose
314 // getter or setter is [element], this selector is a candidate.
315 Element resolved = self.lookupMember(element.name);
316 if (resolved === element) {
317 return super.applies(element, compiler);
318 }
319
320 if (resolved !== null && resolved.kind === ElementKind.ABSTRACT_FIELD) {
321 AbstractFieldElement field = resolved;
322 if (element === field.getter || element === field.setter) {
323 return super.applies(element, compiler);
324 }
325 }
326 }
327
258 return false; 328 return false;
259 } 329 }
260 330
261 bool operator ==(other) { 331 bool operator ==(other) {
262 if (other is !TypedInvocation) return false; 332 if (other is !TypedSelector) return false;
263 if (other.receiverType !== receiverType) return false; 333 if (other.receiverType !== receiverType) return false;
264 return super == other; 334 return super == other;
265 } 335 }
266 } 336 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/codegen.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698