124 lines
4.5 KiB
Java
124 lines
4.5 KiB
Java
package io.gitlab.jfronny.libjf.config.plugin.util;
|
|
|
|
import io.gitlab.jfronny.libjf.config.plugin.BuildMetadata;
|
|
import io.gitlab.jfronny.libjf.config.plugin.asm.value.KnownTypes;
|
|
import org.objectweb.asm.*;
|
|
import org.objectweb.asm.commons.GeneratorAdapter;
|
|
import org.objectweb.asm.commons.Method;
|
|
|
|
import java.lang.invoke.LambdaMetafactory;
|
|
|
|
import static org.objectweb.asm.Opcodes.ASM9;
|
|
import static org.objectweb.asm.Opcodes.H_INVOKESTATIC;
|
|
|
|
public class GeneratorAdapter2 extends GeneratorAdapter {
|
|
private static final Handle metafactory = new Handle(
|
|
H_INVOKESTATIC,
|
|
Type.getInternalName(LambdaMetafactory.class),
|
|
"metafactory",
|
|
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
|
|
false
|
|
);
|
|
|
|
public GeneratorAdapter2(MethodVisitor methodVisitor, int access, String name, String descriptor) {
|
|
super(ASM9, methodVisitor, access, name, descriptor);
|
|
}
|
|
|
|
public void λ(String lambdaMethodName, String lambdaType, Type lambdaDescriptor, Type implDescriptor, String implOwner, String implName) {
|
|
invokeDynamic(lambdaMethodName,
|
|
lambdaType,
|
|
metafactory,
|
|
lambdaDescriptor,
|
|
new Handle(H_INVOKESTATIC, implOwner, implName, implDescriptor.getInternalName(), false),
|
|
implDescriptor);
|
|
}
|
|
|
|
public void λ(String lambdaMethodName, String lambdaType, Type descriptor, String implOwner, String implName) {
|
|
λ(lambdaMethodName, lambdaType, descriptor, descriptor, implOwner, implName);
|
|
}
|
|
|
|
public void runnable(String implOwner, String implName) {
|
|
λ("run",
|
|
"()Ljava/lang/Runnable;",
|
|
Type.getType("()V"),
|
|
implOwner,
|
|
implName);
|
|
}
|
|
|
|
public void supplier(String implOwner, String implName, Type implDescriptor) {
|
|
λ("get",
|
|
"()Ljava/util/function/Supplier;",
|
|
Type.getType("()Ljava/lang/Object;"),
|
|
implDescriptor,
|
|
implOwner,
|
|
implName);
|
|
}
|
|
|
|
public void consumer(String implOwner, String implName, Type implDescriptor) {
|
|
λ("accept",
|
|
"()Ljava/util/function/Consumer;",
|
|
Type.getType("(Ljava/lang/Object;)V"),
|
|
implDescriptor,
|
|
implOwner,
|
|
implName);
|
|
}
|
|
|
|
public void box(Type type) {
|
|
Type boxedType;
|
|
switch (type.getSort()) {
|
|
case Type.VOID:
|
|
return;
|
|
case Type.CHAR:
|
|
boxedType = KnownTypes.CHARACTER_BOX_TYPE;
|
|
break;
|
|
case Type.BOOLEAN:
|
|
boxedType = KnownTypes.BOOLEAN_BOX_TYPE;
|
|
break;
|
|
case Type.DOUBLE:
|
|
boxedType = KnownTypes.DOUBLE_BOX_TYPE;
|
|
break;
|
|
case Type.FLOAT:
|
|
boxedType = KnownTypes.FLOAT_BOX_TYPE;
|
|
break;
|
|
case Type.LONG:
|
|
boxedType = KnownTypes.LONG_BOX_TYPE;
|
|
break;
|
|
case Type.INT:
|
|
boxedType = KnownTypes.INT_BOX_TYPE;
|
|
break;
|
|
case Type.SHORT:
|
|
boxedType = KnownTypes.SHORT_BOX_TYPE;
|
|
break;
|
|
case Type.BYTE:
|
|
boxedType = KnownTypes.BYTE_BOX_TYPE;
|
|
break;
|
|
default:
|
|
boxedType = null;
|
|
break;
|
|
}
|
|
if (boxedType == null) {
|
|
comment("Unkown boxed type, simply casting");
|
|
checkCast(type);
|
|
} else {
|
|
comment("Boxing " + type + " to " + boxedType);
|
|
invokeStatic(boxedType, new Method("valueOf", boxedType, new Type[]{type}));
|
|
}
|
|
}
|
|
|
|
public void invokeIStatic(Type owner, Method method) {
|
|
invokeInsn(Opcodes.INVOKESTATIC, owner, method, true);
|
|
}
|
|
|
|
public void comment(String comment) {
|
|
if (BuildMetadata.isRelease) return;
|
|
push("[Comment/Generator] " + comment);
|
|
pop();
|
|
}
|
|
|
|
// Taken from GeneratorAdapter
|
|
private void invokeInsn(final int opcode, final Type type, final Method method, final boolean isInterface) {
|
|
String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName();
|
|
mv.visitMethodInsn(opcode, owner, method.getName(), method.getDescriptor(), isInterface);
|
|
}
|
|
}
|