// 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.

part of ssa;

class BailoutInfo {
  int instructionId;
  int bailoutId;
  BailoutInfo(this.instructionId, this.bailoutId);
}

/**
 * Keeps track of the execution environment for instructions. An
 * execution environment contains the SSA instructions that are live.
 */
class Environment {
  final Set<HInstruction> lives;
  final List<HBasicBlock> loopMarkers;
  Environment() : lives = new Set<HInstruction>(),
                  loopMarkers = new List<HBasicBlock>();
  Environment.from(Environment other)
    : lives = new Set<HInstruction>.from(other.lives),
      loopMarkers = new List<HBasicBlock>.from(other.loopMarkers);

  void remove(HInstruction instruction) {
    lives.remove(instruction);
  }

  void add(HInstruction instruction) {
    // If the instruction is a check, we add its checked input
    // instead. This allows sharing the same environment between
    // different type guards.
    //
    // Also, we don't need to add code motion invariant instructions
    // in the live set (because we generate them at use-site), except
    // for parameters that are not 'this', which is always passed as
    // the receiver.
    if (instruction is HCheck) {
      HCheck check = instruction;
      add(check.checkedInput);
    } else if (!instruction.isCodeMotionInvariant()
               || (instruction is HParameterValue && instruction is !HThis)) {
      lives.add(instruction);
    } else {
      for (int i = 0, len = instruction.inputs.length; i < len; i++) {
        add(instruction.inputs[i]);
      }
    }
  }

  void addAll(Environment other) {
    lives.addAll(other.lives);
  }

  bool get isEmpty => lives.isEmpty && loopMarkers.isEmpty;
}


/**
 * Visits the graph in dominator order and inserts TypeGuards in places where
 * we consider the guard to be of value. This phase also does type
 * propagation to help find valuable type guards.
 */
