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

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

Introduction

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

Prototype

int LABEL

To view the source code for org.objectweb.asm.tree AbstractInsnNode LABEL.

Click Source Link

Document

The type of LabelNode "instructions".

Usage

From source file:org.jboss.byteman.agent.adapter.BMInsnList.java

License:Open Source License

public void accept(final MethodVisitor mv) {
    // this method visitor must implement LocalScopeMethodVisitor or else we woudl not be here

    LocalScopeMethodVisitor lsmv = (LocalScopeMethodVisitor) mv;

    // first index all local vars by start and end label
    HashMap<Label, LinkedList<LocalVariableNode>> localStarts = new HashMap<Label, LinkedList<LocalVariableNode>>();
    HashMap<Label, LinkedList<LocalVariableNode>> localEnds = new HashMap<Label, LinkedList<LocalVariableNode>>();

    Iterator iterator = localvariables.iterator();
    while (iterator.hasNext()) {
        LocalVariableNode local = (LocalVariableNode) iterator.next();
        Label label = local.start.getLabel();
        LinkedList<LocalVariableNode> locals = localStarts.get(label);
        if (locals == null) {
            locals = new LinkedList<LocalVariableNode>();
            localStarts.put(label, locals);
        }//from w  ww  .j a  v  a 2  s .  com
        locals.addLast(local);
        label = local.end.getLabel();
        locals = localEnds.get(label);
        if (locals == null) {
            locals = new LinkedList<LocalVariableNode>();
            localEnds.put(label, locals);
        }
        locals.addLast(local);
    }

    // now visit the instructions intercepting labels
    AbstractInsnNode insn = getFirst();
    while (insn != null) {
        insn.accept(mv);
        if (insn.getType() == AbstractInsnNode.LABEL) {
            LabelNode labelNode = (LabelNode) insn;
            Label label = labelNode.getLabel();
            List<LocalVariableNode> localStart = localStarts.get(label);
            List<LocalVariableNode> localEnd = localEnds.get(label);
            if (localStart != null) {
                for (LocalVariableNode local : localStart) {
                    lsmv.visitLocalScopeStart(local.name, local.desc, local.signature, local.index,
                            label.getOffset());
                }
            }
            if (localEnd != null) {
                for (LocalVariableNode local : localEnd) {
                    lsmv.visitLocalScopeEnd(local.name, local.desc, local.signature, local.index,
                            label.getOffset());
                }
            }
        }
        insn = insn.getNext();
    }
}

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

License:Apache License

public boolean isEmpty() {
    final boolean result;
    final List<AbstractInsnNode> blockInstructions = getBlockInstructions();
    if (blockInstructions.isEmpty()) {
        result = true;/*from  w ww  .  j a v  a2  s .c o m*/
    } else {
        if (1 == blockInstructions.size()) {
            final AbstractInsnNode soleBlockInstruction = blockInstructions.get(0);
            result = AbstractInsnNode.LABEL == soleBlockInstruction.getType();
        } else {
            result = false;
        }
    }
    return result;
}

From source file:org.parboiled.transform.process.UnusedLabelsRemover.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");
    AbstractInsnNode current = method.instructions.getFirst();

    AbstractInsnNode next;//from  www .j a v  a2  s.c o m
    boolean doRemove;
    while (current != null) {
        next = current.getNext();
        //noinspection SuspiciousMethodCalls
        doRemove = current.getType() == AbstractInsnNode.LABEL && !method.getUsedLabels().contains(current);
        if (doRemove)
            method.instructions.remove(current);
        current = next;
    }
}

From source file:org.spoofax.interpreter.adapter.asm.ASMFactory.java

License:LGPL

