Example usage for org.objectweb.asm.tree InsnList get

List of usage examples for org.objectweb.asm.tree InsnList get

Introduction

In this page you can find the example usage for org.objectweb.asm.tree InsnList get.

Prototype

public AbstractInsnNode get(final int index) 

Source Link

Document

Returns the instruction whose index is given.

Usage

From source file:org.evosuite.regression.bytecode.RegressionClassDiff.java

License:Open Source License

private static Map<String, List<Integer>> getClassInstructions(InputStream classAsInputStream) {
    HashMap<String, List<Integer>> methodInstructionsMap = new HashMap<>();
    try {/*from  w  ww .ja v  a  2  s .  c om*/
        ClassReader reader = new ClassReader(classAsInputStream);
        ClassNode classNode = new ClassNode();
        reader.accept(classNode, 0);
        @SuppressWarnings("unchecked")
        final List<MethodNode> methods = classNode.methods;
        Printer printer = new Textifier();
        TraceMethodVisitor mp = new TraceMethodVisitor(printer);
        for (MethodNode m : methods) {
            List<Integer> instructions = new ArrayList<>();

            InsnList inList = m.instructions;

            String mathodID = m.name + ": " + m.desc;
            System.out.println(mathodID);
            int[] methodInstructions = new int[inList.size()];
            for (int i = 0; i < inList.size(); i++) {
                int op = inList.get(i).getOpcode();
                methodInstructions[i] = op;
                AbstractInsnNode insn = inList.get(i);
                insn.accept(mp);

                // Uncomment the following comment block to print the bytecode
                // instructions
                // StringWriter sw = new StringWriter();
                // printer.print(new PrintWriter(sw));
                // printer.getText().clear();
                // System.out.println(sw.toString());
                // logger.warn("{} -> {}", sw.toString(), op);
                if (op != -1)
                    instructions.add(op);
            }
            methodInstructionsMap.put(mathodID, instructions);
        }
    } catch (IOException e) {
        // Will fail if ClassReader fails
        e.printStackTrace();
    }
    return methodInstructionsMap;
}

From source file:org.evosuite.regression.RegressionClassDiff.java

License:Open Source License

public static Map<String, List<Integer>> getClassInstructions(InputStream classAsInputStream) {
    HashMap<String, List<Integer>> methodInstructionsMap = new HashMap<>();
    try {/*from  w w  w  . j a  v  a2s. com*/
        ClassReader reader = new ClassReader(classAsInputStream);
        ClassNode classNode = new ClassNode();
        reader.accept(classNode, 0);
        @SuppressWarnings("unchecked")
        final List<MethodNode> methods = classNode.methods;
        Printer printer = new Textifier();
        TraceMethodVisitor mp = new TraceMethodVisitor(printer);
        for (MethodNode m : methods) {
            List<Integer> instructions = new ArrayList<>();

            InsnList inList = m.instructions;

            String mathodID = m.name + ": " + m.desc;
            System.out.println(mathodID);
            int[] methodInstructions = new int[inList.size()];
            for (int i = 0; i < inList.size(); i++) {
                int op = inList.get(i).getOpcode();
                methodInstructions[i] = op;
                AbstractInsnNode insn = inList.get(i);
                insn.accept(mp);

                // Uncomment the following comment block to print the bytecode
                // instructions
                // StringWriter sw = new StringWriter();
                // printer.print(new PrintWriter(sw));
                // printer.getText().clear();
                // System.out.println(sw.toString());
                // logger.warn("{} -> {}", sw.toString(), op);
                if (op != -1)
                    instructions.add(op);
            }
            methodInstructionsMap.put(mathodID, instructions);
        }
    } catch (IOException e) {
        // Will fail if ClassReader fails
        e.printStackTrace();
    }
    return methodInstructionsMap;
}

From source file:org.evosuite.testcarver.instrument.Instrumenter.java

License:Open Source License

