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

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

Print this page
rev 7212 : [mq]: remove_get_gen


 309 
 310   inline ParScanThreadState& thread_state(int i);
 311 
 312   void trace_promotion_failed(YoungGCTracer& gc_tracer);
 313   void reset(int active_workers, bool promotion_failed);
 314   void flush();
 315 
 316   #if TASKQUEUE_STATS
 317   static void
 318     print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
 319   void print_termination_stats(outputStream* const st = gclog_or_tty);
 320   static void
 321     print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty);
 322   void print_taskqueue_stats(outputStream* const st = gclog_or_tty);
 323   void reset_stats();
 324   #endif // TASKQUEUE_STATS
 325 
 326 private:
 327   ParallelTaskTerminator& _term;
 328   ParNewGeneration&       _gen;
 329   Generation&             _next_gen;
 330  public:
 331   bool is_valid(int id) const { return id < length(); }
 332   ParallelTaskTerminator* terminator() { return &_term; }
 333 };
 334 
 335 
 336 ParScanThreadStateSet::ParScanThreadStateSet(
 337   int num_threads, Space& to_space, ParNewGeneration& gen,
 338   Generation& old_gen, ObjToScanQueueSet& queue_set,
 339   Stack<oop, mtGC>* overflow_stacks,
 340   size_t desired_plab_sz, ParallelTaskTerminator& term)
 341   : ResourceArray(sizeof(ParScanThreadState), num_threads),
 342     _gen(gen), _next_gen(old_gen), _term(term)
 343 {
 344   assert(num_threads > 0, "sanity check!");
 345   assert(ParGCUseLocalOverflow == (overflow_stacks != NULL),
 346          "overflow_stack allocation mismatch");
 347   // Initialize states.
 348   for (int i = 0; i < num_threads; ++i) {
 349     new ((ParScanThreadState*)_data + i)
 350         ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
 351                            overflow_stacks, desired_plab_sz, term);
 352   }
 353 }
 354 
 355 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i)
 356 {
 357   assert(i >= 0 && i < length(), "sanity check!");
 358   return ((ParScanThreadState*)_data)[i];
 359 }
 360 
 361 void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) {
 362   for (int i = 0; i < length(); ++i) {


 458   // Work in this loop should be kept as lightweight as
 459   // possible since this might otherwise become a bottleneck
 460   // to scaling. Should we add heavy-weight work into this
 461   // loop, consider parallelizing the loop into the worker threads.
 462   for (int i = 0; i < length(); ++i) {
 463     ParScanThreadState& par_scan_state = thread_state(i);
 464 
 465     // Flush stats related to To-space PLAB activity and
 466     // retire the last buffer.
 467     par_scan_state.to_space_alloc_buffer()->
 468       flush_stats_and_retire(_gen.plab_stats(),
 469                              true /* end_of_gc */,
 470                              false /* retain */);
 471 
 472     // Every thread has its own age table.  We need to merge
 473     // them all into one.
 474     ageTable *local_table = par_scan_state.age_table();
 475     _gen.age_table()->merge(local_table);
 476 
 477     // Inform old gen that we're done.
 478     _next_gen.par_promote_alloc_done(i);
 479     _next_gen.par_oop_since_save_marks_iterate_done(i);
 480   }
 481 
 482   if (UseConcMarkSweepGC && ParallelGCThreads > 0) {
 483     // We need to call this even when ResizeOldPLAB is disabled
 484     // so as to avoid breaking some asserts. While we may be able
 485     // to avoid this by reorganizing the code a bit, I am loathe
 486     // to do that unless we find cases where ergo leads to bad
 487     // performance.
 488     CFLS_LAB::compute_desired_plab_size();
 489   }
 490 }
 491 
 492 ParScanClosure::ParScanClosure(ParNewGeneration* g,
 493                                ParScanThreadState* par_scan_state) :
 494   OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g)
 495 {
 496   assert(_g->level() == 0, "Optimized for youngest generation");
 497   _boundary = _g->reserved().end();
 498 }
 499 


 561 
 562       //   if successful, goto Start.
 563       continue;
 564 
 565       // try global overflow list.
 566     } else if (par_gen()->take_from_overflow_list(par_scan_state())) {
 567       continue;
 568     }
 569 
 570     // Otherwise, offer termination.
 571     par_scan_state()->start_term_time();
 572     if (terminator()->offer_termination()) break;
 573     par_scan_state()->end_term_time();
 574   }
 575   assert(par_gen()->_overflow_list == NULL && par_gen()->_num_par_pushes == 0,
 576          "Broken overflow list?");
 577   // Finish the last termination pause.
 578   par_scan_state()->end_term_time();
 579 }
 580 
 581 ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* next_gen,
 582                 HeapWord* young_old_boundary, ParScanThreadStateSet* state_set) :
 583     AbstractGangTask("ParNewGeneration collection"),
 584     _gen(gen), _next_gen(next_gen),
 585     _young_old_boundary(young_old_boundary),
 586     _state_set(state_set)
 587   {}
 588 
 589 // Reset the terminator for the given number of
 590 // active threads.
 591 void ParNewGenTask::set_for_termination(int active_workers) {
 592   _state_set->reset(active_workers, _gen->promotion_failed());
 593   // Should the heap be passed in?  There's only 1 for now so
 594   // grab it instead.
 595   GenCollectedHeap* gch = GenCollectedHeap::heap();
 596   gch->set_n_termination(active_workers);
 597 }
 598 
 599 void ParNewGenTask::work(uint worker_id) {
 600   GenCollectedHeap* gch = GenCollectedHeap::heap();
 601   // Since this is being done in a separate thread, need new resource
 602   // and handle marks.
 603   ResourceMark rm;
 604   HandleMark hm;
 605   // We would need multiple old-gen queues otherwise.
 606   assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen.");
 607 
 608   Generation* old_gen = gch->next_gen(_gen);
 609 
 610   ParScanThreadState& par_scan_state = _state_set->thread_state(worker_id);
 611   assert(_state_set->is_valid(worker_id), "Should not have been called");
 612 
 613   par_scan_state.set_young_old_boundary(_young_old_boundary);
 614 
 615   KlassScanClosure klass_scan_closure(&par_scan_state.to_space_root_closure(),
 616                                       gch->rem_set()->klass_rem_set());
 617   CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure,
 618                                            &par_scan_state.to_space_root_closure(),
 619                                            false);
 620 
 621   par_scan_state.start_strong_roots();
 622   gch->gen_process_roots(_gen->level(),
 623                          true,  // Process younger gens, if any,
 624                                 // as strong roots.
 625                          false, // no scope; this is parallel code
 626                          SharedHeap::SO_ScavengeCodeCache,
 627                          GenCollectedHeap::StrongAndWeakRoots,
 628                          &par_scan_state.to_space_root_closure(),


 751                       ? obj->forwardee()
 752                       : _g->DefNewGeneration::copy_to_survivor_space(obj);
 753       oopDesc::encode_store_heap_oop_not_null(p, new_obj);
 754     }
 755     if (_gc_barrier) {
 756       // If p points to a younger generation, mark the card.
 757       if ((HeapWord*)obj < _gen_boundary) {
 758         _rs->write_ref_field_gc_par(p, obj);
 759       }
 760     }
 761   }
 762 }
 763 
 764 void ScanClosureWithParBarrier::do_oop(oop* p)       { ScanClosureWithParBarrier::do_oop_work(p); }
 765 void ScanClosureWithParBarrier::do_oop(narrowOop* p) { ScanClosureWithParBarrier::do_oop_work(p); }
 766 
 767 class ParNewRefProcTaskProxy: public AbstractGangTask {
 768   typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
 769 public:
 770   ParNewRefProcTaskProxy(ProcessTask& task, ParNewGeneration& gen,
 771                          Generation& next_gen,
 772                          HeapWord* young_old_boundary,
 773                          ParScanThreadStateSet& state_set);
 774 
 775 private:
 776   virtual void work(uint worker_id);
 777   virtual void set_for_termination(int active_workers) {
 778     _state_set.terminator()->reset_for_reuse(active_workers);
 779   }
 780 private:
 781   ParNewGeneration&      _gen;
 782   ProcessTask&           _task;
 783   Generation&            _next_gen;
 784   HeapWord*              _young_old_boundary;
 785   ParScanThreadStateSet& _state_set;
 786 };
 787 
 788 ParNewRefProcTaskProxy::ParNewRefProcTaskProxy(
 789     ProcessTask& task, ParNewGeneration& gen,
 790     Generation& next_gen,
 791     HeapWord* young_old_boundary,
 792     ParScanThreadStateSet& state_set)
 793   : AbstractGangTask("ParNewGeneration parallel reference processing"),
 794     _gen(gen),
 795     _task(task),
 796     _next_gen(next_gen),
 797     _young_old_boundary(young_old_boundary),
 798     _state_set(state_set)
 799 {
 800 }
 801 
 802 void ParNewRefProcTaskProxy::work(uint worker_id)
 803 {
 804   ResourceMark rm;
 805   HandleMark hm;
 806   ParScanThreadState& par_scan_state = _state_set.thread_state(worker_id);
 807   par_scan_state.set_young_old_boundary(_young_old_boundary);
 808   _task.work(worker_id, par_scan_state.is_alive_closure(),
 809              par_scan_state.keep_alive_closure(),
 810              par_scan_state.evacuate_followers_closure());
 811 }
 812 
 813 class ParNewRefEnqueueTaskProxy: public AbstractGangTask {
 814   typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
 815   EnqueueTask& _task;
 816 


 882 }
 883 
 884 
 885 // A Generation that does parallel young-gen collection.
 886 
 887 bool ParNewGeneration::_avoid_promotion_undo = false;
 888 
 889 void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer) {
 890   assert(_promo_failure_scan_stack.is_empty(), "post condition");
 891   _promo_failure_scan_stack.clear(true); // Clear cached segments.
 892 
 893   remove_forwarding_pointers();
 894   if (PrintGCDetails) {
 895     gclog_or_tty->print(" (promotion failed)");
 896   }
 897   // All the spaces are in play for mark-sweep.
 898   swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
 899   from()->set_next_compaction_space(to());
 900   gch->set_incremental_collection_failed();
 901   // Inform the next generation that a promotion failure occurred.
 902   _next_gen->promotion_failure_occurred();
 903 
 904   // Trace promotion failure in the parallel GC threads
 905   thread_state_set.trace_promotion_failed(gc_tracer);
 906   // Single threaded code may have reported promotion failure to the global state
 907   if (_promotion_failed_info.has_failed()) {
 908     gc_tracer.report_promotion_failed(_promotion_failed_info);
 909   }
 910   // Reset the PromotionFailureALot counters.
 911   NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
 912 }
 913 
 914 void ParNewGeneration::collect(bool   full,
 915                                bool   clear_all_soft_refs,
 916                                size_t size,
 917                                bool   is_tlab) {
 918   assert(full || size > 0, "otherwise we don't want to collect");
 919 
 920   GenCollectedHeap* gch = GenCollectedHeap::heap();
 921 
 922   _gc_timer->register_gc_start();
 923 
 924   assert(gch->kind() == CollectedHeap::GenCollectedHeap,
 925     "not a CMS generational heap");
 926   AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
 927   FlexibleWorkGang* workers = gch->workers();
 928   assert(workers != NULL, "Need workgang for parallel work");
 929   int active_workers =
 930       AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
 931                                    workers->active_workers(),
 932                                    Threads::number_of_non_daemon_threads());
 933   workers->set_active_workers(active_workers);
 934   assert(gch->n_gens() == 2,
 935          "Par collection currently only works with single older gen.");
 936   _next_gen = gch->next_gen(this);
 937   // Do we have to avoid promotion_undo?
 938   if (gch->collector_policy()->is_concurrent_mark_sweep_policy()) {
 939     set_avoid_promotion_undo(true);
 940   }
 941 
 942   // If the next generation is too full to accommodate worst-case promotion
 943   // from this generation, pass on collection; let the next generation
 944   // do it.
 945   if (!collection_attempt_is_safe()) {
 946     gch->set_incremental_collection_failed();  // slight lie, in that we did not even attempt one
 947     return;
 948   }
 949   assert(to()->is_empty(), "Else not collection_attempt_is_safe");
 950 
 951   ParNewTracer gc_tracer;
 952   gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start());
 953   gch->trace_heap_before_gc(&gc_tracer);
 954 
 955   init_assuming_no_promotion_failure();
 956 


 962   GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id());
 963   // Capture heap used before collection (for printing).
 964   size_t gch_prev_used = gch->used();
 965 
 966   SpecializationStats::clear();
 967 
 968   age_table()->clear();
 969   to()->clear(SpaceDecorator::Mangle);
 970 
 971   gch->save_marks();
 972   assert(workers != NULL, "Need parallel worker threads.");
 973   int n_workers = active_workers;
 974 
 975   // Set the correct parallelism (number of queues) in the reference processor
 976   ref_processor()->set_active_mt_degree(n_workers);
 977 
 978   // Always set the terminator for the active number of workers
 979   // because only those workers go through the termination protocol.
 980   ParallelTaskTerminator _term(n_workers, task_queues());
 981   ParScanThreadStateSet thread_state_set(workers->active_workers(),
 982                                          *to(), *this, *_next_gen, *task_queues(),
 983                                          _overflow_stacks, desired_plab_sz(), _term);
 984 
 985   ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
 986   gch->set_par_threads(n_workers);
 987   gch->rem_set()->prepare_for_younger_refs_iterate(true);
 988   // It turns out that even when we're using 1 thread, doing the work in a
 989   // separate thread causes wide variance in run times.  We can't help this
 990   // in the multi-threaded case, but we special-case n=1 here to get
 991   // repeatable measurements of the 1-thread overhead of the parallel code.
 992   if (n_workers > 1) {
 993     GenCollectedHeap::StrongRootsScope srs(gch);
 994     workers->run_task(&tsk);
 995   } else {
 996     GenCollectedHeap::StrongRootsScope srs(gch);
 997     tsk.work(0);
 998   }
 999   thread_state_set.reset(0 /* Bad value in debug if not reset */,
1000                          promotion_failed());
1001 
1002   // Process (weak) reference objects found during scavenge.
1003   ReferenceProcessor* rp = ref_processor();
1004   IsAliveClosure is_alive(this);
1005   ScanWeakRefClosure scan_weak_ref(this);