public static IStrategoTerm wrap(AbstractInsnNode node) {
    if (node == null)
        return None.INSTANCE;
    switch (node.getType()) {
    case AbstractInsnNode.FIELD_INSN:
        return wrap((FieldInsnNode) node);
    case AbstractInsnNode.FRAME:
        return wrap((FrameNode) node);
    case AbstractInsnNode.IINC_INSN:
        return wrap((IincInsnNode) node);
    case AbstractInsnNode.INSN:
        return wrap((InsnNode) node);
    case AbstractInsnNode.INT_INSN:
        return wrap((IntInsnNode) node);
    case AbstractInsnNode.INVOKE_DYNAMIC_INSN:
        throw new NotImplementedException();
    case AbstractInsnNode.JUMP_INSN:
        return wrap((JumpInsnNode) node);
    case AbstractInsnNode.LABEL:
        return wrap((LabelNode) node);
    case AbstractInsnNode.LDC_INSN:
        return wrap((LdcInsnNode) node);
    case AbstractInsnNode.LINE:
        return wrap((LineNumberNode) node);
    case AbstractInsnNode.LOOKUPSWITCH_INSN:
        return wrap((LookupSwitchInsnNode) node);
    case AbstractInsnNode.METHOD_INSN:
        return wrap((MethodInsnNode) node);
    case AbstractInsnNode.MULTIANEWARRAY_INSN:
        return wrap((MultiANewArrayInsnNode) node);
    case AbstractInsnNode.TABLESWITCH_INSN:
        return wrap((TableSwitchInsnNode) node);
    case AbstractInsnNode.TYPE_INSN:
        return wrap((TypeInsnNode) node);
    case AbstractInsnNode.VAR_INSN:
        return wrap((VarInsnNode) node);
    case -1:/*ww  w.  j  a  va  2s .  c  om*/
        System.err.println("Bogus " + node.getClass().getName());
        return None.INSTANCE;
    default:
        throw new IllegalArgumentException(
                "Unknown type " + node.getOpcode() + " for " + node.getClass().getName());
    }
}

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

License:Apache License

