Mercurial > hg > graal-compiler
comparison src/share/vm/gc_implementation/g1/heapRegionSet.cpp @ 2152:0fa27f37d4d4
6977804: G1: remove the zero-filling thread
Summary: This changeset removes the zero-filling thread from G1 and collapses the two free region lists we had before (the "free" and "unclean" lists) into one. The new free list uses the new heap region sets / lists abstractions that we'll ultimately use it to keep track of all regions in the heap. A heap region set was also introduced for the humongous regions. Finally, this change increases the concurrency between the thread that completes freeing regions (after a cleanup pause) and the rest of the system (before we'd have to wait for said thread to complete before allocating a new region). The changest also includes a lot of refactoring and code simplification.
Reviewed-by: jcoomes, johnc
author | tonyp |
---|---|
date | Wed, 19 Jan 2011 19:30:42 -0500 |
parents | |
children | 1216415d8e35 |
comparison
equal
deleted
inserted
replaced
2151:cb913d743d09 | 2152:0fa27f37d4d4 |
---|---|
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; | |
29 | |
30 //////////////////// HeapRegionSetBase //////////////////// | |
31 | |
32 void HeapRegionSetBase::set_unrealistically_long_length(size_t len) { | |
33 guarantee(_unrealistically_long_length == 0, "should only be set once"); | |
34 _unrealistically_long_length = len; | |
35 } | |
36 | |
37 size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) { | |
38 assert(hr->startsHumongous(), "pre-condition"); | |
39 assert(hr->capacity() % HeapRegion::GrainBytes == 0, "invariant"); | |
40 size_t region_num = hr->capacity() >> HeapRegion::LogOfHRGrainBytes; | |
41 assert(region_num > 0, "sanity"); | |
42 return region_num; | |
43 } | |
44 | |
45 void HeapRegionSetBase::fill_in_ext_msg(hrl_ext_msg* msg, const char* message) { | |
46 msg->append("[%s] %s " | |
47 "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" " | |
48 "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT, | |
49 name(), message, length(), region_num(), | |
50 total_capacity_bytes(), total_used_bytes()); | |
51 fill_in_ext_msg_extra(msg); | |
52 } | |
53 | |
54 bool HeapRegionSetBase::verify_region(HeapRegion* hr, | |
55 HeapRegionSetBase* expected_containing_set) { | |
56 const char* error_message = NULL; | |
57 | |
58 if (!regions_humongous()) { | |
59 if (hr->isHumongous()) { | |
60 error_message = "the region should not be humongous"; | |
61 } | |
62 } else { | |
63 if (!hr->isHumongous() || !hr->startsHumongous()) { | |
64 error_message = "the region should be 'starts humongous'"; | |
65 } | |
66 } | |
67 | |
68 if (!regions_empty()) { | |
69 if (hr->is_empty()) { | |
70 error_message = "the region should not be empty"; | |
71 } | |
72 } else { | |
73 if (!hr->is_empty()) { | |
74 error_message = "the region should be empty"; | |
75 } | |
76 } | |
77 | |
78 #ifdef ASSERT | |
79 // The _containing_set field is only available when ASSERT is defined. | |
80 if (hr->containing_set() != expected_containing_set) { | |
81 error_message = "inconsistent containing set found"; | |
82 } | |
83 #endif // ASSERT | |
84 | |
85 const char* extra_error_message = verify_region_extra(hr); | |
86 if (extra_error_message != NULL) { | |
87 error_message = extra_error_message; | |
88 } | |
89 | |
90 if (error_message != NULL) { | |
91 outputStream* out = tty; | |
92 out->cr(); | |
93 out->print_cr("## [%s] %s", name(), error_message); | |
94 out->print_cr("## Offending Region: "PTR_FORMAT, hr); | |
95 out->print_cr(" "HR_FORMAT, HR_FORMAT_PARAMS(hr)); | |
96 #ifdef ASSERT | |
97 out->print_cr(" containing set: "PTR_FORMAT, hr->containing_set()); | |
98 #endif // ASSERT | |
99 out->print_cr("## Offending Region Set: "PTR_FORMAT, this); | |
100 print_on(out); | |
101 return false; | |
102 } else { | |
103 return true; | |
104 } | |
105 } | |
106 | |
107 void HeapRegionSetBase::verify() { | |
108 // It's important that we also observe the MT safety protocol even | |
109 // for the verification calls. If we do verification without the | |
110 // appropriate locks and the set changes underneath our feet | |
111 // verification might fail and send us on a wild goose chase. | |
112 hrl_assert_mt_safety_ok(this); | |
113 | |
114 guarantee(( is_empty() && length() == 0 && region_num() == 0 && | |
115 total_used_bytes() == 0 && total_capacity_bytes() == 0) || | |
116 (!is_empty() && length() >= 0 && region_num() >= 0 && | |
117 total_used_bytes() >= 0 && total_capacity_bytes() >= 0), | |
118 hrl_ext_msg(this, "invariant")); | |
119 | |
120 guarantee((!regions_humongous() && region_num() == length()) || | |
121 ( regions_humongous() && region_num() >= length()), | |
122 hrl_ext_msg(this, "invariant")); | |
123 | |
124 guarantee(!regions_empty() || total_used_bytes() == 0, | |
125 hrl_ext_msg(this, "invariant")); | |
126 | |
127 guarantee(total_used_bytes() <= total_capacity_bytes(), | |
128 hrl_ext_msg(this, "invariant")); | |
129 } | |
130 | |
131 void HeapRegionSetBase::verify_start() { | |
132 // See comment in verify() about MT safety and verification. | |
133 hrl_assert_mt_safety_ok(this); | |
134 assert(!_verify_in_progress, | |
135 hrl_ext_msg(this, "verification should not be in progress")); | |
136 | |
137 // Do the basic verification first before we do the checks over the regions. | |
138 HeapRegionSetBase::verify(); | |
139 | |
140 _calc_length = 0; | |
141 _calc_region_num = 0; | |
142 _calc_total_capacity_bytes = 0; | |
143 _calc_total_used_bytes = 0; | |
144 _verify_in_progress = true; | |
145 } | |
146 | |
147 void HeapRegionSetBase::verify_next_region(HeapRegion* hr) { | |
148 // See comment in verify() about MT safety and verification. | |
149 hrl_assert_mt_safety_ok(this); | |
150 assert(_verify_in_progress, | |
151 hrl_ext_msg(this, "verification should be in progress")); | |
152 | |
153 guarantee(verify_region(hr, this), hrl_ext_msg(this, "region verification")); | |
154 | |
155 _calc_length += 1; | |
156 if (!hr->isHumongous()) { | |
157 _calc_region_num += 1; | |
158 } else { | |
159 _calc_region_num += calculate_region_num(hr); | |
160 } | |
161 _calc_total_capacity_bytes += hr->capacity(); | |
162 _calc_total_used_bytes += hr->used(); | |
163 } | |
164 | |
165 void HeapRegionSetBase::verify_end() { | |
166 // See comment in verify() about MT safety and verification. | |
167 hrl_assert_mt_safety_ok(this); | |
168 assert(_verify_in_progress, | |
169 hrl_ext_msg(this, "verification should be in progress")); | |
170 | |
171 guarantee(length() == _calc_length, | |
172 hrl_err_msg("[%s] length: "SIZE_FORMAT" should be == " | |
173 "calc length: "SIZE_FORMAT, | |
174 name(), length(), _calc_length)); | |
175 | |
176 guarantee(region_num() == _calc_region_num, | |
177 hrl_err_msg("[%s] region num: "SIZE_FORMAT" should be == " | |
178 "calc region num: "SIZE_FORMAT, | |
179 name(), region_num(), _calc_region_num)); | |
180 | |
181 guarantee(total_capacity_bytes() == _calc_total_capacity_bytes, | |
182 hrl_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " | |
183 "calc capacity bytes: "SIZE_FORMAT, | |
184 name(), | |
185 total_capacity_bytes(), _calc_total_capacity_bytes)); | |
186 | |
187 guarantee(total_used_bytes() == _calc_total_used_bytes, | |
188 hrl_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " | |
189 "calc used bytes: "SIZE_FORMAT, | |
190 name(), total_used_bytes(), _calc_total_used_bytes)); | |
191 | |
192 _verify_in_progress = false; | |
193 } | |
194 | |
195 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) { | |
196 out->cr(); | |
197 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this); | |
198 out->print_cr(" Region Assumptions"); | |
199 out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous())); | |
200 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty())); | |
201 out->print_cr(" Attributes"); | |
202 out->print_cr(" length : "SIZE_FORMAT_W(14), length()); | |
203 out->print_cr(" region num : "SIZE_FORMAT_W(14), region_num()); | |
204 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", | |
205 total_capacity_bytes()); | |
206 out->print_cr(" total used : "SIZE_FORMAT_W(14)" bytes", | |
207 total_used_bytes()); | |
208 } | |
209 | |
210 void HeapRegionSetBase::clear() { | |
211 _length = 0; | |
212 _region_num = 0; | |
213 _total_used_bytes = 0; | |
214 } | |
215 | |
216 HeapRegionSetBase::HeapRegionSetBase(const char* name) | |
217 : _name(name), _verify_in_progress(false), | |
218 _calc_length(0), _calc_region_num(0), | |
219 _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { } | |
220 | |
221 //////////////////// HeapRegionSet //////////////////// | |
222 | |
223 void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) { | |
224 hrl_assert_mt_safety_ok(this); | |
225 hrl_assert_mt_safety_ok(proxy_set); | |
226 hrl_assert_sets_match(this, proxy_set); | |
227 | |
228 verify_optional(); | |
229 proxy_set->verify_optional(); | |
230 | |
231 if (proxy_set->is_empty()) return; | |
232 | |
233 assert(proxy_set->length() <= _length, | |
234 hrl_err_msg("[%s] proxy set length: "SIZE_FORMAT" " | |
235 "should be <= length: "SIZE_FORMAT, | |
236 name(), proxy_set->length(), _length)); | |
237 _length -= proxy_set->length(); | |
238 | |
239 assert(proxy_set->region_num() <= _region_num, | |
240 hrl_err_msg("[%s] proxy set region num: "SIZE_FORMAT" " | |
241 "should be <= region num: "SIZE_FORMAT, | |
242 name(), proxy_set->region_num(), _region_num)); | |
243 _region_num -= proxy_set->region_num(); | |
244 | |
245 assert(proxy_set->total_used_bytes() <= _total_used_bytes, | |
246 hrl_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " | |
247 "should be <= used bytes: "SIZE_FORMAT, | |
248 name(), proxy_set->total_used_bytes(), | |
249 _total_used_bytes)); | |
250 _total_used_bytes -= proxy_set->total_used_bytes(); | |
251 | |
252 proxy_set->clear(); | |
253 | |
254 verify_optional(); | |
255 proxy_set->verify_optional(); | |
256 } | |
257 | |
258 //////////////////// HeapRegionLinkedList //////////////////// | |
259 | |
260 void HeapRegionLinkedList::fill_in_ext_msg_extra(hrl_ext_msg* msg) { | |
261 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); | |
262 } | |
263 | |
264 void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) { | |
265 hrl_assert_mt_safety_ok(this); | |
266 hrl_assert_mt_safety_ok(from_list); | |
267 | |
268 verify_optional(); | |
269 from_list->verify_optional(); | |
270 | |
271 if (from_list->is_empty()) return; | |
272 | |
273 #ifdef ASSERT | |
274 HeapRegionLinkedListIterator iter(from_list); | |
275 while (iter.more_available()) { | |
276 HeapRegion* hr = iter.get_next(); | |
277 // In set_containing_set() we check that we either set the value | |
278 // from NULL to non-NULL or vice versa to catch bugs. So, we have | |
279 // to NULL it first before setting it to the value. | |
280 hr->set_containing_set(NULL); | |
281 hr->set_containing_set(this); | |
282 } | |
283 #endif // ASSERT | |
284 | |
285 if (_tail != NULL) { | |
286 assert(length() > 0 && _head != NULL, hrl_ext_msg(this, "invariant")); | |
287 _tail->set_next(from_list->_head); | |
288 } else { | |
289 assert(length() == 0 && _head == NULL, hrl_ext_msg(this, "invariant")); | |
290 _head = from_list->_head; | |
291 } | |
292 _tail = from_list->_tail; | |
293 | |
294 _length += from_list->length(); | |
295 _region_num += from_list->region_num(); | |
296 _total_used_bytes += from_list->total_used_bytes(); | |
297 from_list->clear(); | |
298 | |
299 verify_optional(); | |
300 from_list->verify_optional(); | |
301 } | |
302 | |
303 void HeapRegionLinkedList::remove_all() { | |
304 hrl_assert_mt_safety_ok(this); | |
305 verify_optional(); | |
306 | |
307 HeapRegion* curr = _head; | |
308 while (curr != NULL) { | |
309 hrl_assert_region_ok(this, curr, this); | |
310 | |
311 HeapRegion* next = curr->next(); | |
312 curr->set_next(NULL); | |
313 curr->set_containing_set(NULL); | |
314 curr = next; | |
315 } | |
316 clear(); | |
317 | |
318 verify_optional(); | |
319 } | |
320 | |
321 void HeapRegionLinkedList::remove_all_pending(size_t target_count) { | |
322 hrl_assert_mt_safety_ok(this); | |
323 assert(target_count > 1, hrl_ext_msg(this, "pre-condition")); | |
324 assert(!is_empty(), hrl_ext_msg(this, "pre-condition")); | |
325 | |
326 verify_optional(); | |
327 DEBUG_ONLY(size_t old_length = length();) | |
328 | |
329 HeapRegion* curr = _head; | |
330 HeapRegion* prev = NULL; | |
331 size_t count = 0; | |
332 while (curr != NULL) { | |
333 hrl_assert_region_ok(this, curr, this); | |
334 HeapRegion* next = curr->next(); | |
335 | |
336 if (curr->pending_removal()) { | |
337 assert(count < target_count, | |
338 hrl_err_msg("[%s] should not come across more regions " | |
339 "pending for removal than target_count: "SIZE_FORMAT, | |
340 name(), target_count)); | |
341 | |
342 if (prev == NULL) { | |
343 assert(_head == curr, hrl_ext_msg(this, "invariant")); | |
344 _head = next; | |
345 } else { | |
346 assert(_head != curr, hrl_ext_msg(this, "invariant")); | |
347 prev->set_next(next); | |
348 } | |
349 if (next == NULL) { | |
350 assert(_tail == curr, hrl_ext_msg(this, "invariant")); | |
351 _tail = prev; | |
352 } else { | |
353 assert(_tail != curr, hrl_ext_msg(this, "invariant")); | |
354 } | |
355 | |
356 curr->set_next(NULL); | |
357 remove_internal(curr); | |
358 curr->set_pending_removal(false); | |
359 | |
360 count += 1; | |
361 | |
362 // If we have come across the target number of regions we can | |
363 // just bail out. However, for debugging purposes, we can just | |
364 // carry on iterating to make sure there are not more regions | |
365 // tagged with pending removal. | |
366 DEBUG_ONLY(if (count == target_count) break;) | |
367 } else { | |
368 prev = curr; | |
369 } | |
370 curr = next; | |
371 } | |
372 | |
373 assert(count == target_count, | |
374 hrl_err_msg("[%s] count: "SIZE_FORMAT" should be == " | |
375 "target_count: "SIZE_FORMAT, name(), count, target_count)); | |
376 assert(length() + target_count == old_length, | |
377 hrl_err_msg("[%s] new length should be consistent " | |
378 "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" " | |
379 "target_count: "SIZE_FORMAT, | |
380 name(), length(), old_length, target_count)); | |
381 | |
382 verify_optional(); | |
383 } | |
384 | |
385 void HeapRegionLinkedList::verify() { | |
386 // See comment in HeapRegionSetBase::verify() about MT safety and | |
387 // verification. | |
388 hrl_assert_mt_safety_ok(this); | |
389 | |
390 // This will also do the basic verification too. | |
391 verify_start(); | |
392 | |
393 HeapRegion* curr = _head; | |
394 HeapRegion* prev1 = NULL; | |
395 HeapRegion* prev0 = NULL; | |
396 size_t count = 0; | |
397 while (curr != NULL) { | |
398 verify_next_region(curr); | |
399 | |
400 count += 1; | |
401 guarantee(count < _unrealistically_long_length, | |
402 hrl_err_msg("[%s] the calculated length: "SIZE_FORMAT" " | |
403 "seems very long, is there maybe a cycle? " | |
404 "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " | |
405 "prev1: "PTR_FORMAT" length: "SIZE_FORMAT, | |
406 name(), count, curr, prev0, prev1, length())); | |
407 | |
408 prev1 = prev0; | |
409 prev0 = curr; | |
410 curr = curr->next(); | |
411 } | |
412 | |
413 guarantee(_tail == prev0, hrl_ext_msg(this, "post-condition")); | |
414 | |
415 verify_end(); | |
416 } | |
417 | |
418 void HeapRegionLinkedList::clear() { | |
419 HeapRegionSetBase::clear(); | |
420 _head = NULL; | |
421 _tail = NULL; | |
422 } | |
423 | |
424 void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) { | |
425 HeapRegionSetBase::print_on(out, print_contents); | |
426 out->print_cr(" Linking"); | |
427 out->print_cr(" head : "PTR_FORMAT, _head); | |
428 out->print_cr(" tail : "PTR_FORMAT, _tail); | |
429 | |
430 if (print_contents) { | |
431 out->print_cr(" Contents"); | |
432 HeapRegionLinkedListIterator iter(this); | |
433 while (iter.more_available()) { | |
434 HeapRegion* hr = iter.get_next(); | |
435 hr->print_on(out); | |
436 } | |
437 } | |
438 } |