Example usage for org.objectweb.asm Opcodes INSTANCEOF

List of usage examples for org.objectweb.asm Opcodes INSTANCEOF

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes INSTANCEOF.

Prototype

int INSTANCEOF

To view the source code for org.objectweb.asm Opcodes INSTANCEOF.

Click Source Link

Usage

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.TypeInstruction.java

License:Open Source License

public TypeInstruction(final ReadMethod readMethod, final int opcode, final int lineNumber,
        final String className, int newObjIdSeqIndex) {
    super(readMethod, opcode, lineNumber);
    assert opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY || opcode == Opcodes.CHECKCAST
            || opcode == Opcodes.INSTANCEOF;
    assert ((opcode == Opcodes.CHECKCAST || opcode == Opcodes.INSTANCEOF) && newObjIdSeqIndex == -1)
            || ((opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY) && newObjIdSeqIndex != -1);
    this.className = className;
    this.newObjectIdentifierSeqIndex = newObjIdSeqIndex;
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.TypeInstruction.java

License:Open Source License

private TypeInstruction(final ReadMethod readMethod, final int lineNumber, final int opcode,
        final String typeDesc, final int index, int newObjIdSeqIndex) {
    super(readMethod, opcode, lineNumber, index);
    assert opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY || opcode == Opcodes.CHECKCAST
            || opcode == Opcodes.INSTANCEOF;
    assert ((opcode == Opcodes.CHECKCAST || opcode == Opcodes.INSTANCEOF) && newObjIdSeqIndex == -1)
            || ((opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY) && newObjIdSeqIndex != -1);
    this.className = typeDesc;
    this.newObjectIdentifierSeqIndex = newObjIdSeqIndex;
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.TypeInstruction.java

License:Open Source License

@Override
public String toString() {
    String instruction;//from  w w  w .ja  va 2  s.c  o m
    switch (getOpcode()) {
    case Opcodes.NEW:
        instruction = "NEW";
        break;
    case Opcodes.ANEWARRAY:
        instruction = "ANEWARRAY";
        break;
    case Opcodes.CHECKCAST:
        instruction = "CHECKCAST";
        break;
    case Opcodes.INSTANCEOF:
        instruction = "INSTANCEOF";
        break;
    default:
        instruction = "-ERROR-";
    }
    return new StringBuilder(instruction.length() + this.className.length() + 1).append(instruction).append(' ')
            .append(this.className).toString();
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.TypeInstruction2.java

License:Open Source License

public TypeInstruction2(final ReadMethod readMethod, final int opcode, final int lineNumber,
        final String className, long newObjIdSeqIndex) {
    super(readMethod, opcode, lineNumber);
    assert opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY || opcode == Opcodes.CHECKCAST
            || opcode == Opcodes.INSTANCEOF;
    assert ((opcode == Opcodes.CHECKCAST || opcode == Opcodes.INSTANCEOF) && newObjIdSeqIndex == -1)
            || ((opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY) && newObjIdSeqIndex != -1);
    this.className = className;
    this.newObjectIdentifier = newObjIdSeqIndex;
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.TypeInstruction2.java

License:Open Source License

public TypeInstruction2(final ReadMethod readMethod, final int lineNumber, final int opcode,
        final String typeDesc, final int index, long newObjIdSeqIndex) {
    super(readMethod, opcode, lineNumber, index);
    assert opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY || opcode == Opcodes.CHECKCAST
            || opcode == Opcodes.INSTANCEOF;
    assert ((opcode == Opcodes.CHECKCAST || opcode == Opcodes.INSTANCEOF) && newObjIdSeqIndex == -1)
            || ((opcode == Opcodes.NEW || opcode == Opcodes.ANEWARRAY) && newObjIdSeqIndex != -1);
    this.className = typeDesc;
    this.newObjectIdentifier = newObjIdSeqIndex;
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.TypeInstruction2.java

License:Open Source License

@Override
public <InstanceType> InstanceType getNextInstance(TraceIterator infoProv, int stackDepth, long instanceNr,
        InstructionInstanceFactory<InstanceType> instanceFactory) throws TracerException {
    long newobjIndentifier = this.newObjectIdentifier;
    TypeInstrInstanceInfo info;//  www  .  ja  va 2s .c  o  m
    if (this.getOpcode() == Opcodes.CHECKCAST || this.getOpcode() == Opcodes.INSTANCEOF)
        info = TypeInstrInstanceInfo.NO_INFO;
    else
        info = new TypeInstrInstanceInfo(newobjIndentifier);
    return instanceFactory.createInstructionInstance(this,
            infoProv.getNextInstructionOccurenceNumber(getIndex()), stackDepth, instanceNr, info);
}

From source file:de.unisb.cs.st.javaslicer.instructionSimulation.Simulator.java

License:Open Source License

private DynamicInformation simulateTypeInsn(InstructionInstance inst, SimulationEnvironment simEnv) {
    assert inst.getInstruction().getType() == InstructionType.TYPE;
    TypeInstrInstanceInfo info = (TypeInstrInstanceInfo) inst.getAdditionalInfo();
    int stackDepth = inst.getStackDepth();
    switch (inst.getInstruction().getOpcode()) {
    case Opcodes.NEW:
        return new SimpleVariableUsage(DynamicInformation.EMPTY_VARIABLE_SET,
                Collections.<Variable>singleton(
                        simEnv.getOpStackEntry(stackDepth, simEnv.decAndGetOpStack(stackDepth))),
                Collections.<Long, Collection<? extends Variable>>singletonMap(info.getNewObjectIdentifier(),
                        getAllFields(((TypeInstruction) inst.getInstruction()).getJavaClassName(),
                                info.getNewObjectIdentifier())));
    case Opcodes.ANEWARRAY:
        int stackSize = simEnv.getOpStack(stackDepth) - 1;
        IntHolder h = this.maxArrayElem.remove(info.getNewObjectIdentifier());
        Collection<Variable> stackEntryColl = Collections
                .<Variable>singleton(simEnv.getOpStackEntry(stackDepth, stackSize));
        return new SimpleVariableUsage(stackEntryColl, stackEntryColl,
                Collections.<Long, Collection<? extends Variable>>singletonMap(info.getNewObjectIdentifier(),
                        new ArrayElementsList(h == null ? 0 : (h.get() + 1), info.getNewObjectIdentifier())));
    case Opcodes.CHECKCAST:
        return new SimpleVariableUsage(simEnv.getOpStackEntry(stackDepth, simEnv.getOpStack(stackDepth) - 1),
                DynamicInformation.EMPTY_VARIABLE_SET);
    case Opcodes.INSTANCEOF:
        return stackManipulation(simEnv, stackDepth, 1, 1);
    default://  w ww  . j a v a  2  s.c om
        assert false;
        return null;
    }
}

From source file:de.zib.sfs.instrument.DirectByteBufferAdapter.java

License:BSD License

@Override
protected void initializeFields(MethodVisitor constructorMV, String constructorDesc) {
    if ("(Lsun/nio/ch/DirectBuffer;IIIII)V".equals(constructorDesc)) {
        // if we're constructed from another buffer, make sure we're from a
        // file too if the other buffer is too

        // if (db instanceof MappedByteBuffer) {
        constructorMV.visitVarInsn(Opcodes.ALOAD, 1);
        constructorMV.visitTypeInsn(Opcodes.INSTANCEOF, Type.getInternalName(MappedByteBuffer.class));
        Label memoryMappedBufferLabel = new Label();
        constructorMV.visitJumpInsn(Opcodes.IFEQ, memoryMappedBufferLabel);

        // setFromFileChannel(db.isFromFileChannel());
        constructorMV.visitVarInsn(Opcodes.ALOAD, 0);
        constructorMV.visitVarInsn(Opcodes.ALOAD, 1);
        constructorMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                "isFromFileChannel", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false);
        constructorMV.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instrumentedTypeInternalName,
                "setFromFileChannel", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false);

        // callback.openCallback(db.fileDescriptor);
        constructorMV.visitVarInsn(Opcodes.ALOAD, 0);
        constructorMV.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "callback",
                this.callbackTypeDescriptor);
        constructorMV.visitVarInsn(Opcodes.ALOAD, 1);
        constructorMV.visitFieldInsn(Opcodes.GETFIELD, Type.getInternalName(MappedByteBuffer.class),
                "fileDescriptor", Type.getDescriptor(FileDescriptor.class));
        constructorMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.callbackTypeInternalName, "openCallback",
                Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(FileDescriptor.class)), false);

        // }/*from  w  w w.  j  av  a2  s . co m*/
        constructorMV.visitLabel(memoryMappedBufferLabel);
    }
}

