下面列出了org.objectweb.asm.Opcodes# INVOKESPECIAL 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@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);
}
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);
}
}
@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);
}
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();
}
}
@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);
}
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();
}
}
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();
}
}
/**
* Find the first <tt><init></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;
}
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;
}
public int getOpcode(InstanceMethodInvoke.Type type) {
switch (type) {
case INTERFACE:
return Opcodes.INVOKEINTERFACE;
case SPECIAL:
return Opcodes.INVOKESPECIAL;
case VIRTUAL:
default:
return Opcodes.INVOKEVIRTUAL;
}
}
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;
}
@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;
}
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;
}
/**
* Find the call to <tt>super()</tt> or <tt>this()</tt> in a constructor.
* This attempts to locate the first call to <tt><init></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;
}
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;
}
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);
}
}
@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;
}
@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);
}
@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);
}
}
@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);
}