Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp @ 20404:227a9e5e4b4a
8057536: Refactor G1 to allow context specific allocations
Summary: Splitting out a g1 allocator class to simply specialized allocators which can associate each allocation with a given context.
Reviewed-by: mgerdin, brutisso
author | sjohanss |
---|---|
date | Fri, 05 Sep 2014 09:49:19 +0200 |
parents | ee019285a52c |
children |
comparison
equal
deleted
inserted
replaced
20403:8ec8971f511a | 20404:227a9e5e4b4a |
---|---|
36 _dcq(&g1h->dirty_card_queue_set()), | 36 _dcq(&g1h->dirty_card_queue_set()), |
37 _ct_bs(g1h->g1_barrier_set()), | 37 _ct_bs(g1h->g1_barrier_set()), |
38 _g1_rem(g1h->g1_rem_set()), | 38 _g1_rem(g1h->g1_rem_set()), |
39 _hash_seed(17), _queue_num(queue_num), | 39 _hash_seed(17), _queue_num(queue_num), |
40 _term_attempts(0), | 40 _term_attempts(0), |
41 _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)), | |
42 _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)), | |
43 _age_table(false), _scanner(g1h, rp), | 41 _age_table(false), _scanner(g1h, rp), |
44 _strong_roots_time(0), _term_time(0), | 42 _strong_roots_time(0), _term_time(0) { |
45 _alloc_buffer_waste(0), _undo_waste(0) { | |
46 _scanner.set_par_scan_thread_state(this); | 43 _scanner.set_par_scan_thread_state(this); |
47 // we allocate G1YoungSurvRateNumRegions plus one entries, since | 44 // we allocate G1YoungSurvRateNumRegions plus one entries, since |
48 // we "sacrifice" entry 0 to keep track of surviving bytes for | 45 // we "sacrifice" entry 0 to keep track of surviving bytes for |
49 // non-young regions (where the age is -1) | 46 // non-young regions (where the age is -1) |
50 // We also add a few elements at the beginning and at the end in | 47 // We also add a few elements at the beginning and at the end in |
58 vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR, | 55 vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR, |
59 "Not enough space for young surv histo."); | 56 "Not enough space for young surv histo."); |
60 _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; | 57 _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; |
61 memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t)); | 58 memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t)); |
62 | 59 |
63 _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer; | 60 _g1_par_allocator = G1ParGCAllocator::create_allocator(_g1h); |
64 _alloc_buffers[GCAllocForTenured] = &_tenured_alloc_buffer; | |
65 | 61 |
66 _start = os::elapsedTime(); | 62 _start = os::elapsedTime(); |
67 } | 63 } |
68 | 64 |
69 G1ParScanThreadState::~G1ParScanThreadState() { | 65 G1ParScanThreadState::~G1ParScanThreadState() { |
70 retire_alloc_buffers(); | 66 _g1_par_allocator->retire_alloc_buffers(); |
67 delete _g1_par_allocator; | |
71 FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC); | 68 FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC); |
72 } | 69 } |
73 | 70 |
74 void | 71 void |
75 G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) | 72 G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) |
88 outputStream* const st) const | 85 outputStream* const st) const |
89 { | 86 { |
90 const double elapsed_ms = elapsed_time() * 1000.0; | 87 const double elapsed_ms = elapsed_time() * 1000.0; |
91 const double s_roots_ms = strong_roots_time() * 1000.0; | 88 const double s_roots_ms = strong_roots_time() * 1000.0; |
92 const double term_ms = term_time() * 1000.0; | 89 const double term_ms = term_time() * 1000.0; |
90 const size_t alloc_buffer_waste = _g1_par_allocator->alloc_buffer_waste(); | |
91 const size_t undo_waste = _g1_par_allocator->undo_waste(); | |
93 st->print_cr("%3d %9.2f %9.2f %6.2f " | 92 st->print_cr("%3d %9.2f %9.2f %6.2f " |
94 "%9.2f %6.2f " SIZE_FORMAT_W(8) " " | 93 "%9.2f %6.2f " SIZE_FORMAT_W(8) " " |
95 SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7), | 94 SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7), |
96 i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, | 95 i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, |
97 term_ms, term_ms * 100 / elapsed_ms, term_attempts(), | 96 term_ms, term_ms * 100 / elapsed_ms, term_attempts(), |
98 (alloc_buffer_waste() + undo_waste()) * HeapWordSize / K, | 97 (alloc_buffer_waste + undo_waste) * HeapWordSize / K, |
99 alloc_buffer_waste() * HeapWordSize / K, | 98 alloc_buffer_waste * HeapWordSize / K, |
100 undo_waste() * HeapWordSize / K); | 99 undo_waste * HeapWordSize / K); |
101 } | 100 } |
102 | 101 |
103 #ifdef ASSERT | 102 #ifdef ASSERT |
104 bool G1ParScanThreadState::verify_ref(narrowOop* ref) const { | 103 bool G1ParScanThreadState::verify_ref(narrowOop* ref) const { |
105 assert(ref != NULL, "invariant"); | 104 assert(ref != NULL, "invariant"); |
162 markOop m = old->mark(); | 161 markOop m = old->mark(); |
163 int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() | 162 int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() |
164 : m->age(); | 163 : m->age(); |
165 GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, | 164 GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, |
166 word_sz); | 165 word_sz); |
167 HeapWord* obj_ptr = allocate(alloc_purpose, word_sz); | 166 AllocationContext_t context = from_region->allocation_context(); |
167 HeapWord* obj_ptr = _g1_par_allocator->allocate(alloc_purpose, word_sz, context); | |
168 #ifndef PRODUCT | 168 #ifndef PRODUCT |
169 // Should this evacuation fail? | 169 // Should this evacuation fail? |
170 if (_g1h->evacuation_should_fail()) { | 170 if (_g1h->evacuation_should_fail()) { |
171 if (obj_ptr != NULL) { | 171 if (obj_ptr != NULL) { |
172 undo_allocation(alloc_purpose, obj_ptr, word_sz); | 172 _g1_par_allocator->undo_allocation(alloc_purpose, obj_ptr, word_sz, context); |
173 obj_ptr = NULL; | 173 obj_ptr = NULL; |
174 } | 174 } |
175 } | 175 } |
176 #endif // !PRODUCT | 176 #endif // !PRODUCT |
177 | 177 |
244 // given that we know obj is in the heap. | 244 // given that we know obj is in the heap. |
245 _scanner.set_region(_g1h->heap_region_containing_raw(obj)); | 245 _scanner.set_region(_g1h->heap_region_containing_raw(obj)); |
246 obj->oop_iterate_backwards(&_scanner); | 246 obj->oop_iterate_backwards(&_scanner); |
247 } | 247 } |
248 } else { | 248 } else { |
249 undo_allocation(alloc_purpose, obj_ptr, word_sz); | 249 _g1_par_allocator->undo_allocation(alloc_purpose, obj_ptr, word_sz, context); |
250 obj = forward_ptr; | 250 obj = forward_ptr; |
251 } | 251 } |
252 return obj; | 252 return obj; |
253 } | 253 } |
254 | |
255 HeapWord* G1ParScanThreadState::allocate_slow(GCAllocPurpose purpose, size_t word_sz) { | |
256 HeapWord* obj = NULL; | |
257 size_t gclab_word_size = _g1h->desired_plab_sz(purpose); | |
258 if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) { | |
259 G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose); | |
260 add_to_alloc_buffer_waste(alloc_buf->words_remaining()); | |
261 alloc_buf->retire(false /* end_of_gc */, false /* retain */); | |
262 | |
263 HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size); | |
264 if (buf == NULL) { | |
265 return NULL; // Let caller handle allocation failure. | |
266 } | |
267 // Otherwise. | |
268 alloc_buf->set_word_size(gclab_word_size); | |
269 alloc_buf->set_buf(buf); | |
270 | |
271 obj = alloc_buf->allocate(word_sz); | |
272 assert(obj != NULL, "buffer was definitely big enough..."); | |
273 } else { | |
274 obj = _g1h->par_allocate_during_gc(purpose, word_sz); | |
275 } | |
276 return obj; | |
277 } | |
278 | |
279 void G1ParScanThreadState::undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) { | |
280 if (alloc_buffer(purpose)->contains(obj)) { | |
281 assert(alloc_buffer(purpose)->contains(obj + word_sz - 1), | |
282 "should contain whole object"); | |
283 alloc_buffer(purpose)->undo_allocation(obj, word_sz); | |
284 } else { | |
285 CollectedHeap::fill_with_object(obj, word_sz); | |
286 add_to_undo_waste(word_sz); | |
287 } | |
288 } | |
289 | |
290 HeapWord* G1ParScanThreadState::allocate(GCAllocPurpose purpose, size_t word_sz) { | |
291 HeapWord* obj = NULL; | |
292 if (purpose == GCAllocForSurvived) { | |
293 obj = alloc_buffer(GCAllocForSurvived)->allocate_aligned(word_sz, SurvivorAlignmentInBytes); | |
294 } else { | |
295 obj = alloc_buffer(GCAllocForTenured)->allocate(word_sz); | |
296 } | |
297 if (obj != NULL) { | |
298 return obj; | |
299 } | |
300 return allocate_slow(purpose, word_sz); | |
301 } | |
302 | |
303 void G1ParScanThreadState::retire_alloc_buffers() { | |
304 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { | |
305 size_t waste = _alloc_buffers[ap]->words_remaining(); | |
306 add_to_alloc_buffer_waste(waste); | |
307 _alloc_buffers[ap]->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap), | |
308 true /* end_of_gc */, | |
309 false /* retain */); | |
310 } | |
311 } |