// Copyright (c) 2021, 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.optimize.argumentpropagation;

import static com.android.tools.r8.utils.MapUtils.ignoreKey;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ImmediateProgramSubtypingInfo;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodStateCollectionByReference;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.UnknownMethodState;
import com.android.tools.r8.optimize.argumentpropagation.utils.DepthFirstTopDownClassHierarchyTraversal;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.collections.DexMethodSignatureSet;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

public class ArgumentPropagatorUnoptimizableMethods {

  private static final MethodSignatureEquivalence equivalence = MethodSignatureEquivalence.get();

  private final AppView<AppInfoWithLiveness> appView;
  private final ImmediateProgramSubtypingInfo immediateSubtypingInfo;
  private final MethodStateCollectionByReference methodStates;

  public ArgumentPropagatorUnoptimizableMethods(
      AppView<AppInfoWithLiveness> appView,
      ImmediateProgramSubtypingInfo immediateSubtypingInfo,
      MethodStateCollectionByReference methodStates) {
    this.appView = appView;
    this.immediateSubtypingInfo = immediateSubtypingInfo;
    this.methodStates = methodStates;
  }

  // TODO(b/190154391): Consider if we should bail out for classes that inherit from a missing
  //  class.
  public void disableArgumentPropagationForUnoptimizableMethods(
      Collection<DexProgramClass> stronglyConnectedComponent) {
    ProgramMethodSet unoptimizableClassRootMethods = ProgramMethodSet.create();
    ProgramMethodSet unoptimizableInterfaceRootMethods = ProgramMethodSet.create();
    forEachUnoptimizableMethod(
        stronglyConnectedComponent,
        method -> {
          if (method.getDefinition().belongsToVirtualPool()
              && !method.getHolder().isFinal()
              && !method.getAccessFlags().isFinal()) {
            if (method.getHolder().isInterface()) {
              unoptimizableInterfaceRootMethods.add(method);
            } else {
              unoptimizableClassRootMethods.add(method);
            }
          } else {
            disableArgumentPropagationForMethod(method);
          }
        });

    // Disable argument propagation for all overrides of the root methods. Since interface methods
    // may be implemented by classes that are not a subtype of the interface that declares the
    // interface method, we first mark the interface method overrides on such classes as ineligible
    // for argument propagation.
    if (!unoptimizableInterfaceRootMethods.isEmpty()) {
      new UnoptimizableInterfaceMethodPropagator(
              unoptimizableClassRootMethods, unoptimizableInterfaceRootMethods)
          .run(stronglyConnectedComponent);
    }

    // At this point we can mark all overrides by a simple top-down traversal over the class
    // hierarchy.
    new UnoptimizableClassMethodPropagator(
            unoptimizableClassRootMethods, unoptimizableInterfaceRootMethods)
        .run(stronglyConnectedComponent);
  }

  private void disableArgumentPropagationForMethod(ProgramMethod method) {
    methodStates.set(method, UnknownMethodState.get());
  }

  private void forEachUnoptimizableMethod(
      Collection<DexProgramClass> stronglyConnectedComponent, Consumer<ProgramMethod> consumer) {
    AppInfoWithLiveness appInfo = appView.appInfo();
    InternalOptions options = appView.options();
    for (DexProgramClass clazz : stronglyConnectedComponent) {
      clazz.forEachProgramMethod(
          method -> {
            assert !method.getDefinition().belongsToVirtualPool()
                    || !method.getDefinition().isLibraryMethodOverride().isUnknown()
                : "Unexpected virtual method without library method override information: "
                    + method.toSourceString();
            if (method.getDefinition().isLibraryMethodOverride().isPossiblyTrue()
                || appInfo.isMethodTargetedByInvokeDynamic(method)
                || !appInfo
                    .getKeepInfo()
                    .getMethodInfo(method)
                    .isArgumentPropagationAllowed(options)) {
              consumer.accept(method);
            }
          });
    }
  }

