0
|
1 /*
|
|
2 * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
|
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 *
|
|
5 * This code is free software; you can redistribute it and/or modify it
|
|
6 * under the terms of the GNU General Public License version 2 only, as
|
|
7 * published by the Free Software Foundation.
|
|
8 *
|
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 * version 2 for more details (a copy is included in the LICENSE file that
|
|
13 * accompanied this code).
|
|
14 *
|
|
15 * You should have received a copy of the GNU General Public License version
|
|
16 * 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 *
|
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 package sun.jvm.hotspot.types.basic;
|
|
26
|
|
27 import java.util.*;
|
|
28 import sun.jvm.hotspot.debugger.*;
|
|
29 import sun.jvm.hotspot.types.*;
|
|
30 import sun.jvm.hotspot.utilities.*;
|
|
31
|
|
32 /** <P> This is a basic implementation of the Type interface which
|
|
33 should be complete enough to be portable across platforms. The
|
|
34 only issue will be the construction of these objects and their
|
|
35 components from the platform-specific debugging information; see
|
|
36 BasicTypeDataBase. </P>
|
|
37
|
|
38 <P> There are two types of clients of this class. The first is
|
|
39 that which builds the TypeDatabase. This kind of client uses the
|
|
40 additional public methods beyond those in the Type interface to
|
|
41 properly configure the BasicType objects. The second is the
|
|
42 consumer of these types; this kind of client should deal only with
|
|
43 the Type interfaces. </P> */
|
|
44
|
|
45 public class BasicType implements Type {
|
|
46 protected BasicTypeDataBase db;
|
|
47
|
|
48 private String name;
|
|
49 private long size;
|
|
50 private boolean isJavaPrimitiveType;
|
|
51 private boolean isOopType;
|
|
52 // These are only the fields defined in this class, not any of this
|
|
53 // class's superclasses.
|
|
54 private Map nameToFieldMap = new HashMap();
|
|
55 private List fieldList = new LinkedList();
|
|
56 // Superclass, or null if none. Primitive types do not have any
|
|
57 // inheritance relationship.
|
|
58 private Type superclass;
|
|
59
|
|
60 /** superclass may be null */
|
|
61 public BasicType(BasicTypeDataBase db, String name, Type superclass) {
|
|
62 if (name == null) {
|
|
63 throw new IllegalArgumentException("name may not be null");
|
|
64 }
|
|
65 this.db = db;
|
|
66 this.name = name;
|
|
67 this.superclass = superclass;
|
|
68 }
|
|
69
|
|
70 /** Equivalent to BasicType(db, name, null) */
|
|
71 public BasicType(BasicTypeDataBase db, String name) {
|
|
72 this(db, name, null);
|
|
73 }
|
|
74
|
|
75 public boolean equals(Object obj) {
|
|
76 if (obj == null) {
|
|
77 return false;
|
|
78 }
|
|
79
|
|
80 if (!(obj instanceof BasicType)) {
|
|
81 return false;
|
|
82 }
|
|
83
|
|
84 BasicType arg = (BasicType) obj;
|
|
85
|
|
86 if (!name.equals(arg.name)) {
|
|
87 return false;
|
|
88 }
|
|
89
|
|
90 return true;
|
|
91 }
|
|
92
|
|
93 public int hashCode() {
|
|
94 return name.hashCode();
|
|
95 }
|
|
96
|
|
97 public String toString() {
|
|
98 return name;
|
|
99 }
|
|
100
|
|
101 public String getName() {
|
|
102 return name;
|
|
103 }
|
|
104
|
|
105 /** This should only be called at most once, and only by the builder
|
|
106 of the type database */
|
|
107 public void setSuperclass(Type superclass) {
|
|
108 this.superclass = superclass;
|
|
109 }
|
|
110
|
|
111 public Type getSuperclass() {
|
|
112 return superclass;
|
|
113 }
|
|
114
|
|
115 /** This should only be called at most once, and only by the builder
|
|
116 of the type database */
|
|
117 public void setSize(long sizeInBytes) {
|
|
118 this.size = sizeInBytes;
|
|
119 }
|
|
120
|
|
121 public long getSize() {
|
|
122 return size;
|
|
123 }
|
|
124
|
|
125 /** Overridden by BasicCIntegerType */
|
|
126 public boolean isCIntegerType() {
|
|
127 return false;
|
|
128 }
|
|
129
|
|
130 public boolean isCStringType() {
|
|
131 if (isPointerType()) {
|
|
132 Type target = ((PointerType)this).getTargetType();
|
|
133 return target.isCIntegerType() &&
|
|
134 target.getName().equals("const char");
|
|
135 } else {
|
|
136 return false;
|
|
137 }
|
|
138 }
|
|
139
|
|
140 public boolean isJavaPrimitiveType() {
|
|
141 return isJavaPrimitiveType;
|
|
142 }
|
|
143
|
|
144 /** This should only be called at most once, and only by the builder
|
|
145 of the type database */
|
|
146 public void setIsJavaPrimitiveType(boolean isJavaPrimitiveType) {
|
|
147 this.isJavaPrimitiveType = isJavaPrimitiveType;
|
|
148 }
|
|
149
|
|
150 public boolean isOopType() {
|
|
151 return isOopType;
|
|
152 }
|
|
153
|
|
154 /** Overridden by BasicPointerType */
|
|
155 public boolean isPointerType() {
|
|
156 return false;
|
|
157 }
|
|
158
|
|
159 /** This should only be called at most once, and only by the builder
|
|
160 of the type database */
|
|
161 public void setIsOopType(boolean isOopType) {
|
|
162 this.isOopType = isOopType;
|
|
163 }
|
|
164
|
|
165 public Field getField(String fieldName, boolean searchSuperclassFields,
|
|
166 boolean throwExceptionIfNotFound) {
|
|
167 Field field = null;
|
|
168 if (nameToFieldMap != null) {
|
|
169 field = (Field) nameToFieldMap.get(fieldName);
|
|
170
|
|
171 if (field != null) {
|
|
172 return field;
|
|
173 }
|
|
174 }
|
|
175
|
|
176 if (searchSuperclassFields) {
|
|
177 if (superclass != null) {
|
|
178 field = superclass.getField(fieldName, searchSuperclassFields, false);
|
|
179 }
|
|
180 }
|
|
181
|
|
182 if (field == null && throwExceptionIfNotFound) {
|
|
183 throw new RuntimeException("field \"" + fieldName + "\" not found in type " + name);
|
|
184 }
|
|
185
|
|
186 return field;
|
|
187 }
|
|
188
|
|
189 public Field getField(String fieldName, boolean searchSuperclassFields) {
|
|
190 return getField(fieldName, searchSuperclassFields, true);
|
|
191 }
|
|
192
|
|
193 public Field getField(String fieldName) {
|
|
194 return getField(fieldName, true);
|
|
195 }
|
|
196
|
|
197 public Field getField(String fieldName, Type declaredType,
|
|
198 boolean searchSuperclassFields) throws WrongTypeException {
|
|
199 Field res = getField(fieldName, searchSuperclassFields);
|
|
200 if (res == null) {
|
|
201 return null;
|
|
202 }
|
|
203 if (!res.getType().equals(declaredType)) {
|
|
204 throw new WrongTypeException("field \"" + fieldName + "\" in type " + name +
|
|
205 " is not of type " + declaredType +
|
|
206 ", but instead of type " + res.getType());
|
|
207 }
|
|
208 return res;
|
|
209 }
|
|
210
|
|
211 public Field getField(String fieldName, Type declaredType) throws WrongTypeException {
|
|
212 return getField(fieldName, declaredType, false);
|
|
213 }
|
|
214
|
|
215 /** The returned iterator's "remove" method must not be called */
|
|
216 public Iterator getFields() {
|
|
217 return new ConstIterator(fieldList.iterator());
|
|
218 }
|
|
219
|
|
220 //--------------------------------------------------------------------------------
|
|
221 // Specialized field type accessors
|
|
222 //
|
|
223
|
|
224 public JBooleanField getJBooleanField(String fieldName) throws WrongTypeException {
|
|
225 return (JBooleanField) getField(fieldName, db.getJBooleanType());
|
|
226 }
|
|
227
|
|
228 public JByteField getJByteField(String fieldName) throws WrongTypeException {
|
|
229 return (JByteField) getField(fieldName, db.getJByteType());
|
|
230 }
|
|
231
|
|
232 public JCharField getJCharField(String fieldName) throws WrongTypeException {
|
|
233 return (JCharField) getField(fieldName, db.getJCharType());
|
|
234 }
|
|
235
|
|
236 public JDoubleField getJDoubleField(String fieldName) throws WrongTypeException {
|
|
237 return (JDoubleField) getField(fieldName, db.getJDoubleType());
|
|
238 }
|
|
239
|
|
240 public JFloatField getJFloatField(String fieldName) throws WrongTypeException {
|
|
241 return (JFloatField) getField(fieldName, db.getJFloatType());
|
|
242 }
|
|
243
|
|
244 public JIntField getJIntField(String fieldName) throws WrongTypeException {
|
|
245 return (JIntField) getField(fieldName, db.getJIntType());
|
|
246 }
|
|
247
|
|
248 public JLongField getJLongField(String fieldName) throws WrongTypeException {
|
|
249 return (JLongField) getField(fieldName, db.getJLongType());
|
|
250 }
|
|
251
|
|
252 public JShortField getJShortField(String fieldName) throws WrongTypeException {
|
|
253 return (JShortField) getField(fieldName, db.getJShortType());
|
|
254 }
|
|
255
|
|
256 public CIntegerField getCIntegerField(String fieldName) throws WrongTypeException {
|
|
257 Field field = getField(fieldName);
|
|
258 if (!(field.getType() instanceof CIntegerType)) {
|
|
259 throw new WrongTypeException("field \"" + fieldName + "\" in type " + name +
|
|
260 " is not of C integer type, but instead of type " +
|
|
261 field.getType());
|
|
262 }
|
|
263 return (CIntegerField) field;
|
|
264 }
|
|
265
|
|
266 public OopField getOopField(String fieldName) throws WrongTypeException {
|
|
267 Field field = getField(fieldName);
|
|
268 if (!field.getType().isOopType()) {
|
|
269 throw new WrongTypeException("field \"" + fieldName + "\" in type " + name +
|
|
270 " is not of oop type, but instead of type " +
|
|
271 field.getType());
|
|
272 }
|
|
273 return (OopField) field;
|
|
274 }
|
|
275
|
|
276 public AddressField getAddressField(String fieldName) {
|
|
277 // This type can not be inferred (for now), so provide a wrapper
|
|
278 Field field = getField(fieldName);
|
|
279 if (field == null) {
|
|
280 return null;
|
|
281 }
|
|
282 return new BasicAddressFieldWrapper(field);
|
|
283 }
|
|
284
|
|
285 /** This method should only be used by the builder of the
|
|
286 TypeDataBase. Throws a RuntimeException if a field with this
|
|
287 name was already present in this class. */
|
|
288 public void addField(Field field) {
|
|
289 if (nameToFieldMap.get(field.getName()) != null) {
|
|
290 throw new RuntimeException("field of name \"" + field.getName() + "\" already present");
|
|
291 }
|
|
292
|
|
293 nameToFieldMap.put(field.getName(), field);
|
|
294 fieldList.add(field);
|
|
295 }
|
|
296
|
|
297 /** This method should only be used by the builder of the
|
|
298 TypeDataBase. Throws a RuntimeException if a field with this
|
|
299 name was not present in this class. */
|
|
300 public void removeField(Field field) {
|
|
301 if (nameToFieldMap.remove(field.getName()) == null) {
|
|
302 throw new RuntimeException("field of name \"" + field.getName() + "\" was not present");
|
|
303 }
|
|
304 fieldList.remove(field);
|
|
305 }
|
|
306 }
|