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