Java Code Examples for org.objectweb.asm.Opcodes#INVOKESPECIAL

The following examples show how to use org.objectweb.asm.Opcodes#INVOKESPECIAL . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ItemGroupTransformer.java    From patchwork-patcher with GNU Lesser General Public License v3.0 6 votes vote down vote up
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
	if (opcode != Opcodes.INVOKESPECIAL) {
		super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
	}

	if (!owner.equals(ITEM_GROUP) || !name.equals("<init>")) {
		return;
	}

	if (!descriptor.equals("(Ljava/lang/String;)V") && !descriptor.equals("(ILjava/lang/String;)V")) {
		Patchwork.LOGGER.error("Unexpected descriptor for super() in ItemGroup: " + descriptor);
	}

	super.visitMethodInsn(Opcodes.INVOKESPECIAL, PATCHWORK_ITEM_GROUP, name, descriptor, isInterface);
}
 
Example 2
Source File: InstructionAdapter.java    From JByteMod-Beta with GNU General Public License v2.0 6 votes vote down vote up
private void doVisitMethodInsn(
    final int opcode,
    final String owner,
    final String name,
    final String descriptor,
    final boolean isInterface) {
  switch (opcode) {
    case Opcodes.INVOKESPECIAL:
      invokespecial(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKEVIRTUAL:
      invokevirtual(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKESTATIC:
      invokestatic(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKEINTERFACE:
      invokeinterface(owner, name, descriptor);
      break;
    default:
      throw new IllegalArgumentException();
  }
}
 
Example 3
Source File: InstructionAdapter.java    From JReFrameworker with MIT License 6 votes vote down vote up
private void doVisitMethodInsn(
    final int opcode,
    final String owner,
    final String name,
    final String descriptor,
    final boolean isInterface) {
  switch (opcode) {
    case Opcodes.INVOKESPECIAL:
      invokespecial(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKEVIRTUAL:
      invokevirtual(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKESTATIC:
      invokestatic(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKEINTERFACE:
      invokeinterface(owner, name, descriptor);
      break;
    default:
      throw new IllegalArgumentException();
  }
}
 
Example 4
Source File: InterfaceDesugaring.java    From bazel with Apache License 2.0 6 votes vote down vote up
static String normalizeInterfaceMethodName(String name, boolean isLambda, int opcode) {
  if (isLambda) {
    // Rename lambda method to reflect the new owner.  Not doing so confuses LambdaDesugaring
    // if it's run over this class again. LambdaDesugaring has already renamed the method from
    // its original name to include the interface name at this point.
    return name + DependencyCollector.INTERFACE_COMPANION_SUFFIX;
  }

  switch (opcode) {
    case Opcodes.INVOKESPECIAL:
      // Rename static methods holding default method implementations since their descriptor
      // differs from the original method (due to explicit receiver parameter). This avoids
      // possible clashes with static interface methods or generated stubs for default methods
      // that could otherwise have the same name and descriptor by coincidence.
      return name + DEFAULT_COMPANION_METHOD_SUFFIX;
    case Opcodes.INVOKESTATIC: // moved but with same name
      return name + "$$STATIC$$"; // TODO(b/117453106): Stop renaming static interface methods
    case Opcodes.INVOKEINTERFACE: // not moved
    case Opcodes.INVOKEVIRTUAL: // tolerate being called for non-interface methods
      return name;
    default:
      throw new IllegalArgumentException("Unexpected opcode calling " + name + ": " + opcode);
  }
}
 
Example 5
Source File: ConstructorTransformerMethodVisitor.java    From scott with MIT License 6 votes vote down vote up
@Override
public void visitInsn(int opcode) {
	if ((opcode == Opcodes.ARETURN) || (opcode == Opcodes.IRETURN)
			|| (opcode == Opcodes.LRETURN)
			|| (opcode == Opcodes.FRETURN)
			|| (opcode == Opcodes.DRETURN)) {
		throw new RuntimeException(new UnmodifiableClassException("Constructors are supposed to return void"));
	}
	if (opcode == Opcodes.RETURN) {
		super.visitVarInsn(Opcodes.ALOAD, 0);
		super.visitTypeInsn(Opcodes.NEW, Type.getInternalName(ScottReportingRule.class));
		super.visitInsn(Opcodes.DUP);
		super.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(ScottReportingRule.class), "<init>", "()V", false);

		super.visitFieldInsn(Opcodes.PUTFIELD,
				className, "scottReportingRule",
				Type.getDescriptor(ScottReportingRule.class));
	}
	
	super.visitInsn(opcode);
}
 
Example 6
Source File: InstructionAdapter.java    From JReFrameworker with MIT License 6 votes vote down vote up
private void doVisitMethodInsn(
    final int opcode,
    final String owner,
    final String name,
    final String descriptor,
    final boolean isInterface) {
  switch (opcode) {
    case Opcodes.INVOKESPECIAL:
      invokespecial(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKEVIRTUAL:
      invokevirtual(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKESTATIC:
      invokestatic(owner, name, descriptor, isInterface);
      break;
    case Opcodes.INVOKEINTERFACE:
      invokeinterface(owner, name, descriptor);
      break;
    default:
      throw new IllegalArgumentException();
  }
}
 
Example 7
Source File: NestBridgeRefConverter.java    From bazel with Apache License 2.0 6 votes vote down vote up
@Override
public void visitMethodInsn(
    int opcode, String owner, String name, String descriptor, boolean isInterface) {
  MethodKey methodKey = MethodKey.create(ClassName.create(owner), name, descriptor);
  MemberUseKind useKind = MemberUseKind.fromValue(opcode);

  // Desugar invokevirtual on private instance methods within the same class.
  if (!isInterface
      && useKind == MemberUseKind.INVOKEVIRTUAL
      && methodKey.owner().equals(enclosingMethodKey.owner())
      && nestDigest.isPrivateInstanceMethod(methodKey)) {
    super.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, isInterface);
    return;
  }

  if ((isInterface || isCrossMateRefInNest(methodKey, enclosingMethodKey))
      && nestDigest.hasAnyUse(methodKey, useKind)) {
    methodKey.accept(useKind, isInterface, methodToBridgeRedirector, mv);
    return;
  }
  super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
 
Example 8
Source File: Bytecode.java    From Mixin with MIT License 5 votes vote down vote up
/**
 * Find the call to <tt>super()</tt> or <tt>this()</tt> in a constructor.
 * This attempts to locate the first call to <tt>&lt;init&gt;</tt> which
 * isn't an inline call to another object ctor being passed into the super
 * invocation.
 * 
 * @param ctor ctor to scan
 * @param superName name of superclass
 * @param ownerName name of owning class
 * @return Call to <tt>super()</tt>, <tt>this()</tt> or
 *      <tt>DelegateInitialiser.NONE</tt> if not found
 */
public static DelegateInitialiser findDelegateInit(MethodNode ctor, String superName, String ownerName) {
    if (!Constants.CTOR.equals(ctor.name)) {
        return DelegateInitialiser.NONE;
    }
    
    int news = 0;
    for (Iterator<AbstractInsnNode> iter = ctor.instructions.iterator(); iter.hasNext();) {
        AbstractInsnNode insn = iter.next();
        if (insn instanceof TypeInsnNode && insn.getOpcode() == Opcodes.NEW) {
            news++;
        } else if (insn instanceof MethodInsnNode && insn.getOpcode() == Opcodes.INVOKESPECIAL) {
            MethodInsnNode methodNode = (MethodInsnNode)insn;
            if (Constants.CTOR.equals(methodNode.name)) {
                if (news > 0) {
                    news--;
                } else {
                    boolean isSuper = methodNode.owner.equals(superName);
                    if (isSuper || methodNode.owner.equals(ownerName)) {
                        return new DelegateInitialiser(methodNode, isSuper);
                    }
                }
            }
        }
    }
    return DelegateInitialiser.NONE;
}
 
Example 9
Source File: AccessorGeneratorMethodProxy.java    From Mixin with MIT License 5 votes vote down vote up
@Override
public MethodNode generate() {
    int size = Bytecode.getArgsSize(this.argTypes) + this.returnType.getSize() + (this.targetIsStatic ? 0 : 1);
    MethodNode method = this.createMethod(size, size);
    if (!this.targetIsStatic) {
        method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
    }
    Bytecode.loadArgs(this.argTypes, method.instructions, this.targetIsStatic ? 0 : 1);
    boolean isPrivate = Bytecode.hasFlag(this.targetMethod, Opcodes.ACC_PRIVATE);
    int opcode = this.targetIsStatic ? Opcodes.INVOKESTATIC : (isPrivate ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL);
    method.instructions.add(new MethodInsnNode(opcode, this.info.getClassNode().name, this.targetMethod.name, this.targetMethod.desc, false));
    method.instructions.add(new InsnNode(this.returnType.getOpcode(Opcodes.IRETURN)));
    return method;
}
 
Example 10
Source File: LambdaDesugaring.java    From bazel with Apache License 2.0 5 votes vote down vote up
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);
  }
}
 
Example 11
Source File: AnalyzerAdapter.java    From JReFrameworker with MIT License 5 votes vote down vote up
private void doVisitMethodInsn(
    final int opcode,
    final String owner,
    final String name,
    final String descriptor,
    final boolean isInterface) {
  if (mv != null) {
    mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
  }
  if (this.locals == null) {
    labels = null;
    return;
  }
  pop(descriptor);
  if (opcode != Opcodes.INVOKESTATIC) {
    Object value = pop();
    if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
      Object initializedValue;
      if (value == Opcodes.UNINITIALIZED_THIS) {
        initializedValue = this.owner;
      } else {
        initializedValue = uninitializedTypes.get(value);
      }
      for (int i = 0; i < locals.size(); ++i) {
        if (locals.get(i) == value) {
          locals.set(i, initializedValue);
        }
      }
      for (int i = 0; i < stack.size(); ++i) {
        if (stack.get(i) == value) {
          stack.set(i, initializedValue);
        }
      }
    }
  }
  pushDescriptor(descriptor);
  labels = null;
}
 
Example 12
Source File: ContinuableMethodNode.java    From tascalate-javaflow with Apache License 2.0 5 votes vote down vote up
private boolean needsFrameGuard(int opcode, String owner, String name, String desc) {
    if (owner.startsWith("java/") || owner.startsWith("javax/")) {
        //System.out.println("SKIP:: " + owner + "." + name + desc);
        return false;
    }

    // Always create save-point before Continuation methods (like suspend)
    if (CONTINUATION_CLASS_INTERNAL_NAME.equals(owner)) {
        return CONTINUATION_CLASS_CONTINUABLE_METHODS.contains(name);
    }

    // No need to create save-point before constructors -- it's forbidden to suspend in constructors anyway
    if (opcode == Opcodes.INVOKESPECIAL && "<init>".equals(name)) {
        return false;
    }

    if (opcode == Opcodes.INVOKEINTERFACE ||
        opcode == Opcodes.INVOKESPECIAL   ||
        opcode == Opcodes.INVOKESTATIC    ||
        opcode == Opcodes.INVOKEVIRTUAL) {
        ContinuableClassInfo classInfo;
        try {
            classInfo = cciResolver.resolve(owner);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
        return null != classInfo && classInfo.isContinuableMethod(opcode, name, desc, desc);
    }
    return false;
}
 
Example 13
Source File: CheckMethodAdapter.java    From Concurnas with MIT License 5 votes vote down vote up
@Override
public void visitMethodInsn(
    final int opcodeAndSource,
    final String owner,
    final String name,
    final String descriptor,
    final boolean isInterface) {
  if (api < Opcodes.ASM5 && (opcodeAndSource & Opcodes.SOURCE_DEPRECATED) == 0) {
    // Redirect the call to the deprecated version of this method.
    super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
    return;
  }
  int opcode = opcodeAndSource & ~Opcodes.SOURCE_MASK;

  checkVisitCodeCalled();
  checkVisitMaxsNotCalled();
  checkOpcodeMethod(opcode, Method.VISIT_METHOD_INSN);
  if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
    checkMethodIdentifier(version, name, "name");
  }
  checkInternalName(version, owner, "owner");
  checkMethodDescriptor(version, descriptor);
  if (opcode == Opcodes.INVOKEVIRTUAL && isInterface) {
    throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
  }
  if (opcode == Opcodes.INVOKEINTERFACE && !isInterface) {
    throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
  }
  if (opcode == Opcodes.INVOKESPECIAL && isInterface && (version & 0xFFFF) < Opcodes.V1_8) {
    throw new IllegalArgumentException(
        "INVOKESPECIAL can't be used with interfaces prior to Java 8");
  }
  super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
  ++insnCount;
}
 
Example 14
Source File: CheckMethodAdapter.java    From JReFrameworker with MIT License 5 votes vote down vote up
private void doVisitMethodInsn(
    final int opcode,
    final String owner,
    final String name,
    final String descriptor,
    final boolean isInterface) {
  checkVisitCodeCalled();
  checkVisitMaxsNotCalled();
  checkOpcodeMethod(opcode, Method.VISIT_METHOD_INSN);
  if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
    checkMethodIdentifier(version, name, "name");
  }
  checkInternalName(version, owner, "owner");
  checkMethodDescriptor(version, descriptor);
  if (opcode == Opcodes.INVOKEVIRTUAL && isInterface) {
    throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
  }
  if (opcode == Opcodes.INVOKEINTERFACE && !isInterface) {
    throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
  }
  if (opcode == Opcodes.INVOKESPECIAL && isInterface && (version & 0xFFFF) < Opcodes.V1_8) {
    throw new IllegalArgumentException(
        "INVOKESPECIAL can't be used with interfaces prior to Java 8");
  }

  // Calling super.visitMethodInsn requires to call the correct version depending on this.api
  // (otherwise infinite loops can occur). To simplify and to make it easier to automatically
  // remove the backward compatibility code, we inline the code of the overridden method here.
  if (mv != null) {
    mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
  }
  ++insnCount;
}
 
Example 15
Source File: BytecodeInstanceMethodInvokeEmitter.java    From Despector with MIT License 5 votes vote down vote up
public int getOpcode(InstanceMethodInvoke.Type type) {
    switch (type) {
    case INTERFACE:
        return Opcodes.INVOKEINTERFACE;
    case SPECIAL:
        return Opcodes.INVOKESPECIAL;
    case VIRTUAL:
    default:
        return Opcodes.INVOKEVIRTUAL;
    }
}
 
Example 16
Source File: ContinuableMethodNode.java    From tascalate-javaflow with Apache License 2.0 5 votes vote down vote up
private boolean needsFrameGuard(int opcode, String owner, String name, String desc) {
    if (owner.startsWith("java/") || owner.startsWith("javax/")) {
        //System.out.println("SKIP:: " + owner + "." + name + desc);
        return false;
    }

    // Always create save-point before Continuation methods (like suspend)
    if (CONTINUATION_CLASS_INTERNAL_NAME.equals(owner)) {
        return CONTINUATION_CLASS_CONTINUABLE_METHODS.contains(name);
    }

    // No need to create save-point before constructors -- it's forbidden to suspend in constructors anyway
    if (opcode == Opcodes.INVOKESPECIAL && "<init>".equals(name)) {
        return false;
    }

    if (opcode == Opcodes.INVOKEDYNAMIC) {
        // TODO verify CallSite to be continuable?
        return true;
    }

    if (opcode == Opcodes.INVOKEINTERFACE ||
        opcode == Opcodes.INVOKESPECIAL   ||
        opcode == Opcodes.INVOKESTATIC    ||
        opcode == Opcodes.INVOKEVIRTUAL) {
        ContinuableClassInfo classInfo;
        try {
            classInfo = cciResolver.resolve(owner);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
        return null != classInfo && classInfo.isContinuableMethod(opcode, name, desc, desc);
    }
    return false;
}
 
Example 17
Source File: Target.java    From Mixin with MIT License 5 votes vote down vote up
/**
 * Find the first <tt>&lt;init&gt;</tt> invocation after the specified
 * <tt>NEW</tt> insn 
 * 
 * @param newNode NEW insn
 * @return INVOKESPECIAL opcode of ctor, or null if not found
 */
public MethodInsnNode findInitNodeFor(TypeInsnNode newNode) {
    int start = this.indexOf(newNode);
    for (Iterator<AbstractInsnNode> iter = this.insns.iterator(start); iter.hasNext();) {
        AbstractInsnNode insn = iter.next();
        if (insn instanceof MethodInsnNode && insn.getOpcode() == Opcodes.INVOKESPECIAL) {
            MethodInsnNode methodNode = (MethodInsnNode)insn;
            if (Constants.CTOR.equals(methodNode.name) && methodNode.owner.equals(newNode.desc)) {
                return methodNode;
            }
        }
    }
    return null;
}
 
Example 18
Source File: ModuleVanillaReplacement.java    From TFC2 with GNU General Public License v3.0 4 votes vote down vote up
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) 
{
	if(basicClass == null)
		return null;

	ClassNode classNode = ASMHelper.readClassFromBytes(basicClass);

	if (transformedName.equals("net.minecraft.item.Item"))
	{
		String desc = ASMHelper.toMethodDescriptor("V");
		MethodNode methodNode = ASMHelper.findMethodNodeOfClass(classNode, "u", "registerItems", desc);

		if (methodNode != null)
		{
			InsnList list = new InsnList();
			AbstractInsnNode node0 = getLineNumber(methodNode.instructions, 1566);
			node0 = ASMHelper.find(methodNode.instructions, new IntInsnNode(Opcodes.SIPUSH, 337));
			node0 = node0.getNext().getNext();
			AbstractInsnNode newNode = new TypeInsnNode(Opcodes.NEW, gi("com/bioxx/tfc2/items/ItemClayBall"));
			methodNode.instructions.insert(node0, newNode);
			methodNode.instructions.remove(node0);

			node0 = newNode.getNext().getNext();
			MethodInsnNode method = new MethodInsnNode(Opcodes.INVOKESPECIAL, gi("com/bioxx/tfc2/items/ItemClayBall"), "<init>", ASMHelper.toMethodDescriptor("V"), false);
			methodNode.instructions.insert(node0, method);
			methodNode.instructions.remove(node0);
		}
		else
		{
			String msg = "Unable to replace vanilla clay_ball item";
			for(MethodNode m : classNode.methods)
			{
				msg += m.name+", ";
			}
			throw new RuntimeException(msg);
		}
	}
	/*else if (transformedName.equals("net.minecraft.world.gen.feature.WorldGenTallGrass") || 
			transformedName.equals("net.minecraft.world.gen.feature.WorldGenDoublePlant"))
	{
		String desc = ASMHelper.toMethodDescriptor("Z",ObfHelper.toObfClassName(ASMConstants.WORLD),ObfHelper.toObfClassName(ASMConstants.RANDOM),ObfHelper.toObfClassName(ASMConstants.BLOCK_POS));
		MethodNode methodNode = ASMHelper.findMethodNodeOfClass(classNode, "b", "generate", desc);

		if (methodNode != null)
		{
			InsnList list = new InsnList();
			methodNode.instructions.clear();
			list.add(new InsnNode(Opcodes.ICONST_1));
			list.add(new InsnNode(Opcodes.IRETURN));
			methodNode.instructions.insert(list);
		}
		else
			throw new RuntimeException("WorldGenTallGrass | WorldGenDoublePlant: generate (b) method not found");
	}*/

	return ASMHelper.writeClassToBytes(classNode);
}
 
Example 19
Source File: LambdaDesugaring.java    From bazel with Apache License 2.0 4 votes vote down vote up
@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);
    lambdas.generateLambdaClass(
        internalName,
        LambdaInfo.create(
            lambdaClassName,
            desc,
            needFactory,
            bridgeInfo.methodReference(),
            bridgeInfo.bridgeMethod()),
        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);
  }
}
 
