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

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

Introduction

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

Prototype

public abstract AbstractInsnNode clone(Map<LabelNode, LabelNode> clonedLabels);

Source Link

Document

Returns a copy of this instruction.

Usage

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

License:Open Source License

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

    return theInsnListClone;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Clones an invokevirtual/invokespecial/invokeinterface/invokedynamic node and returns it as an instruction list.
 * @param insnNode instruction to clone/*from www  .j av  a 2 s.  c o  m*/
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if node isn't of invoke type
 * @return instruction list with cloned instruction
 */
public static InsnList cloneInvokeNode(AbstractInsnNode insnNode) {
    Validate.notNull(insnNode);
    Validate.isTrue(insnNode instanceof MethodInsnNode || insnNode instanceof InvokeDynamicInsnNode);

    InsnList ret = new InsnList();
    ret.add(insnNode.clone(new HashMap<>()));

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Clones a monitorenter/monitorexit node and returns it as an instruction list.
 * @param insnNode instruction to clone//from  w  w w .j a va 2s .  c om
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if node isn't of invoke type
 * @return instruction list with cloned instruction
 */
public static InsnList cloneMonitorNode(AbstractInsnNode insnNode) {
    Validate.notNull(insnNode);
    Validate.isTrue(insnNode instanceof InsnNode);
    Validate.isTrue(
            insnNode.getOpcode() == Opcodes.MONITORENTER || insnNode.getOpcode() == Opcodes.MONITOREXIT);

    InsnList ret = new InsnList();
    ret.add(insnNode.clone(new HashMap<>()));

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Clones an instruction list. All labels are remapped unless otherwise specified in {@code globalLabels}.
 * @param insnList instruction list to clone
 * @param globalLabels set of labels that should not be remapped
 * @throws NullPointerException if any argument is {@code null}
 * @return instruction list with cloned instructions
 *//*from   w ww .  j av a 2 s  .  c o  m*/
public static InsnList cloneInsnList(InsnList insnList, Set<LabelNode> globalLabels) {
    Validate.notNull(insnList);

    // remap all labelnodes
    Map<LabelNode, LabelNode> labelNodeMapping = new HashMap<>();
    ListIterator<AbstractInsnNode> it = insnList.iterator();
    while (it.hasNext()) {
        AbstractInsnNode abstractInsnNode = it.next();
        if (abstractInsnNode instanceof LabelNode) {
            LabelNode existingLabelNode = (LabelNode) abstractInsnNode;
            labelNodeMapping.put(existingLabelNode, new LabelNode());
        }
    }

    // override remapping such that global labels stay the same
    for (LabelNode globalLabel : globalLabels) {
        labelNodeMapping.put(globalLabel, globalLabel);
    }

    // clone
    InsnList ret = new InsnList();
    it = insnList.iterator();
    while (it.hasNext()) {
        AbstractInsnNode abstractInsnNode = it.next();
        ret.add(abstractInsnNode.clone(labelNodeMapping));
    }

    return ret;
}

From source file:de.tuberlin.uebb.jbop.optimizer.loop.ForLoopBody.java

License:Open Source License

/**
 * Gets the insn list./*  w  w  w .  ja va2s  . co  m*/
 * 
 * @param i
 *          the curretn counter
 * @param footer
 *          the footer
 * @param method
 *          the method
 * @return the insn list of the body in respect to the current counter (<code>i</code>).
 */
public InsnList getInsnList(final int i, final ForLoopFooter footer, final MethodNode method) {
    final InsnList list = new InsnList();
    if (body.isEmpty()) {
        return list;
    }
    final LabelMap labelMap = new LabelMap();
    final int newLocalVar = method.maxLocals + 1;
    final int oldLocalVar = footer.getVarIndex();
    list.add(NodeHelper.getInsnNodeFor(i));
    list.add(new VarInsnNode(Opcodes.ISTORE, newLocalVar));
    for (final AbstractInsnNode node : body) {
        final AbstractInsnNode copyNode = node.clone(labelMap);
        if (copyNode instanceof VarInsnNode) {
            if (((VarInsnNode) copyNode).var == oldLocalVar) {
                ((VarInsnNode) copyNode).var = newLocalVar;
            }
        }
        list.add(copyNode);
    }
    list.add(new SplitMarkNode());
    method.maxLocals++;
    return list;
}

From source file:de.unisb.cs.st.javaslicer.tracer.instrumentation.PauseTracingInstrumenter.java

License:Open Source License

@SuppressWarnings("unchecked")
public void transformMethod(final MethodNode method, final ListIterator<MethodNode> methodIt,
        final String className) {
    if ((method.access & ACC_ABSTRACT) != 0 || (method.access & ACC_NATIVE) != 0)
        return;/* w w  w  . j  av a  2s.  co m*/

    int tracerLocalVarIndex = (method.access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
    for (final Type t : Type.getArgumentTypes(method.desc))
        tracerLocalVarIndex += t.getSize();

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

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

    final ListIterator<AbstractInsnNode> insnIt = method.instructions.iterator();

    insnIt.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class), "getInstance",
            "()L" + Type.getInternalName(Tracer.class) + ";", false));
    insnIt.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class), "getThreadTracer",
            "()L" + Type.getInternalName(ThreadTracer.class) + ";", false));
    insnIt.add(new InsnNode(DUP));
    insnIt.add(new VarInsnNode(ASTORE, tracerLocalVarIndex));
    insnIt.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class), "pauseTracing",
            "()V", true));
    insnIt.add(l0);

    while (insnIt.hasNext()) {
        final AbstractInsnNode insn = insnIt.next();
        switch (insn.getType()) {
        case AbstractInsnNode.INSN:
            switch (insn.getOpcode()) {
            case IRETURN:
            case LRETURN:
            case FRETURN:
            case DRETURN:
            case ARETURN:
            case RETURN:
                insnIt.previous();
                insnIt.add(new VarInsnNode(ALOAD, tracerLocalVarIndex));
                insnIt.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
                        "resumeTracing", "()V", true));
                insnIt.next();
            }
            break;
        case AbstractInsnNode.IINC_INSN:
            if (((IincInsnNode) insn).var >= tracerLocalVarIndex)
                ++((IincInsnNode) insn).var;
            break;
        case AbstractInsnNode.VAR_INSN:
            if (((VarInsnNode) insn).var >= tracerLocalVarIndex)
                ++((VarInsnNode) insn).var;
            break;
        default:
            break;
        }
    }

    method.instructions.add(l1);

    method.instructions.add(new VarInsnNode(ALOAD, tracerLocalVarIndex));
    method.instructions.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
            "resumeTracing", "()V", true));
    method.instructions.add(new InsnNode(ATHROW));

    method.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l1, null));

    // finally: create a copy of the method that gets the ThreadTracer as argument
    if (!"<clinit>".equals(method.name) && this.tracer.wasRedefined(className)) {
        final Type[] oldMethodArguments = Type.getArgumentTypes(method.desc);
        final Type[] newMethodArguments = Arrays.copyOf(oldMethodArguments, oldMethodArguments.length + 1);
        newMethodArguments[oldMethodArguments.length] = Type.getType(ThreadTracer.class);
        final String newMethodDesc = Type.getMethodDescriptor(Type.getReturnType(method.desc),
                newMethodArguments);
        final MethodNode newMethod = new MethodNode(method.access, method.name, newMethodDesc, method.signature,
                (String[]) method.exceptions.toArray(new String[method.exceptions.size()]));
        methodIt.add(newMethod);

        final Map<LabelNode, LabelNode> newMethodLabels = new LazyLabelMap();

        // copy the local variables information to the new method
        for (final Object o : method.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 = method.maxLocals;
        newMethod.maxStack = method.maxStack;

        // copy the try-catch-blocks
        for (final Object o : method.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 4 instructions, replace them with this:
        newMethod.instructions.add(new VarInsnNode(ALOAD, tracerLocalVarIndex));
        final Iterator<AbstractInsnNode> oldInsnIt = method.instructions.iterator(4);
        // and add all the other instructions
        while (oldInsnIt.hasNext()) {
            final AbstractInsnNode insn = oldInsnIt.next();
            newMethod.instructions.add(insn.clone(newMethodLabels));
        }
    }
}

From source file:de.unisb.cs.st.javaslicer.tracer.instrumentation.TracingClassInstrumenter.java

License:Open Source License

@SuppressWarnings("unchecked")
private static void copyMethod(final MethodNode from, final MethodNode to) {
    to.access = from.access;/*w ww .  j av  a2  s  .  co  m*/
    to.annotationDefault = from.annotationDefault;
    to.attrs = from.attrs == null ? null : new ArrayList<Attribute>(from.attrs);
    to.desc = from.desc;
    to.exceptions = from.exceptions == null ? null : new ArrayList<String>(from.exceptions);
    to.instructions.clear();
    final Iterator<?> insnIt = from.instructions.iterator();
    final Map<LabelNode, LabelNode> labelsMap = new HashMap<LabelNode, LabelNode>() {
        private static final long serialVersionUID = 6883684625241587713L;

        @Override
        public LabelNode get(final Object key) {
            LabelNode label = super.get(key);
            if (label == null)
                put((LabelNode) key, label = new LabelNode());
            return label;
        }
    };
    while (insnIt.hasNext()) {
        final AbstractInsnNode insn = (AbstractInsnNode) insnIt.next();
        to.instructions.add(insn.clone(labelsMap));
    }
    to.invisibleAnnotations = from.invisibleAnnotations == null ? null
            : new ArrayList<AnnotationNode>(from.invisibleAnnotations);
    if (from.invisibleParameterAnnotations == null) {
        to.invisibleParameterAnnotations = null;
    } else {
        to.invisibleParameterAnnotations = new List[from.invisibleParameterAnnotations.length];
        for (int i = 0; i < from.invisibleParameterAnnotations.length; ++i) {
            to.invisibleParameterAnnotations[i] = from.invisibleParameterAnnotations[i] == null ? null
                    : new ArrayList<AnnotationNode>(from.invisibleParameterAnnotations[i]);
        }
    }
    if (from.localVariables == null) {
        to.localVariables = null;
    } else {
        to.localVariables = new ArrayList<LocalVariableNode>(from.localVariables.size());
        for (final Object lvObj : from.localVariables) {
            final LocalVariableNode lv = (LocalVariableNode) lvObj;
            to.localVariables.add(new LocalVariableNode(lv.name, lv.desc, lv.signature, labelsMap.get(lv.start),
                    labelsMap.get(lv.end), lv.index));
        }
    }
    to.maxLocals = from.maxLocals;
    to.maxStack = from.maxStack;
    to.name = from.name;
    to.signature = from.signature;
    if (from.tryCatchBlocks == null) {
        to.tryCatchBlocks = null;
    } else {
        to.tryCatchBlocks = new ArrayList<TryCatchBlockNode>(from.tryCatchBlocks.size());
        for (final Object tcbObj : from.tryCatchBlocks) {
            final TryCatchBlockNode tcb = (TryCatchBlockNode) tcbObj;
            to.tryCatchBlocks.add(new TryCatchBlockNode(labelsMap.get(tcb.start), labelsMap.get(tcb.end),
                    labelsMap.get(tcb.handler), tcb.type));
        }
    }
    to.visibleAnnotations = from.visibleAnnotations == null ? null
            : new ArrayList<AnnotationNode>(from.visibleAnnotations);
    if (from.visibleParameterAnnotations == null) {
        to.visibleParameterAnnotations = null;
    } else {
        to.visibleParameterAnnotations = new List[from.visibleParameterAnnotations.length];
        for (int i = 0; i < from.visibleParameterAnnotations.length; ++i) {
            to.visibleParameterAnnotations[i] = from.visibleParameterAnnotations[i] == null ? null
                    : new ArrayList<AnnotationNode>(from.visibleParameterAnnotations[i]);
        }
    }
}

From source file:de.unisb.cs.st.javaslicer.tracer.instrumentation.TracingMethodInstrumenter.java

License:Open Source 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;//from   w w w  . java2 s. com

    // 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) + ";", false));
    this.instructionIterator.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class),
            "getThreadTracer", "()L" + Type.getInternalName(ThreadTracer.class) + ";", false));
    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", true));
    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 = new LazyLabelMap();
    // 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
    // by 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 = new LazyLabelMap();

        // 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:jaspex.speculation.newspec.FlowFrame.java

