Merge

Sat, 14 Aug 2010 00:47:52 -0700

author
johnc
date
Sat, 14 Aug 2010 00:47:52 -0700
changeset 2068
7fcd5f39bd7a
parent 2050
21e519b91576
parent 2067
2d6b74c9a797
child 2069
f121b2772674
child 2071
be3f9c242c9d

Merge

src/share/vm/gc_implementation/parallelScavenge/prefetchQueue.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/arrayKlassKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/compiledICHolderKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/constMethodKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/constantPoolKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/cpCacheKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/klassKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/arguments.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
     1.2 +++ b/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -36,8 +36,8 @@
    1.11  }
    1.12  
    1.13  inline void OrderAccess::release() {
    1.14 -  jint* dummy = (jint*)&dummy;
    1.15 -  __asm__ volatile("stw %%g0, [%0]" : : "r" (dummy) : "memory");
    1.16 +  jint* local_dummy = (jint*)&local_dummy;
    1.17 +  __asm__ volatile("stw %%g0, [%0]" : : "r" (local_dummy) : "memory");
    1.18  }
    1.19  
    1.20  inline void OrderAccess::fence() {
     2.1 --- a/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
     2.2 +++ b/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -30,16 +30,18 @@
    2.11  inline void OrderAccess::storeload()  { fence(); }
    2.12  
    2.13  inline void OrderAccess::acquire() {
    2.14 -  volatile intptr_t dummy;
    2.15 +  volatile intptr_t local_dummy;
    2.16  #ifdef AMD64
    2.17 -  __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (dummy) : : "memory");
    2.18 +  __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory");
    2.19  #else
    2.20 -  __asm__ volatile ("movl 0(%%esp),%0" : "=r" (dummy) : : "memory");
    2.21 +  __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory");
    2.22  #endif // AMD64
    2.23  }
    2.24  
    2.25  inline void OrderAccess::release() {
    2.26 -  dummy = 0;
    2.27 +  // Avoid hitting the same cache-line from
    2.28 +  // different threads.
    2.29 +  volatile jint local_dummy = 0;
    2.30  }
    2.31  
    2.32  inline void OrderAccess::fence() {
     3.1 --- a/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
     3.2 +++ b/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -42,8 +42,8 @@
    3.11  }
    3.12  
    3.13  inline void OrderAccess::release() {
    3.14 -  jint* dummy = (jint*)&dummy;
    3.15 -  __asm__ volatile("stw %%g0, [%0]" : : "r" (dummy) : "memory");
    3.16 +  jint* local_dummy = (jint*)&local_dummy;
    3.17 +  __asm__ volatile("stw %%g0, [%0]" : : "r" (local_dummy) : "memory");
    3.18  }
    3.19  
    3.20  inline void OrderAccess::fence() {
    3.21 @@ -57,7 +57,9 @@
    3.22  }
    3.23  
    3.24  inline void OrderAccess::release() {
    3.25 -  dummy = 0;
    3.26 +  // Avoid hitting the same cache-line from
    3.27 +  // different threads.
    3.28 +  volatile jint local_dummy = 0;
    3.29  }
    3.30  
    3.31  inline void OrderAccess::fence() {
     4.1 --- a/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
     4.2 +++ b/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -40,7 +40,9 @@
    4.11  }
    4.12  
    4.13  inline void OrderAccess::release() {
    4.14 -  dummy = 0;
    4.15 +  // Avoid hitting the same cache-line from
    4.16 +  // different threads.
    4.17 +  volatile jint local_dummy = 0;
    4.18  }
    4.19  
    4.20  inline void OrderAccess::fence() {
    4.21 @@ -53,11 +55,11 @@
    4.22  
    4.23  extern "C" {
    4.24    inline void _OrderAccess_acquire() {
    4.25 -    volatile intptr_t dummy;
    4.26 +    volatile intptr_t local_dummy;
    4.27  #ifdef AMD64
    4.28 -    __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (dummy) : : "memory");
    4.29 +    __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory");
    4.30  #else
    4.31 -    __asm__ volatile ("movl 0(%%esp),%0" : "=r" (dummy) : : "memory");
    4.32 +    __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory");
    4.33  #endif // AMD64
    4.34    }
    4.35    inline void _OrderAccess_fence() {
     5.1 --- a/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
     5.2 +++ b/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
     5.3 @@ -1,5 +1,5 @@
     5.4  /*
     5.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
     5.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     5.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.8   *
     5.9   * This code is free software; you can redistribute it and/or modify it
    5.10 @@ -41,7 +41,7 @@
    5.11  
    5.12  inline void OrderAccess::release() {
    5.13    // A volatile store has release semantics.
    5.14 -  dummy = 0;
    5.15 +  volatile jint local_dummy = 0;
    5.16  }
    5.17  
    5.18  inline void OrderAccess::fence() {
     6.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Aug 13 07:33:20 2010 -0700
     6.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Sat Aug 14 00:47:52 2010 -0700
     6.3 @@ -1965,6 +1965,9 @@
     6.4                                              _intra_sweep_estimate.padded_average());
     6.5    }
     6.6  
     6.7 +  {
     6.8 +    TraceCMSMemoryManagerStats();
     6.9 +  }
    6.10    GenMarkSweep::invoke_at_safepoint(_cmsGen->level(),
    6.11      ref_processor(), clear_all_soft_refs);
    6.12    #ifdef ASSERT
    6.13 @@ -3415,6 +3418,7 @@
    6.14  void CMSCollector::checkpointRootsInitial(bool asynch) {
    6.15    assert(_collectorState == InitialMarking, "Wrong collector state");
    6.16    check_correct_thread_executing();
    6.17 +  TraceCMSMemoryManagerStats tms(_collectorState);
    6.18    ReferenceProcessor* rp = ref_processor();
    6.19    SpecializationStats::clear();
    6.20    assert(_restart_addr == NULL, "Control point invariant");
    6.21 @@ -4748,6 +4752,7 @@
    6.22    // world is stopped at this checkpoint
    6.23    assert(SafepointSynchronize::is_at_safepoint(),
    6.24           "world should be stopped");
    6.25 +  TraceCMSMemoryManagerStats tms(_collectorState);
    6.26    verify_work_stacks_empty();
    6.27    verify_overflow_empty();
    6.28  
    6.29 @@ -5849,6 +5854,8 @@
    6.30    verify_work_stacks_empty();
    6.31    verify_overflow_empty();
    6.32    increment_sweep_count();
    6.33 +  TraceCMSMemoryManagerStats tms(_collectorState);
    6.34 +
    6.35    _inter_sweep_timer.stop();
    6.36    _inter_sweep_estimate.sample(_inter_sweep_timer.seconds());
    6.37    size_policy()->avg_cms_free_at_sweep()->sample(_cmsGen->free());
    6.38 @@ -9121,3 +9128,57 @@
    6.39    }
    6.40    return res;
    6.41  }
    6.42 +
    6.43 +TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase): TraceMemoryManagerStats() {
    6.44 +
    6.45 +  switch (phase) {
    6.46 +    case CMSCollector::InitialMarking:
    6.47 +      initialize(true  /* fullGC */ ,
    6.48 +                 true  /* recordGCBeginTime */,
    6.49 +                 true  /* recordPreGCUsage */,
    6.50 +                 false /* recordPeakUsage */,
    6.51 +                 false /* recordPostGCusage */,
    6.52 +                 true  /* recordAccumulatedGCTime */,
    6.53 +                 false /* recordGCEndTime */,
    6.54 +                 false /* countCollection */  );
    6.55 +      break;
    6.56 +
    6.57 +    case CMSCollector::FinalMarking:
    6.58 +      initialize(true  /* fullGC */ ,
    6.59 +                 false /* recordGCBeginTime */,
    6.60 +                 false /* recordPreGCUsage */,
    6.61 +                 false /* recordPeakUsage */,
    6.62 +                 false /* recordPostGCusage */,
    6.63 +                 true  /* recordAccumulatedGCTime */,
    6.64 +                 false /* recordGCEndTime */,
    6.65 +                 false /* countCollection */  );
    6.66 +      break;
    6.67 +
    6.68 +    case CMSCollector::Sweeping:
    6.69 +      initialize(true  /* fullGC */ ,
    6.70 +                 false /* recordGCBeginTime */,
    6.71 +                 false /* recordPreGCUsage */,
    6.72 +                 true  /* recordPeakUsage */,
    6.73 +                 true  /* recordPostGCusage */,
    6.74 +                 false /* recordAccumulatedGCTime */,
    6.75 +                 true  /* recordGCEndTime */,
    6.76 +                 true  /* countCollection */  );
    6.77 +      break;
    6.78 +
    6.79 +    default:
    6.80 +      ShouldNotReachHere();
    6.81 +  }
    6.82 +}
    6.83 +
    6.84 +// when bailing out of cms in concurrent mode failure
    6.85 +TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(): TraceMemoryManagerStats() {
    6.86 +  initialize(true /* fullGC */ ,
    6.87 +             true /* recordGCBeginTime */,
    6.88 +             true /* recordPreGCUsage */,
    6.89 +             true /* recordPeakUsage */,
    6.90 +             true /* recordPostGCusage */,
    6.91 +             true /* recordAccumulatedGCTime */,
    6.92 +             true /* recordGCEndTime */,
    6.93 +             true /* countCollection */ );
    6.94 +}
    6.95 +
     7.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Fri Aug 13 07:33:20 2010 -0700
     7.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Sat Aug 14 00:47:52 2010 -0700
     7.3 @@ -507,6 +507,7 @@
     7.4    friend class VM_CMS_Operation;
     7.5    friend class VM_CMS_Initial_Mark;
     7.6    friend class VM_CMS_Final_Remark;
     7.7 +  friend class TraceCMSMemoryManagerStats;
     7.8  
     7.9   private:
    7.10    jlong _time_of_last_gc;
    7.11 @@ -1858,3 +1859,11 @@
    7.12      _dead_bit_map(dead_bit_map) {}
    7.13    size_t do_blk(HeapWord* addr);
    7.14  };
    7.15 +
    7.16 +class TraceCMSMemoryManagerStats : public TraceMemoryManagerStats {
    7.17 +
    7.18 + public:
    7.19 +  TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase);
    7.20 +  TraceCMSMemoryManagerStats();
    7.21 +};
    7.22 +
     8.1 --- a/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Fri Aug 13 07:33:20 2010 -0700
     8.2 +++ b/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Sat Aug 14 00:47:52 2010 -0700
     8.3 @@ -339,7 +339,9 @@
     8.4    return res;
     8.5  }
     8.6  
     8.7 -void ConcurrentG1Refine::clean_up_cache(int worker_i, G1RemSet* g1rs) {
     8.8 +void ConcurrentG1Refine::clean_up_cache(int worker_i,
     8.9 +                                        G1RemSet* g1rs,
    8.10 +                                        DirtyCardQueue* into_cset_dcq) {
    8.11    assert(!use_cache(), "cache should be disabled");
    8.12    int start_idx;
    8.13  
    8.14 @@ -353,7 +355,19 @@
    8.15        for (int i = start_idx; i < end_idx; i++) {
    8.16          jbyte* entry = _hot_cache[i];
    8.17          if (entry != NULL) {
    8.18 -          g1rs->concurrentRefineOneCard(entry, worker_i);
    8.19 +          if (g1rs->concurrentRefineOneCard(entry, worker_i, true)) {
    8.20 +            // 'entry' contains references that point into the current
    8.21 +            // collection set. We need to record 'entry' in the DCQS
    8.22 +            // that's used for that purpose.
    8.23 +            //
    8.24 +            // The only time we care about recording cards that contain
    8.25 +            // references that point into the collection set is during
    8.26 +            // RSet updating while within an evacuation pause.
    8.27 +            // In this case worker_i should be the id of a GC worker thread
    8.28 +            assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
    8.29 +            assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "incorrect worker id");
    8.30 +            into_cset_dcq->enqueue(entry);
    8.31 +          }
    8.32          }
    8.33        }
    8.34      }
     9.1 --- a/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Fri Aug 13 07:33:20 2010 -0700
     9.2 +++ b/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Sat Aug 14 00:47:52 2010 -0700
     9.3 @@ -1,5 +1,5 @@
     9.4  /*
     9.5 - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
     9.6 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
     9.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.8   *
     9.9   * This code is free software; you can redistribute it and/or modify it
    9.10 @@ -184,7 +184,7 @@
    9.11    jbyte* cache_insert(jbyte* card_ptr, bool* defer);
    9.12  
    9.13    // Process the cached entries.
    9.14 -  void clean_up_cache(int worker_i, G1RemSet* g1rs);
    9.15 +  void clean_up_cache(int worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq);
    9.16  
    9.17    // Set up for parallel processing of the cards in the hot cache
    9.18    void clear_hot_cache_claimed_index() {
    10.1 --- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Fri Aug 13 07:33:20 2010 -0700
    10.2 +++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Sat Aug 14 00:47:52 2010 -0700
    10.3 @@ -1,5 +1,5 @@
    10.4  /*
    10.5 - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
    10.6 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
    10.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.8   *
    10.9   * This code is free software; you can redistribute it and/or modify it
   10.10 @@ -178,13 +178,14 @@
   10.11  }
   10.12  
   10.13  bool DirtyCardQueueSet::
   10.14 -apply_closure_to_completed_buffer_helper(int worker_i,
   10.15 +apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
   10.16 +                                         int worker_i,
   10.17                                           BufferNode* nd) {
   10.18    if (nd != NULL) {
   10.19      void **buf = BufferNode::make_buffer_from_node(nd);
   10.20      size_t index = nd->index();
   10.21      bool b =
   10.22 -      DirtyCardQueue::apply_closure_to_buffer(_closure, buf,
   10.23 +      DirtyCardQueue::apply_closure_to_buffer(cl, buf,
   10.24                                                index, _sz,
   10.25                                                true, worker_i);
   10.26      if (b) {
   10.27 @@ -199,15 +200,22 @@
   10.28    }
   10.29  }
   10.30  
   10.31 +bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
   10.32 +                                                          int worker_i,
   10.33 +                                                          int stop_at,
   10.34 +                                                          bool during_pause) {
   10.35 +  assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
   10.36 +  BufferNode* nd = get_completed_buffer(stop_at);
   10.37 +  bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd);
   10.38 +  if (res) Atomic::inc(&_processed_buffers_rs_thread);
   10.39 +  return res;
   10.40 +}
   10.41 +
   10.42  bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i,
   10.43                                                            int stop_at,
   10.44 -                                                          bool during_pause)
   10.45 -{
   10.46 -  assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
   10.47 -  BufferNode* nd = get_completed_buffer(stop_at);
   10.48 -  bool res = apply_closure_to_completed_buffer_helper(worker_i, nd);
   10.49 -  if (res) Atomic::inc(&_processed_buffers_rs_thread);
   10.50 -  return res;
   10.51 +                                                          bool during_pause) {
   10.52 +  return apply_closure_to_completed_buffer(_closure, worker_i,
   10.53 +                                           stop_at, during_pause);
   10.54  }
   10.55  
   10.56  void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() {
   10.57 @@ -222,8 +230,8 @@
   10.58    }
   10.59  }
   10.60  
   10.61 -void DirtyCardQueueSet::abandon_logs() {
   10.62 -  assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   10.63 +// Deallocates any completed log buffers
   10.64 +void DirtyCardQueueSet::clear() {
   10.65    BufferNode* buffers_to_delete = NULL;
   10.66    {
   10.67      MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
   10.68 @@ -242,6 +250,12 @@
   10.69      buffers_to_delete = nd->next();
   10.70      deallocate_buffer(BufferNode::make_buffer_from_node(nd));
   10.71    }
   10.72 +
   10.73 +}
   10.74 +
   10.75 +void DirtyCardQueueSet::abandon_logs() {
   10.76 +  assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   10.77 +  clear();
   10.78    // Since abandon is done only at safepoints, we can safely manipulate
   10.79    // these queues.
   10.80    for (JavaThread* t = Threads::first(); t; t = t->next()) {
    11.1 --- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Fri Aug 13 07:33:20 2010 -0700
    11.2 +++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Sat Aug 14 00:47:52 2010 -0700
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
    11.6 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
    11.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.8   *
    11.9   * This code is free software; you can redistribute it and/or modify it
   11.10 @@ -123,7 +123,21 @@
   11.11                                           int stop_at = 0,
   11.12                                           bool during_pause = false);
   11.13  
   11.14 -  bool apply_closure_to_completed_buffer_helper(int worker_i,
   11.15 +  // If there exists some completed buffer, pop it, then apply the
   11.16 +  // specified closure to all its elements, nulling out those elements
   11.17 +  // processed.  If all elements are processed, returns "true".  If no
   11.18 +  // completed buffers exist, returns false.  If a completed buffer exists,
   11.19 +  // but is only partially completed before a "yield" happens, the
   11.20 +  // partially completed buffer (with its processed elements set to NULL)
   11.21 +  // is returned to the completed buffer set, and this call returns false.
   11.22 +  bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
   11.23 +                                         int worker_i = 0,
   11.24 +                                         int stop_at = 0,
   11.25 +                                         bool during_pause = false);
   11.26 +
   11.27 +  // Helper routine for the above.
   11.28 +  bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
   11.29 +                                                int worker_i,
   11.30                                                  BufferNode* nd);
   11.31  
   11.32    BufferNode* get_completed_buffer(int stop_at);
   11.33 @@ -136,6 +150,9 @@
   11.34      return &_shared_dirty_card_queue;
   11.35    }
   11.36  
   11.37 +  // Deallocate any completed log buffers
   11.38 +  void clear();
   11.39 +
   11.40    // If a full collection is happening, reset partial logs, and ignore
   11.41    // completed ones: the full collection will make them all irrelevant.
   11.42    void abandon_logs();
    12.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Aug 13 07:33:20 2010 -0700
    12.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Sat Aug 14 00:47:52 2010 -0700
    12.3 @@ -56,7 +56,12 @@
    12.4      _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true)
    12.5    {}
    12.6    bool do_card_ptr(jbyte* card_ptr, int worker_i) {
    12.7 -    _g1rs->concurrentRefineOneCard(card_ptr, worker_i);
    12.8 +    bool oops_into_cset = _g1rs->concurrentRefineOneCard(card_ptr, worker_i, false);
    12.9 +    // This path is executed by the concurrent refine or mutator threads,
   12.10 +    // concurrently, and so we do not care if card_ptr contains references
   12.11 +    // that point into the collection set.
   12.12 +    assert(!oops_into_cset, "should be");
   12.13 +
   12.14      if (_concurrent && _sts->should_yield()) {
   12.15        // Caller will actually yield.
   12.16        return false;
   12.17 @@ -1322,6 +1327,7 @@
   12.18    SharedHeap(policy_),
   12.19    _g1_policy(policy_),
   12.20    _dirty_card_queue_set(false),
   12.21 +  _into_cset_dirty_card_queue_set(false),
   12.22    _ref_processor(NULL),
   12.23    _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
   12.24    _bot_shared(NULL),
   12.25 @@ -1572,6 +1578,16 @@
   12.26                                        Shared_DirtyCardQ_lock,
   12.27                                        &JavaThread::dirty_card_queue_set());
   12.28    }
   12.29 +
   12.30 +  // Initialize the card queue set used to hold cards containing
   12.31 +  // references into the collection set.
   12.32 +  _into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon,
   12.33 +                                             DirtyCardQ_FL_lock,
   12.34 +                                             -1, // never trigger processing
   12.35 +                                             -1, // no limit on length
   12.36 +                                             Shared_DirtyCardQ_lock,
   12.37 +                                             &JavaThread::dirty_card_queue_set());
   12.38 +
   12.39    // In case we're keeping closure specialization stats, initialize those
   12.40    // counts and that mechanism.
   12.41    SpecializationStats::clear();
   12.42 @@ -1603,14 +1619,16 @@
   12.43    return _g1_committed.byte_size();
   12.44  }
   12.45  
   12.46 -void G1CollectedHeap::iterate_dirty_card_closure(bool concurrent,
   12.47 +void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl,
   12.48 +                                                 DirtyCardQueue* into_cset_dcq,
   12.49 +                                                 bool concurrent,
   12.50                                                   int worker_i) {
   12.51    // Clean cards in the hot card cache
   12.52 -  concurrent_g1_refine()->clean_up_cache(worker_i, g1_rem_set());
   12.53 +  concurrent_g1_refine()->clean_up_cache(worker_i, g1_rem_set(), into_cset_dcq);
   12.54  
   12.55    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   12.56    int n_completed_buffers = 0;
   12.57 -  while (dcqs.apply_closure_to_completed_buffer(worker_i, 0, true)) {
   12.58 +  while (dcqs.apply_closure_to_completed_buffer(cl, worker_i, 0, true)) {
   12.59      n_completed_buffers++;
   12.60    }
   12.61    g1_policy()->record_update_rs_processed_buffers(worker_i,
   12.62 @@ -2692,6 +2710,35 @@
   12.63    }
   12.64  };
   12.65  
   12.66 +#if TASKQUEUE_STATS
   12.67 +void G1CollectedHeap::print_taskqueue_stats_hdr(outputStream* const st) {
   12.68 +  st->print_raw_cr("GC Task Stats");
   12.69 +  st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
   12.70 +  st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
   12.71 +}
   12.72 +
   12.73 +void G1CollectedHeap::print_taskqueue_stats(outputStream* const st) const {
   12.74 +  print_taskqueue_stats_hdr(st);
   12.75 +
   12.76 +  TaskQueueStats totals;
   12.77 +  const int n = MAX2(workers()->total_workers(), 1);
   12.78 +  for (int i = 0; i < n; ++i) {
   12.79 +    st->print("%3d ", i); task_queue(i)->stats.print(st); st->cr();
   12.80 +    totals += task_queue(i)->stats;
   12.81 +  }
   12.82 +  st->print_raw("tot "); totals.print(st); st->cr();
   12.83 +
   12.84 +  DEBUG_ONLY(totals.verify());
   12.85 +}
   12.86 +
   12.87 +void G1CollectedHeap::reset_taskqueue_stats() {
   12.88 +  const int n = MAX2(workers()->total_workers(), 1);
   12.89 +  for (int i = 0; i < n; ++i) {
   12.90 +    task_queue(i)->stats.reset();
   12.91 +  }
   12.92 +}
   12.93 +#endif // TASKQUEUE_STATS
   12.94 +
   12.95  void
   12.96  G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
   12.97    if (GC_locker::check_active_before_gc()) {
   12.98 @@ -2825,93 +2872,57 @@
   12.99        g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty);
  12.100  #endif // YOUNG_LIST_VERBOSE
  12.101  
  12.102 -      // Now choose the CS. We may abandon a pause if we find no
  12.103 -      // region that will fit in the MMU pause.
  12.104 -      bool abandoned = g1_policy()->choose_collection_set(target_pause_time_ms);
  12.105 +      g1_policy()->choose_collection_set(target_pause_time_ms);
  12.106  
  12.107        // Nothing to do if we were unable to choose a collection set.
  12.108 -      if (!abandoned) {
  12.109  #if G1_REM_SET_LOGGING
  12.110 -        gclog_or_tty->print_cr("\nAfter pause, heap:");
  12.111 -        print();
  12.112 +      gclog_or_tty->print_cr("\nAfter pause, heap:");
  12.113 +      print();
  12.114  #endif
  12.115 -        PrepareForRSScanningClosure prepare_for_rs_scan;
  12.116 -        collection_set_iterate(&prepare_for_rs_scan);
  12.117 -
  12.118 -        setup_surviving_young_words();
  12.119 -
  12.120 -        // Set up the gc allocation regions.
  12.121 -        get_gc_alloc_regions();
  12.122 -
  12.123 -        // Actually do the work...
  12.124 -        evacuate_collection_set();
  12.125 -
  12.126 -        free_collection_set(g1_policy()->collection_set());
  12.127 -        g1_policy()->clear_collection_set();
  12.128 -
  12.129 -        cleanup_surviving_young_words();
  12.130 -
  12.131 -        // Start a new incremental collection set for the next pause.
  12.132 -        g1_policy()->start_incremental_cset_building();
  12.133 -
  12.134 -        // Clear the _cset_fast_test bitmap in anticipation of adding
  12.135 -        // regions to the incremental collection set for the next
  12.136 -        // evacuation pause.
  12.137 -        clear_cset_fast_test();
  12.138 -
  12.139 -        if (g1_policy()->in_young_gc_mode()) {
  12.140 -          _young_list->reset_sampled_info();
  12.141 -
  12.142 -          // Don't check the whole heap at this point as the
  12.143 -          // GC alloc regions from this pause have been tagged
  12.144 -          // as survivors and moved on to the survivor list.
  12.145 -          // Survivor regions will fail the !is_young() check.
  12.146 -          assert(check_young_list_empty(false /* check_heap */),
  12.147 -              "young list should be empty");
  12.148 +      PrepareForRSScanningClosure prepare_for_rs_scan;
  12.149 +      collection_set_iterate(&prepare_for_rs_scan);
  12.150 +
  12.151 +      setup_surviving_young_words();
  12.152 +
  12.153 +      // Set up the gc allocation regions.
  12.154 +      get_gc_alloc_regions();
  12.155 +
  12.156 +      // Actually do the work...
  12.157 +      evacuate_collection_set();
  12.158 +
  12.159 +      free_collection_set(g1_policy()->collection_set());
  12.160 +      g1_policy()->clear_collection_set();
  12.161 +
  12.162 +      cleanup_surviving_young_words();
  12.163 +
  12.164 +      // Start a new incremental collection set for the next pause.
  12.165 +      g1_policy()->start_incremental_cset_building();
  12.166 +
  12.167 +      // Clear the _cset_fast_test bitmap in anticipation of adding
  12.168 +      // regions to the incremental collection set for the next
  12.169 +      // evacuation pause.
  12.170 +      clear_cset_fast_test();
  12.171 +
  12.172 +      if (g1_policy()->in_young_gc_mode()) {
  12.173 +        _young_list->reset_sampled_info();
  12.174 +
  12.175 +        // Don't check the whole heap at this point as the
  12.176 +        // GC alloc regions from this pause have been tagged
  12.177 +        // as survivors and moved on to the survivor list.
  12.178 +        // Survivor regions will fail the !is_young() check.
  12.179 +        assert(check_young_list_empty(false /* check_heap */),
  12.180 +               "young list should be empty");
  12.181  
  12.182  #if YOUNG_LIST_VERBOSE
  12.183 -          gclog_or_tty->print_cr("Before recording survivors.\nYoung List:");
  12.184 -          _young_list->print();
  12.185 +        gclog_or_tty->print_cr("Before recording survivors.\nYoung List:");
  12.186 +        _young_list->print();
  12.187  #endif // YOUNG_LIST_VERBOSE
  12.188  
  12.189 -          g1_policy()->record_survivor_regions(_young_list->survivor_length(),
  12.190 +        g1_policy()->record_survivor_regions(_young_list->survivor_length(),
  12.191                                            _young_list->first_survivor_region(),
  12.192                                            _young_list->last_survivor_region());
  12.193  
  12.194 -          _young_list->reset_auxilary_lists();
  12.195 -        }
  12.196 -      } else {
  12.197 -        // We have abandoned the current collection. This can only happen
  12.198 -        // if we're not doing young or partially young collections, and
  12.199 -        // we didn't find an old region that we're able to collect within
  12.200 -        // the allowed time.
  12.201 -
  12.202 -        assert(g1_policy()->collection_set() == NULL, "should be");
  12.203 -        assert(_young_list->length() == 0, "because it should be");
  12.204 -
  12.205 -        // This should be a no-op.
  12.206 -        abandon_collection_set(g1_policy()->inc_cset_head());
  12.207 -
  12.208 -        g1_policy()->clear_incremental_cset();
  12.209 -        g1_policy()->stop_incremental_cset_building();
  12.210 -
  12.211 -        // Start a new incremental collection set for the next pause.
  12.212 -        g1_policy()->start_incremental_cset_building();
  12.213 -
  12.214 -        // Clear the _cset_fast_test bitmap in anticipation of adding
  12.215 -        // regions to the incremental collection set for the next
  12.216 -        // evacuation pause.
  12.217 -        clear_cset_fast_test();
  12.218 -
  12.219 -        // This looks confusing, because the DPT should really be empty
  12.220 -        // at this point -- since we have not done any collection work,
  12.221 -        // there should not be any derived pointers in the table to update;
  12.222 -        // however, there is some additional state in the DPT which is
  12.223 -        // reset at the end of the (null) "gc" here via the following call.
  12.224 -        // A better approach might be to split off that state resetting work
  12.225 -        // into a separate method that asserts that the DPT is empty and call
  12.226 -        // that here. That is deferred for now.
  12.227 -        COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
  12.228 +        _young_list->reset_auxilary_lists();
  12.229        }
  12.230  
  12.231        if (evacuation_failed()) {
  12.232 @@ -2945,7 +2956,7 @@
  12.233        double end_time_sec = os::elapsedTime();
  12.234        double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS;
  12.235        g1_policy()->record_pause_time_ms(pause_time_ms);
  12.236 -      g1_policy()->record_collection_pause_end(abandoned);
  12.237 +      g1_policy()->record_collection_pause_end();
  12.238  
  12.239        assert(regions_accounted_for(), "Region leakage.");
  12.240  
  12.241 @@ -2988,6 +2999,9 @@
  12.242      }
  12.243    }
  12.244  
  12.245 +  TASKQUEUE_STATS_ONLY(if (ParallelGCVerbose) print_taskqueue_stats());
  12.246 +  TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
  12.247 +
  12.248    if (PrintHeapAtGC) {
  12.249      Universe::print_heap_after_gc();
  12.250    }
  12.251 @@ -3346,25 +3360,6 @@
  12.252    }
  12.253  };
  12.254  
  12.255 -class UpdateRSetImmediate : public OopsInHeapRegionClosure {
  12.256 -private:
  12.257 -  G1CollectedHeap* _g1;
  12.258 -  G1RemSet* _g1_rem_set;
  12.259 -public:
  12.260 -  UpdateRSetImmediate(G1CollectedHeap* g1) :
  12.261 -    _g1(g1), _g1_rem_set(g1->g1_rem_set()) {}
  12.262 -
  12.263 -  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  12.264 -  virtual void do_oop(      oop* p) { do_oop_work(p); }
  12.265 -  template <class T> void do_oop_work(T* p) {
  12.266 -    assert(_from->is_in_reserved(p), "paranoia");
  12.267 -    T heap_oop = oopDesc::load_heap_oop(p);
  12.268 -    if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) {
  12.269 -      _g1_rem_set->par_write_ref(_from, p, 0);
  12.270 -    }
  12.271 -  }
  12.272 -};
  12.273 -
  12.274  class UpdateRSetDeferred : public OopsInHeapRegionClosure {
  12.275  private:
  12.276    G1CollectedHeap* _g1;
  12.277 @@ -3389,8 +3384,6 @@
  12.278    }
  12.279  };
  12.280  
  12.281 -
  12.282 -
  12.283  class RemoveSelfPointerClosure: public ObjectClosure {
  12.284  private:
  12.285    G1CollectedHeap* _g1;
  12.286 @@ -3453,7 +3446,7 @@
  12.287  };
  12.288  
  12.289  void G1CollectedHeap::remove_self_forwarding_pointers() {
  12.290 -  UpdateRSetImmediate immediate_update(_g1h);
  12.291 +  UpdateRSetImmediate immediate_update(_g1h->g1_rem_set());
  12.292    DirtyCardQueue dcq(&_g1h->dirty_card_queue_set());
  12.293    UpdateRSetDeferred deferred_update(_g1h, &dcq);
  12.294    OopsInHeapRegionClosure *cl;
  12.295 @@ -3754,10 +3747,6 @@
  12.296      _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)),
  12.297      _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)),
  12.298      _age_table(false),
  12.299 -#if G1_DETAILED_STATS
  12.300 -    _pushes(0), _pops(0), _steals(0),
  12.301 -    _steal_attempts(0),  _overflow_pushes(0),
  12.302 -#endif
  12.303      _strong_roots_time(0), _term_time(0),
  12.304      _alloc_buffer_waste(0), _undo_waste(0)
  12.305  {
  12.306 @@ -3777,14 +3766,41 @@
  12.307    _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
  12.308    memset(_surviving_young_words, 0, real_length * sizeof(size_t));
  12.309  
  12.310 -  _overflowed_refs = new OverflowQueue(10);
  12.311 -
  12.312    _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer;
  12.313    _alloc_buffers[GCAllocForTenured]  = &_tenured_alloc_buffer;
  12.314  
  12.315    _start = os::elapsedTime();
  12.316  }
  12.317  
  12.318 +void
  12.319 +G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st)
  12.320 +{
  12.321 +  st->print_raw_cr("GC Termination Stats");
  12.322 +  st->print_raw_cr("     elapsed  --strong roots-- -------termination-------"
  12.323 +                   " ------waste (KiB)------");
  12.324 +  st->print_raw_cr("thr     ms        ms      %        ms      %    attempts"
  12.325 +                   "  total   alloc    undo");
  12.326 +  st->print_raw_cr("--- --------- --------- ------ --------- ------ --------"
  12.327 +                   " ------- ------- -------");
  12.328 +}
  12.329 +
  12.330 +void
  12.331 +G1ParScanThreadState::print_termination_stats(int i,
  12.332 +                                              outputStream* const st) const
  12.333 +{
  12.334 +  const double elapsed_ms = elapsed_time() * 1000.0;
  12.335 +  const double s_roots_ms = strong_roots_time() * 1000.0;
  12.336 +  const double term_ms    = term_time() * 1000.0;
  12.337 +  st->print_cr("%3d %9.2f %9.2f %6.2f "
  12.338 +               "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
  12.339 +               SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
  12.340 +               i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
  12.341 +               term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
  12.342 +               (alloc_buffer_waste() + undo_waste()) * HeapWordSize / K,
  12.343 +               alloc_buffer_waste() * HeapWordSize / K,
  12.344 +               undo_waste() * HeapWordSize / K);
  12.345 +}
  12.346 +
  12.347  G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
  12.348    _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()),
  12.349    _par_scan_state(par_scan_state) { }
  12.350 @@ -3991,12 +4007,9 @@
  12.351      G1ParScanThreadState* pss = par_scan_state();
  12.352      while (true) {
  12.353        pss->trim_queue();
  12.354 -      IF_G1_DETAILED_STATS(pss->note_steal_attempt());
  12.355  
  12.356        StarTask stolen_task;
  12.357        if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
  12.358 -        IF_G1_DETAILED_STATS(pss->note_steal());
  12.359 -
  12.360          // slightly paranoid tests; I'm trying to catch potential
  12.361          // problems before we go into push_on_queue to know where the
  12.362          // problem is coming from
  12.363 @@ -4115,35 +4128,9 @@
  12.364      // Clean up any par-expanded rem sets.
  12.365      HeapRegionRemSet::par_cleanup();
  12.366  
  12.367 -    MutexLocker x(stats_lock());
  12.368      if (ParallelGCVerbose) {
  12.369 -      gclog_or_tty->print("Thread %d complete:\n", i);
  12.370 -#if G1_DETAILED_STATS
  12.371 -      gclog_or_tty->print("  Pushes: %7d    Pops: %7d   Overflows: %7d   Steals %7d (in %d attempts)\n",
  12.372 -                          pss.pushes(),
  12.373 -                          pss.pops(),
  12.374 -                          pss.overflow_pushes(),
  12.375 -                          pss.steals(),
  12.376 -                          pss.steal_attempts());
  12.377 -#endif
  12.378 -      double elapsed      = pss.elapsed();
  12.379 -      double strong_roots = pss.strong_roots_time();
  12.380 -      double term         = pss.term_time();
  12.381 -      gclog_or_tty->print("  Elapsed: %7.2f ms.\n"
  12.382 -                          "    Strong roots: %7.2f ms (%6.2f%%)\n"
  12.383 -                          "    Termination:  %7.2f ms (%6.2f%%) "
  12.384 -                                                 "(in "SIZE_FORMAT" entries)\n",
  12.385 -                          elapsed * 1000.0,
  12.386 -                          strong_roots * 1000.0, (strong_roots*100.0/elapsed),
  12.387 -                          term * 1000.0, (term*100.0/elapsed),
  12.388 -                          pss.term_attempts());
  12.389 -      size_t total_waste = pss.alloc_buffer_waste() + pss.undo_waste();
  12.390 -      gclog_or_tty->print("  Waste: %8dK\n"
  12.391 -                 "    Alloc Buffer: %8dK\n"
  12.392 -                 "    Undo: %8dK\n",
  12.393 -                 (total_waste * HeapWordSize) / K,
  12.394 -                 (pss.alloc_buffer_waste() * HeapWordSize) / K,
  12.395 -                 (pss.undo_waste() * HeapWordSize) / K);
  12.396 +      MutexLocker x(stats_lock());
  12.397 +      pss.print_termination_stats(i);
  12.398      }
  12.399  
  12.400      assert(pss.refs_to_scan() == 0, "Task queue should be empty");
  12.401 @@ -4260,6 +4247,7 @@
  12.402    if (ParallelGCThreads > 0) {
  12.403      // The individual threads will set their evac-failure closures.
  12.404      StrongRootsScope srs(this);
  12.405 +    if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
  12.406      workers()->run_task(&g1_par_task);
  12.407    } else {
  12.408      StrongRootsScope srs(this);
    13.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Aug 13 07:33:20 2010 -0700
    13.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Sat Aug 14 00:47:52 2010 -0700
    13.3 @@ -46,17 +46,7 @@
    13.4  class ConcurrentG1Refine;
    13.5  class ConcurrentZFThread;
    13.6  
    13.7 -// If want to accumulate detailed statistics on work queues
    13.8 -// turn this on.
    13.9 -#define G1_DETAILED_STATS 0
   13.10 -
   13.11 -#if G1_DETAILED_STATS
   13.12 -#  define IF_G1_DETAILED_STATS(code) code
   13.13 -#else
   13.14 -#  define IF_G1_DETAILED_STATS(code)
   13.15 -#endif
   13.16 -
   13.17 -typedef GenericTaskQueue<StarTask>          RefToScanQueue;
   13.18 +typedef OverflowTaskQueue<StarTask>         RefToScanQueue;
   13.19  typedef GenericTaskQueueSet<RefToScanQueue> RefToScanQueueSet;
   13.20  
   13.21  typedef int RegionIdx_t;   // needs to hold [ 0..max_regions() )
   13.22 @@ -471,6 +461,12 @@
   13.23    virtual void shrink(size_t expand_bytes);
   13.24    void shrink_helper(size_t expand_bytes);
   13.25  
   13.26 +  #if TASKQUEUE_STATS
   13.27 +  static void print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty);
   13.28 +  void print_taskqueue_stats(outputStream* const st = gclog_or_tty) const;
   13.29 +  void reset_taskqueue_stats();
   13.30 +  #endif // TASKQUEUE_STATS
   13.31 +
   13.32    // Do an incremental collection: identify a collection set, and evacuate
   13.33    // its live objects elsewhere.
   13.34    virtual void do_collection_pause();
   13.35 @@ -505,6 +501,12 @@
   13.36    // A function to check the consistency of dirty card logs.
   13.37    void check_ct_logs_at_safepoint();
   13.38  
   13.39 +  // A DirtyCardQueueSet that is used to hold cards that contain
   13.40 +  // references into the current collection set. This is used to
   13.41 +  // update the remembered sets of the regions in the collection
   13.42 +  // set in the event of an evacuation failure.
   13.43 +  DirtyCardQueueSet _into_cset_dirty_card_queue_set;
   13.44 +
   13.45    // After a collection pause, make the regions in the CS into free
   13.46    // regions.
   13.47    void free_collection_set(HeapRegion* cs_head);
   13.48 @@ -656,11 +658,18 @@
   13.49  public:
   13.50    void set_refine_cte_cl_concurrency(bool concurrent);
   13.51  
   13.52 -  RefToScanQueue *task_queue(int i);
   13.53 +  RefToScanQueue *task_queue(int i) const;
   13.54  
   13.55    // A set of cards where updates happened during the GC
   13.56    DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; }
   13.57  
   13.58 +  // A DirtyCardQueueSet that is used to hold cards that contain
   13.59 +  // references into the current collection set. This is used to
   13.60 +  // update the remembered sets of the regions in the collection
   13.61 +  // set in the event of an evacuation failure.
   13.62 +  DirtyCardQueueSet& into_cset_dirty_card_queue_set()
   13.63 +        { return _into_cset_dirty_card_queue_set; }
   13.64 +
   13.65    // Create a G1CollectedHeap with the specified policy.
   13.66    // Must call the initialize method afterwards.
   13.67    // May not return if something goes wrong.
   13.68 @@ -715,7 +724,9 @@
   13.69      OrderAccess::fence();
   13.70    }
   13.71  
   13.72 -  void iterate_dirty_card_closure(bool concurrent, int worker_i);
   13.73 +  void iterate_dirty_card_closure(CardTableEntryClosure* cl,
   13.74 +                                  DirtyCardQueue* into_cset_dcq,
   13.75 +                                  bool concurrent, int worker_i);
   13.76  
   13.77    // The shared block offset table array.
   13.78    G1BlockOffsetSharedArray* bot_shared() const { return _bot_shared; }
   13.79 @@ -1564,9 +1575,6 @@
   13.80    CardTableModRefBS* _ct_bs;
   13.81    G1RemSet* _g1_rem;
   13.82  
   13.83 -  typedef GrowableArray<StarTask> OverflowQueue;
   13.84 -  OverflowQueue* _overflowed_refs;
   13.85 -
   13.86    G1ParGCAllocBuffer  _surviving_alloc_buffer;
   13.87    G1ParGCAllocBuffer  _tenured_alloc_buffer;
   13.88    G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
   13.89 @@ -1583,10 +1591,6 @@
   13.90    int _queue_num;
   13.91  
   13.92    size_t _term_attempts;
   13.93 -#if G1_DETAILED_STATS
   13.94 -  int _pushes, _pops, _steals, _steal_attempts;
   13.95 -  int _overflow_pushes;
   13.96 -#endif
   13.97  
   13.98    double _start;
   13.99    double _start_strong_roots;
  13.100 @@ -1600,7 +1604,7 @@
  13.101    // this points into the array, as we use the first few entries for padding
  13.102    size_t* _surviving_young_words;
  13.103  
  13.104 -#define PADDING_ELEM_NUM (64 / sizeof(size_t))
  13.105 +#define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
  13.106  
  13.107    void   add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
  13.108  
  13.109 @@ -1635,15 +1639,14 @@
  13.110    }
  13.111  
  13.112    RefToScanQueue*   refs()            { return _refs;             }
  13.113 -  OverflowQueue*    overflowed_refs() { return _overflowed_refs;  }
  13.114    ageTable*         age_table()       { return &_age_table;       }
  13.115  
  13.116    G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
  13.117      return _alloc_buffers[purpose];
  13.118    }
  13.119  
  13.120 -  size_t alloc_buffer_waste()                    { return _alloc_buffer_waste; }
  13.121 -  size_t undo_waste()                            { return _undo_waste; }
  13.122 +  size_t alloc_buffer_waste() const              { return _alloc_buffer_waste; }
  13.123 +  size_t undo_waste() const                      { return _undo_waste; }
  13.124  
  13.125    template <class T> void push_on_queue(T* ref) {
  13.126      assert(ref != NULL, "invariant");
  13.127 @@ -1656,12 +1659,7 @@
  13.128        assert(_g1h->obj_in_cs(p), "Should be in CS");
  13.129      }
  13.130  #endif
  13.131 -    if (!refs()->push(ref)) {
  13.132 -      overflowed_refs()->push(ref);
  13.133 -      IF_G1_DETAILED_STATS(note_overflow_push());
  13.134 -    } else {
  13.135 -      IF_G1_DETAILED_STATS(note_push());
  13.136 -    }
  13.137 +    refs()->push(ref);
  13.138    }
  13.139  
  13.140    void pop_from_queue(StarTask& ref) {
  13.141 @@ -1672,7 +1670,6 @@
  13.142               _g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
  13.143                                                       : oopDesc::load_decode_heap_oop((oop*)ref)),
  13.144                "invariant");
  13.145 -      IF_G1_DETAILED_STATS(note_pop());
  13.146      } else {
  13.147        StarTask null_task;
  13.148        ref = null_task;
  13.149 @@ -1680,7 +1677,8 @@
  13.150    }
  13.151  
  13.152    void pop_from_overflow_queue(StarTask& ref) {
  13.153 -    StarTask new_ref = overflowed_refs()->pop();
  13.154 +    StarTask new_ref;
  13.155 +    refs()->pop_overflow(new_ref);
  13.156      assert((oop*)new_ref != NULL, "pop() from a local non-empty stack");
  13.157      assert(UseCompressedOops || !new_ref.is_narrow(), "Error");
  13.158      assert(has_partial_array_mask((oop*)new_ref) ||
  13.159 @@ -1690,8 +1688,8 @@
  13.160      ref = new_ref;
  13.161    }
  13.162  
  13.163 -  int refs_to_scan()                             { return refs()->size();                 }
  13.164 -  int overflowed_refs_to_scan()                  { return overflowed_refs()->length();    }
  13.165 +  int refs_to_scan()            { return refs()->size(); }
  13.166 +  int overflowed_refs_to_scan() { return refs()->overflow_stack()->length(); }
  13.167  
  13.168    template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
  13.169      if (G1DeferredRSUpdate) {
  13.170 @@ -1760,30 +1758,16 @@
  13.171    int* hash_seed() { return &_hash_seed; }
  13.172    int  queue_num() { return _queue_num; }
  13.173  
  13.174 -  size_t term_attempts()   { return _term_attempts; }
  13.175 +  size_t term_attempts() const  { return _term_attempts; }
  13.176    void note_term_attempt() { _term_attempts++; }
  13.177  
  13.178 -#if G1_DETAILED_STATS
  13.179 -  int pushes()          { return _pushes; }
  13.180 -  int pops()            { return _pops; }
  13.181 -  int steals()          { return _steals; }
  13.182 -  int steal_attempts()  { return _steal_attempts; }
  13.183 -  int overflow_pushes() { return _overflow_pushes; }
  13.184 -
  13.185 -  void note_push()          { _pushes++; }
  13.186 -  void note_pop()           { _pops++; }
  13.187 -  void note_steal()         { _steals++; }
  13.188 -  void note_steal_attempt() { _steal_attempts++; }
  13.189 -  void note_overflow_push() { _overflow_pushes++; }
  13.190 -#endif
  13.191 -
  13.192    void start_strong_roots() {
  13.193      _start_strong_roots = os::elapsedTime();
  13.194    }
  13.195    void end_strong_roots() {
  13.196      _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
  13.197    }
  13.198 -  double strong_roots_time() { return _strong_roots_time; }
  13.199 +  double strong_roots_time() const { return _strong_roots_time; }
  13.200  
  13.201    void start_term_time() {
  13.202      note_term_attempt();
  13.203 @@ -1792,12 +1776,17 @@
  13.204    void end_term_time() {
  13.205      _term_time += (os::elapsedTime() - _start_term);
  13.206    }
  13.207 -  double term_time() { return _term_time; }
  13.208 +  double term_time() const { return _term_time; }
  13.209  
  13.210 -  double elapsed() {
  13.211 +  double elapsed_time() const {
  13.212      return os::elapsedTime() - _start;
  13.213    }
  13.214  
  13.215 +  static void
  13.216 +    print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
  13.217 +  void
  13.218 +    print_termination_stats(int i, outputStream* const st = gclog_or_tty) const;
  13.219 +
  13.220    size_t* surviving_young_words() {
  13.221      // We add on to hide entry 0 which accumulates surviving words for
  13.222      // age -1 regions (i.e. non-young ones)
    14.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
    14.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
    14.3 @@ -81,11 +81,10 @@
    14.4    return attempt_allocation_slow(word_size, permit_collection_pause);
    14.5  }
    14.6  
    14.7 -inline RefToScanQueue* G1CollectedHeap::task_queue(int i) {
    14.8 +inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
    14.9    return _task_queues->queue(i);
   14.10  }
   14.11  
   14.12 -
   14.13  inline  bool G1CollectedHeap::isMarkedPrev(oop obj) const {
   14.14    return _cm->prevMarkBitMap()->isMarked((HeapWord *)obj);
   14.15  }
    15.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Fri Aug 13 07:33:20 2010 -0700
    15.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Sat Aug 14 00:47:52 2010 -0700
    15.3 @@ -88,7 +88,6 @@
    15.4    _all_mod_union_times_ms(new NumberSeq()),
    15.5  
    15.6    _summary(new Summary()),
    15.7 -  _abandoned_summary(new AbandonedSummary()),
    15.8  
    15.9  #ifndef PRODUCT
   15.10    _cur_clear_ct_time_ms(0.0),
   15.11 @@ -238,7 +237,6 @@
   15.12    _par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
   15.13  
   15.14    _par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
   15.15 -  _par_last_scan_new_refs_times_ms = new double[_parallel_gc_threads];
   15.16  
   15.17    _par_last_obj_copy_times_ms = new double[_parallel_gc_threads];
   15.18  
   15.19 @@ -842,7 +840,6 @@
   15.20      _par_last_update_rs_times_ms[i] = -1234.0;
   15.21      _par_last_update_rs_processed_buffers[i] = -1234.0;
   15.22      _par_last_scan_rs_times_ms[i] = -1234.0;
   15.23 -    _par_last_scan_new_refs_times_ms[i] = -1234.0;
   15.24      _par_last_obj_copy_times_ms[i] = -1234.0;
   15.25      _par_last_termination_times_ms[i] = -1234.0;
   15.26      _par_last_termination_attempts[i] = -1234.0;
   15.27 @@ -1126,7 +1123,7 @@
   15.28  // Anything below that is considered to be zero
   15.29  #define MIN_TIMER_GRANULARITY 0.0000001
   15.30  
   15.31 -void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
   15.32 +void G1CollectorPolicy::record_collection_pause_end() {
   15.33    double end_time_sec = os::elapsedTime();
   15.34    double elapsed_ms = _last_pause_time_ms;
   15.35    bool parallel = ParallelGCThreads > 0;
   15.36 @@ -1136,7 +1133,7 @@
   15.37    size_t cur_used_bytes = _g1->used();
   15.38    assert(cur_used_bytes == _g1->recalculate_used(), "It should!");
   15.39    bool last_pause_included_initial_mark = false;
   15.40 -  bool update_stats = !abandoned && !_g1->evacuation_failed();
   15.41 +  bool update_stats = !_g1->evacuation_failed();
   15.42  
   15.43  #ifndef PRODUCT
   15.44    if (G1YoungSurvRateVerbose) {
   15.45 @@ -1275,12 +1272,7 @@
   15.46      gclog_or_tty->print_cr("   Recording collection pause(%d)", _n_pauses);
   15.47    }
   15.48  
   15.49 -  PauseSummary* summary;
   15.50 -  if (abandoned) {
   15.51 -    summary = _abandoned_summary;
   15.52 -  } else {
   15.53 -    summary = _summary;
   15.54 -  }
   15.55 +  PauseSummary* summary = _summary;
   15.56  
   15.57    double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
   15.58    double mark_stack_scan_time = avg_value(_par_last_mark_stack_scan_times_ms);
   15.59 @@ -1348,61 +1340,58 @@
   15.60  
   15.61    double other_time_ms = elapsed_ms;
   15.62  
   15.63 -  if (!abandoned) {
   15.64 -    if (_satb_drain_time_set)
   15.65 -      other_time_ms -= _cur_satb_drain_time_ms;
   15.66 -
   15.67 -    if (parallel)
   15.68 -      other_time_ms -= _cur_collection_par_time_ms + _cur_clear_ct_time_ms;
   15.69 -    else
   15.70 -      other_time_ms -=
   15.71 -        update_rs_time +
   15.72 -        ext_root_scan_time + mark_stack_scan_time +
   15.73 -        scan_rs_time + obj_copy_time;
   15.74 +  if (_satb_drain_time_set) {
   15.75 +    other_time_ms -= _cur_satb_drain_time_ms;
   15.76    }
   15.77  
   15.78 +  if (parallel) {
   15.79 +    other_time_ms -= _cur_collection_par_time_ms + _cur_clear_ct_time_ms;
   15.80 +  } else {
   15.81 +    other_time_ms -=
   15.82 +      update_rs_time +
   15.83 +      ext_root_scan_time + mark_stack_scan_time +
   15.84 +      scan_rs_time + obj_copy_time;
   15.85 +  }
   15.86 +
   15.87    if (PrintGCDetails) {
   15.88 -    gclog_or_tty->print_cr("%s%s, %1.8lf secs]",
   15.89 -                           abandoned ? " (abandoned)" : "",
   15.90 +    gclog_or_tty->print_cr("%s, %1.8lf secs]",
   15.91                             (last_pause_included_initial_mark) ? " (initial-mark)" : "",
   15.92                             elapsed_ms / 1000.0);
   15.93  
   15.94 -    if (!abandoned) {
   15.95 -      if (_satb_drain_time_set) {
   15.96 -        print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms);
   15.97 -      }
   15.98 -      if (_last_satb_drain_processed_buffers >= 0) {
   15.99 -        print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers);
  15.100 -      }
  15.101 -      if (parallel) {
  15.102 -        print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
  15.103 -        print_par_stats(2, "GC Worker Start Time",
  15.104 -                        _par_last_gc_worker_start_times_ms, false);
  15.105 -        print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
  15.106 -        print_par_sizes(3, "Processed Buffers",
  15.107 -                        _par_last_update_rs_processed_buffers, true);
  15.108 -        print_par_stats(2, "Ext Root Scanning",
  15.109 -                        _par_last_ext_root_scan_times_ms);
  15.110 -        print_par_stats(2, "Mark Stack Scanning",
  15.111 -                        _par_last_mark_stack_scan_times_ms);
  15.112 -        print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
  15.113 -        print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
  15.114 -        print_par_stats(2, "Termination", _par_last_termination_times_ms);
  15.115 -        print_par_sizes(3, "Termination Attempts",
  15.116 -                        _par_last_termination_attempts, true);
  15.117 -        print_par_stats(2, "GC Worker End Time",
  15.118 -                        _par_last_gc_worker_end_times_ms, false);
  15.119 -        print_stats(2, "Other", parallel_other_time);
  15.120 -        print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
  15.121 -      } else {
  15.122 -        print_stats(1, "Update RS", update_rs_time);
  15.123 -        print_stats(2, "Processed Buffers",
  15.124 -                    (int)update_rs_processed_buffers);
  15.125 -        print_stats(1, "Ext Root Scanning", ext_root_scan_time);
  15.126 -        print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
  15.127 -        print_stats(1, "Scan RS", scan_rs_time);
  15.128 -        print_stats(1, "Object Copying", obj_copy_time);
  15.129 -      }
  15.130 +    if (_satb_drain_time_set) {
  15.131 +      print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms);
  15.132 +    }
  15.133 +    if (_last_satb_drain_processed_buffers >= 0) {
  15.134 +      print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers);
  15.135 +    }
  15.136 +    if (parallel) {
  15.137 +      print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
  15.138 +      print_par_stats(2, "GC Worker Start Time",
  15.139 +                      _par_last_gc_worker_start_times_ms, false);
  15.140 +      print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
  15.141 +      print_par_sizes(3, "Processed Buffers",
  15.142 +                      _par_last_update_rs_processed_buffers, true);
  15.143 +      print_par_stats(2, "Ext Root Scanning",
  15.144 +                      _par_last_ext_root_scan_times_ms);
  15.145 +      print_par_stats(2, "Mark Stack Scanning",
  15.146 +                      _par_last_mark_stack_scan_times_ms);
  15.147 +      print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
  15.148 +      print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
  15.149 +      print_par_stats(2, "Termination", _par_last_termination_times_ms);
  15.150 +      print_par_sizes(3, "Termination Attempts",
  15.151 +                      _par_last_termination_attempts, true);
  15.152 +      print_par_stats(2, "GC Worker End Time",
  15.153 +                      _par_last_gc_worker_end_times_ms, false);
  15.154 +      print_stats(2, "Other", parallel_other_time);
  15.155 +      print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
  15.156 +    } else {
  15.157 +      print_stats(1, "Update RS", update_rs_time);
  15.158 +      print_stats(2, "Processed Buffers",
  15.159 +                  (int)update_rs_processed_buffers);
  15.160 +      print_stats(1, "Ext Root Scanning", ext_root_scan_time);
  15.161 +      print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
  15.162 +      print_stats(1, "Scan RS", scan_rs_time);
  15.163 +      print_stats(1, "Object Copying", obj_copy_time);
  15.164      }
  15.165  #ifndef PRODUCT
  15.166      print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
  15.167 @@ -2178,33 +2167,27 @@
  15.168      print_summary(1, "Other", summary->get_other_seq());
  15.169      {
  15.170        NumberSeq calc_other_times_ms;
  15.171 -      if (body_summary != NULL) {
  15.172 -        // not abandoned
  15.173 -        if (parallel) {
  15.174 -          // parallel
  15.175 -          NumberSeq* other_parts[] = {
  15.176 -            body_summary->get_satb_drain_seq(),
  15.177 -            body_summary->get_parallel_seq(),
  15.178 -            body_summary->get_clear_ct_seq()
  15.179 -          };
  15.180 -          calc_other_times_ms = NumberSeq(summary->get_total_seq(),
  15.181 -                                          3, other_parts);
  15.182 -        } else {
  15.183 -          // serial
  15.184 -          NumberSeq* other_parts[] = {
  15.185 -            body_summary->get_satb_drain_seq(),
  15.186 -            body_summary->get_update_rs_seq(),
  15.187 -            body_summary->get_ext_root_scan_seq(),
  15.188 -            body_summary->get_mark_stack_scan_seq(),
  15.189 -            body_summary->get_scan_rs_seq(),
  15.190 -            body_summary->get_obj_copy_seq()
  15.191 -          };
  15.192 -          calc_other_times_ms = NumberSeq(summary->get_total_seq(),
  15.193 -                                          7, other_parts);
  15.194 -        }
  15.195 +      if (parallel) {
  15.196 +        // parallel
  15.197 +        NumberSeq* other_parts[] = {
  15.198 +          body_summary->get_satb_drain_seq(),
  15.199 +          body_summary->get_parallel_seq(),
  15.200 +          body_summary->get_clear_ct_seq()
  15.201 +        };
  15.202 +        calc_other_times_ms = NumberSeq(summary->get_total_seq(),
  15.203 +                                        3, other_parts);
  15.204        } else {
  15.205 -        // abandoned
  15.206 -        calc_other_times_ms = NumberSeq();
  15.207 +        // serial
  15.208 +        NumberSeq* other_parts[] = {
  15.209 +          body_summary->get_satb_drain_seq(),
  15.210 +          body_summary->get_update_rs_seq(),
  15.211 +          body_summary->get_ext_root_scan_seq(),
  15.212 +          body_summary->get_mark_stack_scan_seq(),
  15.213 +          body_summary->get_scan_rs_seq(),
  15.214 +          body_summary->get_obj_copy_seq()
  15.215 +        };
  15.216 +        calc_other_times_ms = NumberSeq(summary->get_total_seq(),
  15.217 +                                        7, other_parts);
  15.218        }
  15.219        check_other_times(1,  summary->get_other_seq(), &calc_other_times_ms);
  15.220      }
  15.221 @@ -2215,20 +2198,6 @@
  15.222    gclog_or_tty->print_cr("");
  15.223  }
  15.224  
  15.225 -void
  15.226 -G1CollectorPolicy::print_abandoned_summary(PauseSummary* summary) const {
  15.227 -  bool printed = false;
  15.228 -  if (summary->get_total_seq()->num() > 0) {
  15.229 -    printed = true;
  15.230 -    print_summary(summary);
  15.231 -  }
  15.232 -  if (!printed) {
  15.233 -    print_indent(0);
  15.234 -    gclog_or_tty->print_cr("none");
  15.235 -    gclog_or_tty->print_cr("");
  15.236 -  }
  15.237 -}
  15.238 -
  15.239  void G1CollectorPolicy::print_tracing_info() const {
  15.240    if (TraceGen0Time) {
  15.241      gclog_or_tty->print_cr("ALL PAUSES");
  15.242 @@ -2242,9 +2211,6 @@
  15.243      gclog_or_tty->print_cr("EVACUATION PAUSES");
  15.244      print_summary(_summary);
  15.245  
  15.246 -    gclog_or_tty->print_cr("ABANDONED PAUSES");
  15.247 -    print_abandoned_summary(_abandoned_summary);
  15.248 -
  15.249      gclog_or_tty->print_cr("MISC");
  15.250      print_summary_sd(0, "Stop World", _all_stop_world_times_ms);
  15.251      print_summary_sd(0, "Yields", _all_yield_times_ms);
  15.252 @@ -2870,19 +2836,12 @@
  15.253  }
  15.254  #endif // !PRODUCT
  15.255  
  15.256 -bool
  15.257 +void
  15.258  G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
  15.259                                                    double target_pause_time_ms) {
  15.260    // Set this here - in case we're not doing young collections.
  15.261    double non_young_start_time_sec = os::elapsedTime();
  15.262  
  15.263 -  // The result that this routine will return. This will be set to
  15.264 -  // false if:
  15.265 -  // * we're doing a young or partially young collection and we
  15.266 -  //   have added the youg regions to collection set, or
  15.267 -  // * we add old regions to the collection set.
  15.268 -  bool abandon_collection = true;
  15.269 -
  15.270    start_recording_regions();
  15.271  
  15.272    guarantee(target_pause_time_ms > 0.0,
  15.273 @@ -2986,10 +2945,6 @@
  15.274      }
  15.275  
  15.276      assert(_inc_cset_size == _g1->young_list()->length(), "Invariant");
  15.277 -    if (_inc_cset_size > 0) {
  15.278 -      assert(_collection_set != NULL, "Invariant");
  15.279 -      abandon_collection = false;
  15.280 -    }
  15.281  
  15.282      double young_end_time_sec = os::elapsedTime();
  15.283      _recorded_young_cset_choice_time_ms =
  15.284 @@ -3011,10 +2966,6 @@
  15.285      NumberSeq seq;
  15.286      double avg_prediction = 100000000000000000.0; // something very large
  15.287  
  15.288 -    // Save the current size of the collection set to detect
  15.289 -    // if we actually added any old regions.
  15.290 -    size_t n_young_regions = _collection_set_size;
  15.291 -
  15.292      do {
  15.293        hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms,
  15.294                                                        avg_prediction);
  15.295 @@ -3041,12 +2992,6 @@
  15.296      if (!adaptive_young_list_length() &&
  15.297          _collection_set_size < _young_list_fixed_length)
  15.298        _should_revert_to_full_young_gcs  = true;
  15.299 -
  15.300 -    if (_collection_set_size > n_young_regions) {
  15.301 -      // We actually added old regions to the collection set
  15.302 -      // so we are not abandoning this collection.
  15.303 -      abandon_collection = false;
  15.304 -    }
  15.305    }
  15.306  
  15.307  choose_collection_set_end:
  15.308 @@ -3059,19 +3004,6 @@
  15.309    double non_young_end_time_sec = os::elapsedTime();
  15.310    _recorded_non_young_cset_choice_time_ms =
  15.311      (non_young_end_time_sec - non_young_start_time_sec) * 1000.0;
  15.312 -
  15.313 -  // Here we are supposed to return whether the pause should be
  15.314 -  // abandoned or not (i.e., whether the collection set is empty or
  15.315 -  // not). However, this introduces a subtle issue when a pause is
  15.316 -  // initiated explicitly with System.gc() and
  15.317 -  // +ExplicitGCInvokesConcurrent (see Comment #2 in CR 6944166), it's
  15.318 -  // supposed to start a marking cycle, and it's abandoned. So, by
  15.319 -  // returning false here we are telling the caller never to consider
  15.320 -  // a pause to be abandoned. We'll actually remove all the code
  15.321 -  // associated with abandoned pauses as part of CR 6963209, but we are
  15.322 -  // just disabling them this way for the moment to avoid increasing
  15.323 -  // further the amount of changes for CR 6944166.
  15.324 -  return false;
  15.325  }
  15.326  
  15.327  void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() {
  15.328 @@ -3086,7 +3018,7 @@
  15.329  }
  15.330  
  15.331  void G1CollectorPolicy_BestRegionsFirst::
  15.332 -record_collection_pause_end(bool abandoned) {
  15.333 -  G1CollectorPolicy::record_collection_pause_end(abandoned);
  15.334 +record_collection_pause_end() {
  15.335 +  G1CollectorPolicy::record_collection_pause_end();
  15.336    assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end.");
  15.337  }
    16.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Fri Aug 13 07:33:20 2010 -0700
    16.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Sat Aug 14 00:47:52 2010 -0700
    16.3 @@ -63,8 +63,6 @@
    16.4      define_num_seq(mark_stack_scan)
    16.5      define_num_seq(update_rs)
    16.6      define_num_seq(scan_rs)
    16.7 -    define_num_seq(scan_new_refs) // Only for temp use; added to
    16.8 -                                  // in parallel case.
    16.9      define_num_seq(obj_copy)
   16.10      define_num_seq(termination) // parallel only
   16.11      define_num_seq(parallel_other) // parallel only
   16.12 @@ -78,9 +76,6 @@
   16.13    virtual MainBodySummary*    main_body_summary()    { return this; }
   16.14  };
   16.15  
   16.16 -class AbandonedSummary: public PauseSummary {
   16.17 -};
   16.18 -
   16.19  class G1CollectorPolicy: public CollectorPolicy {
   16.20  protected:
   16.21    // The number of pauses during the execution.
   16.22 @@ -150,7 +145,6 @@
   16.23    TruncatedSeq* _concurrent_mark_cleanup_times_ms;
   16.24  
   16.25    Summary*           _summary;
   16.26 -  AbandonedSummary*  _abandoned_summary;
   16.27  
   16.28    NumberSeq* _all_pause_times_ms;
   16.29    NumberSeq* _all_full_gc_times_ms;
   16.30 @@ -177,7 +171,6 @@
   16.31    double* _par_last_update_rs_times_ms;
   16.32    double* _par_last_update_rs_processed_buffers;
   16.33    double* _par_last_scan_rs_times_ms;
   16.34 -  double* _par_last_scan_new_refs_times_ms;
   16.35    double* _par_last_obj_copy_times_ms;
   16.36    double* _par_last_termination_times_ms;
   16.37    double* _par_last_termination_attempts;
   16.38 @@ -576,7 +569,6 @@
   16.39                           NumberSeq* calc_other_times_ms) const;
   16.40  
   16.41    void print_summary (PauseSummary* stats) const;
   16.42 -  void print_abandoned_summary(PauseSummary* summary) const;
   16.43  
   16.44    void print_summary (int level, const char* str, NumberSeq* seq) const;
   16.45    void print_summary_sd (int level, const char* str, NumberSeq* seq) const;
   16.46 @@ -889,7 +881,7 @@
   16.47    virtual void record_collection_pause_end_CH_strong_roots();
   16.48    virtual void record_collection_pause_end_G1_strong_roots();
   16.49  
   16.50 -  virtual void record_collection_pause_end(bool abandoned);
   16.51 +  virtual void record_collection_pause_end();
   16.52  
   16.53    // Record the fact that a full collection occurred.
   16.54    virtual void record_full_collection_start();
   16.55 @@ -933,14 +925,6 @@
   16.56      _par_last_scan_rs_times_ms[thread] = ms;
   16.57    }
   16.58  
   16.59 -  void record_scan_new_refs_time(int thread, double ms) {
   16.60 -    _par_last_scan_new_refs_times_ms[thread] = ms;
   16.61 -  }
   16.62 -
   16.63 -  double get_scan_new_refs_time(int thread) {
   16.64 -    return _par_last_scan_new_refs_times_ms[thread];
   16.65 -  }
   16.66 -
   16.67    void reset_obj_copy_time(int thread) {
   16.68      _par_last_obj_copy_times_ms[thread] = 0.0;
   16.69    }
   16.70 @@ -1010,7 +994,7 @@
   16.71    // Choose a new collection set.  Marks the chosen regions as being
   16.72    // "in_collection_set", and links them together.  The head and number of
   16.73    // the collection set are available via access methods.
   16.74 -  virtual bool choose_collection_set(double target_pause_time_ms) = 0;
   16.75 +  virtual void choose_collection_set(double target_pause_time_ms) = 0;
   16.76  
   16.77    // The head of the list (via "next_in_collection_set()") representing the
   16.78    // current collection set.
   16.79 @@ -1267,7 +1251,7 @@
   16.80    // If the estimated is less then desirable, resize if possible.
   16.81    void expand_if_possible(size_t numRegions);
   16.82  
   16.83 -  virtual bool choose_collection_set(double target_pause_time_ms);
   16.84 +  virtual void choose_collection_set(double target_pause_time_ms);
   16.85    virtual void record_collection_pause_start(double start_time_sec,
   16.86                                               size_t start_used);
   16.87    virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes,
   16.88 @@ -1278,7 +1262,7 @@
   16.89    G1CollectorPolicy_BestRegionsFirst() {
   16.90      _collectionSetChooser = new CollectionSetChooser();
   16.91    }
   16.92 -  void record_collection_pause_end(bool abandoned);
   16.93 +  void record_collection_pause_end();
   16.94    bool should_do_collection_pause(size_t word_size);
   16.95    // This is not needed any more, after the CSet choosing code was
   16.96    // changed to use the pause prediction work. But let's leave the
    17.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
    17.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
    17.3 @@ -1,5 +1,5 @@
    17.4  /*
    17.5 - * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved.
    17.6 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
    17.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.8   *
    17.9   * This code is free software; you can redistribute it and/or modify it
   17.10 @@ -37,7 +37,8 @@
   17.11        _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) {
   17.12      _oc->do_oop(p);
   17.13  #if FILTERINTOCSCLOSURE_DOHISTOGRAMCOUNT
   17.14 -    _dcto_cl->incr_count();
   17.15 +    if (_dcto_cl != NULL)
   17.16 +      _dcto_cl->incr_count();
   17.17  #endif
   17.18    }
   17.19  }
   17.20 @@ -113,7 +114,10 @@
   17.21      if (_g1->in_cset_fast_test(obj)) {
   17.22        Prefetch::write(obj->mark_addr(), 0);
   17.23        Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
   17.24 +
   17.25 +      // Place on the references queue
   17.26        _par_scan_state->push_on_queue(p);
   17.27      }
   17.28    }
   17.29  }
   17.30 +
    18.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Fri Aug 13 07:33:20 2010 -0700
    18.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Sat Aug 14 00:47:52 2010 -0700
    18.3 @@ -122,23 +122,24 @@
    18.4  HRInto_G1RemSet::HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
    18.5    : G1RemSet(g1), _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
    18.6      _cg1r(g1->concurrent_g1_refine()),
    18.7 -    _par_traversal_in_progress(false), _new_refs(NULL),
    18.8 +    _traversal_in_progress(false),
    18.9 +    _cset_rs_update_cl(NULL),
   18.10      _cards_scanned(NULL), _total_cards_scanned(0)
   18.11  {
   18.12    _seq_task = new SubTasksDone(NumSeqTasks);
   18.13    guarantee(n_workers() > 0, "There should be some workers");
   18.14 -  _new_refs = NEW_C_HEAP_ARRAY(GrowableArray<OopOrNarrowOopStar>*, n_workers());
   18.15 +  _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers());
   18.16    for (uint i = 0; i < n_workers(); i++) {
   18.17 -    _new_refs[i] = new (ResourceObj::C_HEAP) GrowableArray<OopOrNarrowOopStar>(8192,true);
   18.18 +    _cset_rs_update_cl[i] = NULL;
   18.19    }
   18.20  }
   18.21  
   18.22  HRInto_G1RemSet::~HRInto_G1RemSet() {
   18.23    delete _seq_task;
   18.24    for (uint i = 0; i < n_workers(); i++) {
   18.25 -    delete _new_refs[i];
   18.26 +    assert(_cset_rs_update_cl[i] == NULL, "it should be");
   18.27    }
   18.28 -  FREE_C_HEAP_ARRAY(GrowableArray<OopOrNarrowOopStar>*, _new_refs);
   18.29 +  FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl);
   18.30  }
   18.31  
   18.32  void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
   18.33 @@ -306,12 +307,45 @@
   18.34    _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
   18.35  }
   18.36  
   18.37 -void HRInto_G1RemSet::updateRS(int worker_i) {
   18.38 -  ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
   18.39 +// Closure used for updating RSets and recording references that
   18.40 +// point into the collection set. Only called during an
   18.41 +// evacuation pause.
   18.42  
   18.43 +class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
   18.44 +  G1RemSet* _g1rs;
   18.45 +  DirtyCardQueue* _into_cset_dcq;
   18.46 +public:
   18.47 +  RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h,
   18.48 +                                              DirtyCardQueue* into_cset_dcq) :
   18.49 +    _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
   18.50 +  {}
   18.51 +  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
   18.52 +    // The only time we care about recording cards that
   18.53 +    // contain references that point into the collection set
   18.54 +    // is during RSet updating within an evacuation pause.
   18.55 +    // In this case worker_i should be the id of a GC worker thread.
   18.56 +    assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
   18.57 +    assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "should be a GC worker");
   18.58 +
   18.59 +    if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) {
   18.60 +      // 'card_ptr' contains references that point into the collection
   18.61 +      // set. We need to record the card in the DCQS
   18.62 +      // (G1CollectedHeap::into_cset_dirty_card_queue_set())
   18.63 +      // that's used for that purpose.
   18.64 +      //
   18.65 +      // Enqueue the card
   18.66 +      _into_cset_dcq->enqueue(card_ptr);
   18.67 +    }
   18.68 +    return true;
   18.69 +  }
   18.70 +};
   18.71 +
   18.72 +void HRInto_G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
   18.73    double start = os::elapsedTime();
   18.74 -  // Apply the appropriate closure to all remaining log entries.
   18.75 -  _g1->iterate_dirty_card_closure(false, worker_i);
   18.76 +  // Apply the given closure to all remaining log entries.
   18.77 +  RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
   18.78 +  _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
   18.79 +
   18.80    // Now there should be no dirty cards.
   18.81    if (G1RSLogCheckCardTable) {
   18.82      CountNonCleanMemRegionClosure cl(_g1);
   18.83 @@ -405,33 +439,6 @@
   18.84    }
   18.85  };
   18.86  
   18.87 -template <class T> void
   18.88 -HRInto_G1RemSet::scanNewRefsRS_work(OopsInHeapRegionClosure* oc,
   18.89 -                                    int worker_i) {
   18.90 -  double scan_new_refs_start_sec = os::elapsedTime();
   18.91 -  G1CollectedHeap* g1h = G1CollectedHeap::heap();
   18.92 -  CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set());
   18.93 -  for (int i = 0; i < _new_refs[worker_i]->length(); i++) {
   18.94 -    T* p = (T*) _new_refs[worker_i]->at(i);
   18.95 -    oop obj = oopDesc::load_decode_heap_oop(p);
   18.96 -    // *p was in the collection set when p was pushed on "_new_refs", but
   18.97 -    // another thread may have processed this location from an RS, so it
   18.98 -    // might not point into the CS any longer.  If so, it's obviously been
   18.99 -    // processed, and we don't need to do anything further.
  18.100 -    if (g1h->obj_in_cs(obj)) {
  18.101 -      HeapRegion* r = g1h->heap_region_containing(p);
  18.102 -
  18.103 -      DEBUG_ONLY(HeapRegion* to = g1h->heap_region_containing(obj));
  18.104 -      oc->set_region(r);
  18.105 -      // If "p" has already been processed concurrently, this is
  18.106 -      // idempotent.
  18.107 -      oc->do_oop(p);
  18.108 -    }
  18.109 -  }
  18.110 -  double scan_new_refs_time_ms = (os::elapsedTime() - scan_new_refs_start_sec) * 1000.0;
  18.111 -  _g1p->record_scan_new_refs_time(worker_i, scan_new_refs_time_ms);
  18.112 -}
  18.113 -
  18.114  void HRInto_G1RemSet::cleanupHRRS() {
  18.115    HeapRegionRemSet::cleanup();
  18.116  }
  18.117 @@ -457,32 +464,48 @@
  18.118      count_cl.print_histo();
  18.119    }
  18.120  
  18.121 -  if (ParallelGCThreads > 0) {
  18.122 -    // The two flags below were introduced temporarily to serialize
  18.123 -    // the updating and scanning of remembered sets. There are some
  18.124 -    // race conditions when these two operations are done in parallel
  18.125 -    // and they are causing failures. When we resolve said race
  18.126 -    // conditions, we'll revert back to parallel remembered set
  18.127 -    // updating and scanning. See CRs 6677707 and 6677708.
  18.128 -    if (G1UseParallelRSetUpdating || (worker_i == 0)) {
  18.129 -      updateRS(worker_i);
  18.130 -      scanNewRefsRS(oc, worker_i);
  18.131 -    } else {
  18.132 -      _g1p->record_update_rs_processed_buffers(worker_i, 0.0);
  18.133 -      _g1p->record_update_rs_time(worker_i, 0.0);
  18.134 -      _g1p->record_scan_new_refs_time(worker_i, 0.0);
  18.135 -    }
  18.136 -    if (G1UseParallelRSetScanning || (worker_i == 0)) {
  18.137 -      scanRS(oc, worker_i);
  18.138 -    } else {
  18.139 -      _g1p->record_scan_rs_time(worker_i, 0.0);
  18.140 -    }
  18.141 +  // We cache the value of 'oc' closure into the appropriate slot in the
  18.142 +  // _cset_rs_update_cl for this worker
  18.143 +  assert(worker_i < (int)n_workers(), "sanity");
  18.144 +  _cset_rs_update_cl[worker_i] = oc;
  18.145 +
  18.146 +  // A DirtyCardQueue that is used to hold cards containing references
  18.147 +  // that point into the collection set. This DCQ is associated with a
  18.148 +  // special DirtyCardQueueSet (see g1CollectedHeap.hpp).  Under normal
  18.149 +  // circumstances (i.e. the pause successfully completes), these cards
  18.150 +  // are just discarded (there's no need to update the RSets of regions
  18.151 +  // that were in the collection set - after the pause these regions
  18.152 +  // are wholly 'free' of live objects. In the event of an evacuation
  18.153 +  // failure the cards/buffers in this queue set are:
  18.154 +  // * passed to the DirtyCardQueueSet that is used to manage deferred
  18.155 +  //   RSet updates, or
  18.156 +  // * scanned for references that point into the collection set
  18.157 +  //   and the RSet of the corresponding region in the collection set
  18.158 +  //   is updated immediately.
  18.159 +  DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
  18.160 +
  18.161 +  assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
  18.162 +
  18.163 +  // The two flags below were introduced temporarily to serialize
  18.164 +  // the updating and scanning of remembered sets. There are some
  18.165 +  // race conditions when these two operations are done in parallel
  18.166 +  // and they are causing failures. When we resolve said race
  18.167 +  // conditions, we'll revert back to parallel remembered set
  18.168 +  // updating and scanning. See CRs 6677707 and 6677708.
  18.169 +  if (G1UseParallelRSetUpdating || (worker_i == 0)) {
  18.170 +    updateRS(&into_cset_dcq, worker_i);
  18.171    } else {
  18.172 -    assert(worker_i == 0, "invariant");
  18.173 -    updateRS(0);
  18.174 -    scanNewRefsRS(oc, 0);
  18.175 -    scanRS(oc, 0);
  18.176 +    _g1p->record_update_rs_processed_buffers(worker_i, 0.0);
  18.177 +    _g1p->record_update_rs_time(worker_i, 0.0);
  18.178    }
  18.179 +  if (G1UseParallelRSetScanning || (worker_i == 0)) {
  18.180 +    scanRS(oc, worker_i);
  18.181 +  } else {
  18.182 +    _g1p->record_scan_rs_time(worker_i, 0.0);
  18.183 +  }
  18.184 +
  18.185 +  // We now clear the cached values of _cset_rs_update_cl for this worker
  18.186 +  _cset_rs_update_cl[worker_i] = NULL;
  18.187  }
  18.188  
  18.189  void HRInto_G1RemSet::
  18.190 @@ -497,9 +520,9 @@
  18.191    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
  18.192    dcqs.concatenate_logs();
  18.193  
  18.194 -  assert(!_par_traversal_in_progress, "Invariant between iterations.");
  18.195 +  assert(!_traversal_in_progress, "Invariant between iterations.");
  18.196 +  set_traversal(true);
  18.197    if (ParallelGCThreads > 0) {
  18.198 -    set_par_traversal(true);
  18.199      _seq_task->set_par_threads((int)n_workers());
  18.200    }
  18.201    guarantee( _cards_scanned == NULL, "invariant" );
  18.202 @@ -519,49 +542,65 @@
  18.203    }
  18.204  };
  18.205  
  18.206 -class UpdateRSetOopsIntoCSImmediate : public OopClosure {
  18.207 +// This closure, applied to a DirtyCardQueueSet, is used to immediately
  18.208 +// update the RSets for the regions in the CSet. For each card it iterates
  18.209 +// through the oops which coincide with that card. It scans the reference
  18.210 +// fields in each oop; when it finds an oop that points into the collection
  18.211 +// set, the RSet for the region containing the referenced object is updated.
  18.212 +// Note: _par_traversal_in_progress in the G1RemSet must be FALSE; otherwise
  18.213 +// the UpdateRSetImmediate closure will cause cards to be enqueued on to
  18.214 +// the DCQS that we're iterating over, causing an infinite loop.
  18.215 +class UpdateRSetCardTableEntryIntoCSetClosure: public CardTableEntryClosure {
  18.216    G1CollectedHeap* _g1;
  18.217 +  CardTableModRefBS* _ct_bs;
  18.218  public:
  18.219 -  UpdateRSetOopsIntoCSImmediate(G1CollectedHeap* g1) : _g1(g1) { }
  18.220 -  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  18.221 -  virtual void do_oop(      oop* p) { do_oop_work(p); }
  18.222 -  template <class T> void do_oop_work(T* p) {
  18.223 -    HeapRegion* to = _g1->heap_region_containing(oopDesc::load_decode_heap_oop(p));
  18.224 -    if (to->in_collection_set()) {
  18.225 -      to->rem_set()->add_reference(p, 0);
  18.226 -    }
  18.227 +  UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1,
  18.228 +                                          CardTableModRefBS* bs):
  18.229 +    _g1(g1), _ct_bs(bs)
  18.230 +  { }
  18.231 +
  18.232 +  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
  18.233 +    // Construct the region representing the card.
  18.234 +    HeapWord* start = _ct_bs->addr_for(card_ptr);
  18.235 +    // And find the region containing it.
  18.236 +    HeapRegion* r = _g1->heap_region_containing(start);
  18.237 +    assert(r != NULL, "unexpected null");
  18.238 +
  18.239 +    // Scan oops in the card looking for references into the collection set
  18.240 +    HeapWord* end   = _ct_bs->addr_for(card_ptr + 1);
  18.241 +    MemRegion scanRegion(start, end);
  18.242 +
  18.243 +    UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set());
  18.244 +    FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl);
  18.245 +    FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl);
  18.246 +
  18.247 +    // We can pass false as the "filter_young" parameter here as:
  18.248 +    // * we should be in a STW pause,
  18.249 +    // * the DCQS to which this closure is applied is used to hold
  18.250 +    //   references that point into the collection set from the prior
  18.251 +    //   RSet updating,
  18.252 +    // * the post-write barrier shouldn't be logging updates to young
  18.253 +    //   regions (but there is a situation where this can happen - see
  18.254 +    //   the comment in HRInto_G1RemSet::concurrentRefineOneCard below -
  18.255 +    //   that should not be applicable here), and
  18.256 +    // * during actual RSet updating, the filtering of cards in young
  18.257 +    //   regions in HeapRegion::oops_on_card_seq_iterate_careful is
  18.258 +    //   employed.
  18.259 +    // As a result, when this closure is applied to "refs into cset"
  18.260 +    // DCQS, we shouldn't see any cards in young regions.
  18.261 +    update_rs_cl.set_region(r);
  18.262 +    HeapWord* stop_point =
  18.263 +      r->oops_on_card_seq_iterate_careful(scanRegion,
  18.264 +                                        &filter_then_update_rs_cset_oop_cl,
  18.265 +                                        false /* filter_young */);
  18.266 +
  18.267 +    // Since this is performed in the event of an evacuation failure, we
  18.268 +    // we shouldn't see a non-null stop point
  18.269 +    assert(stop_point == NULL, "saw an unallocated region");
  18.270 +    return true;
  18.271    }
  18.272  };
  18.273  
  18.274 -class UpdateRSetOopsIntoCSDeferred : public OopClosure {
  18.275 -  G1CollectedHeap* _g1;
  18.276 -  CardTableModRefBS* _ct_bs;
  18.277 -  DirtyCardQueue* _dcq;
  18.278 -public:
  18.279 -  UpdateRSetOopsIntoCSDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) :
  18.280 -    _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) { }
  18.281 -  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  18.282 -  virtual void do_oop(      oop* p) { do_oop_work(p); }
  18.283 -  template <class T> void do_oop_work(T* p) {
  18.284 -    oop obj = oopDesc::load_decode_heap_oop(p);
  18.285 -    if (_g1->obj_in_cs(obj)) {
  18.286 -      size_t card_index = _ct_bs->index_for(p);
  18.287 -      if (_ct_bs->mark_card_deferred(card_index)) {
  18.288 -        _dcq->enqueue((jbyte*)_ct_bs->byte_for_index(card_index));
  18.289 -      }
  18.290 -    }
  18.291 -  }
  18.292 -};
  18.293 -
  18.294 -template <class T> void HRInto_G1RemSet::new_refs_iterate_work(OopClosure* cl) {
  18.295 -  for (size_t i = 0; i < n_workers(); i++) {
  18.296 -    for (int j = 0; j < _new_refs[i]->length(); j++) {
  18.297 -      T* p = (T*) _new_refs[i]->at(j);
  18.298 -      cl->do_oop(p);
  18.299 -    }
  18.300 -  }
  18.301 -}
  18.302 -
  18.303  void HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do() {
  18.304    guarantee( _cards_scanned != NULL, "invariant" );
  18.305    _total_cards_scanned = 0;
  18.306 @@ -580,27 +619,42 @@
  18.307    // Set all cards back to clean.
  18.308    _g1->cleanUpCardTable();
  18.309  
  18.310 -  if (ParallelGCThreads > 0) {
  18.311 -    set_par_traversal(false);
  18.312 +  set_traversal(false);
  18.313 +
  18.314 +  DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set();
  18.315 +  int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num();
  18.316 +
  18.317 +  if (_g1->evacuation_failed()) {
  18.318 +    // Restore remembered sets for the regions pointing into the collection set.
  18.319 +
  18.320 +    if (G1DeferredRSUpdate) {
  18.321 +      // If deferred RS updates are enabled then we just need to transfer
  18.322 +      // the completed buffers from (a) the DirtyCardQueueSet used to hold
  18.323 +      // cards that contain references that point into the collection set
  18.324 +      // to (b) the DCQS used to hold the deferred RS updates
  18.325 +      _g1->dirty_card_queue_set().merge_bufferlists(&into_cset_dcqs);
  18.326 +    } else {
  18.327 +
  18.328 +      CardTableModRefBS* bs = (CardTableModRefBS*)_g1->barrier_set();
  18.329 +      UpdateRSetCardTableEntryIntoCSetClosure update_rs_cset_immediate(_g1, bs);
  18.330 +
  18.331 +      int n_completed_buffers = 0;
  18.332 +      while (into_cset_dcqs.apply_closure_to_completed_buffer(&update_rs_cset_immediate,
  18.333 +                                                    0, 0, true)) {
  18.334 +        n_completed_buffers++;
  18.335 +      }
  18.336 +      assert(n_completed_buffers == into_cset_n_buffers, "missed some buffers");
  18.337 +    }
  18.338    }
  18.339  
  18.340 -  if (_g1->evacuation_failed()) {
  18.341 -    // Restore remembered sets for the regions pointing into
  18.342 -    // the collection set.
  18.343 -    if (G1DeferredRSUpdate) {
  18.344 -      DirtyCardQueue dcq(&_g1->dirty_card_queue_set());
  18.345 -      UpdateRSetOopsIntoCSDeferred deferred_update(_g1, &dcq);
  18.346 -      new_refs_iterate(&deferred_update);
  18.347 -    } else {
  18.348 -      UpdateRSetOopsIntoCSImmediate immediate_update(_g1);
  18.349 -      new_refs_iterate(&immediate_update);
  18.350 -    }
  18.351 -  }
  18.352 -  for (uint i = 0; i < n_workers(); i++) {
  18.353 -    _new_refs[i]->clear();
  18.354 -  }
  18.355 +  // Free any completed buffers in the DirtyCardQueueSet used to hold cards
  18.356 +  // which contain references that point into the collection.
  18.357 +  _g1->into_cset_dirty_card_queue_set().clear();
  18.358 +  assert(_g1->into_cset_dirty_card_queue_set().completed_buffers_num() == 0,
  18.359 +         "all buffers should be freed");
  18.360 +  _g1->into_cset_dirty_card_queue_set().clear_n_completed_buffers();
  18.361  
  18.362 -  assert(!_par_traversal_in_progress, "Invariant between iterations.");
  18.363 +  assert(!_traversal_in_progress, "Invariant between iterations.");
  18.364  }
  18.365  
  18.366  class UpdateRSObjectClosure: public ObjectClosure {
  18.367 @@ -652,7 +706,43 @@
  18.368  
  18.369  static IntHistogram out_of_histo(50, 50);
  18.370  
  18.371 -void HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i) {
  18.372 +class TriggerClosure : public OopClosure {
  18.373 +  bool _trigger;
  18.374 +public:
  18.375 +  TriggerClosure() : _trigger(false) { }
  18.376 +  bool value() const { return _trigger; }
  18.377 +  template <class T> void do_oop_nv(T* p) { _trigger = true; }
  18.378 +  virtual void do_oop(oop* p)        { do_oop_nv(p); }
  18.379 +  virtual void do_oop(narrowOop* p)  { do_oop_nv(p); }
  18.380 +};
  18.381 +
  18.382 +class InvokeIfNotTriggeredClosure: public OopClosure {
  18.383 +  TriggerClosure* _t;
  18.384 +  OopClosure* _oc;
  18.385 +public:
  18.386 +  InvokeIfNotTriggeredClosure(TriggerClosure* t, OopClosure* oc):
  18.387 +    _t(t), _oc(oc) { }
  18.388 +  template <class T> void do_oop_nv(T* p) {
  18.389 +    if (!_t->value()) _oc->do_oop(p);
  18.390 +  }
  18.391 +  virtual void do_oop(oop* p)        { do_oop_nv(p); }
  18.392 +  virtual void do_oop(narrowOop* p)  { do_oop_nv(p); }
  18.393 +};
  18.394 +
  18.395 +class Mux2Closure : public OopClosure {
  18.396 +  OopClosure* _c1;
  18.397 +  OopClosure* _c2;
  18.398 +public:
  18.399 +  Mux2Closure(OopClosure *c1, OopClosure *c2) : _c1(c1), _c2(c2) { }
  18.400 +  template <class T> void do_oop_nv(T* p) {
  18.401 +    _c1->do_oop(p); _c2->do_oop(p);
  18.402 +  }
  18.403 +  virtual void do_oop(oop* p)        { do_oop_nv(p); }
  18.404 +  virtual void do_oop(narrowOop* p)  { do_oop_nv(p); }
  18.405 +};
  18.406 +
  18.407 +bool HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
  18.408 +                                                   bool check_for_refs_into_cset) {
  18.409    // Construct the region representing the card.
  18.410    HeapWord* start = _ct_bs->addr_for(card_ptr);
  18.411    // And find the region containing it.
  18.412 @@ -669,7 +759,16 @@
  18.413  
  18.414    UpdateRSOopClosure update_rs_oop_cl(this, worker_i);
  18.415    update_rs_oop_cl.set_from(r);
  18.416 -  FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r, &update_rs_oop_cl);
  18.417 +
  18.418 +  TriggerClosure trigger_cl;
  18.419 +  FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl);
  18.420 +  InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
  18.421 +  Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
  18.422 +
  18.423 +  FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r,
  18.424 +                        (check_for_refs_into_cset ?
  18.425 +                                (OopClosure*)&mux :
  18.426 +                                (OopClosure*)&update_rs_oop_cl));
  18.427  
  18.428    // Undirty the card.
  18.429    *card_ptr = CardTableModRefBS::clean_card_val();
  18.430 @@ -717,11 +816,18 @@
  18.431      out_of_histo.add_entry(filter_then_update_rs_oop_cl.out_of_region());
  18.432      _conc_refine_cards++;
  18.433    }
  18.434 +
  18.435 +  return trigger_cl.value();
  18.436  }
  18.437  
  18.438 -void HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i) {
  18.439 +bool HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
  18.440 +                                              bool check_for_refs_into_cset) {
  18.441    // If the card is no longer dirty, nothing to do.
  18.442 -  if (*card_ptr != CardTableModRefBS::dirty_card_val()) return;
  18.443 +  if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
  18.444 +    // No need to return that this card contains refs that point
  18.445 +    // into the collection set.
  18.446 +    return false;
  18.447 +  }
  18.448  
  18.449    // Construct the region representing the card.
  18.450    HeapWord* start = _ct_bs->addr_for(card_ptr);
  18.451 @@ -729,7 +835,9 @@
  18.452    HeapRegion* r = _g1->heap_region_containing(start);
  18.453    if (r == NULL) {
  18.454      guarantee(_g1->is_in_permanent(start), "Or else where?");
  18.455 -    return;  // Not in the G1 heap (might be in perm, for example.)
  18.456 +    // Again no need to return that this card contains refs that
  18.457 +    // point into the collection set.
  18.458 +    return false;  // Not in the G1 heap (might be in perm, for example.)
  18.459    }
  18.460    // Why do we have to check here whether a card is on a young region,
  18.461    // given that we dirty young regions and, as a result, the
  18.462 @@ -743,7 +851,7 @@
  18.463    // and it doesn't happen often, but it can happen. So, the extra
  18.464    // check below filters out those cards.
  18.465    if (r->is_young()) {
  18.466 -    return;
  18.467 +    return false;
  18.468    }
  18.469    // While we are processing RSet buffers during the collection, we
  18.470    // actually don't want to scan any cards on the collection set,
  18.471 @@ -756,7 +864,7 @@
  18.472    // however, that if evacuation fails, we have to scan any objects
  18.473    // that were not moved and create any missing entries.
  18.474    if (r->in_collection_set()) {
  18.475 -    return;
  18.476 +    return false;
  18.477    }
  18.478  
  18.479    // Should we defer processing the card?
  18.480 @@ -797,8 +905,14 @@
  18.481    //                  cache.
  18.482    //                  Immediately process res; no need to process card_ptr.
  18.483  
  18.484 +
  18.485    jbyte* res = card_ptr;
  18.486    bool defer = false;
  18.487 +
  18.488 +  // This gets set to true if the card being refined has references
  18.489 +  // that point into the collection set.
  18.490 +  bool oops_into_cset = false;
  18.491 +
  18.492    if (_cg1r->use_cache()) {
  18.493      jbyte* res = _cg1r->cache_insert(card_ptr, &defer);
  18.494      if (res != NULL && (res != card_ptr || defer)) {
  18.495 @@ -815,14 +929,31 @@
  18.496          // Process card pointer we get back from the hot card cache. This
  18.497          // will check whether the region containing the card is young
  18.498          // _after_ checking that the region has been allocated from.
  18.499 -        concurrentRefineOneCard_impl(res, worker_i);
  18.500 +        oops_into_cset = concurrentRefineOneCard_impl(res, worker_i,
  18.501 +                                                      false /* check_for_refs_into_cset */);
  18.502 +        // The above call to concurrentRefineOneCard_impl is only
  18.503 +        // performed if the hot card cache is enabled. This cache is
  18.504 +        // disabled during an evacuation pause - which is the only
  18.505 +        // time when we need know if the card contains references
  18.506 +        // that point into the collection set. Also when the hot card
  18.507 +        // cache is enabled, this code is executed by the concurrent
  18.508 +        // refine threads - rather than the GC worker threads - and
  18.509 +        // concurrentRefineOneCard_impl will return false.
  18.510 +        assert(!oops_into_cset, "should not see true here");
  18.511        }
  18.512      }
  18.513    }
  18.514  
  18.515    if (!defer) {
  18.516 -    concurrentRefineOneCard_impl(card_ptr, worker_i);
  18.517 +    oops_into_cset =
  18.518 +      concurrentRefineOneCard_impl(card_ptr, worker_i, check_for_refs_into_cset);
  18.519 +    // We should only be detecting that the card contains references
  18.520 +    // that point into the collection set if the current thread is
  18.521 +    // a GC worker thread.
  18.522 +    assert(!oops_into_cset || SafepointSynchronize::is_at_safepoint(),
  18.523 +           "invalid result at non safepoint");
  18.524    }
  18.525 +  return oops_into_cset;
  18.526  }
  18.527  
  18.528  class HRRSStatsIter: public HeapRegionClosure {
  18.529 @@ -920,6 +1051,7 @@
  18.530  
  18.531    }
  18.532  }
  18.533 +
  18.534  void HRInto_G1RemSet::prepare_for_verify() {
  18.535    if (G1HRRSFlushLogBuffersOnVerify &&
  18.536        (VerifyBeforeGC || VerifyAfterGC)
  18.537 @@ -932,7 +1064,9 @@
  18.538      }
  18.539      bool cg1r_use_cache = _cg1r->use_cache();
  18.540      _cg1r->set_use_cache(false);
  18.541 -    updateRS(0);
  18.542 +    DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
  18.543 +    updateRS(&into_cset_dcq, 0);
  18.544 +    _g1->into_cset_dirty_card_queue_set().clear();
  18.545      _cg1r->set_use_cache(cg1r_use_cache);
  18.546  
  18.547      assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
    19.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Fri Aug 13 07:33:20 2010 -0700
    19.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Sat Aug 14 00:47:52 2010 -0700
    19.3 @@ -1,5 +1,5 @@
    19.4  /*
    19.5 - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
    19.6 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
    19.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.8   *
    19.9   * This code is free software; you can redistribute it and/or modify it
   19.10 @@ -83,7 +83,13 @@
   19.11    // Refine the card corresponding to "card_ptr".  If "sts" is non-NULL,
   19.12    // join and leave around parts that must be atomic wrt GC.  (NULL means
   19.13    // being done at a safepoint.)
   19.14 -  virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i) {}
   19.15 +  // With some implementations of this routine, when check_for_refs_into_cset
   19.16 +  // is true, a true result may be returned if the given card contains oops
   19.17 +  // that have references into the current collection set.
   19.18 +  virtual bool concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
   19.19 +                                       bool check_for_refs_into_cset) {
   19.20 +    return false;
   19.21 +  }
   19.22  
   19.23    // Print any relevant summary info.
   19.24    virtual void print_summary_info() {}
   19.25 @@ -142,24 +148,22 @@
   19.26    size_t*             _cards_scanned;
   19.27    size_t              _total_cards_scanned;
   19.28  
   19.29 -  // _par_traversal_in_progress is "true" iff a parallel traversal is in
   19.30 -  // progress.  If so, then cards added to remembered sets should also have
   19.31 -  // their references into the collection summarized in "_new_refs".
   19.32 -  bool _par_traversal_in_progress;
   19.33 -  void set_par_traversal(bool b) { _par_traversal_in_progress = b; }
   19.34 -  GrowableArray<OopOrNarrowOopStar>** _new_refs;
   19.35 -  template <class T> void new_refs_iterate_work(OopClosure* cl);
   19.36 -  void new_refs_iterate(OopClosure* cl) {
   19.37 -    if (UseCompressedOops) {
   19.38 -      new_refs_iterate_work<narrowOop>(cl);
   19.39 -    } else {
   19.40 -      new_refs_iterate_work<oop>(cl);
   19.41 -    }
   19.42 -  }
   19.43 +  // _traversal_in_progress is "true" iff a traversal is in progress.
   19.44 +
   19.45 +  bool _traversal_in_progress;
   19.46 +  void set_traversal(bool b) { _traversal_in_progress = b; }
   19.47 +
   19.48 +  // Used for caching the closure that is responsible for scanning
   19.49 +  // references into the collection set.
   19.50 +  OopsInHeapRegionClosure** _cset_rs_update_cl;
   19.51  
   19.52    // The routine that performs the actual work of refining a dirty
   19.53    // card.
   19.54 -  void concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i);
   19.55 +  // If check_for_refs_into_refs is true then a true result is returned
   19.56 +  // if the card contains oops that have references into the current
   19.57 +  // collection set.
   19.58 +  bool concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
   19.59 +                                    bool check_for_refs_into_cset);
   19.60  
   19.61  protected:
   19.62    template <class T> void write_ref_nv(HeapRegion* from, T* p);
   19.63 @@ -188,7 +192,7 @@
   19.64        scanNewRefsRS_work<oop>(oc, worker_i);
   19.65      }
   19.66    }
   19.67 -  void updateRS(int worker_i);
   19.68 +  void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i);
   19.69    HeapRegion* calculateStartRegion(int i);
   19.70  
   19.71    HRInto_G1RemSet* as_HRInto_G1RemSet() { return this; }
   19.72 @@ -219,7 +223,11 @@
   19.73    void scrub_par(BitMap* region_bm, BitMap* card_bm,
   19.74                   int worker_num, int claim_val);
   19.75  
   19.76 -  virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i);
   19.77 +  // If check_for_refs_into_cset is true then a true result is returned
   19.78 +  // if the card contains oops that have references into the current
   19.79 +  // collection set.
   19.80 +  virtual bool concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
   19.81 +                                       bool check_for_refs_into_cset);
   19.82  
   19.83    virtual void print_summary_info();
   19.84    virtual void prepare_for_verify();
   19.85 @@ -265,3 +273,16 @@
   19.86    //  bool idempotent() { return true; }
   19.87    bool apply_to_weak_ref_discovered_field() { return true; }
   19.88  };
   19.89 +
   19.90 +class UpdateRSetImmediate: public OopsInHeapRegionClosure {
   19.91 +private:
   19.92 +  G1RemSet* _g1_rem_set;
   19.93 +
   19.94 +  template <class T> void do_oop_work(T* p);
   19.95 +public:
   19.96 +  UpdateRSetImmediate(G1RemSet* rs) :
   19.97 +    _g1_rem_set(rs) {}
   19.98 +
   19.99 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  19.100 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  19.101 +};
    20.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
    20.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
    20.3 @@ -1,5 +1,5 @@
    20.4  /*
    20.5 - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
    20.6 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
    20.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.8   *
    20.9   * This code is free software; you can redistribute it and/or modify it
   20.10 @@ -56,19 +56,25 @@
   20.11      assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
   20.12    }
   20.13  #endif // ASSERT
   20.14 -  assert(from == NULL || from->is_in_reserved(p),
   20.15 -         "p is not in from");
   20.16 +
   20.17 +  assert(from == NULL || from->is_in_reserved(p), "p is not in from");
   20.18 +
   20.19    HeapRegion* to = _g1->heap_region_containing(obj);
   20.20    // The test below could be optimized by applying a bit op to to and from.
   20.21    if (to != NULL && from != NULL && from != to) {
   20.22 -    // There is a tricky infinite loop if we keep pushing
   20.23 -    // self forwarding pointers onto our _new_refs list.
   20.24 -    // The _par_traversal_in_progress flag is true during the collection pause,
   20.25 -    // false during the evacuation failure handing.
   20.26 -    if (_par_traversal_in_progress &&
   20.27 +    // The _traversal_in_progress flag is true during the collection pause,
   20.28 +    // false during the evacuation failure handling. This should avoid a
   20.29 +    // potential loop if we were to add the card containing 'p' to the DCQS
   20.30 +    // that's used to regenerate the remembered sets for the collection set,
   20.31 +    // in the event of an evacuation failure, here. The UpdateRSImmediate
   20.32 +    // closure will eventally call this routine.
   20.33 +    if (_traversal_in_progress &&
   20.34          to->in_collection_set() && !self_forwarded(obj)) {
   20.35 -      _new_refs[tid]->push((void*)p);
   20.36 -      // Deferred updates to the Cset are either discarded (in the normal case),
   20.37 +
   20.38 +      assert(_cset_rs_update_cl[tid] != NULL, "should have been set already");
   20.39 +      _cset_rs_update_cl[tid]->do_oop(p);
   20.40 +
   20.41 +      // Deferred updates to the CSet are either discarded (in the normal case),
   20.42        // or processed (if an evacuation failure occurs) at the end
   20.43        // of the collection.
   20.44        // See HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do().
   20.45 @@ -89,3 +95,12 @@
   20.46    assert(_from != NULL, "from region must be non-NULL");
   20.47    _rs->par_write_ref(_from, p, _worker_i);
   20.48  }
   20.49 +
   20.50 +template <class T> inline void UpdateRSetImmediate::do_oop_work(T* p) {
   20.51 +  assert(_from->is_in_reserved(p), "paranoia");
   20.52 +  T heap_oop = oopDesc::load_heap_oop(p);
   20.53 +  if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) {
   20.54 +    _g1_rem_set->par_write_ref(_from, p, 0);
   20.55 +  }
   20.56 +}
   20.57 +
    21.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp	Fri Aug 13 07:33:20 2010 -0700
    21.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp	Sat Aug 14 00:47:52 2010 -0700
    21.3 @@ -683,6 +683,8 @@
    21.4      return NULL;
    21.5    }
    21.6  
    21.7 +  assert(!is_young(), "check value of filter_young");
    21.8 +
    21.9    // We used to use "block_start_careful" here.  But we're actually happy
   21.10    // to update the BOT while we do this...
   21.11    HeapWord* cur = block_start(mr.start());
    22.1 --- a/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Fri Aug 13 07:33:20 2010 -0700
    22.2 +++ b/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Sat Aug 14 00:47:52 2010 -0700
    22.3 @@ -424,7 +424,7 @@
    22.4  
    22.5  
    22.6  SparsePRT::SparsePRT(HeapRegion* hr) :
    22.7 -  _expanded(false), _next_expanded(NULL)
    22.8 +  _hr(hr), _expanded(false), _next_expanded(NULL)
    22.9  {
   22.10    _cur = new RSHashTable(InitialCapacity);
   22.11    _next = _cur;
    23.1 --- a/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep	Fri Aug 13 07:33:20 2010 -0700
    23.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep	Sat Aug 14 00:47:52 2010 -0700
    23.3 @@ -149,6 +149,7 @@
    23.4  concurrentMarkSweepGeneration.cpp       iterator.hpp
    23.5  concurrentMarkSweepGeneration.cpp       java.hpp
    23.6  concurrentMarkSweepGeneration.cpp       jvmtiExport.hpp
    23.7 +concurrentMarkSweepGeneration.cpp       memoryService.hpp
    23.8  concurrentMarkSweepGeneration.cpp       oop.inline.hpp
    23.9  concurrentMarkSweepGeneration.cpp       parNewGeneration.hpp
   23.10  concurrentMarkSweepGeneration.cpp       referencePolicy.hpp
   23.11 @@ -165,6 +166,7 @@
   23.12  concurrentMarkSweepGeneration.hpp       gcStats.hpp
   23.13  concurrentMarkSweepGeneration.hpp       generation.hpp
   23.14  concurrentMarkSweepGeneration.hpp       generationCounters.hpp
   23.15 +concurrentMarkSweepGeneration.hpp       memoryService.hpp
   23.16  concurrentMarkSweepGeneration.hpp       mutexLocker.hpp
   23.17  concurrentMarkSweepGeneration.hpp       taskqueue.hpp
   23.18  concurrentMarkSweepGeneration.hpp       virtualspace.hpp
    24.1 --- a/src/share/vm/gc_implementation/includeDB_gc_g1	Fri Aug 13 07:33:20 2010 -0700
    24.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_g1	Sat Aug 14 00:47:52 2010 -0700
    24.3 @@ -1,5 +1,5 @@
    24.4  //
    24.5 -// Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.
    24.6 +// Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
    24.7  // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.8  //
    24.9  // This code is free software; you can redistribute it and/or modify it
   24.10 @@ -241,6 +241,7 @@
   24.11  
   24.12  g1MMUTracker.hpp			debug.hpp
   24.13  g1MMUTracker.hpp			allocation.hpp
   24.14 +
   24.15  g1RemSet.cpp				bufferingOopClosure.hpp
   24.16  g1RemSet.cpp				concurrentG1Refine.hpp
   24.17  g1RemSet.cpp				concurrentG1RefineThread.hpp
    25.1 --- a/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge	Fri Aug 13 07:33:20 2010 -0700
    25.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge	Sat Aug 14 00:47:52 2010 -0700
    25.3 @@ -330,7 +330,6 @@
    25.4  psPromotionManager.cpp                  psScavenge.inline.hpp
    25.5  
    25.6  psPromotionManager.hpp                  allocation.hpp
    25.7 -psPromotionManager.hpp                  prefetchQueue.hpp
    25.8  psPromotionManager.hpp                  psPromotionLAB.hpp
    25.9  psPromotionManager.hpp                  taskqueue.hpp
   25.10  
    26.1 --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Fri Aug 13 07:33:20 2010 -0700
    26.2 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Sat Aug 14 00:47:52 2010 -0700
    26.3 @@ -51,9 +51,14 @@
    26.4    _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
    26.5    _keep_alive_closure(&_scan_weak_ref_closure),
    26.6    _promotion_failure_size(0),
    26.7 -  _pushes(0), _pops(0), _steals(0), _steal_attempts(0), _term_attempts(0),
    26.8    _strong_roots_time(0.0), _term_time(0.0)
    26.9  {
   26.10 +  #if TASKQUEUE_STATS
   26.11 +  _term_attempts = 0;
   26.12 +  _overflow_refills = 0;
   26.13 +  _overflow_refill_objs = 0;
   26.14 +  #endif // TASKQUEUE_STATS
   26.15 +
   26.16    _survivor_chunk_array =
   26.17      (ChunkArray*) old_gen()->get_data_recorder(thread_num());
   26.18    _hash_seed = 17;  // Might want to take time-based random value.
   26.19 @@ -100,7 +105,6 @@
   26.20      // Push remainder.
   26.21      bool ok = work_queue()->push(old);
   26.22      assert(ok, "just popped, push must be okay");
   26.23 -    note_push();
   26.24    } else {
   26.25      // Restore length so that it can be used if there
   26.26      // is a promotion failure and forwarding pointers
   26.27 @@ -126,7 +130,6 @@
   26.28      while (queue->size() > (juint)max_size) {
   26.29        oop obj_to_scan;
   26.30        if (queue->pop_local(obj_to_scan)) {
   26.31 -        note_pop();
   26.32          if ((HeapWord *)obj_to_scan < young_old_boundary()) {
   26.33            if (obj_to_scan->is_objArray() &&
   26.34                obj_to_scan->is_forwarded() &&
   26.35 @@ -271,20 +274,28 @@
   26.36                          GrowableArray<oop>**    overflow_stacks_,
   26.37                          size_t                  desired_plab_sz,
   26.38                          ParallelTaskTerminator& term);
   26.39 +
   26.40 +  ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); }
   26.41 +
   26.42    inline ParScanThreadState& thread_state(int i);
   26.43 -  int pushes() { return _pushes; }
   26.44 -  int pops()   { return _pops; }
   26.45 -  int steals() { return _steals; }
   26.46 +
   26.47    void reset(bool promotion_failed);
   26.48    void flush();
   26.49 +
   26.50 +  #if TASKQUEUE_STATS
   26.51 +  static void
   26.52 +    print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
   26.53 +  void print_termination_stats(outputStream* const st = gclog_or_tty);
   26.54 +  static void
   26.55 +    print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty);
   26.56 +  void print_taskqueue_stats(outputStream* const st = gclog_or_tty);
   26.57 +  void reset_stats();
   26.58 +  #endif // TASKQUEUE_STATS
   26.59 +
   26.60  private:
   26.61    ParallelTaskTerminator& _term;
   26.62    ParNewGeneration&       _gen;
   26.63    Generation&             _next_gen;
   26.64 -  // staticstics
   26.65 -  int _pushes;
   26.66 -  int _pops;
   26.67 -  int _steals;
   26.68  };
   26.69  
   26.70  
   26.71 @@ -294,8 +305,7 @@
   26.72    GrowableArray<oop>** overflow_stack_set_,
   26.73    size_t desired_plab_sz, ParallelTaskTerminator& term)
   26.74    : ResourceArray(sizeof(ParScanThreadState), num_threads),
   26.75 -    _gen(gen), _next_gen(old_gen), _term(term),
   26.76 -    _pushes(0), _pops(0), _steals(0)
   26.77 +    _gen(gen), _next_gen(old_gen), _term(term)
   26.78  {
   26.79    assert(num_threads > 0, "sanity check!");
   26.80    // Initialize states.
   26.81 @@ -323,6 +333,82 @@
   26.82    }
   26.83  }
   26.84  
   26.85 +#if TASKQUEUE_STATS
   26.86 +void
   26.87 +ParScanThreadState::reset_stats()
   26.88 +{
   26.89 +  taskqueue_stats().reset();
   26.90 +  _term_attempts = 0;
   26.91 +  _overflow_refills = 0;
   26.92 +  _overflow_refill_objs = 0;
   26.93 +}
   26.94 +
   26.95 +void ParScanThreadStateSet::reset_stats()
   26.96 +{
   26.97 +  for (int i = 0; i < length(); ++i) {
   26.98 +    thread_state(i).reset_stats();
   26.99 +  }
  26.100 +}
  26.101 +
  26.102 +void
  26.103 +ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st)
  26.104 +{
  26.105 +  st->print_raw_cr("GC Termination Stats");
  26.106 +  st->print_raw_cr("     elapsed  --strong roots-- "
  26.107 +                   "-------termination-------");
  26.108 +  st->print_raw_cr("thr     ms        ms       %   "
  26.109 +                   "    ms       %   attempts");
  26.110 +  st->print_raw_cr("--- --------- --------- ------ "
  26.111 +                   "--------- ------ --------");
  26.112 +}
  26.113 +
  26.114 +void ParScanThreadStateSet::print_termination_stats(outputStream* const st)
  26.115 +{
  26.116 +  print_termination_stats_hdr(st);
  26.117 +
  26.118 +  for (int i = 0; i < length(); ++i) {
  26.119 +    const ParScanThreadState & pss = thread_state(i);
  26.120 +    const double elapsed_ms = pss.elapsed_time() * 1000.0;
  26.121 +    const double s_roots_ms = pss.strong_roots_time() * 1000.0;
  26.122 +    const double term_ms = pss.term_time() * 1000.0;
  26.123 +    st->print_cr("%3d %9.2f %9.2f %6.2f "
  26.124 +                 "%9.2f %6.2f " SIZE_FORMAT_W(8),
  26.125 +                 i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
  26.126 +                 term_ms, term_ms * 100 / elapsed_ms, pss.term_attempts());
  26.127 +  }
  26.128 +}
  26.129 +
  26.130 +// Print stats related to work queue activity.
  26.131 +void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st)
  26.132 +{
  26.133 +  st->print_raw_cr("GC Task Stats");
  26.134 +  st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
  26.135 +  st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
  26.136 +}
  26.137 +
  26.138 +void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st)
  26.139 +{
  26.140 +  print_taskqueue_stats_hdr(st);
  26.141 +
  26.142 +  TaskQueueStats totals;
  26.143 +  for (int i = 0; i < length(); ++i) {
  26.144 +    const ParScanThreadState & pss = thread_state(i);
  26.145 +    const TaskQueueStats & stats = pss.taskqueue_stats();
  26.146 +    st->print("%3d ", i); stats.print(st); st->cr();
  26.147 +    totals += stats;
  26.148 +
  26.149 +    if (pss.overflow_refills() > 0) {
  26.150 +      st->print_cr("    " SIZE_FORMAT_W(10) " overflow refills    "
  26.151 +                   SIZE_FORMAT_W(10) " overflow objects",
  26.152 +                   pss.overflow_refills(), pss.overflow_refill_objs());
  26.153 +    }
  26.154 +  }
  26.155 +  st->print("tot "); totals.print(st); st->cr();
  26.156 +
  26.157 +  DEBUG_ONLY(totals.verify());
  26.158 +}
  26.159 +#endif // TASKQUEUE_STATS
  26.160 +
  26.161  void ParScanThreadStateSet::flush()
  26.162  {
  26.163    // Work in this loop should be kept as lightweight as
  26.164 @@ -346,42 +432,8 @@
  26.165      // Inform old gen that we're done.
  26.166      _next_gen.par_promote_alloc_done(i);
  26.167      _next_gen.par_oop_since_save_marks_iterate_done(i);
  26.168 +  }
  26.169  
  26.170 -    // Flush stats related to work queue activity (push/pop/steal)
  26.171 -    // This could conceivably become a bottleneck; if so, we'll put the
  26.172 -    // stat's gathering under the flag.
  26.173 -    if (PAR_STATS_ENABLED) {
  26.174 -      _pushes += par_scan_state.pushes();
  26.175 -      _pops   += par_scan_state.pops();
  26.176 -      _steals += par_scan_state.steals();
  26.177 -      if (ParallelGCVerbose) {
  26.178 -        gclog_or_tty->print("Thread %d complete:\n"
  26.179 -                            "  Pushes: %7d    Pops: %7d    Steals %7d (in %d attempts)\n",
  26.180 -                            i, par_scan_state.pushes(), par_scan_state.pops(),
  26.181 -                            par_scan_state.steals(), par_scan_state.steal_attempts());
  26.182 -        if (par_scan_state.overflow_pushes() > 0 ||
  26.183 -            par_scan_state.overflow_refills() > 0) {
  26.184 -          gclog_or_tty->print("  Overflow pushes: %7d    "
  26.185 -                              "Overflow refills: %7d for %d objs.\n",
  26.186 -                              par_scan_state.overflow_pushes(),
  26.187 -                              par_scan_state.overflow_refills(),
  26.188 -                              par_scan_state.overflow_refill_objs());
  26.189 -        }
  26.190 -
  26.191 -        double elapsed = par_scan_state.elapsed();
  26.192 -        double strong_roots = par_scan_state.strong_roots_time();
  26.193 -        double term = par_scan_state.term_time();
  26.194 -        gclog_or_tty->print(
  26.195 -                            "  Elapsed: %7.2f ms.\n"
  26.196 -                            "    Strong roots: %7.2f ms (%6.2f%%)\n"
  26.197 -                            "    Termination:  %7.2f ms (%6.2f%%) (in %d entries)\n",
  26.198 -                           elapsed * 1000.0,
  26.199 -                           strong_roots * 1000.0, (strong_roots*100.0/elapsed),
  26.200 -                           term * 1000.0, (term*100.0/elapsed),
  26.201 -                           par_scan_state.term_attempts());
  26.202 -      }
  26.203 -    }
  26.204 -  }
  26.205    if (UseConcMarkSweepGC && ParallelGCThreads > 0) {
  26.206      // We need to call this even when ResizeOldPLAB is disabled
  26.207      // so as to avoid breaking some asserts. While we may be able
  26.208 @@ -456,15 +508,12 @@
  26.209      // We have no local work, attempt to steal from other threads.
  26.210  
  26.211      // attempt to steal work from promoted.
  26.212 -    par_scan_state()->note_steal_attempt();
  26.213      if (task_queues()->steal(par_scan_state()->thread_num(),
  26.214                               par_scan_state()->hash_seed(),
  26.215                               obj_to_scan)) {
  26.216 -      par_scan_state()->note_steal();
  26.217        bool res = work_q->push(obj_to_scan);
  26.218        assert(res, "Empty queue should have room for a push.");
  26.219  
  26.220 -      par_scan_state()->note_push();
  26.221        //   if successful, goto Start.
  26.222        continue;
  26.223  
  26.224 @@ -842,17 +891,6 @@
  26.225    }
  26.226    thread_state_set.reset(promotion_failed());
  26.227  
  26.228 -  if (PAR_STATS_ENABLED && ParallelGCVerbose) {
  26.229 -    gclog_or_tty->print("Thread totals:\n"
  26.230 -               "  Pushes: %7d    Pops: %7d    Steals %7d (sum = %7d).\n",
  26.231 -               thread_state_set.pushes(), thread_state_set.pops(),
  26.232 -               thread_state_set.steals(),
  26.233 -               thread_state_set.pops()+thread_state_set.steals());
  26.234 -  }
  26.235 -  assert(thread_state_set.pushes() == thread_state_set.pops()
  26.236 -                                    + thread_state_set.steals(),
  26.237 -         "Or else the queues are leaky.");
  26.238 -
  26.239    // Process (weak) reference objects found during scavenge.
  26.240    ReferenceProcessor* rp = ref_processor();
  26.241    IsAliveClosure is_alive(this);
  26.242 @@ -932,6 +970,11 @@
  26.243      gch->print_heap_change(gch_prev_used);
  26.244    }
  26.245  
  26.246 +  if (PrintGCDetails && ParallelGCVerbose) {
  26.247 +    TASKQUEUE_STATS_ONLY(thread_state_set.print_termination_stats());
  26.248 +    TASKQUEUE_STATS_ONLY(thread_state_set.print_taskqueue_stats());
  26.249 +  }
  26.250 +
  26.251    if (UseAdaptiveSizePolicy) {
  26.252      size_policy->minor_collection_end(gch->gc_cause());
  26.253      size_policy->avg_survived()->sample(from()->used());
  26.254 @@ -1104,9 +1147,8 @@
  26.255          gclog_or_tty->print("queue overflow!\n");
  26.256        }
  26.257        push_on_overflow_list(old, par_scan_state);
  26.258 -      par_scan_state->note_overflow_push();
  26.259 +      TASKQUEUE_STATS_ONLY(par_scan_state->taskqueue_stats().record_overflow(0));
  26.260      }
  26.261 -    par_scan_state->note_push();
  26.262  
  26.263      return new_obj;
  26.264    }
  26.265 @@ -1227,9 +1269,8 @@
  26.266      if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) {
  26.267        // Add stats for overflow pushes.
  26.268        push_on_overflow_list(old, par_scan_state);
  26.269 -      par_scan_state->note_overflow_push();
  26.270 +      TASKQUEUE_STATS_ONLY(par_scan_state->taskqueue_stats().record_overflow(0));
  26.271      }
  26.272 -    par_scan_state->note_push();
  26.273  
  26.274      return new_obj;
  26.275    }
  26.276 @@ -1466,7 +1507,7 @@
  26.277      cur = next;
  26.278      n++;
  26.279    }
  26.280 -  par_scan_state->note_overflow_refill(n);
  26.281 +  TASKQUEUE_STATS_ONLY(par_scan_state->note_overflow_refill(n));
  26.282  #ifndef PRODUCT
  26.283    assert(_num_par_pushes >= n, "Too many pops?");
  26.284    Atomic::add_ptr(-(intptr_t)n, &_num_par_pushes);
    27.1 --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Fri Aug 13 07:33:20 2010 -0700
    27.2 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Sat Aug 14 00:47:52 2010 -0700
    27.3 @@ -36,9 +36,6 @@
    27.4  typedef Padded<OopTaskQueue> ObjToScanQueue;
    27.5  typedef GenericTaskQueueSet<ObjToScanQueue> ObjToScanQueueSet;
    27.6  
    27.7 -// Enable this to get push/pop/steal stats.
    27.8 -const int PAR_STATS_ENABLED = 0;
    27.9 -
   27.10  class ParKeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
   27.11   private:
   27.12    ParScanWeakRefClosure* _par_cl;
   27.13 @@ -94,8 +91,11 @@
   27.14  
   27.15    bool _to_space_full;
   27.16  
   27.17 -  int _pushes, _pops, _steals, _steal_attempts, _term_attempts;
   27.18 -  int _overflow_pushes, _overflow_refills, _overflow_refill_objs;
   27.19 +#if TASKQUEUE_STATS
   27.20 +  size_t _term_attempts;
   27.21 +  size_t _overflow_refills;
   27.22 +  size_t _overflow_refill_objs;
   27.23 +#endif // TASKQUEUE_STATS
   27.24  
   27.25    // Stats for promotion failure
   27.26    size_t _promotion_failure_size;
   27.27 @@ -181,45 +181,38 @@
   27.28    }
   27.29    void print_and_clear_promotion_failure_size();
   27.30  
   27.31 -  int pushes() { return _pushes; }
   27.32 -  int pops()   { return _pops; }
   27.33 -  int steals() { return _steals; }
   27.34 -  int steal_attempts() { return _steal_attempts; }
   27.35 -  int term_attempts()  { return _term_attempts; }
   27.36 -  int overflow_pushes() { return _overflow_pushes; }
   27.37 -  int overflow_refills() { return _overflow_refills; }
   27.38 -  int overflow_refill_objs() { return _overflow_refill_objs; }
   27.39 +#if TASKQUEUE_STATS
   27.40 +  TaskQueueStats & taskqueue_stats() const { return _work_queue->stats; }
   27.41  
   27.42 -  void note_push()  { if (PAR_STATS_ENABLED) _pushes++; }
   27.43 -  void note_pop()   { if (PAR_STATS_ENABLED) _pops++; }
   27.44 -  void note_steal() { if (PAR_STATS_ENABLED) _steals++; }
   27.45 -  void note_steal_attempt() { if (PAR_STATS_ENABLED) _steal_attempts++; }
   27.46 -  void note_term_attempt()  { if (PAR_STATS_ENABLED) _term_attempts++; }
   27.47 -  void note_overflow_push() { if (PAR_STATS_ENABLED) _overflow_pushes++; }
   27.48 -  void note_overflow_refill(int objs) {
   27.49 -    if (PAR_STATS_ENABLED) {
   27.50 -      _overflow_refills++;
   27.51 -      _overflow_refill_objs += objs;
   27.52 -    }
   27.53 +  size_t term_attempts() const             { return _term_attempts; }
   27.54 +  size_t overflow_refills() const          { return _overflow_refills; }
   27.55 +  size_t overflow_refill_objs() const      { return _overflow_refill_objs; }
   27.56 +
   27.57 +  void note_term_attempt()                 { ++_term_attempts; }
   27.58 +  void note_overflow_refill(size_t objs)   {
   27.59 +    ++_overflow_refills; _overflow_refill_objs += objs;
   27.60    }
   27.61  
   27.62 +  void reset_stats();
   27.63 +#endif // TASKQUEUE_STATS
   27.64 +
   27.65    void start_strong_roots() {
   27.66      _start_strong_roots = os::elapsedTime();
   27.67    }
   27.68    void end_strong_roots() {
   27.69      _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
   27.70    }
   27.71 -  double strong_roots_time() { return _strong_roots_time; }
   27.72 +  double strong_roots_time() const { return _strong_roots_time; }
   27.73    void start_term_time() {
   27.74 -    note_term_attempt();
   27.75 +    TASKQUEUE_STATS_ONLY(note_term_attempt());
   27.76      _start_term = os::elapsedTime();
   27.77    }
   27.78    void end_term_time() {
   27.79      _term_time += (os::elapsedTime() - _start_term);
   27.80    }
   27.81 -  double term_time() { return _term_time; }
   27.82 +  double term_time() const { return _term_time; }
   27.83  
   27.84 -  double elapsed() {
   27.85 +  double elapsed_time() const {
   27.86      return os::elapsedTime() - _start;
   27.87    }
   27.88  };
    28.1 --- a/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp	Fri Aug 13 07:33:20 2010 -0700
    28.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp	Sat Aug 14 00:47:52 2010 -0700
    28.3 @@ -123,7 +123,6 @@
    28.4    assert(start_array != NULL && sp != NULL && pm != NULL, "Sanity");
    28.5    assert(start_array->covered_region().contains(sp->used_region()),
    28.6           "ObjectStartArray does not cover space");
    28.7 -  bool depth_first = pm->depth_first();
    28.8  
    28.9    if (sp->not_empty()) {
   28.10      oop* sp_top = (oop*)space_top;
   28.11 @@ -201,21 +200,12 @@
   28.12            *first_nonclean_card++ = clean_card;
   28.13          }
   28.14          // scan oops in objects
   28.15 -        // hoisted the if (depth_first) check out of the loop
   28.16 -        if (depth_first){
   28.17 -          do {
   28.18 -            oop(bottom_obj)->push_contents(pm);
   28.19 -            bottom_obj += oop(bottom_obj)->size();
   28.20 -            assert(bottom_obj <= sp_top, "just checking");
   28.21 -          } while (bottom_obj < top);
   28.22 -          pm->drain_stacks_cond_depth();
   28.23 -        } else {
   28.24 -          do {
   28.25 -            oop(bottom_obj)->copy_contents(pm);
   28.26 -            bottom_obj += oop(bottom_obj)->size();
   28.27 -            assert(bottom_obj <= sp_top, "just checking");
   28.28 -          } while (bottom_obj < top);
   28.29 -        }
   28.30 +        do {
   28.31 +          oop(bottom_obj)->push_contents(pm);
   28.32 +          bottom_obj += oop(bottom_obj)->size();
   28.33 +          assert(bottom_obj <= sp_top, "just checking");
   28.34 +        } while (bottom_obj < top);
   28.35 +        pm->drain_stacks_cond_depth();
   28.36          // remember top oop* scanned
   28.37          prev_top = top;
   28.38        }
   28.39 @@ -230,7 +220,6 @@
   28.40                                                      uint stripe_number) {
   28.41    int ssize = 128; // Naked constant!  Work unit = 64k.
   28.42    int dirty_card_count = 0;
   28.43 -  bool depth_first = pm->depth_first();
   28.44  
   28.45    oop* sp_top = (oop*)space_top;
   28.46    jbyte* start_card = byte_for(sp->bottom());
   28.47 @@ -363,43 +352,22 @@
   28.48          const int interval = PrefetchScanIntervalInBytes;
   28.49          // scan all objects in the range
   28.50          if (interval != 0) {
   28.51 -          // hoisted the if (depth_first) check out of the loop
   28.52 -          if (depth_first) {
   28.53 -            while (p < to) {
   28.54 -              Prefetch::write(p, interval);
   28.55 -              oop m = oop(p);
   28.56 -              assert(m->is_oop_or_null(), "check for header");
   28.57 -              m->push_contents(pm);
   28.58 -              p += m->size();
   28.59 -            }
   28.60 -            pm->drain_stacks_cond_depth();
   28.61 -          } else {
   28.62 -            while (p < to) {
   28.63 -              Prefetch::write(p, interval);
   28.64 -              oop m = oop(p);
   28.65 -              assert(m->is_oop_or_null(), "check for header");
   28.66 -              m->copy_contents(pm);
   28.67 -              p += m->size();
   28.68 -            }
   28.69 +          while (p < to) {
   28.70 +            Prefetch::write(p, interval);
   28.71 +            oop m = oop(p);
   28.72 +            assert(m->is_oop_or_null(), "check for header");
   28.73 +            m->push_contents(pm);
   28.74 +            p += m->size();
   28.75            }
   28.76 +          pm->drain_stacks_cond_depth();
   28.77          } else {
   28.78 -          // hoisted the if (depth_first) check out of the loop
   28.79 -          if (depth_first) {
   28.80 -            while (p < to) {
   28.81 -              oop m = oop(p);
   28.82 -              assert(m->is_oop_or_null(), "check for header");
   28.83 -              m->push_contents(pm);
   28.84 -              p += m->size();
   28.85 -            }
   28.86 -            pm->drain_stacks_cond_depth();
   28.87 -          } else {
   28.88 -            while (p < to) {
   28.89 -              oop m = oop(p);
   28.90 -              assert(m->is_oop_or_null(), "check for header");
   28.91 -              m->copy_contents(pm);
   28.92 -              p += m->size();
   28.93 -            }
   28.94 +          while (p < to) {
   28.95 +            oop m = oop(p);
   28.96 +            assert(m->is_oop_or_null(), "check for header");
   28.97 +            m->push_contents(pm);
   28.98 +            p += m->size();
   28.99            }
  28.100 +          pm->drain_stacks_cond_depth();
  28.101          }
  28.102          last_scanned = p;
  28.103        }
    29.1 --- a/src/share/vm/gc_implementation/parallelScavenge/prefetchQueue.hpp	Fri Aug 13 07:33:20 2010 -0700
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,68 +0,0 @@
    29.4 -/*
    29.5 - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
    29.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 - *
    29.8 - * This code is free software; you can redistribute it and/or modify it
    29.9 - * under the terms of the GNU General Public License version 2 only, as
   29.10 - * published by the Free Software Foundation.
   29.11 - *
   29.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
   29.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.14 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.15 - * version 2 for more details (a copy is included in the LICENSE file that
   29.16 - * accompanied this code).
   29.17 - *
   29.18 - * You should have received a copy of the GNU General Public License version
   29.19 - * 2 along with this work; if not, write to the Free Software Foundation,
   29.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.21 - *
   29.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   29.23 - * or visit www.oracle.com if you need additional information or have any
   29.24 - * questions.
   29.25 - *
   29.26 - */
   29.27 -
   29.28 -//
   29.29 -// PrefetchQueue is a FIFO queue of variable length (currently 8).
   29.30 -//
   29.31 -// We need to examine the performance penalty of variable lengths.
   29.32 -// We may also want to split this into cpu dependent bits.
   29.33 -//
   29.34 -
   29.35 -const int PREFETCH_QUEUE_SIZE  = 8;
   29.36 -
   29.37 -class PrefetchQueue : public CHeapObj {
   29.38 - private:
   29.39 -  void* _prefetch_queue[PREFETCH_QUEUE_SIZE];
   29.40 -  uint  _prefetch_index;
   29.41 -
   29.42 - public:
   29.43 -  int length() { return PREFETCH_QUEUE_SIZE; }
   29.44 -
   29.45 -  inline void clear() {
   29.46 -    for(int i=0; i<PREFETCH_QUEUE_SIZE; i++) {
   29.47 -      _prefetch_queue[i] = NULL;
   29.48 -    }
   29.49 -    _prefetch_index = 0;
   29.50 -  }
   29.51 -
   29.52 -  template <class T> inline void* push_and_pop(T* p) {
   29.53 -    oop o = oopDesc::load_decode_heap_oop_not_null(p);
   29.54 -    Prefetch::write(o->mark_addr(), 0);
   29.55 -    // This prefetch is intended to make sure the size field of array
   29.56 -    // oops is in cache. It assumes the the object layout is
   29.57 -    // mark -> klass -> size, and that mark and klass are heapword
   29.58 -    // sized. If this should change, this prefetch will need updating!
   29.59 -    Prefetch::write(o->mark_addr() + (HeapWordSize*2), 0);
   29.60 -    _prefetch_queue[_prefetch_index++] = p;
   29.61 -    _prefetch_index &= (PREFETCH_QUEUE_SIZE-1);
   29.62 -    return _prefetch_queue[_prefetch_index];
   29.63 -  }
   29.64 -
   29.65 -  // Stores a NULL pointer in the pop'd location.
   29.66 -  inline void* pop() {
   29.67 -    _prefetch_queue[_prefetch_index++] = NULL;
   29.68 -    _prefetch_index &= (PREFETCH_QUEUE_SIZE-1);
   29.69 -    return _prefetch_queue[_prefetch_index];
   29.70 -  }
   29.71 -};
    30.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Fri Aug 13 07:33:20 2010 -0700
    30.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Sat Aug 14 00:47:52 2010 -0700
    30.3 @@ -27,7 +27,6 @@
    30.4  
    30.5  PSPromotionManager**         PSPromotionManager::_manager_array = NULL;
    30.6  OopStarTaskQueueSet*         PSPromotionManager::_stack_array_depth = NULL;
    30.7 -OopTaskQueueSet*             PSPromotionManager::_stack_array_breadth = NULL;
    30.8  PSOldGen*                    PSPromotionManager::_old_gen = NULL;
    30.9  MutableSpace*                PSPromotionManager::_young_space = NULL;
   30.10  
   30.11 @@ -42,23 +41,14 @@
   30.12    _manager_array = NEW_C_HEAP_ARRAY(PSPromotionManager*, ParallelGCThreads+1 );
   30.13    guarantee(_manager_array != NULL, "Could not initialize promotion manager");
   30.14  
   30.15 -  if (UseDepthFirstScavengeOrder) {
   30.16 -    _stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads);
   30.17 -    guarantee(_stack_array_depth != NULL, "Count not initialize promotion manager");
   30.18 -  } else {
   30.19 -    _stack_array_breadth = new OopTaskQueueSet(ParallelGCThreads);
   30.20 -    guarantee(_stack_array_breadth != NULL, "Count not initialize promotion manager");
   30.21 -  }
   30.22 +  _stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads);
   30.23 +  guarantee(_stack_array_depth != NULL, "Cound not initialize promotion manager");
   30.24  
   30.25    // Create and register the PSPromotionManager(s) for the worker threads.
   30.26    for(uint i=0; i<ParallelGCThreads; i++) {
   30.27      _manager_array[i] = new PSPromotionManager();
   30.28      guarantee(_manager_array[i] != NULL, "Could not create PSPromotionManager");
   30.29 -    if (UseDepthFirstScavengeOrder) {
   30.30 -      stack_array_depth()->register_queue(i, _manager_array[i]->claimed_stack_depth());
   30.31 -    } else {
   30.32 -      stack_array_breadth()->register_queue(i, _manager_array[i]->claimed_stack_breadth());
   30.33 -    }
   30.34 +    stack_array_depth()->register_queue(i, _manager_array[i]->claimed_stack_depth());
   30.35    }
   30.36  
   30.37    // The VMThread gets its own PSPromotionManager, which is not available
   30.38 @@ -93,11 +83,7 @@
   30.39    TASKQUEUE_STATS_ONLY(if (PrintGCDetails && ParallelGCVerbose) print_stats());
   30.40    for (uint i = 0; i < ParallelGCThreads + 1; i++) {
   30.41      PSPromotionManager* manager = manager_array(i);
   30.42 -    if (UseDepthFirstScavengeOrder) {
   30.43 -      assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
   30.44 -    } else {
   30.45 -      assert(manager->claimed_stack_breadth()->is_empty(), "should be empty");
   30.46 -    }
   30.47 +    assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
   30.48      manager->flush_labs();
   30.49    }
   30.50  }
   30.51 @@ -105,10 +91,8 @@
   30.52  #if TASKQUEUE_STATS
   30.53  void
   30.54  PSPromotionManager::print_taskqueue_stats(uint i) const {
   30.55 -  const TaskQueueStats& stats = depth_first() ?
   30.56 -    _claimed_stack_depth.stats : _claimed_stack_breadth.stats;
   30.57    tty->print("%3u ", i);
   30.58 -  stats.print();
   30.59 +  _claimed_stack_depth.stats.print();
   30.60    tty->cr();
   30.61  }
   30.62  
   30.63 @@ -128,8 +112,7 @@
   30.64  
   30.65  void
   30.66  PSPromotionManager::print_stats() {
   30.67 -  const bool df = UseDepthFirstScavengeOrder;
   30.68 -  tty->print_cr("== GC Task Stats (%s-First), GC %3d", df ? "Depth" : "Breadth",
   30.69 +  tty->print_cr("== GC Tasks Stats, GC %3d",
   30.70                  Universe::heap()->total_collections());
   30.71  
   30.72    tty->print("thr "); TaskQueueStats::print_header(1); tty->cr();
   30.73 @@ -147,9 +130,7 @@
   30.74  
   30.75  void
   30.76  PSPromotionManager::reset_stats() {
   30.77 -  TaskQueueStats& stats = depth_first() ?
   30.78 -    claimed_stack_depth()->stats : claimed_stack_breadth()->stats;
   30.79 -  stats.reset();
   30.80 +  claimed_stack_depth()->stats.reset();
   30.81    _masked_pushes = _masked_steals = 0;
   30.82    _arrays_chunked = _array_chunks_processed = 0;
   30.83  }
   30.84 @@ -158,19 +139,13 @@
   30.85  PSPromotionManager::PSPromotionManager() {
   30.86    ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   30.87    assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
   30.88 -  _depth_first = UseDepthFirstScavengeOrder;
   30.89  
   30.90    // We set the old lab's start array.
   30.91    _old_lab.set_start_array(old_gen()->start_array());
   30.92  
   30.93    uint queue_size;
   30.94 -  if (depth_first()) {
   30.95 -    claimed_stack_depth()->initialize();
   30.96 -    queue_size = claimed_stack_depth()->max_elems();
   30.97 -  } else {
   30.98 -    claimed_stack_breadth()->initialize();
   30.99 -    queue_size = claimed_stack_breadth()->max_elems();
  30.100 -  }
  30.101 +  claimed_stack_depth()->initialize();
  30.102 +  queue_size = claimed_stack_depth()->max_elems();
  30.103  
  30.104    _totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0);
  30.105    if (_totally_drain) {
  30.106 @@ -205,14 +180,11 @@
  30.107    _old_lab.initialize(MemRegion(lab_base, (size_t)0));
  30.108    _old_gen_is_full = false;
  30.109  
  30.110 -  _prefetch_queue.clear();
  30.111 -
  30.112    TASKQUEUE_STATS_ONLY(reset_stats());
  30.113  }
  30.114  
  30.115  
  30.116  void PSPromotionManager::drain_stacks_depth(bool totally_drain) {
  30.117 -  assert(depth_first(), "invariant");
  30.118    assert(claimed_stack_depth()->overflow_stack() != NULL, "invariant");
  30.119    totally_drain = totally_drain || _totally_drain;
  30.120  
  30.121 @@ -250,50 +222,6 @@
  30.122    assert(tq->overflow_empty(), "Sanity");
  30.123  }
  30.124  
  30.125 -void PSPromotionManager::drain_stacks_breadth(bool totally_drain) {
  30.126 -  assert(!depth_first(), "invariant");
  30.127 -  assert(claimed_stack_breadth()->overflow_stack() != NULL, "invariant");
  30.128 -  totally_drain = totally_drain || _totally_drain;
  30.129 -
  30.130 -#ifdef ASSERT
  30.131 -  ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
  30.132 -  assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
  30.133 -  MutableSpace* to_space = heap->young_gen()->to_space();
  30.134 -  MutableSpace* old_space = heap->old_gen()->object_space();
  30.135 -  MutableSpace* perm_space = heap->perm_gen()->object_space();
  30.136 -#endif /* ASSERT */
  30.137 -
  30.138 -  OverflowTaskQueue<oop>* const tq = claimed_stack_breadth();
  30.139 -  do {
  30.140 -    oop obj;
  30.141 -
  30.142 -    // Drain overflow stack first, so other threads can steal from
  30.143 -    // claimed stack while we work.
  30.144 -    while (tq->pop_overflow(obj)) {
  30.145 -      obj->copy_contents(this);
  30.146 -    }
  30.147 -
  30.148 -    if (totally_drain) {
  30.149 -      while (tq->pop_local(obj)) {
  30.150 -        obj->copy_contents(this);
  30.151 -      }
  30.152 -    } else {
  30.153 -      while (tq->size() > _target_stack_size && tq->pop_local(obj)) {
  30.154 -        obj->copy_contents(this);
  30.155 -      }
  30.156 -    }
  30.157 -
  30.158 -    // If we could not find any other work, flush the prefetch queue
  30.159 -    if (tq->is_empty()) {
  30.160 -      flush_prefetch_queue();
  30.161 -    }
  30.162 -  } while (totally_drain && !tq->taskqueue_empty() || !tq->overflow_empty());
  30.163 -
  30.164 -  assert(!totally_drain || tq->taskqueue_empty(), "Sanity");
  30.165 -  assert(totally_drain || tq->size() <= _target_stack_size, "Sanity");
  30.166 -  assert(tq->overflow_empty(), "Sanity");
  30.167 -}
  30.168 -
  30.169  void PSPromotionManager::flush_labs() {
  30.170    assert(stacks_empty(), "Attempt to flush lab with live stack");
  30.171  
  30.172 @@ -319,7 +247,7 @@
  30.173  // performance.
  30.174  //
  30.175  
  30.176 -oop PSPromotionManager::copy_to_survivor_space(oop o, bool depth_first) {
  30.177 +oop PSPromotionManager::copy_to_survivor_space(oop o) {
  30.178    assert(PSScavenge::should_scavenge(&o), "Sanity");
  30.179  
  30.180    oop new_obj = NULL;
  30.181 @@ -423,24 +351,20 @@
  30.182          assert(young_space()->contains(new_obj), "Attempt to push non-promoted obj");
  30.183        }
  30.184  
  30.185 -      if (depth_first) {
  30.186 -        // Do the size comparison first with new_obj_size, which we
  30.187 -        // already have. Hopefully, only a few objects are larger than
  30.188 -        // _min_array_size_for_chunking, and most of them will be arrays.
  30.189 -        // So, the is->objArray() test would be very infrequent.
  30.190 -        if (new_obj_size > _min_array_size_for_chunking &&
  30.191 -            new_obj->is_objArray() &&
  30.192 -            PSChunkLargeArrays) {
  30.193 -          // we'll chunk it
  30.194 -          oop* const masked_o = mask_chunked_array_oop(o);
  30.195 -          push_depth(masked_o);
  30.196 -          TASKQUEUE_STATS_ONLY(++_arrays_chunked; ++_masked_pushes);
  30.197 -        } else {
  30.198 -          // we'll just push its contents
  30.199 -          new_obj->push_contents(this);
  30.200 -        }
  30.201 +      // Do the size comparison first with new_obj_size, which we
  30.202 +      // already have. Hopefully, only a few objects are larger than
  30.203 +      // _min_array_size_for_chunking, and most of them will be arrays.
  30.204 +      // So, the is->objArray() test would be very infrequent.
  30.205 +      if (new_obj_size > _min_array_size_for_chunking &&
  30.206 +          new_obj->is_objArray() &&
  30.207 +          PSChunkLargeArrays) {
  30.208 +        // we'll chunk it
  30.209 +        oop* const masked_o = mask_chunked_array_oop(o);
  30.210 +        push_depth(masked_o);
  30.211 +        TASKQUEUE_STATS_ONLY(++_arrays_chunked; ++_masked_pushes);
  30.212        } else {
  30.213 -        push_breadth(new_obj);
  30.214 +        // we'll just push its contents
  30.215 +        new_obj->push_contents(this);
  30.216        }
  30.217      }  else {
  30.218        // We lost, someone else "owns" this object
  30.219 @@ -537,13 +461,7 @@
  30.220      // We won any races, we "own" this object.
  30.221      assert(obj == obj->forwardee(), "Sanity");
  30.222  
  30.223 -    if (depth_first()) {
  30.224 -      obj->push_contents(this);
  30.225 -    } else {
  30.226 -      // Don't bother incrementing the age, just push
  30.227 -      // onto the claimed_stack..
  30.228 -      push_breadth(obj);
  30.229 -    }
  30.230 +    obj->push_contents(this);
  30.231  
  30.232      // Save the mark if needed
  30.233      PSScavenge::oop_promotion_failed(obj, obj_mark);
    31.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Fri Aug 13 07:33:20 2010 -0700
    31.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Sat Aug 14 00:47:52 2010 -0700
    31.3 @@ -48,7 +48,6 @@
    31.4   private:
    31.5    static PSPromotionManager**         _manager_array;
    31.6    static OopStarTaskQueueSet*         _stack_array_depth;
    31.7 -  static OopTaskQueueSet*             _stack_array_breadth;
    31.8    static PSOldGen*                    _old_gen;
    31.9    static MutableSpace*                _young_space;
   31.10  
   31.11 @@ -69,12 +68,10 @@
   31.12    PSOldPromotionLAB                   _old_lab;
   31.13    bool                                _young_gen_is_full;
   31.14    bool                                _old_gen_is_full;
   31.15 -  PrefetchQueue                       _prefetch_queue;
   31.16  
   31.17    OopStarTaskQueue                    _claimed_stack_depth;
   31.18    OverflowTaskQueue<oop>              _claimed_stack_breadth;
   31.19  
   31.20 -  bool                                _depth_first;
   31.21    bool                                _totally_drain;
   31.22    uint                                _target_stack_size;
   31.23  
   31.24 @@ -87,7 +84,6 @@
   31.25  
   31.26    inline static PSPromotionManager* manager_array(int index);
   31.27    template <class T> inline void claim_or_forward_internal_depth(T* p);
   31.28 -  template <class T> inline void claim_or_forward_internal_breadth(T* p);
   31.29  
   31.30    // On the task queues we push reference locations as well as
   31.31    // partially-scanned arrays (in the latter case, we push an oop to
   31.32 @@ -136,19 +132,11 @@
   31.33    void process_array_chunk(oop old);
   31.34  
   31.35    template <class T> void push_depth(T* p) {
   31.36 -    assert(depth_first(), "pre-condition");
   31.37      claimed_stack_depth()->push(p);
   31.38    }
   31.39  
   31.40 -  void push_breadth(oop o) {
   31.41 -    assert(!depth_first(), "pre-condition");
   31.42 -    claimed_stack_breadth()->push(o);
   31.43 -  }
   31.44 -
   31.45   protected:
   31.46    static OopStarTaskQueueSet* stack_array_depth()   { return _stack_array_depth; }
   31.47 -  static OopTaskQueueSet*     stack_array_breadth() { return _stack_array_breadth; }
   31.48 -
   31.49   public:
   31.50    // Static
   31.51    static void initialize();
   31.52 @@ -163,19 +151,12 @@
   31.53      return stack_array_depth()->steal(queue_num, seed, t);
   31.54    }
   31.55  
   31.56 -  static bool steal_breadth(int queue_num, int* seed, oop& t) {
   31.57 -    return stack_array_breadth()->steal(queue_num, seed, t);
   31.58 -  }
   31.59 -
   31.60    PSPromotionManager();
   31.61  
   31.62    // Accessors
   31.63    OopStarTaskQueue* claimed_stack_depth() {
   31.64      return &_claimed_stack_depth;
   31.65    }
   31.66 -  OverflowTaskQueue<oop>* claimed_stack_breadth() {
   31.67 -    return &_claimed_stack_breadth;
   31.68 -  }
   31.69  
   31.70    bool young_gen_is_full()             { return _young_gen_is_full; }
   31.71  
   31.72 @@ -183,18 +164,14 @@
   31.73    void set_old_gen_is_full(bool state) { _old_gen_is_full = state; }
   31.74  
   31.75    // Promotion methods
   31.76 -  oop copy_to_survivor_space(oop o, bool depth_first);
   31.77 +  oop copy_to_survivor_space(oop o);
   31.78    oop oop_promotion_failed(oop obj, markOop obj_mark);
   31.79  
   31.80    void reset();
   31.81  
   31.82    void flush_labs();
   31.83    void drain_stacks(bool totally_drain) {
   31.84 -    if (depth_first()) {
   31.85 -      drain_stacks_depth(totally_drain);
   31.86 -    } else {
   31.87 -      drain_stacks_breadth(totally_drain);
   31.88 -    }
   31.89 +    drain_stacks_depth(totally_drain);
   31.90    }
   31.91   public:
   31.92    void drain_stacks_cond_depth() {
   31.93 @@ -203,22 +180,14 @@
   31.94      }
   31.95    }
   31.96    void drain_stacks_depth(bool totally_drain);
   31.97 -  void drain_stacks_breadth(bool totally_drain);
   31.98  
   31.99 -  bool depth_first() const {
  31.100 -    return _depth_first;
  31.101 -  }
  31.102    bool stacks_empty() {
  31.103 -    return depth_first() ?
  31.104 -      claimed_stack_depth()->is_empty() :
  31.105 -      claimed_stack_breadth()->is_empty();
  31.106 +    return claimed_stack_depth()->is_empty();
  31.107    }
  31.108  
  31.109    inline void process_popped_location_depth(StarTask p);
  31.110  
  31.111 -  inline void flush_prefetch_queue();
  31.112    template <class T> inline void claim_or_forward_depth(T* p);
  31.113 -  template <class T> inline void claim_or_forward_breadth(T* p);
  31.114  
  31.115    TASKQUEUE_STATS_ONLY(inline void record_steal(StarTask& p);)
  31.116  };
    32.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
    32.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
    32.3 @@ -46,32 +46,7 @@
    32.4  }
    32.5  
    32.6  template <class T>
    32.7 -inline void PSPromotionManager::claim_or_forward_internal_breadth(T* p) {
    32.8 -  if (p != NULL) { // XXX: error if p != NULL here
    32.9 -    oop o = oopDesc::load_decode_heap_oop_not_null(p);
   32.10 -    if (o->is_forwarded()) {
   32.11 -      o = o->forwardee();
   32.12 -    } else {
   32.13 -      o = copy_to_survivor_space(o, false);
   32.14 -    }
   32.15 -    // Card mark
   32.16 -    if (PSScavenge::is_obj_in_young((HeapWord*) o)) {
   32.17 -      PSScavenge::card_table()->inline_write_ref_field_gc(p, o);
   32.18 -    }
   32.19 -    oopDesc::encode_store_heap_oop_not_null(p, o);
   32.20 -  }
   32.21 -}
   32.22 -
   32.23 -inline void PSPromotionManager::flush_prefetch_queue() {
   32.24 -  assert(!depth_first(), "invariant");
   32.25 -  for (int i = 0; i < _prefetch_queue.length(); i++) {
   32.26 -    claim_or_forward_internal_breadth((oop*)_prefetch_queue.pop());
   32.27 -  }
   32.28 -}
   32.29 -
   32.30 -template <class T>
   32.31  inline void PSPromotionManager::claim_or_forward_depth(T* p) {
   32.32 -  assert(depth_first(), "invariant");
   32.33    assert(PSScavenge::should_scavenge(p, true), "revisiting object?");
   32.34    assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap,
   32.35           "Sanity");
   32.36 @@ -80,36 +55,6 @@
   32.37    claim_or_forward_internal_depth(p);
   32.38  }
   32.39  
   32.40 -template <class T>
   32.41 -inline void PSPromotionManager::claim_or_forward_breadth(T* p) {
   32.42 -  assert(!depth_first(), "invariant");
   32.43 -  assert(PSScavenge::should_scavenge(p, true), "revisiting object?");
   32.44 -  assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap,
   32.45 -         "Sanity");
   32.46 -  assert(Universe::heap()->is_in(p), "pointer outside heap");
   32.47 -
   32.48 -  if (UsePrefetchQueue) {
   32.49 -    claim_or_forward_internal_breadth((T*)_prefetch_queue.push_and_pop(p));
   32.50 -  } else {
   32.51 -    // This option is used for testing.  The use of the prefetch
   32.52 -    // queue can delay the processing of the objects and thus
   32.53 -    // change the order of object scans.  For example, remembered
   32.54 -    // set updates are typically the clearing of the remembered
   32.55 -    // set (the cards) followed by updates of the remembered set
   32.56 -    // for young-to-old pointers.  In a situation where there
   32.57 -    // is an error in the sequence of clearing and updating
   32.58 -    // (e.g. clear card A, update card A, erroneously clear
   32.59 -    // card A again) the error can be obscured by a delay
   32.60 -    // in the update due to the use of the prefetch queue
   32.61 -    // (e.g., clear card A, erroneously clear card A again,
   32.62 -    // update card A that was pushed into the prefetch queue
   32.63 -    // and thus delayed until after the erronous clear).  The
   32.64 -    // length of the delay is random depending on the objects
   32.65 -    // in the queue and the delay can be zero.
   32.66 -    claim_or_forward_internal_breadth(p);
   32.67 -  }
   32.68 -}
   32.69 -
   32.70  inline void PSPromotionManager::process_popped_location_depth(StarTask p) {
   32.71    if (is_oop_masked(p)) {
   32.72      assert(PSChunkLargeArrays, "invariant");
    33.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Fri Aug 13 07:33:20 2010 -0700
    33.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Sat Aug 14 00:47:52 2010 -0700
    33.3 @@ -157,10 +157,8 @@
    33.4      q->enqueue(new PSRefProcTaskProxy(task, i));
    33.5    }
    33.6    ParallelTaskTerminator terminator(
    33.7 -    ParallelScavengeHeap::gc_task_manager()->workers(),
    33.8 -    UseDepthFirstScavengeOrder ?
    33.9 -        (TaskQueueSetSuper*) PSPromotionManager::stack_array_depth()
   33.10 -      : (TaskQueueSetSuper*) PSPromotionManager::stack_array_breadth());
   33.11 +                 ParallelScavengeHeap::gc_task_manager()->workers(),
   33.12 +                 (TaskQueueSetSuper*) PSPromotionManager::stack_array_depth());
   33.13    if (task.marks_oops_alive() && ParallelGCThreads > 1) {
   33.14      for (uint j=0; j<ParallelGCThreads; j++) {
   33.15        q->enqueue(new StealTask(&terminator));
   33.16 @@ -375,10 +373,8 @@
   33.17        q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::code_cache));
   33.18  
   33.19        ParallelTaskTerminator terminator(
   33.20 -        gc_task_manager()->workers(),
   33.21 -        promotion_manager->depth_first() ?
   33.22 -            (TaskQueueSetSuper*) promotion_manager->stack_array_depth()
   33.23 -          : (TaskQueueSetSuper*) promotion_manager->stack_array_breadth());
   33.24 +                  gc_task_manager()->workers(),
   33.25 +                  (TaskQueueSetSuper*) promotion_manager->stack_array_depth());
   33.26        if (ParallelGCThreads>1) {
   33.27          for (uint j=0; j<ParallelGCThreads; j++) {
   33.28            q->enqueue(new StealTask(&terminator));
    34.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
    34.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
    34.3 @@ -65,7 +65,7 @@
    34.4    oop o = oopDesc::load_decode_heap_oop_not_null(p);
    34.5    oop new_obj = o->is_forwarded()
    34.6          ? o->forwardee()
    34.7 -        : pm->copy_to_survivor_space(o, pm->depth_first());
    34.8 +        : pm->copy_to_survivor_space(o);
    34.9    oopDesc::encode_store_heap_oop_not_null(p, new_obj);
   34.10  
   34.11    // We cannot mark without test, as some code passes us pointers
    35.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp	Fri Aug 13 07:33:20 2010 -0700
    35.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp	Sat Aug 14 00:47:52 2010 -0700
    35.3 @@ -144,29 +144,15 @@
    35.4              "stacks should be empty at this point");
    35.5  
    35.6    int random_seed = 17;
    35.7 -  if (pm->depth_first()) {
    35.8 -    while(true) {
    35.9 -      StarTask p;
   35.10 -      if (PSPromotionManager::steal_depth(which, &random_seed, p)) {
   35.11 -        TASKQUEUE_STATS_ONLY(pm->record_steal(p));
   35.12 -        pm->process_popped_location_depth(p);
   35.13 -        pm->drain_stacks_depth(true);
   35.14 -      } else {
   35.15 -        if (terminator()->offer_termination()) {
   35.16 -          break;
   35.17 -        }
   35.18 -      }
   35.19 -    }
   35.20 -  } else {
   35.21 -    while(true) {
   35.22 -      oop obj;
   35.23 -      if (PSPromotionManager::steal_breadth(which, &random_seed, obj)) {
   35.24 -        obj->copy_contents(pm);
   35.25 -        pm->drain_stacks_breadth(true);
   35.26 -      } else {
   35.27 -        if (terminator()->offer_termination()) {
   35.28 -          break;
   35.29 -        }
   35.30 +  while(true) {
   35.31 +    StarTask p;
   35.32 +    if (PSPromotionManager::steal_depth(which, &random_seed, p)) {
   35.33 +      TASKQUEUE_STATS_ONLY(pm->record_steal(p));
   35.34 +      pm->process_popped_location_depth(p);
   35.35 +      pm->drain_stacks_depth(true);
   35.36 +    } else {
   35.37 +      if (terminator()->offer_termination()) {
   35.38 +        break;
   35.39        }
   35.40      }
   35.41    }
    36.1 --- a/src/share/vm/oops/arrayKlassKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    36.2 +++ b/src/share/vm/oops/arrayKlassKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    36.3 @@ -108,10 +108,6 @@
    36.4  }
    36.5  
    36.6  #ifndef SERIALGC
    36.7 -void arrayKlassKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    36.8 -  assert(obj->blueprint()->oop_is_arrayKlass(),"must be an array klass");
    36.9 -}
   36.10 -
   36.11  void arrayKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   36.12    assert(obj->blueprint()->oop_is_arrayKlass(),"must be an array klass");
   36.13  }
    37.1 --- a/src/share/vm/oops/compiledICHolderKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    37.2 +++ b/src/share/vm/oops/compiledICHolderKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    37.3 @@ -120,10 +120,6 @@
    37.4  }
    37.5  
    37.6  #ifndef SERIALGC
    37.7 -void compiledICHolderKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    37.8 -  assert(obj->is_compiledICHolder(), "must be compiledICHolder");
    37.9 -}
   37.10 -
   37.11  void compiledICHolderKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   37.12    assert(obj->is_compiledICHolder(), "must be compiledICHolder");
   37.13  }
    38.1 --- a/src/share/vm/oops/constMethodKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    38.2 +++ b/src/share/vm/oops/constMethodKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    38.3 @@ -157,10 +157,6 @@
    38.4  }
    38.5  
    38.6  #ifndef SERIALGC
    38.7 -void constMethodKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    38.8 -  assert(obj->is_constMethod(), "should be constMethod");
    38.9 -}
   38.10 -
   38.11  void constMethodKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   38.12    assert(obj->is_constMethod(), "should be constMethod");
   38.13  }
    39.1 --- a/src/share/vm/oops/constantPoolKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    39.2 +++ b/src/share/vm/oops/constantPoolKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    39.3 @@ -268,21 +268,6 @@
    39.4    return cp->object_size();
    39.5  }
    39.6  
    39.7 -void constantPoolKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    39.8 -  assert(obj->is_constantPool(), "should be constant pool");
    39.9 -  constantPoolOop cp = (constantPoolOop) obj;
   39.10 -  if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) {
   39.11 -    oop* base = (oop*)cp->base();
   39.12 -    for (int i = 0; i < cp->length(); ++i, ++base) {
   39.13 -      if (cp->tag_at(i).is_string()) {
   39.14 -        if (PSScavenge::should_scavenge(base)) {
   39.15 -          pm->claim_or_forward_breadth(base);
   39.16 -        }
   39.17 -      }
   39.18 -    }
   39.19 -  }
   39.20 -}
   39.21 -
   39.22  void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   39.23    assert(obj->is_constantPool(), "should be constant pool");
   39.24    constantPoolOop cp = (constantPoolOop) obj;
    40.1 --- a/src/share/vm/oops/cpCacheKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    40.2 +++ b/src/share/vm/oops/cpCacheKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    40.3 @@ -166,29 +166,6 @@
    40.4  }
    40.5  
    40.6  #ifndef SERIALGC
    40.7 -void constantPoolCacheKlass::oop_copy_contents(PSPromotionManager* pm,
    40.8 -                                               oop obj) {
    40.9 -  assert(obj->is_constantPoolCache(), "should be constant pool");
   40.10 -  if (EnableInvokeDynamic) {
   40.11 -    constantPoolCacheOop cache = (constantPoolCacheOop)obj;
   40.12 -    // during a scavenge, it is safe to inspect my pool, since it is perm
   40.13 -    constantPoolOop pool = cache->constant_pool();
   40.14 -    assert(pool->is_constantPool(), "should be constant pool");
   40.15 -    if (pool->has_invokedynamic()) {
   40.16 -      for (int i = 0; i < cache->length(); i++) {
   40.17 -        ConstantPoolCacheEntry* e = cache->entry_at(i);
   40.18 -        oop* p = (oop*)&e->_f1;
   40.19 -        if (e->is_secondary_entry()) {
   40.20 -          if (PSScavenge::should_scavenge(p))
   40.21 -            pm->claim_or_forward_breadth(p);
   40.22 -          assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)),
   40.23 -                 "no live oops here");
   40.24 -        }
   40.25 -      }
   40.26 -    }
   40.27 -  }
   40.28 -}
   40.29 -
   40.30  void constantPoolCacheKlass::oop_push_contents(PSPromotionManager* pm,
   40.31                                                 oop obj) {
   40.32    assert(obj->is_constantPoolCache(), "should be constant pool");
    41.1 --- a/src/share/vm/oops/instanceKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    41.2 +++ b/src/share/vm/oops/instanceKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    41.3 @@ -1809,18 +1809,7 @@
    41.4  }
    41.5  
    41.6  #ifndef SERIALGC
    41.7 -void instanceKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    41.8 -  assert(!pm->depth_first(), "invariant");
    41.9 -  InstanceKlass_OOP_MAP_REVERSE_ITERATE( \
   41.10 -    obj, \
   41.11 -    if (PSScavenge::should_scavenge(p)) { \
   41.12 -      pm->claim_or_forward_breadth(p); \
   41.13 -    }, \
   41.14 -    assert_nothing )
   41.15 -}
   41.16 -
   41.17  void instanceKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   41.18 -  assert(pm->depth_first(), "invariant");
   41.19    InstanceKlass_OOP_MAP_REVERSE_ITERATE( \
   41.20      obj, \
   41.21      if (PSScavenge::should_scavenge(p)) { \
   41.22 @@ -1846,18 +1835,7 @@
   41.23    return size_helper();
   41.24  }
   41.25  
   41.26 -void instanceKlass::copy_static_fields(PSPromotionManager* pm) {
   41.27 -  assert(!pm->depth_first(), "invariant");
   41.28 -  InstanceKlass_OOP_ITERATE( \
   41.29 -    start_of_static_fields(), static_oop_field_size(), \
   41.30 -    if (PSScavenge::should_scavenge(p)) { \
   41.31 -      pm->claim_or_forward_breadth(p); \
   41.32 -    }, \
   41.33 -    assert_nothing )
   41.34 -}
   41.35 -
   41.36  void instanceKlass::push_static_fields(PSPromotionManager* pm) {
   41.37 -  assert(pm->depth_first(), "invariant");
   41.38    InstanceKlass_OOP_ITERATE( \
   41.39      start_of_static_fields(), static_oop_field_size(), \
   41.40      if (PSScavenge::should_scavenge(p)) { \
    42.1 --- a/src/share/vm/oops/instanceKlass.hpp	Fri Aug 13 07:33:20 2010 -0700
    42.2 +++ b/src/share/vm/oops/instanceKlass.hpp	Sat Aug 14 00:47:52 2010 -0700
    42.3 @@ -711,7 +711,6 @@
    42.4  
    42.5  #ifndef SERIALGC
    42.6    // Parallel Scavenge
    42.7 -  void copy_static_fields(PSPromotionManager* pm);
    42.8    void push_static_fields(PSPromotionManager* pm);
    42.9  
   42.10    // Parallel Old
    43.1 --- a/src/share/vm/oops/instanceKlassKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    43.2 +++ b/src/share/vm/oops/instanceKlassKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    43.3 @@ -292,41 +292,7 @@
    43.4  }
    43.5  
    43.6  #ifndef SERIALGC
    43.7 -void instanceKlassKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    43.8 -  assert(!pm->depth_first(), "invariant");
    43.9 -  instanceKlass* ik = instanceKlass::cast(klassOop(obj));
   43.10 -  ik->copy_static_fields(pm);
   43.11 -
   43.12 -  oop* loader_addr = ik->adr_class_loader();
   43.13 -  if (PSScavenge::should_scavenge(loader_addr)) {
   43.14 -    pm->claim_or_forward_breadth(loader_addr);
   43.15 -  }
   43.16 -
   43.17 -  oop* pd_addr = ik->adr_protection_domain();
   43.18 -  if (PSScavenge::should_scavenge(pd_addr)) {
   43.19 -    pm->claim_or_forward_breadth(pd_addr);
   43.20 -  }
   43.21 -
   43.22 -  oop* hk_addr = ik->adr_host_klass();
   43.23 -  if (PSScavenge::should_scavenge(hk_addr)) {
   43.24 -    pm->claim_or_forward_breadth(hk_addr);
   43.25 -  }
   43.26 -
   43.27 -  oop* sg_addr = ik->adr_signers();
   43.28 -  if (PSScavenge::should_scavenge(sg_addr)) {
   43.29 -    pm->claim_or_forward_breadth(sg_addr);
   43.30 -  }
   43.31 -
   43.32 -  oop* bsm_addr = ik->adr_bootstrap_method();
   43.33 -  if (PSScavenge::should_scavenge(bsm_addr)) {
   43.34 -    pm->claim_or_forward_breadth(bsm_addr);
   43.35 -  }
   43.36 -
   43.37 -  klassKlass::oop_copy_contents(pm, obj);
   43.38 -}
   43.39 -
   43.40  void instanceKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   43.41 -  assert(pm->depth_first(), "invariant");
   43.42    instanceKlass* ik = instanceKlass::cast(klassOop(obj));
   43.43    ik->push_static_fields(pm);
   43.44  
   43.45 @@ -355,7 +321,7 @@
   43.46      pm->claim_or_forward_depth(bsm_addr);
   43.47    }
   43.48  
   43.49 -  klassKlass::oop_copy_contents(pm, obj);
   43.50 +  klassKlass::oop_push_contents(pm, obj);
   43.51  }
   43.52  
   43.53  int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
    44.1 --- a/src/share/vm/oops/instanceRefKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    44.2 +++ b/src/share/vm/oops/instanceRefKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    44.3 @@ -273,41 +273,8 @@
    44.4  
    44.5  #ifndef SERIALGC
    44.6  template <class T>
    44.7 -void specialized_oop_copy_contents(instanceRefKlass *ref,
    44.8 -                                   PSPromotionManager* pm, oop obj) {
    44.9 -  assert(!pm->depth_first(), "invariant");
   44.10 -  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
   44.11 -  if (PSScavenge::should_scavenge(referent_addr)) {
   44.12 -    ReferenceProcessor* rp = PSScavenge::reference_processor();
   44.13 -    if (rp->discover_reference(obj, ref->reference_type())) {
   44.14 -      // reference already enqueued, referent and next will be traversed later
   44.15 -      ref->instanceKlass::oop_copy_contents(pm, obj);
   44.16 -      return;
   44.17 -    } else {
   44.18 -      // treat referent as normal oop
   44.19 -      pm->claim_or_forward_breadth(referent_addr);
   44.20 -    }
   44.21 -  }
   44.22 -  // treat next as normal oop
   44.23 -  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
   44.24 -  if (PSScavenge::should_scavenge(next_addr)) {
   44.25 -    pm->claim_or_forward_breadth(next_addr);
   44.26 -  }
   44.27 -  ref->instanceKlass::oop_copy_contents(pm, obj);
   44.28 -}
   44.29 -
   44.30 -void instanceRefKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
   44.31 -  if (UseCompressedOops) {
   44.32 -    specialized_oop_copy_contents<narrowOop>(this, pm, obj);
   44.33 -  } else {
   44.34 -    specialized_oop_copy_contents<oop>(this, pm, obj);
   44.35 -  }
   44.36 -}
   44.37 -
   44.38 -template <class T>
   44.39  void specialized_oop_push_contents(instanceRefKlass *ref,
   44.40                                     PSPromotionManager* pm, oop obj) {
   44.41 -  assert(pm->depth_first(), "invariant");
   44.42    T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
   44.43    if (PSScavenge::should_scavenge(referent_addr)) {
   44.44      ReferenceProcessor* rp = PSScavenge::reference_processor();
    45.1 --- a/src/share/vm/oops/klassKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    45.2 +++ b/src/share/vm/oops/klassKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    45.3 @@ -161,9 +161,6 @@
    45.4  }
    45.5  
    45.6  #ifndef SERIALGC
    45.7 -void klassKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    45.8 -}
    45.9 -
   45.10  void klassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   45.11  }
   45.12  
    46.1 --- a/src/share/vm/oops/klassPS.hpp	Fri Aug 13 07:33:20 2010 -0700
    46.2 +++ b/src/share/vm/oops/klassPS.hpp	Sat Aug 14 00:47:52 2010 -0700
    46.3 @@ -28,7 +28,6 @@
    46.4  
    46.5  #ifndef SERIALGC
    46.6  #define PARALLEL_GC_DECLS \
    46.7 -  virtual void oop_copy_contents(PSPromotionManager* pm, oop obj);          \
    46.8    virtual void oop_push_contents(PSPromotionManager* pm, oop obj);          \
    46.9    /* Parallel Old GC support                                                \
   46.10                                                                              \
   46.11 @@ -43,7 +42,6 @@
   46.12  
   46.13  // Pure virtual version for klass.hpp
   46.14  #define PARALLEL_GC_DECLS_PV \
   46.15 -  virtual void oop_copy_contents(PSPromotionManager* pm, oop obj) = 0;      \
   46.16    virtual void oop_push_contents(PSPromotionManager* pm, oop obj) = 0;      \
   46.17    virtual void oop_follow_contents(ParCompactionManager* cm, oop obj) = 0;  \
   46.18    virtual int  oop_update_pointers(ParCompactionManager* cm, oop obj) = 0;  \
    47.1 --- a/src/share/vm/oops/methodDataKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    47.2 +++ b/src/share/vm/oops/methodDataKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    47.3 @@ -154,13 +154,6 @@
    47.4  
    47.5  
    47.6  #ifndef SERIALGC
    47.7 -void methodDataKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    47.8 -  assert (obj->is_methodData(), "object must be method data");
    47.9 -  methodDataOop m = methodDataOop(obj);
   47.10 -  // This should never point into the young gen.
   47.11 -  assert(!PSScavenge::should_scavenge(m->adr_method()), "Sanity");
   47.12 -}
   47.13 -
   47.14  void methodDataKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   47.15    assert (obj->is_methodData(), "object must be method data");
   47.16    methodDataOop m = methodDataOop(obj);
    48.1 --- a/src/share/vm/oops/methodKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    48.2 +++ b/src/share/vm/oops/methodKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    48.3 @@ -184,10 +184,6 @@
    48.4  }
    48.5  
    48.6  #ifndef SERIALGC
    48.7 -void methodKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    48.8 -  assert(obj->is_method(), "should be method");
    48.9 -}
   48.10 -
   48.11  void methodKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   48.12    assert(obj->is_method(), "should be method");
   48.13  }
    49.1 --- a/src/share/vm/oops/objArrayKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    49.2 +++ b/src/share/vm/oops/objArrayKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    49.3 @@ -426,18 +426,7 @@
    49.4  }
    49.5  
    49.6  #ifndef SERIALGC
    49.7 -void objArrayKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    49.8 -  assert(!pm->depth_first(), "invariant");
    49.9 -  assert(obj->is_objArray(), "obj must be obj array");
   49.10 -  ObjArrayKlass_OOP_ITERATE( \
   49.11 -    objArrayOop(obj), p, \
   49.12 -    if (PSScavenge::should_scavenge(p)) { \
   49.13 -      pm->claim_or_forward_breadth(p); \
   49.14 -    })
   49.15 -}
   49.16 -
   49.17  void objArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   49.18 -  assert(pm->depth_first(), "invariant");
   49.19    assert(obj->is_objArray(), "obj must be obj array");
   49.20    ObjArrayKlass_OOP_ITERATE( \
   49.21      objArrayOop(obj), p, \
    50.1 --- a/src/share/vm/oops/objArrayKlassKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    50.2 +++ b/src/share/vm/oops/objArrayKlassKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    50.3 @@ -229,10 +229,6 @@
    50.4  }
    50.5  
    50.6  #ifndef SERIALGC
    50.7 -void objArrayKlassKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    50.8 -  assert(obj->blueprint()->oop_is_objArrayKlass(),"must be an obj array klass");
    50.9 -}
   50.10 -
   50.11  void objArrayKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   50.12    assert(obj->blueprint()->oop_is_objArrayKlass(),"must be an obj array klass");
   50.13  }
    51.1 --- a/src/share/vm/oops/oop.hpp	Fri Aug 13 07:33:20 2010 -0700
    51.2 +++ b/src/share/vm/oops/oop.hpp	Sat Aug 14 00:47:52 2010 -0700
    51.3 @@ -306,7 +306,6 @@
    51.4  
    51.5  #ifndef SERIALGC
    51.6    // Parallel Scavenge
    51.7 -  void copy_contents(PSPromotionManager* pm);
    51.8    void push_contents(PSPromotionManager* pm);
    51.9  
   51.10    // Parallel Old
    52.1 --- a/src/share/vm/oops/oop.psgc.inline.hpp	Fri Aug 13 07:33:20 2010 -0700
    52.2 +++ b/src/share/vm/oops/oop.psgc.inline.hpp	Sat Aug 14 00:47:52 2010 -0700
    52.3 @@ -24,15 +24,6 @@
    52.4  
    52.5  // ParallelScavengeHeap methods
    52.6  
    52.7 -inline void oopDesc::copy_contents(PSPromotionManager* pm) {
    52.8 -  Klass* klass = blueprint();
    52.9 -  if (!klass->oop_is_typeArray()) {
   52.10 -    // It might contain oops beyond the header, so take the virtual call.
   52.11 -    klass->oop_copy_contents(pm, this);
   52.12 -  }
   52.13 -  // Else skip it.  The typeArrayKlass in the header never needs scavenging.
   52.14 -}
   52.15 -
   52.16  inline void oopDesc::push_contents(PSPromotionManager* pm) {
   52.17    Klass* klass = blueprint();
   52.18    if (!klass->oop_is_typeArray()) {
    53.1 --- a/src/share/vm/oops/symbolKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    53.2 +++ b/src/share/vm/oops/symbolKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    53.3 @@ -184,10 +184,6 @@
    53.4  
    53.5  
    53.6  #ifndef SERIALGC
    53.7 -void symbolKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    53.8 -  assert(obj->is_symbol(), "should be symbol");
    53.9 -}
   53.10 -
   53.11  void symbolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   53.12    assert(obj->is_symbol(), "should be symbol");
   53.13  }
    54.1 --- a/src/share/vm/oops/typeArrayKlass.cpp	Fri Aug 13 07:33:20 2010 -0700
    54.2 +++ b/src/share/vm/oops/typeArrayKlass.cpp	Sat Aug 14 00:47:52 2010 -0700
    54.3 @@ -228,10 +228,6 @@
    54.4  }
    54.5  
    54.6  #ifndef SERIALGC
    54.7 -void typeArrayKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
    54.8 -  assert(obj->is_typeArray(),"must be a type array");
    54.9 -}
   54.10 -
   54.11  void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   54.12    assert(obj->is_typeArray(),"must be a type array");
   54.13  }
    55.1 --- a/src/share/vm/runtime/arguments.cpp	Fri Aug 13 07:33:20 2010 -0700
    55.2 +++ b/src/share/vm/runtime/arguments.cpp	Sat Aug 14 00:47:52 2010 -0700
    55.3 @@ -184,6 +184,8 @@
    55.4    { "DefaultMaxRAM",       JDK_Version::jdk_update(6,18), JDK_Version::jdk(7) },
    55.5    { "DefaultInitialRAMFraction",
    55.6                             JDK_Version::jdk_update(6,18), JDK_Version::jdk(7) },
    55.7 +  { "UseDepthFirstScavengeOrder",
    55.8 +                           JDK_Version::jdk_update(6,22), JDK_Version::jdk(7) },
    55.9    { NULL, JDK_Version(0), JDK_Version(0) }
   55.10  };
   55.11  
    56.1 --- a/src/share/vm/runtime/globals.hpp	Fri Aug 13 07:33:20 2010 -0700
    56.2 +++ b/src/share/vm/runtime/globals.hpp	Sat Aug 14 00:47:52 2010 -0700
    56.3 @@ -3092,10 +3092,6 @@
    56.4                                                                              \
    56.5    product(intx, SafepointSpinBeforeYield, 2000,  "(Unstable)")              \
    56.6                                                                              \
    56.7 -  product(bool, UseDepthFirstScavengeOrder, true,                           \
    56.8 -          "true: the scavenge order will be depth-first, "                  \
    56.9 -          "false: the scavenge order will be breadth-first")                \
   56.10 -                                                                            \
   56.11    product(bool, PSChunkLargeArrays, true,                                   \
   56.12            "true: process large arrays in chunks")                           \
   56.13                                                                              \
    57.1 --- a/src/share/vm/runtime/orderAccess.cpp	Fri Aug 13 07:33:20 2010 -0700
    57.2 +++ b/src/share/vm/runtime/orderAccess.cpp	Sat Aug 14 00:47:52 2010 -0700
    57.3 @@ -1,5 +1,5 @@
    57.4  /*
    57.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
    57.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    57.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    57.8   *
    57.9   * This code is free software; you can redistribute it and/or modify it
   57.10 @@ -25,8 +25,6 @@
   57.11  # include "incls/_precompiled.incl"
   57.12  # include "incls/_orderAccess.cpp.incl"
   57.13  
   57.14 -volatile intptr_t OrderAccess::dummy = 0;
   57.15 -
   57.16  void OrderAccess::StubRoutines_fence() {
   57.17    // Use a stub if it exists.  It may not exist during bootstrap so do
   57.18    // nothing in that case but assert if no fence code exists after threads have been created
    58.1 --- a/src/share/vm/runtime/orderAccess.hpp	Fri Aug 13 07:33:20 2010 -0700
    58.2 +++ b/src/share/vm/runtime/orderAccess.hpp	Sat Aug 14 00:47:52 2010 -0700
    58.3 @@ -1,5 +1,5 @@
    58.4  /*
    58.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
    58.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    58.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    58.8   *
    58.9   * This code is free software; you can redistribute it and/or modify it
   58.10 @@ -166,6 +166,12 @@
   58.11  // and release must include a sequence point, usually via a volatile memory
   58.12  // access.  Other ways to guarantee a sequence point are, e.g., use of
   58.13  // indirect calls and linux's __asm__ volatile.
   58.14 +// Note: as of 6973570, we have replaced the originally static "dummy" field
   58.15 +// (see above) by a volatile store to the stack. All of the versions of the
   58.16 +// compilers that we currently use (SunStudio, gcc and VC++) respect the
   58.17 +// semantics of volatile here. If you build HotSpot using other
   58.18 +// compilers, you may need to verify that no compiler reordering occurs
   58.19 +// across the sequence point respresented by the volatile access.
   58.20  //
   58.21  //
   58.22  //                os::is_MP Considered Redundant
   58.23 @@ -297,10 +303,6 @@
   58.24    static void     release_store_ptr_fence(volatile intptr_t* p, intptr_t v);
   58.25    static void     release_store_ptr_fence(volatile void*     p, void*    v);
   58.26  
   58.27 -  // In order to force a memory access, implementations may
   58.28 -  // need a volatile externally visible dummy variable.
   58.29 -  static volatile intptr_t dummy;
   58.30 -
   58.31   private:
   58.32    // This is a helper that invokes the StubRoutines::fence_entry()
   58.33    // routine if it exists, It should only be used by platforms that
    59.1 --- a/src/share/vm/services/management.cpp	Fri Aug 13 07:33:20 2010 -0700
    59.2 +++ b/src/share/vm/services/management.cpp	Sat Aug 14 00:47:52 2010 -0700
    59.3 @@ -1900,16 +1900,15 @@
    59.4  
    59.5    // Get the GCMemoryManager
    59.6    GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
    59.7 -  if (mgr->last_gc_stat() == NULL) {
    59.8 -    gc_stat->gc_index = 0;
    59.9 -    return;
   59.10 -  }
   59.11  
   59.12    // Make a copy of the last GC statistics
   59.13    // GC may occur while constructing the last GC information
   59.14    int num_pools = MemoryService::num_memory_pools();
   59.15    GCStatInfo* stat = new GCStatInfo(num_pools);
   59.16 -  stat->copy_stat(mgr->last_gc_stat());
   59.17 +  if (mgr->get_last_gc_stat(stat) == 0) {
   59.18 +    gc_stat->gc_index = 0;
   59.19 +    return;
   59.20 +  }
   59.21  
   59.22    gc_stat->gc_index = stat->gc_index();
   59.23    gc_stat->start_time = Management::ticks_to_ms(stat->start_time());
    60.1 --- a/src/share/vm/services/memoryManager.cpp	Fri Aug 13 07:33:20 2010 -0700
    60.2 +++ b/src/share/vm/services/memoryManager.cpp	Sat Aug 14 00:47:52 2010 -0700
    60.3 @@ -166,17 +166,6 @@
    60.4    FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array);
    60.5  }
    60.6  
    60.7 -void GCStatInfo::copy_stat(GCStatInfo* stat) {
    60.8 -  set_index(stat->gc_index());
    60.9 -  set_start_time(stat->start_time());
   60.10 -  set_end_time(stat->end_time());
   60.11 -  assert(_usage_array_size == stat->usage_array_size(), "Must have same array size");
   60.12 -  for (int i = 0; i < _usage_array_size; i++) {
   60.13 -    set_before_gc_usage(i, stat->before_gc_usage_for_pool(i));
   60.14 -    set_after_gc_usage(i, stat->after_gc_usage_for_pool(i));
   60.15 -  }
   60.16 -}
   60.17 -
   60.18  void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) {
   60.19    MemoryUsage* gc_usage_array;
   60.20    if (before_gc) {
   60.21 @@ -187,67 +176,129 @@
   60.22    gc_usage_array[pool_index] = usage;
   60.23  }
   60.24  
   60.25 +void GCStatInfo::clear() {
   60.26 +  _index = 0;
   60.27 +  _start_time = 0L;
   60.28 +  _end_time = 0L;
   60.29 +  size_t len = _usage_array_size * sizeof(MemoryUsage);
   60.30 +  memset(_before_gc_usage_array, 0, len);
   60.31 +  memset(_after_gc_usage_array, 0, len);
   60.32 +}
   60.33 +
   60.34 +
   60.35  GCMemoryManager::GCMemoryManager() : MemoryManager() {
   60.36    _num_collections = 0;
   60.37    _last_gc_stat = NULL;
   60.38 +  _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true);
   60.39 +  _current_gc_stat = NULL;
   60.40    _num_gc_threads = 1;
   60.41  }
   60.42  
   60.43  GCMemoryManager::~GCMemoryManager() {
   60.44    delete _last_gc_stat;
   60.45 +  delete _last_gc_lock;
   60.46 +  delete _current_gc_stat;
   60.47  }
   60.48  
   60.49  void GCMemoryManager::initialize_gc_stat_info() {
   60.50    assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
   60.51    _last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
   60.52 +  _current_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
   60.53 +  // tracking concurrent collections we need two objects: one to update, and one to
   60.54 +  // hold the publicly available "last (completed) gc" information.
   60.55  }
   60.56  
   60.57 -void GCMemoryManager::gc_begin() {
   60.58 -  assert(_last_gc_stat != NULL, "Just checking");
   60.59 -  _accumulated_timer.start();
   60.60 -  _num_collections++;
   60.61 -  _last_gc_stat->set_index(_num_collections);
   60.62 -  _last_gc_stat->set_start_time(Management::timestamp());
   60.63 +void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
   60.64 +                               bool recordAccumulatedGCTime) {
   60.65 +  assert(_last_gc_stat != NULL && _current_gc_stat != NULL, "Just checking");
   60.66 +  if (recordAccumulatedGCTime) {
   60.67 +    _accumulated_timer.start();
   60.68 +  }
   60.69 +  // _num_collections now increases in gc_end, to count completed collections
   60.70 +  if (recordGCBeginTime) {
   60.71 +    _current_gc_stat->set_index(_num_collections+1);
   60.72 +    _current_gc_stat->set_start_time(Management::timestamp());
   60.73 +  }
   60.74  
   60.75 -  // Keep memory usage of all memory pools
   60.76 -  for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
   60.77 -    MemoryPool* pool = MemoryService::get_memory_pool(i);
   60.78 -    MemoryUsage usage = pool->get_memory_usage();
   60.79 -    _last_gc_stat->set_before_gc_usage(i, usage);
   60.80 -    HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin,
   60.81 -      name(), strlen(name()),
   60.82 -      pool->name(), strlen(pool->name()),
   60.83 -      usage.init_size(), usage.used(),
   60.84 -      usage.committed(), usage.max_size());
   60.85 +  if (recordPreGCUsage) {
   60.86 +    // Keep memory usage of all memory pools
   60.87 +    for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
   60.88 +      MemoryPool* pool = MemoryService::get_memory_pool(i);
   60.89 +      MemoryUsage usage = pool->get_memory_usage();
   60.90 +      _current_gc_stat->set_before_gc_usage(i, usage);
   60.91 +      HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin,
   60.92 +        name(), strlen(name()),
   60.93 +        pool->name(), strlen(pool->name()),
   60.94 +        usage.init_size(), usage.used(),
   60.95 +        usage.committed(), usage.max_size());
   60.96 +    }
   60.97    }
   60.98  }
   60.99  
  60.100 -void GCMemoryManager::gc_end() {
  60.101 -  _accumulated_timer.stop();
  60.102 -  _last_gc_stat->set_end_time(Management::timestamp());
  60.103 -
  60.104 -  int i;
  60.105 -  // keep the last gc statistics for all memory pools
  60.106 -  for (i = 0; i < MemoryService::num_memory_pools(); i++) {
  60.107 -    MemoryPool* pool = MemoryService::get_memory_pool(i);
  60.108 -    MemoryUsage usage = pool->get_memory_usage();
  60.109 -
  60.110 -    HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end,
  60.111 -      name(), strlen(name()),
  60.112 -      pool->name(), strlen(pool->name()),
  60.113 -      usage.init_size(), usage.used(),
  60.114 -      usage.committed(), usage.max_size());
  60.115 -
  60.116 -    _last_gc_stat->set_after_gc_usage(i, usage);
  60.117 +// A collector MUST, even if it does not complete for some reason,
  60.118 +// make a TraceMemoryManagerStats object where countCollection is true,
  60.119 +// to ensure the current gc stat is placed in _last_gc_stat.
  60.120 +void GCMemoryManager::gc_end(bool recordPostGCUsage,
  60.121 +                             bool recordAccumulatedGCTime,
  60.122 +                             bool recordGCEndTime, bool countCollection) {
  60.123 +  if (recordAccumulatedGCTime) {
  60.124 +    _accumulated_timer.stop();
  60.125 +  }
  60.126 +  if (recordGCEndTime) {
  60.127 +    _current_gc_stat->set_end_time(Management::timestamp());
  60.128    }
  60.129  
  60.130 -  // Set last collection usage of the memory pools managed by this collector
  60.131 -  for (i = 0; i < num_memory_pools(); i++) {
  60.132 -    MemoryPool* pool = get_memory_pool(i);
  60.133 -    MemoryUsage usage = pool->get_memory_usage();
  60.134 +  if (recordPostGCUsage) {
  60.135 +    int i;
  60.136 +    // keep the last gc statistics for all memory pools
  60.137 +    for (i = 0; i < MemoryService::num_memory_pools(); i++) {
  60.138 +      MemoryPool* pool = MemoryService::get_memory_pool(i);
  60.139 +      MemoryUsage usage = pool->get_memory_usage();
  60.140  
  60.141 -    // Compare with GC usage threshold
  60.142 -    pool->set_last_collection_usage(usage);
  60.143 -    LowMemoryDetector::detect_after_gc_memory(pool);
  60.144 +      HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end,
  60.145 +        name(), strlen(name()),
  60.146 +        pool->name(), strlen(pool->name()),
  60.147 +        usage.init_size(), usage.used(),
  60.148 +        usage.committed(), usage.max_size());
  60.149 +
  60.150 +      _current_gc_stat->set_after_gc_usage(i, usage);
  60.151 +    }
  60.152 +
  60.153 +    // Set last collection usage of the memory pools managed by this collector
  60.154 +    for (i = 0; i < num_memory_pools(); i++) {
  60.155 +      MemoryPool* pool = get_memory_pool(i);
  60.156 +      MemoryUsage usage = pool->get_memory_usage();
  60.157 +
  60.158 +      // Compare with GC usage threshold
  60.159 +      pool->set_last_collection_usage(usage);
  60.160 +      LowMemoryDetector::detect_after_gc_memory(pool);
  60.161 +    }
  60.162 +  }
  60.163 +  if (countCollection) {
  60.164 +    _num_collections++;
  60.165 +    // alternately update two objects making one public when complete
  60.166 +    {
  60.167 +      MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
  60.168 +      GCStatInfo *tmp = _last_gc_stat;
  60.169 +      _last_gc_stat = _current_gc_stat;
  60.170 +      _current_gc_stat = tmp;
  60.171 +      // reset the current stat for diagnosability purposes
  60.172 +      _current_gc_stat->clear();
  60.173 +    }
  60.174    }
  60.175  }
  60.176 +
  60.177 +size_t GCMemoryManager::get_last_gc_stat(GCStatInfo* dest) {
  60.178 +  MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
  60.179 +  if (_last_gc_stat->gc_index() != 0) {
  60.180 +    dest->set_index(_last_gc_stat->gc_index());
  60.181 +    dest->set_start_time(_last_gc_stat->start_time());
  60.182 +    dest->set_end_time(_last_gc_stat->end_time());
  60.183 +    assert(dest->usage_array_size() == _last_gc_stat->usage_array_size(),
  60.184 +           "Must have same array size");
  60.185 +    size_t len = dest->usage_array_size() * sizeof(MemoryUsage);
  60.186 +    memcpy(dest->before_gc_usage_array(), _last_gc_stat->before_gc_usage_array(), len);
  60.187 +    memcpy(dest->after_gc_usage_array(), _last_gc_stat->after_gc_usage_array(), len);
  60.188 +  }
  60.189 +  return _last_gc_stat->gc_index();
  60.190 +}
    61.1 --- a/src/share/vm/services/memoryManager.hpp	Fri Aug 13 07:33:20 2010 -0700
    61.2 +++ b/src/share/vm/services/memoryManager.hpp	Sat Aug 14 00:47:52 2010 -0700
    61.3 @@ -131,6 +131,9 @@
    61.4      return _after_gc_usage_array[pool_index];
    61.5    }
    61.6  
    61.7 +  MemoryUsage* before_gc_usage_array() { return _before_gc_usage_array; }
    61.8 +  MemoryUsage* after_gc_usage_array()  { return _after_gc_usage_array; }
    61.9 +
   61.10    void set_index(size_t index)    { _index = index; }
   61.11    void set_start_time(jlong time) { _start_time = time; }
   61.12    void set_end_time(jlong time)   { _end_time = time; }
   61.13 @@ -143,7 +146,7 @@
   61.14      set_gc_usage(pool_index, usage, false /* after gc */);
   61.15    }
   61.16  
   61.17 -  void copy_stat(GCStatInfo* stat);
   61.18 +  void clear();
   61.19  };
   61.20  
   61.21  class GCMemoryManager : public MemoryManager {
   61.22 @@ -153,6 +156,8 @@
   61.23    elapsedTimer _accumulated_timer;
   61.24    elapsedTimer _gc_timer;         // for measuring every GC duration
   61.25    GCStatInfo*  _last_gc_stat;
   61.26 +  Mutex*       _last_gc_lock;
   61.27 +  GCStatInfo*  _current_gc_stat;
   61.28    int          _num_gc_threads;
   61.29  public:
   61.30    GCMemoryManager();
   61.31 @@ -166,11 +171,16 @@
   61.32    int    num_gc_threads()               { return _num_gc_threads; }
   61.33    void   set_num_gc_threads(int count)  { _num_gc_threads = count; }
   61.34  
   61.35 -  void   gc_begin();
   61.36 -  void   gc_end();
   61.37 +  void   gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
   61.38 +                  bool recordAccumulatedGCTime);
   61.39 +  void   gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime,
   61.40 +                bool recordGCEndTime, bool countCollection);
   61.41  
   61.42    void        reset_gc_stat()   { _num_collections = 0; _accumulated_timer.reset(); }
   61.43 -  GCStatInfo* last_gc_stat()    { return _last_gc_stat; }
   61.44 +
   61.45 +  // Copy out _last_gc_stat to the given destination, returning
   61.46 +  // the collection count. Zero signifies no gc has taken place.
   61.47 +  size_t get_last_gc_stat(GCStatInfo* dest);
   61.48  
   61.49    virtual MemoryManager::Name kind() = 0;
   61.50  };
    62.1 --- a/src/share/vm/services/memoryService.cpp	Fri Aug 13 07:33:20 2010 -0700
    62.2 +++ b/src/share/vm/services/memoryService.cpp	Sat Aug 14 00:47:52 2010 -0700
    62.3 @@ -509,7 +509,10 @@
    62.4    }
    62.5  }
    62.6  
    62.7 -void MemoryService::gc_begin(bool fullGC) {
    62.8 +void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime,
    62.9 +                             bool recordAccumulatedGCTime,
   62.10 +                             bool recordPreGCUsage, bool recordPeakUsage) {
   62.11 +
   62.12    GCMemoryManager* mgr;
   62.13    if (fullGC) {
   62.14      mgr = _major_gc_manager;
   62.15 @@ -517,16 +520,21 @@
   62.16      mgr = _minor_gc_manager;
   62.17    }
   62.18    assert(mgr->is_gc_memory_manager(), "Sanity check");
   62.19 -  mgr->gc_begin();
   62.20 +  mgr->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime);
   62.21  
   62.22    // Track the peak memory usage when GC begins
   62.23 -  for (int i = 0; i < _pools_list->length(); i++) {
   62.24 -    MemoryPool* pool = _pools_list->at(i);
   62.25 -    pool->record_peak_memory_usage();
   62.26 +  if (recordPeakUsage) {
   62.27 +    for (int i = 0; i < _pools_list->length(); i++) {
   62.28 +      MemoryPool* pool = _pools_list->at(i);
   62.29 +      pool->record_peak_memory_usage();
   62.30 +    }
   62.31    }
   62.32  }
   62.33  
   62.34 -void MemoryService::gc_end(bool fullGC) {
   62.35 +void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage,
   62.36 +                           bool recordAccumulatedGCTime,
   62.37 +                           bool recordGCEndTime, bool countCollection) {
   62.38 +
   62.39    GCMemoryManager* mgr;
   62.40    if (fullGC) {
   62.41      mgr = (GCMemoryManager*) _major_gc_manager;
   62.42 @@ -536,7 +544,8 @@
   62.43    assert(mgr->is_gc_memory_manager(), "Sanity check");
   62.44  
   62.45    // register the GC end statistics and memory usage
   62.46 -  mgr->gc_end();
   62.47 +  mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
   62.48 +              countCollection);
   62.49  }
   62.50  
   62.51  void MemoryService::oops_do(OopClosure* f) {
   62.52 @@ -585,12 +594,12 @@
   62.53    return obj;
   62.54  }
   62.55  //
   62.56 -// GC manager type depends on the type of Generation. Depending the space
   62.57 -// availablity and vm option the gc uses major gc manager or minor gc
   62.58 +// GC manager type depends on the type of Generation. Depending on the space
   62.59 +// availablity and vm options the gc uses major gc manager or minor gc
   62.60  // manager or both. The type of gc manager depends on the generation kind.
   62.61 -// For DefNew, ParNew and ASParNew generation doing scavange gc uses minor
   62.62 -// gc manager (so _fullGC is set to false ) and for other generation kind
   62.63 -// DOing mark-sweep-compact uses major gc manager (so _fullGC is set
   62.64 +// For DefNew, ParNew and ASParNew generation doing scavenge gc uses minor
   62.65 +// gc manager (so _fullGC is set to false ) and for other generation kinds
   62.66 +// doing mark-sweep-compact uses major gc manager (so _fullGC is set
   62.67  // to true).
   62.68  TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind) {
   62.69    switch (kind) {
   62.70 @@ -611,13 +620,48 @@
   62.71      default:
   62.72        assert(false, "Unrecognized gc generation kind.");
   62.73    }
   62.74 -  MemoryService::gc_begin(_fullGC);
   62.75 +  // this has to be called in a stop the world pause and represent
   62.76 +  // an entire gc pause, start to finish:
   62.77 +  initialize(_fullGC, true, true, true, true, true, true, true);
   62.78  }
   62.79 -TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC) {
   62.80 +TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC,
   62.81 +                                                 bool recordGCBeginTime,
   62.82 +                                                 bool recordPreGCUsage,
   62.83 +                                                 bool recordPeakUsage,
   62.84 +                                                 bool recordPostGCUsage,
   62.85 +                                                 bool recordAccumulatedGCTime,
   62.86 +                                                 bool recordGCEndTime,
   62.87 +                                                 bool countCollection) {
   62.88 +  initialize(fullGC, recordGCBeginTime, recordPreGCUsage, recordPeakUsage,
   62.89 +             recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
   62.90 +             countCollection);
   62.91 +}
   62.92 +
   62.93 +// for a subclass to create then initialize an instance before invoking
   62.94 +// the MemoryService
   62.95 +void TraceMemoryManagerStats::initialize(bool fullGC,
   62.96 +                                         bool recordGCBeginTime,
   62.97 +                                         bool recordPreGCUsage,
   62.98 +                                         bool recordPeakUsage,
   62.99 +                                         bool recordPostGCUsage,
  62.100 +                                         bool recordAccumulatedGCTime,
  62.101 +                                         bool recordGCEndTime,
  62.102 +                                         bool countCollection) {
  62.103    _fullGC = fullGC;
  62.104 -  MemoryService::gc_begin(_fullGC);
  62.105 +  _recordGCBeginTime = recordGCBeginTime;
  62.106 +  _recordPreGCUsage = recordPreGCUsage;
  62.107 +  _recordPeakUsage = recordPeakUsage;
  62.108 +  _recordPostGCUsage = recordPostGCUsage;
  62.109 +  _recordAccumulatedGCTime = recordAccumulatedGCTime;
  62.110 +  _recordGCEndTime = recordGCEndTime;
  62.111 +  _countCollection = countCollection;
  62.112 +
  62.113 +  MemoryService::gc_begin(_fullGC, _recordGCBeginTime, _recordAccumulatedGCTime,
  62.114 +                          _recordPreGCUsage, _recordPeakUsage);
  62.115  }
  62.116  
  62.117  TraceMemoryManagerStats::~TraceMemoryManagerStats() {
  62.118 -  MemoryService::gc_end(_fullGC);
  62.119 +  MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime,
  62.120 +                        _recordGCEndTime, _countCollection);
  62.121  }
  62.122 +
    63.1 --- a/src/share/vm/services/memoryService.hpp	Fri Aug 13 07:33:20 2010 -0700
    63.2 +++ b/src/share/vm/services/memoryService.hpp	Sat Aug 14 00:47:52 2010 -0700
    63.3 @@ -149,8 +149,13 @@
    63.4    }
    63.5    static void track_memory_pool_usage(MemoryPool* pool);
    63.6  
    63.7 -  static void gc_begin(bool fullGC);
    63.8 -  static void gc_end(bool fullGC);
    63.9 +  static void gc_begin(bool fullGC, bool recordGCBeginTime,
   63.10 +                       bool recordAccumulatedGCTime,
   63.11 +                       bool recordPreGCUsage, bool recordPeakUsage);
   63.12 +  static void gc_end(bool fullGC, bool recordPostGCUsage,
   63.13 +                     bool recordAccumulatedGCTime,
   63.14 +                     bool recordGCEndTime, bool countCollection);
   63.15 +
   63.16  
   63.17    static void oops_do(OopClosure* f);
   63.18  
   63.19 @@ -164,8 +169,34 @@
   63.20  class TraceMemoryManagerStats : public StackObj {
   63.21  private:
   63.22    bool         _fullGC;
   63.23 +  bool         _recordGCBeginTime;
   63.24 +  bool         _recordPreGCUsage;
   63.25 +  bool         _recordPeakUsage;
   63.26 +  bool         _recordPostGCUsage;
   63.27 +  bool         _recordAccumulatedGCTime;
   63.28 +  bool         _recordGCEndTime;
   63.29 +  bool         _countCollection;
   63.30 +
   63.31  public:
   63.32 -  TraceMemoryManagerStats(bool fullGC);
   63.33 +  TraceMemoryManagerStats() {}
   63.34 +  TraceMemoryManagerStats(bool fullGC,
   63.35 +                          bool recordGCBeginTime = true,
   63.36 +                          bool recordPreGCUsage = true,
   63.37 +                          bool recordPeakUsage = true,
   63.38 +                          bool recordPostGCUsage = true,
   63.39 +                          bool recordAccumulatedGCTime = true,
   63.40 +                          bool recordGCEndTime = true,
   63.41 +                          bool countCollection = true);
   63.42 +
   63.43 +  void initialize(bool fullGC,
   63.44 +                  bool recordGCBeginTime,
   63.45 +                  bool recordPreGCUsage,
   63.46 +                  bool recordPeakUsage,
   63.47 +                  bool recordPostGCUsage,
   63.48 +                  bool recordAccumulatedGCTime,
   63.49 +                  bool recordGCEndTime,
   63.50 +                  bool countCollection);
   63.51 +
   63.52    TraceMemoryManagerStats(Generation::Name kind);
   63.53    ~TraceMemoryManagerStats();
   63.54  };
    64.1 --- a/src/share/vm/utilities/taskqueue.cpp	Fri Aug 13 07:33:20 2010 -0700
    64.2 +++ b/src/share/vm/utilities/taskqueue.cpp	Sat Aug 14 00:47:52 2010 -0700
    64.3 @@ -36,6 +36,14 @@
    64.4    "qpush", "qpop", "qpop-s", "qattempt", "qsteal", "opush", "omax"
    64.5  };
    64.6  
    64.7 +TaskQueueStats & TaskQueueStats::operator +=(const TaskQueueStats & addend)
    64.8 +{
    64.9 +  for (unsigned int i = 0; i < last_stat_id; ++i) {
   64.10 +    _stats[i] += addend._stats[i];
   64.11 +  }
   64.12 +  return *this;
   64.13 +}
   64.14 +
   64.15  void TaskQueueStats::print_header(unsigned int line, outputStream* const stream,
   64.16                                    unsigned int width)
   64.17  {
   64.18 @@ -71,6 +79,29 @@
   64.19    }
   64.20    #undef FMT
   64.21  }
   64.22 +
   64.23 +#ifdef ASSERT
   64.24 +// Invariants which should hold after a TaskQueue has been emptied and is
   64.25 +// quiescent; they do not hold at arbitrary times.
   64.26 +void TaskQueueStats::verify() const
   64.27 +{
   64.28 +  assert(get(push) == get(pop) + get(steal),
   64.29 +         err_msg("push=" SIZE_FORMAT " pop=" SIZE_FORMAT " steal=" SIZE_FORMAT,
   64.30 +                 get(push), get(pop), get(steal)));
   64.31 +  assert(get(pop_slow) <= get(pop),
   64.32 +         err_msg("pop_slow=" SIZE_FORMAT " pop=" SIZE_FORMAT,
   64.33 +                 get(pop_slow), get(pop)));
   64.34 +  assert(get(steal) <= get(steal_attempt),
   64.35 +         err_msg("steal=" SIZE_FORMAT " steal_attempt=" SIZE_FORMAT,
   64.36 +                 get(steal), get(steal_attempt)));
   64.37 +  assert(get(overflow) == 0 || get(push) != 0,
   64.38 +         err_msg("overflow=" SIZE_FORMAT " push=" SIZE_FORMAT,
   64.39 +                 get(overflow), get(push)));
   64.40 +  assert(get(overflow_max_len) == 0 || get(overflow) != 0,
   64.41 +         err_msg("overflow_max_len=" SIZE_FORMAT " overflow=" SIZE_FORMAT,
   64.42 +                 get(overflow_max_len), get(overflow)));
   64.43 +}
   64.44 +#endif // ASSERT
   64.45  #endif // TASKQUEUE_STATS
   64.46  
   64.47  int TaskQueueSetSuper::randomParkAndMiller(int *seed0) {
    65.1 --- a/src/share/vm/utilities/taskqueue.hpp	Fri Aug 13 07:33:20 2010 -0700
    65.2 +++ b/src/share/vm/utilities/taskqueue.hpp	Sat Aug 14 00:47:52 2010 -0700
    65.3 @@ -59,15 +59,21 @@
    65.4    inline void record_steal(bool success);
    65.5    inline void record_overflow(size_t new_length);
    65.6  
    65.7 +  TaskQueueStats & operator +=(const TaskQueueStats & addend);
    65.8 +
    65.9    inline size_t get(StatId id) const { return _stats[id]; }
   65.10    inline const size_t* get() const   { return _stats; }
   65.11  
   65.12    inline void reset();
   65.13  
   65.14 +  // Print the specified line of the header (does not include a line separator).
   65.15    static void print_header(unsigned int line, outputStream* const stream = tty,
   65.16                             unsigned int width = 10);
   65.17 +  // Print the statistics (does not include a line separator).
   65.18    void print(outputStream* const stream = tty, unsigned int width = 10) const;
   65.19  
   65.20 +  DEBUG_ONLY(void verify() const;)
   65.21 +
   65.22  private:
   65.23    size_t                    _stats[last_stat_id];
   65.24    static const char * const _names[last_stat_id];
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/test/gc/6581734/Test6581734.java	Sat Aug 14 00:47:52 2010 -0700
    66.3 @@ -0,0 +1,149 @@
    66.4 +/*
    66.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    66.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    66.7 + *
    66.8 + * This code is free software; you can redistribute it and/or modify it
    66.9 + * under the terms of the GNU General Public License version 2 only, as
   66.10 + * published by the Free Software Foundation.
   66.11 + *
   66.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   66.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   66.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   66.15 + * version 2 for more details (a copy is included in the LICENSE file that
   66.16 + * accompanied this code).
   66.17 + *
   66.18 + * You should have received a copy of the GNU General Public License version
   66.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   66.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   66.21 + *
   66.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   66.23 + * or visit www.oracle.com if you need additional information or have any
   66.24 + * questions.
   66.25 + */
   66.26 +
   66.27 +/*
   66.28 + * @test Test6581734.java
   66.29 + * @bug 6581734
   66.30 + * @summary CMS Old Gen's collection usage is zero after GC which is incorrect
   66.31 + * @run main/othervm -Xmx512m -verbose:gc -XX:+UseConcMarkSweepGC Test6581734
   66.32 + *
   66.33 + */
   66.34 +import java.util.*;
   66.35 +import java.lang.management.*;
   66.36 +
   66.37 +// 6581734 states that memory pool usage via the mbean is wrong
   66.38 +// for CMS (zero, even after a collection).
   66.39 +//
   66.40 +// 6580448 states that the collection count similarly is wrong
   66.41 +// (stays at zero for CMS collections)
   66.42 +// -- closed as dup of 6581734 as the same fix resolves both.
   66.43 +
   66.44 +
   66.45 +public class Test6581734 {
   66.46 +
   66.47 +    private String poolName = "CMS";
   66.48 +    private String collectorName = "ConcurrentMarkSweep";
   66.49 +
   66.50 +    public static void main(String [] args) {
   66.51 +
   66.52 +        Test6581734 t = null;
   66.53 +        if (args.length==2) {
   66.54 +            t = new Test6581734(args[0], args[1]);
   66.55 +        } else {
   66.56 +            System.out.println("Defaulting to monitor CMS pool and collector.");
   66.57 +            t = new Test6581734();
   66.58 +        }
   66.59 +        t.run();
   66.60 +    }
   66.61 +
   66.62 +    public Test6581734(String pool, String collector) {
   66.63 +        poolName = pool;
   66.64 +        collectorName = collector;
   66.65 +    }
   66.66 +
   66.67 +    public Test6581734() {
   66.68 +    }
   66.69 +
   66.70 +    public void run() {
   66.71 +        // Use some memory, enough that we expect collections should
   66.72 +        // have happened.
   66.73 +        // Must run with options to ensure no stop the world full GC,
   66.74 +        // but e.g. at least one CMS cycle.
   66.75 +        allocationWork(300*1024*1024);
   66.76 +        System.out.println("Done allocationWork");
   66.77 +
   66.78 +        // Verify some non-zero results are stored.
   66.79 +        List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
   66.80 +        int poolsFound = 0;
   66.81 +        int poolsWithStats = 0;
   66.82 +        for (int i=0; i<pools.size(); i++) {
   66.83 +            MemoryPoolMXBean pool = pools.get(i);
   66.84 +            String name = pool.getName();
   66.85 +            System.out.println("found pool: " + name);
   66.86 +
   66.87 +            if (name.contains(poolName)) {
   66.88 +                long usage = pool.getCollectionUsage().getUsed();
   66.89 +                System.out.println(name + ": usage after GC = " + usage);
   66.90 +                poolsFound++;
   66.91 +                if (usage > 0) {
   66.92 +                    poolsWithStats++;
   66.93 +                }
   66.94 +            }
   66.95 +        }
   66.96 +        if (poolsFound == 0) {
   66.97 +            throw new RuntimeException("No matching memory pools found: test with -XX:+UseConcMarkSweepGC");
   66.98 +        }
   66.99 +
  66.100 +        List<GarbageCollectorMXBean> collectors = ManagementFactory.getGarbageCollectorMXBeans();
  66.101 +        int collectorsFound = 0;
  66.102 +        int collectorsWithTime= 0;
  66.103 +        for (int i=0; i<collectors.size(); i++) {
  66.104 +            GarbageCollectorMXBean collector = collectors.get(i);
  66.105 +            String name = collector.getName();
  66.106 +            System.out.println("found collector: " + name);
  66.107 +            if (name.contains(collectorName)) {
  66.108 +                collectorsFound++;
  66.109 +                System.out.println(name + ": collection count = "
  66.110 +                                   + collector.getCollectionCount());
  66.111 +                System.out.println(name + ": collection time  = "
  66.112 +                                   + collector.getCollectionTime());
  66.113 +                if (collector.getCollectionCount() <= 0) {
  66.114 +                    throw new RuntimeException("collection count <= 0");
  66.115 +                }
  66.116 +                if (collector.getCollectionTime() > 0) {
  66.117 +                    collectorsWithTime++;
  66.118 +                }
  66.119 +            }
  66.120 +        }
  66.121 +        // verify:
  66.122 +        if (poolsWithStats < poolsFound) {
  66.123 +            throw new RuntimeException("pools found with zero stats");
  66.124 +        }
  66.125 +
  66.126 +        if (collectorsWithTime<collectorsFound) {
  66.127 +            throw new RuntimeException("collectors found with zero time";
  66.128 +        }
  66.129 +        System.out.println("Test passed.");
  66.130 +    }
  66.131 +
  66.132 +    public void allocationWork(long target) {
  66.133 +
  66.134 +        long sizeAllocated = 0;
  66.135 +        List list = new LinkedList();
  66.136 +        long delay = 50;
  66.137 +        long count = 0;
  66.138 +
  66.139 +        while (sizeAllocated < target) {
  66.140 +            int size = 1024*1024;
  66.141 +            byte [] alloc = new byte[size];
  66.142 +            if (count % 2 == 0) {
  66.143 +                list.add(alloc);
  66.144 +                sizeAllocated+=size;
  66.145 +                System.out.print(".");
  66.146 +            }
  66.147 +            try { Thread.sleep(delay); } catch (InterruptedException ie) { }
  66.148 +            count++;
  66.149 +        }
  66.150 +    }
  66.151 +
  66.152 +}

mercurial