Example usage for org.objectweb.asm.tree AbstractInsnNode getNext

List of usage examples for org.objectweb.asm.tree AbstractInsnNode getNext

Introduction

In this page you can find the example usage for org.objectweb.asm.tree AbstractInsnNode getNext.

Prototype

public AbstractInsnNode getNext() 

Source Link

Document

Returns the next instruction in the list to which this instruction belongs, if any.

Usage

From source file:analysis.ReferenceGenerator.java

License:Open Source License

private void refInstructions(InsnList insnList) {
    AbstractInsnNode insn;

    insn = insnList.getFirst();/*w ww  . j  a  va2  s.  c  om*/

    Object cst;

    while (insn != null) {
        switch (insn.getType()) {
        case AbstractInsnNode.FIELD_INSN:
            //addTypeClassRef(Type.getType(((FieldInsnNode)insn).desc));
            addFieldRef(((FieldInsnNode) insn).owner, ((FieldInsnNode) insn).name);
            break;
        /*case AbstractInsnNode.INVOKE_DYNAMIC_INSN:
                   
           break;*/
        /*case AbstractInsnNode.LDC_INSN:
           cst = ((LdcInsnNode)insn).cst;
           if(cst instanceof Type) {
              addTypeClassRef((Type)cst);
           }
           break;*/
        case AbstractInsnNode.METHOD_INSN:
            addMethodRef(((MethodInsnNode) insn).owner, ((MethodInsnNode) insn).name,
                    ((MethodInsnNode) insn).desc);
            break;
        case AbstractInsnNode.MULTIANEWARRAY_INSN:
            addTypeClassRef(Type.getType(((MultiANewArrayInsnNode) insn).desc));
            break;
        case AbstractInsnNode.TYPE_INSN:
            addTypeClassRef(Type.getType(((TypeInsnNode) insn).desc));
            break;
        }
        insn = insn.getNext();
    }
}

From source file:br.usp.each.saeg.badua.core.internal.instr.CoverageMethodTransformer.java

License:Open Source License

@Override
@SuppressWarnings("unchecked")
public void transform(final MethodNode methodNode) {

    final DefUseAnalyzer analyzer = new DefUseAnalyzer();
    try {//from w  w w . ja va2  s . c o m
        analyzer.analyze(className, methodNode);
    } catch (final AnalyzerException e) {
        throw new RuntimeException(e);
    }

    final DefUseFrame[] frames = analyzer.getDefUseFrames();
    final Variable[] variables = analyzer.getVariables();
    final int[][] successors = analyzer.getSuccessors();
    final int[][] predecessors = analyzer.getPredecessors();
    final int[][] basicBlocks = analyzer.getBasicBlocks();
    final int[] leaders = analyzer.getLeaders();

    final DefUseChain[] chains = DefUseChain.toBasicBlock(
            new DepthFirstDefUseChainSearch().search(frames, variables, successors, predecessors), leaders,
            basicBlocks);

    this.chains = chains;
    if (chains.length == 0)
        return;

    // basic block definitions
    final Set<Variable>[] defs = (Set<Variable>[]) new Set<?>[basicBlocks.length];
    for (int b = 0; b < basicBlocks.length; b++) {
        defs[b] = new HashSet<Variable>();
        for (final int insnIndex : basicBlocks[b]) {
            defs[b].addAll(frames[insnIndex].getDefinitions());
        }
    }

    // bit-sets
    final BitSet[] potcov = new BitSet[basicBlocks.length];
    final BitSet[] potcovpuse = new BitSet[basicBlocks.length];
    final BitSet[] born = new BitSet[basicBlocks.length];
    final BitSet[] disabled = new BitSet[basicBlocks.length];
    final BitSet[] sleepy = new BitSet[basicBlocks.length];
    for (int b = 0; b < basicBlocks.length; b++) {

        potcov[b] = new BitSet(chains.length);
        potcovpuse[b] = new BitSet(chains.length);
        born[b] = new BitSet(chains.length);
        disabled[b] = new BitSet(chains.length);
        sleepy[b] = new BitSet(chains.length);

        for (int i = 0; i < chains.length; i++) {

            final DefUseChain chain = chains[i];

            if (chain.target != -1 ? chain.target == b : chain.use == b) {
                potcov[b].set(i);
                if (chain.target != -1) {
                    potcovpuse[b].set(i);
                }
            }

            if (chain.def == b) {
                born[b].set(i);
            }

            if (chain.def != b && defs[b].contains(variables[chain.var])) {
                disabled[b].set(i);
            }

            if (chain.target != -1) {
                if (chain.use != b) {
                    sleepy[b].set(i);
                }
            }

        }
    }

    // first/last valid instructions
    final AbstractInsnNode[] first = new AbstractInsnNode[basicBlocks.length];
    final AbstractInsnNode[] last = new AbstractInsnNode[basicBlocks.length];
    for (int b = 0; b < basicBlocks.length; b++) {
        for (final int insnIndex : basicBlocks[b]) {
            final AbstractInsnNode insn = methodNode.instructions.get(insnIndex);

            // skip
            switch (insn.getType()) {
            case AbstractInsnNode.LABEL:
            case AbstractInsnNode.FRAME:
            case AbstractInsnNode.LINE:
                continue;
            }

            if (first[b] == null) {
                first[b] = insn;
            }
            last[b] = insn;
        }
    }

    AbstractInsnNode insn = methodNode.instructions.getFirst();
    final int windows = (chains.length + 63) / 64;
    final int[] indexes = new int[windows];
    for (int w = 0; w < windows; w++) {
        indexes[w] = idGen.nextId();
        LabelFrameNode.insertBefore(insn, methodNode.instructions, init(methodNode, w));
    }

    for (int b = 0; b < basicBlocks.length; b++) {

        final long[] lPotcov = BitSetUtils.toLongArray(potcov[b], windows);
        final long[] lPotcovpuse = BitSetUtils.toLongArray(potcovpuse[b], windows);
        final long[] lBorn = BitSetUtils.toLongArray(born[b], windows);
        final long[] lDisabled = BitSetUtils.toLongArray(disabled[b], windows);
        final long[] lSleepy = BitSetUtils.toLongArray(sleepy[b], windows);

        for (int w = 0; w < windows; w++) {

            final int nPredecessors = predecessors[basicBlocks[b][0]].length;
            final Probe p = probe(methodNode, w, nPredecessors == 0);

            p.potcov = lPotcov[w];
            p.potcovpuse = lPotcovpuse[w];
            p.born = lBorn[w];
            p.disabled = lDisabled[w];
            p.sleepy = lSleepy[w];
            p.singlePredecessor = nPredecessors == 1;

            LabelFrameNode.insertBefore(first[b], methodNode.instructions, p);

        }
        if (isReturn(last[b].getOpcode())) {
            for (int w = 0; w < windows; w++) {
                final Probe p = update(methodNode, w, indexes[w]);
                LabelFrameNode.insertBefore(last[b], methodNode.instructions, p);
            }
        }
    }

    // Finally, update the frames
    while (insn != null) {
        if (insn instanceof FrameNode) {
            final FrameNode frame = (FrameNode) insn;
            frame.local = new ArrayList<Object>(frame.local);
            int size = 0;
            for (final Object obj : frame.local) {
                size++;
                if (obj.equals(Opcodes.DOUBLE) || obj.equals(Opcodes.LONG)) {
                    size++;
                }
            }
            while (size < methodNode.maxLocals) {
                frame.local.add(Opcodes.TOP);
                size++;
            }
            final Integer type = typeOfVars();
            for (int i = 0; i < windows; i++) {
                frame.local.add(type);
                frame.local.add(type);
                frame.local.add(type);
            }
        }
        insn = insn.getNext();
    }

    methodNode.maxLocals = methodNode.maxLocals + windows * numOfVars();
    methodNode.maxStack = methodNode.maxStack + 6;
}

