67 int thread_num_, |
67 int thread_num_, |
68 ObjToScanQueueSet* work_queue_set_, |
68 ObjToScanQueueSet* work_queue_set_, |
69 Stack<oop, mtGC>* overflow_stacks_, |
69 Stack<oop, mtGC>* overflow_stacks_, |
70 size_t desired_plab_sz_, |
70 size_t desired_plab_sz_, |
71 ParallelTaskTerminator& term_) : |
71 ParallelTaskTerminator& term_) : |
72 _to_space(to_space_), _old_gen(old_gen_), _young_gen(young_gen_), _thread_num(thread_num_), |
72 _to_space(to_space_), |
73 _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false), |
73 _old_gen(old_gen_), |
|
74 _young_gen(young_gen_), |
|
75 _thread_num(thread_num_), |
|
76 _work_queue(work_queue_set_->queue(thread_num_)), |
|
77 _to_space_full(false), |
74 _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL), |
78 _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL), |
75 _ageTable(false), // false ==> not the global age table, no perf data. |
79 _ageTable(false), // false ==> not the global age table, no perf data. |
76 _to_space_alloc_buffer(desired_plab_sz_), |
80 _to_space_alloc_buffer(desired_plab_sz_), |
77 _to_space_closure(young_gen_, this), _old_gen_closure(young_gen_, this), |
81 _to_space_closure(young_gen_, this), |
78 _to_space_root_closure(young_gen_, this), _old_gen_root_closure(young_gen_, this), |
82 _old_gen_closure(young_gen_, this), |
|
83 _to_space_root_closure(young_gen_, this), |
|
84 _old_gen_root_closure(young_gen_, this), |
79 _older_gen_closure(young_gen_, this), |
85 _older_gen_closure(young_gen_, this), |
80 _evacuate_followers(this, &_to_space_closure, &_old_gen_closure, |
86 _evacuate_followers(this, &_to_space_closure, &_old_gen_closure, |
81 &_to_space_root_closure, young_gen_, &_old_gen_root_closure, |
87 &_to_space_root_closure, young_gen_, &_old_gen_root_closure, |
82 work_queue_set_, &term_), |
88 work_queue_set_, &term_), |
83 _is_alive_closure(young_gen_), _scan_weak_ref_closure(young_gen_, this), |
89 _is_alive_closure(young_gen_), |
|
90 _scan_weak_ref_closure(young_gen_, this), |
84 _keep_alive_closure(&_scan_weak_ref_closure), |
91 _keep_alive_closure(&_scan_weak_ref_closure), |
85 _strong_roots_time(0.0), _term_time(0.0) |
92 _strong_roots_time(0.0), |
|
93 _term_time(0.0) |
86 { |
94 { |
87 #if TASKQUEUE_STATS |
95 #if TASKQUEUE_STATS |
88 _term_attempts = 0; |
96 _term_attempts = 0; |
89 _overflow_refills = 0; |
97 _overflow_refills = 0; |
90 _overflow_refill_objs = 0; |
98 _overflow_refill_objs = 0; |
91 #endif // TASKQUEUE_STATS |
99 #endif // TASKQUEUE_STATS |
92 |
100 |
93 _survivor_chunk_array = |
101 _survivor_chunk_array = (ChunkArray*) old_gen()->get_data_recorder(thread_num()); |
94 (ChunkArray*) old_gen()->get_data_recorder(thread_num()); |
|
95 _hash_seed = 17; // Might want to take time-based random value. |
102 _hash_seed = 17; // Might want to take time-based random value. |
96 _start = os::elapsedTime(); |
103 _start = os::elapsedTime(); |
97 _old_gen_closure.set_generation(old_gen_); |
104 _old_gen_closure.set_generation(old_gen_); |
98 _old_gen_root_closure.set_generation(old_gen_); |
105 _old_gen_root_closure.set_generation(old_gen_); |
99 } |
106 } |
220 overflow_stack()->push(p); |
226 overflow_stack()->push(p); |
221 assert(young_gen()->overflow_list() == NULL, "Error"); |
227 assert(young_gen()->overflow_list() == NULL, "Error"); |
222 } |
228 } |
223 |
229 |
224 HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) { |
230 HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) { |
225 |
231 // If the object is small enough, try to reallocate the buffer. |
226 // Otherwise, if the object is small enough, try to reallocate the |
|
227 // buffer. |
|
228 HeapWord* obj = NULL; |
232 HeapWord* obj = NULL; |
229 if (!_to_space_full) { |
233 if (!_to_space_full) { |
230 PLAB* const plab = to_space_alloc_buffer(); |
234 PLAB* const plab = to_space_alloc_buffer(); |
231 Space* const sp = to_space(); |
235 Space* const sp = to_space(); |
232 if (word_sz * 100 < |
236 if (word_sz * 100 < ParallelGCBufferWastePct * plab->word_sz()) { |
233 ParallelGCBufferWastePct * plab->word_sz()) { |
|
234 // Is small enough; abandon this buffer and start a new one. |
237 // Is small enough; abandon this buffer and start a new one. |
235 plab->retire(); |
238 plab->retire(); |
236 size_t buf_size = plab->word_sz(); |
239 size_t buf_size = plab->word_sz(); |
237 HeapWord* buf_space = sp->par_allocate(buf_size); |
240 HeapWord* buf_space = sp->par_allocate(buf_size); |
238 if (buf_space == NULL) { |
241 if (buf_space == NULL) { |
239 const size_t min_bytes = |
242 const size_t min_bytes = |
240 PLAB::min_size() << LogHeapWordSize; |
243 PLAB::min_size() << LogHeapWordSize; |
241 size_t free_bytes = sp->free(); |
244 size_t free_bytes = sp->free(); |
242 while(buf_space == NULL && free_bytes >= min_bytes) { |
245 while(buf_space == NULL && free_bytes >= min_bytes) { |
243 buf_size = free_bytes >> LogHeapWordSize; |
246 buf_size = free_bytes >> LogHeapWordSize; |
244 assert(buf_size == (size_t)align_object_size(buf_size), |
247 assert(buf_size == (size_t)align_object_size(buf_size), "Invariant"); |
245 "Invariant"); |
|
246 buf_space = sp->par_allocate(buf_size); |
248 buf_space = sp->par_allocate(buf_size); |
247 free_bytes = sp->free(); |
249 free_bytes = sp->free(); |
248 } |
250 } |
249 } |
251 } |
250 if (buf_space != NULL) { |
252 if (buf_space != NULL) { |
286 class ParScanThreadStateSet: private ResourceArray { |
286 class ParScanThreadStateSet: private ResourceArray { |
287 public: |
287 public: |
288 // Initializes states for the specified number of threads; |
288 // Initializes states for the specified number of threads; |
289 ParScanThreadStateSet(int num_threads, |
289 ParScanThreadStateSet(int num_threads, |
290 Space& to_space, |
290 Space& to_space, |
291 ParNewGeneration& gen, |
291 ParNewGeneration& young_gen, |
292 Generation& old_gen, |
292 Generation& old_gen, |
293 ObjToScanQueueSet& queue_set, |
293 ObjToScanQueueSet& queue_set, |
294 Stack<oop, mtGC>* overflow_stacks_, |
294 Stack<oop, mtGC>* overflow_stacks_, |
295 size_t desired_plab_sz, |
295 size_t desired_plab_sz, |
296 ParallelTaskTerminator& term); |
296 ParallelTaskTerminator& term); |
313 void reset_stats(); |
313 void reset_stats(); |
314 #endif // TASKQUEUE_STATS |
314 #endif // TASKQUEUE_STATS |
315 |
315 |
316 private: |
316 private: |
317 ParallelTaskTerminator& _term; |
317 ParallelTaskTerminator& _term; |
318 ParNewGeneration& _gen; |
318 ParNewGeneration& _young_gen; |
319 Generation& _old_gen; |
319 Generation& _old_gen; |
320 public: |
320 public: |
321 bool is_valid(int id) const { return id < length(); } |
321 bool is_valid(int id) const { return id < length(); } |
322 ParallelTaskTerminator* terminator() { return &_term; } |
322 ParallelTaskTerminator* terminator() { return &_term; } |
323 }; |
323 }; |
324 |
324 |
325 |
325 ParScanThreadStateSet::ParScanThreadStateSet(int num_threads, |
326 ParScanThreadStateSet::ParScanThreadStateSet( |
326 Space& to_space, |
327 int num_threads, Space& to_space, ParNewGeneration& gen, |
327 ParNewGeneration& young_gen, |
328 Generation& old_gen, ObjToScanQueueSet& queue_set, |
328 Generation& old_gen, |
329 Stack<oop, mtGC>* overflow_stacks, |
329 ObjToScanQueueSet& queue_set, |
330 size_t desired_plab_sz, ParallelTaskTerminator& term) |
330 Stack<oop, mtGC>* overflow_stacks, |
|
331 size_t desired_plab_sz, |
|
332 ParallelTaskTerminator& term) |
331 : ResourceArray(sizeof(ParScanThreadState), num_threads), |
333 : ResourceArray(sizeof(ParScanThreadState), num_threads), |
332 _gen(gen), _old_gen(old_gen), _term(term) |
334 _young_gen(young_gen), |
|
335 _old_gen(old_gen), |
|
336 _term(term) |
333 { |
337 { |
334 assert(num_threads > 0, "sanity check!"); |
338 assert(num_threads > 0, "sanity check!"); |
335 assert(ParGCUseLocalOverflow == (overflow_stacks != NULL), |
339 assert(ParGCUseLocalOverflow == (overflow_stacks != NULL), |
336 "overflow_stack allocation mismatch"); |
340 "overflow_stack allocation mismatch"); |
337 // Initialize states. |
341 // Initialize states. |
338 for (int i = 0; i < num_threads; ++i) { |
342 for (int i = 0; i < num_threads; ++i) { |
339 new ((ParScanThreadState*)_data + i) |
343 new ((ParScanThreadState*)_data + i) |
340 ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set, |
344 ParScanThreadState(&to_space, &young_gen, &old_gen, i, &queue_set, |
341 overflow_stacks, desired_plab_sz, term); |
345 overflow_stacks, desired_plab_sz, term); |
342 } |
346 } |
343 } |
347 } |
344 |
348 |
345 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) |
349 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) { |
346 { |
|
347 assert(i >= 0 && i < length(), "sanity check!"); |
350 assert(i >= 0 && i < length(), "sanity check!"); |
348 return ((ParScanThreadState*)_data)[i]; |
351 return ((ParScanThreadState*)_data)[i]; |
349 } |
352 } |
350 |
353 |
351 void ParScanThreadStateSet::trace_promotion_failed(const YoungGCTracer* gc_tracer) { |
354 void ParScanThreadStateSet::trace_promotion_failed(const YoungGCTracer* gc_tracer) { |
355 thread_state(i).promotion_failed_info().reset(); |
358 thread_state(i).promotion_failed_info().reset(); |
356 } |
359 } |
357 } |
360 } |
358 } |
361 } |
359 |
362 |
360 void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed) |
363 void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed) { |
361 { |
|
362 _term.reset_for_reuse(active_threads); |
364 _term.reset_for_reuse(active_threads); |
363 if (promotion_failed) { |
365 if (promotion_failed) { |
364 for (int i = 0; i < length(); ++i) { |
366 for (int i = 0; i < length(); ++i) { |
365 thread_state(i).print_promotion_failure_size(); |
367 thread_state(i).print_promotion_failure_size(); |
366 } |
368 } |
367 } |
369 } |
368 } |
370 } |
369 |
371 |
370 #if TASKQUEUE_STATS |
372 #if TASKQUEUE_STATS |
371 void |
373 void ParScanThreadState::reset_stats() { |
372 ParScanThreadState::reset_stats() |
|
373 { |
|
374 taskqueue_stats().reset(); |
374 taskqueue_stats().reset(); |
375 _term_attempts = 0; |
375 _term_attempts = 0; |
376 _overflow_refills = 0; |
376 _overflow_refills = 0; |
377 _overflow_refill_objs = 0; |
377 _overflow_refill_objs = 0; |
378 } |
378 } |
379 |
379 |
380 void ParScanThreadStateSet::reset_stats() |
380 void ParScanThreadStateSet::reset_stats() { |
381 { |
|
382 for (int i = 0; i < length(); ++i) { |
381 for (int i = 0; i < length(); ++i) { |
383 thread_state(i).reset_stats(); |
382 thread_state(i).reset_stats(); |
384 } |
383 } |
385 } |
384 } |
386 |
385 |
387 void |
386 void ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st) { |
388 ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st) |
|
389 { |
|
390 st->print_raw_cr("GC Termination Stats"); |
387 st->print_raw_cr("GC Termination Stats"); |
391 st->print_raw_cr(" elapsed --strong roots-- " |
388 st->print_raw_cr(" elapsed --strong roots-- -------termination-------"); |
392 "-------termination-------"); |
389 st->print_raw_cr("thr ms ms % ms % attempts"); |
393 st->print_raw_cr("thr ms ms % " |
390 st->print_raw_cr("--- --------- --------- ------ --------- ------ --------"); |
394 " ms % attempts"); |
391 } |
395 st->print_raw_cr("--- --------- --------- ------ " |
392 |
396 "--------- ------ --------"); |
393 void ParScanThreadStateSet::print_termination_stats(outputStream* const st) { |
397 } |
|
398 |
|
399 void ParScanThreadStateSet::print_termination_stats(outputStream* const st) |
|
400 { |
|
401 print_termination_stats_hdr(st); |
394 print_termination_stats_hdr(st); |
402 |
395 |
403 for (int i = 0; i < length(); ++i) { |
396 for (int i = 0; i < length(); ++i) { |
404 const ParScanThreadState & pss = thread_state(i); |
397 const ParScanThreadState & pss = thread_state(i); |
405 const double elapsed_ms = pss.elapsed_time() * 1000.0; |
398 const double elapsed_ms = pss.elapsed_time() * 1000.0; |
406 const double s_roots_ms = pss.strong_roots_time() * 1000.0; |
399 const double s_roots_ms = pss.strong_roots_time() * 1000.0; |
407 const double term_ms = pss.term_time() * 1000.0; |
400 const double term_ms = pss.term_time() * 1000.0; |
408 st->print_cr("%3d %9.2f %9.2f %6.2f " |
401 st->print_cr("%3d %9.2f %9.2f %6.2f %9.2f %6.2f " SIZE_FORMAT_W(8), |
409 "%9.2f %6.2f " SIZE_FORMAT_W(8), |
|
410 i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, |
402 i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, |
411 term_ms, term_ms * 100 / elapsed_ms, pss.term_attempts()); |
403 term_ms, term_ms * 100 / elapsed_ms, pss.term_attempts()); |
412 } |
404 } |
413 } |
405 } |
414 |
406 |
415 // Print stats related to work queue activity. |
407 // Print stats related to work queue activity. |
416 void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st) |
408 void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st) { |
417 { |
|
418 st->print_raw_cr("GC Task Stats"); |
409 st->print_raw_cr("GC Task Stats"); |
419 st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr(); |
410 st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr(); |
420 st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr(); |
411 st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr(); |
421 } |
412 } |
422 |
413 |
423 void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st) |
414 void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st) { |
424 { |
|
425 print_taskqueue_stats_hdr(st); |
415 print_taskqueue_stats_hdr(st); |
426 |
416 |
427 TaskQueueStats totals; |
417 TaskQueueStats totals; |
428 for (int i = 0; i < length(); ++i) { |
418 for (int i = 0; i < length(); ++i) { |
429 const ParScanThreadState & pss = thread_state(i); |
419 const ParScanThreadState & pss = thread_state(i); |
441 |
431 |
442 DEBUG_ONLY(totals.verify()); |
432 DEBUG_ONLY(totals.verify()); |
443 } |
433 } |
444 #endif // TASKQUEUE_STATS |
434 #endif // TASKQUEUE_STATS |
445 |
435 |
446 void ParScanThreadStateSet::flush() |
436 void ParScanThreadStateSet::flush() { |
447 { |
|
448 // Work in this loop should be kept as lightweight as |
437 // Work in this loop should be kept as lightweight as |
449 // possible since this might otherwise become a bottleneck |
438 // possible since this might otherwise become a bottleneck |
450 // to scaling. Should we add heavy-weight work into this |
439 // to scaling. Should we add heavy-weight work into this |
451 // loop, consider parallelizing the loop into the worker threads. |
440 // loop, consider parallelizing the loop into the worker threads. |
452 for (int i = 0; i < length(); ++i) { |
441 for (int i = 0; i < length(); ++i) { |
453 ParScanThreadState& par_scan_state = thread_state(i); |
442 ParScanThreadState& par_scan_state = thread_state(i); |
454 |
443 |
455 // Flush stats related to To-space PLAB activity and |
444 // Flush stats related to To-space PLAB activity and |
456 // retire the last buffer. |
445 // retire the last buffer. |
457 par_scan_state.to_space_alloc_buffer()->flush_and_retire_stats(_gen.plab_stats()); |
446 par_scan_state.to_space_alloc_buffer()->flush_and_retire_stats(_young_gen.plab_stats()); |
458 |
447 |
459 // Every thread has its own age table. We need to merge |
448 // Every thread has its own age table. We need to merge |
460 // them all into one. |
449 // them all into one. |
461 ageTable *local_table = par_scan_state.age_table(); |
450 ageTable *local_table = par_scan_state.age_table(); |
462 _gen.age_table()->merge(local_table); |
451 _young_gen.age_table()->merge(local_table); |
463 |
452 |
464 // Inform old gen that we're done. |
453 // Inform old gen that we're done. |
465 _old_gen.par_promote_alloc_done(i); |
454 _old_gen.par_promote_alloc_done(i); |
466 _old_gen.par_oop_since_save_marks_iterate_done(i); |
455 _old_gen.par_oop_since_save_marks_iterate_done(i); |
467 } |
456 } |
476 } |
465 } |
477 } |
466 } |
478 |
467 |
479 ParScanClosure::ParScanClosure(ParNewGeneration* g, |
468 ParScanClosure::ParScanClosure(ParNewGeneration* g, |
480 ParScanThreadState* par_scan_state) : |
469 ParScanThreadState* par_scan_state) : |
481 OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g) |
470 OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g) { |
482 { |
|
483 _boundary = _g->reserved().end(); |
471 _boundary = _g->reserved().end(); |
484 } |
472 } |
485 |
473 |
486 void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); } |
474 void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); } |
487 void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); } |
475 void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); } |
529 |
517 |
530 void ParEvacuateFollowersClosure::do_void() { |
518 void ParEvacuateFollowersClosure::do_void() { |
531 ObjToScanQueue* work_q = par_scan_state()->work_queue(); |
519 ObjToScanQueue* work_q = par_scan_state()->work_queue(); |
532 |
520 |
533 while (true) { |
521 while (true) { |
534 |
|
535 // Scan to-space and old-gen objs until we run out of both. |
522 // Scan to-space and old-gen objs until we run out of both. |
536 oop obj_to_scan; |
523 oop obj_to_scan; |
537 par_scan_state()->trim_queues(0); |
524 par_scan_state()->trim_queues(0); |
538 |
525 |
539 // We have no local work, attempt to steal from other threads. |
526 // We have no local work, attempt to steal from other threads. |
540 |
527 |
541 // attempt to steal work from promoted. |
528 // Attempt to steal work from promoted. |
542 if (task_queues()->steal(par_scan_state()->thread_num(), |
529 if (task_queues()->steal(par_scan_state()->thread_num(), |
543 par_scan_state()->hash_seed(), |
530 par_scan_state()->hash_seed(), |
544 obj_to_scan)) { |
531 obj_to_scan)) { |
545 bool res = work_q->push(obj_to_scan); |
532 bool res = work_q->push(obj_to_scan); |
546 assert(res, "Empty queue should have room for a push."); |
533 assert(res, "Empty queue should have room for a push."); |
547 |
534 |
548 // if successful, goto Start. |
535 // If successful, goto Start. |
549 continue; |
536 continue; |
550 |
537 |
551 // try global overflow list. |
538 // Try global overflow list. |
552 } else if (par_gen()->take_from_overflow_list(par_scan_state())) { |
539 } else if (par_gen()->take_from_overflow_list(par_scan_state())) { |
553 continue; |
540 continue; |
554 } |
541 } |
555 |
542 |
556 // Otherwise, offer termination. |
543 // Otherwise, offer termination. |
562 "Broken overflow list?"); |
549 "Broken overflow list?"); |
563 // Finish the last termination pause. |
550 // Finish the last termination pause. |
564 par_scan_state()->end_term_time(); |
551 par_scan_state()->end_term_time(); |
565 } |
552 } |
566 |
553 |
567 ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen, Generation* old_gen, |
554 ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen, |
568 HeapWord* young_old_boundary, ParScanThreadStateSet* state_set, |
555 Generation* old_gen, |
|
556 HeapWord* young_old_boundary, |
|
557 ParScanThreadStateSet* state_set, |
569 StrongRootsScope* strong_roots_scope) : |
558 StrongRootsScope* strong_roots_scope) : |
570 AbstractGangTask("ParNewGeneration collection"), |
559 AbstractGangTask("ParNewGeneration collection"), |
571 _young_gen(young_gen), _old_gen(old_gen), |
560 _young_gen(young_gen), _old_gen(old_gen), |
572 _young_old_boundary(young_old_boundary), |
561 _young_old_boundary(young_old_boundary), |
573 _state_set(state_set), |
562 _state_set(state_set), |
574 _strong_roots_scope(strong_roots_scope) |
563 _strong_roots_scope(strong_roots_scope) |
575 {} |
564 {} |
576 |
565 |
577 void ParNewGenTask::work(uint worker_id) { |
566 void ParNewGenTask::work(uint worker_id) { |
578 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
567 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
579 // Since this is being done in a separate thread, need new resource |
568 // Since this is being done in a separate thread, need new resource |
580 // and handle marks. |
569 // and handle marks. |
593 false); |
582 false); |
594 |
583 |
595 par_scan_state.start_strong_roots(); |
584 par_scan_state.start_strong_roots(); |
596 gch->gen_process_roots(_strong_roots_scope, |
585 gch->gen_process_roots(_strong_roots_scope, |
597 GenCollectedHeap::YoungGen, |
586 GenCollectedHeap::YoungGen, |
598 true, // Process younger gens, if any, |
587 true, // Process younger gens, if any, as strong roots. |
599 // as strong roots. |
|
600 GenCollectedHeap::SO_ScavengeCodeCache, |
588 GenCollectedHeap::SO_ScavengeCodeCache, |
601 GenCollectedHeap::StrongAndWeakRoots, |
589 GenCollectedHeap::StrongAndWeakRoots, |
602 &par_scan_state.to_space_root_closure(), |
590 &par_scan_state.to_space_root_closure(), |
603 &par_scan_state.older_gen_closure(), |
591 &par_scan_state.older_gen_closure(), |
604 &cld_scan_closure); |
592 &cld_scan_closure); |
611 |
599 |
612 #ifdef _MSC_VER |
600 #ifdef _MSC_VER |
613 #pragma warning( push ) |
601 #pragma warning( push ) |
614 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list |
602 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list |
615 #endif |
603 #endif |
616 ParNewGeneration:: |
604 ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) |
617 ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) |
|
618 : DefNewGeneration(rs, initial_byte_size, "PCopy"), |
605 : DefNewGeneration(rs, initial_byte_size, "PCopy"), |
619 _overflow_list(NULL), |
606 _overflow_list(NULL), |
620 _is_alive_closure(this), |
607 _is_alive_closure(this), |
621 _plab_stats(YoungPLABSize, PLABWeight) |
608 _plab_stats(YoungPLABSize, PLABWeight) |
622 { |
609 { |
623 NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) |
610 NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) |
624 NOT_PRODUCT(_num_par_pushes = 0;) |
611 NOT_PRODUCT(_num_par_pushes = 0;) |
625 _task_queues = new ObjToScanQueueSet(ParallelGCThreads); |
612 _task_queues = new ObjToScanQueueSet(ParallelGCThreads); |
626 guarantee(_task_queues != NULL, "task_queues allocation failure."); |
613 guarantee(_task_queues != NULL, "task_queues allocation failure."); |
627 |
614 |
628 for (uint i1 = 0; i1 < ParallelGCThreads; i1++) { |
615 for (uint i = 0; i < ParallelGCThreads; i++) { |
629 ObjToScanQueue *q = new ObjToScanQueue(); |
616 ObjToScanQueue *q = new ObjToScanQueue(); |
630 guarantee(q != NULL, "work_queue Allocation failure."); |
617 guarantee(q != NULL, "work_queue Allocation failure."); |
631 _task_queues->register_queue(i1, q); |
618 _task_queues->register_queue(i, q); |
632 } |
619 } |
633 |
620 |
634 for (uint i2 = 0; i2 < ParallelGCThreads; i2++) |
621 for (uint i = 0; i < ParallelGCThreads; i++) { |
635 _task_queues->queue(i2)->initialize(); |
622 _task_queues->queue(i)->initialize(); |
|
623 } |
636 |
624 |
637 _overflow_stacks = NULL; |
625 _overflow_stacks = NULL; |
638 if (ParGCUseLocalOverflow) { |
626 if (ParGCUseLocalOverflow) { |
639 |
627 // typedef to workaround NEW_C_HEAP_ARRAY macro, which can not deal with ',' |
640 // typedef to workaround NEW_C_HEAP_ARRAY macro, which can not deal |
|
641 // with ',' |
|
642 typedef Stack<oop, mtGC> GCOopStack; |
628 typedef Stack<oop, mtGC> GCOopStack; |
643 |
629 |
644 _overflow_stacks = NEW_C_HEAP_ARRAY(GCOopStack, ParallelGCThreads, mtGC); |
630 _overflow_stacks = NEW_C_HEAP_ARRAY(GCOopStack, ParallelGCThreads, mtGC); |
645 for (size_t i = 0; i < ParallelGCThreads; ++i) { |
631 for (size_t i = 0; i < ParallelGCThreads; ++i) { |
646 new (_overflow_stacks + i) Stack<oop, mtGC>(); |
632 new (_overflow_stacks + i) Stack<oop, mtGC>(); |
790 ParNewRefEnqueueTaskProxy(EnqueueTask& task) |
774 ParNewRefEnqueueTaskProxy(EnqueueTask& task) |
791 : AbstractGangTask("ParNewGeneration parallel reference enqueue"), |
775 : AbstractGangTask("ParNewGeneration parallel reference enqueue"), |
792 _task(task) |
776 _task(task) |
793 { } |
777 { } |
794 |
778 |
795 virtual void work(uint worker_id) |
779 virtual void work(uint worker_id) { |
796 { |
|
797 _task.work(worker_id); |
780 _task.work(worker_id); |
798 } |
781 } |
799 }; |
782 }; |
800 |
783 |
801 |
784 void ParNewRefProcTaskExecutor::execute(ProcessTask& task) { |
802 void ParNewRefProcTaskExecutor::execute(ProcessTask& task) |
|
803 { |
|
804 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
785 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
805 WorkGang* workers = gch->workers(); |
786 WorkGang* workers = gch->workers(); |
806 assert(workers != NULL, "Need parallel worker threads."); |
787 assert(workers != NULL, "Need parallel worker threads."); |
807 _state_set.reset(workers->active_workers(), _young_gen.promotion_failed()); |
788 _state_set.reset(workers->active_workers(), _young_gen.promotion_failed()); |
808 ParNewRefProcTaskProxy rp_task(task, _young_gen, _old_gen, |
789 ParNewRefProcTaskProxy rp_task(task, _young_gen, _old_gen, |
810 workers->run_task(&rp_task); |
791 workers->run_task(&rp_task); |
811 _state_set.reset(0 /* bad value in debug if not reset */, |
792 _state_set.reset(0 /* bad value in debug if not reset */, |
812 _young_gen.promotion_failed()); |
793 _young_gen.promotion_failed()); |
813 } |
794 } |
814 |
795 |
815 void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) |
796 void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) { |
816 { |
|
817 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
797 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
818 WorkGang* workers = gch->workers(); |
798 WorkGang* workers = gch->workers(); |
819 assert(workers != NULL, "Need parallel worker threads."); |
799 assert(workers != NULL, "Need parallel worker threads."); |
820 ParNewRefEnqueueTaskProxy enq_task(task); |
800 ParNewRefEnqueueTaskProxy enq_task(task); |
821 workers->run_task(&enq_task); |
801 workers->run_task(&enq_task); |
822 } |
802 } |
823 |
803 |
824 void ParNewRefProcTaskExecutor::set_single_threaded_mode() |
804 void ParNewRefProcTaskExecutor::set_single_threaded_mode() { |
825 { |
|
826 _state_set.flush(); |
805 _state_set.flush(); |
827 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
806 GenCollectedHeap* gch = GenCollectedHeap::heap(); |
828 gch->save_marks(); |
807 gch->save_marks(); |
829 } |
808 } |
830 |
809 |
831 ScanClosureWithParBarrier:: |
810 ScanClosureWithParBarrier:: |
832 ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) : |
811 ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) : |
833 ScanClosure(g, gc_barrier) {} |
812 ScanClosure(g, gc_barrier) |
|
813 { } |
834 |
814 |
835 EvacuateFollowersClosureGeneral:: |
815 EvacuateFollowersClosureGeneral:: |
836 EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, |
816 EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, |
837 OopsInGenClosure* cur, |
817 OopsInGenClosure* cur, |
838 OopsInGenClosure* older) : |
818 OopsInGenClosure* older) : |
839 _gch(gch), |
819 _gch(gch), |
840 _scan_cur_or_nonheap(cur), _scan_older(older) |
820 _scan_cur_or_nonheap(cur), _scan_older(older) |
841 {} |
821 { } |
842 |
822 |
843 void EvacuateFollowersClosureGeneral::do_void() { |
823 void EvacuateFollowersClosureGeneral::do_void() { |
844 do { |
824 do { |
845 // Beware: this call will lead to closure applications via virtual |
825 // Beware: this call will lead to closure applications via virtual |
846 // calls. |
826 // calls. |
847 _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, |
827 _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, |
848 _scan_cur_or_nonheap, |
828 _scan_cur_or_nonheap, |
849 _scan_older); |
829 _scan_older); |
850 } while (!_gch->no_allocs_since_save_marks()); |
830 } while (!_gch->no_allocs_since_save_marks()); |
851 } |
831 } |
852 |
|
853 |
832 |
854 // A Generation that does parallel young-gen collection. |
833 // A Generation that does parallel young-gen collection. |
855 |
834 |
856 void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set) { |
835 void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set) { |
857 assert(_promo_failure_scan_stack.is_empty(), "post condition"); |
836 assert(_promo_failure_scan_stack.is_empty(), "post condition"); |
994 eden()->clear(SpaceDecorator::Mangle); |
973 eden()->clear(SpaceDecorator::Mangle); |
995 from()->clear(SpaceDecorator::Mangle); |
974 from()->clear(SpaceDecorator::Mangle); |
996 if (ZapUnusedHeapArea) { |
975 if (ZapUnusedHeapArea) { |
997 // This is now done here because of the piece-meal mangling which |
976 // This is now done here because of the piece-meal mangling which |
998 // can check for valid mangling at intermediate points in the |
977 // can check for valid mangling at intermediate points in the |
999 // collection(s). When a minor collection fails to collect |
978 // collection(s). When a young collection fails to collect |
1000 // sufficient space resizing of the young generation can occur |
979 // sufficient space resizing of the young generation can occur |
1001 // an redistribute the spaces in the young generation. Mangle |
980 // and redistribute the spaces in the young generation. Mangle |
1002 // here so that unzapped regions don't get distributed to |
981 // here so that unzapped regions don't get distributed to |
1003 // other spaces. |
982 // other spaces. |
1004 to()->mangle_unused_area(); |
983 to()->mangle_unused_area(); |
1005 } |
984 } |
1006 swap_spaces(); |
985 swap_spaces(); |
1111 // the object in the young generation. This method claims the right |
1090 // the object in the young generation. This method claims the right |
1112 // to install the forwarding pointer before it copies the object, |
1091 // to install the forwarding pointer before it copies the object, |
1113 // thus avoiding the need to undo the copy as in |
1092 // thus avoiding the need to undo the copy as in |
1114 // copy_to_survivor_space_avoiding_with_undo. |
1093 // copy_to_survivor_space_avoiding_with_undo. |
1115 |
1094 |
1116 oop ParNewGeneration::copy_to_survivor_space( |
1095 oop ParNewGeneration::copy_to_survivor_space(ParScanThreadState* par_scan_state, |
1117 ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) { |
1096 oop old, |
|
1097 size_t sz, |
|
1098 markOop m) { |
1118 // In the sequential version, this assert also says that the object is |
1099 // In the sequential version, this assert also says that the object is |
1119 // not forwarded. That might not be the case here. It is the case that |
1100 // not forwarded. That might not be the case here. It is the case that |
1120 // the caller observed it to be not forwarded at some time in the past. |
1101 // the caller observed it to be not forwarded at some time in the past. |
1121 assert(is_in_reserved(old), "shouldn't be scavenging this oop"); |
1102 assert(is_in_reserved(old), "shouldn't be scavenging this oop"); |
1122 |
1103 |