Merge
authorkvn
Thu, 07 May 2015 11:28:03 -0700
changeset 30595 1416b16e7f55
parent 30594 e1b420c520a0 (current diff)
parent 30586 23e6e981e89c (diff)
child 30596 0322b394e7fd
Merge
hotspot/test/Makefile
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu May 07 11:28:03 2015 -0700
@@ -1631,36 +1631,22 @@
 
         NOT_LP64(__ get_thread(thread);)
 
-        Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                             PtrQueue::byte_offset_of_active()));
-
         Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
                                              PtrQueue::byte_offset_of_index()));
         Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
                                         PtrQueue::byte_offset_of_buf()));
 
-
         Label done;
         Label runtime;
 
         // Can we store original value in the thread's buffer?
 
-#ifdef _LP64
-        __ movslq(tmp, queue_index);
-        __ cmpq(tmp, 0);
-#else
-        __ cmpl(queue_index, 0);
-#endif
-        __ jcc(Assembler::equal, runtime);
-#ifdef _LP64
-        __ subq(tmp, wordSize);
-        __ movl(queue_index, tmp);
-        __ addq(tmp, buffer);
-#else
-        __ subl(queue_index, wordSize);
-        __ movl(tmp, buffer);
-        __ addl(tmp, queue_index);
-#endif
+        __ movptr(tmp, queue_index);
+        __ testptr(tmp, tmp);
+        __ jcc(Assembler::zero, runtime);
+        __ subptr(tmp, wordSize);
+        __ movptr(queue_index, tmp);
+        __ addptr(tmp, buffer);
 
         // prev_val (rax)
         f.load_argument(0, pre_val);
@@ -1713,6 +1699,7 @@
         assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 
         Label done;
+        Label enqueued;
         Label runtime;
 
         // At this point we know new_value is non-NULL and the new_value crosses regions.
@@ -1752,28 +1739,19 @@
 
         __ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
 
-        __ cmpl(queue_index, 0);
-        __ jcc(Assembler::equal, runtime);
-        __ subl(queue_index, wordSize);
-
-        const Register buffer_addr = rbx;
-        __ push(rbx);
-
-        __ movptr(buffer_addr, buffer);
+        const Register tmp = rdx;
+        __ push(rdx);
 
-#ifdef _LP64
-        __ movslq(rscratch1, queue_index);
-        __ addptr(buffer_addr, rscratch1);
-#else
-        __ addptr(buffer_addr, queue_index);
-#endif
-        __ movptr(Address(buffer_addr, 0), card_addr);
-
-        __ pop(rbx);
-        __ jmp(done);
+        __ movptr(tmp, queue_index);
+        __ testptr(tmp, tmp);
+        __ jcc(Assembler::zero, runtime);
+        __ subptr(tmp, wordSize);
+        __ movptr(queue_index, tmp);
+        __ addptr(tmp, buffer);
+        __ movptr(Address(tmp, 0), card_addr);
+        __ jmp(enqueued);
 
         __ bind(runtime);
-        __ push(rdx);
 #ifdef _LP64
         __ push(r8);
         __ push(r9);
@@ -1795,12 +1773,12 @@
         __ pop(r9);
         __ pop(r8);
 #endif
+        __ bind(enqueued);
         __ pop(rdx);
+
         __ bind(done);
-
         __ pop(rcx);
         __ pop(rax);
-
       }
       break;
 #endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
-#define SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
 
 #include "memory/freeList.hpp"
 #include "gc_implementation/shared/allocationStats.hpp"
@@ -226,4 +226,4 @@
 #endif  // NOT PRODUCT
 };
 
-#endif // SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -28,6 +28,7 @@
 #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
 #include "oops/oop.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // Trim our work_queue so its length is below max at return
 inline void Par_MarkRefsIntoAndScanClosure::trim_queue(uint max) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Thu May 07 11:28:03 2015 -0700
@@ -1082,17 +1082,6 @@
 bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const {
   FreeChunk* fc = (FreeChunk*)p;
   assert(is_in_reserved(p), "Should be in space");
-  // When doing a mark-sweep-compact of the CMS generation, this
-  // assertion may fail because prepare_for_compaction() uses
-  // space that is garbage to maintain information on ranges of
-  // live objects so that these live ranges can be moved as a whole.
-  // Comment out this assertion until that problem can be solved
-  // (i.e., that the block start calculation may look at objects
-  // at address below "p" in finding the object that contains "p"
-  // and those objects (if garbage) may have been modified to hold
-  // live range information.
-  // assert(CollectedHeap::use_parallel_gc_threads() || _bt.block_start(p) == p,
-  //        "Should be a block boundary");
   if (FreeChunk::indicatesFreeChunk(p)) return false;
   Klass* k = oop(p)->klass_or_null();
   if (k != NULL) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu May 07 11:28:03 2015 -0700
@@ -66,6 +66,7 @@
 #include "services/memoryService.hpp"
 #include "services/runtimeService.hpp"
 #include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // statics
 CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL;
@@ -224,16 +225,12 @@
            "Offset of FreeChunk::_prev within FreeChunk must match"
            "  that of OopDesc::_klass within OopDesc");
   )
-  if (CollectedHeap::use_parallel_gc_threads()) {
-    typedef CMSParGCThreadState* CMSParGCThreadStatePtr;
-    _par_gc_thread_states =
-      NEW_C_HEAP_ARRAY(CMSParGCThreadStatePtr, ParallelGCThreads, mtGC);
-    for (uint i = 0; i < ParallelGCThreads; i++) {
-      _par_gc_thread_states[i] = new CMSParGCThreadState(cmsSpace());
-    }
-  } else {
-    _par_gc_thread_states = NULL;
-  }
+
+  _par_gc_thread_states = NEW_C_HEAP_ARRAY(CMSParGCThreadState*, ParallelGCThreads, mtGC);
+  for (uint i = 0; i < ParallelGCThreads; i++) {
+    _par_gc_thread_states[i] = new CMSParGCThreadState(cmsSpace());
+  }
+
   _incremental_collection_failed = false;
   // The "dilatation_factor" is the expansion that can occur on
   // account of the fact that the minimum object size in the CMS
@@ -459,7 +456,6 @@
   _markBitMap(0, Mutex::leaf + 1, "CMS_markBitMap_lock"),
   _modUnionTable((CardTableModRefBS::card_shift - LogHeapWordSize),
                  -1 /* lock-free */, "No_lock" /* dummy */),
-  _modUnionClosure(&_modUnionTable),
   _modUnionClosurePar(&_modUnionTable),
   // Adjust my span to cover old (cms) gen
   _span(cmsGen->reserved()),
@@ -2129,10 +2125,7 @@
 
   bool registerClosure = duringMarking;
 
-  ModUnionClosure* muc = CollectedHeap::use_parallel_gc_threads() ?
-                                               &_modUnionClosurePar
-                                               : &_modUnionClosure;
-  _cmsGen->gc_prologue_work(full, registerClosure, muc);
+  _cmsGen->gc_prologue_work(full, registerClosure, &_modUnionClosurePar);
 
   if (!full) {
     stats().record_gc0_begin();
@@ -2905,8 +2898,8 @@
 class CMSParMarkTask : public AbstractGangTask {
  protected:
   CMSCollector*     _collector;
-  int               _n_workers;
-  CMSParMarkTask(const char* name, CMSCollector* collector, int n_workers) :
+  uint              _n_workers;
+  CMSParMarkTask(const char* name, CMSCollector* collector, uint n_workers) :
       AbstractGangTask(name),
       _collector(collector),
       _n_workers(n_workers) {}
@@ -2920,7 +2913,7 @@
 // Parallel initial mark task
 class CMSParInitialMarkTask: public CMSParMarkTask {
  public:
-  CMSParInitialMarkTask(CMSCollector* collector, int n_workers) :
+  CMSParInitialMarkTask(CMSCollector* collector, uint n_workers) :
       CMSParMarkTask("Scan roots and young gen for initial mark in parallel",
                      collector, n_workers) {}
   void work(uint worker_id);
@@ -3005,11 +2998,11 @@
 
   {
     COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
-    if (CMSParallelInitialMarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
+    if (CMSParallelInitialMarkEnabled) {
       // The parallel version.
       FlexibleWorkGang* workers = gch->workers();
       assert(workers != NULL, "Need parallel worker threads.");
-      int n_workers = workers->active_workers();
+      uint n_workers = workers->active_workers();
       CMSParInitialMarkTask tsk(this, n_workers);
       gch->set_par_threads(n_workers);
       initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
@@ -3150,7 +3143,7 @@
 // MT Concurrent Marking Task
 class CMSConcMarkingTask: public YieldingFlexibleGangTask {
   CMSCollector* _collector;
-  int           _n_workers;                  // requested/desired # workers
+  uint          _n_workers;       // requested/desired # workers
   bool          _result;
   CompactibleFreeListSpace*  _cms_space;
   char          _pad_front[64];   // padding to ...
@@ -3196,7 +3189,7 @@
 
   CMSConcMarkingTerminator* terminator() { return &_term; }
 
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     terminator()->reset_for_reuse(active_workers);
   }
 
@@ -3642,10 +3635,9 @@
 
 bool CMSCollector::do_marking_mt() {
   assert(ConcGCThreads > 0 && conc_workers() != NULL, "precondition");
-  int num_workers = AdaptiveSizePolicy::calc_active_conc_workers(
-                                       conc_workers()->total_workers(),
-                                       conc_workers()->active_workers(),
-                                       Threads::number_of_non_daemon_threads());
+  uint num_workers = AdaptiveSizePolicy::calc_active_conc_workers(conc_workers()->total_workers(),
+                                                                  conc_workers()->active_workers(),
+                                                                  Threads::number_of_non_daemon_threads());
   conc_workers()->set_active_workers(num_workers);
 
   CompactibleFreeListSpace* cms_space  = _cmsGen->cmsSpace();
@@ -4347,7 +4339,7 @@
     // dirtied since the first checkpoint in this GC cycle and prior to
     // the most recent young generation GC, minus those cleaned up by the
     // concurrent precleaning.
-    if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
+    if (CMSParallelRemarkEnabled) {
       GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
       do_remark_parallel();
     } else {
@@ -4491,7 +4483,7 @@
   // workers to be taken from the active workers in the work gang.
   CMSParRemarkTask(CMSCollector* collector,
                    CompactibleFreeListSpace* cms_space,
-                   int n_workers, FlexibleWorkGang* workers,
+                   uint n_workers, FlexibleWorkGang* workers,
                    OopTaskQueueSet* task_queues):
     CMSParMarkTask("Rescan roots and grey objects in parallel",
                    collector, n_workers),
@@ -4504,7 +4496,7 @@
   OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
 
   ParallelTaskTerminator* terminator() { return &_term; }
-  int n_workers() { return _n_workers; }
+  uint n_workers() { return _n_workers; }
 
   void work(uint worker_id);
 
@@ -5067,7 +5059,7 @@
   // Choose to use the number of GC workers most recently set
   // into "active_workers".  If active_workers is not set, set it
   // to ParallelGCThreads.
-  int n_workers = workers->active_workers();
+  uint n_workers = workers->active_workers();
   if (n_workers == 0) {
     assert(n_workers > 0, "Should have been set during scavenge");
     n_workers = ParallelGCThreads;
@@ -5433,7 +5425,7 @@
       // That is OK as long as the Reference lists are balanced (see
       // balance_all_queues() and balance_queues()).
       GenCollectedHeap* gch = GenCollectedHeap::heap();
-      int active_workers = ParallelGCThreads;
+      uint active_workers = ParallelGCThreads;
       FlexibleWorkGang* workers = gch->workers();
       if (workers != NULL) {
         active_workers = workers->active_workers();
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Thu May 07 11:28:03 2015 -0700
@@ -647,7 +647,6 @@
   // Keep this textually after _markBitMap and _span; c'tor dependency.
 
   ConcurrentMarkSweepThread*     _cmsThread;   // The thread doing the work
-  ModUnionClosure    _modUnionClosure;
   ModUnionClosurePar _modUnionClosurePar;
 
   // CMS abstract state machine
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu May 07 11:28:03 2015 -0700
@@ -54,6 +54,7 @@
 #include "runtime/atomic.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
 #include "services/memTracker.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // Concurrent marking bit map wrapper
 
@@ -2314,13 +2315,13 @@
   G1CollectedHeap* _g1h;
   ConcurrentMark*  _cm;
   WorkGang*        _workers;
-  int              _active_workers;
+  uint             _active_workers;
 
 public:
   G1CMRefProcTaskExecutor(G1CollectedHeap* g1h,
-                        ConcurrentMark* cm,
-                        WorkGang* workers,
-                        int n_workers) :
+                          ConcurrentMark* cm,
+                          WorkGang* workers,
+                          uint n_workers) :
     _g1h(g1h), _cm(cm),
     _workers(workers), _active_workers(n_workers) { }
 
@@ -2551,31 +2552,50 @@
   _nextMarkBitMap  = (CMBitMap*)  temp;
 }
 
-class CMObjectClosure;
-
-// Closure for iterating over objects, currently only used for
-// processing SATB buffers.
-class CMObjectClosure : public ObjectClosure {
+// Closure for marking entries in SATB buffers.
+class CMSATBBufferClosure : public SATBBufferClosure {
 private:
   CMTask* _task;
+  G1CollectedHeap* _g1h;
+
+  // This is very similar to CMTask::deal_with_reference, but with
+  // more relaxed requirements for the argument, so this must be more
+  // circumspect about treating the argument as an object.
+  void do_entry(void* entry) const {
+    _task->increment_refs_reached();
+    HeapRegion* hr = _g1h->heap_region_containing_raw(entry);
+    if (entry < hr->next_top_at_mark_start()) {
+      // Until we get here, we don't know whether entry refers to a valid
+      // object; it could instead have been a stale reference.
+      oop obj = static_cast<oop>(entry);
+      assert(obj->is_oop(true /* ignore mark word */),
+             err_msg("Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj)));
+      _task->make_reference_grey(obj, hr);
+    }
+  }
 
 public:
-  void do_object(oop obj) {
-    _task->deal_with_reference(obj);
+  CMSATBBufferClosure(CMTask* task, G1CollectedHeap* g1h)
+    : _task(task), _g1h(g1h) { }
+
+  virtual void do_buffer(void** buffer, size_t size) {
+    for (size_t i = 0; i < size; ++i) {
+      do_entry(buffer[i]);
+    }
   }
-
-  CMObjectClosure(CMTask* task) : _task(task) { }
 };
 
 class G1RemarkThreadsClosure : public ThreadClosure {
-  CMObjectClosure _cm_obj;
+  CMSATBBufferClosure _cm_satb_cl;
   G1CMOopClosure _cm_cl;
   MarkingCodeBlobClosure _code_cl;
   int _thread_parity;
 
  public:
   G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task) :
-    _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
+    _cm_satb_cl(task, g1h),
+    _cm_cl(g1h, g1h->concurrent_mark(), task),
+    _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
     _thread_parity(Threads::thread_claim_parity()) {}
 
   void do_thread(Thread* thread) {
@@ -2591,11 +2611,11 @@
         // live by the SATB invariant but other oops recorded in nmethods may behave differently.
         jt->nmethods_do(&_code_cl);
 
-        jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj);
+        jt->satb_mark_queue().apply_closure_and_empty(&_cm_satb_cl);
       }
     } else if (thread->is_VM_thread()) {
       if (thread->claim_oops_do(true, _thread_parity)) {
-        JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj);
+        JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
       }
     }
   }
@@ -2630,7 +2650,7 @@
     }
   }
 
-  CMRemarkTask(ConcurrentMark* cm, int active_workers) :
+  CMRemarkTask(ConcurrentMark* cm, uint active_workers) :
     AbstractGangTask("Par Remark"), _cm(cm) {
     _cm->terminator()->reset_for_reuse(active_workers);
   }
@@ -3008,7 +3028,7 @@
   ConcurrentMark* _cm;
   BitMap* _cm_card_bm;
   uint _max_worker_id;
-  int _active_workers;
+  uint _active_workers;
   HeapRegionClaimer _hrclaimer;
 
 public:
@@ -3016,7 +3036,7 @@
                            ConcurrentMark* cm,
                            BitMap* cm_card_bm,
                            uint max_worker_id,
-                           int n_workers) :
+                           uint n_workers) :
       AbstractGangTask("Count Aggregation"),
       _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
       _max_worker_id(max_worker_id),
@@ -3033,7 +3053,7 @@
 
 
 void ConcurrentMark::aggregate_count_data() {
-  int n_workers = _g1h->workers()->active_workers();
+  uint n_workers = _g1h->workers()->active_workers();
 
   G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm,
                                            _max_worker_id, n_workers);
@@ -3693,13 +3713,13 @@
   // very counter productive if it did that. :-)
   _draining_satb_buffers = true;
 
-  CMObjectClosure oc(this);
+  CMSATBBufferClosure satb_cl(this, _g1h);
   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
 
   // This keeps claiming and applying the closure to completed buffers
   // until we run out of buffers or we need to abort.
   while (!has_aborted() &&
-         satb_mq_set.apply_closure_to_completed_buffer(&oc)) {
+         satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)) {
     if (_cm->verbose_medium()) {
       gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id);
     }
@@ -3758,6 +3778,10 @@
 #endif // _MARKING_STATS_
 }
 
+bool ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) {
+  return _task_queues->steal(worker_id, hash_seed, obj);
+}
+
 /*****************************************************************************
 
     The do_marking_step(time_target_ms, ...) method is the building
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Thu May 07 11:28:03 2015 -0700
@@ -139,6 +139,11 @@
   static size_t compute_size(size_t heap_size);
   // Returns the amount of bytes on the heap between two marks in the bitmap.
   static size_t mark_distance();
+  // Returns how many bytes (or bits) of the heap a single byte (or bit) of the
+  // mark bitmap corresponds to. This is the same as the mark distance above.
+  static size_t heap_map_factor() {
+    return mark_distance();
+  }
 
   CMBitMap() : CMBitMapRO(LogMinObjAlignment), _listener() { _listener.set_bitmap(this); }
 
@@ -671,9 +676,7 @@
   }
 
   // Attempts to steal an object from the task queues of other tasks
-  bool try_stealing(uint worker_id, int* hash_seed, oop& obj) {
-    return _task_queues->steal(worker_id, hash_seed, obj);
-  }
+  bool try_stealing(uint worker_id, int* hash_seed, oop& obj);
 
   ConcurrentMark(G1CollectedHeap* g1h,
                  G1RegionToSpaceMapper* prev_bitmap_storage,
@@ -1095,9 +1098,9 @@
   void regular_clock_call();
   bool concurrent() { return _concurrent; }
 
-  // Test whether objAddr might have already been passed over by the
+  // Test whether obj might have already been passed over by the
   // mark bitmap scan, and so needs to be pushed onto the mark stack.
-  bool is_below_finger(HeapWord* objAddr, HeapWord* global_finger) const;
+  bool is_below_finger(oop obj, HeapWord* global_finger) const;
 
   template<bool scan> void process_grey_object(oop obj);
 
@@ -1148,8 +1151,18 @@
 
   void set_cm_oop_closure(G1CMOopClosure* cm_oop_closure);
 
-  // It grays the object by marking it and, if necessary, pushing it
-  // on the local queue
+  // Increment the number of references this task has visited.
+  void increment_refs_reached() { ++_refs_reached; }
+
+  // Grey the object by marking it.  If not already marked, push it on
+  // the local queue if below the finger.
+  // Precondition: obj is in region.
+  // Precondition: obj is below region's NTAMS.
+  inline void make_reference_grey(oop obj, HeapRegion* region);
+
+  // Grey the object (by calling make_grey_reference) if required,
+  // e.g. obj is below its containing region's NTAMS.
+  // Precondition: obj is a valid heap object.
   inline void deal_with_reference(oop obj);
 
   // It scans an object and visits its children.
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -27,6 +27,7 @@
 
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // Utility routine to set an exclusive range of cards on the given
 // card liveness bitmap
@@ -259,15 +260,15 @@
              ++_local_pushes );
 }
 
-inline bool CMTask::is_below_finger(HeapWord* objAddr,
-                                    HeapWord* global_finger) const {
-  // If objAddr is above the global finger, then the mark bitmap scan
+inline bool CMTask::is_below_finger(oop obj, HeapWord* global_finger) const {
+  // If obj is above the global finger, then the mark bitmap scan
   // will find it later, and no push is needed.  Similarly, if we have
-  // a current region and objAddr is between the local finger and the
+  // a current region and obj is between the local finger and the
   // end of the current region, then no push is needed.  The tradeoff
   // of checking both vs only checking the global finger is that the
   // local check will be more accurate and so result in fewer pushes,
   // but may also be a little slower.
+  HeapWord* objAddr = (HeapWord*)obj;
   if (_finger != NULL) {
     // We have a current region.
 
@@ -277,7 +278,7 @@
     assert(_region_limit != NULL, "invariant");
     assert(_region_limit <= global_finger, "invariant");
 
-    // True if objAddr is less than the local finger, or is between
+    // True if obj is less than the local finger, or is between
     // the region limit and the global finger.
     if (objAddr < _finger) {
       return true;
@@ -289,13 +290,65 @@
   return objAddr < global_finger;
 }
 
+inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) {
+  if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) {
+
+    if (_cm->verbose_high()) {
+      gclog_or_tty->print_cr("[%u] marked object " PTR_FORMAT,
+                             _worker_id, p2i(obj));
+    }
+
+    // No OrderAccess:store_load() is needed. It is implicit in the
+    // CAS done in CMBitMap::parMark() call in the routine above.
+    HeapWord* global_finger = _cm->finger();
+
+    // We only need to push a newly grey object on the mark
+    // stack if it is in a section of memory the mark bitmap
+    // scan has already examined.  Mark bitmap scanning
+    // maintains progress "fingers" for determining that.
+    //
+    // Notice that the global finger might be moving forward
+    // concurrently. This is not a problem. In the worst case, we
+    // mark the object while it is above the global finger and, by
+    // the time we read the global finger, it has moved forward
+    // past this object. In this case, the object will probably
+    // be visited when a task is scanning the region and will also
+    // be pushed on the stack. So, some duplicate work, but no
+    // correctness problems.
+    if (is_below_finger(obj, global_finger)) {
+      if (obj->is_typeArray()) {
+        // Immediately process arrays of primitive types, rather
+        // than pushing on the mark stack.  This keeps us from
+        // adding humongous objects to the mark stack that might
+        // be reclaimed before the entry is processed - see
+        // selection of candidates for eager reclaim of humongous
+        // objects.  The cost of the additional type test is
+        // mitigated by avoiding a trip through the mark stack,
+        // by only doing a bookkeeping update and avoiding the
+        // actual scan of the object - a typeArray contains no
+        // references, and the metadata is built-in.
+        process_grey_object<false>(obj);
+      } else {
+        if (_cm->verbose_high()) {
+          gclog_or_tty->print_cr("[%u] below a finger (local: " PTR_FORMAT
+                                 ", global: " PTR_FORMAT ") pushing "
+                                 PTR_FORMAT " on mark stack",
+                                 _worker_id, p2i(_finger),
+                                 p2i(global_finger), p2i(obj));
+        }
+        push(obj);
+      }
+    }
+  }
+}
+
 inline void CMTask::deal_with_reference(oop obj) {
   if (_cm->verbose_high()) {
     gclog_or_tty->print_cr("[%u] we're dealing with reference = "PTR_FORMAT,
                            _worker_id, p2i((void*) obj));
   }
 
-  ++_refs_reached;
+  increment_refs_reached();
 
   HeapWord* objAddr = (HeapWord*) obj;
   assert(obj->is_oop_or_null(true /* ignore mark word */), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(obj)));
