Example usage for org.objectweb.asm.tree MethodNode MethodNode

List of usage examples for org.objectweb.asm.tree MethodNode MethodNode

Introduction

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

Prototype

public MethodNode(final int access, final String name, final String descriptor, final String signature,
        final String[] exceptions) 

Source Link

Document

Constructs a new MethodNode .

Usage

From source file:de.tuberlin.uebb.jbop.optimizer.ClassNodeBuilder.java

License:Open Source License

/**
 * adds a new method (public accessor) with the given name and descriptor to the classNode.
 * /*from   w w  w  .  ja v a 2  s .  co  m*/
 * @param methodName
 *          the method name
 * @param descriptor
 *          the descriptor
 * @param modifiers
 *          the modifiers
 * @return the abstract optimizer test
 */
public ClassNodeBuilder addMethod(final String methodName, final String descriptor, final int... modifiers) {
    methodVarIndex = 1;
    final int modifier = getEffectiveModifier(modifiers);
    final MethodNode method = new MethodNode(modifier, methodName, descriptor, null, new String[] {});
    method.exceptions = new ArrayList<>();
    method.invisibleAnnotations = new ArrayList<>();
    method.visibleAnnotations = new ArrayList<>();
    classNode.methods.add(method);
    setLastMethod(method);
    if (isInterface) {
        method.access |= ACC_ABSTRACT;
    }
    return this;
}

From source file:de.unisb.cs.st.javalanche.mutation.bytecodeMutations.removeSystemExit.RemoveSystemExitMethodNode.java

License:Open Source License

public RemoveSystemExitMethodNode(int access, String name, String desc, String signature, String[] exceptions,
        MethodVisitor mv) {/*from www.j  a  v a  2s. c om*/
    super(new MethodNode(access, name, desc, signature, exceptions));
    next = mv;
}

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

License:Open Source License

@SuppressWarnings("unchecked")
public void transform(final ClassNode classNode) {
    if (!this.tracer.wasRedefined(this.readClass.getName()))
        return;//www . j a v  a  2 s  .  c  o m
    if ((classNode.access & ACC_INTERFACE) != 0)
        return;

    // do not modify if the parent class already implements Identifiable
    // (this is the case if the parent class was redefined)
    if (this.tracer.wasRedefined(Type.getObjectType(classNode.superName).getClassName()))
        return;

    classNode.fields
            .add(new FieldNode(ACC_PRIVATE | ACC_SYNTHETIC | ACC_TRANSIENT, ID_FIELD_NAME, "J", null, null));

    classNode.interfaces.add(Type.getInternalName(Identifiable.class));

    final MethodNode getIdMethod = new MethodNode(ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
            "__tracing_get_object_id", "()J", null, null);
    // first, check if the id field is already set:
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new InsnNode(LCONST_0));
    getIdMethod.instructions.add(new InsnNode(LCMP));
    final LabelNode l0 = new LabelNode();
    getIdMethod.instructions.add(new JumpInsnNode(IFNE, l0));

    // code to be executed if it is not set:
    // synchronized, so that the id is only set once
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new InsnNode(MONITORENTER));
    // label for the try-catch block around the synchronized block
    final LabelNode l1 = new LabelNode(), l2 = new LabelNode(), l3 = new LabelNode();
    getIdMethod.tryCatchBlocks.add(new TryCatchBlockNode(l1, l2, l3, null));
    getIdMethod.instructions.add(l1);
    // recheck if the id is set:
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new InsnNode(LCONST_0));
    getIdMethod.instructions.add(new InsnNode(LCMP));
    getIdMethod.instructions.add(new JumpInsnNode(IFNE, l2));

    // it is still unset:
    getIdMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class),
            "getInstance", "()L" + Type.getInternalName(Tracer.class) + ";"));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class),
            "getThreadTracer", "()L" + Type.getInternalName(ThreadTracer.class) + ";"));
    getIdMethod.instructions.add(new InsnNode(DUP));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
            "pauseTracing", "()V"));
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(ObjectIdentifier.class),
            "instance", "L" + Type.getInternalName(ObjectIdentifier.class) + ";"));
    getIdMethod.instructions.add(new InsnNode(ACONST_NULL));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(ObjectIdentifier.class),
            "getNewId", "(Ljava/lang/Object;)J"));
    getIdMethod.instructions.add(new FieldInsnNode(PUTFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
            "resumeTracing", "()V"));

    getIdMethod.instructions.add(l2);
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new InsnNode(MONITOREXIT));
    getIdMethod.instructions.add(new JumpInsnNode(GOTO, l0));
    getIdMethod.instructions.add(l3);
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new InsnNode(MONITOREXIT));
    getIdMethod.instructions.add(new InsnNode(ATHROW));

    getIdMethod.instructions.add(l0);
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new InsnNode(LRETURN));

    classNode.methods.add(getIdMethod);

    // now, instrument all constructors: initialize object id at the beginning of each constructor
    /*
    for (final Object methodObj: classNode.methods) {
    final MethodNode method = (MethodNode) methodObj;
    if (method.name.equals("<init>") && (method.access & ACC_ABSTRACT) == 0) {
        final InsnList newInsns = new InsnList();
        newInsns.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class),
                "getInstance", "()L"+Type.getInternalName(Tracer.class)+";"));
        newInsns.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class),
                "getThreadTracer", "()L"+Type.getInternalName(ThreadTracer.class)+";"));
        newInsns.add(new InsnNode(DUP));
        newInsns.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
                "pauseTracing", "()V"));
        newInsns.add(new VarInsnNode(ALOAD, 0));
        newInsns.add(new FieldInsnNode(GETSTATIC,
                Type.getInternalName(ObjectIdentifier.class), "instance",
                "L" + Type.getInternalName(ObjectIdentifier.class) + ";"));
        // TODO this may give different ids to the same object!!
        newInsns.add(new InsnNode(ACONST_NULL));
        newInsns.add(new MethodInsnNode(INVOKEVIRTUAL,
                Type.getInternalName(ObjectIdentifier.class), "getNewId",
                "(Ljava/lang/Object;)J"));
        newInsns.add(new FieldInsnNode(PUTFIELD, classNode.name, ID_FIELD_NAME, "J"));
        newInsns.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
                "resumeTracing", "()V"));
        method.instructions.insert(newInsns);
    }
    }
    */
}

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

    // 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:dodola.anole.lib.ConstructorDelegationDetector.java

