// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.android.desugar;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.devtools.build.android.desugar.langmodel.ClassName.IN_PROCESS_LABEL_STRIPPER;
import static java.lang.invoke.MethodHandles.publicLookup;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.android.desugar.io.BitFlags;
import com.google.devtools.build.android.desugar.langmodel.ClassAttributeRecord;
import com.google.devtools.build.android.desugar.langmodel.ClassName;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TypeInsnNode;

/**
 * Visitor that desugars classes with uses of lambdas into Java 7-looking code. This includes
 * rewriting lambda-related invokedynamic instructions as well as fixing accessibility of methods
 * that javac emits for lambda bodies.
 *
 * <p>Implementation note: {@link InvokeDynamicLambdaMethodCollector} needs to detect any class that
 * this visitor may rewrite, as we conditionally apply this visitor based on it.
 */
class LambdaDesugaring extends ClassVisitor {

  private final ClassLoader targetLoader;
  private final LambdaClassMaker lambdas;
  private final ImmutableSet.Builder<String> aggregateInterfaceLambdaMethods;
  private final Map<Handle, MethodReferenceBridgeInfo> bridgeMethods = new LinkedHashMap<>();
  private final ImmutableSet<MethodInfo> lambdaMethodsUsedInInvokeDyanmic;
  private final ClassAttributeRecord classAttributeRecord;
  private final boolean allowDefaultMethods;

  private String internalName;
  private boolean isInterface;
  private int lambdaCount;

  public LambdaDesugaring(
      ClassVisitor dest,
      ClassLoader targetLoader,
      LambdaClassMaker lambdas,
      ImmutableSet.Builder<String> aggregateInterfaceLambdaMethods,
      ImmutableSet<MethodInfo> lambdaMethodsUsedInInvokeDyanmic,
      ClassAttributeRecord classAttributeRecord,
      boolean allowDefaultMethods) {
    super(Opcodes.ASM8, dest);
    this.targetLoader = targetLoader;
    this.lambdas = lambdas;
    this.aggregateInterfaceLambdaMethods = aggregateInterfaceLambdaMethods;
    this.lambdaMethodsUsedInInvokeDyanmic = lambdaMethodsUsedInInvokeDyanmic;
    this.classAttributeRecord = classAttributeRecord;
    this.allowDefaultMethods = allowDefaultMethods;
  }