@@ -307,55 +360,7 @@
       // anything with it).
       HeapRegion* hr = _g1h->heap_region_containing_raw(obj);
       if (!hr->obj_allocated_since_next_marking(obj)) {
-        if (_cm->verbose_high()) {
-          gclog_or_tty->print_cr("[%u] "PTR_FORMAT" is not considered marked",
-                                 _worker_id, p2i((void*) obj));
-        }
-
-        // we need to mark it first
-        if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) {
-          // No OrderAccess:store_load() is needed. It is implicit in the
-          // CAS done in CMBitMap::parMark() call in the routine above.
-          HeapWord* global_finger = _cm->finger();
-
-          // We only need to push a newly grey object on the mark
-          // stack if it is in a section of memory the mark bitmap
-          // scan has already examined.  Mark bitmap scanning
-          // maintains progress "fingers" for determining that.
-          //
-          // Notice that the global finger might be moving forward
-          // concurrently. This is not a problem. In the worst case, we
-          // mark the object while it is above the global finger and, by
-          // the time we read the global finger, it has moved forward
-          // past this object. In this case, the object will probably
-          // be visited when a task is scanning the region and will also
-          // be pushed on the stack. So, some duplicate work, but no
-          // correctness problems.
-          if (is_below_finger(objAddr, global_finger)) {
-            if (obj->is_typeArray()) {
-              // Immediately process arrays of primitive types, rather
-              // than pushing on the mark stack.  This keeps us from
-              // adding humongous objects to the mark stack that might
-              // be reclaimed before the entry is processed - see
-              // selection of candidates for eager reclaim of humongous
-              // objects.  The cost of the additional type test is
-              // mitigated by avoiding a trip through the mark stack,
-              // by only doing a bookkeeping update and avoiding the
-              // actual scan of the object - a typeArray contains no
-              // references, and the metadata is built-in.
-              process_grey_object<false>(obj);
-            } else {
-              if (_cm->verbose_high()) {
-                gclog_or_tty->print_cr("[%u] below a finger (local: " PTR_FORMAT
-                                       ", global: " PTR_FORMAT ") pushing "
-                                       PTR_FORMAT " on mark stack",
-                                       _worker_id, p2i(_finger),
-                                       p2i(global_finger), p2i(objAddr));
-              }
-              push(obj);
-            }
-          }
-        }
+        make_reference_grey(obj, hr);
       }
     }
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
 
 #include "memory/allocation.hpp"
 
@@ -78,4 +78,4 @@
   uint   regions_freed()             { return _regions_freed; }
 };
 
-#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp	Thu May 07 11:28:03 2015 -0700
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1Allocator.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
@@ -119,7 +119,6 @@
   size_t gclab_word_size = _g1h->desired_plab_sz(dest);
   if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
     G1PLAB* alloc_buf = alloc_buffer(dest, context);
-    add_to_alloc_buffer_waste(alloc_buf->words_remaining());
     alloc_buf->retire();
 
     HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context);
@@ -153,8 +152,19 @@
   for (uint state = 0; state < InCSetState::Num; state++) {
     G1PLAB* const buf = _alloc_buffers[state];
     if (buf != NULL) {
-      add_to_alloc_buffer_waste(buf->words_remaining());
       buf->flush_and_retire_stats(_g1h->alloc_buffer_stats(state));
     }
   }
 }
+
+void G1DefaultParGCAllocator::waste(size_t& wasted, size_t& undo_wasted) {
+  wasted = 0;
+  undo_wasted = 0;
+  for (uint state = 0; state < InCSetState::Num; state++) {
+    G1PLAB * const buf = _alloc_buffers[state];
+    if (buf != NULL) {
+      wasted += buf->waste();
+      undo_wasted += buf->undo_waste();
+    }
+  }
+}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp	Thu May 07 11:28:03 2015 -0700
@@ -188,12 +188,6 @@
   // architectures have a special compare against zero instructions.
   const uint _survivor_alignment_bytes;
 
-  size_t _alloc_buffer_waste;
-  size_t _undo_waste;
-
-  void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
-  void add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
-
   virtual void retire_alloc_buffers() = 0;
   virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
 
@@ -213,15 +207,12 @@
 
 public:
   G1ParGCAllocator(G1CollectedHeap* g1h) :
-    _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()),
-    _alloc_buffer_waste(0), _undo_waste(0) {
-  }
+    _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { }
   virtual ~G1ParGCAllocator() { }
 
   static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h);
 
-  size_t alloc_buffer_waste() { return _alloc_buffer_waste; }
-  size_t undo_waste() {return _undo_waste; }
+  virtual void waste(size_t& wasted, size_t& undo_wasted) = 0;
 
   // Allocate word_sz words in dest, either directly into the regions or by
   // allocating a new PLAB. Returns the address of the allocated memory, NULL if
@@ -253,14 +244,7 @@
   }
 
   void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
-    if (alloc_buffer(dest, context)->contains(obj)) {
-      assert(alloc_buffer(dest, context)->contains(obj + word_sz - 1),
-             "should contain whole object");
-      alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
-    } else {
-      CollectedHeap::fill_with_object(obj, word_sz);
-      add_to_undo_waste(word_sz);
-    }
+    alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
   }
 };
 
@@ -280,7 +264,9 @@
     return _alloc_buffers[dest.value()];
   }
 
-  virtual void retire_alloc_buffers() ;
+  virtual void retire_alloc_buffers();
+
+  virtual void waste(size_t& wasted, size_t& undo_wasted);
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ALLOCATOR_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Thu May 07 11:28:03 2015 -0700
@@ -23,8 +23,8 @@
  */
 
 #include "precompiled.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.hpp"
 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "memory/space.hpp"
 #include "oops/oop.inline.hpp"
@@ -66,6 +66,20 @@
   return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
 }
 
+#ifdef ASSERT
+void G1BlockOffsetSharedArray::check_index(size_t index, const char* msg) const {
+  assert((index) < (_reserved.word_size() >> LogN_words),
+         err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT,
+                 msg, (index), (_reserved.word_size() >> LogN_words)));
+  assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)),
+         err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT
+                 " (%u) is not in committed area.",
+                 (index),
+                 p2i(address_for_index_raw(index)),
+                 G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
+}
+#endif // ASSERT
+
 //////////////////////////////////////////////////////////////////////
 // G1BlockOffsetArray
 //////////////////////////////////////////////////////////////////////
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Thu May 07 11:28:03 2015 -0700
@@ -170,6 +170,8 @@
 
   bool is_card_boundary(HeapWord* p) const;
 
+  void check_index(size_t index, const char* msg) const NOT_DEBUG_RETURN;
+
 public:
 
   // Return the number of slots needed for an offset array
@@ -179,6 +181,11 @@
     return ReservedSpace::allocation_align_size_up(number_of_slots);
   }
 
+  // Returns how many bytes of the heap a single byte of the BOT corresponds to.
+  static size_t heap_map_factor() {
+    return N_bytes;
+  }
+
   enum SomePublicConstants {
     LogN = 9,
     LogN_words = LogN - LogHeapWordSize,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
 
 #include "gc_implementation/g1/g1BlockOffsetTable.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "memory/space.hpp"
 
@@ -47,17 +46,6 @@
   }
 }
 
-#define check_index(index, msg)                                                \
-  assert((index) < (_reserved.word_size() >> LogN_words),                      \
-         err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, \
-                 msg, (index), (_reserved.word_size() >> LogN_words)));        \
-  assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)),   \
-         err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT             \
-                 " (%u) is not in committed area.",                            \
-                 (index),                                                      \
-                 p2i(address_for_index_raw(index)),                            \
-                 G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
-
 u_char G1BlockOffsetSharedArray::offset_array(size_t index) const {
   check_index(index, "index out of range");
   return _offset_array[index];
@@ -119,8 +107,6 @@
   return result;
 }
 
-#undef check_index
-
 inline size_t
 G1BlockOffsetArray::block_size(const HeapWord* p) const {
   return gsp()->block_size(p);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,17 @@
   _counts->clear_range(mr);
 }
 
+size_t G1CardCounts::compute_size(size_t mem_region_size_in_words) {
+  // We keep card counts for every card, so the size of the card counts table must
+  // be the same as the card table.
+  return G1SATBCardTableLoggingModRefBS::compute_size(mem_region_size_in_words);
+}
+
+size_t G1CardCounts::heap_map_factor() {
+  // See G1CardCounts::compute_size() why we reuse the card table value.
+  return G1SATBCardTableLoggingModRefBS::heap_map_factor();
+}
+
 void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) {
   if (has_count_table()) {
     assert(from_card_num < to_card_num,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp	Thu May 07 11:28:03 2015 -0700
@@ -101,6 +101,14 @@
  public:
   G1CardCounts(G1CollectedHeap* g1h);
 
+  // Return the number of slots needed for a card counts table
+  // that covers mem_region_words words.
+  static size_t compute_size(size_t mem_region_size_in_words);
+
+  // Returns how many bytes of the heap a single byte of the card counts table
+  // corresponds to.
+  static size_t heap_map_factor();
+
   void initialize(G1RegionToSpaceMapper* mapper);
 
   // Increments the refinement count for the given card.
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu May 07 11:28:03 2015 -0700
@@ -66,6 +66,7 @@
 #include "runtime/vmThread.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
 
@@ -1083,11 +1084,9 @@
 class RebuildRSOutOfRegionClosure: public HeapRegionClosure {
   G1CollectedHeap*   _g1h;
   UpdateRSOopClosure _cl;
-  int                _worker_i;
 public:
-  RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, int worker_i = 0) :
+  RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, uint worker_i = 0) :
     _cl(g1->g1_rem_set(), worker_i),
-    _worker_i(worker_i),
     _g1h(g1)
   { }
 
@@ -1166,6 +1165,7 @@
   SvcGCMarker sgcm(SvcGCMarker::FULL);
   ResourceMark rm;
 
+  G1Log::update_level();
   print_heap_before_gc();
   trace_heap_before_gc(gc_tracer);
 
@@ -1890,24 +1890,24 @@
   G1RegionToSpaceMapper* bot_storage =
     create_aux_memory_mapper("Block offset table",
                              G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize),
-                             G1BlockOffsetSharedArray::N_bytes);
+                             G1BlockOffsetSharedArray::heap_map_factor());
 
   ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize));
   G1RegionToSpaceMapper* cardtable_storage =
     create_aux_memory_mapper("Card table",
                              G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize),
-                             G1BlockOffsetSharedArray::N_bytes);
+                             G1SATBCardTableLoggingModRefBS::heap_map_factor());
 
   G1RegionToSpaceMapper* card_counts_storage =
     create_aux_memory_mapper("Card counts table",
-                             G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize),
-                             G1BlockOffsetSharedArray::N_bytes);
+                             G1CardCounts::compute_size(g1_rs.size() / HeapWordSize),
+                             G1CardCounts::heap_map_factor());
 
   size_t bitmap_size = CMBitMap::compute_size(g1_rs.size());
   G1RegionToSpaceMapper* prev_bitmap_storage =
-    create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::mark_distance());
+    create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::heap_map_factor());
   G1RegionToSpaceMapper* next_bitmap_storage =
-    create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::mark_distance());
+    create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::heap_map_factor());
 
   _hrm.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage);
   g1_barrier_set()->initialize(cardtable_storage);
@@ -3039,7 +3039,7 @@
       assert(UseDynamicNumberOfGCThreads ||
         workers()->active_workers() == workers()->total_workers(),
         "If not dynamic should be using all the workers");
-      int n_workers = workers()->active_workers();
+      uint n_workers = workers()->active_workers();
       set_par_threads(n_workers);
       workers()->run_task(&task);
       set_par_threads(0);
@@ -3577,9 +3577,9 @@
   print_taskqueue_stats_hdr(st);
 
   TaskQueueStats totals;
