Example usage for org.objectweb.asm ClassWriter COMPUTE_MAXS

List of usage examples for org.objectweb.asm ClassWriter COMPUTE_MAXS

Introduction

In this page you can find the example usage for org.objectweb.asm ClassWriter COMPUTE_MAXS.

Prototype

int COMPUTE_MAXS

To view the source code for org.objectweb.asm ClassWriter COMPUTE_MAXS.

Click Source Link

Document

A flag to automatically compute the maximum stack size and the maximum number of local variables of methods.

Usage

From source file:Java6to2.java

License:Open Source License

private static byte[] transform(InputStream classfile) throws IOException {
    ClassReader cr = new ClassReader(classfile);
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = new ClassVisitor(ASM7, cw) {
        String internalName;/*from   w  w  w. j  a v  a  2 s  .  c o  m*/
        boolean classLookupMethodGenerated;
        Set fieldsGenerated = new HashSet();

        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
            /* Change class file version to 1.2 */
            cv.visit(V1_2, access, name, signature, superName, interfaces);
            this.internalName = name;
        }

        /**
         * Generates the synthetic "class$" method, used to lookup classes via Class.forName(). This uses the exact same code as does JDK8 javac for target 1.2.
         */
        void generateSyntheticClassLookupMethod() {
            MethodVisitor mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "class$",
                    "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
            {
                Label start = new Label();
                Label end = new Label();
                Label handler = new Label();
                mv.visitTryCatchBlock(start, end, handler, "java/lang/ClassNotFoundException");
                mv.visitLabel(start);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName",
                        "(Ljava/lang/String;)Ljava/lang/Class;", false);
                mv.visitLabel(end);
                mv.visitInsn(ARETURN);
                mv.visitLabel(handler);
                mv.visitVarInsn(ASTORE, 1);
                mv.visitTypeInsn(NEW, "java/lang/NoClassDefFoundError");
                mv.visitInsn(DUP);
                mv.visitMethodInsn(INVOKESPECIAL, "java/lang/NoClassDefFoundError", "<init>", "()V", false);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoClassDefFoundError", "initCause",
                        "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", false);
                mv.visitInsn(ATHROW);
            }
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }

        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            final ClassVisitor cv = this.cv;
            return new MethodVisitor(ASM7, mv) {
                /**
                 * Intercepts class instantiations to see whether they instantiate a StringBuilder. Those instructions were generated by javac for string concatenations. But
                 * StringBuilder is not available on JRE1.2, so we just replace it with StringBuffer.
                 */
                public void visitTypeInsn(int opcode, String type) {
                    if (opcode == NEW && "java/lang/StringBuilder".equals(type)) {
                        mv.visitTypeInsn(opcode, "java/lang/StringBuffer");
                    } else {
                        mv.visitTypeInsn(opcode, type);
                    }
                }

                /**
                 * Intercepts method invocations to see whether they do something with StringBuilder. Those instructions were generated by javac for string concatenations. But
                 * StringBuilder is not available on JRE1.2, so we just replace it with StringBuffer.
                 */
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    if ("java/lang/StringBuilder".equals(owner)) {
                        mv.visitMethodInsn(opcode, "java/lang/StringBuffer", name,
                                desc.replace("java/lang/StringBuilder", "java/lang/StringBuffer"), itf);
                    } else {
                        mv.visitMethodInsn(opcode, owner, name, desc, itf);
                    }
                }

                /**
                 * Intercepts LDC instructions and check whether they are used to load a class. This is not supported on Java 1.2, so we convert it to the same code used by the
                 * JDK8 javac:
                 * <ul>
                 * <li>create synthetic fields holding the resolved class objects
                 * <li>create a synthetic method called "class$" which does Class.forName
                 * </ul>
                 */
                public void visitLdcInsn(Object cst) {
                    if (cst instanceof Type) {
                        Type t = (Type) cst;
                        String syntheticField = "class$"
                                + t.getInternalName().replace('/', '$').replace("[", "");
                        if (!classLookupMethodGenerated) {
                            /* Emit the synthetic "class$" method, used to lookup classes via Class.forName() */
                            generateSyntheticClassLookupMethod();
                            classLookupMethodGenerated = true;
                        }
                        if (!fieldsGenerated.contains(syntheticField)) {
                            /* Generate a synthetic field holding the resolved Class object */
                            cv.visitField(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, syntheticField,
                                    "Ljava/lang/Class;", null, null);
                            fieldsGenerated.add(syntheticField);
                        }
                        mv.visitFieldInsn(GETSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        Label nonNull = new Label();
                        mv.visitJumpInsn(IFNONNULL, nonNull);
                        mv.visitLdcInsn(t.getInternalName().replace('/', '.'));
                        mv.visitMethodInsn(INVOKESTATIC, internalName, "class$",
                                "(Ljava/lang/String;)Ljava/lang/Class;", false);
                        mv.visitInsn(DUP);
                        mv.visitFieldInsn(PUTSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        Label cnt = new Label();
                        mv.visitJumpInsn(GOTO, cnt);
                        mv.visitLabel(nonNull);
                        mv.visitFieldInsn(GETSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        mv.visitLabel(cnt);
                    } else {
                        mv.visitLdcInsn(cst);
                    }
                }
            };
        }
    };
    cr.accept(cv, ClassReader.SKIP_FRAMES); // <- Frames are not used in Java 1.2, so skip them
    return cw.toByteArray();
}

