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]; |