Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @ 3779:04760e41b01e
7016112: CMS: crash during promotion testing
Summary: Also reviewed by mikael.gerdin@oracle.com; stdlib:qsort() does byte-by-byte swapping on Windows. This leads to pointer shearing. Fix is to implement a quicksort that does full pointer updates.
Reviewed-by: never, coleenp, ysr
author | brutisso |
---|---|
date | Tue, 28 Jun 2011 14:23:27 +0200 |
parents | 1d1603768966 |
children | f6f3bb0ee072 |
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(); | |
90 } | |
91 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
92 public Type lookupType(String cTypeName, boolean throwException) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
93 Type fieldType = super.lookupType(cTypeName, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
94 if (fieldType == null && cTypeName.startsWith("const ")) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
95 fieldType = (BasicType)lookupType(cTypeName.substring(6), false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
96 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
97 if (fieldType == null && cTypeName.endsWith(" const")) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
98 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
|
99 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
100 if (fieldType == null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
101 if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">*")) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
102 String ttype = cTypeName.substring("GrowableArray<".length(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
103 cTypeName.length() - 2); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
104 Type templateType = lookupType(ttype, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
105 if (templateType == null && typeNameIsPointerType(ttype)) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
106 templateType = recursiveCreateBasicPointerType(ttype); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
107 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
108 if (templateType == null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
109 lookupOrFail(ttype); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
110 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
111 fieldType = recursiveCreateBasicPointerType(cTypeName); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
112 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
113 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
114 if (fieldType == null && typeNameIsPointerType(cTypeName)) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
115 fieldType = recursiveCreateBasicPointerType(cTypeName); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
116 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
117 if (fieldType == null && throwException) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
118 super.lookupType(cTypeName, true); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
119 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
120 return fieldType; |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
121 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
122 |
0 | 123 private void readVMTypes() { |
124 // Get the variables we need in order to traverse the VMTypeEntry[] | |
125 long typeEntryTypeNameOffset; | |
126 long typeEntrySuperclassNameOffset; | |
127 long typeEntryIsOopTypeOffset; | |
128 long typeEntryIsIntegerTypeOffset; | |
129 long typeEntryIsUnsignedOffset; | |
130 long typeEntrySizeOffset; | |
131 long typeEntryArrayStride; | |
132 | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
133 // 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
|
134 // and try to use it to make sure that symbol lookup is working. |
0 | 135 Address entryAddr = lookupInProcess("gHotSpotVMTypes"); |
136 // System.err.println("gHotSpotVMTypes address = " + entryAddr); | |
137 // Dereference this once to get the pointer to the first VMTypeEntry | |
138 // dumpMemory(entryAddr, 80); | |
139 entryAddr = entryAddr.getAddressAt(0); | |
140 | |
141 if (entryAddr == null) { | |
142 throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); | |
143 } | |
144 | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
145 typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
146 typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
147 typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
148 typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
149 typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
150 typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
151 typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
152 |
0 | 153 // Start iterating down it until we find an entry with no name |
154 Address typeNameAddr = null; | |
155 do { | |
156 // Fetch the type name first | |
157 typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset); | |
158 if (typeNameAddr != null) { | |
159 String typeName = CStringUtilities.getString(typeNameAddr); | |
160 | |
161 String superclassName = null; | |
162 Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset); | |
163 if (superclassNameAddr != null) { | |
164 superclassName = CStringUtilities.getString(superclassNameAddr); | |
165 } | |
166 | |
167 boolean isOopType = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0); | |
168 boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0); | |
169 boolean isUnsigned = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0); | |
170 long size = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true); | |
171 | |
172 createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size); | |
173 } | |
174 | |
175 entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); | |
176 } while (typeNameAddr != null); | |
177 } | |
178 | |
179 private void initializePrimitiveTypes() { | |
180 // Look up the needed primitive types by name...they had better be present | |
181 setJBooleanType(lookupPrimitiveType("jboolean")); | |
182 setJByteType (lookupPrimitiveType("jbyte")); | |
183 setJCharType (lookupPrimitiveType("jchar")); | |
184 setJDoubleType (lookupPrimitiveType("jdouble")); | |
185 setJFloatType (lookupPrimitiveType("jfloat")); | |
186 setJIntType (lookupPrimitiveType("jint")); | |
187 setJLongType (lookupPrimitiveType("jlong")); | |
188 setJShortType (lookupPrimitiveType("jshort")); | |
189 | |
190 // Indicate that these are the Java primitive types | |
191 ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true); | |
192 ((BasicType) getJByteType()).setIsJavaPrimitiveType(true); | |
193 ((BasicType) getJCharType()).setIsJavaPrimitiveType(true); | |
194 ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true); | |
195 ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true); | |
196 ((BasicType) getJIntType()).setIsJavaPrimitiveType(true); | |
197 ((BasicType) getJLongType()).setIsJavaPrimitiveType(true); | |
198 ((BasicType) getJShortType()).setIsJavaPrimitiveType(true); | |
199 } | |
200 | |
201 private Type lookupPrimitiveType(String typeName) { | |
202 Type type = lookupType(typeName, false); | |
203 if (type == null) { | |
204 throw new RuntimeException("Error initializing the HotSpotDataBase: could not find the primitive type \"" + | |
205 typeName + "\" in the remote VM's VMStructs table. This type is required in " + | |
206 "order to determine the size of Java primitive types. Can not continue."); | |
207 } | |
208 return type; | |
209 } | |
210 | |
211 private void readVMStructs() { | |
212 // Get the variables we need in order to traverse the VMStructEntry[] | |
213 long structEntryTypeNameOffset; | |
214 long structEntryFieldNameOffset; | |
215 long structEntryTypeStringOffset; | |
216 long structEntryIsStaticOffset; | |
217 long structEntryOffsetOffset; | |
218 long structEntryAddressOffset; | |
219 long structEntryArrayStride; | |
220 | |
221 structEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset"); | |
222 structEntryFieldNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset"); | |
223 structEntryTypeStringOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset"); | |
224 structEntryIsStaticOffset = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset"); | |
225 structEntryOffsetOffset = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset"); | |
226 structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); | |
227 structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); | |
228 | |
229 // Fetch the address of the VMStructEntry* | |
230 Address entryAddr = lookupInProcess("gHotSpotVMStructs"); | |
231 // Dereference this once to get the pointer to the first VMStructEntry | |
232 entryAddr = entryAddr.getAddressAt(0); | |
233 if (entryAddr == null) { | |
234 throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue"); | |
235 } | |
236 | |
237 // Start iterating down it until we find an entry with no name | |
238 Address fieldNameAddr = null; | |
239 String typeName = null; | |
240 String fieldName = null; | |
241 String typeString = null; | |
242 boolean isStatic = false; | |
243 long offset = 0; | |
244 Address staticFieldAddr = null; | |
245 long size = 0; | |
246 long index = 0; | |
247 String opaqueName = "<opaque>"; | |
248 lookupOrCreateClass(opaqueName, false, false, false); | |
249 | |
250 do { | |
251 // Fetch the field name first | |
252 fieldNameAddr = entryAddr.getAddressAt(structEntryFieldNameOffset); | |
253 if (fieldNameAddr != null) { | |
254 fieldName = CStringUtilities.getString(fieldNameAddr); | |
255 | |
256 // Now the rest of the names. Keep in mind that the type name | |
257 // may be NULL, indicating that the type is opaque. | |
258 Address addr = entryAddr.getAddressAt(structEntryTypeNameOffset); | |
259 if (addr == null) { | |
260 throw new RuntimeException("gHotSpotVMStructs unexpectedly had a NULL type name at index " + index); | |
261 } | |
262 typeName = CStringUtilities.getString(addr); | |
263 | |
264 addr = entryAddr.getAddressAt(structEntryTypeStringOffset); | |
265 if (addr == null) { | |
266 typeString = opaqueName; | |
267 } else { | |
268 typeString = CStringUtilities.getString(addr); | |
269 } | |
270 | |
271 isStatic = !(entryAddr.getCIntegerAt(structEntryIsStaticOffset, C_INT32_SIZE, false) == 0); | |
272 if (isStatic) { | |
273 staticFieldAddr = entryAddr.getAddressAt(structEntryAddressOffset); | |
274 offset = 0; | |
275 } else { | |
276 offset = entryAddr.getCIntegerAt(structEntryOffsetOffset, C_INT64_SIZE, true); | |
277 staticFieldAddr = null; | |
278 } | |
279 | |
280 // The containing Type must already be in the database -- no exceptions | |
281 BasicType containingType = lookupOrFail(typeName); | |
282 | |
283 // 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
|
284 BasicType fieldType = (BasicType)lookupType(typeString); |
0 | 285 |
286 // Create field by type | |
287 createField(containingType, fieldName, fieldType, | |
288 isStatic, offset, staticFieldAddr); | |
289 } | |
290 | |
291 ++index; | |
292 entryAddr = entryAddr.addOffsetTo(structEntryArrayStride); | |
293 } while (fieldNameAddr != null); | |
294 } | |
295 | |
296 private void readVMIntConstants() { | |
297 // Get the variables we need in order to traverse the VMIntConstantEntry[] | |
298 long intConstantEntryNameOffset; | |
299 long intConstantEntryValueOffset; | |
300 long intConstantEntryArrayStride; | |
301 | |
302 intConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset"); | |
303 intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); | |
304 intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); | |
305 | |
306 // Fetch the address of the VMIntConstantEntry* | |
307 Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); | |
308 // Dereference this once to get the pointer to the first VMIntConstantEntry | |
309 entryAddr = entryAddr.getAddressAt(0); | |
310 if (entryAddr == null) { | |
311 throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue"); | |
312 } | |
313 | |
314 // Start iterating down it until we find an entry with no name | |
315 Address nameAddr = null; | |
316 do { | |
317 // Fetch the type name first | |
318 nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset); | |
319 if (nameAddr != null) { | |
320 String name = CStringUtilities.getString(nameAddr); | |
321 int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false); | |
322 | |
323 // Be a little resilient | |
324 Integer oldValue = lookupIntConstant(name, false); | |
325 if (oldValue == null) { | |
326 addIntConstant(name, value); | |
327 } else { | |
328 if (oldValue.intValue() != value) { | |
329 throw new RuntimeException("Error: the integer constant \"" + name + | |
330 "\" had its value redefined (old was " + oldValue + | |
331 ", new is " + value + ". Aborting."); | |
332 } else { | |
333 System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + | |
334 "had its value declared as " + value + " twice. Continuing."); | |
335 } | |
336 } | |
337 } | |
338 | |
339 entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); | |
340 } while (nameAddr != null); | |
341 } | |
342 | |
343 private void readVMLongConstants() { | |
344 // Get the variables we need in order to traverse the VMLongConstantEntry[] | |
345 long longConstantEntryNameOffset; | |
346 long longConstantEntryValueOffset; | |
347 long longConstantEntryArrayStride; | |
348 | |
349 longConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset"); | |
350 longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); | |
351 longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); | |
352 | |
353 // Fetch the address of the VMLongConstantEntry* | |
354 Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); | |
355 // Dereference this once to get the pointer to the first VMLongConstantEntry | |
356 entryAddr = entryAddr.getAddressAt(0); | |
357 if (entryAddr == null) { | |
358 throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue"); | |
359 } | |
360 | |
361 // Start iterating down it until we find an entry with no name | |
362 Address nameAddr = null; | |
363 do { | |
364 // Fetch the type name first | |
365 nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset); | |
366 if (nameAddr != null) { | |
367 String name = CStringUtilities.getString(nameAddr); | |
368 int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true); | |
369 | |
370 // Be a little resilient | |
371 Long oldValue = lookupLongConstant(name, false); | |
372 if (oldValue == null) { | |
373 addLongConstant(name, value); | |
374 } else { | |
375 if (oldValue.longValue() != value) { | |
376 throw new RuntimeException("Error: the long constant \"" + name + | |
377 "\" had its value redefined (old was " + oldValue + | |
378 ", new is " + value + ". Aborting."); | |
379 } else { | |
380 System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + | |
381 "had its value declared as " + value + " twice. Continuing."); | |
382 } | |
383 } | |
384 } | |
385 | |
386 entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); | |
387 } while (nameAddr != null); | |
388 } | |
389 | |
390 private BasicType lookupOrFail(String typeName) { | |
391 BasicType type = (BasicType) lookupType(typeName, false); | |
392 if (type == null) { | |
393 throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " + | |
394 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " + | |
395 "in the debug build of that VM). Can not continue."); | |
396 } | |
397 return type; | |
398 } | |
399 | |
400 private long getLongValueFromProcess(String symbol) { | |
401 return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true); | |
402 } | |
403 | |
404 private Address lookupInProcess(String symbol) throws NoSuchSymbolException { | |
405 // FIXME: abstract away the loadobject name | |
406 for (int i = 0; i < jvmLibNames.length; i++) { | |
407 Address addr = symbolLookup.lookup(jvmLibNames[i], symbol); | |
408 if (addr != null) { | |
409 return addr; | |
410 } | |
411 } | |
412 String errStr = "("; | |
413 for (int i = 0; i < jvmLibNames.length; i++) { | |
414 errStr += jvmLibNames[i]; | |
415 if (i < jvmLibNames.length - 1) { | |
416 errStr += ", "; | |
417 } | |
418 } | |
419 errStr += ")"; | |
420 throw new NoSuchSymbolException(symbol, | |
421 "Could not find symbol \"" + symbol + | |
422 "\" in any of the known library names " + | |
423 errStr); | |
424 } | |
425 | |
426 private BasicType lookupOrCreateClass(String typeName, boolean isOopType, | |
427 boolean isIntegerType, boolean isUnsigned) { | |
428 BasicType type = (BasicType) lookupType(typeName, false); | |
429 if (type == null) { | |
430 // Create a new type | |
431 type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned); | |
432 } | |
433 return type; | |
434 } | |
435 | |
436 /** Creates a new BasicType, initializes its size to -1 so we can | |
437 test to ensure that all types' sizes are initialized by VMTypes, | |
438 and adds it to the database. Takes care of initializing integer | |
439 and oop types properly. */ | |
440 private BasicType createBasicType(String typeName, boolean isOopType, | |
441 boolean isIntegerType, boolean isUnsigned) { | |
442 | |
443 BasicType type = null; | |
444 | |
445 if (isIntegerType) { | |
446 type = new BasicCIntegerType(this, typeName, isUnsigned); | |
447 } else { | |
448 if (typeNameIsPointerType(typeName)) { | |
449 type = recursiveCreateBasicPointerType(typeName); | |
450 } else { | |
451 type = new BasicType(this, typeName); | |
452 } | |
453 | |
454 if (isOopType) { | |
455 // HACK: turn markOop into a C integer type. This allows | |
456 // proper handling of it in the Serviceability Agent. (FIXME | |
457 // -- consider doing something different here) | |
458 if (typeName.equals("markOop")) { | |
459 type = new BasicCIntegerType(this, typeName, true); | |
460 } else { | |
461 type.setIsOopType(true); | |
462 } | |
463 } | |
464 } | |
465 | |
466 type.setSize(UNINITIALIZED_SIZE); | |
467 addType(type); | |
468 return type; | |
469 } | |
470 | |
471 /** Recursively creates a PointerType from the string representation | |
472 of the type's name. Note that this currently needs some | |
473 workarounds due to incomplete information in the VMStructs | |
474 database. */ | |
475 private BasicPointerType recursiveCreateBasicPointerType(String typeName) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
476 BasicPointerType result = (BasicPointerType)super.lookupType(typeName, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
477 if (result != null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
478 return result; |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
479 } |
0 | 480 String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); |
481 Type targetType = null; | |
482 if (typeNameIsPointerType(targetTypeName)) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
483 targetType = lookupType(targetTypeName, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
484 if (targetType == null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
485 targetType = recursiveCreateBasicPointerType(targetTypeName); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
486 } |
0 | 487 } else { |
488 targetType = lookupType(targetTypeName, false); | |
489 if (targetType == null) { | |
490 // Workaround for missing C integer types in database. | |
491 // Also looks like we can't throw an exception for other | |
492 // missing target types because there are some in old | |
493 // VMStructs tables that didn't have the target type declared. | |
494 // For this case, we create basic types that never get filled | |
495 // in. | |
496 | |
497 if (targetTypeName.equals("char") || | |
498 targetTypeName.equals("const char")) { | |
499 // We don't have a representation of const-ness of C types in the SA | |
500 BasicType basicTargetType = createBasicType(targetTypeName, false, true, false); | |
501 basicTargetType.setSize(1); | |
502 targetType = basicTargetType; | |
503 } else if (targetTypeName.equals("u_char")) { | |
504 BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); | |
505 basicTargetType.setSize(1); | |
506 targetType = basicTargetType; | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
507 } else if (targetTypeName.startsWith("GrowableArray<")) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
508 BasicType basicTargetType = createBasicType(targetTypeName, false, false, false); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
509 |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
510 // transfer fields from GenericGrowableArray to template instance |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
511 BasicType generic = lookupOrFail("GenericGrowableArray"); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
512 basicTargetType.setSize(generic.getSize()); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
513 Iterator fields = generic.getFields(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
514 while (fields.hasNext()) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
515 Field f = (Field)fields.next(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
516 basicTargetType.addField(internalCreateField(basicTargetType, f.getName(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
517 f.getType(), f.isStatic(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
518 f.getOffset(), null)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
519 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
520 targetType = basicTargetType; |
0 | 521 } else { |
522 if (DEBUG) { | |
523 System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); | |
524 } | |
525 targetType = createBasicType(targetTypeName, false, false, false); | |
526 } | |
527 } | |
528 } | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
529 result = new BasicPointerType(this, typeName, targetType); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
530 result.setSize(UNINITIALIZED_SIZE); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
531 addType(result); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2072
diff
changeset
|
532 return result; |
0 | 533 } |
534 | |
535 private boolean typeNameIsPointerType(String typeName) { | |
536 int i = typeName.length() - 1; | |
537 while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) { | |
538 --i; | |
539 } | |
540 if (i >= 0 && typeName.charAt(i) == '*') { | |
541 return true; | |
542 } | |
543 return false; | |
544 } | |
545 | |
546 public void createType(String typeName, String superclassName, | |
547 boolean isOopType, boolean isIntegerType, | |
548 boolean isUnsigned, long size) { | |
549 // See whether we have a superclass | |
550 BasicType superclass = null; | |
551 if (superclassName != null) { | |
552 // Fetch or create it (FIXME: would get oop types wrong if | |
553 // they had a hierarchy; consider using lookupOrFail) | |
554 superclass = lookupOrCreateClass(superclassName, false, false, false); | |
555 } | |
556 | |
557 // Lookup or create the current type | |
558 BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned); | |
559 // Set superclass and/or ensure it's correct | |
560 if (superclass != null) { | |
561 if (curType.getSuperclass() == null) { | |
562 // Set the superclass in the current type | |
563 curType.setSuperclass(superclass); | |
564 } | |
565 | |
566 if (curType.getSuperclass() != superclass) { | |
567 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
568 "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " + | |
569 superclass.getName() + ")."); | |
570 } | |
571 } | |
572 | |
573 // Classes are created with a size of UNINITIALIZED_SIZE. | |
574 // Set size if necessary. | |
575 if (curType.getSize() == UNINITIALIZED_SIZE) { | |
576 curType.setSize(size); | |
577 } else { | |
578 if (curType.getSize() != size) { | |
579 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
580 "had its size redefined (old was " + curType.getSize() + ", new is " + size + ")."); | |
581 } | |
582 | |
583 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + | |
584 "had its size declared as " + size + " twice. Continuing."); | |
585 } | |
586 | |
587 } | |
588 | |
589 /** "Virtual constructor" for fields based on type */ | |
590 public void createField(BasicType containingType, | |
591 String name, Type type, boolean isStatic, | |
592 long offset, Address staticFieldAddress) { | |
593 // Add field to containing type | |
594 containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress)); | |
595 } | |
596 | |
597 Field internalCreateField(BasicType containingType, | |
598 String name, Type type, boolean isStatic, | |
599 long offset, Address staticFieldAddress) { | |
600 // "Virtual constructor" based on type | |
601 if (type.isOopType()) { | |
602 return new BasicOopField(this, containingType, name, type, | |
603 isStatic, offset, staticFieldAddress); | |
604 } | |
605 | |
606 if (type instanceof CIntegerType) { | |
607 return new BasicCIntegerField(this, containingType, name, type, | |
608 isStatic, offset, staticFieldAddress); | |
609 } | |
610 | |
611 if (type.equals(getJBooleanType())) { | |
612 return new BasicJBooleanField(this, containingType, name, type, | |
613 isStatic, offset, staticFieldAddress); | |
614 } | |
615 | |
616 if (type.equals(getJByteType())) { | |
617 return new BasicJByteField(this, containingType, name, type, | |
618 isStatic, offset, staticFieldAddress); | |
619 } | |
620 | |
621 if (type.equals(getJCharType())) { | |
622 return new BasicJCharField(this, containingType, name, type, | |
623 isStatic, offset, staticFieldAddress); | |
624 } | |
625 | |
626 if (type.equals(getJDoubleType())) { | |
627 return new BasicJDoubleField(this, containingType, name, type, | |
628 isStatic, offset, staticFieldAddress); | |
629 } | |
630 | |
631 if (type.equals(getJFloatType())) { | |
632 return new BasicJFloatField(this, containingType, name, type, | |
633 isStatic, offset, staticFieldAddress); | |
634 } | |
635 | |
636 if (type.equals(getJIntType())) { | |
637 return new BasicJIntField(this, containingType, name, type, | |
638 isStatic, offset, staticFieldAddress); | |
639 } | |
640 | |
641 if (type.equals(getJLongType())) { | |
642 return new BasicJLongField(this, containingType, name, type, | |
643 isStatic, offset, staticFieldAddress); | |
644 } | |
645 | |
646 if (type.equals(getJShortType())) { | |
647 return new BasicJShortField(this, containingType, name, type, | |
648 isStatic, offset, staticFieldAddress); | |
649 } | |
650 | |
651 // Unknown ("opaque") type. Instantiate ordinary Field. | |
652 return new BasicField(this, containingType, name, type, | |
653 isStatic, offset, staticFieldAddress); | |
654 } | |
655 | |
656 // For debugging | |
657 private void dumpMemory(Address addr, int len) { | |
658 int i = 0; | |
659 while (i < len) { | |
660 System.err.print(addr.addOffsetTo(i) + ":"); | |
661 for (int j = 0; j < 8 && i < len; i++, j++) { | |
662 String s = Long.toHexString(addr.getCIntegerAt(i, 1, true)); | |
663 System.err.print(" 0x"); | |
664 for (int k = 0; k < 2 - s.length(); k++) { | |
665 System.err.print("0"); | |
666 } | |
667 System.err.print(s); | |
668 } | |
669 System.err.println(); | |
670 } | |
671 } | |
672 } |