// // Copyright (C) 2012 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.vm; import java.util.Iterator; import gov.nasa.jpf.Config; import gov.nasa.jpf.util.PSIntMap; import gov.nasa.jpf.util.Predicate; /** * heap implementation that uses a PersistentStagingMsbIntMap as the underlying container * * This is intended for large state spaces, to minimize store/restore costs. While those * are negligible for PersistentMaps, the per-change overhead is not since the container * has to duplicate the access path to the changed node on every modification. Efficiency * of PSIMHeap therefore relies on accessing objects in a consecutive pattern, i.e. * depends on clustered access. * * <2do> this should not be a GenericSGOIDHeap derived class since this includes * a number of non-persistent data structures (allocCounts, intern strings, pinDowns) that * are not persistent, i.e. still requires a memento that creates/restores snapshots of these * and hence looses a lot of the benefit we use a persistent map for * * NOTE - a reference value of 0 represents null and therefore is not a valid SGOID */ public class PSIMHeap extends GenericSGOIDHeap { /** * this sucks - we need a memento in order to store/restore allocCounts, internStrings and pinDownList */ static class PSIMMemento extends GenericSGOIDHeapMemento { PSIntMap<ElementInfo> eiSnap; PSIMMemento (PSIMHeap heap) { super(heap); heap.elementInfos.process(ElementInfo.storer); eiSnap = heap.elementInfos; // no need to transform anything, it's persistent } @Override public Heap restore(Heap inSitu) { super.restore( inSitu); PSIMHeap heap = (PSIMHeap) inSitu; heap.elementInfos = eiSnap; heap.elementInfos.process(ElementInfo.restorer); return heap; } } class SweepPredicate implements Predicate<ElementInfo>{ ThreadInfo ti; int tid; boolean isThreadTermination; protected void setContext() { ti = vm.getCurrentThread(); tid = ti.getId(); isThreadTermination = ti.isTerminated(); } @Override public boolean isTrue (ElementInfo ei) { if (ei.isMarked()){ // live object, prepare for next transition & gc cycle ei.setUnmarked(); ei.setAlive( liveBitValue); ei.cleanUp( PSIMHeap.this, isThreadTermination, tid); return false; } else { // object is no longer reachable // no finalizer support yet ei.processReleaseActions(); // <2do> still have to process finalizers here, which might make the object live again vm.notifyObjectReleased( ti, ei); return true; } } } SweepPredicate sweepPredicate; PSIntMap<ElementInfo> elementInfos; public PSIMHeap (Config config, KernelState ks) { super(config,ks); elementInfos = new PSIntMap<ElementInfo>(); sweepPredicate = new SweepPredicate(); } @Override public int size() { return elementInfos.size(); } @Override protected void set(int index, ElementInfo ei) { elementInfos = elementInfos.set(index, ei); } @Override public ElementInfo get(int ref) { if (ref <= 0) { return null; } else { return elementInfos.get(ref); } } @Override public ElementInfo getModifiable(int ref) { // <2do> this could probably use a specialized replaceValue() method if (ref <= 0) { return null; } else { ElementInfo ei = elementInfos.get(ref); if (ei != null && ei.isFrozen()) { ei = ei.deepClone(); // freshly created ElementInfos are not frozen, so we don't have to defreeze elementInfos = elementInfos.set(ref, ei); } return ei; } } @Override protected void remove(int ref) { elementInfos = elementInfos.remove(ref); } @Override protected void sweep () { sweepPredicate.setContext(); elementInfos = elementInfos.removeAllSatisfying( sweepPredicate); } @Override public Iterator<ElementInfo> iterator() { return elementInfos.iterator(); } @Override public Iterable<ElementInfo> liveObjects() { return elementInfos; } @Override public void resetVolatiles() { // we don't have any } @Override public void restoreVolatiles() { // we don't have any } @Override public Memento<Heap> getMemento(MementoFactory factory) { return factory.getMemento(this); } @Override public Memento<Heap> getMemento() { return new PSIMMemento(this); } }