Chromium Code Reviews| 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..b84155834d3b82bff6ebb06281609176a0b81577 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,133 @@ 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 |
|
Siggi Cherem (dart-lang)
2016/08/19 18:21:46
I'm trying to understand the need for the distinct
sra1
2016/08/19 18:47:44
Correct.
This is just how it is currently done.
I
|
| +/// 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 [arguments], in the order generated |
|
Siggi Cherem (dart-lang)
2016/08/19 18:21:46
[arguments] => [inputs]?
sra1
2016/08/19 18:47:43
Done.
|
| +/// 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 [arguments]. This is the same |
|
Siggi Cherem (dart-lang)
2016/08/19 18:21:46
ditto?
sra1
2016/08/19 18:47:43
Done.
|
| +/// 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; |