private void instrumentGETXXXFieldAccesses(final ClassNode cn, final String internalClassName,
        final MethodNode methodNode) {
    final InsnList instructions = methodNode.instructions;

    AbstractInsnNode ins = null;//from  w w w  . ja  v a2 s .co  m
    FieldInsnNode fieldIns = null;

    for (int i = 0; i < instructions.size(); i++) {
        ins = instructions.get(i);
        if (ins instanceof FieldInsnNode) {
            fieldIns = (FieldInsnNode) ins;

            /*
             * Is field referencing outermost instance? if yes, ignore it
             * http://tns-www.lcs.mit.edu/manuals/java-1.1.1/guide/innerclasses/spec/innerclasses.doc10.html
             */
            if (fieldIns.name.endsWith("$0")) {
                continue;
            }

            final int opcode = ins.getOpcode();
            if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) {
                final InsnList il = new InsnList();

                if (opcode == Opcodes.GETFIELD) {
                    Type fieldType = Type.getType(fieldIns.desc);
                    if (fieldType.getSize() == 1) {
                        instructions.insertBefore(fieldIns, new InsnNode(Opcodes.DUP));
                        il.add(new InsnNode(Opcodes.SWAP));
                    } else if (fieldType.getSize() == 2) {
                        instructions.insertBefore(fieldIns, new InsnNode(Opcodes.DUP));
                        // v
                        // GETFIELD
                        // v, w
                        il.add(new InsnNode(Opcodes.DUP2_X1));
                        // w, v, w
                        il.add(new InsnNode(Opcodes.POP2));
                        // w, v
                        // -> Call
                        // w
                    }
                } else
                    il.add(new InsnNode(Opcodes.ACONST_NULL));

                il.add(new LdcInsnNode(this.captureId));
                il.add(new LdcInsnNode(fieldIns.owner));
                il.add(new LdcInsnNode(fieldIns.name));
                il.add(new LdcInsnNode(fieldIns.desc));

                il.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                        PackageInfo.getNameWithSlash(org.evosuite.testcarver.capture.FieldRegistry.class),
                        "notifyReadAccess",
                        "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"));

                i += il.size();

                instructions.insert(fieldIns, il);
                this.captureId++;
            }
        }
    }
}

From source file:org.evosuite.testcarver.instrument.Instrumenter.java

License:Open Source License

private void instrumentPUTXXXFieldAccesses(final ClassNode cn, final String internalClassName,
        final MethodNode methodNode) {
    final InsnList instructions = methodNode.instructions;

    AbstractInsnNode ins = null;/*w w  w.  j  a  v a2 s. c  om*/
    FieldInsnNode fieldIns = null;

    // needed get right receiver var in case of PUTFIELD

    for (int i = 0; i < instructions.size(); i++) {
        ins = instructions.get(i);
        if (ins instanceof FieldInsnNode) {
            fieldIns = (FieldInsnNode) ins;

            /*
             * Is field referencing outermost instance? if yes, ignore it
             * http://tns-www.lcs.mit.edu/manuals/java-1.1.1/guide/innerclasses/spec/innerclasses.doc10.html
             */
            if (fieldIns.name.endsWith("$0")) {
                continue;
            }

            final int opcode = ins.getOpcode();
            if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) {
                // construction of  
                //   Capturer.capture(final Object receiver, final String methodName, final Object[] methodParams)
                // call
                final InsnList il = new InsnList();

                if (opcode == Opcodes.PUTFIELD) {
                    Type fieldType = Type.getType(fieldIns.desc);
                    if (fieldType.getSize() == 1) {
                        instructions.insertBefore(fieldIns, new InsnNode(Opcodes.DUP2));
                        il.add(new InsnNode(Opcodes.POP));
                    } else if (fieldType.getSize() == 2) {
                        InsnList uglyList = new InsnList();
                        // v, w
                        uglyList.add(new InsnNode(Opcodes.DUP2_X1));
                        // w, v, w
                        uglyList.add(new InsnNode(Opcodes.POP2));
                        // w, v
                        uglyList.add(new InsnNode(Opcodes.DUP));
                        // w, v, v
                        uglyList.add(new InsnNode(Opcodes.DUP2_X2));
                        // v, v, w, v, v
                        uglyList.add(new InsnNode(Opcodes.POP2));
                        // v, v, w
                        instructions.insertBefore(fieldIns, uglyList);
                        // PUTFIELD
                        // v
                    }
                } else
                    il.add(new InsnNode(Opcodes.ACONST_NULL));

                il.add(new LdcInsnNode(this.captureId));
                il.add(new LdcInsnNode(fieldIns.owner));
                il.add(new LdcInsnNode(fieldIns.name));
                il.add(new LdcInsnNode(fieldIns.desc));

                il.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                        PackageInfo.getNameWithSlash(FieldRegistry.class), "notifyModification",
                        "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"));

                // PUTFIELDRegistry.notifyModification also adds corresponding GETFIELD capture instructions
                this.captureId++;
                i += il.size();

                instructions.insert(fieldIns, il);
                this.captureId++;
            }
        }
    }
}

