/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ import java.lang.reflect.Method; import org.jikesrvm.architecture.ArchConstants; import org.jikesrvm.classloader.RVMClass; import org.jikesrvm.classloader.RVMMethod; import org.jikesrvm.compilers.common.CompiledMethod; import org.jikesrvm.mm.mminterface.Selected; import org.jikesrvm.mm.mminterface.Selected.Constraints; import org.vmmagic.pragma.NoInline; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.Extent; import org.vmmagic.unboxed.Offset; import org.vmmagic.unboxed.Word; /** * A class to <em>estimate</em> the code size impact of garbage collector * barriers. * <p> * This will only run on Jikes RVM as it reaches into the * internals of the VM to get access to the generated machine code for * the prototypical methods. * <p> * It can also be used with org.jikesrvm.tools.oth.OptTestHarness to manually inspect and * tune the barrier code sequences. */ class BarrierSize { boolean booleanField; byte byteField; char charField; short shortField; int intField; float floatField; double doubleField; long longField; Object objectField; Address addressField; Word wordField; Extent extentField; Offset offsetField; boolean[] booleanArray; byte[] byteArray; char[] charArray; short[] shortArray; int[] intArray; float[] floatArray; double[] doubleArray; long[] longArray; Object[] objectArray; /** size for the empty method in units */ private static int emptySize; /** the class object for this class */ private static Class<?> thisClass; /** * The size is either in bytes or number of instructions, * depending on the architecture. */ private static final String unit = (ArchConstants.getInstructionWidth() == 1) ? " bytes" : " instructions"; @NoInline void emptyInstanceMethod() { // no content } @NoInline void writeToBooleanField(boolean b) { this.booleanField = b; } @NoInline boolean readFromBooleanField() { return this.booleanField; } @NoInline void writeToByteField(byte b) { this.byteField = b; } @NoInline byte readFromByteField() { return this.byteField; } @NoInline void writeToCharField(char c) { this.charField = c; } @NoInline char readFromCharField() { return this.charField; } @NoInline void writeToShortField(short s) { this.shortField = s; } @NoInline short readFromShortField() { return this.shortField; } @NoInline void writeToIntField(int i) { this.intField = i; } @NoInline int readFromIntField() { return this.intField; } @NoInline void writeToFloatField(float f) { this.floatField = f; } @NoInline float readFromFloatField() { return this.floatField; } @NoInline void writeToDoubleField(double d) { this.doubleField = d; } @NoInline double readFromDoubleField() { return this.doubleField; } @NoInline void writeToLongField(long l) { this.longField = l; } @NoInline Long readFromLongField() { return this.longField; } @NoInline void writeToObjectField(Object o) { this.objectField = o; } @NoInline Object readFromObjectField() { return this.objectField; } @NoInline void writeToAddressField(Address a) { this.addressField = a; } @NoInline Address readFromAddressField() { return this.addressField; } @NoInline void writeToWordField(Word w) { this.wordField = w; } @NoInline Word readFromWordField() { return this.wordField; } @NoInline void writeToExtentField(Extent e) { this.extentField = e; } @NoInline Extent readFromExtentField() { return this.extentField; } @NoInline void writeToOffsetField(Offset o) { this.offsetField = o; } @NoInline Offset readFromOffsetField() { return this.offsetField; } @NoInline void writeToBooleanArray(boolean b) { this.booleanArray[0] = b; } @NoInline boolean readFromBooleanArray() { return this.booleanArray[0]; } @NoInline void writeToByteArray(byte b) { this.byteArray[0] = b; } @NoInline byte readFromByteArray() { return this.byteArray[0]; } @NoInline void writeToCharArray(char c) { this.charArray[0] = c; } @NoInline char readFromCharArray() { return this.charArray[0]; } @NoInline void writeToShortArray(short s) { this.shortArray[0] = s; } @NoInline short readFromShortArray() { return this.shortArray[0]; } @NoInline void writeToIntArray(int i) { this.intArray[0] = i; } @NoInline int readFromIntArray() { return this.intArray[0]; } @NoInline void writeToFloatArray(float f) { this.floatArray[0] = f; } @NoInline float readFromFloatArray() { return this.floatArray[0]; } @NoInline void writeToDoubleArray(double d) { this.doubleArray[0] = d; } @NoInline double readFromDoubleArray() { return this.doubleArray[0]; } @NoInline void writeToLongArray(long l) { this.longArray[0] = l; } @NoInline Long readFromLongArray() { return this.longArray[0]; } @NoInline void writeToObjectArray(Object o) { this.objectArray[0] = o; } private static int methodInstructionCount(String name, Class<?>... parameterTypes) throws SecurityException, NoSuchMethodException { Method m = thisClass.getDeclaredMethod(name, parameterTypes); RVMMethod internalMethod = java.lang.reflect.JikesRVMSupport.getMethodOf(m); internalMethod.compile(); CompiledMethod compiledMethod = internalMethod.getCurrentCompiledMethod(); // Subtract off prologue/epilogue size. This is approximate! // If you really care, count the instructions by hand! return compiledMethod.numberOfInstructions() - emptySize; } private static void printBarrierRequirement(String barrierType, boolean barrierProperty) { System.out.println("Plan requires " + barrierType + " barriers: " + barrierProperty); } private static void printSizeForMethod(String barrierType, int size) { System.out.println("Size of method with " + barrierType + " is " + size + unit); } private static void printHeader(String header) { System.out.println(" ------- " + header + " ------- "); } public static void main(String[] args) throws Exception { RVMClass barrierSize = JikesRVMSupport.getTypeForClass(BarrierSize.class).asClass(); barrierSize.prepareForFirstUse(); thisClass = Class.forName("BarrierSize"); emptySize = methodInstructionCount("emptyInstanceMethod", (Class[])null); Constraints constraints = Selected.Constraints.get(); printHeader("reference barriers"); int oFieldWriteSize = methodInstructionCount("writeToObjectField", Object.class); int oFieldReadSize = methodInstructionCount("readFromObjectField", (Class[])null); printBarrierRequirement("object reference write", constraints.needsObjectReferenceWriteBarrier()); printSizeForMethod("object reference write", oFieldWriteSize); printBarrierRequirement("object reference read", constraints.needsObjectReferenceReadBarrier()); printSizeForMethod("object reference read", oFieldReadSize); System.out.println(); printHeader("primitive barriers"); int booleanWriteSize = methodInstructionCount("writeToBooleanField", boolean.class); printBarrierRequirement("boolean write", constraints.needsBooleanWriteBarrier()); printSizeForMethod("boolean write", booleanWriteSize); int booleanReadSize = methodInstructionCount("readFromBooleanField", (Class[])null); printBarrierRequirement("boolean read", constraints.needsBooleanWriteBarrier()); printSizeForMethod("boolean read", booleanReadSize); int byteWriteSize = methodInstructionCount("writeToByteField", byte.class); printBarrierRequirement("byte write", constraints.needsByteWriteBarrier()); printSizeForMethod("byte write", byteWriteSize); int byteReadSize = methodInstructionCount("readFromByteField", (Class[])null); printBarrierRequirement("byte read", constraints.needsByteWriteBarrier()); printSizeForMethod("byte read", byteReadSize); int charWriteSize = methodInstructionCount("writeToCharField", char.class); printBarrierRequirement("char write", constraints.needsCharWriteBarrier()); printSizeForMethod("char write", charWriteSize); int charReadSize = methodInstructionCount("readFromCharField", (Class[])null); printBarrierRequirement("char read", constraints.needsCharWriteBarrier()); printSizeForMethod("char read", charReadSize); int shortWriteSize = methodInstructionCount("writeToShortField", short.class); printBarrierRequirement("short write", constraints.needsShortWriteBarrier()); printSizeForMethod("short write", shortWriteSize); int shortReadSize = methodInstructionCount("readFromShortField", (Class[])null); printBarrierRequirement("short read", constraints.needsShortWriteBarrier()); printSizeForMethod("short read", shortReadSize); int intWriteSize = methodInstructionCount("writeToIntField", int.class); printBarrierRequirement("int write", constraints.needsIntWriteBarrier()); printSizeForMethod("int write", intWriteSize); int intReadSize = methodInstructionCount("readFromIntField", (Class[])null); printBarrierRequirement("int read", constraints.needsIntWriteBarrier()); printSizeForMethod("int read", intReadSize); int floatWriteSize = methodInstructionCount("writeToFloatField", float.class); printBarrierRequirement("float write", constraints.needsFloatWriteBarrier()); printSizeForMethod("float write", floatWriteSize); int floatReadSize = methodInstructionCount("readFromFloatField", (Class[])null); printBarrierRequirement("float read", constraints.needsFloatWriteBarrier()); printSizeForMethod("float read", floatReadSize); int doubleWriteSize = methodInstructionCount("writeToDoubleField", double.class); printBarrierRequirement("double write", constraints.needsDoubleWriteBarrier()); printSizeForMethod("double write", doubleWriteSize); int doubleReadSize = methodInstructionCount("readFromDoubleField", (Class[])null); printBarrierRequirement("double read", constraints.needsDoubleWriteBarrier()); printSizeForMethod("double read", doubleReadSize); int longWriteSize = methodInstructionCount("writeToLongField", long.class); printBarrierRequirement("long write", constraints.needsLongWriteBarrier()); printSizeForMethod("long write", longWriteSize); int longReadSize = methodInstructionCount("readFromLongField", (Class[])null); printBarrierRequirement("long read", constraints.needsLongWriteBarrier()); printSizeForMethod("long read", longReadSize); System.out.println(); printHeader("primitive array store barriers"); int booleanArrayWriteSize = methodInstructionCount("writeToBooleanArray", boolean.class); printBarrierRequirement("boolean array write", constraints.needsBooleanWriteBarrier()); printSizeForMethod("boolean array write", booleanArrayWriteSize); int booleanArrayReadSize = methodInstructionCount("readFromBooleanArray", (Class[])null); printBarrierRequirement("boolean array read", constraints.needsBooleanWriteBarrier()); printSizeForMethod("boolean array read", booleanArrayReadSize); int byteArrayWriteSize = methodInstructionCount("writeToByteArray", byte.class); printBarrierRequirement("byte array write", constraints.needsByteWriteBarrier()); printSizeForMethod("byte array write", byteArrayWriteSize); int byteArrayReadSize = methodInstructionCount("readFromByteArray", (Class[])null); printBarrierRequirement("byte array read", constraints.needsByteWriteBarrier()); printSizeForMethod("byte array read", byteArrayReadSize); int charArrayWriteSize = methodInstructionCount("writeToCharArray", char.class); printBarrierRequirement("char array write", constraints.needsCharWriteBarrier()); printSizeForMethod("char array write", charArrayWriteSize); int charArrayReadSize = methodInstructionCount("readFromCharArray", (Class[])null); printBarrierRequirement("char array read", constraints.needsCharWriteBarrier()); printSizeForMethod("char array read", charArrayReadSize); int shortArrayWriteSize = methodInstructionCount("writeToShortArray", short.class); printBarrierRequirement("short array write", constraints.needsShortWriteBarrier()); printSizeForMethod("short array write", shortArrayWriteSize); int shortArrayReadSize = methodInstructionCount("readFromShortArray", (Class[])null); printBarrierRequirement("short array read", constraints.needsShortWriteBarrier()); printSizeForMethod("short array read", shortArrayReadSize); int intArrayWriteSize = methodInstructionCount("writeToIntArray", int.class); printBarrierRequirement("int array write", constraints.needsIntWriteBarrier()); printSizeForMethod("int array write", intArrayWriteSize); int intArrayReadSize = methodInstructionCount("readFromIntArray", (Class[])null); printBarrierRequirement("int array read", constraints.needsIntWriteBarrier()); printSizeForMethod("int array read", intArrayReadSize); int floatArrayWriteSize = methodInstructionCount("writeToFloatArray", float.class); printBarrierRequirement("float array write", constraints.needsFloatWriteBarrier()); printSizeForMethod("float array write", floatArrayWriteSize); int floatArrayReadSize = methodInstructionCount("readFromFloatArray", (Class[])null); printBarrierRequirement("float array read", constraints.needsFloatWriteBarrier()); printSizeForMethod("float array read", floatArrayReadSize); int doubleArrayWriteSize = methodInstructionCount("writeToDoubleArray", double.class); printBarrierRequirement("double array write", constraints.needsDoubleWriteBarrier()); printSizeForMethod("double array write", doubleArrayWriteSize); int doubleArrayReadSize = methodInstructionCount("readFromDoubleArray", (Class[])null); printBarrierRequirement("double array read", constraints.needsDoubleWriteBarrier()); printSizeForMethod("double array read", doubleArrayReadSize); int longArrayWriteSize = methodInstructionCount("writeToLongArray", long.class); printBarrierRequirement("long array write", constraints.needsLongWriteBarrier()); printSizeForMethod("long array write", longArrayWriteSize); int longArrayReadSize = methodInstructionCount("readFromLongArray", (Class[])null); printBarrierRequirement("long array read", constraints.needsLongWriteBarrier()); printSizeForMethod("long array read", longArrayReadSize); System.out.println(); printHeader("unboxed barriers"); int addressWriteSize = methodInstructionCount("writeToAddressField", Address.class); printBarrierRequirement("address write", constraints.needsAddressWriteBarrier()); printSizeForMethod("address write", addressWriteSize); int addressReadSize = methodInstructionCount("readFromAddressField", (Class[])null); printBarrierRequirement("address read", constraints.needsAddressWriteBarrier()); printSizeForMethod("address read", addressReadSize); int wordWriteSize = methodInstructionCount("writeToWordField", Word.class); printBarrierRequirement("word write", constraints.needsWordWriteBarrier()); printSizeForMethod("word write", wordWriteSize); int wordReadSize = methodInstructionCount("readFromWordField", (Class[])null); printBarrierRequirement("word read", constraints.needsWordWriteBarrier()); printSizeForMethod("word read", wordReadSize); int extentWriteSize = methodInstructionCount("writeToExtentField", Extent.class); printBarrierRequirement("extent write", constraints.needsExtentWriteBarrier()); printSizeForMethod("extent write", extentWriteSize); int extentReadSize = methodInstructionCount("readFromExtentField", (Class[])null); printBarrierRequirement("extent read", constraints.needsExtentWriteBarrier()); printSizeForMethod("extent read", extentReadSize); int offsetWriteSize = methodInstructionCount("writeToOffsetField", Offset.class); printBarrierRequirement("offset write", constraints.needsOffsetWriteBarrier()); printSizeForMethod("offset write", offsetWriteSize); int offsetReadSize = methodInstructionCount("readFromOffsetField", (Class[])null); printBarrierRequirement("offset read", constraints.needsOffsetWriteBarrier()); printSizeForMethod("offset read", offsetReadSize); } }