  @Override
  public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    checkState(internalName == null, "not intended for reuse but reused for %s", name);
    internalName = name;
    isInterface = BitFlags.isSet(access, Opcodes.ACC_INTERFACE);
    super.visit(version, access, name, signature, superName, interfaces);
  }

  @Override
  public void visitEnd() {
    for (Map.Entry<Handle, MethodReferenceBridgeInfo> bridge : bridgeMethods.entrySet()) {
      Handle original = bridge.getKey();
      Handle neededMethod = bridge.getValue().bridgeMethod();
      checkState(
          neededMethod.getTag() == Opcodes.H_INVOKESTATIC
              || neededMethod.getTag() == Opcodes.H_INVOKEVIRTUAL,
          "Cannot generate bridge method %s to reach %s",
          neededMethod,
          original);
      checkState(
          bridge.getValue().referenced() != null,
          "Need referenced method %s to generate bridge %s",
          original,
          neededMethod);

      int access = Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_FINAL;
      if (neededMethod.getTag() == Opcodes.H_INVOKESTATIC) {
        access |= Opcodes.ACC_STATIC;
      }
      MethodVisitor bridgeMethod =
          super.visitMethod(
              access,
              neededMethod.getName(),
              neededMethod.getDesc(),
              (String) null,
              toInternalNames(bridge.getValue().referenced().getExceptionTypes()));

      // Bridge is a factory method calling a constructor
      if (original.getTag() == Opcodes.H_NEWINVOKESPECIAL) {
        bridgeMethod.visitTypeInsn(Opcodes.NEW, original.getOwner());
        bridgeMethod.visitInsn(Opcodes.DUP);
      }

      int slot = 0;
      if (neededMethod.getTag() != Opcodes.H_INVOKESTATIC) {
        bridgeMethod.visitVarInsn(Opcodes.ALOAD, slot++);
      }
      Type neededType = Type.getMethodType(neededMethod.getDesc());
      for (Type arg : neededType.getArgumentTypes()) {
        bridgeMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
        slot += arg.getSize();
      }
      bridgeMethod.visitMethodInsn(
          invokeOpcode(original),
          original.getOwner(),
          original.getName(),
          original.getDesc(),
          original.isInterface());
      bridgeMethod.visitInsn(neededType.getReturnType().getOpcode(Opcodes.IRETURN));

      bridgeMethod.visitMaxs(0, 0); // rely on class writer to compute these
      bridgeMethod.visitEnd();
    }
    super.visitEnd();
  }

  // If this method changes then InvokeDynamicLambdaMethodCollector may need changes well
  @Override
  public MethodVisitor visitMethod(
      int access, String name, String desc, String signature, String[] exceptions) {
    if (name.equals("$deserializeLambda$") && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC)) {
      // Android doesn't do anything special for lambda serialization so drop the special
      // deserialization hook that javac generates.  This also makes sure we don't reference
      // java/lang/invoke/SerializedLambda, which doesn't exist on Android.
      return null;
    }
    if (name.startsWith("lambda$")
        && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC)
        && lambdaMethodsUsedInInvokeDyanmic.contains(MethodInfo.create(internalName, name, desc))) {
      if (!allowDefaultMethods && isInterface && BitFlags.isSet(access, Opcodes.ACC_STATIC)) {
        // There must be a lambda in the interface (which in the absence of hand-written default or
        // static interface methods must mean it's in the <clinit> method or inside another lambda).
        // We'll move this method out of this class, so just record and drop it here.
        // (Note lambda body methods have unique names, so we don't need to remember desc here.)
        aggregateInterfaceLambdaMethods.add(internalName + '#' + name);
        return null;
      }
      if (BitFlags.isSet(access, Opcodes.ACC_PRIVATE)) {
        // Make lambda body method accessible from lambda class
        access &= ~Opcodes.ACC_PRIVATE;
        if (allowDefaultMethods && isInterface) {
          // java 8 requires interface methods to have exactly one of ACC_PUBLIC and ACC_PRIVATE
          access |= Opcodes.ACC_PUBLIC;
        } else {
          // Method was private so it can be final, which should help VMs perform dispatch.
          access |= Opcodes.ACC_FINAL;
        }
      }
      // Guarantee unique lambda body method name to avoid accidental overriding. This wouldn't be
      // be necessary for static methods but in visitOuterClass we don't know whether a potential
      // outer lambda$ method is static or not, so we just always do it.
      name = uniqueInPackage(internalName, name);
    }
    MethodVisitor dest = super.visitMethod(access, name, desc, signature, exceptions);
    return dest != null
        ? new InvokedynamicRewriter(dest, access, name, desc, signature, exceptions)
        : null;
  }

  // If this method changes then InvokeDynamicLambdaMethodCollector may need changes well
  @Override
  public void visitOuterClass(String owner, String name, String desc) {
    if (name != null && name.startsWith("lambda$")) {
      // Reflect renaming of lambda$ methods.  Proguard gets grumpy if we leave this inconsistent.
      name = uniqueInPackage(owner, name);
    }
    super.visitOuterClass(owner, name, desc);
  }

  // When adding visitXxx methods here then InvokeDynamicLambdaMethodCollector may need changes well

  static String uniqueInPackage(String owner, String name) {
    String suffix = "$" + owner.substring(owner.lastIndexOf('/') + 1);
    // For idempotency, we only attach the package-unique suffix if it isn't there already.  This
    // prevents a cumulative effect when processing a class more than once (which can happen with
    // Bazel, e.g., when re-importing a deploy.jar).  During reprocessing, invokedynamics are
    // already removed, so lambda$ methods have regular call sites that we would also have to re-
    // adjust if we just blindly appended something to lambda$ method names every time we see them.
    return name.endsWith(suffix) ? name : name + suffix;
  }

  /**
   * Makes {@link #visitEnd} generate a bridge method for the given method handle if the referenced
   * method will be invisible to the generated lambda class.
   *
   * @return struct containing either {@code invokedMethod} or {@code invokedMethod} and a handle
   *     representing the bridge method that will be generated for {@code invokedMethod}.
   */
  private MethodReferenceBridgeInfo queueUpBridgeMethodIfNeeded(Handle invokedMethod)
      throws ClassNotFoundException {
    if (invokedMethod.getName().startsWith("lambda$")) {
      // We adjust lambda bodies to be visible
      return MethodReferenceBridgeInfo.noBridge(invokedMethod);
    }

    // invokedMethod is a method reference if we get here
    Executable invoked = findTargetMethod(invokedMethod);
    if (isVisibleToLambdaClass(invoked, invokedMethod.getOwner())) {
      // Referenced method is visible to the generated class, so nothing to do
      return MethodReferenceBridgeInfo.noBridge(invokedMethod);
    }

    // We need a bridge method if we get here
    checkState(
        !isInterface,
        "%s is an interface and shouldn't need bridge to %s",
        internalName,
        invokedMethod);
    checkState(
        !invokedMethod.isInterface(),
        "%s's lambda classes can't see interface method: %s",
        internalName,
        invokedMethod);
    MethodReferenceBridgeInfo result = bridgeMethods.get(invokedMethod);
    if (result != null) {
      return result; // we're already queued up a bridge method for this method reference
    }

    String name = uniqueInPackage(internalName, "bridge$lambda$" + bridgeMethods.size());
    Handle bridgeMethod;
    switch (invokedMethod.getTag()) {
      case Opcodes.H_INVOKESTATIC:
        bridgeMethod =
            new Handle(
                invokedMethod.getTag(), internalName, name, invokedMethod.getDesc(), /*itf*/ false);
        break;
      case Opcodes.H_INVOKEVIRTUAL:
      case Opcodes.H_INVOKESPECIAL: // we end up calling these using invokevirtual
        bridgeMethod =
            new Handle(
                Opcodes.H_INVOKEVIRTUAL,
                internalName,
                name,
                invokedMethod.getDesc(), /*itf*/
                false);
        break;
      case Opcodes.H_NEWINVOKESPECIAL:
        {
          // Call invisible constructor through generated bridge "factory" method, so we need to
          // compute the descriptor for the bridge method from the constructor's descriptor
          String desc =
              Type.getMethodDescriptor(
                  Type.getObjectType(invokedMethod.getOwner()),
                  Type.getArgumentTypes(invokedMethod.getDesc()));
          bridgeMethod =
              new Handle(Opcodes.H_INVOKESTATIC, internalName, name, desc, /*itf*/ false);
          break;
        }
      case Opcodes.H_INVOKEINTERFACE:
        // Shouldn't get here
      default:
        throw new UnsupportedOperationException("Cannot bridge " + invokedMethod);
    }
    result = MethodReferenceBridgeInfo.bridge(invokedMethod, invoked, bridgeMethod);
    MethodReferenceBridgeInfo old = bridgeMethods.put(invokedMethod, result);
    checkState(old == null, "Already had bridge %s so we don't also want %s", old, result);
    return result;
  }

  /**
   * Checks whether the referenced method would be visible by an unrelated class in the same package
   * as the currently visited class.
   */
  private boolean isVisibleToLambdaClass(Executable invoked, String owner) {
    int modifiers = invoked.getModifiers();
    if (Modifier.isPrivate(modifiers)) {
      return false;
    }
    if (Modifier.isPublic(modifiers)) {
      return true;
    }
    // invoked is protected or package-private, either way we need it to be in the same package
    // because the additional visibility protected gives doesn't help lambda classes, which are in
    // a different class hierarchy (and typically just extend Object)
    return packageName(internalName).equals(packageName(owner));
  }

  private Executable findTargetMethod(Handle invokedMethod) throws ClassNotFoundException {
    Type descriptor = Type.getMethodType(invokedMethod.getDesc());
    Class<?> owner = loadFromInternal(invokedMethod.getOwner());
    if (invokedMethod.getTag() == Opcodes.H_NEWINVOKESPECIAL) {
      for (Constructor<?> c : owner.getDeclaredConstructors()) {
        if (Type.getType(c).equals(descriptor)) {
          return c;
        }
      }
    } else {
      for (Method m : owner.getDeclaredMethods()) {
        if (m.getName().equals(invokedMethod.getName()) && Type.getType(m).equals(descriptor)) {
          return m;
        }
      }
    }
    throw new IllegalArgumentException("Referenced method not found: " + invokedMethod);
  }

  private Class<?> loadFromInternal(String internalName) throws ClassNotFoundException {
    return targetLoader.loadClass(internalName.replace('/', '.'));
  }

  static int invokeOpcode(Handle invokedMethod) {
    switch (invokedMethod.getTag()) {
      case Opcodes.H_INVOKESTATIC:
        return Opcodes.INVOKESTATIC;
      case Opcodes.H_INVOKEVIRTUAL:
        return Opcodes.INVOKEVIRTUAL;
      case Opcodes.H_INVOKESPECIAL:
      case Opcodes.H_NEWINVOKESPECIAL: // Must be preceded by NEW
        return Opcodes.INVOKESPECIAL;
      case Opcodes.H_INVOKEINTERFACE:
        return Opcodes.INVOKEINTERFACE;
      default:
        throw new UnsupportedOperationException("Don't know how to call " + invokedMethod);
    }
  }

  private static String[] toInternalNames(Class<?>[] classes) {
    String[] result = new String[classes.length];
    for (int i = 0; i < classes.length; ++i) {
      result[i] = Type.getInternalName(classes[i]);
    }
    return result;
  }

  private static String packageName(String internalClassName) {
    int lastSlash = internalClassName.lastIndexOf('/');
    return lastSlash > 0 ? internalClassName.substring(0, lastSlash) : "";
  }

  /**
   * Desugaring that replaces invokedynamics for {@link java.lang.invoke.LambdaMetafactory} with
   * static factory method invocations and triggers a class to be generated for each invokedynamic.
   */
  private class InvokedynamicRewriter extends MethodNode {

    private final MethodVisitor dest;

    private int lastLabeledLineNumber;

    public InvokedynamicRewriter(
        MethodVisitor dest,
        int access,
        String name,
        String desc,
        String signature,
        String[] exceptions) {
      super(Opcodes.ASM8, access, name, desc, signature, exceptions);
      this.dest = checkNotNull(dest, "Null destination for %s.%s : %s", internalName, name, desc);
    }

    @Override
    public void visitEnd() {
      accept(dest);
    }

    @Override
    public void visitLineNumber(int line, Label start) {
      lastLabeledLineNumber = line;
      super.visitLineNumber(line, start);
    }

    @Override
    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
      if (!"java/lang/invoke/LambdaMetafactory".equals(bsm.getOwner())) {
        // Not an invokedynamic for a lambda expression
        super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
        return;
      }

      try {
        Lookup lookup = createLookup(internalName);
        ArrayList<Object> args = new ArrayList<>(bsmArgs.length + 3);
        args.add(lookup);
        args.add(name);
        args.add(MethodType.fromMethodDescriptorString(desc, targetLoader));
        for (Object bsmArg : bsmArgs) {
          args.add(toJvmMetatype(lookup, bsmArg));
        }

        // Both bootstrap methods in LambdaMetafactory expect a MethodHandle as their 5th argument
        // so we can assume bsmArgs[1] (the 5th arg) to be a Handle.
        MethodReferenceBridgeInfo bridgeInfo = queueUpBridgeMethodIfNeeded((Handle) bsmArgs[1]);

        // Resolve the bootstrap method in "host configuration" (this tool's default classloader)
        // since targetLoader may only contain stubs that we can't actually execute.
        // generateLambdaClass() below will invoke the bootstrap method, so a stub isn't enough,
        // and ultimately we don't care if the bootstrap method was even on the bootclasspath
        // when this class was compiled (although it must've been since javac is unhappy otherwise).
        MethodHandle bsmMethod = toMethodHandle(publicLookup(), bsm, /*target*/ false);
        // Give generated classes to have more stable names (b/35643761).  Use BSM's naming scheme
        // but with separate counter for each surrounding class.
        String lambdaClassName = internalName + "$$Lambda$" + lambdaCount++;
        Type[] capturedTypes = Type.getArgumentTypes(desc);
        boolean needFactory =
            capturedTypes.length != 0
                && !attemptAllocationBeforeArgumentLoads(lambdaClassName, capturedTypes);
        Optional<String> sourceFileName =
            classAttributeRecord.getSourceFileName(
                ClassName.create(internalName).acceptTypeMapper(IN_PROCESS_LABEL_STRIPPER));
        lambdas.generateLambdaClass(
            internalName,
            LambdaInfo.create(
                lambdaClassName,
                desc,
                needFactory,
                bridgeInfo.methodReference(),
                bridgeInfo.bridgeMethod(),
                sourceFileName,
                lastLabeledLineNumber),
            bsmMethod,
            args);
        if (desc.startsWith("()")) {
          // For stateless lambda classes we'll generate a singleton instance that we can just load
          checkState(capturedTypes.length == 0);
          super.visitFieldInsn(
              Opcodes.GETSTATIC,
              lambdaClassName,
              LambdaClassFixer.SINGLETON_FIELD_NAME,
              desc.substring("()".length()));
        } else if (needFactory) {
          // If we were unable to inline the allocation of the generated lambda class then
          // invoke factory method of generated lambda class with the arguments on the stack
          super.visitMethodInsn(
              Opcodes.INVOKESTATIC,
              lambdaClassName,
              LambdaClassFixer.FACTORY_METHOD_NAME,
              desc,
              /*itf*/ false);
        } else {
          // Otherwise we inserted a new/dup pair of instructions above and now just need to invoke
          // the constructor of generated lambda class with the arguments on the stack
          super.visitMethodInsn(
              Opcodes.INVOKESPECIAL,
              lambdaClassName,
              "<init>",
              Type.getMethodDescriptor(Type.VOID_TYPE, capturedTypes),
              /*itf*/ false);
        }
      } catch (IOException | ReflectiveOperationException e) {
        throw new IllegalStateException(
            "Couldn't desugar invokedynamic for "
                + internalName
                + "."
                + name
                + " using "
                + bsm
                + " with arguments "
                + Arrays.toString(bsmArgs),
            e);
      }
    }

    /**
     * Tries to insert a new/dup for the given class name before expected existing instructions that
     * set up arguments for an invokedynamic factory method with the given types.
     *
     * <p>For lambda expressions and simple method references we can assume that arguments are set
     * up with loads of the captured (effectively) final variables. But method references, can in
     * general capture an expression, such as in {@code myObject.toString()::charAt} (a {@code
     * Function&lt;Integer, Character&gt;}), which can also cause null checks to be inserted. In
     * such more complicated cases this method may fail to insert a new/dup pair and returns {@code
     * false}.
     *
     * @param internalName internal name of the class to instantiate
     * @param paramTypes expected invokedynamic argument types, which also must be the parameters of
     *     {@code internalName}'s constructor.
     * @return {@code true} if we were able to insert a new/dup, {@code false} otherwise
     */
    private boolean attemptAllocationBeforeArgumentLoads(String internalName, Type[] paramTypes) {
      checkArgument(paramTypes.length > 0, "Expected at least one param for %s", internalName);
      // Walk backwards past loads corresponding to constructor arguments to find the instruction
      // after which we need to insert our NEW/DUP pair
      AbstractInsnNode insn = instructions.getLast();
      for (int i = paramTypes.length - 1; 0 <= i; --i) {
        if (insn.getOpcode() == Opcodes.GETFIELD) {
          // Lambdas in anonymous inner classes have to load outer scope variables from fields,
          // which manifest as an ALOAD followed by one or more GETFIELDs
          FieldInsnNode getfield = (FieldInsnNode) insn;
          checkState(
              getfield.desc.length() == 1
                  ? getfield.desc.equals(paramTypes[i].getDescriptor())
                  : paramTypes[i].getDescriptor().length() > 1,
              "Expected getfield for %s to set up parameter %s for %s but got %s : %s",
              paramTypes[i],
              i,
              internalName,
              getfield.name,
              getfield.desc);
          insn = insn.getPrevious();

          while (insn.getOpcode() == Opcodes.GETFIELD) {
            // Nested inner classes can cause a cascade of getfields from the outermost one inwards
            checkState(
                ((FieldInsnNode) insn).desc.startsWith("L"),
                "expect object type getfields to get to %s to set up parameter %s for %s, not: %s",
                paramTypes[i],
                i,
                internalName,
                ((FieldInsnNode) insn).desc);
            insn = insn.getPrevious();
          }

          checkState(
              insn.getOpcode() == Opcodes.ALOAD, // should be a this pointer to be precise
              "Expected aload before getfield for %s to set up parameter %s for %s but got %s",
              getfield.name,
              i,
              internalName,
              insn.getOpcode());
        } else if (!isPushForType(insn, paramTypes[i])) {
          // Otherwise expect load of a (effectively) final local variable or a constant. Not seeing
          // that means we're dealing with a method reference on some arbitrary expression,
          // <expression>::m. In that case we give up and keep using the factory method for now,
          // since inserting the NEW/DUP so the new object ends up in the right stack slot is hard
          // in that case. Note this still covers simple cases such as this::m or x::m, where x is a
          // local.
          checkState(
              paramTypes.length == 1,
              "Expected a load for %s to set up parameter %s for %s but got %s",
              paramTypes[i],
              i,
              internalName,
              insn.getOpcode());
          return false;
        }
        insn = insn.getPrevious();
      }

      TypeInsnNode newInsn = new TypeInsnNode(Opcodes.NEW, internalName);
      if (insn == null) {
        // Ran off the front of the instruction list
        instructions.insert(newInsn);
      } else {
        instructions.insert(insn, newInsn);
      }
      instructions.insert(newInsn, new InsnNode(Opcodes.DUP));
      return true;
    }

    /**
     * Returns whether a given instruction can be used to push argument of {@code type} on stack.
     */
    private /* static */ boolean isPushForType(AbstractInsnNode insn, Type type) {
      int opcode = insn.getOpcode();
      if (opcode == type.getOpcode(Opcodes.ILOAD)) {
        return true;
      }
      // b/62060793: AsyncAwait rewrites bytecode to convert java methods into state machine with
      // support of lambdas. Constant zero values are pushed on stack for all yet uninitialized
      // local variables. And SIPUSH instruction is used to advance an internal state of a state
      // machine.
      switch (type.getSort()) {
        case Type.BOOLEAN:
          return opcode == Opcodes.ICONST_0 || opcode == Opcodes.ICONST_1;

        case Type.BYTE:
        case Type.CHAR:
        case Type.SHORT:
        case Type.INT:
          return opcode == Opcodes.SIPUSH
              || opcode == Opcodes.ICONST_0
              || opcode == Opcodes.ICONST_1
              || opcode == Opcodes.ICONST_2
              || opcode == Opcodes.ICONST_3
              || opcode == Opcodes.ICONST_4
              || opcode == Opcodes.ICONST_5
              || opcode == Opcodes.ICONST_M1;

        case Type.LONG:
          return opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1;

        case Type.FLOAT:
          return opcode == Opcodes.FCONST_0
              || opcode == Opcodes.FCONST_1
              || opcode == Opcodes.FCONST_2;

        case Type.DOUBLE:
          return opcode == Opcodes.DCONST_0 || opcode == Opcodes.DCONST_1;

        case Type.OBJECT:
        case Type.ARRAY:
          return opcode == Opcodes.ACONST_NULL;

        default:
          // Support for BIPUSH and LDC* opcodes is not implemented as there is no known use case.
          return false;
      }
    }

    private Lookup createLookup(String lookupClass) throws ReflectiveOperationException {
      Class<?> clazz = loadFromInternal(lookupClass);
      Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class);
      constructor.setAccessible(true);
      return constructor.newInstance(clazz);
    }

    /**
     * Produces a {@link MethodHandle} or {@link MethodType} using {@link #targetLoader} for the
     * given ASM {@link Handle} or {@link Type}. {@code lookup} is only used for resolving {@link
     * Handle}s.
     */
    private Object toJvmMetatype(Lookup lookup, Object asm) throws ReflectiveOperationException {
      if (asm instanceof Number) {
        return asm;
      }
      if (asm instanceof Type) {
        Type type = (Type) asm;
        switch (type.getSort()) {
          case Type.OBJECT:
            return loadFromInternal(type.getInternalName());
          case Type.METHOD:
            return MethodType.fromMethodDescriptorString(type.getDescriptor(), targetLoader);
          default:
            throw new IllegalArgumentException("Cannot convert: " + asm);
        }
      }
      if (asm instanceof Handle) {
        return toMethodHandle(lookup, (Handle) asm, /*target*/ true);
      }
      throw new IllegalArgumentException("Cannot convert: " + asm);
    }

    /**
     * Produces a {@link MethodHandle} using either the context or {@link #targetLoader} class
     * loader, depending on {@code target}.
     */
    private MethodHandle toMethodHandle(Lookup lookup, Handle asmHandle, boolean target)
        throws ReflectiveOperationException {
      Class<?> owner = loadFromInternal(asmHandle.getOwner());
      MethodType signature =
          MethodType.fromMethodDescriptorString(
              asmHandle.getDesc(),
              target ? targetLoader : Thread.currentThread().getContextClassLoader());
      switch (asmHandle.getTag()) {
        case Opcodes.H_INVOKESTATIC:
          return lookup.findStatic(owner, asmHandle.getName(), signature);
        case Opcodes.H_INVOKEVIRTUAL:
        case Opcodes.H_INVOKEINTERFACE:
          return lookup.findVirtual(owner, asmHandle.getName(), signature);
        case Opcodes.H_INVOKESPECIAL: // we end up calling these using invokevirtual
          return lookup.findSpecial(owner, asmHandle.getName(), signature, owner);
        case Opcodes.H_NEWINVOKESPECIAL:
          return lookup.findConstructor(owner, signature);
        default:
          throw new UnsupportedOperationException("Cannot resolve " + asmHandle);
      }
    }
  }

  /**
   * Record of how a lambda class can reach its referenced method through a possibly-different
   * bridge method.
   *
   * <p>In a JVM, lambda classes are allowed to call the referenced methods directly, but we don't
   * have that luxury when the generated lambda class is evaluated using normal visibility rules.
   */
  @AutoValue
  abstract static class MethodReferenceBridgeInfo {
    public static MethodReferenceBridgeInfo noBridge(Handle methodReference) {
      return new AutoValue_LambdaDesugaring_MethodReferenceBridgeInfo(
          methodReference, (Executable) null, methodReference);
    }

    public static MethodReferenceBridgeInfo bridge(
        Handle methodReference, Executable referenced, Handle bridgeMethod) {
      checkArgument(!bridgeMethod.equals(methodReference));
      return new AutoValue_LambdaDesugaring_MethodReferenceBridgeInfo(
          methodReference, checkNotNull(referenced), bridgeMethod);
    }

    public abstract Handle methodReference();

    /** Returns {@code null} iff {@link #bridgeMethod} equals {@link #methodReference}. */
    @Nullable
    public abstract Executable referenced();

    public abstract Handle bridgeMethod();
  }
}