1179   // Try allocating obj in to-space (unless too old)
1180   if (dummyOld.age() < tenuring_threshold()) {
1181     new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
1182     if (new_obj == NULL) {
1183       set_survivor_overflow(true);
1184     }
1185   }
1186 
1187   if (new_obj == NULL) {
1188     // Either to-space is full or we decided to promote
1189     // try allocating obj tenured
1190 
1191     // Attempt to install a null forwarding pointer (atomically),
1192     // to claim the right to install the real forwarding pointer.
1193     forward_ptr = old->forward_to_atomic(ClaimedForwardPtr);
1194     if (forward_ptr != NULL) {
1195       // someone else beat us to it.
1196         return real_forwardee(old);
1197     }
1198 
1199     new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
1200                                        old, m, sz);
1201 
1202     if (new_obj == NULL) {
1203       // promotion failed, forward to self
1204       _promotion_failed = true;
1205       new_obj = old;
1206 
1207       preserve_mark_if_necessary(old, m);
1208       par_scan_state->register_promotion_failure(sz);
1209     }
1210 
1211     old->forward_to(new_obj);
1212     forward_ptr = NULL;
1213   } else {
1214     // Is in to-space; do copying ourselves.
1215     Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
1216     forward_ptr = old->forward_to_atomic(new_obj);
1217     // Restore the mark word copied above.
1218     new_obj->set_mark(m);
1219     // Increment age if obj still in new generation


1297   oopDesc dummyOld;
1298   dummyOld.set_mark(m);
1299   assert(!dummyOld.is_forwarded(),
1300          "should not be called with forwarding pointer mark word.");
1301 
1302   bool failed_to_promote = false;
1303   oop new_obj = NULL;
1304   oop forward_ptr;
1305 
1306   // Try allocating obj in to-space (unless too old)
1307   if (dummyOld.age() < tenuring_threshold()) {
1308     new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
1309     if (new_obj == NULL) {
1310       set_survivor_overflow(true);
1311     }
1312   }
1313 
1314   if (new_obj == NULL) {
1315     // Either to-space is full or we decided to promote
1316     // try allocating obj tenured
1317     new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
1318                                        old, m, sz);
1319 
1320     if (new_obj == NULL) {
1321       // promotion failed, forward to self
1322       forward_ptr = old->forward_to_atomic(old);
1323       new_obj = old;
1324 
1325       if (forward_ptr != NULL) {
1326         return forward_ptr;   // someone else succeeded
1327       }
1328 
1329       _promotion_failed = true;
1330       failed_to_promote = true;
1331 
1332       preserve_mark_if_necessary(old, m);
1333       par_scan_state->register_promotion_failure(sz);
1334     }
1335   } else {
1336     // Is in to-space; do copying ourselves.
1337     Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);