class SsaTypeGuardInserter extends SsaNonSpeculativeTypePropagator
    implements OptimizationPhase {
  final String name = 'SsaTypeGuardInserter';
  final CodegenWorkItem work;
  bool calledInLoop = false;
  bool isRecursiveMethod = false;
  bool hasInsertedChecks = false;
  int stateId = 1;
  Map<HInstruction, HType> savedTypes = new Map<HInstruction, HType>();

  SsaTypeGuardInserter(compiler, this.work) : super(compiler);

  void visitGraph(HGraph graph) {
    // Run the speculative type propagator. This does in-place
    // update of the type of the instructions, and saves the
    // previous types in the [savedTypes] map.
    SsaTypePropagator propagator =
        new SsaSpeculativeTypePropagator(compiler, savedTypes);
    propagator.visitGraph(graph);

    // Put back the original types in the instructions, and save the
    // speculated types in [savedTypes].
    Map<HInstruction, HType> speculativeTypes = new Map<HInstruction, HType>();

    savedTypes.forEach((HInstruction instruction, HType type) {
      speculativeTypes[instruction] = instruction.instructionType;
      instruction.instructionType = type;
    });
    savedTypes = speculativeTypes;

    // Propagate types again, and insert type guards in the graph.
    isRecursiveMethod = graph.isRecursiveMethod;
    calledInLoop = graph.calledInLoop;
    work.guards = <HTypeGuard>[];
    visitDominatorTree(graph);

    // We need to disable the guards, and therefore re-run a
    // non-speculative type propagator that will not use the
    // speculated types.
    work.guards.forEach((HTypeGuard guard) { guard.disable(); });

    propagator = new SsaNonSpeculativeTypePropagator(compiler);
    propagator.visitGraph(graph);
  }

  // Primitive types that are not null are valuable. These include
  // indexable arrays.
  bool typeValuable(HType type) {
    return type.isPrimitive(compiler) && !type.isNull();
  }

  bool get hasTypeGuards => work.guards.length != 0;

  bool isUsedWithIncompatibleSelector(HInstruction instruction,
                                      HType speculativeType) {
    for (HInstruction user in instruction.usedBy) {
      if (user is HCheck
          && isUsedWithIncompatibleSelector(user, speculativeType)) {
        return true;
      } else if (user.selector != null
                 && user.getDartReceiver(compiler) == instruction
                 && !speculativeType.computeMask(compiler).willHit(
                        user.selector, compiler)) {
        return true;
      }
    }
    return false;
  }

  bool typeGuardWouldBeValuable(HInstruction instruction,
                                HType speculativeType) {
    // If the type itself is not valuable, do not generate a guard for it.
    if (!typeValuable(speculativeType)) return false;

    // Do not insert a type guard if the instruction has a type
    // annotation that disagrees with the speculated type.
    Element source = instruction.sourceElement;
    if (source != null) {
      DartType sourceType = source.computeType(compiler);
      if (!sourceType.isMalformed && !sourceType.isDynamic &&
          sourceType.kind == TypeKind.INTERFACE) {
        TypeMask sourceMask = new TypeMask.subtype(sourceType);
        TypeMask speculatedMask = speculativeType.computeMask(compiler);
        if (sourceMask.intersection(speculatedMask, compiler).isEmpty) {
          return false;
        }
      }
    }

    // Do not insert a type guard if one of the calls on it will hit
    // [NoSuchMethodError].
    if (isUsedWithIncompatibleSelector(instruction, speculativeType)) {
      return false;
    }

    // Insert type guards for recursive methods.
    if (isRecursiveMethod) return true;

    // Insert type guards if there are uses in loops.
    bool isNested(HBasicBlock inner, HBasicBlock outer) {
      if (identical(inner, outer)) return false;
      if (outer == null) return true;
      while (inner != null) {
        if (identical(inner, outer)) return true;
        inner = inner.parentLoopHeader;
      }
      return false;
    }

    // If the instruction is not in a loop then the header will be null.
    HBasicBlock currentLoopHeader = instruction.block.enclosingLoopHeader;
    for (HInstruction user in instruction.usedBy) {
      HBasicBlock userLoopHeader = user.block.enclosingLoopHeader;
      if (isNested(userLoopHeader, currentLoopHeader)) return true;
    }

    bool isIndexOperatorOnIndexablePrimitive(instruction) {
      return instruction is HIndex
          || (instruction is HInvokeDynamicMethod
              && instruction.isIndexOperatorOnIndexablePrimitive(compiler));
    }

    // To speed up computations on values loaded from arrays, we
    // insert type guards for builtin array indexing operations in
    // nested loops. Since this can blow up code size quite
    // significantly, we only do it if type guards have already been
    // inserted for this method. The code size price for an additional
    // type guard is much smaller than the first one that causes the
    // generation of a bailout method.
    if (hasTypeGuards
        && isIndexOperatorOnIndexablePrimitive(instruction)) {
      HBasicBlock loopHeader = instruction.block.enclosingLoopHeader;
      if (loopHeader != null && loopHeader.parentLoopHeader != null) {
        return true;
      }
    }

    // If the instruction is used by a phi where a guard would be
    // valuable, put the guard on that instruction.
    for (HInstruction user in instruction.usedBy) {
      if (user is HPhi
          && user.block.id > instruction.id
          && typeGuardWouldBeValuable(user, speculativeType)) {
        return true;
      }
    }

    // Insert type guards if the method is likely to be called in a
    // loop.
    return calledInLoop;
  }

  // Returns whether an invocation of [selector] on [receiver] will throw a
  // [ArgumentError] if the argument is not of the right type.
  bool willThrowArgumentError(Selector selector,
                              HInstruction receiver,
                              HType speculativeType) {
    if (receiver != null
        && (receiver.isInteger() || receiver.isString(compiler))) {
      return selector.isOperator()
          && selector.name != const SourceString('==')
          && (speculativeType.isNumber() && !speculativeType.isInteger());
    }
    return false;
  }

  // Returns whether an invocation of [selector] will throw a
  // [NoSuchMethodError] if the receiver is not of the type
  // [speculativeType].
  bool willThrowNoSuchMethodErrorIfNot(Selector selector,
                                       HType speculativeType) {
    return compiler.world.hasSingleMatch(selector)
        // In some cases, we want the receiver to be an integer,
        // but that does not mean we will get a NoSuchMethodError
        // if it's not: the receiver could be a double.
        && !speculativeType.isInteger()
        // We speculate on the [operator==] instruction, but we know it
        // will never throw a [NoSuchMethodError].
        && selector.name != const SourceString('==');
  }

  bool shouldInsertTypeGuard(HInstruction instruction, HType speculativeType) {
    if (!speculativeType.isUseful()) return false;
    // If the types agree we don't need to check.
    if (speculativeType == instruction.instructionType) return false;
    // If a bailout check is more expensive than doing the actual operation
    // don't do it either.
    return typeGuardWouldBeValuable(instruction, speculativeType);
  }

  HInstruction computeFirstDominatingUserWithSelector(
      HInstruction instruction) {
    // TODO(ngeoffray): We currently only look at the instruction's
    // block, so that we know it will be executed. We should lift this
    // limitation.

    // For a parameter, we look at the first block that contains
    // user instructions.
    HBasicBlock userMustBeInBlock = instruction is HParameterValue
        ? instruction.block.successors[0]
        : instruction.block;

    HInstruction firstUser;
    for (HInstruction user in instruction.usedBy) {
      if (user.block == userMustBeInBlock && user.selector != null) {
        if (firstUser == null || user.dominates(firstUser)) {
          firstUser = user;
        }
      }
    }
    return firstUser;
  }

  /**
   * Tries to insert a type conversion instruction for [instruction]
   * instead of a type guard if we know an user will throw. Returns
   * whether it succeeded at adding a type conversion instruction.
   */
  bool tryTypeConversion(HInstruction instruction, HType speculativeType) {
    HInstruction firstUser =
        computeFirstDominatingUserWithSelector(instruction);
    if (firstUser == null) return false;

    // If we have found a user with a selector, we find out if it
    // will throw [NoSuchMethodError] or [ArgumentError].
    Selector selector = firstUser.selector;
    Selector receiverSelectorOnThrow = null;
    HInstruction receiver = firstUser.getDartReceiver(compiler);
    bool willThrow = false;
    if (receiver == instruction) {
      if (willThrowNoSuchMethodErrorIfNot(selector, speculativeType)) {
        receiverSelectorOnThrow = selector;
        willThrow = true;
      }
    // We need to call the actual method in checked mode to get
    // the right type error.
    } else if (!compiler.enableTypeAssertions
               && willThrowArgumentError(selector, receiver, speculativeType)) {
      willThrow = true;
    }

    if (!willThrow) return false;

    HTypeConversion check = new HTypeConversion(
            null,
            receiverSelectorOnThrow == null
                ? HTypeConversion.ARGUMENT_TYPE_CHECK
                : HTypeConversion.RECEIVER_TYPE_CHECK,
            speculativeType,
            instruction,
            receiverSelectorOnThrow);
    hasInsertedChecks = true;
    firstUser.block.addBefore(firstUser, check);
    instruction.replaceAllUsersDominatedBy(firstUser, check);
    return true;
  }

  bool updateType(HInstruction instruction) {
    bool hasChanged = super.updateType(instruction);
    HType speculativeType = savedTypes[instruction];
    if (speculativeType == null) return hasChanged;

    if (shouldInsertTypeGuard(instruction, speculativeType)
        && !tryTypeConversion(instruction, speculativeType)) {
      HInstruction insertionPoint;
      if (instruction is HPhi) {
        insertionPoint = instruction.block.first;
      } else if (instruction is HParameterValue) {
        // We insert the type guard at the end of the entry block
        // because if a parameter is live, it must be kept in the live
        // environment. Not doing so would mean we could visit a
        // parameter and remove it from the environment before
        // visiting a type guard.
        insertionPoint = instruction.block.last;
      } else {
        insertionPoint = instruction.next;
      }
      // If the previous instruction is also a type guard, then both
      // guards have the same environment, and can therefore share the
      // same state id.
      HBailoutTarget target;
      int state;
      if (insertionPoint.previous is HTypeGuard) {
        HTypeGuard other = insertionPoint.previous;
        target = other.bailoutTarget;
      } else {
        state = stateId++;
        target = new HBailoutTarget(state);
        insertionPoint.block.addBefore(insertionPoint, target);
      }
      HTypeGuard guard = new HTypeGuard(speculativeType, instruction, target);
      work.guards.add(guard);
      // By setting the type of the guard to the speculated type, we
      // help the analysis find valuable type guards. This however
      // requires to run a non-speculative type propagation again
      // after this analysis.
      guard.instructionType = speculativeType;
      instruction.block.rewrite(instruction, guard);
      insertionPoint.block.addBefore(insertionPoint, guard);
    }
    return hasChanged;
  }
}

