40 _numa(heap->numa()), |
40 _numa(heap->numa()), |
41 _survivor_is_full(false), |
41 _survivor_is_full(false), |
42 _old_is_full(false), |
42 _old_is_full(false), |
43 _num_alloc_regions(_numa->num_active_nodes()), |
43 _num_alloc_regions(_numa->num_active_nodes()), |
44 _mutator_alloc_regions(NULL), |
44 _mutator_alloc_regions(NULL), |
45 _survivor_gc_alloc_region(heap->alloc_buffer_stats(G1HeapRegionAttr::Young)), |
45 _survivor_gc_alloc_regions(NULL), |
46 _old_gc_alloc_region(heap->alloc_buffer_stats(G1HeapRegionAttr::Old)), |
46 _old_gc_alloc_region(heap->alloc_buffer_stats(G1HeapRegionAttr::Old)), |
47 _retained_old_gc_alloc_region(NULL) { |
47 _retained_old_gc_alloc_region(NULL) { |
48 |
48 |
49 _mutator_alloc_regions = NEW_C_HEAP_ARRAY(MutatorAllocRegion, _num_alloc_regions, mtGC); |
49 _mutator_alloc_regions = NEW_C_HEAP_ARRAY(MutatorAllocRegion, _num_alloc_regions, mtGC); |
|
50 _survivor_gc_alloc_regions = NEW_C_HEAP_ARRAY(SurvivorGCAllocRegion, _num_alloc_regions, mtGC); |
|
51 G1EvacStats* stat = heap->alloc_buffer_stats(G1HeapRegionAttr::Young); |
|
52 |
50 for (uint i = 0; i < _num_alloc_regions; i++) { |
53 for (uint i = 0; i < _num_alloc_regions; i++) { |
51 ::new(_mutator_alloc_regions + i) MutatorAllocRegion(i); |
54 ::new(_mutator_alloc_regions + i) MutatorAllocRegion(i); |
|
55 ::new(_survivor_gc_alloc_regions + i) SurvivorGCAllocRegion(stat, i); |
52 } |
56 } |
53 } |
57 } |
54 |
58 |
55 G1Allocator::~G1Allocator() { |
59 G1Allocator::~G1Allocator() { |
56 for (uint i = 0; i < _num_alloc_regions; i++) { |
60 for (uint i = 0; i < _num_alloc_regions; i++) { |
57 _mutator_alloc_regions[i].~MutatorAllocRegion(); |
61 _mutator_alloc_regions[i].~MutatorAllocRegion(); |
|
62 _survivor_gc_alloc_regions[i].~SurvivorGCAllocRegion(); |
58 } |
63 } |
59 FREE_C_HEAP_ARRAY(MutatorAllocRegion, _mutator_alloc_regions); |
64 FREE_C_HEAP_ARRAY(MutatorAllocRegion, _mutator_alloc_regions); |
|
65 FREE_C_HEAP_ARRAY(SurvivorGCAllocRegion, _survivor_gc_alloc_regions); |
60 } |
66 } |
61 |
67 |
62 #ifdef ASSERT |
68 #ifdef ASSERT |
63 bool G1Allocator::has_mutator_alloc_region() { |
69 bool G1Allocator::has_mutator_alloc_region() { |
64 uint node_index = current_node_index(); |
70 uint node_index = current_node_index(); |
121 assert_at_safepoint_on_vm_thread(); |
127 assert_at_safepoint_on_vm_thread(); |
122 |
128 |
123 _survivor_is_full = false; |
129 _survivor_is_full = false; |
124 _old_is_full = false; |
130 _old_is_full = false; |
125 |
131 |
126 _survivor_gc_alloc_region.init(); |
132 for (uint i = 0; i < _num_alloc_regions; i++) { |
|
133 survivor_gc_alloc_region(i)->init(); |
|
134 } |
|
135 |
127 _old_gc_alloc_region.init(); |
136 _old_gc_alloc_region.init(); |
128 reuse_retained_old_region(evacuation_info, |
137 reuse_retained_old_region(evacuation_info, |
129 &_old_gc_alloc_region, |
138 &_old_gc_alloc_region, |
130 &_retained_old_gc_alloc_region); |
139 &_retained_old_gc_alloc_region); |
131 } |
140 } |
132 |
141 |
133 void G1Allocator::release_gc_alloc_regions(G1EvacuationInfo& evacuation_info) { |
142 void G1Allocator::release_gc_alloc_regions(G1EvacuationInfo& evacuation_info) { |
134 evacuation_info.set_allocation_regions(survivor_gc_alloc_region()->count() + |
143 uint survivor_region_count = 0; |
|
144 for (uint node_index = 0; node_index < _num_alloc_regions; node_index++) { |
|
145 survivor_region_count += survivor_gc_alloc_region(node_index)->count(); |
|
146 survivor_gc_alloc_region(node_index)->release(); |
|
147 } |
|
148 evacuation_info.set_allocation_regions(survivor_region_count + |
135 old_gc_alloc_region()->count()); |
149 old_gc_alloc_region()->count()); |
136 survivor_gc_alloc_region()->release(); |
150 |
137 // If we have an old GC alloc region to release, we'll save it in |
151 // If we have an old GC alloc region to release, we'll save it in |
138 // _retained_old_gc_alloc_region. If we don't |
152 // _retained_old_gc_alloc_region. If we don't |
139 // _retained_old_gc_alloc_region will become NULL. This is what we |
153 // _retained_old_gc_alloc_region will become NULL. This is what we |
140 // want either way so no reason to check explicitly for either |
154 // want either way so no reason to check explicitly for either |
141 // condition. |
155 // condition. |
142 _retained_old_gc_alloc_region = old_gc_alloc_region()->release(); |
156 _retained_old_gc_alloc_region = old_gc_alloc_region()->release(); |
143 } |
157 } |
144 |
158 |
145 void G1Allocator::abandon_gc_alloc_regions() { |
159 void G1Allocator::abandon_gc_alloc_regions() { |
146 assert(survivor_gc_alloc_region()->get() == NULL, "pre-condition"); |
160 for (uint i = 0; i < _num_alloc_regions; i++) { |
|
161 assert(survivor_gc_alloc_region(i)->get() == NULL, "pre-condition"); |
|
162 } |
147 assert(old_gc_alloc_region()->get() == NULL, "pre-condition"); |
163 assert(old_gc_alloc_region()->get() == NULL, "pre-condition"); |
148 _retained_old_gc_alloc_region = NULL; |
164 _retained_old_gc_alloc_region = NULL; |
149 } |
165 } |
150 |
166 |
151 bool G1Allocator::survivor_is_full() const { |
167 bool G1Allocator::survivor_is_full() const { |
191 return used; |
207 return used; |
192 } |
208 } |
193 |
209 |
194 |
210 |
195 HeapWord* G1Allocator::par_allocate_during_gc(G1HeapRegionAttr dest, |
211 HeapWord* G1Allocator::par_allocate_during_gc(G1HeapRegionAttr dest, |
196 size_t word_size) { |
212 size_t word_size, |
|
213 uint node_index) { |
197 size_t temp = 0; |
214 size_t temp = 0; |
198 HeapWord* result = par_allocate_during_gc(dest, word_size, word_size, &temp); |
215 HeapWord* result = par_allocate_during_gc(dest, word_size, word_size, &temp, node_index); |
199 assert(result == NULL || temp == word_size, |
216 assert(result == NULL || temp == word_size, |
200 "Requested " SIZE_FORMAT " words, but got " SIZE_FORMAT " at " PTR_FORMAT, |
217 "Requested " SIZE_FORMAT " words, but got " SIZE_FORMAT " at " PTR_FORMAT, |
201 word_size, temp, p2i(result)); |
218 word_size, temp, p2i(result)); |
202 return result; |
219 return result; |
203 } |
220 } |
204 |
221 |
205 HeapWord* G1Allocator::par_allocate_during_gc(G1HeapRegionAttr dest, |
222 HeapWord* G1Allocator::par_allocate_during_gc(G1HeapRegionAttr dest, |
206 size_t min_word_size, |
223 size_t min_word_size, |
207 size_t desired_word_size, |
224 size_t desired_word_size, |
208 size_t* actual_word_size) { |
225 size_t* actual_word_size, |
|
226 uint node_index) { |
209 switch (dest.type()) { |
227 switch (dest.type()) { |
210 case G1HeapRegionAttr::Young: |
228 case G1HeapRegionAttr::Young: |
211 return survivor_attempt_allocation(min_word_size, desired_word_size, actual_word_size); |
229 return survivor_attempt_allocation(min_word_size, desired_word_size, actual_word_size, node_index); |
212 case G1HeapRegionAttr::Old: |
230 case G1HeapRegionAttr::Old: |
213 return old_attempt_allocation(min_word_size, desired_word_size, actual_word_size); |
231 return old_attempt_allocation(min_word_size, desired_word_size, actual_word_size); |
214 default: |
232 default: |
215 ShouldNotReachHere(); |
233 ShouldNotReachHere(); |
216 return NULL; // Keep some compilers happy |
234 return NULL; // Keep some compilers happy |
217 } |
235 } |
218 } |
236 } |
219 |
237 |
220 HeapWord* G1Allocator::survivor_attempt_allocation(size_t min_word_size, |
238 HeapWord* G1Allocator::survivor_attempt_allocation(size_t min_word_size, |
221 size_t desired_word_size, |
239 size_t desired_word_size, |
222 size_t* actual_word_size) { |
240 size_t* actual_word_size, |
|
241 uint node_index) { |
223 assert(!_g1h->is_humongous(desired_word_size), |
242 assert(!_g1h->is_humongous(desired_word_size), |
224 "we should not be seeing humongous-size allocations in this path"); |
243 "we should not be seeing humongous-size allocations in this path"); |
225 |
244 |
226 HeapWord* result = survivor_gc_alloc_region()->attempt_allocation(min_word_size, |
245 HeapWord* result = survivor_gc_alloc_region(node_index)->attempt_allocation(min_word_size, |
227 desired_word_size, |
246 desired_word_size, |
228 actual_word_size); |
247 actual_word_size); |
229 if (result == NULL && !survivor_is_full()) { |
248 if (result == NULL && !survivor_is_full()) { |
230 MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag); |
249 MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag); |
231 result = survivor_gc_alloc_region()->attempt_allocation_locked(min_word_size, |
250 result = survivor_gc_alloc_region(node_index)->attempt_allocation_locked(min_word_size, |
232 desired_word_size, |
251 desired_word_size, |
233 actual_word_size); |
252 actual_word_size); |
234 if (result == NULL) { |
253 if (result == NULL) { |
235 set_survivor_full(); |
254 set_survivor_full(); |
236 } |
255 } |
237 } |
256 } |
238 if (result != NULL) { |
257 if (result != NULL) { |
275 } |
294 } |
276 |
295 |
277 G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) : |
296 G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) : |
278 _g1h(G1CollectedHeap::heap()), |
297 _g1h(G1CollectedHeap::heap()), |
279 _allocator(allocator), |
298 _allocator(allocator), |
280 _surviving_alloc_buffer(_g1h->desired_plab_sz(G1HeapRegionAttr::Young)), |
|
281 _tenured_alloc_buffer(_g1h->desired_plab_sz(G1HeapRegionAttr::Old)), |
|
282 _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { |
299 _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { |
283 for (uint state = 0; state < G1HeapRegionAttr::Num; state++) { |
300 for (region_type_t state = 0; state < G1HeapRegionAttr::Num; state++) { |
284 _direct_allocated[state] = 0; |
301 _direct_allocated[state] = 0; |
285 _alloc_buffers[state] = NULL; |
302 uint length = alloc_buffers_length(state); |
286 } |
303 _alloc_buffers[state] = NEW_C_HEAP_ARRAY(PLAB*, length, mtGC); |
287 _alloc_buffers[G1HeapRegionAttr::Young] = &_surviving_alloc_buffer; |
304 for (uint node_index = 0; node_index < length; node_index++) { |
288 _alloc_buffers[G1HeapRegionAttr::Old] = &_tenured_alloc_buffer; |
305 _alloc_buffers[state][node_index] = new PLAB(_g1h->desired_plab_sz(state)); |
|
306 } |
|
307 } |
|
308 } |
|
309 |
|
310 G1PLABAllocator::~G1PLABAllocator() { |
|
311 for (region_type_t state = 0; state < G1HeapRegionAttr::Num; state++) { |
|
312 uint length = alloc_buffers_length(state); |
|
313 for (uint node_index = 0; node_index < length; node_index++) { |
|
314 delete _alloc_buffers[state][node_index]; |
|
315 } |
|
316 FREE_C_HEAP_ARRAY(PLAB*, _alloc_buffers[state]); |
|
317 } |
289 } |
318 } |
290 |
319 |
291 bool G1PLABAllocator::may_throw_away_buffer(size_t const allocation_word_sz, size_t const buffer_size) const { |
320 bool G1PLABAllocator::may_throw_away_buffer(size_t const allocation_word_sz, size_t const buffer_size) const { |
292 return (allocation_word_sz * 100 < buffer_size * ParallelGCBufferWastePct); |
321 return (allocation_word_sz * 100 < buffer_size * ParallelGCBufferWastePct); |
293 } |
322 } |
294 |
323 |
295 HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest, |
324 HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest, |
296 size_t word_sz, |
325 size_t word_sz, |
297 bool* plab_refill_failed) { |
326 bool* plab_refill_failed, |
|
327 uint node_index) { |
298 size_t plab_word_size = _g1h->desired_plab_sz(dest); |
328 size_t plab_word_size = _g1h->desired_plab_sz(dest); |
299 size_t required_in_plab = PLAB::size_required_for_allocation(word_sz); |
329 size_t required_in_plab = PLAB::size_required_for_allocation(word_sz); |
300 |
330 |
301 // Only get a new PLAB if the allocation fits and it would not waste more than |
331 // Only get a new PLAB if the allocation fits and it would not waste more than |
302 // ParallelGCBufferWastePct in the existing buffer. |
332 // ParallelGCBufferWastePct in the existing buffer. |
303 if ((required_in_plab <= plab_word_size) && |
333 if ((required_in_plab <= plab_word_size) && |
304 may_throw_away_buffer(required_in_plab, plab_word_size)) { |
334 may_throw_away_buffer(required_in_plab, plab_word_size)) { |
305 |
335 |
306 PLAB* alloc_buf = alloc_buffer(dest); |
336 PLAB* alloc_buf = alloc_buffer(dest, node_index); |
307 alloc_buf->retire(); |
337 alloc_buf->retire(); |
308 |
338 |
309 size_t actual_plab_size = 0; |
339 size_t actual_plab_size = 0; |
310 HeapWord* buf = _allocator->par_allocate_during_gc(dest, |
340 HeapWord* buf = _allocator->par_allocate_during_gc(dest, |
311 required_in_plab, |
341 required_in_plab, |
312 plab_word_size, |
342 plab_word_size, |
313 &actual_plab_size); |
343 &actual_plab_size, |
|
344 node_index); |
314 |
345 |
315 assert(buf == NULL || ((actual_plab_size >= required_in_plab) && (actual_plab_size <= plab_word_size)), |
346 assert(buf == NULL || ((actual_plab_size >= required_in_plab) && (actual_plab_size <= plab_word_size)), |
316 "Requested at minimum " SIZE_FORMAT ", desired " SIZE_FORMAT " words, but got " SIZE_FORMAT " at " PTR_FORMAT, |
347 "Requested at minimum " SIZE_FORMAT ", desired " SIZE_FORMAT " words, but got " SIZE_FORMAT " at " PTR_FORMAT, |
317 required_in_plab, plab_word_size, actual_plab_size, p2i(buf)); |
348 required_in_plab, plab_word_size, actual_plab_size, p2i(buf)); |
318 |
349 |
327 } |
358 } |
328 // Otherwise. |
359 // Otherwise. |
329 *plab_refill_failed = true; |
360 *plab_refill_failed = true; |
330 } |
361 } |
331 // Try direct allocation. |
362 // Try direct allocation. |
332 HeapWord* result = _allocator->par_allocate_during_gc(dest, word_sz); |
363 HeapWord* result = _allocator->par_allocate_during_gc(dest, word_sz, node_index); |
333 if (result != NULL) { |
364 if (result != NULL) { |
334 _direct_allocated[dest.type()] += word_sz; |
365 _direct_allocated[dest.type()] += word_sz; |
335 } |
366 } |
336 return result; |
367 return result; |
337 } |
368 } |
338 |
369 |
339 void G1PLABAllocator::undo_allocation(G1HeapRegionAttr dest, HeapWord* obj, size_t word_sz) { |
370 void G1PLABAllocator::undo_allocation(G1HeapRegionAttr dest, HeapWord* obj, size_t word_sz, uint node_index) { |
340 alloc_buffer(dest)->undo_allocation(obj, word_sz); |
371 alloc_buffer(dest, node_index)->undo_allocation(obj, word_sz); |
341 } |
372 } |
342 |
373 |
343 void G1PLABAllocator::flush_and_retire_stats() { |
374 void G1PLABAllocator::flush_and_retire_stats() { |
344 for (uint state = 0; state < G1HeapRegionAttr::Num; state++) { |
375 for (region_type_t state = 0; state < G1HeapRegionAttr::Num; state++) { |
345 PLAB* const buf = _alloc_buffers[state]; |
376 G1EvacStats* stats = _g1h->alloc_buffer_stats(state); |
346 if (buf != NULL) { |
377 for (uint node_index = 0; node_index < alloc_buffers_length(state); node_index++) { |
347 G1EvacStats* stats = _g1h->alloc_buffer_stats(state); |
378 PLAB* const buf = alloc_buffer(state, node_index); |
348 buf->flush_and_retire_stats(stats); |
379 if (buf != NULL) { |
349 stats->add_direct_allocated(_direct_allocated[state]); |
380 buf->flush_and_retire_stats(stats); |
350 _direct_allocated[state] = 0; |
381 } |
351 } |
382 } |
|
383 stats->add_direct_allocated(_direct_allocated[state]); |
|
384 _direct_allocated[state] = 0; |
352 } |
385 } |
353 } |
386 } |
354 |
387 |
355 size_t G1PLABAllocator::waste() const { |
388 size_t G1PLABAllocator::waste() const { |
356 size_t result = 0; |
389 size_t result = 0; |
357 for (uint state = 0; state < G1HeapRegionAttr::Num; state++) { |
390 for (region_type_t state = 0; state < G1HeapRegionAttr::Num; state++) { |
358 PLAB * const buf = _alloc_buffers[state]; |
391 for (uint node_index = 0; node_index < alloc_buffers_length(state); node_index++) { |
359 if (buf != NULL) { |
392 PLAB* const buf = alloc_buffer(state, node_index); |
360 result += buf->waste(); |
393 if (buf != NULL) { |
|
394 result += buf->waste(); |
|
395 } |
361 } |
396 } |
362 } |
397 } |
363 return result; |
398 return result; |
364 } |
399 } |
365 |
400 |
366 size_t G1PLABAllocator::undo_waste() const { |
401 size_t G1PLABAllocator::undo_waste() const { |
367 size_t result = 0; |
402 size_t result = 0; |
368 for (uint state = 0; state < G1HeapRegionAttr::Num; state++) { |
403 for (region_type_t state = 0; state < G1HeapRegionAttr::Num; state++) { |
369 PLAB * const buf = _alloc_buffers[state]; |
404 for (uint node_index = 0; node_index < alloc_buffers_length(state); node_index++) { |
370 if (buf != NULL) { |
405 PLAB* const buf = alloc_buffer(state, node_index); |
371 result += buf->undo_waste(); |
406 if (buf != NULL) { |
|
407 result += buf->undo_waste(); |
|
408 } |
372 } |
409 } |
373 } |
410 } |
374 return result; |
411 return result; |
375 } |
412 } |
376 |
413 |