// 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.graph.DexProgramClass.asProgramClassOrNull;

import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.GraphLense.GraphLenseLookupResult;
import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.ir.conversion.CallGraph.Node;
import com.android.tools.r8.ir.conversion.CallGraphBuilderBase.CycleEliminator.CycleEliminationResult;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
import java.util.function.Predicate;

abstract class CallGraphBuilderBase {

  final AppView<AppInfoWithLiveness> appView;
  private final FieldAccessInfoCollection<?> fieldAccessInfoCollection;
  final Map<DexMethod, Node> nodes = new IdentityHashMap<>();
  private final Map<DexMethod, Set<DexEncodedMethod>> possibleTargetsCache =
      new ConcurrentHashMap<>();

  CallGraphBuilderBase(AppView<AppInfoWithLiveness> appView) {
    this.appView = appView;
    this.fieldAccessInfoCollection = appView.appInfo().getFieldAccessInfoCollection();
  }

  public CallGraph build(ExecutorService executorService, Timing timing) throws ExecutionException {
    timing.begin("Build IR processing order constraints");
    timing.begin("Build call graph");
    populateGraph(executorService);
    assert verifyNoRedundantFieldReadEdges();
    timing.end();
    assert verifyAllMethodsWithCodeExists();

    appView.withGeneratedMessageLiteBuilderShrinker(
        shrinker -> shrinker.preprocessCallGraphBeforeCycleElimination(nodes));

    timing.begin("Cycle elimination");
    // Sort the nodes for deterministic cycle elimination.
    Set<Node> nodesWithDeterministicOrder = Sets.newTreeSet(nodes.values());
    CycleEliminator cycleEliminator = new CycleEliminator();
    CycleEliminationResult cycleEliminationResult =
        cycleEliminator.breakCycles(nodesWithDeterministicOrder);
    timing.end();
    timing.end();
    assert cycleEliminator.breakCycles(nodesWithDeterministicOrder).numberOfRemovedCallEdges()
        == 0; // The cycles should be gone.

    return new CallGraph(nodesWithDeterministicOrder, cycleEliminationResult);
  }

  abstract void populateGraph(ExecutorService executorService) throws ExecutionException;

  /** Verify that there are no field read edges in the graph if there is also a call graph edge. */
  private boolean verifyNoRedundantFieldReadEdges() {
    for (Node writer : nodes.values()) {
      for (Node reader : writer.getReadersWithDeterministicOrder()) {
        assert !writer.hasCaller(reader);
      }
    }
    return true;
  }

  Node getOrCreateNode(DexEncodedMethod method) {
    synchronized (nodes) {
      return nodes.computeIfAbsent(method.method, ignore -> new Node(method));
    }
  }

  abstract boolean verifyAllMethodsWithCodeExists();

  class InvokeExtractor extends UseRegistry {

    private final Node currentMethod;
    private final Predicate<DexEncodedMethod> targetTester;

    InvokeExtractor(Node currentMethod, Predicate<DexEncodedMethod> targetTester) {
      super(appView.dexItemFactory());
      this.currentMethod = currentMethod;
      this.targetTester = targetTester;
    }

    private void addClassInitializerTarget(DexProgramClass clazz) {
      assert clazz != null;
      if (clazz.hasClassInitializer()) {
        addCallEdge(clazz.getClassInitializer(), false);
      }
    }

    private void addClassInitializerTarget(DexType type) {
      assert type.isClassType();
      DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(type));
      if (clazz != null) {
        addClassInitializerTarget(clazz);
      }
    }

    private void addCallEdge(DexEncodedMethod callee, boolean likelySpuriousCallEdge) {
      if (!targetTester.test(callee)) {
        return;
      }
      if (callee.accessFlags.isAbstract()) {
        // Not a valid target.
        return;
      }
      if (appView.appInfo().isPinned(callee.method)) {
        // Since the callee is kept, we cannot inline it into the caller, and we also cannot collect
        // any optimization info for the method. Therefore, we drop the call edge to reduce the
        // total number of call graph edges, which should lead to fewer call graph cycles.
        return;
      }
      assert callee.isProgramMethod(appView);
      getOrCreateNode(callee).addCallerConcurrently(currentMethod, likelySpuriousCallEdge);
    }

