Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @ 1913:3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
Summary: Allow CONSTANT_InvokeDynamic nodes to have any number of extra operands.
Reviewed-by: twisti
author | jrose |
---|---|
date | Sat, 30 Oct 2010 13:08:23 -0700 |
parents | c18cbe5936b8 |
children | d6cd0d55d0b5 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
2 * Copyright (c) 2000, 2009, 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:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
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:
844
diff
changeset
|
21 * questions. |
0 | 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); | |
309 } | |
310 | |
311 private void readVMLongConstants() { | |
312 // Get the variables we need in order to traverse the VMLongConstantEntry[] | |
313 long longConstantEntryNameOffset; | |
314 long longConstantEntryValueOffset; | |
315 long longConstantEntryArrayStride; | |
316 | |
317 longConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset"); | |
318 longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); | |
319 longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); | |
320 | |
321 // Fetch the address of the VMLongConstantEntry* | |
322 Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); | |
323 // Dereference this once to get the pointer to the first VMLongConstantEntry | |
324 entryAddr = entryAddr.getAddressAt(0); | |
325 if (entryAddr == null) { | |
326 throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue"); | |
327 } | |
328 | |
329 // Start iterating down it until we find an entry with no name | |
330 Address nameAddr = null; | |
331 do { | |
332 // Fetch the type name first | |
333 nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset); | |
334 if (nameAddr != null) { | |
335 String name = CStringUtilities.getString(nameAddr); | |
336 int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true); | |
337 | |
338 // Be a little resilient | |
339 Long oldValue = lookupLongConstant(name, false); | |
340 if (oldValue == null) { | |
341 addLongConstant(name, value); | |
342 } else { | |
343 if (oldValue.longValue() != value) { | |
344 throw new RuntimeException("Error: the long constant \"" + name + | |
345 "\" had its value redefined (old was " + oldValue + | |
346 ", new is " + value + ". Aborting."); | |
347 } else { | |
348 System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + | |
349 "had its value declared as " + value + " twice. Continuing."); | |
350 } | |
351 } | |
352 } | |
353 | |
354 entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); | |
355 } while (nameAddr != null); | |
356 } | |
357 | |
358 private BasicType lookupOrFail(String typeName) { | |
359 BasicType type = (BasicType) lookupType(typeName, false); | |
360 if (type == null) { | |
361 throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " + | |
362 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " + | |
363 "in the debug build of that VM). Can not continue."); | |
364 } | |
365 return type; | |
366 } | |
367 | |
368 private long getLongValueFromProcess(String symbol) { | |
369 return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true); | |
370 } | |
371 | |
372 private Address lookupInProcess(String symbol) throws NoSuchSymbolException { | |
373 // FIXME: abstract away the loadobject name | |
374 for (int i = 0; i < jvmLibNames.length; i++) { | |
375 Address addr = symbolLookup.lookup(jvmLibNames[i], symbol); | |
376 if (addr != null) { | |
377 return addr; | |
378 } | |
379 } | |
380 String errStr = "("; | |
381 for (int i = 0; i < jvmLibNames.length; i++) { | |
382 errStr += jvmLibNames[i]; | |
383 if (i < jvmLibNames.length - 1) { | |
384 errStr += ", "; | |
385 } | |
386 } | |
387 errStr += ")"; | |
388 throw new NoSuchSymbolException(symbol, | |
389 "Could not find symbol \"" + symbol + | |
390 "\" in any of the known library names " + | |
391 errStr); | |
392 } | |
393 | |
394 private BasicType lookupOrCreateClass(String typeName, boolean isOopType, | |
395 boolean isIntegerType, boolean isUnsigned) { | |
396 BasicType type = (BasicType) lookupType(typeName, false); | |
397 if (type == null) { | |
398 // Create a new type | |
399 type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned); | |
400 } | |
401 return type; | |
402 } | |
403 | |
404 /** Creates a new BasicType, initializes its size to -1 so we can | |
405 test to ensure that all types' sizes are initialized by VMTypes, | |
406 and adds it to the database. Takes care of initializing integer | |
407 and oop types properly. */ | |
408 private BasicType createBasicType(String typeName, boolean isOopType, | |
409 boolean isIntegerType, boolean isUnsigned) { | |
410 | |
411 BasicType type = null; | |
412 | |
413 if (isIntegerType) { | |
414 type = new BasicCIntegerType(this, typeName, isUnsigned); | |
415 } else { | |
416 if (typeNameIsPointerType(typeName)) { | |
417 type = recursiveCreateBasicPointerType(typeName); | |
418 } else { | |
419 type = new BasicType(this, typeName); | |
420 } | |
421 | |
422 if (isOopType) { | |
423 // HACK: turn markOop into a C integer type. This allows | |
424 // proper handling of it in the Serviceability Agent. (FIXME | |
425 // -- consider doing something different here) | |
426 if (typeName.equals("markOop")) { | |
427 type = new BasicCIntegerType(this, typeName, true); | |
428 } else { | |
429 type.setIsOopType(true); | |
430 } | |
431 } | |
432 } | |
433 | |
434 type.setSize(UNINITIALIZED_SIZE); | |
435 addType(type); | |
436 return type; | |
437 } | |
438 | |
439 /** Recursively creates a PointerType from the string representation | |
440 of the type's name. Note that this currently needs some | |
441 workarounds due to incomplete information in the VMStructs | |
442 database. */ | |
443 private BasicPointerType recursiveCreateBasicPointerType(String typeName) { | |
444 String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); | |
445 Type targetType = null; | |
446 if (typeNameIsPointerType(targetTypeName)) { | |
447 targetType = recursiveCreateBasicPointerType(targetTypeName); | |
448 } else { | |
449 targetType = lookupType(targetTypeName, false); | |
450 if (targetType == null) { | |
451 // Workaround for missing C integer types in database. | |
452 // Also looks like we can't throw an exception for other | |
453 // missing target types because there are some in old | |
454 // VMStructs tables that didn't have the target type declared. | |
455 // For this case, we create basic types that never get filled | |
456 // in. | |
457 | |
458 if (targetTypeName.equals("char") || | |
459 targetTypeName.equals("const char")) { | |
460 // We don't have a representation of const-ness of C types in the SA | |
461 BasicType basicTargetType = createBasicType(targetTypeName, false, true, false); | |
462 basicTargetType.setSize(1); | |
463 targetType = basicTargetType; | |
464 } else if (targetTypeName.equals("u_char")) { | |
465 BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); | |
466 basicTargetType.setSize(1); | |
467 targetType = basicTargetType; | |
468 } else { | |
469 if (DEBUG) { | |
470 System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); | |
471 } | |
472 targetType = createBasicType(targetTypeName, false, false, false); | |
473 } | |
474 } | |
475 } | |
476 return new BasicPointerType(this, typeName, targetType); | |
477 } | |
478 | |
479 private boolean typeNameIsPointerType(String typeName) { | |
480 int i = typeName.length() - 1; | |
481 while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) { | |
482 --i; | |
483 } | |
484 if (i >= 0 && typeName.charAt(i) == '*') { | |
485 return true; | |
486 } | |
487 return false; | |
488 } | |
489 | |
490 public void createType(String typeName, String superclassName, | |
491 boolean isOopType, boolean isIntegerType, | |
492 boolean isUnsigned, long size) { | |
493 // See whether we have a superclass | |
494 BasicType superclass = null; | |
495 if (superclassName != null) { | |
496 // Fetch or create it (FIXME: would get oop types wrong if | |
497 // they had a hierarchy; consider using lookupOrFail) | |
498 superclass = lookupOrCreateClass(superclassName, false, false, false); | |
499 } | |
500 | |
501 // Lookup or create the current type | |
502 BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned); | |
503 // Set superclass and/or ensure it's correct | |
504 if (superclass != null) { | |
505 if (curType.getSuperclass() == null) { | |
506 // Set the superclass in the current type | |
507 curType.setSuperclass(superclass); | |
508 } | |
509 | |
510 if (curType.getSuperclass() != superclass) { | |
511 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
512 "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " + | |
513 superclass.getName() + ")."); | |
514 } | |
515 } | |
516 | |
517 // Classes are created with a size of UNINITIALIZED_SIZE. | |
518 // Set size if necessary. | |
519 if (curType.getSize() == UNINITIALIZED_SIZE) { | |
520 curType.setSize(size); | |
521 } else { | |
522 if (curType.getSize() != size) { | |
523 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
524 "had its size redefined (old was " + curType.getSize() + ", new is " + size + ")."); | |
525 } | |
526 | |
527 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
528 "had its size declared as " + size + " twice. Continuing."); | |
529 } | |
530 | |
531 } | |
532 | |
533 /** "Virtual constructor" for fields based on type */ | |
534 public void createField(BasicType containingType, | |
535 String name, Type type, boolean isStatic, | |
536 long offset, Address staticFieldAddress) { | |
537 // Add field to containing type | |
538 containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress)); | |
539 } | |
540 | |
541 Field internalCreateField(BasicType containingType, | |
542 String name, Type type, boolean isStatic, | |
543 long offset, Address staticFieldAddress) { | |
544 // "Virtual constructor" based on type | |
545 if (type.isOopType()) { | |
546 return new BasicOopField(this, containingType, name, type, | |
547 isStatic, offset, staticFieldAddress); | |
548 } | |
549 | |
550 if (type instanceof CIntegerType) { | |
551 return new BasicCIntegerField(this, containingType, name, type, | |
552 isStatic, offset, staticFieldAddress); | |
553 } | |
554 | |
555 if (type.equals(getJBooleanType())) { | |
556 return new BasicJBooleanField(this, containingType, name, type, | |
557 isStatic, offset, staticFieldAddress); | |
558 } | |
559 | |
560 if (type.equals(getJByteType())) { | |
561 return new BasicJByteField(this, containingType, name, type, | |
562 isStatic, offset, staticFieldAddress); | |
563 } | |
564 | |
565 if (type.equals(getJCharType())) { | |
566 return new BasicJCharField(this, containingType, name, type, | |
567 isStatic, offset, staticFieldAddress); | |
568 } | |
569 | |
570 if (type.equals(getJDoubleType())) { | |
571 return new BasicJDoubleField(this, containingType, name, type, | |
572 isStatic, offset, staticFieldAddress); | |
573 } | |
574 | |
575 if (type.equals(getJFloatType())) { | |
576 return new BasicJFloatField(this, containingType, name, type, | |
577 isStatic, offset, staticFieldAddress); | |
578 } | |
579 | |
580 if (type.equals(getJIntType())) { | |
581 return new BasicJIntField(this, containingType, name, type, | |
582 isStatic, offset, staticFieldAddress); | |
583 } | |
584 | |
585 if (type.equals(getJLongType())) { | |
586 return new BasicJLongField(this, containingType, name, type, | |
587 isStatic, offset, staticFieldAddress); | |
588 } | |
589 | |
590 if (type.equals(getJShortType())) { | |
591 return new BasicJShortField(this, containingType, name, type, | |
592 isStatic, offset, staticFieldAddress); | |
593 } | |
594 | |
595 // Unknown ("opaque") type. Instantiate ordinary Field. | |
596 return new BasicField(this, containingType, name, type, | |
597 isStatic, offset, staticFieldAddress); | |
598 } | |
599 | |
600 // For debugging | |
601 private void dumpMemory(Address addr, int len) { | |
602 int i = 0; | |
603 while (i < len) { | |
604 System.err.print(addr.addOffsetTo(i) + ":"); | |
605 for (int j = 0; j < 8 && i < len; i++, j++) { | |
606 String s = Long.toHexString(addr.getCIntegerAt(i, 1, true)); | |
607 System.err.print(" 0x"); | |
608 for (int k = 0; k < 2 - s.length(); k++) { | |
609 System.err.print("0"); | |
610 } | |
611 System.err.print(s); | |
612 } | |
613 System.err.println(); | |
614 } | |
615 } | |
616 } |