From source file:cl.inria.stiq.instrumenter.BCIUtils.java

License:Open Source License

public static void checkLabels(MethodNode aNode) {
    for (int i = 0; i < aNode.instructions.size(); i++) {
        AbstractInsnNode theNode = aNode.instructions.get(i);

        if (theNode instanceof LabelNode) {
            LabelNode theLabelNode = (LabelNode) theNode;
            checkLabel(theLabelNode);/* w w w. jav  a  2 s.  c  o  m*/
        } else if (theNode instanceof JumpInsnNode) {
            JumpInsnNode theJumpNode = (JumpInsnNode) theNode;
            checkLabel(theJumpNode.label);
        } else if (theNode instanceof LookupSwitchInsnNode) {
            LookupSwitchInsnNode theLookupSwitchNode = (LookupSwitchInsnNode) theNode;
            for (LabelNode theLabel : (List<LabelNode>) theLookupSwitchNode.labels)
                checkLabel(theLabel);
            checkLabel(theLookupSwitchNode.dflt);
        } else if (theNode instanceof TableSwitchInsnNode) {
            TableSwitchInsnNode theTableSwitchNode = (TableSwitchInsnNode) theNode;
            for (LabelNode theLabel : (List<LabelNode>) theTableSwitchNode.labels)
                checkLabel(theLabel);
            checkLabel(theTableSwitchNode.dflt);
        }
        theNode = theNode.getNext();
    }
}

From source file:cl.inria.stiq.instrumenter.BCIUtils.java

License:Open Source License

private static InsnList cloneInstructions(ClonerMap aMap, InsnList aList) {
    InsnList theInsnListClone = new InsnList();
    AbstractInsnNode theNode = aList.getFirst();
    while (theNode != null) {
        AbstractInsnNode theClone = theNode.clone(aMap);
        if (theClone instanceof LabelNode) {
            LabelNode theLabelNode = (LabelNode) theClone;
        }/*from   w w w  .j a  va  2s  .c  om*/
        theInsnListClone.add(theClone);
        theNode = theNode.getNext();
    }

    return theInsnListClone;
}

From source file:Client.JClassPatcher.java

License:Open Source License

