/*
* Copyright 2016 higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.lang.io;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import sun.misc.Unsafe;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
interface ByteBufferReuse {
ByteBufferReuse INSTANCE = Inner.getReuse();
ByteBuffer reuse(long addr, int cap, Object att, ByteBuffer toReuse);
class Inner extends Reuses implements Opcodes {
private static ByteBufferReuse getReuse() {
ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
final String reuseImplClassName = "net/openhft/lang/io/ByteBufferReuseImpl";
cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, reuseImplClassName, null,
"sun/reflect/MagicAccessorImpl",
new String[]{"net/openhft/lang/io/ByteBufferReuse"});
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
String attachedBufferFieldName = getAttachedBufferFieldName();
{
mv = cw.visitMethod(ACC_PUBLIC, "reuse",
"(JILjava/lang/Object;Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;",
null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 5);
String directByteBuffer = "java/nio/DirectByteBuffer";
mv.visitTypeInsn(INSTANCEOF, directByteBuffer);
Label l0 = new Label();
mv.visitJumpInsn(IFEQ, l0);
mv.visitVarInsn(ALOAD, 5);
mv.visitTypeInsn(CHECKCAST, directByteBuffer);
mv.visitVarInsn(ASTORE, 6);
mv.visitVarInsn(ALOAD, 6);
mv.visitFieldInsn(GETFIELD, directByteBuffer, attachedBufferFieldName, "Ljava/lang/Object;");
String settableAtt = "net/openhft/lang/io/SettableAtt";
mv.visitTypeInsn(INSTANCEOF, settableAtt);
mv.visitJumpInsn(IFEQ, l0);
mv.visitVarInsn(ALOAD, 6);
mv.visitVarInsn(LLOAD, 1);
mv.visitFieldInsn(PUTFIELD, directByteBuffer, "address", "J");
mv.visitVarInsn(ALOAD, 6);
mv.visitInsn(ICONST_M1);
mv.visitFieldInsn(PUTFIELD, directByteBuffer, "mark", "I");
mv.visitVarInsn(ALOAD, 6);
mv.visitInsn(ICONST_0);
mv.visitFieldInsn(PUTFIELD, directByteBuffer, "position", "I");
mv.visitVarInsn(ALOAD, 6);
mv.visitVarInsn(ILOAD, 3);
mv.visitFieldInsn(PUTFIELD, directByteBuffer, "limit", "I");
mv.visitVarInsn(ALOAD, 6);
mv.visitVarInsn(ILOAD, 3);
mv.visitFieldInsn(PUTFIELD, directByteBuffer, "capacity", "I");
mv.visitVarInsn(ALOAD, 6);
mv.visitFieldInsn(GETFIELD, directByteBuffer, attachedBufferFieldName, "Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, settableAtt);
mv.visitVarInsn(ALOAD, 4);
mv.visitFieldInsn(PUTFIELD, settableAtt, "att", "Ljava/lang/Object;");
mv.visitVarInsn(ALOAD, 6);
mv.visitInsn(ARETURN);
mv.visitLabel(l0);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitTypeInsn(NEW, settableAtt);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, settableAtt, "<init>", "()V", false);
mv.visitVarInsn(ASTORE, 6);
mv.visitVarInsn(ALOAD, 6);
mv.visitVarInsn(ALOAD, 4);
mv.visitFieldInsn(PUTFIELD, settableAtt, "att", "Ljava/lang/Object;");
mv.visitTypeInsn(NEW, directByteBuffer);
mv.visitInsn(DUP);
mv.visitVarInsn(LLOAD, 1);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ALOAD, 6);
mv.visitMethodInsn(INVOKESPECIAL, directByteBuffer, "<init>",
"(JILjava/lang/Object;)V", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(6, 7);
mv.visitEnd();
}
cw.visitEnd();
final byte[] impl = cw.toByteArray();
final Unsafe unsafe = NativeBytes.UNSAFE;
Class clazz = AccessController.doPrivileged(new PrivilegedAction<Class>() {
@Override
public Class run() {
ClassLoader cl = MAGIC_CLASS_LOADER;
return unsafe.defineClass(reuseImplClassName, impl, 0, impl.length, cl, null);
}
});
try {
return (ByteBufferReuse) clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private static String getAttachedBufferFieldName() {
try {
Class<?> clazz = Class.forName("java.nio.DirectByteBuffer");
String[] possibleFieldNames = new String[] { "att",
"viewedBuffer" };
for (String possibleFieldName : possibleFieldNames) {
try {
clazz.getDeclaredField(possibleFieldName);
return possibleFieldName;
} catch (Exception e) {
continue;
}
}
throw new RuntimeException(
"Failed to find any of the possible field names on DirectByteBuffer: "
+ Arrays.toString(possibleFieldNames));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}