private static boolean sameInstruction(AbstractInsnNode o, AbstractInsnNode n) {
    if (o.getType() != o.getType() || o.getOpcode() != n.getOpcode()) {
        return false;
    }//from w ww.  j ava 2  s  .c o m
    switch (o.getType()) {
    case (AbstractInsnNode.INSN): // 0
        if (!sameInsnNode(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.INT_INSN): // 1
        if (!sameIntInsnNode(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.VAR_INSN): // 2
        if (!sameVarInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.TYPE_INSN):// 3
        if (!sameTypeInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.FIELD_INSN): // 4
        if (!sameFieldInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.METHOD_INSN): // 5
        if (!sameMethodInsnNode(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.JUMP_INSN): // 6
        if (!sameJumpInsnNode(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.LABEL): // 7
        if (!sameLabelNode(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.LDC_INSN): // 8
        if (!sameLdcInsnNode(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.IINC_INSN): // 9
        if (!sameIincInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.TABLESWITCH_INSN): // 10
        if (!sameTableSwitchInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.LOOKUPSWITCH_INSN): // 11
        if (!sameLookupSwitchInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.MULTIANEWARRAY_INSN): // 12
        if (!sameMultiANewArrayInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.FRAME): // 13
        if (!sameFrameInsn(o, n)) {
            return false;
        }
        break;
    case (AbstractInsnNode.LINE): // 14
        if (!sameLineNumberNode(o, n)) {
            return false;
        }
        break;
    default:
        throw new IllegalStateException("nyi " + o.getType());
    }
    return true;
}

From source file:pku.sei.checkedcoverage.tracer.instrumentation.TracingMethodInstrumenter.java

License:Creative Commons License

@SuppressWarnings("unchecked")
public void transform(final ListIterator<MethodNode> methodIt) {

    // do not modify abstract or native methods
    if ((this.methodNode.access & ACC_ABSTRACT) != 0 || (this.methodNode.access & ACC_NATIVE) != 0)
        return;// w  w w . j a va2  s.c  o  m

    // check out what labels are jump targets (only these have to be traced)
    analyze(this.methodNode);

    this.instructionIterator = new FixedInstructionIterator(this.methodNode.instructions);
    // in the old method, initialize the new local variable for the threadtracer
    this.instructionIterator.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class),
            "getInstance", "()L" + Type.getInternalName(Tracer.class) + ";"));
    this.instructionIterator.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class),
            "getThreadTracer", "()L" + Type.getInternalName(ThreadTracer.class) + ";"));
    this.instructionIterator.add(new InsnNode(DUP));
    this.instructionIterator.add(new VarInsnNode(ASTORE, this.tracerLocalVarIndex));

    this.instructionIterator.add(
            new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class), "isPaused", "()Z"));
    final LabelNode noTracingLabel = new LabelNode();
    this.instructionIterator.add(new JumpInsnNode(IFNE, noTracingLabel));
    // create a copy of the (uninstrumented) instructions (later, while iterating through the instructions)
    final InsnList oldInstructions = new InsnList();
    final Map<LabelNode, LabelNode> labelCopies = LazyMap.decorate(new HashMap<LabelNode, LabelNode>(),
            new Factory() {
                @Override
                public Object create() {
                    return new LabelNode();
                }
            });
    // copy the try-catch-blocks
    final Object[] oldTryCatchblockNodes = this.methodNode.tryCatchBlocks.toArray();
    for (final Object o : oldTryCatchblockNodes) {
        final TryCatchBlockNode tcb = (TryCatchBlockNode) o;
        final TryCatchBlockNode newTcb = new TryCatchBlockNode(labelCopies.get(tcb.start),
                labelCopies.get(tcb.end), labelCopies.get(tcb.handler), tcb.type);
        this.methodNode.tryCatchBlocks.add(newTcb);
    }

    // increment number of local variables by one (for the threadtracer)
    ++this.methodNode.maxLocals;

    // and increment all local variable indexes after the new one by one
    for (final Object o : this.methodNode.localVariables) {
        final LocalVariableNode localVar = (LocalVariableNode) o;
        if (localVar.index >= this.tracerLocalVarIndex)
            ++localVar.index;
    }

    // store information about local variables in the ReadMethod object
    List<LocalVariable> localVariables = new ArrayList<LocalVariable>();
    for (final Object o : this.methodNode.localVariables) {
        final LocalVariableNode localVar = (LocalVariableNode) o;
        while (localVariables.size() <= localVar.index)
            localVariables.add(null);
        localVariables.set(localVar.index, new LocalVariable(localVar.index, localVar.name, localVar.desc));
    }
    this.readMethod.setLocalVariables(localVariables.toArray(new LocalVariable[localVariables.size()]));
    localVariables = null;

    // each method must start with a (dedicated) label:
    assert this.readMethod.getInstructions().isEmpty();
    traceLabel(null, InstructionType.METHODENTRY);
    assert this.readMethod.getInstructions().size() == 1
            && this.readMethod.getInstructions().get(0) instanceof LabelMarker
            && ((LabelMarker) this.readMethod.getInstructions().get(0)).isAdditionalLabel();
    this.readMethod.setMethodEntryLabel((LabelMarker) this.readMethod.getInstructions().get(0));

    // needed later:
    final LabelNode l0 = new LabelNode();
    this.instructionIterator.add(l0);

    // then, visit the instructions that were in the method before
    while (this.instructionIterator.hasNext()) {
        final AbstractInsnNode insnNode = this.instructionIterator.next();
        switch (insnNode.getType()) {
        case AbstractInsnNode.INSN:
            transformInsn((InsnNode) insnNode);
            break;
        case AbstractInsnNode.INT_INSN:
            transformIntInsn((IntInsnNode) insnNode);
            break;
        case AbstractInsnNode.VAR_INSN:
            transformVarInsn((VarInsnNode) insnNode);
            break;
        case AbstractInsnNode.TYPE_INSN:
            transformTypeInsn((TypeInsnNode) insnNode);
            break;
        case AbstractInsnNode.FIELD_INSN:
            transformFieldInsn((FieldInsnNode) insnNode);
            break;
        case AbstractInsnNode.METHOD_INSN:
            transformMethodInsn((MethodInsnNode) insnNode);
            break;
        case AbstractInsnNode.JUMP_INSN:
            transformJumpInsn((JumpInsnNode) insnNode);
            break;
        case AbstractInsnNode.LABEL:
            transformLabel((LabelNode) insnNode);
            break;
        case AbstractInsnNode.LDC_INSN:
            transformLdcInsn((LdcInsnNode) insnNode);
            break;
        case AbstractInsnNode.IINC_INSN:
            transformIincInsn((IincInsnNode) insnNode);
            break;
        case AbstractInsnNode.TABLESWITCH_INSN:
            transformTableSwitchInsn((TableSwitchInsnNode) insnNode);
            break;
        case AbstractInsnNode.LOOKUPSWITCH_INSN:
            transformLookupSwitchInsn((LookupSwitchInsnNode) insnNode);
            break;
        case AbstractInsnNode.MULTIANEWARRAY_INSN:
            transformMultiANewArrayInsn((MultiANewArrayInsnNode) insnNode);
            break;
        case AbstractInsnNode.FRAME:
            // ignore
            break;
        case AbstractInsnNode.LINE:
            // ignore
            break;
        default:
            throw new RuntimeException("Unknown instruction type " + insnNode.getType() + " ("
                    + insnNode.getClass().getSimpleName() + ")");
        }
        oldInstructions.add(insnNode.clone(labelCopies));
    }

    assert this.outstandingInitializations == 0;

    // add the (old) try-catch blocks to the readMethods
    // (can only be done down here since we use the information in the
    // labels map)
    for (final Object o : oldTryCatchblockNodes) {
        final TryCatchBlockNode tcb = (TryCatchBlockNode) o;
        this.readMethod.addTryCatchBlock(new TryCatchBlock(this.labels.get(tcb.start), this.labels.get(tcb.end),
                this.labels.get(tcb.handler), tcb.type));
    }

    final LabelNode l1 = new LabelNode();
    this.instructionIterator.add(l1);
    final int newPos = this.readMethod.getInstructions().size();
    traceLabel(null, InstructionType.METHODEXIT);
    assert this.readMethod.getInstructions().size() == newPos + 1;
    final AbstractInstruction abnormalTerminationLabel = this.readMethod.getInstructions().get(newPos);
    assert abnormalTerminationLabel instanceof LabelMarker;
    this.readMethod.setAbnormalTerminationLabel((LabelMarker) abnormalTerminationLabel);
    this.methodNode.instructions.add(new InsnNode(ATHROW));

    // add a try catch block around the method so that we can trace when this method is left
    // a thrown exception
    this.methodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l1, null));

    // now add the code that is executed if no tracing should be performed
    this.methodNode.instructions.add(noTracingLabel);
    if (this.firstLine != -1)
        this.methodNode.instructions.add(new LineNumberNode(this.firstLine, noTracingLabel));
    this.methodNode.instructions.add(new InsnNode(ACONST_NULL));
    this.methodNode.instructions.add(new VarInsnNode(ASTORE, this.tracerLocalVarIndex));
    this.methodNode.instructions.add(oldInstructions);

    // finally: create a copy of the method that gets the ThreadTracer as argument
    // this is only necessary for private methods or "<init>"
    if (this.tracer.wasRedefined(this.readMethod.getReadClass().getName())
            && (this.methodNode.access & ACC_PRIVATE) != 0) {
        final Type[] oldMethodArguments = Type.getArgumentTypes(this.methodNode.desc);
        final Type[] newMethodArguments = Arrays.copyOf(oldMethodArguments, oldMethodArguments.length + 1);
        newMethodArguments[oldMethodArguments.length] = Type.getType(ThreadTracer.class);
        final String newMethodDesc = Type.getMethodDescriptor(Type.getReturnType(this.methodNode.desc),
                newMethodArguments);
        final MethodNode newMethod = new MethodNode(this.methodNode.access, this.methodNode.name, newMethodDesc,
                this.methodNode.signature,
                (String[]) this.methodNode.exceptions.toArray(new String[this.methodNode.exceptions.size()]));
        methodIt.add(newMethod);

        int threadTracerParamPos = ((this.readMethod.getAccess() & Opcodes.ACC_STATIC) == 0 ? 1 : 0);
        for (final Type t : oldMethodArguments)
            threadTracerParamPos += t.getSize();

        final Map<LabelNode, LabelNode> newMethodLabels = LazyMap.decorate(new HashMap<LabelNode, LabelNode>(),
                new Factory() {
                    @Override
                    public Object create() {
                        return new LabelNode();
                    }
                });

        // copy the local variables information to the new method
        for (final Object o : this.methodNode.localVariables) {
            final LocalVariableNode lv = (LocalVariableNode) o;
            newMethod.localVariables.add(new LocalVariableNode(lv.name, lv.desc, lv.signature,
                    newMethodLabels.get(lv.start), newMethodLabels.get(lv.end), lv.index));
        }

        newMethod.maxLocals = this.methodNode.maxLocals;
        newMethod.maxStack = this.methodNode.maxStack;

        // copy the try-catch-blocks
        for (final Object o : this.methodNode.tryCatchBlocks) {
            final TryCatchBlockNode tcb = (TryCatchBlockNode) o;
            newMethod.tryCatchBlocks.add(new TryCatchBlockNode(newMethodLabels.get(tcb.start),
                    newMethodLabels.get(tcb.end), newMethodLabels.get(tcb.handler), tcb.type));
        }

        // skip the first 6 instructions, replace them with these:
        newMethod.instructions.add(new VarInsnNode(ALOAD, threadTracerParamPos));
        newMethod.instructions.add(new InsnNode(DUP));
        newMethod.instructions.add(new VarInsnNode(ASTORE, this.tracerLocalVarIndex));
        newMethod.instructions.add(new JumpInsnNode(IFNULL, newMethodLabels.get(noTracingLabel)));
        final Iterator<AbstractInsnNode> oldInsnIt = this.methodNode.instructions.iterator(6);
        // and add all the other instructions
        while (oldInsnIt.hasNext()) {
            final AbstractInsnNode insn = oldInsnIt.next();
            newMethod.instructions.add(insn.clone(newMethodLabels));
        }
    }

    ready();
}

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.  j a v  a  2 s.c  o  m
        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.B.java