-  const int n = workers()->total_workers();
-  for (int i = 0; i < n; ++i) {
-    st->print("%3d ", i); task_queue(i)->stats.print(st); st->cr();
+  const uint n = workers()->total_workers();
+  for (uint i = 0; i < n; ++i) {
+    st->print("%3u ", i); task_queue(i)->stats.print(st); st->cr();
     totals += task_queue(i)->stats;
   }
   st->print_raw("tot "); totals.print(st); st->cr();
@@ -3588,8 +3588,8 @@
 }
 
 void G1CollectedHeap::reset_taskqueue_stats() {
-  const int n = workers()->total_workers();
-  for (int i = 0; i < n; ++i) {
+  const uint n = workers()->total_workers();
+  for (uint i = 0; i < n; ++i) {
     task_queue(i)->stats.reset();
   }
 }
@@ -3648,6 +3648,7 @@
   SvcGCMarker sgcm(SvcGCMarker::MINOR);
   ResourceMark rm;
 
+  G1Log::update_level();
   print_heap_before_gc();
   trace_heap_before_gc(_gc_tracer_stw);
 
@@ -4318,7 +4319,7 @@
 
   ParallelTaskTerminator* terminator() { return &_terminator; }
 
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     _root_processor->set_num_workers(active_workers);
     terminator()->reset_for_reuse(active_workers);
     _n_workers = active_workers;
@@ -4997,13 +4998,13 @@
   G1CollectedHeap*   _g1h;
   RefToScanQueueSet* _queues;
   FlexibleWorkGang*  _workers;
-  int                _active_workers;
+  uint               _active_workers;
 
 public:
   G1STWRefProcTaskExecutor(G1CollectedHeap* g1h,
-                        FlexibleWorkGang* workers,
-                        RefToScanQueueSet *task_queues,
-                        int n_workers) :
+                           FlexibleWorkGang* workers,
+                           RefToScanQueueSet *task_queues,
+                           uint n_workers) :
     _g1h(g1h),
     _queues(task_queues),
     _workers(workers),
@@ -5136,7 +5137,7 @@
   uint _n_workers;
 
 public:
-  G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h,int workers, RefToScanQueueSet *task_queues) :
+  G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, uint workers, RefToScanQueueSet *task_queues) :
     AbstractGangTask("ParPreserveCMReferents"),
     _g1h(g1h),
     _queues(task_queues),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu May 07 11:28:03 2015 -0700
@@ -979,7 +979,7 @@
 
   void set_refine_cte_cl_concurrency(bool concurrent);
 
-  RefToScanQueue *task_queue(int i) const;
+  RefToScanQueue *task_queue(uint i) const;
 
   // A set of cards where updates happened during the GC
   DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -210,7 +210,7 @@
   g1_barrier_set()->g1_mark_as_young(mr);
 }
 
-inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
+inline RefToScanQueue* G1CollectedHeap::task_queue(uint i) const {
   return _task_queues->queue(i);
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Thu May 07 11:28:03 2015 -0700
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
 
 #include "memory/allocation.hpp"
 
@@ -286,4 +286,4 @@
   ~G1GCParPhaseTimesTracker();
 };
 
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Log.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Log.cpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,34 @@
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1_globals.hpp"
 #include "gc_implementation/g1/g1Log.hpp"
-#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
 
 G1Log::LogLevel G1Log::_level = G1Log::LevelNone;
 
+
+// Updates _level based on PrintGC and PrintGCDetails values (unless
+// G1LogLevel is set explicitly)
+// - PrintGC maps to "fine".
+// - PrintGCDetails maps to "finer".
+void G1Log::update_level() {
+  if (FLAG_IS_DEFAULT(G1LogLevel)) {
+    _level = LevelNone;
+    if (PrintGCDetails) {
+      _level = LevelFiner;
+    } else if (PrintGC) {
+      _level = LevelFine;
+    }
+  }
+}
+
+
 // If G1LogLevel has not been set up we will use the values of PrintGC
 // and PrintGCDetails for the logging level.
-// - PrintGC maps to "fine".
-// - PrintGCDetails maps to "finer".
 void G1Log::init() {
-  if (G1LogLevel != NULL && G1LogLevel[0] != '\0') {
-    if (strncmp("none", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
+  if (!FLAG_IS_DEFAULT(G1LogLevel)) {
+    // PrintGC flags change won't have any affect, because G1LogLevel
+    // is set explicitly
+    if (G1LogLevel[0] == '\0' || strncmp("none", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
       _level = LevelNone;
     } else if (strncmp("fine", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
       _level = LevelFine;
@@ -47,10 +64,7 @@
       warning("Unknown logging level '%s', should be one of 'fine', 'finer' or 'finest'.", G1LogLevel);
     }
   } else {
-    if (PrintGCDetails) {
-      _level = LevelFiner;
-    } else if (PrintGC) {
-      _level = LevelFine;
-    }
+    update_level();
   }
 }
+
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Log.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Log.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,9 @@
   }
 
   static void init();
+
+  // Update to log level to reflect runtime changes to manageable flags
+  static void update_level();
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1LOG_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,9 +76,6 @@
 }
 
 void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) {
-  double longest_allowed = longest_pause_internal(start);
-  if (longest_allowed < 0.0)
-    longest_allowed = 0.0;
   double duration = end - start;
 
   remove_expired_entries(end);
@@ -111,41 +108,6 @@
 // this is for trying things out in the future and a couple
 // of other places (debugging)
 
-double G1MMUTrackerQueue::longest_pause(double current_time) {
-  if (_DISABLE_MMU)
-    return _max_gc_time;
-
-  MutexLockerEx x(MMUTracker_lock, Mutex::_no_safepoint_check_flag);
-  remove_expired_entries(current_time);
-
-  return longest_pause_internal(current_time);
-}
-
-double G1MMUTrackerQueue::longest_pause_internal(double current_time) {
-  double target_time = _max_gc_time;
-
-  while( 1 ) {
-    double gc_time =
-      calculate_gc_time(current_time + target_time);
-    double diff = target_time + gc_time - _max_gc_time;
-    if (!is_double_leq_0(diff)) {
-      target_time -= diff;
-      if (is_double_leq_0(target_time)) {
-        target_time = -1.0;
-        break;
-      }
-    } else {
-      break;
-    }
-  }
-
-  return target_time;
-}
-
-// basically the _internal call does not remove expired entries
-// this is for trying things out in the future and a couple
-// of other places (debugging)
-
 double G1MMUTrackerQueue::when_sec(double current_time, double pause_time) {
   if (_DISABLE_MMU)
     return 0.0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,6 @@
   G1MMUTracker(double time_slice, double max_gc_time);
 
   virtual void add_pause(double start, double end, bool gc_thread) = 0;
-  virtual double longest_pause(double current_time) = 0;
   virtual double when_sec(double current_time, double pause_time) = 0;
 
   double max_gc_time() {
@@ -122,7 +121,6 @@
   void remove_expired_entries(double current_time);
   double calculate_gc_time(double current_time);
 
-  double longest_pause_internal(double current_time);
   double when_internal(double current_time, double pause_time);
 
 public:
@@ -130,7 +128,6 @@
 
   virtual void add_pause(double start, double end, bool gc_thread);
 
-  virtual double longest_pause(double current_time);
   virtual double when_sec(double current_time, double pause_time);
 };
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp	Thu May 07 11:28:03 2015 -0700
@@ -29,7 +29,7 @@
 #include "gc_implementation/g1/g1StringDedup.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
   : _g1h(g1h),
@@ -95,8 +95,9 @@
   const double elapsed_ms = elapsed_time() * 1000.0;
   const double s_roots_ms = strong_roots_time() * 1000.0;
   const double term_ms    = term_time() * 1000.0;
-  const size_t alloc_buffer_waste = _g1_par_allocator->alloc_buffer_waste();
-  const size_t undo_waste         = _g1_par_allocator->undo_waste();
+  size_t alloc_buffer_waste = 0;
+  size_t undo_waste = 0;
+  _g1_par_allocator->waste(alloc_buffer_waste, undo_waste);
   st->print_cr("%3d %9.2f %9.2f %6.2f "
                "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
                SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,9 +54,6 @@
   uint              _tenuring_threshold;
   G1ParScanClosure  _scanner;
 
-  size_t            _alloc_buffer_waste;
-  size_t            _undo_waste;
-
   OopsInHeapRegionClosure*      _evac_failure_cl;
 
   int  _hash_seed;
@@ -78,9 +75,6 @@
 
 #define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
 
-  void   add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
-  void   add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
-
   DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
   G1SATBCardTableModRefBS* ctbs()                { return _ct_bs; }
 
@@ -106,10 +100,7 @@
   bool verify_task(StarTask ref) const;
 #endif // ASSERT
 
-  template <class T> void push_on_queue(T* ref) {
-    assert(verify_ref(ref), "sanity");
-    _refs->push(ref);
-  }
+  template <class T> void push_on_queue(T* ref);
 
   template <class T> void update_rs(HeapRegion* from, T* p, uint tid) {
     // If the new value of the field points to the same region or
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -59,6 +59,11 @@
   update_rs(from, p, queue_num());
 }
 
+template <class T> inline void G1ParScanThreadState::push_on_queue(T* ref) {
+  assert(verify_ref(ref), "sanity");
+  _refs->push(ref);
+}
+
 inline void G1ParScanThreadState::do_oop_partial_array(oop* p) {
   assert(has_partial_array_mask(p), "invariant");
   oop from_obj = clear_partial_array_mask(p);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp	Thu May 07 11:28:03 2015 -0700
@@ -329,6 +329,6 @@
   _g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
 }
 
-void G1RootProcessor::set_num_workers(int active_workers) {
+void G1RootProcessor::set_num_workers(uint active_workers) {
   _process_strong_tasks->set_n_threads(active_workers);
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp	Thu May 07 11:28:03 2015 -0700
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
 
 #include "memory/allocation.hpp"
 #include "memory/strongRootsScope.hpp"
@@ -115,7 +115,7 @@
                             uint worker_i);
 
   // Inform the root processor about the number of worker threads
-  void set_num_workers(int active_workers);
+  void set_num_workers(uint active_workers);
 };
 
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Thu May 07 11:28:03 2015 -0700
@@ -153,6 +153,11 @@
     return ReservedSpace::allocation_align_size_up(number_of_slots);
   }
 
+  // Returns how many bytes of the heap a single byte of the Card Table corresponds to.
+  static size_t heap_map_factor() {
+    return CardTableModRefBS::card_size;
+  }
+
   G1SATBCardTableLoggingModRefBS(MemRegion whole_heap);
 
   virtual void initialize() { }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionBounds.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionBounds.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,9 @@
  *
  */
 
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
+
 #include "gc_implementation/g1/heapRegionBounds.hpp"
 
 size_t HeapRegionBounds::min_size() {
@@ -35,3 +38,5 @@
 size_t HeapRegionBounds::target_number() {
   return TARGET_REGION_NUMBER;
 }
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Thu May 07 11:28:03 2015 -0700
@@ -29,6 +29,7 @@
 #include "memory/allocation.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 
@@ -160,10 +161,7 @@
   assert(_lock == NULL || _lock->owned_by_self(),
          "we should have taken the lock before calling this");
 
-  // Even if G1SATBBufferEnqueueingThresholdPercent == 0 we have to
-  // filter the buffer given that this will remove any references into
-  // the CSet as we currently assume that no such refs will appear in
-  // enqueued buffers.
+  // If G1SATBBufferEnqueueingThresholdPercent == 0 we could skip filtering.
 
   // This method should only be called if there is a non-NULL buffer
   // that is full.
@@ -180,25 +178,19 @@
   return should_enqueue;
 }
 
-void ObjPtrQueue::apply_closure_and_empty(ObjectClosure* cl) {
+void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
+  assert(SafepointSynchronize::is_at_safepoint(),
+         "SATB queues must only be processed at safepoints");
   if (_buf != NULL) {
-    apply_closure_to_buffer(cl, _buf, _index, _sz);
+    assert(_index % sizeof(void*) == 0, "invariant");
+    assert(_sz % sizeof(void*) == 0, "invariant");
+    assert(_index <= _sz, "invariant");
+    cl->do_buffer(_buf + byte_index_to_index((int)_index),
+                  byte_index_to_index((int)(_sz - _index)));
     _index = _sz;
   }
 }
 
-void ObjPtrQueue::apply_closure_to_buffer(ObjectClosure* cl,
-                                          void** buf, size_t index, size_t sz) {
-  if (cl == NULL) return;
-  for (size_t i = index; i < sz; i += oopSize) {
-    oop obj = (oop)buf[byte_index_to_index((int)i)];
-    // There can be NULL entries because of destructors.
-    if (obj != NULL) {
-      cl->do_object(obj);
-    }
-  }
-}
-
 #ifndef PRODUCT
 // Helpful for debugging
 
@@ -289,7 +281,7 @@
   shared_satb_queue()->filter();
 }
 
-bool SATBMarkQueueSet::apply_closure_to_completed_buffer(ObjectClosure* cl) {
+bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
   BufferNode* nd = NULL;
   {
     MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
@@ -303,7 +295,18 @@
   }
   if (nd != NULL) {
     void **buf = BufferNode::make_buffer_from_node(nd);
-    ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz);
+    // Skip over NULL entries at beginning (e.g. push end) of buffer.
+    // Filtering can result in non-full completed buffers; see
+    // should_enqueue_buffer.
+    assert(_sz % sizeof(void*) == 0, "invariant");
+    size_t limit = ObjPtrQueue::byte_index_to_index((int)_sz);
+    for (size_t i = 0; i < limit; ++i) {
+      if (buf[i] != NULL) {
+        // Found the end of the block of NULLs; process the remainder.
+        cl->do_buffer(buf + i, limit - i);
+        break;
+      }
+    }
     deallocate_buffer(buf);
     return true;
   } else {
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Thu May 07 11:28:03 2015 -0700
@@ -25,29 +25,30 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_SATBQUEUE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_SATBQUEUE_HPP
 
+#include "memory/allocation.hpp"
 #include "gc_implementation/g1/ptrQueue.hpp"
 
-class ObjectClosure;
 class JavaThread;
 class SATBMarkQueueSet;
 
+// Base class for processing the contents of a SATB buffer.
+class SATBBufferClosure : public StackObj {
+protected:
+  ~SATBBufferClosure() { }
+
+public:
+  // Process the SATB entries in the designated buffer range.
+  virtual void do_buffer(void** buffer, size_t size) = 0;
+};
+
 // A ptrQueue whose elements are "oops", pointers to object heads.
 class ObjPtrQueue: public PtrQueue {
-  friend class Threads;
   friend class SATBMarkQueueSet;
-  friend class G1RemarkThreadsClosure;
 
 private:
   // Filter out unwanted entries from the buffer.
   void filter();
 
-  // Apply the closure to all elements and empty the buffer;
-  void apply_closure_and_empty(ObjectClosure* cl);
-
-  // Apply the closure to all elements of "buf", down to "index" (inclusive.)
-  static void apply_closure_to_buffer(ObjectClosure* cl,
-                                      void** buf, size_t index, size_t sz);
-
 public:
   ObjPtrQueue(PtrQueueSet* qset, bool perm = false) :
     // SATB queues are only active during marking cycles. We create
@@ -60,6 +61,10 @@
   // Process queue entries and free resources.
   void flush();
 
+  // Apply cl to the active part of the buffer.
+  // Prerequisite: Must be at a safepoint.
+  void apply_closure_and_empty(SATBBufferClosure* cl);
+
   // Overrides PtrQueue::should_enqueue_buffer(). See the method's
   // definition for more information.
   virtual bool should_enqueue_buffer();
@@ -97,10 +102,12 @@
   // Filter all the currently-active SATB buffers.
   void filter_thread_buffers();
 
-  // If there exists some completed buffer, pop it, then apply the
-  // closure to all its elements, and return true.  If no
-  // completed buffers exist, return false.
-  bool apply_closure_to_completed_buffer(ObjectClosure* closure);
+  // If there exists some completed buffer, pop and process it, and
+  // return true.  Otherwise return false.  Processing a buffer
+  // consists of applying the closure to the buffer range starting
+  // with the first non-NULL entry to the end of the buffer; the
+  // leading entries may be NULL due to filtering.
+  bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
 
 #ifndef PRODUCT
   // Helpful for debugging
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Thu May 07 11:28:03 2015 -0700
@@ -54,6 +54,7 @@
 #include "utilities/copy.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 #include "utilities/workgroup.hpp"
 
 #ifdef _MSC_VER
@@ -272,16 +273,8 @@
 }
 
 
-void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
-                                                size_t word_sz) {
-  // Is the alloc in the current alloc buffer?
-  if (to_space_alloc_buffer()->contains(obj)) {
-    assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
-           "Should contain whole object.");
-    to_space_alloc_buffer()->undo_allocation(obj, word_sz);
-  } else {
-    CollectedHeap::fill_with_object(obj, word_sz);
-  }
+void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, size_t word_sz) {
+  to_space_alloc_buffer()->undo_allocation(obj, word_sz);
 }
 
 void ParScanThreadState::print_promotion_failure_size() {
@@ -308,7 +301,7 @@
   inline ParScanThreadState& thread_state(int i);
 
   void trace_promotion_failed(const YoungGCTracer* gc_tracer);
-  void reset(int active_workers, bool promotion_failed);
+  void reset(uint active_workers, bool promotion_failed);
   void flush();
 
   #if TASKQUEUE_STATS
@@ -365,7 +358,7 @@
   }
 }
 
-void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
+void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed)
 {
   _term.reset_for_reuse(active_threads);
   if (promotion_failed) {
@@ -583,7 +576,7 @@
 
 // Reset the terminator for the given number of
 // active threads.
-void ParNewGenTask::set_for_termination(int active_workers) {
+void ParNewGenTask::set_for_termination(uint active_workers) {
   _state_set->reset(active_workers, _gen->promotion_failed());
   // Should the heap be passed in?  There's only 1 for now so
   // grab it instead.
@@ -766,7 +759,7 @@
 
 private:
   virtual void work(uint worker_id);
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     _state_set.terminator()->reset_for_reuse(active_workers);
   }
 private:
@@ -912,10 +905,10 @@
   AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
   FlexibleWorkGang* workers = gch->workers();
   assert(workers != NULL, "Need workgang for parallel work");
-  int active_workers =
-      AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
-                                   workers->active_workers(),
-                                   Threads::number_of_non_daemon_threads());
+  uint active_workers =
+       AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
+                                               workers->active_workers(),
+                                               Threads::number_of_non_daemon_threads());
   workers->set_active_workers(active_workers);
   _old_gen = gch->old_gen();
 
@@ -947,7 +940,7 @@
 
   gch->save_marks();
   assert(workers != NULL, "Need parallel worker threads.");
-  int n_workers = active_workers;
+  uint n_workers = active_workers;
 
   // Set the correct parallelism (number of queues) in the reference processor
   ref_processor()->set_active_mt_degree(n_workers);
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Thu May 07 11:28:03 2015 -0700
@@ -250,7 +250,7 @@
 
   // Reset the terminator in ParScanThreadStateSet for
   // "active_workers" threads.
-  virtual void set_for_termination(int active_workers);
+  virtual void set_for_termination(uint active_workers);
 };
 
 class KeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Thu May 07 11:28:03 2015 -0700