  private class UnoptimizableInterfaceMethodPropagator
      extends DepthFirstTopDownClassHierarchyTraversal {

    private final ProgramMethodSet unoptimizableClassRootMethods;
    private final Map<DexProgramClass, Set<Wrapper<DexMethod>>> unoptimizableInterfaceMethods =
        new IdentityHashMap<>();

    UnoptimizableInterfaceMethodPropagator(
        ProgramMethodSet unoptimizableClassRootMethods,
        ProgramMethodSet unoptimizableInterfaceRootMethods) {
      super(
          ArgumentPropagatorUnoptimizableMethods.this.appView,
          ArgumentPropagatorUnoptimizableMethods.this.immediateSubtypingInfo);
      this.unoptimizableClassRootMethods = unoptimizableClassRootMethods;
      unoptimizableInterfaceRootMethods.forEach(this::addUnoptimizableRootMethod);
    }

    private void addUnoptimizableRootMethod(ProgramMethod method) {
      unoptimizableInterfaceMethods
          .computeIfAbsent(method.getHolder(), ignoreKey(Sets::newIdentityHashSet))
          .add(equivalence.wrap(method.getReference()));
    }

    @Override
    public void visit(DexProgramClass clazz) {
      Set<Wrapper<DexMethod>> unoptimizableInterfaceMethodsForClass =
          unoptimizableInterfaceMethods.computeIfAbsent(clazz, ignoreKey(Sets::newIdentityHashSet));

      // Add the unoptimizable interface methods from the parent interfaces.
      immediateSubtypingInfo.forEachImmediateProgramSuperClass(
          clazz,
          superclass ->
              unoptimizableInterfaceMethodsForClass.addAll(
                  unoptimizableInterfaceMethods.get(superclass)));

      // Propagate the unoptimizable interface methods of this interface to all immediate
      // (non-interface) subclasses.
      for (DexProgramClass implementer : immediateSubtypingInfo.getSubclasses(clazz)) {
        if (implementer.isInterface()) {
          continue;
        }

        for (Wrapper<DexMethod> unoptimizableInterfaceMethod :
            unoptimizableInterfaceMethodsForClass) {
          SingleResolutionResult resolutionResult =
              appView
                  .appInfo()
                  .resolveMethodOnClass(unoptimizableInterfaceMethod.get(), implementer)
                  .asSingleResolution();
          if (resolutionResult == null || !resolutionResult.getResolvedHolder().isProgramClass()) {
            continue;
          }

          ProgramMethod resolvedMethod = resolutionResult.getResolvedProgramMethod();
          if (resolvedMethod.getHolder().isInterface()
              || resolvedMethod.getHolder() == implementer) {
            continue;
          }

          unoptimizableClassRootMethods.add(resolvedMethod);
        }
      }
    }

    @Override
    public void prune(DexProgramClass clazz) {
      unoptimizableInterfaceMethods.remove(clazz);
    }

    @Override
    public boolean isRoot(DexProgramClass clazz) {
      return clazz.isInterface() && super.isRoot(clazz);
    }

    @Override
    public void forEachSubClass(DexProgramClass clazz, Consumer<DexProgramClass> consumer) {
      for (DexProgramClass subclass : immediateSubtypingInfo.getSubclasses(clazz)) {
        if (subclass.isInterface()) {
          consumer.accept(subclass);
        }
      }
    }
  }

  private class UnoptimizableClassMethodPropagator
      extends DepthFirstTopDownClassHierarchyTraversal {

    private final Map<DexProgramClass, DexMethodSignatureSet> unoptimizableMethods =
        new IdentityHashMap<>();

    UnoptimizableClassMethodPropagator(
        ProgramMethodSet unoptimizableClassRootMethods,
        ProgramMethodSet unoptimizableInterfaceRootMethods) {
      super(
          ArgumentPropagatorUnoptimizableMethods.this.appView,
          ArgumentPropagatorUnoptimizableMethods.this.immediateSubtypingInfo);
      unoptimizableClassRootMethods.forEach(this::addUnoptimizableRootMethod);
      unoptimizableInterfaceRootMethods.forEach(this::addUnoptimizableRootMethod);
    }

    private void addUnoptimizableRootMethod(ProgramMethod method) {
      unoptimizableMethods
          .computeIfAbsent(method.getHolder(), ignoreKey(DexMethodSignatureSet::create))
          .add(method);
    }

    @Override
    public void visit(DexProgramClass clazz) {
      DexMethodSignatureSet unoptimizableMethodsForClass =
          unoptimizableMethods.computeIfAbsent(clazz, ignoreKey(DexMethodSignatureSet::create));

      // Add the unoptimizable methods from the parent classes.
      immediateSubtypingInfo.forEachImmediateProgramSuperClass(
          clazz,
          superclass -> unoptimizableMethodsForClass.addAll(unoptimizableMethods.get(superclass)));

      // Disable argument propagation for the unoptimizable methods of this class.
      clazz.forEachProgramVirtualMethod(
          method -> {
            if (unoptimizableMethodsForClass.contains(method)) {
              disableArgumentPropagationForMethod(method);
            }
          });
    }

    @Override
    public void prune(DexProgramClass clazz) {
      unoptimizableMethods.remove(clazz);
    }
  }
}
