// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:front_end/src/api_unstable/dart2js.dart' show Link;

import '../closure.dart';
import '../common.dart';
import '../common_elements.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../io/source_information.dart';
import '../js/js.dart' as js;
import '../js_backend/specialized_checks.dart' show IsTestSpecialization;
import '../js_model/type_recipe.dart'
    show TypeEnvironmentStructure, TypeRecipe, TypeExpressionRecipe;
import '../native/behavior.dart';
import '../universe/selector.dart' show Selector;
import '../universe/side_effects.dart' show SideEffects;
import '../util/util.dart';
import '../world.dart' show JClosedWorld;
import 'invoke_dynamic_specializers.dart';
import 'validate.dart';

abstract class HVisitor<R> {
  R visitAbs(HAbs node);
  R visitAdd(HAdd node);
  R visitAwait(HAwait node);
  R visitBitAnd(HBitAnd node);
  R visitBitNot(HBitNot node);
  R visitBitOr(HBitOr node);
  R visitBitXor(HBitXor node);
  R visitBoundsCheck(HBoundsCheck node);
  R visitBreak(HBreak node);
  R visitConstant(HConstant node);
  R visitContinue(HContinue node);
  R visitCreate(HCreate node);
  R visitCreateBox(HCreateBox node);
  R visitDivide(HDivide node);
  R visitExit(HExit node);
  R visitExitTry(HExitTry node);
  R visitFieldGet(HFieldGet node);
  R visitFieldSet(HFieldSet node);
  R visitInvokeExternal(HInvokeExternal node);
  R visitForeignCode(HForeignCode node);
  R visitGetLength(HGetLength node);
  R visitGoto(HGoto node);
  R visitGreater(HGreater node);
  R visitGreaterEqual(HGreaterEqual node);
  R visitIdentity(HIdentity node);
  R visitIf(HIf node);
  R visitIndex(HIndex node);
  R visitIndexAssign(HIndexAssign node);
  R visitInterceptor(HInterceptor node);
  R visitInvokeClosure(HInvokeClosure node);
  R visitInvokeDynamicGetter(HInvokeDynamicGetter node);
  R visitInvokeDynamicMethod(HInvokeDynamicMethod node);
  R visitInvokeDynamicSetter(HInvokeDynamicSetter node);
  R visitInvokeStatic(HInvokeStatic node);
  R visitInvokeSuper(HInvokeSuper node);
  R visitInvokeConstructorBody(HInvokeConstructorBody node);
  R visitInvokeGeneratorBody(HInvokeGeneratorBody node);
  R visitIs(HIs node);
  R visitIsViaInterceptor(HIsViaInterceptor node);
  R visitLateValue(HLateValue node);
  R visitLazyStatic(HLazyStatic node);
  R visitLess(HLess node);
  R visitLessEqual(HLessEqual node);
  R visitLiteralList(HLiteralList node);
  R visitLocalGet(HLocalGet node);
  R visitLocalSet(HLocalSet node);
  R visitLocalValue(HLocalValue node);
  R visitLoopBranch(HLoopBranch node);
  R visitMultiply(HMultiply node);
  R visitNegate(HNegate node);
  R visitNot(HNot node);
  R visitOneShotInterceptor(HOneShotInterceptor node);
  R visitParameterValue(HParameterValue node);
  R visitPhi(HPhi node);
  R visitRangeConversion(HRangeConversion node);
  R visitReadModifyWrite(HReadModifyWrite node);
  R visitRef(HRef node);
  R visitRemainder(HRemainder node);
  R visitReturn(HReturn node);
  R visitShiftLeft(HShiftLeft node);
  R visitShiftRight(HShiftRight node);
  R visitStatic(HStatic node);
  R visitStaticStore(HStaticStore node);
  R visitStringConcat(HStringConcat node);
  R visitStringify(HStringify node);
  R visitSubtract(HSubtract node);
  R visitSwitch(HSwitch node);
  R visitThis(HThis node);
  R visitThrow(HThrow node);
  R visitThrowExpression(HThrowExpression node);
  R visitTruncatingDivide(HTruncatingDivide node);
  R visitTry(HTry node);
  R visitTypeConversion(HTypeConversion node);
  R visitPrimitiveCheck(HPrimitiveCheck node);
  R visitBoolConversion(HBoolConversion node);
  R visitNullCheck(HNullCheck node);
  R visitTypeKnown(HTypeKnown node);
  R visitYield(HYield node);

  R visitTypeInfoReadRaw(HTypeInfoReadRaw node);
  R visitTypeInfoReadVariable(HTypeInfoReadVariable node);
  R visitTypeInfoExpression(HTypeInfoExpression node);

  // Instructions for 'dart:_rti'.
  R visitIsTest(HIsTest node);
  R visitIsTestSimple(HIsTestSimple node);
  R visitAsCheck(HAsCheck node);
  R visitAsCheckSimple(HAsCheckSimple node);
  R visitSubtypeCheck(HSubtypeCheck node);
  R visitLoadType(HLoadType node);
  R visitInstanceEnvironment(HInstanceEnvironment node);
  R visitTypeEval(HTypeEval node);
  R visitTypeBind(HTypeBind node);
}

abstract class HGraphVisitor {
  visitDominatorTree(HGraph graph) {
    // Recursion free version of:
    //
    //     void visitBasicBlockAndSuccessors(HBasicBlock block) {
    //       visitBasicBlock(block);
    //       List dominated = block.dominatedBlocks;
    //       for (int i = 0; i < dominated.length; i++) {
    //         visitBasicBlockAndSuccessors(dominated[i]);
    //       }
    //     }
    //     visitBasicBlockAndSuccessors(graph.entry);

    _Frame frame = new _Frame(null);
    frame.block = graph.entry;
    frame.index = 0;

    visitBasicBlock(frame.block);

    while (frame != null) {
      HBasicBlock block = frame.block;
      int index = frame.index;
      if (index < block.dominatedBlocks.length) {
        frame.index = index + 1;
        frame = frame.next ??= new _Frame(frame);
        frame.block = block.dominatedBlocks[index];
        frame.index = 0;
        visitBasicBlock(frame.block);
        continue;
      }
      frame = frame.previous;
    }
  }

  visitPostDominatorTree(HGraph graph) {
    // Recusion free version of:
    //
    //     void visitBasicBlockAndSuccessors(HBasicBlock block) {
    //       List dominated = block.dominatedBlocks;
    //       for (int i = dominated.length - 1; i >= 0; i--) {
    //         visitBasicBlockAndSuccessors(dominated[i]);
    //       }
    //       visitBasicBlock(block);
    //     }
    //     visitBasicBlockAndSuccessors(graph.entry);

    _Frame frame = new _Frame(null);
    frame.block = graph.entry;
    frame.index = frame.block.dominatedBlocks.length;

    while (frame != null) {
      HBasicBlock block = frame.block;
      int index = frame.index;
      if (index > 0) {
        frame.index = index - 1;
        frame = frame.next ??= new _Frame(frame);
        frame.block = block.dominatedBlocks[index - 1];
        frame.index = frame.block.dominatedBlocks.length;
        continue;
      }
      visitBasicBlock(block);
      frame = frame.previous;
    }
  }

  visitBasicBlock(HBasicBlock block);
}

class _Frame {
  final _Frame previous;
  _Frame next;
  HBasicBlock block;
  int index;
  _Frame(this.previous);
}

abstract class HInstructionVisitor extends HGraphVisitor {
  HBasicBlock currentBlock;

  visitInstruction(HInstruction node);

  @override
  visitBasicBlock(HBasicBlock node) {
    void visitInstructionList(HInstructionList list) {
      HInstruction instruction = list.first;
      while (instruction != null) {
        visitInstruction(instruction);
        instruction = instruction.next;
        assert(instruction != list.first);
      }
    }

    currentBlock = node;
    visitInstructionList(node);
  }
}

class HGraph {
  MemberEntity element; // Used for debug printing.
  HBasicBlock entry;
  HBasicBlock exit;
  HThis thisInstruction;

  /// `true` if this graph should be transformed by a sync*/async/async*
  /// rewrite.
  bool needsAsyncRewrite = false;

  /// If this function requires an async rewrite, this is the element type of
  /// the generator.
  DartType asyncElementType;

  /// Receiver parameter, set for methods using interceptor calling convention.
  HParameterValue explicitReceiverParameter;
  bool isRecursiveMethod = false;
  bool calledInLoop = false;
  bool isLazyInitializer = false;

  final List<HBasicBlock> blocks = <HBasicBlock>[];

  /// Nodes containing list allocations for which there is a known fixed length.
  // TODO(sigmund,sra): consider not storing this explicitly here (e.g. maybe
  // store it on HInstruction, or maybe this can be computed on demand).
  final Set<HInstruction> allocatedFixedLists = new Set<HInstruction>();

  SourceInformation sourceInformation;

  // We canonicalize all constants used within a graph so we do not
  // have to worry about them for global value numbering.
  Map<ConstantValue, HConstant> constants = new Map<ConstantValue, HConstant>();

  HGraph() {
    entry = addNewBlock();
    // The exit block will be added later, so it has an id that is
    // after all others in the system.
    exit = new HBasicBlock();
  }

  void addBlock(HBasicBlock block) {
    int id = blocks.length;
    block.id = id;
    blocks.add(block);
    assert(identical(blocks[id], block));
  }

  HBasicBlock addNewBlock() {
    HBasicBlock result = new HBasicBlock();
    addBlock(result);
    return result;
  }

  HBasicBlock addNewLoopHeaderBlock(
      JumpTarget target, List<LabelDefinition> labels) {
    HBasicBlock result = addNewBlock();
    result.loopInformation = new HLoopInformation(result, target, labels);
    return result;
  }

  HConstant addConstant(ConstantValue constant, JClosedWorld closedWorld,
      {SourceInformation sourceInformation}) {
    HConstant result = constants[constant];
    // TODO(johnniwinther): Support source information per constant reference.
    if (result == null) {
      if (!constant.isConstant) {
        // We use `null` as the value for invalid constant expressions.
        constant = const NullConstantValue();
      }
      AbstractValue type = closedWorld.abstractValueDomain
          .computeAbstractValueForConstant(constant);
      result = new HConstant.internal(constant, type)
        ..sourceInformation = sourceInformation;
      entry.addAtExit(result);
      constants[constant] = result;
    } else if (result.block == null) {
      // The constant was not used anymore.
      entry.addAtExit(result);
    }
    return result;
  }

  HConstant addDeferredConstant(DeferredGlobalConstantValue constant,
      SourceInformation sourceInformation, JClosedWorld closedWorld) {
    return addConstant(constant, closedWorld,
        sourceInformation: sourceInformation);
  }

  HConstant addConstantInt(int i, JClosedWorld closedWorld) {
    return addConstant(constant_system.createIntFromInt(i), closedWorld);
  }

  HConstant addConstantIntAsUnsigned(int i, JClosedWorld closedWorld) {
    return addConstant(
        constant_system.createInt(new BigInt.from(i).toUnsigned(64)),
        closedWorld);
  }

  HConstant addConstantDouble(double d, JClosedWorld closedWorld) {
    return addConstant(constant_system.createDouble(d), closedWorld);
  }

  HConstant addConstantString(String str, JClosedWorld closedWorld) {
    return addConstant(constant_system.createString(str), closedWorld);
  }

  HConstant addConstantStringFromName(js.Name name, JClosedWorld closedWorld) {
    return addConstant(
        new JsNameConstantValue(js.quoteName(name)), closedWorld);
  }

  HConstant addConstantBool(bool value, JClosedWorld closedWorld) {
    return addConstant(constant_system.createBool(value), closedWorld);
  }

  HConstant addConstantNull(JClosedWorld closedWorld) {
    return addConstant(constant_system.createNull(), closedWorld);
  }

  HConstant addConstantUnreachable(JClosedWorld closedWorld) {
    // A constant with an empty type used as the HInstruction of an expression
    // in an unreachable context.
    return addConstant(const UnreachableConstantValue(), closedWorld);
  }

  void finalize(AbstractValueDomain domain) {
    addBlock(exit);
    exit.open();
    exit.close(new HExit(domain));
    assignDominators();
  }

  void assignDominators() {
    // Run through the blocks in order of increasing ids so we are
    // guaranteed that we have computed dominators for all blocks
    // higher up in the dominator tree.
    for (int i = 0, length = blocks.length; i < length; i++) {
      HBasicBlock block = blocks[i];
      List<HBasicBlock> predecessors = block.predecessors;
      if (block.isLoopHeader()) {
        block.assignCommonDominator(predecessors[0]);
      } else {
        for (int j = predecessors.length - 1; j >= 0; j--) {
          block.assignCommonDominator(predecessors[j]);
        }
      }
    }
    assignDominatorRanges();
  }

  void assignDominatorRanges() {
    // DFS walk of dominator tree to assign dfs-in and dfs-out numbers to basic
    // blocks. A dominator has a dfs-in..dfs-out range that includes the range
    // of the dominated block. See [HGraphVisitor.visitDominatorTree] for
    // recursion-free schema.
    _Frame frame = new _Frame(null);
    frame.block = entry;
    frame.index = 0;

    int dfsNumber = 0;
    frame.block.dominatorDfsIn = dfsNumber;

    while (frame != null) {
      HBasicBlock block = frame.block;
      int index = frame.index;
      if (index < block.dominatedBlocks.length) {
        frame.index = index + 1;
        frame = frame.next ??= new _Frame(frame);
        frame.block = block.dominatedBlocks[index];
        frame.index = 0;
        frame.block.dominatorDfsIn = ++dfsNumber;
        continue;
      }
      block.dominatorDfsOut = dfsNumber;
      frame = frame.previous;
    }
  }

  bool isValid() {
    HValidator validator = new HValidator();
    validator.visitGraph(this);
    return validator.isValid;
  }

  @override
  toString() => 'HGraph($element)';
}

class HBaseVisitor extends HGraphVisitor implements HVisitor {
  HBasicBlock currentBlock;

  @override
  visitBasicBlock(HBasicBlock node) {
    currentBlock = node;

    HInstruction instruction = node.first;
    while (instruction != null) {
      instruction.accept(this);
      instruction = instruction.next;
    }
  }

  visitInstruction(HInstruction instruction) {}

  visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node);
  visitBinaryBitOp(HBinaryBitOp node) => visitInvokeBinary(node);
  visitInvoke(HInvoke node) => visitInstruction(node);
  visitInvokeBinary(HInvokeBinary node) => visitInstruction(node);
  visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node);
  visitInvokeDynamicField(HInvokeDynamicField node) => visitInvokeDynamic(node);
  visitInvokeUnary(HInvokeUnary node) => visitInstruction(node);
  visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node);
  visitControlFlow(HControlFlow node) => visitInstruction(node);
  visitFieldAccess(HFieldAccess node) => visitInstruction(node);
  visitRelational(HRelational node) => visitInvokeBinary(node);

  @override
  visitAbs(HAbs node) => visitInvokeUnary(node);
  @override
  visitAdd(HAdd node) => visitBinaryArithmetic(node);
  @override
  visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
  @override
  visitBitNot(HBitNot node) => visitInvokeUnary(node);
  @override
  visitBitOr(HBitOr node) => visitBinaryBitOp(node);
  @override
  visitBitXor(HBitXor node) => visitBinaryBitOp(node);
  @override
  visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
  @override
  visitBreak(HBreak node) => visitJump(node);
  @override
  visitContinue(HContinue node) => visitJump(node);
  visitCheck(HCheck node) => visitInstruction(node);
  @override
  visitConstant(HConstant node) => visitInstruction(node);
  @override
  visitCreate(HCreate node) => visitInstruction(node);
  @override
  visitCreateBox(HCreateBox node) => visitInstruction(node);
  @override
  visitDivide(HDivide node) => visitBinaryArithmetic(node);
  @override
  visitExit(HExit node) => visitControlFlow(node);
  @override
  visitExitTry(HExitTry node) => visitControlFlow(node);
  @override
  visitFieldGet(HFieldGet node) => visitFieldAccess(node);
  @override
  visitFieldSet(HFieldSet node) => visitFieldAccess(node);
  @override
  visitInvokeExternal(HInvokeExternal node) => visitInstruction(node);
  @override
  visitForeignCode(HForeignCode node) => visitInstruction(node);
  @override
  visitGetLength(HGetLength node) => visitInstruction(node);
  @override
  visitGoto(HGoto node) => visitControlFlow(node);
  @override
  visitGreater(HGreater node) => visitRelational(node);
  @override
  visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
  @override
  visitIdentity(HIdentity node) => visitRelational(node);
  @override
  visitIf(HIf node) => visitConditionalBranch(node);
  @override
  visitIndex(HIndex node) => visitInstruction(node);
  @override
  visitIndexAssign(HIndexAssign node) => visitInstruction(node);
  @override
  visitInterceptor(HInterceptor node) => visitInstruction(node);
  @override
  visitInvokeClosure(HInvokeClosure node) => visitInvokeDynamic(node);
  @override
  visitInvokeConstructorBody(HInvokeConstructorBody node) =>
      visitInvokeStatic(node);
  @override
  visitInvokeGeneratorBody(HInvokeGeneratorBody node) =>
      visitInvokeStatic(node);
  @override
  visitInvokeDynamicMethod(HInvokeDynamicMethod node) =>
      visitInvokeDynamic(node);
  @override
  visitInvokeDynamicGetter(HInvokeDynamicGetter node) =>
      visitInvokeDynamicField(node);
  @override
  visitInvokeDynamicSetter(HInvokeDynamicSetter node) =>
      visitInvokeDynamicField(node);
  @override
  visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
  @override
  visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node);
  visitJump(HJump node) => visitControlFlow(node);
  @override
  visitLazyStatic(HLazyStatic node) => visitInstruction(node);
  @override
  visitLess(HLess node) => visitRelational(node);
  @override
  visitLessEqual(HLessEqual node) => visitRelational(node);
  @override
  visitLiteralList(HLiteralList node) => visitInstruction(node);
  visitLocalAccess(HLocalAccess node) => visitInstruction(node);
  @override
  visitLocalGet(HLocalGet node) => visitLocalAccess(node);
  @override
  visitLocalSet(HLocalSet node) => visitLocalAccess(node);
  @override
  visitLocalValue(HLocalValue node) => visitInstruction(node);
  @override
  visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
  @override
  visitNegate(HNegate node) => visitInvokeUnary(node);
  @override
  visitNot(HNot node) => visitInstruction(node);
  @override
  visitOneShotInterceptor(HOneShotInterceptor node) => visitInvokeDynamic(node);
  @override
  visitPhi(HPhi node) => visitInstruction(node);
  @override
  visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
  @override
  visitParameterValue(HParameterValue node) => visitLocalValue(node);
  @override
  visitRangeConversion(HRangeConversion node) => visitCheck(node);
  @override
  visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node);
  @override
  visitRef(HRef node) => node.value.accept(this);
  @override
  visitRemainder(HRemainder node) => visitBinaryArithmetic(node);
  @override
  visitReturn(HReturn node) => visitControlFlow(node);
  @override
  visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
  @override
  visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
  @override
  visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
  @override
  visitSwitch(HSwitch node) => visitControlFlow(node);
  @override
  visitStatic(HStatic node) => visitInstruction(node);
  @override
  visitStaticStore(HStaticStore node) => visitInstruction(node);
  @override
  visitStringConcat(HStringConcat node) => visitInstruction(node);
  @override
  visitStringify(HStringify node) => visitInstruction(node);
  @override
  visitThis(HThis node) => visitParameterValue(node);
  @override
  visitThrow(HThrow node) => visitControlFlow(node);
  @override
  visitThrowExpression(HThrowExpression node) => visitInstruction(node);
  @override
  visitTruncatingDivide(HTruncatingDivide node) => visitBinaryArithmetic(node);
  @override
  visitTry(HTry node) => visitControlFlow(node);
  @override
  visitIs(HIs node) => visitInstruction(node);
  @override
  visitLateValue(HLateValue node) => visitInstruction(node);
  @override
  visitIsViaInterceptor(HIsViaInterceptor node) => visitInstruction(node);
  @override
  visitTypeConversion(HTypeConversion node) => visitCheck(node);
  @override
  visitBoolConversion(HBoolConversion node) => visitCheck(node);
  @override
  visitNullCheck(HNullCheck node) => visitCheck(node);
  @override
  visitPrimitiveCheck(HPrimitiveCheck node) => visitCheck(node);
  @override
  visitTypeKnown(HTypeKnown node) => visitCheck(node);
  @override
  visitAwait(HAwait node) => visitInstruction(node);
  @override
  visitYield(HYield node) => visitInstruction(node);

  @override
  visitTypeInfoReadRaw(HTypeInfoReadRaw node) => visitInstruction(node);
  @override
  visitTypeInfoReadVariable(HTypeInfoReadVariable node) =>
      visitInstruction(node);

  @override
  visitTypeInfoExpression(HTypeInfoExpression node) => visitInstruction(node);

  @override
  visitIsTest(HIsTest node) => visitInstruction(node);
  @override
  visitIsTestSimple(HIsTestSimple node) => visitInstruction(node);
  @override
  visitAsCheck(HAsCheck node) => visitCheck(node);
  @override
  visitAsCheckSimple(HAsCheckSimple node) => visitCheck(node);
  @override
  visitSubtypeCheck(HSubtypeCheck node) => visitCheck(node);
  @override
  visitLoadType(HLoadType node) => visitInstruction(node);
  @override
  visitInstanceEnvironment(HInstanceEnvironment node) => visitInstruction(node);
  @override
  visitTypeEval(HTypeEval node) => visitInstruction(node);
  @override
  visitTypeBind(HTypeBind node) => visitInstruction(node);
}

class SubGraph {
  // The first and last block of the sub-graph.
  final HBasicBlock start;
  final HBasicBlock end;

  const SubGraph(this.start, this.end);

  bool contains(HBasicBlock block) {
    assert(start != null);
    assert(end != null);
    assert(block != null);
    return start.id <= block.id && block.id <= end.id;
  }
}

class SubExpression extends SubGraph {
  const SubExpression(HBasicBlock start, HBasicBlock end) : super(start, end);

  /// Find the condition expression if this sub-expression is a condition.
  HInstruction get conditionExpression {
    HInstruction last = end.last;
    if (last is HConditionalBranch || last is HSwitch) return last.inputs[0];
    return null;
  }
}

class HInstructionList {
  HInstruction first = null;
  HInstruction last = null;

  bool get isEmpty {
    return first == null;
  }

  void internalAddAfter(HInstruction cursor, HInstruction instruction) {
    if (cursor == null) {
      assert(isEmpty);
      first = last = instruction;
    } else if (identical(cursor, last)) {
      last.next = instruction;
      instruction.previous = last;
      last = instruction;
    } else {
      instruction.previous = cursor;
      instruction.next = cursor.next;
      cursor.next.previous = instruction;
      cursor.next = instruction;
    }
  }

  void internalAddBefore(HInstruction cursor, HInstruction instruction) {
    if (cursor == null) {
      assert(isEmpty);
      first = last = instruction;
    } else if (identical(cursor, first)) {
      first.previous = instruction;
      instruction.next = first;
      first = instruction;
    } else {
      instruction.next = cursor;
      instruction.previous = cursor.previous;
      cursor.previous.next = instruction;
      cursor.previous = instruction;
    }
  }

  void detach(HInstruction instruction) {
    assert(_truncatedContainsForAssert(instruction));
    assert(instruction.isInBasicBlock());
    if (instruction.previous == null) {
      first = instruction.next;
    } else {
      instruction.previous.next = instruction.next;
    }
    if (instruction.next == null) {
      last = instruction.previous;
    } else {
      instruction.next.previous = instruction.previous;
    }
    instruction.previous = null;
    instruction.next = null;
  }

  void remove(HInstruction instruction) {
    assert(instruction.usedBy.isEmpty);
    detach(instruction);
  }

  /// Linear search for [instruction].
  bool contains(HInstruction instruction) {
    HInstruction cursor = first;
    while (cursor != null) {
      if (identical(cursor, instruction)) return true;
      cursor = cursor.next;
    }

    return false;
  }

  /// Linear search for [instruction], up to a limit of 100. Returns whether
  /// the instruction is found or the list is too big.
  ///
  /// This is used for assertions only: some tests have pathological cases where
  /// the basic blocks are huge (50K nodes!), and we found that checking for
  /// [contains] within our assertions made compilation really slow.
  bool _truncatedContainsForAssert(HInstruction instruction) {
    HInstruction cursor = first;
    int count = 0;
    while (cursor != null) {
      count++;
      if (count > 100) return true;
      if (identical(cursor, instruction)) return true;
      cursor = cursor.next;
    }

    return false;
  }
}

class HBasicBlock extends HInstructionList {
  // The [id] must be such that any successor's id is greater than
  // this [id]. The exception are back-edges.
  int id;

  static const int STATUS_NEW = 0;
  static const int STATUS_OPEN = 1;
  static const int STATUS_CLOSED = 2;
  int status = STATUS_NEW;

  HInstructionList phis;

  HLoopInformation loopInformation = null;
  HBlockFlow blockFlow = null;
  HBasicBlock parentLoopHeader = null;
  bool isLive = true;

  final List<HBasicBlock> predecessors;
  List<HBasicBlock> successors;

  HBasicBlock dominator = null;
  final List<HBasicBlock> dominatedBlocks;
  int dominatorDfsIn;
  int dominatorDfsOut;

  HBasicBlock() : this.withId(null);
  HBasicBlock.withId(this.id)
      : phis = new HInstructionList(),
        predecessors = <HBasicBlock>[],
        successors = const <HBasicBlock>[],
        dominatedBlocks = <HBasicBlock>[];

  @override
  int get hashCode => id;

  bool isNew() => status == STATUS_NEW;
  bool isOpen() => status == STATUS_OPEN;
  bool isClosed() => status == STATUS_CLOSED;

  bool isLoopHeader() {
    return loopInformation != null;
  }

  void setBlockFlow(HBlockInformation blockInfo, HBasicBlock continuation) {
    blockFlow = new HBlockFlow(blockInfo, continuation);
  }

  bool isLabeledBlock() =>
      blockFlow != null && blockFlow.body is HLabeledBlockInformation;

  HBasicBlock get enclosingLoopHeader {
    if (isLoopHeader()) return this;
    return parentLoopHeader;
  }

  void open() {
    assert(isNew());
    status = STATUS_OPEN;
  }

  void close(HControlFlow end) {
    assert(isOpen());
    addAfter(last, end);
    status = STATUS_CLOSED;
  }

