Mercurial > hg > graal-jvmci-8
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(®_cl, true); | 6985 nm->oops_do(®_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 { |