From source file:de.zib.sfs.instrument.DirectByteBufferAdapter.java

License:BSD License

@Override
protected void appendWrappedMethods(ClassVisitor visitor) {
    // override from MappedByteBuffer so we can re-init the callback
    // properly// w  ww  .j  a v a  2  s  . co m

    // public void setFileDescriptor(FileDescriptor fileDescriptor) {
    MethodVisitor settFileDescriptorMV = visitor.visitMethod(Opcodes.ACC_PUBLIC, "setFileDescriptor",
            Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(FileDescriptor.class)), null, null);
    settFileDescriptorMV.visitCode();

    // this.fileDescriptor = fileDescriptor;
    settFileDescriptorMV.visitVarInsn(Opcodes.ALOAD, 0);
    settFileDescriptorMV.visitVarInsn(Opcodes.ALOAD, 1);
    settFileDescriptorMV.visitFieldInsn(Opcodes.PUTFIELD, Type.getInternalName(MappedByteBuffer.class),
            "fileDescriptor", Type.getDescriptor(FileDescriptor.class));

    // callback.openCallback(this.fileDescriptor);
    settFileDescriptorMV.visitVarInsn(Opcodes.ALOAD, 0);
    settFileDescriptorMV.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "callback",
            this.callbackTypeDescriptor);
    settFileDescriptorMV.visitVarInsn(Opcodes.ALOAD, 0);
    settFileDescriptorMV.visitFieldInsn(Opcodes.GETFIELD, Type.getInternalName(MappedByteBuffer.class),
            "fileDescriptor", Type.getDescriptor(FileDescriptor.class));
    settFileDescriptorMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.callbackTypeInternalName, "openCallback",
            Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(FileDescriptor.class)), false);

    // }
    settFileDescriptorMV.visitInsn(Opcodes.RETURN);
    settFileDescriptorMV.visitMaxs(0, 0);
    settFileDescriptorMV.visitEnd();

    // also override from MappedByteBuffer

    // protected FileDescriptor getFileDescriptorImpl() {
    MethodVisitor getFileDescriptorImplMV = visitor.visitMethod(Opcodes.ACC_PROTECTED, "getFileDescriptorImpl",
            Type.getMethodDescriptor(Type.getType(FileDescriptor.class)), null, null);
    getFileDescriptorImplMV.visitCode();

    // return fileDescriptor;
    // }
    getFileDescriptorImplMV.visitVarInsn(Opcodes.ALOAD, 0);
    getFileDescriptorImplMV.visitFieldInsn(Opcodes.GETFIELD, Type.getInternalName(MappedByteBuffer.class),
            "fileDescriptor", Type.getDescriptor(FileDescriptor.class));
    getFileDescriptorImplMV.visitInsn(Opcodes.ARETURN);
    getFileDescriptorImplMV.visitMaxs(0, 0);
    getFileDescriptorImplMV.visitEnd();

    if (!skipReads()) {
        wrapMethod(Opcodes.ACC_PUBLIC, "get", Type.getType(ByteBuffer.class),
                new Type[] { Type.getType(byte[].class), Type.INT_TYPE, Type.INT_TYPE }, null, null,
                "getCallback", Type.INT_TYPE, new ParameterResultPasser(3));
    }

    if (!skipWrites()) {
        wrapMethod(Opcodes.ACC_PUBLIC, "put", Type.getType(ByteBuffer.class),
                new Type[] { Type.getType(byte[].class), Type.INT_TYPE, Type.INT_TYPE }, null, null,
                "putCallback", Type.INT_TYPE, new ParameterResultPasser(3));
    }

    if (!skipWrites()) {
        // public ByteBuffer put(ByteBuffer src) {
        MethodVisitor bulkPutMV = visitor.visitMethod(Opcodes.ACC_PUBLIC, "put",
                Type.getMethodDescriptor(Type.getType(ByteBuffer.class), Type.getType(ByteBuffer.class)), null,
                null);
        bulkPutMV.visitCode();

        // if (isInstrumentationActive()) {
        isInstrumentationActive(bulkPutMV);
        Label instrumentationActiveLabel = new Label();
        bulkPutMV.visitJumpInsn(Opcodes.IFEQ, instrumentationActiveLabel);

        // return nativeMethodPrefixput(src);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 0);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instrumentedTypeInternalName,
                this.methodPrefix + "put",
                Type.getMethodDescriptor(Type.getType(ByteBuffer.class), Type.getType(ByteBuffer.class)),
                false);
        bulkPutMV.visitInsn(Opcodes.ARETURN);

        // }
        bulkPutMV.visitLabel(instrumentationActiveLabel);

        // setInstrumentationActive(fromFileChannel);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 0);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 0);
        bulkPutMV.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "fromFileChannel",
                Type.getDescriptor(Boolean.TYPE));
        bulkPutMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.instrumentedTypeInternalName,
                "setInstrumentationActive", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false);

        // boolean srcInstrumentationActive = false;
        bulkPutMV.visitInsn(Opcodes.ICONST_0);
        bulkPutMV.visitVarInsn(Opcodes.ISTORE, 2);

        // if (src instanceof MappedByteBuffer) {
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitTypeInsn(Opcodes.INSTANCEOF, Type.getInternalName(MappedByteBuffer.class));
        Label srcInstanceofMappedByteBufferLabel = new Label();
        bulkPutMV.visitJumpInsn(Opcodes.IFEQ, srcInstanceofMappedByteBufferLabel);

        // srcInstrumentationActive = src.isFromFileChannel();
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                "isFromFileChannel", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false);
        bulkPutMV.visitVarInsn(Opcodes.ISTORE, 2);

        // src.setInstrumentationActive(true);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitInsn(Opcodes.ICONST_1);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                "setInstrumentationActive", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false);

        // }
        bulkPutMV.visitLabel(srcInstanceofMappedByteBufferLabel);

        // int length = src.remaining();
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Buffer.class), "remaining",
                Type.getMethodDescriptor(Type.INT_TYPE), false);
        bulkPutMV.visitVarInsn(Opcodes.ISTORE, 4);

        // long startTime = System.nanoTime();
        bulkPutMV.visitMethodInsn(Opcodes.INVOKESTATIC, this.systemInternalName, "nanoTime",
                this.nanoTimeDescriptor, false);
        bulkPutMV.visitVarInsn(Opcodes.LSTORE, 5);

        // ByteBuffer result = nativeMethodPrefixput(src);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 0);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instrumentedTypeInternalName,
                this.methodPrefix + "put",
                Type.getMethodDescriptor(Type.getType(ByteBuffer.class), Type.getType(ByteBuffer.class)),
                false);
        bulkPutMV.visitVarInsn(Opcodes.ASTORE, 7);

        // long endTime = System.nanoTime();
        bulkPutMV.visitMethodInsn(Opcodes.INVOKESTATIC, this.systemInternalName, "nanoTime",
                this.nanoTimeDescriptor, false);
        bulkPutMV.visitVarInsn(Opcodes.LSTORE, 8);

        // if (isInstrumentationActive()) {
        isInstrumentationActive(bulkPutMV);
        Label instrumentationStillActiveLabel = new Label();
        bulkPutMV.visitJumpInsn(Opcodes.IFEQ, instrumentationStillActiveLabel);

        // callback.putCallback(startTime, endTime, length);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 0);
        bulkPutMV.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "callback",
                this.callbackTypeDescriptor);
        bulkPutMV.visitVarInsn(Opcodes.LLOAD, 5);
        bulkPutMV.visitVarInsn(Opcodes.LLOAD, 8);
        bulkPutMV.visitVarInsn(Opcodes.ILOAD, 4);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.callbackTypeInternalName, "putCallback",
                Type.getMethodDescriptor(Type.VOID_TYPE, Type.LONG_TYPE, Type.LONG_TYPE, Type.INT_TYPE), false);

        // setInstrumentationActive(false);
        setInstrumentationActive(bulkPutMV, false);

        // }
        bulkPutMV.visitLabel(instrumentationStillActiveLabel);

        // if (srcInstrumentationActive) {
        bulkPutMV.visitVarInsn(Opcodes.ILOAD, 2);
        Label srcInstrumentationActiveLabel = new Label();
        bulkPutMV.visitJumpInsn(Opcodes.IFEQ, srcInstrumentationActiveLabel);

        // callback.onGetEnd(src.getFileDescriptor(), startTime, endTime,
        // length);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                "getFileDescriptor", Type.getMethodDescriptor(Type.getType(FileDescriptor.class)), false);
        bulkPutMV.visitVarInsn(Opcodes.LLOAD, 5);
        bulkPutMV.visitVarInsn(Opcodes.LLOAD, 8);
        bulkPutMV.visitVarInsn(Opcodes.ILOAD, 4);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKESTATIC, this.callbackTypeInternalName, "getCallback",
                Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(FileDescriptor.class), Type.LONG_TYPE,
                        Type.LONG_TYPE, Type.INT_TYPE),
                false);

        // src.setInstrumentationActive(false);
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 1);
        bulkPutMV.visitInsn(Opcodes.ICONST_0);
        bulkPutMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                "setInstrumentationActive", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false);

        // }
        bulkPutMV.visitLabel(srcInstrumentationActiveLabel);

        // return result;
        // }
        bulkPutMV.visitVarInsn(Opcodes.ALOAD, 7);
        bulkPutMV.visitInsn(Opcodes.ARETURN);
        bulkPutMV.visitMaxs(0, 0);
        bulkPutMV.visitEnd();
    }

    ResultPasser resultDiscarder = new DiscardResultPasser();

    // regular gets and puts
    for (Map.Entry<String, Type> type : TYPES.entrySet()) {
        if (!skipReads()) {
            // public TYPE getTYPE() { ... }
            wrapMethod(Opcodes.ACC_PUBLIC, "get" + type.getKey(), type.getValue(), null, null, null,
                    "get" + type.getKey() + "Callback", null, resultDiscarder);

            // public TYPE getTYPE(int index) { ... }
            wrapMethod(Opcodes.ACC_PUBLIC, "get" + type.getKey(), type.getValue(), new Type[] { Type.INT_TYPE },
                    null, null, "get" + type.getKey() + "Callback", null, resultDiscarder);
        }

        if (!skipWrites()) {
            // public ByteBuffer putTYPE(TYPE value) { ... }
            wrapMethod(Opcodes.ACC_PUBLIC, "put" + type.getKey(), Type.getType(ByteBuffer.class),
                    new Type[] { type.getValue() }, null, null, "put" + type.getKey() + "Callback", null,
                    resultDiscarder);

            // public ByteBuffer putTYPE(int index, TYPE value) { ... }
            wrapMethod(Opcodes.ACC_PUBLIC, "put" + type.getKey(), Type.getType(ByteBuffer.class),
                    new Type[] { Type.INT_TYPE, type.getValue() }, null, null,
                    "put" + type.getKey() + "Callback", null, resultDiscarder);
        }
    }

    visitor.visitEnd();
}

