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

import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.ir.optimize.info.OptimizationFeedback.getSimpleFeedback;
import static com.android.tools.r8.shaking.ObjectAllocationInfoCollectionUtils.mayHaveFinalizeMethodDirectlyOrIndirectly;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;

import com.android.tools.r8.code.CfOrDexInstanceFieldRead;
import com.android.tools.r8.code.CfOrDexStaticFieldRead;
import com.android.tools.r8.graph.AbstractAccessContexts;
import com.android.tools.r8.graph.AbstractAccessContexts.ConcreteAccessContexts;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClassAndField;
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.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeInstructionMetadata;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.ReferenceTypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.conversion.PostMethodProcessor;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackDelayed;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.Sets;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

public class TrivialFieldAccessReprocessor {

  enum FieldClassification {
    CONSTANT,
    NON_CONSTANT,
    UNKNOWN
  }

  private final AppView<AppInfoWithLiveness> appView;
  private final PostMethodProcessor.Builder postMethodProcessorBuilder;

  private final Map<DexEncodedField, ProgramMethodSet> dependencies = new ConcurrentHashMap<>();

  /** Updated concurrently from {@link #processClass(DexProgramClass)}. */
  private final Map<DexEncodedField, AbstractAccessContexts> readFields = new ConcurrentHashMap<>();

  /** Updated concurrently from {@link #processClass(DexProgramClass)}. */
  private final Map<DexEncodedField, AbstractAccessContexts> writtenFields =
      new ConcurrentHashMap<>();

  /** Updated concurrently from {@link #processClass(DexProgramClass)}. */
  private final Set<DexEncodedField> constantFields = Sets.newConcurrentHashSet();

  /** Updated concurrently from {@link #processClass(DexProgramClass)}. */
  private final Set<DexEncodedField> nonConstantFields = Sets.newConcurrentHashSet();

  /** Updated concurrently from {@link #processClass(DexProgramClass)}. */
  private final ProgramMethodSet methodsToReprocess = ProgramMethodSet.createConcurrent();

  public TrivialFieldAccessReprocessor(
      AppView<AppInfoWithLiveness> appView,
      PostMethodProcessor.Builder postMethodProcessorBuilder) {
    this.appView = appView;
    this.postMethodProcessorBuilder = postMethodProcessorBuilder;
  }

  public void run(
      ExecutorService executorService, OptimizationFeedbackDelayed feedback, Timing timing)
      throws ExecutionException {
    AppInfoWithLiveness appInfo = appView.appInfo();

    timing.begin("Trivial field accesses analysis");
    assert feedback.noUpdatesLeft();

    timing.begin("Compute fields of interest");
    computeFieldsWithNonTrivialValue();
    timing.end(); // Compute fields of interest

    timing.begin("Enqueue methods for reprocessing");
    enqueueMethodsForReprocessing(appInfo, executorService);
    timing.end(); // Enqueue methods for reprocessing

    timing.begin("Clear reads and writes from fields of interest");
    clearReadsAndWritesFromFieldsOfInterest(appInfo);
    timing.end(); // Clear reads from fields of interest
    timing.end(); // Trivial field accesses analysis

    constantFields.forEach(this::markFieldAsDead);
    readFields.keySet().forEach(this::markFieldAsDead);
    writtenFields.keySet().forEach(this::markWriteOnlyFieldAsDead);

    // Ensure determinism of method-to-reprocess set.
    appView.testing().checkDeterminism(postMethodProcessorBuilder::dump);
  }

  private void markWriteOnlyFieldAsDead(DexEncodedField field) {
    markFieldAsDead(field);
    getSimpleFeedback()
        .recordFieldHasAbstractValue(
            field, appView, appView.abstractValueFactory().createNullValue());
  }

  private void markFieldAsDead(DexEncodedField field) {
    // Don't mark pinned fields as dead, since they need to remain in the app even if all reads and
    // writes are removed.
    if (appView.appInfo().isPinned(field)) {
      assert field.getType().isAlwaysNull(appView);
    } else {
      getSimpleFeedback().markFieldAsDead(field);
    }
  }

