// 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.analysis;

import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeNewArray;
import com.android.tools.r8.ir.code.NewArrayEmpty;
import com.android.tools.r8.ir.code.NewArrayFilledData;
import com.android.tools.r8.ir.code.NewInstance;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
import com.android.tools.r8.utils.LongInterval;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * An analysis that is used to determine if a value may depend on the runtime environment. The
 * primary use case of this analysis is to determine if a class initializer can safely be postponed:
 *
 * <p>If a class initializer does not have any other side effects than the field assignments to the
 * static fields of the enclosing class, and all the values that are being stored into the static
 * fields do not depend on the runtime environment (i.e., the heap, which can be accessed via
 * static-get instructions), then the class initializer can safely be postponed.
 *
 * <p>All compile time constants are independent of the runtime environment. Furthermore, all newly
 * instantiated arrays and objects are independent of the environment, as long as their content
 * (i.e., array elements and field values) does not depend on the runtime environment.
 *
 * <p>Example: Values that are considered to be independent of the runtime environment:
 *
 * <ul>
 *   <li>{@code true}
 *   <li>{@code 42}
 *   <li>{@code "Hello world!"}
 *   <li>{@code new Object()}
 *   <li>{@code new MyClassWithTrivialInitializer("ABC")}
 *   <li>{@code new MyStandardEnum(42, "A")}
 *   <li>{@code new int[] {0, 1, 2}}
 *   <li>{@code new Object[] {new Object(), new MyClassWithTrivialInitializer()}}
 * </ul>
 *
 * <p>Example: Values that are considered to be dependent on the runtime environment:
 *
 * <ul>
 *   <li>{@code argX} (for methods with arguments)
 *   <li>{@code OtherClass.STATIC_FIELD} (reads a value from the runtime environment)
 *   <li>{@code new MyClassWithTrivialInitializer(OtherClass.FIELD)}
 * </ul>
 */
public class ValueMayDependOnEnvironmentAnalysis {

  private final AppView<?> appView;
  private final IRCode code;
  private final DexType context;

  private final Set<Value> knownNotToDependOnEnvironment = Sets.newIdentityHashSet();
  private final Set<Value> visited = Sets.newIdentityHashSet();

  // Lazily computed mapping from final field definitions of the enclosing class to the static-put
  // instructions in the class initializer that assigns these final fields.
  private Map<DexEncodedField, List<StaticPut>> finalFieldPuts;

  public ValueMayDependOnEnvironmentAnalysis(AppView<?> appView, IRCode code) {
    this.appView = appView;
    this.code = code;
    this.context = code.method.holder();
  }

  public boolean valueMayDependOnEnvironment(Value value) {
    boolean result = valueMayDependOnEnvironment(value, Sets.newIdentityHashSet());
    assert visited.isEmpty();
    return result;
  }

  private boolean valueMayDependOnEnvironment(
      Value value, Set<Value> assumedNotToDependOnEnvironment) {
    Value root = value.getAliasedValue();
    if (assumedNotToDependOnEnvironment.contains(root)) {
      return false;
    }
    if (knownNotToDependOnEnvironment.contains(root)) {
      return false;
    }
    if (!visited.add(root)) {
      // Guard against cycle by conservatively returning true.
      return true;
    }
    try {
      if (root.isConstant()) {
        return false;
      }
      if (isConstantArrayThroughoutMethod(root, assumedNotToDependOnEnvironment)) {
        return false;
      }
      if (root.getAbstractValue(appView, context).isSingleEnumValue()) {
        return false;
      }
      if (isNewInstanceWithoutEnvironmentDependentFields(root, assumedNotToDependOnEnvironment)) {
        return false;
      }
      return true;
    } finally {
      boolean changed = visited.remove(root);
      assert changed;
    }
  }

  private boolean valueMayNotDependOnEnvironmentAssumingArrayDoesNotDependOnEnvironment(
      Value value, Value array, Set<Value> assumedNotToDependOnEnvironment) {
    assert !value.hasAliasedValue();
    assert !array.hasAliasedValue();

    if (assumedNotToDependOnEnvironment.add(array)) {
      boolean valueMayDependOnEnvironment =
          valueMayDependOnEnvironment(value, assumedNotToDependOnEnvironment);
      boolean changed = assumedNotToDependOnEnvironment.remove(array);
      assert changed;
      return !valueMayDependOnEnvironment;
    }
    return !valueMayDependOnEnvironment(value, assumedNotToDependOnEnvironment);
  }

