Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / vm / BoxObjectCacheManager.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 /**
21  * @author Nastaran Shafiei <nastaran.shafiei@gmail.com>
22  * 
23  *         Cache management implementation for the types Boolean, Byte,
24  *         Character, Short, Integer, Long. The references to the caches are in
25  *         the class classes/gov/nasa/jpf/BoxObjectCaches.
26  * 
27  *         All the caches, except Boolean, are initialized on the first
28  *         invocation of valueOf(), and they all exempt from garbage collection.
29  * 
30  *         NOTE: All classes obtained from getResolvedClassInfo in
31  *         BoxObjectCacheManager are safe, and there is no need to check if they
32  *         are initialized. The wrappers and BoxObjectCaches are initialized in
33  *         VM.intialize(), and there are no clinit for array classes.
34  *         
35  *         NOTE: the initXCache allocations are system allocations, whereas the
36  *         valueOfX() allocations are rooted in SUT code
37  */
38 public class BoxObjectCacheManager {
39   private static final String MODEL_CLASS = "gov.nasa.jpf.BoxObjectCaches";
40   private static final int ANCHOR = BoxObjectCacheManager.class.getName().hashCode();  
41   
42   // cache default bounds
43   private static int defLow = -128;
44   private static int defHigh = 127;
45
46   public static int valueOfBoolean (ThreadInfo ti, boolean b) {
47     ClassInfo cls = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Boolean");
48
49     int boolObj;
50     if (b) {
51       boolObj = cls.getStaticElementInfo().getReferenceField("TRUE");
52     } else {
53       boolObj = cls.getStaticElementInfo().getReferenceField("FALSE");
54     }
55
56     return boolObj;
57   }
58
59   // Byte cache bounds
60   private static byte byteLow;
61   private static byte byteHigh;
62
63   public static int initByteCache (ThreadInfo ti) {
64     byteLow = (byte) ti.getVM().getConfig().getInt("vm.cache.low_byte", defLow);
65     byteHigh = (byte) ti.getVM().getConfig().getInt("vm.cache.high_byte", defHigh);
66     int n = (byteHigh - byteLow) + 1;
67     
68     Heap heap = ti.getHeap();
69     ElementInfo eiArray = heap.newSystemArray("Ljava/lang/Byte", n, ti, ANCHOR);
70     int arrayRef = eiArray.getObjectRef();
71
72     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Byte");
73     byte val = byteLow;
74     for (int i = 0; i < n; i++) {
75       ElementInfo eiByte = heap.newSystemObject(ci, ti, ANCHOR);
76       eiByte.setByteField("value", val++);
77       eiArray.setReferenceElement(i, eiByte.getObjectRef());
78     }
79
80     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
81     cacheClass.getModifiableStaticElementInfo().setReferenceField("byteCache", arrayRef);
82     return arrayRef;
83   }
84
85   public static int valueOfByte (ThreadInfo ti, byte b) {
86     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
87     int byteCache = cacheClass.getStaticElementInfo().getReferenceField("byteCache");
88
89     if (byteCache == MJIEnv.NULL) { // initializing the cache on demand
90       byteCache = initByteCache(ti);
91     }
92
93     if (b >= byteLow && b <= byteHigh) { return ti.getElementInfo(byteCache).getReferenceElement(b - byteLow); }
94
95     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Byte");
96     ElementInfo eiByte = ti.getHeap().newObject(ci, ti);
97     eiByte.setByteField("value", b);
98     return eiByte.getObjectRef();
99   }
100
101   // Character cache bound
102   private static int charHigh;
103
104   public static int initCharCache (ThreadInfo ti) {
105     charHigh = ti.getVM().getConfig().getInt("vm.cache.high_char", defHigh);
106     int n = charHigh + 1;
107     
108     Heap heap = ti.getHeap();    
109     ElementInfo eiArray = heap.newSystemArray("Ljava/lang/Character", n, ti, ANCHOR);
110     int arrayRef = eiArray.getObjectRef();
111
112     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Character");
113     for (int i = 0; i < n; i++) {
114       ElementInfo eiChar = heap.newSystemObject(ci, ti, ANCHOR);
115       eiChar.setCharField("value", (char) i);
116       eiArray.setReferenceElement(i, eiChar.getObjectRef());
117     }
118
119     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
120     cacheClass.getModifiableStaticElementInfo().setReferenceField("charCache", arrayRef);
121     return arrayRef;
122   }
123
124   public static int valueOfCharacter (ThreadInfo ti, char c) {
125     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
126     int charCache = cacheClass.getStaticElementInfo().getReferenceField("charCache");
127
128     if (charCache == MJIEnv.NULL) { // initializing the cache on demand
129       charCache = initCharCache(ti);
130     }
131
132     if (c >= 0 && c <= charHigh) { return ti.getElementInfo(charCache).getReferenceElement(c); }
133
134     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Character");
135     ElementInfo eiChar = ti.getHeap().newObject(ci, ti);
136     eiChar.setCharField("value", c);
137     return eiChar.getObjectRef();
138   }
139
140   // Short cache bounds
141   private static short shortLow;
142
143   private static short shortHigh;
144
145   public static int initShortCache (ThreadInfo ti) {
146     shortLow = (short) ti.getVM().getConfig().getInt("vm.cache.low_short", defLow);
147     shortHigh = (short) ti.getVM().getConfig().getInt("vm.cache.high_short", defHigh);
148     int n = (shortHigh - shortLow) + 1;
149     
150     Heap heap = ti.getHeap();    
151     ElementInfo eiArray = heap.newSystemArray("Ljava/lang/Short", n, ti, ANCHOR);
152     int arrayRef = eiArray.getObjectRef();
153
154     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Short");
155     short val = shortLow;
156     for (int i = 0; i < n; i++) {
157       ElementInfo eiShort = heap.newSystemObject(ci, ti, ANCHOR);
158       eiShort.setShortField("value", val++);
159       eiArray.setReferenceElement(i, eiShort.getObjectRef());
160     }
161
162     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
163     cacheClass.getModifiableStaticElementInfo().setReferenceField("shortCache", arrayRef);
164     return arrayRef;
165   }
166
167   public static int valueOfShort (ThreadInfo ti, short s) {
168     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
169     int shortCache = cacheClass.getStaticElementInfo().getReferenceField("shortCache");
170
171     if (shortCache == MJIEnv.NULL) { // initializing the cache on demand
172       shortCache = initShortCache(ti);
173     }
174
175     if (s >= shortLow && s <= shortHigh) { return ti.getElementInfo(shortCache).getReferenceElement(s - shortLow); }
176
177     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Short");
178     ElementInfo eiShort = ti.getHeap().newObject(ci, ti);
179     eiShort.setShortField("value", s);
180     return eiShort.getObjectRef();
181   }
182
183   // Integer cache bounds
184   private static int intLow;
185   private static int intHigh;
186
187   public static int initIntCache (ThreadInfo ti) {
188     intLow = ti.getVM().getConfig().getInt("vm.cache.low_int", defLow);
189     intHigh = ti.getVM().getConfig().getInt("vm.cache.high_int", defHigh);
190     int n = (intHigh - intLow) + 1;
191     
192     Heap heap = ti.getHeap();    
193     ElementInfo eiArray = heap.newSystemArray("Ljava/lang/Integer", n, ti, ANCHOR);
194     int arrayRef = eiArray.getObjectRef();
195
196     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Integer");
197     for (int i = 0; i < n; i++) {
198       ElementInfo eiInteger = heap.newSystemObject(ci, ti, ANCHOR);
199       eiInteger.setIntField("value", i + intLow);
200       eiArray.setReferenceElement(i, eiInteger.getObjectRef());
201     }
202
203     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
204     cacheClass.getModifiableStaticElementInfo().setReferenceField("intCache", arrayRef);
205     return arrayRef;
206   }
207
208   public static int valueOfInteger (ThreadInfo ti, int i) {
209     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
210     int intCache = cacheClass.getStaticElementInfo().getReferenceField("intCache");
211
212     if (intCache == MJIEnv.NULL) { // initializing the cache on demand
213       intCache = initIntCache(ti);
214     }
215
216     if (i >= intLow && i <= intHigh) { return ti.getElementInfo(intCache).getReferenceElement(i - intLow); }
217
218     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Integer");
219     ElementInfo eiInteger = ti.getHeap().newObject(ci, ti);
220     eiInteger.setIntField("value", i);
221     return eiInteger.getObjectRef();
222   }
223
224   // Long cache bounds
225   private static int longLow;
226   private static int longHigh;
227
228   public static int initLongCache (ThreadInfo ti) {
229     longLow = ti.getVM().getConfig().getInt("vm.cache.low_long", defLow);
230     longHigh = ti.getVM().getConfig().getInt("vm.cache.high_long", defHigh);
231     int n = (longHigh - longLow) + 1;
232     
233     Heap heap = ti.getHeap();    
234     ElementInfo eiArray = heap.newSystemArray("Ljava/lang/Long", n, ti, ANCHOR);
235     int arrayRef = eiArray.getObjectRef();
236
237     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Long");
238     for (int i = 0; i < n; i++) {
239       ElementInfo eiLong = heap.newSystemObject(ci, ti, ANCHOR);
240       eiLong.setLongField("value", i + longLow);
241       eiArray.setReferenceElement(i, eiLong.getObjectRef());
242     }
243
244     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
245     cacheClass.getModifiableStaticElementInfo().setReferenceField("longCache", arrayRef);
246     return arrayRef;
247   }
248
249   public static int valueOfLong (ThreadInfo ti, long l) {
250     ClassInfo cacheClass = ClassLoaderInfo.getSystemResolvedClassInfo(MODEL_CLASS);
251     int longCache = cacheClass.getStaticElementInfo().getReferenceField("longCache");
252
253     if (longCache == MJIEnv.NULL) { // initializing the cache on demand
254       longCache = initLongCache(ti);
255     }
256
257     if (l >= longLow && l <= longHigh) { return ti.getElementInfo(longCache).getReferenceElement((int) l - longLow); }
258
259     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Long");
260     ElementInfo eiLong = ti.getHeap().newObject(ci, ti);
261     eiLong.setLongField("value", l);
262     return eiLong.getObjectRef();
263   }
264 }