// Copyright (c) 2019, the R8 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.

package com.android.tools.r8.ir.conversion;

import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.isClassNameValue;

import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.Goto;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.IntSwitch;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.StringSwitch;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.naming.IdentifierNameStringMarker;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceRBTreeMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.io.UTFDataFormatException;
import java.util.LinkedHashMap;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class StringSwitchRemover {

  private final AppView<?> appView;
  private final IdentifierNameStringMarker identifierNameStringMarker;
  private final ClassTypeElement stringType;

  StringSwitchRemover(AppView<?> appView, IdentifierNameStringMarker identifierNameStringMarker) {
    this.appView = appView;
    this.identifierNameStringMarker = identifierNameStringMarker;
    this.stringType = TypeElement.stringClassType(appView, definitelyNotNull());
  }

  public void run(IRCode code) {
    if (!code.metadata().mayHaveStringSwitch()) {
      assert Streams.stream(code.instructions()).noneMatch(Instruction::isStringSwitch);
      return;
    }

    if (!prepareForStringSwitchRemoval(code)) {
      return;
    }

    Set<BasicBlock> newBlocksWithStrings = Sets.newIdentityHashSet();

    ListIterator<BasicBlock> blockIterator = code.listIterator();
    while (blockIterator.hasNext()) {
      BasicBlock block = blockIterator.next();
      StringSwitch theSwitch = block.exit().asStringSwitch();
      if (theSwitch != null) {
        try {
          SingleStringSwitchRemover remover;
          if (theSwitch.numberOfKeys() < appView.options().minimumStringSwitchSize
              || hashCodeOfKeysMayChangeAfterMinification(theSwitch)) {
            remover =
                new SingleEqualityBasedStringSwitchRemover(
                    code, blockIterator, block, theSwitch, newBlocksWithStrings);
          } else {
            remover =
                new SingleHashBasedStringSwitchRemover(
                    code, blockIterator, block, theSwitch, newBlocksWithStrings);
          }
          remover.removeStringSwitch();
        } catch (UTFDataFormatException e) {
          // The keys of a string-switch should never fail to decode.
          throw new Unreachable();
        }
      }
    }

    if (identifierNameStringMarker != null) {
      identifierNameStringMarker.decoupleIdentifierNameStringsInBlocks(code, newBlocksWithStrings);
    }

    assert code.isConsistentSSA(appView);
  }

  // Returns true if minification is enabled and the switch value is guaranteed to be a class name.
  // In this case, we can't use the hash codes of the keys before minification, because they will
  // (potentially) change as a result of minification. Therefore, we currently emit a sequence of
  // if-equals checks for such switches.
  //
  // TODO(b/154483187): This should also use the hash-based string switch elimination.
  private boolean hashCodeOfKeysMayChangeAfterMinification(StringSwitch theSwitch) {
    return appView.options().isMinifying()
        && isClassNameValue(theSwitch.value(), appView.dexItemFactory());
  }

  private boolean prepareForStringSwitchRemoval(IRCode code) {
    boolean hasStringSwitch = false;
    ListIterator<BasicBlock> blockIterator = code.listIterator();
    while (blockIterator.hasNext()) {
      BasicBlock block = blockIterator.next();
      for (BasicBlock predecessor : block.getNormalPredecessors()) {
        StringSwitch exit = predecessor.exit().asStringSwitch();
        if (exit != null) {
          hasStringSwitch = true;
          if (block == exit.fallthroughBlock()) {
            // After the elimination of this string-switch instruction, there will be two
            // fallthrough blocks: one for the instruction that switches on the hash value and one
            // for the instruction that switches on the string id value.
            //
            // The existing fallthrough block will be the fallthrough block for the switch on the
            // hash value. Note that we can't use this block for the switch on the id value since
            // that would lead to critical edges.
            BasicBlock hashSwitchFallthroughBlock = block;

            // The `hashSwitchFallthroughBlock` will jump to the switch on the string id value.
            // This block will have multiple predecessors, hence the need for the split-edge
            // block.
            BasicBlock idSwitchBlock =
                hashSwitchFallthroughBlock.listIterator(code).split(code, blockIterator);

            // Split again such that `idSwitchBlock` becomes a block consisting of a single goto
            // instruction that targets a block that is identical to the original fallthrough
            // block of the string-switch instruction.
            BasicBlock idSwitchFallthroughBlock =
                idSwitchBlock.listIterator(code).split(code, blockIterator);
            break;
          }
        }
      }
    }

    return hasStringSwitch;
  }

  private abstract static class SingleStringSwitchRemover {

    final IRCode code;
    final ListIterator<BasicBlock> blockIterator;
    final Set<BasicBlock> newBlocksWithStrings;

    final Position position;
    final Value stringValue;

    private SingleStringSwitchRemover(
        IRCode code,
        ListIterator<BasicBlock> blockIterator,
        StringSwitch theSwitch,
        Set<BasicBlock> newBlocksWithStrings) {
      this.code = code;
      this.blockIterator = blockIterator;
      this.newBlocksWithStrings = newBlocksWithStrings;
      this.position = theSwitch.getPosition();
      this.stringValue = theSwitch.value();
    }

    abstract void removeStringSwitch();
  }

  private class SingleEqualityBasedStringSwitchRemover extends SingleStringSwitchRemover {

    private final BasicBlock block;
    private final BasicBlock fallthroughBlock;

    private final Map<DexString, BasicBlock> structure;

    private SingleEqualityBasedStringSwitchRemover(
        IRCode code,
        ListIterator<BasicBlock> blockIterator,
        BasicBlock block,
        StringSwitch theSwitch,
        Set<BasicBlock> newBlocksWithStrings) {
      super(code, blockIterator, theSwitch, newBlocksWithStrings);
      this.block = block;
      this.fallthroughBlock = theSwitch.fallthroughBlock();
      this.structure = createStructure(theSwitch);
    }

    private Map<DexString, BasicBlock> createStructure(StringSwitch theSwitch) {
      Map<DexString, BasicBlock> result = new LinkedHashMap<>();
      theSwitch.forEachCase(result::put);
      return result;
    }

    @Override
    void removeStringSwitch() {
      // Remove outgoing control flow edges from the block containing the string switch.
      for (BasicBlock successor : block.getNormalSuccessors()) {
        successor.removePredecessor(block, null);
      }
      block.removeAllNormalSuccessors();
      Set<BasicBlock> blocksTargetedByMultipleSwitchCases = Sets.newIdentityHashSet();
      {
        Set<BasicBlock> seenBefore = SetUtils.newIdentityHashSet(structure.size());
        for (BasicBlock targetBlock : structure.values()) {
          if (!seenBefore.add(targetBlock)) {
            blocksTargetedByMultipleSwitchCases.add(targetBlock);
          }
        }
      }
      // Create a String.equals() check for each case in the string-switch instruction.
      BasicBlock previous = null;
      for (Entry<DexString, BasicBlock> entry : structure.entrySet()) {
        ConstString constStringInstruction =
            new ConstString(code.createValue(stringType), entry.getKey());
        constStringInstruction.setPosition(position);
        InvokeVirtual invokeInstruction =
            new InvokeVirtual(
                appView.dexItemFactory().stringMembers.equals,
                code.createValue(PrimitiveTypeElement.getInt()),
                ImmutableList.of(stringValue, constStringInstruction.outValue()));
        invokeInstruction.setPosition(position);
        If ifInstruction = new If(If.Type.NE, invokeInstruction.outValue());
        ifInstruction.setPosition(Position.none());
        BasicBlock targetBlock = entry.getValue();
        if (blocksTargetedByMultipleSwitchCases.contains(targetBlock)) {
          // Need an intermediate block to avoid critical edges.
          BasicBlock intermediateBlock =
              BasicBlock.createGotoBlock(
                  code.getNextBlockNumber(), Position.none(), code.metadata());
          intermediateBlock.link(targetBlock);
          blockIterator.add(intermediateBlock);
          newBlocksWithStrings.add(intermediateBlock);
          targetBlock = intermediateBlock;
        }
        BasicBlock newBlock =
            BasicBlock.createIfBlock(
                code.getNextBlockNumber(),
                ifInstruction,
                code.metadata(),
                constStringInstruction,
                invokeInstruction);
        newBlock.link(targetBlock);
        blockIterator.add(newBlock);
        newBlocksWithStrings.add(newBlock);
        if (previous == null) {
          // Replace the string-switch instruction by a goto instruction.
          block.exit().replace(new Goto(newBlock), code);
          block.link(newBlock);
        } else {
          // Set the fallthrough block for the previously added if-instruction.
          previous.link(newBlock);
        }
        previous = newBlock;
      }
      assert previous != null;
      // Set the fallthrough block for the last if-instruction.
      previous.link(fallthroughBlock);
    }
  }

  private class SingleHashBasedStringSwitchRemover extends SingleStringSwitchRemover {

    private final BasicBlock hashSwitchBlock;
    private final BasicBlock hashSwitchFallthroughBlock;
    private final BasicBlock idSwitchBlock;
    private final BasicBlock idSwitchFallthroughBlock;

    Int2ReferenceMap<Map<DexString, BasicBlock>> structure;

    private int nextStringId;

    private SingleHashBasedStringSwitchRemover(
        IRCode code,
        ListIterator<BasicBlock> blockIterator,
        BasicBlock hashSwitchBlock,
        StringSwitch theSwitch,
        Set<BasicBlock> newBlocksWithStrings)
        throws UTFDataFormatException {
      super(code, blockIterator, theSwitch, newBlocksWithStrings);
      this.hashSwitchBlock = hashSwitchBlock;
      this.hashSwitchFallthroughBlock = theSwitch.fallthroughBlock();
      this.idSwitchBlock = theSwitch.fallthroughBlock().getUniqueNormalSuccessor();
      this.idSwitchFallthroughBlock = idSwitchBlock.getUniqueNormalSuccessor();
      this.structure = createStructure(theSwitch);
    }

    private int getAndIncrementNextBlockNumber() {
      return code.getNextBlockNumber();
    }

    private Int2ReferenceMap<Map<DexString, BasicBlock>> createStructure(StringSwitch theSwitch)
        throws UTFDataFormatException {
      Int2ReferenceMap<Map<DexString, BasicBlock>> result = new Int2ReferenceRBTreeMap<>();
      theSwitch.forEachCase(
          (key, target) -> {
            int hashCode = key.decodedHashCode();
            if (result.containsKey(hashCode)) {
              result.get(hashCode).put(key, target);
            } else {
              Map<DexString, BasicBlock> cases = new LinkedHashMap<>();
              cases.put(key, target);
              result.put(hashCode, cases);
            }
          });
      return result;
    }

    @Override
    void removeStringSwitch() {
      // Remove outgoing control flow edges from the block containing the string switch.
      for (BasicBlock successor : hashSwitchBlock.getNormalSuccessors()) {
        successor.removePredecessor(hashSwitchBlock, null);
      }
      hashSwitchBlock.removeAllNormalSuccessors();

      // 1. Insert `int id = -1`.
      InstructionListIterator instructionIterator =
          hashSwitchBlock.listIterator(code, hashSwitchBlock.size());
      instructionIterator.previous();

      Phi idPhi = code.createPhi(idSwitchBlock, TypeElement.getInt());
      Value notFoundIdValue =
          instructionIterator.insertConstIntInstruction(code, appView.options(), -1);
      idPhi.appendOperand(notFoundIdValue);

      // 2. Insert `int hashCode = stringValue.hashCode()`.
      InvokeVirtual hashInvoke =
          new InvokeVirtual(
              appView.dexItemFactory().stringMembers.hashCode,
              code.createValue(TypeElement.getInt()),
              ImmutableList.of(stringValue));
      hashInvoke.setPosition(position);
      instructionIterator.add(hashInvoke);

      // 3. Create all the target blocks of the hash switch.
      //
      // Say that the string switch instruction contains the keys "X" and "Y" and assume that "X"
      // and "Y" have the same hash code. Then this will create code that looks like:
      //
      //   Block N:
      //     boolean equalsX = stringValue.equals("X")
      //     if equalsX then goto block N+1 else goto block N+2
      //   Block N+1:
      //     id = 0
      //     goto <id-switch-block>
      //   Block N+2:
      //     boolean equalsY = stringValue.equals("Y")
      //     if equalsY then goto block N+3 else goto block N+4
      //   Block N+3:
      //     id = 1
      //     goto <id-switch-block>
      //   Block N+4:
      //     goto <id-switch-block>
      createHashSwitchTargets(idPhi, notFoundIdValue);
      hashSwitchBlock.link(hashSwitchFallthroughBlock);

      // 4. Insert `switch (hashValue)`.
      IntSwitch hashSwitch = createHashSwitch(hashInvoke.outValue());
      instructionIterator.next();
      instructionIterator.replaceCurrentInstruction(hashSwitch);

      // 5. Link `idSwitchBlock` with all of its target blocks.
      Reference2IntMap<BasicBlock> targetBlockIndices = new Reference2IntOpenHashMap<>();
      targetBlockIndices.defaultReturnValue(-1);
      idSwitchBlock.getMutableSuccessors().clear();
      for (Map<DexString, BasicBlock> cases : structure.values()) {
        for (BasicBlock target : cases.values()) {
          int targetIndex = targetBlockIndices.getInt(target);
          if (targetIndex == -1) {
            targetBlockIndices.put(target, idSwitchBlock.getSuccessors().size());
            idSwitchBlock.link(target);
          }
        }
      }
      idSwitchBlock.getMutableSuccessors().add(idSwitchFallthroughBlock);

      // 6. Insert `switch (idValue)`.
      IntSwitch idSwitch = createIdSwitch(idPhi, targetBlockIndices);
      InstructionListIterator idSwitchBlockInstructionIterator = idSwitchBlock.listIterator(code);
      idSwitchBlockInstructionIterator.next();
      idSwitchBlockInstructionIterator.replaceCurrentInstruction(idSwitch);
    }

    private IntSwitch createHashSwitch(Value hashValue) {
      int[] hashSwitchKeys = structure.keySet().toArray(new int[0]);
      int[] hashSwitchTargetIndices = new int[hashSwitchKeys.length];
      for (int i = 0, offset = hashSwitchBlock.numberOfExceptionalSuccessors();
          i < hashSwitchTargetIndices.length;
          i++) {
        hashSwitchTargetIndices[i] = i + offset;
      }
      int hashSwitchFallthroughIndex = hashSwitchBlock.getSuccessors().size() - 1;
      return new IntSwitch(
          hashValue, hashSwitchKeys, hashSwitchTargetIndices, hashSwitchFallthroughIndex);
    }

    private void createHashSwitchTargets(Phi idPhi, Value notFoundIdValue) {
      for (Map<DexString, BasicBlock> cases : structure.values()) {
        // Create the target block for the hash switch.
        BasicBlock hashBlock =
            BasicBlock.createGotoBlock(getAndIncrementNextBlockNumber(), position, code.metadata());
        blockIterator.add(hashBlock);
        hashSwitchBlock.link(hashBlock);

        // Position the block iterator at the newly created block.
        BasicBlock previous = blockIterator.previous();
        assert previous == hashBlock;
        blockIterator.next();

        BasicBlock current = hashBlock;
        for (Entry<DexString, BasicBlock> entry : cases.entrySet()) {
          current.getMutableSuccessors().clear();

          // Insert `String key = <entry.getKey()>`.
          InstructionListIterator instructionIterator = current.listIterator(code);
          Value keyValue =
              instructionIterator.insertConstStringInstruction(appView, code, entry.getKey());
          newBlocksWithStrings.add(current);

          // Insert `boolean equalsKey = stringValue.equals(key)`.
          InvokeVirtual equalsInvoke =
              new InvokeVirtual(
                  appView.dexItemFactory().stringMembers.equals,
                  code.createValue(TypeElement.getInt()),
                  ImmutableList.of(stringValue, keyValue));
          equalsInvoke.setPosition(position);
          instructionIterator.add(equalsInvoke);

          // Create a new block for the success case.
          BasicBlock equalsKeyBlock =
              BasicBlock.createGotoBlock(
                  getAndIncrementNextBlockNumber(), position, code.metadata(), idSwitchBlock);
          idSwitchBlock.getMutablePredecessors().add(equalsKeyBlock);
          blockIterator.add(equalsKeyBlock);
          current.link(equalsKeyBlock);

          // Insert `int id = <nextStringId++>`.
          Value idValue =
              equalsKeyBlock
                  .listIterator(code)
                  .insertConstIntInstruction(code, appView.options(), nextStringId++);
          idPhi.appendOperand(idValue);

          // Create a new block for the failure case.
          BasicBlock continuationBlock =
              BasicBlock.createGotoBlock(
                  getAndIncrementNextBlockNumber(), position, code.metadata(), idSwitchBlock);
          blockIterator.add(continuationBlock);
          current.link(continuationBlock);

          // Insert `if (equalsKey) goto <id-switch-block> else goto <continuation-block>`.
          instructionIterator.next();
          instructionIterator.replaceCurrentInstruction(new If(Type.NE, equalsInvoke.outValue()));

          current = continuationBlock;
        }
        idPhi.appendOperand(notFoundIdValue);
        idSwitchBlock.getMutablePredecessors().add(current);
      }
    }

    private IntSwitch createIdSwitch(Phi idPhi, Reference2IntMap<BasicBlock> targetBlockIndices) {
      int numberOfCases = nextStringId;
      int[] keys = ArrayUtils.createIdentityArray(numberOfCases);
      int[] targetIndices = new int[numberOfCases];
      int i = 0;
      for (Map<DexString, BasicBlock> cases : structure.values()) {
        for (Entry<DexString, BasicBlock> entry : cases.entrySet()) {
          targetIndices[i++] = targetBlockIndices.getInt(entry.getValue());
        }
      }
      int fallthroughIndex = targetBlockIndices.size();
      return new IntSwitch(idPhi, keys, targetIndices, fallthroughIndex);
    }
  }
}
