Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @ 4670:41034914e2ee
add MethodContents assumption to fix debbugging issue
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Wed, 22 Feb 2012 17:04:27 +0100 |
parents | f6f3bb0ee072 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
2426
1d1603768966
7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents:
2177
diff
changeset
|
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:
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(); | |
3939 | 90 readExternalDefinitions(); |
0 | 91 } |
92 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
93 public Type lookupType(String cTypeName, boolean throwException) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
94 Type fieldType = super.lookupType(cTypeName, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
95 if (fieldType == null && cTypeName.startsWith("const ")) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
96 fieldType = (BasicType)lookupType(cTypeName.substring(6), false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
97 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
98 if (fieldType == null && cTypeName.endsWith(" const")) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
99 fieldType = (BasicType)lookupType(cTypeName.substring(0, cTypeName.length() - 6), false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
100 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
101 if (fieldType == null) { |
3939 | 102 if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">")) { |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
103 String ttype = cTypeName.substring("GrowableArray<".length(), |
3939 | 104 cTypeName.length() - 1); |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
105 Type templateType = lookupType(ttype, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
106 if (templateType == null && typeNameIsPointerType(ttype)) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
107 templateType = recursiveCreateBasicPointerType(ttype); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
108 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
109 if (templateType == null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
110 lookupOrFail(ttype); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
111 } |
3939 | 112 |
113 BasicType basicTargetType = createBasicType(cTypeName, false, false, false); | |
114 | |
115 // transfer fields from GenericGrowableArray to template instance | |
116 BasicType generic = lookupOrFail("GenericGrowableArray"); | |
117 BasicType specific = lookupOrFail("GrowableArray<int>"); | |
118 basicTargetType.setSize(specific.getSize()); | |
119 Iterator fields = generic.getFields(); | |
120 while (fields.hasNext()) { | |
121 Field f = (Field)fields.next(); | |
122 basicTargetType.addField(internalCreateField(basicTargetType, f.getName(), | |
123 f.getType(), f.isStatic(), | |
124 f.getOffset(), null)); | |
125 } | |
126 fieldType = basicTargetType; | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
127 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
128 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
129 if (fieldType == null && typeNameIsPointerType(cTypeName)) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
130 fieldType = recursiveCreateBasicPointerType(cTypeName); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
131 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
132 if (fieldType == null && throwException) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
133 super.lookupType(cTypeName, true); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
134 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
135 return fieldType; |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
136 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
137 |
0 | 138 private void readVMTypes() { |
139 // Get the variables we need in order to traverse the VMTypeEntry[] | |
140 long typeEntryTypeNameOffset; | |
141 long typeEntrySuperclassNameOffset; | |
142 long typeEntryIsOopTypeOffset; | |
143 long typeEntryIsIntegerTypeOffset; | |
144 long typeEntryIsUnsignedOffset; | |
145 long typeEntrySizeOffset; | |
146 long typeEntryArrayStride; | |
147 | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
148 // Fetch the address of the VMTypeEntry*. We get this symbol first |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
149 // and try to use it to make sure that symbol lookup is working. |
0 | 150 Address entryAddr = lookupInProcess("gHotSpotVMTypes"); |
151 // System.err.println("gHotSpotVMTypes address = " + entryAddr); | |
152 // Dereference this once to get the pointer to the first VMTypeEntry | |
153 // dumpMemory(entryAddr, 80); | |
154 entryAddr = entryAddr.getAddressAt(0); | |
155 | |
156 if (entryAddr == null) { | |
157 throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); | |
158 } | |
159 | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
160 typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
161 typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
162 typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
163 typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
164 typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
165 typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
166 typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
167 |
0 | 168 // Start iterating down it until we find an entry with no name |
169 Address typeNameAddr = null; | |
170 do { | |
171 // Fetch the type name first | |
172 typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset); | |
173 if (typeNameAddr != null) { | |
174 String typeName = CStringUtilities.getString(typeNameAddr); | |
175 | |
176 String superclassName = null; | |
177 Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset); | |
178 if (superclassNameAddr != null) { | |
179 superclassName = CStringUtilities.getString(superclassNameAddr); | |
180 } | |
181 | |
182 boolean isOopType = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0); | |
183 boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0); | |
184 boolean isUnsigned = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0); | |
185 long size = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true); | |
186 | |
187 createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size); | |
188 } | |
189 | |
190 entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); | |
191 } while (typeNameAddr != null); | |
192 } | |
193 | |
194 private void initializePrimitiveTypes() { | |
195 // Look up the needed primitive types by name...they had better be present | |
196 setJBooleanType(lookupPrimitiveType("jboolean")); | |
197 setJByteType (lookupPrimitiveType("jbyte")); | |
198 setJCharType (lookupPrimitiveType("jchar")); | |
199 setJDoubleType (lookupPrimitiveType("jdouble")); | |
200 setJFloatType (lookupPrimitiveType("jfloat")); | |
201 setJIntType (lookupPrimitiveType("jint")); | |
202 setJLongType (lookupPrimitiveType("jlong")); | |
203 setJShortType (lookupPrimitiveType("jshort")); | |
204 | |
205 // Indicate that these are the Java primitive types | |
206 ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true); | |
207 ((BasicType) getJByteType()).setIsJavaPrimitiveType(true); | |
208 ((BasicType) getJCharType()).setIsJavaPrimitiveType(true); | |
209 ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true); | |
210 ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true); | |
211 ((BasicType) getJIntType()).setIsJavaPrimitiveType(true); | |
212 ((BasicType) getJLongType()).setIsJavaPrimitiveType(true); | |
213 ((BasicType) getJShortType()).setIsJavaPrimitiveType(true); | |
214 } | |
215 | |
216 private Type lookupPrimitiveType(String typeName) { | |
217 Type type = lookupType(typeName, false); | |
218 if (type == null) { | |
219 throw new RuntimeException("Error initializing the HotSpotDataBase: could not find the primitive type \"" + | |
220 typeName + "\" in the remote VM's VMStructs table. This type is required in " + | |
221 "order to determine the size of Java primitive types. Can not continue."); | |
222 } | |
223 return type; | |
224 } | |
225 | |
3939 | 226 private void readExternalDefinitions() { |
227 String file = System.getProperty("sun.jvm.hotspot.typedb"); | |
228 if (file != null) { | |
229 System.out.println("Reading " + file); | |
230 BufferedReader in = null; | |
231 try { | |
232 StreamTokenizer t = new StreamTokenizer(in = new BufferedReader(new InputStreamReader(new FileInputStream(file)))); | |
233 t.resetSyntax(); | |
234 t.wordChars('\u0000','\uFFFF'); | |
235 t.whitespaceChars(' ', ' '); | |
236 t.whitespaceChars('\n', '\n'); | |
237 t.whitespaceChars('\r', '\r'); | |
238 t.quoteChar('\"'); | |
239 t.eolIsSignificant(true); | |
240 while (t.nextToken() != StreamTokenizer.TT_EOF) { | |
241 if (t.ttype == StreamTokenizer.TT_EOL) { | |
242 continue; | |
243 } | |
244 | |
245 if (t.sval.equals("field")) { | |
246 t.nextToken(); | |
247 BasicType containingType = (BasicType)lookupType(t.sval); | |
248 t.nextToken(); | |
249 String fieldName = t.sval; | |
250 | |
251 // The field's Type must already be in the database -- no exceptions | |
252 t.nextToken(); | |
253 Type fieldType = lookupType(t.sval); | |
254 t.nextToken(); | |
255 boolean isStatic = Boolean.valueOf(t.sval).booleanValue(); | |
256 t.nextToken(); | |
257 long offset = Long.parseLong(t.sval); | |
258 t.nextToken(); | |
259 Address staticAddress = null; | |
260 if (isStatic) { | |
261 throw new InternalError("static fields not supported"); | |
262 } | |
263 | |
264 // check to see if the field already exists | |
265 Iterator i = containingType.getFields(); | |
266 boolean defined = false; | |
267 while (i.hasNext()) { | |
268 Field f = (Field) i.next(); | |
269 if (f.getName().equals(fieldName)) { | |
270 if (f.isStatic() != isStatic) { | |
271 throw new RuntimeException("static/nonstatic mismatch: " + fieldName); | |
272 } | |
273 if (!isStatic) { | |
274 if (f.getOffset() != offset) { | |
275 throw new RuntimeException("bad redefinition of field offset: " + fieldName); | |
276 } | |
277 } else { | |
278 if (!f.getStaticFieldAddress().equals(staticAddress)) { | |
279 throw new RuntimeException("bad redefinition of field location: " + fieldName); | |
280 } | |
281 } | |
282 if (f.getType() != fieldType) { | |
283 System.out.println(fieldType); | |
284 System.out.println(f.getType()); | |
285 throw new RuntimeException("bad redefinition of field type: " + fieldName); | |
286 } | |
287 defined = true; | |
288 break; | |
289 } | |
290 } | |
291 | |
292 if (!defined) { | |
293 // Create field by type | |
294 createField(containingType, | |
295 fieldName, fieldType, | |
296 isStatic, | |
297 offset, | |
298 staticAddress); | |
299 } | |
300 } else if (t.sval.equals("type")) { | |
301 t.nextToken(); | |
302 String typeName = t.sval; | |
303 t.nextToken(); | |
304 String superclassName = t.sval; | |
305 if (superclassName.equals("null")) { | |
306 superclassName = null; | |
307 } | |
308 t.nextToken(); | |
309 boolean isOop = Boolean.valueOf(t.sval).booleanValue(); | |
310 t.nextToken(); | |
311 boolean isInteger = Boolean.valueOf(t.sval).booleanValue(); | |
312 t.nextToken(); | |
313 boolean isUnsigned = Boolean.valueOf(t.sval).booleanValue(); | |
314 t.nextToken(); | |
315 long size = Long.parseLong(t.sval); | |
316 | |
317 BasicType type = null; | |
318 try { | |
319 type = (BasicType)lookupType(typeName); | |
320 } catch (RuntimeException e) { | |
321 } | |
322 if (type != null) { | |
323 if (type.isOopType() != isOop) { | |
324 throw new RuntimeException("oop mismatch in type definition: " + typeName); | |
325 } | |
326 if (type.isCIntegerType() != isInteger) { | |
327 throw new RuntimeException("integer type mismatch in type definition: " + typeName); | |
328 } | |
329 if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) { | |
330 throw new RuntimeException("unsigned mismatch in type definition: " + typeName); | |
331 } | |
332 if (type.getSuperclass() == null) { | |
333 if (superclassName != null) { | |
334 if (type.getSize() == -1) { | |
335 type.setSuperclass(lookupType(superclassName)); | |
336 } else { | |
337 throw new RuntimeException("unexpected superclass in type definition: " + typeName); | |
338 } | |
339 } | |
340 } else { | |
341 if (superclassName == null) { | |
342 throw new RuntimeException("missing superclass in type definition: " + typeName); | |
343 } | |
344 if (!type.getSuperclass().getName().equals(superclassName)) { | |
345 throw new RuntimeException("incorrect superclass in type definition: " + typeName); | |
346 } | |
347 } | |
348 if (type.getSize() != size) { | |
349 if (type.getSize() == -1 || type.getSize() == 0) { | |
350 type.setSize(size); | |
351 } else { | |
352 throw new RuntimeException("size mismatch in type definition: " + typeName + ": " + type.getSize() + " != " + size); | |
353 } | |
354 } | |
355 } | |
356 | |
357 if (lookupType(typeName, false) == null) { | |
358 // Create type | |
359 createType(typeName, superclassName, isOop, isInteger, isUnsigned, size); | |
360 } | |
361 } else { | |
362 throw new InternalError("\"" + t.sval + "\""); | |
363 } | |
364 } | |
365 } catch (IOException ioe) { | |
366 ioe.printStackTrace(); | |
367 } finally { | |
368 try { | |
369 in.close(); | |
370 } catch (Exception e) { | |
371 } | |
372 } | |
373 } | |
374 } | |
375 | |
0 | 376 private void readVMStructs() { |
377 // Get the variables we need in order to traverse the VMStructEntry[] | |
378 long structEntryTypeNameOffset; | |
379 long structEntryFieldNameOffset; | |
380 long structEntryTypeStringOffset; | |
381 long structEntryIsStaticOffset; | |
382 long structEntryOffsetOffset; | |
383 long structEntryAddressOffset; | |
384 long structEntryArrayStride; | |
385 | |
386 structEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset"); | |
387 structEntryFieldNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset"); | |
388 structEntryTypeStringOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset"); | |
389 structEntryIsStaticOffset = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset"); | |
390 structEntryOffsetOffset = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset"); | |
391 structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); | |
392 structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); | |
393 | |
394 // Fetch the address of the VMStructEntry* | |
395 Address entryAddr = lookupInProcess("gHotSpotVMStructs"); | |
396 // Dereference this once to get the pointer to the first VMStructEntry | |
397 entryAddr = entryAddr.getAddressAt(0); | |
398 if (entryAddr == null) { | |
399 throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue"); | |
400 } | |
401 | |
402 // Start iterating down it until we find an entry with no name | |
403 Address fieldNameAddr = null; | |
404 String typeName = null; | |
405 String fieldName = null; | |
406 String typeString = null; | |
407 boolean isStatic = false; | |
408 long offset = 0; | |
409 Address staticFieldAddr = null; | |
410 long size = 0; | |
411 long index = 0; | |
412 String opaqueName = "<opaque>"; | |
413 lookupOrCreateClass(opaqueName, false, false, false); | |
414 | |
415 do { | |
416 // Fetch the field name first | |
417 fieldNameAddr = entryAddr.getAddressAt(structEntryFieldNameOffset); | |
418 if (fieldNameAddr != null) { | |
419 fieldName = CStringUtilities.getString(fieldNameAddr); | |
420 | |
421 // Now the rest of the names. Keep in mind that the type name | |
422 // may be NULL, indicating that the type is opaque. | |
423 Address addr = entryAddr.getAddressAt(structEntryTypeNameOffset); | |
424 if (addr == null) { | |
425 throw new RuntimeException("gHotSpotVMStructs unexpectedly had a NULL type name at index " + index); | |
426 } | |
427 typeName = CStringUtilities.getString(addr); | |
428 | |
429 addr = entryAddr.getAddressAt(structEntryTypeStringOffset); | |
430 if (addr == null) { | |
431 typeString = opaqueName; | |
432 } else { | |
433 typeString = CStringUtilities.getString(addr); | |
434 } | |
435 | |
436 isStatic = !(entryAddr.getCIntegerAt(structEntryIsStaticOffset, C_INT32_SIZE, false) == 0); | |
437 if (isStatic) { | |
438 staticFieldAddr = entryAddr.getAddressAt(structEntryAddressOffset); | |
439 offset = 0; | |
440 } else { | |
441 offset = entryAddr.getCIntegerAt(structEntryOffsetOffset, C_INT64_SIZE, true); | |
442 staticFieldAddr = null; | |
443 } | |
444 | |
445 // The containing Type must already be in the database -- no exceptions | |
446 BasicType containingType = lookupOrFail(typeName); | |
447 | |
448 // The field's Type must already be in the database -- no exceptions | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
449 BasicType fieldType = (BasicType)lookupType(typeString); |
0 | 450 |
451 // Create field by type | |
452 createField(containingType, fieldName, fieldType, | |
453 isStatic, offset, staticFieldAddr); | |
454 } | |
455 | |
456 ++index; | |
457 entryAddr = entryAddr.addOffsetTo(structEntryArrayStride); | |
458 } while (fieldNameAddr != null); | |
459 } | |
460 | |
461 private void readVMIntConstants() { | |
462 // Get the variables we need in order to traverse the VMIntConstantEntry[] | |
463 long intConstantEntryNameOffset; | |
464 long intConstantEntryValueOffset; | |
465 long intConstantEntryArrayStride; | |
466 | |
467 intConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset"); | |
468 intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); | |
469 intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); | |
470 | |
471 // Fetch the address of the VMIntConstantEntry* | |
472 Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); | |
473 // Dereference this once to get the pointer to the first VMIntConstantEntry | |
474 entryAddr = entryAddr.getAddressAt(0); | |
475 if (entryAddr == null) { | |
476 throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue"); | |
477 } | |
478 | |
479 // Start iterating down it until we find an entry with no name | |
480 Address nameAddr = null; | |
481 do { | |
482 // Fetch the type name first | |
483 nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset); | |
484 if (nameAddr != null) { | |
485 String name = CStringUtilities.getString(nameAddr); | |
486 int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false); | |
487 | |
488 // Be a little resilient | |
489 Integer oldValue = lookupIntConstant(name, false); | |
490 if (oldValue == null) { | |
491 addIntConstant(name, value); | |
492 } else { | |
493 if (oldValue.intValue() != value) { | |
494 throw new RuntimeException("Error: the integer constant \"" + name + | |
495 "\" had its value redefined (old was " + oldValue + | |
496 ", new is " + value + ". Aborting."); | |
497 } else { | |
498 System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + | |
499 "had its value declared as " + value + " twice. Continuing."); | |
500 } | |
501 } | |
502 } | |
503 | |
504 entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); | |
505 } while (nameAddr != null); | |
506 } | |
507 | |
508 private void readVMLongConstants() { | |
509 // Get the variables we need in order to traverse the VMLongConstantEntry[] | |
510 long longConstantEntryNameOffset; | |
511 long longConstantEntryValueOffset; | |
512 long longConstantEntryArrayStride; | |
513 | |
514 longConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset"); | |
515 longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); | |
516 longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); | |
517 | |
518 // Fetch the address of the VMLongConstantEntry* | |
519 Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); | |
520 // Dereference this once to get the pointer to the first VMLongConstantEntry | |
521 entryAddr = entryAddr.getAddressAt(0); | |
522 if (entryAddr == null) { | |
523 throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue"); | |
524 } | |
525 | |
526 // Start iterating down it until we find an entry with no name | |
527 Address nameAddr = null; | |
528 do { | |
529 // Fetch the type name first | |
530 nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset); | |
531 if (nameAddr != null) { | |
532 String name = CStringUtilities.getString(nameAddr); | |
533 int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true); | |
534 | |
535 // Be a little resilient | |
536 Long oldValue = lookupLongConstant(name, false); | |
537 if (oldValue == null) { | |
538 addLongConstant(name, value); | |
539 } else { | |
540 if (oldValue.longValue() != value) { | |
541 throw new RuntimeException("Error: the long constant \"" + name + | |
542 "\" had its value redefined (old was " + oldValue + | |
543 ", new is " + value + ". Aborting."); | |
544 } else { | |
545 System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + | |
546 "had its value declared as " + value + " twice. Continuing."); | |
547 } | |
548 } | |
549 } | |
550 | |
551 entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); | |
552 } while (nameAddr != null); | |
553 } | |
554 | |
555 private BasicType lookupOrFail(String typeName) { | |
556 BasicType type = (BasicType) lookupType(typeName, false); | |
557 if (type == null) { | |
558 throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " + | |
559 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " + | |
560 "in the debug build of that VM). Can not continue."); | |
561 } | |
562 return type; | |
563 } | |
564 | |
565 private long getLongValueFromProcess(String symbol) { | |
566 return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true); | |
567 } | |
568 | |
569 private Address lookupInProcess(String symbol) throws NoSuchSymbolException { | |
570 // FIXME: abstract away the loadobject name | |
571 for (int i = 0; i < jvmLibNames.length; i++) { | |
572 Address addr = symbolLookup.lookup(jvmLibNames[i], symbol); | |
573 if (addr != null) { | |
574 return addr; | |
575 } | |
576 } | |
577 String errStr = "("; | |
578 for (int i = 0; i < jvmLibNames.length; i++) { | |
579 errStr += jvmLibNames[i]; | |
580 if (i < jvmLibNames.length - 1) { | |
581 errStr += ", "; | |
582 } | |
583 } | |
584 errStr += ")"; | |
585 throw new NoSuchSymbolException(symbol, | |
586 "Could not find symbol \"" + symbol + | |
587 "\" in any of the known library names " + | |
588 errStr); | |
589 } | |
590 | |
591 private BasicType lookupOrCreateClass(String typeName, boolean isOopType, | |
592 boolean isIntegerType, boolean isUnsigned) { | |
593 BasicType type = (BasicType) lookupType(typeName, false); | |
594 if (type == null) { | |
595 // Create a new type | |
596 type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned); | |
597 } | |
598 return type; | |
599 } | |
600 | |
601 /** Creates a new BasicType, initializes its size to -1 so we can | |
602 test to ensure that all types' sizes are initialized by VMTypes, | |
603 and adds it to the database. Takes care of initializing integer | |
604 and oop types properly. */ | |
605 private BasicType createBasicType(String typeName, boolean isOopType, | |
606 boolean isIntegerType, boolean isUnsigned) { | |
607 | |
608 BasicType type = null; | |
609 | |
610 if (isIntegerType) { | |
611 type = new BasicCIntegerType(this, typeName, isUnsigned); | |
612 } else { | |
613 if (typeNameIsPointerType(typeName)) { | |
614 type = recursiveCreateBasicPointerType(typeName); | |
615 } else { | |
616 type = new BasicType(this, typeName); | |
617 } | |
618 | |
619 if (isOopType) { | |
620 // HACK: turn markOop into a C integer type. This allows | |
621 // proper handling of it in the Serviceability Agent. (FIXME | |
622 // -- consider doing something different here) | |
623 if (typeName.equals("markOop")) { | |
624 type = new BasicCIntegerType(this, typeName, true); | |
625 } else { | |
626 type.setIsOopType(true); | |
627 } | |
628 } | |
629 } | |
630 | |
631 type.setSize(UNINITIALIZED_SIZE); | |
632 addType(type); | |
633 return type; | |
634 } | |
635 | |
636 /** Recursively creates a PointerType from the string representation | |
637 of the type's name. Note that this currently needs some | |
638 workarounds due to incomplete information in the VMStructs | |
639 database. */ | |
640 private BasicPointerType recursiveCreateBasicPointerType(String typeName) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
641 BasicPointerType result = (BasicPointerType)super.lookupType(typeName, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
642 if (result != null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
643 return result; |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
644 } |
0 | 645 String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); |
646 Type targetType = null; | |
647 if (typeNameIsPointerType(targetTypeName)) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
648 targetType = lookupType(targetTypeName, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
649 if (targetType == null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
650 targetType = recursiveCreateBasicPointerType(targetTypeName); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
651 } |
0 | 652 } else { |
653 targetType = lookupType(targetTypeName, false); | |
654 if (targetType == null) { | |
655 // Workaround for missing C integer types in database. | |
656 // Also looks like we can't throw an exception for other | |
657 // missing target types because there are some in old | |
658 // VMStructs tables that didn't have the target type declared. | |
659 // For this case, we create basic types that never get filled | |
660 // in. | |
661 | |
662 if (targetTypeName.equals("char") || | |
663 targetTypeName.equals("const char")) { | |
664 // We don't have a representation of const-ness of C types in the SA | |
665 BasicType basicTargetType = createBasicType(targetTypeName, false, true, false); | |
666 basicTargetType.setSize(1); | |
667 targetType = basicTargetType; | |
668 } else if (targetTypeName.equals("u_char")) { | |
669 BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); | |
670 basicTargetType.setSize(1); | |
671 targetType = basicTargetType; | |
672 } else { | |
673 if (DEBUG) { | |
674 System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); | |
675 } | |
676 targetType = createBasicType(targetTypeName, false, false, false); | |
677 } | |
678 } | |
679 } | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
680 result = new BasicPointerType(this, typeName, targetType); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
681 result.setSize(UNINITIALIZED_SIZE); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
682 addType(result); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
683 return result; |
0 | 684 } |
685 | |
686 private boolean typeNameIsPointerType(String typeName) { | |
687 int i = typeName.length() - 1; | |
688 while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) { | |
689 --i; | |
690 } | |
691 if (i >= 0 && typeName.charAt(i) == '*') { | |
692 return true; | |
693 } | |
694 return false; | |
695 } | |
696 | |
697 public void createType(String typeName, String superclassName, | |
698 boolean isOopType, boolean isIntegerType, | |
699 boolean isUnsigned, long size) { | |
700 // See whether we have a superclass | |
701 BasicType superclass = null; | |
702 if (superclassName != null) { | |
703 // Fetch or create it (FIXME: would get oop types wrong if | |
704 // they had a hierarchy; consider using lookupOrFail) | |
705 superclass = lookupOrCreateClass(superclassName, false, false, false); | |
706 } | |
707 | |
708 // Lookup or create the current type | |
709 BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned); | |
710 // Set superclass and/or ensure it's correct | |
711 if (superclass != null) { | |
712 if (curType.getSuperclass() == null) { | |
713 // Set the superclass in the current type | |
714 curType.setSuperclass(superclass); | |
715 } | |
716 | |
717 if (curType.getSuperclass() != superclass) { | |
718 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
719 "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " + | |
720 superclass.getName() + ")."); | |
721 } | |
722 } | |
723 | |
724 // Classes are created with a size of UNINITIALIZED_SIZE. | |
725 // Set size if necessary. | |
3939 | 726 if (curType.getSize() == UNINITIALIZED_SIZE || curType.getSize() == 0) { |
0 | 727 curType.setSize(size); |
728 } else { | |
729 if (curType.getSize() != size) { | |
730 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
731 "had its size redefined (old was " + curType.getSize() + ", new is " + size + ")."); | |
732 } | |
733 | |
734 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
735 "had its size declared as " + size + " twice. Continuing."); | |
736 } | |
737 | |
738 } | |
739 | |
740 /** "Virtual constructor" for fields based on type */ | |
741 public void createField(BasicType containingType, | |
742 String name, Type type, boolean isStatic, | |
743 long offset, Address staticFieldAddress) { | |
744 // Add field to containing type | |
745 containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress)); | |
746 } | |
747 | |
748 Field internalCreateField(BasicType containingType, | |
749 String name, Type type, boolean isStatic, | |
750 long offset, Address staticFieldAddress) { | |
751 // "Virtual constructor" based on type | |
752 if (type.isOopType()) { | |
753 return new BasicOopField(this, containingType, name, type, | |
754 isStatic, offset, staticFieldAddress); | |
755 } | |
756 | |
757 if (type instanceof CIntegerType) { | |
758 return new BasicCIntegerField(this, containingType, name, type, | |
759 isStatic, offset, staticFieldAddress); | |
760 } | |
761 | |
762 if (type.equals(getJBooleanType())) { | |
763 return new BasicJBooleanField(this, containingType, name, type, | |
764 isStatic, offset, staticFieldAddress); | |
765 } | |
766 | |
767 if (type.equals(getJByteType())) { | |
768 return new BasicJByteField(this, containingType, name, type, | |
769 isStatic, offset, staticFieldAddress); | |
770 } | |
771 | |
772 if (type.equals(getJCharType())) { | |
773 return new BasicJCharField(this, containingType, name, type, | |
774 isStatic, offset, staticFieldAddress); | |
775 } | |
776 | |
777 if (type.equals(getJDoubleType())) { | |
778 return new BasicJDoubleField(this, containingType, name, type, | |
779 isStatic, offset, staticFieldAddress); | |
780 } | |
781 | |
782 if (type.equals(getJFloatType())) { | |
783 return new BasicJFloatField(this, containingType, name, type, | |
784 isStatic, offset, staticFieldAddress); | |
785 } | |
786 | |
787 if (type.equals(getJIntType())) { | |
788 return new BasicJIntField(this, containingType, name, type, | |
789 isStatic, offset, staticFieldAddress); | |
790 } | |
791 | |
792 if (type.equals(getJLongType())) { | |
793 return new BasicJLongField(this, containingType, name, type, | |
794 isStatic, offset, staticFieldAddress); | |
795 } | |
796 | |
797 if (type.equals(getJShortType())) { | |
798 return new BasicJShortField(this, containingType, name, type, | |
799 isStatic, offset, staticFieldAddress); | |
800 } | |
801 | |
802 // Unknown ("opaque") type. Instantiate ordinary Field. | |
803 return new BasicField(this, containingType, name, type, | |
804 isStatic, offset, staticFieldAddress); | |
805 } | |
806 | |
807 // For debugging | |
808 private void dumpMemory(Address addr, int len) { | |
809 int i = 0; | |
810 while (i < len) { | |
811 System.err.print(addr.addOffsetTo(i) + ":"); | |
812 for (int j = 0; j < 8 && i < len; i++, j++) { | |
813 String s = Long.toHexString(addr.getCIntegerAt(i, 1, true)); | |
814 System.err.print(" 0x"); | |
815 for (int k = 0; k < 2 - s.length(); k++) { | |
816 System.err.print("0"); | |
817 } | |
818 System.err.print(s); | |
819 } | |
820 System.err.println(); | |
821 } | |
822 } | |
823 } |