Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @ 271:818a18cd69a8
6730514: assertion failure in mangling code when expanding by 0 bytes
Summary: An expansion by 0 bytes was not anticipated when the assertion was composed.
Reviewed-by: jjh, jcoomes, apetrusenko
author | jmasa |
---|---|
date | Wed, 30 Jul 2008 11:54:00 -0700 |
parents | d1605aabd0a1 |
children | f30ba3b36599 |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 2000-2008 Sun Microsystems, Inc. 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 * | |
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; | |
26 | |
27 import java.io.*; | |
28 import java.util.*; | |
29 import sun.jvm.hotspot.debugger.*; | |
30 import sun.jvm.hotspot.types.*; | |
31 import sun.jvm.hotspot.types.basic.*; | |
32 import sun.jvm.hotspot.utilities.*; | |
33 | |
34 /** <P> This is the cross-platform TypeDataBase used by the Oop | |
35 hierarchy. The decision was made to make this cross-platform by | |
36 having the VM export the necessary symbols via a built-in table; | |
37 see src/share/vm/runtime/vmStructs.[ch]pp for more details. </P> | |
38 | |
39 <P> <B>WARNING</B>: clients should refer to this class through the | |
40 TypeDataBase interface and not directly to the HotSpotTypeDataBase | |
41 type. </P> | |
42 | |
43 <P> NOTE: since we are fetching the sizes of the Java primitive types | |
44 */ | |
45 | |
46 public class HotSpotTypeDataBase extends BasicTypeDataBase { | |
47 private Debugger symbolLookup; | |
48 private String[] jvmLibNames; | |
49 private static final int UNINITIALIZED_SIZE = -1; | |
50 private static final int C_INT8_SIZE = 1; | |
51 private static final int C_INT32_SIZE = 4; | |
52 private static final int C_INT64_SIZE = 8; | |
53 | |
54 private static final boolean DEBUG; | |
55 static { | |
56 DEBUG = System.getProperty("sun.jvm.hotspot.HotSpotTypeDataBase.DEBUG") | |
57 != null; | |
58 } | |
59 | |
60 /** <P> This requires a SymbolLookup mechanism as well as the | |
61 MachineDescription. Note that we do not need a NameMangler since | |
62 we use the vmStructs mechanism to avoid looking up C++ | |
63 symbols. </P> | |
64 | |
65 <P> NOTE that it is guaranteed that this constructor will not | |
66 attempt to fetch any Java values from the remote process, only C | |
67 integers and addresses. This is required because we are fetching | |
68 the sizes of the Java primitive types from the remote process, | |
69 implying that attempting to fetch them before their sizes are | |
70 known is illegal. </P> | |
71 | |
72 <P> Throws NoSuchSymbolException if a problem occurred while | |
73 looking up one of the bootstrapping symbols related to the | |
74 VMStructs table in the remote VM; this may indicate that the | |
75 remote process is not actually a HotSpot VM. </P> | |
76 */ | |
77 public HotSpotTypeDataBase(MachineDescription machDesc, | |
78 VtblAccess vtblAccess, | |
79 Debugger symbolLookup, | |
80 String[] jvmLibNames) throws NoSuchSymbolException { | |
81 super(machDesc, vtblAccess); | |
82 this.symbolLookup = symbolLookup; | |
83 this.jvmLibNames = jvmLibNames; | |
84 | |
85 readVMTypes(); | |
86 initializePrimitiveTypes(); | |
87 readVMStructs(); | |
88 readVMIntConstants(); | |
89 readVMLongConstants(); | |
90 } | |
91 | |
92 private void readVMTypes() { | |
93 // Get the variables we need in order to traverse the VMTypeEntry[] | |
94 long typeEntryTypeNameOffset; | |
95 long typeEntrySuperclassNameOffset; | |
96 long typeEntryIsOopTypeOffset; | |
97 long typeEntryIsIntegerTypeOffset; | |
98 long typeEntryIsUnsignedOffset; | |
99 long typeEntrySizeOffset; | |
100 long typeEntryArrayStride; | |
101 | |
102 typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); | |
103 typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); | |
104 typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); | |
105 typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); | |
106 typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); | |
107 typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); | |
108 typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); | |
109 | |
110 // Fetch the address of the VMTypeEntry* | |
111 Address entryAddr = lookupInProcess("gHotSpotVMTypes"); | |
112 // System.err.println("gHotSpotVMTypes address = " + entryAddr); | |
113 // Dereference this once to get the pointer to the first VMTypeEntry | |
114 // dumpMemory(entryAddr, 80); | |
115 entryAddr = entryAddr.getAddressAt(0); | |
116 | |
117 if (entryAddr == null) { | |
118 throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); | |
119 } | |
120 | |
121 // Start iterating down it until we find an entry with no name | |
122 Address typeNameAddr = null; | |
123 do { | |
124 // Fetch the type name first | |
125 typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset); | |
126 if (typeNameAddr != null) { | |
127 String typeName = CStringUtilities.getString(typeNameAddr); | |
128 | |
129 String superclassName = null; | |
130 Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset); | |
131 if (superclassNameAddr != null) { | |
132 superclassName = CStringUtilities.getString(superclassNameAddr); | |
133 } | |
134 | |
135 boolean isOopType = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0); | |
136 boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0); | |
137 boolean isUnsigned = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0); | |
138 long size = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true); | |
139 | |
140 createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size); | |
141 } | |
142 | |
143 entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); | |
144 } while (typeNameAddr != null); | |
145 } | |
146 | |
147 private void initializePrimitiveTypes() { | |
148 // Look up the needed primitive types by name...they had better be present | |
149 setJBooleanType(lookupPrimitiveType("jboolean")); | |
150 setJByteType (lookupPrimitiveType("jbyte")); | |
151 setJCharType (lookupPrimitiveType("jchar")); | |
152 setJDoubleType (lookupPrimitiveType("jdouble")); | |
153 setJFloatType (lookupPrimitiveType("jfloat")); | |
154 setJIntType (lookupPrimitiveType("jint")); | |
155 setJLongType (lookupPrimitiveType("jlong")); | |
156 setJShortType (lookupPrimitiveType("jshort")); | |
157 | |
158 // Indicate that these are the Java primitive types | |
159 ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true); | |
160 ((BasicType) getJByteType()).setIsJavaPrimitiveType(true); | |
161 ((BasicType) getJCharType()).setIsJavaPrimitiveType(true); | |
162 ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true); | |
163 ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true); | |
164 ((BasicType) getJIntType()).setIsJavaPrimitiveType(true); | |
165 ((BasicType) getJLongType()).setIsJavaPrimitiveType(true); | |
166 ((BasicType) getJShortType()).setIsJavaPrimitiveType(true); | |
167 } | |
168 | |
169 private Type lookupPrimitiveType(String typeName) { | |
170 Type type = lookupType(typeName, false); | |
171 if (type == null) { | |
172 throw new RuntimeException("Error initializing the HotSpotDataBase: could not find the primitive type \"" + | |
173 typeName + "\" in the remote VM's VMStructs table. This type is required in " + | |
174 "order to determine the size of Java primitive types. Can not continue."); | |
175 } | |
176 return type; | |
177 } | |
178 | |
179 private void readVMStructs() { | |
180 // Get the variables we need in order to traverse the VMStructEntry[] | |
181 long structEntryTypeNameOffset; | |
182 long structEntryFieldNameOffset; | |
183 long structEntryTypeStringOffset; | |
184 long structEntryIsStaticOffset; | |
185 long structEntryOffsetOffset; | |
186 long structEntryAddressOffset; | |
187 long structEntryArrayStride; | |
188 | |
189 structEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset"); | |
190 structEntryFieldNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset"); | |
191 structEntryTypeStringOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset"); | |
192 structEntryIsStaticOffset = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset"); | |
193 structEntryOffsetOffset = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset"); | |
194 structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); | |
195 structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); | |
196 | |
197 // Fetch the address of the VMStructEntry* | |
198 Address entryAddr = lookupInProcess("gHotSpotVMStructs"); | |
199 // Dereference this once to get the pointer to the first VMStructEntry | |
200 entryAddr = entryAddr.getAddressAt(0); | |
201 if (entryAddr == null) { | |
202 throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue"); | |
203 } | |
204 | |
205 // Start iterating down it until we find an entry with no name | |
206 Address fieldNameAddr = null; | |
207 String typeName = null; | |
208 String fieldName = null; | |
209 String typeString = null; | |
210 boolean isStatic = false; | |
211 long offset = 0; | |
212 Address staticFieldAddr = null; | |
213 long size = 0; | |
214 long index = 0; | |
215 String opaqueName = "<opaque>"; | |
216 lookupOrCreateClass(opaqueName, false, false, false); | |
217 | |
218 do { | |
219 // Fetch the field name first | |
220 fieldNameAddr = entryAddr.getAddressAt(structEntryFieldNameOffset); | |
221 if (fieldNameAddr != null) { | |
222 fieldName = CStringUtilities.getString(fieldNameAddr); | |
223 | |
224 // Now the rest of the names. Keep in mind that the type name | |
225 // may be NULL, indicating that the type is opaque. | |
226 Address addr = entryAddr.getAddressAt(structEntryTypeNameOffset); | |
227 if (addr == null) { | |
228 throw new RuntimeException("gHotSpotVMStructs unexpectedly had a NULL type name at index " + index); | |
229 } | |
230 typeName = CStringUtilities.getString(addr); | |
231 | |
232 addr = entryAddr.getAddressAt(structEntryTypeStringOffset); | |
233 if (addr == null) { | |
234 typeString = opaqueName; | |
235 } else { | |
236 typeString = CStringUtilities.getString(addr); | |
237 } | |
238 | |
239 isStatic = !(entryAddr.getCIntegerAt(structEntryIsStaticOffset, C_INT32_SIZE, false) == 0); | |
240 if (isStatic) { | |
241 staticFieldAddr = entryAddr.getAddressAt(structEntryAddressOffset); | |
242 offset = 0; | |
243 } else { | |
244 offset = entryAddr.getCIntegerAt(structEntryOffsetOffset, C_INT64_SIZE, true); | |
245 staticFieldAddr = null; | |
246 } | |
247 | |
248 // The containing Type must already be in the database -- no exceptions | |
249 BasicType containingType = lookupOrFail(typeName); | |
250 | |
251 // The field's Type must already be in the database -- no exceptions | |
252 BasicType fieldType = lookupOrFail(typeString); | |
253 | |
254 // Create field by type | |
255 createField(containingType, fieldName, fieldType, | |
256 isStatic, offset, staticFieldAddr); | |
257 } | |
258 | |
259 ++index; | |
260 entryAddr = entryAddr.addOffsetTo(structEntryArrayStride); | |
261 } while (fieldNameAddr != null); | |
262 } | |
263 | |
264 private void readVMIntConstants() { | |
265 // Get the variables we need in order to traverse the VMIntConstantEntry[] | |
266 long intConstantEntryNameOffset; | |
267 long intConstantEntryValueOffset; | |
268 long intConstantEntryArrayStride; | |
269 | |
270 intConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset"); | |
271 intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); | |
272 intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); | |
273 | |
274 // Fetch the address of the VMIntConstantEntry* | |
275 Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); | |
276 // Dereference this once to get the pointer to the first VMIntConstantEntry | |
277 entryAddr = entryAddr.getAddressAt(0); | |
278 if (entryAddr == null) { | |
279 throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue"); | |
280 } | |
281 | |
282 // Start iterating down it until we find an entry with no name | |
283 Address nameAddr = null; | |
284 do { | |
285 // Fetch the type name first | |
286 nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset); | |
287 if (nameAddr != null) { | |
288 String name = CStringUtilities.getString(nameAddr); | |
289 int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false); | |
290 | |
291 // Be a little resilient | |
292 Integer oldValue = lookupIntConstant(name, false); | |
293 if (oldValue == null) { | |
294 addIntConstant(name, value); | |
295 } else { | |
296 if (oldValue.intValue() != value) { | |
297 throw new RuntimeException("Error: the integer constant \"" + name + | |
298 "\" had its value redefined (old was " + oldValue + | |
299 ", new is " + value + ". Aborting."); | |
300 } else { | |
301 System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + | |
302 "had its value declared as " + value + " twice. Continuing."); | |
303 } | |
304 } | |
305 } | |
306 | |
307 entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); | |
308 } while (nameAddr != null); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
309 String symbol = "heapOopSize"; // global int constant and value is initialized at runtime. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
310 addIntConstant(symbol, (int)lookupInProcess(symbol).getCIntegerAt(0, 4, false)); |
0 | 311 } |
312 | |
313 private void readVMLongConstants() { | |
314 // Get the variables we need in order to traverse the VMLongConstantEntry[] | |
315 long longConstantEntryNameOffset; | |
316 long longConstantEntryValueOffset; | |
317 long longConstantEntryArrayStride; | |
318 | |
319 longConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset"); | |
320 longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); | |
321 longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); | |
322 | |
323 // Fetch the address of the VMLongConstantEntry* | |
324 Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); | |
325 // Dereference this once to get the pointer to the first VMLongConstantEntry | |
326 entryAddr = entryAddr.getAddressAt(0); | |
327 if (entryAddr == null) { | |
328 throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue"); | |
329 } | |
330 | |
331 // Start iterating down it until we find an entry with no name | |
332 Address nameAddr = null; | |
333 do { | |
334 // Fetch the type name first | |
335 nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset); | |
336 if (nameAddr != null) { | |
337 String name = CStringUtilities.getString(nameAddr); | |
338 int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true); | |
339 | |
340 // Be a little resilient | |
341 Long oldValue = lookupLongConstant(name, false); | |
342 if (oldValue == null) { | |
343 addLongConstant(name, value); | |
344 } else { | |
345 if (oldValue.longValue() != value) { | |
346 throw new RuntimeException("Error: the long constant \"" + name + | |
347 "\" had its value redefined (old was " + oldValue + | |
348 ", new is " + value + ". Aborting."); | |
349 } else { | |
350 System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + | |
351 "had its value declared as " + value + " twice. Continuing."); | |
352 } | |
353 } | |
354 } | |
355 | |
356 entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); | |
357 } while (nameAddr != null); | |
358 } | |
359 | |
360 private BasicType lookupOrFail(String typeName) { | |
361 BasicType type = (BasicType) lookupType(typeName, false); | |
362 if (type == null) { | |
363 throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " + | |
364 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " + | |
365 "in the debug build of that VM). Can not continue."); | |
366 } | |
367 return type; | |
368 } | |
369 | |
370 private long getLongValueFromProcess(String symbol) { | |
371 return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true); | |
372 } | |
373 | |
374 private Address lookupInProcess(String symbol) throws NoSuchSymbolException { | |
375 // FIXME: abstract away the loadobject name | |
376 for (int i = 0; i < jvmLibNames.length; i++) { | |
377 Address addr = symbolLookup.lookup(jvmLibNames[i], symbol); | |
378 if (addr != null) { | |
379 return addr; | |
380 } | |
381 } | |
382 String errStr = "("; | |
383 for (int i = 0; i < jvmLibNames.length; i++) { | |
384 errStr += jvmLibNames[i]; | |
385 if (i < jvmLibNames.length - 1) { | |
386 errStr += ", "; | |
387 } | |
388 } | |
389 errStr += ")"; | |
390 throw new NoSuchSymbolException(symbol, | |
391 "Could not find symbol \"" + symbol + | |
392 "\" in any of the known library names " + | |
393 errStr); | |
394 } | |
395 | |
396 private BasicType lookupOrCreateClass(String typeName, boolean isOopType, | |
397 boolean isIntegerType, boolean isUnsigned) { | |
398 BasicType type = (BasicType) lookupType(typeName, false); | |
399 if (type == null) { | |
400 // Create a new type | |
401 type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned); | |
402 } | |
403 return type; | |
404 } | |
405 | |
406 /** Creates a new BasicType, initializes its size to -1 so we can | |
407 test to ensure that all types' sizes are initialized by VMTypes, | |
408 and adds it to the database. Takes care of initializing integer | |
409 and oop types properly. */ | |
410 private BasicType createBasicType(String typeName, boolean isOopType, | |
411 boolean isIntegerType, boolean isUnsigned) { | |
412 | |
413 BasicType type = null; | |
414 | |
415 if (isIntegerType) { | |
416 type = new BasicCIntegerType(this, typeName, isUnsigned); | |
417 } else { | |
418 if (typeNameIsPointerType(typeName)) { | |
419 type = recursiveCreateBasicPointerType(typeName); | |
420 } else { | |
421 type = new BasicType(this, typeName); | |
422 } | |
423 | |
424 if (isOopType) { | |
425 // HACK: turn markOop into a C integer type. This allows | |
426 // proper handling of it in the Serviceability Agent. (FIXME | |
427 // -- consider doing something different here) | |
428 if (typeName.equals("markOop")) { | |
429 type = new BasicCIntegerType(this, typeName, true); | |
430 } else { | |
431 type.setIsOopType(true); | |
432 } | |
433 } | |
434 } | |
435 | |
436 type.setSize(UNINITIALIZED_SIZE); | |
437 addType(type); | |
438 return type; | |
439 } | |
440 | |
441 /** Recursively creates a PointerType from the string representation | |
442 of the type's name. Note that this currently needs some | |
443 workarounds due to incomplete information in the VMStructs | |
444 database. */ | |
445 private BasicPointerType recursiveCreateBasicPointerType(String typeName) { | |
446 String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); | |
447 Type targetType = null; | |
448 if (typeNameIsPointerType(targetTypeName)) { | |
449 targetType = recursiveCreateBasicPointerType(targetTypeName); | |
450 } else { | |
451 targetType = lookupType(targetTypeName, false); | |
452 if (targetType == null) { | |
453 // Workaround for missing C integer types in database. | |
454 // Also looks like we can't throw an exception for other | |
455 // missing target types because there are some in old | |
456 // VMStructs tables that didn't have the target type declared. | |
457 // For this case, we create basic types that never get filled | |
458 // in. | |
459 | |
460 if (targetTypeName.equals("char") || | |
461 targetTypeName.equals("const char")) { | |
462 // We don't have a representation of const-ness of C types in the SA | |
463 BasicType basicTargetType = createBasicType(targetTypeName, false, true, false); | |
464 basicTargetType.setSize(1); | |
465 targetType = basicTargetType; | |
466 } else if (targetTypeName.equals("u_char")) { | |
467 BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); | |
468 basicTargetType.setSize(1); | |
469 targetType = basicTargetType; | |
470 } else { | |
471 if (DEBUG) { | |
472 System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); | |
473 } | |
474 targetType = createBasicType(targetTypeName, false, false, false); | |
475 } | |
476 } | |
477 } | |
478 return new BasicPointerType(this, typeName, targetType); | |
479 } | |
480 | |
481 private boolean typeNameIsPointerType(String typeName) { | |
482 int i = typeName.length() - 1; | |
483 while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) { | |
484 --i; | |
485 } | |
486 if (i >= 0 && typeName.charAt(i) == '*') { | |
487 return true; | |
488 } | |
489 return false; | |
490 } | |
491 | |
492 public void createType(String typeName, String superclassName, | |
493 boolean isOopType, boolean isIntegerType, | |
494 boolean isUnsigned, long size) { | |
495 // See whether we have a superclass | |
496 BasicType superclass = null; | |
497 if (superclassName != null) { | |
498 // Fetch or create it (FIXME: would get oop types wrong if | |
499 // they had a hierarchy; consider using lookupOrFail) | |
500 superclass = lookupOrCreateClass(superclassName, false, false, false); | |
501 } | |
502 | |
503 // Lookup or create the current type | |
504 BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned); | |
505 // Set superclass and/or ensure it's correct | |
506 if (superclass != null) { | |
507 if (curType.getSuperclass() == null) { | |
508 // Set the superclass in the current type | |
509 curType.setSuperclass(superclass); | |
510 } | |
511 | |
512 if (curType.getSuperclass() != superclass) { | |
513 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
514 "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " + | |
515 superclass.getName() + ")."); | |
516 } | |
517 } | |
518 | |
519 // Classes are created with a size of UNINITIALIZED_SIZE. | |
520 // Set size if necessary. | |
521 if (curType.getSize() == UNINITIALIZED_SIZE) { | |
522 curType.setSize(size); | |
523 } else { | |
524 if (curType.getSize() != size) { | |
525 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
526 "had its size redefined (old was " + curType.getSize() + ", new is " + size + ")."); | |
527 } | |
528 | |
529 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
530 "had its size declared as " + size + " twice. Continuing."); | |
531 } | |
532 | |
533 } | |
534 | |
535 /** "Virtual constructor" for fields based on type */ | |
536 public void createField(BasicType containingType, | |
537 String name, Type type, boolean isStatic, | |
538 long offset, Address staticFieldAddress) { | |
539 // Add field to containing type | |
540 containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress)); | |
541 } | |
542 | |
543 Field internalCreateField(BasicType containingType, | |
544 String name, Type type, boolean isStatic, | |
545 long offset, Address staticFieldAddress) { | |
546 // "Virtual constructor" based on type | |
547 if (type.isOopType()) { | |
548 return new BasicOopField(this, containingType, name, type, | |
549 isStatic, offset, staticFieldAddress); | |
550 } | |
551 | |
552 if (type instanceof CIntegerType) { | |
553 return new BasicCIntegerField(this, containingType, name, type, | |
554 isStatic, offset, staticFieldAddress); | |
555 } | |
556 | |
557 if (type.equals(getJBooleanType())) { | |
558 return new BasicJBooleanField(this, containingType, name, type, | |
559 isStatic, offset, staticFieldAddress); | |
560 } | |
561 | |
562 if (type.equals(getJByteType())) { | |
563 return new BasicJByteField(this, containingType, name, type, | |
564 isStatic, offset, staticFieldAddress); | |
565 } | |
566 | |
567 if (type.equals(getJCharType())) { | |
568 return new BasicJCharField(this, containingType, name, type, | |
569 isStatic, offset, staticFieldAddress); | |
570 } | |
571 | |
572 if (type.equals(getJDoubleType())) { | |
573 return new BasicJDoubleField(this, containingType, name, type, | |
574 isStatic, offset, staticFieldAddress); | |
575 } | |
576 | |
577 if (type.equals(getJFloatType())) { | |
578 return new BasicJFloatField(this, containingType, name, type, | |
579 isStatic, offset, staticFieldAddress); | |
580 } | |
581 | |
582 if (type.equals(getJIntType())) { | |
583 return new BasicJIntField(this, containingType, name, type, | |
584 isStatic, offset, staticFieldAddress); | |
585 } | |
586 | |
587 if (type.equals(getJLongType())) { | |
588 return new BasicJLongField(this, containingType, name, type, | |
589 isStatic, offset, staticFieldAddress); | |
590 } | |
591 | |
592 if (type.equals(getJShortType())) { | |
593 return new BasicJShortField(this, containingType, name, type, | |
594 isStatic, offset, staticFieldAddress); | |
595 } | |
596 | |
597 // Unknown ("opaque") type. Instantiate ordinary Field. | |
598 return new BasicField(this, containingType, name, type, | |
599 isStatic, offset, staticFieldAddress); | |
600 } | |
601 | |
602 // For debugging | |
603 private void dumpMemory(Address addr, int len) { | |
604 int i = 0; | |
605 while (i < len) { | |
606 System.err.print(addr.addOffsetTo(i) + ":"); | |
607 for (int j = 0; j < 8 && i < len; i++, j++) { | |
608 String s = Long.toHexString(addr.getCIntegerAt(i, 1, true)); | |
609 System.err.print(" 0x"); | |
610 for (int k = 0; k < 2 - s.length(); k++) { | |
611 System.err.print("0"); | |
612 } | |
613 System.err.print(s); | |
614 } | |
615 System.err.println(); | |
616 } | |
617 } | |
618 } |