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

import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfLoad;
import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.dex.CodeToKeep;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.dex.code.DexInvokeDirect;
import com.android.tools.r8.dex.code.DexReturnVoid;
import com.android.tools.r8.graph.DexCode.Try;
import com.android.tools.r8.graph.DexCode.TryHandler;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.lens.MethodLookupResult;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.ThrowingMethodConversionOptions;
import com.android.tools.r8.ir.conversion.SyntheticStraightLineSourceCode;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.IteratorUtils;
import com.android.tools.r8.utils.RetracerForCodePrinting;
import com.android.tools.r8.utils.structural.HashingVisitor;
import com.google.common.collect.ImmutableList;
import java.nio.ShortBuffer;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
 * A piece of code on the form:
 *
 * <pre>
 *   aload_0
 *   invoke-special LSuperClass;-><init>()V
 *   return
 * </pre>
 *
 * <p>Note that (i) {@code SuperClass} may be different from {@link java.lang.Object} and (ii) the
 * method holding this code object may have a non-empty proto.
 */
public class DefaultInstanceInitializerCode extends Code
    implements CfWritableCode, DexWritableCode {

  private static final DefaultInstanceInitializerCode INSTANCE =
      new DefaultInstanceInitializerCode();

  private DefaultInstanceInitializerCode() {}

  public static DefaultInstanceInitializerCode get() {
    return INSTANCE;
  }

  public static boolean canonicalizeCodeIfPossible(AppView<?> appView, ProgramMethod method) {
    if (hasDefaultInstanceInitializerCode(method, appView)) {
      method.setCode(get(), appView);
      return true;
    }
    return false;
  }

  public static void uncanonicalizeCode(AppView<?> appView, ProgramMethod method) {
    uncanonicalizeCode(appView, method, method.getHolder().getSuperType());
  }

  public static void uncanonicalizeCode(
      AppView<?> appView, ProgramMethod method, DexType superType) {
    DexEncodedMethod definition = method.getDefinition();
    assert definition.getCode().isDefaultInstanceInitializerCode();
    method.setCode(get().toCfCode(method, appView.dexItemFactory(), superType), appView);
  }

  private static boolean hasDefaultInstanceInitializerCode(
      ProgramMethod method, AppView<?> appView) {
    if (!method.getDefinition().isInstanceInitializer()) {
      return false;
    }
    Code code = method.getDefinition().getCode();
    if (!code.isCfCode()) {
      return false;
    }
    CfCode cfCode = code.asCfCode();
    if (!method.getDefinition().isInstanceInitializer()
        || !cfCode.getLocalVariables().isEmpty()
        || !cfCode.getTryCatchRanges().isEmpty()) {
      return false;
    }
    if (cfCode.getInstructions().size() > 6) {
      // Default instance initializers typically have the following instruction sequence:
      // [CfLabel, CfPosition, CfLoad, CfInvoke, CfReturnVoid, CfLabel].
      return false;
    }
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    Iterator<CfInstruction> instructionIterator = cfCode.getInstructions().iterator();
    // Allow skipping CfPosition instructions in instance initializers that only call Object.<init>.
    Predicate<CfInstruction> instructionOfInterest =
        method.getHolder().getSuperType() == dexItemFactory.objectType
            ? instruction -> !instruction.isLabel() && !instruction.isPosition()
            : instruction -> !instruction.isLabel();
    CfLoad load = IteratorUtils.nextUntil(instructionIterator, instructionOfInterest).asLoad();
    if (load == null || load.getLocalIndex() != 0) {
      return false;
    }
    CfInvoke invoke = instructionIterator.next().asInvoke();
    if (invoke == null
        || !invoke.isInvokeConstructor(dexItemFactory)
        || invoke.getMethod() != getParentConstructor(method, dexItemFactory)) {
      return false;
    }
    return instructionIterator.next().isReturnVoid();
  }

  @Override
  public Code asCode() {
    return this;
  }

  @Override
  public void acceptHashing(HashingVisitor visitor) {
    visitor.visitInt(getCfWritableCodeKind().hashCode());
  }

  @Override
  public IRCode buildIR(
      ProgramMethod method,
      AppView<?> appView,
      Origin origin,
      MutableMethodConversionOptions conversionOptions) {
    DexMethod originalMethod =
        appView.graphLens().getOriginalMethodSignature(method.getReference());
    DefaultInstanceInitializerSourceCode source =
        new DefaultInstanceInitializerSourceCode(originalMethod);
    return IRBuilder.create(method, appView, source, origin).build(method, conversionOptions);
  }

  @Override
  public IRCode buildInliningIR(
      ProgramMethod context,
      ProgramMethod method,
      AppView<?> appView,
      GraphLens codeLens,
      NumberGenerator valueNumberGenerator,
      Position callerPosition,
      Origin origin,
      RewrittenPrototypeDescription protoChanges) {
    DexMethod originalMethod =
        appView.graphLens().getOriginalMethodSignature(method.getReference());
    DefaultInstanceInitializerSourceCode source =
        new DefaultInstanceInitializerSourceCode(originalMethod, callerPosition);
    return IRBuilder.createForInlining(
            method, appView, codeLens, source, origin, valueNumberGenerator, protoChanges)
        .build(context, new ThrowingMethodConversionOptions(appView.options()));
  }

  @Override
  public int codeSizeInBytes() {
    return DexInvokeDirect.SIZE + DexReturnVoid.SIZE;
  }

  @Override
  public void collectIndexedItems(
      AppView<?> appView,
      IndexedItemCollection indexedItems,
      ProgramMethod context,
      LensCodeRewriterUtils rewriter) {
    DexMethod parentConstructor = getParentConstructor(context, rewriter.dexItemFactory());
    MethodLookupResult lookupResult =
        appView.graphLens().lookupInvokeDirect(parentConstructor, context);
    lookupResult.getReference().collectIndexedItems(appView, indexedItems);
  }

  @Override
  public void collectMixedSectionItems(MixedSectionCollection mixedItems) {
    // Intentionally empty.
  }

  @Override
  protected int computeHashCode() {
    return System.identityHashCode(this);
  }

  @Override
  protected boolean computeEquals(Object other) {
    return this == other;
  }

  @Override
  public int estimatedDexCodeSizeUpperBoundInBytes() {
    return codeSizeInBytes();
  }

  @Override
  public CfWritableCodeKind getCfWritableCodeKind() {
    return CfWritableCodeKind.DEFAULT_INSTANCE_INITIALIZER;
  }

  @Override
  public DexWritableCodeKind getDexWritableCodeKind() {
    return DexWritableCodeKind.DEFAULT_INSTANCE_INITIALIZER;
  }

  @Override
  public DexDebugInfoForWriting getDebugInfoForWriting() {
    return null;
  }

  @Override
  public TryHandler[] getHandlers() {
    return new TryHandler[0];
  }

  @Override
  public DexString getHighestSortingString() {
    return null;
  }

  @Override
  public int getIncomingRegisterSize(ProgramMethod method) {
    return getMaxLocals(method);
  }

  public static DexMethod getParentConstructor(
      DexClassAndMethod method, DexItemFactory dexItemFactory) {
    return dexItemFactory.createInstanceInitializer(method.getHolder().getSuperType());
  }

  private int getMaxLocals(ProgramMethod method) {
    int maxLocals = method.getAccessFlags().isStatic() ? 0 : 1;
    for (DexType parameter : method.getParameters()) {
      maxLocals += parameter.getRequiredRegisters();
    }
    return maxLocals;
  }

  private int getMaxStack() {
    return 1;
  }

  @Override
  public int getOutgoingRegisterSize() {
    return 1;
  }

  @Override
  public int getRegisterSize(ProgramMethod method) {
    return getIncomingRegisterSize(method);
  }

  @Override
  public Try[] getTries() {
    return new Try[0];
  }

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

  @Override
  public CfWritableCode asCfWritableCode() {
    return this;
  }

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

  @Override
  public DexWritableCode asDexWritableCode() {
    return this;
  }

  @Override
  public boolean isEmptyVoidMethod() {
    return false;
  }

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

  @Override
  public DefaultInstanceInitializerCode asDefaultInstanceInitializerCode() {
    return this;
  }

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

  @Override
  public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
    internalRegisterCodeReferences(method, registry);
  }

  @Override
  public void registerCodeReferencesForDesugaring(ClasspathMethod method, UseRegistry registry) {
    internalRegisterCodeReferences(method, registry);
  }

  private void internalRegisterCodeReferences(DexClassAndMethod method, UseRegistry<?> registry) {
    registry.registerInvokeDirect(getParentConstructor(method, registry.dexItemFactory()));
  }

  @Override
  public DexWritableCode rewriteCodeWithJumboStrings(
      ProgramMethod method, ObjectToOffsetMapping mapping, DexItemFactory factory, boolean force) {
    // Intentionally empty. This piece of code does not have any const-string instructions.
    return this;
  }

  @Override
  public void setCallSiteContexts(ProgramMethod method) {
    // Intentionally empty. This piece of code does not have any call sites.
  }

  public CfCode toCfCode(ProgramMethod method, DexItemFactory dexItemFactory) {
    return toCfCode(method, dexItemFactory, method.getHolder().getSuperType());
  }

  public CfCode toCfCode(ProgramMethod method, DexItemFactory dexItemFactory, DexType supertype) {
    List<CfInstruction> instructions =
        Arrays.asList(
            new CfLoad(ValueType.OBJECT, 0),
            new CfInvoke(
                Opcodes.INVOKESPECIAL, dexItemFactory.createInstanceInitializer(supertype), false),
            new CfReturnVoid());
    return new CfCode(method.getHolderType(), getMaxStack(), getMaxLocals(method), instructions);
  }

  @Override
  public void writeCf(
      ProgramMethod method,
      CfVersion classFileVersion,
      AppView<?> appView,
      NamingLens namingLens,
      LensCodeRewriterUtils rewriter,
      MethodVisitor visitor) {
    visitor.visitVarInsn(Opcodes.ALOAD, 0);
    visitor.visitMethodInsn(
        Opcodes.INVOKESPECIAL,
        namingLens.lookupInternalName(method.getHolder().getSuperType()),
        "<init>",
        "()V",
        false);
    visitor.visitInsn(Opcodes.RETURN);
    visitor.visitEnd();
    visitor.visitMaxs(getMaxStack(), getMaxLocals(method));
  }

  @Override
  public void writeDex(
      ShortBuffer shortBuffer,
      ProgramMethod context,
      GraphLens graphLens,
      GraphLens codeLens,
      LensCodeRewriterUtils lensCodeRewriter,
      ObjectToOffsetMapping mapping) {
    DexMethod parentConstructor = getParentConstructor(context, mapping.dexItemFactory());
    MethodLookupResult lookupResult = graphLens.lookupInvokeDirect(parentConstructor, context);
    new DexInvokeDirect(1, lookupResult.getReference(), 0, 0, 0, 0, 0)
        .write(shortBuffer, context, graphLens, codeLens, mapping, lensCodeRewriter);
    new DexReturnVoid().write(shortBuffer, context, graphLens, codeLens, mapping, lensCodeRewriter);
  }

  @Override
  public void writeKeepRulesForDesugaredLibrary(CodeToKeep codeToKeep) {
    // Intentionally empty.
  }

  @Override
  public String toString() {
    return "DefaultInstanceInitializerCode";
  }

  @Override
  public String toString(DexEncodedMethod method, RetracerForCodePrinting retracer) {
    return toString();
  }

  @Override
  public DexWritableCacheKey getCacheLookupKey(ProgramMethod method, DexItemFactory factory) {
    return new AmendedDexWritableCodeKey<DexMethod>(
        this,
        getParentConstructor(method, factory),
        getIncomingRegisterSize(method),
        getRegisterSize(method));
  }

  static class DefaultInstanceInitializerSourceCode extends SyntheticStraightLineSourceCode {

    DefaultInstanceInitializerSourceCode(DexMethod method) {
      this(method, null);
    }

    DefaultInstanceInitializerSourceCode(DexMethod method, Position callerPosition) {
      super(
          getInstructionBuilders(),
          SyntheticPosition.builder()
              .setLine(0)
              .setMethod(method)
              .setCallerPosition(callerPosition)
              .build());
    }

    private static List<Consumer<IRBuilder>> getInstructionBuilders() {
      return ImmutableList.of(
          builder ->
              builder.add(
                  com.android.tools.r8.ir.code.InvokeDirect.builder()
                      .setMethod(
                          getParentConstructor(
                              builder.getProgramMethod(), builder.dexItemFactory()))
                      .setSingleArgument(builder.getReceiverValue())
                      .build()),
          IRBuilder::addReturn);
    }
  }
}
