184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// Copyright 2016 The Bazel Authors. All rights reserved.
284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael//
384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// Licensed under the Apache License, Version 2.0 (the "License");
484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// you may not use this file except in compliance with the License.
584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// You may obtain a copy of the License at
684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael//
784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael//    http://www.apache.org/licenses/LICENSE-2.0
884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael//
984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// Unless required by applicable law or agreed to in writing, software
1084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// distributed under the License is distributed on an "AS IS" BASIS,
1184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// See the License for the specific language governing permissions and
1384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael// limitations under the License.
1484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelpackage com.google.devtools.build.android.desugar;
1584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
1684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport static com.google.common.base.Preconditions.checkArgument;
1784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport static com.google.common.base.Preconditions.checkNotNull;
1884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport static com.google.common.base.Preconditions.checkState;
1984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport static java.lang.invoke.MethodHandles.publicLookup;
2084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport static org.objectweb.asm.Opcodes.ASM5;
2184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
2284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport com.google.auto.value.AutoValue;
2384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport com.google.common.collect.ImmutableSet;
2484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.io.IOException;
2584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.lang.invoke.MethodHandle;
2684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.lang.invoke.MethodHandles.Lookup;
2784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.lang.invoke.MethodType;
2884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.lang.reflect.Constructor;
2984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.lang.reflect.Executable;
3084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.lang.reflect.Method;
3184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.lang.reflect.Modifier;
3284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.util.ArrayList;
3384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.util.Arrays;
3484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.util.HashMap;
3584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport java.util.Map;
3684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport javax.annotation.Nullable;
3784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport org.objectweb.asm.ClassVisitor;
3884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport org.objectweb.asm.Handle;
3984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport org.objectweb.asm.MethodVisitor;
4084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport org.objectweb.asm.Opcodes;
4184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelimport org.objectweb.asm.Type;
4284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
4384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael/**
4484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael * Visitor that desugars classes with uses of lambdas into Java 7-looking code.  This includes
4584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael * rewriting lambda-related invokedynamic instructions as well as fixing accessibility of methods
4684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael * that javac emits for lambda bodies.
4784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael */
4884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michaelclass LambdaDesugaring extends ClassVisitor {
4984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
5084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private final ClassLoader targetLoader;
5184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private final LambdaClassMaker lambdas;
5284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private final ImmutableSet.Builder<String> aggregateInterfaceLambdaMethods;
5384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private final Map<Handle, MethodReferenceBridgeInfo> bridgeMethods = new HashMap<>();
540d1939c7699eea03e166574d0852e91a054ac0daColin Cross  private final boolean allowDefaultMethods;
5584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
5684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private String internalName;
5784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private boolean isInterface;
58d3371d01485317d82c584e39838f6cf565076a68Googler  private int lambdaCount;
5984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
600d1939c7699eea03e166574d0852e91a054ac0daColin Cross  public LambdaDesugaring(
610d1939c7699eea03e166574d0852e91a054ac0daColin Cross      ClassVisitor dest,
620d1939c7699eea03e166574d0852e91a054ac0daColin Cross      ClassLoader targetLoader,
630d1939c7699eea03e166574d0852e91a054ac0daColin Cross      LambdaClassMaker lambdas,
640d1939c7699eea03e166574d0852e91a054ac0daColin Cross      ImmutableSet.Builder<String> aggregateInterfaceLambdaMethods,
650d1939c7699eea03e166574d0852e91a054ac0daColin Cross      boolean allowDefaultMethods) {
6684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    super(Opcodes.ASM5, dest);
6784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    this.targetLoader = targetLoader;
6884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    this.lambdas = lambdas;
6984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    this.aggregateInterfaceLambdaMethods = aggregateInterfaceLambdaMethods;
700d1939c7699eea03e166574d0852e91a054ac0daColin Cross    this.allowDefaultMethods = allowDefaultMethods;
7184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
7284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
7384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  @Override
7484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  public void visit(
7584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      int version,
7684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      int access,
7784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      String name,
7884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      String signature,
7984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      String superName,
8084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      String[] interfaces) {
81d3371d01485317d82c584e39838f6cf565076a68Googler    checkState(internalName == null, "not intended for reuse but reused for %s", name);
8284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    internalName = name;
8384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    isInterface = BitFlags.isSet(access, Opcodes.ACC_INTERFACE);
8484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    super.visit(version, access, name, signature, superName, interfaces);
8584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
8684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
8784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  @Override
8884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  public void visitEnd() {
8984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    for (Map.Entry<Handle, MethodReferenceBridgeInfo> bridge : bridgeMethods.entrySet()) {
9084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      Handle original = bridge.getKey();
9184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      Handle neededMethod = bridge.getValue().bridgeMethod();
9284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      checkState(neededMethod.getTag() == Opcodes.H_INVOKESTATIC
9384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          || neededMethod.getTag() == Opcodes.H_INVOKEVIRTUAL,
9484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          "Cannot generate bridge method %s to reach %s", neededMethod, original);
9584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      checkState(bridge.getValue().referenced() != null,
9684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          "Need referenced method %s to generate bridge %s", original, neededMethod);
9784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
9884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      int access = Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_FINAL;
9984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (neededMethod.getTag() == Opcodes.H_INVOKESTATIC) {
10084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        access |= Opcodes.ACC_STATIC;
10184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
10284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      MethodVisitor bridgeMethod =
10384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          super.visitMethod(
10484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael              access,
10584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael              neededMethod.getName(),
10684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael              neededMethod.getDesc(),
10784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael              (String) null,
10884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael              toInternalNames(bridge.getValue().referenced().getExceptionTypes()));
10984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
11084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      // Bridge is a factory method calling a constructor
11184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (original.getTag() == Opcodes.H_NEWINVOKESPECIAL) {
11284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        bridgeMethod.visitTypeInsn(Opcodes.NEW, original.getOwner());
11384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        bridgeMethod.visitInsn(Opcodes.DUP);
11484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
11584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
11684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      int slot = 0;
11784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (neededMethod.getTag() != Opcodes.H_INVOKESTATIC) {
11884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        bridgeMethod.visitVarInsn(Opcodes.ALOAD, slot++);
11984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
12084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      Type neededType = Type.getMethodType(neededMethod.getDesc());
12184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      for (Type arg : neededType.getArgumentTypes()) {
12284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        bridgeMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
12384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        slot += arg.getSize();
12484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
12584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      bridgeMethod.visitMethodInsn(invokeOpcode(original), original.getOwner(), original.getName(),
12684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          original.getDesc(), original.isInterface());
12784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      bridgeMethod.visitInsn(neededType.getReturnType().getOpcode(Opcodes.IRETURN));
12884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
12984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      bridgeMethod.visitMaxs(0, 0); // rely on class writer to compute these
13084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      bridgeMethod.visitEnd();
13184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
13284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    super.visitEnd();
13384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
13484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
13584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  @Override
13684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  public MethodVisitor visitMethod(
13784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      int access, String name, String desc, String signature, String[] exceptions) {
13884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (name.equals("$deserializeLambda$") && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC)) {
13984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      // Android doesn't do anything special for lambda serialization so drop the special
14084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      // deserialization hook that javac generates.  This also makes sure we don't reference
14184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      // java/lang/invoke/SerializedLambda, which doesn't exist on Android.
14284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return null;
14384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
14484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (name.startsWith("lambda$") && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC)) {
1450d1939c7699eea03e166574d0852e91a054ac0daColin Cross      if (!allowDefaultMethods && isInterface && BitFlags.isSet(access, Opcodes.ACC_STATIC)) {
14684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // There must be a lambda in the interface (which in the absence of hand-written default or
14784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // static interface methods must mean it's in the <clinit> method or inside another lambda).
14884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // We'll move this method out of this class, so just record and drop it here.
14984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // (Note lambda body methods have unique names, so we don't need to remember desc here.)
15084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        aggregateInterfaceLambdaMethods.add(internalName + '#' + name);
15184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return null;
15284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
15384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (BitFlags.isSet(access, Opcodes.ACC_PRIVATE)) {
15484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // Make lambda body method accessible from lambda class
15584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        access &= ~Opcodes.ACC_PRIVATE;
1560d1939c7699eea03e166574d0852e91a054ac0daColin Cross        if (allowDefaultMethods && isInterface) {
1570d1939c7699eea03e166574d0852e91a054ac0daColin Cross          // java 8 requires interface methods to have exactly one of ACC_PUBLIC and ACC_PRIVATE
1580d1939c7699eea03e166574d0852e91a054ac0daColin Cross          access |= Opcodes.ACC_PUBLIC;
1590d1939c7699eea03e166574d0852e91a054ac0daColin Cross        } else {
1600d1939c7699eea03e166574d0852e91a054ac0daColin Cross          // Method was private so it can be final, which should help VMs perform dispatch.
1610d1939c7699eea03e166574d0852e91a054ac0daColin Cross          access |= Opcodes.ACC_FINAL;
1620d1939c7699eea03e166574d0852e91a054ac0daColin Cross        }
16384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
1640ccdd4c939408a7f4d0adbfbed90031e75021e63Googler      // Guarantee unique lambda body method name to avoid accidental overriding. This wouldn't be
1650ccdd4c939408a7f4d0adbfbed90031e75021e63Googler      // be necessary for static methods but in visitOuterClass we don't know whether a potential
1660ccdd4c939408a7f4d0adbfbed90031e75021e63Googler      // outer lambda$ method is static or not, so we just always do it.
1670ccdd4c939408a7f4d0adbfbed90031e75021e63Googler      name = uniqueInPackage(internalName, name);
16884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
16984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    MethodVisitor dest = super.visitMethod(access, name, desc, signature, exceptions);
17084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    return new InvokedynamicRewriter(dest);
17184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
17284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
1730ccdd4c939408a7f4d0adbfbed90031e75021e63Googler  @Override
1740ccdd4c939408a7f4d0adbfbed90031e75021e63Googler  public void visitOuterClass(String owner, String name, String desc) {
1750ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    if (name != null && name.startsWith("lambda$")) {
1760ccdd4c939408a7f4d0adbfbed90031e75021e63Googler      // Reflect renaming of lambda$ methods.  Proguard gets grumpy if we leave this inconsistent.
1770ccdd4c939408a7f4d0adbfbed90031e75021e63Googler      name = uniqueInPackage(owner, name);
1780ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    }
1790ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    super.visitOuterClass(owner, name, desc);
1800ccdd4c939408a7f4d0adbfbed90031e75021e63Googler  }
1810ccdd4c939408a7f4d0adbfbed90031e75021e63Googler
1820ccdd4c939408a7f4d0adbfbed90031e75021e63Googler  static String uniqueInPackage(String owner, String name) {
1830ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    String suffix = "$" + owner.substring(owner.lastIndexOf('/') + 1);
1840ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    // For idempotency, we only attach the package-unique suffix if it isn't there already.  This
1850ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    // prevents a cumulative effect when processing a class more than once (which can happen with
1860ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    // Bazel, e.g., when re-importing a deploy.jar).  During reprocessing, invokedynamics are
1870ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    // already removed, so lambda$ methods have regular call sites that we would also have to re-
1880ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    // adjust if we just blindly appended something to lambda$ method names every time we see them.
1890ccdd4c939408a7f4d0adbfbed90031e75021e63Googler    return name.endsWith(suffix) ? name : name + suffix;
1900ccdd4c939408a7f4d0adbfbed90031e75021e63Googler  }
1910ccdd4c939408a7f4d0adbfbed90031e75021e63Googler
19284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  /**
19384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * Makes {@link #visitEnd} generate a bridge method for the given method handle if the
19484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * referenced method will be invisible to the generated lambda class.
19584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   *
19684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * @return struct containing either {@code invokedMethod} or {@code invokedMethod} and a handle
19784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   *     representing the bridge method that will be generated for {@code invokedMethod}.
19884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   */
19984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private MethodReferenceBridgeInfo queueUpBridgeMethodIfNeeded(Handle invokedMethod)
20084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      throws ClassNotFoundException {
20184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (invokedMethod.getName().startsWith("lambda$")) {
20284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      // We adjust lambda bodies to be visible
20384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return MethodReferenceBridgeInfo.noBridge(invokedMethod);
20484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
20584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
20684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    // invokedMethod is a method reference if we get here
20784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    Executable invoked = findTargetMethod(invokedMethod);
20884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (isVisibleToLambdaClass(invoked, invokedMethod.getOwner())) {
20984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      // Referenced method is visible to the generated class, so nothing to do
21084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return MethodReferenceBridgeInfo.noBridge(invokedMethod);
21184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
21284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
21384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    // We need a bridge method if we get here
21484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    checkState(!isInterface,
21584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        "%s is an interface and shouldn't need bridge to %s", internalName, invokedMethod);
21684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    checkState(!invokedMethod.isInterface(),
21784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        "%s's lambda classes can't see interface method: %s", internalName, invokedMethod);
21884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    MethodReferenceBridgeInfo result = bridgeMethods.get(invokedMethod);
21984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (result != null) {
22084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return result; // we're already queued up a bridge method for this method reference
22184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
22284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
2238264d43883171b6c0233ec9d2bdd17c614027e91Kevin Bierhoff    String name = uniqueInPackage(internalName, "bridge$lambda$" + bridgeMethods.size());
22484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    Handle bridgeMethod;
22584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    switch (invokedMethod.getTag()) {
22684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKESTATIC:
22784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        bridgeMethod = new Handle(invokedMethod.getTag(), internalName, name,
22884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            invokedMethod.getDesc(), /*itf*/ false);
22984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        break;
23084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKEVIRTUAL:
23184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKESPECIAL: // we end up calling these using invokevirtual
23284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        bridgeMethod = new Handle(Opcodes.H_INVOKEVIRTUAL, internalName, name,
23384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            invokedMethod.getDesc(), /*itf*/ false);
23484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        break;
23584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_NEWINVOKESPECIAL: {
23684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // Call invisible constructor through generated bridge "factory" method, so we need to
23784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // compute the descriptor for the bridge method from the constructor's descriptor
23884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        String desc =
23984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            Type.getMethodDescriptor(
24084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael                Type.getObjectType(invokedMethod.getOwner()),
24184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael                Type.getArgumentTypes(invokedMethod.getDesc()));
24284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        bridgeMethod = new Handle(Opcodes.H_INVOKESTATIC, internalName, name, desc, /*itf*/ false);
24384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        break;
24484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
24584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKEINTERFACE:
24684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // Shouldn't get here
24784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      default:
24884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        throw new UnsupportedOperationException("Cannot bridge " + invokedMethod);
24984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
25084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    result = MethodReferenceBridgeInfo.bridge(invokedMethod, invoked, bridgeMethod);
25184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    MethodReferenceBridgeInfo old = bridgeMethods.put(invokedMethod, result);
25284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    checkState(old == null, "Already had bridge %s so we don't also want %s", old, result);
25384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    return result;
25484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
25584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
25684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  /**
25784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * Checks whether the referenced method would be visible by an unrelated class in the same package
25884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * as the currently visited class.
25984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   */
26084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private boolean isVisibleToLambdaClass(Executable invoked, String owner) {
26184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    int modifiers = invoked.getModifiers();
26284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (Modifier.isPrivate(modifiers)) {
26384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return false;
26484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
26584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (Modifier.isPublic(modifiers)) {
26684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return true;
26784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
26884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    // invoked is protected or package-private, either way we need it to be in the same package
26984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    // because the additional visibility protected gives doesn't help lambda classes, which are in
27084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    // a different class hierarchy (and typically just extend Object)
27184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    return packageName(internalName).equals(packageName(owner));
27284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
27384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
27484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private Executable findTargetMethod(Handle invokedMethod) throws ClassNotFoundException {
27584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    Type descriptor = Type.getMethodType(invokedMethod.getDesc());
27684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    Class<?> owner = loadFromInternal(invokedMethod.getOwner());
27784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    if (invokedMethod.getTag() == Opcodes.H_NEWINVOKESPECIAL) {
27884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      for (Constructor<?> c : owner.getDeclaredConstructors()) {
27984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        if (Type.getType(c).equals(descriptor)) {
28084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          return c;
28184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        }
28284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
28384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    } else {
28484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      for (Method m : owner.getDeclaredMethods()) {
28584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        if (m.getName().equals(invokedMethod.getName())
28684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            && Type.getType(m).equals(descriptor)) {
28784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          return m;
28884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        }
28984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
29084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
29184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    throw new IllegalArgumentException("Referenced method not found: " + invokedMethod);
29284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
29384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
29484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private Class<?> loadFromInternal(String internalName) throws ClassNotFoundException {
29584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    return targetLoader.loadClass(internalName.replace('/', '.'));
29684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
29784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
29884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  static int invokeOpcode(Handle invokedMethod) {
29984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    switch (invokedMethod.getTag()) {
30084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKESTATIC:
30184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return Opcodes.INVOKESTATIC;
30284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKEVIRTUAL:
30384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return Opcodes.INVOKEVIRTUAL;
30484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKESPECIAL:
30584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_NEWINVOKESPECIAL: // Must be preceded by NEW
30684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return Opcodes.INVOKESPECIAL;
30784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      case Opcodes.H_INVOKEINTERFACE:
30884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return Opcodes.INVOKEINTERFACE;
30984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      default:
31084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        throw new UnsupportedOperationException("Don't know how to call " + invokedMethod);
31184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
31284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
31384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
31484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private static String[] toInternalNames(Class<?>[] classes) {
31584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    String[] result = new String[classes.length];
31684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    for (int i = 0; i < classes.length; ++i) {
31784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      result[i] = Type.getInternalName(classes[i]);
31884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
31984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    return result;
32084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
32184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
32284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private static String packageName(String internalClassName) {
32384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    int lastSlash = internalClassName.lastIndexOf('/');
32484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    return lastSlash > 0 ? internalClassName.substring(0, lastSlash) : "";
32584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
32684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
32784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  /**
32884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * Desugaring that replaces invokedynamics for {@link java.lang.invoke.LambdaMetafactory} with
32984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * static factory method invocations and triggers a class to be generated for each invokedynamic.
33084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   */
33184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  private class InvokedynamicRewriter extends MethodVisitor {
33284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
33384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    public InvokedynamicRewriter(MethodVisitor dest) {
33484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      super(ASM5, dest);
33584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
33684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
33784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    @Override
33884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
33984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (!"java/lang/invoke/LambdaMetafactory".equals(bsm.getOwner())) {
34084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // Not an invokedynamic for a lambda expression
34184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
34284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return;
34384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
34484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
34584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      try {
34684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        Lookup lookup = createLookup(internalName);
34784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        ArrayList<Object> args = new ArrayList<>(bsmArgs.length + 3);
34884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        args.add(lookup);
34984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        args.add(name);
35084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        args.add(MethodType.fromMethodDescriptorString(desc, targetLoader));
35184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        for (Object bsmArg : bsmArgs) {
35284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          args.add(toJvmMetatype(lookup, bsmArg));
35384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        }
35484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
35584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // Both bootstrap methods in LambdaMetafactory expect a MethodHandle as their 5th argument
35684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // so we can assume bsmArgs[1] (the 5th arg) to be a Handle.
35784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        MethodReferenceBridgeInfo bridgeInfo = queueUpBridgeMethodIfNeeded((Handle) bsmArgs[1]);
35884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
35984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // Resolve the bootstrap method in "host configuration" (this tool's default classloader)
36084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // since targetLoader may only contain stubs that we can't actually execute.
36184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // generateLambdaClass() below will invoke the bootstrap method, so a stub isn't enough,
36284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // and ultimately we don't care if the bootstrap method was even on the bootclasspath
36384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        // when this class was compiled (although it must've been since javac is unhappy otherwise).
36484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        MethodHandle bsmMethod = toMethodHandle(publicLookup(), bsm, /*target*/ false);
365d3371d01485317d82c584e39838f6cf565076a68Googler        // Give generated classes to have more stable names (b/35643761).  Use BSM's naming scheme
366d3371d01485317d82c584e39838f6cf565076a68Googler        // but with separate counter for each surrounding class.
367d3371d01485317d82c584e39838f6cf565076a68Googler        String lambdaClassName = internalName + "$$Lambda$" + (lambdaCount++);
368d3371d01485317d82c584e39838f6cf565076a68Googler        lambdas.generateLambdaClass(
36984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            internalName,
370d3371d01485317d82c584e39838f6cf565076a68Googler            LambdaInfo.create(
371d3371d01485317d82c584e39838f6cf565076a68Googler                lambdaClassName, desc, bridgeInfo.methodReference(), bridgeInfo.bridgeMethod()),
37284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            bsmMethod,
37384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            args);
3744e1287358e04b9755dfcf19d9c1c15dc86600554Googler        if (desc.startsWith("()")) {
3754e1287358e04b9755dfcf19d9c1c15dc86600554Googler          // For stateless lambda classes we'll generate a singleton instance that we can just load
3764e1287358e04b9755dfcf19d9c1c15dc86600554Googler          super.visitFieldInsn(Opcodes.GETSTATIC, lambdaClassName,
3774e1287358e04b9755dfcf19d9c1c15dc86600554Googler              LambdaClassFixer.SINGLETON_FIELD_NAME, desc.substring("()".length()));
3784e1287358e04b9755dfcf19d9c1c15dc86600554Googler        } else {
3794e1287358e04b9755dfcf19d9c1c15dc86600554Googler          // Emit invokestatic that calls the factory method generated in the lambda class
3804e1287358e04b9755dfcf19d9c1c15dc86600554Googler          super.visitMethodInsn(
3814e1287358e04b9755dfcf19d9c1c15dc86600554Googler              Opcodes.INVOKESTATIC,
3824e1287358e04b9755dfcf19d9c1c15dc86600554Googler              lambdaClassName,
3834e1287358e04b9755dfcf19d9c1c15dc86600554Googler              LambdaClassFixer.FACTORY_METHOD_NAME,
3844e1287358e04b9755dfcf19d9c1c15dc86600554Googler              desc,
3854e1287358e04b9755dfcf19d9c1c15dc86600554Googler              /*itf*/ false);
3864e1287358e04b9755dfcf19d9c1c15dc86600554Googler        }
38784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      } catch (IOException | ReflectiveOperationException e) {
38884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        throw new IllegalStateException("Couldn't desugar invokedynamic for " + internalName + "."
38984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            + name + " using " + bsm + " with arguments " + Arrays.toString(bsmArgs), e);
39084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
39184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
39284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
39384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    private Lookup createLookup(String lookupClass) throws ReflectiveOperationException {
39484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      Class<?> clazz = loadFromInternal(lookupClass);
39584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class);
39684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      constructor.setAccessible(true);
39784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return constructor.newInstance(clazz);
39884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
39984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
40084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    /**
40184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael     * Produces a {@link MethodHandle} or {@link MethodType} using {@link #targetLoader} for the
40284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael     * given ASM {@link Handle} or {@link Type}. {@code lookup} is only used for resolving
40384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael     * {@link Handle}s.
40484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael     */
40584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    private Object toJvmMetatype(Lookup lookup, Object asm) throws ReflectiveOperationException {
40684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (asm instanceof Number) {
40784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return asm;
40884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
40984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (asm instanceof Type) {
41084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        Type type = (Type) asm;
41184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        switch (type.getSort()) {
41284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          case Type.OBJECT:
41384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            return loadFromInternal(type.getInternalName());
41484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          case Type.METHOD:
41584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            return MethodType.fromMethodDescriptorString(type.getDescriptor(), targetLoader);
41684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          default:
41784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael            throw new IllegalArgumentException("Cannot convert: " + asm);
41884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        }
41984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
42084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      if (asm instanceof Handle) {
42184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        return toMethodHandle(lookup, (Handle) asm, /*target*/ true);
42284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
42384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      throw new IllegalArgumentException("Cannot convert: " + asm);
42484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
42584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
42684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    /**
42784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael     * Produces a {@link MethodHandle} using either the context or {@link #targetLoader} class
42884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael     * loader, depending on {@code target}.
42984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael     */
43084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    private MethodHandle toMethodHandle(Lookup lookup, Handle asmHandle, boolean target)
43184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        throws ReflectiveOperationException {
43284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      Class<?> owner = loadFromInternal(asmHandle.getOwner());
43384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      MethodType signature = MethodType.fromMethodDescriptorString(asmHandle.getDesc(),
43484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          target ? targetLoader : Thread.currentThread().getContextClassLoader());
43584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      switch (asmHandle.getTag()) {
43684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        case Opcodes.H_INVOKESTATIC:
43784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          return lookup.findStatic(owner, asmHandle.getName(), signature);
43884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        case Opcodes.H_INVOKEVIRTUAL:
43984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        case Opcodes.H_INVOKEINTERFACE:
44084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          return lookup.findVirtual(owner, asmHandle.getName(), signature);
4410d1939c7699eea03e166574d0852e91a054ac0daColin Cross        case Opcodes.H_INVOKESPECIAL: // we end up calling these using invokevirtual
4420d1939c7699eea03e166574d0852e91a054ac0daColin Cross          return lookup.findSpecial(owner, asmHandle.getName(), signature, owner);
44384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        case Opcodes.H_NEWINVOKESPECIAL:
44484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          return lookup.findConstructor(owner, signature);
44584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        default:
44684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          throw new UnsupportedOperationException("Cannot resolve " + asmHandle);
44784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      }
44884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
44984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
45084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
45184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  /**
45284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * Record of how a lambda class can reach its referenced method through a possibly-different
45384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * bridge method.
45484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   *
45584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * <p>In a JVM, lambda classes are allowed to call the referenced methods directly, but we don't
45684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   * have that luxury when the generated lambda class is evaluated using normal visibility rules.
45784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael   */
45884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  @AutoValue
45984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  abstract static class MethodReferenceBridgeInfo {
46084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    public static MethodReferenceBridgeInfo noBridge(Handle methodReference) {
46184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return new AutoValue_LambdaDesugaring_MethodReferenceBridgeInfo(
46284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          methodReference, (Executable) null, methodReference);
46384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
46484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    public static MethodReferenceBridgeInfo bridge(
46584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael        Handle methodReference, Executable referenced, Handle bridgeMethod) {
46684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      checkArgument(!bridgeMethod.equals(methodReference));
46784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael      return new AutoValue_LambdaDesugaring_MethodReferenceBridgeInfo(
46884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael          methodReference, checkNotNull(referenced), bridgeMethod);
46984b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    }
47084b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
47184b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    public abstract Handle methodReference();
47284b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
47384b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    /** Returns {@code null} iff {@link #bridgeMethod} equals {@link #methodReference}. */
47484b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    @Nullable public abstract Executable referenced();
47584b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael
47684b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael    public abstract Handle bridgeMethod();
47784b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael  }
47884b90b3dc637a33f7f6fac59be21b74ba6fc17d6Adam Michael}
479