Java tutorial
/******************************************************************************* * Copyright (c) 2014, 2016 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package com.ibm.layout; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; /** * Helper methods for runtime class generators (Gen*.class) and FactoryMethods */ final class ImplHelper implements Opcodes { /** * Class to describe field properties */ public static final class FieldDesc { @Override public String toString() { return "FieldDesc [name=" + name + ", offset=" + offset + ", size=" + size + ", rawType=" + rawType + ", sig=" + sig + ", sigGeneric=" + sigGeneric + ", impl=" + impl + ", dims=" + Arrays.toString(dims) + "]"; } public String name; public long offset; public long size; public String rawType; // type from descriptor public String sig; // public signature string public String sigGeneric; public String impl; // impl class for non-primitives public long[] dims; // array dim public String elementImpl; // element impl class for non-primitives public String repeatCountMember; } /** * Find classes that must be generated before the current one. * @param interfaceCls A layout interface class * @return Set of required classes. */ static public Type[] getRequiredClasses(Class<? extends Layout> interfaceCls) { /* Return types of field getter methods */ Method[] mm = interfaceCls.getDeclaredMethods(); LinkedHashSet<Type> classSet = new LinkedHashSet<Type>(mm.length); for (int i = 0; i < mm.length; i++) { if (Modifier.isAbstract(mm[i].getModifiers())) { Type t = mm[i].getGenericReturnType(); classSet.add(t); } } /* Superinterface, if it is not a builtin type */ Class<?> superInterface = getSuperInterface(interfaceCls); String superInterfaceName = superInterface.getName(); if (!superInterfaceName.contains("com.ibm.layout")) { classSet.add((Type) superInterface); } return classSet.toArray(new Type[0]); } /** * Find the field description specified by fieldName in array of field description fields * * @param fieldName name of field to search for * @param fields array of field descriptions * @return field description or null if not found */ static public ImplHelper.FieldDesc findField(String fieldName, ImplHelper.FieldDesc[] fields) { for (ImplHelper.FieldDesc f : fields) { if (f.name.equals(fieldName)) { return f; } } return null; } /** * Return a hashtable containing the classes of all fields in the interface class * * @param interfaceCls, interface class * @return hashtable where key is fieldName, and value is fieldType */ static public HashMap<String, String> getFieldClasses(Class<? extends Layout> interfaceCls) { Class<?> superInterface = getSuperInterface(interfaceCls); String superInterfaceName = superInterface.getName(); HashMap<String, String> fieldClasses = new HashMap<>(1); if (!superInterfaceName.contains("com.ibm.layout")) { Class<?> cls = superInterface; while (!cls.getName().contains("com.ibm.layout")) { for (Method i : cls.getDeclaredMethods()) { if (Modifier.isAbstract(i.getModifiers())) { fieldClasses.put(i.getName(), i.getReturnType().getName()); } } cls = getSuperInterface(cls); } } for (Method i : interfaceCls.getDeclaredMethods()) { if (Modifier.isAbstract(i.getModifiers())) { fieldClasses.put(i.getName(), i.getReturnType().getName()); } } return fieldClasses; } /** * Get field descriptions for all fields in interface class * * @param interfaceCls, interface class * @return Array of fieldDescriptions */ static public FieldDesc[] getFieldDesc(Class<? extends Layout> interfaceCls) { String[] desc = getAnnotation(interfaceCls); desc = removePointerFromDesc(desc); FieldDesc[] fldDesc = new FieldDesc[desc.length]; HashMap<String, String> fieldClasses = getFieldClasses(interfaceCls); for (int i = 0; i < desc.length; i++) { String[] split = desc[i].split(":"); fldDesc[i] = new FieldDesc(); fldDesc[i].name = split[0]; fldDesc[i].rawType = split[1]; fldDesc[i].size = Long.parseLong(split[2]); if (i == 0) { fldDesc[i].offset = 0; } else { fldDesc[i].offset = fldDesc[i - 1].offset + fldDesc[i - 1].size; } parseFieldDescDims(fldDesc[i]); if (fldDesc[i].dims == null) { parseNonArraySig(fldDesc[i], fieldClasses); } else { parseArraySig(fldDesc[i]); } } return fldDesc; } /** * * Tests whether input is an integer or not * @param val String containing value to be tested * @return a <code>boolean</code> with the result. */ private static boolean isInteger(String val) { for (int i = 0; i < val.length(); i++) { if (!Character.isDigit(val.charAt(i))) { return false; } } return true; } static private void parseFieldDescDims(FieldDesc fldDesc) { // count the dimensions int dims = getArrayDim(fldDesc.rawType); if (dims > 2) { throw new UnsupportedOperationException("dims > 2"); } if (dims > 0) { // get each dimension fldDesc.dims = new long[dims]; int open = -1; int close = -1; int dimIdx = 0; while (-1 != (open = fldDesc.rawType.indexOf('[', close + 1))) { close = fldDesc.rawType.indexOf(']', open + 1); String size = fldDesc.rawType.substring(open + 1, close); if (isInteger(size)) { fldDesc.dims[dimIdx] = Long.parseLong(size); } else { fldDesc.repeatCountMember = size; } dimIdx++; } } } static private void parseArraySig(FieldDesc fldDesc) { String nonArrayType = getNonArrayType(fldDesc.rawType); int dim = fldDesc.dims.length; fldDesc.elementImpl = ""; switch (nonArrayType) { case "jbyte": fldDesc.sig = "Lcom/ibm/layout/ByteArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/ByteArray" + dim + "DImpl"; break; case "jint": fldDesc.sig = "Lcom/ibm/layout/IntArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/IntArray" + dim + "DImpl"; break; case "jboolean": fldDesc.sig = "Lcom/ibm/layout/BooleanArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/BooleanArray" + dim + "DImpl"; break; case "jchar": fldDesc.sig = "Lcom/ibm/layout/CharArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/CharArray" + dim + "DImpl"; break; case "jshort": fldDesc.sig = "Lcom/ibm/layout/ShortArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/ShortArray" + dim + "DImpl"; break; case "jlong": fldDesc.sig = "Lcom/ibm/layout/LongArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/LongArray" + dim + "DImpl"; break; case "jfloat": fldDesc.sig = "Lcom/ibm/layout/FloatArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/FloatArray" + dim + "DImpl"; break; case "jdouble": fldDesc.sig = "Lcom/ibm/layout/DoubleArray" + dim + "D;"; fldDesc.impl = "com/ibm/layout/gen/DoubleArray" + dim + "DImpl"; break; default: if (null == fldDesc.repeatCountMember) { fldDesc.sig = "Lcom/ibm/layout/Array" + dim + "D;"; fldDesc.sigGeneric = "Lcom/ibm/layout/Array" + dim + "D<" + nonArrayType + ">;"; fldDesc.impl = getArrayClassImplName(nonArrayType, dim); fldDesc.elementImpl = "com/ibm/layout/gen/" + nonArrayType + "Impl"; } else { fldDesc.sig = "Lcom/ibm/layout/VLArray;"; fldDesc.sigGeneric = "Lcom/ibm/layout/VLArray<" + nonArrayType + ">;"; fldDesc.impl = getVLArrayClassImplName(nonArrayType); fldDesc.elementImpl = "com/ibm/layout/gen/" + nonArrayType + "Impl"; } break; } } static private void parseNonArraySig(FieldDesc fldDesc, HashMap<String, String> fieldClasses) { switch (fldDesc.rawType) { case "jboolean": fldDesc.sig = "Z"; break; case "jbyte": fldDesc.sig = "B"; break; case "jchar": fldDesc.sig = "C"; break; case "jshort": fldDesc.sig = "S"; break; case "jint": fldDesc.sig = "I"; break; case "jlong": fldDesc.sig = "J"; break; case "jfloat": fldDesc.sig = "F"; break; case "jdouble": fldDesc.sig = "D"; break; default: // signature of an interface class fldDesc.sig = "L" + getBinaryPackageName(fieldClasses.get(fldDesc.name)) + "/" + fldDesc.rawType + ";"; fldDesc.impl = getImplClassName(fldDesc.rawType); break; } } static private int getArrayDim(String fieldType) { int dim = 0; int indexOf = -1; while (-1 != (indexOf = fieldType.indexOf('[', indexOf + 1))) { dim++; } return dim; } static private String getNonArrayType(String fieldType) { return fieldType.substring(0, fieldType.indexOf('[')); } static private String getBinaryPackageName(String className) { int lastIndex = className.lastIndexOf('.'); if (lastIndex == -1) return ""; return className.substring(0, lastIndex).replace('.', '/'); } static private String[] removePointerFromDesc(String[] desc) { ArrayList<String> tmp = new ArrayList<String>(); for (String s : desc) { if (!isPointerType(s.split(":")[1])) { tmp.add(s); } } return tmp.toArray(new String[0]); } /** * Get the value of the @LayoutDesc annotation for an interface class. * Concatenate the LayoutDesc with all its superclass's. * @param interfaceCls * @return */ public static String[] getAnnotation(Class<?> interfaceCls) { String[] desc; Class<?> cls = interfaceCls; if (null == interfaceCls.getAnnotation(LayoutDesc.class)) { do { cls = getSuperInterface(cls); } while (null == cls.getAnnotation(LayoutDesc.class)); desc = getAnnotation(cls); } else { desc = interfaceCls.getAnnotation(LayoutDesc.class).value(); cls = getSuperInterface(cls); if (null != cls.getAnnotation(LayoutDesc.class)) { desc = concatTwoStringArray(desc, getAnnotation(cls)); } } return desc; } /** * Get the binary name of an interface class */ static public String getInterfaceClassName(Class<? extends LayoutType> interfaceClass) { return interfaceClass.getName().replace('.', '/'); } /** * Get the binary name of the impl's super class */ static public String getImplSuperClassName(Class<? extends LayoutType> interfaceClass) { return "com/ibm/layout/gen/" + interfaceClass.getInterfaces()[0].getSimpleName() + "Impl"; } /** * Get the datalength for singleton layout * @return */ static public long getByteSize(FieldDesc[] fldDesc) { if (fldDesc.length == 0) { return 0; } return fldDesc[fldDesc.length - 1].offset + fldDesc[fldDesc.length - 1].size; } /** * Get the type suffix for the setter/getter for a primitive type * @param fieldSig a field signature * @return */ static public String fieldSig2MethodType(String fieldSig) { char c = fieldSig.charAt(0); switch (c) { case 'Z': return "Boolean"; case 'B': return "Byte"; case 'C': return "Char"; case 'S': return "Short"; case 'I': return "Int"; case 'J': return "Long"; case 'F': return "Float"; case 'D': return "Double"; default: return "UNKNOWN"; } } /** * Get the Signature for a JNI type * @param type string containing JNI type * @return signature for JNI type */ static public String convertJNITypeToSig(String type) { switch (type) { case "jboolean": return "Z"; case "jbyte": return "B"; case "jchar": return "C"; case "jshort": return "S"; case "jint": return "I"; case "jlong": return "J"; case "jfloat": return "F"; case "jdouble": return "D"; default: return null; } } /** * Return whether a field type is nested * @param fieldSig a field signature * @return whether a field type is nested */ static public boolean isTypePrimitive(String fieldSig) { char c = fieldSig.charAt(0); return (c != 'L'); } /** * Get the binary Impl name for a singleton layout. * All Impl classes reside in the same package. * @param simpleName Simple class name * @return Impl class name */ static public String getImplClassName(String simpleName) { return "com/ibm/layout/gen/" + simpleName + "Impl"; } /** * Get the binary Impl name for a singleton layout. * All Impl classes reside in the same package. * @param layoutClass A singleton layout class * @return Impl class name */ static public String getImplClassName(Class<? extends LayoutType> layoutClass) { return getImplClassName(layoutClass.getSimpleName()); } /** * Get the binary Impl name for a 2D array layout. * All Impl classes reside in the same package. * @param layoutClass A 2D array layout class * @return Impl class name */ static public String getArray2DClassImplName(Class<? extends Layout> elementInterfaceClass) { return getArrayClassImplName(elementInterfaceClass.getSimpleName(), 2); } /** * Get the binary Impl name for a 1D array layout. * All Impl classes reside in the same package. * @param layoutClass A 1D array layout class * @return Impl class name */ static public String getArray1DClassImplName(Class<? extends Layout> elementInterfaceClass) { return getArrayClassImplName(elementInterfaceClass.getSimpleName(), 1); } /** * Get the Impl name for an Array layout * @param simpleName simple name of element interface class (must extend Layout) * @param dim number of dimensions * @return */ static public String getArrayClassImplName(String simpleName, int dim) { return "com/ibm/layout/gen/" + simpleName + dim + "DImpl"; } /** * Get the Impl name for a VLArray layout * @param simpleName simple name of element interface class (must extend Layout) * @param repeatCountMember repeat count name * @param enclosingTypeName name of enclosing type * @return */ static public String getVLArrayClassImplName(String simpleName) { return "com/ibm/layout/gen/" + simpleName + "VLArrayImpl"; } /** * Get the Impl name for a VLArray layout * @param elementInterfaceClass a VLA layout class * @param repeatCountMember repeat count name * @param enclosingTypeName name of enclosing type * @return */ static public String getVLArrayClassImplName(Class<? extends Layout> elementInterfaceClass) { return getVLArrayClassImplName(elementInterfaceClass.getSimpleName()); } static public boolean isPointerType(String type) { return type.equals("Pointer"); } /** * Merge Two String arrays together into one. * @param first first String[] * @param second second String[] * @return Merged String[] */ static public String[] concatTwoStringArray(String[] first, String[] second) { List<String> both = new ArrayList<String>(first.length + second.length); Collections.addAll(both, first); Collections.addAll(both, second); return both.toArray(new String[both.size()]); } static String getByteCodeSig(String sig) { if (sig.equals("B") || sig.equals("Z") || sig.equals("C") || sig.equals("S")) { return "I"; } return sig; } static private Class<?> getSuperInterface(Class<?> interfaceCls) { Class<?>[] interfaces = interfaceCls.getInterfaces(); for (Class<?> superInterface : interfaces) { if (Layout.class.isAssignableFrom(superInterface)) { return superInterface; } } return null; } static void getLayoutImpl(ClassVisitor cw, MethodVisitor mv, String typeName) { { mv = cw.visitMethod(ACC_PUBLIC, "copyFrom", "(Lcom/ibm/layout/Layout;)V", null, null); mv.visitCode(); mv.visitFieldInsn(GETSTATIC, typeName, "unsafe", "Lsun/misc/Unsafe;"); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, typeName); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, typeName); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getOffset", "()J", false); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getOffset", "()J", false); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, "sizeof", "()J", false); mv.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "copyMemory", "(Ljava/lang/Object;JLjava/lang/Object;JJ)V", false); mv.visitInsn(RETURN); mv.visitMaxs(9, 2); mv.visitEnd(); } } static void genLayoutTypeImpl(ClassVisitor cw, MethodVisitor mv, FieldVisitor fv, String typeName, boolean layoutContainsVLA) { { fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, "unsafe", "Lsun/misc/Unsafe;", null, null); fv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "containsVLA", "()Z", null, null); mv.visitCode(); //if layout contains VLA return true, otherwise false if (layoutContainsVLA) { mv.visitInsn(ICONST_1); } else { mv.visitInsn(ICONST_0); } mv.visitInsn(IRETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { fv = cw.visitField(ACC_PROTECTED, "location", "Lcom/ibm/layout/Location;", null, null); fv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "bindLocation", "(Lcom/ibm/layout/Location;)V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, "sizeof", "()J", false); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "checkDataFits", "(J)Z", false); Label l0 = new Label(); mv.visitJumpInsn(IFEQ, l0); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn(PUTFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitInsn(RETURN); mv.visitMaxs(3, 2); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "writeToByteArray", "(J[BII)I", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 5); mv.visitInsn(I2L); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, "sizeof", "()J", false); mv.visitInsn(LCMP); Label l0 = new Label(); mv.visitJumpInsn(IFLE, l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, "sizeof", "()J", false); mv.visitInsn(L2I); mv.visitVarInsn(ISTORE, 5); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); Label l1 = new Label(); mv.visitJumpInsn(IFNULL, l1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); mv.visitVarInsn(LLOAD, 1); mv.visitInsn(L2I); mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ILOAD, 4); mv.visitVarInsn(ILOAD, 5); mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", false); Label l2 = new Label(); mv.visitJumpInsn(GOTO, l2); mv.visitLabel(l1); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitFieldInsn(GETSTATIC, typeName, "unsafe", "Lsun/misc/Unsafe;"); mv.visitInsn(ACONST_NULL); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getOffset", "()J", false); mv.visitVarInsn(LLOAD, 1); mv.visitInsn(LADD); mv.visitVarInsn(ALOAD, 3); mv.visitFieldInsn(GETSTATIC, typeName, "unsafe", "Lsun/misc/Unsafe;"); mv.visitVarInsn(ALOAD, 3); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "arrayBaseOffset", "(Ljava/lang/Class;)I", false); mv.visitInsn(I2L); mv.visitVarInsn(ILOAD, 5); mv.visitInsn(I2L); mv.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "copyMemory", "(Ljava/lang/Object;JLjava/lang/Object;JJ)V", false); mv.visitLabel(l2); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ILOAD, 5); mv.visitInsn(IRETURN); mv.visitMaxs(9, 6); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "readFromByteArray", "(J[BII)I", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 5); mv.visitInsn(I2L); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, "sizeof", "()J", false); mv.visitInsn(LCMP); Label l0 = new Label(); mv.visitJumpInsn(IFLE, l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, "sizeof", "()J", false); mv.visitInsn(L2I); mv.visitVarInsn(ISTORE, 5); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); Label l1 = new Label(); mv.visitJumpInsn(IFNULL, l1); mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ILOAD, 4); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); mv.visitVarInsn(LLOAD, 1); mv.visitInsn(L2I); mv.visitVarInsn(ILOAD, 5); mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", false); Label l2 = new Label(); mv.visitJumpInsn(GOTO, l2); mv.visitLabel(l1); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitFieldInsn(GETSTATIC, typeName, "unsafe", "Lsun/misc/Unsafe;"); mv.visitVarInsn(ALOAD, 3); mv.visitFieldInsn(GETSTATIC, typeName, "unsafe", "Lsun/misc/Unsafe;"); mv.visitVarInsn(ALOAD, 3); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "arrayBaseOffset", "(Ljava/lang/Class;)I", false); mv.visitVarInsn(ILOAD, 4); mv.visitInsn(IADD); mv.visitInsn(I2L); mv.visitInsn(ACONST_NULL); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getOffset", "()J", false); mv.visitVarInsn(LLOAD, 1); mv.visitInsn(LADD); mv.visitVarInsn(ILOAD, 5); mv.visitInsn(I2L); mv.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", "copyMemory", "(Ljava/lang/Object;JLjava/lang/Object;JJ)V", false); mv.visitLabel(l2); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ILOAD, 5); mv.visitInsn(IRETURN); mv.visitMaxs(9, 6); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "asByteBuffer", "()Ljava/nio/ByteBuffer;", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); Label l0 = new Label(); mv.visitJumpInsn(IFNULL, l0); mv.visitTypeInsn(NEW, "java/lang/UnsupportedOperationException"); mv.visitInsn(DUP); mv.visitLdcInsn("not off-heap"); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "(Ljava/lang/String;)V", false); mv.visitInsn(ATHROW); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getOffset", "()J", false); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, "sizeof", "()J", false); mv.visitMethodInsn(INVOKESTATIC, "com/ibm/layout/UnsafeHelper", "bufferFromAddress", "(JJ)Ljava/nio/ByteBuffer;", false); mv.visitVarInsn(ASTORE, 1); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKESTATIC, "java/nio/ByteOrder", "nativeOrder", "()Ljava/nio/ByteOrder;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/nio/ByteBuffer", "order", "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;", false); mv.visitInsn(POP); mv.visitVarInsn(ALOAD, 1); mv.visitInsn(ARETURN); mv.visitMaxs(4, 2); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "asByteBuffer", "(Lcom/ibm/layout/Location;J)Ljava/nio/ByteBuffer;", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getData", "()[B", false); Label l0 = new Label(); mv.visitJumpInsn(IFNULL, l0); mv.visitTypeInsn(NEW, "java/lang/UnsupportedOperationException"); mv.visitInsn(DUP); mv.visitLdcInsn("not off-heap"); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "(Ljava/lang/String;)V", false); mv.visitInsn(ATHROW); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/Location", "getOffset", "()J", false); mv.visitVarInsn(LLOAD, 1); mv.visitMethodInsn(INVOKESTATIC, "com/ibm/layout/UnsafeHelper", "bufferFromAddress", "(JJ)Ljava/nio/ByteBuffer;", false); mv.visitVarInsn(ASTORE, 3); mv.visitVarInsn(ALOAD, 3); mv.visitMethodInsn(INVOKESTATIC, "java/nio/ByteOrder", "nativeOrder", "()Ljava/nio/ByteOrder;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/nio/ByteBuffer", "order", "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;", false); mv.visitInsn(POP); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(ARETURN); mv.visitMaxs(4, 4); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "unsafeCast", "(Ljava/lang/Class;)Lcom/ibm/layout/Layout;", "<T::Lcom/ibm/layout/Layout;>(Ljava/lang/Class<TT;>;)TT;", null); mv.visitCode(); Label l0 = new Label(); Label l1 = new Label(); Label l2 = new Label(); mv.visitTryCatchBlock(l0, l1, l2, "java/lang/NoSuchMethodException"); Label l3 = new Label(); mv.visitTryCatchBlock(l0, l1, l3, "java/lang/SecurityException"); Label l4 = new Label(); mv.visitTryCatchBlock(l0, l1, l4, "java/lang/InstantiationException"); Label l5 = new Label(); mv.visitTryCatchBlock(l0, l1, l5, "java/lang/IllegalAccessException"); Label l6 = new Label(); mv.visitTryCatchBlock(l0, l1, l6, "java/lang/IllegalArgumentException"); Label l7 = new Label(); mv.visitTryCatchBlock(l0, l1, l7, "java/lang/reflect/InvocationTargetException"); mv.visitLabel(l0); mv.visitMethodInsn(INVOKESTATIC, "com/ibm/layout/LayoutHelper", "getFactory", "()Lcom/ibm/layout/LayoutHelper;", false); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/LayoutHelper", "genLayoutImpl", "(Ljava/lang/Class;)Ljava/lang/Class;", false); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitInsn(ICONST_0); mv.visitTypeInsn(ANEWARRAY, "java/lang/Class"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getDeclaredConstructor", "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", false); mv.visitVarInsn(ASTORE, 3); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(ICONST_1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Constructor", "setAccessible", "(Z)V", false); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(ICONST_0); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Constructor", "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;", false); mv.visitTypeInsn(CHECKCAST, "com/ibm/layout/Layout"); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEINTERFACE, "com/ibm/layout/Layout", "bindLocation", "(Lcom/ibm/layout/Location;)V", true); mv.visitVarInsn(ALOAD, 4); mv.visitLabel(l1); mv.visitInsn(ARETURN); mv.visitLabel(l2); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/NoSuchMethodException" }); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false); Label l8 = new Label(); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l3); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/SecurityException" }); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/SecurityException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l4); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/InstantiationException" }); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/InstantiationException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l5); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/IllegalAccessException" }); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/IllegalAccessException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l6); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/IllegalArgumentException" }); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/IllegalArgumentException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l7); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/reflect/InvocationTargetException" }); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/InvocationTargetException", "printStackTrace", "()V", false); mv.visitLabel(l8); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitInsn(ACONST_NULL); mv.visitInsn(ARETURN); mv.visitMaxs(2, 5); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "unsafeCast", "(Ljava/lang/Class;J)Lcom/ibm/layout/Array1D;", "<T::Lcom/ibm/layout/Layout;>(Ljava/lang/Class<TT;>;J)Lcom/ibm/layout/Array1D<TT;>;", null); mv.visitCode(); Label l0 = new Label(); Label l1 = new Label(); Label l2 = new Label(); mv.visitTryCatchBlock(l0, l1, l2, "java/lang/NoSuchMethodException"); Label l3 = new Label(); mv.visitTryCatchBlock(l0, l1, l3, "java/lang/SecurityException"); Label l4 = new Label(); mv.visitTryCatchBlock(l0, l1, l4, "java/lang/InstantiationException"); Label l5 = new Label(); mv.visitTryCatchBlock(l0, l1, l5, "java/lang/IllegalAccessException"); Label l6 = new Label(); mv.visitTryCatchBlock(l0, l1, l6, "java/lang/IllegalArgumentException"); Label l7 = new Label(); mv.visitTryCatchBlock(l0, l1, l7, "java/lang/reflect/InvocationTargetException"); mv.visitLabel(l0); mv.visitMethodInsn(INVOKESTATIC, "com/ibm/layout/LayoutHelper", "getFactory", "()Lcom/ibm/layout/LayoutHelper;", false); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/LayoutHelper", "genLayoutImpl", "(Ljava/lang/Class;)Ljava/lang/Class;", false); mv.visitVarInsn(ASTORE, 5); mv.visitVarInsn(ALOAD, 5); mv.visitInsn(ICONST_0); mv.visitTypeInsn(ANEWARRAY, "java/lang/Class"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getDeclaredConstructor", "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", false); mv.visitVarInsn(ASTORE, 6); mv.visitVarInsn(ALOAD, 6); mv.visitInsn(ICONST_1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Constructor", "setAccessible", "(Z)V", false); mv.visitVarInsn(ALOAD, 6); mv.visitInsn(ICONST_0); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Constructor", "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;", false); mv.visitTypeInsn(CHECKCAST, "com/ibm/layout/Layout"); mv.visitMethodInsn(INVOKEINTERFACE, "com/ibm/layout/Layout", "sizeof", "()J", true); mv.visitVarInsn(LSTORE, 7); mv.visitVarInsn(ALOAD, 4); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/layout/LayoutHelper", "genArray1DImpl", "(Ljava/lang/Class;)Ljava/lang/Class;", false); mv.visitVarInsn(ASTORE, 9); mv.visitVarInsn(ALOAD, 9); mv.visitInsn(ICONST_2); mv.visitTypeInsn(ANEWARRAY, "java/lang/Class"); mv.visitInsn(DUP); mv.visitInsn(ICONST_0); mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;"); mv.visitInsn(AASTORE); mv.visitInsn(DUP); mv.visitInsn(ICONST_1); mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;"); mv.visitInsn(AASTORE); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getDeclaredConstructor", "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", false); mv.visitVarInsn(ASTORE, 10); mv.visitVarInsn(ALOAD, 10); mv.visitInsn(ICONST_1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Constructor", "setAccessible", "(Z)V", false); mv.visitVarInsn(ALOAD, 10); mv.visitInsn(ICONST_2); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); mv.visitInsn(DUP); mv.visitInsn(ICONST_0); mv.visitVarInsn(LLOAD, 2); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); mv.visitInsn(AASTORE); mv.visitInsn(DUP); mv.visitInsn(ICONST_1); mv.visitVarInsn(LLOAD, 7); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); mv.visitInsn(AASTORE); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Constructor", "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;", false); mv.visitTypeInsn(CHECKCAST, "com/ibm/layout/Array1D"); mv.visitVarInsn(ASTORE, 11); mv.visitVarInsn(ALOAD, 11); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, typeName, "location", "Lcom/ibm/layout/Location;"); mv.visitMethodInsn(INVOKEINTERFACE, "com/ibm/layout/Array1D", "bindLocation", "(Lcom/ibm/layout/Location;)V", true); mv.visitVarInsn(ALOAD, 11); mv.visitLabel(l1); mv.visitInsn(ARETURN); mv.visitLabel(l2); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/NoSuchMethodException" }); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false); Label l8 = new Label(); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l3); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/SecurityException" }); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/SecurityException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l4); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/InstantiationException" }); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/InstantiationException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l5); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/IllegalAccessException" }); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/IllegalAccessException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l6); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/IllegalArgumentException" }); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/IllegalArgumentException", "printStackTrace", "()V", false); mv.visitJumpInsn(GOTO, l8); mv.visitLabel(l7); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/reflect/InvocationTargetException" }); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/InvocationTargetException", "printStackTrace", "()V", false); mv.visitLabel(l8); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitInsn(ACONST_NULL); mv.visitInsn(ARETURN); mv.visitMaxs(6, 12); mv.visitEnd(); } } }