private void markAndTraverse(final Oop obj) { // End of path if (obj == null) { return; } // Visited object if (!markBits.mark(obj)) { return; } // Root of work list for objects to be visited. A simple // stack for saving new objects to be analyzed. final Stack workList = new Stack(); // Next object to be visited. Oop next = obj; try { // Node in the list currently being visited. while (true) { final Oop currObj = next; // For the progress meter if (progressThunk != null) { visitedSize += currObj.getObjectSize(); double curFrac = (double) visitedSize / (double) usedSize; if (curFrac > lastNotificationFraction + MINIMUM_NOTIFICATION_FRACTION) { progressThunk.heapIterationFractionUpdate(curFrac); lastNotificationFraction = curFrac; } } if (DEBUG) { ++depth; printHeader(); System.err.println("ReversePtrs.markAndTraverse(" + currObj.getHandle() + ")"); } // Iterate over the references in the object. Do the // reverse pointer analysis for each reference. // Add the reference to the work-list so that its // references will be visited. currObj.iterate( new DefaultOopVisitor() { public void doOop(OopField field, boolean isVMField) { // "field" refers to a reference in currObj Oop next = field.getValue(currObj); rp.put(new LivenessPathElement(currObj, field.getID()), next); if ((next != null) && markBits.mark(next)) { workList.push(next); } } }, false); if (DEBUG) { --depth; } // Get the next object to visit. next = (Oop) workList.pop(); } } catch (EmptyStackException e) { // Done } catch (NullPointerException e) { System.err.println("ReversePtrs: WARNING: " + e + " during traversal"); } catch (Exception e) { System.err.println("ReversePtrs: WARNING: " + e + " during traversal"); } }
public double getValue(Oop obj) { return obj.getHandle().getJDoubleAt(getOffset()); }