From source file:analysis.RuntimeTemplateGenerator.java

License:Open Source License

public JarClasses generateTemplate() {
    ClassReader classReader;// ww w. j av  a  2s.  c  o m
    ClassVisitor classVisitor;
    ClassWriter classWriter;

    Map<String, JarClasses.Entry> entries = new HashMap<String, JarClasses.Entry>();

    for (ClassReference ref : references) {
        classReader = classes.get(ref.getName());

        classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        classVisitor = getClassTransformer(ref, classWriter);

        classReader.accept(classVisitor, ClassReader.SKIP_FRAMES);

        entries.put(ref.getName(), new JarClasses.Entry(classWriter.toByteArray(), ref.getName()));
    }

    return new JarClasses(entries);
}

From source file:appeng.core.api.ApiPart.java

License:Open Source License

public Class getClassByDesc(String addendum, String fullPath, String root, String next) {
    if (this.roots.get(fullPath) != null) {
        return this.roots.get(fullPath);
    }/*from  w  w  w  .  j ava2 s  .  c o m*/

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    ClassNode n = this.getReader(next);
    String originalName = n.name;

    try {
        n.name = n.name + '_' + addendum;
        n.superName = Class.forName(root).getName().replace(".", "/");
    } catch (Throwable t) {
        AELog.error(t);
    }

    for (MethodNode mn : n.methods) {
        Iterator<AbstractInsnNode> i = mn.instructions.iterator();
        while (i.hasNext()) {
            this.processNode(i.next(), n.superName);
        }
    }

    DefaultPackageClassNameRemapper remapper = new DefaultPackageClassNameRemapper();
    remapper.inputOutput.put("appeng/api/parts/LayerBase", n.superName);
    remapper.inputOutput.put(originalName, n.name);
    n.accept(new RemappingClassAdapter(cw, remapper));
    // n.accept( cw );

    // n.accept( new TraceClassVisitor( new PrintWriter( System.out ) ) );
    byte[] byteArray = cw.toByteArray();
    int size = byteArray.length;
    Class clazz = this.loadClass(n.name.replace("/", "."), byteArray);

    try {
        Object fish = clazz.newInstance();
        Class rootC = Class.forName(root);

        boolean hasError = false;

        if (!rootC.isInstance(fish)) {
            hasError = true;
            AELog.severe("Error, Expected layer to implement " + root + " did not.");
        }

        if (fish instanceof LayerBase) {
            hasError = true;
            AELog.severe("Error, Expected layer to NOT implement LayerBase but it DID.");
        }

        if (!fullPath.contains(".fmp.")) {
            if (!(fish instanceof TileCableBus)) {
                hasError = true;
                AELog.severe("Error, Expected layer to implement TileCableBus did not.");
            }

            if (!(fish instanceof TileEntity)) {
                hasError = true;
                AELog.severe("Error, Expected layer to implement TileEntity did not.");
            }
        }

        if (!hasError) {
            AELog.info("Layer: " + n.name + " loaded successfully - " + size + " bytes");
        }
    } catch (Throwable t) {
        AELog.severe("Layer: " + n.name + " Failed.");
        AELog.error(t);
    }

    this.roots.put(fullPath, clazz);
    return clazz;
}

From source file:appeng.coremod.asm.ASMIntegration.java

License:Open Source License

@Nullable
@Override// w ww. j  a va2 s.com
public byte[] transform(final String name, final String transformedName, final byte[] basicClass) {
    if (basicClass == null || transformedName.startsWith("appeng.coremod")) {
        return basicClass;
    }

    if (transformedName.startsWith("appeng.")) {
        final ClassNode classNode = new ClassNode();
        final ClassReader classReader = new ClassReader(basicClass);
        classReader.accept(classNode, 0);

        try {
            final boolean reWrite = this.removeOptionals(classNode);

            if (reWrite) {
                final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                classNode.accept(writer);
                return writer.toByteArray();
            }
        } catch (final Throwable t) {
            t.printStackTrace();
        }
    }
    return basicClass;
}

From source file:appeng.coremod.transformer.IntegrationTransformer.java

License:Open Source License

@Nullable
@Override//from   w ww.j  av  a 2 s .  c o  m
public byte[] transform(final String name, final String transformedName, final byte[] basicClass) {
    if (basicClass == null) {
        return basicClass;
    }

    if (transformedName.startsWith("appeng.")) {
        final ClassNode classNode = new ClassNode();
        final ClassReader classReader = new ClassReader(basicClass);
        classReader.accept(classNode, 0);

        try {
            final boolean reWrite = this.removeOptionals(classNode);

            if (reWrite) {
                final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                classNode.accept(writer);
                return writer.toByteArray();
            }
        } catch (final Throwable t) {
            t.printStackTrace();
        }
    }
    return basicClass;
}

From source file:appeng.transformer.asm.ASMIntegration.java

License:Open Source License