From source file:org.mutabilitydetector.checkers.settermethod.InitialValueFinder.java

License:Apache License

private AbstractInsnNode findValueSetUpInsnIn(final MethodNode constructor) {
    final List<ControlFlowBlock> blocks = enhancedClassNode.getControlFlowBlocksForMethod(constructor);
    final Finder<AssignmentInsn> f = EffectiveAssignmentInsnFinder.newInstance(variable, blocks);
    final AssignmentInsn effectiveAssignmentInsn = f.find();
    final int indexOfAssignmentInstruction = effectiveAssignmentInsn.getIndexWithinMethod();
    final InsnList instructions = constructor.instructions;
    final AbstractInsnNode result = instructions.get(indexOfAssignmentInstruction - 1);
    return result;
}

From source file:org.springsource.loaded.TypeDiffComputer.java

License:Apache License

/**
 * Determine if there any differences between the methods supplied. A MethodDelta object is built to record any differences and
 * stored against the type delta./*from  www  .  j a  va2s  . c o  m*/
 * 
 * @param oMethod 'old' method
 * @param nMethod 'new' method
 * @param td the type delta where changes are currently being accumulated
 */
private static void computeAnyMethodDifferences(MethodNode oMethod, MethodNode nMethod, TypeDelta td) {
    MethodDelta md = new MethodDelta(oMethod.name, oMethod.desc);
    if (oMethod.access != nMethod.access) {
        md.setAccessChanged(oMethod.access, nMethod.access);
    }
    // TODO annotations
    InsnList oInstructions = oMethod.instructions;
    InsnList nInstructions = nMethod.instructions;
    if (oInstructions.size() != nInstructions.size()) {
        md.setInstructionsChanged(oInstructions.toArray(), nInstructions.toArray());
    } else {
        // TODO Just interested in constructors right now - should add others
        if (oMethod.name.charAt(0) == '<') {
            String oInvokeSpecialDescriptor = null;
            String nInvokeSpecialDescriptor = null;
            int oUninitCount = 0;
            int nUninitCount = 0;
            boolean codeChange = false;
            for (int i = 0, max = oInstructions.size(); i < max; i++) {
                AbstractInsnNode oInstruction = oInstructions.get(i);
                AbstractInsnNode nInstruction = nInstructions.get(i);
                if (!codeChange) {
                    if (!sameInstruction(oInstruction, nInstruction)) {
                        codeChange = true;
                    }

                }
                if (oInstruction.getType() == AbstractInsnNode.TYPE_INSN) {
                    if (oInstruction.getOpcode() == Opcodes.NEW) {
                        oUninitCount++;
                    }
                }
                if (nInstruction.getType() == AbstractInsnNode.TYPE_INSN) {
                    if (nInstruction.getOpcode() == Opcodes.NEW) {
                        nUninitCount++;
                    }
                }
                if (oInstruction.getType() == AbstractInsnNode.METHOD_INSN) {
                    MethodInsnNode mi = (MethodInsnNode) oInstruction;
                    if (mi.getOpcode() == INVOKESPECIAL && mi.name.equals("<init>")) {
                        if (oUninitCount == 0) {
                            // this is the one!
                            oInvokeSpecialDescriptor = mi.desc;
                        } else {
                            oUninitCount--;
                        }
                    }
                }
                if (nInstruction.getType() == AbstractInsnNode.METHOD_INSN) {
                    MethodInsnNode mi = (MethodInsnNode) nInstruction;
                    if (mi.getOpcode() == INVOKESPECIAL && mi.name.equals("<init>")) {
                        if (nUninitCount == 0) {
                            // this is the one!
                            nInvokeSpecialDescriptor = mi.desc;
                        } else {
                            nUninitCount--;
                        }
                    }
                }
            }
            // Has the invokespecial changed?
            if (oInvokeSpecialDescriptor == null) {
                if (nInvokeSpecialDescriptor != null) {
                    md.setInvokespecialChanged(oInvokeSpecialDescriptor, nInvokeSpecialDescriptor);
                }
            } else {
                if (!oInvokeSpecialDescriptor.equals(nInvokeSpecialDescriptor)) {
                    md.setInvokespecialChanged(oInvokeSpecialDescriptor, nInvokeSpecialDescriptor);
                }
            }
            if (codeChange) {
                md.setCodeChanged(oInstructions.toArray(), nInstructions.toArray());
            }
        }
    }
    if (md.hasAnyChanges()) {
        // it needs recording
        td.addChangedMethod(md);
    }

}

