Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| =================================================================== |
| --- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 19293) |
| +++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
| @@ -185,39 +185,38 @@ |
| // 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) { |
| - 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 = builder.addParameter(scopeData.boxElement); |
| + if (scopeData == null) return; |
| + 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 = builder.addParameter(scopeData.boxElement); |
| + } 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 |
| + // need to make sure that parameters are copied into the box if necessary. |
| + scopeData.capturedVariableMapping.forEach((Element from, Element to) { |
| + // The [from] can only be a parameter for function-scopes and not |
| + // loop scopes. |
| + if (from.isParameter() && !element.isGenerativeConstructorBody()) { |
| + // Now that the redirection is set up, the update to the local will |
| + // write the parameter value into the box. |
| + // Store the captured parameter in the box. Get the current value |
| + // before we put the redirection in place. |
| + // We don't need to update the local for a generative |
| + // constructor body, because it receives a box that already |
| + // contains the updates as the last parameter. |
| + HInstruction instruction = readLocal(from); |
| + redirectElement(from, to); |
| + updateLocal(from, instruction); |
| } else { |
| - box = createBox(); |
| + redirectElement(from, to); |
| } |
| - // 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 |
| - // need to make sure that parameters are copied into the box if necessary. |
| - scopeData.capturedVariableMapping.forEach((Element from, Element to) { |
| - // The [from] can only be a parameter for function-scopes and not |
| - // loop scopes. |
| - if (from.isParameter() && !element.isGenerativeConstructorBody()) { |
| - // Now that the redirection is set up, the update to the local will |
| - // write the parameter value into the box. |
| - // Store the captured parameter in the box. Get the current value |
| - // before we put the redirection in place. |
| - // We don't need to update the local for a generative |
| - // constructor body, because it receives a box that already |
| - // contains the updates as the last parameter. |
| - HInstruction instruction = readLocal(from); |
| - redirectElement(from, to); |
| - updateLocal(from, instruction); |
| - } else { |
| - redirectElement(from, to); |
| - } |
| - }); |
| - } |
| + }); |
| } |
| /** |
| @@ -1144,7 +1143,8 @@ |
| Link<Node> arguments, |
| List<FunctionElement> constructors, |
| Map<Element, HInstruction> fieldValues, |
| - FunctionElement inlinedFromElement) { |
| + FunctionElement inlinedFromElement, |
| + Node callNode) { |
| compiler.withCurrentElement(constructor, () { |
| assert(invariant(constructor, constructor.isImplementation)); |
| constructors.addLast(constructor); |
| @@ -1164,6 +1164,30 @@ |
| element: constructor); |
| } |
| + ClassElement superclass = constructor.getEnclosingClass(); |
| + if (compiler.world.needsRti(superclass)) { |
| + // If [superclass] needs rti, we have to give a value to its |
|
kasperl
2013/03/01 12:05:34
rti -> RTI
ngeoffray
2013/03/01 12:14:08
Done.
|
| + // type parameters. Those values are in the [supertype] |
| + // declaration of [subclass]. |
| + ClassElement subclass = inlinedFromElement.getEnclosingClass(); |
| + DartType supertype = subclass.supertype; |
| + Link<DartType> typeVariables = superclass.typeVariables; |
| + supertype.typeArguments.forEach((DartType argument) { |
| + localsHandler.updateLocal(typeVariables.head.element, |
| + analyzeTypeArgument(argument, callNode)); |
| + typeVariables = typeVariables.tail; |
| + }); |
| + // If the supertype is a raw type, we need to set to null the |
| + // type variables. |
| + assert(typeVariables.isEmpty |
| + || superType.typeVariables == typeVariables); |
| + while (!typeVariables.isEmpty) { |
| + localsHandler.updateLocal(typeVariables.head.element, |
| + graph.addConstantNull(constantSystem)); |
| + typeVariables = typeVariables.tail; |
| + } |
| + } |
| + |
| inlinedFrom(constructor, () { |
| buildFieldInitializers(constructor.enclosingElement.implementation, |
| fieldValues); |
| @@ -1246,7 +1270,7 @@ |
| Selector selector = elements.getSelector(call); |
| Link<Node> arguments = call.arguments; |
| inlineSuperOrRedirect(target, selector, arguments, constructors, |
| - fieldValues, constructor); |
| + fieldValues, constructor, call); |
| foundSuperOrRedirect = true; |
| } else { |
| // A field initializer. |
| @@ -1281,7 +1305,8 @@ |
| const Link<Node>(), |
| constructors, |
| fieldValues, |
| - constructor); |
| + constructor, |
| + functionNode); |
| } |
| } |
| } |
| @@ -1389,12 +1414,12 @@ |
| add(newObject); |
| // Create the runtime type information, if needed. |
| - List<HInstruction> inputs = <HInstruction>[]; |
| if (compiler.world.needsRti(classElement)) { |
| + List<HInstruction> rtiInputs = <HInstruction>[]; |
| classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
| - inputs.add(localsHandler.directLocals[typeVariable.element]); |
| + rtiInputs.add(localsHandler.readLocal(typeVariable.element)); |
| }); |
| - callSetRuntimeTypeInfo(classElement, inputs, newObject); |
| + callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); |
| } |
| // Generate calls to the constructor bodies. |
| @@ -1405,23 +1430,22 @@ |
| if (body == null) continue; |
| List bodyCallInputs = <HInstruction>[]; |
| bodyCallInputs.add(newObject); |
| - FunctionSignature functionSignature = body.computeSignature(compiler); |
| - functionSignature.orderedForEachParameter((parameter) { |
| - if (!localsHandler.isBoxed(parameter)) { |
| - // The parameter will be a field in the box passed as the |
| - // last parameter. So no need to pass it. |
| - bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| - } |
| - }); |
| - |
| - // If parameters are checked, we pass the already computed |
| - // boolean to the constructor body. |
| TreeElements elements = |
| compiler.enqueuer.resolution.getCachedElements(constructor); |
| Node node = constructor.parseNode(compiler); |
| ClosureClassMap parameterClosureData = |
| compiler.closureToClassMapper.getMappingForNestedFunction(node); |
| + |
| + |
| + FunctionSignature functionSignature = body.computeSignature(compiler); |
| functionSignature.orderedForEachParameter((parameter) { |
| + // if [parameter] is boxed, it will be a field in the box passed as the |
| + // last parameter. So no need to direclty pass it. |
| + if (!localsHandler.isBoxed(parameter)) { |
| + bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| + } |
| + // If [parameter] is checked, we pass the already computed |
| + // boolean to the constructor body. |
| if (elements.isParameterChecked(parameter)) { |
| Element fieldCheck = |
| parameterClosureData.parametersWithSentinel[parameter]; |
| @@ -1429,7 +1453,16 @@ |
| } |
| }); |
| - // If there are locals that escape (ie used in closures), we |
| + ClassElement currentClass = constructor.getEnclosingClass(); |
| + if (compiler.world.needsRti(currentClass)) { |
| + // If [currentClass] needs RTI, we add the type variables as |
| + // parameters of the generative constructor body. |
| + currentClass.typeVariables.forEach((DartType argument) { |
| + bodyCallInputs.add(localsHandler.readLocal(argument.element)); |
| + }); |
| + } |
| + |
| + // If there are locals that escape (ie mutated in closures), we |
| // pass the box to the constructor. |
| ClosureScope scopeData = parameterClosureData.capturingScopes[node]; |
| if (scopeData != null) { |
| @@ -1560,7 +1593,8 @@ |
| // Add the type parameters of the class as parameters of this |
| // method. |
| var enclosing = element.enclosingElement; |
| - if (element.isConstructor() && compiler.world.needsRti(enclosing)) { |
| + if ((element.isConstructor() || element.isGenerativeConstructorBody()) |
| + && compiler.world.needsRti(enclosing)) { |
| enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
| HParameterValue param = addParameter(typeVariable.element); |
| localsHandler.directLocals[typeVariable.element] = param; |
| @@ -3104,11 +3138,10 @@ |
| member = closureClass.methodElement; |
| member = member.getOutermostEnclosingMemberOrTopLevel(); |
| } |
| - if (member.isFactoryConstructor()) { |
| + if (member.isConstructor() || member.isGenerativeConstructorBody()) { |
| // The type variable is stored in a parameter of the method. |
| return localsHandler.readLocal(type.element); |
| - } else if (member.isInstanceMember() || |
| - member.isGenerativeConstructor()) { |
| + } else if (member.isInstanceMember()) { |
| // The type variable is stored on the object. Generate code to extract |
| // the type arguments from the object, substitute them as an instance |
| // of the type we are testing against (if necessary), and extract the |