use of org.objectweb.asm.tree.ClassNode in project LogisticsPipes by RS485.
the class LogisticsClassTransformer method addAddInfoPart.
private byte[] addAddInfoPart(byte[] bytes, String className) {
final ClassReader reader = new ClassReader(bytes);
final ClassNode node = new ClassNode();
reader.accept(node, 0);
node.interfaces.add("logisticspipes/asm/addinfo/IAddInfoProvider");
{
FieldVisitor fv = node.visitField(Opcodes.ACC_PRIVATE, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;", "Ljava/util/ArrayList<Llogisticspipes/asm/addinfo/IAddInfo;>;", null);
fv.visitEnd();
}
MethodVisitor mv;
{
mv = node.visitMethod(Opcodes.ACC_PUBLIC, "getLogisticsPipesAddInfo", "(Ljava/lang/Class;)Llogisticspipes/asm/addinfo/IAddInfo;", "<T::Llogisticspipes/asm/addinfo/IAddInfo;>(Ljava/lang/Class<TT;>;)TT;", null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(11, l0);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
Label l1 = new Label();
mv.visitJumpInsn(Opcodes.IFNONNULL, l1);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLineNumber(12, l2);
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitInsn(Opcodes.ARETURN);
mv.visitLabel(l1);
mv.visitLineNumber(14, l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/ArrayList", "iterator", "()Ljava/util/Iterator;", false);
mv.visitVarInsn(Opcodes.ASTORE, 2);
Label l3 = new Label();
mv.visitLabel(l3);
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "java/util/Iterator" }, 0, null);
mv.visitVarInsn(Opcodes.ALOAD, 2);
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true);
Label l4 = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, l4);
mv.visitVarInsn(Opcodes.ALOAD, 2);
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true);
mv.visitTypeInsn(Opcodes.CHECKCAST, "logisticspipes/asm/addinfo/IAddInfo");
mv.visitVarInsn(Opcodes.ASTORE, 3);
Label l5 = new Label();
mv.visitLabel(l5);
mv.visitLineNumber(15, l5);
mv.visitVarInsn(Opcodes.ALOAD, 3);
Label l6 = new Label();
mv.visitJumpInsn(Opcodes.IFNONNULL, l6);
mv.visitJumpInsn(Opcodes.GOTO, l3);
mv.visitLabel(l6);
mv.visitLineNumber(16, l6);
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "logisticspipes/asm/addinfo/IAddInfo" }, 0, null);
mv.visitVarInsn(Opcodes.ALOAD, 3);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mv.visitVarInsn(Opcodes.ALOAD, 1);
Label l7 = new Label();
mv.visitJumpInsn(Opcodes.IF_ACMPNE, l7);
Label l8 = new Label();
mv.visitLabel(l8);
mv.visitLineNumber(17, l8);
mv.visitVarInsn(Opcodes.ALOAD, 3);
mv.visitInsn(Opcodes.ARETURN);
mv.visitLabel(l7);
mv.visitLineNumber(19, l7);
mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
mv.visitJumpInsn(Opcodes.GOTO, l3);
mv.visitLabel(l4);
mv.visitLineNumber(20, l4);
mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitInsn(Opcodes.ARETURN);
Label l9 = new Label();
mv.visitLabel(l9);
mv.visitLocalVariable("info", "Llogisticspipes/asm/addinfo/IAddInfo;", null, l5, l7, 3);
mv.visitLocalVariable("this", "L" + className + ";", null, l0, l9, 0);
mv.visitLocalVariable("clazz", "Ljava/lang/Class;", "Ljava/lang/Class<TT;>;", l0, l9, 1);
mv.visitMaxs(2, 4);
mv.visitEnd();
}
{
mv = node.visitMethod(Opcodes.ACC_PUBLIC, "setLogisticsPipesAddInfo", "(Llogisticspipes/asm/addinfo/IAddInfo;)V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(25, l0);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
Label l1 = new Label();
mv.visitJumpInsn(Opcodes.IFNONNULL, l1);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLineNumber(26, l2);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitTypeInsn(Opcodes.NEW, "java/util/ArrayList");
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
mv.visitFieldInsn(Opcodes.PUTFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
mv.visitLabel(l1);
mv.visitLineNumber(28, l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitVarInsn(Opcodes.ISTORE, 2);
Label l3 = new Label();
mv.visitLabel(l3);
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { Opcodes.INTEGER }, 0, null);
mv.visitVarInsn(Opcodes.ILOAD, 2);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/ArrayList", "size", "()I", false);
Label l4 = new Label();
mv.visitJumpInsn(Opcodes.IF_ICMPGE, l4);
Label l5 = new Label();
mv.visitLabel(l5);
mv.visitLineNumber(29, l5);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
mv.visitVarInsn(Opcodes.ILOAD, 2);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/ArrayList", "get", "(I)Ljava/lang/Object;", false);
Label l6 = new Label();
mv.visitJumpInsn(Opcodes.IFNONNULL, l6);
Label l7 = new Label();
mv.visitJumpInsn(Opcodes.GOTO, l7);
mv.visitLabel(l6);
mv.visitLineNumber(30, l6);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
mv.visitVarInsn(Opcodes.ILOAD, 2);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/ArrayList", "get", "(I)Ljava/lang/Object;", false);
mv.visitTypeInsn(Opcodes.CHECKCAST, "logisticspipes/asm/addinfo/IAddInfo");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mv.visitJumpInsn(Opcodes.IF_ACMPNE, l7);
Label l8 = new Label();
mv.visitLabel(l8);
mv.visitLineNumber(31, l8);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
mv.visitVarInsn(Opcodes.ILOAD, 2);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/ArrayList", "set", "(ILjava/lang/Object;)Ljava/lang/Object;", false);
mv.visitInsn(Opcodes.POP);
Label l9 = new Label();
mv.visitLabel(l9);
mv.visitLineNumber(32, l9);
mv.visitInsn(Opcodes.RETURN);
mv.visitLabel(l7);
mv.visitLineNumber(28, l7);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitIincInsn(2, 1);
mv.visitJumpInsn(Opcodes.GOTO, l3);
mv.visitLabel(l4);
mv.visitLineNumber(35, l4);
mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, "logisticsPipesAdditionalInformation", "Ljava/util/ArrayList;");
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/ArrayList", "add", "(Ljava/lang/Object;)Z", false);
mv.visitInsn(Opcodes.POP);
Label l10 = new Label();
mv.visitLabel(l10);
mv.visitLineNumber(36, l10);
mv.visitInsn(Opcodes.RETURN);
Label l11 = new Label();
mv.visitLabel(l11);
mv.visitLocalVariable("i", "I", null, l3, l4, 2);
mv.visitLocalVariable("this", "L" + className + ";", null, l0, l11, 0);
mv.visitLocalVariable("info", "Llogisticspipes/asm/addinfo/IAddInfo;", null, l0, l11, 1);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
node.accept(writer);
return writer.toByteArray();
}
use of org.objectweb.asm.tree.ClassNode in project LogisticsPipes by RS485.
the class LogisticsClassTransformer method transform.
@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
// if dev environment and transform on first class is launched, boot the AT remapper
if (LogisticsPipesCoreLoader.isDevelopmentEnvironment() && name.equals("net.minecraftforge.fml.common.Loader"))
bootATRemapper();
Thread thread = Thread.currentThread();
if (thread.getName().equals("Minecraft main thread") || thread.getName().equals("main") || thread.getName().equals("Server thread")) {
// Only clear when called from the main thread to avoid ConcurrentModificationException on start
clearNegativeInterfaceCache();
}
if (bytes == null) {
return null;
}
if (transformedName.startsWith("logisticspipes.") || transformedName.startsWith("net.minecraft")) {
return ParamProfiler.handleClass(applyLPTransforms(transformedName, bytes));
}
byte[] tmp = bytes.clone();
bytes = applyLPTransforms(transformedName, bytes);
if (!Arrays.equals(bytes, tmp)) {
final ClassReader reader = new ClassReader(bytes);
final ClassNode node = new ClassNode();
reader.accept(node, 0);
node.sourceFile = "[LP|ASM] " + node.sourceFile;
ClassWriter writer = new ClassWriter(0);
node.accept(writer);
bytes = writer.toByteArray();
}
return ParamProfiler.handleClass(bytes);
}
use of org.objectweb.asm.tree.ClassNode in project LogisticsPipes by RS485.
the class ParamProfiler method handleClass.
public static byte[] handleClass(byte[] bytes) {
if (!isActive)
return bytes;
final ClassReader reader = new ClassReader(bytes);
final ClassNode node = new ClassNode();
reader.accept(node, 0);
final String className = node.name;
for (final MethodNode m : node.methods) {
final String methodName = m.name;
final String methodDesc = m.desc;
final boolean isConst = methodName.contains("<") || methodName.contains(">");
if (isConst)
continue;
final long methodId = minMethodId++;
final List<String> varList = new ArrayList<>();
if (!methodDesc.startsWith("("))
throw new UnsupportedOperationException(methodDesc);
outer: for (int i = 1; i < methodDesc.length(); i++) {
switch(methodDesc.charAt(i)) {
case ')':
break outer;
case 'L':
int startA = i;
while (methodDesc.charAt(i) != ';') i++;
varList.add(methodDesc.substring(startA, i + 1));
break;
case '[':
int startB = i;
while (methodDesc.charAt(i) == '[') i++;
if (methodDesc.charAt(i) == 'L') {
while (methodDesc.charAt(i) != ';') i++;
}
varList.add(methodDesc.substring(startB, i + 1));
break;
default:
varList.add(String.valueOf(methodDesc.charAt(i)));
}
}
final List<Label> catchStatement = new ArrayList<>();
MethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {
@Override
public void visitCode() {
super.visitCode();
Label l0 = new Label();
visitLabel(l0);
visitLdcInsn(new Long(methodId));
visitLdcInsn(className + "+" + methodName + "+" + methodDesc);
if ((m.access & Opcodes.ACC_STATIC) != 0) {
visitInsn(Opcodes.ACONST_NULL);
} else {
visitVarInsn(Opcodes.ALOAD, 0);
}
visitIntInsn(Opcodes.BIPUSH, varList.size());
visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
int count = 0;
int pos = 0;
if ((m.access & Opcodes.ACC_STATIC) == 0) {
pos = 1;
}
for (String varNode : varList) {
visitInsn(Opcodes.DUP);
visitIntInsn(Opcodes.BIPUSH, count++);
if (!varNode.startsWith("L") && !varNode.startsWith("[")) {
switch(varNode.charAt(0)) {
case 'I':
visitVarInsn(Opcodes.ILOAD, pos);
pos += 1;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
break;
case 'J':
visitVarInsn(Opcodes.LLOAD, pos);
pos += 2;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
break;
case 'Z':
visitVarInsn(Opcodes.ILOAD, pos);
pos += 1;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
break;
case 'B':
visitVarInsn(Opcodes.ILOAD, pos);
pos += 1;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
break;
case 'C':
visitVarInsn(Opcodes.ILOAD, pos);
pos += 1;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
break;
case 'S':
visitVarInsn(Opcodes.ILOAD, pos);
pos += 1;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
break;
case 'F':
visitVarInsn(Opcodes.FLOAD, pos);
pos += 1;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
break;
case 'D':
visitVarInsn(Opcodes.DLOAD, pos);
pos += 2;
visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
break;
default:
throw new UnsupportedOperationException("'" + varNode + "'");
}
} else {
visitVarInsn(Opcodes.ALOAD, pos);
pos += 1;
}
visitInsn(Opcodes.AASTORE);
}
visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/ParamProfiler", "methodStart", "(JLjava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V", false);
}
@Override
public void visitInsn(int opcode) {
if (opcode == Opcodes.RETURN || opcode == Opcodes.IRETURN || opcode == Opcodes.LRETURN || opcode == Opcodes.FRETURN || opcode == Opcodes.DRETURN || opcode == Opcodes.ARETURN) {
visitLdcInsn(new Long(methodId));
visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/ParamProfiler", "methodEnd", "(J)V", false);
}
super.visitInsn(opcode);
}
@Override
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
catchStatement.add(handler);
super.visitTryCatchBlock(start, end, handler, type);
}
boolean watchForHandling = false;
@Override
public void visitLabel(Label label) {
watchForHandling = false;
super.visitLabel(label);
if (catchStatement.contains(label)) {
watchForHandling = true;
}
}
@Override
public void visitVarInsn(int opcode, int var) {
super.visitVarInsn(opcode, var);
if (watchForHandling) {
watchForHandling = false;
Label l = new Label();
visitLabel(l);
visitVarInsn(Opcodes.ALOAD, var);
visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/ParamProfiler", "handleException", "(Ljava/lang/Throwable;)V", false);
}
}
};
m.accept(mv);
node.methods.set(node.methods.indexOf(m), mv);
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
node.accept(writer);
return writer.toByteArray();
}
use of org.objectweb.asm.tree.ClassNode in project LogisticsPipes by RS485.
the class LogisticsPipesClassInjector method transform.
@Override
@SuppressWarnings("unchecked")
public byte[] transform(String name, String transformedName, byte[] bytes) {
if (bytes != null) {
if (name.startsWith("logisticspipes.")) {
final ClassReader reader = new ClassReader(bytes);
final ClassNode node = new ClassNode();
reader.accept(node, 0);
if (node.visibleAnnotations != null) {
for (AnnotationNode a : node.visibleAnnotations) {
if (a.desc.equals("Llogisticspipes/asm/ModVersionedClass;")) {
if (a.values.size() == 8 && a.values.get(0).equals("modId") && a.values.get(2).equals("version") && a.values.get(4).equals("classData") && a.values.get(6).equals("classDataDev")) {
String modId = a.values.get(1).toString();
String version = a.values.get(3).toString();
String classData = a.values.get(5).toString();
String classDataDev = a.values.get(7).toString();
if (ModStatusHelper.isModLoaded(modId) && !ModStatusHelper.isModVersionEqualsOrHigher(modId, version)) {
if (isObfEnv == null) {
try {
isObfEnv = (Class.forName("net.minecraft.world.World").getDeclaredField("chunkProvider") == null);
} catch (Throwable e) {
isObfEnv = true;
}
}
bytes = transform(name, transformedName, BaseEncoding.base64().decode(isObfEnv ? classData : classDataDev));
}
} else {
throw new UnsupportedOperationException("Can't parse the annotations correctly");
}
}
}
}
}
return bytes;
}
try {
if (name.startsWith("logisticspipes.proxy.opencomputers.asm.BaseWrapperClass$") && name.endsWith("$OpenComputersWrapper")) {
String correctName = name.substring(56, name.length() - 21);
Class<?> clazz = Launch.classLoader.findClass(correctName);
bytes = ClassCreator.getWrappedClassAsBytes(CCObjectWrapper.getWrapperInformation(clazz), clazz.getName());
Set<String> set = new TreeSet<>();
set.add(name);
Launch.classLoader.clearNegativeEntries(set);
Map<String, byte[]> map = (Map<String, byte[]>) fResourceCache.get(Launch.classLoader);
map.put(name, bytes);
return bytes;
}
} catch (Exception e) {
if (LogisticsPipes.isDEBUG()) {
// For better Debugging
e.printStackTrace();
return bytes;
}
throw new RuntimeException(e);
}
return bytes;
}
use of org.objectweb.asm.tree.ClassNode in project dex2jar by pxb1988.
the class WaveTest method test0.
private void test0(InvocationWeaver iw, String prefix) throws IOException, RecognitionException {
ClassNode before = Jasmins.parse(prefix + "-before.j", getClass().getResourceAsStream("/weave/" + prefix + "-before.j"));
ClassNode expectedAfter = Jasmins.parse(prefix + "-after.j", getClass().getResourceAsStream("/weave/" + prefix + "-after.j"));
ClassNode expectedGen = Jasmins.parse(prefix + "-gen.j", getClass().getResourceAsStream("/weave/" + prefix + "-gen.j"));
ClassNode after = new ClassNode();
before.accept(iw.wrapper(after));
assertEqual(expectedAfter, after);
ClassNode gen = new ClassNode();
iw.buildInvocationClz(LdcOptimizeAdapter.wrap(gen));
assertEqual(expectedGen, gen);
}
Aggregations