@Nullable
@Override/*from ww w . j  a v a  2 s. co m*/
public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (basicClass == null || transformedName.startsWith("appeng.transformer")) {
        return basicClass;
    }

    if (transformedName.startsWith("appeng.")) {
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(basicClass);
        classReader.accept(classNode, 0);

        try {
            boolean reWrite = this.removeOptionals(classNode);

            if (reWrite) {
                ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                classNode.accept(writer);
                return writer.toByteArray();
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
    return basicClass;
}

From source file:appeng.transformer.asm.ASMTweaker.java

License:Open Source License

@Nullable
@Override/*from ww w  . jav  a2s.c om*/
public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (basicClass == null) {
        return null;
    }

    try {
        if (transformedName != null && this.privateToPublicMethods.containsKey(transformedName)) {
            ClassNode classNode = new ClassNode();
            ClassReader classReader = new ClassReader(basicClass);
            classReader.accept(classNode, 0);

            for (PublicLine set : this.privateToPublicMethods.get(transformedName)) {
                this.makePublic(classNode, set);
            }

            // CALL VIRTUAL!
            if (transformedName.equals("net.minecraft.client.gui.inventory.GuiContainer")) {
                for (MethodNode mn : classNode.methods) {
                    if (mn.name.equals("func_146977_a") || (mn.name.equals("a") && mn.desc.equals("(Lzk;)V"))) {
                        MethodNode newNode = new MethodNode(Opcodes.ACC_PUBLIC, "func_146977_a_original",
                                mn.desc, mn.signature, EXCEPTIONS);
                        newNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        newNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
                        newNode.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, classNode.name,
                                mn.name, mn.desc, false));
                        newNode.instructions.add(new InsnNode(Opcodes.RETURN));
                        this.log(newNode.name + newNode.desc + " - New Method");
                        classNode.methods.add(newNode);
                        break;
                    }
                }

                for (MethodNode mn : classNode.methods) {
                    if (mn.name.equals("func_73863_a") || mn.name.equals("drawScreen")
                            || (mn.name.equals("a") && mn.desc.equals("(IIF)V"))) {
                        Iterator<AbstractInsnNode> i = mn.instructions.iterator();
                        while (i.hasNext()) {
                            AbstractInsnNode in = i.next();
                            if (in.getOpcode() == Opcodes.INVOKESPECIAL) {
                                MethodInsnNode n = (MethodInsnNode) in;
                                if (n.name.equals("func_146977_a")
                                        || (n.name.equals("a") && n.desc.equals("(Lzk;)V"))) {
                                    this.log(n.name + n.desc + " - Invoke Virtual");
                                    mn.instructions.insertBefore(n, new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
                                            n.owner, n.name, n.desc, false));
                                    mn.instructions.remove(in);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            classNode.accept(writer);
            return writer.toByteArray();
        }
    } catch (Throwable ignored) {
    }

    return basicClass;
}

From source file:autostack.Transformer.java

License:Open Source License

public byte[] transform(ClassLoader loader, final String className, Class<?> classBeingRedefined,
        ProtectionDomain protectionDomain, byte[] classfileBuffer) {
    try {/*from  w  ww  . ja  va 2  s .  c om*/
        if (className == null || className.startsWith("java/") || className.startsWith("sun/")
                || className.startsWith("jdk/internal/") || className.startsWith("org/lwjgl/"))
            return null;
        for (String pack : packages)
            if (!className.startsWith(pack))
                return null;
        ClassReader cr = new ClassReader(classfileBuffer);
        final Map<String, Integer> stackMethods = new HashMap<String, Integer>();
        // Scan all methods that need auto-stack
        if (debugTransform)
            System.out.println("[autostack] scanning methods in class: " + className.replace('/', '.'));
        cr.accept(new ClassVisitor(ASM5) {
            public MethodVisitor visitMethod(final int access, final String methodName, final String methodDesc,
                    String signature, String[] exceptions) {
                if ((access & (ACC_NATIVE | ACC_ABSTRACT)) != 0) {
                    // Don't try to analyze native or abstract methods.
                    return null;
                }
                MethodVisitor mv = new MethodVisitor(ASM5) {
                    boolean mark, catches, notransform, nostackparam, forcestack;

                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                        if ("Lautostack/NoTransform;".equals(desc))
                            notransform = true;
                        else if ("Lautostack/NoStackParam;".equals(desc))
                            nostackparam = true;
                        else if ("Lautostack/UseNewStack;".equals(desc))
                            forcestack = true;
                        return null;
                    }

                    public void visitMethodInsn(int opcode, String owner, String name, String desc,
                            boolean itf) {
                        if (opcode == INVOKESTATIC && !itf && (owner.startsWith("org/lwjgl/")
                                && (name.equals("mallocStack") || name.equals("callocStack"))
                                || owner.equals(MEMORYSTACK) && (name.equals("stackGet")
                                        || name.equals("stackPop") || name.equals("stackPush")
                                        || name.startsWith("stackMalloc") || name.startsWith("stackCalloc")
                                        || name.equals("stackUTF8") || name.equals("stackASCII")
                                        || name.equals("stackUTF16") || name.equals("stackFloats")
                                        || name.equals("stackInts") || name.equals("stackBytes")
                                        || name.equals("stackShorts") || name.equals("stackPointers")
                                        || name.equals("stackLongs")))) {
                            mark = true;
                        }
                    }

                    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
                        catches = true;
                    }

                    public void visitEnd() {
                        int flag = (access & ACC_PRIVATE) != 0 ? 8 : 0;
                        flag |= nostackparam ? 16 : 0;
                        if (mark || notransform || forcestack || nostackparam) {
                            if (notransform) {
                                flag |= 2;
                                if (debugTransform)
                                    System.out.println("[autostack]   will not transform method: "
                                            + className.replace('/', '.') + "." + methodName);
                            } else {
                                if (checkStack)
                                    flag |= 4;
                                flag |= catches ? 1 : 0;
                                if (debugTransform)
                                    System.out.println("[autostack]   will transform method: "
                                            + className.replace('/', '.') + "." + methodName);
                            }
                            stackMethods.put(methodName + methodDesc, Integer.valueOf(flag));
                        }
                    }
                };
                return mv;
            }
        }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
        if (stackMethods.isEmpty())
            return null;

        // Now, transform all such methods
        if (debugTransform)
            System.out.println("[autostack] transforming methods in class: " + className.replace('/', '.'));
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
        cr.accept(new ClassVisitor(ASM5, cw) {
            boolean classDefaultNewStack = defaultNewStack;
            boolean classNoTransform;

            @Override
            public void visit(int version, int access, String name, String signature, String superName,
                    String[] interfaces) {
                cv.visit(version, access, name, signature, superName, interfaces);
                if (!checkStack) {
                    return;
                }
                /* Generate simple synthetic "compare stack pointers and throw if not equal" method */
                MethodVisitor mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStack$",
                        "(II)V", null, new String[] { "java/lang/AssertionError" });
                {
                    mv.visitCode();
                    mv.visitVarInsn(ILOAD, 0);
                    mv.visitVarInsn(ILOAD, 1);
                    Label l0 = new Label();
                    mv.visitJumpInsn(IF_ICMPEQ, l0);
                    mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
                    mv.visitInsn(DUP);
                    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
                    mv.visitInsn(DUP);
                    mv.visitLdcInsn("Stack pointers differ: ");
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitVarInsn(ILOAD, 0);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitLdcInsn(" != ");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                            "()Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitInsn(ATHROW);
                    mv.visitLabel(l0);
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                    mv.visitInsn(RETURN);
                    mv.visitMaxs(5, 2);
                    mv.visitEnd();
                }

                mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStackWithThrowable$",
                        "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", null, null);
                {
                    mv.visitCode();
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitVarInsn(ILOAD, 2);
                    Label l0 = new Label();
                    mv.visitJumpInsn(IF_ICMPEQ, l0);
                    mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
                    mv.visitInsn(DUP);
                    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
                    mv.visitInsn(DUP);
                    mv.visitLdcInsn("Stack pointers differ: ");
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitLdcInsn(" != ");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
                    mv.visitVarInsn(ILOAD, 2);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                            "()Ljava/lang/String;", false);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
                            "(Ljava/lang/String;Ljava/lang/Throwable;)V", false);
                    mv.visitInsn(ARETURN);
                    mv.visitLabel(l0);
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitInsn(ARETURN);
                    mv.visitMaxs(5, 3);
                    mv.visitEnd();
                }
            }

            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                if ("Lautostack/UseCallerStack;".equals(desc)) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]   class declares to use caller stack for all methods, unless overridden by method");
                    classDefaultNewStack = false;
                    return null;
                } else if ("Lautostack/UseNewStack;".equals(desc)) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]   class declares to use new stack for all methods, unless overridden by method");
                    classDefaultNewStack = true;
                    return null;
                } else if ("Lautostack/NoTransform;".equals(desc)) {
                    if (debugTransform)
                        System.out.println("[autostack]   class declares to not transform any methods");
                    classNoTransform = true;
                    return null;
                }
                return cv.visitAnnotation(desc, visible);
            }

            public MethodVisitor visitMethod(final int access, final String name, final String desc,
                    String signature, String[] exceptions) {
                Integer info = stackMethods.get(name + desc);
                if (info == null)
                    return super.visitMethod(access, name, desc, signature, exceptions);
                boolean catches = (info.intValue() & 1) == 1;
                final boolean notransform = classNoTransform || (info.intValue() & 2) == 2;
                if (debugTransform && !notransform)
                    System.out.println(
                            "[autostack]   transform method: " + className.replace('/', '.') + "." + name);
                final boolean memoryStackParam = stackAsParameter && (access & ACC_PRIVATE) != 0
                        && (info.intValue() & 16) == 0;
                MethodVisitor mv;
                final Type[] paramTypes = Type.getArgumentTypes(desc);
                final boolean isStatic = (access & ACC_STATIC) != 0;
                final boolean isConstructor = "<init>".equals(name);
                if (memoryStackParam) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]     changing signature of method to add additional MemoryStack parameter");

                    // Add additional MemoryStack parameter to the method signature index of the local stays the same
                    int paramEndIndex = desc.indexOf(')');
                    String beforeDesc = desc.substring(0, paramEndIndex);
                    String afterDesc = desc.substring(paramEndIndex);
                    mv = super.visitMethod(access | ACC_SYNTHETIC, name,
                            beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, signature, exceptions);

                    // Re-introduce the original method which just delegates
                    if (debugTransform)
                        System.out.println("[autostack]     adding delegate method with original signature");
                    MethodVisitor omv = super.visitMethod(access, name, desc, signature, exceptions);
                    omv.visitCode();
                    int param = 0;
                    if (!isStatic) {
                        omv.visitVarInsn(ALOAD, 0);
                        param++;
                    }
                    for (int i = 0; i < paramTypes.length; i++) {
                        omv.visitVarInsn(paramTypes[i].getOpcode(ILOAD), param);
                        param += paramTypes[i].getSize();
                    }
                    omv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet", "()L" + MEMORYSTACK + ";",
                            false);
                    boolean isPrivate = (access & ACC_PRIVATE) != 0;
                    int opcode = isStatic ? INVOKESTATIC : isPrivate ? INVOKESPECIAL : INVOKEVIRTUAL;
                    omv.visitMethodInsn(opcode, className, name,
                            beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false);
                    Type retType = Type.getReturnType(desc);
                    omv.visitInsn(retType.getOpcode(IRETURN));
                    omv.visitMaxs(-1, -1);
                    omv.visitEnd();
                } else {
                    mv = super.visitMethod(access, name, desc, signature, exceptions);
                }
                if (catches)
                    mv = new TryCatchBlockSorter(mv, access, name, desc, signature, exceptions);
                mv = new MethodVisitor(ASM5, mv) {
                    Label tryLabel = new Label();
                    Label finallyLabel = new Label();
                    int lastLine = 0;
                    boolean newStack = classDefaultNewStack;
                    int stackVarIndex;
                    int stackPointerVarIndex;
                    int firstAdditionalLocal;
                    int additionalLocals;
                    Object[] replacedLocals;

                    public void visitInsn(int opcode) {
                        if (notransform) {
                            mv.visitInsn(opcode);
                            return;
                        }
                        if (opcode >= IRETURN && opcode <= RETURN && (newStack || checkStack)) {
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] restore stack pointer because of return at "
                                        + className.replace('/', '.') + "." + name + ":" + lastLine);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            if (newStack && !checkStack) {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false);
                            } else if (checkStack) {
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, className, "$checkStack$", "(II)V", false);
                            }
                        }
                        mv.visitInsn(opcode);
                    }

                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                        if ("Lautostack/UseCallerStack;".equals(desc)) {
                            if (!notransform) {
                                if (debugTransform)
                                    System.out.println("[autostack]     method declares to use caller stack");
                                newStack = false;
                            }
                            return null;
                        } else if ("Lautostack/UseNewStack;".equals(desc)) {
                            if (!notransform) {
                                if (debugTransform)
                                    System.out.println("[autostack]     method declares to use new stack");
                                newStack = true;
                            }
                            return null;
                        } else if ("Lautostack/NoTransform;".equals(desc)) {
                            return null;
                        } else if ("Lautostack/NoStackParam;".equals(desc)) {
                            return null;
                        }
                        return mv.visitAnnotation(desc, visible);
                    }

                    public void visitVarInsn(int opcode, int var) {
                        if (notransform) {
                            mv.visitVarInsn(opcode, var);
                            return;
                        }
                        if (var >= firstAdditionalLocal)
                            var += additionalLocals;
                        mv.visitVarInsn(opcode, var);
                    }

                    public void visitIincInsn(int var, int increment) {
                        if (notransform) {
                            mv.visitIincInsn(var, increment);
                            return;
                        }
                        if (var >= firstAdditionalLocal)
                            var += additionalLocals;
                        mv.visitIincInsn(var, increment);
                    }

                    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
                        if (notransform) {
                            mv.visitFrame(type, nLocal, local, nStack, stack);
                            return;
                        }
                        if (type == F_FULL) {
                            int noThis = isStatic ? 0 : 1;
                            Object[] locals = new Object[local.length + additionalLocals];
                            if (!isStatic)
                                locals[0] = local[0];
                            int replacementLength = replacedLocals.length;
                            System.arraycopy(replacedLocals, noThis, locals, noThis,
                                    replacementLength - noThis);
                            int len = locals.length - replacementLength;
                            System.arraycopy(local, replacementLength - additionalLocals, locals,
                                    replacementLength, len);
                            mv.visitFrame(type, nLocal + additionalLocals, locals, nStack, stack);
                        } else
                            mv.visitFrame(type, nLocal, local, nStack, stack);
                    }

                    public void visitLocalVariable(String name, String desc, String signature, Label start,
                            Label end, int index) {
                        if (notransform) {
                            mv.visitLocalVariable(className, desc, signature, start, end, index);
                            return;
                        }
                        if (index >= firstAdditionalLocal)
                            index += additionalLocals;
                        mv.visitLocalVariable(name, desc, signature, start, end, index);
                    }

                    private boolean doesNotTakeStackItself(String desc) {
                        return desc.lastIndexOf("L" + MEMORYSTACK + ";)") == -1;
                    }

                    public void visitMethodInsn(int opcode, String owner, String name, String desc,
                            boolean itf) {
                        String completeName = name + desc;
                        Integer info = stackMethods.get(completeName);
                        if (opcode != INVOKESTATIC || notransform) {
                            mv.visitMethodInsn(opcode, owner, name, desc, itf);
                            return;
                        }
                        if (stackAsParameter && info != null && (info.intValue() & 8) != 0
                                && (info.intValue() & 16) == 0) {
                            /* Rewrite invocation to have additional MemoryStack parameter */
                            if (debugTransform)
                                System.out.println(
                                        "[autostack]     rewrite invocation of " + owner.replace('/', '.') + "."
                                                + name + " at line " + lastLine + " --> "
                                                + owner.replace('/', '.') + "." + name + "(..., MemoryStack)");
                            int paramEndIndex = desc.indexOf(')');
                            String beforeDesc = desc.substring(0, paramEndIndex);
                            String afterDesc = desc.substring(paramEndIndex);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitMethodInsn(opcode, owner, name,
                                    beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, itf);
                            return;
                        }
                        if (owner.startsWith("org/lwjgl/")
                                && (name.equals("mallocStack") || name.equals("callocStack"))
                                && doesNotTakeStackItself(desc)) {
                            if (debugTransform)
                                System.out.println(
                                        "[autostack]     rewrite invocation of " + owner.replace('/', '.') + "."
                                                + name + " at line " + lastLine + " --> aload " + stackVarIndex
                                                + "; invokestatic " + owner.replace('/', '.') + "." + name);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            int paramEndIndex = desc.indexOf(')');
                            String beforeDesc = desc.substring(0, paramEndIndex);
                            String afterDesc = desc.substring(paramEndIndex);
                            mv.visitMethodInsn(opcode, owner, name,
                                    beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false);
                        } else if (owner.equals(MEMORYSTACK) && name.equals("stackGet")) {
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.equals("stackPush") || name.equals("stackPop"))) {
                            String newName = "p" + name.substring(6);
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.startsWith("stackMalloc") || name.startsWith("stackCalloc"))) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitInsn(SWAP);
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK) && (name.equals("stackASCII")
                                || name.equals("stackUTF8") || name.equals("stackUTF16"))) {
                            String newName = name.substring(5);
                            boolean withBoolean = desc.startsWith("(Ljava/lang/CharSequence;Z");
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            if (withBoolean) {
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                            } else {
                                mv.visitInsn(SWAP);
                            }
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.equals("stackFloats") || name.equals("stackInts")
                                        || name.equals("stackBytes") || name.equals("stackShorts")
                                        || name.equals("stackPointers")
                                                && (desc.startsWith("([Lorg/lwjgl/system/Pointer;")
                                                        || desc.startsWith("(Lorg/lwjgl/system/Pointer;")))) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            Type[] argTypes = Type.getArgumentTypes(desc);
                            if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 1) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 2) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 3) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP2_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                                mv.visitInsn(SWAP);
                                mv.visitInsn(POP);
                            } else {
                                if (debugTransform)
                                    System.out.println("[autostack]     failed to rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + ". Not yet implemented.");
                                /* Give up. Not possible without an additional local */
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf);
                            }
                        } else if (owner.equals(MEMORYSTACK) && name.equals("stackLongs")) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            Type[] argTypes = Type.getArgumentTypes(desc);
                            if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 1) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else {
                                if (debugTransform)
                                    System.out.println("[autostack]     failed to rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + ". Not yet implemented.");
                                /* Give up. Not possible without an additional local */
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf);
                            }
                        } else {
                            mv.visitMethodInsn(opcode, owner, name, desc, itf);
                        }
                    }

                    public void visitLineNumber(int line, Label start) {
                        mv.visitLineNumber(line, start);
                        lastLine = line;
                    }

                    public void visitCode() {
                        if (notransform) {
                            mv.visitCode();
                            return;
                        }
                        additionalLocals = newStack || checkStack ? 2 : 1;
                        replacedLocals = new Object[paramTypes.length + additionalLocals + (isStatic ? 0 : 1)];
                        if (!newStack && !checkStack) {
                            replacedLocals[replacedLocals.length - 1] = MEMORYSTACK;
                        } else {
                            replacedLocals[replacedLocals.length - 2] = MEMORYSTACK;
                            replacedLocals[replacedLocals.length - 1] = INTEGER;
                        }
                        if (!isStatic)
                            replacedLocals[0] = isConstructor ? TOP : className;
                        int var = isStatic ? 0 : 1;
                        for (int t = 0, i = var; t < paramTypes.length; t++, i++) {
                            Type type = paramTypes[t];
                            var += type.getSize();
                            switch (type.getSort()) {
                            case Type.INT:
                            case Type.BYTE:
                            case Type.BOOLEAN:
                            case Type.SHORT:
                            case Type.CHAR:
                                replacedLocals[i] = INTEGER;
                                break;
                            case Type.LONG:
                                replacedLocals[i] = LONG;
                                break;
                            case Type.FLOAT:
                                replacedLocals[i] = FLOAT;
                                break;
                            case Type.DOUBLE:
                                replacedLocals[i] = DOUBLE;
                                break;
                            case Type.OBJECT:
                            case Type.ARRAY:
                                replacedLocals[i] = type.getInternalName();
                                break;
                            default:
                                throw new AssertionError("Unhandled parameter type: " + type);
                            }
                        }
                        firstAdditionalLocal = var;
                        stackVarIndex = var;
                        stackPointerVarIndex = var + 1;
                        mv.visitCode();
                        if (newStack && !checkStack || checkStack) {
                            if (!memoryStackParam) {
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet",
                                        "()L" + MEMORYSTACK + ";", false);
                                mv.visitInsn(DUP);
                                mv.visitVarInsn(ASTORE, stackVarIndex);
                            } else {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                            }
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                            mv.visitVarInsn(ISTORE, stackPointerVarIndex);
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] save stack pointer [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString",
                                        "(I)Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            mv.visitLabel(tryLabel);
                            if (!memoryStackParam)
                                mv.visitFrame(F_APPEND, 2, new Object[] { MEMORYSTACK, INTEGER }, 0, null);
                            else
                                mv.visitFrame(F_APPEND, 1, new Object[] { INTEGER }, 0, null);
                        } else if (!newStack && !checkStack) {
                            if (!memoryStackParam) {
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet",
                                        "()L" + MEMORYSTACK + ";", false);
                                mv.visitVarInsn(ASTORE, stackVarIndex);
                            }
                            if (debugRuntime) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] current stack pointer is [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString",
                                        "(I)Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            mv.visitLabel(tryLabel);
                            if (!memoryStackParam)
                                mv.visitFrame(F_APPEND, 1, new Object[] { MEMORYSTACK }, 0, null);
                        }
                    }

                    public void visitMaxs(int maxStack, int maxLocals) {
                        if (notransform) {
                            mv.visitMaxs(maxStack, maxLocals);
                            return;
                        }
                        if (newStack && !checkStack || checkStack) {
                            mv.visitLabel(finallyLabel);
                            mv.visitFrame(F_FULL, replacedLocals.length, replacedLocals, 1,
                                    new Object[] { "java/lang/Throwable" });
                            mv.visitTryCatchBlock(tryLabel, finallyLabel, finallyLabel, null);
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] restore stack pointer because of throw [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitInsn(DUP);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString",
                                        "()Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn(
                                        "] at " + className.replace('/', '.') + "." + name + ":" + lastLine);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            if (newStack && !checkStack) {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false);
                            }
                            if (checkStack) {
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, className, "$checkStackWithThrowable$",
                                        "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", false);
                            }
                            mv.visitInsn(ATHROW);
                        }
                        mv.visitMaxs(-1, maxLocals + additionalLocals);
                    }
                };
                return mv;
            }
        }, 0);
        byte[] arr = cw.toByteArray();
        if (trace) {
            cr = new ClassReader(arr);
            cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), 0);
        }
        return arr;
    } catch (Throwable t) {
        t.printStackTrace();
        throw new RuntimeException(t);
    }
}