From source file:org.teavm.parsing.ProgramParser.java

License:Apache License

private void prepare(MethodNode method) {
    InsnList instructions = method.instructions;
    minLocal = 0;//from  w w w .  j  a v a2 s .  c  o m
    if ((method.access & Opcodes.ACC_STATIC) != 0) {
        minLocal = 1;
    }
    labelIndexes = new HashMap<>();
    lineNumbers = new HashMap<>();
    for (int i = 0; i < instructions.size(); ++i) {
        AbstractInsnNode node = instructions.get(i);
        if (node instanceof LabelNode) {
            labelIndexes.put(((LabelNode) node).getLabel(), i);
        }
        if (node instanceof LineNumberNode) {
            LineNumberNode lineNumberNode = (LineNumberNode) node;
            lineNumbers.put(lineNumberNode.start.getLabel(), lineNumberNode.line);
        }
    }
    for (LocalVariableNode localVar : method.localVariables) {
        int location = labelIndexes.get(localVar.start.getLabel());
        List<LocalVariableNode> vars = localVariableMap.get(location);
        if (vars == null) {
            vars = new ArrayList<>();
            localVariableMap.put(location, vars);
        }
        vars.add(localVar);
    }
    targetInstructions = new ArrayList<>(instructions.size());
    targetInstructions.addAll(Collections.nCopies(instructions.size(), null));
    basicBlocks.addAll(Collections.nCopies(instructions.size(), null));
    stackBefore = new StackFrame[instructions.size()];
    stackAfter = new StackFrame[instructions.size()];
}

From source file:org.teavm.parsing.ProgramParser.java

License:Apache License

private void doAnalyze(MethodNode method) {
    InsnList instructions = method.instructions;
    Deque<Step> workStack = new ArrayDeque<>();
    for (Object obj : method.tryCatchBlocks) {
        TryCatchBlockNode tryCatchNode = (TryCatchBlockNode) obj;
        if (tryCatchNode.start == tryCatchNode.handler) {
            continue;
        }/*from  w ww. j a v  a2 s  .  c  o m*/
        workStack.push(new Step(-2, labelIndexes.get(tryCatchNode.handler.getLabel())));
    }
    workStack.push(new Step(-1, 0));
    while (!workStack.isEmpty()) {
        Step step = workStack.pop();
        index = step.target;
        if (stackBefore[index] != null) {
            continue;
        }
        switch (step.source) {
        case -1:
            stack = new StackFrame(minLocal + method.maxLocals - 1);
            break;
        case -2:
            stack = new StackFrame(minLocal + method.maxLocals - 1);
            pushSingle();
            break;
        default:
            stack = stackAfter[step.source];
            break;
        }
        stackBefore[index] = stack;
        nextIndexes = new int[] { index + 1 };
        instructions.get(index).accept(methodVisitor);
        stackAfter[index] = stack;
        flushInstructions();
        if (nextIndexes.length != 1) {
            emitNextBasicBlock();
        }
        for (int next : nextIndexes) {
            workStack.push(new Step(index, next));
        }
    }
    for (Object obj : method.tryCatchBlocks) {
        TryCatchBlockNode tryCatchNode = (TryCatchBlockNode) obj;
        if (tryCatchNode.start == tryCatchNode.handler) {
            continue;
        }
        int start = labelIndexes.get(tryCatchNode.start.getLabel());
        int end = labelIndexes.get(tryCatchNode.end.getLabel());
        getBasicBlock(start);
        getBasicBlock(end);
        for (int i = start; i < end; ++i) {
            BasicBlock block = basicBlocks.get(i);
            if (block != null) {
                TryCatchBlock tryCatch = new TryCatchBlock();
                if (tryCatchNode.type != null) {
                    tryCatch.setExceptionType(tryCatchNode.type.replace('/', '.'));
                }
                tryCatch.setHandler(getBasicBlock(labelIndexes.get(tryCatchNode.handler.getLabel())));
                tryCatch.setExceptionVariable(getVariable(minLocal + method.maxLocals));
                block.getTryCatchBlocks().add(tryCatch);
            }
        }
    }
}

From source file:pl.clareo.coroutines.core.MethodTransformer.java

License:Apache License

