Mercurial > hg > graal-compiler
comparison src/share/vm/memory/heapInspection.cpp @ 10405:f2110083203d
8005849: JEP 167: Event-Based JVM Tracing
Reviewed-by: acorn, coleenp, sla
Contributed-by: Karen Kinnear <karen.kinnear@oracle.com>, Bengt Rutisson <bengt.rutisson@oracle.com>, Calvin Cheung <calvin.cheung@oracle.com>, Erik Gahlin <erik.gahlin@oracle.com>, Erik Helin <erik.helin@oracle.com>, Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com>, Keith McGuigan <keith.mcguigan@oracle.com>, Mattias Tobiasson <mattias.tobiasson@oracle.com>, Markus Gronlund <markus.gronlund@oracle.com>, Mikael Auno <mikael.auno@oracle.com>, Nils Eliasson <nils.eliasson@oracle.com>, Nils Loodin <nils.loodin@oracle.com>, Rickard Backman <rickard.backman@oracle.com>, Staffan Larsen <staffan.larsen@oracle.com>, Stefan Karlsson <stefan.karlsson@oracle.com>, Yekaterina Kantserova <yekaterina.kantserova@oracle.com>
author | sla |
---|---|
date | Mon, 10 Jun 2013 11:30:51 +0200 |
parents | 92ef81e2f571 |
children | e0c9a1d29eb4 |
comparison
equal
deleted
inserted
replaced
10404:d0add7016434 | 10405:f2110083203d |
---|---|
93 if (elt->is_equal(k)) { | 93 if (elt->is_equal(k)) { |
94 return elt; | 94 return elt; |
95 } | 95 } |
96 elt = elt->next(); | 96 elt = elt->next(); |
97 } | 97 } |
98 elt = new KlassInfoEntry(k, list()); | 98 elt = new (std::nothrow) KlassInfoEntry(k, list()); |
99 // We may be out of space to allocate the new entry. | 99 // We may be out of space to allocate the new entry. |
100 if (elt != NULL) { | 100 if (elt != NULL) { |
101 set_list(elt); | 101 set_list(elt); |
102 } | 102 } |
103 return elt; | 103 return elt; |
125 // This has the SIDE EFFECT of creating a KlassInfoEntry | 125 // This has the SIDE EFFECT of creating a KlassInfoEntry |
126 // for <k>, if one doesn't exist yet. | 126 // for <k>, if one doesn't exist yet. |
127 _table->lookup(k); | 127 _table->lookup(k); |
128 } | 128 } |
129 | 129 |
130 KlassInfoTable::KlassInfoTable(int size, HeapWord* ref, | 130 KlassInfoTable::KlassInfoTable(bool need_class_stats) { |
131 bool need_class_stats) { | 131 _size_of_instances_in_words = 0; |
132 _size = 0; | 132 _size = 0; |
133 _ref = ref; | 133 _ref = (HeapWord*) Universe::boolArrayKlassObj(); |
134 _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); | 134 _buckets = |
135 (KlassInfoBucket*) AllocateHeap(sizeof(KlassInfoBucket) * _num_buckets, | |
136 mtInternal, 0, AllocFailStrategy::RETURN_NULL); | |
135 if (_buckets != NULL) { | 137 if (_buckets != NULL) { |
136 _size = size; | 138 _size = _num_buckets; |
137 for (int index = 0; index < _size; index++) { | 139 for (int index = 0; index < _size; index++) { |
138 _buckets[index].initialize(); | 140 _buckets[index].initialize(); |
139 } | 141 } |
140 if (need_class_stats) { | 142 if (need_class_stats) { |
141 AllClassesFinder finder(this); | 143 AllClassesFinder finder(this); |
177 // elt may be NULL if it's a new klass for which we | 179 // elt may be NULL if it's a new klass for which we |
178 // could not allocate space for a new entry in the hashtable. | 180 // could not allocate space for a new entry in the hashtable. |
179 if (elt != NULL) { | 181 if (elt != NULL) { |
180 elt->set_count(elt->count() + 1); | 182 elt->set_count(elt->count() + 1); |
181 elt->set_words(elt->words() + obj->size()); | 183 elt->set_words(elt->words() + obj->size()); |
184 _size_of_instances_in_words += obj->size(); | |
182 return true; | 185 return true; |
183 } else { | 186 } else { |
184 return false; | 187 return false; |
185 } | 188 } |
186 } | 189 } |
190 for (int index = 0; index < _size; index++) { | 193 for (int index = 0; index < _size; index++) { |
191 _buckets[index].iterate(cic); | 194 _buckets[index].iterate(cic); |
192 } | 195 } |
193 } | 196 } |
194 | 197 |
198 size_t KlassInfoTable::size_of_instances_in_words() const { | |
199 return _size_of_instances_in_words; | |
200 } | |
201 | |
195 int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { | 202 int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { |
196 return (*e1)->compare(*e1,*e2); | 203 return (*e1)->compare(*e1,*e2); |
197 } | 204 } |
198 | 205 |
199 KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) : | 206 KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title) : |
200 _cit(cit), | 207 _cit(cit), |
201 _title(title) { | 208 _title(title) { |
202 _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(estimatedCount,true); | 209 _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(_histo_initial_size, true); |
203 } | 210 } |
204 | 211 |
205 KlassInfoHisto::~KlassInfoHisto() { | 212 KlassInfoHisto::~KlassInfoHisto() { |
206 delete _elements; | 213 delete _elements; |
207 } | 214 } |
442 | 449 |
443 class RecordInstanceClosure : public ObjectClosure { | 450 class RecordInstanceClosure : public ObjectClosure { |
444 private: | 451 private: |
445 KlassInfoTable* _cit; | 452 KlassInfoTable* _cit; |
446 size_t _missed_count; | 453 size_t _missed_count; |
454 BoolObjectClosure* _filter; | |
447 public: | 455 public: |
448 RecordInstanceClosure(KlassInfoTable* cit) : | 456 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) : |
449 _cit(cit), _missed_count(0) {} | 457 _cit(cit), _missed_count(0), _filter(filter) {} |
450 | 458 |
451 void do_object(oop obj) { | 459 void do_object(oop obj) { |
452 if (!_cit->record_instance(obj)) { | 460 if (should_visit(obj)) { |
453 _missed_count++; | 461 if (!_cit->record_instance(obj)) { |
462 _missed_count++; | |
463 } | |
454 } | 464 } |
455 } | 465 } |
456 | 466 |
457 size_t missed_count() { return _missed_count; } | 467 size_t missed_count() { return _missed_count; } |
468 | |
469 private: | |
470 bool should_visit(oop obj) { | |
471 return _filter == NULL || _filter->do_object_b(obj); | |
472 } | |
458 }; | 473 }; |
459 | 474 |
460 void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { | 475 size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *filter) { |
461 ResourceMark rm; | 476 ResourceMark rm; |
462 // Get some random number for ref (the hash key) | 477 |
463 HeapWord* ref = (HeapWord*) Universe::boolArrayKlassObj(); | 478 RecordInstanceClosure ric(cit, filter); |
464 CollectedHeap* heap = Universe::heap(); | 479 Universe::heap()->object_iterate(&ric); |
465 bool is_shared_heap = false; | 480 return ric.missed_count(); |
481 } | |
482 | |
483 void HeapInspection::heap_inspection(outputStream* st) { | |
484 ResourceMark rm; | |
466 | 485 |
467 if (_print_help) { | 486 if (_print_help) { |
468 for (int c=0; c<KlassSizeStats::_num_columns; c++) { | 487 for (int c=0; c<KlassSizeStats::_num_columns; c++) { |
469 st->print("%s:\n\t", name_table[c]); | 488 st->print("%s:\n\t", name_table[c]); |
470 const int max_col = 60; | 489 const int max_col = 60; |
480 st->print_cr(".\n"); | 499 st->print_cr(".\n"); |
481 } | 500 } |
482 return; | 501 return; |
483 } | 502 } |
484 | 503 |
485 // Collect klass instance info | 504 KlassInfoTable cit(_print_class_stats); |
486 KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats); | |
487 if (!cit.allocation_failed()) { | 505 if (!cit.allocation_failed()) { |
488 // Iterate over objects in the heap | 506 size_t missed_count = populate_table(&cit); |
489 RecordInstanceClosure ric(&cit); | |
490 Universe::heap()->object_iterate(&ric); | |
491 | |
492 // Report if certain classes are not counted because of | |
493 // running out of C-heap for the histogram. | |
494 size_t missed_count = ric.missed_count(); | |
495 if (missed_count != 0) { | 507 if (missed_count != 0) { |
496 st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT | 508 st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT |
497 " total instances in data below", | 509 " total instances in data below", |
498 missed_count); | 510 missed_count); |
499 } | 511 } |
512 | |
500 // Sort and print klass instance info | 513 // Sort and print klass instance info |
501 const char *title = "\n" | 514 const char *title = "\n" |
502 " num #instances #bytes class name\n" | 515 " num #instances #bytes class name\n" |
503 "----------------------------------------------"; | 516 "----------------------------------------------"; |
504 KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size); | 517 KlassInfoHisto histo(&cit, title); |
505 HistoClosure hc(&histo); | 518 HistoClosure hc(&histo); |
519 | |
506 cit.iterate(&hc); | 520 cit.iterate(&hc); |
521 | |
507 histo.sort(); | 522 histo.sort(); |
508 histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); | 523 histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); |
509 } else { | 524 } else { |
510 st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); | 525 st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); |
511 } | 526 } |
512 st->flush(); | 527 st->flush(); |
513 | |
514 if (need_prologue && is_shared_heap) { | |
515 SharedHeap* sh = (SharedHeap*)heap; | |
516 sh->gc_epilogue(false /* !full */); // release all acquired locks, etc. | |
517 } | |
518 } | 528 } |
519 | 529 |
520 class FindInstanceClosure : public ObjectClosure { | 530 class FindInstanceClosure : public ObjectClosure { |
521 private: | 531 private: |
522 Klass* _klass; | 532 Klass* _klass; |