| Index: lib/compiler/implementation/ssa/builder.dart
|
| ===================================================================
|
| --- lib/compiler/implementation/ssa/builder.dart (revision 14321)
|
| +++ lib/compiler/implementation/ssa/builder.dart (working copy)
|
| @@ -322,15 +322,21 @@
|
| * If the scope (function or loop) [node] has captured variables then this
|
| * method creates a box and sets up the redirections.
|
| */
|
| - void enterScope(Node node) {
|
| + void enterScope(Node node, Element element) {
|
| // See if any variable in the top-scope of the function is captured. If yes
|
| // we need to create a box-object.
|
| ClosureScope scopeData = closureData.capturingScopes[node];
|
| if (scopeData != null) {
|
| - // The scope has captured variables. Create a box.
|
| - // TODO(floitsch): Clean up this hack. Should we create a box-object by
|
| - // just creating an empty object literal?
|
| - HInstruction box = createBox();
|
| + HInstruction box;
|
| + // The scope has captured variables.
|
| + if (element != null && element.isGenerativeConstructorBody()) {
|
| + // The box is passed as a parameter to a generative
|
| + // constructor body.
|
| + box = new HParameterValue(scopeData.boxElement);
|
| + builder.add(box);
|
| + } else {
|
| + box = createBox();
|
| + }
|
| // Add the box to the known locals.
|
| directLocals[scopeData.boxElement] = box;
|
| // Make sure that accesses to the boxed locals go into the box. We also
|
| @@ -398,7 +404,7 @@
|
| });
|
| }
|
|
|
| - enterScope(node);
|
| + enterScope(node, element);
|
|
|
| // If the freeVariableMapping is not empty, then this function was a
|
| // nested closure that captures variables. Redirect the captured
|
| @@ -610,7 +616,7 @@
|
| // redirections already now. This way the initializer can write its
|
| // values into the box.
|
| // For other loops the box will be created when entering the body.
|
| - enterScope(node);
|
| + enterScope(node, null);
|
| }
|
| }
|
|
|
| @@ -641,7 +647,7 @@
|
| // If there are no declared boxed loop variables then we did not create the
|
| // box before the initializer and we have to create the box now.
|
| if (!scopeData.hasBoxedLoopVariables()) {
|
| - enterScope(node);
|
| + enterScope(node, null);
|
| }
|
| }
|
|
|
| @@ -1170,16 +1176,17 @@
|
| compiler.enqueuer.resolution.getCachedElements(constructor);
|
|
|
| ClosureClassMap oldClosureData = localsHandler.closureData;
|
| + Node node = constructor.parseNode(compiler);
|
| localsHandler.closureData =
|
| compiler.closureToClassMapper.computeClosureToClassMapping(
|
| - constructor, constructor.parseNode(compiler), elements);
|
| + constructor, node, elements);
|
|
|
| params.orderedForEachParameter((Element parameterElement) {
|
| if (elements.isParameterChecked(parameterElement)) {
|
| addParameterCheckInstruction(parameterElement);
|
| }
|
| });
|
| -
|
| + localsHandler.enterScope(node, constructor);
|
| buildInitializers(constructor, constructors, fieldValues);
|
| localsHandler.closureData = oldClosureData;
|
| elements = oldElements;
|
| @@ -1369,6 +1376,11 @@
|
| FunctionSignature functionSignature = body.computeSignature(compiler);
|
| int arity = functionSignature.parameterCount;
|
| functionSignature.orderedForEachParameter((parameter) {
|
| + // TODO(ngeoffray): No need to pass the parameters that are
|
| + // captured and stored in a box. Because this information is
|
| + // not trivial to get in codegen.dart, we just pass the
|
| + // parameters anyway. We need to update both codegen.dart and
|
| + // builder.dart on how parameters are being passed.
|
| bodyCallInputs.add(localsHandler.readLocal(parameter));
|
| });
|
|
|
| @@ -1387,6 +1399,13 @@
|
| }
|
| });
|
|
|
| + // If there are locals that escape (ie used in closures), we
|
| + // pass the box to the constructor.
|
| + ClosureScope scopeData = parameterClosureData.capturingScopes[node];
|
| + if (scopeData != null) {
|
| + bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement));
|
| + }
|
| +
|
| // TODO(ahe): The constructor name is statically resolved. See
|
| // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner
|
| // way to do this?
|
|
|