/**
 * Computes the environment for each SSA instruction: visits the graph
 * in post-dominator order. Removes an instruction from the environment
 * and adds its inputs to the environment at the instruction's
 * definition.
 *
 * At the end of the computation, insert type guards in the graph.
 */
class SsaEnvironmentBuilder extends HBaseVisitor implements OptimizationPhase {
  final Compiler compiler;
  final String name = 'SsaEnvironmentBuilder';

  final Map<HBailoutTarget, Environment> capturedEnvironments;
  final Map<HBasicBlock, Environment> liveInstructions;
  Environment environment;
  /**
   * The set of current loop headers that dominate the current block.
   */
  Set<HBasicBlock> loopMarkers;

  SsaEnvironmentBuilder(Compiler this.compiler)
    : capturedEnvironments = new Map<HBailoutTarget, Environment>(),
      liveInstructions = new Map<HBasicBlock, Environment>(),
      loopMarkers = new Set<HBasicBlock>();


  void visitGraph(HGraph graph) {
    visitPostDominatorTree(graph);
    if (!liveInstructions[graph.entry].isEmpty) {
      compiler.internalError('Bailout environment computation',
          node: compiler.currentElement.parseNode(compiler));
    }
    updateLoopMarkers();
    insertCapturedEnvironments();
  }

