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