Chromium Code Reviews| Index: pkg/compiler/lib/src/ssa/optimize.dart |
| diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart |
| index 4700112b3211ec528f9b1bd3194091f8c985be00..04f5e429857eae8fff90e30819bfd7be89699ed9 100644 |
| --- a/pkg/compiler/lib/src/ssa/optimize.dart |
| +++ b/pkg/compiler/lib/src/ssa/optimize.dart |
| @@ -1037,6 +1037,68 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| return handleInterceptedCall(node); |
| } |
| + bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { |
| + ClassWorld classWorld = compiler.world; |
| + if (classWorld.isUsedAsMixin(cls)) return true; |
| + |
| + return classWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { |
| + return !backend.rti.isTrivialSubstitution(subclass, cls); |
| + }); |
| + } |
| + |
| + HInstruction visitTypeInfoExpression(HTypeInfoExpression node) { |
| + // Identify the case where the type info expression would be of the form: |
| + // |
| + // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] |
| + // |
| + // and k is the number of type arguments of 'this'. We can simply copy the |
| + // list from 'this'. |
| + HInstruction tryCopyInfo() { |
| + if (node.kind != TypeInfoExpressionKind.INSTANCE) return null; |
| + |
| + HInstruction source; |
| + int expectedIndex = 0; |
| + |
| + for (HInstruction argument in node.inputs) { |
| + if (argument is HTypeInfoReadVariable) { |
| + HInstruction nextSource = argument.object; |
| + if (nextSource is HThis) { |
| + // TODO(sra): Handle non-this cases (i.e. inlined code). Some |
| + // non-this cases will have a TypeMask that does not need |
| + // substitution, even though the general case does, e.g. inlining a |
| + // method on an exact class. |
| + if (source == null) { |
| + source = nextSource; |
| + ClassElement contextClass = |
| + nextSource.sourceElement.enclosingClass; |
| + if (node.inputs.length != contextClass.typeVariables.length) { |
| + return null; |
| + } |
| + if (needsSubstitutionForTypeVariableAccess(contextClass)) { |
| + return null; |
| + } |
| + } |
| + if (nextSource != source) return null; |
| + // Check that the index is the one we expect. |
| + int index = argument.variable.element.index; |
| + if (index != expectedIndex++) return null; |
| + continue; |
| + } |
| + } |
| + // Fall-through for unrecognized argument. |
|
Siggi Cherem (dart-lang)
2016/09/02 18:02:29
nit: I might prefer to remove the "continue" above
sra1
2016/09/02 18:23:14
Done.
|
| + return null; |
| + } |
| + |
| + if (source == null) return null; |
| + return new HTypeInfoReadRaw(source, backend.dynamicType); |
| + } |
| + |
| + // TODO(sra): Consider fusing type expression trees with no type variables, |
| + // as these could be represented like constants. |
| + |
| + return tryCopyInfo() ?? node; |
| + } |
| + |
| HInstruction visitTypeInfoReadVariable(HTypeInfoReadVariable node) { |
| TypeVariableType variable = node.variable; |
| HInstruction object = node.object; |