From source file:de.zib.sfs.instrument.FileChannelImplAdapter.java

License:BSD License

protected void wrapFileChannelImplMethod(int access, String name, Type returnType, Type[] argumentTypes,
        String signature, String[] exceptions, String callbackName, String oppositeCallbackName,
        Type additionalCallbackArgumentType, int bufferArgumentTypeIndex, boolean isTransferMethod) {
    String methodDescriptor = Type.getMethodDescriptor(returnType, argumentTypes);

    // <access> <returnType> <name>(<argumentTypes> arguments) throws
    // <exceptions> {
    MethodVisitor mv = this.cv.visitMethod(access, name, methodDescriptor, signature, exceptions);
    mv.visitCode();//from   w w  w  .  j  ava  2s  .  co  m

    // if (isInstrumentationActive()) {
    isInstrumentationActive(mv);
    Label instrumentationActiveLabel = new Label();
    mv.visitJumpInsn(Opcodes.IFEQ, instrumentationActiveLabel);

    // return methodPrefix<name>(arguments);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    int argumentIndex = 1;
    for (Type argument : argumentTypes) {
        mv.visitVarInsn(argument.getOpcode(Opcodes.ILOAD), argumentIndex);
        argumentIndex += argument.getSize();
    }
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instrumentedTypeInternalName, this.methodPrefix + name,
            methodDescriptor, false);
    mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));

    // }
    mv.visitLabel(instrumentationActiveLabel);

    // setInstrumentationActive(true);
    setInstrumentationActive(mv, true);

    // we need to set the instrumentation flag for the source/destination
    // buffer(s) as well

    // boolean bufferInstrumentationActive = false;
    int bufferInstrumentationActiveIndex = 1;
    for (Type argument : argumentTypes) {
        bufferInstrumentationActiveIndex += argument.getSize();
    }
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitVarInsn(Opcodes.ISTORE, bufferInstrumentationActiveIndex);

    // obtain actual index of the buffer(s) in the argument list
    int bufferArgumentIndex = 1;
    for (int i = 0; i < bufferArgumentTypeIndex; ++i) {
        bufferArgumentIndex += argumentTypes[i].getSize();
    }

    if (argumentTypes[bufferArgumentTypeIndex].getSort() == Type.ARRAY) {
        // If the first buffer in the array is a MappedByteBuffer, assume
        // they all are. If not, this will crash the users' program.

        // if (<buffers>[0] instanceof MappedByteBuffer) {
        mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        mv.visitInsn(Opcodes.ICONST_0);
        mv.visitInsn(Opcodes.AALOAD);
        mv.visitTypeInsn(Opcodes.INSTANCEOF, Type.getInternalName(MappedByteBuffer.class));
        Label bufferInstanceofMappedByteBufferLabel = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, bufferInstanceofMappedByteBufferLabel);

        // only trace mmapped file channels if desired
        if (this.traceMmap) {
            // if (<buffers>[0].isFromFileChannel()) {
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitInsn(Opcodes.ICONST_0);
            mv.visitInsn(Opcodes.AALOAD);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                    "isFromFileChannel", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false);
            Label fromFileChannelLabel = new Label();
            mv.visitJumpInsn(Opcodes.IFEQ, fromFileChannelLabel);

            int iIndex = bufferInstrumentationActiveIndex + 1;

            // for (int i = 0; i < <buffers>.length; ++i) {
            // <buffers>[i].setInstrumentationActive(true);
            // }
            mv.visitInsn(Opcodes.ICONST_0);
            mv.visitVarInsn(Opcodes.ISTORE, iIndex);
            Label loopConditionLabel = new Label();
            mv.visitJumpInsn(Opcodes.GOTO, loopConditionLabel);
            Label loopStartLabel = new Label();
            mv.visitLabel(loopStartLabel);
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitVarInsn(Opcodes.ILOAD, iIndex);
            mv.visitInsn(Opcodes.AALOAD);
            mv.visitInsn(Opcodes.ICONST_1);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                    "setInstrumentationActive", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE),
                    false);
            mv.visitIincInsn(iIndex, 1);
            mv.visitLabel(loopConditionLabel);
            mv.visitVarInsn(Opcodes.ILOAD, iIndex);
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitInsn(Opcodes.ARRAYLENGTH);
            mv.visitJumpInsn(Opcodes.IF_ICMPLT, loopStartLabel);

            // bufferInstrumentationActive = true;
            mv.visitInsn(Opcodes.ICONST_1);
            mv.visitVarInsn(Opcodes.ISTORE, bufferInstrumentationActiveIndex);

            // }
            mv.visitLabel(fromFileChannelLabel);
        }

        // }
        mv.visitLabel(bufferInstanceofMappedByteBufferLabel);
    } else {
        // We need to handle the transferFrom/transferTo methods a little
        // differently. Their "buffers" only need to be FileChannelImpls,
        // the rest remains the same.

        // if (buffer instanceof MappedByteBuffer) {
        // if (buffer instanceof FileChannelImpl) {
        mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        if (!isTransferMethod) {
            mv.visitTypeInsn(Opcodes.INSTANCEOF, Type.getInternalName(MappedByteBuffer.class));
        } else {
            mv.visitTypeInsn(Opcodes.INSTANCEOF, Type.getInternalName(FileChannelImpl.class));
        }
        Label bufferInstanceofMappedByteBufferLabel = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, bufferInstanceofMappedByteBufferLabel);

        // additional check required if the buffer is a MappedByteBuffer,
        // and we want to trace those
        Label fromFileChannelLabel = new Label();
        if (!isTransferMethod && this.traceMmap) {
            // if (buffer.isFromFileChannel()) {
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                    "isFromFileChannel", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false);
            mv.visitJumpInsn(Opcodes.IFEQ, fromFileChannelLabel);
        }

        // either we're dealing with a FileChannelImpl (in a
        // transferTo/transferFrom method), or this is a regular read or
        // write and we want to count in mmapped buffers
        if (isTransferMethod || this.traceMmap) {
            // buffer.setInstrumentationActive(true);
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitInsn(Opcodes.ICONST_1);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
                    !isTransferMethod ? Type.getInternalName(MappedByteBuffer.class)
                            : Type.getInternalName(FileChannelImpl.class),
                    "setInstrumentationActive", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE),
                    false);

            // bufferInstrumentationActive = true;
            mv.visitInsn(Opcodes.ICONST_1);
            mv.visitVarInsn(Opcodes.ISTORE, bufferInstrumentationActiveIndex);
        }

        if (!isTransferMethod && this.traceMmap) {
            // }
            mv.visitLabel(fromFileChannelLabel);
        }

        // }
        mv.visitLabel(bufferInstanceofMappedByteBufferLabel);
    }

    // long startTime = System.nanoTime();
    int startTimeIndex = bufferInstrumentationActiveIndex + 1;
    storeTime(mv, startTimeIndex);

    // <returnType> result = methodPrefix<name>(arguments);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    argumentIndex = 1;
    for (Type argument : argumentTypes) {
        mv.visitVarInsn(argument.getOpcode(Opcodes.ILOAD), argumentIndex);
        argumentIndex += argument.getSize();
    }
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instrumentedTypeInternalName, this.methodPrefix + name,
            methodDescriptor, false);
    int resultIndex = startTimeIndex + 2;
    mv.visitVarInsn(returnType.getOpcode(Opcodes.ISTORE), resultIndex);
    int endTimeIndex = resultIndex + returnType.getSize();

    // long endTime = System.nanoTime();
    storeTime(mv, endTimeIndex);

    // if map(...) was involved in this, then it may have reset the
    // instrumentationActive flag if we don't trace mmap calls, so we need
    // to check again whether instrumentation is still active, and only
    // report the data then

    // if (isInstrumentationActive()) {
    isInstrumentationActive(mv);
    Label instrumentationStillActiveLabel = new Label();
    mv.visitJumpInsn(Opcodes.IFEQ, instrumentationStillActiveLabel);

    // callback.<callbackName>(startTime, endTime, result);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "callback",
            this.callbackTypeDescriptor);
    mv.visitVarInsn(Opcodes.LLOAD, startTimeIndex);
    mv.visitVarInsn(Opcodes.LLOAD, endTimeIndex);
    mv.visitVarInsn(returnType.getOpcode(Opcodes.ILOAD), resultIndex);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.callbackTypeInternalName, callbackName,
            Type.getMethodDescriptor(Type.VOID_TYPE, Type.LONG_TYPE, Type.LONG_TYPE,
                    additionalCallbackArgumentType),
            false);

    // }
    mv.visitLabel(instrumentationStillActiveLabel);

    // same for the buffer

    if (argumentTypes[bufferArgumentTypeIndex].getSort() != Type.ARRAY) {
        // if (buffer instanceof MappedByteBuffer) {
        // if (buffer instanceof FileChannelImpl) {
        mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        if (!isTransferMethod) {
            mv.visitTypeInsn(Opcodes.INSTANCEOF, Type.getInternalName(MappedByteBuffer.class));
        } else {
            mv.visitTypeInsn(Opcodes.INSTANCEOF, Type.getInternalName(FileChannelImpl.class));
        }
        Label bufferInstanceofMappedByteBufferLabel = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, bufferInstanceofMappedByteBufferLabel);

        // additional check required if the buffer is a MappedByteBuffer,
        // and we want to trace those
        Label fromFileChannelLabel = new Label();
        if (!isTransferMethod && this.traceMmap) {
            // if (buffer.isFromFileChannel()) {
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                    "isFromFileChannel", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false);
            mv.visitJumpInsn(Opcodes.IFEQ, fromFileChannelLabel);
        }

        // either we're dealing with a FileChannelImpl (in a
        // transferTo/transferFrom method), which might have flipped its
        // instrumentationActive flag because mmap was used, or this is a
        // regular read or write and we want to count in mmapped buffers
        if (isTransferMethod || this.traceMmap) {
            // if traceMmap is true, then we could actually just set
            // bufferInstrumentationActive to true

            // bufferInstrumentationActive =
            // buffer.isInstrumentationActive();
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
                    !isTransferMethod ? Type.getInternalName(MappedByteBuffer.class)
                            : Type.getInternalName(FileChannelImpl.class),
                    "isInstrumentationActive", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false);
            mv.visitVarInsn(Opcodes.ISTORE, bufferInstrumentationActiveIndex);
        }

        if (!isTransferMethod && this.traceMmap) {
            // }
            mv.visitLabel(fromFileChannelLabel);
        }

        // }
        mv.visitLabel(bufferInstanceofMappedByteBufferLabel);
    }

    // if (bufferInstrumentationActive) {
    mv.visitVarInsn(Opcodes.ILOAD, bufferInstrumentationActiveIndex);
    Label bufferInstrumentationActiveLabel = new Label();
    mv.visitJumpInsn(Opcodes.IFEQ, bufferInstrumentationActiveLabel);

    // callback.<oppositeCallbackName>(buffer.getFileDescriptor(),
    // startTime, endTime, result);
    if (!isTransferMethod) {
        if (argumentTypes[bufferArgumentTypeIndex].getSort() == Type.ARRAY) {
            // TODO this calls the opposite callback only on the first
            // element in the buffer array, but there is not really a way to
            // tell which buffer has received how many bytes, and thus which
            // file
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
            mv.visitInsn(Opcodes.ICONST_0);
            mv.visitInsn(Opcodes.AALOAD);
        } else {
            mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        }
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                "getFileDescriptor", Type.getMethodDescriptor(Type.getType(FileDescriptor.class)), false);
    } else {
        mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(FileChannelImpl.class),
                "getFileDescriptor", Type.getMethodDescriptor(Type.getType(FileDescriptor.class)), false);
    }
    mv.visitVarInsn(Opcodes.LLOAD, startTimeIndex);
    mv.visitVarInsn(Opcodes.LLOAD, endTimeIndex);
    mv.visitVarInsn(returnType.getOpcode(Opcodes.ILOAD), resultIndex);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, this.callbackTypeInternalName, oppositeCallbackName,
            Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(FileDescriptor.class), Type.LONG_TYPE,
                    Type.LONG_TYPE, additionalCallbackArgumentType),
            false);

    // revert the active instrumentation flag for the buffer
    if (argumentTypes[bufferArgumentTypeIndex].getSort() == Type.ARRAY) {
        int iIndex = bufferInstrumentationActiveIndex + 1;

        // for (int i = 0; i < <buffers>.length; ++i) {
        // <buffers>[i].setInstrumentationActive(false);
        // }
        mv.visitInsn(Opcodes.ICONST_0);
        mv.visitVarInsn(Opcodes.ISTORE, iIndex);
        Label loopConditionLabel = new Label();
        mv.visitJumpInsn(Opcodes.GOTO, loopConditionLabel);
        Label loopStartLabel = new Label();
        mv.visitLabel(loopStartLabel);
        mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        mv.visitVarInsn(Opcodes.ILOAD, iIndex);
        mv.visitInsn(Opcodes.AALOAD);
        mv.visitInsn(Opcodes.ICONST_0);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class),
                "setInstrumentationActive", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false);
        mv.visitIincInsn(iIndex, 1);
        mv.visitLabel(loopConditionLabel);
        mv.visitVarInsn(Opcodes.ILOAD, iIndex);
        mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        mv.visitInsn(Opcodes.ARRAYLENGTH);
        mv.visitJumpInsn(Opcodes.IF_ICMPLT, loopStartLabel);
    } else {
        // buffer.setInstrumentationActive(false);
        mv.visitVarInsn(Opcodes.ALOAD, bufferArgumentIndex);
        mv.visitInsn(Opcodes.ICONST_0);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
                !isTransferMethod ? Type.getInternalName(MappedByteBuffer.class)
                        : Type.getInternalName(FileChannelImpl.class),
                "setInstrumentationActive", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false);
    }

    // }
    mv.visitLabel(bufferInstrumentationActiveLabel);

    // setInstrumentationActive(false);
    setInstrumentationActive(mv, false);

    // return result;
    // }
    mv.visitVarInsn(returnType.getOpcode(Opcodes.ILOAD), resultIndex);
    mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}