Print this page


Split Close
Expand all
Collapse all
          --- old/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
          +++ new/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
↓ open down ↓ 284 lines elided ↑ open up ↑
 285  285  }
 286  286  
 287  287  void ConcurrentMarkSweepGeneration::ref_processor_init() {
 288  288    assert(collector() != NULL, "no collector");
 289  289    collector()->ref_processor_init();
 290  290  }
 291  291  
 292  292  void CMSCollector::ref_processor_init() {
 293  293    if (_ref_processor == NULL) {
 294  294      // Allocate and initialize a reference processor
 295      -    _ref_processor = ReferenceProcessor::create_ref_processor(
 296      -        _span,                               // span
 297      -        _cmsGen->refs_discovery_is_atomic(), // atomic_discovery
 298      -        _cmsGen->refs_discovery_is_mt(),     // mt_discovery
 299      -        &_is_alive_closure,
 300      -        ParallelGCThreads,
 301      -        ParallelRefProcEnabled);
      295 +    _ref_processor =
      296 +      new ReferenceProcessor(_span,                               // span
      297 +                             (ParallelGCThreads > 1) && ParallelRefProcEnabled, // mt processing
      298 +                             ParallelGCThreads,                   // mt processing degree
      299 +                             _cmsGen->refs_discovery_is_mt(),     // mt discovery
      300 +                             MAX2(ConcGCThreads, ParallelGCThreads), // mt discovery degree
      301 +                             _cmsGen->refs_discovery_is_atomic(), // discovery is not atomic
      302 +                             &_is_alive_closure,                  // closure for liveness info
      303 +                             false);                              // next field updates do not need write barrier
 302  304      // Initialize the _ref_processor field of CMSGen
 303  305      _cmsGen->set_ref_processor(_ref_processor);
 304  306  
 305  307      // Allocate a dummy ref processor for perm gen.
 306  308      ReferenceProcessor* rp2 = new ReferenceProcessor();
 307  309      if (rp2 == NULL) {
 308  310        vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
 309  311      }
 310  312      _permGen->set_ref_processor(rp2);
 311  313    }
↓ open down ↓ 322 lines elided ↑ open up ↑
 634  636    if (!_markStack.allocate(MarkStackSize)) {
 635  637      warning("Failed to allocate CMS Marking Stack");
 636  638      return;
 637  639    }
 638  640    if (!_revisitStack.allocate(CMSRevisitStackSize)) {
 639  641      warning("Failed to allocate CMS Revisit Stack");
 640  642      return;
 641  643    }
 642  644  
 643  645    // Support for multi-threaded concurrent phases
 644      -  if (CollectedHeap::use_parallel_gc_threads() && CMSConcurrentMTEnabled) {
      646 +  if (CMSConcurrentMTEnabled) {
 645  647      if (FLAG_IS_DEFAULT(ConcGCThreads)) {
 646  648        // just for now
 647  649        FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3)/4);
 648  650      }
 649  651      if (ConcGCThreads > 1) {
 650  652        _conc_workers = new YieldingFlexibleWorkGang("Parallel CMS Threads",
 651  653                                   ConcGCThreads, true);
 652  654        if (_conc_workers == NULL) {
 653  655          warning("GC/CMS: _conc_workers allocation failure: "
 654  656                "forcing -CMSConcurrentMTEnabled");
↓ open down ↓ 1338 lines elided ↑ open up ↑
1993 1995    // Temporarily, clear the "is_alive_non_header" field of the
1994 1996    // reference processor.
1995 1997    ReferenceProcessorIsAliveMutator y(ref_processor(), NULL);
1996 1998  
1997 1999    // Temporarily make reference _processing_ single threaded (non-MT).
1998 2000    ReferenceProcessorMTProcMutator z(ref_processor(), false);
1999 2001  
2000 2002    // Temporarily make refs discovery atomic
2001 2003    ReferenceProcessorAtomicMutator w(ref_processor(), true);
2002 2004  
     2005 +  // Temporarily make refs discovery ST
     2006 +  ReferenceProcessorMTDiscoveryMutator(ref_processor(), false);
     2007 +
2003 2008    ref_processor()->set_enqueuing_is_done(false);
2004 2009    ref_processor()->enable_discovery();
2005 2010    ref_processor()->setup_policy(clear_all_soft_refs);
2006 2011    // If an asynchronous collection finishes, the _modUnionTable is
2007 2012    // all clear.  If we are assuming the collection from an asynchronous
2008 2013    // collection, clear the _modUnionTable.
2009 2014    assert(_collectorState != Idling || _modUnionTable.isAllClear(),
2010 2015      "_modUnionTable should be clear if the baton was not passed");
2011 2016    _modUnionTable.clear_all();
2012 2017  
↓ open down ↓ 2243 lines elided ↑ open up ↑
4256 4261  
4257 4262    // Since the actual number of workers we get may be different
4258 4263    // from the number we requested above, do we need to do anything different
4259 4264    // below? In particular, may be we need to subclass the SequantialSubTasksDone
4260 4265    // class?? XXX
4261 4266    cms_space ->initialize_sequential_subtasks_for_marking(num_workers);
4262 4267    perm_space->initialize_sequential_subtasks_for_marking(num_workers);
4263 4268  
4264 4269    // Refs discovery is already non-atomic.
4265 4270    assert(!ref_processor()->discovery_is_atomic(), "Should be non-atomic");
4266      -  // Mutate the Refs discovery so it is MT during the
4267      -  // multi-threaded marking phase.
4268      -  ReferenceProcessorMTMutator mt(ref_processor(), num_workers > 1);
     4271 +  assert(num_workers <= 1 || ref_processor()->discovery_is_mt(), "Discovery should be MT");
4269 4272    DEBUG_ONLY(RememberKlassesChecker cmx(should_unload_classes());)
4270 4273    conc_workers()->start_task(&tsk);
4271 4274    while (tsk.yielded()) {
4272 4275      tsk.coordinator_yield();
4273 4276      conc_workers()->continue_task(&tsk);
4274 4277    }
4275 4278    // If the task was aborted, _restart_addr will be non-NULL
4276 4279    assert(tsk.completed() || _restart_addr != NULL, "Inconsistency");
4277 4280    while (_restart_addr != NULL) {
4278 4281      // XXX For now we do not make use of ABORTED state and have not
↓ open down ↓ 1290 lines elided ↑ open up ↑
5569 5572    // of parallel tasks (per constituent space) that are dynamically
5570 5573    // claimed by the parallel threads.
5571 5574    cms_space->initialize_sequential_subtasks_for_rescan(n_workers);
5572 5575    perm_space->initialize_sequential_subtasks_for_rescan(n_workers);
5573 5576  
5574 5577    // It turns out that even when we're using 1 thread, doing the work in a
5575 5578    // separate thread causes wide variance in run times.  We can't help this
5576 5579    // in the multi-threaded case, but we special-case n=1 here to get
5577 5580    // repeatable measurements of the 1-thread overhead of the parallel code.
5578 5581    if (n_workers > 1) {
5579      -    // Make refs discovery MT-safe
5580      -    ReferenceProcessorMTMutator mt(ref_processor(), true);
     5582 +    // Make refs discovery MT-safe, if it isn't already
     5583 +    ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), true);
5581 5584      GenCollectedHeap::StrongRootsScope srs(gch);
5582 5585      workers->run_task(&tsk);
5583 5586    } else {
5584 5587      GenCollectedHeap::StrongRootsScope srs(gch);
5585 5588      tsk.work(0);
5586 5589    }
5587 5590    gch->set_par_threads(0);  // 0 ==> non-parallel.
5588 5591    // restore, single-threaded for now, any preserved marks
5589 5592    // as a result of work_q overflow
5590 5593    restore_preserved_marks_if_any();
↓ open down ↓ 105 lines elided ↑ open up ↑
5696 5699    const MemRegion        _span;
5697 5700    ProcessTask&           _task;
5698 5701  
5699 5702  public:
5700 5703    CMSRefProcTaskProxy(ProcessTask&     task,
5701 5704                        CMSCollector*    collector,
5702 5705                        const MemRegion& span,
5703 5706                        CMSBitMap*       mark_bit_map,
5704 5707                        AbstractWorkGang* workers,
5705 5708                        OopTaskQueueSet* task_queues):
     5709 +    // XXX Should superclass AGTWOQ also know about AWG since it knows
     5710 +    // about the task_queues used by the AWG? Then it could initialize
     5711 +    // the terminator() object. See 6984287. The set_for_termination()
     5712 +    // below is a temporary band-aid for the regression in 6984287.
5706 5713      AbstractGangTaskWOopQueues("Process referents by policy in parallel",
5707 5714        task_queues),
5708 5715      _task(task),
5709 5716      _collector(collector), _span(span), _mark_bit_map(mark_bit_map)
5710      -    {
5711      -      assert(_collector->_span.equals(_span) && !_span.is_empty(),
5712      -             "Inconsistency in _span");
5713      -    }
     5717 +  {
     5718 +    assert(_collector->_span.equals(_span) && !_span.is_empty(),
     5719 +           "Inconsistency in _span");
     5720 +    set_for_termination(workers->active_workers());
     5721 +  }
5714 5722  
5715 5723    OopTaskQueueSet* task_queues() { return queues(); }
5716 5724  
5717 5725    OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
5718 5726  
5719 5727    void do_work_steal(int i,
5720 5728                       CMSParDrainMarkingStackClosure* drain,
5721 5729                       CMSParKeepAliveClosure* keep_alive,
5722 5730                       int* seed);
5723 5731  
↓ open down ↓ 141 lines elided ↑ open up ↑
5865 5873                                  &cmsKeepAliveClosure, false /* !preclean */);
5866 5874    {
5867 5875      TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty);
5868 5876      if (rp->processing_is_mt()) {
5869 5877        // Set the degree of MT here.  If the discovery is done MT, there
5870 5878        // may have been a different number of threads doing the discovery
5871 5879        // and a different number of discovered lists may have Ref objects.
5872 5880        // That is OK as long as the Reference lists are balanced (see
5873 5881        // balance_all_queues() and balance_queues()).
5874 5882  
5875      -
5876      -      rp->set_mt_degree(ParallelGCThreads);
     5883 +      rp->set_active_mt_degree(ParallelGCThreads);
5877 5884        CMSRefProcTaskExecutor task_executor(*this);
5878 5885        rp->process_discovered_references(&_is_alive_closure,
5879 5886                                          &cmsKeepAliveClosure,
5880 5887                                          &cmsDrainMarkingStackClosure,
5881 5888                                          &task_executor);
5882 5889      } else {
5883 5890        rp->process_discovered_references(&_is_alive_closure,
5884 5891                                          &cmsKeepAliveClosure,
5885 5892                                          &cmsDrainMarkingStackClosure,
5886 5893                                          NULL);
↓ open down ↓ 3390 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX