src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/gc_implementation/parNew/parNewGeneration.cpp

src/share/vm/gc_implementation/parNew/parNewGeneration.cpp

Print this page
rev 7212 : [mq]: remove_get_gen
rev 7215 : imported patch remove_levels
rev 7216 : imported patch cleanup

*** 61,100 **** #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif ParScanThreadState::ParScanThreadState(Space* to_space_, ! ParNewGeneration* gen_, Generation* old_gen_, int thread_num_, ObjToScanQueueSet* work_queue_set_, Stack<oop, mtGC>* overflow_stacks_, size_t desired_plab_sz_, ! ParallelTaskTerminator& term_) : ! _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_), ! _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false), _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL), _ageTable(false), // false ==> not the global age table, no perf data. _to_space_alloc_buffer(desired_plab_sz_), ! _to_space_closure(gen_, this), _old_gen_closure(gen_, this), ! _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this), ! _older_gen_closure(gen_, this), ! _evacuate_followers(this, &_to_space_closure, &_old_gen_closure, ! &_to_space_root_closure, gen_, &_old_gen_root_closure, ! work_queue_set_, &term_), ! _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this), _keep_alive_closure(&_scan_weak_ref_closure), ! _strong_roots_time(0.0), _term_time(0.0) ! { #if TASKQUEUE_STATS _term_attempts = 0; _overflow_refills = 0; _overflow_refill_objs = 0; #endif // TASKQUEUE_STATS ! _survivor_chunk_array = ! (ChunkArray*) old_gen()->get_data_recorder(thread_num()); _hash_seed = 17; // Might want to take time-based random value. _start = os::elapsedTime(); _old_gen_closure.set_generation(old_gen_); _old_gen_root_closure.set_generation(old_gen_); } --- 61,111 ---- #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif ParScanThreadState::ParScanThreadState(Space* to_space_, ! ParNewGeneration* young_gen_, Generation* old_gen_, int thread_num_, ObjToScanQueueSet* work_queue_set_, Stack<oop, mtGC>* overflow_stacks_, size_t desired_plab_sz_, ! ParallelTaskTerminator& term_) ! : _to_space(to_space_), ! _old_gen(old_gen_), ! _young_gen(young_gen_), ! _thread_num(thread_num_), ! _work_queue(work_queue_set_->queue(thread_num_)), ! _to_space_full(false), _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL), _ageTable(false), // false ==> not the global age table, no perf data. _to_space_alloc_buffer(desired_plab_sz_), ! _to_space_closure(young_gen_, this), ! _old_gen_closure(young_gen_, this), ! _to_space_root_closure(young_gen_, this), ! _old_gen_root_closure(young_gen_, this), ! _older_gen_closure(young_gen_, this), ! _evacuate_followers(this, ! &_to_space_closure, ! &_old_gen_closure, ! &_to_space_root_closure, ! young_gen_, ! &_old_gen_root_closure, ! work_queue_set_, ! &term_), ! _is_alive_closure(young_gen_), ! _scan_weak_ref_closure(young_gen_, this), _keep_alive_closure(&_scan_weak_ref_closure), ! _strong_roots_time(0.0), ! _term_time(0.0) { #if TASKQUEUE_STATS _term_attempts = 0; _overflow_refills = 0; _overflow_refill_objs = 0; #endif // TASKQUEUE_STATS ! _survivor_chunk_array = (ChunkArray*) old_gen()->get_data_recorder(thread_num()); _hash_seed = 17; // Might want to take time-based random value. _start = os::elapsedTime(); _old_gen_closure.set_generation(old_gen_); _old_gen_root_closure.set_generation(old_gen_); }
*** 153,163 **** // object is in old generation obj->oop_iterate_range(&_old_gen_closure, start, end); } } - void ParScanThreadState::trim_queues(int max_size) { ObjToScanQueue* queue = work_queue(); do { while (queue->size() > (juint)max_size) { oop obj_to_scan; --- 164,173 ----
*** 221,239 **** overflow_stack()->push(p); assert(young_gen()->overflow_list() == NULL, "Error"); } HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) { ! ! // Otherwise, if the object is small enough, try to reallocate the ! // buffer. HeapWord* obj = NULL; if (!_to_space_full) { ParGCAllocBuffer* const plab = to_space_alloc_buffer(); Space* const sp = to_space(); ! if (word_sz * 100 < ! ParallelGCBufferWastePct * plab->word_sz()) { // Is small enough; abandon this buffer and start a new one. plab->retire(false, false); size_t buf_size = plab->word_sz(); HeapWord* buf_space = sp->par_allocate(buf_size); if (buf_space == NULL) { --- 231,246 ---- overflow_stack()->push(p); assert(young_gen()->overflow_list() == NULL, "Error"); } HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) { ! // If the object is small enough, try to reallocate the buffer. HeapWord* obj = NULL; if (!_to_space_full) { ParGCAllocBuffer* const plab = to_space_alloc_buffer(); Space* const sp = to_space(); ! if (word_sz * 100 < ParallelGCBufferWastePct * plab->word_sz()) { // Is small enough; abandon this buffer and start a new one. plab->retire(false, false); size_t buf_size = plab->word_sz(); HeapWord* buf_space = sp->par_allocate(buf_size); if (buf_space == NULL) {
*** 271,283 **** } } return obj; } ! ! void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, ! size_t word_sz) { // Is the alloc in the current alloc buffer? if (to_space_alloc_buffer()->contains(obj)) { assert(to_space_alloc_buffer()->contains(obj + word_sz - 1), "Should contain whole object."); to_space_alloc_buffer()->undo_allocation(obj, word_sz); --- 278,288 ---- } } return obj; } ! void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, size_t word_sz) { // Is the alloc in the current alloc buffer? if (to_space_alloc_buffer()->contains(obj)) { assert(to_space_alloc_buffer()->contains(obj + word_sz - 1), "Should contain whole object."); to_space_alloc_buffer()->undo_allocation(obj, word_sz);
*** 299,309 **** ParScanThreadStateSet(int num_threads, Space& to_space, ParNewGeneration& gen, Generation& old_gen, ObjToScanQueueSet& queue_set, ! Stack<oop, mtGC>* overflow_stacks_, size_t desired_plab_sz, ParallelTaskTerminator& term); ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); } --- 304,314 ---- ParScanThreadStateSet(int num_threads, Space& to_space, ParNewGeneration& gen, Generation& old_gen, ObjToScanQueueSet& queue_set, ! Stack<oop, mtGC>* overflow_stacks, size_t desired_plab_sz, ParallelTaskTerminator& term); ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); }
*** 324,348 **** #endif // TASKQUEUE_STATS private: ParallelTaskTerminator& _term; ParNewGeneration& _gen; ! Generation& _next_gen; public: bool is_valid(int id) const { return id < length(); } ParallelTaskTerminator* terminator() { return &_term; } }; ! ! ParScanThreadStateSet::ParScanThreadStateSet( ! int num_threads, Space& to_space, ParNewGeneration& gen, ! Generation& old_gen, ObjToScanQueueSet& queue_set, Stack<oop, mtGC>* overflow_stacks, ! size_t desired_plab_sz, ParallelTaskTerminator& term) : ResourceArray(sizeof(ParScanThreadState), num_threads), ! _gen(gen), _next_gen(old_gen), _term(term) ! { assert(num_threads > 0, "sanity check!"); assert(ParGCUseLocalOverflow == (overflow_stacks != NULL), "overflow_stack allocation mismatch"); // Initialize states. for (int i = 0; i < num_threads; ++i) { --- 329,356 ---- #endif // TASKQUEUE_STATS private: ParallelTaskTerminator& _term; ParNewGeneration& _gen; ! Generation& _old_gen; public: bool is_valid(int id) const { return id < length(); } ParallelTaskTerminator* terminator() { return &_term; } }; ! ParScanThreadStateSet::ParScanThreadStateSet(int num_threads, ! Space& to_space, ! ParNewGeneration& gen, ! Generation& old_gen, ! ObjToScanQueueSet& queue_set, Stack<oop, mtGC>* overflow_stacks, ! size_t desired_plab_sz, ! ParallelTaskTerminator& term) : ResourceArray(sizeof(ParScanThreadState), num_threads), ! _gen(gen), ! _old_gen(old_gen), ! _term(term) { assert(num_threads > 0, "sanity check!"); assert(ParGCUseLocalOverflow == (overflow_stacks != NULL), "overflow_stack allocation mismatch"); // Initialize states. for (int i = 0; i < num_threads; ++i) {
*** 350,361 **** ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set, overflow_stacks, desired_plab_sz, term); } } ! inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) ! { assert(i >= 0 && i < length(), "sanity check!"); return ((ParScanThreadState*)_data)[i]; } void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) { --- 358,368 ---- ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set, overflow_stacks, desired_plab_sz, term); } } ! inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) { assert(i >= 0 && i < length(), "sanity check!"); return ((ParScanThreadState*)_data)[i]; } void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) {
*** 365,415 **** thread_state(i).promotion_failed_info().reset(); } } } ! void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed) ! { _term.reset_for_reuse(active_threads); if (promotion_failed) { for (int i = 0; i < length(); ++i) { thread_state(i).print_promotion_failure_size(); } } } #if TASKQUEUE_STATS void ! ParScanThreadState::reset_stats() ! { taskqueue_stats().reset(); _term_attempts = 0; _overflow_refills = 0; _overflow_refill_objs = 0; } ! void ParScanThreadStateSet::reset_stats() ! { for (int i = 0; i < length(); ++i) { thread_state(i).reset_stats(); } } ! void ! ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st) ! { st->print_raw_cr("GC Termination Stats"); st->print_raw_cr(" elapsed --strong roots-- " "-------termination-------"); st->print_raw_cr("thr ms ms % " " ms % attempts"); st->print_raw_cr("--- --------- --------- ------ " "--------- ------ --------"); } ! void ParScanThreadStateSet::print_termination_stats(outputStream* const st) ! { print_termination_stats_hdr(st); for (int i = 0; i < length(); ++i) { const ParScanThreadState & pss = thread_state(i); const double elapsed_ms = pss.elapsed_time() * 1000.0; --- 372,416 ---- thread_state(i).promotion_failed_info().reset(); } } } ! void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed) { _term.reset_for_reuse(active_threads); if (promotion_failed) { for (int i = 0; i < length(); ++i) { thread_state(i).print_promotion_failure_size(); } } } #if TASKQUEUE_STATS void ! ParScanThreadState::reset_stats() { taskqueue_stats().reset(); _term_attempts = 0; _overflow_refills = 0; _overflow_refill_objs = 0; } ! void ParScanThreadStateSet::reset_stats() { for (int i = 0; i < length(); ++i) { thread_state(i).reset_stats(); } } ! void ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st) { st->print_raw_cr("GC Termination Stats"); st->print_raw_cr(" elapsed --strong roots-- " "-------termination-------"); st->print_raw_cr("thr ms ms % " " ms % attempts"); st->print_raw_cr("--- --------- --------- ------ " "--------- ------ --------"); } ! void ParScanThreadStateSet::print_termination_stats(outputStream* const st) { print_termination_stats_hdr(st); for (int i = 0; i < length(); ++i) { const ParScanThreadState & pss = thread_state(i); const double elapsed_ms = pss.elapsed_time() * 1000.0;
*** 421,439 **** term_ms, term_ms * 100 / elapsed_ms, pss.term_attempts()); } } // Print stats related to work queue activity. ! void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st) ! { st->print_raw_cr("GC Task Stats"); st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr(); st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr(); } ! void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st) ! { print_taskqueue_stats_hdr(st); TaskQueueStats totals; for (int i = 0; i < length(); ++i) { const ParScanThreadState & pss = thread_state(i); --- 422,438 ---- term_ms, term_ms * 100 / elapsed_ms, pss.term_attempts()); } } // Print stats related to work queue activity. ! void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st) { st->print_raw_cr("GC Task Stats"); st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr(); st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr(); } ! void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st) { print_taskqueue_stats_hdr(st); TaskQueueStats totals; for (int i = 0; i < length(); ++i) { const ParScanThreadState & pss = thread_state(i);
*** 451,462 **** DEBUG_ONLY(totals.verify()); } #endif // TASKQUEUE_STATS ! void ParScanThreadStateSet::flush() ! { // Work in this loop should be kept as lightweight as // possible since this might otherwise become a bottleneck // to scaling. Should we add heavy-weight work into this // loop, consider parallelizing the loop into the worker threads. for (int i = 0; i < length(); ++i) { --- 450,460 ---- DEBUG_ONLY(totals.verify()); } #endif // TASKQUEUE_STATS ! void ParScanThreadStateSet::flush() { // Work in this loop should be kept as lightweight as // possible since this might otherwise become a bottleneck // to scaling. Should we add heavy-weight work into this // loop, consider parallelizing the loop into the worker threads. for (int i = 0; i < length(); ++i) {
*** 473,484 **** // them all into one. ageTable *local_table = par_scan_state.age_table(); _gen.age_table()->merge(local_table); // Inform old gen that we're done. ! _next_gen.par_promote_alloc_done(i); ! _next_gen.par_oop_since_save_marks_iterate_done(i); } if (UseConcMarkSweepGC && ParallelGCThreads > 0) { // We need to call this even when ResizeOldPLAB is disabled // so as to avoid breaking some asserts. While we may be able --- 471,482 ---- // them all into one. ageTable *local_table = par_scan_state.age_table(); _gen.age_table()->merge(local_table); // Inform old gen that we're done. ! _old_gen.par_promote_alloc_done(i); ! _old_gen.par_oop_since_save_marks_iterate_done(i); } if (UseConcMarkSweepGC && ParallelGCThreads > 0) { // We need to call this even when ResizeOldPLAB is disabled // so as to avoid breaking some asserts. While we may be able
*** 488,501 **** CFLS_LAB::compute_desired_plab_size(); } } ParScanClosure::ParScanClosure(ParNewGeneration* g, ! ParScanThreadState* par_scan_state) : ! OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g) ! { ! assert(_g->level() == 0, "Optimized for youngest generation"); _boundary = _g->reserved().end(); } void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); } void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); } --- 486,499 ---- CFLS_LAB::compute_desired_plab_size(); } } ParScanClosure::ParScanClosure(ParNewGeneration* g, ! ParScanThreadState* par_scan_state) ! : OopsInKlassOrGenClosure(g), ! _par_scan_state(par_scan_state), ! _g(g) { _boundary = _g->reserved().end(); } void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); } void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); }
*** 509,553 **** void ParRootScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, true); } void ParRootScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, true); } ParScanWeakRefClosure::ParScanWeakRefClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) ! : ScanWeakRefClosure(g), _par_scan_state(par_scan_state) ! {} void ParScanWeakRefClosure::do_oop(oop* p) { ParScanWeakRefClosure::do_oop_work(p); } void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); } #ifdef WIN32 #pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */ #endif ! ParEvacuateFollowersClosure::ParEvacuateFollowersClosure( ! ParScanThreadState* par_scan_state_, ! ParScanWithoutBarrierClosure* to_space_closure_, ! ParScanWithBarrierClosure* old_gen_closure_, ! ParRootScanWithoutBarrierClosure* to_space_root_closure_, ! ParNewGeneration* par_gen_, ! ParRootScanWithBarrierTwoGensClosure* old_gen_root_closure_, ! ObjToScanQueueSet* task_queues_, ! ParallelTaskTerminator* terminator_) : ! ! _par_scan_state(par_scan_state_), ! _to_space_closure(to_space_closure_), ! _old_gen_closure(old_gen_closure_), ! _to_space_root_closure(to_space_root_closure_), ! _old_gen_root_closure(old_gen_root_closure_), ! _par_gen(par_gen_), ! _task_queues(task_queues_), ! _terminator(terminator_) ! {} void ParEvacuateFollowersClosure::do_void() { ObjToScanQueue* work_q = par_scan_state()->work_queue(); while (true) { - // Scan to-space and old-gen objs until we run out of both. oop obj_to_scan; par_scan_state()->trim_queues(0); // We have no local work, attempt to steal from other threads. --- 507,549 ---- void ParRootScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, true); } void ParRootScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, true); } ParScanWeakRefClosure::ParScanWeakRefClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) ! : ScanWeakRefClosure(g), ! _par_scan_state(par_scan_state) { ! } void ParScanWeakRefClosure::do_oop(oop* p) { ParScanWeakRefClosure::do_oop_work(p); } void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); } #ifdef WIN32 #pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */ #endif ! ParEvacuateFollowersClosure::ParEvacuateFollowersClosure(ParScanThreadState* par_scan_state, ! ParScanWithoutBarrierClosure* to_space_closure, ! ParScanWithBarrierClosure* old_gen_closure, ! ParRootScanWithoutBarrierClosure* to_space_root_closure, ! ParNewGeneration* par_gen, ! ParRootScanWithBarrierTwoGensClosure* old_gen_root_closure, ! ObjToScanQueueSet* task_queues, ! ParallelTaskTerminator* terminator) ! : _par_scan_state(par_scan_state), ! _to_space_closure(to_space_closure), ! _old_gen_closure(old_gen_closure), ! _to_space_root_closure(to_space_root_closure), ! _old_gen_root_closure(old_gen_root_closure), ! _par_gen(par_gen), ! _task_queues(task_queues), ! _terminator(terminator) { ! } void ParEvacuateFollowersClosure::do_void() { ObjToScanQueue* work_q = par_scan_state()->work_queue(); while (true) { // Scan to-space and old-gen objs until we run out of both. oop obj_to_scan; par_scan_state()->trim_queues(0); // We have no local work, attempt to steal from other threads.
*** 576,597 **** "Broken overflow list?"); // Finish the last termination pause. par_scan_state()->end_term_time(); } ! ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* next_gen, ! HeapWord* young_old_boundary, ParScanThreadStateSet* state_set) : ! AbstractGangTask("ParNewGeneration collection"), ! _gen(gen), _next_gen(next_gen), _young_old_boundary(young_old_boundary), ! _state_set(state_set) ! {} // Reset the terminator for the given number of // active threads. void ParNewGenTask::set_for_termination(int active_workers) { ! _state_set->reset(active_workers, _gen->promotion_failed()); // Should the heap be passed in? There's only 1 for now so // grab it instead. GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->set_n_termination(active_workers); } --- 572,595 ---- "Broken overflow list?"); // Finish the last termination pause. par_scan_state()->end_term_time(); } ! ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen, ! Generation* old_gen, ! HeapWord* young_old_boundary, ! ParScanThreadStateSet* state_set) ! : AbstractGangTask("ParNewGeneration collection"), ! _young_gen(young_gen), _old_gen(old_gen), _young_old_boundary(young_old_boundary), ! _state_set(state_set) { ! } // Reset the terminator for the given number of // active threads. void ParNewGenTask::set_for_termination(int active_workers) { ! _state_set->reset(active_workers, _young_gen->promotion_failed()); // Should the heap be passed in? There's only 1 for now so // grab it instead. GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->set_n_termination(active_workers); }
*** 600,613 **** GenCollectedHeap* gch = GenCollectedHeap::heap(); // Since this is being done in a separate thread, need new resource // and handle marks. ResourceMark rm; HandleMark hm; - // We would need multiple old-gen queues otherwise. - assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen."); ! Generation* old_gen = gch->next_gen(_gen); ParScanThreadState& par_scan_state = _state_set->thread_state(worker_id); assert(_state_set->is_valid(worker_id), "Should not have been called"); par_scan_state.set_young_old_boundary(_young_old_boundary); --- 598,609 ---- GenCollectedHeap* gch = GenCollectedHeap::heap(); // Since this is being done in a separate thread, need new resource // and handle marks. ResourceMark rm; HandleMark hm; ! Generation* old_gen = gch->old_gen(); ParScanThreadState& par_scan_state = _state_set->thread_state(worker_id); assert(_state_set->is_valid(worker_id), "Should not have been called"); par_scan_state.set_young_old_boundary(_young_old_boundary);
*** 617,627 **** CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure, &par_scan_state.to_space_root_closure(), false); par_scan_state.start_strong_roots(); ! gch->gen_process_roots(_gen->level(), true, // Process younger gens, if any, // as strong roots. false, // no scope; this is parallel code SharedHeap::SO_ScavengeCodeCache, GenCollectedHeap::StrongAndWeakRoots, --- 613,623 ---- CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure, &par_scan_state.to_space_root_closure(), false); par_scan_state.start_strong_roots(); ! gch->gen_process_roots(Generation::Young, true, // Process younger gens, if any, // as strong roots. false, // no scope; this is parallel code SharedHeap::SO_ScavengeCodeCache, GenCollectedHeap::StrongAndWeakRoots,
*** 638,653 **** #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif ParNewGeneration:: ! ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level) ! : DefNewGeneration(rs, initial_byte_size, level, "PCopy"), _overflow_list(NULL), _is_alive_closure(this), ! _plab_stats(YoungPLABSize, PLABWeight) ! { NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) NOT_PRODUCT(_num_par_pushes = 0;) _task_queues = new ObjToScanQueueSet(ParallelGCThreads); guarantee(_task_queues != NULL, "task_queues allocation failure."); --- 634,648 ---- #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif ParNewGeneration:: ! ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) ! : DefNewGeneration(rs, initial_byte_size, "PCopy"), _overflow_list(NULL), _is_alive_closure(this), ! _plab_stats(YoungPLABSize, PLABWeight) { NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) NOT_PRODUCT(_num_par_pushes = 0;) _task_queues = new ObjToScanQueueSet(ParallelGCThreads); guarantee(_task_queues != NULL, "task_queues allocation failure.");
*** 655,670 **** ObjToScanQueue *q = new ObjToScanQueue(); guarantee(q != NULL, "work_queue Allocation failure."); _task_queues->register_queue(i1, q); } ! for (uint i2 = 0; i2 < ParallelGCThreads; i2++) _task_queues->queue(i2)->initialize(); _overflow_stacks = NULL; if (ParGCUseLocalOverflow) { - // typedef to workaround NEW_C_HEAP_ARRAY macro, which can not deal // with ',' typedef Stack<oop, mtGC> GCOopStack; _overflow_stacks = NEW_C_HEAP_ARRAY(GCOopStack, ParallelGCThreads, mtGC); --- 650,665 ---- ObjToScanQueue *q = new ObjToScanQueue(); guarantee(q != NULL, "work_queue Allocation failure."); _task_queues->register_queue(i1, q); } ! for (uint i2 = 0; i2 < ParallelGCThreads; i2++) { _task_queues->queue(i2)->initialize(); + } _overflow_stacks = NULL; if (ParGCUseLocalOverflow) { // typedef to workaround NEW_C_HEAP_ARRAY macro, which can not deal // with ',' typedef Stack<oop, mtGC> GCOopStack; _overflow_stacks = NEW_C_HEAP_ARRAY(GCOopStack, ParallelGCThreads, mtGC);
*** 686,697 **** #ifdef _MSC_VER #pragma warning( pop ) #endif // ParNewGeneration:: ! ParKeepAliveClosure::ParKeepAliveClosure(ParScanWeakRefClosure* cl) : ! DefNewGeneration::KeepAliveClosure(cl), _par_cl(cl) {} template <class T> void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop_work(T* p) { #ifdef ASSERT { --- 681,693 ---- #ifdef _MSC_VER #pragma warning( pop ) #endif // ParNewGeneration:: ! ParKeepAliveClosure::ParKeepAliveClosure(ParScanWeakRefClosure* cl) ! : DefNewGeneration::KeepAliveClosure(cl), _par_cl(cl) { ! } template <class T> void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop_work(T* p) { #ifdef ASSERT {
*** 713,724 **** void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(oop* p) { ParKeepAliveClosure::do_oop_work(p); } void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(narrowOop* p) { ParKeepAliveClosure::do_oop_work(p); } // ParNewGeneration:: ! KeepAliveClosure::KeepAliveClosure(ScanWeakRefClosure* cl) : ! DefNewGeneration::KeepAliveClosure(cl) {} template <class T> void /*ParNewGeneration::*/KeepAliveClosure::do_oop_work(T* p) { #ifdef ASSERT { --- 709,721 ---- void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(oop* p) { ParKeepAliveClosure::do_oop_work(p); } void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(narrowOop* p) { ParKeepAliveClosure::do_oop_work(p); } // ParNewGeneration:: ! KeepAliveClosure::KeepAliveClosure(ScanWeakRefClosure* cl) ! : DefNewGeneration::KeepAliveClosure(cl) { ! } template <class T> void /*ParNewGeneration::*/KeepAliveClosure::do_oop_work(T* p) { #ifdef ASSERT {
*** 766,808 **** class ParNewRefProcTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; public: ParNewRefProcTaskProxy(ProcessTask& task, ParNewGeneration& gen, ! Generation& next_gen, HeapWord* young_old_boundary, ParScanThreadStateSet& state_set); private: virtual void work(uint worker_id); virtual void set_for_termination(int active_workers) { _state_set.terminator()->reset_for_reuse(active_workers); } private: ! ParNewGeneration& _gen; ProcessTask& _task; ! Generation& _next_gen; HeapWord* _young_old_boundary; ParScanThreadStateSet& _state_set; }; ! ParNewRefProcTaskProxy::ParNewRefProcTaskProxy( ! ProcessTask& task, ParNewGeneration& gen, ! Generation& next_gen, HeapWord* young_old_boundary, ParScanThreadStateSet& state_set) : AbstractGangTask("ParNewGeneration parallel reference processing"), ! _gen(gen), _task(task), ! _next_gen(next_gen), _young_old_boundary(young_old_boundary), ! _state_set(state_set) ! { } ! void ParNewRefProcTaskProxy::work(uint worker_id) ! { ResourceMark rm; HandleMark hm; ParScanThreadState& par_scan_state = _state_set.thread_state(worker_id); par_scan_state.set_young_old_boundary(_young_old_boundary); _task.work(worker_id, par_scan_state.is_alive_closure(), --- 763,803 ---- class ParNewRefProcTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; public: ParNewRefProcTaskProxy(ProcessTask& task, ParNewGeneration& gen, ! Generation& old_gen, HeapWord* young_old_boundary, ParScanThreadStateSet& state_set); private: virtual void work(uint worker_id); virtual void set_for_termination(int active_workers) { _state_set.terminator()->reset_for_reuse(active_workers); } private: ! ParNewGeneration& _young_gen; ProcessTask& _task; ! Generation& _old_gen; HeapWord* _young_old_boundary; ParScanThreadStateSet& _state_set; }; ! ParNewRefProcTaskProxy::ParNewRefProcTaskProxy(ProcessTask& task, ! ParNewGeneration& young_gen, ! Generation& old_gen, HeapWord* young_old_boundary, ParScanThreadStateSet& state_set) : AbstractGangTask("ParNewGeneration parallel reference processing"), ! _young_gen(young_gen), _task(task), ! _old_gen(old_gen), _young_old_boundary(young_old_boundary), ! _state_set(state_set) { } ! void ParNewRefProcTaskProxy::work(uint worker_id) { ResourceMark rm; HandleMark hm; ParScanThreadState& par_scan_state = _state_set.thread_state(worker_id); par_scan_state.set_young_old_boundary(_young_old_boundary); _task.work(worker_id, par_scan_state.is_alive_closure(),
*** 815,894 **** EnqueueTask& _task; public: ParNewRefEnqueueTaskProxy(EnqueueTask& task) : AbstractGangTask("ParNewGeneration parallel reference enqueue"), ! _task(task) ! { } ! virtual void work(uint worker_id) ! { _task.work(worker_id); } }; ! ! void ParNewRefProcTaskExecutor::execute(ProcessTask& task) ! { GenCollectedHeap* gch = GenCollectedHeap::heap(); assert(gch->kind() == CollectedHeap::GenCollectedHeap, "not a generational heap"); FlexibleWorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); _state_set.reset(workers->active_workers(), _generation.promotion_failed()); ! ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(), _generation.reserved().end(), _state_set); workers->run_task(&rp_task); _state_set.reset(0 /* bad value in debug if not reset */, _generation.promotion_failed()); } ! void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) ! { GenCollectedHeap* gch = GenCollectedHeap::heap(); FlexibleWorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); ParNewRefEnqueueTaskProxy enq_task(task); workers->run_task(&enq_task); } ! void ParNewRefProcTaskExecutor::set_single_threaded_mode() ! { _state_set.flush(); GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->set_par_threads(0); // 0 ==> non-parallel. gch->save_marks(); } ! ScanClosureWithParBarrier:: ! ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) : ! ScanClosure(g, gc_barrier) {} EvacuateFollowersClosureGeneral:: ! EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level, OopsInGenClosure* cur, ! OopsInGenClosure* older) : ! _gch(gch), _level(level), ! _scan_cur_or_nonheap(cur), _scan_older(older) ! {} void EvacuateFollowersClosureGeneral::do_void() { do { // Beware: this call will lead to closure applications via virtual // calls. ! _gch->oop_since_save_marks_iterate(_level, _scan_cur_or_nonheap, _scan_older); ! } while (!_gch->no_allocs_since_save_marks(_level)); } // A Generation that does parallel young-gen collection. bool ParNewGeneration::_avoid_promotion_undo = false; ! void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer) { assert(_promo_failure_scan_stack.is_empty(), "post condition"); _promo_failure_scan_stack.clear(true); // Clear cached segments. remove_forwarding_pointers(); if (PrintGCDetails) { --- 810,888 ---- EnqueueTask& _task; public: ParNewRefEnqueueTaskProxy(EnqueueTask& task) : AbstractGangTask("ParNewGeneration parallel reference enqueue"), ! _task(task) { ! } ! virtual void work(uint worker_id) { _task.work(worker_id); } }; ! void ParNewRefProcTaskExecutor::execute(ProcessTask& task) { GenCollectedHeap* gch = GenCollectedHeap::heap(); assert(gch->kind() == CollectedHeap::GenCollectedHeap, "not a generational heap"); FlexibleWorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); _state_set.reset(workers->active_workers(), _generation.promotion_failed()); ! ParNewRefProcTaskProxy rp_task(task, _generation, *(gch->old_gen()), _generation.reserved().end(), _state_set); workers->run_task(&rp_task); _state_set.reset(0 /* bad value in debug if not reset */, _generation.promotion_failed()); } ! void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) { GenCollectedHeap* gch = GenCollectedHeap::heap(); FlexibleWorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); ParNewRefEnqueueTaskProxy enq_task(task); workers->run_task(&enq_task); } ! void ParNewRefProcTaskExecutor::set_single_threaded_mode() { _state_set.flush(); GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->set_par_threads(0); // 0 ==> non-parallel. gch->save_marks(); } ! ScanClosureWithParBarrier::ScanClosureWithParBarrier(ParNewGeneration* g, ! bool gc_barrier) ! : ScanClosure(g, gc_barrier) { ! } EvacuateFollowersClosureGeneral:: ! EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, OopsInGenClosure* cur, ! OopsInGenClosure* older) ! : _gch(gch), ! _scan_cur_or_nonheap(cur), ! _scan_older(older) { ! } void EvacuateFollowersClosureGeneral::do_void() { do { // Beware: this call will lead to closure applications via virtual // calls. ! _gch->oop_since_save_marks_iterate(Generation::Young, _scan_cur_or_nonheap, _scan_older); ! } while (!_gch->no_allocs_since_save_marks(true /* include_young */)); } // A Generation that does parallel young-gen collection. bool ParNewGeneration::_avoid_promotion_undo = false; ! void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ! ParScanThreadStateSet& thread_state_set, ! ParNewTracer& gc_tracer) { assert(_promo_failure_scan_stack.is_empty(), "post condition"); _promo_failure_scan_stack.clear(true); // Clear cached segments. remove_forwarding_pointers(); if (PrintGCDetails) {
*** 897,907 **** // All the spaces are in play for mark-sweep. swap_spaces(); // Make life simpler for CMS || rescan; see 6483690. from()->set_next_compaction_space(to()); gch->set_incremental_collection_failed(); // Inform the next generation that a promotion failure occurred. ! _next_gen->promotion_failure_occurred(); // Trace promotion failure in the parallel GC threads thread_state_set.trace_promotion_failed(gc_tracer); // Single threaded code may have reported promotion failure to the global state if (_promotion_failed_info.has_failed()) { --- 891,901 ---- // All the spaces are in play for mark-sweep. swap_spaces(); // Make life simpler for CMS || rescan; see 6483690. from()->set_next_compaction_space(to()); gch->set_incremental_collection_failed(); // Inform the next generation that a promotion failure occurred. ! _old_gen->promotion_failure_occurred(); // Trace promotion failure in the parallel GC threads thread_state_set.trace_promotion_failed(gc_tracer); // Single threaded code may have reported promotion failure to the global state if (_promotion_failed_info.has_failed()) {
*** 929,941 **** int active_workers = AdaptiveSizePolicy::calc_active_workers(workers->total_workers(), workers->active_workers(), Threads::number_of_non_daemon_threads()); workers->set_active_workers(active_workers); ! assert(gch->n_gens() == 2, ! "Par collection currently only works with single older gen."); ! _next_gen = gch->next_gen(this); // Do we have to avoid promotion_undo? if (gch->collector_policy()->is_concurrent_mark_sweep_policy()) { set_avoid_promotion_undo(true); } --- 923,933 ---- int active_workers = AdaptiveSizePolicy::calc_active_workers(workers->total_workers(), workers->active_workers(), Threads::number_of_non_daemon_threads()); workers->set_active_workers(active_workers); ! _old_gen = gch->old_gen(); // Do we have to avoid promotion_undo? if (gch->collector_policy()->is_concurrent_mark_sweep_policy()) { set_avoid_promotion_undo(true); }
*** 977,990 **** // Always set the terminator for the active number of workers // because only those workers go through the termination protocol. ParallelTaskTerminator _term(n_workers, task_queues()); ParScanThreadStateSet thread_state_set(workers->active_workers(), ! *to(), *this, *_next_gen, *task_queues(), _overflow_stacks, desired_plab_sz(), _term); ! ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set); gch->set_par_threads(n_workers); gch->rem_set()->prepare_for_younger_refs_iterate(true); // It turns out that even when we're using 1 thread, doing the work in a // separate thread causes wide variance in run times. We can't help this // in the multi-threaded case, but we special-case n=1 here to get --- 969,982 ---- // Always set the terminator for the active number of workers // because only those workers go through the termination protocol. ParallelTaskTerminator _term(n_workers, task_queues()); ParScanThreadStateSet thread_state_set(workers->active_workers(), ! *to(), *this, *_old_gen, *task_queues(), _overflow_stacks, desired_plab_sz(), _term); ! ParNewGenTask tsk(this, _old_gen, reserved().end(), &thread_state_set); gch->set_par_threads(n_workers); gch->rem_set()->prepare_for_younger_refs_iterate(true); // It turns out that even when we're using 1 thread, doing the work in a // separate thread causes wide variance in run times. We can't help this // in the multi-threaded case, but we special-case n=1 here to get
*** 1005,1015 **** ScanWeakRefClosure scan_weak_ref(this); KeepAliveClosure keep_alive(&scan_weak_ref); ScanClosure scan_without_gc_barrier(this, false); ScanClosureWithParBarrier scan_with_gc_barrier(this, true); set_promo_failure_scan_stack_closure(&scan_without_gc_barrier); ! EvacuateFollowersClosureGeneral evacuate_followers(gch, _level, &scan_without_gc_barrier, &scan_with_gc_barrier); rp->setup_policy(clear_all_soft_refs); // Can the mt_degree be set later (at run_task() time would be best)? rp->set_active_mt_degree(active_workers); ReferenceProcessorStats stats; --- 997,1007 ---- ScanWeakRefClosure scan_weak_ref(this); KeepAliveClosure keep_alive(&scan_weak_ref); ScanClosure scan_without_gc_barrier(this, false); ScanClosureWithParBarrier scan_with_gc_barrier(this, true); set_promo_failure_scan_stack_closure(&scan_without_gc_barrier); ! EvacuateFollowersClosureGeneral evacuate_followers(gch, &scan_without_gc_barrier, &scan_with_gc_barrier); rp->setup_policy(clear_all_soft_refs); // Can the mt_degree be set later (at run_task() time would be best)? rp->set_active_mt_degree(active_workers); ReferenceProcessorStats stats;
*** 1194,1205 **** if (forward_ptr != NULL) { // someone else beat us to it. return real_forwardee(old); } ! new_obj = _next_gen->par_promote(par_scan_state->thread_num(), ! old, m, sz); if (new_obj == NULL) { // promotion failed, forward to self _promotion_failed = true; new_obj = old; --- 1186,1196 ---- if (forward_ptr != NULL) { // someone else beat us to it. return real_forwardee(old); } ! new_obj = _old_gen->par_promote(par_scan_state->thread_num(), old, m, sz); if (new_obj == NULL) { // promotion failed, forward to self _promotion_failed = true; new_obj = old;
*** 1226,1236 **** // This code must come after the CAS test, or it will print incorrect // information. if (TraceScavenge) { gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", is_in_reserved(new_obj) ? "copying" : "tenuring", ! new_obj->klass()->internal_name(), (void *)old, (void *)new_obj, new_obj->size()); } #endif if (forward_ptr == NULL) { oop obj_to_push = new_obj; --- 1217,1230 ---- // This code must come after the CAS test, or it will print incorrect // information. if (TraceScavenge) { gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", is_in_reserved(new_obj) ? "copying" : "tenuring", ! new_obj->klass()->internal_name(), ! (void *)old, ! (void *)new_obj, ! new_obj->size()); } #endif if (forward_ptr == NULL) { oop obj_to_push = new_obj;
*** 1312,1322 **** } if (new_obj == NULL) { // Either to-space is full or we decided to promote // try allocating obj tenured ! new_obj = _next_gen->par_promote(par_scan_state->thread_num(), old, m, sz); if (new_obj == NULL) { // promotion failed, forward to self forward_ptr = old->forward_to_atomic(old); --- 1306,1316 ---- } if (new_obj == NULL) { // Either to-space is full or we decided to promote // try allocating obj tenured ! new_obj = _old_gen->par_promote(par_scan_state->thread_num(), old, m, sz); if (new_obj == NULL) { // promotion failed, forward to self forward_ptr = old->forward_to_atomic(old);
*** 1347,1357 **** // This code must come after the CAS test, or it will print incorrect // information. if (TraceScavenge) { gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", is_in_reserved(new_obj) ? "copying" : "tenuring", ! new_obj->klass()->internal_name(), (void *)old, (void *)new_obj, new_obj->size()); } #endif // Now attempt to install the forwarding pointer (atomically). // We have to copy the mark word before overwriting with forwarding --- 1341,1354 ---- // This code must come after the CAS test, or it will print incorrect // information. if (TraceScavenge) { gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", is_in_reserved(new_obj) ? "copying" : "tenuring", ! new_obj->klass()->internal_name(), ! (void*)old, ! (void*)new_obj, ! new_obj->size()); } #endif // Now attempt to install the forwarding pointer (atomically). // We have to copy the mark word before overwriting with forwarding
*** 1393,1403 **** // Must be in to_space. assert(to()->is_in_reserved(new_obj), "Checking"); par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz); } else { assert(!_avoid_promotion_undo, "Should not be here if avoiding."); ! _next_gen->par_promote_alloc_undo(par_scan_state->thread_num(), (HeapWord*)new_obj, sz); } return forward_ptr; } --- 1390,1400 ---- // Must be in to_space. assert(to()->is_in_reserved(new_obj), "Checking"); par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz); } else { assert(!_avoid_promotion_undo, "Should not be here if avoiding."); ! _old_gen->par_promote_alloc_undo(par_scan_state->thread_num(), (HeapWord*)new_obj, sz); } return forward_ptr; }
*** 1509,1519 **** size_t objsFromOverflow = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, (size_t)ParGCDesiredObjsFromOverflowList); assert(!UseCompressedOops, "Error"); assert(par_scan_state->overflow_stack() == NULL, "Error"); ! if (_overflow_list == NULL) return false; // Otherwise, there was something there; try claiming the list. oop prefix = cast_to_oop(Atomic::xchg_ptr(BUSY, &_overflow_list)); // Trim off a prefix of at most objsFromOverflow items Thread* tid = Thread::current(); --- 1506,1518 ---- size_t objsFromOverflow = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, (size_t)ParGCDesiredObjsFromOverflowList); assert(!UseCompressedOops, "Error"); assert(par_scan_state->overflow_stack() == NULL, "Error"); ! if (_overflow_list == NULL) { ! return false; ! } // Otherwise, there was something there; try claiming the list. oop prefix = cast_to_oop(Atomic::xchg_ptr(BUSY, &_overflow_list)); // Trim off a prefix of at most objsFromOverflow items Thread* tid = Thread::current();
src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File