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