KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gov > nasa > jpf > jvm > ElementInfo


1 //
2
// Copyright (C) 2005 United States Government as represented by the
3
// Administrator of the National Aeronautics and Space Administration
4
// (NASA). All Rights Reserved.
5
//
6
// This software is distributed under the NASA Open Source Agreement
7
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
8
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
9
// directory tree for the complete NOSA document.
10
//
11
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
12
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
13
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
14
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
15
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
16
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
17
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
18
//
19
package gov.nasa.jpf.jvm;
20
21 import gov.nasa.jpf.JPFException;
22 import gov.nasa.jpf.util.Debug;
23 import gov.nasa.jpf.util.HashData;
24 import gov.nasa.jpf.util.HashPool;
25
26 import java.util.HashMap JavaDoc;
27 import java.util.Vector JavaDoc;
28
29 /**
30  * Describes an element of memory containing the field values of a class or an
31  * object. In the case of a class, contains the values of the static fields. For
32  * an object contains the values of the object fields.
33  *
34  * @see gov.nasa.jpf.jvm.FieldInfo
35  */

36 public abstract class ElementInfo implements Storable, Reference, Cloneable JavaDoc {
37   static final int storingDataLength = 3;
38
39   protected static HashPool fieldsPool = new HashPool();
40
41   protected static HashPool monitorPool = new HashPool();
42
43   protected static HashPool racePool = new HashPool();
44
45   protected Fields fields;
46
47   protected Monitor monitor;
48
49   protected Area area;
50
51   protected int index;
52
53   // object attribute flag values
54
public static final int ATTR_NONE = 0x0;
55
56   public static final int ATTR_PROP_MASK = 0x0000ffff;
57
58   // the propagated ones - only lower 16 bits can be used
59

60   public static final int ATTR_TSHARED = 0x1; // reachable
61
// from
62
// different
63
// threads
64

65   // this one is redundant if we just base it on the ClassInfo
66
// (->fields->classinfo)
67
// but we might use code attrs in the future to set this on a per-instance
68
// basis
69
public static final int ATTR_IMMUTABLE = 0x2; // object
70
// doesn't
71
// change value
72

73   // don't promote to shared along this path
74
public static final int ATTR_NO_PROMOTE = 0x4;
75
76   // the non-propagated attributes - use only higher 16 bits
77

78   // to-be-done, would be code attr, too, and could easily be checked at runtime
79
// (hello, a new property)
80
public static final int ATTR_SINGLE_WRITER = 0x10000;
81
82   // don't propagate attributes through this object
83
public static final int ATTR_NO_PROPAGATE = 0x20000;
84
85   // object is assumed to be fully protected (i.e. no field access that is
86
// not protected by a lock)
87
public static final int ATTR_PROTECTED = 0x40000;
88
89   // don't reycle this object as long as the flag is set
90
public static final int ATTR_PINDOWN = 0x80000;
91
92   // these are our state-stored object attributes
93
// WATCH OUT! only include info that otherwise reflects a state change, so
94
// that
95
// we don't introduce new changes. It's value is used to hash the state!
96
// <2do> what a pity - 32 stored bits for (currently) only 2 bits of
97
// information,
98
// but we might use this as a hash for more complex reference info in the
99
// future.
100
// We distinguish between propagates and private object attributes, the first
101
// ones tored in the lower 2 bytes
102
protected int attributes;
103
104   /*
105    * The following information is used to cache the value of the indexes so that
106    * an explicit indexing is not necessary at each storing.
107    */

108   protected int fIndex = -1;
109
110   protected int mIndex = -1;
111
112   static HashMap JavaDoc lockDiscipline = new HashMap JavaDoc();
113
114   public ElementInfo(Fields f, Monitor m) {
115     fields = f;
116     monitor = m;
117
118     attributes = f.getClassInfo().getElementInfoAttrs();
119   }
120
121   protected ElementInfo() {
122   }
123
124   public String JavaDoc toString() {
125     return (getClassInfo().getName() + '@' + index);
126   }
127
128   public FieldLockInfo getFieldLockInfo(String JavaDoc fid) {
129     return (FieldLockInfo) lockDiscipline.get(fid);
130   }
131
132   public void setFieldLockInfo(String JavaDoc fid, FieldLockInfo flInfo) {
133     lockDiscipline.put(fid, flInfo);
134   }
135
136   /**
137    * do we have a reference field with value objRef?
138    */

139   boolean hasRefField(int objRef) {
140     return fields.hasRefField(objRef);
141   }
142
143   void setShared() {
144     attributes |= ATTR_TSHARED;
145   }
146
147   /**
148    * set shared, but only if the ATTR_TSHARED bit isn't masked out
149    */

150   void setShared(int attrMask) {
151     attributes |= (attrMask & ATTR_TSHARED);
152   }
153
154   /**
155    * the recursive phase2 marker entry, which propagates the attributes set by a
156    * previous phase1. This one is called on all 'root'-marked objects after
157    * phase1 is completed. ElementInfo is not an ideal place for this method, as
158    * it has to access some innards of both ClassInfo (FieldInfo container) and
159    * Fields. But on the other hand, we want to keep the whole heap traversal
160    * business as much centralized in ElementInfo and DynamicArea as possible
161    *
162    * @aspects: gc
163    */

164   void markRecursive(int tid, int attrMask) {
165     DynamicArea heap = DynamicArea.getHeap();
166     int i, n;
167
168     if (isArray()) {
169       if (fields.isReferenceArray()) {
170         n = fields.arrayLength();
171         for (i = 0; i < n; i++) {
172           heap.markRecursive(fields.getIntValue(i), tid, attributes, attrMask,
173               null);
174         }
175       }
176     } else {
177       ClassInfo ci = getClassInfo();
178       boolean isWeakRef = ci.isWeakReference();
179         
180       do {
181         n = ci.getNumberOfDeclaredInstanceFields();
182         boolean isRef = isWeakRef && ci.isRefClass(); // is this the java.lang.ref.Reference part?
183

184         for (i = 0; i < n; i++) {
185           FieldInfo fi = ci.getDeclaredInstanceField(i);
186           if (fi.isReference()) {
187             if ((i == 0) && isRef) {
188               // we need to reset the ref field once the referenced object goes away
189
// NOTE: only the *first* WeakReference field is a weak ref
190
// (this is why we have our own implementation)
191
heap.registerWeakReference(fields);
192             } else {
193
194               // the refAttrs are not immediately masked because we have to
195
// preserve
196
// the mask values up to the point where we would promote a
197
// otherwise
198
// unshared root object due to a different thread id (in case we
199
// didn't
200
// catch a mask on the way that prevents this)
201
heap.markRecursive(fields
202                   .getReferenceValue(fi.getStorageOffset()), tid, attributes,
203                   attrMask, fi);
204             }
205           }
206         }
207         ci = ci.getSuperClass();
208       } while (ci != null);
209     }
210   }
211
212   boolean hasEqualPropagatedAttributes(int refAttrs, int attrMask) {
213     int mask = ATTR_PROP_MASK & attrMask;
214     return ((attributes & mask) == (refAttrs & mask));
215   }
216
217   void propagateAttributes(int refAttr, int attrMask) {
218     attributes |= ((refAttr & attrMask) & ATTR_PROP_MASK);
219   }
220
221   public boolean isShared() {
222     return ((attributes & ATTR_TSHARED) != 0);
223   }
224
225   public boolean isImmutable() {
226     return ((attributes & ATTR_IMMUTABLE) != 0);
227   }
228
229   public boolean isSchedulingRelevant() {
230     // only mutable, shared objects are relevant
231
return ((attributes & (ATTR_TSHARED | ATTR_IMMUTABLE)) == ATTR_TSHARED);
232   }
233
234   /**
235    * check if there are any propagated attributes in ei we don't have yet
236    */

237   public boolean needsAttributePropagationFrom(ElementInfo ei) {
238     int a = attributes;
239     int o = ei.attributes;
240
241     if (a != o) {
242       if ((o & ATTR_PROP_MASK) > (a & ATTR_PROP_MASK))
243         return true;
244
245       for (int i = 0; i < 16; i++, o >>= 1, a >>= 1) {
246         if ((o & 0x1) > (a & 0x1)) {
247           return true;
248         }
249       }
250     }
251
252     return false;
253   }
254
255   public void setArea(Area newArea) {
256     area = newArea;
257   }
258
259   public Area getArea() {
260     return area;
261   }
262
263   /** a bit simplistic, but will do for object equalness */
264   public boolean equals(Object JavaDoc other) {
265     if (getClass() != other.getClass())
266       return false;
267
268     ElementInfo ei = (ElementInfo) other;
269     return fields.equals(ei.fields);
270   }
271
272   public ClassInfo getClassInfo() {
273     return fields.getClassInfo();
274   }
275
276   abstract protected FieldInfo getFieldInfo(String JavaDoc clsBase, String JavaDoc fname);
277
278   abstract protected ElementInfo getElementInfo(ClassInfo ci);
279
280   protected FieldInfo getFieldInfo(String JavaDoc fname) {
281     return getFieldInfo(null, fname);
282   }
283
284   public int getIntField(String JavaDoc fname) {
285     return getIntField(fname, null);
286   }
287
288   public long getLongField(String JavaDoc fname) {
289     return getLongField(fname, null);
290   }
291
292   public void setIntField(FieldInfo fi, int value) {
293     //checkFieldInfo(fi); // in case somebody caches and uses the wrong
294
// FieldInfo
295
ElementInfo ei = getElementInfo(fi.getClassInfo()); // might not be 'this'
296
// in case of a static
297

298     if (!fi.isReference()) {
299       ei.cloneFields().setIntValue(fi.getStorageOffset(), value);
300     } else {
301       throw new JPFException("reference field: " + fi.getName());
302     }
303   }
304
305   public void setIntField(String JavaDoc fname, String JavaDoc clsBase, int value) {
306     setIntField(getFieldInfo(clsBase, fname), value);
307   }
308
309   public void setIntField(String JavaDoc fname, int value) {
310     setIntField(fname, null, value);
311   }
312
313   public void setLongField(String JavaDoc fname, long value) {
314     FieldInfo fi = getFieldInfo(fname);
315     ElementInfo ei = getElementInfo(fi.getClassInfo());
316     ei.cloneFields().setLongValue(fi.getStorageOffset(), value);
317   }
318
319   void updateReachability(int oldRef, int newRef) {
320     ThreadInfo ti = ThreadInfo.getCurrent(); // might be null if still in VM
321
// init
322
if ((ti == null) || ti.isInCtor() || !ti.usePor()) {
323       return;
324     }
325
326     if (oldRef != newRef) {
327       DynamicArea heap = DynamicArea.getHeap();
328       ElementInfo oei, nei;
329
330       if (isShared()) {
331         if (oldRef != -1) {
332           oei = heap.get(oldRef);
333           if (!oei.isImmutable()) { // it's already shared, anyway
334
// Ok, give up and do a full mark, the old object might not be
335
// reachable anymore
336
heap.analyzeHeap(false); // takes care of the newRef, too
337
return;
338           }
339         }
340
341         if (newRef != -1) {
342           nei = heap.get(newRef);
343           if (!nei.isShared() && !nei.isImmutable()) {
344             // no need to walk the whole heap, just recursively promote nei
345
// and all its reachables to 'shared'
346
nei.setShared();
347             heap.initGc(); // doesn't belong here, should be encapsulated in DA
348
nei.markRecursive(ti.getIndex(), ATTR_PROP_MASK);
349           }
350         }
351       } else { // we are not shared (oldRef can't change status)
352
if (newRef != -1) {
353           nei = heap.get(newRef);
354           if (nei.isSchedulingRelevant()) { // shared and mutable
355
// give up, nei might become non-shared
356
heap.analyzeHeap(false);
357           }
358         }
359       }
360     }
361
362     if (oldRef != -1) {
363       JVM.getVM().getSystemState().activateGC(); // needs GC at the end of this
364
// transition
365
}
366   }
367
368   public void setReferenceField(FieldInfo fi, int value) {
369     ElementInfo ei = getElementInfo(fi.getClassInfo()); // might not be 'this'
370
// in case of a static
371
Fields f = ei.cloneFields();
372     int off = fi.getStorageOffset();
373
374     if (fi.isReference()) {
375       int oldValue = f.getReferenceValue(off);
376       f.setReferenceValue(off, value);
377       updateReachability(oldValue, value);
378     } else {
379       throw new JPFException("not a reference field: " + fi.getName());
380     }
381   }
382
383   public void setReferenceField(String JavaDoc fname, String JavaDoc clsBase, int value) {
384     setReferenceField(getFieldInfo(clsBase, fname), value);
385   }
386
387   public void setReferenceField(String JavaDoc fname, int value) {
388     setReferenceField(fname, null, value);
389   }
390
391   public int getReferenceField(String JavaDoc fname, String JavaDoc clsBase) {
392     FieldInfo fi = getFieldInfo(clsBase, fname);
393     ElementInfo ei = getElementInfo(fi.getClassInfo());
394
395     if (!fi.isReference()) {
396       throw new JPFException("not a reference field: " + fi.getName());
397     }
398     return ei.fields.getIntValue(fi.getStorageOffset());
399   }
400
401   public int getReferenceField(String JavaDoc fname) {
402     return getReferenceField(fname, null);
403   }
404
405   public int getIntField(String JavaDoc fname, String JavaDoc clsBase) {
406     // be aware of that static fields are not flattened (they are unique), i.e.
407
// the FieldInfo might actually refer to another ClassInfo/StaticElementInfo
408
FieldInfo fi = getFieldInfo(clsBase, fname);
409     ElementInfo ei = getElementInfo(fi.getClassInfo());
410     return ei.fields.getIntValue(fi.getStorageOffset());
411   }
412
413   public void setLongField(String JavaDoc fname, String JavaDoc clsBase, long value) {
414     FieldInfo fi = getFieldInfo(clsBase, fname);
415     ElementInfo ei = getElementInfo(fi.getClassInfo());
416     ei.cloneFields().setLongValue(fi.getStorageOffset(), value);
417   }
418
419   public long getLongField(String JavaDoc fname, String JavaDoc clsBase) {
420     FieldInfo fi = getFieldInfo(clsBase, fname);
421     ElementInfo ei = getElementInfo(fi.getClassInfo());
422     return ei.fields.getLongValue(fi.getStorageOffset());
423   }
424
425   public boolean getBooleanField(String JavaDoc fname, String JavaDoc refType) {
426     FieldInfo fi = getFieldInfo(refType, fname);
427     ElementInfo ei = getElementInfo(fi.getClassInfo());
428     return ei.fields.getBooleanValue(fi.getStorageOffset());
429   }
430
431   public byte getByteField(String JavaDoc fname, String JavaDoc refType) {
432     FieldInfo fi = getFieldInfo(refType, fname);
433     ElementInfo ei = getElementInfo(fi.getClassInfo());
434     return ei.fields.getByteValue(fi.getStorageOffset());
435   }
436
437   public char getCharField(String JavaDoc fname, String JavaDoc refType) {
438     FieldInfo fi = getFieldInfo(refType, fname);
439     ElementInfo ei = getElementInfo(fi.getClassInfo());
440     return ei.fields.getCharValue(fi.getStorageOffset());
441   }
442
443   public double getDoubleField(String JavaDoc fname, String JavaDoc refType) {
444     FieldInfo fi = getFieldInfo(refType, fname);
445     ElementInfo ei = getElementInfo(fi.getClassInfo());
446     return ei.fields.getDoubleValue(fi.getStorageOffset());
447   }
448
449   public float getFloatField(String JavaDoc fname, String JavaDoc refType) {
450     FieldInfo fi = getFieldInfo(refType, fname);
451     ElementInfo ei = getElementInfo(fi.getClassInfo());
452     return ei.fields.getFloatValue(fi.getStorageOffset());
453   }
454
455   public short getShortField(String JavaDoc fname, String JavaDoc refType) {
456     FieldInfo fi = getFieldInfo(refType, fname);
457     ElementInfo ei = getElementInfo(fi.getClassInfo());
458     return ei.fields.getShortValue(fi.getStorageOffset());
459   }
460
461   private void checkFieldInfo(FieldInfo fi) {
462     if (!getClassInfo().isInstanceOf(fi.getClassInfo())) {
463       throw new JPFException("wrong FieldInfo : " + fi.getName()
464           + " , no such field in " + getClassInfo().getName());
465     }
466   }
467
468   // those are the cached field value accessors. The caller is responsible
469
// for assuring type compatibility
470
public int getIntField(FieldInfo fi) {
471     checkFieldInfo(fi);
472     return fields.getIntValue(fi.getStorageOffset());
473   }
474
475   public long getLongField(FieldInfo fi) {
476     checkFieldInfo(fi);
477     return fields.getLongValue(fi.getStorageOffset());
478   }
479
480   public void setLongField(FieldInfo fi, long val) {
481     checkFieldInfo(fi);
482     cloneFields().setLongValue(fi.getStorageOffset(), val);
483   }
484
485   private void checkArray(int index) {
486     if (!isArray()) { // <2do> should check for !long array
487
throw new JPFException(
488           "cannot access non array objects by index");
489     }
490     if ((index < 0) || (index >= fields.size())) {
491       throw new JPFException("illegal array offset: " + index);
492     }
493   }
494
495   private void checkLongArray(int index) {
496     if (!isArray()) { // <2do> should check for !int array
497
throw new JPFException(
498           "cannot access non array objects by index");
499     }
500     if ((index < 0) || (index >= (fields.size() - 1))) {
501       throw new JPFException("illegal long array offset: " + index);
502     }
503   }
504
505   private boolean isReferenceArray() {
506     return getClassInfo().isReferenceArray();
507   }
508
509   // those are not really fields, so treat them differently!
510
public void setElement(int index, int value) {
511     checkArray(index);
512     if (isReferenceArray()) {
513       cloneFields().setReferenceValue(index, value);
514     } else {
515       cloneFields().setIntValue(index, value);
516     }
517   }
518
519   public void setLongElement(int index, long value) {
520     checkArray(index);
521     cloneFields().setLongValue(index*2, value);
522   }
523
524   public int getElement(int index) {
525     checkArray(index);
526     return fields.getIntValue(index);
527   }
528
529   public long getLongElement(int index) {
530     checkArray(index);
531     return fields.getLongValue(index*2);
532   }
533
534   public void setIndex(int newIndex) {
535     index = newIndex;
536   }
537
538   public int getIndex() {
539     return index;
540   }
541
542   public int getThisReference() {
543     return index;
544   }
545
546   public int getLockCount() {
547     return monitor.getLockCount();
548   }
549
550   public int getLockingThread() {
551     return monitor.getLockingThread();
552   }
553
554   public boolean isLocked() {
555     return (monitor.getLockCount() > 0);
556   }
557
558   public boolean isArray() {
559     return fields.isArray();
560   }
561
562   public String JavaDoc getArrayType() {
563     if (!fields.isArray()) {
564       throw new JPFException("object is not an array");
565     }
566
567     return Types.getArrayElementType(fields.getType());
568   }
569
570   public Object JavaDoc getBacktrackData() {
571     return null;
572   }
573
574   public char getCharArrayElement(int index) {
575     return (char) getElement(index);
576   }
577
578   public int getIntArrayElement(int findex) {
579     return getElement(findex);
580   }
581
582   public long getLongArrayElement(int findex) {
583     return getLongElement(findex);
584   }
585
586   public boolean[] asBooleanArray() {
587     return fields.asBooleanArray();
588   }
589
590   public byte[] asByteArray() {
591     return fields.asByteArray();
592   }
593
594   public short[] asShortArray() {
595     return fields.asShortArray();
596   }
597
598   public char[] asCharArray() {
599     return fields.asCharArray();
600   }
601
602   public int[] asIntArray() {
603     return fields.asIntArray();
604   }
605
606   public long[] asLongArray() {
607     return fields.asLongArray();
608   }
609
610   public float[] asFloatArray() {
611     return fields.asFloatArray();
612   }
613
614   public double[] asDoubleArray() {
615     return fields.asDoubleArray();
616   }
617
618   public boolean isNull() {
619     return (index == -1);
620   }
621
622   public Reference getObjectField(String JavaDoc fname, String JavaDoc referenceType) {
623     return area.ks.da.get(getIntField(fname, referenceType));
624   }
625
626   // <2do> just here for the Storable interface - it's NOT the one that is
627
// used for heavy duty state storage, because we want to avoid all the
628
// small array allocations. Change the Storable interface at some point!
629
public int[] getStoringData() {
630     int[] data = new int[3];
631
632     data[0] = getFieldsIndex();
633     data[1] = getMonitorIndex();
634     data[2] = attributes;
635
636     return data;
637   }
638
639   /**
640    * <2do>pcm - these two will become the new Storable interface (but that has
641    * a huge fan out)
642    */

643   public int getStoringDataLength() {
644     return 3;
645   }
646
647   /**
648    * answer an estimate of the heap size in bytes (this is of course VM
649    * dependent, but we can give an upper bound for the fields/elements, and that
650    * should be good in terms of application specific properties)
651    */

652   public int getHeapSize() {
653     return fields.getHeapSize();
654   }
655
656   public String JavaDoc getStringField(String JavaDoc fname, String JavaDoc referenceType) {
657     int ref = getIntField(fname, referenceType);
658
659     if (ref != -1) {
660       ElementInfo ei = area.ks.da.get(ref);
661       if (ei == null) {
662         System.out.println("OUTCH: " + ref + ", this: " + index);
663       }
664       return ei.asString();
665     } else {
666       return "null";
667     }
668   }
669
670   public String JavaDoc getType() {
671     return fields.getType();
672   }
673
674   public int[] getWaitingThreads() {
675     return monitor.getWaitingThreads();
676   }
677
678   public int arrayLength() {
679     return fields.arrayLength();
680   }
681
682   public String JavaDoc asString() {
683     if (!fields.getClassInfo().instanceOf("java.lang.String")) {
684       throw new JPFException("object is not of type java.lang.String");
685     }
686
687     int value = getIntField("value", "java.lang.String");
688     int length = getIntField("count", "java.lang.String");
689     int offset = getIntField("offset", "java.lang.String");
690
691     ElementInfo e = area.get(value);
692
693     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
694
695     for (int i = offset; i < (offset + length); i++) {
696       sb.append((char) e.fields.getIntValue(i));
697     }
698
699     return sb.toString();
700   }
701
702   void updateLockingInfo() {
703     int tid = monitor.getLockingThread();
704     if (tid != -1) {
705       // here we can update ThreadInfo lock object info (so that we don't
706
// have to store it separately)
707
// NOTE - the threads need to be restored *before* the Areas, or this is
708
// going to choke
709
ThreadInfo ti = area.ks.tl.get(tid);
710       // note that we add only once, i.e. rely on the monitor lockCount to
711
// determine when to remove an object from our lock set
712
ti.addLockedObject(this);
713     }
714   }
715
716   public void backtrackTo(ArrayOffset storing, Object JavaDoc backtrack) {
717     setFieldsIndex(storing.get());
718     setMonitorIndex(storing.get());
719
720     attributes = storing.get();
721
722     updateLockingInfo();
723   }
724
725   public boolean canLock(ThreadInfo th) {
726     return monitor.canLock(th);
727   }
728
729   public void checkArrayBounds(int index)
730       throws ArrayIndexOutOfBoundsExecutiveException {
731     if (outOfBounds(index)) {
732       throw new ArrayIndexOutOfBoundsExecutiveException(area.ks.ss
733           .getRunningThread().createAndThrowException(
734               "java.lang.ArrayIndexOutOfBoundsException"));
735     }
736   }
737
738   public void checkLongArrayBounds(int index)
739       throws ArrayIndexOutOfBoundsExecutiveException {
740     checkArrayBounds(index);
741     checkArrayBounds(index + 1);
742   }
743
744   public Object JavaDoc clone() {
745     try {
746       ElementInfo ei = (ElementInfo) super.clone();
747
748       if (ei.fIndex == -1) {
749         ei.fields = (Fields) fields.clone();
750       }
751
752       if (ei.mIndex == -1) {
753         ei.monitor = (Monitor) monitor.clone();
754       }
755
756       area = null;
757       index = -1;
758
759       return ei;
760     } catch (CloneNotSupportedException JavaDoc e) {
761       e.printStackTrace();
762       throw new InternalError JavaDoc("should not happen");
763     }
764   }
765
766   public void hash(HashData hd) {
767     fields.hash(hd);
768     monitor.hash(hd);
769   }
770
771   public int hashCode() {
772     HashData hd = new HashData();
773
774     hash(hd);
775
776     return hd.getValue();
777   }
778
779   public boolean instanceOf(String JavaDoc type) {
780     return Types.instanceOf(fields.getType(), type);
781   }
782
783   public void interrupt() {
784     area.ks.tl.locate(index).interrupt();
785   }
786
787   public void lock(ThreadInfo th) {
788     cloneMonitor().lock(th, getRef());
789
790     // don't re-add if we are recursive - the lock count is avaliable in
791
// the monitor
792
if (monitor.getLockCount() == 1) {
793       th.addLockedObject(this);
794     }
795   }
796
797   public void lockNotified(ThreadInfo th) {
798     cloneMonitor().lockNotified(th, getRef());
799
800     // pcm - this is important, if we later-on backtrack (reset the
801
// ThreadInfo.lockedObjects set, and then restore from the saved heap), the
802
// lock set would not include the lock when we continue to execute this
803
// thread
804
th.addLockedObject(this); //wv: add locked object back here
805
}
806
807   abstract public int getNumberOfFields();
808
809   abstract public FieldInfo getFieldInfo(int i);
810
811   public void log() {
812     if (fIndex == -1) {
813       Debug.println(Debug.MESSAGE, "(fields have changed)");
814     }
815
816     ClassInfo ci = getClassInfo();
817     int n = getNumberOfFields();
818     for (int i = 0; i < n; i++) {
819       FieldInfo fi = getFieldInfo(i);
820       Debug.println(Debug.MESSAGE, fi.getName() + ": "
821           + fi.valueToString(fields));
822     }
823
824     if (mIndex == -1) {
825       Debug.println(Debug.MESSAGE, "(monitor has changed)");
826     }
827
828     monitor.log();
829   }
830
831   public void notifies() {
832     cloneMonitor().notify(area.ks.ss);
833   }
834
835   public void notifiesAll() {
836     cloneMonitor().notifyAll(area.ks.ss);
837   }
838
839   public boolean outOfBounds(int index) {
840     if (!fields.isArray()) {
841       throw new JPFException("object is not an array");
842     }
843
844     return (index < 0 || index >= fields.size());
845   }
846
847   /**
848    * imperatively set GC status
849    *
850    * @param keepAlive -
851    * true: keep alive no matter what, false: gc normally
852    */

853   public void pinDown(boolean keepAlive) {
854     if (keepAlive) {
855       attributes |= ATTR_PINDOWN;
856     } else {
857       attributes &= ~ATTR_PINDOWN;
858     }
859   }
860
861   /**
862    * this is the heavy duty state storer for ElementInfos
863    */

864   public int storeDataTo(int[] buffer, int idx) {
865     buffer[idx++] = getFieldsIndex();
866     buffer[idx++] = getMonitorIndex();
867     buffer[idx] = attributes;
868
869     return 3;
870   }
871
872   public void unlock(ThreadInfo th) {
873     cloneMonitor().unlock(th, getRef());
874
875     if (monitor.getLockCount() == 0) {
876       th.removeLockedObject(this);
877     }
878   }
879
880   public void wait(ThreadInfo th) {
881     cloneMonitor().wait(th, getRef());
882     th.removeLockedObject(this); //wv: remove locked object here
883
}
884
885   protected void setFieldsIndex(int index) {
886     if (fIndex == index) {
887       return;
888     }
889
890     fIndex = index;
891     fields = (Fields) fieldsPool.getObject(index);
892   }
893
894   protected int getFieldsIndex() {
895     if (fIndex != -1) {
896       return fIndex;
897     }
898
899     HashPool.PoolEntry e = fieldsPool.getEntry(fields);
900     fields = (Fields) e.getObject();
901
902     return fIndex = e.getIndex();
903   }
904
905   protected void setMonitorIndex(int index) {
906     if (mIndex == index) {
907       return;
908     }
909
910     mIndex = index;
911     monitor = (Monitor) monitorPool.getObject(index);
912   }
913
914   protected int getMonitorIndex() {
915     if (mIndex != -1) {
916       return mIndex;
917     }
918
919     HashPool.PoolEntry e = monitorPool.getEntry(monitor);
920     monitor = (Monitor) e.getObject();
921
922     return mIndex = e.getIndex();
923   }
924
925   /**
926    * The various lock methods need access to a Ref object to do their work. The
927    * subclass should return an appropriate type. This is a simple factory
928    * method.
929    *
930    * @return the right kind of Ref object for the given ElementInfo
931    */

932   protected abstract Ref getRef();
933
934   protected Fields cloneFields() {
935     if (fIndex == -1) {
936       return fields;
937     }
938
939     fIndex = -1;
940     area.ks.data = null;
941     area.hasChanged.set(index);
942     area.anyChanged = true;
943
944     return fields = (Fields) fields.clone();
945   }
946
947   protected Monitor cloneMonitor() {
948     if (mIndex == -1) {
949       return monitor;
950     }
951
952     mIndex = -1;
953     area.ks.data = null;
954     area.hasChanged.set(index);
955     area.anyChanged = true;
956
957     monitor = (Monitor) monitor.clone();
958
959     return monitor;
960   }
961
962   boolean isLockedBy(ThreadInfo ti) {
963     return ((monitor != null) && (monitor.getLockingThread() == ti.index));
964   }
965
966   void _printAttributes(String JavaDoc cls, String JavaDoc msg, int oldAttrs) {
967     if (getClassInfo().getName().equals(cls)) {
968       System.out.println(msg + " " + this + " attributes: "
969           + Integer.toHexString(attributes) + " was: "
970           + Integer.toHexString(oldAttrs));
971     }
972   }
973   
974   /*
975    * The following code is used to linearize a rooted structure in the heap
976    */

977   
978   public Vector JavaDoc linearize (Vector JavaDoc result) {
979     DynamicArea heap = DynamicArea.getHeap();
980     int i, n;
981     
982     if (isArray()) {
983       if (fields.isReferenceArray()) {
984         n = fields.arrayLength();
985         for (i=0; i<n; i++) {
986           result = heap.linearize(fields.getIntValue(i),result);
987         }
988       }
989     } else {
990       ClassInfo ci = getClassInfo();
991       do {
992         n = ci.getNumberOfDeclaredInstanceFields();
993         for (i=0; i<n; i++) {
994           FieldInfo fi = ci.getDeclaredInstanceField(i);
995           if (fi.isReference()) {
996             if ((i == 0) && ci.isWeakReference()) {
997               // we need to reset the ref field once the referenced object goes away
998
// NOTE: only the *first* WeakReference field is a weak ref
999
// (this is why we have our own implementation)
1000

1001                //dont' know what to do here?
1002
return result;
1003                
1004            } else {
1005              // the refAttrs are not immediately masked because we have to preserve
1006
// the mask values up to the point where we would promote a otherwise
1007
// unshared root object due to a different thread id (in case we didn't
1008
// catch a mask on the way that prevents this)
1009
result = heap.linearize(fields.getReferenceValue(fi.getStorageOffset()),result);
1010            }
1011          }
1012        }
1013        ci = ci.getSuperClass();
1014      } while (ci != null);
1015    }
1016    return result;
1017  }
1018}
1019
1020
Popular Tags