@@ -57,7 +57,7 @@
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
 
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
   CLDToOopClosure mark_and_push_from_clds(&mark_and_push_closure, true);
   MarkingCodeBlobClosure mark_and_push_in_blobs(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
 
@@ -85,8 +85,8 @@
     PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
 
   switch (_root_type) {
     case universe:
@@ -156,8 +156,8 @@
     PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
   _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
                 mark_and_push_closure, follow_stack_closure);
 }
@@ -213,7 +213,7 @@
 
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
 
   oop obj = NULL;
   ObjArrayTask task;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Thu May 07 11:28:03 2015 -0700
@@ -37,7 +37,7 @@
 #include "oops/objArrayKlass.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 PSOldGen*            ParCompactionManager::_old_gen = NULL;
 ParCompactionManager**  ParCompactionManager::_manager_array = NULL;
@@ -179,11 +179,11 @@
 void InstanceKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
   assert(obj != NULL, "can't follow the content of NULL object");
 
-  PSParallelCompact::follow_klass(cm, this);
+  cm->follow_klass(this);
   // Only mark the header and let the scan of the meta-data mark
   // everything else.
 
-  PSParallelCompact::MarkAndPushClosure cl(cm);
+  ParCompactionManager::MarkAndPushClosure cl(cm);
   InstanceKlass::oop_oop_iterate_oop_maps<true>(obj, &cl);
 }
 
@@ -201,9 +201,9 @@
     // the call to follow_class_loader is made when the class loader itself
     // is handled.
     if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
-      PSParallelCompact::follow_class_loader(cm, klass->class_loader_data());
+      cm->follow_class_loader(klass->class_loader_data());
     } else {
-      PSParallelCompact::follow_klass(cm, klass);
+      cm->follow_klass(klass);
     }
   } else {
     // If klass is NULL then this a mirror for a primitive type.
@@ -212,7 +212,7 @@
     assert(java_lang_Class::is_primitive(obj), "Sanity check");
   }
 
-  PSParallelCompact::MarkAndPushClosure cl(cm);
+  ParCompactionManager::MarkAndPushClosure cl(cm);
   oop_oop_iterate_statics<true>(obj, &cl);
 }
 
@@ -221,7 +221,7 @@
 
   ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
   if (loader_data != NULL) {
-    PSParallelCompact::follow_class_loader(cm, loader_data);
+    cm->follow_class_loader(loader_data);
   }
 }
 
@@ -253,37 +253,24 @@
           gclog_or_tty->print_cr("       Non NULL normal " PTR_FORMAT, p2i(obj));
         }
       )
-      PSParallelCompact::mark_and_push(cm, referent_addr);
+      cm->mark_and_push(referent_addr);
     }
   }
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    // Treat discovered as normal oop, if ref is not "active",
-    // i.e. if next is non-NULL.
-    T  next_oop = oopDesc::load_heap_oop(next_addr);
-    if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
-      T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(discovered_addr));
-        }
-      )
-      PSParallelCompact::mark_and_push(cm, discovered_addr);
-    }
-  } else {
-#ifdef ASSERT
-    // In the case of older JDKs which do not use the discovered
-    // field for the pending list, an inactive ref (next != NULL)
-    // must always have a NULL discovered field.
-    T next = oopDesc::load_heap_oop(next_addr);
-    oop discovered = java_lang_ref_Reference::discovered(obj);
-    assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
-           err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
-                   p2i(obj)));
-#endif
+  // Treat discovered as normal oop, if ref is not "active",
+  // i.e. if next is non-NULL.
+  T  next_oop = oopDesc::load_heap_oop(next_addr);
+  if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+    T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+    debug_only(
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(discovered_addr));
+      }
+    )
+    cm->mark_and_push(discovered_addr);
   }
-  PSParallelCompact::mark_and_push(cm, next_addr);
+  cm->mark_and_push(next_addr);
   klass->InstanceKlass::oop_pc_follow_contents(obj, cm);
 }
 
@@ -297,7 +284,7 @@
 }
 
 void ObjArrayKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
-  PSParallelCompact::follow_klass(cm, this);
+  cm->follow_klass(this);
 
   if (UseCompressedOops) {
     oop_pc_follow_contents_specialized<narrowOop>(objArrayOop(obj), 0, cm);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Thu May 07 11:28:03 2015 -0700
@@ -29,11 +29,6 @@
 #include "utilities/stack.hpp"
 #include "utilities/taskqueue.hpp"
 
-// Move to some global location
-#define HAS_BEEN_MOVED 0x1501d01d
-// End move to some global location
-
-
 class MutableSpace;
 class PSOldGen;
 class ParCompactionManager;
@@ -170,24 +165,23 @@
   bool should_copy();
 
   // Save for later processing.  Must not fail.
-  inline void push(oop obj) { _marking_stack.push(obj); }
+  inline void push(oop obj);
   inline void push_objarray(oop objarray, size_t index);
   inline void push_region(size_t index);
 
+  // Check mark and maybe push on marking stack.
+  template <typename T> inline void mark_and_push(T* p);
+
+  inline void follow_klass(Klass* klass);
+
+  void follow_class_loader(ClassLoaderData* klass);
+
   // Access function for compaction managers
   static ParCompactionManager* gc_thread_compaction_manager(int index);
 
-  static bool steal(int queue_num, int* seed, oop& t) {
-    return stack_array()->steal(queue_num, seed, t);
-  }
-
-  static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t) {
-    return _objarray_queues->steal(queue_num, seed, t);
-  }
-
-  static bool steal(int queue_num, int* seed, size_t& region) {
-    return region_array()->steal(queue_num, seed, region);
-  }
+  static bool steal(int queue_num, int* seed, oop& t);
+  static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t);
+  static bool steal(int queue_num, int* seed, size_t& region);
 
   // Process tasks remaining on any marking stack
   void follow_marking_stacks();
@@ -200,6 +194,39 @@
   void follow_contents(objArrayOop array, int index);
 
   void update_contents(oop obj);
+
+  class MarkAndPushClosure: public ExtendedOopClosure {
+   private:
+    ParCompactionManager* _compaction_manager;
+   public:
+    MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
+
+    template <typename T> void do_oop_nv(T* p);
+    virtual void do_oop(oop* p);
+    virtual void do_oop(narrowOop* p);
+
+    // This closure provides its own oop verification code.
+    debug_only(virtual bool should_verify_oops() { return false; })
+  };
+
+  class FollowStackClosure: public VoidClosure {
+   private:
+    ParCompactionManager* _compaction_manager;
+   public:
+    FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
+    virtual void do_void();
+  };
+
+  // The one and only place to start following the classes.
+  // Should only be applied to the ClassLoaderData klasses list.
+  class FollowKlassClosure : public KlassClosure {
+   private:
+    MarkAndPushClosure* _mark_and_push_closure;
+   public:
+    FollowKlassClosure(MarkAndPushClosure* mark_and_push_closure) :
+        _mark_and_push_closure(mark_and_push_closure) { }
+    void do_klass(Klass* klass);
+  };
 };
 
 inline ParCompactionManager* ParCompactionManager::manager_array(int index) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -31,6 +31,23 @@
 #include "oops/oop.inline.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/globalDefinitions.hpp"
+#include "utilities/taskqueue.inline.hpp"
+
+inline bool ParCompactionManager::steal(int queue_num, int* seed, oop& t) {
+  return stack_array()->steal(queue_num, seed, t);
+}
+
+inline bool ParCompactionManager::steal_objarray(int queue_num, int* seed, ObjArrayTask& t) {
+  return _objarray_queues->steal(queue_num, seed, t);
+}
+
+inline bool ParCompactionManager::steal(int queue_num, int* seed, size_t& region) {
+  return region_array()->steal(queue_num, seed, region);
+}
+
+inline void ParCompactionManager::push(oop obj) {
+  _marking_stack.push(obj);
+}
 
 void ParCompactionManager::push_objarray(oop obj, size_t index)
 {
@@ -50,6 +67,47 @@
   region_stack()->push(index);
 }
 
+template <typename T>
+inline void ParCompactionManager::mark_and_push(T* p) {
+  T heap_oop = oopDesc::load_heap_oop(p);
+  if (!oopDesc::is_null(heap_oop)) {
+    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+    assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap");
+
+    if (mark_bitmap()->is_unmarked(obj) && PSParallelCompact::mark_obj(obj)) {
+      push(obj);
+    }
+  }
+}
+
+template <typename T>
+inline void ParCompactionManager::MarkAndPushClosure::do_oop_nv(T* p) {
+  _compaction_manager->mark_and_push(p);
+}
+
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(oop* p)       { do_oop_nv(p); }
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+
+inline void ParCompactionManager::follow_klass(Klass* klass) {
+  oop holder = klass->klass_holder();
+  mark_and_push(&holder);
+}
+
+inline void ParCompactionManager::FollowStackClosure::do_void() {
+  _compaction_manager->follow_marking_stacks();
+}
+
+inline void ParCompactionManager::FollowKlassClosure::do_klass(Klass* klass) {
+  klass->oops_do(_mark_and_push_closure);
+}
+
+inline void ParCompactionManager::follow_class_loader(ClassLoaderData* cld) {
+  MarkAndPushClosure mark_and_push_closure(this);
+  FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
+
+  cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
+}
+
 inline void ParCompactionManager::follow_contents(oop obj) {
   assert(PSParallelCompact::mark_bitmap()->is_marked(obj), "should be marked");
   obj->pc_follow_contents(this);
@@ -69,7 +127,7 @@
 
   // Push the non-NULL elements of the next stride on the marking stack.
   for (T* e = beg; e < end; e++) {
-    PSParallelCompact::mark_and_push<T>(cm, e);
+    cm->mark_and_push<T>(e);
   }
 
   if (end_index < len) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Thu May 07 11:28:03 2015 -0700
@@ -108,7 +108,6 @@
 bool      PSParallelCompact::_print_phases = false;
 
 ReferenceProcessor* PSParallelCompact::_ref_processor = NULL;
-Klass*              PSParallelCompact::_updated_int_array_klass_obj = NULL;
 
 double PSParallelCompact::_dwl_mean;
 double PSParallelCompact::_dwl_std_dev;
@@ -820,17 +819,9 @@
 
 bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); }
 
-void PSParallelCompact::KeepAliveClosure::do_oop(oop* p)       { PSParallelCompact::KeepAliveClosure::do_oop_work(p); }
-void PSParallelCompact::KeepAliveClosure::do_oop(narrowOop* p) { PSParallelCompact::KeepAliveClosure::do_oop_work(p); }
-
 PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_pointer_closure;
 PSParallelCompact::AdjustKlassClosure PSParallelCompact::_adjust_klass_closure;
 
-void PSParallelCompact::FollowStackClosure::do_void() { _compaction_manager->follow_marking_stacks(); }
-
-void PSParallelCompact::FollowKlassClosure::do_klass(Klass* klass) {
-  klass->oops_do(_mark_and_push_closure);
-}
 void PSParallelCompact::AdjustKlassClosure::do_klass(Klass* klass) {
   klass->oops_do(&PSParallelCompact::_adjust_pointer_closure);
 }
@@ -2350,8 +2341,8 @@
   TaskQueueSetSuper* qset = ParCompactionManager::region_array();
   ParallelTaskTerminator terminator(active_gc_threads, qset);
 
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
 
   // Need new claim bits before marking starts.
   ClassLoaderDataGraph::clear_claimed_marks();
@@ -2425,14 +2416,6 @@
   _gc_tracer.report_object_count_after_gc(is_alive_closure());
 }
 
-void PSParallelCompact::follow_class_loader(ParCompactionManager* cm,
-                                            ClassLoaderData* cld) {
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
-
-  cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
-}
-
 // This should be moved to the shared markSweep code!
 class PSAlwaysTrueClosure: public BoolObjectClosure {
 public:
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Thu May 07 11:28:03 2015 -0700
@@ -28,7 +28,6 @@
 #include "gc_implementation/parallelScavenge/objectStartArray.hpp"
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
 #include "gc_implementation/parallelScavenge/parMarkBitMap.hpp"
-#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
 #include "gc_implementation/shared/collectorCounters.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
 #include "gc_interface/collectedHeap.hpp"
@@ -933,25 +932,6 @@
     virtual bool do_object_b(oop p);
   };
 
-  class KeepAliveClosure: public OopClosure {
-   private:
-    ParCompactionManager* _compaction_manager;
-   protected:
-    template <class T> inline void do_oop_work(T* p);
-   public:
-    KeepAliveClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
-    virtual void do_oop(oop* p);
-    virtual void do_oop(narrowOop* p);
-  };
-
-  class FollowStackClosure: public VoidClosure {
-   private:
-    ParCompactionManager* _compaction_manager;
-   public:
-    FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
-    virtual void do_void();
-  };
-
   class AdjustPointerClosure: public ExtendedOopClosure {
    public:
     template <typename T> void do_oop_nv(T* p);
@@ -967,12 +947,8 @@
     void do_klass(Klass* klass);
   };
 
-  friend class KeepAliveClosure;
-  friend class FollowStackClosure;
   friend class AdjustPointerClosure;
   friend class AdjustKlassClosure;
-  friend class FollowKlassClosure;
-  friend class InstanceClassLoaderKlass;
   friend class RefProcTaskProxy;
 
  private:
@@ -994,9 +970,6 @@
   // Reference processing (used in ...follow_contents)
   static ReferenceProcessor*  _ref_processor;
 
-  // Updated location of intArrayKlassObj.
-  static Klass* _updated_int_array_klass_obj;
-
   // Values computed at initialization and used by dead_wood_limiter().
   static double _dwl_mean;
   static double _dwl_std_dev;
@@ -1142,30 +1115,6 @@
   static void reset_millis_since_last_gc();
 
  public:
-  class MarkAndPushClosure: public ExtendedOopClosure {
-   private:
-    ParCompactionManager* _compaction_manager;
-   public:
-    MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
-
-    template <typename T> void do_oop_nv(T* p);
-    virtual void do_oop(oop* p);
-    virtual void do_oop(narrowOop* p);
-
-    // This closure provides its own oop verification code.
-    debug_only(virtual bool should_verify_oops() { return false; })
-  };
-
-  // The one and only place to start following the classes.
-  // Should only be applied to the ClassLoaderData klasses list.
-  class FollowKlassClosure : public KlassClosure {
-   private:
-    MarkAndPushClosure* _mark_and_push_closure;
-   public:
-    FollowKlassClosure(MarkAndPushClosure* mark_and_push_closure) :
-        _mark_and_push_closure(mark_and_push_closure) { }
-    void do_klass(Klass* klass);
-  };
 
   PSParallelCompact();
 
@@ -1193,23 +1142,13 @@
 
   // Used to add tasks
   static GCTaskManager* const gc_task_manager();
-  static Klass* updated_int_array_klass_obj() {
-    return _updated_int_array_klass_obj;
-  }
 
   // Marking support
   static inline bool mark_obj(oop obj);
   static inline bool is_marked(oop obj);
-  // Check mark and maybe push on marking stack
-  template <class T> static inline void mark_and_push(ParCompactionManager* cm,
-                                                      T* p);
+
   template <class T> static inline void adjust_pointer(T* p);
 
-  static inline void follow_klass(ParCompactionManager* cm, Klass* klass);
-
-  static void follow_class_loader(ParCompactionManager* cm,
-                                  ClassLoaderData* klass);
-
   // Compaction support.
   // Return true if p is in the range [beg_addr, end_addr).
   static inline bool is_in(HeapWord* p, HeapWord* beg_addr, HeapWord* end_addr);
@@ -1337,11 +1276,6 @@
   return mark_bitmap()->is_marked(obj);
 }
 
-template <class T>
-inline void PSParallelCompact::KeepAliveClosure::do_oop_work(T* p) {
-  mark_and_push(_compaction_manager, p);
-}
-
 inline bool PSParallelCompact::print_phases() {
   return _print_phases;
 }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -26,38 +26,11 @@
 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPARALLELCOMPACT_INLINE_HPP
 
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
 #include "gc_interface/collectedHeap.hpp"
 #include "oops/klass.hpp"
 #include "oops/oop.inline.hpp"
 
