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

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
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(
38 Set<Selector> selectors, Element member, Compiler compiler) {
kasperl 2012/04/25 14:14:54 Move first argument to previous line and split aft
ngeoffray 2012/04/26 09:31:51 Done.
39 if (selectors === null) return false;
40 for (Selector selector in selectors) {
41 if (selector.applies(member, compiler)) return true;
42 }
43 return false;
44 }
45
46 bool hasInvocation(Element member, Compiler compiler) {
47 return hasMatchingSelector(
48 compiler.universe.invokedNames[member.name], member, compiler);
49 }
50
51 bool hasGetter(Element member, Compiler compiler) {
52 return hasMatchingSelector(
53 compiler.universe.invokedGetters[member.name], member, compiler);
54 }
55
56 bool hasSetter(Element member, Compiler compiler) {
57 return hasMatchingSelector(
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.constant(this.kind, this.argumentCount);
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 =
63 static final Selector SETTER = const Selector(SelectorKind.SETTER, 1); 104 const Selector.constant(SelectorKind.GETTER, 0);
105 static final Selector SETTER =
106 const Selector.constant(SelectorKind.SETTER, 1);
64 static final Selector UNARY_OPERATOR = 107 static final Selector UNARY_OPERATOR =
65 const Selector(SelectorKind.OPERATOR, 0); 108 const Selector.constant(SelectorKind.OPERATOR, 0);
66 static final Selector BINARY_OPERATOR = 109 static final Selector BINARY_OPERATOR =
67 const Selector(SelectorKind.OPERATOR, 1); 110 const Selector.constant(SelectorKind.OPERATOR, 1);
68 static final Selector INDEX = const Selector(SelectorKind.INDEX, 1); 111 static final Selector INDEX =
69 static final Selector INDEX_SET = const Selector(SelectorKind.INDEX, 2); 112 const Selector.constant(SelectorKind.INDEX, 1);
113 static final Selector INDEX_SET =
114 const Selector.constant(SelectorKind.INDEX, 2);
70 static final Selector INDEX_AND_INDEX_SET = 115 static final Selector INDEX_AND_INDEX_SET =
71 const Selector(SelectorKind.INDEX, 2); 116 const Selector.constant(SelectorKind.INDEX, 2);
72 static final Selector GETTER_AND_SETTER = 117 static final Selector GETTER_AND_SETTER =
73 const Selector(SelectorKind.SETTER, 1); 118 const Selector.constant(SelectorKind.SETTER, 1);
74 static final Selector INVOCATION_0 = 119 static final Selector INVOCATION_0 =
75 const Selector(SelectorKind.INVOCATION, 0); 120 const Selector.constant(SelectorKind.INVOCATION, 0);
76 static final Selector INVOCATION_1 = 121 static final Selector INVOCATION_1 =
77 const Selector(SelectorKind.INVOCATION, 1); 122 const Selector.constant(SelectorKind.INVOCATION, 1);
78 static final Selector INVOCATION_2 = 123 static final Selector INVOCATION_2 =
79 const Selector(SelectorKind.INVOCATION, 2); 124 const Selector.constant(SelectorKind.INVOCATION, 2);
80 125
81 bool applies(FunctionElement element, Compiler compiler) { 126 bool applies(Element element, Compiler compiler) {
82 FunctionParameters parameters = element.computeParameters(compiler); 127 if (element.isSetter()) return kind === SelectorKind.SETTER;
128 if (element.isGetter()) {
129 return kind === SelectorKind.GETTER || kind === SelectorKind.INVOCATION;
130 }
131 if (element.isField()) {
132 return kind === SelectorKind.GETTER
133 || kind === SelectorKind.INVOCATION
134 || kind === SelectorKind.SETTER;
135 }
136 if (kind === SelectorKind.GETTER) return true;
137
138 FunctionElement function = element;
139 FunctionParameters parameters = function.computeParameters(compiler);
83 if (argumentCount > parameters.parameterCount) return false; 140 if (argumentCount > parameters.parameterCount) return false;
84 int requiredParameterCount = parameters.requiredParameterCount; 141 int requiredParameterCount = parameters.requiredParameterCount;
85 int optionalParameterCount = parameters.optionalParameterCount; 142 int optionalParameterCount = parameters.optionalParameterCount;
86 if (positionalArgumentCount < requiredParameterCount) return false; 143 if (positionalArgumentCount < requiredParameterCount) return false;
87 144
88 bool hasOptionalParameters = !parameters.optionalParameters.isEmpty(); 145 bool hasOptionalParameters = !parameters.optionalParameters.isEmpty();
89 if (namedArguments.isEmpty()) { 146 if (namedArguments.isEmpty()) {
90 if (!hasOptionalParameters) { 147 if (!hasOptionalParameters) {
91 return requiredParameterCount == argumentCount; 148 return requiredParameterCount == argumentCount;
92 } else { 149 } else {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 return true; 253 return true;
197 } 254 }
198 255
199 bool operator ==(other) { 256 bool operator ==(other) {
200 if (other is !Selector) return false; 257 if (other is !Selector) return false;
201 return argumentCount == other.argumentCount 258 return argumentCount == other.argumentCount
202 && namedArguments.length == other.namedArguments.length 259 && namedArguments.length == other.namedArguments.length
203 && sameNames(namedArguments, other.namedArguments); 260 && sameNames(namedArguments, other.namedArguments);
204 } 261 }
205 262
206 List<SourceString> getOrderedNamedArguments() => namedArguments; 263 List<SourceString> getOrderedNamedArguments() {
264 if (namedArguments.isEmpty()) return namedArguments;
265 if (!orderedNamedArguments.isEmpty()) return orderedNamedArguments;
266
267 orderedNamedArguments.addAll(namedArguments);
268 orderedNamedArguments.sort((SourceString first, SourceString second) {
269 return first.slowToString().compareTo(second.slowToString());
270 });
271 return orderedNamedArguments;
272 }
207 273
208 toString() => '$kind $argumentCount'; 274 toString() => '$kind $argumentCount';
209 } 275 }
210 276
211 class Invocation extends Selector { 277 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 /** 278 /**
243 * The type of the receiver. Any subtype of that type can be the 279 * The type of the receiver. Any subtype of that type can be the
244 * target of the invocation. 280 * target of the invocation.
245 */ 281 */
246 final Type receiverType; 282 final Type receiverType;
247 283
248 TypedInvocation(this.receiverType, Selector selector) 284 TypedSelector(this.receiverType, Selector selector)
249 : super(selector.argumentCount, selector.namedArguments); 285 : super(selector.kind,
286 selector.argumentCount,
287 selector.namedArguments);
250 288
251 bool applies(FunctionElement element, Compiler compiler) { 289 bool applies(Element element, Compiler compiler) {
252 if (!element.enclosingElement.isClass()) return false; 290 if (!element.enclosingElement.isClass()) return false;
253 291
292 // A closure can be called through any typed selector:
293 // class A {
294 // get foo() => () => 42;
295 // bar() => foo(); // The call to 'foo' is a typed selector.
296 // }
297 if (element.enclosingElement.superclass === compiler.closureClass) {
298 return super.applies(element, compiler);
299 }
300
254 ClassElement other = element.enclosingElement; 301 ClassElement other = element.enclosingElement;
255 ClassElement self = receiverType.element; 302 ClassElement self = receiverType.element;
256 if (!other.isSubclassOf(self)) return false; 303
257 return super.applies(element, compiler); 304 // If the class of the element is a subclass of this selector's
305 // class, it is a candidate.
306 if (other.isSubclassOf(self)) {
307 return super.applies(element, compiler);
308 }
309
310 if (self.isSubclassOf(other)) {
311 // Resolve an invocation of [element.name] on [self]. If the
312 // found element is [element], or is an abstract field whose
313 // getter or setter is [element], this selector is a candidate.
314
kasperl 2012/04/25 14:14:54 I'd remove this newline.
ngeoffray 2012/04/26 09:31:51 Done.
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
« lib/compiler/implementation/enqueue.dart ('K') | « lib/compiler/implementation/ssa/codegen.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698