private void patchApplet(ClassNode node) {
    Logger.Info("Patching applet (" + node.name + ".class)");

    Iterator<MethodNode> methodNodeList = node.methods.iterator();
    while (methodNodeList.hasNext()) {
        MethodNode methodNode = methodNodeList.next();

        if (methodNode.name.equals("run") && methodNode.desc.equals("()V")) {
            // Mouse and keyboard listener hooks
            AbstractInsnNode findNode = methodNode.instructions.getFirst();
            for (;;) {
                AbstractInsnNode next = findNode.getNext();

                if (next == null)
                    break;

                if (findNode.getOpcode() == Opcodes.ALOAD && next.getOpcode() == Opcodes.ALOAD) {
                    AbstractInsnNode invokeNode = next.getNext();
                    MethodInsnNode invoke = (MethodInsnNode) invokeNode;
                    methodNode.instructions.remove(next);
                    methodNode.instructions.remove(invokeNode);
                    if (invoke.name.equals("addMouseListener"))
                        methodNode.instructions.insert(findNode, new FieldInsnNode(Opcodes.PUTSTATIC,
                                "Game/MouseHandler", "listener_mouse", "Ljava/awt/event/MouseListener;"));
                    else if (invoke.name.equals("addMouseMotionListener"))
                        methodNode.instructions.insert(findNode,
                                new FieldInsnNode(Opcodes.PUTSTATIC, "Game/MouseHandler",
                                        "listener_mouse_motion", "Ljava/awt/event/MouseMotionListener;"));
                    else if (invoke.name.equals("addKeyListener"))
                        methodNode.instructions.insert(findNode, new FieldInsnNode(Opcodes.PUTSTATIC,
                                "Game/KeyboardHandler", "listener_key", "Ljava/awt/event/KeyListener;"));
                }//w  w  w  . j a  v  a 2  s  .com
                findNode = findNode.getNext();
            }
        }
    }
}

From source file:Client.JClassPatcher.java

License:Open Source License