1378         simulate_overflow = true;
1379       }
1380     )
1381     if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) {
1382       // Add stats for overflow pushes.
1383       push_on_overflow_list(old, par_scan_state);
1384       TASKQUEUE_STATS_ONLY(par_scan_state->taskqueue_stats().record_overflow(0));
1385     }
1386 
1387     return new_obj;
1388   }
1389 
1390   // Oops.  Someone beat us to it.  Undo the allocation.  Where did we
1391   // allocate it?
1392   if (is_in_reserved(new_obj)) {
1393     // Must be in to_space.
1394     assert(to()->is_in_reserved(new_obj), "Checking");
1395     par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
1396   } else {
1397     assert(!_avoid_promotion_undo, "Should not be here if avoiding.");
1398     _next_gen->par_promote_alloc_undo(par_scan_state->thread_num(),
1399                                       (HeapWord*)new_obj, sz);
1400   }
1401 
1402   return forward_ptr;
1403 }
1404 
1405 #ifndef PRODUCT
1406 // It's OK to call this multi-threaded;  the worst thing
1407 // that can happen is that we'll get a bunch of closely
1408 // spaced simulated overflows, but that's OK, in fact
1409 // probably good as it would exercise the overflow code
1410 // under contention.
1411 bool ParNewGeneration::should_simulate_overflow() {
1412   if (_overflow_counter-- <= 0) { // just being defensive
1413     _overflow_counter = ParGCWorkQueueOverflowInterval;
1414     return true;
1415   } else {
1416     return false;
1417   }
1418 }




 309 
 310   inline ParScanThreadState& thread_state(int i);
 311 
 312   void trace_promotion_failed(YoungGCTracer& gc_tracer);
 313   void reset(int active_workers, bool promotion_failed);
 314   void flush();
 315 
 316   #if TASKQUEUE_STATS
 317   static void
 318     print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
 319   void print_termination_stats(outputStream* const st = gclog_or_tty);
 320   static void
 321     print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty);
 322   void print_taskqueue_stats(outputStream* const st = gclog_or_tty);
 323   void reset_stats();
 324   #endif // TASKQUEUE_STATS
 325 
 326 private:
 327   ParallelTaskTerminator& _term;
 328   ParNewGeneration&       _gen;
 329   Generation&             _old_gen;
 330  public:
 331   bool is_valid(int id) const { return id < length(); }
 332   ParallelTaskTerminator* terminator() { return &_term; }
 333 };
 334 
 335 
 336 ParScanThreadStateSet::ParScanThreadStateSet(
 337   int num_threads, Space& to_space, ParNewGeneration& gen,
 338   Generation& old_gen, ObjToScanQueueSet& queue_set,
 339   Stack<oop, mtGC>* overflow_stacks,
 340   size_t desired_plab_sz, ParallelTaskTerminator& term)
 341   : ResourceArray(sizeof(ParScanThreadState), num_threads),
 342     _gen(gen), _old_gen(old_gen), _term(term)
 343 {
 344   assert(num_threads > 0, "sanity check!");
 345   assert(ParGCUseLocalOverflow == (overflow_stacks != NULL),
 346          "overflow_stack allocation mismatch");
 347   // Initialize states.
 348   for (int i = 0; i < num_threads; ++i) {
 349     new ((ParScanThreadState*)_data + i)
 350         ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
 351                            overflow_stacks, desired_plab_sz, term);
 352   }
 353 }
 354 
 355 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i)
 356 {
 357   assert(i >= 0 && i < length(), "sanity check!");
 358   return ((ParScanThreadState*)_data)[i];
 359 }
 360 
 361 void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) {
 362   for (int i = 0; i < length(); ++i) {


 458   // Work in this loop should be kept as lightweight as
 459   // possible since this might otherwise become a bottleneck
 460   // to scaling. Should we add heavy-weight work into this
 461   // loop, consider parallelizing the loop into the worker threads.
 462   for (int i = 0; i < length(); ++i) {
 463     ParScanThreadState& par_scan_state = thread_state(i);
 464 
 465     // Flush stats related to To-space PLAB activity and
 466     // retire the last buffer.
 467     par_scan_state.to_space_alloc_buffer()->
 468       flush_stats_and_retire(_gen.plab_stats(),
 469                              true /* end_of_gc */,
 470                              false /* retain */);
 471 
 472     // Every thread has its own age table.  We need to merge
 473     // them all into one.
 474     ageTable *local_table = par_scan_state.age_table();
 475     _gen.age_table()->merge(local_table);
 476 
 477     // Inform old gen that we're done.
 478     _old_gen.par_promote_alloc_done(i);
 479     _old_gen.par_oop_since_save_marks_iterate_done(i);
 480   }
 481 
 482   if (UseConcMarkSweepGC && ParallelGCThreads > 0) {
 483     // We need to call this even when ResizeOldPLAB is disabled
 484     // so as to avoid breaking some asserts. While we may be able
 485     // to avoid this by reorganizing the code a bit, I am loathe
 486     // to do that unless we find cases where ergo leads to bad
 487     // performance.
 488     CFLS_LAB::compute_desired_plab_size();
 489   }
 490 }
 491 
 492 ParScanClosure::ParScanClosure(ParNewGeneration* g,
 493                                ParScanThreadState* par_scan_state) :
 494   OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g)
 495 {
 496   assert(_g->level() == 0, "Optimized for youngest generation");
 497   _boundary = _g->reserved().end();
 498 }
 499 


 561 
 562       //   if successful, goto Start.
 563       continue;
 564 
 565       // try global overflow list.
 566     } else if (par_gen()->take_from_overflow_list(par_scan_state())) {
 567       continue;
 568     }
 569 
 570     // Otherwise, offer termination.
 571     par_scan_state()->start_term_time();
 572     if (terminator()->offer_termination()) break;
 573     par_scan_state()->end_term_time();
 574   }
 575   assert(par_gen()->_overflow_list == NULL && par_gen()->_num_par_pushes == 0,
 576          "Broken overflow list?");
 577   // Finish the last termination pause.
 578   par_scan_state()->end_term_time();
 579 }
 580 
 581 ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* old_gen,
 582                 HeapWord* young_old_boundary, ParScanThreadStateSet* state_set) :
 583     AbstractGangTask("ParNewGeneration collection"),
 584     _gen(gen), _old_gen(old_gen),
 585     _young_old_boundary(young_old_boundary),
 586     _state_set(state_set)
 587   {}
 588 
 589 // Reset the terminator for the given number of
 590 // active threads.
 591 void ParNewGenTask::set_for_termination(int active_workers) {
 592   _state_set->reset(active_workers, _gen->promotion_failed());
 593   // Should the heap be passed in?  There's only 1 for now so
 594   // grab it instead.
 595   GenCollectedHeap* gch = GenCollectedHeap::heap();
 596   gch->set_n_termination(active_workers);
 597 }
 598 
 599 void ParNewGenTask::work(uint worker_id) {
 600   GenCollectedHeap* gch = GenCollectedHeap::heap();
 601   // Since this is being done in a separate thread, need new resource
 602   // and handle marks.
 603   ResourceMark rm;
 604   HandleMark hm;
 605   // We would need multiple old-gen queues otherwise.
 606   assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen.");
 607 
 608   Generation* old_gen = gch->old_gen();
 609 
 610   ParScanThreadState& par_scan_state = _state_set->thread_state(worker_id);
 611   assert(_state_set->is_valid(worker_id), "Should not have been called");
 612 
 613   par_scan_state.set_young_old_boundary(_young_old_boundary);
 614 
 615   KlassScanClosure klass_scan_closure(&par_scan_state.to_space_root_closure(),
 616                                       gch->rem_set()->klass_rem_set());
 617   CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure,
 618                                            &par_scan_state.to_space_root_closure(),
 619                                            false);
 620 
 621   par_scan_state.start_strong_roots();
 622   gch->gen_process_roots(_gen->level(),
 623                          true,  // Process younger gens, if any,
 624                                 // as strong roots.
 625                          false, // no scope; this is parallel code
 626                          SharedHeap::SO_ScavengeCodeCache,
 627                          GenCollectedHeap::StrongAndWeakRoots,
 628                          &par_scan_state.to_space_root_closure(),


 751                       ? obj->forwardee()
 752                       : _g->DefNewGeneration::copy_to_survivor_space(obj);
 753       oopDesc::encode_store_heap_oop_not_null(p, new_obj);
 754     }
 755     if (_gc_barrier) {
 756       // If p points to a younger generation, mark the card.
 757       if ((HeapWord*)obj < _gen_boundary) {
 758         _rs->write_ref_field_gc_par(p, obj);
 759       }
 760     }
 761   }
 762 }
 763 
 764 void ScanClosureWithParBarrier::do_oop(oop* p)       { ScanClosureWithParBarrier::do_oop_work(p); }
 765 void ScanClosureWithParBarrier::do_oop(narrowOop* p) { ScanClosureWithParBarrier::do_oop_work(p); }
 766 
 767 class ParNewRefProcTaskProxy: public AbstractGangTask {
 768   typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
 769 public:
 770   ParNewRefProcTaskProxy(ProcessTask& task, ParNewGeneration& gen,
 771                          Generation& old_gen,
 772                          HeapWord* young_old_boundary,
 773                          ParScanThreadStateSet& state_set);
 774 
 775 private:
 776   virtual void work(uint worker_id);
 777   virtual void set_for_termination(int active_workers) {
 778     _state_set.terminator()->reset_for_reuse(active_workers);
 779   }
 780 private:
 781   ParNewGeneration&      _gen;
 782   ProcessTask&           _task;
 783   Generation&            _old_gen;
 784   HeapWord*              _young_old_boundary;
 785   ParScanThreadStateSet& _state_set;
 786 };
 787 
 788 ParNewRefProcTaskProxy::ParNewRefProcTaskProxy(
 789     ProcessTask& task, ParNewGeneration& gen,
 790     Generation& old_gen,
 791     HeapWord* young_old_boundary,
 792     ParScanThreadStateSet& state_set)
 793   : AbstractGangTask("ParNewGeneration parallel reference processing"),
 794     _gen(gen),
 795     _task(task),
 796     _old_gen(old_gen),
 797     _young_old_boundary(young_old_boundary),
 798     _state_set(state_set)
 799 {
 800 }
 801 
 802 void ParNewRefProcTaskProxy::work(uint worker_id)
 803 {
 804   ResourceMark rm;
 805   HandleMark hm;
 806   ParScanThreadState& par_scan_state = _state_set.thread_state(worker_id);
 807   par_scan_state.set_young_old_boundary(_young_old_boundary);
 808   _task.work(worker_id, par_scan_state.is_alive_closure(),
 809              par_scan_state.keep_alive_closure(),
 810              par_scan_state.evacuate_followers_closure());
 811 }
 812 
 813 class ParNewRefEnqueueTaskProxy: public AbstractGangTask {
 814   typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
 815   EnqueueTask& _task;
 816 


 882 }
 883 
 884 
 885 // A Generation that does parallel young-gen collection.
 886 
 887 bool ParNewGeneration::_avoid_promotion_undo = false;
 888 
 889 void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer) {
 890   assert(_promo_failure_scan_stack.is_empty(), "post condition");
 891   _promo_failure_scan_stack.clear(true); // Clear cached segments.
 892 
 893   remove_forwarding_pointers();
 894   if (PrintGCDetails) {
 895     gclog_or_tty->print(" (promotion failed)");
 896   }
 897   // All the spaces are in play for mark-sweep.
 898   swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
 899   from()->set_next_compaction_space(to());
 900   gch->set_incremental_collection_failed();
 901   // Inform the next generation that a promotion failure occurred.
 902   _old_gen->promotion_failure_occurred();
 903 
 904   // Trace promotion failure in the parallel GC threads
 905   thread_state_set.trace_promotion_failed(gc_tracer);
 906   // Single threaded code may have reported promotion failure to the global state
 907   if (_promotion_failed_info.has_failed()) {
 908     gc_tracer.report_promotion_failed(_promotion_failed_info);
 909   }
 910   // Reset the PromotionFailureALot counters.
 911   NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
 912 }
 913 
 914 void ParNewGeneration::collect(bool   full,
 915                                bool   clear_all_soft_refs,
 916                                size_t size,
 917                                bool   is_tlab) {
 918   assert(full || size > 0, "otherwise we don't want to collect");
 919 
 920   GenCollectedHeap* gch = GenCollectedHeap::heap();
 921 
 922   _gc_timer->register_gc_start();
 923 
 924   assert(gch->kind() == CollectedHeap::GenCollectedHeap,
 925     "not a CMS generational heap");
 926   AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
 927   FlexibleWorkGang* workers = gch->workers();
 928   assert(workers != NULL, "Need workgang for parallel work");
 929   int active_workers =
 930       AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
 931                                    workers->active_workers(),
 932                                    Threads::number_of_non_daemon_threads());
 933   workers->set_active_workers(active_workers);
 934   assert(gch->n_gens() == 2,
 935          "Par collection currently only works with single older gen.");
 936   _old_gen = gch->old_gen();
 937   // Do we have to avoid promotion_undo?
 938   if (gch->collector_policy()->is_concurrent_mark_sweep_policy()) {
 939     set_avoid_promotion_undo(true);
 940   }
 941 
 942   // If the next generation is too full to accommodate worst-case promotion
 943   // from this generation, pass on collection; let the next generation
 944   // do it.
 945   if (!collection_attempt_is_safe()) {
 946     gch->set_incremental_collection_failed();  // slight lie, in that we did not even attempt one
 947     return;
 948   }
 949   assert(to()->is_empty(), "Else not collection_attempt_is_safe");
 950 
 951   ParNewTracer gc_tracer;
 952   gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start());
 953   gch->trace_heap_before_gc(&gc_tracer);
 954 
 955   init_assuming_no_promotion_failure();
 956 


 962   GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id());
 963   // Capture heap used before collection (for printing).
 964   size_t gch_prev_used = gch->used();
 965 
 966   SpecializationStats::clear();
 967 
 968   age_table()->clear();
 969   to()->clear(SpaceDecorator::Mangle);
 970 
 971   gch->save_marks();
 972   assert(workers != NULL, "Need parallel worker threads.");
 973   int n_workers = active_workers;
 974 
 975   // Set the correct parallelism (number of queues) in the reference processor
 976   ref_processor()->set_active_mt_degree(n_workers);
 977 
 978   // Always set the terminator for the active number of workers
 979   // because only those workers go through the termination protocol.
 980   ParallelTaskTerminator _term(n_workers, task_queues());
 981   ParScanThreadStateSet thread_state_set(workers->active_workers(),
 982                                          *to(), *this, *_old_gen, *task_queues(),
 983                                          _overflow_stacks, desired_plab_sz(), _term);
 984 
 985   ParNewGenTask tsk(this, _old_gen, reserved().end(), &thread_state_set);
 986   gch->set_par_threads(n_workers);
 987   gch->rem_set()->prepare_for_younger_refs_iterate(true);
 988   // It turns out that even when we're using 1 thread, doing the work in a
 989   // separate thread causes wide variance in run times.  We can't help this
 990   // in the multi-threaded case, but we special-case n=1 here to get
 991   // repeatable measurements of the 1-thread overhead of the parallel code.
 992   if (n_workers > 1) {
 993     GenCollectedHeap::StrongRootsScope srs(gch);
 994     workers->run_task(&tsk);
 995   } else {
 996     GenCollectedHeap::StrongRootsScope srs(gch);
 997     tsk.work(0);
 998   }
 999   thread_state_set.reset(0 /* Bad value in debug if not reset */,
1000                          promotion_failed());
1001 
1002   // Process (weak) reference objects found during scavenge.
1003   ReferenceProcessor* rp = ref_processor();
1004   IsAliveClosure is_alive(this);
1005   ScanWeakRefClosure scan_weak_ref(this);