    private void addFieldReadEdge(DexEncodedMethod writer) {
      assert !writer.accessFlags.isAbstract();
      if (!targetTester.test(writer)) {
        return;
      }
      assert writer.isProgramMethod(appView);
      getOrCreateNode(writer).addReaderConcurrently(currentMethod);
    }

    private void processInvoke(Invoke.Type originalType, DexMethod originalMethod) {
      DexEncodedMethod source = currentMethod.method;
      DexMethod context = source.method;
      GraphLenseLookupResult result =
          appView.graphLense().lookupMethod(originalMethod, context, originalType);
      DexMethod method = result.getMethod();
      Invoke.Type type = result.getType();
      if (type == Invoke.Type.INTERFACE || type == Invoke.Type.VIRTUAL) {
        // For virtual and interface calls add all potential targets that could be called.
        ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
        DexEncodedMethod target = resolutionResult.getSingleTarget();
        if (target != null) {
          processInvokeWithDynamicDispatch(type, target, context.holder);
        }
      } else {
        DexEncodedMethod singleTarget =
            appView.appInfo().lookupSingleTarget(type, method, context.holder, appView);
        if (singleTarget != null) {
          assert !source.accessFlags.isBridge() || singleTarget != currentMethod.method;
          DexProgramClass clazz =
              asProgramClassOrNull(appView.definitionFor(singleTarget.method.holder));
          if (clazz != null) {
            // For static invokes, the class could be initialized.
            if (type == Invoke.Type.STATIC) {
              addClassInitializerTarget(clazz);
            }
            addCallEdge(singleTarget, false);
          }
        }
      }
    }

    private void processInvokeWithDynamicDispatch(
        Invoke.Type type, DexEncodedMethod encodedTarget, DexType context) {
      DexMethod target = encodedTarget.method;
      DexClass clazz = appView.definitionFor(target.holder);
      if (clazz == null) {
        assert false : "Unable to lookup holder of `" + target.toSourceString() + "`";
        return;
      }

      if (!appView.options().testing.addCallEdgesForLibraryInvokes) {
        if (clazz.isLibraryClass()) {
          // Likely to have many possible targets.
          return;
        }
      }

      boolean isInterface = type == Invoke.Type.INTERFACE;
      Set<DexEncodedMethod> possibleTargets =
          possibleTargetsCache.computeIfAbsent(
              target,
              method -> {
                ResolutionResult resolution =
                    appView.appInfo().resolveMethod(method.holder, method, isInterface);
                if (resolution.isVirtualTarget()) {
                  LookupResult lookupResult =
                      resolution.lookupVirtualDispatchTargets(
                          appView.definitionForProgramType(context), appView.appInfo());
                  if (lookupResult.isLookupResultSuccess()) {
                    // TODO(b/150277553): Add lambda methods to the call graph.
                    Set<DexEncodedMethod> targets = new HashSet<>();
                    lookupResult
                        .asLookupResultSuccess()
                        .forEach(
                            methodTarget -> targets.add(methodTarget.getMethod()),
                            lambdaTarget -> {
                              assert false;
                            });
                    return targets;
                  }
                }
                return null;
              });
      if (possibleTargets != null) {
        boolean likelySpuriousCallEdge =
            possibleTargets.size() >= appView.options().callGraphLikelySpuriousCallEdgeThreshold;
        for (DexEncodedMethod possibleTarget : possibleTargets) {
          if (possibleTarget.isProgramMethod(appView)) {
            addCallEdge(possibleTarget, likelySpuriousCallEdge);
          }
        }
      }
    }

    private void processFieldRead(DexField field) {
      if (!field.holder.isClassType()) {
        return;
      }

      DexEncodedField encodedField = appView.appInfo().resolveField(field);
      if (encodedField == null || appView.appInfo().isPinned(encodedField.field)) {
        return;
      }

      DexProgramClass clazz =
          asProgramClassOrNull(appView.definitionFor(encodedField.field.holder));
      if (clazz == null) {
        return;
      }

      // Each static field access implicitly triggers the class initializer.
      if (encodedField.isStatic()) {
        addClassInitializerTarget(clazz);
      }

      FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(encodedField.field);
      if (fieldAccessInfo != null) {
        if (fieldAccessInfo.getNumberOfWriteContexts() == 1) {
          fieldAccessInfo.forEachWriteContext(this::addFieldReadEdge);
        }
      }
    }

