Mercurial > hg > graal-compiler
comparison src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp @ 794:315a5d70b295
6484957: G1: parallel concurrent refinement
6826318: G1: remove traversal-based refinement code
Summary: Removed traversal-based refinement code as it's no longer used. Made the concurrent refinement (queue-based) parallel.
Reviewed-by: tonyp
author | iveresov |
---|---|
date | Mon, 11 May 2009 16:30:56 -0700 |
parents | 25e146966e7c |
children | 215f81b4d9b3 |
comparison
equal
deleted
inserted
replaced
758:9b3a41ccc927 | 794:315a5d70b295 |
---|---|
23 */ | 23 */ |
24 | 24 |
25 #include "incls/_precompiled.incl" | 25 #include "incls/_precompiled.incl" |
26 #include "incls/_concurrentG1Refine.cpp.incl" | 26 #include "incls/_concurrentG1Refine.cpp.incl" |
27 | 27 |
28 bool ConcurrentG1Refine::_enabled = false; | |
29 | |
30 ConcurrentG1Refine::ConcurrentG1Refine() : | 28 ConcurrentG1Refine::ConcurrentG1Refine() : |
31 _pya(PYA_continue), _last_pya(PYA_continue), | |
32 _last_cards_during(), _first_traversal(false), | |
33 _card_counts(NULL), _cur_card_count_histo(NULL), _cum_card_count_histo(NULL), | 29 _card_counts(NULL), _cur_card_count_histo(NULL), _cum_card_count_histo(NULL), |
34 _hot_cache(NULL), | 30 _hot_cache(NULL), |
35 _def_use_cache(false), _use_cache(false), | 31 _def_use_cache(false), _use_cache(false), |
36 _n_periods(0), _total_cards(0), _total_travs(0) | 32 _n_periods(0), _total_cards(0), _total_travs(0), |
33 _threads(NULL), _n_threads(0) | |
37 { | 34 { |
38 if (G1ConcRefine) { | 35 if (G1ConcRefine) { |
39 _cg1rThread = new ConcurrentG1RefineThread(this); | 36 _n_threads = (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads; |
40 assert(cg1rThread() != NULL, "Conc refine should have been created"); | 37 if (_n_threads > 0) { |
41 assert(cg1rThread()->cg1r() == this, | 38 _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads); |
42 "Conc refine thread should refer to this"); | 39 ConcurrentG1RefineThread *next = NULL; |
43 } else { | 40 for (int i = _n_threads - 1; i >= 0; i--) { |
44 _cg1rThread = NULL; | 41 ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, i); |
42 assert(t != NULL, "Conc refine should have been created"); | |
43 assert(t->cg1r() == this, "Conc refine thread should refer to this"); | |
44 _threads[i] = t; | |
45 next = t; | |
46 } | |
47 } | |
45 } | 48 } |
46 } | 49 } |
47 | 50 |
48 void ConcurrentG1Refine::init() { | 51 void ConcurrentG1Refine::init() { |
49 if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) { | 52 if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) { |
73 _n_hot = 0; | 76 _n_hot = 0; |
74 _hot_cache_idx = 0; | 77 _hot_cache_idx = 0; |
75 } | 78 } |
76 } | 79 } |
77 | 80 |
81 void ConcurrentG1Refine::stop() { | |
82 if (_threads != NULL) { | |
83 for (int i = 0; i < _n_threads; i++) { | |
84 _threads[i]->stop(); | |
85 } | |
86 } | |
87 } | |
88 | |
78 ConcurrentG1Refine::~ConcurrentG1Refine() { | 89 ConcurrentG1Refine::~ConcurrentG1Refine() { |
79 if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) { | 90 if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) { |
80 assert(_card_counts != NULL, "Logic"); | 91 assert(_card_counts != NULL, "Logic"); |
81 FREE_C_HEAP_ARRAY(unsigned char, _card_counts); | 92 FREE_C_HEAP_ARRAY(unsigned char, _card_counts); |
82 assert(_cur_card_count_histo != NULL, "Logic"); | 93 assert(_cur_card_count_histo != NULL, "Logic"); |
86 } | 97 } |
87 if (G1ConcRSLogCacheSize > 0) { | 98 if (G1ConcRSLogCacheSize > 0) { |
88 assert(_hot_cache != NULL, "Logic"); | 99 assert(_hot_cache != NULL, "Logic"); |
89 FREE_C_HEAP_ARRAY(jbyte*, _hot_cache); | 100 FREE_C_HEAP_ARRAY(jbyte*, _hot_cache); |
90 } | 101 } |
91 } | 102 if (_threads != NULL) { |
92 | 103 for (int i = 0; i < _n_threads; i++) { |
93 bool ConcurrentG1Refine::refine() { | 104 delete _threads[i]; |
94 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | 105 } |
95 unsigned cards_before = g1h->g1_rem_set()->conc_refine_cards(); | 106 FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads); |
96 clear_hot_cache(); // Any previous values in this are now invalid. | 107 } |
97 g1h->g1_rem_set()->concurrentRefinementPass(this); | 108 } |
98 _traversals++; | 109 |
99 unsigned cards_after = g1h->g1_rem_set()->conc_refine_cards(); | 110 void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { |
100 unsigned cards_during = cards_after-cards_before; | 111 if (_threads != NULL) { |
101 // If this is the first traversal in the current enabling | 112 for (int i = 0; i < _n_threads; i++) { |
102 // and we did some cards, or if the number of cards found is decreasing | 113 tc->do_thread(_threads[i]); |
103 // sufficiently quickly, then keep going. Otherwise, sleep a while. | 114 } |
104 bool res = | 115 } |
105 (_first_traversal && cards_during > 0) | 116 } |
106 || | 117 |
107 (!_first_traversal && cards_during * 3 < _last_cards_during * 2); | |
108 _last_cards_during = cards_during; | |
109 _first_traversal = false; | |
110 return res; | |
111 } | |
112 | |
113 void ConcurrentG1Refine::enable() { | |
114 MutexLocker x(G1ConcRefine_mon); | |
115 if (!_enabled) { | |
116 _enabled = true; | |
117 _first_traversal = true; _last_cards_during = 0; | |
118 G1ConcRefine_mon->notify_all(); | |
119 } | |
120 } | |
121 | |
122 unsigned ConcurrentG1Refine::disable() { | |
123 MutexLocker x(G1ConcRefine_mon); | |
124 if (_enabled) { | |
125 _enabled = false; | |
126 return _traversals; | |
127 } else { | |
128 return 0; | |
129 } | |
130 } | |
131 | |
132 void ConcurrentG1Refine::wait_for_ConcurrentG1Refine_enabled() { | |
133 G1ConcRefine_mon->lock(); | |
134 while (!_enabled) { | |
135 G1ConcRefine_mon->wait(Mutex::_no_safepoint_check_flag); | |
136 } | |
137 G1ConcRefine_mon->unlock(); | |
138 _traversals = 0; | |
139 }; | |
140 | |
141 void ConcurrentG1Refine::set_pya_restart() { | |
142 // If we're using the log-based RS barrier, the above will cause | |
143 // in-progress traversals of completed log buffers to quit early; we will | |
144 // also abandon all other buffers. | |
145 if (G1RSBarrierUseQueue) { | |
146 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); | |
147 dcqs.abandon_logs(); | |
148 // Reset the post-yield actions. | |
149 _pya = PYA_continue; | |
150 _last_pya = PYA_continue; | |
151 } else { | |
152 _pya = PYA_restart; | |
153 } | |
154 } | |
155 | |
156 void ConcurrentG1Refine::set_pya_cancel() { | |
157 _pya = PYA_cancel; | |
158 } | |
159 | |
160 PostYieldAction ConcurrentG1Refine::get_pya() { | |
161 if (_pya != PYA_continue) { | |
162 jint val = _pya; | |
163 while (true) { | |
164 jint val_read = Atomic::cmpxchg(PYA_continue, &_pya, val); | |
165 if (val_read == val) { | |
166 PostYieldAction res = (PostYieldAction)val; | |
167 assert(res != PYA_continue, "Only the refine thread should reset."); | |
168 _last_pya = res; | |
169 return res; | |
170 } else { | |
171 val = val_read; | |
172 } | |
173 } | |
174 } | |
175 // QQQ WELL WHAT DO WE RETURN HERE??? | |
176 // make up something! | |
177 return PYA_continue; | |
178 } | |
179 | |
180 PostYieldAction ConcurrentG1Refine::get_last_pya() { | |
181 PostYieldAction res = _last_pya; | |
182 _last_pya = PYA_continue; | |
183 return res; | |
184 } | |
185 | |
186 bool ConcurrentG1Refine::do_traversal() { | |
187 return _cg1rThread->do_traversal(); | |
188 } | |
189 | 118 |
190 int ConcurrentG1Refine::add_card_count(jbyte* card_ptr) { | 119 int ConcurrentG1Refine::add_card_count(jbyte* card_ptr) { |
191 size_t card_num = (card_ptr - _ct_bot); | 120 size_t card_num = (card_ptr - _ct_bot); |
192 guarantee(0 <= card_num && card_num < _n_card_counts, "Bounds"); | 121 guarantee(0 <= card_num && card_num < _n_card_counts, "Bounds"); |
193 unsigned char cnt = _card_counts[card_num]; | 122 unsigned char cnt = _card_counts[card_num]; |