Index: pkg/compiler/lib/src/ssa/nodes.dart |
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart |
index 01be037e760a15d6cdae80c1e36b9cc40e021483..d08ea7390b3d547f8747b281bf66e7fc0abcafb2 100644 |
--- a/pkg/compiler/lib/src/ssa/nodes.dart |
+++ b/pkg/compiler/lib/src/ssa/nodes.dart |
@@ -99,6 +99,10 @@ abstract class HVisitor<R> { |
R visitVoidType(HVoidType node); |
R visitInterfaceType(HInterfaceType node); |
R visitDynamicType(HDynamicType node); |
+ |
+ R visitTypeInfoReadRaw(HTypeInfoReadRaw node); |
+ R visitTypeInfoReadVariable(HTypeInfoReadVariable node); |
+ R visitTypeInfoExpression(HTypeInfoExpression node); |
} |
abstract class HGraphVisitor { |
@@ -394,6 +398,11 @@ class HBaseVisitor extends HGraphVisitor implements HVisitor { |
visitDynamicType(HDynamicType node) => visitInstruction(node); |
visitAwait(HAwait node) => visitInstruction(node); |
visitYield(HYield node) => visitInstruction(node); |
+ |
+ visitTypeInfoReadRaw(HTypeInfoReadRaw node) => visitInstruction(node); |
+ visitTypeInfoReadVariable(HTypeInfoReadVariable node) => |
+ visitInstruction(node); |
+ visitTypeInfoExpression(HTypeInfoExpression node) => visitInstruction(node); |
} |
class SubGraph { |
@@ -854,6 +863,10 @@ abstract class HInstruction implements Spannable { |
static const int TRUNCATING_DIVIDE_TYPECODE = 36; |
static const int IS_VIA_INTERCEPTOR_TYPECODE = 37; |
+ static const int TYPE_INFO_READ_RAW_TYPECODE = 38; |
+ static const int TYPE_INFO_READ_VARIABLE_TYPECODE = 39; |
+ static const int TYPE_INFO_EXPRESSION_TYPECODE = 40; |
+ |
HInstruction(this.inputs, this.instructionType) |
: id = idCounter++, |
usedBy = <HInstruction>[] { |
@@ -3182,6 +3195,134 @@ class HSwitchBlockInformation implements HStatementInformation { |
visitor.visitSwitchInfo(this); |
} |
+/// Reads raw reified type info from an object. |
+class HTypeInfoReadRaw extends HInstruction { |
+ HTypeInfoReadRaw(HInstruction receiver, TypeMask instructionType) |
+ : super(<HInstruction>[receiver], instructionType) { |
+ setUseGvn(); |
+ } |
+ |
+ accept(HVisitor visitor) => visitor.visitTypeInfoReadRaw(this); |
+ |
+ bool canThrow() => false; |
+ |
+ int typeCode() => HInstruction.TYPE_INFO_READ_RAW_TYPECODE; |
+ bool typeEquals(HInstruction other) => other is HTypeInfoReadRaw; |
+ |
+ bool dataEquals(HTypeInfoReadRaw other) { |
+ return true; |
+ } |
+} |
+ |
+/// Reads a type variable from an object. The read may be a simple indexing of |
+/// the type parameters or it may require 'substitution'. |
+class HTypeInfoReadVariable extends HInstruction { |
+ /// The type variable being read. |
+ final TypeVariableType variable; |
+ |
+ HTypeInfoReadVariable( |
+ this.variable, HInstruction receiver, TypeMask instructionType) |
+ : super(<HInstruction>[receiver], instructionType) { |
+ setUseGvn(); |
+ } |
+ |
+ accept(HVisitor visitor) => visitor.visitTypeInfoReadVariable(this); |
+ |
+ bool canThrow() => false; |
+ |
+ int typeCode() => HInstruction.TYPE_INFO_READ_VARIABLE_TYPECODE; |
+ bool typeEquals(HInstruction other) => other is HTypeInfoReadVariable; |
+ |
+ bool dataEquals(HTypeInfoReadVariable other) { |
+ return variable.element == other.variable.element; |
+ } |
+} |
+ |
+enum TypeInfoExpressionKind { COMPLETE, INSTANCE } |
+ |
+/// Constructs a representation of a closed or ground-term type (that is, a type |
+/// without type variables). |
+/// |
+/// There are two forms: |
+/// |
+/// - COMPLETE: A complete form that is self contained, used for the values of |
+/// type parameters and non-raw is-checks. |
+/// |
+/// - INSTANCE: A headless flat form for representing the sequence of values of |
+/// the type parameters of an instance of a generic type. |
+/// |
+/// The COMPLETE form value is constructed from [dartType] by replacing the type |
+/// variables with consecutive values from [inputs], in the order generated by |
+/// [DartType.forEachTypeVariable]. The type variables in [dartType] are |
+/// treated as 'holes' in the term, which means that it must be ensured at |
+/// construction, that duplicate occurences of a type variable in [dartType] are |
+/// assigned the same value. |
+/// |
+/// The INSTANCE form is constructed as a list of [inputs]. This is the same as |
+/// the COMPLETE form for the 'thisType', except the root term's type is |
+/// missing; this is implicit as the raw type of instance. The [dartType] of |
+/// the INSTANCE form must be the thisType of some class. |
+/// |
+/// We want to remove the constrains on the INSTANCE form. In the meantime we |
+/// get by with a tree of TypeExpressions. Consider: |
+/// |
+/// class Foo<T> { |
+/// ... new Set<List<T>>() |
+/// } |
+/// class Set<E1> { |
+/// factory Set() => new _LinkedHashSet<E1>(); |
+/// } |
+/// class List<E2> { ... } |
+/// class _LinkedHashSet<E3> { ... } |
+/// |
+/// After inlining the factory constructor for `Set<E1>`, the HForeignNew |
+/// should have type `_LinkedHashSet<List<T>>` and the TypeExpression should be |
+/// a tree: |
+/// |
+/// HForeignNew(dartType: _LinkedHashSet<List<T>>, |
+/// [], // No arguments |
+/// HTypeInfoExpression(INSTANCE, |
+/// dartType: _LinkedHashSet<E3>, // _LinkedHashSet's thisType |
+/// HTypeInfoExpression(COMPLETE, // E3 = List<T> |
+/// dartType: List<E2>, |
+/// HTypeInfoReadVariable(this, T)))) // E2 = T |
+ |
+// TODO(sra): The INSTANCE form requires the actual instance for full |
+// interpretation. If the COMPLETE form was used on instances, then we could |
+// simplify HTypeInfoReadVariable without an object. |
+ |
+class HTypeInfoExpression extends HInstruction { |
+ final TypeInfoExpressionKind kind; |
+ final DartType dartType; |
+ HTypeInfoExpression(this.kind, this.dartType, List<HInstruction> inputs, |
+ TypeMask instructionType) |
+ : super(inputs, instructionType) { |
+ setUseGvn(); |
+ } |
+ |
+ accept(HVisitor visitor) => visitor.visitTypeInfoExpression(this); |
+ |
+ bool canThrow() => false; |
+ |
+ int typeCode() => HInstruction.TYPE_INFO_EXPRESSION_TYPECODE; |
+ bool typeEquals(HInstruction other) => other is HTypeInfoExpression; |
+ |
+ bool dataEquals(HTypeInfoExpression other) { |
+ return kind == other.kind && dartType == other.dartType; |
+ } |
+ |
+ String toString() => 'HTypeInfoExpression $kindAsString $dartType'; |
+ |
+ String get kindAsString { |
+ switch (kind) { |
+ case TypeInfoExpressionKind.COMPLETE: |
+ return 'COMPLETE'; |
+ case TypeInfoExpressionKind.INSTANCE: |
+ return 'INSTANCE'; |
+ } |
+ } |
+} |
+ |
class HReadTypeVariable extends HInstruction { |
/// The type variable being read. |
final TypeVariableType dartType; |