License:Open Source License

/** Mtodo que implementa a deteco e correco do problema dos mltiplos fluxos de controlo.
  * Retorna true se alterou o mtodo, e false cc.
  **//*from w w  w  .ja v  a2s  . com*/
private static boolean computeControlFlowGraph(String owner, String superOwner, MethodNode mn,
        LabelMap labelMap, boolean ranBefore) {
    //Log.debug("Visiting: {}.{}", owner, mn.name);

    FlowAnalyzer analyzer = new FlowAnalyzer(new FutureVerifier(owner, superOwner));

    try {
        analyzer.analyze(owner, mn);
        //if (ranBefore) printCode(mn, Arrays.asList(analyzer.getFrames()), null, null);
        FrameInjector.injectFrames(mn, analyzer.getFrames());
        return false;
    } catch (AnalyzerException e) {
        /*e.printStackTrace();*/ }

    // Se chegmos aqui, o Analyzer detectou problemas, e vamos ter que fazer correces no mtodo

    // Detectar o primeiro LabelNode onde aparece um MergedUninitializedValue
    LabelNode problemLabelNode = null;
    FlowFrame problemFrame = null;
    int problemPosition = -1;
    boolean problemInStack = false;

    List<FlowFrame> frames = listGenericCast(Arrays.asList(analyzer.getFrames()));

    outer: for (int i = 0; i < frames.size(); i++) {
        FlowFrame f = frames.get(i);
        if (f == null)
            continue;

        int localsStartPos = 0;
        int stackStartPos = 0;
        // Identificar se alguma entrada nos locals/stack da frame deve ser escolhida como
        // problemtica
        // Isto  um loop porque algumas das entradas encontradas podem ser backwards edges,
        // e no estamos interessadas nessas
        while (true) {
            for (int j = localsStartPos; j < f.getLocals(); j++) {
                if (f.getLocal(j) instanceof MergedUninitializedValue) {
                    problemPosition = j;
                    problemInStack = false;
                    localsStartPos = j + 1;
                }
            }
            for (int j = stackStartPos; j < f.getStackSize() && (problemPosition < 0); j++) {
                if (f.getStack(j) instanceof MergedUninitializedValue) {
                    problemPosition = j;
                    problemInStack = true;
                    stackStartPos = j + 1;
                }
            }

            // J processamos completamente a frame e no encontramos nada, ou s
            // encontramos backwards edges, passar  prxima
            if (problemPosition < 0)
                continue outer;

            if ((f.predecessors().size() > 0)
                    && (getPredecessorWithFuture(f, problemInStack, problemPosition) == null)) {
                // Isto pode acontecer quando instruco que encontrmos  o target de
                // um "backwards edge". Nesse caso, no  esta a instruco que queremos
                // processar, mas queremos uma que tenha como predecessor um Future,
                // no um MergedUninitializedValue
                /*Log.debug("Found result of backwards edge at " +
                   (problemInStack ? "stack" : "locals") + " position " + i +
                   ", continuing");*/
                problemPosition = -1;
                continue;
            }

            if (problemInStack && !(mn.instructions.get(i) instanceof LabelNode)
                    && (mn.instructions.get(i - 1) instanceof VarInsnNode)) {
                // Caso especial: Uma instruco de load colocou um
                // MergedUninitializedValue na stack, e como no estava l na instruco
                // anterior o getPredecessorWithFuture no detecta este caso, mas no
                // estamos interessados nesta frame, estamos interessadas na que originou
                // o MUV que estava nos locals
                problemPosition = -1;
                continue;
            }

            // Frame e posio escolhidas so consideradas problemticas
            break;
        }

        AbstractInsnNode insn = mn.instructions.get(i);
        // First node with problematic frame should be a LabelNode
        if (!(insn instanceof LabelNode))
            throw new AssertionError();
        problemLabelNode = (LabelNode) insn;
        problemFrame = f;

        printCode(mn, frames, problemFrame.predecessors(), f);
        Log.trace("First problematic frame is " + f + "\n\t\tPredecessors: " + f.predecessors());
        break;
    }

    if (problemLabelNode == null) {
        Log.warn("Errors found during analysis, bytecode possibly invalid, bailing out");
        throw new AssertionError(); // Causar revert de todas as alteraes no mtodo
        //return false;
    }

    // Duplicar cdigo problemtico, para depois o alterar com o DelayGetFutureMethodVisitor
    InsnList il = new InsnList();

    // Label que marca o inicio do cdigo a copiar
    LabelNode copiedBlockStartLabel = new LabelNode();

    // Criar mapa para passar ao AbstractInsnNode (ver javadoc ASM)
    //LabelMap labelMap = new LabelMap();
    labelMap.put(problemLabelNode, copiedBlockStartLabel);

    // Adiciona copiedBlockStartLabel  nova il
    il.add(problemLabelNode.clone(labelMap));

    // Usado para manter a ltima (inclusiv) instruco do bloco copiado
    AbstractInsnNode lastInsn = null;

    // Simular execuo das frames durante a cpia
    // O objectivo disto  resolver problemas como o NewSpecExample17, onde cdigo copiado deve
    // fazer branch para:
    // -- Cdigo copiado numa iterao anterior ("cdigo novo") se a frame continuar a conter um
    //    futuro, porque o cdigo novo  o que  suposto lidar com a existncia do futuro
    // -- Cdigo existente do mtodo ("cdigo antigo") se a frame j no contm um futuro, o que
    //    significa que a concretizao se faz durante o bloco actual
    FlowFrame currentFrame = analyzer.newFrame(problemFrame);
    if (problemInStack) {
        currentFrame.setStack(problemPosition,
                ((MergedUninitializedValue) currentFrame.getStack(problemPosition)).getFuture());
    } else {
        currentFrame.setLocal(problemPosition,
                ((MergedUninitializedValue) currentFrame.getLocal(problemPosition)).getFuture());
    }

    for (AbstractInsnNode n = problemLabelNode.getNext(); n != null; n = n.getNext()) {
        if (n instanceof LabelNode) {
            LabelNode labelNode = (LabelNode) n;
            if (getNextIgnoreLabelLineNop(labelNode) instanceof FrameNode) {
                // Se label se refere a uma frame, o bloco terminou
                // FIXME: Tem que se saltar sempre para labels novas, se existirem?
                il.add(new JumpInsnNode(GOTO, labelMap.get(labelNode)));
                break;
            } else {
                // Caso contrrio, substituimos por uma nova label, para permitir
                // que os LineNumberNodes continuem a existir no novo cdigo.
                labelMap.put(labelNode, new LabelNode());
            }
        }

        // Detectar, no caso de um salto, qual a label que se deve utilizar (ver comentrios acima)
        // FIXME: Ser que no caso do switch/case algumas das labels tm que apontar para o cdigo
        //     novo, e outras para o antigo?
        if (n instanceof JumpInsnNode || n instanceof LookupSwitchInsnNode
                || n instanceof TableSwitchInsnNode) {
            // Se ProblemPosition ainda tem um Futuro, saltar para cdigo novo
            if ((problemInStack && isFuture(currentFrame.getStack(problemPosition)))
                    || (!problemInStack && isFuture(currentFrame.getLocal(problemPosition)))) {
                il.add(n.clone(labelMap));
            } else { // Deixou de ter um Futuro, saltar para cdigo antigo
                il.add(n.clone(new LabelMap()));
            }
        } else {
            il.add(n.clone(labelMap));
        }

        lastInsn = n;

        // Se chegamos ao fim do bloco (GOTO, ATHROW ou *RETURN) tambm paramos a cpia
        if (n.getOpcode() == GOTO || n.getOpcode() == ATHROW || returnOpcodes.contains(n.getOpcode()))
            break;

        // Actualizar currentFrame -- simular execuo da instruco actual
        try {
            currentFrame = analyzer.computeNextFrame(currentFrame, n);
        } catch (AnalyzerException e) {
            // Ocorreu um erro, continuamos com a ltima frame vlida
            //Log.debug("WARNING: AnalyzerException during computeNextFrame");
        }
        //Log.debug("CurrentFrame: " + currentFrame + " (isFuture? " +
        //   (isFuture(currentFrame.getLocal(problemPosition)) ? "yes" : "no") + ")");
    }

    LabelNode copiedBlockEndLabel = new LabelNode();
    il.add(copiedBlockEndLabel);

    mn.instructions.add(il);
    il = mn.instructions;

    // Detectar qual dos seus predecessores originou o Futuro que ficou no MergedUninitializedValue

    if (problemFrame.predecessors().isEmpty()) { // ProblemFrame  o inicio de um exception handler
        // Popular predecessors da problemFrame com control flows de exceptions
        analyzer.populateExceptionPredecessors(problemFrame);

        //printCode(mn, frames, problemFrame.predecessors());

        // Adicionar um novo tryCatchBlock com:
        // - Range [Primeira instruco com Future,
        //      ltima instruco que tem future *E* faz parte da lista de predecessors]
        //   Razo: Lista de predecessors --> handler ainda est activo
        //          Tem future --> future pode ser substituido mais tarde
        //             (por exemplo { i = doA(); j = doB(); i = 0 })
        // - Target: Novo bloco copiado -- copiedBlockStartLabel

        AbstractInsnNode startBlockInsn = null;
        AbstractInsnNode endBlockInsn = null;

        for (FlowFrame f : problemFrame.predecessors()) {
            BasicValue v = problemInStack ? f.getStack(problemPosition) : f.getLocal(problemPosition);
            if (isFuture(v)) {
                AbstractInsnNode insn = insnForFrame(il, frames, f);

                if (startBlockInsn == null) {
                    startBlockInsn = insn;
                }

                if (endBlockInsn != null) {
                    // Detectar se o bloco actual terminou
                    if (getTryCatchBlock(mn, startBlockInsn, insn) == null)
                        break;
                }

                endBlockInsn = insn;
            } else if (startBlockInsn != null) {
                break;
            }
        }

        // Provavelmente o problema do NewSpecExample20, ver comentrios no ficheiro
        if (startBlockInsn == null || endBlockInsn == null) {
            throw new AssertionError("KNOWN BUG: Probably picked the wrong code to copy");
        }

        //Log.debug("PredecessorInsn [Exception]: First " + startBlockInsn + " Last " + endBlockInsn);

        LabelNode startBlockLabel = labelBefore(il, startBlockInsn);
        LabelNode endBlockLabel = labelAfter(il, endBlockInsn);

        TryCatchBlockNode originalBlock = getTryCatchBlock(mn, startBlockInsn, endBlockInsn);
        assert (originalBlock != null);

        mn.tryCatchBlocks.add(0, new SafeTryCatchBlockNode(startBlockLabel, endBlockLabel,
                copiedBlockStartLabel, originalBlock.type));

        if (originalBlock.start.equals(startBlockLabel) && originalBlock.end.equals(endBlockLabel)) {
            // Novo bloco substitui completamente o antigo
            mn.tryCatchBlocks.remove(originalBlock);
        } else {
            // Como o novo try/catch substitui o antigo, para que o verificador da JVM e do ASM
            // lidem melhor com a coisa (embora segundo os specs no seria necessrio), vamos
            // alterar o inicio e/ou o fim do bloco original para deixar de conter as instruces
            // que esto cobertas pelo novo bloco
            if (originalBlock.start.equals(startBlockLabel)) {
                originalBlock.start = endBlockLabel;
            } else if (originalBlock.end.equals(endBlockLabel)) {
                originalBlock.end = startBlockLabel;
            } else {
                Log.debug("FIXME: Original (old) try catch block should be adjusted");
            }
        }
    } else { // Existem predecessores, problemFrame  um bloco de cdigo normal
        FlowFrame predecessorWithFuture = getPredecessorWithFuture(problemFrame, problemInStack,
                problemPosition);

        if (predecessorWithFuture == null)
            throw new AssertionError();

        AbstractInsnNode predecessorInsn = insnForFrame(il, frames, predecessorWithFuture);
        //Log.debug("PredecessorInsn: " + predecessorInsn);

        // Detectar como vai ser feito o salto para a nova seco do cdigo

        // Casos possveis:
        // - Predecessor  instruco imediatamente antes da labelnode (e no  um salto)
        //   -> No alteramos, adicionamos goto
        //   -> Se for um salto, podemos ou no ter que alterar, dependendo de ser ou no
        //      um salto para a labelNode que marca o incio da seco problemtica
        // - Predecessor  jump / table|lookup switch
        //   -> Temos que alterar
        // Fazendo clone com o labelmap obtemos um n que tem o salto para a nova label trocado
        // pelo salto para a antiga.
        if (directlyPrecedes(predecessorInsn, problemLabelNode)
                && !hasLabelAsTarget(predecessorInsn, problemLabelNode)) {
            // No temos que alterar n, saltamos directamente para novo bloco
            il.insert(predecessorInsn, new JumpInsnNode(GOTO, copiedBlockStartLabel));
        } else {
            if (!((predecessorInsn instanceof LookupSwitchInsnNode)
                    || (predecessorInsn instanceof TableSwitchInsnNode)
                    || (predecessorInsn instanceof JumpInsnNode))) {
                throw new AssertionError(); // Instruco tem que ser salto
            }
            // N tem que ser alterado
            AbstractInsnNode replacementNode = predecessorInsn.clone(labelMap);
            il.set(predecessorInsn, replacementNode);
            if (lastInsn == predecessorInsn)
                lastInsn = replacementNode;
        }
    }

    // Corrigir exception handlers do mtodo

    // Como blocos de cdigo so copiados, temos tambm que copiar os exception handlers,
    // para que os try/catch continuem a funcionar correctamente
    List<AbstractInsnNode> copiedCodeRange = getRange(problemLabelNode, lastInsn);
    List<SafeTryCatchBlockNode> newTryCatchBlocks = new ArrayList<SafeTryCatchBlockNode>();
    for (TryCatchBlockNode tryCatchBlock : mn.tryCatchBlocks) {
        List<AbstractInsnNode> blockRange = getRange(tryCatchBlock.start, tryCatchBlock.end);
        blockRange.retainAll(copiedCodeRange);
        if (blockRange.isEmpty())
            continue;
        // Corner case: Supostamente um try/catch block cobre [start, end[, enquanto
        // que o getRange devolve [start, end]
        if (blockRange.size() == 1 && problemLabelNode == tryCatchBlock.end)
            continue;

        //Log.debug("Exception handler table needs fixup");

        // Determinar a nova label de inicio
        LabelNode newStart;
        if (copiedCodeRange.contains(tryCatchBlock.start)) {
            // loco excepo comea j dentro do copiedCodeRange
            newStart = labelMap.getMapping(tryCatchBlock.start);
        } else {
            // Bloco excepo comea fora do copiedCodeRange
            newStart = copiedBlockStartLabel;
        }

        // Determinar a nova label de fim
        LabelNode newEnd;
        if (copiedCodeRange.contains(tryCatchBlock.end)) {
            // Bloco excepo comea dentro do copiedCodeRange
            newEnd = labelMap.getMapping(tryCatchBlock.end);
        } else {
            // Bloco excepo acaba fora do copiedCodeRange
            newEnd = copiedBlockEndLabel;
        }

        newTryCatchBlocks
                .add(new SafeTryCatchBlockNode(newStart, newEnd, tryCatchBlock.handler, tryCatchBlock.type));
    }
    mn.tryCatchBlocks.addAll(newTryCatchBlocks);

    return true;
}

