comparison agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2004 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
31 /** <P> This is a basic implementation of the TypeDataBase interface.
32 It allows an external type database builder to add types to be
33 consumed by a client through the Type interfaces. It has no
34 knowledge of symbol lookup; for example, the builder is
35 responsible for providing the addresses of static fields. </P>
36
37 <P> Among other things, the database builder is responsible for
38 providing the Types for the Java primitive types, as well as their
39 sizes. </P>
40 */
41
42 public class BasicTypeDataBase implements TypeDataBase {
43 private MachineDescription machDesc;
44 private VtblAccess vtblAccess;
45 /** Maps strings to Type objects. This does not contain the primitive types. */
46 private Map nameToTypeMap = new HashMap();
47 /** Maps strings to Integers, used for enums, etc. */
48 private Map nameToIntConstantMap = new HashMap();
49 /** Maps strings to Longs, used for 32/64-bit constants, etc. */
50 private Map nameToLongConstantMap = new HashMap();
51 /** Primitive types. */
52 private Type jbooleanType;
53 private Type jbyteType;
54 private Type jcharType;
55 private Type jdoubleType;
56 private Type jfloatType;
57 private Type jintType;
58 private Type jlongType;
59 private Type jshortType;
60
61 /** For debugging */
62 private static final boolean DEBUG;
63 static {
64 DEBUG = System.getProperty("sun.jvm.hotspot.types.basic.BasicTypeDataBase.DEBUG") != null;
65 }
66
67 public BasicTypeDataBase(MachineDescription machDesc, VtblAccess vtblAccess) {
68 this.machDesc = machDesc;
69 this.vtblAccess = vtblAccess;
70 }
71
72 public Type lookupType(String cTypeName) {
73 return lookupType(cTypeName, true);
74 }
75
76 public Type lookupType(String cTypeName, boolean throwException) {
77 Type type = (Type) nameToTypeMap.get(cTypeName);
78 if (type == null && throwException) {
79 throw new RuntimeException("No type named \"" + cTypeName + "\" in database");
80 }
81 return type;
82 }
83
84 public Integer lookupIntConstant(String constantName) {
85 return lookupIntConstant(constantName, true);
86 }
87
88 public Integer lookupIntConstant(String constantName, boolean throwException) {
89 Integer i = (Integer) nameToIntConstantMap.get(constantName);
90 if (i == null) {
91 if (throwException) {
92 throw new RuntimeException("No integer constant named \"" + constantName + "\" present in type database");
93 }
94 }
95 return i;
96 }
97
98 public Long lookupLongConstant(String constantName) {
99 return lookupLongConstant(constantName, true);
100 }
101
102 public Long lookupLongConstant(String constantName, boolean throwException) {
103 Long i = (Long) nameToLongConstantMap.get(constantName);
104 if (i == null) {
105 if (throwException) {
106 throw new RuntimeException("No long constant named \"" + constantName + "\" present in type database");
107 }
108 }
109 return i;
110 }
111
112 public Type getJBooleanType() {
113 return jbooleanType;
114 }
115
116 public Type getJByteType() {
117 return jbyteType;
118 }
119
120 public Type getJCharType() {
121 return jcharType;
122 }
123
124 public Type getJDoubleType() {
125 return jdoubleType;
126 }
127
128 public Type getJFloatType() {
129 return jfloatType;
130 }
131
132 public Type getJIntType() {
133 return jintType;
134 }
135
136 public Type getJLongType() {
137 return jlongType;
138 }
139
140 public Type getJShortType() {
141 return jshortType;
142 }
143
144 public long getAddressSize() {
145 return machDesc.getAddressSize();
146 }
147
148 public long getOopSize() {
149 return machDesc.getOopSize();
150 }
151
152 public boolean addressTypeIsEqualToType(Address addr, Type type) {
153 if (addr == null) {
154 return false;
155 }
156
157 // This implementation should be suitably platform-independent; we
158 // search nearby memory for the vtbl value of the given type.
159
160 Address vtblAddr = vtblAccess.getVtblForType(type);
161
162 if (vtblAddr == null) {
163 // Type was not polymorphic, or an error occurred during lookup
164 if (DEBUG) {
165 System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: vtblAddr == null");
166 }
167
168 return false;
169 }
170
171 // The first implementation searched three locations for this vtbl
172 // value; scanning through the entire object was considered, but
173 // we thought we knew where we were looking, and looking only in
174 // these specific locations should reduce the probability of
175 // mistaking random bits as a pointer (although, realistically
176 // speaking, the likelihood of finding a match between the bit
177 // pattern of, for example, a double and the vtbl is vanishingly
178 // small.)
179 // 1. The first word of the object (should handle MSVC++ as
180 // well as the SparcWorks compilers with compatibility set to
181 // v5.0 or greater)
182 // 2. and 3. The last two Address-aligned words of the part of
183 // the object defined by its topmost polymorphic superclass.
184 // This should handle the SparcWorks compilers, v4.2 or
185 // earlier, as well as any other compilers which place the vptr
186 // at the end of the user-defined fields of the first base
187 // class with virtual functions.
188 //
189 // Unfortunately this algorithm did not work properly for the
190 // specific case of the ThreadShadow/Thread inheritance situation,
191 // because the Solaris compiler seems to cleverly eliminate the
192 // vtbl for ThreadShadow since the only virtual is empty. (We
193 // should get rid of the ThreadShadow and fix the include
194 // databases, but need to postpone this for the present.) The
195 // current solution performs the three-location check for this
196 // class and all of its known superclasses rather than just the
197 // topmost polymorphic one.
198
199 Type curType = type;
200
201 try {
202 while (curType != null) {
203 // Using the size information we have for this type, check the
204 // three locations described above.
205
206 // (1)
207 if (vtblAddr.equals(addr.getAddressAt(0))) {
208 return true;
209 }
210
211 // (2)
212 long offset = curType.getSize();
213 // I don't think this should be misaligned under any
214 // circumstances, but I'm not sure (FIXME: also not sure which
215 // way to go here, up or down -- assuming down)
216 offset -= (offset % getAddressSize());
217 if (offset <= 0) {
218 return false;
219 }
220 if (vtblAddr.equals(addr.getAddressAt(offset))) {
221 return true;
222 }
223 offset -= getAddressSize();
224 if (offset <= 0) {
225 return false;
226 }
227 if (vtblAddr.equals(addr.getAddressAt(offset))) {
228 return true;
229 }
230
231 curType = curType.getSuperclass();
232 }
233 }
234 catch (Exception e) {
235 // Any UnmappedAddressExceptions, etc. are a good indication
236 // that the pointer is not of the specified type
237 if (DEBUG) {
238 System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: exception occurred during lookup:");
239 e.printStackTrace();
240 }
241
242 return false;
243 }
244
245 if (DEBUG) {
246 System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: all vptr tests failed for type " +
247 type.getName());
248 }
249
250 return false;
251 }
252
253 public Type guessTypeForAddress(Address addr) {
254 for (Iterator iter = getTypes(); iter.hasNext(); ) {
255 Type t = (Type) iter.next();
256 if (addressTypeIsEqualToType(addr, t)) {
257 return t;
258 }
259 }
260 return null;
261 }
262
263 public long cIntegerTypeMaxValue(long sizeInBytes, boolean isUnsigned) {
264 return machDesc.cIntegerTypeMaxValue(sizeInBytes, isUnsigned);
265 }
266
267 public long cIntegerTypeMinValue(long sizeInBytes, boolean isUnsigned) {
268 return machDesc.cIntegerTypeMinValue(sizeInBytes, isUnsigned);
269 }
270
271 public Iterator getTypes() {
272 return nameToTypeMap.values().iterator();
273 }
274
275 public Iterator getIntConstants() {
276 return nameToIntConstantMap.keySet().iterator();
277 }
278
279 public Iterator getLongConstants() {
280 return nameToLongConstantMap.keySet().iterator();
281 }
282
283 //--------------------------------------------------------------------------------
284 // Public routines only for use by the database builder
285 //
286
287 /** This method should only be called by the builder of the
288 TypeDataBase and at most once */
289 public void setJBooleanType(Type type) {
290 jbooleanType = type;
291 }
292
293 /** This method should only be called by the builder of the
294 TypeDataBase and at most once */
295 public void setJByteType(Type type) {
296 jbyteType = type;
297 }
298
299 /** This method should only be called by the builder of the
300 TypeDataBase and at most once */
301 public void setJCharType(Type type) {
302 jcharType = type;
303 }
304
305 /** This method should only be called by the builder of the
306 TypeDataBase and at most once */
307 public void setJDoubleType(Type type) {
308 jdoubleType = type;
309 }
310
311 /** This method should only be called by the builder of the
312 TypeDataBase and at most once */
313 public void setJFloatType(Type type) {
314 jfloatType = type;
315 }
316
317 /** This method should only be called by the builder of the
318 TypeDataBase and at most once */
319 public void setJIntType(Type type) {
320 jintType = type;
321 }
322
323 /** This method should only be called by the builder of the
324 TypeDataBase and at most once */
325 public void setJLongType(Type type) {
326 jlongType = type;
327 }
328
329 /** This method should only be called by the builder of the
330 TypeDataBase and at most once */
331 public void setJShortType(Type type) {
332 jshortType = type;
333 }
334
335 /** This method should only be used by the builder of the
336 TypeDataBase. Throws a RuntimeException if a class with this
337 name was already present. */
338 public void addType(Type type) {
339 if (nameToTypeMap.get(type.getName()) != null) {
340 throw new RuntimeException("type of name \"" + type.getName() + "\" already present");
341 }
342
343 nameToTypeMap.put(type.getName(), type);
344 }
345
346 /** This method should only be used by the builder of the
347 TypeDataBase. Throws a RuntimeException if this class was not
348 present. */
349 public void removeType(Type type) {
350 Type curType = (Type) nameToTypeMap.get(type.getName());
351 if (curType == null) {
352 throw new RuntimeException("type of name \"" + type.getName() + "\" not present");
353 }
354
355 if (!curType.equals(type)) {
356 throw new RuntimeException("a different type of name \"" + type.getName() + "\" was present");
357 }
358
359 nameToTypeMap.remove(type.getName());
360 }
361
362 /** This method should only be used by the builder of the
363 TypeDataBase. Throws a RuntimeException if an integer constant
364 with this name was already present. */
365 public void addIntConstant(String name, int value) {
366 if (nameToIntConstantMap.get(name) != null) {
367 throw new RuntimeException("int constant of name \"" + name + "\" already present");
368 }
369
370 nameToIntConstantMap.put(name, new Integer(value));
371 }
372
373 /** This method should only be used by the builder of the
374 TypeDataBase. Throws a RuntimeException if an integer constant
375 with this name was not present. */
376 public void removeIntConstant(String name) {
377 Integer curConstant = (Integer) nameToIntConstantMap.get(name);
378 if (curConstant == null) {
379 throw new RuntimeException("int constant of name \"" + name + "\" not present");
380 }
381
382 nameToIntConstantMap.remove(name);
383 }
384
385 /** This method should only be used by the builder of the
386 TypeDataBase. Throws a RuntimeException if a long constant with
387 this name was already present. */
388 public void addLongConstant(String name, long value) {
389 if (nameToLongConstantMap.get(name) != null) {
390 throw new RuntimeException("long constant of name \"" + name + "\" already present");
391 }
392
393 nameToLongConstantMap.put(name, new Long(value));
394 }
395
396 /** This method should only be used by the builder of the
397 TypeDataBase. Throws a RuntimeException if a long constant with
398 this name was not present. */
399 public void removeLongConstant(String name) {
400 Long curConstant = (Long) nameToLongConstantMap.get(name);
401 if (curConstant == null) {
402 throw new RuntimeException("long constant of name \"" + name + "\" not present");
403 }
404
405 nameToLongConstantMap.remove(name);
406 }
407 }