Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

StaticArea.java

00001 package gov.nasa.arc.ase.jpf.jvm;
00002 
00003 import de.fub.bytecode.*;
00004 import de.fub.bytecode.classfile.*;
00005 import de.fub.bytecode.generic.*;
00006 import gov.nasa.arc.ase.jpf.*;
00007 import gov.nasa.arc.ase.util.Debug;
00008 import gov.nasa.arc.ase.util.HashData;
00009 import gov.nasa.arc.ase.util.HashPool;
00010 import java.io.*;
00011 import java.util.*;
00012 // ifdef RACE
00013 import gov.nasa.arc.ase.jpf.jvm.runtime.*;
00014 //#endif RACE
00015 
00016 public class StaticArea {
00017   Vector classes;           // value of static variables
00018   Vector objinfo;           // monitor associated with the class
00019 
00020 // ifdef NO_COMPRESSION
00021   // These variables are used to speed up recomputation
00022   // of the storing data keeping track of what is changed.
00023   BitSet classChanged;
00024   BitSet objinfoChanged;
00025   boolean anyClassChanged;
00026   boolean anyObjectInfoChanged;
00027 
00028   // These variables contain the indexes used by the storing
00029   // information in a sort of cache.
00030   int[] classData;
00031   int[] objinfoData;
00032 //#endif NO_COMPRESSION
00033 
00034   private static final int EXTRA_GROW_SIZE  = 10;
00035 
00036   // Creates a new (empty) static area.
00037   public StaticArea() {
00038     classes = new Vector();     // no classes loaded
00039     objinfo = new Vector();
00040 
00041 // ifdef NO_COMPRESSION
00042     // nothing has been changed yet
00043     classChanged = new BitSet();
00044     objinfoChanged = new BitSet();
00045     anyClassChanged = false;
00046     anyObjectInfoChanged = false;
00047 
00048     // Initially there are no classes and so the data is an empty array
00049     classData = new int[0];
00050     objinfoData = new int[0];
00051 //#endif NO_COMPRESSION
00052   }  
00053   // loads a new class
00054   //** warning: using heap symmetry classes don't have a new_id **//
00055   public int addClass(ClassInfo ci) {
00056     int index = indexFor(ci.getClassName());
00057 
00058 // ifdef DEBUG
00059 
00060 
00061 //#endif DEBUG
00062 
00063     if (index >= classes.size()) {
00064       classes.setSize(index + EXTRA_GROW_SIZE);
00065       objinfo.setSize(index + EXTRA_GROW_SIZE);
00066     }
00067 
00068     Fields fs = ci.createStaticFields();
00069     classes.setElementAt(fs, index);
00070 
00071     ci.reflection.setClassRef(index);
00072 
00073     objinfo.setElementAt(new ObjectInfo(), index);
00074 
00075 // ifdef NO_COMPRESSION
00076     // sets the flags so that the new class will be detected
00077     classChanged.set(index);
00078     objinfoChanged.set(index);
00079     anyClassChanged = true;
00080     anyObjectInfoChanged = true;
00081 //#endif NO_COMPRESSION
00082 
00083     return index;
00084   }  
00085 // ifdef NO_COMPRESSION
00086   // creates a clone of the class entry so that changes affect the current
00087   // state but not the pools. The entry will be indexed again later.
00088   private void cloneClass(int index) {
00089     // if it has been changed already it's already a clone!
00090     if(!classChanged.get(index)) {
00091       Object o = ((Fields)classes.get(index)).clone();
00092       classes.setElementAt(o, index);
00093       // we can't compute a new index now because more then one change at the
00094       // same time may happen so we just invalidate that index
00095       classChanged.set(index);
00096       anyClassChanged = true;
00097     }
00098   }  
00099   // creates a clone of the object info so that changes affect the current
00100   // state but not the pools. The entry will be indexed again later.
00101   private void cloneObjectInfo(int index) {
00102     // if it has been changed already it's already a clone!
00103     if(!objinfoChanged.get(index)) {
00104       Object o = ((ObjectInfo)objinfo.get(index)).clone();
00105       objinfo.setElementAt(o, index);
00106       // we can't compute new index now because more then one change at the
00107       // same time may happen so we just invalidate that index
00108       objinfoChanged.set(index);
00109       anyObjectInfoChanged = true;
00110     }
00111   }  
00112   // checks if a class has already been loaded
00113   public boolean containsClass(String classname) {
00114     return hasClass(classname);
00115   }  
00116   // returns the class information for a specific class
00117   public ClassInfo getClass(int classref) {
00118     return ((Fields)classes.get(classref)).getClassInfo();
00119   }  
00120   // these functions are used to hide the objinfo internal structure
00121   // and to make the pool system work. Every call to methods is filtered
00122   // thought these methods that can duplicate the object info if it
00123   // is going to be altered.
00124 
00125 // ifdef RACE
00126   // get the status of the lock for a class
00127   public LockStatus getLockStatus(String classname,String fieldname) {
00128     int index = indexOf(classname);
00129     return ((Fields)classes.get(index)).getLockStatus(fieldname);
00130   }  
00131 // ifdef NO_FASTBACKTRACK
00132 
00133 
00134 
00135 
00136 // ifdef NO_COMPRESSION
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 //#endif NO_COMPRESSION
00154 
00155 //#endif NO_FASTBACKTRACK
00156 
00157 // ifdef NO_COMPRESSION
00158   // Gets the storing information from the static area
00159   public int[] getStoringData() {
00160     // First we need to update the information in case there had been
00161     // any change
00162     update();
00163 
00164     // Mainly we need to create one big array from the two we have
00165     int cl = classData.length;      // how many classes
00166     int il = objinfoData.length;    // these numbers should be the same
00167 // ifdef DEBUG
00168 
00169 //#endif DEBUG
00170 
00171     // allocate enough space for both structures
00172     int[] data = new int[cl + il];
00173 
00174     // copy the information in the new array
00175     System.arraycopy(classData, 0, data, 0, cl);
00176     System.arraycopy(objinfoData, 0, data, cl, il);
00177 
00178     return data;
00179   }  
00180 //#endif MARK_N_SWEEP
00181 
00182   // ------------------------------------------
00183   //   access to the underlying fields object
00184   // ------------------------------------------
00185 
00186   public long getValue(int classref, String fieldname) {
00187     return ((Fields)classes.get(classref)).getValue(fieldname);
00188   }  
00189   public long getValue(String classname, String fieldname) {
00190     return ((Fields)classes.get(indexOf(classname))).getValue(fieldname);
00191   }  
00192   public int getVariableType(int classref, int index) {
00193     return ((Fields)classes.get(classref)).getClassInfo().getStaticFieldType(index);
00194   }  
00195   public int getVariableType(int classref, String fname) {
00196     return ((Fields)classes.get(classref)).getClassInfo().getStaticFieldType(fname);
00197   }  
00198 //#endif NO_COMPRESSION
00199 
00200   public int getVariableType(String classname, int index) {
00201     int classref = indexOf(classname);
00202     return ((Fields)classes.get(classref)).getClassInfo().getStaticFieldType(index);
00203   }  
00204   public int getVariableType(String classname, String fname) {
00205     int classref = indexOf(classname);
00206     return ((Fields)classes.get(classref)).getClassInfo().getStaticFieldType(fname);
00207   }  
00208   // checks if a class is present in the static area
00209   public boolean hasClass(String classname) {
00210 // ifdef NO_STATIC_SYMMETRY
00211     if(!StaticMap.hasEntry(classname)) return false;
00212 //#endif NO_STATIC_SYMMETRY
00213     int index = indexOf(classname);
00214     return (index >= 0 && index < classes.size() && classes.get(index) != null);
00215   }  
00216   public void hash(HashData hd) {
00217     for(int i = 0, l = classes.size(); i < l; i++) {
00218       Object o = classes.get(i);
00219       if(o != null) hd.add(o.hashCode());
00220     }
00221 
00222     for(int i = 0, l = objinfo.size(); i < l; i++) {
00223       Object o = objinfo.get(i);
00224       if(o != null) hd.add(o.hashCode());
00225     }
00226   }  
00227   public int hashCode() {
00228     HashData hd = new HashData();
00229 
00230     for(int i = 0, l = classes.size(); i < l; i++) {
00231       Object o = classes.get(i);
00232       if(o != null) hd.add(o.hashCode());
00233     }
00234 
00235     for(int i = 0, l = objinfo.size(); i < l; i++) {
00236       Object o = objinfo.get(i);
00237       if(o != null) hd.add(o.hashCode());
00238     }
00239 
00240     return hd.getValue();
00241   }  
00242   private int indexFor(String classname) {
00243 // ifdef NO_STATIC_SYMMETRY
00244     return StaticMap.addEntry(classname);
00245 //#else NO_STATIC_SYMMETRY
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 //#endif NO_STATIC_SYMMETRY
00255   }  
00256 // ifdef DEBUG
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 //#endif DEBUG
00269 
00270 // ifdef DEBUG
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 //#endif DEBUG
00283 //#endif NO_COMPRESSION
00284 
00285   // these functions are use to access the information stored in the classes
00286   // vector without having direct access so that if something is going to be
00287   // changed a copy is created first. This is necessary to make the pool system
00288   // work properly.
00289 
00290   // returns the identifier of a class given the name
00291   public int indexOf(String classname) {
00292 // ifdef NO_STATIC_SYMMETRY
00293     return StaticMap.getEntry(classname);
00294 //#else NO_STATIC_SYMMETRY
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 //#endif NO_STATIC_SYMMETRY
00306   }  
00307 // ifdef NO_COMPRESSION
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 //#endif NO_COMPRESSION
00392 
00393 // ifdef NO_FASTBACKTRACK
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 //#endif NO_FASTBACKTRACK
00419   public boolean isLoaded(String classname) {
00420     return StaticMap.hasEntry(classname);
00421   }  
00422   public void log() {
00423     Debug.println(Debug.MESSAGE, "SA");
00424     for(int i = 0; i < classes.size(); i++) {
00425       Fields f = (Fields)classes.get(i);
00426       if(f != null) {
00427     Debug.println(Debug.MESSAGE, "  @" + i + " " + f.getClassInfo().getClassName());
00428     f.log(i, false);
00429       }
00430     }
00431   }  
00432 // ifdef MARK_N_SWEEP
00433   public void mark(DynamicArea da) {
00434     int length = classes.size();
00435     for(int index = 0; index < length; index++) {
00436       Fields f = (Fields)classes.get(index);
00437       if(f != null) f.mark(da);
00438     }
00439   }  
00440 //#endif RACE
00441 
00442   // checks if a lock is possible
00443   public boolean monitorCheckLock(int classref, ThreadInfo th) {
00444     return ((ObjectInfo)objinfo.get(classref)).getMonitor().checkLock(th);
00445   }  
00446   // The followings functions are used only to access the previous one
00447   // using a class name instead of an index.
00448 
00449   public boolean monitorCheckLock(String className, ThreadInfo th) {
00450     return monitorCheckLock(indexOf(className), th);
00451   }  
00452   // checks if it can acquire the lock
00453   public boolean monitorCheckLockAfterNotified(int classref, ThreadInfo th) {
00454     return ((ObjectInfo)objinfo.get(classref)).getMonitor().checkLockAfterNotified(th);
00455   }  
00456   public boolean monitorCheckLockAfterNotified(String className, ThreadInfo th) {
00457     return monitorCheckLockAfterNotified(indexOf(className), th);
00458   }  
00459   // tries to acquire the lock on the monitor of the class
00460   public boolean monitorLock(int classref, ThreadInfo th) {
00461 // ifdef NO_COMPRESSION
00462     // needs to clone the object info because it is going to change
00463     cloneObjectInfo(classref);
00464 //#endif NO_COMPRESSION
00465     return ((ObjectInfo)objinfo.get(classref)).getMonitor().lock(th, new ClassRef(classref));
00466   }  
00467   public boolean monitorLock(String className, ThreadInfo th) {
00468     return monitorLock(indexOf(className), th);
00469   }  
00470   // tries to acquire the lock
00471   public boolean monitorLockAfterNotified(int classref, ThreadInfo th) {
00472 // ifdef NO_COMPRESSION
00473     // needs to clone the object info because it is going to change
00474     cloneObjectInfo(classref);
00475 //#endif NO_COMPRESSION
00476     return ((ObjectInfo)objinfo.get(classref)).getMonitor().lockAfterNotified(th, new ClassRef(classref));
00477   }  
00478   public boolean monitorLockAfterNotified(String className, ThreadInfo th) {
00479     return monitorLockAfterNotified(indexOf(className), th);
00480   }  
00481   // notifies the processes waiting
00482   public void monitorNotify(int classref, KernelState ks, Scheduler sch) {
00483 // ifdef NO_COMPRESSION
00484     // needs to clone the object info because it is going to change
00485     cloneObjectInfo(classref);
00486 //#endif NO_COMPRESSION
00487     ((ObjectInfo)objinfo.get(classref)).getMonitor().notify(ks, sch);
00488   }  
00489   public void monitorNotify(String className, KernelState ks, Scheduler sch) {
00490     monitorNotify(indexOf(className), ks, sch);
00491   }  
00492   // notifies all the threads waiting
00493   public void monitorNotifyAll(int classref, KernelState ks) {
00494 // ifdef NO_COMPRESSION
00495     // needs to clone the object info because it is going to change
00496     cloneObjectInfo(classref);
00497 //#endif NO_COMPRESSION
00498     ((ObjectInfo)objinfo.get(classref)).getMonitor().notifyAll(ks);
00499   }  
00500   public void monitorNotifyAll(String className, KernelState ks) {
00501     monitorNotifyAll(indexOf(className), ks);
00502   }  
00503   // releases the monitor
00504   public void monitorUnlock(int classref, ThreadInfo th) {
00505 // ifdef NO_COMPRESSION
00506     // needs to clone the object info because it is going to change
00507     cloneObjectInfo(classref);
00508 //#endif NO_COMPRESSION
00509     ((ObjectInfo)objinfo.get(classref)).getMonitor().unlock(th, new ClassRef(classref));
00510   }  
00511   public void monitorUnlock(String className, ThreadInfo th) {
00512     monitorUnlock(indexOf(className), th);
00513   }  
00514   // waits on the class monitor
00515   public void monitorWait(int classref, ThreadInfo th) {
00516 // ifdef NO_COMPRESSION
00517     // needs to clone the object info because it is going to change
00518     cloneObjectInfo(classref);
00519 //#endif NO_COMPRESSION
00520     ((ObjectInfo)objinfo.get(classref)).getMonitor().wait(th, new ClassRef(classref));
00521   }  
00522   public void monitorWait(String className, ThreadInfo th) {
00523     monitorWait(indexOf(className), th);
00524   }  
00525 //#endif NO_COMPRESSION
00526 
00527 // ifdef NO_COMPRESSION
00528   // this function recreated a static area from the storing data
00529   // tries to reuse as much as possible using the indexes we already have
00530   public void revertTo(int[] data) {
00531     // extracts the new class and object info data
00532     int len = data.length / 2;
00533 
00534     int[] nClassData = new int[len];
00535     int[] nObjinfoData = new int[len];
00536 
00537     System.arraycopy(data, 0, nClassData, 0, len);
00538     System.arraycopy(data, len, nObjinfoData, 0, len);
00539 
00540     int s = classData.length;
00541 
00542     if (s >= len) {
00543       // if there are less classes now then before
00544       // we just update the one in common
00545       for (int idx = 0; idx < len; idx++) {
00546     if(nClassData[idx] != classData[idx])
00547       classes.setElementAt(
00548           VirtualMachine.fieldsPool.getObject(nClassData[idx]),
00549           idx);
00550     if(nObjinfoData[idx] != objinfoData[idx])
00551       objinfo.setElementAt(
00552           VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00553           idx);
00554       }
00555       // then throw away the rest
00556       classes.setSize(len);
00557       objinfo.setSize(len);
00558     } else {
00559       // otherwise we update the one in common
00560       for (int idx = 0; idx < s; idx++) {
00561     if(nClassData[idx] != classData[idx])
00562       classes.setElementAt(
00563           VirtualMachine.fieldsPool.getObject(nClassData[idx]),
00564           idx);
00565     if(nObjinfoData[idx] != objinfoData[idx])
00566       objinfo.setElementAt(
00567           VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00568           idx);
00569       }
00570       classes.setSize(len);
00571       objinfo.setSize(len);
00572       // and we add the next ones (if any)
00573       for (int idx = s; idx < len; idx++) {
00574     classes.setElementAt(
00575         VirtualMachine.fieldsPool.getObject(nClassData[idx]),
00576         idx);
00577     objinfo.setElementAt(
00578         VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00579         idx);
00580       }
00581     }
00582     classData = nClassData;
00583     objinfoData = nObjinfoData;
00584   }  
00585   public void setValue(int classref, String fieldname, long value) {
00586 // ifdef NO_COMPRESSION
00587     cloneClass(classref);
00588 //#endif NO_COMPRESSION
00589     ((Fields)classes.get(classref)).setValue(fieldname, value);
00590   }  
00591   public void setValue(String classname, String fieldname, long value) {
00592 // ifdef NO_COMPRESSION
00593     cloneClass(indexOf(classname));
00594 //#endif NO_COMPRESSION
00595     ((Fields)classes.get(indexOf(classname))).setValue(fieldname, value);
00596   }  
00597   // The following group of functions are used when something is changed
00598   // all the data structure must be updated but we can do it in a smart
00599   // way and avoid updating what's not changed.
00600   private void update() {
00601     if (anyClassChanged) {
00602       // Updates classData
00603       updateClasses();
00604 
00605       // Clears all the flags because no updates are necessary anymore
00606       classChanged = new BitSet();
00607       anyClassChanged = false;
00608     }
00609 
00610     if (anyObjectInfoChanged) {
00611       // Updates objinfoData
00612       updateObjectInfos();
00613 
00614       // Clears all the flags because no updates are necessary anymore
00615       objinfoChanged = new BitSet();
00616       anyObjectInfoChanged = false;
00617     }
00618   }  
00619   // updates the classes
00620   private void updateClasses() {
00621     // we have to keep in mind that there could be empty spaces
00622     // due to unloaded classes or classes loaded in a different
00623     // order and to when classes are added or removed
00624     int size = classes.size();
00625     int old_size = classData.length;
00626     int actual_size = -1;   // there could be empty slots at the end!
00627 
00628 // ifdef DEBUG
00629 
00630 
00631 //#endif DEBUG
00632 
00633     // first we create an array as long as the classes vector
00634     int[] data = new int[size];
00635     for(int i = 0; i < size; i++) {
00636       // for each entry we have to test a couple of conditions
00637       Fields o = (Fields)classes.get(i);
00638       if(o != null) {
00639     // if the entry at index i it's not null then
00640     // the actual size it's at least i.
00641     actual_size = i;
00642 
00643     if (classChanged.get(i)) {
00644       // if it's changed then we have to check the pool
00645       HashPool.PoolEntry e = VirtualMachine.fieldsPool.getEntry(o);
00646       // set the reference so that we keep just one copy if it was in the
00647       // pool already
00648       classes.setElementAt(e.getObject(), i);
00649       // set the correct index we got from the pool
00650       data[i] = e.getIndex();
00651     } else {
00652       // if it's not changed it means it was already there
00653       // so we get the old value from the old class data
00654 // ifdef DEBUG
00655 
00656 //#endif DEBUG
00657       data[i] = classData[i];
00658     }
00659       } else {
00660     // if the entry is null it will be a 0 in the data
00661     data[i] = 0;
00662       }
00663     }
00664 
00665     // now we have to put the information in the class data avoid to
00666     // store all the zeros at the end (that are unuseful).
00667     classData = new int[++actual_size];
00668     System.arraycopy(data, 0, classData, 0, actual_size);
00669   }  
00670   // updates the object infos
00671   private void updateObjectInfos() {
00672     // we have to keep in mind that there could be empty spaces
00673     // due to unloaded classes or classes loaded in a different
00674     // order and to when classes are added or removed
00675     int size = objinfo.size();
00676     int old_size = objinfoData.length;
00677     int actual_size = -1;   // there could be empty slots at the end!
00678 
00679 // ifdef DEBUG
00680 
00681 
00682 //#endif DEBUG
00683 
00684     // first we create an array as long as the object info vector
00685     int[] data = new int[size];
00686     for(int i = 0; i < size; i++) {
00687       // for each entry we have to test a couple of conditions
00688       ObjectInfo o = (ObjectInfo)objinfo.get(i);
00689       if(o != null) {
00690     // if the entry at index i it's not null then
00691     // the actual size it's at least i.
00692     actual_size = i;
00693 
00694     if (objinfoChanged.get(i)) {
00695       // if it's changed then we have to check the pool
00696       HashPool.PoolEntry e = VirtualMachine.objectInfoPool.getEntry(o);
00697       // set the reference so that we keep just one copy if it was in the
00698       // pool already
00699       objinfo.setElementAt(e.getObject(), i);
00700       // set the correct index we got from the pool
00701       data[i] = e.getIndex();
00702     } else {
00703       // if it's not changed it means it was already there
00704       // so we get the old value from the old object info data
00705 // ifdef DEBUG
00706 
00707 //#endif DEBUG
00708       data[i] = objinfoData[i];
00709     }
00710       } else {
00711     // if the entry is null it will be a 0 in the data
00712     data[i] = 0;
00713       }
00714     }
00715 
00716     // now we have to put the information in the object info data avoid to
00717     // store all the zeros at the end (that are unuseful).
00718     objinfoData = new int[++actual_size];
00719     System.arraycopy(data, 0, objinfoData, 0, actual_size);
00720   }  
00721 }

Generated at Thu Feb 7 06:55:51 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001