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

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 hasOneMatchingSelector(
kasperl 2012/04/25 13:38:06 These are all "at least one", right? Maybe just re
ngeoffray 2012/04/25 13:58:44 Done.
38 Set<Selector> selectors, Element member, Compiler compiler) {
39 if (selectors === null) return false;
40 for (Selector selector in selectors) {
41 if (selector.applies(member, compiler)) return true;
42 };
kasperl 2012/04/25 13:38:06 Remove ;
ngeoffray 2012/04/25 13:58:44 Done.
43 return false;
44 }
45
46 bool hasOneInvocation(Element member, Compiler compiler) {
47 return hasOneMatchingSelector(
48 compiler.universe.invokedNames[member.name], member, compiler);
49 }
50
51 bool hasOneGetter(Element member, Compiler compiler) {
52 return hasOneMatchingSelector(
53 compiler.universe.invokedGetters[member.name], member, compiler);
54 }
55
56 bool hasOneSetter(Element member, Compiler compiler) {
57 return hasOneMatchingSelector(
58 compiler.universe.invokedSetters[member.name], member, compiler);
59 }
36 } 60 }
37 61
38 class SelectorKind { 62 class SelectorKind {
39 final String name; 63 final String name;
40 const SelectorKind(this.name); 64 const SelectorKind(this.name);
41 65
42 static final SelectorKind GETTER = const SelectorKind('getter'); 66 static final SelectorKind GETTER = const SelectorKind('getter');
43 static final SelectorKind SETTER = const SelectorKind('setter'); 67 static final SelectorKind SETTER = const SelectorKind('setter');
44 static final SelectorKind INVOCATION = const SelectorKind('invocation'); 68 static final SelectorKind INVOCATION = const SelectorKind('invocation');
45 static final SelectorKind OPERATOR = const SelectorKind('operator'); 69 static final SelectorKind OPERATOR = const SelectorKind('operator');
46 static final SelectorKind INDEX = const SelectorKind('index'); 70 static final SelectorKind INDEX = const SelectorKind('index');
47 71
48 toString() => name; 72 toString() => name;
49 } 73 }
50 74
51 class Selector implements Hashable { 75 class Selector implements Hashable {
52 // The numbers of arguments of the selector. Includes named arguments. 76 // The numbers of arguments of the selector. Includes named arguments.
53 final int argumentCount; 77 final int argumentCount;
54 final SelectorKind kind; 78 final SelectorKind kind;
55 const Selector(this.kind, this.argumentCount); 79 final List<SourceString> namedArguments = const <SourceString>[];
80 final List<SourceString> orderedNamedArguments = const <SourceString>[];
81
82 // The const constructor.
83 const Selector.cons(this.kind, this.argumentCount);
kasperl 2012/04/25 13:38:06 What does cons mean? Rename to constant?
ngeoffray 2012/04/25 13:58:44 Done.
84
85 Selector(
86 this.kind,
87 this.argumentCount,
88 [List<SourceString> namedArguments = const <SourceString>[]])
89 : this.namedArguments = namedArguments,
90 this.orderedNamedArguments = namedArguments.isEmpty()
91 ? namedArguments
92 : <SourceString>[];
93
94 Selector.invocation(
95 int argumentCount,
96 [List<SourceString> namedArguments = const <SourceString>[]])
97 : this(SelectorKind.INVOCATION, argumentCount, namedArguments);
56 98
57 int hashCode() => argumentCount + 1000 * namedArguments.length; 99 int hashCode() => argumentCount + 1000 * namedArguments.length;
58 List<SourceString> get namedArguments() => const <SourceString>[]; 100 int get namedArgumentCount() => namedArguments.length;
59 int get namedArgumentCount() => 0; 101 int get positionalArgumentCount() => argumentCount - namedArgumentCount;
60 int get positionalArgumentCount() => argumentCount;
61 102
62 static final Selector GETTER = const Selector(SelectorKind.GETTER, 0); 103 static final Selector GETTER = const Selector.cons(SelectorKind.GETTER, 0);
kasperl 2012/04/25 13:38:06 I would probably break the line before const here
ngeoffray 2012/04/25 13:58:44 Done.
63 static final Selector SETTER = const Selector(SelectorKind.SETTER, 1); 104 static final Selector SETTER = const Selector.cons(SelectorKind.SETTER, 1);
64 static final Selector UNARY_OPERATOR = 105 static final Selector UNARY_OPERATOR =
65 const Selector(SelectorKind.OPERATOR, 0); 106 const Selector.cons(SelectorKind.OPERATOR, 0);
66 static final Selector BINARY_OPERATOR = 107 static final Selector BINARY_OPERATOR =
67 const Selector(SelectorKind.OPERATOR, 1); 108 const Selector.cons(SelectorKind.OPERATOR, 1);
68 static final Selector INDEX = const Selector(SelectorKind.INDEX, 1); 109 static final Selector INDEX = const Selector.cons(SelectorKind.INDEX, 1);
69 static final Selector INDEX_SET = const Selector(SelectorKind.INDEX, 2); 110 static final Selector INDEX_SET = const Selector.cons(SelectorKind.INDEX, 2);
70 static final Selector INDEX_AND_INDEX_SET = 111 static final Selector INDEX_AND_INDEX_SET =
71 const Selector(SelectorKind.INDEX, 2); 112 const Selector.cons(SelectorKind.INDEX, 2);
72 static final Selector GETTER_AND_SETTER = 113 static final Selector GETTER_AND_SETTER =
73 const Selector(SelectorKind.SETTER, 1); 114 const Selector.cons(SelectorKind.SETTER, 1);
74 static final Selector INVOCATION_0 = 115 static final Selector INVOCATION_0 =
75 const Selector(SelectorKind.INVOCATION, 0); 116 const Selector.cons(SelectorKind.INVOCATION, 0);
76 static final Selector INVOCATION_1 = 117 static final Selector INVOCATION_1 =
77 const Selector(SelectorKind.INVOCATION, 1); 118 const Selector.cons(SelectorKind.INVOCATION, 1);
78 static final Selector INVOCATION_2 = 119 static final Selector INVOCATION_2 =
79 const Selector(SelectorKind.INVOCATION, 2); 120 const Selector.cons(SelectorKind.INVOCATION, 2);
80 121
81 bool applies(FunctionElement element, Compiler compiler) { 122 bool applies(Element element, Compiler compiler) {
82 FunctionParameters parameters = element.computeParameters(compiler); 123 if (element.isSetter()) return kind === SelectorKind.SETTER;
124 if (element.isGetter()) {
125 return kind === SelectorKind.GETTER || kind === SelectorKind.INVOCATION;
126 }
127 if (element.isField()) {
128 return kind === SelectorKind.GETTER
129 || kind === SelectorKind.INVOCATION
130 || kind == SelectorKind.SETTER;
kasperl 2012/04/25 13:38:06 ===?
ngeoffray 2012/04/25 13:58:44 Done.
131 }
132 if (kind === SelectorKind.GETTER) return true;
133
134 FunctionElement function = element;
135 FunctionParameters parameters = function.computeParameters(compiler);
83 if (argumentCount > parameters.parameterCount) return false; 136 if (argumentCount > parameters.parameterCount) return false;
84 int requiredParameterCount = parameters.requiredParameterCount; 137 int requiredParameterCount = parameters.requiredParameterCount;
85 int optionalParameterCount = parameters.optionalParameterCount; 138 int optionalParameterCount = parameters.optionalParameterCount;
86 if (positionalArgumentCount < requiredParameterCount) return false; 139 if (positionalArgumentCount < requiredParameterCount) return false;
87 140
88 bool hasOptionalParameters = !parameters.optionalParameters.isEmpty(); 141 bool hasOptionalParameters = !parameters.optionalParameters.isEmpty();
89 if (namedArguments.isEmpty()) { 142 if (namedArguments.isEmpty()) {
90 if (!hasOptionalParameters) { 143 if (!hasOptionalParameters) {
91 return requiredParameterCount == argumentCount; 144 return requiredParameterCount == argumentCount;
92 } else { 145 } else {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 return true; 249 return true;
197 } 250 }
198 251
199 bool operator ==(other) { 252 bool operator ==(other) {
200 if (other is !Selector) return false; 253 if (other is !Selector) return false;
201 return argumentCount == other.argumentCount 254 return argumentCount == other.argumentCount
202 && namedArguments.length == other.namedArguments.length 255 && namedArguments.length == other.namedArguments.length
203 && sameNames(namedArguments, other.namedArguments); 256 && sameNames(namedArguments, other.namedArguments);
204 } 257 }
205 258
206 List<SourceString> getOrderedNamedArguments() => namedArguments; 259 List<SourceString> getOrderedNamedArguments() {
260 if (namedArguments.isEmpty()) return namedArguments;
261 if (!orderedNamedArguments.isEmpty()) return orderedNamedArguments;
262
263 orderedNamedArguments.addAll(namedArguments);
264 orderedNamedArguments.sort((SourceString first, SourceString second) {
265 return first.slowToString().compareTo(second.slowToString());
266 });
267 return orderedNamedArguments;
268 }
207 269
208 toString() => '$kind $argumentCount'; 270 toString() => '$kind $argumentCount';
209 } 271 }
210 272
211 class Invocation extends Selector { 273 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 /** 274 /**
243 * The type of the receiver. Any subtype of that type can be the 275 * The type of the receiver. Any subtype of that type can be the
244 * target of the invocation. 276 * target of the invocation.
245 */ 277 */
246 final Type receiverType; 278 final Type receiverType;
247 279
248 TypedInvocation(this.receiverType, Selector selector) 280 TypedSelector(this.receiverType, Selector selector)
249 : super(selector.argumentCount, selector.namedArguments); 281 : super(selector.kind,
282 selector.argumentCount,
283 selector.namedArguments);
250 284
251 bool applies(FunctionElement element, Compiler compiler) { 285 bool applies(Element element, Compiler compiler) {
252 if (!element.enclosingElement.isClass()) return false; 286 if (!element.enclosingElement.isClass()) return false;
253 287
288 // A closure can be called through any typed selector:
289 // class A {
290 // get foo() => () => 42;
291 // bar() => foo(); // The call to 'foo' is a typed selector.
292 // }
293 if (element.enclosingElement.superclass === compiler.closureClass) {
294 return super.applies(element, compiler);
295 }
296
254 ClassElement other = element.enclosingElement; 297 ClassElement other = element.enclosingElement;
255 ClassElement self = receiverType.element; 298 ClassElement self = receiverType.element;
256 if (!other.isSubclassOf(self)) return false; 299
257 return super.applies(element, compiler); 300 // If the class of the element is a subclass of this selector's
301 // class, it is a candidate.
302 if (other.isSubclassOf(self)) {
303 return super.applies(element, compiler);
304 }
305
306 if (self.isSubclassOf(other)) {
307 // Resolve an invocation of [element.name] on [self]. If the
308 // found element is [element], or is an abstract field whose
309 // getter or setter is [element], this selector is a candidate.
310
311 Element resolved = self.lookupMember(element.name);
312 if (resolved === element) {
313 return super.applies(element, compiler);
314 }
315
316 if (resolved !== null && resolved.kind === ElementKind.ABSTRACT_FIELD) {
317 AbstractFieldElement field = resolved;
318 if (element === field.getter || element === field.setter) {
319 return super.applies(element, compiler);
320 }
321 }
322 }
323
258 return false; 324 return false;
259 } 325 }
260 326
261 bool operator ==(other) { 327 bool operator ==(other) {
262 if (other is !TypedInvocation) return false; 328 if (other is !TypedSelector) return false;
263 if (other.receiverType !== receiverType) return false; 329 if (other.receiverType !== receiverType) return false;
264 return super == other; 330 return super == other;
265 } 331 }
266 } 332 }
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