    private void processFieldWrite(DexField field) {
      if (field.holder.isClassType()) {
        DexEncodedField encodedField = appView.appInfo().resolveField(field);
        if (encodedField != null && encodedField.isStatic()) {
          // Each static field access implicitly triggers the class initializer.
          addClassInitializerTarget(field.holder);
        }
      }
    }

    @Override
    public boolean registerInvokeVirtual(DexMethod method) {
      processInvoke(Invoke.Type.VIRTUAL, method);
      return false;
    }

    @Override
    public boolean registerInvokeDirect(DexMethod method) {
      processInvoke(Invoke.Type.DIRECT, method);
      return false;
    }

    @Override
    public boolean registerInvokeStatic(DexMethod method) {
      processInvoke(Invoke.Type.STATIC, method);
      return false;
    }

    @Override
    public boolean registerInvokeInterface(DexMethod method) {
      processInvoke(Invoke.Type.INTERFACE, method);
      return false;
    }

    @Override
    public boolean registerInvokeSuper(DexMethod method) {
      processInvoke(Invoke.Type.SUPER, method);
      return false;
    }

    @Override
    public boolean registerInstanceFieldRead(DexField field) {
      processFieldRead(field);
      return false;
    }

    @Override
    public boolean registerInstanceFieldWrite(DexField field) {
      processFieldWrite(field);
      return false;
    }

    @Override
    public boolean registerNewInstance(DexType type) {
      if (type.isClassType()) {
        addClassInitializerTarget(type);
      }
      return false;
    }

    @Override
    public boolean registerStaticFieldRead(DexField field) {
      processFieldRead(field);
      return false;
    }

    @Override
    public boolean registerStaticFieldWrite(DexField field) {
      processFieldWrite(field);
      return false;
    }

    @Override
    public boolean registerTypeReference(DexType type) {
      return false;
    }

    @Override
    public void registerCallSite(DexCallSite callSite) {
      registerMethodHandle(
          callSite.bootstrapMethod, MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
    }
  }

  static class CycleEliminator {

    static final String CYCLIC_FORCE_INLINING_MESSAGE =
        "Unable to satisfy force inlining constraints due to cyclic force inlining";

    private static class CallEdge {

      private final Node caller;
      private final Node callee;

      CallEdge(Node caller, Node callee) {
        this.caller = caller;
        this.callee = callee;
      }
    }

    static class StackEntryInfo {

      final int index;
      final Node predecessor;

      boolean processed;

      StackEntryInfo(int index, Node predecessor) {
        this.index = index;
        this.predecessor = predecessor;
      }
    }

    static class CycleEliminationResult {

      private Map<DexEncodedMethod, Set<DexEncodedMethod>> removedCallEdges;

      CycleEliminationResult(Map<DexEncodedMethod, Set<DexEncodedMethod>> removedCallEdges) {
        this.removedCallEdges = removedCallEdges;
      }

      void forEachRemovedCaller(DexEncodedMethod callee, Consumer<DexEncodedMethod> fn) {
        removedCallEdges.getOrDefault(callee, ImmutableSet.of()).forEach(fn);
      }

      int numberOfRemovedCallEdges() {
        int numberOfRemovedCallEdges = 0;
        for (Set<DexEncodedMethod> nodes : removedCallEdges.values()) {
          numberOfRemovedCallEdges += nodes.size();
        }
        return numberOfRemovedCallEdges;
      }
    }

    // DFS stack.
    private Deque<Node> stack = new ArrayDeque<>();

    // Nodes on the DFS stack.
    private Map<Node, StackEntryInfo> stackEntryInfo = new IdentityHashMap<>();

