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 |
+ // 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 |
+ || superclass.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 |