package vm; import gc.BitMap; import icecaptools.IcecapCVar; import icecaptools.IcecapCompileMe; import java.util.Iterator; import reflect.ClassInfo; import reflect.ObjectInfo; import reflect.StaticRefInfo; import thread.Thread; import thread.ThreadManager; import util.ReferenceIterator; public class HVMHeap implements Heap { @IcecapCVar private static int java_heap_size; private EmptyIterator emptyIterator; private ObjectReferenceIterator objectReferenceIterator; private ObjectInfo oi; private BitMap bitMap; private int blockSize; private int startAddress; private int heapSize; public HVMHeap() { emptyIterator = new EmptyIterator(); oi = new ObjectInfo(); blockSize = _getBlockSize(); startAddress = _getStartAddress(); heapSize = _getHeapSize(); objectReferenceIterator = new ObjectReferenceIterator(this); } public static Heap getHeap() { return new HVMHeap(); } @Override public int getMemoryLeftInProcent() { return 100; } private void unimplemented(String from) { Thread.print(from); while (true) ; } private static class EmptyIterator implements ReferenceIterator { @Override public boolean hasNext() { return false; } @Override public int next() { return -1; } } private static class StaticReferenceIterator implements ReferenceIterator { private int[] offsets; private short top; public StaticReferenceIterator(int[] offsets) { this.offsets = offsets; top = 0; } @Override public boolean hasNext() { return top < offsets.length; } @Override public int next() { int ref = StaticRefInfo.getReference(offsets[top]); top++; return ref; } } @Override public ReferenceIterator getStaticRef() { int[] offsets = StaticRefInfo.getOffsets(); return new StaticReferenceIterator(offsets); } private static class ThreadIterator { private Iterator<Thread> threads; private Thread nextThread; public ThreadIterator() { ThreadManager manager = Thread.getScheduler(); threads = manager.getThreads(); advance(); } private void advance() { if (threads.hasNext()) { Thread current = threads.next(); if (current != Thread.currentThread()) { nextThread = current; if (nextThread.getStack() == null) { advance(); } } else { advance(); } } else { nextThread = null; } } public boolean hasNext() { return nextThread != null; } public Thread next() { Thread t = nextThread; advance(); return t; } } private static class StackRefIterator implements ReferenceIterator { private int[] currentStack; private int currentIndex; private short top; private Thread currentThread; ThreadIterator threads; public StackRefIterator() { threads = new ThreadIterator(); currentStack = null; advance(); } private void advance() { if (currentStack == null) { if (threads.hasNext()) { currentThread = threads.next(); currentStack = currentThread.getStack(); currentIndex = 0; top = currentThread.getJavaStackTop(); } } else { currentIndex++; if (currentIndex == top) { currentIndex = currentThread.getCStackTop(); } else if (currentIndex == currentStack.length) { currentStack = null; advance(); } else { } } } @Override public boolean hasNext() { return currentStack != null; } @Override @IcecapCompileMe public int next() { int ref = currentStack[currentIndex]; advance(); return ref; } } @Override public ReferenceIterator getRefFromStacks() { return new StackRefIterator(); } @Override public boolean isRefAnObj(int ref) { oi.setAddress(ref); short classId = oi.classId; if (classId >= 0) { if (classId < ClassInfo.getNumberOfClasses()) { return true; } } return false; } @Override public boolean isRefAllocated(int ref) { return true; } private static class ObjectReferenceIterator implements ReferenceIterator { private ReferenceIterator referenceOffsets; private ObjectInfo oi; private int nextRef; private int startAddress; private int endAddress; ObjectReferenceIterator(Heap heap) { this.startAddress = heap.getStartAddress(); this.endAddress = startAddress + heap.getHeapSize(); } public void initObjectReferenceIterator(ReferenceIterator referenceOffsets, ObjectInfo oi) { this.referenceOffsets = referenceOffsets; this.oi = oi; nextRef = 0; } @Override public boolean hasNext() { if (nextRef != 0) { return true; } if (referenceOffsets.hasNext()) { nextRef = oi.getRef((short) referenceOffsets.next()); if ((nextRef >= startAddress) && (nextRef < endAddress)) { return true; } else { return hasNext(); } } else { return false; } } @Override public int next() { int ref = nextRef; nextRef = 0; return ref; } } @Override public ReferenceIterator getRefFromObj(int ref) { oi.setAddress(ref); short classId = oi.classId; if (classId >= 0) { if (classId < ClassInfo.getNumberOfClasses()) { ClassInfo cInfo = ClassInfo.getClassInfo(classId); ReferenceIterator referenceOffsets = cInfo.getReferenceOffsets(ref); if (referenceOffsets != null) { objectReferenceIterator.initObjectReferenceIterator(referenceOffsets, oi); return objectReferenceIterator; } } } return emptyIterator; } private int _getBlockSize() { return 4; } private int _getStartAddress() { return getHeapStart(); } private static native int getHeapStart(); @IcecapCompileMe private int _getHeapSize() { return java_heap_size; } @Override public void setBitMap(BitMap bitMap) { this.bitMap = bitMap; } @Override public int getBlockSize() { return blockSize; } @Override public int getStartAddress() { return startAddress; } @Override public int getHeapSize() { return heapSize; } }