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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart

Issue 14416014: After a dynamic call, refine the receiver type by looking at the potential targets of that call. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 library simple_types_inferrer; 5 library simple_types_inferrer;
6 6
7 import 'dart:collection' show Queue, LinkedHashSet; 7 import 'dart:collection' show Queue, LinkedHashSet;
8 8
9 import '../closure.dart' show ClosureClassMap, ClosureScope; 9 import '../closure.dart' show ClosureClassMap, ClosureScope;
10 import '../dart_types.dart' show DartType, FunctionType, TypeKind; 10 import '../dart_types.dart' show DartType, FunctionType, TypeKind;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 if (constructorsToVisitCount != 0) constructorsToVisitCount--; 89 if (constructorsToVisitCount != 0) constructorsToVisitCount--;
90 } 90 }
91 91
92 /** 92 /**
93 * Returns whether all generative constructors of the class have 93 * Returns whether all generative constructors of the class have
94 * been analyzed. 94 * been analyzed.
95 */ 95 */
96 bool get isDone => constructorsToVisitCount == 0; 96 bool get isDone => constructorsToVisitCount == 0;
97 } 97 }
98 98
99 /**
100 * A sentinel type mask class used by the inferrer for the give up
101 * type, and the dynamic type.
102 */
103 class SentinelTypeMask extends TypeMask {
104 final String name;
105
106 SentinelTypeMask(this.name) : super(null, 0, false);
107
108 bool operator==(other) {
109 return identical(this, other);
110 }
111
112 TypeMask nullable() {
113 throw 'Unsupported operation';
114 }
115
116 bool get isNullable => true;
117
118 String toString() => '$name sentinel type mask';
119 }
120
121 final OPTIMISTIC = 0; 99 final OPTIMISTIC = 0;
122 final RETRY = 1; 100 final RETRY = 1;
123 final PESSIMISTIC = 2; 101 final PESSIMISTIC = 2;
124 102
125 class SimpleTypesInferrer extends TypesInferrer { 103 class SimpleTypesInferrer extends TypesInferrer {
126 InternalSimpleTypesInferrer internal; 104 InternalSimpleTypesInferrer internal;
127 Compiler compiler; 105 Compiler compiler;
128 106
129 SimpleTypesInferrer(Compiler compiler) : 107 SimpleTypesInferrer(Compiler compiler) :
130 compiler = compiler, 108 compiler = compiler,
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 * Heuristic for avoiding too many re-analysis of an element. 232 * Heuristic for avoiding too many re-analysis of an element.
255 */ 233 */
256 final int MAX_ANALYSIS_COUNT_PER_ELEMENT = 5; 234 final int MAX_ANALYSIS_COUNT_PER_ELEMENT = 5;
257 235
258 int optimismState; 236 int optimismState;
259 237
260 /** 238 /**
261 * Sentinel used by the inferrer to notify that it does not know 239 * Sentinel used by the inferrer to notify that it does not know
262 * the type of a specific element. 240 * the type of a specific element.
263 */ 241 */
264 final TypeMask dynamicType = new SentinelTypeMask('dynamic'); 242 TypeMask dynamicType;
265 bool isDynamicType(TypeMask type) => identical(type, dynamicType); 243 bool isDynamicType(TypeMask type) => type == dynamicType;
266 244
267 TypeMask nullType; 245 TypeMask nullType;
268 TypeMask intType; 246 TypeMask intType;
269 TypeMask doubleType; 247 TypeMask doubleType;
270 TypeMask numType; 248 TypeMask numType;
271 TypeMask boolType; 249 TypeMask boolType;
272 TypeMask functionType; 250 TypeMask functionType;
273 TypeMask listType; 251 TypeMask listType;
274 TypeMask constListType; 252 TypeMask constListType;
275 TypeMask fixedListType; 253 TypeMask fixedListType;
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 rawTypeOf(backend.growableListImplementation)); 514 rawTypeOf(backend.growableListImplementation));
537 515
538 mapType = new TypeMask.nonNullSubtype( 516 mapType = new TypeMask.nonNullSubtype(
539 rawTypeOf(backend.mapImplementation)); 517 rawTypeOf(backend.mapImplementation));
540 constMapType = new TypeMask.nonNullSubtype( 518 constMapType = new TypeMask.nonNullSubtype(
541 rawTypeOf(backend.constMapImplementation)); 519 rawTypeOf(backend.constMapImplementation));
542 functionType = new TypeMask.nonNullSubtype( 520 functionType = new TypeMask.nonNullSubtype(
543 rawTypeOf(backend.functionImplementation)); 521 rawTypeOf(backend.functionImplementation));
544 typeType = new TypeMask.nonNullExact( 522 typeType = new TypeMask.nonNullExact(
545 rawTypeOf(backend.typeImplementation)); 523 rawTypeOf(backend.typeImplementation));
524
525 dynamicType = new TypeMask.subclass(
526 rawTypeOf(compiler.objectClass));
546 } 527 }
547 528
548 dump() { 529 dump() {
549 int interestingTypes = 0; 530 int interestingTypes = 0;
550 returnTypeOf.forEach((Element element, TypeMask type) { 531 returnTypeOf.forEach((Element element, TypeMask type) {
551 if (type != nullType && !isDynamicType(type)) { 532 if (type != nullType && !isDynamicType(type)) {
552 interestingTypes++; 533 interestingTypes++;
553 } 534 }
554 }); 535 });
555 typeOf.forEach((Element element, TypeMask type) { 536 typeOf.forEach((Element element, TypeMask type) {
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 enqueueCallersOf(field); 1161 enqueueCallersOf(field);
1181 } 1162 }
1182 }); 1163 });
1183 } 1164 }
1184 1165
1185 /** 1166 /**
1186 * Returns the least upper bound between [firstType] and 1167 * Returns the least upper bound between [firstType] and
1187 * [secondType]. 1168 * [secondType].
1188 */ 1169 */
1189 TypeMask computeLUB(TypeMask firstType, TypeMask secondType) { 1170 TypeMask computeLUB(TypeMask firstType, TypeMask secondType) {
1190 assert(secondType != null);
1191 if (firstType == null) { 1171 if (firstType == null) {
1192 return secondType; 1172 return secondType;
1193 } else if (isDynamicType(secondType)) { 1173 } else if (isDynamicType(secondType)) {
1194 return secondType; 1174 return secondType;
1195 } else if (isDynamicType(firstType)) { 1175 } else if (isDynamicType(firstType)) {
1196 return firstType; 1176 return firstType;
1197 } else { 1177 } else {
1198 TypeMask union = firstType.union(secondType, compiler); 1178 TypeMask union = firstType.union(secondType, compiler);
1199 // TODO(kasperl): If the union isn't nullable it seems wasteful 1179 // TODO(kasperl): If the union isn't nullable it seems wasteful
1200 // to use dynamic. Fix that. 1180 // to use dynamic. Fix that.
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1583 // same as [newType]. 1563 // same as [newType].
1584 ClosureClassMap nestedClosureData = 1564 ClosureClassMap nestedClosureData =
1585 compiler.closureToClassMapper.getMappingForNestedFunction(node); 1565 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1586 nestedClosureData.forEachNonBoxedCapturedVariable((Element variable) { 1566 nestedClosureData.forEachNonBoxedCapturedVariable((Element variable) {
1587 // The type may be null for instance contexts (this and type 1567 // The type may be null for instance contexts (this and type
1588 // parameters), as well as captured argument checks. 1568 // parameters), as well as captured argument checks.
1589 if (locals.locals[variable] == null) return; 1569 if (locals.locals[variable] == null) return;
1590 inferrer.recordType(variable, locals.locals[variable]); 1570 inferrer.recordType(variable, locals.locals[variable]);
1591 }); 1571 });
1592 1572
1573 locals.update(elements[node], inferrer.functionType);
1593 return inferrer.functionType; 1574 return inferrer.functionType;
1594 } 1575 }
1595 1576
1596 TypeMask visitFunctionDeclaration(FunctionDeclaration node) { 1577 TypeMask visitFunctionDeclaration(FunctionDeclaration node) {
1597 locals.update(elements[node], inferrer.functionType); 1578 locals.update(elements[node], inferrer.functionType);
1598 return visit(node.function); 1579 return visit(node.function);
1599 } 1580 }
1600 1581
1601 TypeMask visitLiteralString(LiteralString node) { 1582 TypeMask visitLiteralString(LiteralString node) {
1602 return inferrer.stringType; 1583 return inferrer.stringType;
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
2071 Selector selector, 2052 Selector selector,
2072 TypeMask receiver, 2053 TypeMask receiver,
2073 ArgumentsTypes arguments, 2054 ArgumentsTypes arguments,
2074 [Selector constraint]) { 2055 [Selector constraint]) {
2075 if (selector.mask != receiver) { 2056 if (selector.mask != receiver) {
2076 selector = inferrer.isDynamicType(receiver) 2057 selector = inferrer.isDynamicType(receiver)
2077 ? selector.asUntyped 2058 ? selector.asUntyped
2078 : new TypedSelector(receiver, selector); 2059 : new TypedSelector(receiver, selector);
2079 updateSelectorInTree(node, selector); 2060 updateSelectorInTree(node, selector);
2080 } 2061 }
2062
2063 // If the receiver of the call is a local, we may know more about
2064 // its type by refining it with the potential targets of the
2065 // calls.
2066 if (node.asSend() != null
2067 && node.asSend().receiver != null
2068 && Elements.isLocal(elements[node.asSend().receiver])) {
2069 Element element = elements[node.asSend().receiver];
2070 TypeMask refinedMask = new TypeMask.refineWith(
2071 locals.use(element), selector, compiler);
2072 locals.update(element, refinedMask);
2073 }
2074
2081 return inferrer.registerCalledSelector( 2075 return inferrer.registerCalledSelector(
2082 node, selector, receiver, outermostElement, arguments, 2076 node, selector, receiver, outermostElement, arguments,
2083 constraint, inLoop); 2077 constraint, inLoop);
2084 } 2078 }
2085 2079
2086 TypeMask visitDynamicSend(Send node) { 2080 TypeMask visitDynamicSend(Send node) {
2087 Element element = elements[node]; 2081 Element element = elements[node];
2088 TypeMask receiverType; 2082 TypeMask receiverType;
2089 bool isCallOnThis = false; 2083 bool isCallOnThis = false;
2090 if (node.receiver == null) { 2084 if (node.receiver == null) {
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2299 } 2293 }
2300 2294
2301 TypeMask visitParenthesizedExpression(ParenthesizedExpression node) { 2295 TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
2302 return visit(node.expression); 2296 return visit(node.expression);
2303 } 2297 }
2304 2298
2305 void internalError(String reason, {Node node}) { 2299 void internalError(String reason, {Node node}) {
2306 compiler.internalError(reason, node: node); 2300 compiler.internalError(reason, node: node);
2307 } 2301 }
2308 } 2302 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698