  void updateLoopMarkers() {
    // If the block is a loop header, we need to merge the loop
    // header's live instructions into every environment that contains
    // the loop marker.
    // For example with the following loop (read the example in
    // reverse):
    //
    // while (true) { <-- (4) update the marker with the environment
    //   use(x);      <-- (3) environment = {x}
    //   bailout;     <-- (2) has the marker when computed
    // }              <-- (1) create a loop marker
    //
    // The bailout instruction first captures the marker, but it
    // will be replaced by the live environment at the loop entry,
    // in this case {x}.
    capturedEnvironments.forEach((ignoredInstruction, env) {
      env.loopMarkers.forEach((HBasicBlock header) {
        env.addAll(liveInstructions[header]);
      });
      env.loopMarkers.clear();
    });
  }

  void visitBasicBlock(HBasicBlock block) {
    environment = new Environment();

    // Add to the environment the live instructions of its successor, as well as
    // the inputs of the phis of the successor that flow from this block.
    for (int i = 0; i < block.successors.length; i++) {
      HBasicBlock successor = block.successors[i];
      Environment successorEnv = liveInstructions[successor];
      if (successorEnv != null) {
        environment.addAll(successorEnv);
      } else {
        // If we haven't computed the liveInstructions of that successor, we
        // know it must be a loop header.
        assert(successor.isLoopHeader());
        assert(!block.isLoopHeader());
        loopMarkers.add(successor);
      }

      int index = successor.predecessors.indexOf(block);
      for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) {
        environment.add(phi.inputs[index]);
      }
    }

    if (block.isLoopHeader()) {
      loopMarkers.remove(block);
    }

    // If the block is a loop header, we're adding all [loopMarkers]
    // after removing it from the list of [loopMarkers], because
    // it will just recompute the loop phis.
    environment.loopMarkers.addAll(loopMarkers);

    // Iterate over all instructions to remove an instruction from the
    // environment and add its inputs.
    HInstruction instruction = block.last;
    while (instruction != null) {
      instruction.accept(this);
      instruction = instruction.previous;
    }

    // We just remove the phis from the environment. The inputs of the
    // phis will be put in the environment of the predecessors.
    for (HPhi phi = block.phis.first; phi != null; phi = phi.next) {
      environment.remove(phi);
    }