    // Subset of the DFS stack, where the nodes on the stack satisfy that the edge from the
    // predecessor to the node itself is a field read edge.
    //
    // This stack is used to efficiently compute if there is a field read edge inside a cycle when
    // a cycle is found.
    private Deque<Node> writerStack = new ArrayDeque<>();

    // Set of nodes that have been visited entirely.
    private Set<Node> marked = Sets.newIdentityHashSet();

    // Call edges that should be removed when the caller has been processed. These are not removed
    // directly since that would lead to ConcurrentModificationExceptions.
    private Map<Node, Set<Node>> calleesToBeRemoved = new IdentityHashMap<>();

    // Field read edges that should be removed when the reader has been processed. These are not
    // removed directly since that would lead to ConcurrentModificationExceptions.
    private Map<Node, Set<Node>> writersToBeRemoved = new IdentityHashMap<>();

    // Mapping from callee to the set of callers that were removed from the callee.
    private Map<DexEncodedMethod, Set<DexEncodedMethod>> removedCallEdges = new IdentityHashMap<>();

    // Set of nodes from which cycle elimination must be rerun to ensure that all cycles will be
    // removed.
    private LinkedHashSet<Node> revisit = new LinkedHashSet<>();

    CycleEliminationResult breakCycles(Collection<Node> roots) {
      // Break cycles in this call graph by removing edges causing cycles. We do this in a fixpoint
      // because the algorithm does not guarantee that all cycles will be removed from the graph
      // when we remove an edge in the middle of a cycle that contains another cycle.
      do {
        traverse(roots);
        roots = revisit;
        prepareForNewTraversal();
      } while (!roots.isEmpty());

      CycleEliminationResult result = new CycleEliminationResult(removedCallEdges);
      if (Log.ENABLED) {
        Log.info(getClass(), "# call graph cycles broken: %s", result.numberOfRemovedCallEdges());
      }
      reset();
      return result;
    }

    private void prepareForNewTraversal() {
      assert calleesToBeRemoved.isEmpty();
      assert stack.isEmpty();
      assert stackEntryInfo.isEmpty();
      assert writersToBeRemoved.isEmpty();
      assert writerStack.isEmpty();
      marked.clear();
      revisit = new LinkedHashSet<>();
    }

    private void reset() {
      assert marked.isEmpty();
      assert revisit.isEmpty();
      assert stack.isEmpty();
      assert stackEntryInfo.isEmpty();
      assert writerStack.isEmpty();
      removedCallEdges = new IdentityHashMap<>();
    }

    private static class WorkItem {
      boolean isNode() {
        return false;
      }

      NodeWorkItem asNode() {
        return null;
      }

      boolean isIterator() {
        return false;
      }

      IteratorWorkItem asIterator() {
        return null;
      }
    }

    private static class NodeWorkItem extends WorkItem {
      private final Node node;

      NodeWorkItem(Node node) {
        this.node = node;
      }

      @Override
      boolean isNode() {
        return true;
      }

      @Override
      NodeWorkItem asNode() {
        return this;
      }
    }

    private static class IteratorWorkItem extends WorkItem {
      private final Node callerOrReader;
      private final Iterator<Node> calleesAndWriters;

      IteratorWorkItem(Node callerOrReader, Iterator<Node> calleesAndWriters) {
        this.callerOrReader = callerOrReader;
        this.calleesAndWriters = calleesAndWriters;
      }

      @Override
      boolean isIterator() {
        return true;
      }

      @Override
      IteratorWorkItem asIterator() {
        return this;
      }
    }

