Search in sources :

Example 1 with LabelNode

use of jdk.internal.org.objectweb.asm.tree.LabelNode in project jdk8u_jdk by JetBrains.

the class JSRInlinerAdapter method markSubroutines.

/**
     * Walks the method and determines which internal subroutine(s), if any,
     * each instruction is a method of.
     */
private void markSubroutines() {
    BitSet anyvisited = new BitSet();
    // First walk the main subroutine and find all those instructions which
    // can be reached without invoking any JSR at all
    markSubroutineWalk(mainSubroutine, 0, anyvisited);
    // to that subroutine without following any JSR links.
    for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads.entrySet().iterator(); it.hasNext(); ) {
        Map.Entry<LabelNode, BitSet> entry = it.next();
        LabelNode lab = entry.getKey();
        BitSet sub = entry.getValue();
        int index = instructions.indexOf(lab);
        markSubroutineWalk(sub, index, anyvisited);
    }
}
Also used : LabelNode(jdk.internal.org.objectweb.asm.tree.LabelNode) BitSet(java.util.BitSet) HashMap(java.util.HashMap) AbstractMap(java.util.AbstractMap) Map(java.util.Map)

Example 2 with LabelNode

use of jdk.internal.org.objectweb.asm.tree.LabelNode in project jdk8u_jdk by JetBrains.

the class Analyzer method findSubroutine.

private void findSubroutine(int insn, final Subroutine sub, final List<AbstractInsnNode> calls) throws AnalyzerException {
    while (true) {
        if (insn < 0 || insn >= n) {
            throw new AnalyzerException(null, "Execution can fall off end of the code");
        }
        if (subroutines[insn] != null) {
            return;
        }
        subroutines[insn] = sub.copy();
        AbstractInsnNode node = insns.get(insn);
        // calls findSubroutine recursively on normal successors
        if (node instanceof JumpInsnNode) {
            if (node.getOpcode() == JSR) {
                // do not follow a JSR, it leads to another subroutine!
                calls.add(node);
            } else {
                JumpInsnNode jnode = (JumpInsnNode) node;
                findSubroutine(insns.indexOf(jnode.label), sub, calls);
            }
        } else if (node instanceof TableSwitchInsnNode) {
            TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
            findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
            for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
                LabelNode l = tsnode.labels.get(i);
                findSubroutine(insns.indexOf(l), sub, calls);
            }
        } else if (node instanceof LookupSwitchInsnNode) {
            LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
            findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
            for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
                LabelNode l = lsnode.labels.get(i);
                findSubroutine(insns.indexOf(l), sub, calls);
            }
        }
        // calls findSubroutine recursively on exception handler successors
        List<TryCatchBlockNode> insnHandlers = handlers[insn];
        if (insnHandlers != null) {
            for (int i = 0; i < insnHandlers.size(); ++i) {
                TryCatchBlockNode tcb = insnHandlers.get(i);
                findSubroutine(insns.indexOf(tcb.handler), sub, calls);
            }
        }
        // if insn does not falls through to the next instruction, return.
        switch(node.getOpcode()) {
            case GOTO:
            case RET:
            case TABLESWITCH:
            case LOOKUPSWITCH:
            case IRETURN:
            case LRETURN:
            case FRETURN:
            case DRETURN:
            case ARETURN:
            case RETURN:
            case ATHROW:
                return;
        }
        insn++;
    }
}
Also used : LabelNode(jdk.internal.org.objectweb.asm.tree.LabelNode) TryCatchBlockNode(jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode) TableSwitchInsnNode(jdk.internal.org.objectweb.asm.tree.TableSwitchInsnNode) JumpInsnNode(jdk.internal.org.objectweb.asm.tree.JumpInsnNode) LookupSwitchInsnNode(jdk.internal.org.objectweb.asm.tree.LookupSwitchInsnNode) AbstractInsnNode(jdk.internal.org.objectweb.asm.tree.AbstractInsnNode)

Example 3 with LabelNode

use of jdk.internal.org.objectweb.asm.tree.LabelNode in project Bytecoder by mirkosertic.

the class Analyzer method findSubroutine.