1179   // Try allocating obj in to-space (unless too old)
1180   if (dummyOld.age() < tenuring_threshold()) {
1181     new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
1182     if (new_obj == NULL) {
1183       set_survivor_overflow(true);
1184     }
1185   }
1186 
1187   if (new_obj == NULL) {
1188     // Either to-space is full or we decided to promote
1189     // try allocating obj tenured
1190 
1191     // Attempt to install a null forwarding pointer (atomically),
1192     // to claim the right to install the real forwarding pointer.
1193     forward_ptr = old->forward_to_atomic(ClaimedForwardPtr);
1194     if (forward_ptr != NULL) {
1195       // someone else beat us to it.
1196         return real_forwardee(old);
1197     }
1198 
1199     new_obj = _old_gen->par_promote(par_scan_state->thread_num(),
1200                                     old, m, sz);
1201 
1202     if (new_obj == NULL) {
1203       // promotion failed, forward to self
1204       _promotion_failed = true;
1205       new_obj = old;
1206 
1207       preserve_mark_if_necessary(old, m);
1208       par_scan_state->register_promotion_failure(sz);
1209     }
1210 
1211     old->forward_to(new_obj);
1212     forward_ptr = NULL;
1213   } else {
1214     // Is in to-space; do copying ourselves.
1215     Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
1216     forward_ptr = old->forward_to_atomic(new_obj);
1217     // Restore the mark word copied above.
1218     new_obj->set_mark(m);
1219     // Increment age if obj still in new generation


1297   oopDesc dummyOld;
1298   dummyOld.set_mark(m);
1299   assert(!dummyOld.is_forwarded(),
1300          "should not be called with forwarding pointer mark word.");
1301 
1302   bool failed_to_promote = false;
1303   oop new_obj = NULL;
1304   oop forward_ptr;
1305 
1306   // Try allocating obj in to-space (unless too old)
1307   if (dummyOld.age() < tenuring_threshold()) {
1308     new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
1309     if (new_obj == NULL) {
1310       set_survivor_overflow(true);
1311     }
1312   }
1313 
1314   if (new_obj == NULL) {
1315     // Either to-space is full or we decided to promote
1316     // try allocating obj tenured
1317     new_obj = _old_gen->par_promote(par_scan_state->thread_num(),
1318                                     old, m, sz);
1319 
1320     if (new_obj == NULL) {
1321       // promotion failed, forward to self
1322       forward_ptr = old->forward_to_atomic(old);
1323       new_obj = old;
1324 
1325       if (forward_ptr != NULL) {
1326         return forward_ptr;   // someone else succeeded
1327       }
1328 
1329       _promotion_failed = true;
1330       failed_to_promote = true;
1331 
1332       preserve_mark_if_necessary(old, m);
1333       par_scan_state->register_promotion_failure(sz);
1334     }
1335   } else {
1336     // Is in to-space; do copying ourselves.
1337     Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);


1378         simulate_overflow = true;
1379       }
1380     )
1381     if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) {
1382       // Add stats for overflow pushes.
1383       push_on_overflow_list(old, par_scan_state);
1384       TASKQUEUE_STATS_ONLY(par_scan_state->taskqueue_stats().record_overflow(0));
1385     }
1386 
1387     return new_obj;
1388   }
1389 
1390   // Oops.  Someone beat us to it.  Undo the allocation.  Where did we
1391   // allocate it?
1392   if (is_in_reserved(new_obj)) {
1393     // Must be in to_space.
1394     assert(to()->is_in_reserved(new_obj), "Checking");
1395     par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
1396   } else {
1397     assert(!_avoid_promotion_undo, "Should not be here if avoiding.");
1398     _old_gen->par_promote_alloc_undo(par_scan_state->thread_num(),
1399                                      (HeapWord*)new_obj, sz);
1400   }
1401 
1402   return forward_ptr;
1403 }
1404 
1405 #ifndef PRODUCT
1406 // It's OK to call this multi-threaded;  the worst thing
1407 // that can happen is that we'll get a bunch of closely
1408 // spaced simulated overflows, but that's OK, in fact
1409 // probably good as it would exercise the overflow code
1410 // under contention.
1411 bool ParNewGeneration::should_simulate_overflow() {
1412   if (_overflow_counter-- <= 0) { // just being defensive
1413     _overflow_counter = ParGCWorkQueueOverflowInterval;
1414     return true;
1415   } else {
1416     return false;
1417   }
1418 }


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