// Copyright (c) 2017, 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.code;

import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.cf.TypeVerificationHelper;
import com.android.tools.r8.graph.AppInfo.ResolutionResult;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeEnvironment;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
import com.android.tools.r8.ir.optimize.InliningOracle;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.Collection;
import java.util.List;

public abstract class InvokeMethod extends Invoke {

  private final DexMethod method;

  public InvokeMethod(DexMethod target, Value result, List<Value> arguments) {
    super(result, arguments);
    this.method = target;
  }

  @Override
  public DexType getReturnType() {
    return method.proto.returnType;
  }

  public DexMethod getInvokedMethod() {
    return method;
  }

  @Override
  public boolean identicalNonValueNonPositionParts(Instruction other) {
    return method == other.asInvokeMethod().getInvokedMethod();
  }

  @Override
  public int compareNonValueParts(Instruction other) {
    return getInvokedMethod().slowCompareTo(other.asInvokeMethod().getInvokedMethod());
  }

  @Override
  public String toString() {
    return super.toString() + "; method: " + method.toSourceString();
  }

  @Override
  public boolean isInvokeMethod() {
    return true;
  }

  @Override
  public InvokeMethod asInvokeMethod() {
    return this;
  }

  // TODO(jsjeon): merge lookupSingleTarget and computeSingleTarget.
  public abstract DexEncodedMethod lookupSingleTarget(AppInfoWithLiveness appInfo,
      DexType invocationContext);

  public abstract Collection<DexEncodedMethod> lookupTargets(AppInfoWithSubtyping appInfo,
      DexType invocationContext);

  // This method is used for inlining and/or other optimizations, such as value propagation.
  // It returns the target method iff this invoke has only one target.
  public DexEncodedMethod computeSingleTarget(AppInfoWithLiveness appInfo) {
    // TODO(jsjeon): revisit all usage of this method and pass proper invocation context.
    return computeSingleTarget(appInfo, TypeAnalysis.getDefaultTypeEnvironment(), null);
  }

  // TODO(b/72693244): By annotating type lattice to value, avoid passing type env.
  public DexEncodedMethod computeSingleTarget(
      AppInfoWithLiveness appInfo, TypeEnvironment typeEnvironment, DexType invocationContext) {
    // In subclasses, e.g., invoke-virtual or invoke-super, use a narrower receiver type by using
    // receiver type and type environment or invocation context---where the current invoke is.
    return lookupSingleTarget(appInfo, appInfo.dexItemFactory.objectType);
  }

  @Override
  public abstract Constraint inliningConstraint(AppInfoWithLiveness info,
      DexType invocationContext);

  protected Constraint inliningConstraintForSinlgeTargetInvoke(AppInfoWithLiveness info,
      DexType invocationContext) {
    if (method.holder.isArrayType()) {
      return Constraint.ALWAYS;
    }
    DexEncodedMethod target = lookupSingleTarget(info, invocationContext);
    if (target != null) {
      DexType methodHolder = target.method.holder;
      DexClass methodClass = info.definitionFor(methodHolder);
      if ((methodClass != null)) {
        Constraint methodConstraint = Constraint
            .deriveConstraint(invocationContext, methodHolder, target.accessFlags, info);
        // We also have to take the constraint of the enclosing class into account.
        Constraint classConstraint = Constraint
            .deriveConstraint(invocationContext, methodHolder, methodClass.accessFlags, info);
        return Constraint.min(methodConstraint, classConstraint);
      }
    }
    return Constraint.NEVER;
  }

  protected Constraint inliningConstraintForVirtualInvoke(AppInfoWithSubtyping info,
      DexType invocationContext) {
    if (method.holder.isArrayType()) {
      return Constraint.ALWAYS;
    }
    Collection<DexEncodedMethod> targets = lookupTargets(info, invocationContext);
    if (targets == null || targets.isEmpty()) {
      return Constraint.NEVER;
    }

    Constraint result = Constraint.ALWAYS;

    // Perform resolution and derive inlining constraints based on the accessibility of the
    // resolution result.
    ResolutionResult resolutionResult = info.resolveMethod(method.holder, method);
    DexEncodedMethod resolutionTarget = resolutionResult.asResultOfResolve();
    if (resolutionTarget == null) {
      // This will fail at runtime.
      return Constraint.NEVER;
    }
    DexType methodHolder = resolutionTarget.method.holder;
    DexClass methodClass = info.definitionFor(methodHolder);
    assert methodClass != null;
    Constraint methodConstraint = Constraint
        .deriveConstraint(invocationContext, methodHolder, resolutionTarget.accessFlags, info);
    result = Constraint.min(result, methodConstraint);
    // We also have to take the constraint of the enclosing class of the resolution result
    // into account. We do not allow inlining this method if it is calling something that
    // is inaccessible. Inlining in that case could move the code to another package making a
    // call succeed that should not succeed. Conversely, if the resolution result is accessible,
    // we have to make sure that inlining cannot make it inaccessible.
    Constraint classConstraint = Constraint
        .deriveConstraint(invocationContext, methodHolder, methodClass.accessFlags, info);
    result = Constraint.min(result, classConstraint);
    if (result == Constraint.NEVER) {
      return result;
    }

    // For each of the actual potential targets, derive constraints based on the accessibility
    // of the method itself.
    for (DexEncodedMethod target : targets) {
      methodHolder = target.method.holder;
      methodClass = info.definitionFor(methodHolder);
      assert methodClass != null;
      methodConstraint = Constraint
          .deriveConstraint(invocationContext, methodHolder, target.accessFlags, info);
      result = Constraint.min(result, methodConstraint);
      if (result == Constraint.NEVER) {
        return result;
      }
    }

    return result;
  }

  public abstract InlineAction computeInlining(InliningOracle decider, DexType invocationContext);

  @Override
  public void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper) {
    helper.loadInValues(this, it);
    if (getReturnType().isVoidType()) {
      return;
    }
    if (outValue == null) {
      helper.popOutType(getReturnType(), this, it);
    } else {
      assert outValue.isUsed();
      helper.storeOutValue(this, it);
    }
  }

  @Override
  public boolean hasInvariantVerificationType() {
    return true;
  }

  @Override
  public DexType computeVerificationType(TypeVerificationHelper helper) {
    return getReturnType();
  }

}
