523 public: 524 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) : 525 _cit(cit), _missed_count(0), _filter(filter) {} 526 527 void do_object(oop obj) { 528 if (should_visit(obj)) { 529 if (!_cit->record_instance(obj)) { 530 _missed_count++; 531 } 532 } 533 } 534 535 size_t missed_count() { return _missed_count; } 536 537 private: 538 bool should_visit(oop obj) { 539 return _filter == NULL || _filter->do_object_b(obj); 540 } 541 }; 542 543 void ParHeapInspectTask::work(uint worker_id) { 544 size_t missed_count = 0; 545 if (!_success) { 546 // other worker has failed on parallel iteration. 547 return; 548 } 549 550 KlassInfoTable cit(false); 551 if (!cit.allocation_failed()) { 552 RecordInstanceClosure ric(&cit, _filter); 553 _poi->object_iterate(&ric, worker_id); 554 missed_count = ric.missed_count(); 555 } else { 556 // fail to allocate memory, stop parallel mode. 557 _success = false; 558 return; 559 } 560 { 561 MutexLocker x(&_mutex); 562 563 if (!_shared_cit->merge(&cit)) { 564 _success = false; 565 return; 566 } 567 _shared_missed_count += missed_count; 568 } 569 } 570 571 size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *filter, size_t parallel_thread_num) { 572 ResourceMark rm; 573 574 // Try parallel first. 575 if (parallel_thread_num > 1) { 576 ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(parallel_thread_num); 577 if (poi != NULL) { 578 ParHeapInspectTask task(poi, cit, filter); 579 Universe::heap()->run_task(&task); 580 return task.missed_count(); 581 } 582 } 583 584 // If no parallel iteration available, run serially. 585 RecordInstanceClosure ric(cit, filter); 586 Universe::heap()->object_iterate(&ric); 587 return ric.missed_count(); 588 } 589 590 void HeapInspection::heap_inspection(outputStream* st, size_t parallel_thread_num) { 591 ResourceMark rm; 592 593 KlassInfoTable cit(false); 594 if (!cit.allocation_failed()) { 595 size_t missed_count = 0;; 596 // populate table with object allocation info 597 missed_count = populate_table(&cit, NULL, parallel_thread_num); 598 if (missed_count != 0) { 599 log_info(gc, classhisto)("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT 600 " total instances in data below", | 523 public: 524 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) : 525 _cit(cit), _missed_count(0), _filter(filter) {} 526 527 void do_object(oop obj) { 528 if (should_visit(obj)) { 529 if (!_cit->record_instance(obj)) { 530 _missed_count++; 531 } 532 } 533 } 534 535 size_t missed_count() { return _missed_count; } 536 537 private: 538 bool should_visit(oop obj) { 539 return _filter == NULL || _filter->do_object_b(obj); 540 } 541 }; 542 543 // Heap inspection for every worker. 544 // When native OOM hanppens for KlassInfoTable, set _success to false. 545 // TODO(?) it seems atomically set/get _success is unnecessary becasue it 546 // is set to true at constructor and can only be set to false here. 547 // the only risk seems a worker may continue inspect heap when another 548 // worker set _success to false, but this is OK because the current worker 549 // doesn't change _success if everything is OK for it's inpection work, and 550 // the _success will be false finally and serial heap inpection can be tried. 551 void ParHeapInspectTask::work(uint worker_id) { 552 size_t missed_count = 0; 553 if (!_success) { 554 // other worker has failed on parallel iteration. 555 return; 556 } 557 558 KlassInfoTable cit(false); 559 if (!cit.allocation_failed()) { 560 RecordInstanceClosure ric(&cit, _filter); 561 _poi->object_iterate(&ric, worker_id); 562 missed_count = ric.missed_count(); 563 } else { 564 // fail to allocate memory, stop parallel mode. 565 _success = false; 566 return; 567 } 568 { 569 MutexLocker x(&_mutex); 570 571 if (!_shared_cit->merge(&cit)) { 572 _success = false; 573 return; 574 } 575 _shared_missed_count += missed_count; 576 } 577 } 578 579 size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *filter, size_t parallel_thread_num) { 580 ResourceMark rm; 581 582 // Try parallel first. 583 if (parallel_thread_num > 1) { 584 ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(parallel_thread_num); 585 if (poi != NULL) { 586 ParHeapInspectTask task(poi, cit, filter); 587 Universe::heap()->run_task(&task); 588 delete poi; 589 if (task.success()) { 590 return task.missed_count(); 591 } 592 } 593 } 594 595 // If no parallel iteration available, run serially. 596 RecordInstanceClosure ric(cit, filter); 597 Universe::heap()->object_iterate(&ric); 598 return ric.missed_count(); 599 } 600 601 void HeapInspection::heap_inspection(outputStream* st, size_t parallel_thread_num) { 602 ResourceMark rm; 603 604 KlassInfoTable cit(false); 605 if (!cit.allocation_failed()) { 606 size_t missed_count = 0;; 607 // populate table with object allocation info 608 missed_count = populate_table(&cit, NULL, parallel_thread_num); 609 if (missed_count != 0) { 610 log_info(gc, classhisto)("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT 611 " total instances in data below", |