List of usage examples for org.objectweb.asm Opcodes ALOAD
int ALOAD
To view the source code for org.objectweb.asm Opcodes ALOAD.
Click Source Link
From source file:de.zib.sfs.instrument.DirectByteBufferAdapter.java
License:BSD License
@Override protected void wrapMethod(int access, String name, Type returnType, Type[] argumentTypes, String signature, String[] exceptions, String callbackName, Type additionalCallbackArgumentType, ResultPasser resultPasser) {/*from www .j a va 2s .co m*/ argumentTypes = argumentTypes == null ? new Type[] {} : argumentTypes; 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(); // if (isInstrumentationActive() || !fromFileChannel) { isInstrumentationActive(mv); Label instrumentationActiveLabel = new Label(); mv.visitJumpInsn(Opcodes.IFNE, instrumentationActiveLabel); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "fromFileChannel", Type.getDescriptor(Boolean.TYPE)); Label fromFileChannelLabel = new Label(); mv.visitJumpInsn(Opcodes.IFNE, fromFileChannelLabel); mv.visitLabel(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); if (!Type.VOID_TYPE.equals(returnType)) { mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); } else { mv.visitInsn(Opcodes.RETURN); } // } mv.visitLabel(fromFileChannelLabel); // setInstrumentationActive(true); setInstrumentationActive(mv, true); // long startTime = System.nanoTime(); int startTimeIndex = 1; for (Type argument : argumentTypes) { startTimeIndex += argument.getSize(); } 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 endTimeIndex = startTimeIndex + 2; if (!Type.VOID_TYPE.equals(returnType)) { mv.visitVarInsn(returnType.getOpcode(Opcodes.ISTORE), startTimeIndex + 2); endTimeIndex += returnType.getSize(); } // long endTime = System.nanoTime(); storeTime(mv, endTimeIndex); // callback.<callbackMethod>(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); // -1 indicates no result should be passed int resultIndex = resultPasser.getResultIndex(); if (resultIndex != -1) { // result of the actual operation requested if (resultIndex == 0) { mv.visitVarInsn(returnType.getOpcode(Opcodes.ILOAD), startTimeIndex + 2); resultPasser.passResult(mv); } else { // some parameter requested mv.visitVarInsn(argumentTypes[resultIndex - 1].getOpcode(Opcodes.ILOAD), resultIndex); resultPasser.passResult(mv); } } Type[] callbackArgumentTypes; if (additionalCallbackArgumentType == null) { callbackArgumentTypes = new Type[] { Type.LONG_TYPE, Type.LONG_TYPE }; } else { callbackArgumentTypes = new Type[] { Type.LONG_TYPE, Type.LONG_TYPE, additionalCallbackArgumentType }; } mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.callbackTypeInternalName, callbackName, Type.getMethodDescriptor(Type.VOID_TYPE, callbackArgumentTypes), false); // setInstrumentationActive(false); setInstrumentationActive(mv, false); // return result;? // } if (!Type.VOID_TYPE.equals(returnType)) { mv.visitVarInsn(returnType.getOpcode(Opcodes.ILOAD), startTimeIndex + 2); mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); } else { mv.visitInsn(Opcodes.RETURN); } mv.visitMaxs(0, 0); mv.visitEnd(); }
From source file:de.zib.sfs.instrument.FileChannelImplAdapter.java
License:BSD License
@Override protected void initializeFields(MethodVisitor constructorMV, String constructorDesc) { // callback.openCallback(fd); constructorMV.visitVarInsn(Opcodes.ALOAD, 0); constructorMV.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "callback", this.callbackTypeDescriptor); constructorMV.visitVarInsn(Opcodes.ALOAD, 0); constructorMV.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "fd", Type.getDescriptor(FileDescriptor.class)); constructorMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.callbackTypeInternalName, "openCallback", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(FileDescriptor.class)), false); }
From source file:de.zib.sfs.instrument.FileChannelImplAdapter.java
License:BSD License
@Override protected void appendWrappedMethods(ClassVisitor visitor) { // public FileDescriptor getFileDescriptor() { MethodVisitor getFileDescriptorMV = visitor.visitMethod(Opcodes.ACC_PUBLIC, "getFileDescriptor", Type.getMethodDescriptor(Type.getType(FileDescriptor.class)), null, null); getFileDescriptorMV.visitCode();/*from w w w. ja v a 2 s .c om*/ // return fileDescriptor; // } getFileDescriptorMV.visitVarInsn(Opcodes.ALOAD, 0); getFileDescriptorMV.visitFieldInsn(Opcodes.GETFIELD, Type.getInternalName(FileChannelImpl.class), "fd", Type.getDescriptor(FileDescriptor.class)); getFileDescriptorMV.visitInsn(Opcodes.ARETURN); getFileDescriptorMV.visitMaxs(0, 0); getFileDescriptorMV.visitEnd(); if (!skipReads()) { wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "read", Type.INT_TYPE, new Type[] { Type.getType(ByteBuffer.class) }, null, new String[] { Type.getInternalName(IOException.class) }, "readCallback", "writeCallback", Type.INT_TYPE, 0, false); wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "read", Type.INT_TYPE, new Type[] { Type.getType(ByteBuffer.class), Type.LONG_TYPE }, null, new String[] { Type.getInternalName(IOException.class) }, "readCallback", "writeCallback", Type.INT_TYPE, 0, false); wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "read", Type.LONG_TYPE, new Type[] { Type.getType(ByteBuffer[].class), Type.INT_TYPE, Type.INT_TYPE }, null, new String[] { Type.getInternalName(IOException.class) }, "readCallback", "writeCallback", Type.LONG_TYPE, 0, false); // transferTo is basically a read wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "transferTo", Type.LONG_TYPE, new Type[] { Type.LONG_TYPE, Type.LONG_TYPE, Type.getType(WritableByteChannel.class) }, null, new String[] { Type.getInternalName(IOException.class) }, "readCallback", "writeCallback", Type.LONG_TYPE, 2, true); } // repeat for write methods if (!skipWrites()) { wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "write", Type.INT_TYPE, new Type[] { Type.getType(ByteBuffer.class) }, null, new String[] { Type.getInternalName(IOException.class) }, "writeCallback", "readCallback", Type.INT_TYPE, 0, false); wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "write", Type.INT_TYPE, new Type[] { Type.getType(ByteBuffer.class), Type.LONG_TYPE }, null, new String[] { Type.getInternalName(IOException.class) }, "writeCallback", "readCallback", Type.INT_TYPE, 0, false); wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "write", Type.LONG_TYPE, new Type[] { Type.getType(ByteBuffer[].class), Type.INT_TYPE, Type.INT_TYPE }, null, new String[] { Type.getInternalName(IOException.class) }, "writeCallback", "readCallback", Type.LONG_TYPE, 0, false); // transferFrom is basically a write wrapFileChannelImplMethod(Opcodes.ACC_PUBLIC, "transferFrom", Type.LONG_TYPE, new Type[] { Type.getType(ReadableByteChannel.class), Type.LONG_TYPE, Type.LONG_TYPE }, null, new String[] { Type.getInternalName(IOException.class) }, "writeCallback", "readCallback", Type.LONG_TYPE, 0, true); } String mapMethodDescriptor = Type.getMethodDescriptor(Type.getType(MappedByteBuffer.class), Type.getType(MapMode.class), Type.LONG_TYPE, Type.LONG_TYPE); // public MappedByteBuffer map(MapMode mode, long position, long size) // throws IOException { MethodVisitor mapMV = visitor.visitMethod(Opcodes.ACC_PUBLIC, "map", mapMethodDescriptor, null, new String[] { Type.getInternalName(IOException.class) }); mapMV.visitCode(); // MappedByteBuffer mbb = nativeMethodPrefixmap(mode, position, size); mapMV.visitVarInsn(Opcodes.ALOAD, 0); mapMV.visitVarInsn(Opcodes.ALOAD, 1); mapMV.visitVarInsn(Opcodes.LLOAD, 2); mapMV.visitVarInsn(Opcodes.LLOAD, 4); mapMV.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instrumentedTypeInternalName, this.methodPrefix + "map", mapMethodDescriptor, false); mapMV.visitVarInsn(Opcodes.ASTORE, 6); // mbb.setFromFileChannel(true); mapMV.visitVarInsn(Opcodes.ALOAD, 6); mapMV.visitInsn(Opcodes.ICONST_1); mapMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class), "setFromFileChannel", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false); // mbb.setFileDescriptor(fd); mapMV.visitVarInsn(Opcodes.ALOAD, 6); mapMV.visitVarInsn(Opcodes.ALOAD, 0); mapMV.visitFieldInsn(Opcodes.GETFIELD, this.instrumentedTypeInternalName, "fd", Type.getDescriptor(FileDescriptor.class)); mapMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(MappedByteBuffer.class), "setFileDescriptor", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(FileDescriptor.class)), false); // if we don't want to trace mmap calls, then map needs to reset the // instrumentationActive flag if (!this.traceMmap) { // setInstrumentationActive(false); setInstrumentationActive(mapMV, false); } // return mbb; // } mapMV.visitVarInsn(Opcodes.ALOAD, 6); mapMV.visitInsn(Opcodes.ARETURN); mapMV.visitMaxs(0, 0); mapMV.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 ww . jav a 2s . com // 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(); }
From source file:de.zib.sfs.instrument.MappedByteBufferAdapter.java
License:BSD License
@Override protected void initializeFields(MethodVisitor constructorMV, String constructorDesc) { // fromFileChannel = false; constructorMV.visitVarInsn(Opcodes.ALOAD, 0); constructorMV.visitInsn(Opcodes.ICONST_0); constructorMV.visitFieldInsn(Opcodes.PUTFIELD, Type.getInternalName(MappedByteBuffer.class), "fromFileChannel", Type.getDescriptor(Boolean.TYPE)); }
From source file:de.zib.sfs.instrument.MappedByteBufferAdapter.java
License:BSD License
@Override protected void appendWrappedMethods(ClassVisitor visitor) { // public void setFromFileChannel(boolean fromFileChannel) { MethodVisitor setFromFileChannelMV = visitor.visitMethod(Opcodes.ACC_PUBLIC, "setFromFileChannel", Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), null, null); setFromFileChannelMV.visitCode();//from w ww . j av a 2 s . c om // this.fromFileChannel = fromFileChannel; setFromFileChannelMV.visitVarInsn(Opcodes.ALOAD, 0); setFromFileChannelMV.visitVarInsn(Opcodes.ILOAD, 1); setFromFileChannelMV.visitFieldInsn(Opcodes.PUTFIELD, Type.getInternalName(MappedByteBuffer.class), "fromFileChannel", Type.getDescriptor(Boolean.TYPE)); // } setFromFileChannelMV.visitInsn(Opcodes.RETURN); setFromFileChannelMV.visitMaxs(0, 0); setFromFileChannelMV.visitEnd(); // public boolean isFromFileChannel() { MethodVisitor isFromFileChannelMV = visitor.visitMethod(Opcodes.ACC_PUBLIC, "isFromFileChannel", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), null, null); isFromFileChannelMV.visitCode(); // return fromFileChannel; // } isFromFileChannelMV.visitVarInsn(Opcodes.ALOAD, 0); isFromFileChannelMV.visitFieldInsn(Opcodes.GETFIELD, Type.getInternalName(MappedByteBuffer.class), "fromFileChannel", Type.getDescriptor(Boolean.TYPE)); isFromFileChannelMV.visitInsn(Opcodes.IRETURN); isFromFileChannelMV.visitMaxs(0, 0); isFromFileChannelMV.visitEnd(); // 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)); // } settFileDescriptorMV.visitInsn(Opcodes.RETURN); settFileDescriptorMV.visitMaxs(0, 0); settFileDescriptorMV.visitEnd(); // public FileDescriptor getFileDescriptor() { MethodVisitor getFileDescriptorMV = visitor.visitMethod(Opcodes.ACC_PUBLIC, "getFileDescriptor", Type.getMethodDescriptor(Type.getType(FileDescriptor.class)), null, null); getFileDescriptorMV.visitCode(); // return getFileDescriptorImpl(); // } getFileDescriptorMV.visitVarInsn(Opcodes.ALOAD, 0); getFileDescriptorMV.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instrumentedTypeInternalName, "getFileDescriptorImpl", Type.getMethodDescriptor(Type.getType(FileDescriptor.class)), false); getFileDescriptorMV.visitInsn(Opcodes.ARETURN); getFileDescriptorMV.visitMaxs(0, 0); getFileDescriptorMV.visitEnd(); // 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(); visitor.visitEnd(); }
From source file:de.zib.sfs.instrument.ZipFileAdapter.java
License:BSD License
@Override public void visitEnd() { if (!this.skip.contains(OperationCategory.ZIP)) { // public void close() { MethodVisitor closeMethodMV = this.cv.visitMethod(Opcodes.ACC_PUBLIC, "close", Type.getMethodDescriptor(Type.VOID_TYPE), null, new String[] { Type.getInternalName(IOException.class) }); closeMethodMV.visitCode();//from ww w .ja va 2 s .c o m // ZipFileCallback.closeCallback(jzfile); closeMethodMV.visitVarInsn(Opcodes.ALOAD, 0); closeMethodMV.visitFieldInsn(Opcodes.GETFIELD, Type.getInternalName(ZipFile.class), "jzfile", Type.getDescriptor(Long.TYPE)); closeMethodMV.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ZipFileCallback.class), "closeCallback", Type.getMethodDescriptor(Type.VOID_TYPE, Type.LONG_TYPE), false); // methodPrefixclose(); closeMethodMV.visitVarInsn(Opcodes.ALOAD, 0); closeMethodMV.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(ZipFile.class), this.methodPrefix + "close", Type.getMethodDescriptor(Type.VOID_TYPE), false); // } closeMethodMV.visitInsn(Opcodes.RETURN); closeMethodMV.visitMaxs(0, 0); closeMethodMV.visitEnd(); } this.cv.visitEnd(); }
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 w w . j av a 2 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:dodola.anole.lib.IncrementalChangeVisitor.java
License:Apache License
/** * To each class, add the dispatch method called by the original code that acts as a trampoline to * invoke the changed methods./*from w w w . j a va2 s.c om*/ * <p/> * Pseudo code: * <code> * Object access$dispatch(String name, object[] args) { * if (name.equals( * "firstMethod.(L$type;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;")) { * return firstMethod(($type)arg[0], (String)arg[1], arg[2]); * } * if (name.equals("secondMethod.(L$type;Ljava/lang/String;I;)V")) { * secondMethod(($type)arg[0], (String)arg[1], (int)arg[2]); * return; * } * ... * StringBuilder $local1 = new StringBuilder(); * $local1.append("Method not found "); * $local1.append(name); * $local1.append(" in " + visitedClassName + * "$dispatch implementation, restart the application"); * throw new $package/InstantReloadException($local1.toString()); * } * </code> */ private void addDispatchMethod() { int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_VARARGS; Method m = new Method("access$dispatch", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;"); MethodVisitor visitor = super.visitMethod(access, m.getName(), m.getDescriptor(), null, null); final GeneratorAdapter mv = new GeneratorAdapter(access, m, visitor); if (TRACING_ENABLED) { mv.push("Redirecting "); mv.loadArg(0); trace(mv, 2); } List<MethodNode> allMethods = new ArrayList<MethodNode>(); // if we are disabled, do not generate any dispatch, the method will throw an exception // if invoked which should never happen. if (!instantRunDisabled) { //noinspection unchecked allMethods.addAll(classNode.methods); allMethods.addAll(addedMethods); } final Map<String, MethodNode> methods = new HashMap<String, MethodNode>(); for (MethodNode methodNode : allMethods) { if (methodNode.name.equals("<clinit>") || methodNode.name.equals("<init>")) { continue; } if (!isAccessCompatibleWithInstantRun(methodNode.access)) { continue; } methods.put(methodNode.name + "." + methodNode.desc, methodNode); } new StringSwitch() { @Override void visitString() { mv.visitVarInsn(Opcodes.ALOAD, 1); } @Override void visitCase(String methodName) { MethodNode methodNode = methods.get(methodName); String name = methodNode.name; boolean isStatic = (methodNode.access & Opcodes.ACC_STATIC) != 0; String newDesc = computeOverrideMethodDesc(methodNode.desc, isStatic); if (TRACING_ENABLED) { trace(mv, "M: " + name + " P:" + newDesc); } Type[] args = Type.getArgumentTypes(newDesc); int argc = 0; for (Type t : args) { mv.visitVarInsn(Opcodes.ALOAD, 2); mv.push(argc); mv.visitInsn(Opcodes.AALOAD); ByteCodeUtils.unbox(mv, t); argc++; } mv.visitMethodInsn(Opcodes.INVOKESTATIC, visitedClassName + "$override", isStatic ? computeOverrideMethodName(name, methodNode.desc) : name, newDesc, false); Type ret = Type.getReturnType(methodNode.desc); if (ret.getSort() == Type.VOID) { mv.visitInsn(Opcodes.ACONST_NULL); } else { mv.box(ret); } mv.visitInsn(Opcodes.ARETURN); } @Override void visitDefault() { writeMissingMessageWithHash(mv, visitedClassName); } }.visit(mv, methods.keySet()); mv.visitMaxs(0, 0); mv.visitEnd(); super.visitEnd(); }
From source file:dodola.anole.lib.IncrementalSupportVisitor.java
License:Apache License
/*** * Inserts a trampoline to this class so that the updated methods can make calls to super * class methods./* w w w. j a v a 2s . c o m*/ * <p/> * Pseudo code for this trampoline: * <code> * Object access$super($classType instance, String name, object[] args) { * switch(name) { * case "firstMethod.(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;": * return super~instance.firstMethod((String)arg[0], arg[1]); * case "secondMethod.(Ljava/lang/String;I)V": * return super~instance.firstMethod((String)arg[0], arg[1]); * <p> * default: * StringBuilder $local1 = new StringBuilder(); * $local1.append("Method not found "); * $local1.append(name); * $local1.append(" in " $classType $super implementation"); * throw new $package/InstantReloadException($local1.toString()); * } * </code> */ private void createAccessSuper() { int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_VARARGS; Method m = new Method("access$super", "(L" + visitedClassName + ";Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;"); MethodVisitor visitor = super.visitMethod(access, m.getName(), m.getDescriptor(), null, null); final GeneratorAdapter mv = new GeneratorAdapter(access, m, visitor); // Gather all methods from itself and its superclasses to generate a giant access$super // implementation. // This will work fine as long as we don't support adding methods to a class. final Map<String, MethodReference> uniqueMethods = new HashMap<String, MethodReference>(); if (parentNodes.isEmpty()) { // if we cannot determine the parents for this class, let's blindly add all the // method of the current class as a gateway to a possible parent version. addAllNewMethods(uniqueMethods, classNode); } else { // otherwise, use the parent list. for (ClassNode parentNode : parentNodes) { addAllNewMethods(uniqueMethods, parentNode); } } new StringSwitch() { @Override void visitString() { mv.visitVarInsn(Opcodes.ALOAD, 1); } @Override void visitCase(String methodName) { MethodReference methodRef = uniqueMethods.get(methodName); mv.visitVarInsn(Opcodes.ALOAD, 0); Type[] args = Type.getArgumentTypes(methodRef.method.desc); int argc = 0; for (Type t : args) { mv.visitVarInsn(Opcodes.ALOAD, 2); mv.push(argc); mv.visitInsn(Opcodes.AALOAD); ByteCodeUtils.unbox(mv, t); argc++; } if (TRACING_ENABLED) { trace(mv, "super selected ", methodRef.owner.name, methodRef.method.name, methodRef.method.desc); } // Call super on the other object, yup this works cos we are on the right place to // call from. mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodRef.owner.name, methodRef.method.name, methodRef.method.desc, false); Type ret = Type.getReturnType(methodRef.method.desc); if (ret.getSort() == Type.VOID) { mv.visitInsn(Opcodes.ACONST_NULL); } else { mv.box(ret); } mv.visitInsn(Opcodes.ARETURN); } @Override void visitDefault() { writeMissingMessageWithHash(mv, visitedClassName); } }.visit(mv, uniqueMethods.keySet()); mv.visitMaxs(0, 0); mv.visitEnd(); }