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

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

Issue 12528008: Implement CHA through type mask and TypedSelector in the simple type inferrer. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (revision 19615)
+++ sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (working copy)
@@ -15,7 +15,7 @@
// of Selector from dart2jslib.dart fail. For now, we work around that
// by importing universe.dart explicitly and disabling the re-export.
import '../dart2jslib.dart' hide Selector;
-import '../universe/universe.dart' show Selector;
+import '../universe/universe.dart' show Selector, TypedSelector;
/**
* A work queue that ensures there are no duplicates, and adds and
@@ -254,7 +254,7 @@
if (selector == null || selector.isSetter() || selector.isIndexSet()) {
return null;
}
- return getTypeIfValuable(returnTypeOfSelector(selector));
+ return getTypeIfValuable(typeOfSelector(selector));
}
/**
@@ -319,27 +319,28 @@
void initializeTypes() {
// TODO(ngeoffray): Is that the right type?
- nullType = new TypeMask.exact(compiler.nullClass.computeType(compiler));
+ Backend backend = compiler.backend;
+ nullType = new TypeMask.exact(
+ backend.nullImplementation.computeType(compiler));
intType = new TypeMask.nonNullExact(
- compiler.intClass.rawType);
+ compiler.backend.intImplementation.rawType);
doubleType = new TypeMask.nonNullExact(
- compiler.doubleClass.rawType);
- // TODO(ngeoffray): Switch to subtype once we do proper union.
- numType = new TypeMask.nonNullExact(
- compiler.numClass.rawType);
+ backend.doubleImplementation.rawType);
+ numType = new TypeMask.nonNullSubclass(
+ backend.numImplementation.rawType);
stringType = new TypeMask.nonNullExact(
- compiler.stringClass.rawType);
+ backend.stringImplementation.rawType);
boolType = new TypeMask.nonNullExact(
- compiler.boolClass.rawType);
+ backend.boolImplementation.rawType);
listType = new TypeMask.nonNullExact(
- compiler.listClass.rawType);
- mapType = new TypeMask.nonNullExact(
- compiler.mapClass.rawType);
+ backend.listImplementation.rawType);
+ mapType = new TypeMask.nonNullSubtype(
+ backend.mapImplementation.rawType);
functionType = new TypeMask.nonNullSubtype(
- compiler.functionClass.rawType);
+ backend.functionImplementation.rawType);
typeType = new TypeMask.nonNullExact(
- compiler.typeClass.rawType);
+ backend.typeImplementation.rawType);
}
dump() {
@@ -461,10 +462,10 @@
}
/**
- * Returns the union of the return types of all elements that match
+ * Returns the union of the types of all elements that match
* the called [selector].
*/
- TypeMask returnTypeOfSelector(Selector selector) {
+ TypeMask typeOfSelector(Selector selector) {
TypeMask result;
iterateOverElements(selector, (Element element) {
assert(element.isImplementation);
@@ -552,22 +553,6 @@
}
/**
- * Registers that [caller] accesses an element matching [selector]
- * through a property access.
- */
- void registerGetterOnSelector(Element caller, Selector selector) {
- assert(isNotClosure(caller));
- if (analyzeCount.containsKey(caller)) return;
- iterateOverElements(selector, (Element element) {
- assert(element.isImplementation);
- Set<Element> callers = callersOf.putIfAbsent(
- element, () => new Set<Element>());
- callers.add(caller);
- return true;
- });
- }
-
- /**
* Registers that [caller] closurizes [function].
*/
void registerGetFunction(Element caller, Element function) {
@@ -872,6 +857,26 @@
return returnType;
}
+ TypeMask _thisType;
+ TypeMask get thisType {
+ if (_thisType != null) return _thisType;
+ ClassElement cls = outermostElement.getEnclosingClass();
+ if (compiler.world.isUsedAsMixin(cls)) {
+ return _thisType = new TypeMask.nonNullSubtype(cls.rawType);
+ } else if (compiler.world.hasAnySubclass(cls)) {
+ return _thisType = new TypeMask.nonNullSubclass(cls.rawType);
+ } else {
+ return _thisType = new TypeMask.nonNullExact(cls.rawType);
+ }
+ }
+
+ TypeMask _superType;
+ TypeMask get superType {
+ if (_superType != null) return _superType;
+ return _superType = new TypeMask.nonNullExact(
+ outermostElement.getEnclosingClass().superclass);
+ }
+
void recordReturnType(TypeMask type) {
returnType = inferrer.computeLUB(returnType, type);
}
@@ -1072,9 +1077,11 @@
}
TypeMask visitIdentifier(Identifier node) {
- if (node.isThis() || node.isSuper()) {
- // TODO(ngeoffray): Represent subclasses.
+ if (node.isThis()) {
+ // TODO(ngeoffray): use subtypes and subclasses masks when inferring.
return inferrer.dynamicType;
kasperl 2013/03/07 14:09:17 Use thisType?
ngeoffray 2013/03/08 11:32:37 Done.
+ } else if (node.isSuper()) {
+ return superType;
}
return inferrer.dynamicType;
}
@@ -1125,29 +1132,31 @@
if (typesReturned.isEmpty) return inferrer.dynamicType;
TypeMask returnType;
for (var type in typesReturned) {
- ClassElement mappedType;
+ TypeMask mappedType;
if (type == native.SpecialType.JsObject) {
- mappedType = compiler.objectClass;
+ mappedType = new TypeMask.nonNullExact(compiler.objectClass.rawType);
} else if (type == native.SpecialType.JsArray) {
- mappedType = compiler.listClass;
+ mappedType = inferrer.listType;
+ } else if (type.element == compiler.stringClass) {
+ mappedType = inferrer.stringType;
+ } else if (type.element == compiler.intClass) {
+ mappedType = inferrer.intType;
+ } else if (type.element == compiler.doubleClass) {
+ mappedType = inferrer.doubleType;
+ } else if (type.element == compiler.numClass) {
+ mappedType = inferrer.numType;
+ } else if (type.element == compiler.boolClass) {
+ mappedType = inferrer.boolType;
} else {
- mappedType = type.element;
- // For primitive types, we know how to handle them here and
- // in the backend.
- if (mappedType != compiler.stringClass
- && mappedType != compiler.intClass
- && mappedType != compiler.doubleClass
- && mappedType != compiler.boolClass
- && mappedType != compiler.numClass) {
- Set<ClassElement> subtypes = compiler.world.subtypes[mappedType];
- // TODO(ngeoffray): Handle subtypes and subclasses.
- if (subtypes != null && !subtypes.isEmpty) {
- return inferrer.dynamicType;
- }
+ Set<ClassElement> subtypes = compiler.world.subtypes[type.element];
+ // TODO(ngeoffray): Handle subtypes and subclasses.
kasperl 2013/03/07 14:09:17 Isn't this completely trivial?
ngeoffray 2013/03/08 11:32:37 Yes. Done.
+ if (subtypes != null && !subtypes.isEmpty) {
+ return inferrer.dynamicType;
}
+ mappedType = new TypeMask.nonNullExact(type.element.rawType);
}
if (returnType == null) {
- returnType = new TypeMask.nonNullExact(mappedType.rawType);
+ returnType = mappedType;
} else {
return inferrer.dynamicType;
}
@@ -1223,16 +1232,7 @@
inferrer.registerGetterOnElement(outermostElement, element);
return inferrer.typeOfElement(element);
} else if (Elements.isInstanceSend(node, elements)) {
- TypeMask receiverType;
- if (node.receiver == null) {
- // TODO(ngeoffray): Use subclass or subtype if the class is
- // used as a mixin.
- receiverType = inferrer.dynamicType;
- } else {
- receiverType = node.receiver.accept(this);
- }
- Selector selector = elements.getSelector(node);
- return handleDynamicSend(selector, receiverType, null);
+ return visitDynamicSend(node);
} else if (Elements.isStaticOrTopLevelFunction(element)) {
inferrer.registerGetFunction(outermostElement, element);
return inferrer.functionType;
@@ -1263,27 +1263,31 @@
TypeMask handleDynamicSend(Selector selector,
TypeMask receiver,
ArgumentsTypes arguments) {
- if (selector.isGetter()) {
- assert(arguments == null);
- inferrer.registerGetterOnSelector(outermostElement, selector);
- } else if (selector.isSetter()) {
+ if (selector.isSetter()) {
// TODO(ngeoffray): Register called setter.
+ // We return null to prevent using a type for a called setter.
+ // The return type is the right hand side of the setter.
+ return null;
} else {
inferrer.registerCalledSelector(outermostElement, selector, arguments);
}
- return inferrer.returnTypeOfSelector(selector);
+ if (!inferrer.isDynamicType(receiver)) {
+ selector = new TypedSelector(receiver, selector);
+ }
+ return inferrer.typeOfSelector(selector);
}
TypeMask visitDynamicSend(Send node) {
+ Element element = elements[node];
TypeMask receiverType;
- if (node.receiver == null) {
- // TODO(ngeoffray): Use subclass or subtype if the class is
- // used as a mixin.
- receiverType = inferrer.dynamicType;
+ if (element != null && element.isInstanceMember()) {
+ receiverType = thisType;
} else {
receiverType = visit(node.receiver);
}
- ArgumentsTypes arguments = analyzeArguments(node.arguments);
+ ArgumentsTypes arguments = node.isPropertyAccess
+ ? null
+ : analyzeArguments(node.arguments);
Selector selector = elements.getSelector(node);
return handleDynamicSend(selector, receiverType, arguments);
}

Powered by Google App Engine
This is Rietveld 408576698