Example 20
Source File: InterfaceDesugaring.java    From bazel with Apache License 2.0 4 votes vote down vote up
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
  // Assume that any static interface methods on the classpath are moved
  if ((itf || owner.equals(interfaceName)) && !bootclasspath.isKnown(owner)) {
    if (name.startsWith("lambda$")) {
      // Redirect lambda invocations to completely remove all lambda methods from interfaces.
      checkArgument(
          !owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX),
          "shouldn't consider %s an interface",
          owner);
      if (opcode == Opcodes.INVOKEINTERFACE) {
        opcode = Opcodes.INVOKESTATIC;
        desc = companionDefaultMethodDescriptor(owner, desc);
      } else {
        checkArgument(
            opcode == Opcodes.INVOKESTATIC,
            "Unexpected opcode %s to invoke %s.%s",
            opcode,
            owner,
            name);
      }
      // Reflect that InterfaceDesugaring moves and renames the lambda body method
      name = normalizeInterfaceMethodName(name, /*isLambda=*/ true, opcode);
      owner += DependencyCollector.INTERFACE_COMPANION_SUFFIX;
      itf = false;
      // Record dependency on companion class
      depsCollector.assumeCompanionClass(declaringClass, owner);

      String expectedLambdaMethodName = LambdaDesugaring.uniqueInPackage(owner, name);
      checkState(
          name.equals(expectedLambdaMethodName),
          "Unexpected lambda body method name for %s: real=%s, expected=%s",
          owner,
          name,
          expectedLambdaMethodName);
    } else if ((opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.INVOKESPECIAL)) {
      checkArgument(
          !owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX),
          "shouldn't consider %s an interface",
          owner);
      if (opcode == Opcodes.INVOKESPECIAL) {
        // Turn Interface.super.m() into DefiningInterface$$CC.m(receiver). Note that owner
        // always refers to the current type's immediate super-interface, but the default method
        // may be inherited by that interface, so we have to figure out where the method is
        // defined and invoke it in the corresponding companion class (b/73355452).  Note that
        // we're always dealing with interfaces here, and all interface methods are public,
        // so using Class.getMethods should suffice to find inherited methods.  Also note this
        // can only be a default method invocation, no abstract method invocation.
        owner =
            findDefaultMethod(owner, name, desc)
                .getDeclaringClass()
                .getName()
                .replace('.', '/');
        desc = companionDefaultMethodDescriptor(owner, desc);
      }
      name = normalizeInterfaceMethodName(name, /*isLambda=*/ false, opcode);
      owner += DependencyCollector.INTERFACE_COMPANION_SUFFIX;
      opcode = Opcodes.INVOKESTATIC;
      itf = false;
      // Record dependency on companion class
      depsCollector.assumeCompanionClass(declaringClass, owner);
    } // else non-lambda INVOKEINTERFACE, which needs no rewriting
  }
  super.visitMethodInsn(opcode, owner, name, desc, itf);
}