comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 20494:7baf47cb97cb

8048268: G1 Code Root Migration performs poorly Summary: Replace G1CodeRootSet with a Hashtable based implementation, merge Code Root Migration phase into Code Root Scanning Reviewed-by: jmasa, brutisso, tschatzl
author mgerdin
date Fri, 29 Aug 2014 13:12:21 +0200
parents c02ec279b062
children fa56205f142c
comparison
equal deleted inserted replaced
20493:152cf4afc11f 20494:7baf47cb97cb
4578 } 4578 }
4579 _count++; 4579 _count++;
4580 } 4580 }
4581 }; 4581 };
4582 4582
4583 class G1CodeBlobClosure : public CodeBlobClosure {
4584 class HeapRegionGatheringOopClosure : public OopClosure {
4585 G1CollectedHeap* _g1h;
4586 OopClosure* _work;
4587 nmethod* _nm;
4588
4589 template <typename T>
4590 void do_oop_work(T* p) {
4591 _work->do_oop(p);
4592 T oop_or_narrowoop = oopDesc::load_heap_oop(p);
4593 if (!oopDesc::is_null(oop_or_narrowoop)) {
4594 oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop);
4595 HeapRegion* hr = _g1h->heap_region_containing_raw(o);
4596 assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in CS then evacuation failed and nm must already be in the remset");
4597 hr->add_strong_code_root(_nm);
4598 }
4599 }
4600
4601 public:
4602 HeapRegionGatheringOopClosure(OopClosure* oc) : _g1h(G1CollectedHeap::heap()), _work(oc), _nm(NULL) {}
4603
4604 void do_oop(oop* o) {
4605 do_oop_work(o);
4606 }
4607
4608 void do_oop(narrowOop* o) {
4609 do_oop_work(o);
4610 }
4611
4612 void set_nm(nmethod* nm) {
4613 _nm = nm;
4614 }
4615 };
4616
4617 HeapRegionGatheringOopClosure _oc;
4618 public:
4619 G1CodeBlobClosure(OopClosure* oc) : _oc(oc) {}
4620
4621 void do_code_blob(CodeBlob* cb) {
4622 nmethod* nm = cb->as_nmethod_or_null();
4623 if (nm != NULL) {
4624 if (!nm->test_set_oops_do_mark()) {
4625 _oc.set_nm(nm);
4626 nm->oops_do(&_oc);
4627 nm->fix_oop_relocations();
4628 }
4629 }
4630 }
4631 };
4632
4583 class G1ParTask : public AbstractGangTask { 4633 class G1ParTask : public AbstractGangTask {
4584 protected: 4634 protected:
4585 G1CollectedHeap* _g1h; 4635 G1CollectedHeap* _g1h;
4586 RefToScanQueueSet *_queues; 4636 RefToScanQueueSet *_queues;
4587 ParallelTaskTerminator _terminator; 4637 ParallelTaskTerminator _terminator;
4643 4693
4644 } 4694 }
4645 4695
4646 void do_cld(ClassLoaderData* cld) { 4696 void do_cld(ClassLoaderData* cld) {
4647 cld->oops_do(_oop_closure, &_klass_in_cld_closure, _claim); 4697 cld->oops_do(_oop_closure, &_klass_in_cld_closure, _claim);
4648 }
4649 };
4650
4651 class G1CodeBlobClosure: public CodeBlobClosure {
4652 OopClosure* _f;
4653
4654 public:
4655 G1CodeBlobClosure(OopClosure* f) : _f(f) {}
4656 void do_code_blob(CodeBlob* blob) {
4657 nmethod* that = blob->as_nmethod_or_null();
4658 if (that != NULL) {
4659 if (!that->test_set_oops_do_mark()) {
4660 that->oops_do(_f);
4661 that->fix_oop_relocations();
4662 }
4663 }
4664 } 4698 }
4665 }; 4699 };
4666 4700
4667 void work(uint worker_id) { 4701 void work(uint worker_id) {
4668 if (worker_id >= _n_workers) return; // no work needed this round 4702 if (worker_id >= _n_workers) return; // no work needed this round
4852 } 4886 }
4853 } 4887 }
4854 g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms); 4888 g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms);
4855 4889
4856 // Now scan the complement of the collection set. 4890 // Now scan the complement of the collection set.
4857 MarkingCodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots, CodeBlobToOopClosure::FixRelocations); 4891 G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots);
4858 4892
4859 g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i); 4893 g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
4860 4894
4861 _process_strong_tasks->all_tasks_completed(); 4895 _process_strong_tasks->all_tasks_completed();
4862 } 4896 }
5898 // Reset and re-enable the hot card cache. 5932 // Reset and re-enable the hot card cache.
5899 // Note the counts for the cards in the regions in the 5933 // Note the counts for the cards in the regions in the
5900 // collection set are reset when the collection set is freed. 5934 // collection set are reset when the collection set is freed.
5901 hot_card_cache->reset_hot_cache(); 5935 hot_card_cache->reset_hot_cache();
5902 hot_card_cache->set_use_cache(true); 5936 hot_card_cache->set_use_cache(true);
5903
5904 // Migrate the strong code roots attached to each region in
5905 // the collection set. Ideally we would like to do this
5906 // after we have finished the scanning/evacuation of the
5907 // strong code roots for a particular heap region.
5908 migrate_strong_code_roots();
5909 5937
5910 purge_code_root_memory(); 5938 purge_code_root_memory();
5911 5939
5912 if (g1_policy()->during_initial_mark_pause()) { 5940 if (g1_policy()->during_initial_mark_pause()) {
5913 // Reset the claim values set during marking the strong code roots 5941 // Reset the claim values set during marking the strong code roots
6900 assert(!hr->continuesHumongous(), 6928 assert(!hr->continuesHumongous(),
6901 err_msg("trying to add code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT 6929 err_msg("trying to add code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
6902 " starting at "HR_FORMAT, 6930 " starting at "HR_FORMAT,
6903 _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); 6931 _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
6904 6932
6905 // HeapRegion::add_strong_code_root() avoids adding duplicate 6933 // HeapRegion::add_strong_code_root_locked() avoids adding duplicate entries.
6906 // entries but having duplicates is OK since we "mark" nmethods 6934 hr->add_strong_code_root_locked(_nm);
6907 // as visited when we scan the strong code root lists during the GC.
6908 hr->add_strong_code_root(_nm);
6909 assert(hr->rem_set()->strong_code_roots_list_contains(_nm),
6910 err_msg("failed to add code root "PTR_FORMAT" to remembered set of region "HR_FORMAT,
6911 _nm, HR_FORMAT_PARAMS(hr)));
6912 } 6935 }
6913 } 6936 }
6914 6937
6915 public: 6938 public:
6916 RegisterNMethodOopClosure(G1CollectedHeap* g1h, nmethod* nm) : 6939 RegisterNMethodOopClosure(G1CollectedHeap* g1h, nmethod* nm) :
6933 err_msg("trying to remove code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT 6956 err_msg("trying to remove code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
6934 " starting at "HR_FORMAT, 6957 " starting at "HR_FORMAT,
6935 _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); 6958 _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
6936 6959
6937 hr->remove_strong_code_root(_nm); 6960 hr->remove_strong_code_root(_nm);
6938 assert(!hr->rem_set()->strong_code_roots_list_contains(_nm),
6939 err_msg("failed to remove code root "PTR_FORMAT" of region "HR_FORMAT,
6940 _nm, HR_FORMAT_PARAMS(hr)));
6941 } 6961 }
6942 } 6962 }
6943 6963
6944 public: 6964 public:
6945 UnregisterNMethodOopClosure(G1CollectedHeap* g1h, nmethod* nm) : 6965 UnregisterNMethodOopClosure(G1CollectedHeap* g1h, nmethod* nm) :
6963 guarantee(nm != NULL, "sanity"); 6983 guarantee(nm != NULL, "sanity");
6964 UnregisterNMethodOopClosure reg_cl(this, nm); 6984 UnregisterNMethodOopClosure reg_cl(this, nm);
6965 nm->oops_do(&reg_cl, true); 6985 nm->oops_do(&reg_cl, true);
6966 } 6986 }
6967 6987
6968 class MigrateCodeRootsHeapRegionClosure: public HeapRegionClosure {
6969 public:
6970 bool doHeapRegion(HeapRegion *hr) {
6971 assert(!hr->isHumongous(),
6972 err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
6973 HR_FORMAT_PARAMS(hr)));
6974 hr->migrate_strong_code_roots();
6975 return false;
6976 }
6977 };
6978
6979 void G1CollectedHeap::migrate_strong_code_roots() {
6980 MigrateCodeRootsHeapRegionClosure cl;
6981 double migrate_start = os::elapsedTime();
6982 collection_set_iterate(&cl);
6983 double migration_time_ms = (os::elapsedTime() - migrate_start) * 1000.0;
6984 g1_policy()->phase_times()->record_strong_code_root_migration_time(migration_time_ms);
6985 }
6986
6987 void G1CollectedHeap::purge_code_root_memory() { 6988 void G1CollectedHeap::purge_code_root_memory() {
6988 double purge_start = os::elapsedTime(); 6989 double purge_start = os::elapsedTime();
6989 G1CodeRootSet::purge_chunks(G1CodeRootsChunkCacheKeepPercent); 6990 G1CodeRootSet::purge();
6990 double purge_time_ms = (os::elapsedTime() - purge_start) * 1000.0; 6991 double purge_time_ms = (os::elapsedTime() - purge_start) * 1000.0;
6991 g1_policy()->phase_times()->record_strong_code_root_purge_time(purge_time_ms); 6992 g1_policy()->phase_times()->record_strong_code_root_purge_time(purge_time_ms);
6992 } 6993 }
6993 6994
6994 class RebuildStrongCodeRootClosure: public CodeBlobClosure { 6995 class RebuildStrongCodeRootClosure: public CodeBlobClosure {