-template <typename T>
-inline void PSParallelCompact::mark_and_push(ParCompactionManager* cm, T* p) {
-  T heap_oop = oopDesc::load_heap_oop(p);
-  if (!oopDesc::is_null(heap_oop)) {
-    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap");
-
-    if (mark_bitmap()->is_unmarked(obj) && mark_obj(obj)) {
-      cm->push(obj);
-    }
-  }
-}
-
-template <typename T>
-inline void PSParallelCompact::MarkAndPushClosure::do_oop_nv(T* p) {
-  mark_and_push(_compaction_manager, p);
-}
-
-inline void PSParallelCompact::MarkAndPushClosure::do_oop(oop* p)       { do_oop_nv(p); }
-inline void PSParallelCompact::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
-
-inline void PSParallelCompact::follow_klass(ParCompactionManager* cm, Klass* klass) {
-  oop holder = klass->klass_holder();
-  mark_and_push(cm, &holder);
-}
-
 template <class T>
 inline void PSParallelCompact::adjust_pointer(T* p) {
   T heap_oop = oopDesc::load_heap_oop(p);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Thu May 07 11:28:03 2015 -0700
@@ -36,7 +36,7 @@
 #include "oops/instanceMirrorKlass.inline.hpp"
 #include "oops/objArrayKlass.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = NULL;
 OopStarTaskQueueSet*           PSPromotionManager::_stack_array_depth = NULL;
@@ -365,33 +365,19 @@
   // Treat discovered as normal oop, if ref is not "active",
   // i.e. if next is non-NULL.
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    T  next_oop = oopDesc::load_heap_oop(next_addr);
-    if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
-      T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(discovered_addr));
-        }
-      )
-      if (PSScavenge::should_scavenge(discovered_addr)) {
-        pm->claim_or_forward_depth(discovered_addr);
+  T  next_oop = oopDesc::load_heap_oop(next_addr);
+  if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+    T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+    debug_only(
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(discovered_addr));
       }
+    )
+    if (PSScavenge::should_scavenge(discovered_addr)) {
+      pm->claim_or_forward_depth(discovered_addr);
     }
-  } else {
-#ifdef ASSERT
-    // In the case of older JDKs which do not use the discovered
-    // field for the pending list, an inactive ref (next != NULL)
-    // must always have a NULL discovered field.
-    oop next = oopDesc::load_decode_heap_oop(next_addr);
-    oop discovered = java_lang_ref_Reference::discovered(obj);
-    assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
-           err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
-                   p2i(obj)));
-#endif
   }
-
   // Treat next as normal oop;  next is a link in the reference queue.
   if (PSScavenge::should_scavenge(next_addr)) {
     pm->claim_or_forward_depth(next_addr);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Thu May 07 11:28:03 2015 -0700
@@ -45,10 +45,6 @@
 // FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate!
 //
 
-// Move to some global location
-#define HAS_BEEN_MOVED 0x1501d01d
-// End move to some global location
-
 class MutableSpace;
 class PSOldGen;
 class ParCompactionManager;
@@ -143,9 +139,7 @@
                                                     int start, int end);
   void process_array_chunk(oop old);
 
-  template <class T> void push_depth(T* p) {
-    claimed_stack_depth()->push(p);
-  }
+  template <class T> void push_depth(T* p);
 
   inline void promotion_trace_event(oop new_obj, oop old_obj, size_t obj_size,
                                     uint age, bool tenured,
@@ -163,9 +157,7 @@
   static PSPromotionManager* gc_thread_promotion_manager(int index);
   static PSPromotionManager* vm_thread_promotion_manager();
 
-  static bool steal_depth(int queue_num, int* seed, StarTask& t) {
-    return stack_array_depth()->steal(queue_num, seed, t);
-  }
+  static bool steal_depth(int queue_num, int* seed, StarTask& t);
 
   PSPromotionManager();
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -31,6 +31,7 @@
 #include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 #include "oops/oop.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 inline PSPromotionManager* PSPromotionManager::manager_array(int index) {
   assert(_manager_array != NULL, "access of NULL manager_array");
@@ -39,6 +40,11 @@
 }
 
 template <class T>
+inline void PSPromotionManager::push_depth(T* p) {
+  claimed_stack_depth()->push(p);
+}
+
+template <class T>
 inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) {
   if (p != NULL) { // XXX: error if p != NULL here
     oop o = oopDesc::load_decode_heap_oop_not_null(p);
@@ -99,7 +105,7 @@
 // performance.
 //
 template<bool promote_immediately>
-oop PSPromotionManager::copy_to_survivor_space(oop o) {
+inline oop PSPromotionManager::copy_to_survivor_space(oop o) {
   assert(should_scavenge(&o), "Sanity");
 
   oop new_obj = NULL;
@@ -317,6 +323,10 @@
   }
 }
 
+inline bool PSPromotionManager::steal_depth(int queue_num, int* seed, StarTask& t) {
+  return stack_array_depth()->steal(queue_num, seed, t);
+}
+
 #if TASKQUEUE_STATS
 void PSPromotionManager::record_steal(StarTask& p) {
   if (is_oop_masked(p)) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp	Thu May 07 11:28:03 2015 -0700
@@ -39,8 +39,7 @@
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 #include "services/management.hpp"
-#include "utilities/stack.inline.hpp"
-#include "utilities/taskqueue.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 //
 // ScavengeRootsTask
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,10 +97,10 @@
 //    Calculate the number of GC threads based on the size of the heap.
 //    Use the larger.
 
-int AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
-                                            const uintx min_workers,
-                                            uintx active_workers,
-                                            uintx application_workers) {
+uint AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
+                                                     const uintx min_workers,
+                                                     uintx active_workers,
+                                                     uintx application_workers) {
   // If the user has specifically set the number of
   // GC threads, use them.
 
@@ -178,9 +178,9 @@
   return new_active_workers;
 }
 
-int AdaptiveSizePolicy::calc_active_workers(uintx total_workers,
-                                            uintx active_workers,
-                                            uintx application_workers) {
+uint AdaptiveSizePolicy::calc_active_workers(uintx total_workers,
+                                             uintx active_workers,
+                                             uintx application_workers) {
   // If the user has specifically set the number of
   // GC threads, use them.
 
@@ -188,13 +188,14 @@
   // or the users has requested a specific number, set the active
   // number of workers to all the workers.
 
-  int new_active_workers;
+  uint new_active_workers;
   if (!UseDynamicNumberOfGCThreads ||
      (!FLAG_IS_DEFAULT(ParallelGCThreads) && !ForceDynamicNumberOfGCThreads)) {
     new_active_workers = total_workers;
   } else {
+    uintx min_workers = (total_workers == 1) ? 1 : 2;
     new_active_workers = calc_default_active_workers(total_workers,
-                                                     2, /* Minimum number of workers */
+                                                     min_workers,
                                                      active_workers,
                                                      application_workers);
   }
@@ -202,18 +203,17 @@
   return new_active_workers;
 }
 
-int AdaptiveSizePolicy::calc_active_conc_workers(uintx total_workers,
-                                                 uintx active_workers,
-                                                 uintx application_workers) {
+uint AdaptiveSizePolicy::calc_active_conc_workers(uintx total_workers,
+                                                  uintx active_workers,
+                                                  uintx application_workers) {
   if (!UseDynamicNumberOfGCThreads ||
      (!FLAG_IS_DEFAULT(ConcGCThreads) && !ForceDynamicNumberOfGCThreads)) {
     return ConcGCThreads;
   } else {
-    int no_of_gc_threads = calc_default_active_workers(
-                             total_workers,
-                             1, /* Minimum number of workers */
-                             active_workers,
-                             application_workers);
+    uint no_of_gc_threads = calc_default_active_workers(total_workers,
+                                                        1, /* Minimum number of workers */
+                                                        active_workers,
+                                                        application_workers);
     return no_of_gc_threads;
   }
 }
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -343,10 +343,10 @@
                      uint gc_cost_ratio);
 
   // Return number default  GC threads to use in the next GC.
-  static int calc_default_active_workers(uintx total_workers,
-                                         const uintx min_workers,
-                                         uintx active_workers,
-                                         uintx application_workers);
+  static uint calc_default_active_workers(uintx total_workers,
+                                          const uintx min_workers,
+                                          uintx active_workers,
+                                          uintx application_workers);
 
   // Return number of GC threads to use in the next GC.
   // This is called sparingly so as not to change the
@@ -358,14 +358,14 @@
   // GC workers from the calls above.  For example,
   // a CMS parallel remark uses the same number of GC
   // workers as the most recent ParNew collection.
-  static int calc_active_workers(uintx total_workers,
-                                 uintx active_workers,
-                                 uintx application_workers);
+  static uint calc_active_workers(uintx total_workers,
+                                  uintx active_workers,
+                                  uintx application_workers);
 
   // Return number of GC threads to use in the next concurrent GC phase.
-  static int calc_active_conc_workers(uintx total_workers,
-                                      uintx active_workers,
-                                      uintx application_workers);
+  static uint calc_active_conc_workers(uintx total_workers,
+                                       uintx active_workers,
+                                       uintx application_workers);
 
   bool is_gc_cms_adaptive_size_policy() {
     return kind() == _gc_cms_adaptive_size_policy;
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Thu May 07 11:28:03 2015 -0700
@@ -145,31 +145,18 @@
     }
   }
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    // Treat discovered as normal oop, if ref is not "active",
-    // i.e. if next is non-NULL.
-    T  next_oop = oopDesc::load_heap_oop(next_addr);
-    if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
-      T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(discovered_addr));
-        }
-      )
-      MarkSweep::mark_and_push(discovered_addr);
-    }
-  } else {
-#ifdef ASSERT
-    // In the case of older JDKs which do not use the discovered
-    // field for the pending list, an inactive ref (next != NULL)
-    // must always have a NULL discovered field.
-    oop next = oopDesc::load_decode_heap_oop(next_addr);
-    oop discovered = java_lang_ref_Reference::discovered(obj);
-    assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
-        err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
-            p2i(obj)));
-#endif
+  // Treat discovered as normal oop, if ref is not "active",
+  // i.e. if next is non-NULL.
+  T  next_oop = oopDesc::load_heap_oop(next_addr);
+  if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+    T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+    debug_only(
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(discovered_addr));
+      }
+    )
+    MarkSweep::mark_and_push(discovered_addr);
   }
   // treat next as normal oop.  next is a link in the reference queue.
   debug_only(
--- a/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP
-#define SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
 
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "memory/allocation.hpp"
@@ -42,4 +42,4 @@
 
 #endif // INCLUDE_SERVICES
 
-#endif // SHARE_VM_OBJECT_COUNT_EVENT_SENDER
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
--- a/hotspot/src/share/vm/gc_implementation/shared/plab.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.cpp	Thu May 07 11:28:03 2015 -0700
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/shared/plab.hpp"
+#include "gc_interface/collectedHeap.hpp"
 #include "memory/threadLocalAllocBuffer.hpp"
 #include "oops/arrayOop.hpp"
 #include "oops/oop.inline.hpp"
@@ -39,7 +40,7 @@
 
 PLAB::PLAB(size_t desired_plab_sz_) :
   _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
-  _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0)
+  _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0), _undo_wasted(0)
 {
   // ArrayOopDesc::header_size depends on command line initialization.
   AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0;
@@ -62,13 +63,15 @@
   // Now flush the statistics.
   stats->add_allocated(_allocated);
   stats->add_wasted(_wasted);
+  stats->add_undo_wasted(_undo_wasted);
   stats->add_unused(unused);
 
   // Since we have flushed the stats we need to clear  the _allocated and _wasted
   // fields in case somebody retains an instance of this over GCs. Not doing so
   // will artifically inflate the values in the statistics.
-  _allocated = 0;
-  _wasted = 0;
+  _allocated   = 0;
+  _wasted      = 0;
+  _undo_wasted = 0;
 }
 
 void PLAB::retire() {
@@ -84,6 +87,28 @@
   return result;
 }
 
+void PLAB::add_undo_waste(HeapWord* obj, size_t word_sz) {
+  CollectedHeap::fill_with_object(obj, word_sz);
+  _undo_wasted += word_sz;
+}
+
+void PLAB::undo_last_allocation(HeapWord* obj, size_t word_sz) {
+  assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
+  assert(pointer_delta(_top, obj) == word_sz, "Bad undo");
+  _top = obj;
+}
+
+void PLAB::undo_allocation(HeapWord* obj, size_t word_sz) {
+  // Is the alloc in the current alloc buffer?
+  if (contains(obj)) {
+    assert(contains(obj + word_sz - 1),
+      "should contain whole object");
+    undo_last_allocation(obj, word_sz);
+  } else {
+    add_undo_waste(obj, word_sz);
+  }
+}
+
 // Compute desired plab size and latch result for later
 // use. This should be called once at the end of parallel
 // scavenge; it clears the sensor accumulators.
@@ -98,8 +123,9 @@
            err_msg("Inconsistency in PLAB stats: "
                    "_allocated: "SIZE_FORMAT", "
                    "_wasted: "SIZE_FORMAT", "
-                   "_unused: "SIZE_FORMAT,
-                   _allocated, _wasted, _unused));
+                   "_unused: "SIZE_FORMAT", "
+                   "_undo_wasted: "SIZE_FORMAT,
+                   _allocated, _wasted, _unused, _undo_wasted));
 
     _allocated = 1;
   }
--- a/hotspot/src/share/vm/gc_implementation/shared/plab.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.hpp	Thu May 07 11:28:03 2015 -0700
@@ -45,6 +45,7 @@
   // In support of ergonomic sizing of PLAB's
   size_t    _allocated;     // in HeapWord units
   size_t    _wasted;        // in HeapWord units
+  size_t    _undo_wasted;
   char      tail[32];
   static size_t AlignmentReserve;
 
@@ -62,6 +63,12 @@
   // the amount of remaining space.
   size_t retire_internal();
 
+  void add_undo_waste(HeapWord* obj, size_t word_sz);
+
+  // Undo the last allocation in the buffer, which is required to be of the
+  // "obj" of the given "word_sz".
+  void undo_last_allocation(HeapWord* obj, size_t word_sz);
+
 public:
   // Initializes the buffer to be empty, but with the given "word_sz".
   // Must get initialized with "set_buf" for an allocation to succeed.
@@ -90,18 +97,17 @@
   // Allocate the object aligned to "alignment_in_bytes".
   HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
 
-  // Undo the last allocation in the buffer, which is required to be of the
+  // Undo any allocation in the buffer, which is required to be of the
   // "obj" of the given "word_sz".
-  void undo_allocation(HeapWord* obj, size_t word_sz) {
-    assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
-    assert(pointer_delta(_top, obj)     == word_sz, "Bad undo");
-    _top = obj;
-  }
+  void undo_allocation(HeapWord* obj, size_t word_sz);
 
   // The total (word) size of the buffer, including both allocated and
   // unallocated space.
   size_t word_sz() { return _word_sz; }
 
+  size_t waste() { return _wasted; }
+  size_t undo_waste() { return _undo_wasted; }
+
   // Should only be done if we are about to reset with a new buffer of the
   // given size.
   void set_word_size(size_t new_word_sz) {
@@ -146,20 +152,23 @@
 class PLABStats VALUE_OBJ_CLASS_SPEC {
   size_t _allocated;      // Total allocated
   size_t _wasted;         // of which wasted (internal fragmentation)
+  size_t _undo_wasted;    // of which wasted on undo (is not used for calculation of PLAB size)
   size_t _unused;         // Unused in last buffer
   size_t _desired_plab_sz;// Output of filter (below), suitably trimmed and quantized
   AdaptiveWeightedAverage
          _filter;         // Integrator with decay
 
   void reset() {
-    _allocated = 0;
-    _wasted    = 0;
-    _unused    = 0;
+    _allocated   = 0;
+    _wasted      = 0;
+    _undo_wasted = 0;
+    _unused      = 0;
   }
  public:
   PLABStats(size_t desired_plab_sz_, unsigned wt) :
     _allocated(0),
     _wasted(0),
+    _undo_wasted(0),
     _unused(0),
     _desired_plab_sz(desired_plab_sz_),
     _filter(wt)
@@ -192,6 +201,10 @@
   void add_wasted(size_t v) {
     Atomic::add_ptr(v, &_wasted);
   }
+
+  void add_undo_wasted(size_t v) {
+    Atomic::add_ptr(v, &_undo_wasted);
+  }
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_HPP
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Thu May 07 11:28:03 2015 -0700
@@ -598,13 +598,6 @@
 #endif
 
  public:
-  // This is a convenience method that is used in cases where
-  // the actual number of GC worker threads is not pertinent but
-  // only whether there more than 0.  Use of this method helps
-  // reduce the occurrence of ParallelGCThreads to uses where the
-  // actual number may be germane.
-  static bool use_parallel_gc_threads() { return ParallelGCThreads > 0; }
-
   // Copy the current allocation context statistics for the specified contexts.
   // For each context in contexts, set the corresponding entries in the totals
   // and accuracy arrays to the current values held by the statistics.  Each
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Thu May 07 11:28:03 2015 -0700
@@ -640,7 +640,7 @@
   // All threads execute the following. A specific chunk of buckets
   // from the StringTable are the individual tasks.
   if (weak_roots != NULL) {
-    if (CollectedHeap::use_parallel_gc_threads()) {
+    if (is_par) {
       StringTable::possibly_parallel_oops_do(weak_roots);
     } else {
       StringTable::oops_do(weak_roots);
--- a/hotspot/src/share/vm/memory/guardedMemory.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/guardedMemory.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
-#define SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+#ifndef SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
+#define SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
 
 #include "memory/allocation.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -323,4 +323,4 @@
 #endif
 }; // GuardedMemory
 
-#endif // SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+#endif // SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Thu May 07 11:28:03 2015 -0700
@@ -252,7 +252,7 @@
 // Used to manage the free list of Metablocks (a block corresponds
 // to the allocation of a quantum of metadata).
 class BlockFreelist VALUE_OBJ_CLASS_SPEC {
-  BlockTreeDictionary* _dictionary;
+  BlockTreeDictionary* const _dictionary;
 
   // Only allocate and split from freelist if the size of the allocation
   // is at least 1/4th the size of the available block.
@@ -269,13 +269,7 @@
   MetaWord* get_block(size_t word_size);
   void return_block(MetaWord* p, size_t word_size);
 
-  size_t total_size() {
-  if (dictionary() == NULL) {
-    return 0;
-  } else {
-    return dictionary()->total_size();
-  }
-}
+  size_t total_size() { return dictionary()->total_size(); }
 
   void print_on(outputStream* st) const;
 };
@@ -814,30 +808,21 @@
 
 // BlockFreelist methods
 
-BlockFreelist::BlockFreelist() : _dictionary(NULL) {}
+BlockFreelist::BlockFreelist() : _dictionary(new BlockTreeDictionary()) {}
 
 BlockFreelist::~BlockFreelist() {
-  if (_dictionary != NULL) {
-    if (Verbose && TraceMetadataChunkAllocation) {
-      _dictionary->print_free_lists(gclog_or_tty);
-    }
-    delete _dictionary;
+  if (Verbose && TraceMetadataChunkAllocation) {
+    dictionary()->print_free_lists(gclog_or_tty);
   }
+  delete _dictionary;
 }
 
 void BlockFreelist::return_block(MetaWord* p, size_t word_size) {
   Metablock* free_chunk = ::new (p) Metablock(word_size);
-  if (dictionary() == NULL) {
-   _dictionary = new BlockTreeDictionary();
-  }
   dictionary()->return_chunk(free_chunk);
 }
 
 MetaWord* BlockFreelist::get_block(size_t word_size) {
-  if (dictionary() == NULL) {
-    return NULL;
-  }
-
   if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
     // Dark matter.  Too small for dictionary.
     return NULL;
@@ -866,9 +851,6 @@
 }
 
 void BlockFreelist::print_on(outputStream* st) const {
-  if (dictionary() == NULL) {
-    return;
-  }
   dictionary()->print_free_lists(st);
 }
 
--- a/hotspot/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,9 @@
  * questions.
  *
  */
-#ifndef SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
-#define SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+
+#ifndef SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
+#define SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
 
 #include "memory/allocation.hpp"
 
@@ -100,4 +101,4 @@
   }
 };
 
-#endif // SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+#endif // SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
--- a/hotspot/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
-#define SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#ifndef SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
+#define SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
 
 #include "memory/allocation.hpp"
 #include "utilities/debug.hpp"
@@ -49,4 +49,4 @@
   }
 };
 
-#endif // SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#endif // SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp	Thu May 07 11:28:03 2015 -0700
@@ -21,8 +21,9 @@
  * questions.
  *
  */
-#ifndef SHARE_VM_MEMORY_METASPACE_SHARED_HPP
-#define SHARE_VM_MEMORY_METASPACE_SHARED_HPP
+
+#ifndef SHARE_VM_MEMORY_METASPACESHARED_HPP
+#define SHARE_VM_MEMORY_METASPACESHARED_HPP
 
 #include "classfile/compactHashtable.hpp"
 #include "memory/allocation.hpp"
@@ -153,4 +154,4 @@
   static int count_class(const char* classlist_file);
   static void estimate_regions_size() NOT_CDS_RETURN;
 };
