Chromium Code Reviews| Index: lib/compiler/implementation/closure.dart |
| =================================================================== |
| --- lib/compiler/implementation/closure.dart (revision 11792) |
| +++ lib/compiler/implementation/closure.dart (working copy) |
| @@ -19,7 +19,7 @@ |
| String get name => "Closure Simplifier"; |
| ClosureClassMap computeClosureToClassMapping(FunctionExpression node, |
| - TreeElements elements) { |
| + TreeElements elements) { |
| return measure(() { |
| ClosureClassMap cached = closureMappingCache[node]; |
| if (cached !== null) return cached; |
| @@ -141,6 +141,10 @@ |
| final Set<Element> usedVariablesInTry; |
| + // A map from the parameter element to the variable element that |
| + // holds the sentinel check. |
| + final Map<Element, Element> parametersWithSentinel; |
| + |
| ClosureClassMap(this.closureElement, |
| this.closureClassElement, |
| this.callElement, |
| @@ -148,7 +152,8 @@ |
| : this.freeVariableMapping = new Map<Element, Element>(), |
| this.capturedFieldMapping = new Map<Element, Element>(), |
| this.capturingScopes = new Map<Node, ClosureScope>(), |
| - this.usedVariablesInTry = new Set<Element>(); |
| + this.usedVariablesInTry = new Set<Element>(), |
| + this.parametersWithSentinel = new Map<Element, Element>(); |
| bool isClosure() => closureElement !== null; |
| } |
| @@ -312,6 +317,26 @@ |
| useLocal(closureData.thisElement); |
| } else if (node.isSuperCall) { |
| useLocal(closureData.thisElement); |
| + } else if (node.isOperator |
| + && node.argumentsNode is Prefix |
| + && node.selector.source.stringValue == '?') { |
| + Element parameter = elements[node.receiver]; |
| + FunctionElement enclosing = parameter.enclosingElement; |
| + if (currentFunctionElement != enclosing) { |
| + // If the parameter is from an outer function, we need to put |
| + // the check in a field of the closure class. |
| + FunctionExpression node = enclosing.parseNode(compiler); |
| + ClosureClassMap cached = closureMappingCache[node]; |
| + if (!cached.parametersWithSentinel.containsKey(parameter)) { |
| + SourceString parameterName = parameter.name; |
| + String name = '${parameterName.slowToString()}_check'; |
|
kasperl
2012/09/04 10:50:08
Is it a problem if this conflicts with other param
ngeoffray
2012/09/04 10:53:44
No, the namer will disambiguate the elements.
|
| + Element newElement = new Element(new SourceString(name), |
| + ElementKind.VARIABLE, |
| + enclosing); |
| + useLocal(newElement); |
| + cached.parametersWithSentinel[parameter] = newElement; |
| + } |
| + } |
| } |
| node.visitChildren(this); |
| } |
| @@ -478,6 +503,7 @@ |
| } |
| closureData = new ClosureClassMap(null, null, null, thisElement); |
| } |
| + closureMappingCache[node] = closureData; |
| inNewScope(node, () { |
| // We have to declare the implicit 'this' parameter. |
| @@ -501,7 +527,6 @@ |
| if (node.body !== null) node.body.accept(this); |
| }); |
| - closureMappingCache[node] = closureData; |
| ClosureClassMap savedClosureData = closureData; |
| bool savedInsideClosure = insideClosure; |