Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp @ 1090:fa357420e7d2
6899058: G1: Internal error in ptrQueue.cpp:201 in nightly tests
Summary: Fixes a race on the dirty card queue completed buffer list between worker thread(s) performing a flush of a deferred store barrier (enqueueing a newly completed buffer) and worker thread(s) in the RSet updating code claiming completed buffers. Removed the routine that removes elements from the completed update buffer queue using a CAS.
Reviewed-by: ysr, tonyp
author | johnc |
---|---|
date | Tue, 24 Nov 2009 15:19:30 -0800 |
parents | 035d2e036a9b |
children | 44f61c24ddab |
rev | line source |
---|---|
342 | 1 /* |
844 | 2 * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. |
342 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_concurrentG1Refine.cpp.incl" | |
27 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
28 // Possible sizes for the card counts cache: odd primes that roughly double in size. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
29 // (See jvmtiTagMap.cpp). |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
30 int ConcurrentG1Refine::_cc_cache_sizes[] = { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
31 16381, 32771, 76831, 150001, 307261, |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
32 614563, 1228891, 2457733, 4915219, 9830479, |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
33 19660831, 39321619, 78643219, 157286461, -1 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
34 }; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
35 |
342 | 36 ConcurrentG1Refine::ConcurrentG1Refine() : |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
37 _card_counts(NULL), _card_epochs(NULL), |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
38 _n_card_counts(0), _max_n_card_counts(0), |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
39 _cache_size_index(0), _expand_card_counts(false), |
342 | 40 _hot_cache(NULL), |
41 _def_use_cache(false), _use_cache(false), | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
42 _n_periods(0), |
794 | 43 _threads(NULL), _n_threads(0) |
342 | 44 { |
45 if (G1ConcRefine) { | |
795
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
46 _n_threads = (int)thread_num(); |
794 | 47 if (_n_threads > 0) { |
48 _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads); | |
795
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
49 int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids(); |
794 | 50 ConcurrentG1RefineThread *next = NULL; |
51 for (int i = _n_threads - 1; i >= 0; i--) { | |
795
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
52 ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i); |
794 | 53 assert(t != NULL, "Conc refine should have been created"); |
54 assert(t->cg1r() == this, "Conc refine thread should refer to this"); | |
55 _threads[i] = t; | |
56 next = t; | |
57 } | |
58 } | |
342 | 59 } |
60 } | |
61 | |
795
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
62 size_t ConcurrentG1Refine::thread_num() { |
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
63 if (G1ConcRefine) { |
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
64 return (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads; |
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
65 } |
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
66 return 0; |
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
67 } |
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
68 |
342 | 69 void ConcurrentG1Refine::init() { |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
70 if (G1ConcRSLogCacheSize > 0) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
71 _g1h = G1CollectedHeap::heap(); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
72 _max_n_card_counts = |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
73 (unsigned) (_g1h->g1_reserved_obj_bytes() >> CardTableModRefBS::card_shift); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
74 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
75 size_t max_card_num = ((size_t)1 << (sizeof(unsigned)*BitsPerByte-1)) - 1; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
76 guarantee(_max_n_card_counts < max_card_num, "card_num representation"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
77 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
78 int desired = _max_n_card_counts / InitialCacheFraction; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
79 for (_cache_size_index = 0; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
80 _cc_cache_sizes[_cache_size_index] >= 0; _cache_size_index++) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
81 if (_cc_cache_sizes[_cache_size_index] >= desired) break; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
82 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
83 _cache_size_index = MAX2(0, (_cache_size_index - 1)); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
84 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
85 int initial_size = _cc_cache_sizes[_cache_size_index]; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
86 if (initial_size < 0) initial_size = _max_n_card_counts; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
87 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
88 // Make sure we don't go bigger than we will ever need |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
89 _n_card_counts = MIN2((unsigned) initial_size, _max_n_card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
90 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
91 _card_counts = NEW_C_HEAP_ARRAY(CardCountCacheEntry, _n_card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
92 _card_epochs = NEW_C_HEAP_ARRAY(CardEpochCacheEntry, _n_card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
93 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
94 Copy::fill_to_bytes(&_card_counts[0], |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
95 _n_card_counts * sizeof(CardCountCacheEntry)); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
96 Copy::fill_to_bytes(&_card_epochs[0], _n_card_counts * sizeof(CardEpochCacheEntry)); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
97 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
98 ModRefBarrierSet* bs = _g1h->mr_bs(); |
342 | 99 guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition"); |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
100 _ct_bs = (CardTableModRefBS*)bs; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
101 _ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start()); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
102 |
342 | 103 _def_use_cache = true; |
104 _use_cache = true; | |
105 _hot_cache_size = (1 << G1ConcRSLogCacheSize); | |
106 _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size); | |
107 _n_hot = 0; | |
108 _hot_cache_idx = 0; | |
889 | 109 |
110 // For refining the cards in the hot cache in parallel | |
111 int n_workers = (ParallelGCThreads > 0 ? | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
112 _g1h->workers()->total_workers() : 1); |
889 | 113 _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / n_workers); |
114 _hot_cache_par_claimed_idx = 0; | |
342 | 115 } |
116 } | |
117 | |
794 | 118 void ConcurrentG1Refine::stop() { |
119 if (_threads != NULL) { | |
120 for (int i = 0; i < _n_threads; i++) { | |
121 _threads[i]->stop(); | |
122 } | |
123 } | |
124 } | |
125 | |
342 | 126 ConcurrentG1Refine::~ConcurrentG1Refine() { |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
127 if (G1ConcRSLogCacheSize > 0) { |
342 | 128 assert(_card_counts != NULL, "Logic"); |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
129 FREE_C_HEAP_ARRAY(CardCountCacheEntry, _card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
130 assert(_card_epochs != NULL, "Logic"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
131 FREE_C_HEAP_ARRAY(CardEpochCacheEntry, _card_epochs); |
342 | 132 assert(_hot_cache != NULL, "Logic"); |
133 FREE_C_HEAP_ARRAY(jbyte*, _hot_cache); | |
134 } | |
794 | 135 if (_threads != NULL) { |
136 for (int i = 0; i < _n_threads; i++) { | |
137 delete _threads[i]; | |
138 } | |
799
f89cf529c3c7
6849122: G1: Typo introduced during implementation of the parallel refinement
iveresov
parents:
795
diff
changeset
|
139 FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads); |
342 | 140 } |
141 } | |
142 | |
794 | 143 void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { |
144 if (_threads != NULL) { | |
145 for (int i = 0; i < _n_threads; i++) { | |
146 tc->do_thread(_threads[i]); | |
147 } | |
342 | 148 } |
149 } | |
150 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
151 bool ConcurrentG1Refine::is_young_card(jbyte* card_ptr) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
152 HeapWord* start = _ct_bs->addr_for(card_ptr); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
153 HeapRegion* r = _g1h->heap_region_containing(start); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
154 if (r != NULL && r->is_young()) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
155 return true; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
156 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
157 // This card is not associated with a heap region |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
158 // so can't be young. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
159 return false; |
342 | 160 } |
161 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
162 jbyte* ConcurrentG1Refine::add_card_count(jbyte* card_ptr, int* count, bool* defer) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
163 unsigned new_card_num = ptr_2_card_num(card_ptr); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
164 unsigned bucket = hash(new_card_num); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
165 assert(0 <= bucket && bucket < _n_card_counts, "Bounds"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
166 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
167 CardCountCacheEntry* count_ptr = &_card_counts[bucket]; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
168 CardEpochCacheEntry* epoch_ptr = &_card_epochs[bucket]; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
169 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
170 // We have to construct a new entry if we haven't updated the counts |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
171 // during the current period, or if the count was updated for a |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
172 // different card number. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
173 unsigned int new_epoch = (unsigned int) _n_periods; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
174 julong new_epoch_entry = make_epoch_entry(new_card_num, new_epoch); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
175 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
176 while (true) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
177 // Fetch the previous epoch value |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
178 julong prev_epoch_entry = epoch_ptr->_value; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
179 julong cas_res; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
180 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
181 if (extract_epoch(prev_epoch_entry) != new_epoch) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
182 // This entry has not yet been updated during this period. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
183 // Note: we update the epoch value atomically to ensure |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
184 // that there is only one winner that updates the cached |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
185 // card_ptr value even though all the refine threads share |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
186 // the same epoch value. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
187 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
188 cas_res = (julong) Atomic::cmpxchg((jlong) new_epoch_entry, |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
189 (volatile jlong*)&epoch_ptr->_value, |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
190 (jlong) prev_epoch_entry); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
191 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
192 if (cas_res == prev_epoch_entry) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
193 // We have successfully won the race to update the |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
194 // epoch and card_num value. Make it look like the |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
195 // count and eviction count were previously cleared. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
196 count_ptr->_count = 1; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
197 count_ptr->_evict_count = 0; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
198 *count = 0; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
199 // We can defer the processing of card_ptr |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
200 *defer = true; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
201 return card_ptr; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
202 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
203 // We did not win the race to update the epoch field, so some other |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
204 // thread must have done it. The value that gets returned by CAS |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
205 // should be the new epoch value. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
206 assert(extract_epoch(cas_res) == new_epoch, "unexpected epoch"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
207 // We could 'continue' here or just re-read the previous epoch value |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
208 prev_epoch_entry = epoch_ptr->_value; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
209 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
210 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
211 // The epoch entry for card_ptr has been updated during this period. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
212 unsigned old_card_num = extract_card_num(prev_epoch_entry); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
213 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
214 // The card count that will be returned to caller |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
215 *count = count_ptr->_count; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
216 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
217 // Are we updating the count for the same card? |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
218 if (new_card_num == old_card_num) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
219 // Same card - just update the count. We could have more than one |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
220 // thread racing to update count for the current card. It should be |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
221 // OK not to use a CAS as the only penalty should be some missed |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
222 // increments of the count which delays identifying the card as "hot". |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
223 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
224 if (*count < max_jubyte) count_ptr->_count++; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
225 // We can defer the processing of card_ptr |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
226 *defer = true; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
227 return card_ptr; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
228 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
229 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
230 // Different card - evict old card info |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
231 if (count_ptr->_evict_count < max_jubyte) count_ptr->_evict_count++; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
232 if (count_ptr->_evict_count > G1CardCountCacheExpandThreshold) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
233 // Trigger a resize the next time we clear |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
234 _expand_card_counts = true; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
235 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
236 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
237 cas_res = (julong) Atomic::cmpxchg((jlong) new_epoch_entry, |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
238 (volatile jlong*)&epoch_ptr->_value, |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
239 (jlong) prev_epoch_entry); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
240 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
241 if (cas_res == prev_epoch_entry) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
242 // We successfully updated the card num value in the epoch entry |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
243 count_ptr->_count = 0; // initialize counter for new card num |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
244 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
245 // Even though the region containg the card at old_card_num was not |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
246 // in the young list when old_card_num was recorded in the epoch |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
247 // cache it could have been added to the free list and subsequently |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
248 // added to the young list in the intervening time. If the evicted |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
249 // card is in a young region just return the card_ptr and the evicted |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
250 // card will not be cleaned. See CR 6817995. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
251 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
252 jbyte* old_card_ptr = card_num_2_ptr(old_card_num); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
253 if (is_young_card(old_card_ptr)) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
254 *count = 0; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
255 // We can defer the processing of card_ptr |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
256 *defer = true; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
257 return card_ptr; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
258 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
259 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
260 // We do not want to defer processing of card_ptr in this case |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
261 // (we need to refine old_card_ptr and card_ptr) |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
262 *defer = false; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
263 return old_card_ptr; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
264 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
265 // Someone else beat us - try again. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
266 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
267 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
268 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
269 jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
270 int count; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
271 jbyte* cached_ptr = add_card_count(card_ptr, &count, defer); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
272 assert(cached_ptr != NULL, "bad cached card ptr"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
273 assert(!is_young_card(cached_ptr), "shouldn't get a card in young region"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
274 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
275 // The card pointer we obtained from card count cache is not hot |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
276 // so do not store it in the cache; return it for immediate |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
277 // refining. |
342 | 278 if (count < G1ConcRSHotCardLimit) { |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
279 return cached_ptr; |
342 | 280 } |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
281 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
282 // Otherwise, the pointer we got from the _card_counts is hot. |
342 | 283 jbyte* res = NULL; |
284 MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag); | |
285 if (_n_hot == _hot_cache_size) { | |
286 res = _hot_cache[_hot_cache_idx]; | |
287 _n_hot--; | |
288 } | |
289 // Now _n_hot < _hot_cache_size, and we can insert at _hot_cache_idx. | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
290 _hot_cache[_hot_cache_idx] = cached_ptr; |
342 | 291 _hot_cache_idx++; |
292 if (_hot_cache_idx == _hot_cache_size) _hot_cache_idx = 0; | |
293 _n_hot++; | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
294 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
295 if (res != NULL) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
296 // Even though the region containg res was not in the young list |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
297 // when it was recorded in the hot cache it could have been added |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
298 // to the free list and subsequently added to the young list in |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
299 // the intervening time. If res is in a young region, return NULL |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
300 // so that res is not cleaned. See CR 6817995. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
301 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
302 if (is_young_card(res)) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
303 res = NULL; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
304 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
305 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
306 |
342 | 307 return res; |
308 } | |
309 | |
310 void ConcurrentG1Refine::clean_up_cache(int worker_i, G1RemSet* g1rs) { | |
311 assert(!use_cache(), "cache should be disabled"); | |
889 | 312 int start_idx; |
313 | |
314 while ((start_idx = _hot_cache_par_claimed_idx) < _n_hot) { // read once | |
315 int end_idx = start_idx + _hot_cache_par_chunk_size; | |
316 | |
317 if (start_idx == | |
318 Atomic::cmpxchg(end_idx, &_hot_cache_par_claimed_idx, start_idx)) { | |
319 // The current worker has successfully claimed the chunk [start_idx..end_idx) | |
320 end_idx = MIN2(end_idx, _n_hot); | |
321 for (int i = start_idx; i < end_idx; i++) { | |
322 jbyte* entry = _hot_cache[i]; | |
323 if (entry != NULL) { | |
324 g1rs->concurrentRefineOneCard(entry, worker_i); | |
325 } | |
326 } | |
342 | 327 } |
328 } | |
329 } | |
330 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
331 void ConcurrentG1Refine::expand_card_count_cache() { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
332 if (_n_card_counts < _max_n_card_counts) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
333 int new_idx = _cache_size_index+1; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
334 int new_size = _cc_cache_sizes[new_idx]; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
335 if (new_size < 0) new_size = _max_n_card_counts; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
336 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
337 // Make sure we don't go bigger than we will ever need |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
338 new_size = MIN2((unsigned) new_size, _max_n_card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
339 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
340 // Expand the card count and card epoch tables |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
341 if (new_size > (int)_n_card_counts) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
342 // We can just free and allocate a new array as we're |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
343 // not interested in preserving the contents |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
344 assert(_card_counts != NULL, "Logic!"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
345 assert(_card_epochs != NULL, "Logic!"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
346 FREE_C_HEAP_ARRAY(CardCountCacheEntry, _card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
347 FREE_C_HEAP_ARRAY(CardEpochCacheEntry, _card_epochs); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
348 _n_card_counts = new_size; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
349 _card_counts = NEW_C_HEAP_ARRAY(CardCountCacheEntry, _n_card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
350 _card_epochs = NEW_C_HEAP_ARRAY(CardEpochCacheEntry, _n_card_counts); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
351 _cache_size_index = new_idx; |
342 | 352 } |
353 } | |
354 } | |
355 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
356 void ConcurrentG1Refine::clear_and_record_card_counts() { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
357 if (G1ConcRSLogCacheSize == 0) return; |
342 | 358 |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
359 #ifndef PRODUCT |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
360 double start = os::elapsedTime(); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
361 #endif |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
362 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
363 if (_expand_card_counts) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
364 expand_card_count_cache(); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
365 _expand_card_counts = false; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
366 // Only need to clear the epochs. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
367 Copy::fill_to_bytes(&_card_epochs[0], _n_card_counts * sizeof(CardEpochCacheEntry)); |
342 | 368 } |
369 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
370 int this_epoch = (int) _n_periods; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
371 assert((this_epoch+1) <= max_jint, "to many periods"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
372 // Update epoch |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
373 _n_periods++; |
342 | 374 |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
375 #ifndef PRODUCT |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
376 double elapsed = os::elapsedTime() - start; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
377 _g1h->g1_policy()->record_cc_clear_time(elapsed * 1000.0); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
889
diff
changeset
|
378 #endif |
342 | 379 } |
1019 | 380 |
381 void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { | |
382 for (int i = 0; i < _n_threads; ++i) { | |
383 _threads[i]->print_on(st); | |
384 st->cr(); | |
385 } | |
386 } | |
387 |