Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @ 1836:894b1d7c7e01
6423256: GC stacks should use a better data structure
6942771: SEGV in ParScanThreadState::take_from_overflow_stack
Reviewed-by: apetrusenko, ysr, pbk
author | jcoomes |
---|---|
date | Tue, 28 Sep 2010 15:56:15 -0700 |
parents | 8b10f48633dc |
children | a7214d79fcf1 |
comparison
equal
deleted
inserted
replaced
1835:4805b9f4779e | 1836:894b1d7c7e01 |
---|---|
32 ParScanThreadState::ParScanThreadState(Space* to_space_, | 32 ParScanThreadState::ParScanThreadState(Space* to_space_, |
33 ParNewGeneration* gen_, | 33 ParNewGeneration* gen_, |
34 Generation* old_gen_, | 34 Generation* old_gen_, |
35 int thread_num_, | 35 int thread_num_, |
36 ObjToScanQueueSet* work_queue_set_, | 36 ObjToScanQueueSet* work_queue_set_, |
37 GrowableArray<oop>** overflow_stack_set_, | 37 Stack<oop>* overflow_stacks_, |
38 size_t desired_plab_sz_, | 38 size_t desired_plab_sz_, |
39 ParallelTaskTerminator& term_) : | 39 ParallelTaskTerminator& term_) : |
40 _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_), | 40 _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_), |
41 _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false), | 41 _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false), |
42 _overflow_stack(overflow_stack_set_[thread_num_]), | 42 _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL), |
43 _ageTable(false), // false ==> not the global age table, no perf data. | 43 _ageTable(false), // false ==> not the global age table, no perf data. |
44 _to_space_alloc_buffer(desired_plab_sz_), | 44 _to_space_alloc_buffer(desired_plab_sz_), |
45 _to_space_closure(gen_, this), _old_gen_closure(gen_, this), | 45 _to_space_closure(gen_, this), _old_gen_closure(gen_, this), |
46 _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this), | 46 _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this), |
47 _older_gen_closure(gen_, this), | 47 _older_gen_closure(gen_, this), |
157 | 157 |
158 bool ParScanThreadState::take_from_overflow_stack() { | 158 bool ParScanThreadState::take_from_overflow_stack() { |
159 assert(ParGCUseLocalOverflow, "Else should not call"); | 159 assert(ParGCUseLocalOverflow, "Else should not call"); |
160 assert(young_gen()->overflow_list() == NULL, "Error"); | 160 assert(young_gen()->overflow_list() == NULL, "Error"); |
161 ObjToScanQueue* queue = work_queue(); | 161 ObjToScanQueue* queue = work_queue(); |
162 GrowableArray<oop>* of_stack = overflow_stack(); | 162 Stack<oop>* const of_stack = overflow_stack(); |
163 uint num_overflow_elems = of_stack->length(); | 163 const size_t num_overflow_elems = of_stack->size(); |
164 uint num_take_elems = MIN2(MIN2((queue->max_elems() - queue->size())/4, | 164 const size_t space_available = queue->max_elems() - queue->size(); |
165 (juint)ParGCDesiredObjsFromOverflowList), | 165 const size_t num_take_elems = MIN3(space_available / 4, |
166 num_overflow_elems); | 166 ParGCDesiredObjsFromOverflowList, |
167 num_overflow_elems); | |
167 // Transfer the most recent num_take_elems from the overflow | 168 // Transfer the most recent num_take_elems from the overflow |
168 // stack to our work queue. | 169 // stack to our work queue. |
169 for (size_t i = 0; i != num_take_elems; i++) { | 170 for (size_t i = 0; i != num_take_elems; i++) { |
170 oop cur = of_stack->pop(); | 171 oop cur = of_stack->pop(); |
171 oop obj_to_push = cur->forwardee(); | 172 oop obj_to_push = cur->forwardee(); |
269 ParScanThreadStateSet(int num_threads, | 270 ParScanThreadStateSet(int num_threads, |
270 Space& to_space, | 271 Space& to_space, |
271 ParNewGeneration& gen, | 272 ParNewGeneration& gen, |
272 Generation& old_gen, | 273 Generation& old_gen, |
273 ObjToScanQueueSet& queue_set, | 274 ObjToScanQueueSet& queue_set, |
274 GrowableArray<oop>** overflow_stacks_, | 275 Stack<oop>* overflow_stacks_, |
275 size_t desired_plab_sz, | 276 size_t desired_plab_sz, |
276 ParallelTaskTerminator& term); | 277 ParallelTaskTerminator& term); |
277 | 278 |
278 ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); } | 279 ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); } |
279 | 280 |
300 | 301 |
301 | 302 |
302 ParScanThreadStateSet::ParScanThreadStateSet( | 303 ParScanThreadStateSet::ParScanThreadStateSet( |
303 int num_threads, Space& to_space, ParNewGeneration& gen, | 304 int num_threads, Space& to_space, ParNewGeneration& gen, |
304 Generation& old_gen, ObjToScanQueueSet& queue_set, | 305 Generation& old_gen, ObjToScanQueueSet& queue_set, |
305 GrowableArray<oop>** overflow_stack_set_, | 306 Stack<oop>* overflow_stacks, |
306 size_t desired_plab_sz, ParallelTaskTerminator& term) | 307 size_t desired_plab_sz, ParallelTaskTerminator& term) |
307 : ResourceArray(sizeof(ParScanThreadState), num_threads), | 308 : ResourceArray(sizeof(ParScanThreadState), num_threads), |
308 _gen(gen), _next_gen(old_gen), _term(term) | 309 _gen(gen), _next_gen(old_gen), _term(term) |
309 { | 310 { |
310 assert(num_threads > 0, "sanity check!"); | 311 assert(num_threads > 0, "sanity check!"); |
312 assert(ParGCUseLocalOverflow == (overflow_stacks != NULL), | |
313 "overflow_stack allocation mismatch"); | |
311 // Initialize states. | 314 // Initialize states. |
312 for (int i = 0; i < num_threads; ++i) { | 315 for (int i = 0; i < num_threads; ++i) { |
313 new ((ParScanThreadState*)_data + i) | 316 new ((ParScanThreadState*)_data + i) |
314 ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set, | 317 ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set, |
315 overflow_stack_set_, desired_plab_sz, term); | 318 overflow_stacks, desired_plab_sz, term); |
316 } | 319 } |
317 } | 320 } |
318 | 321 |
319 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) | 322 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) |
320 { | 323 { |
594 } | 597 } |
595 | 598 |
596 for (uint i2 = 0; i2 < ParallelGCThreads; i2++) | 599 for (uint i2 = 0; i2 < ParallelGCThreads; i2++) |
597 _task_queues->queue(i2)->initialize(); | 600 _task_queues->queue(i2)->initialize(); |
598 | 601 |
599 _overflow_stacks = NEW_C_HEAP_ARRAY(GrowableArray<oop>*, ParallelGCThreads); | 602 _overflow_stacks = NULL; |
600 guarantee(_overflow_stacks != NULL, "Overflow stack set allocation failure"); | 603 if (ParGCUseLocalOverflow) { |
601 for (uint i = 0; i < ParallelGCThreads; i++) { | 604 _overflow_stacks = NEW_C_HEAP_ARRAY(Stack<oop>, ParallelGCThreads); |
602 if (ParGCUseLocalOverflow) { | 605 for (size_t i = 0; i < ParallelGCThreads; ++i) { |
603 _overflow_stacks[i] = new (ResourceObj::C_HEAP) GrowableArray<oop>(512, true); | 606 new (_overflow_stacks + i) Stack<oop>(); |
604 guarantee(_overflow_stacks[i] != NULL, "Overflow Stack allocation failure."); | |
605 } else { | |
606 _overflow_stacks[i] = NULL; | |
607 } | 607 } |
608 } | 608 } |
609 | 609 |
610 if (UsePerfData) { | 610 if (UsePerfData) { |
611 EXCEPTION_MARK; | 611 EXCEPTION_MARK; |
935 | 935 |
936 assert(to()->is_empty(), "to space should be empty now"); | 936 assert(to()->is_empty(), "to space should be empty now"); |
937 } else { | 937 } else { |
938 assert(HandlePromotionFailure, | 938 assert(HandlePromotionFailure, |
939 "Should only be here if promotion failure handling is on"); | 939 "Should only be here if promotion failure handling is on"); |
940 if (_promo_failure_scan_stack != NULL) { | 940 assert(_promo_failure_scan_stack.is_empty(), "post condition"); |
941 // Can be non-null because of reference processing. | 941 _promo_failure_scan_stack.clear(true); // Clear cached segments. |
942 // Free stack with its elements. | 942 |
943 delete _promo_failure_scan_stack; | |
944 _promo_failure_scan_stack = NULL; | |
945 } | |
946 remove_forwarding_pointers(); | 943 remove_forwarding_pointers(); |
947 if (PrintGCDetails) { | 944 if (PrintGCDetails) { |
948 gclog_or_tty->print(" (promotion failed)"); | 945 gclog_or_tty->print(" (promotion failed)"); |
949 } | 946 } |
950 // All the spaces are in play for mark-sweep. | 947 // All the spaces are in play for mark-sweep. |
1395 ObjToScanQueue* work_q = par_scan_state->work_queue(); | 1392 ObjToScanQueue* work_q = par_scan_state->work_queue(); |
1396 // How many to take? | 1393 // How many to take? |
1397 size_t objsFromOverflow = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, | 1394 size_t objsFromOverflow = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, |
1398 (size_t)ParGCDesiredObjsFromOverflowList); | 1395 (size_t)ParGCDesiredObjsFromOverflowList); |
1399 | 1396 |
1397 assert(!UseCompressedOops, "Error"); | |
1400 assert(par_scan_state->overflow_stack() == NULL, "Error"); | 1398 assert(par_scan_state->overflow_stack() == NULL, "Error"); |
1401 assert(!UseCompressedOops, "Error"); | |
1402 if (_overflow_list == NULL) return false; | 1399 if (_overflow_list == NULL) return false; |
1403 | 1400 |
1404 // Otherwise, there was something there; try claiming the list. | 1401 // Otherwise, there was something there; try claiming the list. |
1405 oop prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); | 1402 oop prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); |
1406 // Trim off a prefix of at most objsFromOverflow items | 1403 // Trim off a prefix of at most objsFromOverflow items |