package reflect; import icecaptools.IcecapCVar; import icecaptools.IcecapCompileMe; import util.ReferenceIterator; import vm.Address; import vm.Address32Bit; import vm.Machine; import vm.HardwareObject; public abstract class ClassInfo extends HardwareObject { public ClassInfo(Address address) { super(address); } @IcecapCVar private static short NUMBEROFCLASSES_var; @IcecapCVar private static byte SUPPORTGC_var; private static class CachedClassInfo { ClassInfo cInfo; StringBuffer name; short[] references; } private static CachedClassInfo[] clazzes; private static ObjectReferenceOffsetIterator iterator; private static ReferencesArray ra; private static ArrayOverlay ao; private static ArrayReferenceOffsetIterator aroi; public short superClass; public byte dimension; public byte hasLock; public short dobjectSize; public short pobjectSize; @IcecapCompileMe protected static boolean gCSupported() { return SUPPORTGC_var > 0; } @IcecapCompileMe public static ClassInfo getClassInfoFromArchitecture(short index) { switch (Machine.architecture) { case Machine.X86_64: return new ClassInfoX86_64(index); default: return new ClassInfoX86_32(index); } } @IcecapCompileMe private static CachedClassInfo getCachedClassInfo(short index) { if (clazzes != null) { CachedClassInfo ccInfo = clazzes[index]; if (ccInfo != null) { return ccInfo; } else { ccInfo = new CachedClassInfo(); ccInfo.cInfo = getClassInfoFromArchitecture(index); clazzes[index] = ccInfo; } } else { clazzes = new CachedClassInfo[NUMBEROFCLASSES_var]; iterator = new ObjectReferenceOffsetIterator(); ra = new ReferencesArray(); ao = new ArrayOverlay(); aroi = new ArrayReferenceOffsetIterator(); } return getCachedClassInfo(index); } public static ClassInfo getClassInfo(short index) { CachedClassInfo ccInfo = getCachedClassInfo(index); return ccInfo.cInfo; } @IcecapCompileMe public static short getNumberOfClasses() { return NUMBEROFCLASSES_var; } public StringBuffer getName() { short index = getIndex(); CachedClassInfo ccInfo = clazzes[index]; StringBuffer buffer = ccInfo.name; if (buffer != null) { return buffer; } else { buffer = new StringBuffer(); CString cstring = new CString(getNameRef()); while (cstring.hasNext()) { buffer.append(cstring.next()); } ccInfo.name = buffer; return buffer; } } protected abstract short getIndex(); protected abstract Address getNameRef(); private static class ObjectReferenceOffsetIterator implements ReferenceIterator { private short[] offsets; private short top; public ObjectReferenceOffsetIterator() { } @Override public boolean hasNext() { return top < offsets.length; } @Override public int next() { int ref = offsets[top]; top++; return ref; } public void setOffsets(short[] offsets) { this.offsets = offsets; top = 0; } } private static class ArrayReferenceOffsetIterator implements ReferenceIterator { private short offset; private short length; public ArrayReferenceOffsetIterator() { } @Override public boolean hasNext() { return length > 0; } @Override public int next() { int next = offset; offset += 4; length--; return next; } public void reset(short length) { this.length = length; this.offset = 2; } } private static class ArrayOverlay extends HeapAccessor { @SuppressWarnings("unused") public short classid; public short length; public ArrayOverlay() { super(0); } public void setAddress(int ref) { ((Address32Bit)address).address = ref; } } public ReferenceIterator getReferenceOffsets(int ref) { short index = getIndex(); CachedClassInfo ccInfo = clazzes[index]; short[] references = ccInfo.references; if (references != null) { return newObjectReferenceOffsetIterator(references); } else { if (gCSupported()) { Address r = getReferencesRef(); if (!r.isNull()) { return getReferenceIterator(ccInfo, r); } else if (this.dimension == 1) // this is a 1 dimensional array { if (this.dobjectSize > 0) // of component type { ao.setAddress(ref); short length = ao.length; aroi.reset(length); return aroi; } } } return null; } } private ReferenceIterator getReferenceIterator(CachedClassInfo ccInfo, Address r) { short[] references; ra.setAddress(r); byte shortReferences; byte byteReferences; byte top = 0; shortReferences = ra.getShortReferences(); byteReferences = ra.getByteReferences(); references = new short[shortReferences + byteReferences]; for (byte i = 0; i < shortReferences; i++) { references[top++] = ra.nextShort(); } for (byte i = 0; i < byteReferences; i++) { short s = ra.nextShort(); references[top++] = (short) (s & 0xff); i++; if (i < byteReferences) { references[top++] = (short) (s >> 8); } } ccInfo.references = references; return newObjectReferenceOffsetIterator(references); } protected abstract Address getReferencesRef(); private ReferenceIterator newObjectReferenceOffsetIterator(short[] offsets) { iterator.setOffsets(offsets); return iterator; } public abstract Address getInterfacesRef(); }