From source file:org.coldswap.asm.field.PrivateStaticFieldReplacer.java

License:Open Source License

/**
 * Removes any initializing reference of the field.
 *
 * @param classNode containing the old class.
 * @param fieldNode containing the old field.
 * @return the initializing list of instructions.
 *//*from w  w  w  . ja v  a  2  s .  c  o  m*/
@SuppressWarnings("unchecked")
private InsnList cleanClInit(ClassNode classNode, FieldNode fieldNode) {
    List<MethodNode> methodNodes = classNode.methods;
    AbstractInsnNode firstInst = null;
    int counter = 0;
    for (MethodNode methodNode : methodNodes) {
        if (methodNode.name.equals("<clinit>")) {
            // search for PUTSTATIC
            InsnList insnList = methodNode.instructions;
            Iterator iterator1 = insnList.iterator();
            while (iterator1.hasNext()) {
                AbstractInsnNode ins2 = (AbstractInsnNode) iterator1.next();
                // if a initializing has been found, then copy everything from
                // the corresponding label to the PUTSTATIC
                if (ins2.getOpcode() == Opcodes.PUTSTATIC) {
                    final Boolean[] fieldFound = { false };
                    final FieldNode fNode = fieldNode;
                    ins2.accept(new MethodVisitor(Opcodes.ASM5) {
                        @Override
                        public void visitFieldInsn(int i, String s, String s2, String s3) {
                            if (s2.equals(fNode.name)) {
                                fieldFound[0] = true;
                            }
                            super.visitFieldInsn(i, s, s2, s3);
                        }
                    });
                    if (fieldFound[0]) {
                        // find the first PUTSTATIC before this one.
                        boolean staticFound = false;
                        while (!staticFound) {
                            AbstractInsnNode tmpInst = ins2.getPrevious();
                            if (tmpInst != null) {
                                if (tmpInst.getOpcode() != Opcodes.F_NEW) {
                                    if (tmpInst.getOpcode() == Opcodes.PUTSTATIC) {
                                        staticFound = true;
                                    } else {
                                        firstInst = tmpInst;
                                        counter++;
                                    }
                                }
                            } else {
                                staticFound = true;
                            }
                            ins2 = tmpInst;
                        }

                        break;
                    }
                }
            }

            if (firstInst != null) {
                InsnList iList = new InsnList();
                iList.add(firstInst.clone(null));
                counter--;
                while (counter > 0) {
                    AbstractInsnNode ain = firstInst.getNext();
                    iList.add(ain.clone(null));
                    counter--;
                    insnList.remove(firstInst);
                    firstInst = ain;
                }
                // remove last instruction and the putstatic instruction
                AbstractInsnNode putStatic = firstInst.getNext();
                insnList.remove(firstInst);
                insnList.remove(putStatic);
                return iList;
            }
        }
    }
    return null;
}