Index: sdk/lib/_internal/compiler/implementation/ssa/nodes.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart |
index 774ab84a4384117b534b3d3d3ba1c4ae3aeb6b0b..3b0443e937b9cd2f81fd1a2f1f0e200c52b92c89 100644 |
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart |
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart |
@@ -38,6 +38,7 @@ abstract class HVisitor<R> { |
R visitInvokeSuper(HInvokeSuper node); |
R visitInvokeConstructorBody(HInvokeConstructorBody node); |
R visitIs(HIs node); |
+ R visitIsViaInterceptor(HIsViaInterceptor node); |
R visitLazyStatic(HLazyStatic node); |
R visitLess(HLess node); |
R visitLessEqual(HLessEqual node); |
@@ -335,6 +336,7 @@ class HBaseVisitor extends HGraphVisitor implements HVisitor { |
visitTruncatingDivide(HTruncatingDivide node) => visitBinaryArithmetic(node); |
visitTry(HTry node) => visitControlFlow(node); |
visitIs(HIs node) => visitInstruction(node); |
+ visitIsViaInterceptor(HIsViaInterceptor node) => visitInstruction(node); |
visitTypeConversion(HTypeConversion node) => visitCheck(node); |
visitTypeKnown(HTypeKnown node) => visitCheck(node); |
visitReadTypeVariable(HReadTypeVariable node) => visitInstruction(node); |
@@ -801,6 +803,7 @@ abstract class HInstruction implements Spannable { |
static const int INTERFACE_TYPE_TYPECODE = 34; |
static const int DYNAMIC_TYPE_TYPECODE = 35; |
static const int TRUNCATING_DIVIDE_TYPECODE = 36; |
+ static const int IS_VIA_INTERCEPTOR_TYPECODE = 37; |
HInstruction(this.inputs, this.instructionType) |
: id = idCounter++, usedBy = <HInstruction>[] { |
@@ -1237,6 +1240,15 @@ abstract class HInstruction implements Spannable { |
} |
} |
+/** |
+ * Late instructions are used after the main optimization phases. They capture |
+ * codegen decisions just prior to generating JavaScript. |
+ */ |
+abstract class HLateInstruction extends HInstruction { |
+ HLateInstruction(List<HInstruction> inputs, TypeMask type) |
+ : super(inputs, type); |
+} |
+ |
class HBoolify extends HInstruction { |
HBoolify(HInstruction value, TypeMask type) |
: super(<HInstruction>[value], type) { |
@@ -2025,6 +2037,9 @@ abstract class HRelational extends HInvokeBinary { |
} |
class HIdentity extends HRelational { |
+ // Cached codegen decision. |
+ String singleComparisonOp; // null, '===', '==' |
+ |
HIdentity(left, right, selector, type) : super(left, right, selector, type); |
accept(HVisitor visitor) => visitor.visitIdentity(this); |
@@ -2342,6 +2357,30 @@ class HIs extends HInstruction { |
} |
} |
+/** |
+ * HIsViaInterceptor is a late-stage instruction for a type test that can be |
+ * done entirely on an interceptor. It is not a HCheck because the checked |
+ * input is not one of the inputs. |
+ */ |
+class HIsViaInterceptor extends HLateInstruction { |
+ final DartType typeExpression; |
+ HIsViaInterceptor(this.typeExpression, HInstruction interceptor, |
+ TypeMask type) |
+ : super(<HInstruction>[interceptor], type) { |
+ setUseGvn(); |
+ } |
+ |
+ HInstruction get interceptor => inputs[0]; |
+ |
+ accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this); |
+ toString() => "$interceptor is $typeExpression"; |
+ int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE; |
+ bool typeEquals(HInstruction other) => other is HIsViaInterceptor; |
+ bool dataEquals(HIs other) { |
+ return typeExpression == other.typeExpression; |
+ } |
+} |
+ |
class HTypeConversion extends HCheck { |
final DartType typeExpression; |
final int kind; |