private void patchClient(ClassNode node) {
    Logger.Info("Patching client (" + node.name + ".class)");

    Iterator<MethodNode> methodNodeList = node.methods.iterator();
    while (methodNodeList.hasNext()) {
        MethodNode methodNode = methodNodeList.next();

        // I (I)V is where most of the interface is processed
        if (methodNode.name.equals("I") && methodNode.desc.equals("(I)V")) {
            // Show combat menu
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                if (insnNode.getOpcode() == Opcodes.BIPUSH) {
                    IntInsnNode bipush = (IntInsnNode) insnNode;

                    if (bipush.operand == -9) {
                        AbstractInsnNode findNode = insnNode;
                        while (findNode.getOpcode() != Opcodes.IF_ICMPEQ)
                            findNode = findNode.getNext();

                        LabelNode label = ((JumpInsnNode) findNode).label;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Client/Settings", "COMBAT_MENU", "Z"));
                        methodNode.instructions.insertBefore(insnNode, new JumpInsnNode(Opcodes.IFGT, label));
                        break;
                    }//  w  w  w  .jav  a2 s .  co  m
                }
            }
        } else if (methodNode.name.equals("J") && methodNode.desc.equals("(I)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Chat command patch
                if (insnNode.getOpcode() == Opcodes.SIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    if (call.operand == 627) {
                        AbstractInsnNode jmpNode = insnNode;
                        while (jmpNode.getOpcode() != Opcodes.IFEQ)
                            jmpNode = jmpNode.getNext();

                        AbstractInsnNode insertNode = insnNode;
                        while (insertNode.getOpcode() != Opcodes.INVOKEVIRTUAL)
                            insertNode = insertNode.getPrevious();

                        JumpInsnNode jmp = (JumpInsnNode) jmpNode;
                        methodNode.instructions.insert(insertNode, new VarInsnNode(Opcodes.ASTORE, 2));
                        methodNode.instructions.insert(insertNode, new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "Game/Client", "processChatCommand", "(Ljava/lang/String;)Ljava/lang/String;"));
                        methodNode.instructions.insert(insertNode, new VarInsnNode(Opcodes.ALOAD, 2));
                    }
                }
            }
        } else if (methodNode.name.equals("h") && methodNode.desc.equals("(B)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Private chat command patch
                if (insnNode.getOpcode() == Opcodes.GETFIELD) {
                    FieldInsnNode field = (FieldInsnNode) insnNode;
                    if (field.owner.equals("client") && field.name.equals("Ob")
                            && insnNode.getPrevious().getPrevious().getOpcode() != Opcodes.INVOKEVIRTUAL) {
                        insnNode = insnNode.getPrevious().getPrevious();
                        methodNode.instructions.insert(insnNode,
                                new FieldInsnNode(Opcodes.PUTFIELD, "client", "Ob", "Ljava/lang/String;"));
                        methodNode.instructions.insert(insnNode,
                                new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Client", "processPrivateCommand",
                                        "(Ljava/lang/String;)Ljava/lang/String;"));
                        methodNode.instructions.insert(insnNode,
                                new FieldInsnNode(Opcodes.GETFIELD, "client", "Ob", "Ljava/lang/String;"));
                        methodNode.instructions.insert(insnNode, new VarInsnNode(Opcodes.ALOAD, 0));
                        methodNode.instructions.insert(insnNode, new VarInsnNode(Opcodes.ALOAD, 0));
                        break;
                    }
                }
            }
        } else if (methodNode.name.equals("a") && methodNode.desc.equals("(IIIIIIII)V")) {
            // Draw NPC hook
            AbstractInsnNode insnNode = methodNode.instructions.getLast();
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 8));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 1));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 7));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 4));

            methodNode.instructions.insertBefore(insnNode,
                    new FieldInsnNode(Opcodes.GETSTATIC, "e", "Mb", "[Ljava/lang/String;"));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ALOAD, 0));
            methodNode.instructions.insertBefore(insnNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "Tb", "[Lta;"));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 6));
            methodNode.instructions.insertBefore(insnNode, new InsnNode(Opcodes.AALOAD));
            methodNode.instructions.insertBefore(insnNode, new FieldInsnNode(Opcodes.GETFIELD, "ta", "t", "I"));
            methodNode.instructions.insertBefore(insnNode, new InsnNode(Opcodes.AALOAD));
            methodNode.instructions.insertBefore(insnNode, new MethodInsnNode(Opcodes.INVOKESTATIC,
                    "Game/Client", "drawNPC", "(IIIILjava/lang/String;)V"));
        } else if (methodNode.name.equals("b") && methodNode.desc.equals("(IIIIIIII)V")) {
            // Draw Player hook
            AbstractInsnNode insnNode = methodNode.instructions.getLast();
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 5));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 6));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 2));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 7));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ALOAD, 0));
            methodNode.instructions.insertBefore(insnNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "rg", "[Lta;"));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 8));
            methodNode.instructions.insertBefore(insnNode, new InsnNode(Opcodes.AALOAD));
            methodNode.instructions.insertBefore(insnNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "ta", "C", "Ljava/lang/String;"));
            methodNode.instructions.insertBefore(insnNode, new MethodInsnNode(Opcodes.INVOKESTATIC,
                    "Game/Client", "drawPlayer", "(IIIILjava/lang/String;)V"));
        } else if (methodNode.name.equals("b") && methodNode.desc.equals("(IIIIIII)V")) {
            // Draw Item hook
            // ILOAD 4 is item id
            AbstractInsnNode insnNode = methodNode.instructions.getLast();
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 3));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 7));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 5));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 1));
            methodNode.instructions.insertBefore(insnNode, new VarInsnNode(Opcodes.ILOAD, 4));
            methodNode.instructions.insertBefore(insnNode,
                    new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Client", "drawItem", "(IIIII)V"));
        } else if (methodNode.name.equals("L") && methodNode.desc.equals("(I)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Right click bounds fix
                if (insnNode.getOpcode() == Opcodes.SIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    AbstractInsnNode nextNode = insnNode.getNext();

                    if (call.operand == 510) {
                        call.operand = 512 - call.operand;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                    } else if (call.operand == 315) {
                        call.operand = 334 - call.operand;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "height_client", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                    } else if (call.operand == -316) {
                        call.operand = 334 - (call.operand * -1);
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "height_client", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.INEG));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                    }
                }
            }
        } else if (methodNode.name.equals("a") && methodNode.desc.equals("(ZZ)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Friends chat mouse fix
                if (insnNode.getOpcode() == Opcodes.SIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    if (call.operand == 489 || call.operand == 429) {
                        call.operand = 512 - call.operand;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                    }
                    if (call.operand == -430) {
                        call.operand = 512 - (call.operand * -1);
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.INEG));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                    }
                }
            }
        } else if (methodNode.name.equals("i") && methodNode.desc.equals("(I)V")) {
            AbstractInsnNode lastNode = methodNode.instructions.getLast().getPrevious();

            // Send combat style option
            LabelNode label = new LabelNode();

            methodNode.instructions.insert(lastNode, label);

            // Format
            methodNode.instructions.insert(lastNode,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "da", "b", "(I)V", false));
            methodNode.instructions.insert(lastNode, new IntInsnNode(Opcodes.SIPUSH, 21294));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "Jh", "Lda;"));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));

            // Write byte
            methodNode.instructions.insert(lastNode,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "ja", "c", "(II)V", false));
            methodNode.instructions.insert(lastNode, new IntInsnNode(Opcodes.BIPUSH, -80));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETSTATIC, "Client/Settings", "COMBAT_STYLE", "I"));
            methodNode.instructions.insert(lastNode, new FieldInsnNode(Opcodes.GETFIELD, "da", "f", "Lja;"));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "Jh", "Lda;"));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));

            // Create Packet
            methodNode.instructions.insert(lastNode,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "da", "b", "(II)V", false));
            methodNode.instructions.insert(lastNode, new InsnNode(Opcodes.ICONST_0));
            methodNode.instructions.insert(lastNode, new IntInsnNode(Opcodes.BIPUSH, 29));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "Jh", "Lda;"));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));

            // Skip combat packet if style is already controlled
            methodNode.instructions.insert(lastNode, new JumpInsnNode(Opcodes.IF_ICMPLE, label));
            methodNode.instructions.insert(lastNode, new InsnNode(Opcodes.ICONST_0));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETSTATIC, "Client/Settings", "COMBAT_STYLE", "I"));

            // Client init_game
            methodNode.instructions.insert(lastNode,
                    new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Client", "init_game", "()V", false));
        } else if (methodNode.name.equals("o") && methodNode.desc.equals("(I)V")) {
            // Client.init_login patch
            AbstractInsnNode findNode = methodNode.instructions.getLast();
            methodNode.instructions.insertBefore(findNode,
                    new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Client", "init_login", "()V", false));
        } else if (methodNode.name.equals("a") && methodNode.desc.equals("(B)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Camera view distance crash fix
                if (insnNode.getOpcode() == Opcodes.SIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    if (call.operand == 15000) {
                        call.operand = 32767;
                    }
                }
            }

            // Client.init patch
            AbstractInsnNode findNode = methodNode.instructions.getFirst();
            methodNode.instructions.insertBefore(findNode, new VarInsnNode(Opcodes.ALOAD, 0));
            methodNode.instructions.insertBefore(findNode,
                    new FieldInsnNode(Opcodes.PUTSTATIC, "Game/Client", "instance", "Ljava/lang/Object;"));
            methodNode.instructions.insertBefore(findNode,
                    new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Client", "init", "()V", false));
        } else if (methodNode.name.equals("G") && methodNode.desc.equals("(I)V")) {
            // TODO: This can be shortened, I'll fix it another time

            // NPC Dialogue keyboard
            AbstractInsnNode lastNode = methodNode.instructions.getLast().getPrevious();

            LabelNode label = new LabelNode();

            methodNode.instructions.insert(lastNode, label);

            // Hide dialogue
            methodNode.instructions.insert(lastNode, new FieldInsnNode(Opcodes.PUTFIELD, "client", "Ph", "Z"));
            methodNode.instructions.insert(lastNode, new InsnNode(Opcodes.ICONST_0));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));

            // Format
            methodNode.instructions.insert(lastNode,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "da", "b", "(I)V", false));
            methodNode.instructions.insert(lastNode, new IntInsnNode(Opcodes.SIPUSH, 21294));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "Jh", "Lda;"));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));

            // Write byte
            methodNode.instructions.insert(lastNode,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "ja", "c", "(II)V", false));
            methodNode.instructions.insert(lastNode, new IntInsnNode(Opcodes.BIPUSH, 115));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETSTATIC, "Game/KeyboardHandler", "dialogue_option", "I"));
            methodNode.instructions.insert(lastNode, new FieldInsnNode(Opcodes.GETFIELD, "da", "f", "Lja;"));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "Jh", "Lda;"));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));

            // Create Packet
            methodNode.instructions.insert(lastNode,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "da", "b", "(II)V", false));
            methodNode.instructions.insert(lastNode, new InsnNode(Opcodes.ICONST_0));
            methodNode.instructions.insert(lastNode, new IntInsnNode(Opcodes.BIPUSH, 116));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETFIELD, "client", "Jh", "Lda;"));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));

            // Check if dialogue option is pressed
            methodNode.instructions.insert(lastNode, new JumpInsnNode(Opcodes.IF_ICMPGE, label));
            // Menu option count
            methodNode.instructions.insert(lastNode, new FieldInsnNode(Opcodes.GETFIELD, "client", "Id", "I"));
            methodNode.instructions.insert(lastNode, new VarInsnNode(Opcodes.ALOAD, 0));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETSTATIC, "Game/KeyboardHandler", "dialogue_option", "I"));
            methodNode.instructions.insert(lastNode, new JumpInsnNode(Opcodes.IFLT, label));
            methodNode.instructions.insert(lastNode,
                    new FieldInsnNode(Opcodes.GETSTATIC, "Game/KeyboardHandler", "dialogue_option", "I"));
        } else if (methodNode.name.equals("f") && methodNode.desc.equals("(I)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Hide Roof option
                if (insnNode.getOpcode() == Opcodes.GETFIELD) {
                    FieldInsnNode field = (FieldInsnNode) insnNode;

                    if (field.owner.equals("client") && field.name.equals("yj")) {
                        AbstractInsnNode nextNode = insnNode.getNext();
                        if (nextNode.getOpcode() == Opcodes.IFNE) {
                            LabelNode label = ((JumpInsnNode) nextNode).label;
                            methodNode.instructions.insert(nextNode, new JumpInsnNode(Opcodes.IFGT, label));
                            methodNode.instructions.insert(nextNode,
                                    new FieldInsnNode(Opcodes.GETSTATIC, "Client/Settings", "HIDE_ROOFS", "Z"));
                        }
                    }
                }

                // Move wilderness skull
                if (insnNode.getOpcode() == Opcodes.SIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    if (call.operand == 465 || call.operand == 453) {
                        call.operand = 512 - call.operand;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                    }
                }
            }
        } else if (methodNode.name.equals("a") && methodNode.desc.equals("(IIZ)Z")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Move the load screen text dialogue
                if (insnNode.getOpcode() == Opcodes.SIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    if (call.operand == 256) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 192) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "height", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IADD));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 19));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    }
                }
            }
        } else if (methodNode.name.equals("d") && methodNode.desc.equals("(B)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Center logout dialogue
                if (insnNode.getOpcode() == Opcodes.SIPUSH || insnNode.getOpcode() == Opcodes.BIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    if (call.operand == 256) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 173) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "height", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 126) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 130));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 137) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "height", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 36));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    }
                }
            }
        } else if (methodNode.name.equals("j") && methodNode.desc.equals("(I)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Center welcome box
                if (insnNode.getOpcode() == Opcodes.SIPUSH || insnNode.getOpcode() == Opcodes.BIPUSH) {
                    IntInsnNode call = (IntInsnNode) insnNode;
                    if (call.operand == 256) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 167) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "height", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 6));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 56) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 200));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == -87) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.INEG));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 169));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 426) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IADD));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 170));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 106) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.ISUB));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 150));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    } else if (call.operand == 406) {
                        call.operand = 2;
                        methodNode.instructions.insertBefore(insnNode,
                                new FieldInsnNode(Opcodes.GETSTATIC, "Game/Renderer", "width", "I"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IADD));
                        methodNode.instructions.insert(insnNode, new IntInsnNode(Opcodes.SIPUSH, 150));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.IDIV));
                    }
                }
            }
        } else if (methodNode.name.equals("k") && methodNode.desc.equals("(B)V")) {
            Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
            while (insnNodeList.hasNext()) {
                AbstractInsnNode insnNode = insnNodeList.next();

                // Save settings from combat menu
                if (insnNode.getOpcode() == Opcodes.PUTFIELD) {
                    FieldInsnNode field = (FieldInsnNode) insnNode;

                    if (field.owner.equals("client") && field.name.equals("Fg")) {
                        methodNode.instructions.insert(insnNode, new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "Client/Settings", "save", "()V", false));
                        methodNode.instructions.insert(insnNode,
                                new FieldInsnNode(Opcodes.PUTSTATIC, "Client/Settings", "COMBAT_STYLE", "I"));
                        methodNode.instructions.insert(insnNode,
                                new FieldInsnNode(Opcodes.GETFIELD, "client", "Fg", "I"));
                        methodNode.instructions.insert(insnNode, new VarInsnNode(Opcodes.ALOAD, 0));
                    }
                }
            }
        } else if (methodNode.name.equals("a") && methodNode.desc
                .equals("(ZLjava/lang/String;ILjava/lang/String;IILjava/lang/String;Ljava/lang/String;)V")) {
            AbstractInsnNode first = methodNode.instructions.getFirst();
            methodNode.instructions.insertBefore(first, new VarInsnNode(Opcodes.ALOAD, 7));
            methodNode.instructions.insertBefore(first, new VarInsnNode(Opcodes.ALOAD, 4));
            methodNode.instructions.insertBefore(first, new VarInsnNode(Opcodes.ILOAD, 5));
            methodNode.instructions.insertBefore(first, new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Client",
                    "messageHook", "(Ljava/lang/String;Ljava/lang/String;I)V"));
        }
    }
}