  /**
   * Used to identify if an array is "constant" in the sense that none of the values written into
   * the array may depend on the environment.
   *
   * <p>Examples include {@code new int[] {1,2,3}} and {@code new Object[]{new Object()}}.
   */
  public boolean isConstantArrayThroughoutMethod(Value value) {
    boolean result = isConstantArrayThroughoutMethod(value, Sets.newIdentityHashSet());
    assert visited.isEmpty();
    return result;
  }

  private boolean isConstantArrayThroughoutMethod(
      Value value, Set<Value> assumedNotToDependOnEnvironment) {
    Value root = value.getAliasedValue();
    if (root.isPhi()) {
      // Would need to track the aliases, just give up.
      return false;
    }

    Instruction definition = root.definition;

    // Check that it is a constant array with a known size at this point in the IR.
    long size;
    if (definition.isInvokeNewArray()) {
      InvokeNewArray invokeNewArray = definition.asInvokeNewArray();
      for (Value argument : invokeNewArray.arguments()) {
        if (!argument.isConstant()) {
          return false;
        }
      }
      size = invokeNewArray.arguments().size();
    } else if (definition.isNewArrayEmpty()) {
      NewArrayEmpty newArrayEmpty = definition.asNewArrayEmpty();
      Value sizeValue = newArrayEmpty.size().getAliasedValue();
      if (!sizeValue.hasValueRange()) {
        return false;
      }
      LongInterval sizeRange = sizeValue.getValueRange();
      if (!sizeRange.isSingleValue()) {
        return false;
      }
      size = sizeRange.getSingleValue();
    } else {
      // Some other array creation.
      return false;
    }

    if (size < 0) {
      // Check for NegativeArraySizeException.
      return false;
    }

    if (size == 0) {
      // Empty arrays are always constant.
      return true;
    }

    // Allow array-put and new-array-filled-data instructions that immediately follow the array
    // creation.
    Set<Value> arrayValues = Sets.newIdentityHashSet();
    Set<Instruction> consumedInstructions = Sets.newIdentityHashSet();

    for (Instruction instruction : definition.getBlock().instructionsAfter(definition)) {
      if (instruction.isArrayPut()) {
        ArrayPut arrayPut = instruction.asArrayPut();
        Value array = arrayPut.array().getAliasedValue();
        if (array != root) {
          // This ends the chain of array-put instructions that are allowed immediately after the
          // array creation.
          break;
        }

        LongInterval indexRange = arrayPut.index().getValueRange();
        if (!indexRange.isSingleValue()) {
          return false;
        }

        long index = indexRange.getSingleValue();
        if (index < 0 || index >= size) {
          return false;
        }

        // Check if the value being written into the array may depend on the environment.
        //
        // When analyzing if the value may depend on the environment, we assume that the current
        // array does not depend on the environment. Otherwise, we would classify the value as
        // possibly depending on the environment since it could escape via the array and then
        // be mutated indirectly.
        Value rhs = arrayPut.value().getAliasedValue();
        if (!valueMayNotDependOnEnvironmentAssumingArrayDoesNotDependOnEnvironment(
            rhs, root, assumedNotToDependOnEnvironment)) {
          return false;
        }

        arrayValues.add(rhs);
        consumedInstructions.add(arrayPut);
        continue;
      }

      if (instruction.isNewArrayFilledData()) {
        NewArrayFilledData newArrayFilledData = instruction.asNewArrayFilledData();
        Value array = newArrayFilledData.src();
        if (array != root) {
          break;
        }

        consumedInstructions.add(newArrayFilledData);
        continue;
      }

      if (instruction.instructionMayHaveSideEffects(appView, context)) {
        // This ends the chain of array-put instructions that are allowed immediately after the
        // array creation.
        break;
      }
    }

    // Check that the array is not mutated before the end of this method.
    //
    // Currently, we only allow the array to flow into static-put instructions that are not
    // followed by an instruction that may have side effects. Instructions that do not have any
    // side effects are ignored because they cannot mutate the array.
    if (valueMayBeMutatedBeforeMethodExit(
        root, assumedNotToDependOnEnvironment, consumedInstructions)) {
      return false;
    }

    if (assumedNotToDependOnEnvironment.isEmpty()) {
      knownNotToDependOnEnvironment.add(root);
      knownNotToDependOnEnvironment.addAll(arrayValues);
    }

    return true;
  }

