| 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;
|
|
|