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

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

Introduction

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

Prototype

public void insertBefore(final AbstractInsnNode nextInsn, final InsnList insnList) 

Source Link

Document

Inserts the given instructions before the specified instruction.

Usage

From source file:org.parboiled.transform.process.RuleMethodRewriter.java

License:Open Source License

private void createNewGroupClassInstance(final InstructionGroup group) {
    final String internalName = group.getGroupClassType().getInternalName();
    final InstructionGraphNode root = group.getRoot();
    final AbstractInsnNode rootInsn = root.getInstruction();
    final InsnList insnList = method.instructions;
    final String constant = method.name
            + (root.isActionRoot() ? "_Action" + ++actionNr : "_VarInit" + ++varInitNr);

    final CodeBlock block = CodeBlock.newCodeBlock();

    block.newobj(internalName).dup().ldc(constant).invokespecial(internalName, "<init>",
            CodegenUtils.sig(void.class, String.class));

    if (root.isActionRoot() && method.hasSkipActionsInPredicatesAnnotation())
        block.dup().invokevirtual(internalName, "setSkipInPredicates", CodegenUtils.sig(void.class));

    insnList.insertBefore(rootInsn, block.getInstructionList());
}

From source file:org.parboiled.transform.process.RuleMethodRewriter.java

License:Open Source License

private void initializeFields(final InstructionGroup group) {
    final String internalName = group.getGroupClassType().getInternalName();

    InsnList insnList;
    AbstractInsnNode rootInsn;/*  w  w  w.  jav  a 2s .  co m*/
    int opcode;
    VarInsnNode varNode;
    FieldInsnNode fieldNode;

    for (final FieldNode field : group.getFields()) {
        insnList = method.instructions;
        rootInsn = group.getRoot().getInstruction();
        // TODO: replace with method in CodeBlock?
        opcode = LoadingOpcode.forType((Type) field.value);
        varNode = new VarInsnNode(opcode, field.access);
        fieldNode = new FieldInsnNode(PUTFIELD, internalName, field.name, field.desc);

        insnList.insertBefore(rootInsn, new InsnNode(DUP));
        // the FieldNodes access and value members have been reused for the
        // var index / Type respectively!
        insnList.insertBefore(rootInsn, varNode);
        insnList.insertBefore(rootInsn, fieldNode);
    }
}

From source file:org.parboiled.transform.process.VarFramingGenerator.java

License:Apache License

@Override
public void process(@Nonnull final ParserClassNode classNode, @Nonnull final RuleMethod method)
        throws Exception {
    Objects.requireNonNull(classNode, "classNode");
    Objects.requireNonNull(method, "method");
    final InsnList instructions = method.instructions;

    AbstractInsnNode ret = instructions.getLast();
    while (ret.getOpcode() != ARETURN)
        ret = ret.getPrevious();// w ww. ja v a2s . c  o  m

    final CodeBlock block = CodeBlock.newCodeBlock();

    block.newobj(CodegenUtils.p(VarFramingMatcher.class)).dup_x1().swap();

    createVarFieldArray(block, method);

    block.invokespecial(CodegenUtils.p(VarFramingMatcher.class), "<init>",
            CodegenUtils.sig(void.class, Rule.class, Var[].class));

    instructions.insertBefore(ret, block.getInstructionList());

    method.setBodyRewritten();
}

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  w w w. ja va  2  s. com*/
        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:pxb.android.dex2jar.optimize.D.java

License:Apache License

private void cut(MethodNode method) {
    InsnList insns = method.instructions;
    method.instructions = null;/*from  w  w  w . j a v  a  2s  . c o m*/
    {
        AbstractInsnNode p = insns.getFirst();
        if (!(p instanceof LabelNode)) {
            insns.insertBefore(p, new LabelNode());
        }
        AbstractInsnNode q = insns.getLast();
        if (!(q instanceof LabelNode)) {
            insns.insert(q, new LabelNode());
        }
    }
    @SuppressWarnings("serial")
    Map<LabelNode, LabelNode> cloneMap = new HashMap<LabelNode, LabelNode>() {
        public LabelNode get(Object key) {

            LabelNode l = super.get(key);
            if (l == null) {
                l = new LabelNode();
                put((LabelNode) key, l);
            }
            return l;
        }
    };
    Map<LabelNode, Block> preBlockMap = new HashMap<LabelNode, Block>();
    int i = 0;
    LabelNode label = null;
    Block block = null;
    List<AbstractInsnNode> currentInsnList = null;
    for (AbstractInsnNode p = insns.getFirst(); p != null; p = p.getNext()) {
        final AbstractInsnNode cp = p.clone(cloneMap);
        switch (cp.getType()) {
        case AbstractInsnNode.LABEL: {
            if (label != null) {
                block = new Block(i++, label);
                block.insns = currentInsnList;
                block.next = (LabelNode) cp;
                addToMap(block);
            }
            currentInsnList = new ArrayList<AbstractInsnNode>();
            label = (LabelNode) cp;
            preBlockMap.put(label, block);
            break;
        }
        case AbstractInsnNode.JUMP_INSN:
        case AbstractInsnNode.LOOKUPSWITCH_INSN:
        case AbstractInsnNode.TABLESWITCH_INSN: {
            if (cp.getOpcode() == GOTO) {
                block = new Block(i++, label);
                block.next = (LabelNode) ((JumpInsnNode) cp).label;
            } else {//
                block = new BranchBlock(i++, label, cp);
                block.next = (LabelNode) getNextLabelNode(p, insns).clone(cloneMap);
            }
            block.insns = currentInsnList;
            addToMap(block);
            currentInsnList = null;
            label = null;
            break;
        }
        case AbstractInsnNode.FRAME:
        case AbstractInsnNode.LINE:
            // ignore
            break;
        default:
            switch (cp.getOpcode()) {
            case IRETURN:
            case LRETURN:
            case FRETURN:
            case DRETURN:
            case ARETURN:
            case RETURN:
            case ATHROW:
                block = new EndBlock(i++, label, cp);
                block.next = null;
                getNextLabelNode(p, insns);
                block.insns = currentInsnList;
                addToMap(block);
                currentInsnList = null;
                label = null;
                break;
            default:
                currentInsnList.add(cp);
            }

        }
    }

    for (Iterator<?> it = method.tryCatchBlocks.iterator(); it.hasNext();) {
        TryCatchBlockNode tcn = (TryCatchBlockNode) it.next();

        Block s = map.get((LabelNode) tcn.start.clone(cloneMap));
        Block e = map.get((LabelNode) tcn.end.clone(cloneMap));
        Block handler = map.get(tcn.handler.clone(cloneMap));
        TcbK key = new TcbK(s, e);

        Map<Block, String> handlers = tcbs.get(key);
        if (handlers == null) {
            handlers = new TreeMap<Block, String>(new Comparator<Block>() {
                @Override
                public int compare(Block o1, Block o2) {
                    return o1.id - o2.id;
                }
            });
            tcbs.put(key, handlers);
        }
        handlers.put(handler, tcn.type);
        tcn.start = s.label;
        tcn.end = e.label;
        tcn.handler = handler.label;
    }
}