Fixes default method resolution (#159)
[jpf-core.git] / src / main / gov / nasa / jpf / vm / PreciseAllocationContext.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
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
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
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.
17  */
18 package gov.nasa.jpf.vm;
19
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.util.OATHash;
22
23 import java.util.Arrays;
24 import java.util.HashMap;
25
26 /**
27  * class that captures execution context consisting of executing thread and 
28  * pc's of ti's current StackFrames
29  * 
30  * note that we pool (i.e. use static factory methods) in order to avoid
31  * creating a myriad of redundant objects
32  */
33 public class PreciseAllocationContext implements AllocationContext {
34
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>();
38   
39   protected ThreadInfo ti;
40   protected Instruction[] cc;
41   protected int hashCode; // computed once during construction (from LookupContext)
42   
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 {
46     int stackDepth;
47     
48     LookupContext (){
49       cc = new Instruction[64];
50     }
51     
52     @Override
53         public int getStackDepth(){
54       return stackDepth;
55     }    
56   }
57   
58   private static LookupContext lookupContext = new LookupContext();
59   
60   static boolean init (Config config) {
61     ccCache = new HashMap<PreciseAllocationContext,PreciseAllocationContext>();
62     return true;
63   }
64   
65   public static synchronized PreciseAllocationContext getSUTExecutionContext (ClassInfo ci, ThreadInfo ti){
66     int stackDepth = ti.getStackDepth();
67     int h = 0;
68     
69     lookupContext.ti = ti;
70     lookupContext.stackDepth = stackDepth;
71     
72     h = OATHash.hashMixin(h, ti.getId());
73     
74     Instruction[] cc = lookupContext.cc;
75     if (cc.length < stackDepth){
76       cc = new Instruction[stackDepth];
77       lookupContext.cc = cc;
78     }
79
80     int i=0;
81     for (StackFrame f = ti.getTopFrame(); f != null; f = f.getPrevious()){
82       Instruction insn = f.getPC();
83       cc[i++] = insn;
84       h = OATHash.hashMixin(h, insn.hashCode());
85     }
86     h = OATHash.hashFinalize(h);
87     lookupContext.hashCode = h;
88     
89     PreciseAllocationContext ec = ccCache.get(lookupContext);
90     if (ec == null){
91       ec = new PreciseAllocationContext(ti, Arrays.copyOf(cc, stackDepth), h);
92       ccCache.put(ec, ec);
93     }
94     
95     return ec;
96   }
97   
98   protected PreciseAllocationContext(){
99     // for subclassing
100   }
101   
102   // we only construct this from a LookupContext, which already has all the data
103   private PreciseAllocationContext (ThreadInfo ti, Instruction[] cc, int hashCode){
104     this.ti = ti;
105     this.cc = cc;
106     this.hashCode = hashCode;
107   }
108   
109   @Override
110   public int hashCode(){
111     return hashCode;
112   }
113   
114   public int getStackDepth(){
115     return cc.length;
116   }
117     
118   @Override
119   public boolean equals (Object o){
120     if (o == this){ // identity shortcut
121       return true;
122       
123     } else {
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]) {
132                   return false;
133                 }
134               }
135               return true;
136             }
137           }
138         }
139       }
140       
141       return false;
142     }
143   }
144   
145   // for automatic field init allocations
146   @Override
147   public AllocationContext extend (ClassInfo ci, int anchor) {
148     return new PreciseAllocationContext(ti, cc, OATHash.hash(hashCode, ci.hashCode()));
149   }
150   
151   /** mostly for debugging purposes */
152   @Override
153   public String toString(){
154     StringBuffer sb = new StringBuffer();
155     sb.append("(tid=");
156     sb.append(ti.getId());
157     sb.append(",stack=[");
158     for (int i=0; i<cc.length; i++){
159       if (i>0){
160         sb.append(',');
161       }
162       sb.append(cc[i]);
163     }
164     sb.append("])");
165     return sb.toString();
166   }
167 }