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

DynamicArea.java

00001 package gov.nasa.arc.ase.jpf.jvm;
00002 
00003 import de.fub.bytecode.*;
00004 import de.fub.bytecode.classfile.*;
00005 import gov.nasa.arc.ase.util.PoolObject;
00006 import de.fub.bytecode.generic.*;
00007 import gov.nasa.arc.ase.jpf.*;
00008 import gov.nasa.arc.ase.jpf.jvm.reflection.Reflection;
00009 import gov.nasa.arc.ase.util.Debug;
00010 import gov.nasa.arc.ase.util.HashData;
00011 import gov.nasa.arc.ase.util.HashPool;
00012 import java.io.*;
00013 import java.util.*;
00014 // ifdef RACE
00015 import gov.nasa.arc.ase.jpf.jvm.runtime.*;
00016 //#endif RACE
00017 
00018 public class DynamicArea {
00019   static BitSet ZERO = new BitSet();
00020   Vector objects;           // value of the object variables
00021   Vector objinfo;           // monitor associated with the object
00022 
00023 // ifdef NO_COMPRESSION
00024   // These variables are used to speed up recomputation
00025   // of the storing data keeping track of what is changed
00026   BitSet objectChanged;
00027   BitSet objinfoChanged;
00028   private boolean anyObjectChanged;
00029   private boolean anyObjectInfoChanged;
00030   
00031   // These variables contain the indexes used by the storing
00032   // information in a sort of cache.
00033   int[] objectData;
00034   int[] objinfoData;
00035 //#endif RACE
00036 
00037   // this is the main entry for the garbage collection
00038   // when garbage collection is switched on this function
00039   // is called to free unused objects.
00040   // the current implementation is a mark and sweep algorithm.
00041 // ifdef MARK_N_SWEEP
00042   public BitSet isUsed = null;
00043 
00044 //#endif NO_COMPRESSION
00045 
00046   // Creates a new (empty) dynamic area
00047   public DynamicArea() {
00048     objects = new Vector();     // no object created yet
00049     objinfo = new Vector();
00050 
00051 // ifdef NO_COMPRESSION
00052     // nothing has been changed yet
00053     objectChanged = new BitSet();
00054     objinfoChanged = new BitSet();
00055     anyObjectChanged = false;
00056     anyObjectInfoChanged = false;
00057 //#endif NO_COMPRESSION
00058 
00059 // ifdef NO_COMPRESSION
00060     // Initially there are no objects and so the data is an empty array
00061     objectData = new int[0];
00062     objinfoData = new int[0];
00063 //#endif NO_COMPRESSION
00064   }  
00065   //** warning: this is not necesserely the length of an array **//
00066   // returns the length of an array (or the number of field of an object)
00067   public int arraylength(int objref) {
00068     return ((Fields)objects.get(objref)).getVariables().length;
00069   }  
00070 //#endif MARK_N_SWEEP
00071 
00072 // ifdef NO_COMPRESSION
00073   // this function creates a copy of an object entry in case it needs to
00074   // be modified
00075   private void cloneObject(int index) {
00076     // if it has already been cloned we don't need to do it again
00077     if(!objectChanged.get(index)) {
00078       Object o = ((Fields)objects.get(index)).clone();
00079       objects.setElementAt(o, index);
00080 
00081       // we just invalidate the entry because the same fields can be changed
00082       // more then once in a single step
00083       objectChanged.set(index);
00084       anyObjectChanged = true;
00085     }
00086   }  
00087   // creates a copy of the object info entry
00088   private void cloneObjectInfo(int index) {
00089     // if it has already been cloned there's no need to clone it again
00090     if(!objinfoChanged.get(index)) {
00091       Object o = ((ObjectInfo)objinfo.get(index)).clone();
00092       objinfo.setElementAt(o, index);
00093 
00094       // invalidate the current entry so that the index will be recalculated
00095       objinfoChanged.set(index);
00096       anyObjectInfoChanged = true;
00097     }
00098   }  
00099   // converts an array object into an array of integers
00100   public long[] convert2Array(int objref) {
00101     //** warning: does not check if this is really an array
00102     int length = arraylength(objref);       // length of the array
00103 
00104 // ifdef DEBUG
00105 
00106 //#endif DEBUG
00107 
00108     // creates an array and fills it with data
00109     long[] result = new long[length];
00110     for(int i = 0; i < length; i++) {
00111       result[i] = getValue(objref, i);
00112 // ifdef DEBUG
00113 
00114 //#endif DEBUG
00115     }
00116 
00117     // returns the array (for a normal class would be the list of field values
00118     return result;
00119   }  
00120   // even if the object is a string, it is not stored in the system as a string
00121   // like for the other primitive types. it is necessary so to have a function
00122   // to convert between the two
00123   public String convert2String(int objref) {
00124     // object reference of the array containing the characters
00125     int value = (int)getValue(objref, "value");
00126   
00127     // number of characters in the string
00128     int length = (int)getValue(objref, "count");
00129 
00130 // ifdef DEBUG
00131 
00132 //#endif DEBUG
00133 
00134     // get a new empty string and then adds one character at the time
00135     StringBuffer sb = new StringBuffer();
00136 
00137     for(int i = 0; i < length; i++)
00138       sb.append((char)getValue(value, i));
00139 
00140 // ifdef DEBUG
00141 
00142 //#endif DEBUG
00143 
00144     // returns the string object corresponding to the one we internally have
00145     // this makes possible for function that know about the internal
00146     // rapresentation of strings to work, but gives us a way to use normal
00147     // string functions on string objects.
00148     return sb.toString();
00149   }  
00150   public void gc(KernelState ks) {
00151     List o = objects;
00152 
00153     int length = o.size() - 1;
00154     while(length > 0 && o.get(length) == null)
00155       length--;
00156     length++;
00157 
00158     isUsed = new BitSet(length);
00159 
00160     List threads = ks.threads;
00161     int nthreads = threads.size();
00162 
00163 // ifdef DEBUG
00164 
00165 //#endif DEBUG
00166     for(int i = 0; i < nthreads; i++) {
00167       ThreadInfo th = (ThreadInfo)threads.get(i);
00168       th.mark(this);
00169     }
00170     ks.static_area.mark(this);
00171 // ifdef DEBUG
00172 
00173 
00174 //#endif DEBUG
00175 
00176     int count = 0;
00177 
00178     for(int i = 0; i < length; i++)
00179       if(!isUsed.get(i)) {
00180     if(objects.get(i) != null) {
00181       count++;
00182 // ifdef DEBUG
00183 
00184 //#endif DEBUG
00185 
00186       objects.setElementAt(null, i);
00187       objinfo.setElementAt(null, i);
00188       anyObjectChanged = true;
00189       anyObjectInfoChanged = true;
00190       objectChanged.set(i);
00191       objinfoChanged.set(i);
00192     }
00193 // ifdef DEBUG
00194 
00195 
00196 //#endif DEBUG
00197       }
00198 // ifdef DEBUG
00199 
00200 
00201 
00202 
00203 
00204 //#endif DEBUG
00205 
00206     Runner.GCs += count;
00207 
00208     isUsed = null;
00209   }  
00210   // get the class information for an object
00211   public ClassInfo getClass(int objref) {
00212     return ((Fields)objects.get(objref)).getClassInfo();
00213   }  
00214   public LockStatus getLockStatus(int objref) {
00215     return ((Fields)objects.get(objref)).getLockStatus();  
00216   }  
00217 // ifdef RACE
00218   // the following functions are used to access the fields information
00219   public LockStatus getLockStatus(int objref, String fieldname) {
00220     return ((Fields)objects.get(objref)).getLockStatus(fieldname);
00221   }  
00222 //#endif NO_COMPRESSION
00223 
00224   public Reflection getReflection(int objref) {
00225     Reflection r = (Reflection)getClass(objref).reflection.clone();
00226     r.setObjectReference(objref);
00227 
00228     return r;
00229   }  
00230 // ifdef NO_FASTBACKTRACK
00231 
00232 
00233 
00234 
00235 // ifdef NO_COMPRESSION
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 //#endif NO_COMPRESSION
00253 
00254 //#endif NO_FASTBACKTRACK
00255 
00256 // ifdef NO_COMPRESSION
00257   // Gets the storing information from the dynamic area
00258   public int[] getStoringData() {
00259     // First we need to update the information in case there had been
00260     // any change
00261     update();
00262 
00263     // Mainly we need to get one big array from the two we have
00264     int ol = objectData.length;     // how many objects
00265     int il = objinfoData.length;    // these numbers should be the same
00266 // ifdef DEBUG
00267 
00268 //#endif DEBUG
00269 
00270     // allocate enough space for both structures
00271     int[] data = new int[ol + il];
00272 
00273     // copy the information in the new array
00274     System.arraycopy(objectData, 0, data, 0, ol);
00275     System.arraycopy(objinfoData, 0, data, ol, il);
00276 
00277     return data;
00278   }  
00279   public long getValue(int objref, int index) {
00280     return ((Fields)objects.get(objref)).getValue(index);
00281   }  
00282   // ------------------------------------------
00283   //   access to the underlying fields object
00284   // ------------------------------------------
00285 
00286   public long getValue(int objref, String fieldname) {
00287     return ((Fields)objects.get(objref)).getValue(fieldname);
00288   }  
00289 // ifdef INITIALIZE
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 //#endif INITIALIZE
00301 
00302   public int getVariableType(int objref, int index) {
00303     return ((Fields)objects.get(objref)).getClassInfo().getFieldType(index);
00304   }  
00305   public int getVariableType(int objref, String fname) {
00306     return ((Fields)objects.get(objref)).getClassInfo().getFieldType(fname);
00307   }  
00308   public void hash(HashData hd) {
00309     for(int i = 0, l = objects.size(); i < l; i++) {
00310       Object o = objects.get(i);
00311       if(o != null) hd.add(o.hashCode());
00312     }
00313 
00314     for(int i = 0, l = objinfo.size(); i < l; i++) {
00315       Object o = objinfo.get(i);
00316       if(o != null) hd.add(o.hashCode());
00317     }
00318   }  
00319   public int hashCode() {
00320     HashData hd = new HashData();
00321 
00322     for(int i = 0, l = objects.size(); i < l; i++) {
00323       Object o = objects.get(i);
00324       if(o != null) hd.add(o.hashCode());
00325     }
00326 
00327     for(int i = 0, l = objinfo.size(); i < l; i++) {
00328       Object o = objinfo.get(i);
00329       if(o != null) hd.add(o.hashCode());
00330     }
00331 
00332     return hd.getValue();
00333   }  
00334 // ifdef NO_COMPRESSION
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 
00392 
00393 
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_COMPRESSION
00419 
00420 // ifdef NO_FASTBACKTRACK
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 //#endif NO_FASTBACKTRACK
00446 
00447   private int indexFor(ThreadInfo th) {
00448 // ifdef NO_DYNAMIC_SYMMETRY
00449 
00450 
00451 
00452 
00453 
00454 
00455 //#else NO_DYNAMIC_SYMMETRY
00456     DynamicMapIndex i = new DynamicMapIndex(th.getPC(),
00457 // ifdef THREAD_SYMMETRY
00458 
00459 //#endif THREAD_SYMMETRY
00460     0);
00461 
00462     if(!DynamicMap.hasEntry(i)) return DynamicMap.addEntry(i);
00463 
00464     int index = DynamicMap.getEntry(i);
00465 
00466     if(index < objects.size())
00467       while(objects.get(index) != null) {
00468     i.next();
00469 
00470     if(!DynamicMap.hasEntry(i)) return DynamicMap.addEntry(i);
00471     index = DynamicMap.getEntry(i);
00472     if(index >= objects.size()) return index;
00473       }
00474 
00475     return index;
00476 //#endif NO_DYNAMIC_SYMMETRY
00477   }  
00478   // checks if an object is an instance of the given class (directly or indirectly)
00479   public boolean instanceOfClass(int objref, String classname) {
00480     Fields f = (Fields)objects.get(objref);
00481     if(f == null) return false;
00482 
00483     // gets the class information for that object
00484     ClassInfo ci =  f.getClassInfo();
00485     // can't have a null classinfo reference
00486     if (ci == null) {
00487       Debug.println(Debug.ERROR, "ci field for object " + objref + " is null");
00488       System.exit(0);
00489     }
00490     
00491     // now we go up until we get to the top of the hierarchy
00492     while (ci != null)
00493       // check if this is the class we are looking for
00494       if (ci.getClassName().equals(classname)) 
00495     return true;
00496       else
00497     // goes up one level
00498     ci = ci.getSuperClassInfo();
00499 
00500     // at this point we know it's not an instance of that class
00501     return false;
00502   }  
00503 // ifdef REFERENCE_COUNT
00504 
00505 
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
00578 
00579 
00580 
00581 //#endif REFERENCE_COUNT
00582 
00583 // ifdef MARK_N_SWEEP
00584   public boolean isFieldRef(int objref, String fieldname) {
00585     return ((Fields)objects.get(objref)).isRef(fieldname);
00586   }  
00587 //#endif MARK_N_SWEEP
00588 
00589   public void log() {
00590     Debug.println(Debug.MESSAGE, "DA");
00591     for(int i = 0; i < objects.size(); i++) {
00592       Fields f = (Fields)objects.get(i);
00593       if(f != null) {
00594 // ifdef REFERENCE_COUNT
00595 
00596 //#else REFERENCE_COUNT
00597     Debug.println(Debug.MESSAGE, "  #" + i);
00598 //#endif REFERENCE_COUNT
00599     f.log(i, true);
00600       }
00601     }
00602   }  
00603   public void mark(int objref) {
00604 // ifdef DEBUG
00605 
00606 //#endif DEBUG
00607     if(objref == -1) return;
00608 
00609     if(isUsed.get(objref)) return;
00610     isUsed.set(objref);
00611     
00612     ((Fields)objects.get(objref)).mark(this);
00613   }  
00614 //#endif NO_COMPRESSION
00615 
00616   // the following functions are used to access the monitor information
00617   public boolean monitorCheckLock(int objref, ThreadInfo th) {
00618     return ((ObjectInfo)objinfo.get(objref)).getMonitor().checkLock(th);
00619   }  
00620   public boolean monitorCheckLockAfterNotified(int objref, ThreadInfo th) {
00621     return ((ObjectInfo)objinfo.get(objref)).getMonitor().checkLockAfterNotified(th);
00622   }  
00623   public boolean monitorLock(int objref, ThreadInfo th) {
00624 // ifdef NO_COMPRESSION
00625     // the object info needs to be cloned
00626     cloneObjectInfo(objref);
00627 //#endif NO_COMPRESSION
00628     // needs to get the object info again because clone object info changed it
00629     return ((ObjectInfo)objinfo.get(objref)).getMonitor().lock(th, new ObjRef(objref));
00630   }  
00631   public boolean monitorLockAfterNotified(int objref, ThreadInfo th) {
00632 // ifdef NO_COMPRESSION
00633     // the object info needs to be cloned
00634     cloneObjectInfo(objref);
00635 //#endif NO_COMPRESSION
00636     // needs to get the object info again because clone object info changed it
00637     return ((ObjectInfo)objinfo.get(objref)).getMonitor().lockAfterNotified(th, new ObjRef(objref));
00638   }  
00639   public int monitorLockCount(int objref) {
00640     return ((ObjectInfo)objinfo.get(objref)).getMonitor().getLockCount();
00641   }  
00642   public int monitorLockingThread(int objref) {
00643     return ((ObjectInfo)objinfo.get(objref)).getMonitor().getLockingThread();
00644   }  
00645   public void monitorNotify(int objref, KernelState ks, Scheduler sch) {
00646 // ifdef NO_COMPRESSION
00647     // the object info needs to be cloned
00648     cloneObjectInfo(objref);
00649 //#endif NO_COMPRESSION
00650     // needs to get the object info again because clone object info changed it
00651     ((ObjectInfo)objinfo.get(objref)).getMonitor().notify(ks, sch);
00652   }  
00653   public void monitorNotifyAll(int objref, KernelState ks) {
00654 // ifdef NO_COMPRESSION
00655     // the object info needs to be cloned
00656     cloneObjectInfo(objref);
00657 //#endif NO_COMPRESSION
00658     // needs to get the object info again because clone object info changed it
00659     ((ObjectInfo)objinfo.get(objref)).getMonitor().notifyAll(ks);
00660   }  
00661   public void monitorUnlock(int objref, ThreadInfo th) {
00662 // ifdef NO_COMPRESSION
00663     // the object info needs to be cloned
00664     cloneObjectInfo(objref);
00665 //#endif NO_COMPRESSION
00666     // needs to get the object info again because clone object info changed it
00667     ((ObjectInfo)objinfo.get(objref)).getMonitor().unlock(th, new ObjRef(objref));
00668   }  
00669   public void monitorWait(int objref, ThreadInfo th) {
00670 // ifdef NO_COMPRESSION
00671     // the object info needs to be cloned
00672     cloneObjectInfo(objref);
00673 //#endif NO_COMPRESSION
00674     // needs to get the object info again because clone object info changed it
00675     ((ObjectInfo)objinfo.get(objref)).getMonitor().wait(th, new ObjRef(objref));
00676   }  
00677   public List monitorWaitingThreads(int objref) {
00678     return (List)((ArrayList)((ObjectInfo)objinfo.get(objref)).getMonitor().getWaitingThreads()).clone();
00679   }  
00680   // Creates a new array object of the given type.
00681   //** optimization: ci is actually never used here... **//
00682   public int newArrayObject(String type, int size, ThreadInfo th) {
00683     Fields fields = new Fields(null, size); // the fields of the object
00684     ObjectInfo oi;          // The object info of the new object
00685 
00686     // we need to get the new object info
00687     oi = new ObjectInfo();
00688 // ifdef INITIALIZE
00689 
00690 //#endif INITIALIZE
00691 
00692     // compute the position for the new object
00693     int index = indexFor(th);
00694 
00695     // once we got the index we should check a couple of things
00696     // first if there is not enough space then we should make room for it
00697     if (index >= objects.size()) {
00698       objects.setSize(index+10); 
00699       objinfo.setSize(index+10); 
00700     }
00701 
00702     // at this point we insert the fields we created for that object
00703     // and a new object info in the dynamic area
00704     objects.setElementAt(fields, index);
00705     objinfo.setElementAt(oi, index);
00706 
00707 // ifdef NO_COMPRESSION
00708     // states that we changed something
00709     objectChanged.set(index);
00710     objinfoChanged.set(index);
00711     anyObjectChanged= true;
00712     anyObjectInfoChanged = true;
00713 //#endif NO_COMPRESSION
00714 
00715     // now we should get the elements of the array
00716     for(int i = 0; i < size; i++) {
00717       fields.setValue(i, Types.newValue(type));
00718 // ifdef MARK_N_SWEEP
00719       if(Types.isReference(type))
00720     fields.setValueRef(i);
00721 //#endif MARK_N_SWEEP
00722     }
00723 
00724     // this is the object reference for the newly created object
00725     return index;
00726   }  
00727   // another "special" object is the class object. Here's how we get one
00728   //** optimization: jpfvm could be a static class or merged with virtual machine **//
00729   public int newClassObject(String str, ThreadInfo th) {
00730     JPFVM jpfvm = JPFVM.getJPFVM();
00731 
00732     // loads and links the java.lang.Class class
00733     ClassInfo ci = jpfvm.getClass("java.lang.Class");
00734 
00735     // creates an object and it will fill the fields by hand
00736     int objref   = newObject(ci, th);
00737 
00738     //** missing: the object should be initialized but implemetation is incomplete **//
00739     
00740     // returns the object reference
00741     return objref;
00742   }  
00743 // ifdef DEBUG
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 //#endif DEBUG
00756 
00757 // ifdef DEBUG
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 //#endif DEBUG
00770 //#endif NO_COMPRESSION
00771 
00772   // creates a new object of the given class
00773   // every instruction that creates a new object is assigned a distinct id
00774   // used by the heap symmetry
00775   public int newObject(ClassInfo ci, ThreadInfo th) {
00776 // ifdef DEBUG
00777 
00778 //#endif DEBUG
00779 
00780     // gets the non static fields. these will have to be stored in the
00781     // dynamic area.
00782     Fields fs = ci.createFields();
00783     ObjectInfo oi;          // The object info of the new object
00784 
00785     // we need to get the new object info
00786     oi = new ObjectInfo();
00787 
00788     // We need to decide now which entry in the dynamic area to use
00789     int index = indexFor(th);
00790 
00791     // once we got the index we should check a couple of things
00792     // first if there is not enough space then we should make room for it
00793     if (index >= objects.size()) {
00794       objects.setSize(index+10); 
00795       objinfo.setSize(index+10); 
00796     }
00797 
00798     // at this point we insert the fields we created for that object
00799     // and a new object info in the dynamic area
00800     objects.setElementAt(fs, index);
00801     objinfo.setElementAt(oi, index);
00802 
00803 // ifdef NO_COMPRESSION
00804     // states that we changed something
00805     objectChanged.set(index);
00806     objinfoChanged.set(index);
00807     anyObjectChanged= true;
00808     anyObjectInfoChanged = true;
00809 //#endif NO_COMPRESSION
00810 
00811 // ifdef DEBUG
00812 
00813 //#endif DEBUG
00814     //
00815     // returns the object reference of the newly created object
00816     return index;
00817   }  
00818   // creates a new string object
00819   // strings are handled separately due to their special nature
00820   // in the java virtual machine
00821   //** optimization: jpfvm could be a static class or merged with virtual machine **//
00822   public int newStringObject(String str, ThreadInfo th) {
00823     JPFVM jpfvm = JPFVM.getJPFVM();
00824 
00825     // gets the class information (and link the class if it was not done before)
00826     ClassInfo ci = jpfvm.getClass("java.lang.String");
00827 
00828     // creates the new object for the string
00829     int objref = newObject(ci, th);
00830 
00831     // creates a new array for storing the characters
00832     int value = newArrayObject("C", str.length(), th);
00833 
00834     // now fills the various fields
00835     setValue(objref, "value", value);
00836     for(int i = 0, s = str.length(); i < s; i++)
00837       setValue(value, i, str.charAt(i));
00838     setValue(objref, "offset", 0);
00839     setValue(objref, "count", str.length());
00840 
00841     // returns the object reference
00842     return objref;
00843   }  
00844 // ifdef NO_COMPRESSION
00845   public void revertTo(int[] data) {
00846     int len = data.length / 2;
00847 
00848     int[] nObjectData = new int[len];
00849     int[] nObjinfoData = new int[len];
00850 
00851     System.arraycopy(data, 0, nObjectData, 0, len);
00852     System.arraycopy(data, len, nObjinfoData, 0, len);
00853 
00854     int s = objectData.length;
00855 
00856     if (s >= len) {
00857       for (int idx = 0; idx < len; idx++) {
00858     if(nObjectData[idx] != objectData[idx])
00859       objects.setElementAt(
00860           VirtualMachine.fieldsPool.getObject(nObjectData[idx]),
00861           idx);
00862     if(nObjinfoData[idx] != objinfoData[idx])
00863       objinfo.setElementAt(
00864           VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00865           idx);
00866       }
00867       objects.setSize(len);
00868       objinfo.setSize(len);
00869     } else {
00870       for (int idx = 0; idx < s; idx++) {
00871     if(nObjectData[idx] != objectData[idx])
00872       objects.setElementAt(
00873           VirtualMachine.fieldsPool.getObject(nObjectData[idx]),
00874           idx);
00875     if(nObjinfoData[idx] != objinfoData[idx])
00876       objinfo.setElementAt(
00877           VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00878           idx);
00879       }
00880       objects.setSize(len);
00881       objinfo.setSize(len);
00882       for (int idx = s; idx < len; idx++) {
00883     objects.setElementAt(
00884         VirtualMachine.fieldsPool.getObject(nObjectData[idx]),
00885         idx);
00886     objinfo.setElementAt(
00887         VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00888         idx);
00889       }
00890     }
00891     objectData = nObjectData;
00892     objinfoData = nObjinfoData;
00893   }  
00894   public void setValue(int objref, int index, long value) {
00895 // ifdef NO_COMPRESSION
00896     cloneObject(objref);
00897 //#endif NO_COMPRESSION
00898     ((Fields)objects.get(objref)).setValue(index, value);
00899   }  
00900   public void setValue(int objref, String fieldname, long value) {
00901 // ifdef NO_COMPRESSION
00902     cloneObject(objref);
00903 //#endif NO_COMPRESSION
00904     ((Fields)objects.get(objref)).setValue(fieldname, value);
00905   }  
00906   // The following group of functions are used when something is changed
00907   // all the data structure must be updated but we can do it in a smart
00908   // way and avoid updating what's not changed.
00909   private void update() {
00910     if (anyObjectChanged) {
00911       // Updates objectData
00912       updateObjects();
00913 
00914       // Clears all the flags because no updates are necessary anymore
00915       objectChanged.and(ZERO);
00916       anyObjectChanged = false;
00917     }
00918 
00919     if (anyObjectInfoChanged) {
00920       // Updates objinfoData
00921       updateObjectInfos();
00922 
00923       // Clears all the flags because no updates are necessary anymore
00924       objinfoChanged.and(ZERO);
00925       anyObjectInfoChanged = false;
00926     }
00927   }  
00928   // updates the object infos
00929   private void updateObjectInfos() {
00930     // we have to keep in mind that there could be empty spaces
00931     // due to object created and destroyed.
00932     int size = objinfo.size();
00933     int old_size = objinfoData.length;
00934     int actual_size = -1;   // there could be empty slots at the end!
00935 
00936 // ifdef DEBUG
00937 
00938 
00939 //#endif DEBUG
00940 
00941     // first we get an array as long as the object info vector
00942     int[] data = new int[size];
00943     for(int i = 0; i < size; i++) {
00944       // for each entry we have to test a couple of conditions
00945       ObjectInfo o = (ObjectInfo)objinfo.get(i);
00946       if(o != null) {
00947     // if the entry at index i it's not null then
00948     // the actual size it's at least i.
00949     actual_size = i;
00950 
00951     if (objinfoChanged.get(i)) {
00952       // if it's changed then we have to check the pool
00953       HashPool.PoolEntry e = VirtualMachine.objectInfoPool.getEntry(o);
00954       // set the reference so that we keep just one copy if it was in the
00955       // pool already
00956       objinfo.setElementAt(e.getObject(), i);
00957       // set the correct index we got from the pool
00958       data[i] = e.getIndex();
00959     } else {
00960       // if it's not changed it means it was already there
00961       // so we get the old value from the old object info data
00962 // ifdef DEBUG
00963 
00964 //#endif DEBUG
00965       data[i] = objinfoData[i];
00966     }
00967       } else {
00968     // if the entry is null it will be a 0 in the data
00969     data[i] = 0;
00970       }
00971     }
00972 
00973     // now we have to put the information in the object info data avoid to
00974     // store all the zeros at the end (that are unuseful).
00975     objinfoData = new int[++actual_size];
00976     System.arraycopy(data, 0, objinfoData, 0, actual_size);
00977   }  
00978   // updates the objects
00979   private void updateObjects() {
00980     // we have to keep in mind that there could be empty spaces
00981     // due to object created and destroyed
00982     int size = objects.size();
00983     int old_size = objectData.length;
00984     int actual_size = -1;   // there could be empty slots at the end!
00985 
00986 // ifdef DEBUG
00987 
00988 
00989 //#endif DEBUG
00990 
00991     // first we get an array as long as the object vector
00992     int[] data = new int[size];
00993     for(int i = 0; i < size; i++) {
00994       // for each entry we have to test a couple of conditions
00995       Fields o = (Fields)objects.get(i);
00996       if(o != null) {
00997     // if the entry at index i it's not null then
00998     // the actual size it's at least i.
00999     actual_size = i;
01000 
01001     if (objectChanged.get(i)) {
01002       // if it's changed then we have to check the pool
01003       HashPool.PoolEntry e = VirtualMachine.fieldsPool.getEntry(o);
01004       // set the reference so that we keep just one copy if it was in the
01005       // pool already
01006       objects.setElementAt(e.getObject(), i);
01007       // set the correct index we got from the pool
01008       data[i] = e.getIndex();
01009     } else {
01010       // if it's not changed it means it was already there
01011       // so we get the old value from the old object data
01012 // ifdef DEBUG
01013 
01014 //#endif DEBUG
01015       data[i] = objectData[i];
01016     }
01017       } else {
01018     // if the entry is null it will be a 0 in the data
01019     data[i] = 0;
01020       }
01021     }
01022 
01023     // now we have to put the information in the object data avoid to
01024     // store all the zeros at the end (that are unuseful).
01025     objectData = new int[++actual_size];
01026     System.arraycopy(data, 0, objectData, 0, actual_size);
01027   }  
01028 }

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