License:Apache License

/**
 * Splits the constructor in two methods, the "set up" and the "body" parts (see above).
 *///  w ww . j  a v a2 s .co  m
private static Constructor split(String owner, MethodNode method, VarInsnNode loadThis,
        MethodInsnNode delegation, int loadThisLine) {
    String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]);
    String newDesc = method.desc.replaceAll("\\((.*)\\)V", "([Ljava/lang/Object;$1)Ljava/lang/Object;");

    MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null,
            exceptions);
    AbstractInsnNode insn = loadThis.getNext();
    while (insn != delegation) {
        insn.accept(initArgs);
        insn = insn.getNext();
    }
    LabelNode labelBefore = new LabelNode();
    labelBefore.accept(initArgs);

    GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc);
    // Copy the arguments back to the argument array
    // The init_args part cannot access the "this" object and can have side effects on the
    // local variables. Because of this we use the first argument (which we want to keep
    // so all the other arguments remain unchanged) as a reference to the array where to
    // return the values of the modified local variables.
    Type[] types = Type.getArgumentTypes(initArgs.desc);
    int stack = 1; // Skip the first one which is a reference to the local array.
    for (int i = 1; i < types.length; i++) {
        Type type = types[i];
        // This is not this, but the array of local arguments final values.
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.push(i);
        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), stack);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
        stack += type.getSize();
    }
    // Create the args array with the values to send to the delegated constructor
    Type[] returnTypes = Type.getArgumentTypes(delegation.desc);
    // The extra element for the qualified name of the constructor.
    mv.push(returnTypes.length + 1);
    mv.newArray(Type.getType(Object.class));
    int args = mv.newLocal(Type.getType("[Ljava/lang/Object;"));
    mv.storeLocal(args);
    for (int i = returnTypes.length - 1; i >= 0; i--) {
        Type type = returnTypes[i];
        mv.loadLocal(args);
        mv.swap(type, Type.getType(Object.class));
        mv.push(i + 1);
        mv.swap(type, Type.INT_TYPE);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
    }

    // Store the qualified name of the constructor in the first element of the array.
    mv.loadLocal(args);
    mv.push(0);
    mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called.
    mv.arrayStore(Type.getType(Object.class));

    mv.loadLocal(args);
    mv.returnValue();

    newDesc = method.desc.replace("(", "(L" + owner + ";");
    MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null,
            exceptions);
    LabelNode labelAfter = new LabelNode();
    labelAfter.accept(body);
    Set<LabelNode> bodyLabels = new HashSet<LabelNode>();

    insn = delegation.getNext();
    while (insn != null) {
        if (insn instanceof LabelNode) {
            bodyLabels.add((LabelNode) insn);
        }
        insn.accept(body);
        insn = insn.getNext();
    }

    // manually transfer the exception table from the existing constructor to the new
    // "init$body" method. The labels were transferred just above so we can reuse them.

    //noinspection unchecked
    for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) {
        tryCatch.accept(body);
    }

    //noinspection unchecked
    for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) {
        boolean startsInBody = bodyLabels.contains(variable.start);
        boolean endsInBody = bodyLabels.contains(variable.end);
        if (!startsInBody && !endsInBody) {
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                variable.accept(initArgs);
            }
        } else if (startsInBody && endsInBody) {
            variable.accept(body);
        } else if (!startsInBody && endsInBody) {
            // The variable spans from the args to the end of the method, create two:
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                        variable.start, labelBefore, variable.index);
                var0.accept(initArgs);
            }
            LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                    labelAfter, variable.end, variable.index);
            var1.accept(body);
        } else {
            throw new IllegalStateException("Local variable starts after it ends.");
        }
    }

    return new Constructor(loadThis, loadThisLine, initArgs, delegation, body);
}

