001: //
002: // Copyright (C) 2005 United States Government as represented by the
003: // Administrator of the National Aeronautics and Space Administration
004: // (NASA). All Rights Reserved.
005: //
006: // This software is distributed under the NASA Open Source Agreement
007: // (NOSA), version 1.3. The NOSA has been approved by the Open Source
008: // Initiative. See the file NOSA-1.3-JPF at the top of the distribution
009: // directory tree for the complete NOSA document.
010: //
011: // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
012: // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
013: // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
014: // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
015: // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
016: // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
017: // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
018: //
019: package gov.nasa.jpf.jvm;
020:
021: import gov.nasa.jpf.JPFException;
022: import gov.nasa.jpf.util.HashData;
023:
024: /**
025: * Represents the fields (adat part) of an object or class. Contains the
026: * values of the fields, not their descriptors. Descriptors are represented by
027: * gov.nasa.jpf.jvm.FieldInfo objects, which are stored in the
028: * ClassInfo structure.
029: * @see gov.nasa.jpf.jvm.FieldInfo
030: */
031: public abstract class Fields implements Cloneable {
032: static int FATTR_MASK = 0xffff; // pass all propagated attributes
033:
034: /** Type of the object or class */
035: protected final String type;
036:
037: /** the class of this object */
038: protected final ClassInfo ci;
039:
040: /** this is where we store the instance data */
041: protected int[] values;
042:
043: protected Fields(String type, ClassInfo ci, int dataSize) {
044: this .type = type;
045: this .ci = ci;
046:
047: values = new int[dataSize];
048: }
049:
050: /**
051: * give an approximation of the heap size in bytes - we assume fields a word
052: * aligned, hence the number of fields*4 should be good. Note that this is
053: * overridden by ArrayFields (arrays would be packed)
054: */
055: public int getHeapSize() {
056: return values.length * 4;
057: }
058:
059: /**
060: * do we have a reference field with value objRef? This is used by
061: * the reachability analysis
062: */
063: public boolean hasRefField(int objRef) {
064: return ci.hasRefField(objRef, this );
065: }
066:
067: /**
068: * Returns true if the fields belong to an array.
069: */
070: public boolean isArray() {
071: return Types.getBaseType(type) == Types.T_ARRAY;
072: }
073:
074: public boolean isReferenceArray() {
075: return false;
076: }
077:
078: /**
079: * Returns a reference to the class information.
080: */
081: public ClassInfo getClassInfo() {
082: return ci;
083: }
084:
085: // <2do> pcm - Grr, this is only here to hide the Dynamic/StaticFieldInfo branching
086: // remove once this is gone!
087: public abstract FieldInfo getFieldInfo(String clsBase, String fname);
088:
089: public abstract int getNumberOfFields();
090:
091: // NOTE - fieldIndex (ClassInfo) != storageOffset (Fields). We *don't pad anymore!
092: public abstract FieldInfo getFieldInfo(int fieldIndex);
093:
094: // our low level getters and setters
095: public int getIntValue(int index) {
096: return values[index];
097: }
098:
099: // same as above, just here to make intentions clear
100: public int getReferenceValue(int index) {
101: return values[index];
102: }
103:
104: public long getLongValue(int index) {
105: return Types.intsToLong(values[index + 1], values[index]);
106: }
107:
108: public boolean getBooleanValue(int index) {
109: return Types.intToBoolean(values[index]);
110: }
111:
112: public byte getByteValue(int index) {
113: return (byte) values[index];
114: }
115:
116: public char getCharValue(int index) {
117: return (char) values[index];
118: }
119:
120: public short getShortValue(int index) {
121: return (short) values[index];
122: }
123:
124: public void setReferenceValue(int index, int newValue) {
125: values[index] = newValue;
126: }
127:
128: public void setIntValue(int index, int newValue) {
129: values[index] = newValue;
130: }
131:
132: public void setLongValue(int index, long newValue) {
133: values[index++] = Types.hiLong(newValue);
134: values[index] = Types.loLong(newValue);
135: }
136:
137: public void setDoubleValue(int index, double newValue) {
138: values[index++] = Types.hiDouble(newValue);
139: values[index] = Types.loDouble(newValue);
140: }
141:
142: public void setFloatValue(int index, float newValue) {
143: values[index] = Types.floatToInt(newValue);
144: }
145:
146: public float getFloatValue(int index) {
147: return Types.intToFloat(values[index]);
148: }
149:
150: public double getDoubleValue(int index) {
151: return Types.intsToDouble(values[index + 1], values[index]);
152: }
153:
154: /**
155: * Returns the type of the object or class associated with the fields.
156: */
157: public String getType() {
158: return type;
159: }
160:
161: /**
162: * Creates a clone.
163: */
164: public Object clone() {
165: Fields f;
166:
167: try {
168: f = (Fields) super .clone();
169: f.values = (int[]) values.clone();
170: } catch (CloneNotSupportedException e) {
171: throw new InternalError(e.getMessage());
172: }
173:
174: return f;
175: }
176:
177: /**
178: * Checks for equality.
179: */
180: public boolean equals(Object o) {
181: if (o == null) {
182: return false;
183: }
184:
185: if (!(o instanceof Fields)) {
186: return false;
187: }
188:
189: Fields f = (Fields) o;
190:
191: if (!type.equals(f.type)) {
192: return false;
193: }
194:
195: if (ci != f.ci) {
196: return false;
197: }
198:
199: int[] v1 = values;
200: int[] v2 = f.values;
201: int l = v1.length;
202:
203: if (l != v2.length) {
204: return false;
205: }
206:
207: for (int i = 0; i < l; i++) {
208: if (v1[i] != v2[i]) {
209: return false;
210: }
211: }
212:
213: return true;
214: }
215:
216: /**
217: * Adds some data to the computation of an hashcode.
218: */
219: public void hash(HashData hd) {
220: for (int i = 0, s = values.length; i < s; i++) {
221: hd.add(values[i]);
222: }
223: }
224:
225: public int arrayLength() {
226: // re-implemented by ArrayFields
227: throw new JPFException("attempt to get length of non-array: "
228: + ci.getName());
229: }
230:
231: public boolean[] asBooleanArray() {
232: throw new JPFException("not an array object: " + ci.getName());
233: }
234:
235: public byte[] asByteArray() {
236: throw new JPFException("not an array object: " + ci.getName());
237: }
238:
239: public char[] asCharArray() {
240: throw new JPFException("not an array object: " + ci.getName());
241: }
242:
243: public short[] asShortArray() {
244: throw new JPFException("not an array object: " + ci.getName());
245: }
246:
247: public int[] asIntArray() {
248: throw new JPFException("not an array object: " + ci.getName());
249: }
250:
251: public long[] asLongArray() {
252: throw new JPFException("not an array object: " + ci.getName());
253: }
254:
255: public float[] asFloatArray() {
256: throw new JPFException("not an array object: " + ci.getName());
257: }
258:
259: public double[] asDoubleArray() {
260: throw new JPFException("not an array object: " + ci.getName());
261: }
262:
263: /**
264: * Computes an hash code.
265: */
266: public int hashCode() {
267: HashData hd = new HashData();
268:
269: hash(hd);
270:
271: return hd.getValue();
272: }
273:
274: /**
275: * Size of the fields.
276: */
277: public int size() {
278: return values.length;
279: }
280:
281: public String toString() {
282: StringBuffer sb = new StringBuffer();
283: sb.append("Fields(");
284:
285: sb.append("type=");
286: sb.append(type);
287: sb.append(",");
288:
289: sb.append("ci=");
290: sb.append(ci.getName());
291: sb.append(",");
292:
293: sb.append("values=");
294: sb.append('[');
295:
296: for (int i = 0; i < values.length; i++) {
297: if (i != 0) {
298: sb.append(',');
299: }
300:
301: sb.append(values[i]);
302: }
303:
304: sb.append(']');
305: sb.append(",");
306:
307: sb.append(")");
308:
309: return sb.toString();
310: }
311:
312: protected abstract String getLogChar();
313: }
|