Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(298)

Unified Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 267153002: Support general handling of type variables by substituting types into the current context. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased + reinserted unalias Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ordered_typeset.dart ('k') | tests/language/generic_field_mixin2_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698