From source file:edu.ubc.mirrors.holograms.FrameAnalyzerAdaptor.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    final MethodVisitor superVisitor = super.visitMethod(access, name, desc, signature, exceptions);
    final Map<Label, LabelNode> labelNodes = new HashMap<Label, LabelNode>();
    final FrameVerifier verifier = new FrameVerifier(vm, loader, holograms);

    MethodNode analyzer = new MethodNode(access, name, desc, null, null) {
        @Override/*w w w  . j  av  a  2  s  .c om*/
        public void visitEnd() {
            FrameAnalyzer a = new FrameAnalyzer(verifier);
            Frame<FrameValue>[] frames = null;
            try {
                frames = a.analyze(thisType.getInternalName(), this);
                if (superVisitor != null) {
                    if (insertFrames) {
                        frames = a.insertFrames();
                    }
                    accept(superVisitor);
                }
            } catch (Throwable e) {
                if (e instanceof IndexOutOfBoundsException && maxLocals == 0 && maxStack == 0) {
                    throw new RuntimeException(
                            "Data flow checking option requires valid, non zero maxLocals and maxStack values.");
                }
                if (frames == null) {
                    frames = a.getFrames();
                }
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw, true);
                printAnalyzerResult(this, frames, pw);
                pw.close();
                throw new RuntimeException(sw.toString(), e);
            }
        }

        @Override
        protected LabelNode getLabelNode(Label l) {
            LabelNode node = labelNodes.get(l);
            if (node == null) {
                node = new LabelNode(l);
                labelNodes.put(l, node);
            }
            return node;
        }
    };

    analyzer.instructions = new FrameInsnList();

    // Inline subroutines since other pieces of the pipeline can't handle them
    return new JSRInlinerAdapter(analyzer, access, name, desc, signature, exceptions);
}

From source file:edu.ubc.mirrors.test.NativeMethodCounter.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {

    if ((access & Opcodes.ACC_NATIVE) != 0) {
        nativeMethodCount++;/*from   w ww . j  av  a 2  s.co m*/
        Set<MethodNode> methods = classesWithNativeMethods.get(currentClass);
        if (methods == null) {
            methods = new HashSet<MethodNode>();
            classesWithNativeMethods.put(currentClass, methods);
        }
        methods.add(new MethodNode(access, name, desc, signature, exceptions));
    }

    return super.visitMethod(access, name, desc, signature, exceptions);
}

From source file:fr.insalyon.telecom.jooflux.InvokeMethodAdapter.java

License:Mozilla Public License

public InvokeMethodAdapter(int access, String name, String desc, String signature, String[] exceptions,
        MethodVisitor methodVisitor) {//  w w w  .jav a 2  s  .c  om
    super(access, new MethodNode(access, name, desc, signature, exceptions));
    this.methodVisitor = methodVisitor;
}

From source file:gemlite.core.internal.asm.serialize.DataSerializeHelper.java

License:Apache License

private void implementInterface(ClassNode cn) {
    MethodNode toMethod = new MethodNode(ACC_PUBLIC, "toData", "(Ljava/io/DataOutput;)V", null,
            new String[] { "java/io/IOException" });
    InsnList instToMethod = toMethod.instructions;

    MethodNode fromMethod = new MethodNode(ACC_PUBLIC, "fromData", "(Ljava/io/DataInput;)V", null,
            new String[] { "java/io/IOException", "java/lang/ClassNotFoundException" });
    InsnList instFromMethod = fromMethod.instructions;
    for (int i = 0; i < cn.fields.size(); i++) {
        FieldNode fn = (FieldNode) cn.fields.get(i);

        fp.toMethod(cn.name, fn, instToMethod);
        fp.fromMethod(cn.name, fn, instFromMethod);
    }//from w w w  . j a v  a  2s  .  c  o m
    instToMethod.add(new InsnNode(RETURN));
    cn.methods.add(toMethod);

    instFromMethod.add(new InsnNode(RETURN));
    cn.methods.add(fromMethod);

    //    if (DomainMojoHelper.log().isDebugEnabled())
    //      DomainMojoHelper.log().debug(cn.name + " add toData and fromData method.");
}