Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/g1/heapRegionSet.cpp @ 4912:a9647476d1a4
7132029: G1: mixed GC phase lasts for longer than it should
Summary: Revamp of the mechanism that chooses old regions for inclusion in the CSet. It simplifies the code and introduces min and max bounds on the number of old regions added to the CSet at each mixed GC to avoid pathological cases. It also ensures that when we do a mixed GC we'll always find old regions to add to the CSet (i.e., it eliminates the case where a mixed GC will collect no old regions which can happen today).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Wed, 15 Feb 2012 13:06:53 -0500 |
parents | 8aae2050e83e |
children | 720b6a76dd9d |
rev | line source |
---|---|
2152 | 1 /* |
2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. | |
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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 * | |
23 */ | |
24 | |
25 #include "precompiled.hpp" | |
26 #include "gc_implementation/g1/heapRegionSet.inline.hpp" | |
27 | |
28 size_t HeapRegionSetBase::_unrealistically_long_length = 0; | |
4072 | 29 HRSPhase HeapRegionSetBase::_phase = HRSPhaseNone; |
2152 | 30 |
31 //////////////////// HeapRegionSetBase //////////////////// | |
32 | |
33 void HeapRegionSetBase::set_unrealistically_long_length(size_t len) { | |
34 guarantee(_unrealistically_long_length == 0, "should only be set once"); | |
35 _unrealistically_long_length = len; | |
36 } | |
37 | |
38 size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) { | |
39 assert(hr->startsHumongous(), "pre-condition"); | |
40 assert(hr->capacity() % HeapRegion::GrainBytes == 0, "invariant"); | |
41 size_t region_num = hr->capacity() >> HeapRegion::LogOfHRGrainBytes; | |
42 assert(region_num > 0, "sanity"); | |
43 return region_num; | |
44 } | |
45 | |
2361 | 46 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { |
2152 | 47 msg->append("[%s] %s " |
48 "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" " | |
49 "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT, | |
50 name(), message, length(), region_num(), | |
51 total_capacity_bytes(), total_used_bytes()); | |
52 fill_in_ext_msg_extra(msg); | |
53 } | |
54 | |
55 bool HeapRegionSetBase::verify_region(HeapRegion* hr, | |
56 HeapRegionSetBase* expected_containing_set) { | |
57 const char* error_message = NULL; | |
58 | |
59 if (!regions_humongous()) { | |
60 if (hr->isHumongous()) { | |
61 error_message = "the region should not be humongous"; | |
62 } | |
63 } else { | |
64 if (!hr->isHumongous() || !hr->startsHumongous()) { | |
65 error_message = "the region should be 'starts humongous'"; | |
66 } | |
67 } | |
68 | |
69 if (!regions_empty()) { | |
70 if (hr->is_empty()) { | |
71 error_message = "the region should not be empty"; | |
72 } | |
73 } else { | |
74 if (!hr->is_empty()) { | |
75 error_message = "the region should be empty"; | |
76 } | |
77 } | |
78 | |
79 #ifdef ASSERT | |
80 // The _containing_set field is only available when ASSERT is defined. | |
81 if (hr->containing_set() != expected_containing_set) { | |
82 error_message = "inconsistent containing set found"; | |
83 } | |
84 #endif // ASSERT | |
85 | |
86 const char* extra_error_message = verify_region_extra(hr); | |
87 if (extra_error_message != NULL) { | |
88 error_message = extra_error_message; | |
89 } | |
90 | |
91 if (error_message != NULL) { | |
92 outputStream* out = tty; | |
93 out->cr(); | |
94 out->print_cr("## [%s] %s", name(), error_message); | |
95 out->print_cr("## Offending Region: "PTR_FORMAT, hr); | |
96 out->print_cr(" "HR_FORMAT, HR_FORMAT_PARAMS(hr)); | |
97 #ifdef ASSERT | |
98 out->print_cr(" containing set: "PTR_FORMAT, hr->containing_set()); | |
99 #endif // ASSERT | |
100 out->print_cr("## Offending Region Set: "PTR_FORMAT, this); | |
101 print_on(out); | |
102 return false; | |
103 } else { | |
104 return true; | |
105 } | |
106 } | |
107 | |
108 void HeapRegionSetBase::verify() { | |
109 // It's important that we also observe the MT safety protocol even | |
110 // for the verification calls. If we do verification without the | |
111 // appropriate locks and the set changes underneath our feet | |
112 // verification might fail and send us on a wild goose chase. | |
2361 | 113 hrs_assert_mt_safety_ok(this); |
2152 | 114 |
115 guarantee(( is_empty() && length() == 0 && region_num() == 0 && | |
116 total_used_bytes() == 0 && total_capacity_bytes() == 0) || | |
117 (!is_empty() && length() >= 0 && region_num() >= 0 && | |
118 total_used_bytes() >= 0 && total_capacity_bytes() >= 0), | |
2361 | 119 hrs_ext_msg(this, "invariant")); |
2152 | 120 |
121 guarantee((!regions_humongous() && region_num() == length()) || | |
122 ( regions_humongous() && region_num() >= length()), | |
2361 | 123 hrs_ext_msg(this, "invariant")); |
2152 | 124 |
125 guarantee(!regions_empty() || total_used_bytes() == 0, | |
2361 | 126 hrs_ext_msg(this, "invariant")); |
2152 | 127 |
128 guarantee(total_used_bytes() <= total_capacity_bytes(), | |
2361 | 129 hrs_ext_msg(this, "invariant")); |
2152 | 130 } |
131 | |
132 void HeapRegionSetBase::verify_start() { | |
133 // See comment in verify() about MT safety and verification. | |
2361 | 134 hrs_assert_mt_safety_ok(this); |
2152 | 135 assert(!_verify_in_progress, |
2361 | 136 hrs_ext_msg(this, "verification should not be in progress")); |
2152 | 137 |
138 // Do the basic verification first before we do the checks over the regions. | |
139 HeapRegionSetBase::verify(); | |
140 | |
141 _calc_length = 0; | |
142 _calc_region_num = 0; | |
143 _calc_total_capacity_bytes = 0; | |
144 _calc_total_used_bytes = 0; | |
145 _verify_in_progress = true; | |
146 } | |
147 | |
148 void HeapRegionSetBase::verify_next_region(HeapRegion* hr) { | |
149 // See comment in verify() about MT safety and verification. | |
2361 | 150 hrs_assert_mt_safety_ok(this); |
2152 | 151 assert(_verify_in_progress, |
2361 | 152 hrs_ext_msg(this, "verification should be in progress")); |
2152 | 153 |
2361 | 154 guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification")); |
2152 | 155 |
156 _calc_length += 1; | |
157 if (!hr->isHumongous()) { | |
158 _calc_region_num += 1; | |
159 } else { | |
160 _calc_region_num += calculate_region_num(hr); | |
161 } | |
162 _calc_total_capacity_bytes += hr->capacity(); | |
163 _calc_total_used_bytes += hr->used(); | |
164 } | |
165 | |
166 void HeapRegionSetBase::verify_end() { | |
167 // See comment in verify() about MT safety and verification. | |
2361 | 168 hrs_assert_mt_safety_ok(this); |
2152 | 169 assert(_verify_in_progress, |
2361 | 170 hrs_ext_msg(this, "verification should be in progress")); |
2152 | 171 |
172 guarantee(length() == _calc_length, | |
2361 | 173 hrs_err_msg("[%s] length: "SIZE_FORMAT" should be == " |
2152 | 174 "calc length: "SIZE_FORMAT, |
175 name(), length(), _calc_length)); | |
176 | |
177 guarantee(region_num() == _calc_region_num, | |
2361 | 178 hrs_err_msg("[%s] region num: "SIZE_FORMAT" should be == " |
2152 | 179 "calc region num: "SIZE_FORMAT, |
180 name(), region_num(), _calc_region_num)); | |
181 | |
182 guarantee(total_capacity_bytes() == _calc_total_capacity_bytes, | |
2361 | 183 hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " |
2152 | 184 "calc capacity bytes: "SIZE_FORMAT, |
185 name(), | |
186 total_capacity_bytes(), _calc_total_capacity_bytes)); | |
187 | |
188 guarantee(total_used_bytes() == _calc_total_used_bytes, | |
2361 | 189 hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " |
2152 | 190 "calc used bytes: "SIZE_FORMAT, |
191 name(), total_used_bytes(), _calc_total_used_bytes)); | |
192 | |
193 _verify_in_progress = false; | |
194 } | |
195 | |
4072 | 196 void HeapRegionSetBase::clear_phase() { |
197 assert(_phase != HRSPhaseNone, "pre-condition"); | |
198 _phase = HRSPhaseNone; | |
199 } | |
200 | |
201 void HeapRegionSetBase::set_phase(HRSPhase phase) { | |
202 assert(_phase == HRSPhaseNone, "pre-condition"); | |
203 assert(phase != HRSPhaseNone, "pre-condition"); | |
204 _phase = phase; | |
205 } | |
206 | |
2152 | 207 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) { |
208 out->cr(); | |
209 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this); | |
210 out->print_cr(" Region Assumptions"); | |
211 out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous())); | |
212 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty())); | |
213 out->print_cr(" Attributes"); | |
214 out->print_cr(" length : "SIZE_FORMAT_W(14), length()); | |
215 out->print_cr(" region num : "SIZE_FORMAT_W(14), region_num()); | |
216 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", | |
217 total_capacity_bytes()); | |
218 out->print_cr(" total used : "SIZE_FORMAT_W(14)" bytes", | |
219 total_used_bytes()); | |
220 } | |
221 | |
222 void HeapRegionSetBase::clear() { | |
223 _length = 0; | |
224 _region_num = 0; | |
225 _total_used_bytes = 0; | |
226 } | |
227 | |
228 HeapRegionSetBase::HeapRegionSetBase(const char* name) | |
229 : _name(name), _verify_in_progress(false), | |
230 _calc_length(0), _calc_region_num(0), | |
231 _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { } | |
232 | |
233 //////////////////// HeapRegionSet //////////////////// | |
234 | |
235 void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) { | |
2361 | 236 hrs_assert_mt_safety_ok(this); |
237 hrs_assert_mt_safety_ok(proxy_set); | |
238 hrs_assert_sets_match(this, proxy_set); | |
2152 | 239 |
240 verify_optional(); | |
241 proxy_set->verify_optional(); | |
242 | |
243 if (proxy_set->is_empty()) return; | |
244 | |
245 assert(proxy_set->length() <= _length, | |
2361 | 246 hrs_err_msg("[%s] proxy set length: "SIZE_FORMAT" " |
2152 | 247 "should be <= length: "SIZE_FORMAT, |
248 name(), proxy_set->length(), _length)); | |
249 _length -= proxy_set->length(); | |
250 | |
251 assert(proxy_set->region_num() <= _region_num, | |
2361 | 252 hrs_err_msg("[%s] proxy set region num: "SIZE_FORMAT" " |
2152 | 253 "should be <= region num: "SIZE_FORMAT, |
254 name(), proxy_set->region_num(), _region_num)); | |
255 _region_num -= proxy_set->region_num(); | |
256 | |
257 assert(proxy_set->total_used_bytes() <= _total_used_bytes, | |
2361 | 258 hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " |
2152 | 259 "should be <= used bytes: "SIZE_FORMAT, |
260 name(), proxy_set->total_used_bytes(), | |
261 _total_used_bytes)); | |
262 _total_used_bytes -= proxy_set->total_used_bytes(); | |
263 | |
264 proxy_set->clear(); | |
265 | |
266 verify_optional(); | |
267 proxy_set->verify_optional(); | |
268 } | |
269 | |
270 //////////////////// HeapRegionLinkedList //////////////////// | |
271 | |
2361 | 272 void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { |
2152 | 273 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); |
274 } | |
275 | |
2432
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
276 void HeapRegionLinkedList::add_as_head(HeapRegionLinkedList* from_list) { |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
277 hrs_assert_mt_safety_ok(this); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
278 hrs_assert_mt_safety_ok(from_list); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
279 |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
280 verify_optional(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
281 from_list->verify_optional(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
282 |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
283 if (from_list->is_empty()) return; |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
284 |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
285 #ifdef ASSERT |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
286 HeapRegionLinkedListIterator iter(from_list); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
287 while (iter.more_available()) { |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
288 HeapRegion* hr = iter.get_next(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
289 // In set_containing_set() we check that we either set the value |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
290 // from NULL to non-NULL or vice versa to catch bugs. So, we have |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
291 // to NULL it first before setting it to the value. |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
292 hr->set_containing_set(NULL); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
293 hr->set_containing_set(this); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
294 } |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
295 #endif // ASSERT |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
296 |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
297 if (_head != NULL) { |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
298 assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant")); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
299 from_list->_tail->set_next(_head); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
300 } else { |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
301 assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant")); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
302 _tail = from_list->_tail; |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
303 } |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
304 _head = from_list->_head; |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
305 |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
306 _length += from_list->length(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
307 _region_num += from_list->region_num(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
308 _total_used_bytes += from_list->total_used_bytes(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
309 from_list->clear(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
310 |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
311 verify_optional(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
312 from_list->verify_optional(); |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
313 } |
455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
tonyp
parents:
2361
diff
changeset
|
314 |
2152 | 315 void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) { |
2361 | 316 hrs_assert_mt_safety_ok(this); |
317 hrs_assert_mt_safety_ok(from_list); | |
2152 | 318 |
319 verify_optional(); | |
320 from_list->verify_optional(); | |
321 | |
322 if (from_list->is_empty()) return; | |
323 | |
324 #ifdef ASSERT | |
325 HeapRegionLinkedListIterator iter(from_list); | |
326 while (iter.more_available()) { | |
327 HeapRegion* hr = iter.get_next(); | |
328 // In set_containing_set() we check that we either set the value | |
329 // from NULL to non-NULL or vice versa to catch bugs. So, we have | |
330 // to NULL it first before setting it to the value. | |
331 hr->set_containing_set(NULL); | |
332 hr->set_containing_set(this); | |
333 } | |
334 #endif // ASSERT | |
335 | |
336 if (_tail != NULL) { | |
2361 | 337 assert(length() > 0 && _head != NULL, hrs_ext_msg(this, "invariant")); |
2152 | 338 _tail->set_next(from_list->_head); |
339 } else { | |
2361 | 340 assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant")); |
2152 | 341 _head = from_list->_head; |
342 } | |
343 _tail = from_list->_tail; | |
344 | |
345 _length += from_list->length(); | |
346 _region_num += from_list->region_num(); | |
347 _total_used_bytes += from_list->total_used_bytes(); | |
348 from_list->clear(); | |
349 | |
350 verify_optional(); | |
351 from_list->verify_optional(); | |
352 } | |
353 | |
354 void HeapRegionLinkedList::remove_all() { | |
2361 | 355 hrs_assert_mt_safety_ok(this); |
2152 | 356 verify_optional(); |
357 | |
358 HeapRegion* curr = _head; | |
359 while (curr != NULL) { | |
2361 | 360 hrs_assert_region_ok(this, curr, this); |
2152 | 361 |
362 HeapRegion* next = curr->next(); | |
363 curr->set_next(NULL); | |
364 curr->set_containing_set(NULL); | |
365 curr = next; | |
366 } | |
367 clear(); | |
368 | |
369 verify_optional(); | |
370 } | |
371 | |
372 void HeapRegionLinkedList::remove_all_pending(size_t target_count) { | |
2361 | 373 hrs_assert_mt_safety_ok(this); |
374 assert(target_count > 1, hrs_ext_msg(this, "pre-condition")); | |
375 assert(!is_empty(), hrs_ext_msg(this, "pre-condition")); | |
2152 | 376 |
377 verify_optional(); | |
378 DEBUG_ONLY(size_t old_length = length();) | |
379 | |
380 HeapRegion* curr = _head; | |
381 HeapRegion* prev = NULL; | |
382 size_t count = 0; | |
383 while (curr != NULL) { | |
2361 | 384 hrs_assert_region_ok(this, curr, this); |
2152 | 385 HeapRegion* next = curr->next(); |
386 | |
387 if (curr->pending_removal()) { | |
388 assert(count < target_count, | |
2361 | 389 hrs_err_msg("[%s] should not come across more regions " |
2152 | 390 "pending for removal than target_count: "SIZE_FORMAT, |
391 name(), target_count)); | |
392 | |
393 if (prev == NULL) { | |
2361 | 394 assert(_head == curr, hrs_ext_msg(this, "invariant")); |
2152 | 395 _head = next; |
396 } else { | |
2361 | 397 assert(_head != curr, hrs_ext_msg(this, "invariant")); |
2152 | 398 prev->set_next(next); |
399 } | |
400 if (next == NULL) { | |
2361 | 401 assert(_tail == curr, hrs_ext_msg(this, "invariant")); |
2152 | 402 _tail = prev; |
403 } else { | |
2361 | 404 assert(_tail != curr, hrs_ext_msg(this, "invariant")); |
2152 | 405 } |
406 | |
407 curr->set_next(NULL); | |
408 remove_internal(curr); | |
409 curr->set_pending_removal(false); | |
410 | |
411 count += 1; | |
412 | |
413 // If we have come across the target number of regions we can | |
414 // just bail out. However, for debugging purposes, we can just | |
415 // carry on iterating to make sure there are not more regions | |
416 // tagged with pending removal. | |
417 DEBUG_ONLY(if (count == target_count) break;) | |
418 } else { | |
419 prev = curr; | |
420 } | |
421 curr = next; | |
422 } | |
423 | |
424 assert(count == target_count, | |
2361 | 425 hrs_err_msg("[%s] count: "SIZE_FORMAT" should be == " |
2152 | 426 "target_count: "SIZE_FORMAT, name(), count, target_count)); |
427 assert(length() + target_count == old_length, | |
2361 | 428 hrs_err_msg("[%s] new length should be consistent " |
2152 | 429 "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" " |
430 "target_count: "SIZE_FORMAT, | |
431 name(), length(), old_length, target_count)); | |
432 | |
433 verify_optional(); | |
434 } | |
435 | |
436 void HeapRegionLinkedList::verify() { | |
437 // See comment in HeapRegionSetBase::verify() about MT safety and | |
438 // verification. | |
2361 | 439 hrs_assert_mt_safety_ok(this); |
2152 | 440 |
441 // This will also do the basic verification too. | |
442 verify_start(); | |
443 | |
444 HeapRegion* curr = _head; | |
445 HeapRegion* prev1 = NULL; | |
446 HeapRegion* prev0 = NULL; | |
447 size_t count = 0; | |
448 while (curr != NULL) { | |
449 verify_next_region(curr); | |
450 | |
451 count += 1; | |
452 guarantee(count < _unrealistically_long_length, | |
2361 | 453 hrs_err_msg("[%s] the calculated length: "SIZE_FORMAT" " |
2152 | 454 "seems very long, is there maybe a cycle? " |
455 "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " | |
456 "prev1: "PTR_FORMAT" length: "SIZE_FORMAT, | |
457 name(), count, curr, prev0, prev1, length())); | |
458 | |
459 prev1 = prev0; | |
460 prev0 = curr; | |
461 curr = curr->next(); | |
462 } | |
463 | |
2361 | 464 guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition")); |
2152 | 465 |
466 verify_end(); | |
467 } | |
468 | |
469 void HeapRegionLinkedList::clear() { | |
470 HeapRegionSetBase::clear(); | |
471 _head = NULL; | |
472 _tail = NULL; | |
473 } | |
474 | |
475 void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) { | |
476 HeapRegionSetBase::print_on(out, print_contents); | |
477 out->print_cr(" Linking"); | |
478 out->print_cr(" head : "PTR_FORMAT, _head); | |
479 out->print_cr(" tail : "PTR_FORMAT, _tail); | |
480 | |
481 if (print_contents) { | |
482 out->print_cr(" Contents"); | |
483 HeapRegionLinkedListIterator iter(this); | |
484 while (iter.more_available()) { | |
485 HeapRegion* hr = iter.get_next(); | |
486 hr->print_on(out); | |
487 } | |
488 } | |
489 } |