// 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.optimize.info;

import static java.util.Collections.emptySet;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.ir.analysis.inlining.NeverSimpleInliningConstraint;
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraint;
import com.android.tools.r8.ir.analysis.type.DynamicType;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.enums.classification.EnumUnboxerMethodClassification;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.BitSetUtils;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions;
import java.util.BitSet;
import java.util.Collections;
import java.util.Set;

public class MutableMethodOptimizationInfo extends MethodOptimizationInfo
    implements MutableOptimizationInfo {

  private CallSiteOptimizationInfo argumentInfos = CallSiteOptimizationInfo.top();
  private Set<DexType> initializedClassesOnNormalExit =
      DefaultMethodOptimizationInfo.UNKNOWN_INITIALIZED_CLASSES_ON_NORMAL_EXIT;
  private int returnedArgument = DefaultMethodOptimizationInfo.UNKNOWN_RETURNED_ARGUMENT;
  private AbstractValue abstractReturnValue =
      DefaultMethodOptimizationInfo.UNKNOWN_ABSTRACT_RETURN_VALUE;
  private ClassInlinerMethodConstraint classInlinerConstraint =
      ClassInlinerMethodConstraint.alwaysFalse();
  private EnumUnboxerMethodClassification enumUnboxerMethodClassification =
      EnumUnboxerMethodClassification.unknown();
  private DynamicType dynamicType = DynamicType.unknown();
  private InlinePreference inlining = InlinePreference.Default;
  // Stores information about instance methods and constructors for
  // class inliner, null value indicates that the method is not eligible.
  private BridgeInfo bridgeInfo = null;
  private InstanceInitializerInfoCollection instanceInitializerInfoCollection =
      InstanceInitializerInfoCollection.empty();
  // Stores information about nullability hint per parameter. If set, that means, the method
  // somehow (e.g., null check, such as arg != null, or using checkParameterIsNotNull) ensures
  // the corresponding parameter is not null, or throws NPE before any other side effects.
  // This info is used by {@link UninstantiatedTypeOptimization#rewriteInvoke} that replaces an
  // invocation with null throwing code if an always-null argument is passed. Also used by Inliner
  // to give a credit to null-safe code, e.g., Kotlin's null safe argument.
  // Note that this bit set takes into account the receiver for instance methods.
  private BitSet nonNullParamOrThrow =
      DefaultMethodOptimizationInfo.NO_NULL_PARAMETER_OR_THROW_FACTS;
  // Stores information about nullability facts per parameter. If set, that means, the method
  // somehow (e.g., null check, such as arg != null, or NPE-throwing instructions such as array
  // access or another invocation) ensures the corresponding parameter is not null, and that is
  // guaranteed until the normal exits. That is, if the invocation of this method is finished
  // normally, the recorded parameter is definitely not null. These facts are used to propagate
  // non-null information through {@link NonNullTracker}.
  // Note that this bit set takes into account the receiver for instance methods.
  private BitSet nonNullParamOnNormalExits =
      DefaultMethodOptimizationInfo.NO_NULL_PARAMETER_ON_NORMAL_EXITS_FACTS;

  private SimpleInliningConstraint simpleInliningConstraint =
      NeverSimpleInliningConstraint.getInstance();

  private BitSet unusedArguments = null;

  // To reduce the memory footprint of UpdatableMethodOptimizationInfo, all the boolean fields are
  // merged into a flag int field. The various static final FLAG fields indicate which bit is
  // used by each boolean. DEFAULT_FLAGS encodes the default value for efficient instantiation and
  // is computed during class initialization from the default method optimization info. The
  // methods setFlag, clearFlag and isFlagSet are used to access the booleans.
  private static final int CANNOT_BE_KEPT_FLAG = 0x1;
  private static final int CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG = 0x2;
  private static final int HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG = 0x4;
  private static final int MAY_HAVE_SIDE_EFFECT_FLAG = 0x8;
  private static final int RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG = 0x10;
  private static final int UNUSED_FLAG_1 = 0x20;
  private static final int NEVER_RETURNS_NORMALLY_FLAG = 0x40;
  private static final int UNUSED_FLAG_2 = 0x80;
  private static final int CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG = 0x100;
  private static final int TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG = 0x200;
  private static final int INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG = 0x400;
  private static final int REACHABILITY_SENSITIVE_FLAG = 0x800;
  private static final int RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG = 0x1000;

  private static final int DEFAULT_FLAGS;

  static {
    int defaultFlags = 0;
    MethodOptimizationInfo defaultOptInfo = DefaultMethodOptimizationInfo.DEFAULT_INSTANCE;
    defaultFlags |= BooleanUtils.intValue(defaultOptInfo.cannotBeKept()) * CANNOT_BE_KEPT_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.classInitializerMayBePostponed())
            * CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.hasBeenInlinedIntoSingleCallSite())
            * HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.mayHaveSideEffects()) * MAY_HAVE_SIDE_EFFECT_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.returnValueOnlyDependsOnArguments())
            * RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG;
    defaultFlags |= 0 * UNUSED_FLAG_1;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.neverReturnsNormally()) * NEVER_RETURNS_NORMALLY_FLAG;
    defaultFlags |= 0 * UNUSED_FLAG_2;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.checksNullReceiverBeforeAnySideEffect())
            * CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.triggersClassInitBeforeAnySideEffect())
            * TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.isInitializerEnablingJavaVmAssertions())
            * INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.isReachabilitySensitive())
            * REACHABILITY_SENSITIVE_FLAG;
    defaultFlags |=
        BooleanUtils.intValue(defaultOptInfo.returnValueHasBeenPropagated())
            * RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG;
    DEFAULT_FLAGS = defaultFlags;
  }

  private int flags = DEFAULT_FLAGS;

  MutableMethodOptimizationInfo() {
    // Intentionally left empty, just use the default values.
  }

  // Copy constructor used to create a mutable copy. Do not forget to copy from template when a new
  // field is added.
  private MutableMethodOptimizationInfo(MutableMethodOptimizationInfo template) {
    argumentInfos = template.argumentInfos;
    flags = template.flags;
    initializedClassesOnNormalExit = template.initializedClassesOnNormalExit;
    returnedArgument = template.returnedArgument;
    abstractReturnValue = template.abstractReturnValue;
    dynamicType = template.dynamicType;
    inlining = template.inlining;
    simpleInliningConstraint = template.simpleInliningConstraint;
    bridgeInfo = template.bridgeInfo;
    instanceInitializerInfoCollection = template.instanceInitializerInfoCollection;
    nonNullParamOrThrow = template.nonNullParamOrThrow;
    nonNullParamOnNormalExits = template.nonNullParamOnNormalExits;
    classInlinerConstraint = template.classInlinerConstraint;
    enumUnboxerMethodClassification = template.enumUnboxerMethodClassification;
  }

  public MutableMethodOptimizationInfo fixup(
      AppView<AppInfoWithLiveness> appView, MethodOptimizationInfoFixer fixer) {
    return fixupArgumentInfos(fixer)
        .fixupBridgeInfo(fixer)
        .fixupClassInlinerMethodConstraint(appView, fixer)
        .fixupEnumUnboxerMethodClassification(fixer)
        .fixupInstanceInitializerInfo(appView, fixer)
        .fixupNonNullParamOnNormalExits(fixer)
        .fixupNonNullParamOrThrow(fixer)
        .fixupReturnedArgumentIndex(fixer)
        .fixupSimpleInliningConstraint(appView, fixer)
        .fixupUnusedArguments(fixer);
  }

  public MutableMethodOptimizationInfo fixupClassTypeReferences(
      AppView<AppInfoWithLiveness> appView, GraphLens lens) {
    return fixupClassTypeReferences(appView, lens, emptySet());
  }

  public MutableMethodOptimizationInfo fixupClassTypeReferences(
      AppView<AppInfoWithLiveness> appView, GraphLens lens, Set<DexType> prunedTypes) {
    dynamicType = dynamicType.rewrittenWithLens(appView, lens, prunedTypes);
    return this;
  }

  public MutableMethodOptimizationInfo fixupAbstractReturnValue(
      AppView<AppInfoWithLiveness> appView, GraphLens lens) {
    abstractReturnValue = abstractReturnValue.rewrittenWithLens(appView, lens);
    return this;
  }

  public MutableMethodOptimizationInfo fixupInstanceInitializerInfo(
      AppView<AppInfoWithLiveness> appView, GraphLens lens, PrunedItems prunedItems) {
    instanceInitializerInfoCollection =
        instanceInitializerInfoCollection.rewrittenWithLens(appView, lens, prunedItems);
    return this;
  }

  private void setFlag(int flag, boolean value) {
    if (value) {
      setFlag(flag);
    } else {
      clearFlag(flag);
    }
  }

  private void setFlag(int flag) {
    flags |= flag;
  }

  private void clearFlag(int flag) {
    flags &= ~flag;
  }

  private boolean isFlagSet(int flag) {
    return (flags & flag) != 0;
  }

  @Override
  public boolean cannotBeKept() {
    return isFlagSet(CANNOT_BE_KEPT_FLAG);
  }

  // TODO(b/140214568): Should be package-private.
  public void markCannotBeKept() {
    setFlag(CANNOT_BE_KEPT_FLAG);
  }

  @Override
  public boolean classInitializerMayBePostponed() {
    return isFlagSet(CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG);
  }

  void markClassInitializerMayBePostponed() {
    setFlag(CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG);
  }

  void unsetClassInitializerMayBePostponed() {
    clearFlag(CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG);
  }

  @Override
  public CallSiteOptimizationInfo getArgumentInfos() {
    return argumentInfos;
  }

  public MutableMethodOptimizationInfo fixupArgumentInfos(MethodOptimizationInfoFixer fixer) {
    if (argumentInfos.isConcreteCallSiteOptimizationInfo()) {
      argumentInfos =
          fixer.fixupCallSiteOptimizationInfo(argumentInfos.asConcreteCallSiteOptimizationInfo());
    }
    return this;
  }

  void setArgumentInfos(CallSiteOptimizationInfo argumentInfos) {
    this.argumentInfos = argumentInfos;
  }

  @Override
  public ClassInlinerMethodConstraint getClassInlinerMethodConstraint() {
    return classInlinerConstraint;
  }

  public MutableMethodOptimizationInfo fixupClassInlinerMethodConstraint(
      AppView<AppInfoWithLiveness> appView, MethodOptimizationInfoFixer fixer) {
    classInlinerConstraint =
        fixer.fixupClassInlinerMethodConstraint(appView, classInlinerConstraint);
    return this;
  }

  void setClassInlinerMethodConstraint(ClassInlinerMethodConstraint classInlinerConstraint) {
    this.classInlinerConstraint = classInlinerConstraint;
  }

  void unsetClassInlinerMethodConstraint() {
    this.classInlinerConstraint = ClassInlinerMethodConstraint.alwaysFalse();
  }

  @Override
  public EnumUnboxerMethodClassification getEnumUnboxerMethodClassification() {
    return enumUnboxerMethodClassification;
  }

  void setEnumUnboxerMethodClassification(
      EnumUnboxerMethodClassification enumUnboxerMethodClassification) {
    // Check monotonicity.
    assert !this.enumUnboxerMethodClassification.isCheckNotNullClassification()
        || enumUnboxerMethodClassification.isCheckNotNullClassification();
    this.enumUnboxerMethodClassification = enumUnboxerMethodClassification;
  }

  public void unsetEnumUnboxerMethodClassification() {
    this.enumUnboxerMethodClassification = EnumUnboxerMethodClassification.unknown();
  }

  public MutableMethodOptimizationInfo fixupEnumUnboxerMethodClassification(
      MethodOptimizationInfoFixer fixer) {
    enumUnboxerMethodClassification =
        fixer.fixupEnumUnboxerMethodClassification(enumUnboxerMethodClassification);
    return this;
  }

  @Override
  public DynamicType getDynamicType() {
    return dynamicType;
  }

  @Override
  public Set<DexType> getInitializedClassesOnNormalExit() {
    return initializedClassesOnNormalExit;
  }

  @Override
  public InstanceInitializerInfo getContextInsensitiveInstanceInitializerInfo() {
    return instanceInitializerInfoCollection.getContextInsensitive();
  }

  @Override
  public InstanceInitializerInfo getInstanceInitializerInfo(InvokeDirect invoke) {
    return instanceInitializerInfoCollection.get(invoke);
  }

  public MutableMethodOptimizationInfo fixupInstanceInitializerInfo(
      AppView<AppInfoWithLiveness> appView, MethodOptimizationInfoFixer fixer) {
    instanceInitializerInfoCollection =
        fixer.fixupInstanceInitializerInfo(appView, instanceInitializerInfoCollection);
    return this;
  }

  @Override
  public BitSet getNonNullParamOrThrow() {
    return nonNullParamOrThrow;
  }

  public MutableMethodOptimizationInfo fixupNonNullParamOrThrow(MethodOptimizationInfoFixer fixer) {
    nonNullParamOrThrow = fixer.fixupNonNullParamOrThrow(nonNullParamOrThrow);
    return this;
  }

  void setNonNullParamOrThrow(BitSet facts) {
    this.nonNullParamOrThrow = facts;
  }

  void unsetNonNullParamOrThrow() {
    this.nonNullParamOrThrow = null;
  }

  @Override
  public BitSet getNonNullParamOnNormalExits() {
    return nonNullParamOnNormalExits;
  }

  public MutableMethodOptimizationInfo fixupNonNullParamOnNormalExits(
      MethodOptimizationInfoFixer fixer) {
    nonNullParamOnNormalExits = fixer.fixupNonNullParamOnNormalExits(nonNullParamOnNormalExits);
    return this;
  }

  void setNonNullParamOnNormalExits(BitSet facts) {
    this.nonNullParamOnNormalExits = facts;
  }

  void unsetNonNullParamOnNormalExits() {
    nonNullParamOnNormalExits = null;
  }

  @Override
  public boolean hasBeenInlinedIntoSingleCallSite() {
    return isFlagSet(HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG);
  }

  void markInlinedIntoSingleCallSite() {
    setFlag(HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG);
  }

  void unsetInlinedIntoSingleCallSite() {
    clearFlag(HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG);
  }

  @Override
  public boolean isReachabilitySensitive() {
    return isFlagSet(REACHABILITY_SENSITIVE_FLAG);
  }

  @Override
  public boolean returnsArgument() {
    return returnedArgument != -1;
  }

  @Override
  public int getReturnedArgument() {
    assert returnsArgument();
    return returnedArgument;
  }

  @Override
  public boolean neverReturnsNormally() {
    return isFlagSet(NEVER_RETURNS_NORMALLY_FLAG);
  }

  @Override
  public BridgeInfo getBridgeInfo() {
    return bridgeInfo;
  }

  public MutableMethodOptimizationInfo fixupBridgeInfo(MethodOptimizationInfoFixer fixer) {
    if (bridgeInfo != null) {
      assert bridgeInfo.isVirtualBridgeInfo();
      bridgeInfo = fixer.fixupBridgeInfo(bridgeInfo.asVirtualBridgeInfo());
    }
    return this;
  }

  void setBridgeInfo(BridgeInfo bridgeInfo) {
    this.bridgeInfo = bridgeInfo;
  }

  void unsetBridgeInfo() {
    this.bridgeInfo = null;
  }

  @Override
  public AbstractValue getAbstractReturnValue() {
    return abstractReturnValue;
  }

  @Override
  public SimpleInliningConstraint getNopInliningConstraint(InternalOptions options) {
    // We currently require that having a simple inlining constraint implies that the method becomes
    // empty after inlining. Therefore, an invoke is a nop if the simple inlining constraint is
    // satisfied (if the invoke does not trigger other side effects, such as class initialization).
    assert options.simpleInliningConstraintThreshold == 0;
    return getSimpleInliningConstraint();
  }

  @Override
  public SimpleInliningConstraint getSimpleInliningConstraint() {
    return simpleInliningConstraint;
  }

  @Override
  public BitSet getUnusedArguments() {
    return unusedArguments;
  }

  public MutableMethodOptimizationInfo fixupUnusedArguments(MethodOptimizationInfoFixer fixer) {
    fixupUnusedArguments(fixer.fixupUnusedArguments(unusedArguments));
    return this;
  }

  public MutableMethodOptimizationInfo fixupUnusedArguments(BitSet unusedArguments) {
    this.unusedArguments =
        unusedArguments != null && !unusedArguments.isEmpty() ? unusedArguments : null;
    return this;
  }

  void setUnusedArguments(BitSet unusedArguments) {
    // Verify monotonicity (i.e., unused arguments should never become used).
    assert !hasUnusedArguments() || unusedArguments != null;
    assert !hasUnusedArguments()
        || BitSetUtils.verifyLessThanOrEqualTo(getUnusedArguments(), unusedArguments);
    this.unusedArguments =
        unusedArguments != null && !unusedArguments.isEmpty() ? unusedArguments : null;
  }

  void unsetUnusedArguments() {
    unusedArguments = null;
  }

  @Override
  public boolean isInitializerEnablingJavaVmAssertions() {
    return isFlagSet(INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG);
  }

  @Override
  public boolean isMultiCallerMethod() {
    return inlining == InlinePreference.MultiCallerInline;
  }

  @Override
  public boolean forceInline() {
    return inlining == InlinePreference.ForceInline;
  }

  @Override
  public boolean checksNullReceiverBeforeAnySideEffect() {
    return isFlagSet(CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG);
  }

  @Override
  public boolean triggersClassInitBeforeAnySideEffect() {
    return isFlagSet(TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG);
  }

  @Override
  public boolean mayHaveSideEffects() {
    return isFlagSet(MAY_HAVE_SIDE_EFFECT_FLAG);
  }

  @Override
  public boolean mayHaveSideEffects(InvokeMethod invoke, InternalOptions options) {
    if (!mayHaveSideEffects()) {
      return false;
    }
    if (getNopInliningConstraint(options).isSatisfied(invoke)) {
      return false;
    }
    return true;
  }

  @Override
  public boolean returnValueOnlyDependsOnArguments() {
    return isFlagSet(RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG);
  }

  public void setReachabilitySensitive(boolean reachabilitySensitive) {
    setFlag(REACHABILITY_SENSITIVE_FLAG, reachabilitySensitive);
  }

  void unsetReachabilitySensitive() {
    clearFlag(REACHABILITY_SENSITIVE_FLAG);
  }

  void setSimpleInliningConstraint(SimpleInliningConstraint constraint) {
    this.simpleInliningConstraint = constraint;
  }

  void unsetSimpleInliningConstraint() {
    simpleInliningConstraint = NeverSimpleInliningConstraint.getInstance();
  }

  public MutableMethodOptimizationInfo fixupSimpleInliningConstraint(
      AppView<AppInfoWithLiveness> appView, MethodOptimizationInfoFixer fixer) {
    simpleInliningConstraint =
        fixer.fixupSimpleInliningConstraint(
            appView, simpleInliningConstraint, appView.simpleInliningConstraintFactory());
    return this;
  }

  void setInstanceInitializerInfoCollection(
      InstanceInitializerInfoCollection instanceInitializerInfoCollection) {
    this.instanceInitializerInfoCollection = instanceInitializerInfoCollection;
  }

  void unsetInstanceInitializerInfoCollection() {
    instanceInitializerInfoCollection = InstanceInitializerInfoCollection.empty();
  }

  void setInitializerEnablingJavaAssertions() {
    setFlag(INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG);
  }

  void unsetInitializerEnablingJavaVmAssertions() {
    clearFlag(INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG);
  }

  void markInitializesClassesOnNormalExit(Set<DexType> initializedClassesOnNormalExit) {
    this.initializedClassesOnNormalExit = initializedClassesOnNormalExit;
  }

  void unsetInitializedClassesOnNormalExit() {
    initializedClassesOnNormalExit = Collections.emptySet();
  }

  void markReturnsArgument(int returnedArgumentIndex) {
    assert returnedArgumentIndex >= 0;
    assert returnedArgument == -1 || returnedArgument == returnedArgumentIndex;
    returnedArgument = returnedArgumentIndex;
  }

  void unsetReturnedArgument() {
    returnedArgument = -1;
  }

  public MutableMethodOptimizationInfo fixupReturnedArgumentIndex(
      MethodOptimizationInfoFixer fixer) {
    returnedArgument = fixer.fixupReturnedArgumentIndex(returnedArgument);
    return this;
  }

  void markMayNotHaveSideEffects() {
    clearFlag(MAY_HAVE_SIDE_EFFECT_FLAG);
  }

  void unsetMayNotHaveSideEffects() {
    setFlag(MAY_HAVE_SIDE_EFFECT_FLAG);
  }

  void markReturnValueOnlyDependsOnArguments() {
    setFlag(RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG);
  }

  void unsetReturnValueOnlyDependsOnArguments() {
    clearFlag(RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG);
  }

  void markNeverReturnsNormally() {
    setFlag(NEVER_RETURNS_NORMALLY_FLAG);
  }

  void unsetNeverReturnsNormally() {
    clearFlag(NEVER_RETURNS_NORMALLY_FLAG);
  }

  void markReturnsAbstractValue(AbstractValue value) {
    assert !abstractReturnValue.isSingleValue() || abstractReturnValue.equals(value)
        : "return single value changed from " + abstractReturnValue + " to " + value;
    abstractReturnValue = value;
  }

  void unsetAbstractReturnValue() {
    abstractReturnValue = UnknownValue.getInstance();
  }

  void setDynamicType(AppView<?> appView, DynamicType newDynamicType, DexEncodedMethod method) {
    assert newDynamicType != null;
    // We may get more precise type information if the method is reprocessed (e.g., due to
    // optimization info collected from all call sites), and hence the
    // `returnsObjectWithUpperBoundType` is allowed to become more precise.
    // TODO(b/142559221): non-materializable assume instructions?
    // Nullability could be less precise, though. For example, suppose a value is known to be
    // non-null after a safe invocation, hence recorded with the non-null variant. If that call is
    // inlined and the method is reprocessed, such non-null assumption cannot be made again.
    assert verifyDynamicType(appView, newDynamicType, method);
    dynamicType = newDynamicType;
  }

  private boolean verifyDynamicType(
      AppView<?> appView, DynamicType newDynamicType, DexEncodedMethod method) {
    if (appView.enableWholeProgramOptimizations()) {
      TypeElement staticReturnType = method.getReturnType().toTypeElement(appView);
      TypeElement previousDynamicUpperBoundType =
          dynamicType.getDynamicUpperBoundType(staticReturnType);
      TypeElement newDynamicUpperBoundType =
          newDynamicType.getDynamicUpperBoundType(staticReturnType);
      assert newDynamicUpperBoundType.lessThanOrEqualUpToNullability(
              previousDynamicUpperBoundType, appView)
          : "upper bound type changed from "
              + previousDynamicUpperBoundType
              + " to "
              + newDynamicUpperBoundType;
    }
    return true;
  }

  void unsetDynamicType() {
    dynamicType = DynamicType.unknown();
  }

  // TODO(b/140214568): Should be package-private.
  public void markForceInline() {
    // For concurrent scenarios we should allow the flag to be already set
    assert inlining == InlinePreference.Default || inlining == InlinePreference.ForceInline;
    inlining = InlinePreference.ForceInline;
  }

  void unsetForceInline() {
    inlining = InlinePreference.Default;
  }

  void setMultiCallerMethod() {
    if (inlining == InlinePreference.Default) {
      inlining = InlinePreference.MultiCallerInline;
    } else {
      assert inlining == InlinePreference.ForceInline;
    }
  }

  void markCheckNullReceiverBeforeAnySideEffect(boolean mark) {
    setFlag(CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG, mark);
  }

  void unsetCheckNullReceiverBeforeAnySideEffect() {
    clearFlag(CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG);
  }

  void markTriggerClassInitBeforeAnySideEffect(boolean mark) {
    setFlag(TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG, mark);
  }

  void unsetTriggerClassInitBeforeAnySideEffect() {
    clearFlag(TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG);
  }

  // TODO(b/140214568): Should be package-private.
  public void markAsPropagated() {
    setFlag(RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG);
  }

  @Override
  public boolean returnValueHasBeenPropagated() {
    return isFlagSet(RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG);
  }

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

  @Override
  public MutableMethodOptimizationInfo toMutableOptimizationInfo() {
    return this;
  }

  @Override
  public MutableMethodOptimizationInfo asMutableMethodOptimizationInfo() {
    return this;
  }

  public MutableMethodOptimizationInfo mutableCopy() {
    return new MutableMethodOptimizationInfo(this);
  }
}