From source file:blockphysics.asm.BPTransformer.java

License:Open Source License

private byte[] transformTileEntityPiston(byte[] bytes) {
    /*try// www. j  ava  2s. co m
    {
        FileOutputStream fos = new FileOutputStream("d:/TileEntityPiston.orig.class");
        fos.write(bytes);
      fos.close();
    } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
    }*/

    System.out.print("[BlockPhysics] Patching TileEntityPiston.class ........");

    boolean ok = false, ok2 = false, ok3 = false, ok4 = false, ok5 = false;
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    MethodNode m;
    Iterator<MethodNode> methods = classNode.methods.iterator();
    while (methods.hasNext()) {
        m = methods.next();
        if (m.name.equals("<init>") && m.desc.equals("(IIIZZ)V")) {
            for (int index = m.instructions.size() - 1; index >= 0; index--) {
                if (m.instructions.get(index).getOpcode() == RETURN) {
                    InsnList toInject = new InsnList();
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new InsnNode(ACONST_NULL));
                    toInject.add(new FieldInsnNode(PUTFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new InsnNode(ICONST_0));
                    toInject.add(new FieldInsnNode(PUTFIELD, "ast", "bpmeta", "I"));

                    m.instructions.insertBefore(m.instructions.get(index), toInject);

                    ok = true;
                    break;
                }
            }
        } else if (m.name.equals("f") && m.desc.equals("()V")) {
            for (int index = m.instructions.size() - 1; index >= 0; index--) {
                if (m.instructions.get(index).getOpcode() == INVOKEVIRTUAL
                        && m.instructions.get(index).getType() == AbstractInsnNode.METHOD_INSN
                        && ((MethodInsnNode) m.instructions.get(index)).owner.equals("abv")
                        && ((MethodInsnNode) m.instructions.get(index)).name.equals("g")
                        && ((MethodInsnNode) m.instructions.get(index)).desc.equals("(IIII)V")) {
                    InsnList toInject = new InsnList();

                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "k", "Labv;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "l", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "m", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "n", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "bpmeta", "I"));
                    toInject.add(new MethodInsnNode(INVOKESTATIC, "blockphysics/BlockPhysics", "setBlockBPdata",
                            "(Labv;IIII)Z"));
                    toInject.add(new InsnNode(POP));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    LabelNode l1 = new LabelNode();
                    toInject.add(new JumpInsnNode(IFNULL, l1));
                    toInject.add(new FieldInsnNode(GETSTATIC, "aqw", "s", "[Laqw;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "a", "I"));
                    toInject.add(new InsnNode(AALOAD));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "k", "Labv;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "b", "I"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "aqw", "createTileEntity", "(Labv;I)Lasm;"));
                    toInject.add(new VarInsnNode(ASTORE, 1));
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "asm", "a", "(Lbx;)V"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "k", "Labv;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "l", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "m", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "n", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "abv", "a", "(IIILasm;)V"));
                    toInject.add(l1);

                    m.instructions.insert(m.instructions.get(index), toInject);

                    ok2 = true;
                    break;
                }
            }
        } else if (m.name.equals("a") && m.desc.equals("(Lbx;)V")) {
            for (int index = m.instructions.size() - 1; index >= 0; index--) {
                if (m.instructions.get(index).getOpcode() == RETURN) {
                    InsnList toInject = new InsnList();
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new LdcInsnNode("BPData"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "bx", "b", "(Ljava/lang/String;)Z"));
                    LabelNode l1 = new LabelNode();
                    toInject.add(new JumpInsnNode(IFEQ, l1));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new LdcInsnNode("BPData"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "bx", "c", "(Ljava/lang/String;)B"));
                    toInject.add(new FieldInsnNode(PUTFIELD, "ast", "bpmeta", "I"));
                    toInject.add(l1);
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new LdcInsnNode("TileEntityData"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "bx", "b", "(Ljava/lang/String;)Z"));
                    LabelNode l0 = new LabelNode();
                    toInject.add(new JumpInsnNode(IFEQ, l0));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new LdcInsnNode("TileEntityData"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "bx", "l", "(Ljava/lang/String;)Lbx;"));
                    toInject.add(new FieldInsnNode(PUTFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    toInject.add(l0);

                    m.instructions.insertBefore(m.instructions.get(index), toInject);

                    ok3 = true;
                    break;
                }
            }
        } else if (m.name.equals("b") && m.desc.equals("(Lbx;)V")) {
            for (int index = m.instructions.size() - 1; index >= 0; index--) {
                if (m.instructions.get(index).getOpcode() == RETURN) {
                    InsnList toInject = new InsnList();
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new LdcInsnNode("BPData"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "bpmeta", "I"));
                    toInject.add(new InsnNode(I2B));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "bx", "a", "(Ljava/lang/String;B)V"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    LabelNode l0 = new LabelNode();
                    toInject.add(new JumpInsnNode(IFNULL, l0));
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new LdcInsnNode("TileEntityData"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "bx", "a", "(Ljava/lang/String;Lbx;)V"));
                    toInject.add(l0);

                    m.instructions.insertBefore(m.instructions.get(index), toInject);

                    ok4 = true;
                    break;
                }
            }
        } else if (m.name.equals("h") && m.desc.equals("()V")) {
            for (int index = m.instructions.size() - 1; index >= 0; index--) {
                if (m.instructions.get(index).getOpcode() == INVOKEVIRTUAL
                        && m.instructions.get(index).getType() == AbstractInsnNode.METHOD_INSN
                        && ((MethodInsnNode) m.instructions.get(index)).owner.equals("abv")
                        && ((MethodInsnNode) m.instructions.get(index)).name.equals("g")
                        && ((MethodInsnNode) m.instructions.get(index)).desc.equals("(IIII)V")) {
                    InsnList toInject = new InsnList();

                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "k", "Labv;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "l", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "m", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "n", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "bpmeta", "I"));
                    toInject.add(new MethodInsnNode(INVOKESTATIC, "blockphysics/BlockPhysics", "setBlockBPdata",
                            "(Labv;IIII)Z"));
                    toInject.add(new InsnNode(POP));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    LabelNode l0 = new LabelNode();
                    toInject.add(new JumpInsnNode(IFNULL, l0));
                    toInject.add(new FieldInsnNode(GETSTATIC, "aqw", "s", "[Laqw;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "a", "I"));
                    toInject.add(new InsnNode(AALOAD));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "k", "Labv;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "b", "I"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "aqw", "createTileEntity", "(Labv;I)Lasm;"));
                    toInject.add(new VarInsnNode(ASTORE, 1));
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "movingBlockTileEntityData", "Lbx;"));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "asm", "a", "(Lbx;)V"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "k", "Labv;"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "l", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "m", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 0));
                    toInject.add(new FieldInsnNode(GETFIELD, "ast", "n", "I"));
                    toInject.add(new VarInsnNode(ALOAD, 1));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "abv", "a", "(IIILasm;)V"));
                    toInject.add(l0);

                    m.instructions.insert(m.instructions.get(index), toInject);

                    ok5 = true;
                    break;
                }
            }
        }
    }

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(cw);

    if (ok && ok2 && ok3 && ok4 && ok5)
        System.out.println("OK");
    else
        System.out.println("Failed." + ok + ok2 + ok3 + ok4 + ok5);

    FieldVisitor fv;

    fv = cw.visitField(ACC_PUBLIC, "movingBlockTileEntityData", "Lbx;", null, null);
    fv.visitEnd();

    fv = cw.visitField(ACC_PUBLIC, "bpmeta", "I", null, null);
    fv.visitEnd();

    cw.visitEnd();

    /*try
    {
       FileOutputStream fos = new FileOutputStream("d:/TileEntityPiston.mod.class");
       fos.write(cw.toByteArray());
     fos.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }*/

    return cw.toByteArray();
}