  void addAtEntry(HInstruction instruction) {
    assert(instruction is! HPhi);
    internalAddBefore(first, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void addAtExit(HInstruction instruction) {
    assert(isClosed());
    assert(last is HControlFlow);
    assert(instruction is! HPhi);
    internalAddBefore(last, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void moveAtExit(HInstruction instruction) {
    assert(instruction is! HPhi);
    assert(instruction.isInBasicBlock());
    assert(isClosed());
    assert(last is HControlFlow);
    internalAddBefore(last, instruction);
    instruction.block = this;
    assert(isValid());
  }

  void add(HInstruction instruction) {
    assert(instruction is! HControlFlow);
    assert(instruction is! HPhi);
    internalAddAfter(last, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void addPhi(HPhi phi) {
    assert(phi.inputs.length == 0 || phi.inputs.length == predecessors.length);
    assert(phi.block == null);
    phis.internalAddAfter(phis.last, phi);
    phi.notifyAddedToBlock(this);
  }

  void removePhi(HPhi phi) {
    phis.remove(phi);
    assert(phi.block == this);
    phi.notifyRemovedFromBlock();
  }

  void addAfter(HInstruction cursor, HInstruction instruction) {
    assert(cursor is! HPhi);
    assert(instruction is! HPhi);
    assert(isOpen() || isClosed());
    internalAddAfter(cursor, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void addBefore(HInstruction cursor, HInstruction instruction) {
    assert(cursor is! HPhi);
    assert(instruction is! HPhi);
    assert(isOpen() || isClosed());
    internalAddBefore(cursor, instruction);
    instruction.notifyAddedToBlock(this);
  }

  @override
  void remove(HInstruction instruction) {
    assert(isOpen() || isClosed());
    assert(instruction is! HPhi);
    super.remove(instruction);
    assert(instruction.block == this);
    instruction.notifyRemovedFromBlock();
  }

  void addSuccessor(HBasicBlock block) {
    if (successors.isEmpty) {
      successors = [block];
    } else {
      successors.add(block);
    }
    block.predecessors.add(this);
  }

  void postProcessLoopHeader() {
    assert(isLoopHeader());
    // Only the first entry into the loop is from outside the
    // loop. All other entries must be back edges.
    for (int i = 1, length = predecessors.length; i < length; i++) {
      loopInformation.addBackEdge(predecessors[i]);
    }
  }

  /// Rewrites all uses of the [from] instruction to using the [to]
  /// instruction instead.
  void rewrite(HInstruction from, HInstruction to) {
    for (HInstruction use in from.usedBy) {
      use.rewriteInput(from, to);
    }
    to.usedBy.addAll(from.usedBy);
    from.usedBy.clear();
  }

  /// Rewrites all uses of the [from] instruction to using either the
  /// [to] instruction, or a [HCheck] instruction that has better type
  /// information on [to], and that dominates the user.
  void rewriteWithBetterUser(HInstruction from, HInstruction to) {
    // BUG(11841): Turn this method into a phase to be run after GVN phases.
    Link<HCheck> better = const Link<HCheck>();
    for (HInstruction user in to.usedBy) {
      if (user == from || user is! HCheck) continue;
      HCheck check = user;
      if (check.checkedInput == to) {
        better = better.prepend(user);
      }
    }

    if (better.isEmpty) return rewrite(from, to);

    L1:
    for (HInstruction user in from.usedBy) {
      for (HCheck check in better) {
        if (check.dominates(user)) {
          user.rewriteInput(from, check);
          check.usedBy.add(user);
          continue L1;
        }
      }
      user.rewriteInput(from, to);
      to.usedBy.add(user);
    }
    from.usedBy.clear();
  }

  bool isExitBlock() {
    return identical(first, last) && first is HExit;
  }

  void addDominatedBlock(HBasicBlock block) {
    assert(isClosed());
    assert(id != null && block.id != null);
    assert(dominatedBlocks.indexOf(block) < 0);
    // Keep the list of dominated blocks sorted such that if there are two
    // succeeding blocks in the list, the predecessor is before the successor.
    // Assume that we add the dominated blocks in the right order.
    int index = dominatedBlocks.length;
    while (index > 0 && dominatedBlocks[index - 1].id > block.id) {
      index--;
    }
    if (index == dominatedBlocks.length) {
      dominatedBlocks.add(block);
    } else {
      dominatedBlocks.insert(index, block);
    }
    assert(block.dominator == null);
    block.dominator = this;
  }

  void removeDominatedBlock(HBasicBlock block) {
    assert(isClosed());
    assert(id != null && block.id != null);
    int index = dominatedBlocks.indexOf(block);
    assert(index >= 0);
    if (index == dominatedBlocks.length - 1) {
      dominatedBlocks.removeLast();
    } else {
      dominatedBlocks.removeRange(index, index + 1);
    }
    assert(identical(block.dominator, this));
    block.dominator = null;
  }

  void assignCommonDominator(HBasicBlock predecessor) {
    assert(isClosed());
    if (dominator == null) {
      // If this basic block doesn't have a dominator yet we use the
      // given predecessor as the dominator.
      predecessor.addDominatedBlock(this);
    } else if (predecessor.dominator != null) {
      // If the predecessor has a dominator and this basic block has a
      // dominator, we find a common parent in the dominator tree and
      // use that as the dominator.
      HBasicBlock block0 = dominator;
      HBasicBlock block1 = predecessor;
      while (!identical(block0, block1)) {
        if (block0.id > block1.id) {
          block0 = block0.dominator;
        } else {
          block1 = block1.dominator;
        }
        assert(block0 != null && block1 != null);
      }
      if (!identical(dominator, block0)) {
        dominator.removeDominatedBlock(this);
        block0.addDominatedBlock(this);
      }
    }
  }

  void forEachPhi(void f(HPhi phi)) {
    HPhi current = phis.first;
    while (current != null) {
      HInstruction saved = current.next;
      f(current);
      current = saved;
    }
  }

  void forEachInstruction(void f(HInstruction instruction)) {
    HInstruction current = first;
    while (current != null) {
      HInstruction saved = current.next;
      f(current);
      current = saved;
    }
  }

  bool isValid() {
    assert(isClosed());
    HValidator validator = new HValidator();
    validator.visitBasicBlock(this);
    return validator.isValid;
  }

  bool dominates(HBasicBlock other) {
    return this.dominatorDfsIn <= other.dominatorDfsIn &&
        other.dominatorDfsOut <= this.dominatorDfsOut;
  }

  @override
  toString() => 'HBasicBlock($id)';
}

abstract class HInstruction implements Spannable {
  Entity sourceElement;
  SourceInformation sourceInformation;

  final int id = idCounter++;
  static int idCounter;

  final List<HInstruction> inputs;
  final List<HInstruction> usedBy = [];

  HBasicBlock block;
  HInstruction previous = null;
  HInstruction next = null;

  SideEffects sideEffects = new SideEffects.empty();
  bool _useGvn = false;

  // Type codes.
  static const int UNDEFINED_TYPECODE = -1;
  static const int TYPE_GUARD_TYPECODE = 1;
  static const int BOUNDS_CHECK_TYPECODE = 2;
  static const int INTEGER_CHECK_TYPECODE = 3;
  static const int INTERCEPTOR_TYPECODE = 4;
  static const int ADD_TYPECODE = 5;
  static const int DIVIDE_TYPECODE = 6;
  static const int MULTIPLY_TYPECODE = 7;
  static const int SUBTRACT_TYPECODE = 8;
  static const int SHIFT_LEFT_TYPECODE = 9;
  static const int BIT_OR_TYPECODE = 10;
  static const int BIT_AND_TYPECODE = 11;
  static const int BIT_XOR_TYPECODE = 12;
  static const int NEGATE_TYPECODE = 13;
  static const int BIT_NOT_TYPECODE = 14;
  static const int NOT_TYPECODE = 15;
  static const int IDENTITY_TYPECODE = 16;
  static const int GREATER_TYPECODE = 17;
  static const int GREATER_EQUAL_TYPECODE = 18;
  static const int LESS_TYPECODE = 19;
  static const int LESS_EQUAL_TYPECODE = 20;
  static const int STATIC_TYPECODE = 21;
  static const int STATIC_STORE_TYPECODE = 22;
  static const int FIELD_GET_TYPECODE = 23;
  static const int TYPE_CONVERSION_TYPECODE = 24;
  static const int TYPE_KNOWN_TYPECODE = 25;
  static const int INVOKE_STATIC_TYPECODE = 26;
  static const int INDEX_TYPECODE = 27;
  static const int IS_TYPECODE = 28;
  static const int INVOKE_DYNAMIC_TYPECODE = 29;
  static const int SHIFT_RIGHT_TYPECODE = 30;

  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;

  static const int INVOKE_EXTERNAL_TYPECODE = 41;
  static const int FOREIGN_CODE_TYPECODE = 42;
  static const int REMAINDER_TYPECODE = 43;
  static const int GET_LENGTH_TYPECODE = 44;
  static const int ABS_TYPECODE = 45;
  static const int BOOL_CONVERSION_TYPECODE = 46;
  static const int NULL_CHECK_TYPECODE = 47;
  static const int PRIMITIVE_CHECK_TYPECODE = 48;

  static const int IS_TEST_TYPECODE = 49;
  static const int IS_TEST_SIMPLE_TYPECODE = 50;
  static const int AS_CHECK_TYPECODE = 51;
  static const int AS_CHECK_SIMPLE_TYPECODE = 52;
  static const int SUBTYPE_CHECK_TYPECODE = 53;
  static const int LOAD_TYPE_TYPECODE = 54;
  static const int INSTANCE_ENVIRONMENT_TYPECODE = 55;
  static const int TYPE_EVAL_TYPECODE = 56;
  static const int TYPE_BIND_TYPECODE = 57;

  HInstruction(this.inputs, this.instructionType) {
    assert(inputs.every((e) => e != null), "inputs: $inputs");
  }

  @override
  int get hashCode => id;

  bool useGvn() => _useGvn;
  void setUseGvn() {
    _useGvn = true;
  }

  bool get isMovable => useGvn();

  /// A pure instruction is an instruction that does not have any side
  /// effect, nor any dependency. They can be moved anywhere in the
  /// graph.
  bool isPure(AbstractValueDomain domain) {
    return !sideEffects.hasSideEffects() &&
        !sideEffects.dependsOnSomething() &&
        !canThrow(domain);
  }

  /// An instruction is an 'allocation' is it is the sole alias for an object.
  /// This applies to instructions that allocate new objects and can be extended
  /// to methods that return other allocations without escaping them.
  bool isAllocation(AbstractValueDomain domain) => false;

  /// Overridden by [HCheck] to return the actual non-[HCheck]
  /// instruction it checks against.
  HInstruction nonCheck() => this;

  /// Can this node throw an exception?
  bool canThrow(AbstractValueDomain domain) => false;

  /// Does this node potentially affect control flow.
  bool isControlFlow() => false;

  bool isValue(AbstractValueDomain domain) =>
      domain.isPrimitiveValue(instructionType);

  AbstractBool isNull(AbstractValueDomain domain) =>
      domain.isNull(instructionType);

  AbstractBool isConflicting(AbstractValueDomain domain) =>
      domain.isEmpty(instructionType);

  AbstractBool isPrimitive(AbstractValueDomain domain) =>
      domain.isPrimitive(instructionType);

  AbstractBool isPrimitiveNumber(AbstractValueDomain domain) =>
      domain.isPrimitiveNumber(instructionType);

  AbstractBool isPrimitiveBoolean(AbstractValueDomain domain) =>
      domain.isPrimitiveBoolean(instructionType);

  AbstractBool isPrimitiveArray(AbstractValueDomain domain) =>
      domain.isPrimitiveArray(instructionType);

  AbstractBool isIndexablePrimitive(AbstractValueDomain domain) =>
      domain.isIndexablePrimitive(instructionType);

  AbstractBool isFixedArray(AbstractValueDomain domain) =>
      domain.isFixedArray(instructionType);

  AbstractBool isExtendableArray(AbstractValueDomain domain) =>
      domain.isExtendableArray(instructionType);

  AbstractBool isMutableArray(AbstractValueDomain domain) =>
      domain.isMutableArray(instructionType);

  AbstractBool isMutableIndexable(AbstractValueDomain domain) =>
      domain.isMutableIndexable(instructionType);

  AbstractBool isArray(AbstractValueDomain domain) =>
      domain.isArray(instructionType);

  AbstractBool isPrimitiveString(AbstractValueDomain domain) =>
      domain.isPrimitiveString(instructionType);

  AbstractBool isInteger(AbstractValueDomain domain) =>
      domain.isInteger(instructionType);

  AbstractBool isUInt32(AbstractValueDomain domain) =>
      domain.isUInt32(instructionType);

  AbstractBool isUInt31(AbstractValueDomain domain) =>
      domain.isUInt31(instructionType);

  AbstractBool isPositiveInteger(AbstractValueDomain domain) =>
      domain.isPositiveInteger(instructionType);

  AbstractBool isPositiveIntegerOrNull(AbstractValueDomain domain) =>
      domain.isPositiveIntegerOrNull(instructionType);

  AbstractBool isIntegerOrNull(AbstractValueDomain domain) =>
      domain.isIntegerOrNull(instructionType);

  AbstractBool isNumber(AbstractValueDomain domain) =>
      domain.isNumber(instructionType);

  AbstractBool isNumberOrNull(AbstractValueDomain domain) =>
      domain.isNumberOrNull(instructionType);

  AbstractBool isDouble(AbstractValueDomain domain) =>
      domain.isDouble(instructionType);

  AbstractBool isDoubleOrNull(AbstractValueDomain domain) =>
      domain.isDoubleOrNull(instructionType);

  AbstractBool isBoolean(AbstractValueDomain domain) =>
      domain.isBoolean(instructionType);

  AbstractBool isBooleanOrNull(AbstractValueDomain domain) =>
      domain.isBooleanOrNull(instructionType);

  AbstractBool isString(AbstractValueDomain domain) =>
      domain.isString(instructionType);

  AbstractBool isStringOrNull(AbstractValueDomain domain) =>
      domain.isStringOrNull(instructionType);

  AbstractBool isPrimitiveOrNull(AbstractValueDomain domain) =>
      domain.isPrimitiveOrNull(instructionType);

  /// Type of the instruction.
  AbstractValue instructionType;

  HInstruction getDartReceiver(JClosedWorld closedWorld) => null;
  bool onlyThrowsNSM() => false;

  bool isInBasicBlock() => block != null;

  bool gvnEquals(HInstruction other) {
    assert(useGvn() && other.useGvn());
    // Check that the type and the sideEffects match.
    bool hasSameType = typeEquals(other);
    assert(hasSameType == (typeCode() == other.typeCode()));
    if (!hasSameType) return false;
    if (sideEffects != other.sideEffects) return false;
    // Check that the inputs match.
    final int inputsLength = inputs.length;
    final List<HInstruction> otherInputs = other.inputs;
    if (inputsLength != otherInputs.length) return false;
    for (int i = 0; i < inputsLength; i++) {
      if (!identical(inputs[i].nonCheck(), otherInputs[i].nonCheck())) {
        return false;
      }
    }
    // Check that the data in the instruction matches.
    return dataEquals(other);
  }

  int gvnHashCode() {
    int result = typeCode();
    int length = inputs.length;
    for (int i = 0; i < length; i++) {
      result = (result * 19) + (inputs[i].nonCheck().id) + (result >> 7);
    }
    return result;
  }

  // These methods should be overwritten by instructions that
  // participate in global value numbering.
  int typeCode() => HInstruction.UNDEFINED_TYPECODE;
  bool typeEquals(covariant HInstruction other) => false;
  bool dataEquals(covariant HInstruction other) => false;

  accept(HVisitor visitor);

  void notifyAddedToBlock(HBasicBlock targetBlock) {
    assert(!isInBasicBlock());
    assert(block == null);
    // Add [this] to the inputs' uses.
    for (int i = 0; i < inputs.length; i++) {
      assert(inputs[i].isInBasicBlock());
      inputs[i].usedBy.add(this);
    }
    block = targetBlock;
    assert(isValid());
  }

  void notifyRemovedFromBlock() {
    assert(isInBasicBlock());
    assert(usedBy.isEmpty);

    // Remove [this] from the inputs' uses.
    for (int i = 0; i < inputs.length; i++) {
      inputs[i].removeUser(this);
    }
    this.block = null;
    assert(isValid());
  }

  /// Do a in-place change of [from] to [to]. Warning: this function
  /// does not update [inputs] and [usedBy]. Use [changeUse] instead.
  void rewriteInput(HInstruction from, HInstruction to) {
    for (int i = 0; i < inputs.length; i++) {
      if (identical(inputs[i], from)) inputs[i] = to;
    }
  }

  /// Removes all occurrences of [instruction] from [list].
  void removeFromList(List<HInstruction> list, HInstruction instruction) {
    int length = list.length;
    int i = 0;
    while (i < length) {
      if (instruction == list[i]) {
        list[i] = list[length - 1];
        length--;
      } else {
        i++;
      }
    }
    list.length = length;
  }

  /// Removes all occurrences of [user] from [usedBy].
  void removeUser(HInstruction user) {
    removeFromList(usedBy, user);
  }

  // Change all uses of [oldInput] by [this] to [newInput]. Also
  // updates the [usedBy] of [oldInput] and [newInput].
  void changeUse(HInstruction oldInput, HInstruction newInput) {
    assert(newInput != null && !identical(oldInput, newInput));
    for (int i = 0; i < inputs.length; i++) {
      if (identical(inputs[i], oldInput)) {
        inputs[i] = newInput;
        newInput.usedBy.add(this);
      }
    }
    removeFromList(oldInput.usedBy, this);
  }

  void replaceAllUsersDominatedBy(
      HInstruction cursor, HInstruction newInstruction) {
    DominatedUses.of(this, cursor).replaceWith(newInstruction);
  }

  void moveBefore(HInstruction other) {
    assert(this is! HControlFlow);
    assert(this is! HPhi);
    assert(other is! HPhi);
    block.detach(this);
    other.block.internalAddBefore(other, this);
    block = other.block;
  }

  bool isConstant() => false;
  bool isConstantBoolean() => false;
  bool isConstantNull() => false;
  bool isConstantNumber() => false;
  bool isConstantInteger() => false;
  bool isConstantString() => false;
  bool isConstantList() => false;
  bool isConstantMap() => false;
  bool isConstantFalse() => false;
  bool isConstantTrue() => false;

  bool isInterceptor(JClosedWorld closedWorld) => false;

  bool isValid() {
    HValidator validator = new HValidator();
    validator.currentBlock = block;
    validator.visitInstruction(this);
    return validator.isValid;
  }

  bool isCodeMotionInvariant() => false;

  bool isJsStatement() => false;

  bool dominates(HInstruction other) {
    // An instruction does not dominates itself.
    if (this == other) return false;
    if (block != other.block) return block.dominates(other.block);

    HInstruction current = this.next;
    while (current != null) {
      if (current == other) return true;
      current = current.next;
    }
    return false;
  }

  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
    if (type == null) return this;
    // Only the builder knows how to create [HTypeConversion]
    // instructions with generics. It has the generic type context
    // available.
    assert(type is! TypeVariableType);
    assert(closedWorld.dartTypes.treatAsRawType(type) || type is FunctionType);
    if (type is DynamicType) return this;
    if (type is VoidType) return this;
    if (type == closedWorld.commonElements.objectType) return this;
    if (type is FunctionType || type is FutureOrType) {
      return new HTypeConversion(type, kind,
          closedWorld.abstractValueDomain.dynamicType, this, sourceInformation);
    }
    assert(type is InterfaceType);
    if (kind == HTypeConversion.TYPE_CHECK &&
        !closedWorld.dartTypes.treatAsRawType(type)) {
      throw 'creating compound check to $type (this = ${this})';
    } else {
      InterfaceType interfaceType = type;
      AbstractValue subtype = closedWorld.abstractValueDomain
          .createNullableSubtype(interfaceType.element);
      return new HTypeConversion(type, kind, subtype, this, sourceInformation);
    }
  }

  /// Return whether the instructions do not belong to a loop or
  /// belong to the same loop.
  bool hasSameLoopHeaderAs(HInstruction other) {
    return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
  }

  @override
  String toString() => '${this.runtimeType}()';
}

/// The set of uses of [source] that are dominated by [dominator].
class DominatedUses {
  final HInstruction _source;

  // Two list of matching length holding (instruction, input-index) pairs for
  // the dominated uses.
  final List<HInstruction> _instructions = <HInstruction>[];
  final List<int> _indexes = <int>[];

  DominatedUses._(this._source);

  /// The uses of [source] that are dominated by [dominator].
  ///
  /// The uses by [dominator] are included in the result, unless
  /// [excludeDominator] is `true`, so `true` selects uses following
  /// [dominator].
  ///
  /// The uses include the in-edges of a HPhi node that corresponds to a
  /// dominated block. (There can be many such edges on a single phi at the exit
  /// of a loop with many break statements).  If [excludePhiOutEdges] is `true`
  /// then these edge uses are not included.
  static DominatedUses of(HInstruction source, HInstruction dominator,
      {bool excludeDominator: false, bool excludePhiOutEdges: false}) {
    return new DominatedUses._(source)
      .._compute(source, dominator, excludeDominator, excludePhiOutEdges);
  }

  bool get isEmpty => _instructions.isEmpty;
  bool get isNotEmpty => !isEmpty;
  int get length => _instructions.length;

  /// Changes all the uses in the set to [newInstruction].
  void replaceWith(HInstruction newInstruction) {
    assert(!identical(newInstruction, _source));
    if (isEmpty) return;
    for (int i = 0; i < _instructions.length; i++) {
      HInstruction user = _instructions[i];
      int index = _indexes[i];
      HInstruction oldInstruction = user.inputs[index];
      assert(
          identical(oldInstruction, _source),
          'Input ${index} of ${user} changed.'
          '\n  Found: ${oldInstruction}\n  Expected: ${_source}');
      user.inputs[index] = newInstruction;
      oldInstruction.usedBy.remove(user);
      newInstruction.usedBy.add(user);
    }
  }

  bool get isSingleton => _instructions.length == 1;

  HInstruction get single => _instructions.single;

  Iterable<HInstruction> get instructions => _instructions;

  void _addUse(HInstruction user, int inputIndex) {
    _instructions.add(user);
    _indexes.add(inputIndex);
  }

  void _compute(HInstruction source, HInstruction dominator,
      bool excludeDominator, bool excludePhiOutEdges) {
    // Keep track of all instructions that we have to deal with later and count
    // the number of them that are in the current block.
    Set<HInstruction> users = new Setlet<HInstruction>();
    Set<HInstruction> seen = new Setlet<HInstruction>();
    int usersInCurrentBlock = 0;

    HBasicBlock dominatorBlock = dominator.block;

    // Run through all the users and see if they are dominated, or potentially
    // dominated, or partially dominated by [dominator]. It is easier to
    // de-duplicate [usedBy] and process all inputs of an instruction than to
    // track the repeated elements of usedBy and match them up by index.
    for (HInstruction current in source.usedBy) {
      if (!seen.add(current)) continue;
      HBasicBlock currentBlock = current.block;
      if (dominatorBlock.dominates(currentBlock)) {
        users.add(current);
        if (identical(currentBlock, dominatorBlock)) usersInCurrentBlock++;
      } else if (!excludePhiOutEdges && current is HPhi) {
        // A non-dominated HPhi.
        // See if there a dominated edge into the phi. The input must be
        // [source] and the position must correspond to a dominated block.
        List<HBasicBlock> predecessors = currentBlock.predecessors;
        for (int i = 0; i < predecessors.length; i++) {
          if (current.inputs[i] != source) continue;
          HBasicBlock predecessor = predecessors[i];
          if (dominatorBlock.dominates(predecessor)) {
            _addUse(current, i);
          }
        }
      }
    }

    // Run through all the phis in the same block as [dominator] and remove them
    // from the users set. These come before [dominator].
    // TODO(sra): Could we simply not add them in the first place?
    if (usersInCurrentBlock > 0) {
      for (HPhi phi = dominatorBlock.phis.first; phi != null; phi = phi.next) {
        if (users.remove(phi)) {
          if (--usersInCurrentBlock == 0) break;
        }
      }
    }

    // Run through all the instructions before [dominator] and remove them from
    // the users set.
    if (usersInCurrentBlock > 0) {
      HInstruction current = dominatorBlock.first;
      while (!identical(current, dominator)) {
        if (users.contains(current)) {
          // TODO(29302): Use 'user.remove(current)' as the condition.
          users.remove(current);
          if (--usersInCurrentBlock == 0) break;
        }
        current = current.next;
      }
      if (excludeDominator) {
        users.remove(dominator);
      }
    }

    // Convert users into a list of (user, input-index) uses.
    for (HInstruction user in users) {
      var inputs = user.inputs;
      for (int i = 0; i < inputs.length; i++) {
        if (inputs[i] == source) {
          _addUse(user, i);
        }
      }
    }
  }
}

/// A reference to a [HInstruction] that can hold its own source information.
///
/// This used for attaching source information to reads of locals.
class HRef extends HInstruction {
  HRef(HInstruction value, SourceInformation sourceInformation)
      : super([value], value.instructionType) {
    this.sourceInformation = sourceInformation;
  }

  HInstruction get value => inputs[0];

  @override
  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
    HInstruction converted = value.convertType(closedWorld, type, kind);
    if (converted == value) return this;
    HTypeConversion conversion = converted;
    conversion.inputs[0] = this;
    return conversion;
  }

  @override
  accept(HVisitor visitor) => visitor.visitRef(this);

  @override
  String toString() => 'HRef(${value})';
}

/// 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, AbstractValue type)
      : super(inputs, type);
}

/// A [HCheck] instruction is an instruction that might do a dynamic
/// check at runtime on another instruction. To have proper instruction
/// dependencies in the graph, instructions that depend on the check
/// being done reference the [HCheck] instruction instead of the
/// instruction itself.
abstract class HCheck extends HInstruction {
  HCheck(inputs, type) : super(inputs, type) {
    setUseGvn();
  }
  HInstruction get checkedInput => inputs[0];
  @override
  bool isJsStatement() => true;
  @override
  bool canThrow(AbstractValueDomain domain) => true;

  @override
  HInstruction nonCheck() => checkedInput.nonCheck();
}

class HBoundsCheck extends HCheck {
  static const int ALWAYS_FALSE = 0;
  static const int FULL_CHECK = 1;
  static const int ALWAYS_ABOVE_ZERO = 2;
  static const int ALWAYS_BELOW_LENGTH = 3;
  static const int ALWAYS_TRUE = 4;

  /// Details which tests have been done statically during compilation.
  /// Default is that all checks must be performed dynamically.
  int staticChecks = FULL_CHECK;

  HBoundsCheck(length, index, array, type)
      : super(<HInstruction>[length, index, array], type);

  HInstruction get length => inputs[1];
  HInstruction get index => inputs[0];
  HInstruction get array => inputs[2];
  // There can be an additional fourth input which is the index to report to
  // [ioore]. This is used by the expansion of [JSArray.removeLast].
  HInstruction get reportedIndex => inputs.length > 3 ? inputs[3] : index;
  @override
  bool isControlFlow() => true;

  @override
  accept(HVisitor visitor) => visitor.visitBoundsCheck(this);
  @override
  int typeCode() => HInstruction.BOUNDS_CHECK_TYPECODE;
  @override
  bool typeEquals(other) => other is HBoundsCheck;
  @override
  bool dataEquals(HInstruction other) => true;
}

abstract class HConditionalBranch extends HControlFlow {
  HConditionalBranch(AbstractValueDomain domain, List<HInstruction> inputs)
      : super(domain, inputs);
  HInstruction get condition => inputs[0];
  HBasicBlock get trueBranch => block.successors[0];
  HBasicBlock get falseBranch => block.successors[1];
}

abstract class HControlFlow extends HInstruction {
  HControlFlow(AbstractValueDomain domain, List<HInstruction> inputs)
      // TODO(johnniwinther): May only expression-like [HInstruction]s should
      // have an `instructionType`, or statement-like [HInstruction]s should
      // have a throwing getter.
      : super(inputs, domain.emptyType);
  @override
  bool isControlFlow() => true;
  @override
  bool isJsStatement() => true;
}

// Allocates and initializes an instance.
class HCreate extends HInstruction {
  final ClassEntity element;

  /// Does this instruction have reified type information as the last input?
  final bool hasRtiInput;

  /// If this field is not `null`, this call is from an inlined constructor and
  /// we have to register the instantiated type in the code generator. The
  /// [instructionType] of this node is not enough, because we also need the
  /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
  List<InterfaceType> instantiatedTypes;

  /// If this node creates a closure class, [callMethod] is the call method of
  /// the closure class.
  FunctionEntity callMethod;

  HCreate(this.element, List<HInstruction> inputs, AbstractValue type,
      SourceInformation sourceInformation,
      {this.instantiatedTypes, this.hasRtiInput: false, this.callMethod})
      : super(inputs, type) {
    this.sourceInformation = sourceInformation;
  }

  @override
  bool isAllocation(AbstractValueDomain domain) => true;

  HInstruction get rtiInput {
    assert(hasRtiInput);
    return inputs.last;
  }

  @override
  accept(HVisitor visitor) => visitor.visitCreate(this);

  @override
  String toString() => 'HCreate($element, ${instantiatedTypes})';
}

// Allocates a box to hold mutated captured variables.
class HCreateBox extends HInstruction {
  HCreateBox(AbstractValue type) : super(<HInstruction>[], type);

  @override
  bool isAllocation(AbstractValueDomain domain) => true;

  @override
  accept(HVisitor visitor) => visitor.visitCreateBox(this);

  @override
  String toString() => 'HCreateBox()';
}

abstract class HInvoke extends HInstruction {
  bool _isAllocation = false;

  /// [isInterceptedCall] is true if this invocation uses the interceptor
  /// calling convention where the first input is the methods and the second
  /// input is the Dart receiver.
  bool isInterceptedCall = false;

  HInvoke(List<HInstruction> inputs, AbstractValue resultType)
      : super(inputs, resultType) {
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }
  static const int ARGUMENTS_OFFSET = 1;

  @override
  bool canThrow(AbstractValueDomain domain) => true;

  @override
  bool isAllocation(AbstractValueDomain domain) => _isAllocation;

  void setAllocation(bool value) {
    _isAllocation = value;
  }
}

abstract class HInvokeDynamic extends HInvoke {
  final InvokeDynamicSpecializer specializer;

  Selector _selector;
  AbstractValue _receiverType;
  final AbstractValue _originalReceiverType;

  // Cached target when non-nullable receiver type and selector determine a
  // single target. This is in effect a direct call (except for a possible
  // `null` receiver). The element should only be set if the inputs are correct
  // for a direct call. These constraints exclude caching a target when the call
  // needs defaulted arguments, is `noSuchMethod` (legacy), or is a call-through
  // stub.
  MemberEntity element;

  HInvokeDynamic(Selector selector, this._receiverType, this.element,
      List<HInstruction> inputs, bool isIntercepted, AbstractValue resultType)
      : this._selector = selector,
        this._originalReceiverType = _receiverType,
        specializer = isIntercepted
            ? InvokeDynamicSpecializer.lookupSpecializer(selector)
            : const InvokeDynamicSpecializer(),
        super(inputs, resultType) {
    assert(isIntercepted != null);
    assert(_receiverType != null);
    isInterceptedCall = isIntercepted;
  }

  Selector get selector => _selector;

  set selector(Selector selector) {
    _selector = selector;
    element = null; // Cached element would no longer match new selector.
  }

  AbstractValue get receiverType => _receiverType;

  void updateReceiverType(
      AbstractValueDomain abstractValueDomain, AbstractValue value) {
    _receiverType =
        abstractValueDomain.intersection(_originalReceiverType, value);
  }

  @override
  String toString() => 'invoke dynamic: selector=$selector, mask=$receiverType';

  HInstruction get receiver => inputs[0];

  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) {
    return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
  }

  /// The type arguments passed in this dynamic invocation.
  List<DartType> get typeArguments;

  /// Returns whether this call is on an interceptor object.
  bool isCallOnInterceptor(JClosedWorld closedWorld) {
    return isInterceptedCall && receiver.isInterceptor(closedWorld);
  }

  @override
  int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;

  @override
  bool typeEquals(other) => other is HInvokeDynamic;

  @override
  bool dataEquals(HInvokeDynamic other) {
    // Use the name and the kind instead of [Selector.operator==]
    // because we don't need to check the arity (already checked in
    // [gvnEquals]), and the receiver types may not be in sync.
    // TODO(sra): If we GVN calls with named (optional) arguments then the
    // selector needs a deeper check for the same subset of named arguments.
    return selector.name == other.selector.name &&
        selector.kind == other.selector.kind;
  }
}

class HInvokeClosure extends HInvokeDynamic {
  @override
  final List<DartType> typeArguments;

  HInvokeClosure(Selector selector, AbstractValue receiverType,
      List<HInstruction> inputs, AbstractValue resultType, this.typeArguments)
      : super(selector, receiverType, null, inputs, false, resultType) {
    assert(selector.isClosureCall);
    assert(selector.callStructure.typeArgumentCount == typeArguments.length);
    assert(!isInterceptedCall);
  }
  @override
  accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
}

class HInvokeDynamicMethod extends HInvokeDynamic {
  @override
  final List<DartType> typeArguments;

  HInvokeDynamicMethod(
      Selector selector,
      AbstractValue receiverType,
      List<HInstruction> inputs,
      AbstractValue resultType,
      this.typeArguments,
      SourceInformation sourceInformation,
      {bool isIntercepted: false})
      : super(selector, receiverType, null, inputs, isIntercepted, resultType) {
    this.sourceInformation = sourceInformation;
    assert(selector.callStructure.typeArgumentCount == typeArguments.length);
  }

  @override
  String toString() =>
      'invoke dynamic method: selector=$selector, mask=$receiverType';
  @override
  accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
}

abstract class HInvokeDynamicField extends HInvokeDynamic {
  HInvokeDynamicField(
      Selector selector,
      AbstractValue receiverType,
      MemberEntity element,
      List<HInstruction> inputs,
      bool isIntercepted,
      AbstractValue resultType)
      : super(
            selector, receiverType, element, inputs, isIntercepted, resultType);

  @override
  String toString() =>
      'invoke dynamic field: selector=$selector, mask=$receiverType';
}

class HInvokeDynamicGetter extends HInvokeDynamicField {
  HInvokeDynamicGetter(
      Selector selector,
      AbstractValue receiverType,
      MemberEntity element,
      List<HInstruction> inputs,
      bool isIntercepted,
      AbstractValue resultType,
      SourceInformation sourceInformation)
      : super(selector, receiverType, element, inputs, isIntercepted,
            resultType) {
    this.sourceInformation = sourceInformation;
  }

  @override
  accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);

  bool get isTearOff => element != null && element.isFunction;

  @override
  List<DartType> get typeArguments => const <DartType>[];

  // There might be an interceptor input, so `inputs.last` is the dart receiver.
  @override
  bool canThrow(AbstractValueDomain domain) => isTearOff
      ? inputs.last.isNull(domain).isPotentiallyTrue
      : super.canThrow(domain);

  @override
  String toString() =>
      'invoke dynamic getter: selector=$selector, mask=$receiverType';
}

class HInvokeDynamicSetter extends HInvokeDynamicField {
  /// If `true` a call to the setter is needed for checking the type even
  /// though the target field is known.
  bool needsCheck = false;

  HInvokeDynamicSetter(
      Selector selector,
      AbstractValue receiverType,
      MemberEntity element,
      List<HInstruction> inputs,
      bool isIntercepted,
      // TODO(johnniwinther): The result type for a setter should be the empty
      // type.
      AbstractValue resultType,
      SourceInformation sourceInformation)
      : super(selector, receiverType, element, inputs, isIntercepted,
            resultType) {
    this.sourceInformation = sourceInformation;
  }

  @override
  accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);

  @override
  List<DartType> get typeArguments => const <DartType>[];

  @override
  String toString() =>
      'invoke dynamic setter: selector=$selector, mask=$receiverType, element=$element';
}

class HInvokeStatic extends HInvoke {
  final MemberEntity element;

  /// The type arguments passed in this static invocation.
  final List<DartType> typeArguments;

  final bool targetCanThrow;

  @override
  bool canThrow(AbstractValueDomain domain) => targetCanThrow;

  /// If this instruction is a call to a constructor, [instantiatedTypes]
  /// contains the type(s) used in the (Dart) `New` expression(s). The
  /// [instructionType] of this node is not enough, because we also need the
  /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
  List<InterfaceType> instantiatedTypes;

  /// The first input must be the target.
  HInvokeStatic(this.element, inputs, AbstractValue type, this.typeArguments,
      {this.targetCanThrow: true, bool isIntercepted: false})
      : super(inputs, type) {
    isInterceptedCall = isIntercepted;
  }

  @override
  accept(HVisitor visitor) => visitor.visitInvokeStatic(this);

  @override
  int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;

  @override
  String toString() => 'invoke static: $element';
}

class HInvokeSuper extends HInvokeStatic {
  /// The class where the call to super is being done.
  final ClassEntity caller;
  final bool isSetter;
  final Selector selector;

  HInvokeSuper(
      MemberEntity element,
      this.caller,
      this.selector,
      List<HInstruction> inputs,
      bool isIntercepted,
      AbstractValue type,
      List<DartType> typeArguments,
      SourceInformation sourceInformation,
      {this.isSetter})
      : super(element, inputs, type, typeArguments,
            isIntercepted: isIntercepted) {
    this.sourceInformation = sourceInformation;
  }

  HInstruction get receiver => inputs[0];
  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) {
    return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
  }

  /// Returns whether this call is on an interceptor object.
  bool isCallOnInterceptor(JClosedWorld closedWorld) {
    return isInterceptedCall && receiver.isInterceptor(closedWorld);
  }

  @override
  toString() => 'invoke super: $element';
  @override
  accept(HVisitor visitor) => visitor.visitInvokeSuper(this);

  HInstruction get value {
    assert(isSetter);
    // The 'inputs' are [receiver, value] or [interceptor, receiver, value].
    return inputs.last;
  }
}

class HInvokeConstructorBody extends HInvokeStatic {
  // The 'inputs' are
  //     [receiver, arg1, ..., argN] or
  //     [interceptor, receiver, arg1, ... argN].
  HInvokeConstructorBody(
      ConstructorBodyEntity element,
      List<HInstruction> inputs,
      AbstractValue type,
      SourceInformation sourceInformation)
      : super(element, inputs, type, const <DartType>[]) {
    this.sourceInformation = sourceInformation;
  }

