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

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

Issue 19619006: Make the loop/break/continue handling in the inferrer both simpler, and more generic. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart (revision 25340)
+++ sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart (working copy)
@@ -48,6 +48,25 @@
* [secondType].
*/
T computeLUB(T firstType, T secondType);
+
+ /**
+ * Returns a new type for holding the potential types of [element].
+ * [inputType] is the first incoming type of the phi.
+ */
+ T allocatePhi(Node node, Element element, T inputType);
+
+ /**
+ * Simplies the phi representing [element] and of the type
+ * [phiType]. For example, if this phi has one incoming input, an
+ * implementation of this method could just return that incoming
+ * input type.
+ */
+ T simplifyPhi(Node node, Element element, T phiType);
+
+ /**
+ * Adds [newType] as an input of [phiType].
+ */
+ T addPhiInput(Element element, T phiType, T newType);
}
/**
@@ -133,6 +152,18 @@
Selector newTypedSelector(TypeMask receiver, Selector selector) {
return new TypedSelector(receiver, selector);
}
+
+ TypeMask addPhiInput(Element element, TypeMask phiType, TypeMask newType) {
+ return computeLUB(phiType, newType);
+ }
+
+ TypeMask allocatePhi(Node node, Element element, TypeMask inputType) {
+ return inputType;
+ }
+
+ TypeMask simplifyPhi(Node node, Element element, TypeMask phiType) {
+ return phiType;
+ }
}
/**
@@ -186,6 +217,16 @@
variables.forEach(f);
}
+ void forEachLocalUntil(int level, void f(Element, T type)) {
+ if (blockLevel < level) return;
+ forEachOwnLocal(f);
+ if (parent != null) parent.forEachLocalUntil(level, f);
+ }
+
+ void forEachLocal(void f(Element, T type)) {
+ forEachLocalUntil(0, f);
+ }
+
void remove(Element element) {
variables.remove(element);
}
@@ -367,6 +408,46 @@
return changed;
}
+ /**
+ * Merge all [LocalsHandler] in [handlers] into [:this:]. Returns
+ * whether a local in [:this:] has changed.
+ */
+ bool mergeAll(List<LocalsHandler<T>> handlers) {
+ bool changed = false;
+ handlers.forEach((LocalsHandler<T> handler) {
+ if (handler.seenReturnOrThrow) return;
+ int level = locals.blockLevel;
+ handler.locals.forEachLocalUntil(level, (Element local, T otherType) {
+ T myType = locals[local];
+ if (myType == null) return;
+ T newType = types.addPhiInput(local, myType, otherType);
+ if (newType != myType) {
+ changed = true;
+ locals[local] = newType;
+ }
+ });
+ });
+ return changed;
+ }
+
+ void startLoop(Node loop) {
+ locals.forEachLocal((Element element, T type) {
+ T newType = types.allocatePhi(loop, element, type);
+ if (newType != type) {
+ locals[element] = type;
+ }
+ });
+ }
+
+ void endLoop(Node loop) {
+ locals.forEachLocal((Element element, T type) {
+ T newType = types.simplifyPhi(loop, element, type);
+ if (newType != type) {
+ locals[element] = type;
+ }
+ });
+ }
+
void updateField(Element element, T type) {
fieldScope.updateField(element, type);
}
@@ -694,22 +775,18 @@
breaksFor.remove(element);
}
- void mergeBreaks(TargetElement element) {
- if (element == null) return;
- if (!element.isBreakTarget) return;
- for (LocalsHandler<T> handler in breaksFor[element]) {
- locals.merge(handler, discardIfAborts: false);
- }
+ List<LocalsHandler<T>> getBreaks(TargetElement element) {
+ List<LocalsHandler<T>> list = <LocalsHandler<T>>[locals];
+ if (element == null) return list;
+ if (!element.isBreakTarget) return list;
+ return list..addAll(breaksFor[element]);
}
- bool mergeContinues(TargetElement element) {
- if (element == null) return false;
- if (!element.isContinueTarget) return false;
- bool changed = false;
- for (LocalsHandler<T> handler in continuesFor[element]) {
- changed = locals.merge(handler, discardIfAborts: false) || changed;
- }
- return changed;
+ List<LocalsHandler<T>> getLoopBackEdges(TargetElement element) {
+ List<LocalsHandler<T>> list = <LocalsHandler<T>>[locals];
+ if (element == null) return list;
+ if (!element.isContinueTarget) return list;
+ return list..addAll(continuesFor[element]);
}
T handleLoop(Node node, void logic()) {
@@ -717,16 +794,19 @@
bool changed = false;
TargetElement target = elements[node];
setupBreaksAndContinues(target);
+ locals.startLoop(node);
+ LocalsHandler<T> saved;
do {
- LocalsHandler<T> saved = locals;
+ saved = locals;
locals = new LocalsHandler<T>.from(locals);
logic();
- changed = saved.merge(locals);
+ changed = saved.mergeAll(getLoopBackEdges(target));
locals = saved;
- changed = mergeContinues(target) || changed;
} while (changed);
loopLevel--;
- mergeBreaks(target);
+ saved.mergeAll(getBreaks(target));
+ locals = saved;
+ locals.endLoop(node);
clearBreaksAndContinues(target);
}
@@ -821,7 +901,7 @@
TargetElement targetElement = elements[body];
setupBreaksAndContinues(targetElement);
visit(body);
- mergeBreaks(targetElement);
+ locals.mergeAll(getBreaks(targetElement));
clearBreaksAndContinues(targetElement);
}
}
@@ -871,23 +951,25 @@
// visit all cases and update [locals] until we have reached a
// fixed point.
bool changed;
+ locals.startLoop(node);
do {
changed = false;
for (Node switchCase in node.cases) {
LocalsHandler<T> saved = locals;
locals = new LocalsHandler<T>.from(locals);
visit(switchCase);
- changed = saved.merge(locals, discardIfAborts: false) || changed;
+ changed = saved.mergeAll([locals]) || changed;
locals = saved;
}
} while (changed);
+ locals.endLoop(node);
forEachLabeledCase((TargetElement target) {
clearBreaksAndContinues(target);
});
} else {
LocalsHandler<T> saved = locals;
- List<LocalsHandler<T>> localsToMerge = <LocalsHandler>[];
+ List<LocalsHandler<T>> localsToMerge = <LocalsHandler<T>>[];
for (SwitchCase switchCase in node.cases) {
if (switchCase.isDefaultCase) {
@@ -902,9 +984,7 @@
localsToMerge.add(locals);
}
}
- for (LocalsHandler<T> handler in localsToMerge) {
- saved.merge(handler, discardIfAborts: false);
- }
+ saved.mergeAll(localsToMerge);
locals = saved;
}
clearBreaksAndContinues(elements[node]);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698