private void findSubroutine(int insn, final Subroutine sub, final List<AbstractInsnNode> calls) throws AnalyzerException {
    while (true) {
        if (insn < 0 || insn >= n) {
            throw new AnalyzerException(null, "Execution can fall off end of the code");
        }
        if (subroutines[insn] != null) {
            return;
        }
        subroutines[insn] = sub.copy();
        AbstractInsnNode node = insns.get(insn);
        // calls findSubroutine recursively on normal successors
        if (node instanceof JumpInsnNode) {
            if (node.getOpcode() == JSR) {
                // do not follow a JSR, it leads to another subroutine!
                calls.add(node);
            } else {
                JumpInsnNode jnode = (JumpInsnNode) node;
                findSubroutine(insns.indexOf(jnode.label), sub, calls);
            }
        } else if (node instanceof TableSwitchInsnNode) {
            TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
            findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
            for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
                LabelNode l = tsnode.labels.get(i);
                findSubroutine(insns.indexOf(l), sub, calls);
            }
        } else if (node instanceof LookupSwitchInsnNode) {
            LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
            findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
            for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
                LabelNode l = lsnode.labels.get(i);
                findSubroutine(insns.indexOf(l), sub, calls);
            }
        }
        // calls findSubroutine recursively on exception handler successors
        List<TryCatchBlockNode> insnHandlers = handlers[insn];
        if (insnHandlers != null) {
            for (int i = 0; i < insnHandlers.size(); ++i) {
                TryCatchBlockNode tcb = insnHandlers.get(i);
                findSubroutine(insns.indexOf(tcb.handler), sub, calls);
            }
        }
        // if insn does not falls through to the next instruction, return.
        switch(node.getOpcode()) {
            case GOTO:
            case RET:
            case TABLESWITCH:
            case LOOKUPSWITCH:
            case IRETURN:
            case LRETURN:
            case FRETURN:
            case DRETURN:
            case ARETURN:
            case RETURN:
            case ATHROW:
                return;
        }
        insn++;
    }
}
Also used : LabelNode(jdk.internal.org.objectweb.asm.tree.LabelNode) TryCatchBlockNode(jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode) TableSwitchInsnNode(jdk.internal.org.objectweb.asm.tree.TableSwitchInsnNode) JumpInsnNode(jdk.internal.org.objectweb.asm.tree.JumpInsnNode) LookupSwitchInsnNode(jdk.internal.org.objectweb.asm.tree.LookupSwitchInsnNode) AbstractInsnNode(jdk.internal.org.objectweb.asm.tree.AbstractInsnNode)

Example 4 with LabelNode

use of jdk.internal.org.objectweb.asm.tree.LabelNode in project Bytecoder by mirkosertic.

the class Analyzer method analyze.

/**
 * Analyzes the given method.
 *
 * @param owner
 *            the internal name of the class to which the method belongs.
 * @param m
 *            the method to be analyzed.
 * @return the symbolic state of the execution stack frame at each bytecode
 *         instruction of the method. The size of the returned array is
 *         equal to the number of instructions (and labels) of the method. A
 *         given frame is <tt>null</tt> if and only if the corresponding
 *         instruction cannot be reached (dead code).
 * @throws AnalyzerException
 *             if a problem occurs during the analysis.
 */