  @override
  String toString() => 'invoke constructor body: ${element.name}';
  @override
  accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this);
}

class HInvokeGeneratorBody extends HInvokeStatic {
  // Directly call the JGeneratorBody method. The generator body can be a static
  // method or a member. The target is directly called.
  // The 'inputs' are
  //     [arg1, ..., argN] or
  //     [receiver, arg1, ..., argN] or
  //     [interceptor, receiver, arg1, ... argN].
  // The 'inputs' may or may not have an additional type argument used for
  // creating the generator (T for new Completer<T>() inside the body).
  HInvokeGeneratorBody(FunctionEntity element, List<HInstruction> inputs,
      AbstractValue type, SourceInformation sourceInformation)
      : super(element, inputs, type, const <DartType>[]) {
    this.sourceInformation = sourceInformation;
  }

  @override
  String toString() => 'HInvokeGeneratorBody(${element.name})';
  @override
  accept(HVisitor visitor) => visitor.visitInvokeGeneratorBody(this);
}

abstract class HFieldAccess extends HInstruction {
  final FieldEntity element;

  HFieldAccess(this.element, List<HInstruction> inputs, AbstractValue type)
      : super(inputs, type);

  HInstruction get receiver => inputs[0];
}

class HFieldGet extends HFieldAccess {
  final bool isAssignable;

  HFieldGet(FieldEntity element, HInstruction receiver, AbstractValue type,
      SourceInformation sourceInformation,
      {bool isAssignable})
      : this.isAssignable =
            (isAssignable != null) ? isAssignable : element.isAssignable,
        super(element, <HInstruction>[receiver], type) {
    this.sourceInformation = sourceInformation;
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
    if (this.isAssignable) {
      sideEffects.setDependsOnInstancePropertyStore();
    }
  }

  @override
  bool isInterceptor(JClosedWorld closedWorld) {
    if (sourceElement == null) return false;
    // In case of a closure inside an interceptor class, [:this:] is
    // stored in the generated closure class, and accessed through a
    // [HFieldGet].
    if (sourceElement is ThisLocal) {
      ThisLocal thisLocal = sourceElement;
      return closedWorld.interceptorData
          .isInterceptedClass(thisLocal.enclosingClass);
    }
    return false;
  }

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
  @override
  bool onlyThrowsNSM() => true;

  @override
  accept(HVisitor visitor) => visitor.visitFieldGet(this);

  @override
  int typeCode() => HInstruction.FIELD_GET_TYPECODE;
  @override
  bool typeEquals(other) => other is HFieldGet;
  @override
  bool dataEquals(HFieldGet other) => element == other.element;
  @override
  String toString() => "FieldGet(element=$element,type=$instructionType)";
}

class HFieldSet extends HFieldAccess {
  HFieldSet(AbstractValueDomain domain, FieldEntity element,
      HInstruction receiver, HInstruction value)
      : super(element, <HInstruction>[receiver, value], domain.emptyType) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesInstanceProperty();
  }

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
  @override
  bool onlyThrowsNSM() => true;

  HInstruction get value => inputs[1];
  @override
  accept(HVisitor visitor) => visitor.visitFieldSet(this);

  // HFieldSet is an expression if it has a user.
  @override
  bool isJsStatement() => usedBy.isEmpty;

  @override
  String toString() => "FieldSet(element=$element,type=$instructionType)";
}

class HGetLength extends HInstruction {
  final bool isAssignable;
  HGetLength(HInstruction receiver, AbstractValue type,
      {bool this.isAssignable})
      : super(<HInstruction>[receiver], type) {
    assert(isAssignable != null);
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
    if (this.isAssignable) {
      sideEffects.setDependsOnInstancePropertyStore();
    }
  }

  HInstruction get receiver => inputs.single;

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
  @override
  bool onlyThrowsNSM() => true;

  @override
  accept(HVisitor visitor) => visitor.visitGetLength(this);

  @override
  int typeCode() => HInstruction.GET_LENGTH_TYPECODE;
  @override
  bool typeEquals(other) => other is HGetLength;
  @override
  bool dataEquals(HGetLength other) => true;
  @override
  String toString() => "GetLength()";
}

/// HReadModifyWrite is a late stage instruction for a field (property) update
/// via an assignment operation or pre- or post-increment.
class HReadModifyWrite extends HLateInstruction {
  static const ASSIGN_OP = 0;
  static const PRE_OP = 1;
  static const POST_OP = 2;
  final FieldEntity element;
  final String jsOp;
  final int opKind;

  HReadModifyWrite._(this.element, this.jsOp, this.opKind,
      List<HInstruction> inputs, AbstractValue type)
      : super(inputs, type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesInstanceProperty();
    sideEffects.setDependsOnInstancePropertyStore();
  }

  HReadModifyWrite.assignOp(FieldEntity element, String jsOp,
      HInstruction receiver, HInstruction operand, AbstractValue type)
      : this._(
            element, jsOp, ASSIGN_OP, <HInstruction>[receiver, operand], type);

  HReadModifyWrite.preOp(FieldEntity element, String jsOp,
      HInstruction receiver, AbstractValue type)
      : this._(element, jsOp, PRE_OP, <HInstruction>[receiver], type);

  HReadModifyWrite.postOp(FieldEntity element, String jsOp,
      HInstruction receiver, AbstractValue type)
      : this._(element, jsOp, POST_OP, <HInstruction>[receiver], type);

  HInstruction get receiver => inputs[0];