    // Finally save the liveInstructions of that block.
    liveInstructions[block] = environment;
  }

  void visitBailoutTarget(HBailoutTarget target) {
    visitInstruction(target);
    capturedEnvironments[target] = new Environment.from(environment);
  }

  void visitInstruction(HInstruction instruction) {
    environment.remove(instruction);
    for (int i = 0, len = instruction.inputs.length; i < len; i++) {
      environment.add(instruction.inputs[i]);
    }
  }

  /**
   * Stores all live variables in the bailout target and the guards.
   */
  void insertCapturedEnvironments() {
    capturedEnvironments.forEach((HBailoutTarget target, Environment env) {
      assert(target.inputs.length == 0);
      target.inputs.addAll(env.lives);
      // TODO(floitsch): we should add the bailout-target's input variables
      // as input to the guards only in the optimized version. The
      // non-optimized version does not use the bailout guards and it is
      // unnecessary to keep the variables alive until the check.
      for (HTypeGuard guard in target.usedBy) {
        // A type-guard initially only has two inputs: the guarded instruction
        // and the bailout-target. Only after adding the environment is it
        // allowed to have more inputs.
        assert(guard.inputs.length == 2);
        guard.inputs.addAll(env.lives);
      }
      for (HInstruction live in env.lives) {
        live.usedBy.add(target);
        live.usedBy.addAll(target.usedBy);
      }
    });
  }
}

/**
 * Propagates bailout information to blocks that need it. This visitor
 * is run before codegen, to know which blocks have to deal with
 * bailouts.
 */
class SsaBailoutPropagator extends HBaseVisitor {
  final Compiler compiler;
  /**
   * A list to propagate bailout information to blocks that start a
   * guarded or labeled list of statements. Currently, these blocks
   * are:
   *    - first block of a then branch,
   *    - first block of an else branch,
   *    - a loop header,
   *    - labeled block.
   */
  final List<HBasicBlock> blocks;

  /**
   * The current subgraph we are visiting.
   */
  SubGraph subGraph;

  /**
   * The current block information we are visiting.
   */
  HBlockInformation currentBlockInformation;

  /**
   * Max number of arguments to the bailout (not counting the state).
   */
  int bailoutArity;
  /**
   * A map from variables to their names.  These are the names in the
   * unoptimized (bailout) version of the function.  Their names could be
   * different in the optimized version.
   */
  VariableNames variableNames;
  /**
   * Maps from the variable names to their positions in the argument list of the
   * bailout instruction.  Because of the way the variable allocator works,
   * several variables can end up with the same name (if their live ranges do
   * not overlap), therefore they can have the same position in the bailout
   * argument list
   */
  Map<String, int> parameterNames;

  /**
   * If set to true, the graph has either multiple bailouts in
   * different places, or a bailout inside an if or a loop. For such a
   * graph, the code generator will emit a generic switch.
   */
  bool hasComplexBailoutTargets = false;

  /**
   * The first type guard in the graph.
   */
  HBailoutTarget firstBailoutTarget;

  /**
   * If set, it is the first block in the graph where we generate
   * code. Blocks before this one are dead code in the bailout
   * version.
   */

  SsaBailoutPropagator(this.compiler, this.variableNames)
      : blocks = <HBasicBlock>[],
        bailoutArity = 0,
        parameterNames = new Map<String, int>();

  void visitGraph(HGraph graph) {
    subGraph = new SubGraph(graph.entry, graph.exit);
    visitBasicBlock(graph.entry);
    if (!blocks.isEmpty) {
      compiler.internalError('Bailout propagation',
          node: compiler.currentElement.parseNode(compiler));
    }
  }

  /**
   * Returns true if we can visit the given [blockFlow]. False
   * otherwise. Currently, try/catch and switch are not in bailout
   * methods, so this method only deals with loops and labeled blocks.
   * If [blockFlow] is a labeled block or a loop, we also visit the
   * continuation of the block flow.
   */
  bool handleBlockFlow(HBlockFlow blockFlow) {
    HBlockInformation body = blockFlow.body;

    // We reach here again when starting to visit a subgraph. Just
    // return to visiting the block.
    if (currentBlockInformation == body) return false;

    HBlockInformation oldInformation = currentBlockInformation;
    if (body is HLabeledBlockInformation) {
      currentBlockInformation = body;
      HLabeledBlockInformation info = body;
      visitStatements(info.body, newFlow: true);
    } else if (body is HLoopBlockInformation) {
      currentBlockInformation = body;
      HLoopBlockInformation info = body;
      if (info.initializer != null) {
        visitExpression(info.initializer);
      }
      blocks.add(info.loopHeader);
      if (!info.isDoWhile()) {
        visitExpression(info.condition);
      }
      visitStatements(info.body, newFlow: false);
      if (info.isDoWhile()) {
        visitExpression(info.condition);
      }
      if (info.updates != null) {
        visitExpression(info.updates);
      }
      blocks.removeLast();
    } else {
      assert(body is! HTryBlockInformation);
      assert(body is! HSwitchBlockInformation);
      // [HIfBlockInformation] is handled by visitIf.
      return false;
    }

    currentBlockInformation = oldInformation;
    if (blockFlow.continuation != null) {
      visitBasicBlock(blockFlow.continuation);
    }
    return true;
  }