From source file:Client.JClassPatcher.java

License:Open Source License

private void patchRenderer(ClassNode node) {
    Logger.Info("Patching renderer (" + node.name + ".class)");

    Iterator<MethodNode> methodNodeList = node.methods.iterator();
    while (methodNodeList.hasNext()) {
        MethodNode methodNode = methodNodeList.next();

        // Renderer present hook
        if (methodNode.desc.equals("(Ljava/awt/Graphics;III)V")) {
            AbstractInsnNode findNode = methodNode.instructions.getFirst();
            FieldInsnNode imageNode = null;

            while (findNode.getOpcode() != Opcodes.POP) {
                findNode = findNode.getNext();
                if (findNode == null) {
                    Logger.Error("Unable to find present hook");
                    break;
                }//  w  w  w  . j  a  va2s  .  c  om
            }

            while (findNode.getOpcode() != Opcodes.INVOKESPECIAL) {
                if (findNode.getOpcode() == Opcodes.GETFIELD)
                    imageNode = (FieldInsnNode) findNode;

                AbstractInsnNode prev = findNode.getPrevious();
                methodNode.instructions.remove(findNode);
                findNode = prev;
            }

            methodNode.instructions.insert(findNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Renderer",
                    "present", "(Ljava/awt/Graphics;Ljava/awt/Image;)V", false));
            methodNode.instructions.insert(findNode,
                    new FieldInsnNode(Opcodes.GETFIELD, node.name, imageNode.name, imageNode.desc));
            methodNode.instructions.insert(findNode, new VarInsnNode(Opcodes.ALOAD, 0));
            methodNode.instructions.insert(findNode, new VarInsnNode(Opcodes.ALOAD, 1));
        } else if (methodNode.name.equals("a") && methodNode.desc.equals("(IILjava/lang/String;IIBI)V")) {
            AbstractInsnNode start = methodNode.instructions.getFirst();
            while (start != null) {
                if (start.getOpcode() == Opcodes.ALOAD && start.getNext().getOpcode() == Opcodes.ILOAD
                        && start.getNext().getNext().getOpcode() == Opcodes.INVOKEVIRTUAL
                        && start.getNext().getNext().getNext().getOpcode() == Opcodes.ISTORE) {
                    break;
                }

                start = start.getNext();
            }
            start = start.getPrevious();

            LabelNode finishLabel = ((JumpInsnNode) start.getPrevious().getPrevious()).label;
            LabelNode failLabel = new LabelNode();

            methodNode.instructions.insertBefore(start, new IntInsnNode(Opcodes.BIPUSH, 126));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C"));
            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPNE, failLabel));

            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I"));
            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPGE, failLabel));

            methodNode.instructions.insertBefore(start, new IntInsnNode(Opcodes.BIPUSH, 126));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C"));
            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPNE, failLabel));

            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_1));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
                    "java/lang/String", "substring", "(II)Ljava/lang/String;"));
            methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKESTATIC,
                    "java/lang/Integer", "parseInt", "(Ljava/lang/String;)I"));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ISTORE, 4));
            methodNode.instructions.insertBefore(start, new IincInsnNode(10, 5));

            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.GOTO, finishLabel));

            methodNode.instructions.insertBefore(start, failLabel);
        }
    }
}

