// // 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.Arrays; import java.util.HashMap; import gov.nasa.jpf.Config; import gov.nasa.jpf.util.OATHash; /** * class that captures execution context consisting of executing thread and * pc's of ti's current StackFrames * * note that we pool (i.e. use static factory methods) in order to avoid * creating a myriad of redundant objects */ public class PreciseAllocationContext implements AllocationContext { // this is search global, i.e. does not have to be backtracked, but has to be // re-initialized between JPF runs (everything that changes hashCode) static private HashMap<PreciseAllocationContext,PreciseAllocationContext> ccCache = new HashMap<PreciseAllocationContext,PreciseAllocationContext>(); protected ThreadInfo ti; protected Instruction[] cc; protected int hashCode; // computed once during construction (from LookupContext) // a mutable ExecutionContext that is only used internally to avoid creating superfluous new instances to // find out if we already have seen a similar one private static class LookupContext extends PreciseAllocationContext { int stackDepth; LookupContext (){ cc = new Instruction[64]; } public int getStackDepth(){ return stackDepth; } } private static LookupContext lookupContext = new LookupContext(); static boolean init (Config config) { ccCache = new HashMap<PreciseAllocationContext,PreciseAllocationContext>(); return true; } public static synchronized PreciseAllocationContext getSUTExecutionContext (ClassInfo ci, ThreadInfo ti){ int stackDepth = ti.getStackDepth(); int h = 0; lookupContext.ti = ti; lookupContext.stackDepth = stackDepth; h = OATHash.hashMixin(h, ti.getId()); Instruction[] cc = lookupContext.cc; if (cc.length < stackDepth){ cc = new Instruction[stackDepth]; lookupContext.cc = cc; } int i=0; for (StackFrame f = ti.getTopFrame(); f != null; f = f.getPrevious()){ Instruction insn = f.getPC().getValue(); cc[i++] = insn; h = OATHash.hashMixin(h, insn.hashCode()); } h = OATHash.hashFinalize(h); lookupContext.hashCode = h; PreciseAllocationContext ec = ccCache.get(lookupContext); if (ec == null){ ec = new PreciseAllocationContext(ti, Arrays.copyOf(cc, stackDepth), h); ccCache.put(ec, ec); } return ec; } protected PreciseAllocationContext(){ // for subclassing } // we only construct this from a LookupContext, which already has all the data private PreciseAllocationContext (ThreadInfo ti, Instruction[] cc, int hashCode){ this.ti = ti; this.cc = cc; this.hashCode = hashCode; } public int hashCode(){ return hashCode; } public int getStackDepth(){ return cc.length; } public boolean equals (Object o){ if (o == this){ // identity shortcut return true; } else { if (o instanceof PreciseAllocationContext){ PreciseAllocationContext other = (PreciseAllocationContext)o; if (hashCode == other.hashCode){ // we might get here because of bin masking if (ti.getId() == other.ti.getId()) { Instruction[] ccOther = other.cc; if (cc.length == other.getStackDepth()) { for (int i = 0; i < cc.length; i++) { if (cc[i] != ccOther[i]) { return false; } } return true; } } } } return false; } } // for automatic field init allocations public AllocationContext extend (ClassInfo ci, int anchor) { return new PreciseAllocationContext(ti, cc, OATHash.hash(hashCode, ci.hashCode())); } /** mostly for debugging purposes */ public String toString(){ StringBuilder sb = new StringBuilder(); sb.append("(tid="); sb.append(ti.getId()); sb.append(",stack=["); for (int i=0; i<cc.length; i++){ if (i>0){ sb.append(','); } sb.append(cc[i]); } sb.append("])"); return sb.toString(); } }