@SuppressWarnings("unchecked")
MethodNode transform(String coroutineName, boolean generateDebugCode) {
    MethodNode transformedMethod = new MethodNode();
    transformedMethod.access = ACC_PUBLIC | ACC_FINAL | (method.access & ACC_STATIC);
    transformedMethod.name = coroutineName;
    transformedMethod.desc = COROUTINE_METHOD_DESCRIPTOR;
    transformedMethod.exceptions = method.exceptions;
    final InsnList newCode = transformedMethod.instructions;
    Analyzer analyzer = new Analyzer(new BasicInterpreter() {

        @Override/*from   www  .j ava  2 s.  c  om*/
        public Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2)
                throws AnalyzerException {
            if (insn.getOpcode() == AALOAD) {
                return new BasicValue(((BasicValue) value1).getType().getElementType());
            }
            return super.binaryOperation(insn, value1, value2);
        };

        @Override
        public Value merge(Value v, Value w) {
            if (v == NULL_VALUE) {
                BasicValue w1 = (BasicValue) w;
                if (w1.isReference()) {
                    return w1;
                }
            }
            if (w == NULL_VALUE) {
                BasicValue v1 = (BasicValue) v;
                if (v1.isReference())
                    return v1;
            }
            if (!v.equals(w)) {
                BasicValue v1 = (BasicValue) v;
                BasicValue w1 = (BasicValue) w;
                if (v1.isReference() & w1.isReference()) {
                    Class<?> c1;
                    Class<?> c2;
                    try {
                        c1 = MethodTransformer.getClass(v1);
                        c2 = MethodTransformer.getClass(w1);
                    } catch (ClassNotFoundException e) {
                        throw new CoroutineGenerationException(
                                "It was needed to load a class during transformation process but loading unexpectedly failed",
                                e);
                    }
                    if (c1.isAssignableFrom(c2)) {
                        return v;
                    }
                    if (c2.isAssignableFrom(c1)) {
                        return w;
                    }
                }
            } else {
                return v;
            }
            return BasicValue.UNINITIALIZED_VALUE;
        }

        @Override
        public Value newValue(Type type) {
            if (type != null) {
                int typeSort = type.getSort();
                switch (typeSort) {
                case Type.VOID:
                    return NULL_VALUE;
                case Type.BOOLEAN:
                case Type.CHAR:
                case Type.BYTE:
                case Type.SHORT:
                case Type.INT:
                    return BasicValue.INT_VALUE;
                case Type.FLOAT:
                    return BasicValue.FLOAT_VALUE;
                case Type.LONG:
                    return BasicValue.LONG_VALUE;
                case Type.DOUBLE:
                    return BasicValue.DOUBLE_VALUE;
                case Type.ARRAY:
                case Type.OBJECT:
                    if (type.getInternalName().equals("null")) {
                        return NULL_VALUE;
                    }
                    return new BasicValue(type);
                default:
                    throw new Error("Internal error");
                }
            }
            return BasicValue.UNINITIALIZED_VALUE;
        }
    });
    Frame[] frames;
    try {
        frames = analyzer.analyze(methodOwner, method);
    } catch (AnalyzerException e) {
        throw new CoroutineGenerationException(e);
    }
    InsnList code = method.instructions;
    final List<Integer> yields = new ArrayList<Integer>(8);
    /*
     * Copy instructions patching variable indexes and frames, remember
     * yield indexes
     */
    int ic = 0;
    Iterator<AbstractInsnNode> i = code.iterator();
    while (i.hasNext()) {
        AbstractInsnNode insn = i.next();
        switch (insn.getType()) {
        case AbstractInsnNode.FRAME:
            FrameNode frame = (FrameNode) insn.clone(labelsMap);
            // update values
            if (frame.type == F_FULL) {
                if (isStatic) {
                    frame.local.addAll(0, argsStackMapList);
                } else {
                    frame.local.addAll(1, argsStackMapList);
                }
            }
            newCode.add(frame);
            break;
        case AbstractInsnNode.IINC_INSN:
            IincInsnNode iinc = (IincInsnNode) insn.clone(labelsMap);
            iinc.var += variableIndexOffset;
            newCode.add(iinc);
            break;
        case AbstractInsnNode.INSN:
            switch (insn.getOpcode()) {
            case DRETURN:
            case FRETURN:
            case IRETURN:
            case LRETURN:
            case ARETURN:
            case RETURN:
                newCode.add(new InsnNode(POP));
                newCode.add(throwex("java/util/NoSuchElementException"));
                break;
            default:
                newCode.add(insn.clone(labelsMap));
            }
            break;
        case AbstractInsnNode.JUMP_INSN:
            if (insn.getOpcode() == JSR) {
                throw new CoroutineGenerationException("<jsr> not allowed");
            }
            JumpInsnNode jump = (JumpInsnNode) insn;
            LabelNode target = jump.label;
            if (!labelsMap.containsKey(target)) {
                labelsMap.put(target, new LabelNode());
            }
            newCode.add(jump.clone(labelsMap));
            break;
        case AbstractInsnNode.LABEL:
            if (!labelsMap.containsKey(insn)) {
                labelsMap.put((LabelNode) insn, new LabelNode());
            }
            newCode.add(insn.clone(labelsMap));
            break;
        case AbstractInsnNode.METHOD_INSN:
            if (insn.getOpcode() == INVOKESTATIC) {
                MethodInsnNode method = (MethodInsnNode) insn;
                if (method.owner.equals(COROUTINES_NAME)) {
                    String methodName = method.name;
                    if (methodName.equals("_")) {
                        /*
                         * a call to artificial CoIterator, since it is
                         * not needed after instrumentation we replace
                         * it with null. This null will be popped by
                         * corresponding ARETURN. Stack is not changed
                         */
                        newCode.add(new InsnNode(ACONST_NULL));
                        break;
                    }
                    if (methodName.equals("yield")) {
                        /*
                         * a call to yield - core of coroutine
                         * processing
                         */
                        yields.add(ic);
                    }
                }
            }
            newCode.add(insn.clone(labelsMap));
            break;
        case AbstractInsnNode.VAR_INSN:
            if (insn.getOpcode() == RET) {
                throw new CoroutineGenerationException("<ret> not allowed");
            }
            VarInsnNode var = (VarInsnNode) insn.clone(labelsMap);
            if (var.var != 0 || isStatic) {
                var.var += variableIndexOffset;
            }
            newCode.add(var);
            break;
        default:
            newCode.add(insn.clone(labelsMap));
            break;
        }
        ic += 1;
    }
    /*
     * patch yields in transformed code
     */
    final List<LabelNode> gotos = new ArrayList<LabelNode>(9);
    final Set<TryCatchBlockNode> patchedTryCatchBlocks = new HashSet<TryCatchBlockNode>();
    int yieldIndex = 0;
    i = newCode.iterator();
    while (i.hasNext()) {
        AbstractInsnNode insn = i.next();
        /*
         * track locals
         */
        int insnType = insn.getType();
        if (insnType == AbstractInsnNode.VAR_INSN) {
            int opcode = insn.getOpcode();
            if (opcode == ASTORE || opcode == DSTORE || opcode == LSTORE || opcode == ISTORE
                    || opcode == FSTORE) {
                int varIndex = ((VarInsnNode) insn).var - variableIndexOffset;
                finals[varIndex] = false;
            }
            continue;
        }
        /*
         * track line numbers
         */
        if (insnType == AbstractInsnNode.LINE) {
            lineNumber = ((LineNumberNode) insn).line;
            continue;
        }
        if (insnType != AbstractInsnNode.METHOD_INSN) {
            continue;
        }
        MethodInsnNode method = (MethodInsnNode) insn;
        if (!method.owner.equals(COROUTINES_NAME) || !method.name.equals("yield")) {
            continue;
        }
        InsnList yieldCode = new InsnList();
        int index = yields.get(yieldIndex);
        Frame f = frames[index];
        /*
         * a) operand on the top of stack is passed to the caller, we will
         * save it in 'in' parameter OR there is nothing to be passed to the
         * caller in case of yield() overload
         */
        boolean yieldWithArgument = Type.getArgumentTypes(method.desc).length != 0;
        boolean nonemptyStack;
        Type[] stackContents = null;
        int stackTop = 0;
        if (yieldWithArgument) {
            yieldCode.add(input(getStackTop(f)));
            nonemptyStack = f.getStackSize() > 1;
            stackTop = 1;
        } else {
            nonemptyStack = f.getStackSize() > 0;
        }
        /*
         * b) save remaining stack
         */
        if (nonemptyStack) {
            stackContents = getStackContents(f);
            // sanitize stack
            for (Type t : stackContents) {
                if (t == null) {
                    throw new CoroutineGenerationException(
                            "It is not possible to yield with uninitialized memory on the stack. Probably you use construct such as: new A(..,yield,..). Please move this yield call out of constructor");
                }
            }
            yieldCode.add(savestack(frame, stackContents, stackTop));
        }
        /*
         * c) save locals and state
         */
        Type[] locals = getLocals(f);
        yieldCode.add(saveLocals(locals));
        yieldCode.add(new VarInsnNode(ALOAD, frame));
        yieldCode.add(makeInt(++yieldIndex));
        yieldCode.add(new MethodInsnNode(INVOKEVIRTUAL, FRAME_NAME, "setState", "(I)V"));
        /*
         * d) jump to exit - in debug mode save line number
         */
        if (generateDebugCode) {
            yieldCode.add(new VarInsnNode(ALOAD, frame));
            yieldCode.add(makeInt(lineNumber));
            yieldCode.add(new MethodInsnNode(INVOKEVIRTUAL, FRAME_NAME, "setLineOfCode", "(I)V"));
        }
        yieldCode.add(new JumpInsnNode(GOTO, yieldLabel));
        /*
         * e) fix jump from switch statement
         */
        LabelNode jump = new LabelNode();
        gotos.add(jump);
        yieldCode.add(jump);
        yieldCode.add(emitCleanFrame());
        /*
         * f) check if exit condition occurs, load locals, restore stack and
         * stack map
         */
        yieldCode.add(new VarInsnNode(ALOAD, frame));
        yieldCode.add(new MethodInsnNode(INVOKEVIRTUAL, FRAME_NAME, "isCoroutineClosed", "()Z"));
        LabelNode continueHere = new LabelNode();
        yieldCode.add(new JumpInsnNode(IFEQ, continueHere));
        yieldCode.add(throwex(COROUTINE_EXIT_EXCEPTION));
        yieldCode.add(continueHere);
        yieldCode.add(new FrameNode(F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK));
        /*
         * find previous frame node, load locals then emit new frame node
         * and load rest
         */
        FrameNode prevFrame = findPreviousFrame(code.get(index));
        Type[] prevLocals;
        if (prevFrame != null) {
            Frame oldFrame = frames[code.indexOf(prevFrame)];
            prevLocals = getLocals(oldFrame);
        } else {
            prevLocals = getLocals(frames[0]);
        }
        yieldCode.add(restoreLocals(prevLocals));
        FrameNode frameNode = mergeFrames(getFrameTypes(prevLocals), null);
        if (frameNode.type != F_SAME) {
            // bug fix - when no locals are restored and the stack is empty
            // two frames are collapsed
            yieldCode.add(frameNode);
        }
        if (nonemptyStack) {
            yieldCode.add(loadstack(frame, stackContents, stackTop));
        }
        // restore temp locals in scope
        yieldCode.add(restoreLocals(diff(locals, prevLocals)));
        /*
         * push "sent" value
         */
        yieldCode.add(new VarInsnNode(ALOAD, out));
        newCode.insertBefore(method, yieldCode);
        /*
         * patch try catch blocks
         */
        List<TryCatchBlockNode> tryCatchBlocks = analyzer.getHandlers(index);
        if (tryCatchBlocks != null) {
            for (TryCatchBlockNode tryCatchBlock : tryCatchBlocks) {
                if (!patchedTryCatchBlocks.contains(tryCatchBlock)) {
                    LabelNode handler = tryCatchBlock.handler;
                    InsnList handlerPatch = new InsnList();
                    String exceptionType = tryCatchBlock.type == null ? "java/lang/Throwable"
                            : tryCatchBlock.type;
                    FrameNode catchFrame = emitCatchFrame(exceptionType);
                    handlerPatch.add(catchFrame);
                    Type[] ls = getLocals(frames[code.indexOf(handler)]);
                    handlerPatch.add(restoreLocals(ls));
                    handlerPatch.add(
                            mergeFrames(getFrameTypes(ls), new Type[] { Type.getObjectType(exceptionType) }));
                    patchedTryCatchBlocks.add(tryCatchBlock);
                    AbstractInsnNode newHandler = labelsMap.get(handler);
                    // remove "real" frame since it is not needed now
                    newCode.remove(findNextFrame(newHandler));
                    newCode.insert(newHandler, handlerPatch);
                }
            }
        }
        newCode.remove(method);
    }
    /*
     * copy local variables (wath out for indices change) and try catch
     * blocks to new method (clone)
     */
    List<TryCatchBlockNode> tryCatchBlocks = method.tryCatchBlocks;
    if (!tryCatchBlocks.isEmpty()) {
        transformedMethod.tryCatchBlocks = new ArrayList<TryCatchBlockNode>(tryCatchBlocks.size());
        for (TryCatchBlockNode tryCatchBlock : tryCatchBlocks) {
            transformedMethod.tryCatchBlocks.add(
                    new TryCatchBlockNode(labelsMap.get(tryCatchBlock.start), labelsMap.get(tryCatchBlock.end),
                            labelsMap.get(tryCatchBlock.handler), tryCatchBlock.type));
        }
    }
    if (method.localVariables != null) {
        List<LocalVariableNode> localVariables = method.localVariables;
        List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>(localVariables.size());
        for (LocalVariableNode localVariable : localVariables) {
            int newIndex = localVariable.index;
            if (newIndex != 0 || isStatic) {
                newIndex += variableIndexOffset;
            }
            newLocalVariables
                    .add(new LocalVariableNode(localVariable.name, localVariable.desc, localVariable.signature,
                            labelsMap.get(localVariable.start), labelsMap.get(localVariable.end), newIndex));
        }
        transformedMethod.localVariables = newLocalVariables;
    }
    newCode.insert(codeBefore(gotos));
    newCode.add(codeAfter());
    return transformedMethod;
}