  private void computeFieldsWithNonTrivialValue() {
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      for (DexEncodedField field : clazz.instanceFields()) {
        FieldClassification fieldClassification = classifyField(field, appView);
        switch (fieldClassification) {
          case CONSTANT:
            // Reprocess reads and writes.
            constantFields.add(field);
            break;
          case NON_CONSTANT:
            // Only reprocess writes, to allow branch pruning.
            nonConstantFields.add(field);
            break;
          default:
            assert fieldClassification == FieldClassification.UNKNOWN;
            break;
        }
      }
      if (appView.canUseInitClass() || !clazz.classInitializationMayHaveSideEffects(appView)) {
        for (DexEncodedField field : clazz.staticFields()) {
          FieldClassification fieldClassification = classifyField(field, appView);
          if (fieldClassification == FieldClassification.CONSTANT) {
            constantFields.add(field);
          } else {
            assert fieldClassification == FieldClassification.NON_CONSTANT
                || fieldClassification == FieldClassification.UNKNOWN;
          }
        }
      }
    }
    assert verifyNoConstantFieldsOnSynthesizedClasses(appView);
  }

  private void clearReadsAndWritesFromFieldsOfInterest(AppInfoWithLiveness appInfo) {
    FieldAccessInfoCollection<?> fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
    for (DexEncodedField field : constantFields) {
      fieldAccessInfoCollection.get(field.getReference()).asMutable().clearReads();
    }
    for (DexEncodedField field : readFields.keySet()) {
      fieldAccessInfoCollection.get(field.getReference()).asMutable().clearWrites();
    }
    for (DexEncodedField field : writtenFields.keySet()) {
      fieldAccessInfoCollection.get(field.getReference()).asMutable().clearReads();
    }
  }

  private void enqueueMethodsForReprocessing(
      AppInfoWithLiveness appInfo, ExecutorService executorService) throws ExecutionException {
    ThreadUtils.processItems(appInfo.classes(), this::processClass, executorService);
    ThreadUtils.processItems(
        appInfo.getSyntheticItems().getPendingSyntheticClasses(),
        this::processClass,
        executorService);
    processFieldsNeverRead(appInfo);
    processFieldsNeverWritten(appInfo);
    postMethodProcessorBuilder.rewrittenWithLens(appView.graphLens()).put(methodsToReprocess);
  }

  private void processClass(DexProgramClass clazz) {
    clazz.forEachProgramMethodMatching(
        DexEncodedMethod::hasCode,
        method -> method.registerCodeReferences(new TrivialFieldAccessUseRegistry(method)));
  }

  private static FieldClassification classifyField(
      DexEncodedField field, AppView<AppInfoWithLiveness> appView) {
    FieldAccessInfo fieldAccessInfo =
        appView.appInfo().getFieldAccessInfoCollection().get(field.getReference());
    if (fieldAccessInfo == null
        || fieldAccessInfo.hasReflectiveAccess()
        || fieldAccessInfo.isAccessedFromMethodHandle()
        || fieldAccessInfo.isReadFromAnnotation()) {
      return FieldClassification.UNKNOWN;
    }
    AbstractValue abstractValue = field.getOptimizationInfo().getAbstractValue();
    if (abstractValue.isSingleValue()) {
      SingleValue singleValue = abstractValue.asSingleValue();
      if (!singleValue.isMaterializableInAllContexts(appView)) {
        return FieldClassification.UNKNOWN;
      }
      if (singleValue.isSingleConstValue()) {
        return FieldClassification.CONSTANT;
      }
      if (singleValue.isSingleFieldValue()) {
        SingleFieldValue singleFieldValue = singleValue.asSingleFieldValue();
        DexField singleField = singleFieldValue.getField();
        if (singleField != field.getReference()
            && !singleFieldValue.mayHaveFinalizeMethodDirectlyOrIndirectly(appView)) {
          return FieldClassification.CONSTANT;
        }
      }
      return FieldClassification.UNKNOWN;
    }
    if (abstractValue.isNonConstantNumberValue()) {
      return FieldClassification.NON_CONSTANT;
    }
    return FieldClassification.UNKNOWN;
  }

  private void processFieldsNeverRead(AppInfoWithLiveness appInfo) {
    FieldAccessInfoCollection<?> fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
    writtenFields
        .entrySet()
        .removeIf(
            entry ->
                !entry.getValue().isConcrete()
                    || !canOptimizeOnlyReadOrWrittenField(
                        entry.getKey(), true, fieldAccessInfoCollection));
    writtenFields.forEach(
        (field, contexts) -> {
          assert !readFields.containsKey(field);
          fieldAccessInfoCollection.get(field.getReference()).asMutable().clearReads();
          methodsToReprocess.addAll(
              contexts.asConcrete().getAccessesWithContexts().values().iterator().next());
          methodsToReprocess.addAll(dependencies.getOrDefault(field, ProgramMethodSet.empty()));
        });
  }

  private void processFieldsNeverWritten(AppInfoWithLiveness appInfo) {
    FieldAccessInfoCollection<?> fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
    readFields
        .entrySet()
        .removeIf(
            entry ->
                !entry.getValue().isConcrete()
                    || !canOptimizeOnlyReadOrWrittenField(
                        entry.getKey(), false, fieldAccessInfoCollection));
    readFields.forEach(
        (field, contexts) -> {
          assert !writtenFields.containsKey(field);
          methodsToReprocess.addAll(
              contexts.asConcrete().getAccessesWithContexts().values().iterator().next());
          methodsToReprocess.addAll(dependencies.getOrDefault(field, ProgramMethodSet.empty()));
        });
  }

  private boolean canOptimizeOnlyReadOrWrittenField(
      DexEncodedField field,
      boolean isWrite,
      FieldAccessInfoCollection<?> fieldAccessInfoCollection) {
    assert !appView.appInfo().isPinned(field) || field.getType().isAlwaysNull(appView);

    FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(field.getReference());
    if (fieldAccessInfo == null) {
      assert false
          : "Expected program field with concrete accesses to be present in field access "
              + "collection";
      return false;
    }

    if (fieldAccessInfo.hasReflectiveAccess()
        || fieldAccessInfo.isAccessedFromMethodHandle()
        || fieldAccessInfo.isReadFromRecordInvokeDynamic()
        || fieldAccessInfo.isReadFromAnnotation()) {
      return false;
    }

    if (isWrite && field.getType().isReferenceType()) {
      ReferenceTypeElement fieldType = field.getTypeElement(appView).asReferenceType();
      ClassTypeElement classType =
          (fieldType.isArrayType() ? fieldType.asArrayType().getBaseType() : fieldType)
              .asClassType();
      if (classType != null && mayHaveFinalizeMethodDirectlyOrIndirectly(appView, classType)) {
        return false;
      }
    }

    return true;
  }

  private static boolean verifyNoConstantFieldsOnSynthesizedClasses(
      AppView<AppInfoWithLiveness> appView) {
    for (DexProgramClass clazz :
        appView.appInfo().getSyntheticItems().getPendingSyntheticClasses()) {
      for (DexEncodedField field : clazz.fields()) {
        assert field.getOptimizationInfo().getAbstractValue().isUnknown();
      }
    }
    return true;
  }

  class TrivialFieldAccessUseRegistry extends UseRegistry<ProgramMethod> {

    TrivialFieldAccessUseRegistry(ProgramMethod method) {
      super(appView, method);
    }

    private void registerFieldAccess(
        DexField reference,
        boolean isStatic,
        boolean isWrite,
        BytecodeInstructionMetadata metadata) {
      FieldResolutionResult resolutionResult = appView.appInfo().resolveField(reference);
      if (!resolutionResult.hasProgramResult()) {
        // We don't care about field accesses that may not resolve to a program field.
        return;
      }

      ProgramField field = resolutionResult.getProgramField();
      DexEncodedField definition = field.getDefinition();

      if (definition.isStatic() != isStatic
          || appView.isCfByteCodePassThrough(getContext().getDefinition())
          || resolutionResult.isAccessibleFrom(getContext(), appView).isPossiblyFalse()
          || !resolutionResult.isSingleProgramFieldResolutionResult()
          || appView.appInfo().isNeverReprocessMethod(getContext())) {
        recordAccessThatCannotBeOptimized(field, definition);
        return;
      }

      if (metadata != null) {
        if (isUnusedReadAfterMethodStaticizing(field, metadata)) {
          // Ignore this read.
          dependencies
              .computeIfAbsent(field.getDefinition(), ignoreKey(ProgramMethodSet::createConcurrent))
              .add(getContext());
          return;
        }
        if (metadata.isReadForWrite()) {
          // Ignore this read. If the field ends up only being written, then we will still reprocess
          // the method with the read-for-write instruction, since the method contains a write that
          // requires reprocessing.
          return;
        }
      }

      // Record access.
      if (field.isProgramField() && appView.appInfo().mayPropagateValueFor(appView, field)) {
        if (field.getAccessFlags().isStatic() == isStatic) {
          if (isWrite) {
            recordFieldAccessContext(definition, writtenFields, readFields);
          } else {
            recordFieldAccessContext(definition, readFields, writtenFields);
          }
        } else {
          destroyFieldAccessContexts(definition);
        }
      }

      if (constantFields.contains(definition)
          || (!isWrite && nonConstantFields.contains(definition))) {
        methodsToReprocess.add(getContext());
      }
    }

    private boolean isUnusedReadAfterMethodStaticizing(
        DexClassAndField field, BytecodeInstructionMetadata metadata) {
      if (!metadata.isReadForInvokeReceiver()
          || field.getOptimizationInfo().getDynamicType().getNullability().isMaybeNull()) {
        return false;
      }
      Set<DexMethod> readForInvokeReceiver = metadata.getReadForInvokeReceiver();
      for (DexMethod methodReference : readForInvokeReceiver) {
        DexMethod rewrittenMethodReference =
            appView.graphLens().getRenamedMethodSignature(methodReference, appView.codeLens());
        DexProgramClass holder =
            asProgramClassOrNull(appView.definitionFor(rewrittenMethodReference.getHolderType()));
        ProgramMethod method = rewrittenMethodReference.lookupOnProgramClass(holder);
        if (method == null) {
          assert false;
          return false;
        }
        if (!method.getDefinition().isStatic()) {
          return false;
        }
      }
      return true;
    }

    private void recordAccessThatCannotBeOptimized(
        DexClassAndField field, DexEncodedField definition) {
      constantFields.remove(definition);
      if (field.isProgramField() && appView.appInfo().mayPropagateValueFor(appView, field)) {
        destroyFieldAccessContexts(definition);
      }
    }

    private void recordFieldAccessContext(
        DexEncodedField field,
        Map<DexEncodedField, AbstractAccessContexts> fieldAccesses,
        Map<DexEncodedField, AbstractAccessContexts> otherFieldAccesses) {
      synchronized (field) {
        AbstractAccessContexts otherAccessContexts =
            otherFieldAccesses.getOrDefault(field, AbstractAccessContexts.empty());
        if (otherAccessContexts.isBottom()) {
          // Only read or written.
          AbstractAccessContexts accessContexts =
              fieldAccesses.computeIfAbsent(field, ignore -> new ConcreteAccessContexts());
          assert accessContexts.isConcrete();
          accessContexts.asConcrete().recordAccess(field.getReference(), getContext());
        } else if (!otherAccessContexts.isTop()) {
          // Now both read and written.
          fieldAccesses.put(field, AbstractAccessContexts.unknown());
          otherFieldAccesses.put(field, AbstractAccessContexts.unknown());
        } else {
          // Already read and written.
          assert fieldAccesses.getOrDefault(field, AbstractAccessContexts.empty()).isTop();
          assert otherFieldAccesses.getOrDefault(field, AbstractAccessContexts.empty()).isTop();
        }
      }
    }

    private void destroyFieldAccessContexts(DexEncodedField field) {
      synchronized (field) {
        readFields.put(field, AbstractAccessContexts.unknown());
        writtenFields.put(field, AbstractAccessContexts.unknown());
      }
    }

    @Override
    public void registerInstanceFieldRead(DexField field) {
      registerFieldAccess(field, false, false, BytecodeInstructionMetadata.none());
    }

    @Override
    public void registerInstanceFieldReadInstruction(CfOrDexInstanceFieldRead instruction) {
      BytecodeInstructionMetadata metadata =
          getContext().getDefinition().getCode().getMetadata(instruction);
      registerFieldAccess(instruction.getField(), false, false, metadata);
    }

    @Override
    public void registerInstanceFieldWrite(DexField field) {
      registerFieldAccess(field, false, true, null);
    }

    @Override
    public void registerStaticFieldRead(DexField field) {
      registerFieldAccess(field, true, false, BytecodeInstructionMetadata.none());
    }

    @Override
    public void registerStaticFieldReadInstruction(CfOrDexStaticFieldRead instruction) {
      BytecodeInstructionMetadata metadata =
          getContext().getDefinition().getCode().getMetadata(instruction);
      registerFieldAccess(instruction.getField(), true, false, metadata);
    }

    @Override
    public void registerStaticFieldWrite(DexField field) {
      registerFieldAccess(field, true, true, null);
    }

    @Override
    public void registerInitClass(DexType clazz) {}

    @Override
    public void registerInvokeVirtual(DexMethod method) {}

    @Override
    public void registerInvokeDirect(DexMethod method) {}

    @Override
    public void registerInvokeStatic(DexMethod method) {}

    @Override
    public void registerInvokeInterface(DexMethod method) {}

    @Override
    public void registerInvokeSuper(DexMethod method) {}

    @Override
    public void registerNewInstance(DexType type) {}

    @Override
    public void registerTypeReference(DexType type) {}

    @Override
    public void registerInstanceOf(DexType type) {}
  }
}