    private void traverse(Collection<Node> roots) {
      Deque<WorkItem> workItems = new ArrayDeque<>(roots.size());
      for (Node node : roots) {
        workItems.addLast(new NodeWorkItem(node));
      }
      while (!workItems.isEmpty()) {
        WorkItem workItem = workItems.removeFirst();
        if (workItem.isNode()) {
          Node node = workItem.asNode().node;
          if (marked.contains(node)) {
            // Already visited all nodes that can be reached from this node.
            continue;
          }

          Node predecessor = stack.isEmpty() ? null : stack.peek();
          push(node, predecessor);

          // The callees and writers must be sorted before calling traverse recursively.
          // This ensures that cycles are broken the same way across multiple compilations.
          Iterator<Node> calleesAndWriterIterator =
              Iterators.concat(
                  node.getCalleesWithDeterministicOrder().iterator(),
                  node.getWritersWithDeterministicOrder().iterator());
          workItems.addFirst(new IteratorWorkItem(node, calleesAndWriterIterator));
        } else {
          assert workItem.isIterator();
          IteratorWorkItem iteratorWorkItem = workItem.asIterator();
          Node newCallerOrReader =
              iterateCalleesAndWriters(
                  iteratorWorkItem.calleesAndWriters, iteratorWorkItem.callerOrReader);
          if (newCallerOrReader != null) {
            // We did not finish the work on this iterator, so add it again.
            workItems.addFirst(iteratorWorkItem);
            workItems.addFirst(new NodeWorkItem(newCallerOrReader));
          } else {
            assert !iteratorWorkItem.calleesAndWriters.hasNext();
            pop(iteratorWorkItem.callerOrReader);
            marked.add(iteratorWorkItem.callerOrReader);

            Collection<Node> calleesToBeRemovedFromCaller =
                calleesToBeRemoved.remove(iteratorWorkItem.callerOrReader);
            if (calleesToBeRemovedFromCaller != null) {
              calleesToBeRemovedFromCaller.forEach(
                  callee -> {
                    callee.removeCaller(iteratorWorkItem.callerOrReader);
                    recordCallEdgeRemoval(iteratorWorkItem.callerOrReader, callee);
                  });
            }

            Collection<Node> writersToBeRemovedFromReader =
                writersToBeRemoved.remove(iteratorWorkItem.callerOrReader);
            if (writersToBeRemovedFromReader != null) {
              writersToBeRemovedFromReader.forEach(
                  writer -> writer.removeReader(iteratorWorkItem.callerOrReader));
            }
          }
        }
      }
    }

    private Node iterateCalleesAndWriters(
        Iterator<Node> calleeOrWriterIterator, Node callerOrReader) {
      while (calleeOrWriterIterator.hasNext()) {
        Node calleeOrWriter = calleeOrWriterIterator.next();
        StackEntryInfo calleeOrWriterStackEntryInfo = stackEntryInfo.get(calleeOrWriter);
        boolean foundCycle = calleeOrWriterStackEntryInfo != null;
        if (!foundCycle) {
          return calleeOrWriter;
        }

        // Found a cycle that needs to be eliminated. If it is a field read edge, then remove it
        // right away.
        boolean isFieldReadEdge = calleeOrWriter.hasReader(callerOrReader);
        if (isFieldReadEdge) {
          removeFieldReadEdge(callerOrReader, calleeOrWriter);
          continue;
        }

        // Otherwise, it is a call edge. Check if there is a field read edge in the cycle, and if
        // so, remove that edge.
        if (!writerStack.isEmpty()) {
          Node lastKnownWriter = writerStack.peek();
          StackEntryInfo lastKnownWriterStackEntryInfo = stackEntryInfo.get(lastKnownWriter);
          boolean cycleContainsLastKnownWriter =
              lastKnownWriterStackEntryInfo.index > calleeOrWriterStackEntryInfo.index;
          if (cycleContainsLastKnownWriter) {
            assert verifyCycleSatisfies(
                calleeOrWriter,
                cycle ->
                    cycle.contains(lastKnownWriter)
                        && cycle.contains(lastKnownWriterStackEntryInfo.predecessor));
            if (!lastKnownWriterStackEntryInfo.processed) {
              removeFieldReadEdge(lastKnownWriterStackEntryInfo.predecessor, lastKnownWriter);
              revisit.add(lastKnownWriter);
              lastKnownWriterStackEntryInfo.processed = true;
            }
            continue;
          }
        }

        // It is a call edge, and the cycle does not contain any field read edges. In this case, we
        // remove the call edge if it is safe according to force inlining.
        if (callEdgeRemovalIsSafe(callerOrReader, calleeOrWriter)) {
          // Break the cycle by removing the edge node->calleeOrWriter.
          // Need to remove `calleeOrWriter` from `node.callees` using the iterator to prevent a
          // ConcurrentModificationException.
          removeCallEdge(callerOrReader, calleeOrWriter);
          continue;
        }

        // The call edge cannot be removed due to force inlining. Find another call edge in the
        // cycle that can safely be removed instead.
        LinkedList<Node> cycle = extractCycle(calleeOrWriter);

        // Break the cycle by finding an edge that can be removed without breaking force
        // inlining. If that is not possible, this call fails with a compilation error.
        CallEdge edge = findCallEdgeForRemoval(cycle);

        // The edge will be null if this cycle has already been eliminated as a result of
        // another cycle elimination.
        if (edge != null) {
          assert callEdgeRemovalIsSafe(edge.caller, edge.callee);

          // Break the cycle by removing the edge caller->callee.
          removeCallEdge(edge.caller, edge.callee);
        }

        // Recover the stack.
        recoverStack(cycle);
      }
      return null;
    }