License:Apache License

private void cut() {
    // long timeStart = System.currentTimeMillis();

    // log.debug("enter {}", m);
    int blockIndex = 0;

    // dump();//from   w  w  w. j av  a 2  s. c o  m

    Map<Integer, AbstractInsnNode> in = new HashMap<Integer, AbstractInsnNode>();
    Map<Integer, AbstractInsnNode> out = new HashMap<Integer, AbstractInsnNode>();

    AbstractInsnNode p = method.instructions.getFirst();

    if (!(p instanceof LabelNode)) {
        insnList.insertBefore(p, new LabelNode());
    }

    AbstractInsnNode q = method.instructions.getLast();
    if (!(q instanceof LabelNode)) {
        insnList.insert(q, new LabelNode());
    }

    AbstractInsnNode first = method.instructions.getFirst();
    p = first.getNext();
    // Blocks
    while (p != null) {
        if (isRead(p)) {
            int r = var(p);
            if (in.get(r) == null) {
                if (out.get(r) == null) {
                    in.put(r, p);
                }
            }
        } else if (isWrite(p)) {
            int r = var(p);
            out.put(r, p);
        } else if (needBreak(p)) {
            if (p.getType() != AbstractInsnNode.LABEL) {
                q = p.getNext();
                if (q != null && q.getType() == AbstractInsnNode.LABEL) {
                    p = q;
                } else {
                    method.instructions.insert(p, new LabelNode());
                    p = p.getNext();
                }
            }
            Block block = new Block(blockIndex++);
            block.first = (LabelNode) first;
            block.last = (LabelNode) p;
            block.in = in;
            block.out = out;
            blocks.add(block);
            blockMaps.put(block.first.getLabel(), block);
            first = p;
            in = new HashMap<Integer, AbstractInsnNode>();
            out = new HashMap<Integer, AbstractInsnNode>();
        }
        p = p.getNext();
    }
}

From source file:pxb.android.dex2jar.optimize.D.java

License:Apache License

private static LabelNode getNextLabelNode(AbstractInsnNode p, InsnList insns) {
    AbstractInsnNode q = p.getNext();/*from   ww  w .ja  va  2  s .  c o  m*/
    if (q.getType() == AbstractInsnNode.LABEL) {
        return (LabelNode) q;
    } else {
        LabelNode r = new LabelNode();
        insns.insert(p, r);
        return r;
    }
}

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 ww .  j  ava2  s .co 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;
    }
}