  private boolean isNewInstanceWithoutEnvironmentDependentFields(
      Value value, Set<Value> assumedNotToDependOnEnvironment) {
    assert !value.hasAliasedValue();

    if (value.isPhi() || !value.definition.isNewInstance()) {
      return false;
    }

    NewInstance newInstance = value.definition.asNewInstance();
    DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(newInstance.clazz));
    if (clazz == null) {
      return false;
    }

    // Find the single constructor invocation.
    InvokeMethod constructorInvoke = null;
    for (Instruction instruction : value.uniqueUsers()) {
      if (!instruction.isInvokeDirect()) {
        continue;
      }

      InvokeDirect invoke = instruction.asInvokeDirect();
      if (!appView.dexItemFactory().isConstructor(invoke.getInvokedMethod())) {
        continue;
      }

      if (invoke.getReceiver().getAliasedValue() != value) {
        continue;
      }

      if (constructorInvoke == null) {
        constructorInvoke = invoke;
      } else {
        // Not a single constructor invocation, give up.
        return false;
      }
    }

    if (constructorInvoke == null) {
      // Didn't find a constructor invocation, give up.
      return false;
    }

    // Check that it is a trivial initializer (otherwise, the constructor could do anything).
    DexEncodedMethod constructor = appView.definitionFor(constructorInvoke.getInvokedMethod());
    if (constructor == null) {
      return false;
    }

    if (clazz.hasInstanceFieldsDirectlyOrIndirectly(appView)) {
      InstanceInitializerInfo initializerInfo =
          constructor.getOptimizationInfo().getInstanceInitializerInfo();
      if (initializerInfo.instanceFieldInitializationMayDependOnEnvironment()) {
        return false;
      }

      // Check that none of the arguments to the constructor depend on the environment.
      for (int i = 1; i < constructorInvoke.arguments().size(); i++) {
        Value argument = constructorInvoke.arguments().get(i);
        if (valueMayDependOnEnvironment(argument, assumedNotToDependOnEnvironment)) {
          return false;
        }
      }

      // Finally, check that the object does not escape.
      if (valueMayBeMutatedBeforeMethodExit(
          value, assumedNotToDependOnEnvironment, ImmutableSet.of(constructorInvoke))) {
        return false;
      }
    }

    if (assumedNotToDependOnEnvironment.isEmpty()) {
      knownNotToDependOnEnvironment.add(value);
    }

    return true;
  }

  private boolean valueMayBeMutatedBeforeMethodExit(
      Value value, Set<Value> assumedNotToDependOnEnvironment, Set<Instruction> whitelist) {
    assert !value.hasAliasedValue();

    if (value.numberOfPhiUsers() > 0) {
      // Could be mutated indirectly.
      return true;
    }

    Set<Instruction> visited = Sets.newIdentityHashSet();
    for (Instruction user : value.uniqueUsers()) {
      if (whitelist.contains(user)) {
        continue;
      }

      if (user.isArrayPut()) {
        ArrayPut arrayPut = user.asArrayPut();
        if (value == arrayPut.value()
            && !valueMayDependOnEnvironment(arrayPut.array(), assumedNotToDependOnEnvironment)) {
          continue;
        }
      }

      if (user.isStaticPut()) {
        StaticPut staticPut = user.asStaticPut();
        if (visited.contains(staticPut)) {
          // Already visited previously.
          continue;
        }
        for (Instruction instruction : code.getInstructionsReachableFrom(staticPut)) {
          if (!visited.add(instruction)) {
            // Already visited previously.
            continue;
          }
          if (instruction.isStaticPut()) {
            StaticPut otherStaticPut = instruction.asStaticPut();
            if (otherStaticPut.getField().holder == staticPut.getField().holder
                && instruction.instructionInstanceCanThrow(appView, context).cannotThrow()) {
              continue;
            }
            return true;
          }
          if (instruction.instructionMayTriggerMethodInvocation(appView, context)
              && instruction.instructionMayHaveSideEffects(appView, context)) {
            return true;
          }
        }
        continue;
      }

      // Other user than array-put or static-put, just give up.
      return false;
    }

    return false;
  }
}