@SuppressWarnings("unchecked")
public Frame<V>[] analyze(final String owner, final MethodNode m) throws AnalyzerException {
    if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
        frames = (Frame<V>[]) new Frame<?>[0];
        return frames;
    }
    n = m.instructions.size();
    insns = m.instructions;
    handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
    frames = (Frame<V>[]) new Frame<?>[n];
    subroutines = new Subroutine[n];
    queued = new boolean[n];
    queue = new int[n];
    top = 0;
    // computes exception handlers for each instruction
    for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
        TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
        int begin = insns.indexOf(tcb.start);
        int end = insns.indexOf(tcb.end);
        for (int j = begin; j < end; ++j) {
            List<TryCatchBlockNode> insnHandlers = handlers[j];
            if (insnHandlers == null) {
                insnHandlers = new ArrayList<TryCatchBlockNode>();
                handlers[j] = insnHandlers;
            }
            insnHandlers.add(tcb);
        }
    }
    // computes the subroutine for each instruction:
    Subroutine main = new Subroutine(null, m.maxLocals, null);
    List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
    Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
    findSubroutine(0, main, subroutineCalls);
    while (!subroutineCalls.isEmpty()) {
        JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
        Subroutine sub = subroutineHeads.get(jsr.label);
        if (sub == null) {
            sub = new Subroutine(jsr.label, m.maxLocals, jsr);
            subroutineHeads.put(jsr.label, sub);
            findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
        } else {
            sub.callers.add(jsr);
        }
    }
    for (int i = 0; i < n; ++i) {
        if (subroutines[i] != null && subroutines[i].start == null) {
            subroutines[i] = null;
        }
    }
    // initializes the data structures for the control flow analysis
    Frame<V> current = newFrame(m.maxLocals, m.maxStack);
    Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
    current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
    Type[] args = Type.getArgumentTypes(m.desc);
    int local = 0;
    if ((m.access & ACC_STATIC) == 0) {
        Type ctype = Type.getObjectType(owner);
        current.setLocal(local++, interpreter.newValue(ctype));
    }
    for (int i = 0; i < args.length; ++i) {
        current.setLocal(local++, interpreter.newValue(args[i]));
        if (args[i].getSize() == 2) {
            current.setLocal(local++, interpreter.newValue(null));
        }
    }
    while (local < m.maxLocals) {
        current.setLocal(local++, interpreter.newValue(null));
    }
    merge(0, current, null);
    init(owner, m);
    // control flow analysis
    while (top > 0) {
        int insn = queue[--top];
        Frame<V> f = frames[insn];
        Subroutine subroutine = subroutines[insn];
        queued[insn] = false;
        AbstractInsnNode insnNode = null;
        try {
            insnNode = m.instructions.get(insn);
            int insnOpcode = insnNode.getOpcode();
            int insnType = insnNode.getType();
            if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
                merge(insn + 1, f, subroutine);
                newControlFlowEdge(insn, insn + 1);
            } else {
                current.init(f).execute(insnNode, interpreter);
                subroutine = subroutine == null ? null : subroutine.copy();
                if (insnNode instanceof JumpInsnNode) {
                    JumpInsnNode j = (JumpInsnNode) insnNode;
                    if (insnOpcode != GOTO && insnOpcode != JSR) {
                        merge(insn + 1, current, subroutine);
                        newControlFlowEdge(insn, insn + 1);
                    }
                    int jump = insns.indexOf(j.label);
                    if (insnOpcode == JSR) {
                        merge(jump, current, new Subroutine(j.label, m.maxLocals, j));
                    } else {
                        merge(jump, current, subroutine);
                    }
                    newControlFlowEdge(insn, jump);
                } else if (insnNode instanceof LookupSwitchInsnNode) {
                    LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
                    int jump = insns.indexOf(lsi.dflt);
                    merge(jump, current, subroutine);
                    newControlFlowEdge(insn, jump);
                    for (int j = 0; j < lsi.labels.size(); ++j) {
                        LabelNode label = lsi.labels.get(j);
                        jump = insns.indexOf(label);
                        merge(jump, current, subroutine);
                        newControlFlowEdge(insn, jump);
                    }
                } else if (insnNode instanceof TableSwitchInsnNode) {
                    TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
                    int jump = insns.indexOf(tsi.dflt);
                    merge(jump, current, subroutine);
                    newControlFlowEdge(insn, jump);
                    for (int j = 0; j < tsi.labels.size(); ++j) {
                        LabelNode label = tsi.labels.get(j);
                        jump = insns.indexOf(label);
                        merge(jump, current, subroutine);
                        newControlFlowEdge(insn, jump);
                    }
                } else if (insnOpcode == RET) {
                    if (subroutine == null) {
                        throw new AnalyzerException(insnNode, "RET instruction outside of a sub routine");
                    }
                    for (int i = 0; i < subroutine.callers.size(); ++i) {
                        JumpInsnNode caller = subroutine.callers.get(i);
                        int call = insns.indexOf(caller);
                        if (frames[call] != null) {
                            merge(call + 1, frames[call], current, subroutines[call], subroutine.access);
                            newControlFlowEdge(insn, call + 1);
                        }
                    }
                } else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
                    if (subroutine != null) {
                        if (insnNode instanceof VarInsnNode) {
                            int var = ((VarInsnNode) insnNode).var;
                            subroutine.access[var] = true;
                            if (insnOpcode == LLOAD || insnOpcode == DLOAD || insnOpcode == LSTORE || insnOpcode == DSTORE) {
                                subroutine.access[var + 1] = true;
                            }
                        } else if (insnNode instanceof IincInsnNode) {
                            int var = ((IincInsnNode) insnNode).var;
                            subroutine.access[var] = true;
                        }
                    }
                    merge(insn + 1, current, subroutine);
                    newControlFlowEdge(insn, insn + 1);
                }
            }
            List<TryCatchBlockNode> insnHandlers = handlers[insn];
            if (insnHandlers != null) {
                for (int i = 0; i < insnHandlers.size(); ++i) {
                    TryCatchBlockNode tcb = insnHandlers.get(i);
                    Type type;
                    if (tcb.type == null) {
                        type = Type.getObjectType("java/lang/Throwable");
                    } else {
                        type = Type.getObjectType(tcb.type);
                    }
                    int jump = insns.indexOf(tcb.handler);
                    if (newControlFlowExceptionEdge(insn, tcb)) {
                        handler.init(f);
                        handler.clearStack();
                        handler.push(interpreter.newValue(type));
                        merge(jump, handler, subroutine);
                    }
                }
            }
        } catch (AnalyzerException e) {
            throw new AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.getMessage(), e);
        } catch (Exception e) {
            throw new AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.getMessage(), e);
        }
    }
    return frames;
}
Also used : LabelNode(jdk.internal.org.objectweb.asm.tree.LabelNode) TryCatchBlockNode(jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode) TableSwitchInsnNode(jdk.internal.org.objectweb.asm.tree.TableSwitchInsnNode) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) AbstractInsnNode(jdk.internal.org.objectweb.asm.tree.AbstractInsnNode) Type(jdk.internal.org.objectweb.asm.Type) JumpInsnNode(jdk.internal.org.objectweb.asm.tree.JumpInsnNode) IincInsnNode(jdk.internal.org.objectweb.asm.tree.IincInsnNode) InsnList(jdk.internal.org.objectweb.asm.tree.InsnList) ArrayList(java.util.ArrayList) List(java.util.List) LookupSwitchInsnNode(jdk.internal.org.objectweb.asm.tree.LookupSwitchInsnNode) VarInsnNode(jdk.internal.org.objectweb.asm.tree.VarInsnNode)

