Mercurial > hg > graal-compiler
comparison src/share/vm/gc_implementation/g1/heapRegionSeq.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 | 2250ee17e258 |
children | a672e43650cc |
comparison
equal
deleted
inserted
replaced
2151:cb913d743d09 | 2152:0fa27f37d4d4 |
---|---|
63 _seq_bottom(NULL) | 63 _seq_bottom(NULL) |
64 {} | 64 {} |
65 | 65 |
66 // Private methods. | 66 // Private methods. |
67 | 67 |
68 HeapWord* | |
69 HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) { | |
70 assert(G1CollectedHeap::isHumongous(word_size), | |
71 "Allocation size should be humongous"); | |
72 int cur = ind; | |
73 int first = cur; | |
74 size_t sumSizes = 0; | |
75 while (cur < _regions.length() && sumSizes < word_size) { | |
76 // Loop invariant: | |
77 // For all i in [first, cur): | |
78 // _regions.at(i)->is_empty() | |
79 // && _regions.at(i) is contiguous with its predecessor, if any | |
80 // && sumSizes is the sum of the sizes of the regions in the interval | |
81 // [first, cur) | |
82 HeapRegion* curhr = _regions.at(cur); | |
83 if (curhr->is_empty() | |
84 && (first == cur | |
85 || (_regions.at(cur-1)->end() == | |
86 curhr->bottom()))) { | |
87 sumSizes += curhr->capacity() / HeapWordSize; | |
88 } else { | |
89 first = cur + 1; | |
90 sumSizes = 0; | |
91 } | |
92 cur++; | |
93 } | |
94 if (sumSizes >= word_size) { | |
95 _alloc_search_start = cur; | |
96 | |
97 // We need to initialize the region(s) we just discovered. This is | |
98 // a bit tricky given that it can happen concurrently with | |
99 // refinement threads refining cards on these regions and | |
100 // potentially wanting to refine the BOT as they are scanning | |
101 // those cards (this can happen shortly after a cleanup; see CR | |
102 // 6991377). So we have to set up the region(s) carefully and in | |
103 // a specific order. | |
104 | |
105 // Currently, allocs_are_zero_filled() returns false. The zero | |
106 // filling infrastructure will be going away soon (see CR 6977804). | |
107 // So no need to do anything else here. | |
108 bool zf = G1CollectedHeap::heap()->allocs_are_zero_filled(); | |
109 assert(!zf, "not supported"); | |
110 | |
111 // This will be the "starts humongous" region. | |
112 HeapRegion* first_hr = _regions.at(first); | |
113 { | |
114 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
115 first_hr->set_zero_fill_allocated(); | |
116 } | |
117 // The header of the new object will be placed at the bottom of | |
118 // the first region. | |
119 HeapWord* new_obj = first_hr->bottom(); | |
120 // This will be the new end of the first region in the series that | |
121 // should also match the end of the last region in the seriers. | |
122 // (Note: sumSizes = "region size" x "number of regions we found"). | |
123 HeapWord* new_end = new_obj + sumSizes; | |
124 // This will be the new top of the first region that will reflect | |
125 // this allocation. | |
126 HeapWord* new_top = new_obj + word_size; | |
127 | |
128 // First, we need to zero the header of the space that we will be | |
129 // allocating. When we update top further down, some refinement | |
130 // threads might try to scan the region. By zeroing the header we | |
131 // ensure that any thread that will try to scan the region will | |
132 // come across the zero klass word and bail out. | |
133 // | |
134 // NOTE: It would not have been correct to have used | |
135 // CollectedHeap::fill_with_object() and make the space look like | |
136 // an int array. The thread that is doing the allocation will | |
137 // later update the object header to a potentially different array | |
138 // type and, for a very short period of time, the klass and length | |
139 // fields will be inconsistent. This could cause a refinement | |
140 // thread to calculate the object size incorrectly. | |
141 Copy::fill_to_words(new_obj, oopDesc::header_size(), 0); | |
142 | |
143 // We will set up the first region as "starts humongous". This | |
144 // will also update the BOT covering all the regions to reflect | |
145 // that there is a single object that starts at the bottom of the | |
146 // first region. | |
147 first_hr->set_startsHumongous(new_top, new_end); | |
148 | |
149 // Then, if there are any, we will set up the "continues | |
150 // humongous" regions. | |
151 HeapRegion* hr = NULL; | |
152 for (int i = first + 1; i < cur; ++i) { | |
153 hr = _regions.at(i); | |
154 { | |
155 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
156 hr->set_zero_fill_allocated(); | |
157 } | |
158 hr->set_continuesHumongous(first_hr); | |
159 } | |
160 // If we have "continues humongous" regions (hr != NULL), then the | |
161 // end of the last one should match new_end. | |
162 assert(hr == NULL || hr->end() == new_end, "sanity"); | |
163 | |
164 // Up to this point no concurrent thread would have been able to | |
165 // do any scanning on any region in this series. All the top | |
166 // fields still point to bottom, so the intersection between | |
167 // [bottom,top] and [card_start,card_end] will be empty. Before we | |
168 // update the top fields, we'll do a storestore to make sure that | |
169 // no thread sees the update to top before the zeroing of the | |
170 // object header and the BOT initialization. | |
171 OrderAccess::storestore(); | |
172 | |
173 // Now that the BOT and the object header have been initialized, | |
174 // we can update top of the "starts humongous" region. | |
175 assert(first_hr->bottom() < new_top && new_top <= first_hr->end(), | |
176 "new_top should be in this region"); | |
177 first_hr->set_top(new_top); | |
178 | |
179 // Now, we will update the top fields of the "continues humongous" | |
180 // regions. The reason we need to do this is that, otherwise, | |
181 // these regions would look empty and this will confuse parts of | |
182 // G1. For example, the code that looks for a consecutive number | |
183 // of empty regions will consider them empty and try to | |
184 // re-allocate them. We can extend is_empty() to also include | |
185 // !continuesHumongous(), but it is easier to just update the top | |
186 // fields here. | |
187 hr = NULL; | |
188 for (int i = first + 1; i < cur; ++i) { | |
189 hr = _regions.at(i); | |
190 if ((i + 1) == cur) { | |
191 // last continues humongous region | |
192 assert(hr->bottom() < new_top && new_top <= hr->end(), | |
193 "new_top should fall on this region"); | |
194 hr->set_top(new_top); | |
195 } else { | |
196 // not last one | |
197 assert(new_top > hr->end(), "new_top should be above this region"); | |
198 hr->set_top(hr->end()); | |
199 } | |
200 } | |
201 // If we have continues humongous regions (hr != NULL), then the | |
202 // end of the last one should match new_end and its top should | |
203 // match new_top. | |
204 assert(hr == NULL || | |
205 (hr->end() == new_end && hr->top() == new_top), "sanity"); | |
206 | |
207 return new_obj; | |
208 } else { | |
209 // If we started from the beginning, we want to know why we can't alloc. | |
210 return NULL; | |
211 } | |
212 } | |
213 | |
214 void HeapRegionSeq::print_empty_runs() { | 68 void HeapRegionSeq::print_empty_runs() { |
215 int empty_run = 0; | 69 int empty_run = 0; |
216 int n_empty = 0; | 70 int n_empty = 0; |
217 int empty_run_start; | 71 int empty_run_start; |
218 for (int i = 0; i < _regions.length(); i++) { | 72 for (int i = 0; i < _regions.length(); i++) { |
282 cur--; | 136 cur--; |
283 } | 137 } |
284 return res; | 138 return res; |
285 } | 139 } |
286 | 140 |
287 HeapWord* HeapRegionSeq::obj_allocate(size_t word_size) { | 141 int HeapRegionSeq::find_contiguous_from(int from, size_t num) { |
288 int cur = _alloc_search_start; | 142 assert(num > 1, "pre-condition"); |
289 // Make sure "cur" is a valid index. | 143 assert(0 <= from && from <= _regions.length(), |
290 assert(cur >= 0, "Invariant."); | 144 err_msg("from: %d should be valid and <= than %d", |
291 HeapWord* res = alloc_obj_from_region_index(cur, word_size); | 145 from, _regions.length())); |
292 if (res == NULL) | 146 |
293 res = alloc_obj_from_region_index(0, word_size); | 147 int curr = from; |
148 int first = -1; | |
149 size_t num_so_far = 0; | |
150 while (curr < _regions.length() && num_so_far < num) { | |
151 HeapRegion* curr_hr = _regions.at(curr); | |
152 if (curr_hr->is_empty()) { | |
153 if (first == -1) { | |
154 first = curr; | |
155 num_so_far = 1; | |
156 } else { | |
157 num_so_far += 1; | |
158 } | |
159 } else { | |
160 first = -1; | |
161 num_so_far = 0; | |
162 } | |
163 curr += 1; | |
164 } | |
165 | |
166 assert(num_so_far <= num, "post-condition"); | |
167 if (num_so_far == num) { | |
168 // we find enough space for the humongous object | |
169 assert(from <= first && first < _regions.length(), "post-condition"); | |
170 assert(first < curr && (curr - first) == (int) num, "post-condition"); | |
171 for (int i = first; i < first + (int) num; ++i) { | |
172 assert(_regions.at(i)->is_empty(), "post-condition"); | |
173 } | |
174 return first; | |
175 } else { | |
176 // we failed to find enough space for the humongous object | |
177 return -1; | |
178 } | |
179 } | |
180 | |
181 int HeapRegionSeq::find_contiguous(size_t num) { | |
182 assert(num > 1, "otherwise we should not be calling this"); | |
183 assert(0 <= _alloc_search_start && _alloc_search_start <= _regions.length(), | |
184 err_msg("_alloc_search_start: %d should be valid and <= than %d", | |
185 _alloc_search_start, _regions.length())); | |
186 | |
187 int start = _alloc_search_start; | |
188 int res = find_contiguous_from(start, num); | |
189 if (res == -1 && start != 0) { | |
190 // Try starting from the beginning. If _alloc_search_start was 0, | |
191 // no point in doing this again. | |
192 res = find_contiguous_from(0, num); | |
193 } | |
194 if (res != -1) { | |
195 assert(0 <= res && res < _regions.length(), | |
196 err_msg("res: %d should be valid", res)); | |
197 _alloc_search_start = res + (int) num; | |
198 } | |
199 assert(0 < _alloc_search_start && _alloc_search_start <= _regions.length(), | |
200 err_msg("_alloc_search_start: %d should be valid", | |
201 _alloc_search_start)); | |
294 return res; | 202 return res; |
295 } | 203 } |
296 | 204 |
297 void HeapRegionSeq::iterate(HeapRegionClosure* blk) { | 205 void HeapRegionSeq::iterate(HeapRegionClosure* blk) { |
298 iterate_from((HeapRegion*)NULL, blk); | 206 iterate_from((HeapRegion*)NULL, blk); |
374 } | 282 } |
375 } | 283 } |
376 | 284 |
377 MemRegion HeapRegionSeq::shrink_by(size_t shrink_bytes, | 285 MemRegion HeapRegionSeq::shrink_by(size_t shrink_bytes, |
378 size_t& num_regions_deleted) { | 286 size_t& num_regions_deleted) { |
287 // Reset this in case it's currently pointing into the regions that | |
288 // we just removed. | |
289 _alloc_search_start = 0; | |
290 | |
379 assert(shrink_bytes % os::vm_page_size() == 0, "unaligned"); | 291 assert(shrink_bytes % os::vm_page_size() == 0, "unaligned"); |
380 assert(shrink_bytes % HeapRegion::GrainBytes == 0, "unaligned"); | 292 assert(shrink_bytes % HeapRegion::GrainBytes == 0, "unaligned"); |
381 | 293 |
382 if (_regions.length() == 0) { | 294 if (_regions.length() == 0) { |
383 num_regions_deleted = 0; | 295 num_regions_deleted = 0; |
393 if (cur->isHumongous()) { | 305 if (cur->isHumongous()) { |
394 return MemRegion(last_start, end); | 306 return MemRegion(last_start, end); |
395 } | 307 } |
396 assert(cur == _regions.top(), "Should be top"); | 308 assert(cur == _regions.top(), "Should be top"); |
397 if (!cur->is_empty()) break; | 309 if (!cur->is_empty()) break; |
398 cur->reset_zero_fill(); | |
399 shrink_bytes -= cur->capacity(); | 310 shrink_bytes -= cur->capacity(); |
400 num_regions_deleted++; | 311 num_regions_deleted++; |
401 _regions.pop(); | 312 _regions.pop(); |
402 last_start = cur->bottom(); | 313 last_start = cur->bottom(); |
403 // We need to delete these somehow, but can't currently do so here: if | 314 // We need to delete these somehow, but can't currently do so here: if |
408 j--; | 319 j--; |
409 } | 320 } |
410 return MemRegion(last_start, end); | 321 return MemRegion(last_start, end); |
411 } | 322 } |
412 | 323 |
413 | |
414 class PrintHeapRegionClosure : public HeapRegionClosure { | 324 class PrintHeapRegionClosure : public HeapRegionClosure { |
415 public: | 325 public: |
416 bool doHeapRegion(HeapRegion* r) { | 326 bool doHeapRegion(HeapRegion* r) { |
417 gclog_or_tty->print(PTR_FORMAT ":", r); | 327 gclog_or_tty->print(PTR_FORMAT ":", r); |
418 r->print(); | 328 r->print(); |