  void visitBasicBlock(HBasicBlock block) {
    // Abort traversal if we are leaving the currently active sub-graph.
    if (!subGraph.contains(block)) return;

    HBlockFlow blockFlow = block.blockFlow;
    if (blockFlow != null && handleBlockFlow(blockFlow)) return;

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

  void visitExpression(HSubExpressionBlockInformation info) {
    visitSubGraph(info.subExpression);
  }

  /**
   * Visit the statements in [info]. If [newFlow] is true, we add the
   * first block of [statements] to the list of [blocks].
   */
  void visitStatements(HSubGraphBlockInformation info, {bool newFlow}) {
    SubGraph graph = info.subGraph;
    if (newFlow) blocks.add(graph.start);
    visitSubGraph(graph);
    if (newFlow) blocks.removeLast();
  }

  void visitSubGraph(SubGraph graph) {
    SubGraph oldSubGraph = subGraph;
    subGraph = graph;
    visitBasicBlock(graph.start);
    subGraph = oldSubGraph;
  }

  void visitIf(HIf instruction) {
    int preVisitedBlocks = 0;
    HIfBlockInformation info = instruction.blockInformation.body;
    visitStatements(info.thenGraph, newFlow: true);
    preVisitedBlocks++;
    visitStatements(info.elseGraph, newFlow: true);
    preVisitedBlocks++;

    HBasicBlock joinBlock = instruction.joinBlock;
    if (joinBlock != null
        && !identical(joinBlock.dominator, instruction.block)) {
      // The join block is dominated by a block in one of the branches.
      // The subgraph traversal never reached it, so we visit it here
      // instead.
      visitBasicBlock(joinBlock);
    }

    // Visit all the dominated blocks that are not part of the then or else
    // branches, and is not the join block.
    // Depending on how the then/else branches terminate
    // (e.g., return/throw/break) there can be any number of these.
    List<HBasicBlock> dominated = instruction.block.dominatedBlocks;
    int dominatedCount = dominated.length;
    for (int i = preVisitedBlocks; i < dominatedCount; i++) {
      HBasicBlock dominatedBlock = dominated[i];
      visitBasicBlock(dominatedBlock);
    }
  }

  void visitGoto(HGoto goto) {
    HBasicBlock block = goto.block;
    HBasicBlock successor = block.successors[0];
    if (identical(successor.dominator, block)) {
      visitBasicBlock(block.successors[0]);
    }
  }

  void visitLoopBranch(HLoopBranch branch) {
    // For a do-while loop, the body has already been visited.
    if (!branch.isDoWhile()) {
      visitBasicBlock(branch.block.dominatedBlocks[0]);
    }
  }

  visitBailoutTarget(HBailoutTarget target) {
    int inputLength = target.inputs.length;
    for (HInstruction input in target.inputs) {
      String inputName = variableNames.getName(input);
      int position = parameterNames[inputName];
      if (position == null) {
        position = parameterNames[inputName] = bailoutArity++;
      }
    }

    if (blocks.isEmpty) {
      // If [currentBlockInformation] is not null, we are in the
      // middle of a loop/labeled block and this is too complex to handle for
      // now.
      if (firstBailoutTarget == null && currentBlockInformation == null) {
        firstBailoutTarget = target;
      } else {
        hasComplexBailoutTargets = true;
      }
    } else {
      hasComplexBailoutTargets = true;
      blocks.forEach((HBasicBlock block) {
        block.bailoutTargets.add(target);
      });
    }
  }
}
