Mercurial > hg > Members > kono > jpf-core
view src/main/gov/nasa/jpf/vm/PSIMHeap.java @ 23:db918c531e6d
streamlined class init, which was a mixed case of registerClass()/initializeClass() and pushRequiredClinits(). Now it is a single initializeClass(ti) method which combines the previous initializeClass(), pushRequiredClinits() and pushClinit() methods. The reason for combining these is the forthcoming replacement of separately locked clinits from different DirectCallStackFrames with a single synthetic frame that calls clinits from nested synchronized blocks. This is required to model hotspot, which does cause deadlocks with concurrent init of classes that cause subclass init during their clinit executions.
author | Peter Mehlitz <Peter.C.Mehlitz@nasa.gov> |
---|---|
date | Wed, 15 Apr 2015 22:40:21 -0700 |
parents | 61d41facf527 |
children |
line wrap: on
line source
/* * Copyright (C) 2014, United States Government, as represented by the * Administrator of the National Aeronautics and Space Administration. * All rights reserved. * * The Java Pathfinder core (jpf-core) platform is licensed under the * Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package gov.nasa.jpf.vm; import gov.nasa.jpf.Config; import gov.nasa.jpf.util.PSIntMap; import gov.nasa.jpf.util.Predicate; import java.util.Iterator; /** * 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); } }