Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java @ 11996:22a5aff0df0b
8019396: SA-JDI OSThread class initialization throws an exception
Summary: Method sun.jvm.hotspot.runtime.OSThread.initialize throws a sun.jvm.hotspot.types.WrongTypeException
Reviewed-by: dholmes, mgerdin
author | dsamersoff |
---|---|
date | Tue, 06 Aug 2013 14:28:48 +0400 |
parents | 117bb0519114 |
children | de6a9e811145 |
rev | line source |
---|---|
0 | 1 /* |
3939 | 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.types.basic; | |
26 | |
8755
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
27 import java.util.HashMap; |
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
28 import java.util.Iterator; |
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
29 import java.util.Map; |
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
30 |
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
31 import sun.jvm.hotspot.debugger.Address; |
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
32 import sun.jvm.hotspot.debugger.MachineDescription; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
33 import sun.jvm.hotspot.runtime.VM; |
8755
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
34 import sun.jvm.hotspot.types.Type; |
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
35 import sun.jvm.hotspot.types.TypeDataBase; |
0 | 36 |
37 /** <P> This is a basic implementation of the TypeDataBase interface. | |
38 It allows an external type database builder to add types to be | |
39 consumed by a client through the Type interfaces. It has no | |
40 knowledge of symbol lookup; for example, the builder is | |
41 responsible for providing the addresses of static fields. </P> | |
42 | |
43 <P> Among other things, the database builder is responsible for | |
44 providing the Types for the Java primitive types, as well as their | |
45 sizes. </P> | |
46 */ | |
47 | |
48 public class BasicTypeDataBase implements TypeDataBase { | |
49 private MachineDescription machDesc; | |
50 private VtblAccess vtblAccess; | |
51 /** Maps strings to Type objects. This does not contain the primitive types. */ | |
52 private Map nameToTypeMap = new HashMap(); | |
53 /** Maps strings to Integers, used for enums, etc. */ | |
54 private Map nameToIntConstantMap = new HashMap(); | |
55 /** Maps strings to Longs, used for 32/64-bit constants, etc. */ | |
56 private Map nameToLongConstantMap = new HashMap(); | |
57 /** Primitive types. */ | |
58 private Type jbooleanType; | |
59 private Type jbyteType; | |
60 private Type jcharType; | |
61 private Type jdoubleType; | |
62 private Type jfloatType; | |
63 private Type jintType; | |
64 private Type jlongType; | |
65 private Type jshortType; | |
66 | |
67 /** For debugging */ | |
68 private static final boolean DEBUG; | |
69 static { | |
70 DEBUG = System.getProperty("sun.jvm.hotspot.types.basic.BasicTypeDataBase.DEBUG") != null; | |
71 } | |
72 | |
73 public BasicTypeDataBase(MachineDescription machDesc, VtblAccess vtblAccess) { | |
74 this.machDesc = machDesc; | |
75 this.vtblAccess = vtblAccess; | |
76 } | |
77 | |
78 public Type lookupType(String cTypeName) { | |
79 return lookupType(cTypeName, true); | |
80 } | |
81 | |
82 public Type lookupType(String cTypeName, boolean throwException) { | |
83 Type type = (Type) nameToTypeMap.get(cTypeName); | |
84 if (type == null && throwException) { | |
85 throw new RuntimeException("No type named \"" + cTypeName + "\" in database"); | |
86 } | |
87 return type; | |
88 } | |
89 | |
90 public Integer lookupIntConstant(String constantName) { | |
91 return lookupIntConstant(constantName, true); | |
92 } | |
93 | |
94 public Integer lookupIntConstant(String constantName, boolean throwException) { | |
95 Integer i = (Integer) nameToIntConstantMap.get(constantName); | |
96 if (i == null) { | |
97 if (throwException) { | |
98 throw new RuntimeException("No integer constant named \"" + constantName + "\" present in type database"); | |
99 } | |
100 } | |
101 return i; | |
102 } | |
103 | |
104 public Long lookupLongConstant(String constantName) { | |
105 return lookupLongConstant(constantName, true); | |
106 } | |
107 | |
108 public Long lookupLongConstant(String constantName, boolean throwException) { | |
109 Long i = (Long) nameToLongConstantMap.get(constantName); | |
110 if (i == null) { | |
111 if (throwException) { | |
112 throw new RuntimeException("No long constant named \"" + constantName + "\" present in type database"); | |
113 } | |
114 } | |
115 return i; | |
116 } | |
117 | |
118 public Type getJBooleanType() { | |
119 return jbooleanType; | |
120 } | |
121 | |
122 public Type getJByteType() { | |
123 return jbyteType; | |
124 } | |
125 | |
126 public Type getJCharType() { | |
127 return jcharType; | |
128 } | |
129 | |
130 public Type getJDoubleType() { | |
131 return jdoubleType; | |
132 } | |
133 | |
134 public Type getJFloatType() { | |
135 return jfloatType; | |
136 } | |
137 | |
138 public Type getJIntType() { | |
139 return jintType; | |
140 } | |
141 | |
142 public Type getJLongType() { | |
143 return jlongType; | |
144 } | |
145 | |
146 public Type getJShortType() { | |
147 return jshortType; | |
148 } | |
149 | |
150 public long getAddressSize() { | |
151 return machDesc.getAddressSize(); | |
152 } | |
153 | |
154 public long getOopSize() { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
155 return VM.getVM().getOopSize(); |
0 | 156 } |
157 | |
8755
117bb0519114
8009456: SA: typeToVtbl of BasicTypeDataBase should not be static
sla
parents:
3939
diff
changeset
|
158 HashMap typeToVtbl = new HashMap(); |
3939 | 159 |
160 private Address vtblForType(Type type) { | |
161 Address vtblAddr = (Address)typeToVtbl.get(type); | |
162 if (vtblAddr == null) { | |
163 vtblAddr = vtblAccess.getVtblForType(type); | |
164 if (vtblAddr != null) { | |
165 typeToVtbl.put(type, vtblAddr); | |
166 } | |
167 } | |
168 return vtblAddr; | |
169 } | |
170 | |
0 | 171 public boolean addressTypeIsEqualToType(Address addr, Type type) { |
172 if (addr == null) { | |
173 return false; | |
174 } | |
175 | |
176 // This implementation should be suitably platform-independent; we | |
177 // search nearby memory for the vtbl value of the given type. | |
178 | |
3939 | 179 Address vtblAddr = vtblForType(type); |
0 | 180 |
181 if (vtblAddr == null) { | |
182 // Type was not polymorphic, or an error occurred during lookup | |
183 if (DEBUG) { | |
184 System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: vtblAddr == null"); | |
185 } | |
186 | |
187 return false; | |
188 } | |
189 | |
190 // The first implementation searched three locations for this vtbl | |
191 // value; scanning through the entire object was considered, but | |
192 // we thought we knew where we were looking, and looking only in | |
193 // these specific locations should reduce the probability of | |
194 // mistaking random bits as a pointer (although, realistically | |
195 // speaking, the likelihood of finding a match between the bit | |
196 // pattern of, for example, a double and the vtbl is vanishingly | |
197 // small.) | |
198 // 1. The first word of the object (should handle MSVC++ as | |
199 // well as the SparcWorks compilers with compatibility set to | |
200 // v5.0 or greater) | |
201 // 2. and 3. The last two Address-aligned words of the part of | |
202 // the object defined by its topmost polymorphic superclass. | |
203 // This should handle the SparcWorks compilers, v4.2 or | |
204 // earlier, as well as any other compilers which place the vptr | |
205 // at the end of the user-defined fields of the first base | |
206 // class with virtual functions. | |
207 // | |
208 // Unfortunately this algorithm did not work properly for the | |
209 // specific case of the ThreadShadow/Thread inheritance situation, | |
210 // because the Solaris compiler seems to cleverly eliminate the | |
211 // vtbl for ThreadShadow since the only virtual is empty. (We | |
212 // should get rid of the ThreadShadow and fix the include | |
213 // databases, but need to postpone this for the present.) The | |
214 // current solution performs the three-location check for this | |
215 // class and all of its known superclasses rather than just the | |
216 // topmost polymorphic one. | |
217 | |
218 Type curType = type; | |
219 | |
220 try { | |
221 while (curType != null) { | |
222 // Using the size information we have for this type, check the | |
223 // three locations described above. | |
224 | |
225 // (1) | |
226 if (vtblAddr.equals(addr.getAddressAt(0))) { | |
227 return true; | |
228 } | |
229 | |
230 // (2) | |
231 long offset = curType.getSize(); | |
232 // I don't think this should be misaligned under any | |
233 // circumstances, but I'm not sure (FIXME: also not sure which | |
234 // way to go here, up or down -- assuming down) | |
235 offset -= (offset % getAddressSize()); | |
236 if (offset <= 0) { | |
237 return false; | |
238 } | |
239 if (vtblAddr.equals(addr.getAddressAt(offset))) { | |
240 return true; | |
241 } | |
242 offset -= getAddressSize(); | |
243 if (offset <= 0) { | |
244 return false; | |
245 } | |
246 if (vtblAddr.equals(addr.getAddressAt(offset))) { | |
247 return true; | |
248 } | |
249 | |
250 curType = curType.getSuperclass(); | |
251 } | |
252 } | |
253 catch (Exception e) { | |
254 // Any UnmappedAddressExceptions, etc. are a good indication | |
255 // that the pointer is not of the specified type | |
256 if (DEBUG) { | |
257 System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: exception occurred during lookup:"); | |
258 e.printStackTrace(); | |
259 } | |
260 | |
261 return false; | |
262 } | |
263 | |
264 if (DEBUG) { | |
265 System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: all vptr tests failed for type " + | |
266 type.getName()); | |
267 } | |
268 | |
269 return false; | |
270 } | |
271 | |
3939 | 272 public Type findDynamicTypeForAddress(Address addr, Type baseType) { |
273 // This implementation should be suitably platform-independent; we | |
274 // search nearby memory for the vtbl value of the given type. | |
275 | |
276 if (vtblForType(baseType) == null) { | |
277 // Type was not polymorphic which is an error of some sort | |
278 throw new InternalError(baseType + " does not appear to be polymorphic"); | |
279 } | |
280 | |
281 // This is a more restricted version of guessTypeForAddress since | |
282 // that function has some limitations since it doesn't really know | |
283 // where in the hierarchy a virtual type starts and just poking | |
284 // around in memory is likely to trip over some vtable address, | |
285 // resulting in false positives. Eventually all uses should | |
286 // switch to this logic but in the interests of stability it will | |
287 // be separate for the moment. | |
288 | |
289 // Assuming that the base type is truly the first polymorphic type | |
290 // then the vtbl for all subclasss should be at several defined | |
291 // locations so only those locations will be checked. It's also | |
292 // required that the caller knows that the static type is at least | |
293 // baseType. See the notes in guessTypeForAddress for the logic of | |
294 // the locations searched. | |
295 | |
296 Address loc1 = addr.getAddressAt(0); | |
297 Address loc2 = null; | |
298 Address loc3 = null; | |
299 long offset2 = baseType.getSize(); | |
300 // I don't think this should be misaligned under any | |
301 // circumstances, but I'm not sure (FIXME: also not sure which | |
302 // way to go here, up or down -- assuming down) | |
303 offset2 = offset2 - (offset2 % getAddressSize()) - getAddressSize(); | |
304 if (offset2 > 0) { | |
305 loc2 = addr.getAddressAt(offset2); | |
306 } | |
307 long offset3 = offset2 - getAddressSize(); | |
308 if (offset3 > 0) { | |
309 loc3 = addr.getAddressAt(offset3); | |
310 } | |
311 | |
312 Type loc2Match = null; | |
313 Type loc3Match = null; | |
314 for (Iterator iter = getTypes(); iter.hasNext(); ) { | |
315 Type type = (Type) iter.next(); | |
316 Type superClass = type; | |
317 while (superClass != baseType && superClass != null) { | |
318 superClass = superClass.getSuperclass(); | |
319 } | |
320 if (superClass == null) continue; | |
321 Address vtblAddr = vtblForType(type); | |
322 if (vtblAddr == null) { | |
323 // This occurs sometimes for intermediate types that are never | |
324 // instantiated. | |
325 if (DEBUG) { | |
326 System.err.println("null vtbl for " + type); | |
327 } | |
328 continue; | |
329 } | |
330 // Prefer loc1 match | |
331 if (vtblAddr.equals(loc1)) return type; | |
332 if (loc2 != null && loc2Match == null && vtblAddr.equals(loc2)) { | |
333 loc2Match = type; | |
334 } | |
335 if (loc3 != null && loc3Match == null && vtblAddr.equals(loc3)) { | |
336 loc3Match = type; | |
337 } | |
338 } | |
339 if (loc2Match != null) return loc2Match; | |
340 if (loc3Match != null) return loc3Match; | |
341 return null; | |
342 } | |
343 | |
0 | 344 public Type guessTypeForAddress(Address addr) { |
345 for (Iterator iter = getTypes(); iter.hasNext(); ) { | |
346 Type t = (Type) iter.next(); | |
347 if (addressTypeIsEqualToType(addr, t)) { | |
348 return t; | |
349 } | |
350 } | |
351 return null; | |
352 } | |
353 | |
354 public long cIntegerTypeMaxValue(long sizeInBytes, boolean isUnsigned) { | |
355 return machDesc.cIntegerTypeMaxValue(sizeInBytes, isUnsigned); | |
356 } | |
357 | |
358 public long cIntegerTypeMinValue(long sizeInBytes, boolean isUnsigned) { | |
359 return machDesc.cIntegerTypeMinValue(sizeInBytes, isUnsigned); | |
360 } | |
361 | |
362 public Iterator getTypes() { | |
363 return nameToTypeMap.values().iterator(); | |
364 } | |
365 | |
366 public Iterator getIntConstants() { | |
367 return nameToIntConstantMap.keySet().iterator(); | |
368 } | |
369 | |
370 public Iterator getLongConstants() { | |
371 return nameToLongConstantMap.keySet().iterator(); | |
372 } | |
373 | |
374 //-------------------------------------------------------------------------------- | |
375 // Public routines only for use by the database builder | |
376 // | |
377 | |
378 /** This method should only be called by the builder of the | |
379 TypeDataBase and at most once */ | |
380 public void setJBooleanType(Type type) { | |
381 jbooleanType = type; | |
382 } | |
383 | |
384 /** This method should only be called by the builder of the | |
385 TypeDataBase and at most once */ | |
386 public void setJByteType(Type type) { | |
387 jbyteType = type; | |
388 } | |
389 | |
390 /** This method should only be called by the builder of the | |
391 TypeDataBase and at most once */ | |
392 public void setJCharType(Type type) { | |
393 jcharType = type; | |
394 } | |
395 | |
396 /** This method should only be called by the builder of the | |
397 TypeDataBase and at most once */ | |
398 public void setJDoubleType(Type type) { | |
399 jdoubleType = type; | |
400 } | |
401 | |
402 /** This method should only be called by the builder of the | |
403 TypeDataBase and at most once */ | |
404 public void setJFloatType(Type type) { | |
405 jfloatType = type; | |
406 } | |
407 | |
408 /** This method should only be called by the builder of the | |
409 TypeDataBase and at most once */ | |
410 public void setJIntType(Type type) { | |
411 jintType = type; | |
412 } | |
413 | |
414 /** This method should only be called by the builder of the | |
415 TypeDataBase and at most once */ | |
416 public void setJLongType(Type type) { | |
417 jlongType = type; | |
418 } | |
419 | |
420 /** This method should only be called by the builder of the | |
421 TypeDataBase and at most once */ | |
422 public void setJShortType(Type type) { | |
423 jshortType = type; | |
424 } | |
425 | |
426 /** This method should only be used by the builder of the | |
427 TypeDataBase. Throws a RuntimeException if a class with this | |
428 name was already present. */ | |
429 public void addType(Type type) { | |
430 if (nameToTypeMap.get(type.getName()) != null) { | |
431 throw new RuntimeException("type of name \"" + type.getName() + "\" already present"); | |
432 } | |
433 | |
434 nameToTypeMap.put(type.getName(), type); | |
435 } | |
436 | |
437 /** This method should only be used by the builder of the | |
438 TypeDataBase. Throws a RuntimeException if this class was not | |
439 present. */ | |
440 public void removeType(Type type) { | |
441 Type curType = (Type) nameToTypeMap.get(type.getName()); | |
442 if (curType == null) { | |
443 throw new RuntimeException("type of name \"" + type.getName() + "\" not present"); | |
444 } | |
445 | |
446 if (!curType.equals(type)) { | |
447 throw new RuntimeException("a different type of name \"" + type.getName() + "\" was present"); | |
448 } | |
449 | |
450 nameToTypeMap.remove(type.getName()); | |
451 } | |
452 | |
453 /** This method should only be used by the builder of the | |
454 TypeDataBase. Throws a RuntimeException if an integer constant | |
455 with this name was already present. */ | |
456 public void addIntConstant(String name, int value) { | |
457 if (nameToIntConstantMap.get(name) != null) { | |
458 throw new RuntimeException("int constant of name \"" + name + "\" already present"); | |
459 } | |
460 | |
461 nameToIntConstantMap.put(name, new Integer(value)); | |
462 } | |
463 | |
464 /** This method should only be used by the builder of the | |
465 TypeDataBase. Throws a RuntimeException if an integer constant | |
466 with this name was not present. */ | |
467 public void removeIntConstant(String name) { | |
468 Integer curConstant = (Integer) nameToIntConstantMap.get(name); | |
469 if (curConstant == null) { | |
470 throw new RuntimeException("int constant of name \"" + name + "\" not present"); | |
471 } | |
472 | |
473 nameToIntConstantMap.remove(name); | |
474 } | |
475 | |
476 /** This method should only be used by the builder of the | |
477 TypeDataBase. Throws a RuntimeException if a long constant with | |
478 this name was already present. */ | |
479 public void addLongConstant(String name, long value) { | |
480 if (nameToLongConstantMap.get(name) != null) { | |
481 throw new RuntimeException("long constant of name \"" + name + "\" already present"); | |
482 } | |
483 | |
484 nameToLongConstantMap.put(name, new Long(value)); | |
485 } | |
486 | |
487 /** This method should only be used by the builder of the | |
488 TypeDataBase. Throws a RuntimeException if a long constant with | |
489 this name was not present. */ | |
490 public void removeLongConstant(String name) { | |
491 Long curConstant = (Long) nameToLongConstantMap.get(name); | |
492 if (curConstant == null) { | |
493 throw new RuntimeException("long constant of name \"" + name + "\" not present"); | |
494 } | |
495 | |
496 nameToLongConstantMap.remove(name); | |
497 } | |
498 } |