    private void push(Node node, Node predecessor) {
      stack.push(node);
      assert !stackEntryInfo.containsKey(node);
      stackEntryInfo.put(node, new StackEntryInfo(stack.size() - 1, predecessor));
      if (predecessor != null && predecessor.getWritersWithDeterministicOrder().contains(node)) {
        writerStack.push(node);
      }
    }

    private void pop(Node node) {
      Node popped = stack.pop();
      assert popped == node;
      assert stackEntryInfo.containsKey(node);
      stackEntryInfo.remove(node);
      if (writerStack.peek() == popped) {
        writerStack.pop();
      }
    }

    private void removeCallEdge(Node caller, Node callee) {
      calleesToBeRemoved.computeIfAbsent(caller, ignore -> Sets.newIdentityHashSet()).add(callee);
    }

    private void removeFieldReadEdge(Node reader, Node writer) {
      writersToBeRemoved.computeIfAbsent(reader, ignore -> Sets.newIdentityHashSet()).add(writer);
    }

    private LinkedList<Node> extractCycle(Node entry) {
      LinkedList<Node> cycle = new LinkedList<>();
      do {
        assert !stack.isEmpty();
        cycle.add(stack.pop());
      } while (cycle.getLast() != entry);
      return cycle;
    }

    private boolean verifyCycleSatisfies(Node entry, Predicate<LinkedList<Node>> predicate) {
      LinkedList<Node> cycle = extractCycle(entry);
      assert predicate.test(cycle);
      recoverStack(cycle);
      return true;
    }

    private CallEdge findCallEdgeForRemoval(LinkedList<Node> extractedCycle) {
      Node callee = extractedCycle.getLast();
      for (Node caller : extractedCycle) {
        if (caller.hasWriter(callee)) {
          // Not a call edge.
          assert !caller.hasCallee(callee);
          assert !callee.hasCaller(caller);
          callee = caller;
          continue;
        }
        if (!caller.hasCallee(callee)) {
          // No need to break any edges since this cycle has already been broken previously.
          assert !callee.hasCaller(caller);
          return null;
        }
        if (callEdgeRemovalIsSafe(caller, callee)) {
          return new CallEdge(caller, callee);
        }
        callee = caller;
      }
      throw new CompilationError(CYCLIC_FORCE_INLINING_MESSAGE);
    }

    private static boolean callEdgeRemovalIsSafe(Node callerOrReader, Node calleeOrWriter) {
      // All call edges where the callee is a method that should be force inlined must be kept,
      // to guarantee that the IR converter will process the callee before the caller.
      assert calleeOrWriter.hasCaller(callerOrReader);
      return !calleeOrWriter.method.getOptimizationInfo().forceInline();
    }

    private void recordCallEdgeRemoval(Node caller, Node callee) {
      removedCallEdges
          .computeIfAbsent(callee.method, ignore -> SetUtils.newIdentityHashSet(2))
          .add(caller.method);
    }

    private void recoverStack(LinkedList<Node> extractedCycle) {
      Iterator<Node> descendingIt = extractedCycle.descendingIterator();
      while (descendingIt.hasNext()) {
        stack.push(descendingIt.next());
      }
    }
  }
}
