2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.vm;
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.util.OATHash;
23 import java.util.Arrays;
24 import java.util.HashMap;
27 * class that captures execution context consisting of executing thread and
28 * pc's of ti's current StackFrames
30 * note that we pool (i.e. use static factory methods) in order to avoid
31 * creating a myriad of redundant objects
33 public class PreciseAllocationContext implements AllocationContext {
35 // this is search global, i.e. does not have to be backtracked, but has to be
36 // re-initialized between JPF runs (everything that changes hashCode)
37 static private HashMap<PreciseAllocationContext,PreciseAllocationContext> ccCache = new HashMap<PreciseAllocationContext,PreciseAllocationContext>();
39 protected ThreadInfo ti;
40 protected Instruction[] cc;
41 protected int hashCode; // computed once during construction (from LookupContext)
43 // a mutable ExecutionContext that is only used internally to avoid creating superfluous new instances to
44 // find out if we already have seen a similar one
45 private static class LookupContext extends PreciseAllocationContext {
49 cc = new Instruction[64];
53 public int getStackDepth(){
58 private static LookupContext lookupContext = new LookupContext();
60 static boolean init (Config config) {
61 ccCache = new HashMap<PreciseAllocationContext,PreciseAllocationContext>();
65 public static synchronized PreciseAllocationContext getSUTExecutionContext (ClassInfo ci, ThreadInfo ti){
66 int stackDepth = ti.getStackDepth();
69 lookupContext.ti = ti;
70 lookupContext.stackDepth = stackDepth;
72 h = OATHash.hashMixin(h, ti.getId());
74 Instruction[] cc = lookupContext.cc;
75 if (cc.length < stackDepth){
76 cc = new Instruction[stackDepth];
77 lookupContext.cc = cc;
81 for (StackFrame f = ti.getTopFrame(); f != null; f = f.getPrevious()){
82 Instruction insn = f.getPC();
84 h = OATHash.hashMixin(h, insn.hashCode());
86 h = OATHash.hashFinalize(h);
87 lookupContext.hashCode = h;
89 PreciseAllocationContext ec = ccCache.get(lookupContext);
91 ec = new PreciseAllocationContext(ti, Arrays.copyOf(cc, stackDepth), h);
98 protected PreciseAllocationContext(){
102 // we only construct this from a LookupContext, which already has all the data
103 private PreciseAllocationContext (ThreadInfo ti, Instruction[] cc, int hashCode){
106 this.hashCode = hashCode;
110 public int hashCode(){
114 public int getStackDepth(){
119 public boolean equals (Object o){
120 if (o == this){ // identity shortcut
124 if (o instanceof PreciseAllocationContext){
125 PreciseAllocationContext other = (PreciseAllocationContext)o;
126 if (hashCode == other.hashCode){ // we might get here because of bin masking
127 if (ti.getId() == other.ti.getId()) {
128 Instruction[] ccOther = other.cc;
129 if (cc.length == other.getStackDepth()) {
130 for (int i = 0; i < cc.length; i++) {
131 if (cc[i] != ccOther[i]) {
145 // for automatic field init allocations
147 public AllocationContext extend (ClassInfo ci, int anchor) {
148 return new PreciseAllocationContext(ti, cc, OATHash.hash(hashCode, ci.hashCode()));
151 /** mostly for debugging purposes */
153 public String toString(){
154 StringBuffer sb = new StringBuffer();
156 sb.append(ti.getId());
157 sb.append(",stack=[");
158 for (int i=0; i<cc.length; i++){
165 return sb.toString();