Mercurial > hg > truffle
annotate src/share/vm/prims/jvmtiTrace.cpp @ 452:00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery.
Reviewed-by: apetrusenko, jcoomes
author | ysr |
---|---|
date | Thu, 20 Nov 2008 12:27:41 -0800 |
parents | 885fe0f95828 |
children | ad8c8ca4ab0f |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. | |
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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_jvmtiTrace.cpp.incl" | |
27 | |
28 // | |
29 // class JvmtiTrace | |
30 // | |
31 // Support for JVMTI tracing code | |
32 // | |
33 // ------------ | |
34 // Usage: | |
35 // -XX:TraceJVMTI=DESC,DESC,DESC | |
36 // | |
37 // DESC is DOMAIN ACTION KIND | |
38 // | |
39 // DOMAIN is function name | |
40 // event name | |
41 // "all" (all functions and events) | |
42 // "func" (all functions except boring) | |
43 // "allfunc" (all functions) | |
44 // "event" (all events) | |
45 // "ec" (event controller) | |
46 // | |
47 // ACTION is "+" (add) | |
48 // "-" (remove) | |
49 // | |
50 // KIND is | |
51 // for func | |
52 // "i" (input params) | |
53 // "e" (error returns) | |
54 // "o" (output) | |
55 // for event | |
56 // "t" (event triggered aka posted) | |
57 // "s" (event sent) | |
58 // | |
59 // Example: | |
60 // -XX:TraceJVMTI=ec+,GetCallerFrame+ie,Breakpoint+s | |
61 | |
62 #ifdef JVMTI_TRACE | |
63 | |
64 bool JvmtiTrace::_initialized = false; | |
65 bool JvmtiTrace::_on = false; | |
66 bool JvmtiTrace::_trace_event_controller = false; | |
67 | |
68 void JvmtiTrace::initialize() { | |
69 if (_initialized) { | |
70 return; | |
71 } | |
72 SafeResourceMark rm; | |
73 | |
74 const char *very_end; | |
75 const char *curr; | |
370
885fe0f95828
6744783: HotSpot segfaults if given -XX options with an empty string argument
never
parents:
0
diff
changeset
|
76 if (TraceJVMTI != NULL) { |
0 | 77 curr = TraceJVMTI; |
78 } else { | |
79 curr = ""; // hack in fixed tracing here | |
80 } | |
81 very_end = curr + strlen(curr); | |
82 while (curr < very_end) { | |
83 const char *curr_end = strchr(curr, ','); | |
84 if (curr_end == NULL) { | |
85 curr_end = very_end; | |
86 } | |
87 const char *op_pos = strchr(curr, '+'); | |
88 const char *minus_pos = strchr(curr, '-'); | |
89 if (minus_pos != NULL && (minus_pos < op_pos || op_pos == NULL)) { | |
90 op_pos = minus_pos; | |
91 } | |
92 char op; | |
93 const char *flags = op_pos + 1; | |
94 const char *flags_end = curr_end; | |
95 if (op_pos == NULL || op_pos > curr_end) { | |
96 flags = "ies"; | |
97 flags_end = flags + strlen(flags); | |
98 op_pos = curr_end; | |
99 op = '+'; | |
100 } else { | |
101 op = *op_pos; | |
102 } | |
103 jbyte bits = 0; | |
104 for (; flags < flags_end; ++flags) { | |
105 switch (*flags) { | |
106 case 'i': | |
107 bits |= SHOW_IN; | |
108 break; | |
109 case 'I': | |
110 bits |= SHOW_IN_DETAIL; | |
111 break; | |
112 case 'e': | |
113 bits |= SHOW_ERROR; | |
114 break; | |
115 case 'o': | |
116 bits |= SHOW_OUT; | |
117 break; | |
118 case 'O': | |
119 bits |= SHOW_OUT_DETAIL; | |
120 break; | |
121 case 't': | |
122 bits |= SHOW_EVENT_TRIGGER; | |
123 break; | |
124 case 's': | |
125 bits |= SHOW_EVENT_SENT; | |
126 break; | |
127 default: | |
128 tty->print_cr("Invalid trace flag '%c'", *flags); | |
129 break; | |
130 } | |
131 } | |
132 const int FUNC = 1; | |
133 const int EXCLUDE = 2; | |
134 const int ALL_FUNC = 4; | |
135 const int EVENT = 8; | |
136 const int ALL_EVENT = 16; | |
137 int domain = 0; | |
138 size_t len = op_pos - curr; | |
139 if (op_pos == curr) { | |
140 domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT | EXCLUDE; | |
141 } else if (len==3 && strncmp(curr, "all", 3)==0) { | |
142 domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT; | |
143 } else if (len==7 && strncmp(curr, "allfunc", 7)==0) { | |
144 domain = ALL_FUNC | FUNC; | |
145 } else if (len==4 && strncmp(curr, "func", 4)==0) { | |
146 domain = ALL_FUNC | FUNC | EXCLUDE; | |
147 } else if (len==8 && strncmp(curr, "allevent", 8)==0) { | |
148 domain = ALL_EVENT | EVENT; | |
149 } else if (len==5 && strncmp(curr, "event", 5)==0) { | |
150 domain = ALL_EVENT | EVENT; | |
151 } else if (len==2 && strncmp(curr, "ec", 2)==0) { | |
152 _trace_event_controller = true; | |
153 tty->print_cr("JVMTI Tracing the event controller"); | |
154 } else { | |
155 domain = FUNC | EVENT; // go searching | |
156 } | |
157 | |
158 int exclude_index = 0; | |
159 if (domain & FUNC) { | |
160 if (domain & ALL_FUNC) { | |
161 if (domain & EXCLUDE) { | |
162 tty->print("JVMTI Tracing all significant functions"); | |
163 } else { | |
164 tty->print_cr("JVMTI Tracing all functions"); | |
165 } | |
166 } | |
167 for (int i = 0; i <= _max_function_index; ++i) { | |
168 if (domain & EXCLUDE && i == _exclude_functions[exclude_index]) { | |
169 ++exclude_index; | |
170 } else { | |
171 bool do_op = false; | |
172 if (domain & ALL_FUNC) { | |
173 do_op = true; | |
174 } else { | |
175 const char *fname = function_name(i); | |
176 if (fname != NULL) { | |
177 size_t fnlen = strlen(fname); | |
178 if (len==fnlen && strncmp(curr, fname, fnlen)==0) { | |
179 tty->print_cr("JVMTI Tracing the function: %s", fname); | |
180 do_op = true; | |
181 } | |
182 } | |
183 } | |
184 if (do_op) { | |
185 if (op == '+') { | |
186 _trace_flags[i] |= bits; | |
187 } else { | |
188 _trace_flags[i] &= ~bits; | |
189 } | |
190 _on = true; | |
191 } | |
192 } | |
193 } | |
194 } | |
195 if (domain & EVENT) { | |
196 if (domain & ALL_EVENT) { | |
197 tty->print_cr("JVMTI Tracing all events"); | |
198 } | |
199 for (int i = 0; i <= _max_event_index; ++i) { | |
200 bool do_op = false; | |
201 if (domain & ALL_EVENT) { | |
202 do_op = true; | |
203 } else { | |
204 const char *ename = event_name(i); | |
205 if (ename != NULL) { | |
206 size_t evtlen = strlen(ename); | |
207 if (len==evtlen && strncmp(curr, ename, evtlen)==0) { | |
208 tty->print_cr("JVMTI Tracing the event: %s", ename); | |
209 do_op = true; | |
210 } | |
211 } | |
212 } | |
213 if (do_op) { | |
214 if (op == '+') { | |
215 _event_trace_flags[i] |= bits; | |
216 } else { | |
217 _event_trace_flags[i] &= ~bits; | |
218 } | |
219 _on = true; | |
220 } | |
221 } | |
222 } | |
223 if (!_on && (domain & (FUNC|EVENT))) { | |
224 tty->print_cr("JVMTI Trace domain not found"); | |
225 } | |
226 curr = curr_end + 1; | |
227 } | |
228 _initialized = true; | |
229 } | |
230 | |
231 | |
232 void JvmtiTrace::shutdown() { | |
233 int i; | |
234 _on = false; | |
235 _trace_event_controller = false; | |
236 for (i = 0; i <= _max_function_index; ++i) { | |
237 _trace_flags[i] = 0; | |
238 } | |
239 for (i = 0; i <= _max_event_index; ++i) { | |
240 _event_trace_flags[i] = 0; | |
241 } | |
242 } | |
243 | |
244 | |
245 const char* JvmtiTrace::enum_name(const char** names, const jint* values, jint value) { | |
246 for (int index = 0; names[index] != 0; ++index) { | |
247 if (values[index] == value) { | |
248 return names[index]; | |
249 } | |
250 } | |
251 return "*INVALID-ENUM-VALUE*"; | |
252 } | |
253 | |
254 | |
255 // return a valid string no matter what state the thread is in | |
256 const char *JvmtiTrace::safe_get_thread_name(Thread *thread) { | |
257 if (thread == NULL) { | |
258 return "NULL"; | |
259 } | |
260 if (!thread->is_Java_thread()) { | |
261 return thread->name(); | |
262 } | |
263 JavaThread *java_thread = (JavaThread *)thread; | |
264 oop threadObj = java_thread->threadObj(); | |
265 if (threadObj == NULL) { | |
266 return "NULL"; | |
267 } | |
268 typeArrayOop name = java_lang_Thread::name(threadObj); | |
269 if (name == NULL) { | |
270 return "<NOT FILLED IN>"; | |
271 } | |
272 return UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); | |
273 } | |
274 | |
275 | |
276 // return the name of the current thread | |
277 const char *JvmtiTrace::safe_get_current_thread_name() { | |
278 if (JvmtiEnv::is_vm_live()) { | |
279 return JvmtiTrace::safe_get_thread_name(Thread::current()); | |
280 } else { | |
281 return "VM not live"; | |
282 } | |
283 } | |
284 | |
285 // return a valid string no matter what the state of k_mirror | |
286 const char * JvmtiTrace::get_class_name(oop k_mirror) { | |
287 if (java_lang_Class::is_primitive(k_mirror)) { | |
288 return "primitive"; | |
289 } | |
290 klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); | |
291 if (k_oop == NULL) { | |
292 return "INVALID"; | |
293 } | |
294 return Klass::cast(k_oop)->external_name(); | |
295 } | |
296 | |
297 #endif /*JVMTI_TRACE */ |