From source file:Client.JClassPatcher.java

License:Open Source License

private void patchRandom(ClassNode node) {
    Logger.Info("Patching random (" + node.name + ".class)");

    Iterator<MethodNode> methodNodeList = node.methods.iterator();
    while (methodNodeList.hasNext()) {
        MethodNode methodNode = methodNodeList.next();

        if (methodNode.name.equals("a")) {
            // System.out.println(methodNode.desc);
            if (methodNode.desc.equals("(ILtb;)V")) {
                Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
                while (insnNodeList.hasNext()) {
                    AbstractInsnNode insnNode = insnNodeList.next();
                    AbstractInsnNode nextNode = insnNode.getNext();

                    if (nextNode == null)
                        break;

                    if (insnNode.getOpcode() == Opcodes.ALOAD && nextNode.getOpcode() == Opcodes.ICONST_0) {
                        VarInsnNode call = (VarInsnNode) insnNode;
                        System.out.println("Patching validation...");

                        methodNode.instructions.insert(insnNode, new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
                                "java/util/Random", "nextBytes", "([B)V"));
                        methodNode.instructions.insert(insnNode, new VarInsnNode(Opcodes.ALOAD, 2));
                        methodNode.instructions.insert(insnNode,
                                new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/Random", "<init>", "()V"));
                        methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.DUP));
                        methodNode.instructions.insert(insnNode,
                                new TypeInsnNode(Opcodes.NEW, "java/util/Random"));
                    }//  ww w .  j  ava 2  s  .  c om
                }
            }
        }
    }
}

