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

Unified Diff: sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart

Issue 11348297: Widen big concrete types to dynamic. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cache constants. Created 8 years 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 3b2334cf63f504df5d006b88f0004e73836be689..97ec3e80b1dd9aed32b0b13bec09bbd5589c06d0 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -75,22 +75,31 @@ class NullBaseType implements BaseType {
* concrete type.
*/
abstract class ConcreteType {
- factory ConcreteType.empty() => new UnionType(new Set<BaseType>());
+ final ConcreteTypesInferrer inferrer;
+
+ ConcreteType(this.inferrer);
+
+ factory ConcreteType.empty(ConcreteTypesInferrer inferrer) {
+ return new UnionType(inferrer, new Set<BaseType>());
+ }
/**
* The singleton constituted of the unknown base type is the unknown concrete
* type.
*/
- factory ConcreteType.singleton(BaseType baseType) {
- if (baseType.isUnknown()) {
- return const UnknownConcreteType();
+ factory ConcreteType.singleton(ConcreteTypesInferrer inferrer,
+ BaseType baseType) {
+ if (baseType.isUnknown() || inferrer.compiler.maxConcreteTypeSize < 1) {
+ return new UnknownConcreteType(inferrer);
}
Set<BaseType> singletonSet = new Set<BaseType>();
singletonSet.add(baseType);
- return new UnionType(singletonSet);
+ return new UnionType(inferrer, singletonSet);
}
- factory ConcreteType.unknown() => const UnknownConcreteType();
+ factory ConcreteType.unknown(ConcreteTypesInferrer inferrer) {
+ return new UnknownConcreteType(inferrer);
+ }
ConcreteType union(ConcreteType other);
bool isUnkown();
@@ -107,8 +116,8 @@ abstract class ConcreteType {
/**
* The unkown concrete type: it is absorbing for the union.
*/
-class UnknownConcreteType implements ConcreteType {
- const UnknownConcreteType();
+class UnknownConcreteType extends ConcreteType {
+ UnknownConcreteType(ConcreteTypesInferrer inferrer) : super(inferrer);
bool isUnkown() => true;
bool isEmpty() => false;
bool operator ==(ConcreteType other) => identical(this, other);
@@ -123,14 +132,14 @@ class UnknownConcreteType implements ConcreteType {
/**
* An immutable set of base types, like [: {int, bool} :].
*/
-class UnionType implements ConcreteType {
+class UnionType extends ConcreteType {
final Set<BaseType> baseTypes;
/**
* The argument should NOT be mutated later. Do not call directly, use
* ConcreteType.singleton instead.
*/
- UnionType(this.baseTypes);
+ UnionType(ConcreteTypesInferrer inferrer, this.baseTypes) : super (inferrer);
bool isUnkown() => false;
bool isEmpty() => baseTypes.isEmpty;
@@ -155,12 +164,14 @@ class UnionType implements ConcreteType {
// there are no nested classes. We need factory methods instead.
ConcreteType union(ConcreteType other) {
if (other.isUnkown()) {
- return const UnknownConcreteType();
+ return new UnknownConcreteType(inferrer);
}
UnionType otherUnion = other; // cast
Set<BaseType> newBaseTypes = new Set<BaseType>.from(baseTypes);
newBaseTypes.addAll(otherUnion.baseTypes);
- return new UnionType(newBaseTypes);
+ return newBaseTypes.length > inferrer.compiler.maxConcreteTypeSize
+ ? new UnknownConcreteType(inferrer)
ahe 2012/12/20 10:18:22 You're discarding information here. The abstract
polux 2012/12/20 10:31:50 For now I've been assuming concrete types only hol
+ : new UnionType(inferrer, newBaseTypes);
}
ClassElement getUniqueType() {
@@ -185,12 +196,15 @@ class UnionType implements ConcreteType {
*/
class ConcreteTypeCartesianProduct
implements Iterable<ConcreteTypesEnvironment> {
+ final ConcreteTypesInferrer inferrer;
final BaseType baseTypeOfThis;
final Map<Element, ConcreteType> concreteTypes;
- ConcreteTypeCartesianProduct(this.baseTypeOfThis, this.concreteTypes);
+ ConcreteTypeCartesianProduct(this.inferrer, this.baseTypeOfThis,
+ this.concreteTypes);
Iterator iterator() => concreteTypes.isEmpty
- ? [new ConcreteTypesEnvironment(baseTypeOfThis)].iterator()
- : new ConcreteTypeCartesianProductIterator(baseTypeOfThis, concreteTypes);
+ ? [new ConcreteTypesEnvironment(inferrer, baseTypeOfThis)].iterator()
+ : new ConcreteTypeCartesianProductIterator(inferrer, baseTypeOfThis,
+ concreteTypes);
String toString() {
List<ConcreteTypesEnvironment> cartesianProduct =
new List<ConcreteTypesEnvironment>.from(this);
@@ -202,6 +216,7 @@ class ConcreteTypeCartesianProduct
* An helper class for [ConcreteTypeCartesianProduct].
*/
class ConcreteTypeCartesianProductIterator implements Iterator {
+ final ConcreteTypesInferrer inferrer;
final BaseType baseTypeOfThis;
final Map<Element, ConcreteType> concreteTypes;
final Map<Element, BaseType> nextValues;
@@ -209,11 +224,11 @@ class ConcreteTypeCartesianProductIterator implements Iterator {
int size = 1;
int counter = 0;
- ConcreteTypeCartesianProductIterator(this.baseTypeOfThis,
- Map<Element, ConcreteType> concreteTypes) :
- this.concreteTypes = concreteTypes,
- nextValues = new Map<Element, BaseType>(),
- state = new Map<Element, Iterator>() {
+ ConcreteTypeCartesianProductIterator(this.inferrer, this.baseTypeOfThis,
+ Map<Element, ConcreteType> concreteTypes)
+ : this.concreteTypes = concreteTypes,
+ nextValues = new Map<Element, BaseType>(),
+ state = new Map<Element, Iterator>() {
if (concreteTypes.isEmpty) {
size = 0;
return;
@@ -230,8 +245,10 @@ class ConcreteTypeCartesianProductIterator implements Iterator {
ConcreteTypesEnvironment takeSnapshot() {
Map<Element, ConcreteType> result = new Map<Element, ConcreteType>();
- nextValues.forEach((k, v) { result[k] = new ConcreteType.singleton(v); });
- return new ConcreteTypesEnvironment.of(result, baseTypeOfThis);
+ nextValues.forEach((k, v) {
+ result[k] = inferrer.singletonConcreteType(v);
+ });
+ return new ConcreteTypesEnvironment.of(inferrer, result, baseTypeOfThis);
}
ConcreteTypesEnvironment next() {
@@ -283,24 +300,26 @@ class BaseTypes {
* [ConcreteTypes]. Each visitor owns one.
*/
class ConcreteTypesEnvironment {
+ final ConcreteTypesInferrer inferrer;
final Map<Element, ConcreteType> environment;
final BaseType typeOfThis;
- ConcreteTypesEnvironment([this.typeOfThis]) :
+
+ ConcreteTypesEnvironment(this.inferrer, [this.typeOfThis]) :
this.environment = new Map<Element, ConcreteType>();
- ConcreteTypesEnvironment.of(this.environment, this.typeOfThis);
+ ConcreteTypesEnvironment.of(this.inferrer, this.environment, this.typeOfThis);
ConcreteType lookupType(Element element) => environment[element];
ConcreteType lookupTypeOfThis() {
return (typeOfThis == null)
? null
- : new ConcreteType.singleton(typeOfThis);
+ : inferrer.singletonConcreteType(typeOfThis);
}
ConcreteTypesEnvironment put(Element element, ConcreteType type) {
Map<Element, ConcreteType> newMap =
new Map<Element, ConcreteType>.from(environment);
newMap[element] = type;
- return new ConcreteTypesEnvironment.of(newMap, typeOfThis);
+ return new ConcreteTypesEnvironment.of(inferrer, newMap, typeOfThis);
}
ConcreteTypesEnvironment join(ConcreteTypesEnvironment other) {
@@ -317,7 +336,7 @@ class ConcreteTypesEnvironment {
newMap[element] = currentType.union(type);
}
});
- return new ConcreteTypesEnvironment.of(newMap, typeOfThis);
+ return new ConcreteTypesEnvironment.of(inferrer, newMap, typeOfThis);
}
bool operator ==(ConcreteTypesEnvironment other) {
@@ -422,7 +441,10 @@ class ConcreteTypesInferrer {
inferredParameterTypes = new Map<VariableElement, ConcreteType>(),
workQueue = new Queue<InferenceWorkItem>(),
callers = new Map<FunctionElement, Set<FunctionElement>>(),
- readers = new Map<Element, Set<FunctionElement>>();
+ readers = new Map<Element, Set<FunctionElement>>() {
+ unknownConcreteType = new ConcreteType.unknown(this);
+ emptyConcreteType = new ConcreteType.empty(this);
+ }
/**
* Populates [cache] with ad hoc rules like:
@@ -440,11 +462,11 @@ class ConcreteTypesInferrer {
FunctionElement method,
BaseType argumentType) {
ArgumentsTypes argumentsTypes = new ArgumentsTypes(
- [new ConcreteType.singleton(argumentType)],
+ [singletonConcreteType(argumentType)],
new Map());
Map<Element, ConcreteType> argumentMap =
associateArguments(method, argumentsTypes);
- return new ConcreteTypesEnvironment.of(argumentMap, receiverType);
+ return new ConcreteTypesEnvironment.of(this, argumentMap, receiverType);
}
// Adds the rule {receiverType}.method({argumentType}) -> {returnType}
@@ -462,7 +484,7 @@ class ConcreteTypesInferrer {
cache.containsKey(methodElement)
? cache[methodElement]
: new Map<ConcreteTypesEnvironment, ConcreteType>();
- map[environment] = new ConcreteType.singleton(returnType);
+ map[environment] = singletonConcreteType(returnType);
cache[methodElement] = map;
}
@@ -487,6 +509,17 @@ class ConcreteTypesInferrer {
// --- utility methods ---
+ /** The unknown concrete type */
+ ConcreteType unknownConcreteType;
+
+ /** The empty concrete type */
+ ConcreteType emptyConcreteType;
+
+ /** Creates a singleton concrete type containing [baseType]. */
+ ConcreteType singletonConcreteType(BaseType baseType) {
+ return new ConcreteType.singleton(this, baseType);
+ }
+
/**
* Returns all the members with name [methodName].
*/
@@ -518,7 +551,7 @@ class ConcreteTypesInferrer {
*/
ConcreteType getFieldType(Element field) {
ConcreteType result = inferredFieldTypes[field];
- return (result == null) ? new ConcreteType.empty() : result;
+ return (result == null) ? emptyConcreteType : result;
}
/**
@@ -609,16 +642,16 @@ class ConcreteTypesInferrer {
ConcreteType getSendReturnType(FunctionElement function,
BaseType receiverType,
ArgumentsTypes argumentsTypes) {
- ConcreteType result = new ConcreteType.empty();
+ ConcreteType result = emptyConcreteType;
Map<Element, ConcreteType> argumentMap =
associateArguments(function, argumentsTypes);
// if the association failed, this send will never occur or will fail
if (argumentMap == null) {
- return new ConcreteType.empty();
+ return emptyConcreteType;
}
argumentMap.forEach(augmentParameterType);
ConcreteTypeCartesianProduct product =
- new ConcreteTypeCartesianProduct(receiverType, argumentMap);
+ new ConcreteTypeCartesianProduct(this, receiverType, argumentMap);
for (ConcreteTypesEnvironment environment in product) {
result = result.union(
getMonomorphicSendReturnType(function, environment));
@@ -689,7 +722,7 @@ class ConcreteTypesInferrer {
// in order to handle "?parameter" tests
leftOverNamedParameters.forEach((_, Element namedParameter) {
result[namedParameter] =
- new ConcreteType.singleton(const NullBaseType());
+ singletonConcreteType(const NullBaseType());
});
return result;
}
@@ -710,7 +743,7 @@ class ConcreteTypesInferrer {
workQueue.addLast(
new InferenceWorkItem(function, environment));
// in case of a constructor, optimize by returning the class
- return new ConcreteType.empty();
+ return emptyConcreteType;
}
}
@@ -727,7 +760,7 @@ class ConcreteTypesInferrer {
// This should never happen since we only deal with concrete types, except
// for external methods whose typing rules have not been hardcoded yet.
if (!tree.hasBody()) {
- return new ConcreteType.unknown();
+ return unknownConcreteType;
}
TreeElements elements =
compiler.enqueuer.resolution.resolvedElements[element];
@@ -773,7 +806,7 @@ class ConcreteTypesInferrer {
if (enclosingClass != compiler.objectClass) {
FunctionElement target = superClass.lookupConstructor(
new Selector.callDefaultConstructor(enclosingClass.getLibrary()));
- final superClassConcreteType = new ConcreteType.singleton(
+ final superClassConcreteType = singletonConcreteType(
new ClassBaseType(enclosingClass));
getSendReturnType(target, new ClassBaseType(enclosingClass),
new ArgumentsTypes(new List(), new Map()));
@@ -781,7 +814,7 @@ class ConcreteTypesInferrer {
}
tree.accept(visitor);
- return new ConcreteType.singleton(new ClassBaseType(enclosingClass));
+ return singletonConcreteType(new ClassBaseType(enclosingClass));
}
void analyzeMain(Element element) {
@@ -790,7 +823,7 @@ class ConcreteTypesInferrer {
populateCacheWithBuiltinRules();
try {
workQueue.addLast(
- new InferenceWorkItem(element, new ConcreteTypesEnvironment()));
+ new InferenceWorkItem(element, new ConcreteTypesEnvironment(this)));
while (!workQueue.isEmpty) {
InferenceWorkItem item = workQueue.removeFirst();
ConcreteType concreteType = analyze(item.method, item.environment);
@@ -943,7 +976,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType visitExpressionStatement(ExpressionStatement node) {
analyze(node.expression);
- return new ConcreteType.empty();
+ return inferrer.emptyConcreteType;
}
ConcreteType visitFor(For node) {
@@ -951,7 +984,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
analyze(node.initializer);
}
analyze(node.conditionStatement);
- ConcreteType result = new ConcreteType.empty();
+ ConcreteType result = inferrer.emptyConcreteType;
ConcreteTypesEnvironment oldEnvironment;
do {
oldEnvironment = environment;
@@ -990,7 +1023,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType thenType = analyze(node.thenPart);
ConcreteTypesEnvironment snapshot = environment;
ConcreteType elseType = node.hasElsePart ? analyze(node.elsePart)
- : new ConcreteType.empty();
+ : inferrer.emptyConcreteType;
environment = environment.join(snapshot);
return thenType.union(elseType);
}
@@ -1100,7 +1133,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
if (operatorName.stringValue == '++'
|| operatorName.stringValue == '--') {
List<ConcreteType> positionalArguments = <ConcreteType>[
- new ConcreteType.singleton(inferrer.baseTypes.intBaseType)];
+ inferrer.singletonConcreteType(inferrer.baseTypes.intBaseType)];
argumentsTypes = new ArgumentsTypes(positionalArguments, new Map());
} else {
argumentsTypes = analyzeArguments(node.arguments);
@@ -1122,15 +1155,15 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
}
ConcreteType visitLiteralInt(LiteralInt node) {
- return new ConcreteType.singleton(inferrer.baseTypes.intBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.intBaseType);
}
ConcreteType visitLiteralDouble(LiteralDouble node) {
- return new ConcreteType.singleton(inferrer.baseTypes.doubleBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.doubleBaseType);
}
ConcreteType visitLiteralBool(LiteralBool node) {
- return new ConcreteType.singleton(inferrer.baseTypes.boolBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
}
ConcreteType visitLiteralString(LiteralString node) {
@@ -1138,19 +1171,19 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
// the unknown type.
if (inferrer.testMode
&& node.dartString.slowToString() == "__dynamic_for_test") {
- return new ConcreteType.unknown();
+ return inferrer.unknownConcreteType;
}
- return new ConcreteType.singleton(inferrer.baseTypes.stringBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.stringBaseType);
}
ConcreteType visitStringJuxtaposition(StringJuxtaposition node) {
analyze(node.first);
analyze(node.second);
- return new ConcreteType.singleton(inferrer.baseTypes.stringBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.stringBaseType);
}
ConcreteType visitLiteralNull(LiteralNull node) {
- return new ConcreteType.singleton(const NullBaseType());
+ return inferrer.singletonConcreteType(const NullBaseType());
}
ConcreteType visitNewExpression(NewExpression node) {
@@ -1163,11 +1196,11 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType visitLiteralList(LiteralList node) {
visitNodeList(node.elements);
- return new ConcreteType.singleton(inferrer.baseTypes.listBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.listBaseType);
}
ConcreteType visitNodeList(NodeList node) {
- ConcreteType type = new ConcreteType.empty();
+ ConcreteType type = inferrer.emptyConcreteType;
// The concrete type of a sequence of statements is the union of the
// statement's types.
for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
@@ -1183,13 +1216,13 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType visitReturn(Return node) {
final expression = node.expression;
return (expression == null)
- ? new ConcreteType.singleton(const NullBaseType())
+ ? inferrer.singletonConcreteType(const NullBaseType())
: analyze(expression);
}
ConcreteType visitThrow(Throw node) {
if (node.expression != null) analyze(node.expression);
- return new ConcreteType.empty();
+ return inferrer.emptyConcreteType;
}
ConcreteType visitTypeAnnotation(TypeAnnotation node) {
@@ -1205,12 +1238,12 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
link = link.tail) {
analyze(link.head);
}
- return new ConcreteType.empty();
+ return inferrer.emptyConcreteType;
}
ConcreteType visitWhile(While node) {
analyze(node.condition);
- ConcreteType result = new ConcreteType.empty();
+ ConcreteType result = inferrer.emptyConcreteType;
ConcreteTypesEnvironment oldEnvironment;
do {
oldEnvironment = environment;
@@ -1238,25 +1271,25 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType visitStringInterpolation(StringInterpolation node) {
node.visitChildren(this);
- return new ConcreteType.singleton(inferrer.baseTypes.stringBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.stringBaseType);
}
ConcreteType visitStringInterpolationPart(StringInterpolationPart node) {
node.visitChildren(this);
- return new ConcreteType.singleton(inferrer.baseTypes.stringBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.stringBaseType);
}
ConcreteType visitEmptyStatement(EmptyStatement node) {
- return new ConcreteType.empty();
+ return inferrer.emptyConcreteType;
}
ConcreteType visitBreakStatement(BreakStatement node) {
- return new ConcreteType.empty();
+ return inferrer.emptyConcreteType;
}
ConcreteType visitContinueStatement(ContinueStatement node) {
// TODO(polux): we can be more precise
- return new ConcreteType.empty();
+ return inferrer.emptyConcreteType;
}
ConcreteType visitForIn(ForIn node) {
@@ -1273,7 +1306,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType visitLiteralMap(LiteralMap node) {
visitNodeList(node.entries);
- return new ConcreteType.singleton(inferrer.baseTypes.mapBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.mapBaseType);
}
ConcreteType visitLiteralMapEntry(LiteralMapEntry node) {
@@ -1357,7 +1390,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
// node is a field of not(this)
assert(node.receiver != null);
- ConcreteType result = new ConcreteType.empty();
+ ConcreteType result = inferrer.emptyConcreteType;
void augmentResult(BaseType baseReceiverType, Element member) {
if (member.isField()) {
result = result.union(analyzeFieldRead(member));
@@ -1403,7 +1436,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType analyzeDynamicSend(ConcreteType receiverType,
SourceString canonicalizedMethodName,
ArgumentsTypes argumentsTypes) {
- ConcreteType result = new ConcreteType.empty();
+ ConcreteType result = inferrer.emptyConcreteType;
if (receiverType.isUnkown()) {
List<Element> methods =
@@ -1448,7 +1481,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType visitDynamicSend(Send node) {
ConcreteType receiverType = (node.receiver != null)
? analyze(node.receiver)
- : new ConcreteType.singleton(
+ : inferrer.singletonConcreteType(
new ClassBaseType(currentMethod.getEnclosingClass()));
SourceString name =
canonicalizeMethodName(node.selector.asIdentifier().source);
@@ -1459,7 +1492,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
argumentsTypes);
return returnType.isEmpty()
? returnType
- : new ConcreteType.singleton(inferrer.baseTypes.boolBaseType);
+ : inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
} else {
return analyzeDynamicSend(receiverType, name, argumentsTypes);
}
@@ -1481,6 +1514,6 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
}
ConcreteType visitTypeReferenceSend(Send) {
- return new ConcreteType.singleton(inferrer.baseTypes.typeBaseType);
+ return inferrer.singletonConcreteType(inferrer.baseTypes.typeBaseType);
}
}

Powered by Google App Engine
This is Rietveld 408576698