| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| index 2dfa9d176d98cbdd24fe53d8d69018ee87732a39..7343ea09998696e3fe2d04754f44bcde6ab881e5 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| @@ -115,9 +115,26 @@ class LocalsHandler {
|
| SsaBuilder builder;
|
| ClosureClassMap closureData;
|
|
|
| - LocalsHandler(this.builder)
|
| - : directLocals = new Map<Element, HInstruction>(),
|
| - redirectionMapping = new Map<Element, Element>();
|
| + /// The class that defines the current type environment or null if no type
|
| + /// variables are in scope.
|
| + final ClassElement contextClass;
|
| +
|
| + LocalsHandler(this.builder, this.contextClass)
|
| + : redirectionMapping = new Map<Element, Element>(),
|
| + directLocals = new Map<Element, HInstruction>();
|
| +
|
| + /// Substituted type variables occurring in [type] into the context of
|
| + /// [contextClass].
|
| + DartType substInContext(DartType type) {
|
| + if (contextClass != null) {
|
| + ClassElement typeContext = Types.getClassContext(type);
|
| + if (typeContext != null) {
|
| + type = type.substByContext(
|
| + contextClass.asInstanceOf(typeContext));
|
| + }
|
| + }
|
| + return type;
|
| + }
|
|
|
| get typesTask => builder.compiler.typesTask;
|
|
|
| @@ -129,6 +146,7 @@ class LocalsHandler {
|
| LocalsHandler.from(LocalsHandler other)
|
| : directLocals = new Map<Element, HInstruction>.from(other.directLocals),
|
| redirectionMapping = other.redirectionMapping,
|
| + contextClass = other.contextClass,
|
| builder = other.builder,
|
| closureData = other.closureData;
|
|
|
| @@ -969,7 +987,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| this.work = work,
|
| this.rti = backend.rti,
|
| super(work.resolutionTree, backend.compiler) {
|
| - localsHandler = new LocalsHandler(this);
|
| + localsHandler = new LocalsHandler(this, work.element.contextClass);
|
| sourceElementStack.add(work.element);
|
| }
|
|
|
| @@ -1526,7 +1544,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| */
|
| void setupStateForInlining(FunctionElement function,
|
| List<HInstruction> compiledArguments) {
|
| - localsHandler = new LocalsHandler(this);
|
| + localsHandler = new LocalsHandler(this, function.contextClass);
|
| localsHandler.closureData =
|
| compiler.closureToClassMapper.computeClosureToClassMapping(
|
| function, function.parseNode(compiler), elements);
|
| @@ -1620,31 +1638,9 @@ class SsaBuilder extends ResolvedVisitor {
|
| if (!compiler.enableTypeAssertions) return;
|
|
|
| FunctionSignature signature = function.functionSignature;
|
| -
|
| - InterfaceType contextType;
|
| - if (function.isSynthesized && function.isGenerativeConstructor) {
|
| - // Synthesized constructors reuse the parameters from the
|
| - // [targetConstructor]. In face of generic types, the type variables
|
| - // occurring in the parameter types must be substituted by the type
|
| - // arguments of the enclosing class.
|
| - FunctionElement target = function;
|
| - while (target.targetConstructor != null) {
|
| - target = target.targetConstructor;
|
| - }
|
| - if (target != function) {
|
| - ClassElement functionClass = function.enclosingClass;
|
| - ClassElement targetClass = target.enclosingClass;
|
| - contextType = functionClass.thisType.asInstanceOf(targetClass);
|
| - }
|
| - }
|
| -
|
| signature.orderedForEachParameter((ParameterElement parameter) {
|
| HInstruction argument = localsHandler.readLocal(parameter);
|
| - DartType parameterType = parameter.type;
|
| - if (contextType != null) {
|
| - parameterType = parameterType.substByContext(contextType);
|
| - }
|
| - potentiallyCheckType(argument, parameterType);
|
| + potentiallyCheckType(argument, parameter.type);
|
| });
|
| }
|
|
|
| @@ -1671,6 +1667,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| // the current type. [InterfaceType.asInstanceOf] takes care
|
| // of both.
|
| InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass);
|
| + type = localsHandler.substInContext(type);
|
| Link<DartType> typeVariables = enclosingClass.typeVariables;
|
| type.typeArguments.forEach((DartType argument) {
|
| localsHandler.updateLocal(
|
| @@ -1938,14 +1935,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| assert(isNativeUpgradeFactory);
|
| } else {
|
| fields.add(member);
|
| - DartType type = member.type;
|
| - if (enclosingClass.isMixinApplication) {
|
| - // TODO(johnniwinther): Add a member-like abstraction for fields
|
| - // that normalizes this.
|
| - type = type.substByContext(
|
| - enclosingClass.thisType.asInstanceOf(
|
| - member.enclosingElement));
|
| - }
|
| + DartType type = localsHandler.substInContext(member.type);
|
| constructorArguments.add(potentiallyCheckType(value, type));
|
| }
|
| },
|
| @@ -2088,6 +2078,8 @@ class SsaBuilder extends ResolvedVisitor {
|
| // If [currentClass] needs RTI, we add the type variables as
|
| // parameters of the generative constructor body.
|
| currentClass.typeVariables.forEach((DartType argument) {
|
| + // TODO(johnniwinther): Substitute [argument] with
|
| + // `localsHandler.substInContext(argument)`.
|
| bodyCallInputs.add(localsHandler.readLocal(argument.element));
|
| });
|
| }
|
| @@ -2180,11 +2172,29 @@ class SsaBuilder extends ResolvedVisitor {
|
| }
|
| }
|
|
|
| + /// Check that [type] is valid in the context of `localsHandler.contextClass`.
|
| + /// This should only be called in assertions.
|
| + bool assertTypeInContext(DartType type, [Spannable spannable]) {
|
| + return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable,
|
| + () {
|
| + ClassElement contextClass = Types.getClassContext(type);
|
| + return contextClass == null ||
|
| + contextClass == localsHandler.contextClass;
|
| + },
|
| + message: "Type '$type' is not valid context of "
|
| + "${localsHandler.contextClass}.");
|
| + }
|
| +
|
| + /// Build a [HTypeConversion] for convertion [original] to type [type].
|
| + ///
|
| + /// Invariant: [type] must be valid in the context.
|
| + /// See [LocalsHandler.substInContext].
|
| HInstruction buildTypeConversion(HInstruction original,
|
| DartType type,
|
| int kind) {
|
| if (type == null) return original;
|
| type = type.unalias(compiler);
|
| + assert(assertTypeInContext(type, original));
|
| if (type.kind == TypeKind.INTERFACE && !type.treatAsRaw) {
|
| TypeMask subtype = new TypeMask.subtype(type.element);
|
| HInstruction representations = buildTypeArgumentRepresentations(type);
|
| @@ -2215,6 +2225,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| HInstruction potentiallyCheckType(HInstruction original, DartType type,
|
| { int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
|
| if (!compiler.enableTypeAssertions) return original;
|
| + type = localsHandler.substInContext(type);
|
| HInstruction other = buildTypeConversion(original, type, kind);
|
| if (other != original) add(other);
|
| compiler.enqueuer.codegen.registerIsCheck(type, work.resolutionTree);
|
| @@ -2223,8 +2234,10 @@ class SsaBuilder extends ResolvedVisitor {
|
|
|
| void assertIsSubtype(ast.Node node, DartType subtype, DartType supertype,
|
| String message) {
|
| - HInstruction subtypeInstruction = analyzeTypeArgument(subtype);
|
| - HInstruction supertypeInstruction = analyzeTypeArgument(supertype);
|
| + HInstruction subtypeInstruction =
|
| + analyzeTypeArgument(localsHandler.substInContext(subtype));
|
| + HInstruction supertypeInstruction =
|
| + analyzeTypeArgument(localsHandler.substInContext(supertype));
|
| HInstruction messageInstruction =
|
| graph.addConstantString(new ast.DartString.literal(message), compiler);
|
| Element element = backend.getAssertIsSubtype();
|
| @@ -3162,7 +3175,9 @@ class SsaBuilder extends ResolvedVisitor {
|
| generateTypeError(node, element.message);
|
| } else {
|
| HInstruction converted = buildTypeConversion(
|
| - expression, type, HTypeConversion.CAST_TYPE_CHECK);
|
| + expression,
|
| + localsHandler.substInContext(type),
|
| + HTypeConversion.CAST_TYPE_CHECK);
|
| if (converted != expression) add(converted);
|
| stack.add(converted);
|
| }
|
| @@ -3180,7 +3195,6 @@ class SsaBuilder extends ResolvedVisitor {
|
| HInstruction expression = pop();
|
| bool isNot = node.isIsNotCheck;
|
| DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
|
| - type = type.unalias(compiler);
|
| HInstruction instruction = buildIsNode(node, type, expression);
|
| if (isNot) {
|
| add(instruction);
|
| @@ -3189,8 +3203,10 @@ class SsaBuilder extends ResolvedVisitor {
|
| push(instruction);
|
| }
|
|
|
| - HInstruction buildIsNode(ast.Node node, DartType type, HInstruction expression) {
|
| - type = type.unalias(compiler);
|
| + HInstruction buildIsNode(ast.Node node,
|
| + DartType type,
|
| + HInstruction expression) {
|
| + type = localsHandler.substInContext(type).unalias(compiler);
|
| if (type.kind == TypeKind.FUNCTION) {
|
| List arguments = [buildFunctionType(type), expression];
|
| pushInvokeDynamic(
|
| @@ -3842,6 +3858,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| * Helper to create an instruction that gets the value of a type variable.
|
| */
|
| HInstruction addTypeVariableReference(TypeVariableType type) {
|
| + assert(assertTypeInContext(type));
|
| Element member = sourceElement;
|
| bool isClosure = member.enclosingElement.isClosure;
|
| if (isClosure) {
|
| @@ -3893,6 +3910,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| }
|
|
|
| HInstruction analyzeTypeArgument(DartType argument) {
|
| + assert(assertTypeInContext(argument));
|
| if (argument.treatAsDynamic) {
|
| // Represent [dynamic] as [null].
|
| return graph.addConstantNull(compiler);
|
| @@ -3921,6 +3939,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| return newObject;
|
| }
|
| List<HInstruction> inputs = <HInstruction>[];
|
| + type = localsHandler.substInContext(type);
|
| type.typeArguments.forEach((DartType argument) {
|
| inputs.add(analyzeTypeArgument(argument));
|
| });
|
| @@ -4029,6 +4048,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| bool isRedirected = functionElement.isRedirectingFactory;
|
| InterfaceType type = elements.getType(node);
|
| InterfaceType expectedType = functionElement.computeTargetType(type);
|
| + expectedType = localsHandler.substInContext(expectedType);
|
|
|
| if (checkTypeVariableBounds(node, type)) return;
|
|
|
| @@ -4266,7 +4286,8 @@ class SsaBuilder extends ResolvedVisitor {
|
| }
|
| } else if (element.isTypeVariable) {
|
| TypeVariableElement typeVariable = element;
|
| - HInstruction value = addTypeVariableReference(typeVariable.type);
|
| + DartType type = localsHandler.substInContext(typeVariable.type);
|
| + HInstruction value = analyzeTypeArgument(type);
|
| pushInvokeStatic(node,
|
| backend.getRuntimeTypeToString(),
|
| [value],
|
| @@ -4830,6 +4851,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| ClassElement cls = redirectingConstructor.enclosingClass;
|
| InterfaceType targetType =
|
| redirectingConstructor.computeTargetType(cls.thisType);
|
| + targetType = localsHandler.substInContext(targetType);
|
| targetType.typeArguments.forEach((DartType argument) {
|
| inputs.add(analyzeTypeArgument(argument));
|
| });
|
| @@ -4880,7 +4902,7 @@ class SsaBuilder extends ResolvedVisitor {
|
| }
|
|
|
| HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) {
|
| - InterfaceType type = elements.getType(node);
|
| + InterfaceType type = localsHandler.substInContext(elements.getType(node));
|
| if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
|
| return object;
|
| }
|
| @@ -5127,6 +5149,7 @@ class SsaBuilder extends ResolvedVisitor {
|
|
|
| InterfaceType type = elements.getType(node);
|
| InterfaceType expectedType = functionElement.computeTargetType(type);
|
| + expectedType = localsHandler.substInContext(expectedType);
|
|
|
| if (constructor.isFactoryConstructor) {
|
| compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements);
|
|
|