From source file:com.android.build.gradle.internal.incremental.ConstructorBuilder.java

License:Apache License

/**
 * Splits the constructor in two methods, the "set up" and the "body" parts (see above).
 *//*w  ww. j  a  va2 s  .  c om*/
@NonNull
private static Constructor split(@NonNull String owner, @NonNull MethodNode method,
        @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine,
        @NonNull List<LocalVariable> variables, int localsAtLoadThis) {
    String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]);

    // Do not add the local array yet, as we treat it as a new variable.
    String newDesc = method.desc.replace(")V", ")Ljava/lang/Object;");
    newDesc = newDesc.replace("(", "([L" + owner + ";");

    Type[] argumentTypes = Type.getArgumentTypes(newDesc);

    // Store the non hotswappable part of the constructor
    List<AbstractInsnNode> fixed = Lists.newLinkedList();
    AbstractInsnNode insn = method.instructions.getFirst();
    while (insn != loadThis) {
        fixed.add(insn);
        insn = insn.getNext();
    }
    fixed.add(loadThis);

    MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null,
            exceptions);
    GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc);
    int newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;"));

    mv.loadLocal(newArgument);
    ByteCodeUtils.restoreVariables(mv, variables.subList(0, localsAtLoadThis));

    // Now insert the original method
    insn = loadThis.getNext();
    while (insn != delegation) {
        insn.accept(mv);
        insn = insn.getNext();
    }
    LabelNode labelBefore = new LabelNode();
    labelBefore.accept(mv);

    // Create the args array with the local variables and the values to send to the delegated constructor
    Type[] returnTypes = Type.getArgumentTypes(delegation.desc);
    // The extra elements for the local variables and the qualified name of the constructor.
    mv.push(returnTypes.length + 2);
    mv.newArray(Type.getType(Object.class));
    int args = mv.newLocal(Type.getType("[Ljava/lang/Object;"));
    mv.storeLocal(args);
    for (int i = returnTypes.length - 1; i >= 0; i--) {
        Type type = returnTypes[i];
        mv.loadLocal(args);
        mv.swap(type, Type.getType(Object.class));
        mv.push(i + 2);
        mv.swap(type, Type.INT_TYPE);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
    }

    // Store the qualified name of the constructor in the second element of the array.
    mv.loadLocal(args);
    mv.push(1);
    mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called.
    mv.arrayStore(Type.getType(Object.class));

    // Create the locals array and place it in the first element of the return array
    mv.loadLocal(args);
    mv.push(0);
    mv.push(argumentTypes.length + 1);
    mv.newArray(Type.getType(Object.class));
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(Arrays.asList(argumentTypes)), 0);

    mv.dup();
    mv.push(argumentTypes.length);
    ByteCodeUtils.newVariableArray(mv, variables);
    mv.arrayStore(Type.getType(Object.class));

    mv.arrayStore(Type.getType(Object.class));

    mv.loadLocal(args);
    mv.returnValue();

    // Move the first variable up to be an argument
    initArgs.desc = initArgs.desc.replace(")", "[Ljava/lang/Object;)");

    newDesc = method.desc.replace("(", "(L" + owner + ";");
    MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null,
            exceptions);
    mv = new GeneratorAdapter(body, body.access, body.name, body.desc);
    newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;"));

    LabelNode labelAfter = new LabelNode();
    labelAfter.accept(body);
    Set<LabelNode> bodyLabels = new HashSet<LabelNode>();

    mv.loadLocal(newArgument);
    ByteCodeUtils.restoreVariables(mv, variables);

    insn = delegation.getNext();
    while (insn != null) {
        if (insn instanceof LabelNode) {
            bodyLabels.add((LabelNode) insn);
        }
        insn.accept(mv);
        insn = insn.getNext();
    }

    // manually transfer the exception table from the existing constructor to the new
    // "init$body" method. The labels were transferred just above so we can reuse them.

    //noinspection unchecked
    for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) {
        tryCatch.accept(mv);
    }

    //noinspection unchecked
    for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) {
        boolean startsInBody = bodyLabels.contains(variable.start);
        boolean endsInBody = bodyLabels.contains(variable.end);
        if (!startsInBody && !endsInBody) {
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                variable.accept(initArgs);
            }
        } else if (startsInBody && endsInBody) {
            variable.accept(body);
        } else if (!startsInBody && endsInBody) {
            // The variable spans from the args to the end of the method, create two:
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                        variable.start, labelBefore, variable.index);
                var0.accept(initArgs);
            }
            LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                    labelAfter, variable.end, variable.index);
            var1.accept(body);
        } else {
            throw new IllegalStateException("Local variable starts after it ends.");
        }
    }
    // Move the first variable up to be an argument
    body.desc = body.desc.replace(")", "[Ljava/lang/Object;)");

    return new Constructor(owner, fixed, loadThis, loadThisLine, initArgs, delegation, body, variables,
            localsAtLoadThis);
}

