21 * questions. |
21 * questions. |
22 * |
22 * |
23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
|
26 #include "gc_implementation/g1/heapRegionRemSet.hpp" |
26 #include "gc_implementation/g1/heapRegionSet.inline.hpp" |
27 #include "gc_implementation/g1/heapRegionSet.inline.hpp" |
27 |
28 |
28 uint HeapRegionSetBase::_unrealistically_long_length = 0; |
29 uint FreeRegionList::_unrealistically_long_length = 0; |
29 HRSPhase HeapRegionSetBase::_phase = HRSPhaseNone; |
|
30 |
|
31 //////////////////// HeapRegionSetBase //////////////////// |
|
32 |
|
33 void HeapRegionSetBase::set_unrealistically_long_length(uint len) { |
|
34 guarantee(_unrealistically_long_length == 0, "should only be set once"); |
|
35 _unrealistically_long_length = len; |
|
36 } |
|
37 |
30 |
38 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { |
31 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { |
39 msg->append("[%s] %s ln: %u rn: %u cy: "SIZE_FORMAT" ud: "SIZE_FORMAT, |
32 msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT, |
40 name(), message, length(), region_num(), |
33 name(), message, length(), total_capacity_bytes()); |
41 total_capacity_bytes(), total_used_bytes()); |
|
42 fill_in_ext_msg_extra(msg); |
34 fill_in_ext_msg_extra(msg); |
43 } |
35 } |
44 |
36 |
45 bool HeapRegionSetBase::verify_region(HeapRegion* hr, |
37 #ifndef PRODUCT |
46 HeapRegionSetBase* expected_containing_set) { |
38 void HeapRegionSetBase::verify_region(HeapRegion* hr) { |
47 const char* error_message = NULL; |
39 assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrs_index())); |
48 |
40 assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrs_index())); // currently we don't use these sets for young regions |
49 if (!regions_humongous()) { |
41 assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrs_index(), name())); |
50 if (hr->isHumongous()) { |
42 assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrs_index(), name())); |
51 error_message = "the region should not be humongous"; |
43 assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrs_index())); |
52 } |
44 } |
53 } else { |
45 #endif |
54 if (!hr->isHumongous() || !hr->startsHumongous()) { |
|
55 error_message = "the region should be 'starts humongous'"; |
|
56 } |
|
57 } |
|
58 |
|
59 if (!regions_empty()) { |
|
60 if (hr->is_empty()) { |
|
61 error_message = "the region should not be empty"; |
|
62 } |
|
63 } else { |
|
64 if (!hr->is_empty()) { |
|
65 error_message = "the region should be empty"; |
|
66 } |
|
67 } |
|
68 |
|
69 #ifdef ASSERT |
|
70 // The _containing_set field is only available when ASSERT is defined. |
|
71 if (hr->containing_set() != expected_containing_set) { |
|
72 error_message = "inconsistent containing set found"; |
|
73 } |
|
74 #endif // ASSERT |
|
75 |
|
76 const char* extra_error_message = verify_region_extra(hr); |
|
77 if (extra_error_message != NULL) { |
|
78 error_message = extra_error_message; |
|
79 } |
|
80 |
|
81 if (error_message != NULL) { |
|
82 outputStream* out = tty; |
|
83 out->cr(); |
|
84 out->print_cr("## [%s] %s", name(), error_message); |
|
85 out->print_cr("## Offending Region: "PTR_FORMAT, hr); |
|
86 out->print_cr(" "HR_FORMAT, HR_FORMAT_PARAMS(hr)); |
|
87 #ifdef ASSERT |
|
88 out->print_cr(" containing set: "PTR_FORMAT, hr->containing_set()); |
|
89 #endif // ASSERT |
|
90 out->print_cr("## Offending Region Set: "PTR_FORMAT, this); |
|
91 print_on(out); |
|
92 return false; |
|
93 } else { |
|
94 return true; |
|
95 } |
|
96 } |
|
97 |
46 |
98 void HeapRegionSetBase::verify() { |
47 void HeapRegionSetBase::verify() { |
99 // It's important that we also observe the MT safety protocol even |
48 // It's important that we also observe the MT safety protocol even |
100 // for the verification calls. If we do verification without the |
49 // for the verification calls. If we do verification without the |
101 // appropriate locks and the set changes underneath our feet |
50 // appropriate locks and the set changes underneath our feet |
102 // verification might fail and send us on a wild goose chase. |
51 // verification might fail and send us on a wild goose chase. |
103 hrs_assert_mt_safety_ok(this); |
52 check_mt_safety(); |
104 |
53 |
105 guarantee(( is_empty() && length() == 0 && region_num() == 0 && |
54 guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) || |
106 total_used_bytes() == 0 && total_capacity_bytes() == 0) || |
55 (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0), |
107 (!is_empty() && length() >= 0 && region_num() >= 0 && |
|
108 total_used_bytes() >= 0 && total_capacity_bytes() >= 0), |
|
109 hrs_ext_msg(this, "invariant")); |
|
110 |
|
111 guarantee((!regions_humongous() && region_num() == length()) || |
|
112 ( regions_humongous() && region_num() >= length()), |
|
113 hrs_ext_msg(this, "invariant")); |
|
114 |
|
115 guarantee(!regions_empty() || total_used_bytes() == 0, |
|
116 hrs_ext_msg(this, "invariant")); |
|
117 |
|
118 guarantee(total_used_bytes() <= total_capacity_bytes(), |
|
119 hrs_ext_msg(this, "invariant")); |
56 hrs_ext_msg(this, "invariant")); |
120 } |
57 } |
121 |
58 |
122 void HeapRegionSetBase::verify_start() { |
59 void HeapRegionSetBase::verify_start() { |
123 // See comment in verify() about MT safety and verification. |
60 // See comment in verify() about MT safety and verification. |
124 hrs_assert_mt_safety_ok(this); |
61 check_mt_safety(); |
125 assert(!_verify_in_progress, |
62 assert(!_verify_in_progress, |
126 hrs_ext_msg(this, "verification should not be in progress")); |
63 hrs_ext_msg(this, "verification should not be in progress")); |
127 |
64 |
128 // Do the basic verification first before we do the checks over the regions. |
65 // Do the basic verification first before we do the checks over the regions. |
129 HeapRegionSetBase::verify(); |
66 HeapRegionSetBase::verify(); |
130 |
67 |
131 _calc_length = 0; |
|
132 _calc_region_num = 0; |
|
133 _calc_total_capacity_bytes = 0; |
|
134 _calc_total_used_bytes = 0; |
|
135 _verify_in_progress = true; |
68 _verify_in_progress = true; |
136 } |
69 } |
137 |
70 |
138 void HeapRegionSetBase::verify_next_region(HeapRegion* hr) { |
71 void HeapRegionSetBase::verify_end() { |
139 // See comment in verify() about MT safety and verification. |
72 // See comment in verify() about MT safety and verification. |
140 hrs_assert_mt_safety_ok(this); |
73 check_mt_safety(); |
141 assert(_verify_in_progress, |
74 assert(_verify_in_progress, |
142 hrs_ext_msg(this, "verification should be in progress")); |
75 hrs_ext_msg(this, "verification should be in progress")); |
143 |
76 |
144 guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification")); |
|
145 |
|
146 _calc_length += 1; |
|
147 _calc_region_num += hr->region_num(); |
|
148 _calc_total_capacity_bytes += hr->capacity(); |
|
149 _calc_total_used_bytes += hr->used(); |
|
150 } |
|
151 |
|
152 void HeapRegionSetBase::verify_end() { |
|
153 // See comment in verify() about MT safety and verification. |
|
154 hrs_assert_mt_safety_ok(this); |
|
155 assert(_verify_in_progress, |
|
156 hrs_ext_msg(this, "verification should be in progress")); |
|
157 |
|
158 guarantee(length() == _calc_length, |
|
159 hrs_err_msg("[%s] length: %u should be == calc length: %u", |
|
160 name(), length(), _calc_length)); |
|
161 |
|
162 guarantee(region_num() == _calc_region_num, |
|
163 hrs_err_msg("[%s] region num: %u should be == calc region num: %u", |
|
164 name(), region_num(), _calc_region_num)); |
|
165 |
|
166 guarantee(total_capacity_bytes() == _calc_total_capacity_bytes, |
|
167 hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " |
|
168 "calc capacity bytes: "SIZE_FORMAT, |
|
169 name(), |
|
170 total_capacity_bytes(), _calc_total_capacity_bytes)); |
|
171 |
|
172 guarantee(total_used_bytes() == _calc_total_used_bytes, |
|
173 hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " |
|
174 "calc used bytes: "SIZE_FORMAT, |
|
175 name(), total_used_bytes(), _calc_total_used_bytes)); |
|
176 |
|
177 _verify_in_progress = false; |
77 _verify_in_progress = false; |
178 } |
|
179 |
|
180 void HeapRegionSetBase::clear_phase() { |
|
181 assert(_phase != HRSPhaseNone, "pre-condition"); |
|
182 _phase = HRSPhaseNone; |
|
183 } |
|
184 |
|
185 void HeapRegionSetBase::set_phase(HRSPhase phase) { |
|
186 assert(_phase == HRSPhaseNone, "pre-condition"); |
|
187 assert(phase != HRSPhaseNone, "pre-condition"); |
|
188 _phase = phase; |
|
189 } |
78 } |
190 |
79 |
191 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) { |
80 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) { |
192 out->cr(); |
81 out->cr(); |
193 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this); |
82 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this); |
194 out->print_cr(" Region Assumptions"); |
83 out->print_cr(" Region Assumptions"); |
195 out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous())); |
84 out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous())); |
196 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty())); |
85 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty())); |
197 out->print_cr(" Attributes"); |
86 out->print_cr(" Attributes"); |
198 out->print_cr(" length : %14u", length()); |
87 out->print_cr(" length : %14u", length()); |
199 out->print_cr(" region num : %14u", region_num()); |
|
200 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", |
88 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", |
201 total_capacity_bytes()); |
89 total_capacity_bytes()); |
202 out->print_cr(" total used : "SIZE_FORMAT_W(14)" bytes", |
90 } |
203 total_used_bytes()); |
91 |
204 } |
92 HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker) |
205 |
|
206 void HeapRegionSetBase::clear() { |
|
207 _length = 0; |
|
208 _region_num = 0; |
|
209 _total_used_bytes = 0; |
|
210 } |
|
211 |
|
212 HeapRegionSetBase::HeapRegionSetBase(const char* name) |
|
213 : _name(name), _verify_in_progress(false), |
93 : _name(name), _verify_in_progress(false), |
214 _calc_length(0), _calc_region_num(0), |
94 _is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker), |
215 _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { } |
95 _count() |
216 |
96 { } |
217 //////////////////// HeapRegionSet //////////////////// |
97 |
218 |
98 void FreeRegionList::set_unrealistically_long_length(uint len) { |
219 void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) { |
99 guarantee(_unrealistically_long_length == 0, "should only be set once"); |
220 hrs_assert_mt_safety_ok(this); |
100 _unrealistically_long_length = len; |
221 hrs_assert_mt_safety_ok(proxy_set); |
101 } |
222 hrs_assert_sets_match(this, proxy_set); |
102 |
223 |
103 void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { |
224 verify_optional(); |
|
225 proxy_set->verify_optional(); |
|
226 |
|
227 if (proxy_set->is_empty()) return; |
|
228 |
|
229 assert(proxy_set->length() <= _length, |
|
230 hrs_err_msg("[%s] proxy set length: %u should be <= length: %u", |
|
231 name(), proxy_set->length(), _length)); |
|
232 _length -= proxy_set->length(); |
|
233 |
|
234 assert(proxy_set->region_num() <= _region_num, |
|
235 hrs_err_msg("[%s] proxy set region num: %u should be <= region num: %u", |
|
236 name(), proxy_set->region_num(), _region_num)); |
|
237 _region_num -= proxy_set->region_num(); |
|
238 |
|
239 assert(proxy_set->total_used_bytes() <= _total_used_bytes, |
|
240 hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " |
|
241 "should be <= used bytes: "SIZE_FORMAT, |
|
242 name(), proxy_set->total_used_bytes(), |
|
243 _total_used_bytes)); |
|
244 _total_used_bytes -= proxy_set->total_used_bytes(); |
|
245 |
|
246 proxy_set->clear(); |
|
247 |
|
248 verify_optional(); |
|
249 proxy_set->verify_optional(); |
|
250 } |
|
251 |
|
252 //////////////////// HeapRegionLinkedList //////////////////// |
|
253 |
|
254 void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { |
|
255 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); |
104 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); |
256 } |
105 } |
257 |
106 |
258 void HeapRegionLinkedList::add_as_head(HeapRegionLinkedList* from_list) { |
107 void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) { |
259 hrs_assert_mt_safety_ok(this); |
108 check_mt_safety(); |
260 hrs_assert_mt_safety_ok(from_list); |
109 from_list->check_mt_safety(); |
261 |
110 |
262 verify_optional(); |
111 verify_optional(); |
263 from_list->verify_optional(); |
112 from_list->verify_optional(); |
264 |
113 |
265 if (from_list->is_empty()) return; |
114 if (from_list->is_empty()) { |
|
115 return; |
|
116 } |
266 |
117 |
267 #ifdef ASSERT |
118 #ifdef ASSERT |
268 HeapRegionLinkedListIterator iter(from_list); |
119 FreeRegionListIterator iter(from_list); |
269 while (iter.more_available()) { |
120 while (iter.more_available()) { |
270 HeapRegion* hr = iter.get_next(); |
121 HeapRegion* hr = iter.get_next(); |
271 // In set_containing_set() we check that we either set the value |
122 // In set_containing_set() we check that we either set the value |
272 // from NULL to non-NULL or vice versa to catch bugs. So, we have |
123 // from NULL to non-NULL or vice versa to catch bugs. So, we have |
273 // to NULL it first before setting it to the value. |
124 // to NULL it first before setting it to the value. |
274 hr->set_containing_set(NULL); |
125 hr->set_containing_set(NULL); |
275 hr->set_containing_set(this); |
126 hr->set_containing_set(this); |
276 } |
127 } |
277 #endif // ASSERT |
128 #endif // ASSERT |
278 |
129 |
279 if (_head != NULL) { |
130 if (_head == NULL) { |
280 assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant")); |
131 assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant")); |
281 from_list->_tail->set_next(_head); |
132 _head = from_list->_head; |
|
133 _tail = from_list->_tail; |
282 } else { |
134 } else { |
283 assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant")); |
135 assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant")); |
284 _tail = from_list->_tail; |
136 if (as_head) { |
285 } |
137 from_list->_tail->set_next(_head); |
286 _head = from_list->_head; |
138 _head = from_list->_head; |
287 |
139 } else { |
288 _length += from_list->length(); |
140 _tail->set_next(from_list->_head); |
289 _region_num += from_list->region_num(); |
141 _tail = from_list->_tail; |
290 _total_used_bytes += from_list->total_used_bytes(); |
142 } |
|
143 } |
|
144 |
|
145 _count.increment(from_list->length(), from_list->total_capacity_bytes()); |
291 from_list->clear(); |
146 from_list->clear(); |
292 |
147 |
293 verify_optional(); |
148 verify_optional(); |
294 from_list->verify_optional(); |
149 from_list->verify_optional(); |
295 } |
150 } |
296 |
151 |
297 void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) { |
152 void FreeRegionList::add_as_head(FreeRegionList* from_list) { |
298 hrs_assert_mt_safety_ok(this); |
153 add_as_head_or_tail(from_list, true /* as_head */); |
299 hrs_assert_mt_safety_ok(from_list); |
154 } |
300 |
155 |
301 verify_optional(); |
156 void FreeRegionList::add_as_tail(FreeRegionList* from_list) { |
302 from_list->verify_optional(); |
157 add_as_head_or_tail(from_list, false /* as_head */); |
303 |
158 } |
304 if (from_list->is_empty()) return; |
159 |
305 |
160 void FreeRegionList::remove_all() { |
306 #ifdef ASSERT |
161 check_mt_safety(); |
307 HeapRegionLinkedListIterator iter(from_list); |
|
308 while (iter.more_available()) { |
|
309 HeapRegion* hr = iter.get_next(); |
|
310 // In set_containing_set() we check that we either set the value |
|
311 // from NULL to non-NULL or vice versa to catch bugs. So, we have |
|
312 // to NULL it first before setting it to the value. |
|
313 hr->set_containing_set(NULL); |
|
314 hr->set_containing_set(this); |
|
315 } |
|
316 #endif // ASSERT |
|
317 |
|
318 if (_tail != NULL) { |
|
319 assert(length() > 0 && _head != NULL, hrs_ext_msg(this, "invariant")); |
|
320 _tail->set_next(from_list->_head); |
|
321 } else { |
|
322 assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant")); |
|
323 _head = from_list->_head; |
|
324 } |
|
325 _tail = from_list->_tail; |
|
326 |
|
327 _length += from_list->length(); |
|
328 _region_num += from_list->region_num(); |
|
329 _total_used_bytes += from_list->total_used_bytes(); |
|
330 from_list->clear(); |
|
331 |
|
332 verify_optional(); |
|
333 from_list->verify_optional(); |
|
334 } |
|
335 |
|
336 void HeapRegionLinkedList::remove_all() { |
|
337 hrs_assert_mt_safety_ok(this); |
|
338 verify_optional(); |
162 verify_optional(); |
339 |
163 |
340 HeapRegion* curr = _head; |
164 HeapRegion* curr = _head; |
341 while (curr != NULL) { |
165 while (curr != NULL) { |
342 hrs_assert_region_ok(this, curr, this); |
166 verify_region(curr); |
343 |
167 |
344 HeapRegion* next = curr->next(); |
168 HeapRegion* next = curr->next(); |
345 curr->set_next(NULL); |
169 curr->set_next(NULL); |
346 curr->set_containing_set(NULL); |
170 curr->set_containing_set(NULL); |
347 curr = next; |
171 curr = next; |