-#endif // SHARE_VM_MEMORY_METASPACE_SHARED_HPP
+#endif // SHARE_VM_MEMORY_METASPACESHARED_HPP
--- a/hotspot/src/share/vm/memory/metaspaceTracer.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceTracer.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_METASPACE_TRACER_HPP
-#define SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+#ifndef SHARE_VM_MEMORY_METASPACETRACER_HPP
+#define SHARE_VM_MEMORY_METASPACETRACER_HPP
 
 #include "memory/allocation.hpp"
 #include "memory/metaspace.hpp"
@@ -52,4 +52,4 @@
 
 };
 
-#endif // SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+#endif // SHARE_VM_MEMORY_METASPACETRACER_HPP
--- a/hotspot/src/share/vm/memory/padded.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/padded.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,9 @@
  *
  */
 
+#ifndef SHARE_VM_MEMORY_PADDED_INLINE_HPP
+#define SHARE_VM_MEMORY_PADDED_INLINE_HPP
+
 #include "memory/allocation.inline.hpp"
 #include "memory/padded.hpp"
 #include "utilities/debug.hpp"
@@ -86,3 +89,5 @@
 
   return (T*)align_pointer_up(chunk, alignment);
 }
+
+#endif // SHARE_VM_MEMORY_PADDED_INLINE_HPP
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp	Thu May 07 11:28:03 2015 -0700
@@ -37,7 +37,6 @@
 
 ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
 ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy      = NULL;
-bool             ReferenceProcessor::_pending_list_uses_discovered_field = false;
 jlong            ReferenceProcessor::_soft_ref_timestamp_clock = 0;
 
 void referenceProcessor_init() {
@@ -63,7 +62,6 @@
   guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
             RefDiscoveryPolicy == ReferentBasedDiscovery,
             "Unrecognized RefDiscoveryPolicy");
-  _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field();
 }
 
 void ReferenceProcessor::enable_discovery(bool check_no_refs) {
@@ -353,10 +351,6 @@
   // all linked Reference objects. Note that it is important to not dirty any
   // cards during reference processing since this will cause card table
   // verification to fail for G1.
-  //
-  // BKWRD COMPATIBILITY NOTE: For older JDKs (prior to the fix for 4956777),
-  // the "next" field is used to chain the pending list, not the discovered
-  // field.
   if (TraceReferenceGC && PrintGCDetails) {
     gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list "
                            INTPTR_FORMAT, p2i(refs_list.head()));
@@ -364,64 +358,30 @@
 
   oop obj = NULL;
   oop next_d = refs_list.head();
-  if (pending_list_uses_discovered_field()) { // New behavior
-    // Walk down the list, self-looping the next field
-    // so that the References are not considered active.
-    while (obj != next_d) {
-      obj = next_d;
-      assert(obj->is_instanceRef(), "should be reference object");
-      next_d = java_lang_ref_Reference::discovered(obj);
-      if (TraceReferenceGC && PrintGCDetails) {
-        gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
-                               p2i(obj), p2i(next_d));
-      }
-      assert(java_lang_ref_Reference::next(obj) == NULL,
-             "Reference not active; should not be discovered");
-      // Self-loop next, so as to make Ref not active.
-      java_lang_ref_Reference::set_next_raw(obj, obj);
-      if (next_d != obj) {
-        oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
-      } else {
-        // This is the last object.
-        // Swap refs_list into pending_list_addr and
-        // set obj's discovered to what we read from pending_list_addr.
-        oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
-        // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above.
-        java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL
-        oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
-      }
+  // Walk down the list, self-looping the next field
+  // so that the References are not considered active.
+  while (obj != next_d) {
+    obj = next_d;
+    assert(obj->is_instanceRef(), "should be reference object");
+    next_d = java_lang_ref_Reference::discovered(obj);
+    if (TraceReferenceGC && PrintGCDetails) {
+      gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
+                             p2i(obj), p2i(next_d));
     }
-  } else { // Old behavior
-    // Walk down the list, copying the discovered field into
-    // the next field and clearing the discovered field.
-    while (obj != next_d) {
-      obj = next_d;
-      assert(obj->is_instanceRef(), "should be reference object");
-      next_d = java_lang_ref_Reference::discovered(obj);
-      if (TraceReferenceGC && PrintGCDetails) {
-        gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
-                               p2i(obj), p2i(next_d));
-      }
-      assert(java_lang_ref_Reference::next(obj) == NULL,
-             "The reference should not be enqueued");
-      if (next_d == obj) {  // obj is last
-        // Swap refs_list into pending_list_addr and
-        // set obj's next to what we read from pending_list_addr.
-        oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
-        // Need oop_check on pending_list_addr above;
-        // see special oop-check code at the end of
-        // enqueue_discovered_reflists() further below.
-        if (old == NULL) {
-          // obj should be made to point to itself, since
-          // pending list was empty.
-          java_lang_ref_Reference::set_next(obj, obj);
-        } else {
-          java_lang_ref_Reference::set_next(obj, old);
-        }
-      } else {
-        java_lang_ref_Reference::set_next(obj, next_d);
-      }
-      java_lang_ref_Reference::set_discovered(obj, (oop) NULL);
+    assert(java_lang_ref_Reference::next(obj) == NULL,
+           "Reference not active; should not be discovered");
+    // Self-loop next, so as to make Ref not active.
+    java_lang_ref_Reference::set_next_raw(obj, obj);
+    if (next_d != obj) {
+      oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
+    } else {
+      // This is the last object.
+      // Swap refs_list into pending_list_addr and
+      // set obj's discovered to what we read from pending_list_addr.
+      oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
+      // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above.
+      java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL
+      oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
     }
   }
 }
@@ -515,22 +475,6 @@
   _refs_list.dec_length(1);
 }
 
-// Make the Reference object active again.
-void DiscoveredListIterator::make_active() {
-  // The pre barrier for G1 is probably just needed for the old
-  // reference processing behavior. Should we guard this with
-  // ReferenceProcessor::pending_list_uses_discovered_field() ?
-  if (UseG1GC) {
-    HeapWord* next_addr = java_lang_ref_Reference::next_addr(_ref);
-    if (UseCompressedOops) {
-      oopDesc::bs()->write_ref_field_pre((narrowOop*)next_addr, NULL);
-    } else {
-      oopDesc::bs()->write_ref_field_pre((oop*)next_addr, NULL);
-    }
-  }
-  java_lang_ref_Reference::set_next_raw(_ref, NULL);
-}
-
 void DiscoveredListIterator::clear_referent() {
   oop_store_raw(_referent_addr, NULL);
 }
@@ -567,8 +511,6 @@
       }
       // Remove Reference object from list
       iter.remove();
-      // Make the Reference object active again
-      iter.make_active();
       // keep the referent around
       iter.make_referent_alive();
       iter.move_to_next();
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp	Thu May 07 11:28:03 2015 -0700
@@ -161,9 +161,6 @@
   // Remove the current reference from the list
   void remove();
 
-  // Make the Reference object active again.
-  void make_active();
-
   // Make the referent alive.
   inline void make_referent_alive() {
     if (UseCompressedOops) {
@@ -200,9 +197,6 @@
   size_t total_count(DiscoveredList lists[]);
 
  protected:
-  // Compatibility with pre-4965777 JDK's
-  static bool _pending_list_uses_discovered_field;
-
   // The SoftReference master timestamp clock
   static jlong _soft_ref_timestamp_clock;
 
@@ -421,13 +415,6 @@
   bool discovery_is_atomic() const { return _discovery_is_atomic; }
   void set_atomic_discovery(bool atomic) { _discovery_is_atomic = atomic; }
 
-  // whether the JDK in which we are embedded is a pre-4965777 JDK,
-  // and thus whether or not it uses the discovered field to chain
-  // the entries in the pending list.
-  static bool pending_list_uses_discovered_field() {
-    return _pending_list_uses_discovered_field;
-  }
-
   // whether discovery is done by multiple threads same-old-timeously
   bool discovery_is_mt() const { return _discovery_is_mt; }
   void set_mt_discovery(bool mt) { _discovery_is_mt = mt; }
--- a/hotspot/src/share/vm/memory/referenceType.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/referenceType.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_REFRERENCETYPE_HPP
-#define SHARE_VM_MEMORY_REFRERENCETYPE_HPP
+#ifndef SHARE_VM_MEMORY_REFERENCETYPE_HPP
+#define SHARE_VM_MEMORY_REFERENCETYPE_HPP
 
 #include "utilities/debug.hpp"
 
@@ -39,4 +39,4 @@
   REF_CLEANER    // Subclass of sun/misc/Cleaner
 };
 
-#endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP
+#endif // SHARE_VM_MEMORY_REFERENCETYPE_HPP
--- a/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -55,30 +55,17 @@
     }
   }
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    T next_oop  = oopDesc::load_heap_oop(next_addr);
-    // Treat discovered as normal oop, if ref is not "active" (next non-NULL)
-    if (!oopDesc::is_null(next_oop) && contains(disc_addr)) {
-      // i.e. ref is not "active"
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(disc_addr));
-        }
-      )
-      Devirtualizer<nv>::do_oop(closure, disc_addr);
-    }
-  } else {
-    // In the case of older JDKs which do not use the discovered field for
-    // the pending list, an inactive ref (next != NULL) must always have a
-    // NULL discovered field.
+  T next_oop  = oopDesc::load_heap_oop(next_addr);
+  // Treat discovered as normal oop, if ref is not "active" (next non-NULL)
+  if (!oopDesc::is_null(next_oop) && contains(disc_addr)) {
+    // i.e. ref is not "active"
     debug_only(
-      T next_oop = oopDesc::load_heap_oop(next_addr);
-      T disc_oop = oopDesc::load_heap_oop(disc_addr);
-      assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop),
-           err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL"
-                   "discovered field", p2i(obj)));
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(disc_addr));
+      }
     )
+    Devirtualizer<nv>::do_oop(closure, disc_addr);
   }
   // treat next as normal oop
   if (contains(next_addr)) {
--- a/hotspot/src/share/vm/runtime/java.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp	Thu May 07 11:28:03 2015 -0700
@@ -651,11 +651,15 @@
       minor = micro;
       micro = 0;
     }
+    // Incompatible with pre-4243978 JDK.
+    if (info.pending_list_uses_discovered_field == 0) {
+      vm_exit_during_initialization(
+        "Incompatible JDK is not using Reference.discovered field for pending list");
+    }
     _current = JDK_Version(major, minor, micro, info.update_version,
                            info.special_update_version, build,
                            info.thread_park_blocker == 1,
-                           info.post_vm_init_hook_enabled == 1,
-                           info.pending_list_uses_discovered_field == 1);
+                           info.post_vm_init_hook_enabled == 1);
   }
 }
 
--- a/hotspot/src/share/vm/runtime/java.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/java.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,6 @@
   bool _partially_initialized;
 
   bool _thread_park_blocker;
-  bool _pending_list_uses_discovered_field;
   bool _post_vm_init_hook_enabled;
 
   bool is_valid() const {
@@ -114,18 +113,17 @@
 
   JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
                   _special(0), _build(0), _partially_initialized(false),
-                  _thread_park_blocker(false), _post_vm_init_hook_enabled(false),
-                  _pending_list_uses_discovered_field(false) {}
+                  _thread_park_blocker(false), _post_vm_init_hook_enabled(false)
+                  {}
 
   JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
               uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
-              bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false,
-              bool pending_list_uses_discovered_field = false) :
+              bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) :
       _major(major), _minor(minor), _micro(micro), _update(update),
       _special(special), _build(build), _partially_initialized(false),
       _thread_park_blocker(thread_park_blocker),
-      _post_vm_init_hook_enabled(post_vm_init_hook_enabled),
-      _pending_list_uses_discovered_field(pending_list_uses_discovered_field) {}
+      _post_vm_init_hook_enabled(post_vm_init_hook_enabled)
+      {}
 
   // Returns the current running JDK version
   static JDK_Version current() { return _current; }
@@ -152,10 +150,6 @@
   bool post_vm_init_hook_enabled() const {
     return _post_vm_init_hook_enabled;
   }
-  // For compatibility wrt pre-4965777 JDK's
-  bool pending_list_uses_discovered_field() const {
-    return _pending_list_uses_discovered_field;
-  }
 
   // Performs a full ordering comparison using all fields (update, build, etc.)
   int compare(const JDK_Version& other) const;
--- a/hotspot/src/share/vm/runtime/thread.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Thu May 07 11:28:03 2015 -0700
@@ -4210,13 +4210,13 @@
                Abstract_VM_Version::vm_info_string());
   st->cr();
 
-#if INCLUDE_ALL_GCS
+#if INCLUDE_SERVICES
   // Dump concurrent locks
   ConcurrentLocksDump concurrent_locks;
   if (print_concurrent_locks) {
     concurrent_locks.dump_at_safepoint();
   }
-#endif // INCLUDE_ALL_GCS
+#endif // INCLUDE_SERVICES
 
   ALL_JAVA_THREADS(p) {
     ResourceMark rm;
@@ -4229,11 +4229,11 @@
       }
     }
     st->cr();
-#if INCLUDE_ALL_GCS
+#if INCLUDE_SERVICES
     if (print_concurrent_locks) {
       concurrent_locks.print_locks_on(p, st);
     }
-#endif // INCLUDE_ALL_GCS
+#endif // INCLUDE_SERVICES
   }
 
   VMThread::vm_thread()->print_on(st);
--- a/hotspot/src/share/vm/runtime/vm_version.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp	Thu May 07 11:28:03 2015 -0700
@@ -78,7 +78,7 @@
 int Abstract_VM_Version::_vm_micro_version = 0;
 int Abstract_VM_Version::_vm_build_number = 0;
 bool Abstract_VM_Version::_initialized = false;
-int Abstract_VM_Version::_parallel_worker_threads = 0;
+unsigned int Abstract_VM_Version::_parallel_worker_threads = 0;
 bool Abstract_VM_Version::_parallel_worker_threads_initialized = false;
 
 #ifdef ASSERT
--- a/hotspot/src/share/vm/runtime/vm_version.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vm_version.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
   static int          _vm_micro_version;
   static int          _vm_build_number;
   static bool         _initialized;
-  static int          _parallel_worker_threads;
+  static unsigned int _parallel_worker_threads;
   static bool         _parallel_worker_threads_initialized;
   static int          _reserve_for_allocation_prefetch;
 
--- a/hotspot/src/share/vm/utilities/taskqueue.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.cpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,8 +31,6 @@
 #include "utilities/stack.inline.hpp"
 #include "utilities/taskqueue.hpp"
 
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
 #ifdef TRACESPINNING
 uint ParallelTaskTerminator::_total_yields = 0;
 uint ParallelTaskTerminator::_total_spins = 0;
@@ -131,7 +129,7 @@
 }
 
 ParallelTaskTerminator::
-ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set) :
+ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set) :
   _n_threads(n_threads),
   _queue_set(queue_set),
   _offered_termination(0) {}
@@ -154,7 +152,7 @@
 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
   assert(_n_threads > 0, "Initialization is incorrect");
   assert(_offered_termination < _n_threads, "Invariant");
-  Atomic::inc(&_offered_termination);
+  Atomic::inc((int *)&_offered_termination);
 
   uint yield_count = 0;
   // Number of hard spin loops done since last yield
@@ -216,8 +214,8 @@
       } else {
         if (PrintGCDetails && Verbose) {
          gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() "
-           "thread %d sleeps after %d yields",
-           Thread::current(), yield_count);
+           "thread " PTR_FORMAT " sleeps after %u yields",
+           p2i(Thread::current()), yield_count);
         }
         yield_count = 0;
         // A sleep will cause this processor to seek work on another processor's