From source file:blockphysics.asm.BPTransformer.java

License:Open Source License

private byte[] transformBlockFurnace(byte[] bytes) {
    /*try//from  ww  w.  j a  va 2 s  .c  om
     {
         FileOutputStream fos = new FileOutputStream("d:/BlockFurnace.orig.class");
         fos.write(bytes);
       fos.close();
     } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }*/

    System.out.print("[BlockPhysics] Patching BlockFurnace.class ............");

    boolean ok = false;
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    MethodNode m;
    Iterator<MethodNode> methods = classNode.methods.iterator();
    while (methods.hasNext()) {
        m = methods.next();
        if (m.name.equals("a") && m.desc.equals("(Labv;III)V")) {
            for (int index = 0; index < m.instructions.size(); index++) {
                if (m.instructions.get(index).getOpcode() == INVOKESPECIAL
                        && m.instructions.get(index).getType() == AbstractInsnNode.METHOD_INSN
                        && ((MethodInsnNode) m.instructions.get(index)).owner.equals("aoh")
                        && ((MethodInsnNode) m.instructions.get(index)).name.equals("k")
                        && ((MethodInsnNode) m.instructions.get(index)).desc.equals("(Labv;III)V")) {
                    index = index - 5;
                    for (int i = 0; i < 6; i++)
                        m.instructions.remove(m.instructions.get(index));

                    ok = true;
                    break;
                }
            }
        }
    }

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(cw);

    if (ok)
        System.out.println("OK");
    else
        System.out.println("Failed." + ok);

    /*try
    {
       FileOutputStream fos = new FileOutputStream("d:/BlockFurnace.mod.class");
       fos.write(cw.toByteArray());
     fos.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }*/

    return cw.toByteArray();
}