From source file:works.cirno.mocha.parameter.name.ASMParameterAnalyzer.java

License:Open Source License

@Override
@SuppressWarnings("unchecked")
public Parameter[] getParameters(InvokeTarget target, Parameter[] parameters) {
    if (!enabled) {
        return parameters;
    }/*from   w  w w . j ava 2 s.  com*/
    Class<?> controllerClass = target.getControllerClass();
    Method method = target.getMethod();
    String methodName = method.getName();

    Class<?>[] parameterTypes = method.getParameterTypes();
    int parameterCount = parameterTypes.length;

    // /////////Resolve parameter names by asm
    {
        if (log.isDebugEnabled()) {
            log.debug("Analyzing method {}.{}", controllerClass.getName(), method.getName());
        }
        ClassNode node = classNodeCache.get(controllerClass);
        if (node == null) {
            String name = controllerClass.getName();
            {
                int idx = name.lastIndexOf('.');
                if (idx > 0) {
                    name = name.substring(idx + 1);
                }
            }

            try (InputStream is = controllerClass.getResourceAsStream(name + ".class")) {
                if (is == null) {
                    throw new FileNotFoundException(name + ".class");
                }
                ClassReader cr = new ClassReader(is);
                node = new ClassNode();
                cr.accept(node, ClassReader.SKIP_FRAMES);
                classNodeCache.put(controllerClass, node);
            } catch (IOException e) {
                log.warn("Can't read bytecode of class " + name);
                return null;
            }
        }

        if (parameters == null) {
            parameters = new Parameter[parameterCount];
        } else if (parameters.length != parameterCount) {
            throw new IllegalArgumentException(
                    "Input parameters' length is different than parameters of target");
        }

        boolean methodNodeGot = false;
        for (MethodNode m : (List<MethodNode>) node.methods) {
            if (methodName.equals(m.name)) {
                String[] names = new String[parameterCount];
                // do it
                {
                    IdentityHashMap<LabelNode, Integer> labelPosMap = new IdentityHashMap<>();
                    int pos = 0;
                    InsnList il = m.instructions;
                    for (int i = 0, max = il.size(); i < max; i++) {
                        AbstractInsnNode ain = il.get(i);
                        if (ain.getType() == AbstractInsnNode.LABEL) {
                            LabelNode label = (LabelNode) ain;
                            labelPosMap.put(label, pos++);
                        }
                    }
                    int[] poses = new int[parameterCount];
                    for (int i = 0; i < parameterCount; i++) {
                        poses[i] = Integer.MAX_VALUE;
                    }

                    for (LocalVariableNode lvn : (List<LocalVariableNode>) m.localVariables) {
                        if (lvn.index > 0 && lvn.index <= parameterCount) {
                            int idx = lvn.index - 1;
                            int startPos = labelPosMap.get(lvn.start);
                            if (poses[idx] > startPos) {
                                poses[idx] = startPos;
                                names[idx] = lvn.name;
                            }
                        }
                    }
                }

                if (log.isDebugEnabled()) {
                    log.debug("Method {}.{} has parameter: {}", controllerClass.getName(), method.getName(),
                            Arrays.toString(names));
                }
                for (int i = 0; i < parameterCount; i++) {
                    if (parameters[i] == null || parameters[i].getName() == null) {
                        parameters[i] = new Parameter(names[i], parameterTypes[i]);
                    }
                }

                methodNodeGot = true;
                break;
            }
        }
        if (!methodNodeGot) {
            throw new IllegalStateException("Can't get method " + method.getName() + " from ASM");
        }
        return parameters;
    }
}