@@ -232,7 +230,7 @@
 #endif
       if (peek_in_queue_set() ||
           (terminator != NULL && terminator->should_exit_termination())) {
-        Atomic::dec(&_offered_termination);
+        Atomic::dec((int *)&_offered_termination);
         assert(_offered_termination < _n_threads, "Invariant");
         return false;
       }
@@ -265,7 +263,7 @@
 }
 #endif // ASSERT
 
-void ParallelTaskTerminator::reset_for_reuse(int n_threads) {
+void ParallelTaskTerminator::reset_for_reuse(uint n_threads) {
   reset_for_reuse();
   _n_threads = n_threads;
 }
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,6 @@
 #define SHARE_VM_UTILITIES_TASKQUEUE_HPP
 
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/orderAccess.inline.hpp"
 #include "utilities/stack.hpp"
 
 // Simple TaskQueue stats that are collected by default in debug builds.
@@ -134,11 +131,7 @@
       if (_fields._top == 0) ++_fields._tag;
     }
 
-    Age cmpxchg(const Age new_age, const Age old_age) volatile {
-      return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
-                                          (volatile intptr_t *)&_data,
-                                          (intptr_t)old_age._data);
-    }
+    Age cmpxchg(const Age new_age, const Age old_age) volatile;
 
     bool operator ==(const Age& other) const { return _data == other._data; }
 
@@ -315,121 +308,6 @@
   assert(sizeof(Age) == sizeof(size_t), "Depends on this.");
 }
 
-template<class E, MEMFLAGS F, unsigned int N>
-void GenericTaskQueue<E, F, N>::initialize() {
-  _elems = _array_allocator.allocate(N);
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
-  // tty->print_cr("START OopTaskQueue::oops_do");
-  uint iters = size();
-  uint index = _bottom;
-  for (uint i = 0; i < iters; ++i) {
-    index = decrement_index(index);
-    // tty->print_cr("  doing entry %d," INTPTR_T " -> " INTPTR_T,
-    //            index, &_elems[index], _elems[index]);
-    E* t = (E*)&_elems[index];      // cast away volatility
-    oop* p = (oop*)t;
-    assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
-    f->do_oop(p);
-  }
-  // tty->print_cr("END OopTaskQueue::oops_do");
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
-  if (dirty_n_elems == N - 1) {
-    // Actually means 0, so do the push.
-    uint localBot = _bottom;
-    // g++ complains if the volatile result of the assignment is
-    // unused, so we cast the volatile away.  We cannot cast directly
-    // to void, because gcc treats that as not using the result of the
-    // assignment.  However, casting to E& means that we trigger an
-    // unused-value warning.  So, we cast the E& to void.
-    (void)const_cast<E&>(_elems[localBot] = t);
-    OrderAccess::release_store(&_bottom, increment_index(localBot));
-    TASKQUEUE_STATS_ONLY(stats.record_push());
-    return true;
-  }
-  return false;
-}
-
-// pop_local_slow() is done by the owning thread and is trying to
-// get the last task in the queue.  It will compete with pop_global()
-// that will be used by other threads.  The tag age is incremented
-// whenever the queue goes empty which it will do here if this thread
-// gets the last task or in pop_global() if the queue wraps (top == 0
-// and pop_global() succeeds, see pop_global()).
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
-  // This queue was observed to contain exactly one element; either this
-  // thread will claim it, or a competing "pop_global".  In either case,
-  // the queue will be logically empty afterwards.  Create a new Age value
-  // that represents the empty queue for the given value of "_bottom".  (We
-  // must also increment "tag" because of the case where "bottom == 1",
-  // "top == 0".  A pop_global could read the queue element in that case,
-  // then have the owner thread do a pop followed by another push.  Without
-  // the incrementing of "tag", the pop_global's CAS could succeed,
-  // allowing it to believe it has claimed the stale element.)
-  Age newAge((idx_t)localBot, oldAge.tag() + 1);
-  // Perhaps a competing pop_global has already incremented "top", in which
-  // case it wins the element.
-  if (localBot == oldAge.top()) {
-    // No competing pop_global has yet incremented "top"; we'll try to
-    // install new_age, thus claiming the element.
-    Age tempAge = _age.cmpxchg(newAge, oldAge);
-    if (tempAge == oldAge) {
-      // We win.
-      assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
-      TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
-      return true;
-    }
-  }
-  // We lose; a completing pop_global gets the element.  But the queue is empty
-  // and top is greater than bottom.  Fix this representation of the empty queue
-  // to become the canonical one.
-  _age.set(newAge);
-  assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
-  return false;
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
-  Age oldAge = _age.get();
-  // Architectures with weak memory model require a barrier here
-  // to guarantee that bottom is not older than age,
-  // which is crucial for the correctness of the algorithm.
-#if !(defined SPARC || defined IA32 || defined AMD64)
-  OrderAccess::fence();
-#endif
-  uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
-  uint n_elems = size(localBot, oldAge.top());
-  if (n_elems == 0) {
-    return false;
-  }
-
-  // g++ complains if the volatile result of the assignment is
-  // unused, so we cast the volatile away.  We cannot cast directly
-  // to void, because gcc treats that as not using the result of the
-  // assignment.  However, casting to E& means that we trigger an
-  // unused-value warning.  So, we cast the E& to void.
-  (void) const_cast<E&>(t = _elems[oldAge.top()]);
-  Age newAge(oldAge);
-  newAge.increment();
-  Age resAge = _age.cmpxchg(newAge, oldAge);
-
-  // Note that using "_bottom" here might fail, since a pop_local might
-  // have decremented it.
-  assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
-  return resAge == oldAge;
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
-  FREE_C_HEAP_ARRAY(E, _elems);
-}
-
 // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
 // elements that do not fit in the TaskQueue.
 //
@@ -468,24 +346,6 @@
   overflow_t _overflow_stack;
 };
 
-template <class E, MEMFLAGS F, unsigned int N>
-bool OverflowTaskQueue<E, F, N>::push(E t)
-{
-  if (!taskqueue_t::push(t)) {
-    overflow_stack()->push(t);
-    TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size()));
-  }
-  return true;
-}
-
-template <class E, MEMFLAGS F, unsigned int N>
-bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
-{
-  if (overflow_empty()) return false;
-  t = overflow_stack()->pop();
-  return true;
-}
-
 class TaskQueueSetSuper {
 protected:
   static int randomParkAndMiller(int* seed0);
@@ -506,13 +366,7 @@
 public:
   typedef typename T::element_type E;
 
-  GenericTaskQueueSet(int n) : _n(n) {
-    typedef T* GenericTaskQueuePtr;
-    _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
-    for (int i = 0; i < n; i++) {
-      _queues[i] = NULL;
-    }
-  }
+  GenericTaskQueueSet(int n);
 
   bool steal_best_of_2(uint queue_num, int* seed, E& t);
 
@@ -541,40 +395,6 @@
   return _queues[i];
 }
 
-template<class T, MEMFLAGS F> bool
-GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
-  for (uint i = 0; i < 2 * _n; i++) {
-    if (steal_best_of_2(queue_num, seed, t)) {
-      TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
-      return true;
-    }
-  }
-  TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
-  return false;
-}
-
-template<class T, MEMFLAGS F> bool
-GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
-  if (_n > 2) {
-    uint k1 = queue_num;
-    while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
-    uint k2 = queue_num;
-    while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
-    // Sample both and try the larger.
-    uint sz1 = _queues[k1]->size();
-    uint sz2 = _queues[k2]->size();
-    if (sz2 > sz1) return _queues[k2]->pop_global(t);
-    else return _queues[k1]->pop_global(t);
-  } else if (_n == 2) {
-    // Just try the other one.
-    uint k = (queue_num + 1) % 2;
-    return _queues[k]->pop_global(t);
-  } else {
-    assert(_n == 1, "can't be zero.");
-    return false;
-  }
-}
-
 template<class T, MEMFLAGS F>
 bool GenericTaskQueueSet<T, F>::peek() {
   // Try all the queues.
@@ -598,9 +418,9 @@
 
 class ParallelTaskTerminator: public StackObj {
 private:
-  int _n_threads;
+  uint _n_threads;
   TaskQueueSetSuper* _queue_set;
-  int _offered_termination;
+  uint _offered_termination;
 
 #ifdef TRACESPINNING
   static uint _total_yields;
@@ -617,7 +437,7 @@
 
   // "n_threads" is the number of threads to be terminated.  "queue_set" is a
   // queue sets of work queues of other threads.
-  ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set);
+  ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
 
   // The current thread has no work, and is ready to terminate if everyone
   // else is.  If returns "true", all threads are terminated.  If returns
@@ -639,7 +459,7 @@
   void reset_for_reuse();
   // Same as above but the number of parallel threads is set to the
   // given number.
-  void reset_for_reuse(int n_threads);
+  void reset_for_reuse(uint n_threads);
 
 #ifdef TRACESPINNING
   static uint total_yields() { return _total_yields; }
@@ -649,65 +469,6 @@
 #endif
 };
 
