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

import static com.android.tools.r8.dex.Constants.TEMPORARY_INSTANCE_INITIALIZER_PREFIX;

import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger.Mode;
import com.android.tools.r8.horizontalclassmerging.code.ConstructorEntryPointSynthesizedCode;
import com.android.tools.r8.ir.conversion.ExtraConstantIntParameter;
import com.android.tools.r8.ir.conversion.ExtraParameter;
import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.Iterables;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class InstanceInitializerMerger {

  private final AppView<?> appView;
  private final DexItemFactory dexItemFactory;
  private final MergeGroup group;
  private final List<ProgramMethod> instanceInitializers;
  private final InstanceInitializerDescription instanceInitializerDescription;
  private final Mode mode;

  InstanceInitializerMerger(
      AppView<?> appView, MergeGroup group, List<ProgramMethod> instanceInitializers, Mode mode) {
    this(appView, group, instanceInitializers, mode, null);
  }

  InstanceInitializerMerger(
      AppView<?> appView,
      MergeGroup group,
      List<ProgramMethod> instanceInitializers,
      Mode mode,
      InstanceInitializerDescription instanceInitializerDescription) {
    this.appView = appView;
    this.dexItemFactory = appView.dexItemFactory();
    this.group = group;
    this.instanceInitializers = instanceInitializers;
    this.instanceInitializerDescription = instanceInitializerDescription;
    this.mode = mode;

    // Constructors should not be empty and all constructors should have the same prototype.
    assert !instanceInitializers.isEmpty();
    assert instanceInitializers.stream().map(ProgramMethod::getProto).distinct().count() == 1;
  }

  /**
   * The method reference template describes which arguments the constructor must have, and is used
   * to generate the final reference by appending null arguments until it is fresh.
   */
  private DexMethod generateReferenceMethodTemplate() {
    DexMethod methodTemplate = instanceInitializers.iterator().next().getReference();
    if (instanceInitializers.size() > 1) {
      methodTemplate = dexItemFactory.appendTypeToMethod(methodTemplate, dexItemFactory.intType);
    }
    return methodTemplate.withHolder(group.getTarget(), dexItemFactory);
  }

  public int getArity() {
    return instanceInitializers.iterator().next().getReference().getArity();
  }

  public List<ProgramMethod> getInstanceInitializers() {
    return instanceInitializers;
  }

  public int size() {
    return instanceInitializers.size();
  }

  public static class Builder {

    private final AppView<? extends AppInfoWithClassHierarchy> appView;
    private int estimatedDexCodeSize;
    private final List<List<ProgramMethod>> instanceInitializerGroups = new ArrayList<>();
    private final Mode mode;

    public Builder(AppView<? extends AppInfoWithClassHierarchy> appView, Mode mode) {
      this.appView = appView;
      this.mode = mode;
      createNewGroup();
    }

    private void createNewGroup() {
      estimatedDexCodeSize = 0;
      instanceInitializerGroups.add(new ArrayList<>());
    }

    public Builder add(ProgramMethod instanceInitializer) {
      int estimatedMaxSizeInBytes =
          instanceInitializer.getDefinition().getCode().estimatedDexCodeSizeUpperBoundInBytes();
      // If the constructor gets too large, then the constructor should be merged into a new group.
      if (estimatedDexCodeSize + estimatedMaxSizeInBytes
              > appView.options().minimumVerificationSizeLimitInBytes() / 2
          && estimatedDexCodeSize > 0) {
        createNewGroup();
      }

      ListUtils.last(instanceInitializerGroups).add(instanceInitializer);
      estimatedDexCodeSize += estimatedMaxSizeInBytes;
      return this;
    }

    public Builder addEquivalent(ProgramMethod instanceInitializer) {
      ListUtils.last(instanceInitializerGroups).add(instanceInitializer);
      return this;
    }

    public List<InstanceInitializerMerger> build(MergeGroup group) {
      assert instanceInitializerGroups.stream().noneMatch(List::isEmpty);
      return ListUtils.map(
          instanceInitializerGroups,
          instanceInitializers ->
              new InstanceInitializerMerger(appView, group, instanceInitializers, mode));
    }

    public InstanceInitializerMerger buildSingle(
        MergeGroup group, InstanceInitializerDescription instanceInitializerDescription) {
      assert instanceInitializerGroups.stream().noneMatch(List::isEmpty);
      assert instanceInitializerGroups.size() == 1;
      List<ProgramMethod> instanceInitializers = ListUtils.first(instanceInitializerGroups);
      return new InstanceInitializerMerger(
          appView, group, instanceInitializers, mode, instanceInitializerDescription);
    }
  }

  // Returns true if we can simply use an existing constructor as the new constructor.
  private boolean isTrivialMerge(ClassMethodsBuilder classMethodsBuilder) {
    if (group.hasClassIdField()) {
      // We need to set the class id field.
      return false;
    }
    DexMethod trivialInstanceInitializerReference =
        ListUtils.first(instanceInitializers)
            .getReference()
            .withHolder(group.getTarget(), dexItemFactory);
    if (!classMethodsBuilder.isFresh(trivialInstanceInitializerReference)) {
      // We need to append null arguments for disambiguation.
      return false;
    }
    return isMergeOfEquivalentInstanceInitializers();
  }

  private boolean isMergeOfEquivalentInstanceInitializers() {
    Iterator<ProgramMethod> instanceInitializerIterator = instanceInitializers.iterator();
    ProgramMethod firstInstanceInitializer = instanceInitializerIterator.next();
    if (!instanceInitializerIterator.hasNext()) {
      return true;
    }
    // We need all the constructors to be equivalent.
    InstanceInitializerInfo instanceInitializerInfo =
        firstInstanceInitializer
            .getDefinition()
            .getOptimizationInfo()
            .getContextInsensitiveInstanceInitializerInfo();
    if (!instanceInitializerInfo.hasParent()) {
      // We don't know the parent constructor of the first constructor.
      return false;
    }
    DexMethod parent = instanceInitializerInfo.getParent();
    return Iterables.all(
        instanceInitializers,
        instanceInitializer ->
            isSideEffectFreeInstanceInitializerWithParent(instanceInitializer, parent));
  }

  private boolean isSideEffectFreeInstanceInitializerWithParent(
      ProgramMethod instanceInitializer, DexMethod parent) {
    MethodOptimizationInfo optimizationInfo =
        instanceInitializer.getDefinition().getOptimizationInfo();
    return !optimizationInfo.mayHaveSideEffects()
        && optimizationInfo.getContextInsensitiveInstanceInitializerInfo().getParent() == parent;
  }

  private DexMethod moveInstanceInitializer(
      ClassMethodsBuilder classMethodsBuilder, ProgramMethod instanceInitializer) {
    DexMethod method =
        dexItemFactory.createFreshMethodNameWithHolder(
            TEMPORARY_INSTANCE_INITIALIZER_PREFIX,
            instanceInitializer.getHolderType(),
            instanceInitializer.getProto(),
            group.getTarget().getType(),
            classMethodsBuilder::isFresh);

    DexEncodedMethod encodedMethod =
        instanceInitializer.getDefinition().toTypeSubstitutedMethod(method);
    encodedMethod.getMutableOptimizationInfo().markForceInline();
    encodedMethod.getAccessFlags().unsetConstructor();
    encodedMethod.getAccessFlags().unsetPublic();
    encodedMethod.getAccessFlags().unsetProtected();
    encodedMethod.getAccessFlags().setPrivate();
    classMethodsBuilder.addDirectMethod(encodedMethod);

    return method;
  }

  private MethodAccessFlags getAccessFlags() {
    // TODO(b/164998929): ensure this behaviour is correct, should probably calculate upper bound
    return MethodAccessFlags.fromSharedAccessFlags(
        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, true);
  }

  /** Synthesize a new method which selects the constructor based on a parameter type. */
  void merge(
      ClassMethodsBuilder classMethodsBuilder,
      HorizontalClassMergerGraphLens.Builder lensBuilder,
      Reference2IntMap<DexType> classIdentifiers,
      SyntheticArgumentClass syntheticArgumentClass) {
    // TODO(b/189296638): Handle merging of equivalent constructors when
    //  `instanceInitializerDescription` is set.
    if (isTrivialMerge(classMethodsBuilder)) {
      mergeTrivial(classMethodsBuilder, lensBuilder);
      return;
    }

    assert mode.isInitial();

    // Tree map as must be sorted.
    Int2ReferenceSortedMap<DexMethod> typeConstructorClassMap = new Int2ReferenceAVLTreeMap<>();

    // Move constructors to target class.
    CfVersion classFileVersion = null;
    for (ProgramMethod instanceInitializer : instanceInitializers) {
      if (instanceInitializer.getDefinition().hasClassFileVersion()) {
        classFileVersion =
            Ordered.maxIgnoreNull(
                classFileVersion, instanceInitializer.getDefinition().getClassFileVersion());
      }
      DexMethod movedInstanceInitializer =
          moveInstanceInitializer(classMethodsBuilder, instanceInitializer);
      lensBuilder.mapMethod(movedInstanceInitializer, movedInstanceInitializer);
      lensBuilder.recordNewMethodSignature(
          instanceInitializer.getReference(), movedInstanceInitializer);
      typeConstructorClassMap.put(
          classIdentifiers.getInt(instanceInitializer.getHolderType()), movedInstanceInitializer);
    }

    // Create merged constructor reference.
    DexMethod methodReferenceTemplate = generateReferenceMethodTemplate();
    DexMethod newConstructorReference =
        dexItemFactory.createInstanceInitializerWithFreshProto(
            methodReferenceTemplate,
            syntheticArgumentClass.getArgumentClasses(),
            classMethodsBuilder::isFresh);
    int extraNulls = newConstructorReference.getArity() - methodReferenceTemplate.getArity();

    ProgramMethod representative = ListUtils.first(instanceInitializers);
    DexMethod originalConstructorReference =
        appView.graphLens().getOriginalMethodSignature(representative.getReference());

    // Create a special original method signature for the synthesized constructor that did not exist
    // prior to horizontal class merging. Otherwise we might accidentally think that the synthesized
    // constructor corresponds to the previous <init>() method on the target class, which could have
    // unintended side-effects such as leading to unused argument removal being applied to the
    // synthesized constructor all-though it by construction doesn't have any unused arguments.
    DexMethod bridgeConstructorReference =
        dexItemFactory.createFreshMethodNameWithoutHolder(
            "$r8$init$bridge",
            originalConstructorReference.getProto(),
            originalConstructorReference.getHolderType(),
            classMethodsBuilder::isFresh);

    ConstructorEntryPointSynthesizedCode synthesizedCode =
        new ConstructorEntryPointSynthesizedCode(
            typeConstructorClassMap,
            newConstructorReference,
            group.hasClassIdField() ? group.getClassIdField() : null,
            bridgeConstructorReference);
    DexEncodedMethod newConstructor =
        new DexEncodedMethod(
            newConstructorReference,
            getAccessFlags(),
            MethodTypeSignature.noSignature(),
            DexAnnotationSet.empty(),
            ParameterAnnotationsList.empty(),
            synthesizedCode,
            true,
            classFileVersion);

    // Map each old constructor to the newly synthesized constructor in the graph lens.
    for (ProgramMethod oldInstanceInitializer : instanceInitializers) {
      List<ExtraParameter> extraParameters = new ArrayList<>();
      if (instanceInitializers.size() > 1) {
        int classIdentifier = classIdentifiers.getInt(oldInstanceInitializer.getHolderType());
        extraParameters.add(new ExtraConstantIntParameter(classIdentifier));
      }
      extraParameters.addAll(Collections.nCopies(extraNulls, new ExtraUnusedNullParameter()));
      lensBuilder.mapMergedConstructor(
          oldInstanceInitializer.getReference(), newConstructorReference, extraParameters);
    }

    // Add a mapping from a synthetic name to the synthetic constructor.
    lensBuilder.recordNewMethodSignature(bridgeConstructorReference, newConstructorReference);

    classMethodsBuilder.addDirectMethod(newConstructor);
  }

  private void mergeTrivial(
      ClassMethodsBuilder classMethodsBuilder, HorizontalClassMergerGraphLens.Builder lensBuilder) {
    ProgramMethod representative = ListUtils.first(instanceInitializers);
    DexMethod newMethodReference =
        representative.getReference().withHolder(group.getTarget(), dexItemFactory);
    lensBuilder.moveMethods(instanceInitializers, newMethodReference, representative);

    DexEncodedMethod newMethod =
        representative.getHolder() == group.getTarget()
            ? representative.getDefinition()
            : representative.getDefinition().toTypeSubstitutedMethod(newMethodReference);
    fixupAccessFlagsForTrivialMerge(newMethod.getAccessFlags());

    classMethodsBuilder.addDirectMethod(newMethod);
  }

  private void fixupAccessFlagsForTrivialMerge(MethodAccessFlags accessFlags) {
    if (!accessFlags.isPublic()) {
      accessFlags.unsetPrivate();
      accessFlags.unsetProtected();
      accessFlags.setPublic();
    }
  }
}
