// 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.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.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.environmentdependence.ValueGraph;
import com.android.tools.r8.ir.analysis.environmentdependence.ValueGraph.Node;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
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.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.SetUtils;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.IdentityHashMap;
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 ProgramMethod context;

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

  public boolean anyValueMayDependOnEnvironment(Iterable<Value> values) {
    ValueGraph graph = new ValueGraph();
    Set<Instruction> consumedInstructions = Sets.newIdentityHashSet();
    Set<Value> mutableValues = Sets.newIdentityHashSet();
    WorkList<Value> worklist = WorkList.newIdentityWorkList(values);
    while (worklist.hasNext()) {
      Value value = worklist.next();
      Value root = value.getAliasedValue();
      Node node = graph.createNodeIfAbsent(root);
      if (root != value) {
        // An alias depends on the environment if the aliased value depends on the environment, thus
        // an edge is added from the alias to the aliased value.
        graph.addDirectedEdge(graph.createNodeIfAbsent(value), node);
      }
      if (!addValueToValueGraph(root, node, graph, consumedInstructions, mutableValues, worklist)) {
        return true;
      }
    }

    // At this point, the graph has been populated with a node for each value of interest, and edges
    // have been added to reflect the dependency. We now attempt to prove that no values depend on
    // environment, starting from the leaves of the graph.
    //
    // First we collapse strongly connected components in the graph. By doing so we will attempt to
    // prove that all values in a strongly connected component are independent of the environment at
    // once.
    graph.mergeStronglyConnectedComponents();

    Set<Node> nodesDependentOnEnvironment = SetUtils.newIdentityHashSet(graph.getNodes());
    while (!nodesDependentOnEnvironment.isEmpty()) {
      Set<Node> newNodesIndependentOfEnvironment = Sets.newIdentityHashSet();
      for (Node node : nodesDependentOnEnvironment) {
        boolean isDependentOfEnvironment =
            node.hasSuccessorThatMatches(
                successor ->
                    nodesDependentOnEnvironment.contains(successor)
                        && !newNodesIndependentOfEnvironment.contains(successor));
        if (!isDependentOfEnvironment) {
          newNodesIndependentOfEnvironment.add(node);
        }
      }
      if (newNodesIndependentOfEnvironment.isEmpty()) {
        return true;
      }
      nodesDependentOnEnvironment.removeAll(newNodesIndependentOfEnvironment);
    }

    // At this point, we have proved that all values in the graph are independent on the
    // environment. However, we still need to prove that they are not mutated between the point
    // where they are defined and all normal exits.
    return anyValueMayBeMutatedBeforeMethodExit(mutableValues, consumedInstructions);
  }

  private boolean addValueToValueGraph(
      Value value,
      Node node,
      ValueGraph graph,
      Set<Instruction> consumedInstructions,
      Set<Value> mutableValues,
      WorkList<Value> worklist) {
    return addConstantValueToValueGraph(value)
        || addArrayValueToValueGraph(
            value, node, graph, consumedInstructions, mutableValues, worklist)
        || addNewInstanceValueToValueGraph(
            value, node, graph, consumedInstructions, mutableValues, worklist);
  }

  private boolean addConstantValueToValueGraph(Value value) {
    // Constants do not depend on any other values, thus no edges are added to the graph.
    if (value.isConstant()) {
      return true;
    }
    assert !value.getAliasedValue().isConstant();
    AbstractValue abstractValue = value.getAbstractValue(appView, context);
    if (abstractValue.isSingleConstValue()) {
      return true;
    }
    if (abstractValue.isSingleFieldValue()) {
      DexField fieldReference = abstractValue.asSingleFieldValue().getField();
      DexClass holder = appView.definitionForHolder(fieldReference);
      DexEncodedField field = fieldReference.lookupOnClass(holder);
      if (field != null && field.isEnum()) {
        return true;
      }
    }
    return false;
  }

  private boolean addArrayValueToValueGraph(
      Value value,
      Node node,
      ValueGraph graph,
      Set<Instruction> consumedInstructions,
      Set<Value> mutableValues,
      WorkList<Value> worklist) {
    if (value.isPhi()) {
      // Would need to track the aliases, just give up.
      return false;
    }

    Instruction definition = value.definition;

    // Check that it is a constant array with a known size at this point in the IR.
    if (definition.isInvokeNewArray()) {
      InvokeNewArray invokeNewArray = definition.asInvokeNewArray();
      for (Value argument : invokeNewArray.arguments()) {
        graph.addDirectedEdge(node, graph.createNodeIfAbsent(argument));
        worklist.addIfNotSeen(argument);
      }
    } else if (definition.isNewArrayEmpty()) {
      NewArrayEmpty newArrayEmpty = definition.asNewArrayEmpty();
      Value sizeValue = newArrayEmpty.size();
      graph.addDirectedEdge(node, graph.createNodeIfAbsent(sizeValue));
      worklist.addIfNotSeen(sizeValue);
    } else {
      // Some other array creation.
      return false;
    }

    // Allow array-put and new-array-filled-data instructions that immediately follow the array
    // creation.
    for (Instruction instruction : definition.getBlock().instructionsAfter(definition)) {
      if (instruction.isArrayPut()) {
        ArrayPut arrayPut = instruction.asArrayPut();
        Value array = arrayPut.array().getAliasedValue();
        if (array != value) {
          // This ends the chain of array-put instructions that are allowed immediately after the
          // array creation.
          break;
        }
        graph.addDirectedEdge(node, graph.createNodeIfAbsent(arrayPut.index()));
        worklist.addIfNotSeen(arrayPut.index());
        graph.addDirectedEdge(node, graph.createNodeIfAbsent(arrayPut.value()));
        worklist.addIfNotSeen(arrayPut.value());
      } else if (instruction.isNewArrayFilledData()) {
        NewArrayFilledData newArrayFilledData = instruction.asNewArrayFilledData();
        Value array = newArrayFilledData.src();
        if (array != value) {
          // This ends the chain of array-put instructions that are allowed immediately after the
          // array creation.
          break;
        }
        consumedInstructions.add(instruction);
      } else if (instruction.instructionMayHaveSideEffects(appView, context)) {
        // This ends the chain of array-put instructions that are allowed immediately after the
        // array creation.
        break;
      }
      consumedInstructions.add(instruction);
    }
    mutableValues.add(value);
    return true;
  }

  private boolean addNewInstanceValueToValueGraph(
      Value value,
      Node node,
      ValueGraph graph,
      Set<Instruction> consumedInstructions,
      Set<Value> mutableValues,
      WorkList<Value> worklist) {
    if (!value.isDefinedByInstructionSatisfying(Instruction::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.
    InvokeDirect constructorInvoke =
        newInstance.getUniqueConstructorInvoke(appView.dexItemFactory());
    if (constructorInvoke == null || constructorInvoke.getInvokedMethod().holder != clazz.type) {
      // Didn't find a (valid) constructor invocation, give up.
      return false;
    }

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

    InstanceInitializerInfo initializerInfo =
        constructor.getOptimizationInfo().getInstanceInitializerInfo(constructorInvoke);

    List<DexEncodedField> fields = clazz.getDirectAndIndirectInstanceFields(appView);
    if (!fields.isEmpty()) {
      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.getArgument(i);
        graph.addDirectedEdge(node, graph.createNodeIfAbsent(argument));
        worklist.addIfNotSeen(argument);
      }

      // Mark this value as mutable if it has a non-final field.
      boolean hasNonFinalField = false;
      for (DexEncodedField field : fields) {
        if (!field.isFinal()) {
          hasNonFinalField = true;
          break;
        }
      }
      if (hasNonFinalField) {
        mutableValues.add(value);
      }
    }

    if (!initializerInfo.mayHaveOtherSideEffectsThanInstanceFieldAssignments()) {
      consumedInstructions.add(constructorInvoke);
    }

    return true;
  }

  private boolean anyValueMayBeMutatedBeforeMethodExit(
      Set<Value> values, Set<Instruction> whitelist) {
    Set<BasicBlock> initialBlocks = Sets.newIdentityHashSet();
    for (Value value : values) {
      assert !value.isPhi();
      initialBlocks.add(value.definition.getBlock());
    }
    Map<BasicBlock, TrackedValuesState> blockExitStates = new IdentityHashMap<>();
    Deque<BasicBlock> worklist = new ArrayDeque<>(initialBlocks);
    while (!worklist.isEmpty()) {
      BasicBlock block = worklist.removeFirst();
      TrackedValuesState state = computeBlockEntryState(block, blockExitStates);
      boolean changed = false;
      for (Instruction instruction : block.getInstructions()) {
        if (whitelist.contains(instruction)) {
          continue;
        }
        if (instruction.isStaticPut()) {
          StaticPut staticPut = instruction.asStaticPut();
          if (state.isTrackingValue(staticPut.value())) {
            changed |= state.recordTrackedValueHasEscaped();
          }
          if (state.hasTrackedValueEscaped()) {
            DexType holder = staticPut.getField().holder;
            if (holder.classInitializationMayHaveSideEffectsInContext(appView, context)) {
              return true;
            }
          }
          continue;
        }
        if (instruction.instructionMayTriggerMethodInvocation(appView, context)) {
          if (instruction.hasInValueThatMatches(state::isTrackingValue)) {
            changed |= state.recordTrackedValueHasEscaped();
          }
          if (state.hasTrackedValueEscaped()
              && instruction.instructionMayHaveSideEffects(appView, context)) {
            return true;
          }
        }
        if (instruction.hasOutValue() && values.contains(instruction.outValue())) {
          changed |= state.startTrackingValue(instruction.outValue());
        }
      }
      blockExitStates.put(block, state);
      if (changed) {
        worklist.addAll(block.getSuccessors());
      }
    }
    return false;
  }

  private TrackedValuesState computeBlockEntryState(
      BasicBlock block, Map<BasicBlock, TrackedValuesState> states) {
    TrackedValuesState state = new TrackedValuesState();
    for (BasicBlock predecessor : block.getPredecessors()) {
      state.add(states.getOrDefault(predecessor, TrackedValuesState.empty()));
    }
    return state;
  }

  static class TrackedValuesState {

    private static final TrackedValuesState EMPTY = new TrackedValuesState();

    boolean hasTrackedValueEscaped;
    Set<Value> trackedValues = Sets.newIdentityHashSet();

    public static TrackedValuesState empty() {
      return EMPTY;
    }

    public void add(TrackedValuesState state) {
      hasTrackedValueEscaped |= state.hasTrackedValueEscaped;
      trackedValues.addAll(state.trackedValues);
    }

    public boolean hasTrackedValueEscaped() {
      return hasTrackedValueEscaped;
    }

    public boolean isTrackingValue(Value value) {
      return trackedValues.contains(value);
    }

    public boolean recordTrackedValueHasEscaped() {
      if (hasTrackedValueEscaped) {
        return false;
      }
      hasTrackedValueEscaped = true;
      return true;
    }

    public boolean startTrackingValue(Value value) {
      return trackedValues.add(value);
    }
  }
}