From source file:com.android.build.gradle.internal.incremental.ConstructorDelegationDetector.java

License:Apache License

/**
 * Splits the constructor in two methods, the "set up" and the "body" parts (see above).
 *//*  ww w. ja  va  2 s. co  m*/
@NonNull
private static Constructor split(@NonNull String owner, @NonNull MethodNode method,
        @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine) {
    String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]);
    String newDesc = method.desc.replaceAll("\\((.*)\\)V", "([Ljava/lang/Object;$1)Ljava/lang/Object;");

    MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null,
            exceptions);
    AbstractInsnNode insn = loadThis.getNext();
    while (insn != delegation) {
        insn.accept(initArgs);
        insn = insn.getNext();
    }
    LabelNode labelBefore = new LabelNode();
    labelBefore.accept(initArgs);

    GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc);
    // Copy the arguments back to the argument array
    // The init_args part cannot access the "this" object and can have side effects on the
    // local variables. Because of this we use the first argument (which we want to keep
    // so all the other arguments remain unchanged) as a reference to the array where to
    // return the values of the modified local variables.
    Type[] types = Type.getArgumentTypes(initArgs.desc);
    int stack = 1; // Skip the first one which is a reference to the local array.
    for (int i = 1; i < types.length; i++) {
        Type type = types[i];
        // This is not this, but the array of local arguments final values.
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.push(i);
        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), stack);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
        stack += type.getSize();
    }
    // Create the args array with the values to send to the delegated constructor
    Type[] returnTypes = Type.getArgumentTypes(delegation.desc);
    // The extra element for the qualified name of the constructor.
    mv.push(returnTypes.length + 1);
    mv.newArray(Type.getType(Object.class));
    int args = mv.newLocal(Type.getType("[Ljava/lang/Object;"));
    mv.storeLocal(args);
    for (int i = returnTypes.length - 1; i >= 0; i--) {
        Type type = returnTypes[i];
        mv.loadLocal(args);
        mv.swap(type, Type.getType(Object.class));
        mv.push(i + 1);
        mv.swap(type, Type.INT_TYPE);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
    }

    // Store the qualified name of the constructor in the first element of the array.
    mv.loadLocal(args);
    mv.push(0);
    mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called.
    mv.arrayStore(Type.getType(Object.class));

    mv.loadLocal(args);
    mv.returnValue();

    newDesc = method.desc.replace("(", "(L" + owner + ";");
    MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null,
            exceptions);
    LabelNode labelAfter = new LabelNode();
    labelAfter.accept(body);
    Set<LabelNode> bodyLabels = new HashSet<LabelNode>();

    insn = delegation.getNext();
    while (insn != null) {
        if (insn instanceof LabelNode) {
            bodyLabels.add((LabelNode) insn);
        }
        insn.accept(body);
        insn = insn.getNext();
    }

    // manually transfer the exception table from the existing constructor to the new
    // "init$body" method. The labels were transferred just above so we can reuse them.

    //noinspection unchecked
    for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) {
        tryCatch.accept(body);
    }

    //noinspection unchecked
    for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) {
        boolean startsInBody = bodyLabels.contains(variable.start);
        boolean endsInBody = bodyLabels.contains(variable.end);
        if (!startsInBody && !endsInBody) {
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                variable.accept(initArgs);
            }
        } else if (startsInBody && endsInBody) {
            variable.accept(body);
        } else if (!startsInBody && endsInBody) {
            // The variable spans from the args to the end of the method, create two:
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                        variable.start, labelBefore, variable.index);
                var0.accept(initArgs);
            }
            LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                    labelAfter, variable.end, variable.index);
            var1.accept(body);
        } else {
            throw new IllegalStateException("Local variable starts after it ends.");
        }
    }

    return new Constructor(loadThis, loadThisLine, initArgs, delegation, body);
}