-template<class E, MEMFLAGS F, unsigned int N> inline bool
-GenericTaskQueue<E, F, N>::push(E t) {
-  uint localBot = _bottom;
-  assert(localBot < N, "_bottom out of range.");
-  idx_t top = _age.top();
-  uint dirty_n_elems = dirty_size(localBot, top);
-  assert(dirty_n_elems < N, "n_elems out of range.");
-  if (dirty_n_elems < max_elems()) {
-    // g++ complains if the volatile result of the assignment is
-    // unused, so we cast the volatile away.  We cannot cast directly
-    // to void, because gcc treats that as not using the result of the
-    // assignment.  However, casting to E& means that we trigger an
-    // unused-value warning.  So, we cast the E& to void.
-    (void) const_cast<E&>(_elems[localBot] = t);
-    OrderAccess::release_store(&_bottom, increment_index(localBot));
-    TASKQUEUE_STATS_ONLY(stats.record_push());
-    return true;
-  } else {
-    return push_slow(t, dirty_n_elems);
-  }
-}
-
-template<class E, MEMFLAGS F, unsigned int N> inline bool
-GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
-  uint localBot = _bottom;
-  // This value cannot be N-1.  That can only occur as a result of
-  // the assignment to bottom in this method.  If it does, this method
-  // resets the size to 0 before the next call (which is sequential,
-  // since this is pop_local.)
-  uint dirty_n_elems = dirty_size(localBot, _age.top());
-  assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
-  if (dirty_n_elems == 0) return false;
-  localBot = decrement_index(localBot);
-  _bottom = localBot;
-  // This is necessary to prevent any read below from being reordered
-  // before the store just above.
-  OrderAccess::fence();
-  // g++ complains if the volatile result of the assignment is
-  // unused, so we cast the volatile away.  We cannot cast directly
-  // to void, because gcc treats that as not using the result of the
-  // assignment.  However, casting to E& means that we trigger an
-  // unused-value warning.  So, we cast the E& to void.
-  (void) const_cast<E&>(t = _elems[localBot]);
-  // This is a second read of "age"; the "size()" above is the first.
-  // If there's still at least one element in the queue, based on the
-  // "_bottom" and "age" we've read, then there can be no interference with
-  // a "pop_global" operation, and we're done.
-  idx_t tp = _age.top();    // XXX
-  if (size(localBot, tp) > 0) {
-    assert(dirty_size(localBot, tp) != N - 1, "sanity");
-    TASKQUEUE_STATS_ONLY(stats.record_pop());
-    return true;
-  } else {
-    // Otherwise, the queue contained exactly one element; we take the slow
-    // path.
-    return pop_local_slow(localBot, _age.get());
-  }
-}
-
 typedef GenericTaskQueue<oop, mtGC>             OopTaskQueue;
 typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/taskqueue.inline.hpp	Thu May 07 11:28:03 2015 -0700
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
+#define SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
+
+#include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/taskqueue.hpp"
+#include "utilities/stack.inline.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
+
+template <class T, MEMFLAGS F>
+inline GenericTaskQueueSet<T, F>::GenericTaskQueueSet(int n) : _n(n) {
+  typedef T* GenericTaskQueuePtr;
+  _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
+  for (int i = 0; i < n; i++) {
+    _queues[i] = NULL;
+  }
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline void GenericTaskQueue<E, F, N>::initialize() {
+  _elems = _array_allocator.allocate(N);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
+  FREE_C_HEAP_ARRAY(E, _elems);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
+  if (dirty_n_elems == N - 1) {
+    // Actually means 0, so do the push.
+    uint localBot = _bottom;
+    // g++ complains if the volatile result of the assignment is
+    // unused, so we cast the volatile away.  We cannot cast directly
+    // to void, because gcc treats that as not using the result of the
+    // assignment.  However, casting to E& means that we trigger an
+    // unused-value warning.  So, we cast the E& to void.
+    (void)const_cast<E&>(_elems[localBot] = t);
+    OrderAccess::release_store(&_bottom, increment_index(localBot));
+    TASKQUEUE_STATS_ONLY(stats.record_push());
+    return true;
+  }
+  return false;
+}
+
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::push(E t) {
+  uint localBot = _bottom;
+  assert(localBot < N, "_bottom out of range.");
+  idx_t top = _age.top();
+  uint dirty_n_elems = dirty_size(localBot, top);
+  assert(dirty_n_elems < N, "n_elems out of range.");
+  if (dirty_n_elems < max_elems()) {
+    // g++ complains if the volatile result of the assignment is
+    // unused, so we cast the volatile away.  We cannot cast directly
+    // to void, because gcc treats that as not using the result of the
+    // assignment.  However, casting to E& means that we trigger an
+    // unused-value warning.  So, we cast the E& to void.
+    (void) const_cast<E&>(_elems[localBot] = t);
+    OrderAccess::release_store(&_bottom, increment_index(localBot));
+    TASKQUEUE_STATS_ONLY(stats.record_push());
+    return true;
+  } else {
+    return push_slow(t, dirty_n_elems);
+  }
+}
+
+template <class E, MEMFLAGS F, unsigned int N>
+inline bool OverflowTaskQueue<E, F, N>::push(E t)
+{
+  if (!taskqueue_t::push(t)) {
+    overflow_stack()->push(t);
+    TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size()));
+  }
+  return true;
+}
+
+// pop_local_slow() is done by the owning thread and is trying to
+// get the last task in the queue.  It will compete with pop_global()
+// that will be used by other threads.  The tag age is incremented
+// whenever the queue goes empty which it will do here if this thread
+// gets the last task or in pop_global() if the queue wraps (top == 0
+// and pop_global() succeeds, see pop_global()).
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
+  // This queue was observed to contain exactly one element; either this
+  // thread will claim it, or a competing "pop_global".  In either case,
+  // the queue will be logically empty afterwards.  Create a new Age value
+  // that represents the empty queue for the given value of "_bottom".  (We
+  // must also increment "tag" because of the case where "bottom == 1",
+  // "top == 0".  A pop_global could read the queue element in that case,
+  // then have the owner thread do a pop followed by another push.  Without
+  // the incrementing of "tag", the pop_global's CAS could succeed,
+  // allowing it to believe it has claimed the stale element.)
+  Age newAge((idx_t)localBot, oldAge.tag() + 1);
+  // Perhaps a competing pop_global has already incremented "top", in which
+  // case it wins the element.
+  if (localBot == oldAge.top()) {
+    // No competing pop_global has yet incremented "top"; we'll try to
+    // install new_age, thus claiming the element.
+    Age tempAge = _age.cmpxchg(newAge, oldAge);
+    if (tempAge == oldAge) {
+      // We win.
+      assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
+      TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
+      return true;
+    }
+  }
+  // We lose; a completing pop_global gets the element.  But the queue is empty
+  // and top is greater than bottom.  Fix this representation of the empty queue
+  // to become the canonical one.
+  _age.set(newAge);
+  assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
+  return false;
+}
+
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
+  uint localBot = _bottom;
+  // This value cannot be N-1.  That can only occur as a result of
+  // the assignment to bottom in this method.  If it does, this method
+  // resets the size to 0 before the next call (which is sequential,
+  // since this is pop_local.)
+  uint dirty_n_elems = dirty_size(localBot, _age.top());
+  assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
+  if (dirty_n_elems == 0) return false;
+  localBot = decrement_index(localBot);
+  _bottom = localBot;
+  // This is necessary to prevent any read below from being reordered
+  // before the store just above.
+  OrderAccess::fence();
+  // g++ complains if the volatile result of the assignment is
+  // unused, so we cast the volatile away.  We cannot cast directly
+  // to void, because gcc treats that as not using the result of the
+  // assignment.  However, casting to E& means that we trigger an
+  // unused-value warning.  So, we cast the E& to void.
+  (void) const_cast<E&>(t = _elems[localBot]);
+  // This is a second read of "age"; the "size()" above is the first.
+  // If there's still at least one element in the queue, based on the
+  // "_bottom" and "age" we've read, then there can be no interference with
+  // a "pop_global" operation, and we're done.
+  idx_t tp = _age.top();    // XXX
+  if (size(localBot, tp) > 0) {
+    assert(dirty_size(localBot, tp) != N - 1, "sanity");
+    TASKQUEUE_STATS_ONLY(stats.record_pop());
+    return true;
+  } else {
+    // Otherwise, the queue contained exactly one element; we take the slow
+    // path.
+    return pop_local_slow(localBot, _age.get());
+  }
+}
+
+template <class E, MEMFLAGS F, unsigned int N>
+bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
+{
+  if (overflow_empty()) return false;
+  t = overflow_stack()->pop();
+  return true;
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
+  Age oldAge = _age.get();
+  // Architectures with weak memory model require a barrier here
+  // to guarantee that bottom is not older than age,
+  // which is crucial for the correctness of the algorithm.
+#if !(defined SPARC || defined IA32 || defined AMD64)
+  OrderAccess::fence();
+#endif
+  uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
+  uint n_elems = size(localBot, oldAge.top());
+  if (n_elems == 0) {
+    return false;
+  }
+
+  // g++ complains if the volatile result of the assignment is
+  // unused, so we cast the volatile away.  We cannot cast directly
+  // to void, because gcc treats that as not using the result of the
+  // assignment.  However, casting to E& means that we trigger an
+  // unused-value warning.  So, we cast the E& to void.
+  (void) const_cast<E&>(t = _elems[oldAge.top()]);
+  Age newAge(oldAge);
+  newAge.increment();
+  Age resAge = _age.cmpxchg(newAge, oldAge);
+
+  // Note that using "_bottom" here might fail, since a pop_local might
+  // have decremented it.
+  assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
+  return resAge == oldAge;
+}
+
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
+  if (_n > 2) {
+    uint k1 = queue_num;
+    while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
+    uint k2 = queue_num;
+    while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
+    // Sample both and try the larger.
+    uint sz1 = _queues[k1]->size();
+    uint sz2 = _queues[k2]->size();
+    if (sz2 > sz1) return _queues[k2]->pop_global(t);
+    else return _queues[k1]->pop_global(t);
+  } else if (_n == 2) {
+    // Just try the other one.
+    uint k = (queue_num + 1) % 2;
+    return _queues[k]->pop_global(t);
+  } else {
+    assert(_n == 1, "can't be zero.");
+    return false;
+  }
+}
+
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
+  for (uint i = 0; i < 2 * _n; i++) {
+    if (steal_best_of_2(queue_num, seed, t)) {
+      TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
+      return true;
+    }
+  }
+  TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
+  return false;
+}
+
+template <unsigned int N, MEMFLAGS F>
+inline typename TaskQueueSuper<N, F>::Age TaskQueueSuper<N, F>::Age::cmpxchg(const Age new_age, const Age old_age) volatile {
+  return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
+                                      (volatile intptr_t *)&_data,
+                                      (intptr_t)old_age._data);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
+  // tty->print_cr("START OopTaskQueue::oops_do");
+  uint iters = size();
+  uint index = _bottom;
+  for (uint i = 0; i < iters; ++i) {
+    index = decrement_index(index);
+    // tty->print_cr("  doing entry %d," INTPTR_T " -> " INTPTR_T,
+    //            index, &_elems[index], _elems[index]);
+    E* t = (E*)&_elems[index];      // cast away volatility
+    oop* p = (oop*)t;
+    assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
+    f->do_oop(p);
+  }
+  // tty->print_cr("END OopTaskQueue::oops_do");
+}
+
+
+#endif // SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
--- a/hotspot/src/share/vm/utilities/workgroup.cpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/workgroup.cpp	Thu May 07 11:28:03 2015 -0700
@@ -29,8 +29,6 @@
 #include "runtime/os.hpp"
 #include "utilities/workgroup.hpp"
 
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
 // Definitions of WorkGang methods.
 
 AbstractWorkGang::AbstractWorkGang(const char* name,
@@ -155,7 +153,7 @@
   // Wait for them to be finished
   while (finished_workers() < no_of_parallel_workers) {
     if (TraceWorkGang) {
-      tty->print_cr("Waiting in work gang %s: %d/%d finished sequence %d",
+      tty->print_cr("Waiting in work gang %s: %u/%u finished sequence %d",
                     name(), finished_workers(), no_of_parallel_workers,
                     _sequence_number);
     }
@@ -163,11 +161,11 @@
   }
   _task = NULL;
   if (TraceWorkGang) {
-    tty->print_cr("\nFinished work gang %s: %d/%d sequence %d",
+    tty->print_cr("\nFinished work gang %s: %u/%u sequence %d",
                   name(), finished_workers(), no_of_parallel_workers,
                   _sequence_number);
     Thread* me = Thread::current();
-    tty->print_cr("  T: 0x%x  VM_thread: %d", me, me->is_VM_thread());
+    tty->print_cr("  T: " PTR_FORMAT "  VM_thread: %d", p2i(me), me->is_VM_thread());
   }
 }
 
@@ -190,7 +188,7 @@
   monitor()->notify_all();
   while (finished_workers() < active_workers()) {
     if (TraceWorkGang) {
-      tty->print_cr("Waiting in work gang %s: %d/%d finished",
+      tty->print_cr("Waiting in work gang %s: %u/%u finished",
                     name(), finished_workers(), active_workers());
     }
     monitor()->wait(/* no_safepoint_check */ true);
@@ -251,7 +249,7 @@
   assert(_gang != NULL, "No gang to run in");
   os::set_priority(this, NearMaxPriority);
   if (TraceWorkGang) {
-    tty->print_cr("Running gang worker for gang %s id %d",
+    tty->print_cr("Running gang worker for gang %s id %u",
                   gang()->name(), id());
   }
   // The VM thread should not execute here because MutexLocker's are used
@@ -274,7 +272,7 @@
       // in the outer loop.
       gang()->internal_worker_poll(&data);
       if (TraceWorkGang) {
-        tty->print("Polled outside for work in gang %s worker %d",
+        tty->print("Polled outside for work in gang %s worker %u",
                    gang()->name(), id());
         tty->print("  terminate: %s",
                    data.terminate() ? "true" : "false");
@@ -308,7 +306,7 @@
         gang_monitor->wait(/* no_safepoint_check */ true);
         gang()->internal_worker_poll(&data);
         if (TraceWorkGang) {
-          tty->print("Polled inside for work in gang %s worker %d",
+          tty->print("Polled inside for work in gang %s worker %u",
                      gang()->name(), id());
           tty->print("  terminate: %s",
                      data.terminate() ? "true" : "false");
@@ -325,14 +323,14 @@
       // Drop gang mutex.
     }
     if (TraceWorkGang) {
-      tty->print("Work for work gang %s id %d task %s part %d",
+      tty->print("Work for work gang %s id %u task %s part %d",
                  gang()->name(), id(), data.task()->name(), part);
     }
     assert(data.task() != NULL, "Got null task");
     data.task()->work(part);
     {
       if (TraceWorkGang) {
-        tty->print("Finish for work gang %s id %d task %s part %d",
+        tty->print("Finish for work gang %s id %u task %s part %d",
                    gang()->name(), id(), data.task()->name(), part);
       }
       // Grab the gang mutex.
--- a/hotspot/src/share/vm/utilities/workgroup.hpp	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/workgroup.hpp	Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@
   // and may inherit this method that does nothing.  Some
   // tasks do some coordination on termination and override
   // this method to implement that coordination.
-  virtual void set_for_termination(int active_workers) {};
+  virtual void set_for_termination(uint active_workers) {};
 
   // Debugging accessor for the name.
   const char* name() const PRODUCT_RETURN_(return NULL;);
@@ -102,7 +102,7 @@
   AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues) :
     AbstractGangTask(name), _queues(queues), _terminator(0, _queues) {}
   ParallelTaskTerminator* terminator() { return &_terminator; }
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     terminator()->reset_for_reuse(active_workers);
   }
   OopTaskQueueSet* queues() { return _queues; }
--- a/hotspot/test/Makefile	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/Makefile	Thu May 07 11:28:03 2015 -0700
@@ -28,8 +28,6 @@
 
 ALT_MAKE ?= closed
 
--include $(ALT_MAKE)/Makefile
-
 GETMIXEDPATH=echo
 
 # Utilities used
@@ -306,6 +304,8 @@
 endif
 JTREG_BASIC_OPTIONS += $(JTREG_KEY_OPTION)
 
+-include $(ALT_MAKE)/Makefile
+
 # Make sure jtreg exists
 $(JTREG): $(JT_HOME)
 
@@ -405,15 +405,6 @@
 
 ################################################################
 
-# internalvmtests (run internal unit tests inside the VM)
-
-hotspot_internalvmtests internalvmtests: prep $(PRODUCT_HOME)
-	$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -XX:+ExecuteInternalVMTests -version
-
-PHONY_LIST += hotspot_internalvmtests internalvmtests
-
-################################################################
-
 # Phony targets (e.g. these are not filenames)
 .PHONY: all clean prep $(PHONY_LIST)
 
--- a/hotspot/test/TEST.groups	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/TEST.groups	Thu May 07 11:28:03 2015 -0700
@@ -233,6 +233,7 @@
   gc/arguments/TestParallelGCThreads.java \
   gc/arguments/TestUseCompressedOopsErgo.java \
   gc/class_unloading/TestG1ClassUnloadingHWM.java \
+  gc/ergonomics/TestDynamicNumberOfGCThreads.java
   gc/g1/ \
   gc/metaspace/G1AddMetaspaceDependency.java \
   gc/metaspace/TestMetaspacePerfCounters.java \
@@ -262,6 +263,7 @@
   gc/arguments/TestMinInitialErgonomics.java \
   gc/arguments/TestParallelGCThreads.java \
   gc/arguments/TestUseCompressedOopsErgo.java \
+  gc/ergonomics/TestDynamicNumberOfGCThreads.java
   gc/metaspace/TestMetaspacePerfCounters.java \
   gc/parallelScavenge/ \
   gc/startup_warnings/TestParallelGC.java \
@@ -279,6 +281,7 @@
   gc/arguments/TestUseCompressedOopsErgo.java \
   gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java \
   gc/concurrentMarkSweep/ \
+  gc/ergonomics/TestDynamicNumberOfGCThreads.java
   gc/startup_warnings/TestCMS.java \
   gc/startup_warnings/TestDefNewCMS.java \
   gc/startup_warnings/TestParNewCMS.java
--- a/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java	Thu May 07 11:28:03 2015 -0700
@@ -28,29 +28,30 @@
  * @library /testlibrary
  * @modules java.base/sun.misc
  *          java.management
- * @ignore 8073669
  * @build TestSoftReferencesBehaviorOnOOME
  * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 512 2k
  * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 128k 256k
- * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k 10
+ * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k
  */
 import com.oracle.java.testlibrary.Utils;
+import com.oracle.java.testlibrary.Asserts;
 import java.lang.ref.SoftReference;
 import java.util.LinkedList;
 import java.util.Random;
 
 public class TestSoftReferencesBehaviorOnOOME {
 
-    private static final Random rndGenerator = Utils.getRandomInstance();
-
+    /**
+     * Test generates a lot of soft references to objects with random payloads.
+     * Then it provokes OOME and checks that all SoftReferences has been gone
+     * @param args - [minSize] [maxSize] [freq]
+     *  where
+     *  - minSize - min size of random objects
+     *  - maxSize - max size of random objects
+     */
     public static void main(String[] args) {
-        int semiRefAllocFrequency = DEFAULT_FREQUENCY;
-        long minSize = DEFAULT_MIN_SIZE,
-                maxSize = DEFAULT_MAX_SIZE;
-
-        if ( args.length >= 3 ) {
-            semiRefAllocFrequency = Integer.parseInt(args[2]);
-        }
+        long minSize = DEFAULT_MIN_SIZE;
+        long maxSize = DEFAULT_MAX_SIZE;
 
         if ( args.length >= 2) {
             maxSize = getBytesCount(args[1]);
@@ -60,46 +61,49 @@
             minSize = getBytesCount(args[0]);
         }
 
-        new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize, semiRefAllocFrequency);
+        new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize);
     }
 
     /**
      * Test that all SoftReferences has been cleared at time of OOM.
      */
-    void softReferencesOom(long minSize, long maxSize, int semiRefAllocFrequency) {
-        System.out.format( "minSize = %d, maxSize = %d, freq = %d%n", minSize, maxSize, semiRefAllocFrequency );
-        long counter = 0;
+    void softReferencesOom(long minSize, long maxSize) {
+        System.out.format( "minSize = %d, maxSize = %d%n", minSize, maxSize );
+
+        LinkedList<SoftReference> arrSoftRefs = new LinkedList();
+        staticRef = arrSoftRefs;
+        LinkedList arrObjects = new LinkedList();
+        staticRef = arrObjects;
 
         long multiplier = maxSize - minSize;
-        LinkedList<SoftReference> arrSoftRefs = new LinkedList();
-        LinkedList arrObjects = new LinkedList();
         long numberOfNotNulledObjects = 0;
-        long oomSoftArraySize = 0;
 
         try {
-            while (true) {
-                // Keep every Xth object to make sure we hit OOM pretty fast
-                if (counter % semiRefAllocFrequency != 0) {
-                    long allocationSize = ((int) (rndGenerator.nextDouble() * multiplier))
-                            + minSize;
-                    arrObjects.add(new byte[(int)allocationSize]);
-                } else {
-                    arrSoftRefs.add(new SoftReference(new Object()));
-                }
+
+            // Lets allocate as many as we can - taking size of all SoftRerefences
+            // by minimum. So it can provoke some GC but we surely will allocate enough.
+            long numSofts = (long) ((0.95 * Runtime.getRuntime().totalMemory()) / minSize);
+            System.out.println("num Soft: " + numSofts);
+
+            while (numSofts-- > 0) {
+                int allocationSize = ((int) (RND_GENERATOR.nextDouble() * multiplier))
+                            + (int)minSize;
+                arrSoftRefs.add(new SoftReference(new byte[allocationSize]));
+            }
 
-                counter++;
-                if (counter == Long.MAX_VALUE) {
-                    counter = 0;
-                }
+            System.out.println("free: " + Runtime.getRuntime().freeMemory());
+
+            // provoke OOME.
+            while (true) {
+                arrObjects.add(new byte[(int) Runtime.getRuntime().totalMemory()]);
             }
+
         } catch (OutOfMemoryError oome) {
+
             // Clear allocated ballast, so we don't get another OOM.
-
+            staticRef = null;
             arrObjects = null;
-
-            // Get the number of soft refs first, so we don't trigger
-            // another OOM.
-            oomSoftArraySize = arrSoftRefs.size();
+            long oomSoftArraySize = arrSoftRefs.size();
 
             for (SoftReference sr : arrSoftRefs) {
                 Object o = sr.get();
@@ -111,15 +115,14 @@
 
             // Make sure we clear all refs before we return failure
             arrSoftRefs = null;
-
-            if (numberOfNotNulledObjects > 0) {
-                throw new RuntimeException(numberOfNotNulledObjects + " out of "
-                        + oomSoftArraySize + " SoftReferences was not "
-                        + "null at time of OutOfMemoryError");
-            }
+            Asserts.assertFalse(numberOfNotNulledObjects > 0,
+                    "" + numberOfNotNulledObjects + " out of "
+                    + oomSoftArraySize + " SoftReferences was not "
+                    + "null at time of OutOfMemoryError"
+            );
         } finally {
-            arrSoftRefs = null;
-            arrObjects = null;
+            Asserts.assertTrue(arrObjects == null, "OOME hasn't been provoked");
+            Asserts.assertTrue(arrSoftRefs == null, "OOME hasn't been provoked");
         }
     }
 
@@ -128,9 +131,7 @@
         long mod = 1;
 
         if (arg.trim().length() >= 2) {
-            mod = postfixes.indexOf(
-                    arg.trim().charAt(arg.length() - 1)
-            );
+            mod = postfixes.indexOf(arg.trim().charAt(arg.length() - 1));
 
             if (mod != -1) {
                 mod = (long) Math.pow(1024, mod+1);
@@ -143,7 +144,8 @@
         return Long.parseLong(arg) * mod;
     }
 
+    private static final Random RND_GENERATOR = Utils.getRandomInstance();
     private static final long DEFAULT_MIN_SIZE = 512;
     private static final long DEFAULT_MAX_SIZE = 1024;
-    private static final int DEFAULT_FREQUENCY = 4;
+    private static Object staticRef; // to prevent compile optimisations
 }
--- a/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Thu May 07 11:28:03 2015 -0700
@@ -44,14 +44,24 @@
   }
 
   private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output) {
+    output.shouldHaveExitValue(0); // test should run succesfully
     output.shouldContain("new_active_workers");
-    output.shouldHaveExitValue(0);
   }
 
   private static void testDynamicNumberOfGCThreads(String gcFlag) throws Exception {
     // UseDynamicNumberOfGCThreads and TraceDynamicGCThreads enabled
-    ProcessBuilder pb_enabled =
-      ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-Xmx10M", "-XX:+PrintGCDetails",  "-XX:+UseDynamicNumberOfGCThreads", "-XX:+TraceDynamicGCThreads", GCTest.class.getName());
+    String[] baseArgs = {"-XX:+" + gcFlag, "-Xmx10M", "-XX:+PrintGCDetails",  "-XX:+UseDynamicNumberOfGCThreads", "-XX:+TraceDynamicGCThreads", GCTest.class.getName()};
+
+    // Base test with gc and +UseDynamicNumberOfGCThreads:
+    ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(baseArgs);
+    verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
+
+    // Ensure it also works on uniprocessors or if user specifies -XX:ParallelGCThreads=1:
+    String[] extraArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+ForceDynamicNumberOfGCThreads", "-XX:ParallelGCThreads=1"};
+    String[] finalArgs = new String[baseArgs.length + extraArgs.length];
+    System.arraycopy(extraArgs, 0, finalArgs, 0,                extraArgs.length);
+    System.arraycopy(baseArgs,  0, finalArgs, extraArgs.length, baseArgs.length);
+    pb_enabled = ProcessTools.createJavaProcessBuilder(finalArgs);
     verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
   }
 
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java	Thu May 07 11:28:03 2015 -0700
@@ -76,7 +76,6 @@
         printTestInfo(maxCacheSize);
 
         vmOpts.add("-XX:G1ConcRSLogCacheSize=" + hotCardTableSize);
-        vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
 
         // for 32 bits ObjectAlignmentInBytes is not a option
         if (Platform.is32bit()) {
@@ -98,7 +97,7 @@
 
     private void performTest(List<String> opts) throws Exception {
         ProcessBuilder pb
-                = ProcessTools.createJavaProcessBuilder(
+                = ProcessTools.createJavaProcessBuilder(true,
                         opts.toArray(new String[opts.size()])
                 );
 
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java	Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData05
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java	Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData10
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java	Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData15
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java	Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData20
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java	Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData25
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java	Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java	Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData30
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"