Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/g1/heapRegionSeq.cpp @ 12233:40136aa2cdb1
8010722: assert: failed: heap size is too big for compressed oops
Summary: Use conservative assumptions of required alignment for the various garbage collector components into account when determining the maximum heap size that supports compressed oops. Using this conservative value avoids several circular dependencies in the calculation.
Reviewed-by: stefank, dholmes
author | tschatzl |
---|---|
date | Wed, 11 Sep 2013 16:25:02 +0200 |
parents | b0d20fa374b4 |
children | a19bea467577 |
rev | line source |
---|---|
342 | 1 /* |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
960
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
960
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
960
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
3766 | 26 #include "gc_implementation/g1/heapRegion.hpp" |
27 #include "gc_implementation/g1/heapRegionSeq.inline.hpp" | |
28 #include "gc_implementation/g1/heapRegionSets.hpp" | |
1972 | 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" |
30 #include "memory/allocation.hpp" | |
342 | 31 |
3766 | 32 // Private |
342 | 33 |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
34 uint HeapRegionSeq::find_contiguous_from(uint from, uint num) { |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
35 uint len = length(); |
3766 | 36 assert(num > 1, "use this only for sequences of length 2 or greater"); |
37 assert(from <= len, | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
38 err_msg("from: %u should be valid and <= than %u", from, len)); |
342 | 39 |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
40 uint curr = from; |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
41 uint first = G1_NULL_HRS_INDEX; |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
42 uint num_so_far = 0; |
3766 | 43 while (curr < len && num_so_far < num) { |
44 if (at(curr)->is_empty()) { | |
45 if (first == G1_NULL_HRS_INDEX) { | |
2152 | 46 first = curr; |
47 num_so_far = 1; | |
48 } else { | |
49 num_so_far += 1; | |
50 } | |
51 } else { | |
3766 | 52 first = G1_NULL_HRS_INDEX; |
2152 | 53 num_so_far = 0; |
54 } | |
55 curr += 1; | |
56 } | |
57 assert(num_so_far <= num, "post-condition"); | |
58 if (num_so_far == num) { | |
2361 | 59 // we found enough space for the humongous object |
3766 | 60 assert(from <= first && first < len, "post-condition"); |
61 assert(first < curr && (curr - first) == num, "post-condition"); | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
62 for (uint i = first; i < first + num; ++i) { |
3766 | 63 assert(at(i)->is_empty(), "post-condition"); |
2152 | 64 } |
65 return first; | |
66 } else { | |
67 // we failed to find enough space for the humongous object | |
3766 | 68 return G1_NULL_HRS_INDEX; |
2152 | 69 } |
70 } | |
71 | |
3766 | 72 // Public |
73 | |
74 void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end, | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
75 uint max_length) { |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
76 assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0, |
3766 | 77 "bottom should be heap region aligned"); |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
78 assert((uintptr_t) end % HeapRegion::GrainBytes == 0, |
3766 | 79 "end should be heap region aligned"); |
80 | |
81 _length = 0; | |
82 _heap_bottom = bottom; | |
83 _heap_end = end; | |
84 _region_shift = HeapRegion::LogOfHRGrainBytes; | |
85 _next_search_index = 0; | |
86 _allocated_length = 0; | |
87 _max_length = max_length; | |
88 | |
6197 | 89 _regions = NEW_C_HEAP_ARRAY(HeapRegion*, max_length, mtGC); |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
90 memset(_regions, 0, (size_t) max_length * sizeof(HeapRegion*)); |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
91 _regions_biased = _regions - ((uintx) bottom >> _region_shift); |
3766 | 92 |
93 assert(&_regions[0] == &_regions_biased[addr_to_index_biased(bottom)], | |
94 "bottom should be included in the region with index 0"); | |
95 } | |
96 | |
97 MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, | |
98 HeapWord* new_end, | |
99 FreeRegionList* list) { | |
100 assert(old_end < new_end, "don't call it otherwise"); | |
101 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
102 | |
103 HeapWord* next_bottom = old_end; | |
104 assert(_heap_bottom <= next_bottom, "invariant"); | |
105 while (next_bottom < new_end) { | |
106 assert(next_bottom < _heap_end, "invariant"); | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
107 uint index = length(); |
2152 | 108 |
3766 | 109 assert(index < _max_length, "otherwise we cannot expand further"); |
110 if (index == 0) { | |
111 // We have not allocated any regions so far | |
112 assert(next_bottom == _heap_bottom, "invariant"); | |
113 } else { | |
114 // next_bottom should match the end of the last/previous region | |
115 assert(next_bottom == at(index - 1)->end(), "invariant"); | |
116 } | |
117 | |
118 if (index == _allocated_length) { | |
119 // We have to allocate a new HeapRegion. | |
120 HeapRegion* new_hr = g1h->new_heap_region(index, next_bottom); | |
121 if (new_hr == NULL) { | |
122 // allocation failed, we bail out and return what we have done so far | |
123 return MemRegion(old_end, next_bottom); | |
124 } | |
125 assert(_regions[index] == NULL, "invariant"); | |
126 _regions[index] = new_hr; | |
10242
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
127 increment_allocated_length(); |
3766 | 128 } |
129 // Have to increment the length first, otherwise we will get an | |
130 // assert failure at(index) below. | |
10242
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
131 increment_length(); |
3766 | 132 HeapRegion* hr = at(index); |
133 list->add_as_tail(hr); | |
134 | |
135 next_bottom = hr->end(); | |
2152 | 136 } |
3766 | 137 assert(next_bottom == new_end, "post-condition"); |
138 return MemRegion(old_end, next_bottom); | |
139 } | |
140 | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
141 uint HeapRegionSeq::free_suffix() { |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
142 uint res = 0; |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
143 uint index = length(); |
3766 | 144 while (index > 0) { |
145 index -= 1; | |
146 if (!at(index)->is_empty()) { | |
147 break; | |
148 } | |
149 res += 1; | |
2152 | 150 } |
342 | 151 return res; |
152 } | |
153 | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
154 uint HeapRegionSeq::find_contiguous(uint num) { |
3766 | 155 assert(num > 1, "use this only for sequences of length 2 or greater"); |
156 assert(_next_search_index <= length(), | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
157 err_msg("_next_search_index: %u should be valid and <= than %u", |
3766 | 158 _next_search_index, length())); |
159 | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
160 uint start = _next_search_index; |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
161 uint res = find_contiguous_from(start, num); |
3766 | 162 if (res == G1_NULL_HRS_INDEX && start > 0) { |
163 // Try starting from the beginning. If _next_search_index was 0, | |
164 // no point in doing this again. | |
165 res = find_contiguous_from(0, num); | |
166 } | |
167 if (res != G1_NULL_HRS_INDEX) { | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
168 assert(res < length(), err_msg("res: %u should be valid", res)); |
3766 | 169 _next_search_index = res + num; |
170 assert(_next_search_index <= length(), | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
171 err_msg("_next_search_index: %u should be valid and <= than %u", |
3766 | 172 _next_search_index, length())); |
173 } | |
174 return res; | |
342 | 175 } |
176 | |
3766 | 177 void HeapRegionSeq::iterate(HeapRegionClosure* blk) const { |
178 iterate_from((HeapRegion*) NULL, blk); | |
179 } | |
342 | 180 |
3766 | 181 void HeapRegionSeq::iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const { |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
182 uint hr_index = 0; |
3766 | 183 if (hr != NULL) { |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
184 hr_index = hr->hrs_index(); |
342 | 185 } |
3766 | 186 |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
187 uint len = length(); |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
188 for (uint i = hr_index; i < len; i += 1) { |
3766 | 189 bool res = blk->doHeapRegion(at(i)); |
342 | 190 if (res) { |
191 blk->incomplete(); | |
192 return; | |
193 } | |
194 } | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
195 for (uint i = 0; i < hr_index; i += 1) { |
3766 | 196 bool res = blk->doHeapRegion(at(i)); |
342 | 197 if (res) { |
198 blk->incomplete(); | |
199 return; | |
200 } | |
201 } | |
202 } | |
203 | |
10242
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
204 uint HeapRegionSeq::shrink_by(uint num_regions_to_remove) { |
2152 | 205 // Reset this in case it's currently pointing into the regions that |
206 // we just removed. | |
3766 | 207 _next_search_index = 0; |
2152 | 208 |
3766 | 209 assert(length() > 0, "the region sequence should not be empty"); |
210 assert(length() <= _allocated_length, "invariant"); | |
211 assert(_allocated_length > 0, "we should have at least one region committed"); | |
10242
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
212 assert(num_regions_to_remove < length(), "We should never remove all regions"); |
342 | 213 |
10242
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
214 uint i = 0; |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
215 for (; i < num_regions_to_remove; i++) { |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
216 HeapRegion* cur = at(length() - 1); |
3766 | 217 |
10242
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
218 if (!cur->is_empty()) { |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
219 // We have to give up if the region can not be moved |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
220 break; |
342 | 221 } |
10242
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
222 assert(!cur->isHumongous(), "Humongous regions should not be empty"); |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
223 |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
224 decrement_length(); |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
225 } |
b0d20fa374b4
8013872: G1: HeapRegionSeq::shrink_by() has invalid assert
brutisso
parents:
6197
diff
changeset
|
226 return i; |
342 | 227 } |
228 | |
3766 | 229 #ifndef PRODUCT |
230 void HeapRegionSeq::verify_optional() { | |
231 guarantee(_length <= _allocated_length, | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
232 err_msg("invariant: _length: %u _allocated_length: %u", |
3766 | 233 _length, _allocated_length)); |
234 guarantee(_allocated_length <= _max_length, | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
235 err_msg("invariant: _allocated_length: %u _max_length: %u", |
3766 | 236 _allocated_length, _max_length)); |
237 guarantee(_next_search_index <= _length, | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
238 err_msg("invariant: _next_search_index: %u _length: %u", |
3766 | 239 _next_search_index, _length)); |
240 | |
241 HeapWord* prev_end = _heap_bottom; | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
242 for (uint i = 0; i < _allocated_length; i += 1) { |
3766 | 243 HeapRegion* hr = _regions[i]; |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
244 guarantee(hr != NULL, err_msg("invariant: i: %u", i)); |
3766 | 245 guarantee(hr->bottom() == prev_end, |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
246 err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT, |
3766 | 247 i, HR_FORMAT_PARAMS(hr), prev_end)); |
248 guarantee(hr->hrs_index() == i, | |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
249 err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index())); |
3766 | 250 if (i < _length) { |
251 // Asserts will fire if i is >= _length | |
252 HeapWord* addr = hr->bottom(); | |
253 guarantee(addr_to_region(addr) == hr, "sanity"); | |
254 guarantee(addr_to_region_unsafe(addr) == hr, "sanity"); | |
255 } else { | |
256 guarantee(hr->is_empty(), "sanity"); | |
257 guarantee(!hr->isHumongous(), "sanity"); | |
258 // using assert instead of guarantee here since containing_set() | |
259 // is only available in non-product builds. | |
260 assert(hr->containing_set() == NULL, "sanity"); | |
261 } | |
262 if (hr->startsHumongous()) { | |
263 prev_end = hr->orig_end(); | |
264 } else { | |
265 prev_end = hr->end(); | |
266 } | |
342 | 267 } |
6010
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
268 for (uint i = _allocated_length; i < _max_length; i += 1) { |
720b6a76dd9d
7157073: G1: type change size_t -> uint for region counts / indexes
tonyp
parents:
3766
diff
changeset
|
269 guarantee(_regions[i] == NULL, err_msg("invariant i: %u", i)); |
3766 | 270 } |
342 | 271 } |
3766 | 272 #endif // PRODUCT |