  bool get isPreOp => opKind == PRE_OP;
  bool get isPostOp => opKind == POST_OP;
  bool get isAssignOp => opKind == ASSIGN_OP;

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
  @override
  bool onlyThrowsNSM() => true;

  HInstruction get value => inputs[1];
  @override
  accept(HVisitor visitor) => visitor.visitReadModifyWrite(this);

  @override
  bool isJsStatement() => isAssignOp;
  @override
  String toString() => "ReadModifyWrite $jsOp $opKind $element";
}

abstract class HLocalAccess extends HInstruction {
  final Local variable;

  HLocalAccess(this.variable, List<HInstruction> inputs, AbstractValue type)
      : super(inputs, type);

  HInstruction get receiver => inputs[0];
}

class HLocalGet extends HLocalAccess {
  // No need to use GVN for a [HLocalGet], it is just a local
  // access.
  HLocalGet(Local variable, HLocalValue local, AbstractValue type,
      SourceInformation sourceInformation)
      : super(variable, <HInstruction>[local], type) {
    this.sourceInformation = sourceInformation;
  }

  @override
  accept(HVisitor visitor) => visitor.visitLocalGet(this);

  HLocalValue get local => inputs[0];
}

class HLocalSet extends HLocalAccess {
  HLocalSet(AbstractValueDomain domain, Local variable, HLocalValue local,
      HInstruction value)
      : super(variable, <HInstruction>[local, value], domain.emptyType);

  @override
  accept(HVisitor visitor) => visitor.visitLocalSet(this);

  HLocalValue get local => inputs[0];
  HInstruction get value => inputs[1];
  @override
  bool isJsStatement() => true;
}

/// Invocation of a native or JS-interop method.
///
/// Includes various invocations where the JavaScript form is similar to the
/// Dart form:
///
///     receiver.property          // An instance getter
///     receiver.property = value  // An instance setter
///     receiver.method(arg)       // An instance method
///
///     Class.property             // A static getter
///     Class.property = value     // A static setter
///     Class.method(arg)          // A static method
///     new Class(arg)             // A constructor
///
/// HInvokeDynamicMethod can be lowered to HInvokeExternal with the same
/// [element]. The difference is a HInvokeDynamicMethod is a call to a
/// Dart-calling-convention stub identifed by [element] that contains a call to
/// the external method, whereas a HInvokeExternal instruction is a direct
/// JavaScript call to the external method identified by [element].
class HInvokeExternal extends HInvoke {
  final FunctionEntity element;

  // The following fields are functions of [element] that are extracted for
  // convenience.
  final NativeBehavior nativeBehavior;
  final NativeThrowBehavior throwBehavior;

  HInvokeExternal(this.element, List<HInstruction> inputs, AbstractValue type,
      this.nativeBehavior,
      {SourceInformation sourceInformation})
      : throwBehavior =
            nativeBehavior?.throwBehavior ?? NativeThrowBehavior.MAY,
        super(inputs, type) {
    if (nativeBehavior == null) {
      sideEffects.setAllSideEffects();
      sideEffects.setDependsOnSomething();
    } else {
      sideEffects.add(nativeBehavior.sideEffects);
    }
    if (nativeBehavior != null && nativeBehavior.useGvn) {
      setUseGvn();
    }
    this.sourceInformation = sourceInformation;
  }

  @override
  accept(HVisitor visitor) => visitor.visitInvokeExternal(this);

  @override
  bool isJsStatement() => false;

  @override
  bool canThrow(AbstractValueDomain domain) {
    if (element.isInstanceMember) {
      if (inputs.length > 0) {
        return inputs.first.isNull(domain).isPotentiallyTrue
            ? throwBehavior.canThrow
            : throwBehavior.onNonNull.canThrow;
      }
    }
    return throwBehavior.canThrow;
  }

  @override
  bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard;

  @override
  bool isAllocation(AbstractValueDomain domain) =>
      nativeBehavior != null &&
      nativeBehavior.isAllocation &&
      this.isNull(domain).isDefinitelyFalse;

  /// Returns `true` if the call will throw an NoSuchMethod error if [receiver]
  /// is `null` before having any other side-effects.
  bool isNullGuardFor(HInstruction receiver) {
    if (!element.isInstanceMember) return false;
    if (inputs.length < 1) return false;
    if (inputs.first.nonCheck() != receiver.nonCheck()) return false;
    return true;
  }

  @override
  int typeCode() => HInstruction.INVOKE_EXTERNAL_TYPECODE;
  @override
  bool typeEquals(other) => other is HInvokeExternal;
  @override
  bool dataEquals(HInvokeExternal other) {
    return element == other.element;
  }

  @override
  String toString() => 'HInvokeExternal($element)';
}

abstract class HForeign extends HInstruction {
  HForeign(AbstractValue type, List<HInstruction> inputs) : super(inputs, type);

  bool get isStatement => false;
  NativeBehavior get nativeBehavior => null;

  @override
  bool canThrow(AbstractValueDomain domain) {
    return sideEffects.hasSideEffects() || sideEffects.dependsOnSomething();
  }
}

class HForeignCode extends HForeign {
  final js.Template codeTemplate;
  @override
  final bool isStatement;
  @override
  final NativeBehavior nativeBehavior;
  NativeThrowBehavior throwBehavior;
  final FunctionEntity foreignFunction;

  HForeignCode(this.codeTemplate, AbstractValue type, List<HInstruction> inputs,
      {this.isStatement: false,
      SideEffects effects,
      NativeBehavior nativeBehavior,
      NativeThrowBehavior throwBehavior,
      this.foreignFunction})
      : this.nativeBehavior = nativeBehavior,
        this.throwBehavior = throwBehavior,
        super(type, inputs) {
    assert(codeTemplate != null);
    if (effects == null && nativeBehavior != null) {
      effects = nativeBehavior.sideEffects;
    }
    if (this.throwBehavior == null) {
      this.throwBehavior = (nativeBehavior == null)
          ? NativeThrowBehavior.MAY
          : nativeBehavior.throwBehavior;
    }
    assert(this.throwBehavior != null);

    if (effects != null) sideEffects.add(effects);
    if (nativeBehavior != null && nativeBehavior.useGvn) {
      setUseGvn();
    }
  }

  HForeignCode.statement(js.Template codeTemplate, List<HInstruction> inputs,
      SideEffects effects, NativeBehavior nativeBehavior, AbstractValue type)
      : this(codeTemplate, type, inputs,
            isStatement: true,
            effects: effects,
            nativeBehavior: nativeBehavior);

  @override
  accept(HVisitor visitor) => visitor.visitForeignCode(this);

  @override
  bool isJsStatement() => isStatement;
  @override
  bool canThrow(AbstractValueDomain domain) {
    if (inputs.length > 0) {
      return inputs.first.isNull(domain).isPotentiallyTrue
          ? throwBehavior.canThrow
          : throwBehavior.onNonNull.canThrow;
    }
    return throwBehavior.canThrow;
  }

  @override
  bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard;

  @override
  bool isAllocation(AbstractValueDomain domain) =>
      nativeBehavior != null &&
      nativeBehavior.isAllocation &&
      isNull(domain).isDefinitelyFalse;

  /// Returns `true` if the template will throw an NoSuchMethod error if
  /// [receiver] is `null` before having any other side-effects.
  bool isNullGuardFor(HInstruction receiver) {
    if (!throwBehavior.isNullNSMGuard) return false;
    if (inputs.length < 1) return false;
    if (inputs.first.nonCheck() != receiver.nonCheck()) return false;
    return true;
  }

  @override
  int typeCode() => HInstruction.FOREIGN_CODE_TYPECODE;
  @override
  bool typeEquals(other) => other is HForeignCode;
  @override
  bool dataEquals(HForeignCode other) {
    return codeTemplate.source != null &&
        codeTemplate.source == other.codeTemplate.source;
  }

  @override
  String toString() => 'HForeignCode("${codeTemplate.source}")';
}