Example 5 with LabelNode

use of jdk.internal.org.objectweb.asm.tree.LabelNode in project Bytecoder by mirkosertic.

the class JSRInlinerAdapter method markSubroutines.

/**
 * Walks the method and determines which internal subroutine(s), if any,
 * each instruction is a method of.
 */
private void markSubroutines() {
    BitSet anyvisited = new BitSet();
    // First walk the main subroutine and find all those instructions which
    // can be reached without invoking any JSR at all
    markSubroutineWalk(mainSubroutine, 0, anyvisited);
    // to that subroutine without following any JSR links.
    for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads.entrySet().iterator(); it.hasNext(); ) {
        Map.Entry<LabelNode, BitSet> entry = it.next();
        LabelNode lab = entry.getKey();
        BitSet sub = entry.getValue();
        int index = instructions.indexOf(lab);
        markSubroutineWalk(sub, index, anyvisited);
    }
}
Also used : LabelNode(jdk.internal.org.objectweb.asm.tree.LabelNode) BitSet(java.util.BitSet) HashMap(java.util.HashMap) AbstractMap(java.util.AbstractMap) Map(java.util.Map)

Aggregations

LabelNode (jdk.internal.org.objectweb.asm.tree.LabelNode)12 JumpInsnNode (jdk.internal.org.objectweb.asm.tree.JumpInsnNode)10 AbstractInsnNode (jdk.internal.org.objectweb.asm.tree.AbstractInsnNode)8 LookupSwitchInsnNode (jdk.internal.org.objectweb.asm.tree.LookupSwitchInsnNode)8 TableSwitchInsnNode (jdk.internal.org.objectweb.asm.tree.TableSwitchInsnNode)8 BitSet (java.util.BitSet)6 TryCatchBlockNode (jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode)6 HashMap (java.util.HashMap)4 AbstractMap (java.util.AbstractMap)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Map (java.util.Map)2 Type (jdk.internal.org.objectweb.asm.Type)2 IincInsnNode (jdk.internal.org.objectweb.asm.tree.IincInsnNode)2 InsnList (jdk.internal.org.objectweb.asm.tree.InsnList)2 InsnNode (jdk.internal.org.objectweb.asm.tree.InsnNode)2 LocalVariableNode (jdk.internal.org.objectweb.asm.tree.LocalVariableNode)2 VarInsnNode (jdk.internal.org.objectweb.asm.tree.VarInsnNode)2