Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @ 13705:ac5b0f31f7a2
Truffle API-change: FrameDescriptors are now stored in the RootNode in a final field instead of the CallTarget.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Fri, 17 Jan 2014 17:06:08 +0100 |
parents | cfa2c82f4c04 |
children |
rev | line source |
---|---|
0 | 1 /* |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
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:
196
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
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:
196
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.oops; | |
26 | |
27 import java.util.*; | |
28 | |
29 import sun.jvm.hotspot.debugger.*; | |
30 import sun.jvm.hotspot.memory.*; | |
31 import sun.jvm.hotspot.runtime.*; | |
32 import sun.jvm.hotspot.types.TypeDataBase; | |
33 import sun.jvm.hotspot.utilities.*; | |
34 import sun.jvm.hotspot.jdi.JVMTIThreadState; | |
35 | |
36 /** A utility class encapsulating useful oop operations */ | |
37 | |
38 public class OopUtilities implements /* imports */ JVMTIThreadState { | |
39 | |
40 // FIXME: access should be synchronized and cleared when VM is | |
41 // resumed | |
42 // String fields | |
43 private static IntField offsetField; | |
44 private static IntField countField; | |
45 private static OopField valueField; | |
46 // ThreadGroup fields | |
47 private static OopField threadGroupParentField; | |
48 private static OopField threadGroupNameField; | |
49 private static IntField threadGroupNThreadsField; | |
50 private static OopField threadGroupThreadsField; | |
51 private static IntField threadGroupNGroupsField; | |
52 private static OopField threadGroupGroupsField; | |
53 // Thread fields | |
54 private static OopField threadNameField; | |
55 private static OopField threadGroupField; | |
56 private static LongField threadEETopField; | |
57 // threadStatus field is new since 1.5 | |
58 private static IntField threadStatusField; | |
59 // parkBlocker field is new since 1.6 | |
60 private static OopField threadParkBlockerField; | |
61 | |
62 // possible values of java_lang_Thread::ThreadStatus | |
63 private static int THREAD_STATUS_NEW; | |
64 /* | |
65 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
66 | |
67 private static int THREAD_STATUS_RUNNABLE; | |
68 private static int THREAD_STATUS_SLEEPING; | |
69 private static int THREAD_STATUS_IN_OBJECT_WAIT; | |
70 private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED; | |
71 private static int THREAD_STATUS_PARKED; | |
72 private static int THREAD_STATUS_PARKED_TIMED; | |
73 private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER; | |
74 private static int THREAD_STATUS_TERMINATED; | |
75 */ | |
76 | |
77 // java.util.concurrent.locks.AbstractOwnableSynchronizer fields | |
78 private static OopField absOwnSyncOwnerThreadField; | |
79 | |
80 static { | |
81 VM.registerVMInitializedObserver(new Observer() { | |
82 public void update(Observable o, Object data) { | |
83 initialize(VM.getVM().getTypeDataBase()); | |
84 } | |
85 }); | |
86 } | |
87 | |
88 private static synchronized void initialize(TypeDataBase db) { | |
89 // FIXME: don't need this observer; however, do need a VM resumed | |
90 // and suspended observer to refetch fields | |
91 } | |
92 | |
93 public static String charArrayToString(TypeArray charArray) { | |
94 if (charArray == null) { | |
95 return null; | |
96 } | |
97 return charArrayToString(charArray, 0, (int) charArray.getLength()); | |
98 } | |
99 | |
100 public static String charArrayToString(TypeArray charArray, int offset, int length) { | |
101 if (charArray == null) { | |
102 return null; | |
103 } | |
104 final int limit = offset + length; | |
105 if (Assert.ASSERTS_ENABLED) { | |
106 Assert.that(offset >= 0 && limit <= charArray.getLength(), "out of bounds"); | |
107 } | |
108 StringBuffer buf = new StringBuffer(length); | |
109 for (int i = offset; i < limit; i++) { | |
110 buf.append(charArray.getCharAt(i)); | |
111 } | |
112 return buf.toString(); | |
113 } | |
114 | |
3939 | 115 public static String escapeString(String s) { |
116 StringBuilder sb = null; | |
117 for (int index = 0; index < s.length(); index++) { | |
118 char value = s.charAt(index); | |
119 if (value >= 32 && value < 127 || value == '\'' || value == '\\') { | |
120 if (sb != null) { | |
121 sb.append(value); | |
122 } | |
123 } else { | |
124 if (sb == null) { | |
125 sb = new StringBuilder(s.length() * 2); | |
126 sb.append(s, 0, index); | |
127 } | |
128 sb.append("\\u"); | |
129 if (value < 0x10) sb.append("000"); | |
130 else if (value < 0x100) sb.append("00"); | |
131 else if (value < 0x1000) sb.append("0"); | |
132 sb.append(Integer.toHexString(value)); | |
133 } | |
134 } | |
135 if (sb != null) { | |
136 return sb.toString(); | |
137 } | |
138 return s; | |
139 } | |
140 | |
0 | 141 public static String stringOopToString(Oop stringOop) { |
142 if (offsetField == null) { | |
143 InstanceKlass k = (InstanceKlass) stringOop.getKlass(); | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
144 offsetField = (IntField) k.findField("offset", "I"); // optional |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
145 countField = (IntField) k.findField("count", "I"); // optional |
0 | 146 valueField = (OopField) k.findField("value", "[C"); |
147 if (Assert.ASSERTS_ENABLED) { | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
148 Assert.that(valueField != null, "Field \'value\' of java.lang.String not found"); |
0 | 149 } |
150 } | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
151 if (offsetField != null && countField != null) { |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
152 return charArrayToString((TypeArray) valueField.getValue(stringOop), |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
153 offsetField.getValue(stringOop), |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
154 countField.getValue(stringOop)); |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
155 } |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
156 return charArrayToString((TypeArray) valueField.getValue(stringOop)); |
0 | 157 } |
158 | |
3939 | 159 public static String stringOopToEscapedString(Oop stringOop) { |
160 return escapeString(stringOopToString(stringOop)); | |
161 } | |
162 | |
0 | 163 private static void initThreadGroupFields() { |
164 if (threadGroupParentField == null) { | |
165 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
166 InstanceKlass k = sysDict.getThreadGroupKlass(); | |
167 threadGroupParentField = (OopField) k.findField("parent", "Ljava/lang/ThreadGroup;"); | |
168 threadGroupNameField = (OopField) k.findField("name", "Ljava/lang/String;"); | |
169 threadGroupNThreadsField = (IntField) k.findField("nthreads", "I"); | |
170 threadGroupThreadsField = (OopField) k.findField("threads", "[Ljava/lang/Thread;"); | |
171 threadGroupNGroupsField = (IntField) k.findField("ngroups", "I"); | |
172 threadGroupGroupsField = (OopField) k.findField("groups", "[Ljava/lang/ThreadGroup;"); | |
173 if (Assert.ASSERTS_ENABLED) { | |
174 Assert.that(threadGroupParentField != null && | |
175 threadGroupNameField != null && | |
176 threadGroupNThreadsField != null && | |
177 threadGroupThreadsField != null && | |
178 threadGroupNGroupsField != null && | |
179 threadGroupGroupsField != null, "must find all java.lang.ThreadGroup fields"); | |
180 } | |
181 } | |
182 } | |
183 | |
184 public static Oop threadGroupOopGetParent(Oop threadGroupOop) { | |
185 initThreadGroupFields(); | |
186 return threadGroupParentField.getValue(threadGroupOop); | |
187 } | |
188 | |
189 public static String threadGroupOopGetName(Oop threadGroupOop) { | |
190 initThreadGroupFields(); | |
191 return stringOopToString(threadGroupNameField.getValue(threadGroupOop)); | |
192 } | |
193 | |
194 public static Oop[] threadGroupOopGetThreads(Oop threadGroupOop) { | |
195 initThreadGroupFields(); | |
196 int nthreads = threadGroupNThreadsField.getValue(threadGroupOop); | |
197 Oop[] result = new Oop[nthreads]; | |
198 ObjArray threads = (ObjArray) threadGroupThreadsField.getValue(threadGroupOop); | |
199 for (int i = 0; i < nthreads; i++) { | |
200 result[i] = threads.getObjAt(i); | |
201 } | |
202 return result; | |
203 } | |
204 | |
205 public static Oop[] threadGroupOopGetGroups(Oop threadGroupOop) { | |
206 initThreadGroupFields(); | |
207 int ngroups = threadGroupNGroupsField.getValue(threadGroupOop); | |
208 Oop[] result = new Oop[ngroups]; | |
209 ObjArray groups = (ObjArray) threadGroupGroupsField.getValue(threadGroupOop); | |
210 for (int i = 0; i < ngroups; i++) { | |
211 result[i] = groups.getObjAt(i); | |
212 } | |
213 return result; | |
214 } | |
215 | |
216 private static void initThreadFields() { | |
217 if (threadNameField == null) { | |
218 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
219 InstanceKlass k = sysDict.getThreadKlass(); | |
220 threadNameField = (OopField) k.findField("name", "[C"); | |
221 threadGroupField = (OopField) k.findField("group", "Ljava/lang/ThreadGroup;"); | |
222 threadEETopField = (LongField) k.findField("eetop", "J"); | |
223 threadStatusField = (IntField) k.findField("threadStatus", "I"); | |
224 threadParkBlockerField = (OopField) k.findField("parkBlocker", | |
225 "Ljava/lang/Object;"); | |
226 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
227 THREAD_STATUS_NEW = db.lookupIntConstant("java_lang_Thread::NEW").intValue(); | |
228 /* | |
229 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
230 | |
231 THREAD_STATUS_RUNNABLE = db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue(); | |
232 THREAD_STATUS_SLEEPING = db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue(); | |
233 THREAD_STATUS_IN_OBJECT_WAIT = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue(); | |
234 THREAD_STATUS_IN_OBJECT_WAIT_TIMED = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue(); | |
235 THREAD_STATUS_PARKED = db.lookupIntConstant("java_lang_Thread::PARKED").intValue(); | |
236 THREAD_STATUS_PARKED_TIMED = db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue(); | |
237 THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue(); | |
238 THREAD_STATUS_TERMINATED = db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue(); | |
239 */ | |
240 | |
241 if (Assert.ASSERTS_ENABLED) { | |
242 // it is okay to miss threadStatusField, because this was | |
243 // introduced only in 1.5 JDK. | |
244 Assert.that(threadNameField != null && | |
245 threadGroupField != null && | |
246 threadEETopField != null, "must find all java.lang.Thread fields"); | |
247 } | |
248 } | |
249 } | |
250 | |
251 public static Oop threadOopGetThreadGroup(Oop threadOop) { | |
252 initThreadFields(); | |
253 return threadGroupField.getValue(threadOop); | |
254 } | |
255 | |
256 public static String threadOopGetName(Oop threadOop) { | |
257 initThreadFields(); | |
258 return charArrayToString((TypeArray) threadNameField.getValue(threadOop)); | |
259 } | |
260 | |
261 /** May return null if, e.g., thread was not started */ | |
262 public static JavaThread threadOopGetJavaThread(Oop threadOop) { | |
263 initThreadFields(); | |
264 Address addr = threadOop.getHandle().getAddressAt(threadEETopField.getOffset()); | |
265 if (addr == null) { | |
266 return null; | |
267 } | |
268 return VM.getVM().getThreads().createJavaThreadWrapper(addr); | |
269 } | |
270 | |
271 /** returns value of java.lang.Thread.threadStatus field */ | |
272 public static int threadOopGetThreadStatus(Oop threadOop) { | |
273 initThreadFields(); | |
274 // The threadStatus is only present starting in 1.5 | |
275 if (threadStatusField != null) { | |
276 return (int) threadStatusField.getValue(threadOop); | |
277 } else { | |
278 // All we can easily figure out is if it is alive, but that is | |
279 // enough info for a valid unknown status. | |
280 JavaThread thr = threadOopGetJavaThread(threadOop); | |
281 if (thr == null) { | |
282 // the thread hasn't run yet or is in the process of exiting | |
283 return THREAD_STATUS_NEW; | |
284 } else { | |
285 return JVMTI_THREAD_STATE_ALIVE; | |
286 } | |
287 } | |
288 } | |
289 | |
290 /** returns value of java.lang.Thread.parkBlocker field */ | |
291 public static Oop threadOopGetParkBlocker(Oop threadOop) { | |
292 initThreadFields(); | |
293 if (threadParkBlockerField != null) { | |
294 return threadParkBlockerField.getValue(threadOop); | |
295 } | |
296 return null; | |
297 } | |
298 | |
299 // initialize fields for j.u.c.l AbstractOwnableSynchornizer class | |
300 private static void initAbsOwnSyncFields() { | |
301 if (absOwnSyncOwnerThreadField == null) { | |
302 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
303 InstanceKlass k = sysDict.getAbstractOwnableSynchronizerKlass(); | |
304 absOwnSyncOwnerThreadField = | |
305 (OopField) k.findField("exclusiveOwnerThread", | |
306 "Ljava/lang/Thread;"); | |
307 } | |
308 } | |
309 | |
310 // return exclusiveOwnerThread field of AbstractOwnableSynchronizer class | |
311 public static Oop abstractOwnableSynchronizerGetOwnerThread(Oop oop) { | |
312 initAbsOwnSyncFields(); | |
313 if (absOwnSyncOwnerThreadField == null) { | |
314 return null; // pre-1.6 VM? | |
315 } else { | |
316 return absOwnSyncOwnerThreadField.getValue(oop); | |
317 } | |
318 } | |
319 } |