Mercurial > hg > graal-jvmci-8
annotate src/share/vm/runtime/perfData.cpp @ 3979:4dfb2df418f2
6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
author | johnc |
---|---|
date | Thu, 22 Sep 2011 10:57:37 -0700 |
parents | f95d63e2154a |
children | d2a62e0f25eb |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2001, 2010, 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:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
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:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/vmSymbols.hpp" | |
27 #include "oops/oop.inline.hpp" | |
28 #include "runtime/handles.inline.hpp" | |
29 #include "runtime/java.hpp" | |
30 #include "runtime/mutex.hpp" | |
31 #include "runtime/mutexLocker.hpp" | |
32 #include "runtime/os.hpp" | |
33 #include "runtime/perfData.hpp" | |
34 #include "utilities/exceptions.hpp" | |
35 #include "utilities/globalDefinitions.hpp" | |
0 | 36 |
37 PerfDataList* PerfDataManager::_all = NULL; | |
38 PerfDataList* PerfDataManager::_sampled = NULL; | |
39 PerfDataList* PerfDataManager::_constants = NULL; | |
40 | |
41 /* | |
42 * The jvmstat global and subsysem jvmstat counter name spaces. The top | |
43 * level name spaces imply the interface stability level of the counter, | |
44 * which generally follows the Java package, class, and property naming | |
45 * conventions. The CounterNS enumeration values should be used to index | |
46 * into this array. | |
47 */ | |
48 const char* PerfDataManager::_name_spaces[] = { | |
49 // top level name spaces | |
50 "java", // stable and supported name space | |
51 "com.sun", // unstable but supported name space | |
52 "sun", // unstable and unsupported name space | |
53 // subsystem name spaces | |
54 "java.gc", // Garbage Collection name spaces | |
55 "com.sun.gc", | |
56 "sun.gc", | |
57 "java.ci", // Compiler name spaces | |
58 "com.sun.ci", | |
59 "sun.ci", | |
60 "java.cls", // Class Loader name spaces | |
61 "com.sun.cls", | |
62 "sun.cls", | |
63 "java.rt", // Runtime name spaces | |
64 "com.sun.rt", | |
65 "sun.rt", | |
66 "java.os", // Operating System name spaces | |
67 "com.sun.os", | |
68 "sun.os", | |
69 "java.threads", // Threads System name spaces | |
70 "com.sun.threads", | |
71 "sun.threads", | |
72 "java.property", // Java Property name spaces | |
73 "com.sun.property", | |
74 "sun.property", | |
75 "", | |
76 }; | |
77 | |
78 PerfData::PerfData(CounterNS ns, const char* name, Units u, Variability v) | |
79 : _name(NULL), _u(u), _v(v), _valuep(NULL), | |
80 _on_c_heap(false) { | |
81 | |
82 const char* prefix = PerfDataManager::ns_to_string(ns); | |
83 | |
84 _name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2); | |
85 assert(_name != NULL && strlen(name) != 0, "invalid name"); | |
86 | |
87 if (ns == NULL_NS) { | |
88 // No prefix is added to counters with the NULL_NS namespace. | |
89 strcpy(_name, name); | |
90 // set the F_Supported flag based on the counter name prefix. | |
91 if (PerfDataManager::is_stable_supported(_name) || | |
92 PerfDataManager::is_unstable_supported(_name)) { | |
93 _flags = F_Supported; | |
94 } | |
95 else { | |
96 _flags = F_None; | |
97 } | |
98 } | |
99 else { | |
100 sprintf(_name, "%s.%s", prefix, name); | |
101 // set the F_Supported flag based on the given namespace. | |
102 if (PerfDataManager::is_stable_supported(ns) || | |
103 PerfDataManager::is_unstable_supported(ns)) { | |
104 _flags = F_Supported; | |
105 } | |
106 else { | |
107 _flags = F_None; | |
108 } | |
109 } | |
110 } | |
111 | |
112 PerfData::~PerfData() { | |
113 if (_name != NULL) { | |
114 FREE_C_HEAP_ARRAY(char, _name); | |
115 } | |
116 if (is_on_c_heap()) { | |
117 FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep); | |
118 } | |
119 } | |
120 | |
121 void PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) { | |
122 | |
123 size_t dlen = vlen==0 ? 1 : vlen; | |
124 | |
125 size_t namelen = strlen(name()) + 1; // include null terminator | |
126 size_t size = sizeof(PerfDataEntry) + namelen; | |
127 size_t pad_length = ((size % dsize) == 0) ? 0 : dsize - (size % dsize); | |
128 size += pad_length; | |
129 size_t data_start = size; | |
130 size += (dsize * dlen); | |
131 | |
132 // align size to assure allocation in units of 8 bytes | |
133 int align = sizeof(jlong) - 1; | |
134 size = ((size + align) & ~align); | |
135 char* psmp = PerfMemory::alloc(size); | |
136 | |
137 if (psmp == NULL) { | |
138 // out of PerfMemory memory resources. allocate on the C heap | |
139 // to avoid vm termination. | |
140 psmp = NEW_C_HEAP_ARRAY(char, size); | |
141 _on_c_heap = true; | |
142 } | |
143 | |
144 // compute the addresses for the name and data | |
145 char* cname = psmp + sizeof(PerfDataEntry); | |
146 | |
147 // data is in the last dsize*dlen bytes of the entry | |
148 void* valuep = (void*) (psmp + data_start); | |
149 | |
150 assert(is_on_c_heap() || PerfMemory::contains(cname), "just checking"); | |
151 assert(is_on_c_heap() || PerfMemory::contains((char*)valuep), "just checking"); | |
152 | |
153 // copy the name, including null terminator, into PerfData memory | |
154 strcpy(cname, name()); | |
155 | |
156 | |
157 // set the header values in PerfData memory | |
158 PerfDataEntry* pdep = (PerfDataEntry*)psmp; | |
159 pdep->entry_length = (jint)size; | |
160 pdep->name_offset = (jint) ((uintptr_t) cname - (uintptr_t) psmp); | |
161 pdep->vector_length = (jint)vlen; | |
162 pdep->data_type = (jbyte) type2char(dtype); | |
163 pdep->data_units = units(); | |
164 pdep->data_variability = variability(); | |
165 pdep->flags = (jbyte)flags(); | |
166 pdep->data_offset = (jint) data_start; | |
167 | |
168 if (PerfTraceDataCreation) { | |
169 tty->print("name = %s, dtype = %d, variability = %d," | |
170 " units = %d, dsize = %d, vlen = %d," | |
171 " pad_length = %d, size = %d, on_c_heap = %s," | |
172 " address = " INTPTR_FORMAT "," | |
173 " data address = " INTPTR_FORMAT "\n", | |
174 cname, dtype, variability(), | |
175 units(), dsize, vlen, | |
176 pad_length, size, is_on_c_heap() ? "TRUE":"FALSE", | |
177 psmp, valuep); | |
178 } | |
179 | |
180 // record the start of the entry and the location of the data field. | |
181 _pdep = pdep; | |
182 _valuep = valuep; | |
183 | |
184 // mark the PerfData memory region as having been updated. | |
185 PerfMemory::mark_updated(); | |
186 } | |
187 | |
188 PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v) | |
189 : PerfData(ns, namep, u, v) { | |
190 | |
191 create_entry(T_LONG, sizeof(jlong)); | |
192 } | |
193 | |
194 int PerfLong::format(char* buffer, int length) { | |
195 return jio_snprintf(buffer, length,"%lld", *(jlong*)_valuep); | |
196 } | |
197 | |
198 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u, | |
199 Variability v, jlong* sampled) | |
200 : PerfLong(ns, namep, u, v), | |
201 _sampled(sampled), _sample_helper(NULL) { | |
202 | |
203 sample(); | |
204 } | |
205 | |
206 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u, | |
207 Variability v, PerfLongSampleHelper* helper) | |
208 : PerfLong(ns, namep, u, v), | |
209 _sampled(NULL), _sample_helper(helper) { | |
210 | |
211 sample(); | |
212 } | |
213 | |
214 void PerfLongVariant::sample() { | |
215 | |
216 assert(_sample_helper != NULL || _sampled != NULL, "unexpected state"); | |
217 | |
218 if (_sample_helper != NULL) { | |
219 *(jlong*)_valuep = _sample_helper->take_sample(); | |
220 } | |
221 else if (_sampled != NULL) { | |
222 *(jlong*)_valuep = *_sampled; | |
223 } | |
224 } | |
225 | |
226 PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u, | |
227 Variability v, jint length) | |
228 : PerfData(ns, namep, u, v), _length(length) { | |
229 | |
230 create_entry(T_BYTE, sizeof(jbyte), (size_t)_length); | |
231 } | |
232 | |
233 void PerfString::set_string(const char* s2) { | |
234 | |
235 // copy n bytes of the string, assuring the null string is | |
236 // copied if s2 == NULL. | |
237 strncpy((char *)_valuep, s2 == NULL ? "" : s2, _length); | |
238 | |
239 // assure the string is null terminated when strlen(s2) >= _length | |
240 ((char*)_valuep)[_length-1] = '\0'; | |
241 } | |
242 | |
243 int PerfString::format(char* buffer, int length) { | |
244 return jio_snprintf(buffer, length, "%s", (char*)_valuep); | |
245 } | |
246 | |
247 PerfStringConstant::PerfStringConstant(CounterNS ns, const char* namep, | |
248 const char* initial_value) | |
249 : PerfString(ns, namep, V_Constant, | |
250 initial_value == NULL ? 1 : | |
251 MIN2((jint)(strlen((char*)initial_value)+1), | |
252 (jint)(PerfMaxStringConstLength+1)), | |
253 initial_value) { | |
254 | |
255 if (PrintMiscellaneous && Verbose) { | |
256 if (is_valid() && initial_value != NULL && | |
257 ((jint)strlen(initial_value) > (jint)PerfMaxStringConstLength)) { | |
258 | |
259 warning("Truncating PerfStringConstant: name = %s," | |
260 " length = " INT32_FORMAT "," | |
261 " PerfMaxStringConstLength = " INT32_FORMAT "\n", | |
262 namep, | |
263 (jint)strlen(initial_value), | |
264 (jint)PerfMaxStringConstLength); | |
265 } | |
266 } | |
267 } | |
268 | |
269 | |
270 | |
271 | |
272 | |
273 | |
274 void PerfDataManager::destroy() { | |
275 | |
276 if (_all == NULL) | |
277 // destroy already called, or initialization never happened | |
278 return; | |
279 | |
280 for (int index = 0; index < _all->length(); index++) { | |
281 PerfData* p = _all->at(index); | |
282 delete p; | |
283 } | |
284 | |
285 delete(_all); | |
286 delete(_sampled); | |
287 delete(_constants); | |
288 | |
289 _all = NULL; | |
290 _sampled = NULL; | |
291 _constants = NULL; | |
292 } | |
293 | |
294 void PerfDataManager::add_item(PerfData* p, bool sampled) { | |
295 | |
296 MutexLocker ml(PerfDataManager_lock); | |
297 | |
298 if (_all == NULL) { | |
299 _all = new PerfDataList(100); | |
300 } | |
301 | |
302 assert(!_all->contains(p->name()), "duplicate name added"); | |
303 | |
304 // add to the list of all perf data items | |
305 _all->append(p); | |
306 | |
307 if (p->variability() == PerfData::V_Constant) { | |
308 if (_constants == NULL) { | |
309 _constants = new PerfDataList(25); | |
310 } | |
311 _constants->append(p); | |
312 return; | |
313 } | |
314 | |
315 if (sampled) { | |
316 if (_sampled == NULL) { | |
317 _sampled = new PerfDataList(25); | |
318 } | |
319 _sampled->append(p); | |
320 } | |
321 } | |
322 | |
323 PerfDataList* PerfDataManager::all() { | |
324 | |
325 MutexLocker ml(PerfDataManager_lock); | |
326 | |
327 if (_all == NULL) | |
328 return NULL; | |
329 | |
330 PerfDataList* clone = _all->clone(); | |
331 return clone; | |
332 } | |
333 | |
334 PerfDataList* PerfDataManager::sampled() { | |
335 | |
336 MutexLocker ml(PerfDataManager_lock); | |
337 | |
338 if (_sampled == NULL) | |
339 return NULL; | |
340 | |
341 PerfDataList* clone = _sampled->clone(); | |
342 return clone; | |
343 } | |
344 | |
345 PerfDataList* PerfDataManager::constants() { | |
346 | |
347 MutexLocker ml(PerfDataManager_lock); | |
348 | |
349 if (_constants == NULL) | |
350 return NULL; | |
351 | |
352 PerfDataList* clone = _constants->clone(); | |
353 return clone; | |
354 } | |
355 | |
356 char* PerfDataManager::counter_name(const char* ns, const char* name) { | |
357 assert(ns != NULL, "ns string required"); | |
358 assert(name != NULL, "name string required"); | |
359 | |
360 size_t len = strlen(ns) + strlen(name) + 2; | |
361 char* result = NEW_RESOURCE_ARRAY(char, len); | |
362 sprintf(result, "%s.%s", ns, name); | |
363 return result; | |
364 } | |
365 | |
366 char* PerfDataManager::name_space(const char* ns, const char* sub, | |
367 int instance) { | |
368 char intbuf[40]; | |
369 jio_snprintf(intbuf, 40, UINT32_FORMAT, instance); | |
370 return name_space(ns, name_space(sub, intbuf)); | |
371 } | |
372 | |
373 char *PerfDataManager::name_space(const char* ns, int instance) { | |
374 char intbuf[40]; | |
375 jio_snprintf(intbuf, 40, UINT32_FORMAT, instance); | |
376 return name_space(ns, intbuf); | |
377 } | |
378 | |
379 PerfStringConstant* PerfDataManager::create_string_constant(CounterNS ns, | |
380 const char* name, | |
381 const char* s, | |
382 TRAPS) { | |
383 | |
384 PerfStringConstant* p = new PerfStringConstant(ns, name, s); | |
385 | |
386 if (!p->is_valid()) { | |
387 // allocation of native resources failed. | |
388 delete p; | |
389 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
390 } | |
391 | |
392 add_item(p, false); | |
393 | |
394 return p; | |
395 } | |
396 | |
397 PerfLongConstant* PerfDataManager::create_long_constant(CounterNS ns, | |
398 const char* name, | |
399 PerfData::Units u, | |
400 jlong val, TRAPS) { | |
401 | |
402 PerfLongConstant* p = new PerfLongConstant(ns, name, u, val); | |
403 | |
404 if (!p->is_valid()) { | |
405 // allocation of native resources failed. | |
406 delete p; | |
407 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
408 } | |
409 | |
410 add_item(p, false); | |
411 | |
412 return p; | |
413 } | |
414 | |
415 PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns, | |
416 const char* name, | |
417 jint max_length, | |
418 const char* s, | |
419 TRAPS) { | |
420 | |
421 if (max_length == 0 && s != NULL) max_length = (jint)strlen(s); | |
422 | |
423 assert(max_length != 0, "PerfStringVariable with length 0"); | |
424 | |
425 PerfStringVariable* p = new PerfStringVariable(ns, name, max_length, s); | |
426 | |
427 if (!p->is_valid()) { | |
428 // allocation of native resources failed. | |
429 delete p; | |
430 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
431 } | |
432 | |
433 add_item(p, false); | |
434 | |
435 return p; | |
436 } | |
437 | |
438 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, | |
439 const char* name, | |
440 PerfData::Units u, | |
441 jlong ival, TRAPS) { | |
442 | |
443 PerfLongVariable* p = new PerfLongVariable(ns, name, u, ival); | |
444 | |
445 if (!p->is_valid()) { | |
446 // allocation of native resources failed. | |
447 delete p; | |
448 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
449 } | |
450 | |
451 add_item(p, false); | |
452 | |
453 return p; | |
454 } | |
455 | |
456 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, | |
457 const char* name, | |
458 PerfData::Units u, | |
459 jlong* sp, TRAPS) { | |
460 | |
461 // Sampled counters not supported if UsePerfData is false | |
462 if (!UsePerfData) return NULL; | |
463 | |
464 PerfLongVariable* p = new PerfLongVariable(ns, name, u, sp); | |
465 | |
466 if (!p->is_valid()) { | |
467 // allocation of native resources failed. | |
468 delete p; | |
469 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
470 } | |
471 | |
472 add_item(p, true); | |
473 | |
474 return p; | |
475 } | |
476 | |
477 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, | |
478 const char* name, | |
479 PerfData::Units u, | |
480 PerfSampleHelper* sh, | |
481 TRAPS) { | |
482 | |
483 // Sampled counters not supported if UsePerfData is false | |
484 if (!UsePerfData) return NULL; | |
485 | |
486 PerfLongVariable* p = new PerfLongVariable(ns, name, u, sh); | |
487 | |
488 if (!p->is_valid()) { | |
489 // allocation of native resources failed. | |
490 delete p; | |
491 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
492 } | |
493 | |
494 add_item(p, true); | |
495 | |
496 return p; | |
497 } | |
498 | |
499 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, | |
500 const char* name, | |
501 PerfData::Units u, | |
502 jlong ival, TRAPS) { | |
503 | |
504 PerfLongCounter* p = new PerfLongCounter(ns, name, u, ival); | |
505 | |
506 if (!p->is_valid()) { | |
507 // allocation of native resources failed. | |
508 delete p; | |
509 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
510 } | |
511 | |
512 add_item(p, false); | |
513 | |
514 return p; | |
515 } | |
516 | |
517 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, | |
518 const char* name, | |
519 PerfData::Units u, | |
520 jlong* sp, TRAPS) { | |
521 | |
522 // Sampled counters not supported if UsePerfData is false | |
523 if (!UsePerfData) return NULL; | |
524 | |
525 PerfLongCounter* p = new PerfLongCounter(ns, name, u, sp); | |
526 | |
527 if (!p->is_valid()) { | |
528 // allocation of native resources failed. | |
529 delete p; | |
530 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
531 } | |
532 | |
533 add_item(p, true); | |
534 | |
535 return p; | |
536 } | |
537 | |
538 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, | |
539 const char* name, | |
540 PerfData::Units u, | |
541 PerfSampleHelper* sh, | |
542 TRAPS) { | |
543 | |
544 // Sampled counters not supported if UsePerfData is false | |
545 if (!UsePerfData) return NULL; | |
546 | |
547 PerfLongCounter* p = new PerfLongCounter(ns, name, u, sh); | |
548 | |
549 if (!p->is_valid()) { | |
550 // allocation of native resources failed. | |
551 delete p; | |
552 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
553 } | |
554 | |
555 add_item(p, true); | |
556 | |
557 return p; | |
558 } | |
559 | |
560 PerfDataList::PerfDataList(int length) { | |
561 | |
562 _set = new(ResourceObj::C_HEAP) PerfDataArray(length, true); | |
563 } | |
564 | |
565 PerfDataList::PerfDataList(PerfDataList* p) { | |
566 | |
567 _set = new(ResourceObj::C_HEAP) PerfDataArray(p->length(), true); | |
568 | |
569 _set->appendAll(p->get_impl()); | |
570 } | |
571 | |
572 PerfDataList::~PerfDataList() { | |
573 | |
574 delete _set; | |
575 | |
576 } | |
577 | |
578 bool PerfDataList::by_name(void* name, PerfData* pd) { | |
579 | |
580 if (pd == NULL) | |
581 return false; | |
582 | |
583 return strcmp((const char*)name, pd->name()) == 0; | |
584 } | |
585 | |
586 PerfData* PerfDataList::find_by_name(const char* name) { | |
587 | |
588 int i = _set->find((void*)name, PerfDataList::by_name); | |
589 | |
590 if (i >= 0 && i <= _set->length()) | |
591 return _set->at(i); | |
592 else | |
593 return NULL; | |
594 } | |
595 | |
596 PerfDataList* PerfDataList::clone() { | |
597 | |
598 PerfDataList* copy = new PerfDataList(this); | |
599 | |
600 assert(copy != NULL, "just checking"); | |
601 | |
602 return copy; | |
603 } |