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

Unified Diff: sdk/lib/_internal/compiler/implementation/resolution/members.dart

Issue 26232003: Support type promotion in dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 7 years, 2 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/resolution/members.dart
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index f09879ab20914fcddc018b49ab112a750cde9c09..e6a1c2096bc227c0884a25b2ac2b97ba8a582614 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -39,6 +39,19 @@ abstract class TreeElements {
/// Register additional dependencies required by [currentElement].
/// For example, elements that are used by a backend.
void registerDependency(Element element);
+
+ /// Returns [:true:] if [element] is potentially mutated anywhere in its
+ /// scope.
+ bool isPotentiallyMutated(VariableElement element);
+
+ /// Returns [:true:] if [element] is potentially mutated in [node].
+ bool isPotentiallyMutatedIn(Node node, VariableElement element);
+
+ /// Returns [:true:] if [element] is potentially mutated in a closure.
+ bool isPotentiallyMutatedInClosure(VariableElement element);
+
+ /// Returns [:true:] if [element] is accessed by a closure in [node].
+ bool isAccessedByClosureIn(Node node, VariableElement element);
}
class TreeElementMapping implements TreeElements {
@@ -49,6 +62,13 @@ class TreeElementMapping implements TreeElements {
final Set<Node> superUses = new LinkedHashSet<Node>();
final Set<Element> otherDependencies = new LinkedHashSet<Element>();
final Map<Node, Constant> constants = new Map<Node, Constant>();
+ final Set<VariableElement> potentiallyMutated = new Set<VariableElement>();
+ final Map<Node, Set<VariableElement>> potentiallyMutatedIn =
+ new Map<Node, Set<VariableElement>>();
+ final Set<VariableElement> potentiallyMutatedInClosure =
+ new Set<VariableElement>();
+ final Map<Node, Set<VariableElement>> accessedByClosureIn =
+ new Map<Node, Set<VariableElement>>();
final int hashCode = ++hashCodeCounter;
static int hashCodeCounter = 0;
@@ -159,6 +179,42 @@ class TreeElementMapping implements TreeElements {
otherDependencies.add(element.implementation);
}
+ bool isPotentiallyMutated(VariableElement element) {
+ return potentiallyMutated.contains(element);
+ }
+
+ void setPotentiallyMutated(VariableElement element) {
+ potentiallyMutated.add(element);
+ }
+
+ bool isPotentiallyMutatedIn(Node node, VariableElement element) {
+ Set<Element> mutatedIn = potentiallyMutatedIn[node];
+ return mutatedIn != null && mutatedIn.contains(element);
+ }
+
+ void setPotentiallyMutatedIn(Node node, VariableElement element) {
+ potentiallyMutatedIn.putIfAbsent(
+ node, () => new Set<VariableElement>()).add(element);
+ }
+
+ bool isPotentiallyMutatedInClosure(VariableElement element) {
+ return potentiallyMutatedInClosure.contains(element);
+ }
+
+ void setPotentiallyMutatedInClosure(VariableElement element) {
+ potentiallyMutatedInClosure.add(element);
+ }
+
+ bool isAccessedByClosureIn(Node node, VariableElement element) {
+ Set<Element> accessedIn = accessedByClosureIn[node];
+ return accessedIn != null && accessedIn.contains(element);
+ }
+
+ void setAccessedByClosureIn(Node node, VariableElement element) {
+ accessedByClosureIn.putIfAbsent(
+ node, () => new Set<VariableElement>()).add(element);
+ }
+
String toString() => 'TreeElementMapping($currentElement)';
}
@@ -1846,6 +1902,16 @@ class ResolverVisitor extends MappingVisitor<Element> {
/// error when verifying that all final variables are initialized.
bool allowFinalWithoutInitializer = false;
+ /// The nodes for which variable access and mutation must be registed in order
karlklose 2013/10/15 11:56:17 'registed' -> 'registered'.
Johnni Winther 2013/10/15 15:57:00 Done.
+ /// to determine when variable types are promoted.
karlklose 2013/10/15 11:56:17 'when the static type of variables is promoted.'
Johnni Winther 2013/10/15 15:57:00 Done.
+ Link<Node> promotionScope = const Link<Node>();
+
+ bool isPotentiallyMutableTarget(Element target) {
+ if (target == null) return false;
+ return (target.isVariable() || target.isParameter()) &&
+ !(target.modifiers.isFinal() || target.modifiers.isConst());
+ }
+
// TODO(ahe): Find a way to share this with runtime implementation.
static final RegExp symbolValidationPattern =
new RegExp(r'^(?:[a-zA-Z$][a-zA-Z$0-9_]*\.)*(?:[a-zA-Z$][a-zA-Z$0-9_]*=?|'
@@ -1944,6 +2010,13 @@ class ResolverVisitor extends MappingVisitor<Element> {
return result;
}
+ doInPromotionScope(Node node, action()) {
+ promotionScope = promotionScope.prepend(node);
+ var result = action();
+ promotionScope = promotionScope.tail;
+ return result;
+ }
+
visitInStaticContext(Node node) {
inStaticContext(() => visit(node));
}
@@ -2186,8 +2259,9 @@ class ResolverVisitor extends MappingVisitor<Element> {
}
visitIf(If node) {
- visit(node.condition);
- visitIn(node.thenPart, new BlockScope(scope));
+ doInPromotionScope(node.condition.expression, () => visit(node.condition));
+ doInPromotionScope(node.thenPart, () =>
karlklose 2013/10/15 11:56:17 Break line before closure.
Johnni Winther 2013/10/15 15:57:00 Done.
+ visitIn(node.thenPart, new BlockScope(scope)));
visitIn(node.elsePart, new BlockScope(scope));
}
@@ -2413,7 +2487,12 @@ class ResolverVisitor extends MappingVisitor<Element> {
visitSend(Send node) {
bool oldSendIsMemberAccess = sendIsMemberAccess;
sendIsMemberAccess = node.isPropertyAccess || node.isCall;
- Element target = resolveSend(node);
+ Element target;
+ if (node.isLogicalAnd) {
+ target = doInPromotionScope(node.receiver, () => resolveSend(node));
+ } else {
+ target = resolveSend(node);
+ }
sendIsMemberAccess = oldSendIsMemberAccess;
if (target != null
@@ -2453,6 +2532,13 @@ class ResolverVisitor extends MappingVisitor<Element> {
// Don't try to make constants of calls to type literals.
analyzeConstant(node, isConst: !node.isCall);
}
+ if (isPotentiallyMutableTarget(target)) {
+ if (enclosingElement != target.enclosingElement) {
+ for (Node scope in promotionScope) {
+ mapping.setAccessedByClosureIn(scope, target);
+ }
+ }
+ }
}
bool resolvedArguments = false;
@@ -2471,6 +2557,10 @@ class ResolverVisitor extends MappingVisitor<Element> {
compiler.enqueuer.resolution.registerAsCheck(type, mapping);
}
resolvedArguments = true;
+ } else if (identical(operatorString, '&&')) {
+ doInPromotionScope(node.arguments.head,
+ () => resolveArguments(node.argumentsNode));
+ resolvedArguments = true;
}
}
@@ -2573,6 +2663,15 @@ class ResolverVisitor extends MappingVisitor<Element> {
node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER);
compiler.backend.registerThrowNoSuchMethod(mapping);
}
+ if (isPotentiallyMutableTarget(target)) {
+ mapping.setPotentiallyMutated(target);
+ if (enclosingElement != target.enclosingElement) {
+ mapping.setPotentiallyMutatedInClosure(target);
+ }
+ for (Node scope in promotionScope) {
+ mapping.setPotentiallyMutatedIn(scope, target);
+ }
+ }
}
visit(node.argumentsNode);
@@ -2999,7 +3098,9 @@ class ResolverVisitor extends MappingVisitor<Element> {
}
visitConditional(Conditional node) {
- node.visitChildren(this);
+ doInPromotionScope(node.condition, () => visit(node.condition));
+ doInPromotionScope(node.thenExpression, () => visit(node.thenExpression));
+ visit(node.elseExpression);
}
visitStringInterpolation(StringInterpolation node) {

Powered by Google App Engine
This is Rietveld 408576698