abstract class HInvokeBinary extends HInstruction {
  final Selector selector;
  HInvokeBinary(
      HInstruction left, HInstruction right, this.selector, AbstractValue type)
      : super(<HInstruction>[left, right], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  HInstruction get left => inputs[0];
  HInstruction get right => inputs[1];

  constant_system.BinaryOperation operation();
}

abstract class HBinaryArithmetic extends HInvokeBinary {
  HBinaryArithmetic(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  constant_system.BinaryOperation operation();
}

class HAdd extends HBinaryArithmetic {
  HAdd(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitAdd(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.add;
  @override
  int typeCode() => HInstruction.ADD_TYPECODE;
  @override
  bool typeEquals(other) => other is HAdd;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HDivide extends HBinaryArithmetic {
  HDivide(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitDivide(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.divide;
  @override
  int typeCode() => HInstruction.DIVIDE_TYPECODE;
  @override
  bool typeEquals(other) => other is HDivide;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HMultiply extends HBinaryArithmetic {
  HMultiply(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitMultiply(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.multiply;
  @override
  int typeCode() => HInstruction.MULTIPLY_TYPECODE;
  @override
  bool typeEquals(other) => other is HMultiply;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HSubtract extends HBinaryArithmetic {
  HSubtract(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitSubtract(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.subtract;
  @override
  int typeCode() => HInstruction.SUBTRACT_TYPECODE;
  @override
  bool typeEquals(other) => other is HSubtract;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HTruncatingDivide extends HBinaryArithmetic {
  HTruncatingDivide(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);

  @override
  constant_system.BinaryOperation operation() =>
      constant_system.truncatingDivide;
  @override
  int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE;
  @override
  bool typeEquals(other) => other is HTruncatingDivide;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HRemainder extends HBinaryArithmetic {
  HRemainder(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitRemainder(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.remainder;
  @override
  int typeCode() => HInstruction.REMAINDER_TYPECODE;
  @override
  bool typeEquals(other) => other is HRemainder;
  @override
  bool dataEquals(HInstruction other) => true;
}

/// An [HSwitch] instruction has one input for the incoming
/// value, and one input per constant that it can switch on.
/// Its block has one successor per constant, and one for the default.
class HSwitch extends HControlFlow {
  HSwitch(AbstractValueDomain domain, List<HInstruction> inputs)
      : super(domain, inputs);

  HConstant constant(int index) => inputs[index + 1];
  HInstruction get expression => inputs[0];

  /// Provides the target to jump to if none of the constants match
  /// the expression. If the switch had no default case, this is the
  /// following join-block.
  HBasicBlock get defaultTarget => block.successors.last;

  @override
  accept(HVisitor visitor) => visitor.visitSwitch(this);

  @override
  String toString() => "HSwitch cases = $inputs";
}

abstract class HBinaryBitOp extends HInvokeBinary {
  HBinaryBitOp(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
}

class HShiftLeft extends HBinaryBitOp {
  HShiftLeft(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitShiftLeft(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.shiftLeft;
  @override
  int typeCode() => HInstruction.SHIFT_LEFT_TYPECODE;
  @override
  bool typeEquals(other) => other is HShiftLeft;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HShiftRight extends HBinaryBitOp {
  HShiftRight(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitShiftRight(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.shiftRight;
  @override
  int typeCode() => HInstruction.SHIFT_RIGHT_TYPECODE;
  @override
  bool typeEquals(other) => other is HShiftRight;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitOr extends HBinaryBitOp {
  HBitOr(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitBitOr(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.bitOr;
  @override
  int typeCode() => HInstruction.BIT_OR_TYPECODE;
  @override
  bool typeEquals(other) => other is HBitOr;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitAnd extends HBinaryBitOp {
  HBitAnd(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitBitAnd(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.bitAnd;
  @override
  int typeCode() => HInstruction.BIT_AND_TYPECODE;
  @override
  bool typeEquals(other) => other is HBitAnd;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitXor extends HBinaryBitOp {
  HBitXor(HInstruction left, HInstruction right, Selector selector,
      AbstractValue type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitBitXor(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.bitXor;
  @override
  int typeCode() => HInstruction.BIT_XOR_TYPECODE;
  @override
  bool typeEquals(other) => other is HBitXor;
  @override
  bool dataEquals(HInstruction other) => true;
}

abstract class HInvokeUnary extends HInstruction {
  final Selector selector;
  HInvokeUnary(HInstruction input, this.selector, type)
      : super(<HInstruction>[input], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  HInstruction get operand => inputs[0];

  constant_system.UnaryOperation operation();
}

class HNegate extends HInvokeUnary {
  HNegate(HInstruction input, Selector selector, AbstractValue type)
      : super(input, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitNegate(this);

  @override
  constant_system.UnaryOperation operation() => constant_system.negate;
  @override
  int typeCode() => HInstruction.NEGATE_TYPECODE;
  @override
  bool typeEquals(other) => other is HNegate;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HAbs extends HInvokeUnary {
  HAbs(HInstruction input, Selector selector, AbstractValue type)
      : super(input, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitAbs(this);

  @override
  constant_system.UnaryOperation operation() => constant_system.abs;
  @override
  int typeCode() => HInstruction.ABS_TYPECODE;
  @override
  bool typeEquals(other) => other is HAbs;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitNot extends HInvokeUnary {
  HBitNot(HInstruction input, Selector selector, AbstractValue type)
      : super(input, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitBitNot(this);

  @override
  constant_system.UnaryOperation operation() => constant_system.bitNot;
  @override
  int typeCode() => HInstruction.BIT_NOT_TYPECODE;
  @override
  bool typeEquals(other) => other is HBitNot;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HExit extends HControlFlow {
  HExit(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
  @override
  toString() => 'exit';
  @override
  accept(HVisitor visitor) => visitor.visitExit(this);
}

class HGoto extends HControlFlow {
  HGoto(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
  @override
  toString() => 'goto';
  @override
  accept(HVisitor visitor) => visitor.visitGoto(this);
}

abstract class HJump extends HControlFlow {
  final JumpTarget target;
  final LabelDefinition label;
  HJump(AbstractValueDomain domain, this.target,
      SourceInformation sourceInformation)
      : label = null,
        super(domain, const <HInstruction>[]) {
    this.sourceInformation = sourceInformation;
  }
  HJump.toLabel(AbstractValueDomain domain, LabelDefinition label,
      SourceInformation sourceInformation)
      : label = label,
        target = label.target,
        super(domain, const <HInstruction>[]) {
    this.sourceInformation = sourceInformation;
  }
}

class HBreak extends HJump {
  /// Signals that this is a special break instruction for the synthetic loop
  /// generated for a switch statement with continue statements. See
  /// [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
  final bool breakSwitchContinueLoop;

  HBreak(AbstractValueDomain domain, JumpTarget target,
      SourceInformation sourceInformation,
      {bool this.breakSwitchContinueLoop: false})
      : super(domain, target, sourceInformation);

  HBreak.toLabel(AbstractValueDomain domain, LabelDefinition label,
      SourceInformation sourceInformation)
      : breakSwitchContinueLoop = false,
        super.toLabel(domain, label, sourceInformation);

  @override
  String toString() => (label != null) ? 'break ${label.labelName}' : 'break';

  @override
  accept(HVisitor visitor) => visitor.visitBreak(this);
}

class HContinue extends HJump {
  HContinue(AbstractValueDomain domain, JumpTarget target,
      SourceInformation sourceInformation)
      : super(domain, target, sourceInformation);

  HContinue.toLabel(AbstractValueDomain domain, LabelDefinition label,
      SourceInformation sourceInformation)
      : super.toLabel(domain, label, sourceInformation);

  @override
  String toString() =>
      (label != null) ? 'continue ${label.labelName}' : 'continue';

  @override
  accept(HVisitor visitor) => visitor.visitContinue(this);
}

class HTry extends HControlFlow {
  HLocalValue exception;
  HBasicBlock catchBlock;
  HBasicBlock finallyBlock;
  HTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
  @override
  toString() => 'try';
  @override
  accept(HVisitor visitor) => visitor.visitTry(this);
  HBasicBlock get joinBlock => this.block.successors.last;
}

// An [HExitTry] control flow node is used when the body of a try or
// the body of a catch contains a return, break or continue. To build
// the control flow graph, we explicitly mark the body that
// leads to one of this instruction a predecessor of catch and
// finally.
class HExitTry extends HControlFlow {
  HExitTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
  @override
  toString() => 'exit try';
  @override
  accept(HVisitor visitor) => visitor.visitExitTry(this);
  HBasicBlock get bodyTrySuccessor => block.successors[0];
}

class HIf extends HConditionalBranch {
  HBlockFlow blockInformation = null;
  HIf(AbstractValueDomain domain, HInstruction condition)
      : super(domain, <HInstruction>[condition]);
  @override
  toString() => 'if';
  @override
  accept(HVisitor visitor) => visitor.visitIf(this);

  HBasicBlock get thenBlock {
    assert(identical(block.dominatedBlocks[0], block.successors[0]));
    return block.successors[0];
  }

  HBasicBlock get elseBlock {
    assert(identical(block.dominatedBlocks[1], block.successors[1]));
    return block.successors[1];
  }

  HBasicBlock get joinBlock => blockInformation.continuation;
}

class HLoopBranch extends HConditionalBranch {
  static const int CONDITION_FIRST_LOOP = 0;
  static const int DO_WHILE_LOOP = 1;

  final int kind;
  HLoopBranch(AbstractValueDomain domain, HInstruction condition,
      [this.kind = CONDITION_FIRST_LOOP])
      : super(domain, <HInstruction>[condition]);
  @override
  toString() => 'loop-branch';
  @override
  accept(HVisitor visitor) => visitor.visitLoopBranch(this);
}

class HConstant extends HInstruction {
  final ConstantValue constant;
  HConstant.internal(this.constant, AbstractValue constantType)
      : super(<HInstruction>[], constantType);

  @override
  toString() => 'literal: ${constant.toStructuredText(null)}';
  @override
  accept(HVisitor visitor) => visitor.visitConstant(this);

  @override
  bool isConstant() => true;
  @override
  bool isConstantBoolean() => constant.isBool;
  @override
  bool isConstantNull() => constant.isNull;
  @override
  bool isConstantNumber() => constant.isNum;
  @override
  bool isConstantInteger() => constant.isInt;
  @override
  bool isConstantString() => constant.isString;
  @override
  bool isConstantList() => constant.isList;
  @override
  bool isConstantMap() => constant.isMap;
  @override
  bool isConstantFalse() => constant.isFalse;
  @override
  bool isConstantTrue() => constant.isTrue;

  @override
  bool isInterceptor(JClosedWorld closedWorld) => constant.isInterceptor;

  // Maybe avoid this if the literal is big?
  @override
  bool isCodeMotionInvariant() => true;

  @override
  set instructionType(type) {
    // Only lists can be specialized. The SSA builder uses the
    // inferrer for finding the type of a constant list. We should
    // have the constant know its type instead.
    if (!isConstantList()) return;
    super.instructionType = type;
  }
}

class HNot extends HInstruction {
  HNot(HInstruction value, AbstractValue type)
      : super(<HInstruction>[value], type) {
    setUseGvn();
  }

  @override
  accept(HVisitor visitor) => visitor.visitNot(this);
  @override
  int typeCode() => HInstruction.NOT_TYPECODE;
  @override
  bool typeEquals(other) => other is HNot;
  @override
  bool dataEquals(HInstruction other) => true;
}

/// An [HLocalValue] represents a local. Unlike [HParameterValue]s its
/// first use must be in an HLocalSet. That is, [HParameterValue]s have a
/// value from the start, whereas [HLocalValue]s need to be initialized first.
class HLocalValue extends HInstruction {
  HLocalValue(Entity variable, AbstractValue type)
      : super(<HInstruction>[], type) {
    sourceElement = variable;
  }

  @override
  toString() => 'local ${sourceElement.name}';
  @override
  accept(HVisitor visitor) => visitor.visitLocalValue(this);
}

class HParameterValue extends HLocalValue {
  bool _potentiallyUsedAsVariable = true;

  HParameterValue(Entity variable, AbstractValue type) : super(variable, type);

  // [HParameterValue]s are either the value of the parameter (in fully SSA
  // converted code), or the mutable variable containing the value (in
  // incompletely SSA converted code, e.g. methods containing exceptions).
  bool usedAsVariable() {
    if (_potentiallyUsedAsVariable) {
      // If the HParameterValue is used as a variable, all of the uses should be
      // HLocalGet or HLocalSet, so this loop exits fast.
      for (HInstruction user in usedBy) {
        if (user is HLocalGet) return true;
        if (user is HLocalSet && user.local == this) return true;
      }
      // An 'ssa-conversion' optimization can make the HParameterValue change
      // from a variable to a value, but there is no transformation that
      // re-introduces the variable.
      // TODO(sra): The builder knows that most parameters are not variables to
      // begin with, so could initialize [_potentiallyUsedAsVariable] to
      // `false`.
      _potentiallyUsedAsVariable = false;
    }
    return false;
  }

  @override
  toString() => 'parameter ${sourceElement.name}';
  @override
  accept(HVisitor visitor) => visitor.visitParameterValue(this);
}

class HThis extends HParameterValue {
  HThis(ThisLocal element, AbstractValue type) : super(element, type);

  @override
  ThisLocal get sourceElement => super.sourceElement;

  @override
  void set sourceElement(covariant ThisLocal local) {
    super.sourceElement = local;
  }

  @override
  accept(HVisitor visitor) => visitor.visitThis(this);

  @override
  bool isCodeMotionInvariant() => true;

  @override
  bool isInterceptor(JClosedWorld closedWorld) {
    return closedWorld.interceptorData
        .isInterceptedClass(sourceElement.enclosingClass);
  }

  @override
  String toString() => 'this';
}

class HPhi extends HInstruction {
  static const IS_NOT_LOGICAL_OPERATOR = 0;
  static const IS_AND = 1;
  static const IS_OR = 2;

  int logicalOperatorType = IS_NOT_LOGICAL_OPERATOR;

  // The order of the [inputs] must correspond to the order of the
  // predecessor-edges. That is if an input comes from the first predecessor
  // of the surrounding block, then the input must be the first in the [HPhi].
  HPhi(Local variable, List<HInstruction> inputs, AbstractValue type)
      : super(inputs, type) {
    sourceElement = variable;
  }
  HPhi.noInputs(Local variable, AbstractValue type)
      : this(variable, <HInstruction>[], type);
  HPhi.singleInput(Local variable, HInstruction input, AbstractValue type)
      : this(variable, <HInstruction>[input], type);
  HPhi.manyInputs(Local variable, List<HInstruction> inputs, AbstractValue type)
      : this(variable, inputs, type);

  void addInput(HInstruction input) {
    assert(isInBasicBlock());
    inputs.add(input);
    assert(inputs.length <= block.predecessors.length);
    input.usedBy.add(this);
  }

  @override
  toString() => 'phi $id';
  @override
  accept(HVisitor visitor) => visitor.visitPhi(this);
}

abstract class HRelational extends HInvokeBinary {
  bool usesBoolifiedInterceptor = false;
  HRelational(left, right, selector, type) : super(left, right, selector, type);
}

class HIdentity extends HRelational {
  // Cached codegen decision.
  String singleComparisonOp; // null, '===', '=='

  HIdentity(left, right, selector, type) : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitIdentity(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.identity;
  @override
  int typeCode() => HInstruction.IDENTITY_TYPECODE;
  @override
  bool typeEquals(other) => other is HIdentity;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HGreater extends HRelational {
  HGreater(left, right, selector, type) : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitGreater(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.greater;
  @override
  int typeCode() => HInstruction.GREATER_TYPECODE;
  @override
  bool typeEquals(other) => other is HGreater;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HGreaterEqual extends HRelational {
  HGreaterEqual(left, right, selector, type)
      : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitGreaterEqual(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.greaterEqual;
  @override
  int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE;
  @override
  bool typeEquals(other) => other is HGreaterEqual;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HLess extends HRelational {
  HLess(left, right, selector, type) : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitLess(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.less;
  @override
  int typeCode() => HInstruction.LESS_TYPECODE;
  @override
  bool typeEquals(other) => other is HLess;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HLessEqual extends HRelational {
  HLessEqual(left, right, selector, type) : super(left, right, selector, type);
  @override
  accept(HVisitor visitor) => visitor.visitLessEqual(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.lessEqual;
  @override
  int typeCode() => HInstruction.LESS_EQUAL_TYPECODE;
  @override
  bool typeEquals(other) => other is HLessEqual;
  @override
  bool dataEquals(HInstruction other) => true;
}

/// Return statement, either with or without a value.
class HReturn extends HControlFlow {
  HReturn(AbstractValueDomain domain, HInstruction /*?*/ value,
      SourceInformation sourceInformation)
      : super(domain, [if (value != null) value]) {
    this.sourceInformation = sourceInformation;
  }
  @override
  toString() => 'return';
  @override
  accept(HVisitor visitor) => visitor.visitReturn(this);
}

class HThrowExpression extends HInstruction {
  HThrowExpression(AbstractValueDomain domain, HInstruction value,
      SourceInformation sourceInformation)
      : super(<HInstruction>[value], domain.emptyType) {
    this.sourceInformation = sourceInformation;
  }
  @override
  toString() => 'throw expression';
  @override
  accept(HVisitor visitor) => visitor.visitThrowExpression(this);
  @override
  bool canThrow(AbstractValueDomain domain) => true;
}

class HAwait extends HInstruction {
  HAwait(HInstruction value, AbstractValue type)
      : super(<HInstruction>[value], type);
  @override
  toString() => 'await';
  @override
  accept(HVisitor visitor) => visitor.visitAwait(this);
  // An await will throw if its argument is not a real future.
  @override
  bool canThrow(AbstractValueDomain domain) => true;
  @override
  SideEffects sideEffects = new SideEffects();
}

class HYield extends HInstruction {
  HYield(AbstractValueDomain domain, HInstruction value, this.hasStar,
      SourceInformation sourceInformation)
      : super(<HInstruction>[value], domain.emptyType) {
    this.sourceInformation = sourceInformation;
  }
  bool hasStar;
  @override
  toString() => 'yield';
  @override
  accept(HVisitor visitor) => visitor.visitYield(this);
  @override
  bool canThrow(AbstractValueDomain domain) => false;
  @override
  SideEffects sideEffects = new SideEffects();
}

class HThrow extends HControlFlow {
  final bool isRethrow;
  HThrow(AbstractValueDomain domain, HInstruction value,
      SourceInformation sourceInformation,
      {this.isRethrow: false})
      : super(domain, <HInstruction>[value]) {
    this.sourceInformation = sourceInformation;
  }
  @override
  toString() => 'throw';
  @override
  accept(HVisitor visitor) => visitor.visitThrow(this);
}

// TODO(johnniwinther): Change this to a "HStaticLoad" of a field when we use
// CFE constants. It has been used for static tear-offs even though these should
// have been constants.
class HStatic extends HInstruction {
  final MemberEntity element;

  HStatic(this.element, AbstractValue type, SourceInformation sourceInformation)
      : super(<HInstruction>[], type) {
    assert(element != null);
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    if (element.isAssignable) {
      sideEffects.setDependsOnStaticPropertyStore();
    }
    setUseGvn();
    this.sourceInformation = sourceInformation;
  }
  @override
  toString() => 'static ${element.name}';
  @override
  accept(HVisitor visitor) => visitor.visitStatic(this);

  @override
  int gvnHashCode() => super.gvnHashCode() ^ element.hashCode;
  @override
  int typeCode() => HInstruction.STATIC_TYPECODE;
  @override
  bool typeEquals(other) => other is HStatic;
  @override
  bool dataEquals(HStatic other) => element == other.element;
  @override
  bool isCodeMotionInvariant() => !element.isAssignable;
}

class HInterceptor extends HInstruction {
  // This field should originally be null to allow GVN'ing all
  // [HInterceptor] on the same input.
  Set<ClassEntity> interceptedClasses;

  // inputs[0] is initially the only input, the receiver.

  // inputs[1] is a constant interceptor when the interceptor is a constant
  // except for a `null` receiver.  This is used when the receiver can't be
  // falsy, except for `null`, allowing the generation of code like
  //
  //     (a && C.JSArray_methods).get$first(a)
  //

  HInterceptor(HInstruction receiver, AbstractValue type)
      : super(<HInstruction>[receiver], type) {
    this.sourceInformation = receiver.sourceInformation;
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  @override
  String toString() => 'interceptor on $interceptedClasses';
  @override
  accept(HVisitor visitor) => visitor.visitInterceptor(this);
  HInstruction get receiver => inputs[0];

  bool get isConditionalConstantInterceptor => inputs.length == 2;
  HInstruction get conditionalConstantInterceptor => inputs[1];
  void set conditionalConstantInterceptor(HConstant constant) {
    assert(!isConditionalConstantInterceptor);
    inputs.add(constant);
  }

  @override
  bool isInterceptor(JClosedWorld closedWorld) => true;

  @override
  int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
  @override
  bool typeEquals(other) => other is HInterceptor;
  @override
  bool dataEquals(HInterceptor other) {
    return interceptedClasses == other.interceptedClasses ||
        (interceptedClasses.length == other.interceptedClasses.length &&
            interceptedClasses.containsAll(other.interceptedClasses));
  }
}

/// A "one-shot" interceptor is a call to a synthetized method that
/// will fetch the interceptor of its first parameter, and make a call
/// on a given selector with the remaining parameters.
///
/// In order to share the same optimizations with regular interceptor
/// calls, this class extends [HInvokeDynamic] and also has the null
/// constant as the first input.
class HOneShotInterceptor extends HInvokeDynamic {
  @override
  List<DartType> typeArguments;
  Set<ClassEntity> interceptedClasses;

  HOneShotInterceptor(
      AbstractValueDomain domain,
      Selector selector,
      AbstractValue receiverType,
      List<HInstruction> inputs,
      AbstractValue resultType,
      this.typeArguments,
      this.interceptedClasses)
      : super(selector, receiverType, null, inputs, true, resultType) {
    assert(inputs[0] is HConstant);
    assert(inputs[0].instructionType == domain.nullType);
    assert(selector.callStructure.typeArgumentCount == typeArguments.length);
  }
  @override
  bool isCallOnInterceptor(JClosedWorld closedWorld) => true;

  @override
  String toString() =>
      'one shot interceptor: selector=$selector, mask=$receiverType';
  @override
  accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
}

/// An [HLazyStatic] is a static that is initialized lazily at first read.
class HLazyStatic extends HInstruction {
  final FieldEntity element;

  HLazyStatic(
      this.element, AbstractValue type, SourceInformation sourceInformation)
      : super(<HInstruction>[], type) {
    // TODO(4931): The first access has side-effects, but we afterwards we
    // should be able to GVN.
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
    this.sourceInformation = sourceInformation;
  }

  @override
  toString() => 'lazy static ${element.name}';
  @override
  accept(HVisitor visitor) => visitor.visitLazyStatic(this);

  @override
  int typeCode() => 30;
  // TODO(4931): can we do better here?
  @override
  bool isCodeMotionInvariant() => false;
  @override
  bool canThrow(AbstractValueDomain domain) => true;
}

class HStaticStore extends HInstruction {
  MemberEntity element;
  HStaticStore(AbstractValueDomain domain, this.element, HInstruction value)
      : super(<HInstruction>[value], domain.emptyType) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesStaticProperty();
  }
  @override
  toString() => 'static store ${element.name}';
  @override
  accept(HVisitor visitor) => visitor.visitStaticStore(this);

  HInstruction get value => inputs.single;

  @override
  int typeCode() => HInstruction.STATIC_STORE_TYPECODE;
  @override
  bool typeEquals(other) => other is HStaticStore;
  @override
  bool dataEquals(HStaticStore other) => element == other.element;
  @override
  bool isJsStatement() => usedBy.isEmpty;
}

class HLiteralList extends HInstruction {
  HLiteralList(List<HInstruction> inputs, AbstractValue type)
      : super(inputs, type);
  @override
  toString() => 'literal list';
  @override
  accept(HVisitor visitor) => visitor.visitLiteralList(this);

  @override
  bool isAllocation(AbstractValueDomain domain) => true;
}

/// The primitive array indexing operation. Note that this instruction
/// does not throw because we generate the checks explicitly.
class HIndex extends HInstruction {
  final Selector selector;
  HIndex(HInstruction receiver, HInstruction index, this.selector,
      AbstractValue type)
      : super(<HInstruction>[receiver, index], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setDependsOnIndexStore();
    setUseGvn();
  }

  @override
  String toString() => 'index operator';
  @override
  accept(HVisitor visitor) => visitor.visitIndex(this);

  HInstruction get receiver => inputs[0];
  HInstruction get index => inputs[1];

  // Implicit dependency on HBoundsCheck or constraints on index.
  // TODO(27272): Make HIndex dependent on bounds checking.
  @override
  bool get isMovable => false;

  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
  @override
  bool onlyThrowsNSM() => true;
  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  int typeCode() => HInstruction.INDEX_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HIndex;
  @override
  bool dataEquals(HIndex other) => true;
}

/// The primitive array assignment operation. Note that this instruction
/// does not throw because we generate the checks explicitly.
class HIndexAssign extends HInstruction {
  final Selector selector;
  HIndexAssign(AbstractValueDomain domain, HInstruction receiver,
      HInstruction index, HInstruction value, this.selector)
      : super(<HInstruction>[receiver, index, value], domain.emptyType) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesIndex();
  }
  @override
  String toString() => 'index assign operator';
  @override
  accept(HVisitor visitor) => visitor.visitIndexAssign(this);

  HInstruction get receiver => inputs[0];
  HInstruction get index => inputs[1];
  HInstruction get value => inputs[2];

  // Implicit dependency on HBoundsCheck or constraints on index.
  // TODO(27272): Make HIndex dependent on bounds checking.
  @override
  bool get isMovable => false;

  @override
  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
  @override
  bool onlyThrowsNSM() => true;
  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;
}

/// Is-test using legacy constructor based typ representation.
class HIs extends HInstruction {
  /// A check against a raw type: 'o is int', 'o is A'.
  static const int RAW_CHECK = 0;

  /// A check against a type with type arguments: 'o is List<int>', 'o is C<T>'.
  static const int COMPOUND_CHECK = 1;

  /// A check against a single type variable: 'o is T'.
  static const int VARIABLE_CHECK = 2;

  final DartType typeExpression;
  final int kind;
  final bool useInstanceOf;

  HIs.direct(DartType typeExpression, HInstruction expression,
      AbstractValue type, SourceInformation sourceInformation)
      : this.internal(
            typeExpression, [expression], RAW_CHECK, type, sourceInformation);

  // Pre-verified that the check can be done using 'instanceof'.
  HIs.instanceOf(DartType typeExpression, HInstruction expression,
      AbstractValue type, SourceInformation sourceInformation)
      : this.internal(
            typeExpression, [expression], RAW_CHECK, type, sourceInformation,
            useInstanceOf: true);

  factory HIs.raw(
      DartType typeExpression,
      HInstruction expression,
      HInterceptor interceptor,
      AbstractValue type,
      SourceInformation sourceInformation) {
    // TODO(sigmund): re-add `&& typeExpression.treatAsRaw` or something
    // equivalent (which started failing once we allowed typeExpressions that
    // contain type parameters matching the original bounds of the type).
    assert((typeExpression is FunctionType || typeExpression is InterfaceType),
        "Unexpected raw is-test type: $typeExpression");
    return new HIs.internal(typeExpression, [expression, interceptor],
        RAW_CHECK, type, sourceInformation);
  }

  HIs.compound(
      DartType typeExpression,
      HInstruction expression,
      HInstruction call,
      AbstractValue type,
      SourceInformation sourceInformation)
      : this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type,
            sourceInformation);

  HIs.variable(
      DartType typeExpression,
      HInstruction expression,
      HInstruction call,
      AbstractValue type,
      SourceInformation sourceInformation)
      : this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type,
            sourceInformation);

  HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind,
      AbstractValue type, SourceInformation sourceInformation,
      {bool this.useInstanceOf: false})
      : super(inputs, type) {
    assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK);
    setUseGvn();
    this.sourceInformation = sourceInformation;
  }

  HInstruction get expression => inputs[0];

  HInstruction get interceptor {
    assert(kind == RAW_CHECK);
    return inputs.length > 1 ? inputs[1] : null;
  }

  HInstruction get checkCall {
    assert(kind == VARIABLE_CHECK || kind == COMPOUND_CHECK);
    return inputs[1];
  }

  bool get isRawCheck => kind == RAW_CHECK;
  bool get isVariableCheck => kind == VARIABLE_CHECK;
  bool get isCompoundCheck => kind == COMPOUND_CHECK;

  @override
  accept(HVisitor visitor) => visitor.visitIs(this);

  @override
  toString() => "$expression is $typeExpression";

  @override
  int typeCode() => HInstruction.IS_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HIs;

  @override
  bool dataEquals(HIs other) {
    return typeExpression == other.typeExpression && kind == other.kind;
  }
}

/// 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, AbstractValue type)
      : super(<HInstruction>[interceptor], type) {
    setUseGvn();
  }

  HInstruction get interceptor => inputs[0];

  @override
  accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this);
  @override
  toString() => "$interceptor is $typeExpression";
  @override
  int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HIsViaInterceptor;
  @override
  bool dataEquals(HIs other) {
    return typeExpression == other.typeExpression;
  }
}

/// HLateValue is a late-stage instruction that can be used to force a value
/// into a temporary.
///
/// HLateValue is useful for naming values that would otherwise be generated at
/// use site, for example, if 'this' is used many times, replacing uses of
/// 'this' with HLateValue(HThis) will have the effect of copying 'this' to a
/// temporary will reduce the size of minified code.
class HLateValue extends HLateInstruction {
  HLateValue(HInstruction target) : super([target], target.instructionType);

  HInstruction get target => inputs.single;

  @override
  accept(HVisitor visitor) => visitor.visitLateValue(this);
  @override
  toString() => 'HLateValue($target)';
}

/// Type check or cast using legacy constructor-based type representation.
class HTypeConversion extends HCheck {
  // Values for [kind].
  static const int TYPE_CHECK = 0;
  static const int CAST_CHECK = 1;

  final DartType typeExpression;
  final int kind;

  AbstractValue checkedType; // Not final because we refine it.

  HTypeConversion(this.typeExpression, this.kind, AbstractValue type,
      HInstruction input, SourceInformation sourceInformation)
      : checkedType = type,
        super(<HInstruction>[input], type) {
    this.sourceElement = input.sourceElement;
    this.sourceInformation = sourceInformation;
  }

  HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
      AbstractValue type, HInstruction input, HInstruction typeRepresentation)
      : checkedType = type,
        super(<HInstruction>[input, typeRepresentation], type) {
    sourceElement = input.sourceElement;
  }

  bool get hasTypeRepresentation {
    return typeExpression != null &&
        typeExpression is InterfaceType &&
        inputs.length > 1;
  }

  HInstruction get typeRepresentation => inputs[1];

  @override
  HInstruction get checkedInput => super.checkedInput;

  @override
  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
    if (typeExpression == type) {
      return this;
    }
    return super.convertType(closedWorld, type, kind);
  }

  bool get isTypeCheck => kind == TYPE_CHECK;
  bool get isCastCheck => kind == CAST_CHECK;

  @override
  accept(HVisitor visitor) => visitor.visitTypeConversion(this);

  @override
  bool isJsStatement() => isControlFlow();
  @override
  bool isControlFlow() => false;

  @override
  int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HTypeConversion;
  @override
  bool isCodeMotionInvariant() => false;

  @override
  bool dataEquals(HTypeConversion other) {
    return kind == other.kind &&
        typeExpression == other.typeExpression &&
        checkedType == other.checkedType;
  }

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    DartType type = typeExpression;
    if (type != null) {
      if (type is TypeVariableType) {
        return false;
      }
      if (type is FutureOrType) {
        // `null` always passes type conversion.
        if (checkedInput.isNull(abstractValueDomain).isDefinitelyTrue) {
          return true;
        }
        // TODO(johnniwinther): Optimize FutureOr type conversions.
        return false;
      }
      if (!closedWorld.dartTypes.treatAsRawType(type)) {
        // `null` always passes type conversion.
        if (checkedInput.isNull(abstractValueDomain).isDefinitelyTrue) {
          return true;
        }
        return false;
      }
      if (type is FunctionType) {
        // `null` always passes type conversion.
        if (checkedInput.isNull(abstractValueDomain).isDefinitelyTrue) {
          return true;
        }
        // TODO(johnniwinther): Optimize function type conversions.
        return false;
      }
    }
    // Type is refined from `dynamic`, so it might become non-redundant.
    if (abstractValueDomain.containsAll(checkedType).isPotentiallyTrue) {
      return false;
    }
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
  }

  @override
  String toString() => 'HTypeConversion(type=$typeExpression, kind=$kind, '
      '${hasTypeRepresentation ? 'representation=$typeRepresentation, ' : ''}'
      'checkedInput=$checkedInput)';
}

/// Check for receiver or argument type when lowering operation to a primitive,
/// e.g. lowering `+` to [HAdd].
///
/// After NNBD, `a + b` will require `a` and `b` are non-nullable and these
/// checks will become explicit in the source (e.g. `a! + b!`). At that time,
/// this check should be removed.  If needed, the `!` check can be optimized
/// give the same signals to the JavaScript VM.
class HPrimitiveCheck extends HCheck {
  // Values for [kind].
  static const int ARGUMENT_TYPE_CHECK = 1;
  static const int RECEIVER_TYPE_CHECK = 3;

  final DartType typeExpression;
  final int kind;

  // [receiverTypeCheckSelector] is the selector used for a receiver type check
  // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
  // compiled to the following, for which we need the selector `$add`.
  //
  //     if (typeof x != "number") x.$add();
  //
  final Selector receiverTypeCheckSelector;

  AbstractValue checkedType; // Not final because we refine it.

  HPrimitiveCheck(this.typeExpression, this.kind, AbstractValue type,
      HInstruction input, SourceInformation sourceInformation,
      {this.receiverTypeCheckSelector})
      : checkedType = type,
        super(<HInstruction>[input], type) {
    assert(isReceiverTypeCheck == (receiverTypeCheckSelector != null));
    this.sourceElement = input.sourceElement;
    this.sourceInformation = sourceInformation;
  }

  @override
  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
    if (typeExpression == type) {
      return this;
    }
    return super.convertType(closedWorld, type, kind);
  }

  bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
  bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;

  @override
  accept(HVisitor visitor) => visitor.visitPrimitiveCheck(this);

  @override
  bool isJsStatement() => true;
  @override
  bool isControlFlow() => true;

  @override
  int typeCode() => HInstruction.PRIMITIVE_CHECK_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HPrimitiveCheck;
  @override
  bool isCodeMotionInvariant() => false;

  @override
  bool dataEquals(HPrimitiveCheck other) {
    return kind == other.kind &&
        checkedType == other.checkedType &&
        receiverTypeCheckSelector == other.receiverTypeCheckSelector;
  }

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    // Type is refined from `dynamic`, so it might become non-redundant.
    if (abstractValueDomain.containsAll(checkedType).isPotentiallyTrue) {
      return false;
    }
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
  }

  @override
  String toString() => 'HPrimitiveCheck(checkedType=$checkedType, kind=$kind, '
      'checkedInput=$checkedInput)';
}

/// A check that the input to a condition (if, ?:, while, etc) is non-null. The
/// front-end generates 'as bool' checks, but until the transition to NNBD is
/// complete, this allows `null` to be passed to the condition.
///
// TODO(sra): Once NNDB is far enough along that the front-end can generate `as
// bool!` checks and the backend checks them correctly, this instruction will
// become unnecessary and should be removed.
class HBoolConversion extends HCheck {
  HBoolConversion(HInstruction input, AbstractValue type)
      : super(<HInstruction>[input], type);

  @override
  bool isJsStatement() => false;

  @override
  bool isCodeMotionInvariant() => false;

  @override
  accept(HVisitor visitor) => visitor.visitBoolConversion(this);

  @override
  int typeCode() => HInstruction.BOOL_CONVERSION_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HBoolConversion;
  @override
  bool dataEquals(HBoolConversion other) => true;

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain
        .isIn(inputType, instructionType)
        .isDefinitelyTrue;
  }

  @override
  toString() => 'HBoolConversion($checkedInput)';
}

/// A check that the input is not null. This corresponds to the postfix
/// null-check operator '!'.
///
/// A null check is inserted on the receiver when inlining an instance method or
/// field getter or setter when the receiver might be null. In these cases, the
/// [selector] and [field] members are assigned.
class HNullCheck extends HCheck {
  Selector selector;
  FieldEntity field;

  HNullCheck(HInstruction input, AbstractValue type)
      : super(<HInstruction>[input], type);

  @override
  bool isControlFlow() => true;
  @override
  bool isJsStatement() => true;

  @override
  bool isCodeMotionInvariant() => false;

  @override
  accept(HVisitor visitor) => visitor.visitNullCheck(this);

  @override
  int typeCode() => HInstruction.NULL_CHECK_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HNullCheck;
  @override
  bool dataEquals(HNullCheck other) => true;

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isNull(inputType).isDefinitelyFalse;
  }

  @override
  toString() {
    String fieldString = field == null ? '' : ', $field';
    String selectorString = selector == null ? '' : ', $selector';
    return 'HNullCheck($checkedInput$fieldString$selectorString)';
  }
}

/// The [HTypeKnown] instruction marks a value with a refined type.
class HTypeKnown extends HCheck {
  AbstractValue knownType;
  final bool _isMovable;

  HTypeKnown.pinned(AbstractValue knownType, HInstruction input)
      : this.knownType = knownType,
        this._isMovable = false,
        super(<HInstruction>[input], knownType);

  HTypeKnown.witnessed(
      AbstractValue knownType, HInstruction input, HInstruction witness)
      : this.knownType = knownType,
        this._isMovable = true,
        super(<HInstruction>[input, witness], knownType);

  @override
  toString() => 'TypeKnown $knownType';
  @override
  accept(HVisitor visitor) => visitor.visitTypeKnown(this);

  @override
  bool isJsStatement() => false;
  @override
  bool isControlFlow() => false;
  @override
  bool canThrow(AbstractValueDomain domain) => false;

  bool get isPinned => inputs.length == 1;

  HInstruction get witness => inputs.length == 2 ? inputs[1] : null;

  @override
  int typeCode() => HInstruction.TYPE_KNOWN_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HTypeKnown;
  @override
  bool isCodeMotionInvariant() => true;
  @override
  bool get isMovable => _isMovable && useGvn();

  @override
  bool dataEquals(HTypeKnown other) {
    return knownType == other.knownType &&
        instructionType == other.instructionType;
  }

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    if (abstractValueDomain.containsAll(knownType).isPotentiallyTrue) {
      return false;
    }
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isIn(inputType, knownType).isDefinitelyTrue;
  }
}

class HRangeConversion extends HCheck {
  HRangeConversion(HInstruction input, type)
      : super(<HInstruction>[input], type) {
    sourceElement = input.sourceElement;
  }

  @override
  bool get isMovable => false;

  @override
  accept(HVisitor visitor) => visitor.visitRangeConversion(this);
}

class HStringConcat extends HInstruction {
  HStringConcat(HInstruction left, HInstruction right, AbstractValue type)
      : super(<HInstruction>[left, right], type) {
    // TODO(sra): Until Issue 9293 is fixed, this false dependency keeps the
    // concats bunched with stringified inputs for much better looking code with
    // fewer temps.
    sideEffects.setDependsOnSomething();
  }

  HInstruction get left => inputs[0];
  HInstruction get right => inputs[1];

  @override
  accept(HVisitor visitor) => visitor.visitStringConcat(this);
  @override
  toString() => "string concat";
}

/// The part of string interpolation which converts and interpolated expression
/// into a String value.
class HStringify extends HInstruction {
  HStringify(HInstruction input, AbstractValue resultType)
      : super(<HInstruction>[input], resultType) {
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }

  @override
  accept(HVisitor visitor) => visitor.visitStringify(this);
  @override
  toString() => "stringify";
}

/// Non-block-based (aka. traditional) loop information.
class HLoopInformation {
  final HBasicBlock header;
  final List<HBasicBlock> blocks;
  final List<HBasicBlock> backEdges;
  final List<LabelDefinition> labels;
  final JumpTarget target;

  /// Corresponding block information for the loop.
  HLoopBlockInformation loopBlockInformation;

  HLoopInformation(this.header, this.target, this.labels)
      : blocks = new List<HBasicBlock>(),
        backEdges = new List<HBasicBlock>();

  void addBackEdge(HBasicBlock predecessor) {
    backEdges.add(predecessor);
    List<HBasicBlock> workQueue = <HBasicBlock>[predecessor];
    do {
      HBasicBlock current = workQueue.removeLast();
      addBlock(current, workQueue);
    } while (!workQueue.isEmpty);
  }

  // Adds a block and transitively all its predecessors in the loop as
  // loop blocks.
  void addBlock(HBasicBlock block, List<HBasicBlock> workQueue) {
    if (identical(block, header)) return;
    HBasicBlock parentHeader = block.parentLoopHeader;
    if (identical(parentHeader, header)) {
      // Nothing to do in this case.
    } else if (parentHeader != null) {
      workQueue.add(parentHeader);
    } else {
      block.parentLoopHeader = header;
      blocks.add(block);
      workQueue.addAll(block.predecessors);
    }
  }
}

/// Embedding of a [HBlockInformation] for block-structure based traversal
/// in a dominator based flow traversal by attaching it to a basic block.
/// To go back to dominator-based traversal, a [HSubGraphBlockInformation]
/// structure can be added in the block structure.
class HBlockFlow {
  final HBlockInformation body;
  final HBasicBlock continuation;
  HBlockFlow(this.body, this.continuation);
}

/// Information about a syntactic-like structure.
abstract class HBlockInformation {
  HBasicBlock get start;
  HBasicBlock get end;
  bool accept(HBlockInformationVisitor visitor);
}

/// Information about a statement-like structure.
abstract class HStatementInformation extends HBlockInformation {
  @override
  bool accept(HStatementInformationVisitor visitor);
}

/// Information about an expression-like structure.
abstract class HExpressionInformation extends HBlockInformation {
  @override
  bool accept(HExpressionInformationVisitor visitor);
  HInstruction get conditionExpression;
}

abstract class HStatementInformationVisitor {
  bool visitLabeledBlockInfo(HLabeledBlockInformation info);
  bool visitLoopInfo(HLoopBlockInformation info);
  bool visitIfInfo(HIfBlockInformation info);
  bool visitTryInfo(HTryBlockInformation info);
  bool visitSwitchInfo(HSwitchBlockInformation info);
  bool visitSequenceInfo(HStatementSequenceInformation info);
  // Pseudo-structure embedding a dominator-based traversal into
  // the block-structure traversal. This will eventually go away.
  bool visitSubGraphInfo(HSubGraphBlockInformation info);
}

abstract class HExpressionInformationVisitor {
  bool visitAndOrInfo(HAndOrBlockInformation info);
  bool visitSubExpressionInfo(HSubExpressionBlockInformation info);
}

abstract class HBlockInformationVisitor
    implements HStatementInformationVisitor, HExpressionInformationVisitor {}

/// Generic class wrapping a [SubGraph] as a block-information until
/// all structures are handled properly.
class HSubGraphBlockInformation implements HStatementInformation {
  final SubGraph subGraph;
  HSubGraphBlockInformation(this.subGraph);

  @override
  HBasicBlock get start => subGraph.start;
  @override
  HBasicBlock get end => subGraph.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitSubGraphInfo(this);
}

/// Generic class wrapping a [SubExpression] as a block-information until
/// expressions structures are handled properly.
class HSubExpressionBlockInformation implements HExpressionInformation {
  final SubExpression subExpression;
  HSubExpressionBlockInformation(this.subExpression);

  @override
  HBasicBlock get start => subExpression.start;
  @override
  HBasicBlock get end => subExpression.end;

  @override
  HInstruction get conditionExpression => subExpression.conditionExpression;

  @override
  bool accept(HExpressionInformationVisitor visitor) =>
      visitor.visitSubExpressionInfo(this);
}

/// A sequence of separate statements.
class HStatementSequenceInformation implements HStatementInformation {
  final List<HStatementInformation> statements;
  HStatementSequenceInformation(this.statements);

  @override
  HBasicBlock get start => statements[0].start;
  @override
  HBasicBlock get end => statements.last.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitSequenceInfo(this);
}

class HLabeledBlockInformation implements HStatementInformation {
  final HStatementInformation body;
  final List<LabelDefinition> labels;
  final JumpTarget target;
  final bool isContinue;

  HLabeledBlockInformation(this.body, List<LabelDefinition> labels,
      {this.isContinue: false})
      : this.labels = labels,
        this.target = labels[0].target;

  HLabeledBlockInformation.implicit(this.body, this.target,
      {this.isContinue: false})
      : this.labels = const <LabelDefinition>[];

  @override
  HBasicBlock get start => body.start;
  @override
  HBasicBlock get end => body.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitLabeledBlockInfo(this);
}

class HLoopBlockInformation implements HStatementInformation {
  static const int WHILE_LOOP = 0;
  static const int FOR_LOOP = 1;
  static const int DO_WHILE_LOOP = 2;
  static const int FOR_IN_LOOP = 3;
  static const int SWITCH_CONTINUE_LOOP = 4;
  static const int NOT_A_LOOP = -1;

  final int kind;
  final HExpressionInformation initializer;
  final HExpressionInformation condition;
  final HStatementInformation body;
  final HExpressionInformation updates;
  final JumpTarget target;
  final List<LabelDefinition> labels;
  final SourceInformation sourceInformation;

  HLoopBlockInformation(this.kind, this.initializer, this.condition, this.body,
      this.updates, this.target, this.labels, this.sourceInformation) {
    assert(
        (kind == DO_WHILE_LOOP ? body.start : condition.start).isLoopHeader());
  }

  @override
  HBasicBlock get start {
    if (initializer != null) return initializer.start;
    if (kind == DO_WHILE_LOOP) {
      return body.start;
    }
    return condition.start;
  }

  HBasicBlock get loopHeader {
    return kind == DO_WHILE_LOOP ? body.start : condition.start;
  }

  @override
  HBasicBlock get end {
    if (updates != null) return updates.end;
    if (kind == DO_WHILE_LOOP && condition != null) {
      return condition.end;
    }
    return body.end;
  }

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitLoopInfo(this);
}

class HIfBlockInformation implements HStatementInformation {
  final HExpressionInformation condition;
  final HStatementInformation thenGraph;
  final HStatementInformation elseGraph;
  HIfBlockInformation(this.condition, this.thenGraph, this.elseGraph);

  @override
  HBasicBlock get start => condition.start;
  @override
  HBasicBlock get end => elseGraph == null ? thenGraph.end : elseGraph.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitIfInfo(this);
}

class HAndOrBlockInformation implements HExpressionInformation {
  final bool isAnd;
  final HExpressionInformation left;
  final HExpressionInformation right;
  HAndOrBlockInformation(this.isAnd, this.left, this.right);

  @override
  HBasicBlock get start => left.start;
  @override
  HBasicBlock get end => right.end;

  // We don't currently use HAndOrBlockInformation.
  @override
  HInstruction get conditionExpression {
    return null;
  }

  @override
  bool accept(HExpressionInformationVisitor visitor) =>
      visitor.visitAndOrInfo(this);
}

class HTryBlockInformation implements HStatementInformation {
  final HStatementInformation body;
  final HLocalValue catchVariable;
  final HStatementInformation catchBlock;
  final HStatementInformation finallyBlock;
  HTryBlockInformation(
      this.body, this.catchVariable, this.catchBlock, this.finallyBlock);

  @override
  HBasicBlock get start => body.start;
  @override
  HBasicBlock get end =>
      finallyBlock == null ? catchBlock.end : finallyBlock.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitTryInfo(this);
}

class HSwitchBlockInformation implements HStatementInformation {
  final HExpressionInformation expression;
  final List<HStatementInformation> statements;
  final JumpTarget target;
  final List<LabelDefinition> labels;
  final SourceInformation sourceInformation;

  HSwitchBlockInformation(this.expression, this.statements, this.target,
      this.labels, this.sourceInformation);

  @override
  HBasicBlock get start => expression.start;
  @override
  HBasicBlock get end {
    // We don't create a switch block if there are no cases.
    assert(!statements.isEmpty);
    return statements.last.end;
  }

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitSwitchInfo(this);
}

/// Reads raw reified type info from an object.
class HTypeInfoReadRaw extends HInstruction {
  HTypeInfoReadRaw(HInstruction receiver, AbstractValue instructionType)
      : super(<HInstruction>[receiver], instructionType) {
    setUseGvn();
  }

  @override
  accept(HVisitor visitor) => visitor.visitTypeInfoReadRaw(this);

  @override
  bool canThrow(AbstractValueDomain domain) => false;

  @override
  int typeCode() => HInstruction.TYPE_INFO_READ_RAW_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HTypeInfoReadRaw;

  @override
  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'. There may be an
/// interceptor argument to access the substitution of native classes.
class HTypeInfoReadVariable extends HInstruction {
  /// The type variable being read.
  final TypeVariableType variable;
  final bool isIntercepted;

  HTypeInfoReadVariable.intercepted(this.variable, HInstruction interceptor,
      HInstruction receiver, AbstractValue instructionType)
      : isIntercepted = true,
        super(<HInstruction>[interceptor, receiver], instructionType) {
    setUseGvn();
  }

  HTypeInfoReadVariable.noInterceptor(
      this.variable, HInstruction receiver, AbstractValue instructionType)
      : isIntercepted = false,
        super(<HInstruction>[receiver], instructionType) {
    setUseGvn();
  }

  HInstruction get interceptor {
    assert(isIntercepted);
    return inputs.first;
  }

  HInstruction get object => inputs.last;

  @override
  accept(HVisitor visitor) => visitor.visitTypeInfoReadVariable(this);

  @override
  bool canThrow(AbstractValueDomain domain) => false;

  @override
  int typeCode() => HInstruction.TYPE_INFO_READ_VARIABLE_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HTypeInfoReadVariable;

  @override
  bool dataEquals(HTypeInfoReadVariable other) {
    return variable == other.variable;
  }

  @override
  String toString() => 'HTypeInfoReadVariable($variable)';
}

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 HCreate should
/// have type `_LinkedHashSet<List<T>>` and the TypeExpression should be a tree:
///
///    HCreate(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;

  /// `true` if this
  final bool isTypeVariableReplacement;

  HTypeInfoExpression(this.kind, this.dartType, List<HInstruction> inputs,
      AbstractValue instructionType,
      {this.isTypeVariableReplacement: false})
      : super(inputs, instructionType) {
    setUseGvn();
  }

  @override
  accept(HVisitor visitor) => visitor.visitTypeInfoExpression(this);

  @override
  bool canThrow(AbstractValueDomain domain) => false;

  @override
  int typeCode() => HInstruction.TYPE_INFO_EXPRESSION_TYPECODE;
  @override
  bool typeEquals(HInstruction other) => other is HTypeInfoExpression;

  @override
  bool dataEquals(HTypeInfoExpression other) {
    return kind == other.kind && dartType == other.dartType;
  }

  @override
  String toString() => 'HTypeInfoExpression($kindAsString, $dartType)';

  // ignore: MISSING_RETURN
  String get kindAsString {
    switch (kind) {
      case TypeInfoExpressionKind.COMPLETE:
        return 'COMPLETE';
      case TypeInfoExpressionKind.INSTANCE:
        return 'INSTANCE';
    }
  }
}

// -----------------------------------------------------------------------------

/// Is-test using Rti form of type expression.
///
/// This instruction can be used for any type. Tests for simple types are
/// lowered to other instructions, so this instruction remains for types that
/// depend on type variables and complex types.
class HIsTest extends HInstruction {
  final AbstractValueWithPrecision checkedAbstractValue;
  final DartType dartType;

  HIsTest(this.dartType, this.checkedAbstractValue, HInstruction checked,
      HInstruction rti, AbstractValue type)
      : super([rti, checked], type) {
    setUseGvn();
  }

  // The type input is first to facilitate the `type.is(value)` codegen pattern.
  HInstruction get typeInput => inputs[0];
  HInstruction get checkedInput => inputs[1];

  AbstractBool evaluate(JClosedWorld closedWorld) =>
      _isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld);

  @override
  accept(HVisitor visitor) => visitor.visitIsTest(this);

  @override
  int typeCode() => HInstruction.IS_TEST_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HIsTest;

  @override
  bool dataEquals(HIsTest other) => true;

  @override
  String toString() => 'HIsTest()';
}

/// Simple is-test for a known type that can be achieved without reference to an
/// Rti describing the type.
class HIsTestSimple extends HInstruction {
  final DartType dartType;
  final AbstractValueWithPrecision checkedAbstractValue;
  final IsTestSpecialization specialization;

  HIsTestSimple(this.dartType, this.checkedAbstractValue, this.specialization,
      HInstruction checked, AbstractValue type)
      : super([checked], type) {
    setUseGvn();
  }

  HInstruction get checkedInput => inputs[0];

  AbstractBool evaluate(JClosedWorld closedWorld) =>
      _isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld);

  @override
  accept(HVisitor visitor) => visitor.visitIsTestSimple(this);

  @override
  int typeCode() => HInstruction.IS_TEST_SIMPLE_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HIsTestSimple;

  @override
  bool dataEquals(HIsTestSimple other) => dartType == other.dartType;

  @override
  String toString() => 'HIsTestSimple()';
}

AbstractBool _isTestResult(HInstruction expression, DartType dartType,
    AbstractValueWithPrecision checkedAbstractValue, JClosedWorld closedWorld) {
  AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
  AbstractValue subsetType = expression.instructionType;
  AbstractValue supersetType = checkedAbstractValue.abstractValue;
  if (checkedAbstractValue.isPrecise &&
      abstractValueDomain.isIn(subsetType, supersetType).isDefinitelyTrue) {
    return AbstractBool.True;
  }

  // TODO(39287): Let the abstract value domain fully handle this.
  // Currently, the abstract value domain cannot (soundly) state that an is-test
  // is definitely false, so we reuse some of the case-by-case logic from the
  // old [HIs] optimization.
  if (closedWorld.dartTypes.isTopType(dartType)) return AbstractBool.True;
  if (dartType is! InterfaceType) return AbstractBool.Maybe;
  InterfaceType type = dartType;
  ClassEntity element = type.element;
  if (type.typeArguments.isNotEmpty) return AbstractBool.Maybe;
  JCommonElements commonElements = closedWorld.commonElements;
  if (expression.isInteger(abstractValueDomain).isDefinitelyTrue) {
    if (element == commonElements.intClass ||
        element == commonElements.numClass ||
        commonElements.isNumberOrStringSupertype(element)) {
      return AbstractBool.True;
    }
    if (element == commonElements.doubleClass) {
      // We let the JS semantics decide for that check. Currently the code we
      // emit will always return true.
      return AbstractBool.Maybe;
    }
    return AbstractBool.False;
  }
  if (expression.isDouble(abstractValueDomain).isDefinitelyTrue) {
    if (element == commonElements.doubleClass ||
        element == commonElements.numClass ||
        commonElements.isNumberOrStringSupertype(element)) {
      return AbstractBool.True;
    }
    if (element == commonElements.intClass) {
      // We let the JS semantics decide for that check. Currently the code we
      // emit will return true for a double that can be represented as a 31-bit
      // integer and for -0.0.
      return AbstractBool.Maybe;
    }
    return AbstractBool.False;
  }
  if (expression.isNumber(abstractValueDomain).isDefinitelyTrue) {
    if (element == commonElements.numClass) {
      return AbstractBool.True;
    }
    // We cannot just return false, because the expression may be of type int or
    // double.
    return AbstractBool.Maybe;
  }
  if (expression.isPrimitiveNumber(abstractValueDomain).isPotentiallyTrue &&
      element == commonElements.intClass) {
    // We let the JS semantics decide for that check.
    return AbstractBool.Maybe;
  }
  // We need the raw check because we don't have the notion of generics in the
  // backend. For example, `this` in a class `A<T>` is currently always
  // considered to have the raw type.
  if (closedWorld.dartTypes.treatAsRawType(type)) {
    return abstractValueDomain.isInstanceOf(subsetType, element);
  }
  return AbstractBool.Maybe;
}

/// Type cast or type check using Rti form of type expression.
class HAsCheck extends HCheck {
  final AbstractValueWithPrecision checkedType;
  final DartType checkedTypeExpression;
  final bool isTypeError;

  HAsCheck(
      HInstruction checked,
      HInstruction rti,
      this.checkedType,
      this.checkedTypeExpression,
      this.isTypeError,
      AbstractValue instructionType)
      : assert(isTypeError != null),
        super([rti, checked], instructionType);

  // The type input is first to facilitate the `type.as(value)` codegen pattern.
  HInstruction get typeInput => inputs[0];
  @override
  HInstruction get checkedInput => inputs[1];

  @override
  bool isJsStatement() => false;

  @override
  accept(HVisitor visitor) => visitor.visitAsCheck(this);

  @override
  int typeCode() => HInstruction.AS_CHECK_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HAsCheck;

  @override
  bool dataEquals(HAsCheck other) {
    return isTypeError == other.isTypeError;
  }

  bool isRedundant(JClosedWorld closedWorld) {
    if (!checkedType.isPrecise) return false;
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain
        .isIn(inputType, checkedType.abstractValue)
        .isDefinitelyTrue;
  }

  @override
  String toString() {
    String error = isTypeError ? 'TypeError' : 'CastError';
    return 'HAsCheck($error)';
  }
}

/// Type cast or type check for simple known types that are achieved via a
/// simple static call.
class HAsCheckSimple extends HCheck {
  final DartType dartType;
  final AbstractValueWithPrecision checkedType;
  final bool isTypeError;
  final MemberEntity method;

  HAsCheckSimple(HInstruction checked, this.dartType, this.checkedType,
      this.isTypeError, this.method, AbstractValue type)
      : assert(isTypeError != null),
        super([checked], type);

  @override
  HInstruction get checkedInput => inputs[0];

  @override
  bool isJsStatement() => false;

  @override
  accept(HVisitor visitor) => visitor.visitAsCheckSimple(this);

  bool isRedundant(JClosedWorld closedWorld) {
    if (!checkedType.isPrecise) return false;
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain
        .isIn(inputType, checkedType.abstractValue)
        .isDefinitelyTrue;
  }

  @override
  int typeCode() => HInstruction.AS_CHECK_SIMPLE_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HAsCheckSimple;

  @override
  bool dataEquals(HAsCheckSimple other) {
    return isTypeError == other.isTypeError && dartType == other.dartType;
  }

  @override
  String toString() {
    String error = isTypeError ? 'TypeError' : 'CastError';
    return 'HAsCheckSimple($error)';
  }
}

/// Subtype check comparing two Rti types.
class HSubtypeCheck extends HCheck {
  HSubtypeCheck(
      HInstruction subtype, HInstruction supertype, AbstractValue type)
      : super([subtype, supertype], type) {
    setUseGvn();
  }

  HInstruction get typeInput => inputs[1];

  @override
  accept(HVisitor visitor) => visitor.visitSubtypeCheck(this);

  @override
  int typeCode() => HInstruction.SUBTYPE_CHECK_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HSubtypeCheck;

  @override
  bool dataEquals(HSubtypeCheck other) => true;

  @override
  String toString() => 'HSubtypeCheck()';
}

/// Common superclass for instructions that generate Rti values.
abstract class HRtiInstruction extends HInstruction {
  HRtiInstruction(List<HInstruction> inputs, AbstractValue type)
      : super(inputs, type);
}

/// Evaluates an Rti type recipe in the global environment.
class HLoadType extends HRtiInstruction {
  TypeRecipe typeExpression;

  HLoadType(this.typeExpression, AbstractValue instructionType)
      : super([], instructionType) {
    setUseGvn();
  }

  HLoadType.type(DartType dartType, AbstractValue instructionType)
      : this(TypeExpressionRecipe(dartType), instructionType);

  @override
  accept(HVisitor visitor) => visitor.visitLoadType(this);

  @override
  int typeCode() => HInstruction.LOAD_TYPE_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HLoadType;

  @override
  bool dataEquals(HLoadType other) {
    return typeExpression == other.typeExpression;
  }

  @override
  String toString() => 'HLoadType($typeExpression)';
}

/// The reified Rti environment stored on a class instance.
///
/// Classes with reified type arguments have the type environment stored on the
/// instance. The reified environment is typically stored as the instance type,
/// e.g. "UnmodifiableListView<int>".
class HInstanceEnvironment extends HRtiInstruction {
  AbstractValue codegenInputType; // Assigned in SsaTypeKnownRemover

  HInstanceEnvironment(HInstruction instance, AbstractValue type)
      : super([instance], type) {
    setUseGvn();
  }

  @override
  accept(HVisitor visitor) => visitor.visitInstanceEnvironment(this);

  @override
  int typeCode() => HInstruction.INSTANCE_ENVIRONMENT_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HInstanceEnvironment;

  @override
  bool dataEquals(HInstanceEnvironment other) => true;

  @override
  String toString() => 'HInstanceEnvironment()';
}

/// Evaluates an Rti type recipe in an Rti environment.
class HTypeEval extends HRtiInstruction {
  TypeEnvironmentStructure envStructure;
  TypeRecipe typeExpression;

  HTypeEval(HInstruction environment, this.envStructure, this.typeExpression,
      AbstractValue type)
      : super([environment], type) {
    setUseGvn();
  }

  @override
  accept(HVisitor visitor) => visitor.visitTypeEval(this);

  @override
  int typeCode() => HInstruction.TYPE_EVAL_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HTypeEval;

  @override
  bool dataEquals(HTypeEval other) {
    return TypeRecipe.yieldsSameType(
        typeExpression, envStructure, other.typeExpression, other.envStructure);
  }

  @override
  String toString() => 'HTypeEval($typeExpression)';
}

/// Extends an Rti type environment with generic function types.
class HTypeBind extends HRtiInstruction {
  HTypeBind(
      HInstruction environment, HInstruction typeArguments, AbstractValue type)
      : super([environment, typeArguments], type) {
    setUseGvn();
  }

  @override
  accept(HVisitor visitor) => visitor.visitTypeBind(this);

  @override
  int typeCode() => HInstruction.TYPE_BIND_TYPECODE;

  @override
  bool typeEquals(HInstruction other) => other is HTypeBind;

  @override
  bool dataEquals(HTypeBind other) => true;

  @override
  String toString() => 'HTypeBind()';
}
