changeset 7372:5efc25c36716 hs25.60-b17

Merge
author amurillo
date Thu, 21 May 2015 22:54:21 -0700
parents a20bd9718799 (current diff) b6ca1802dc7c (diff)
children c26d09f1065c
files test/gc/g1/TestEagerReclaimHumongousRegions2.java test/gc/g1/TestG1TraceReclaimDeadHumongousObjectsAtYoungGC.java
diffstat 42 files changed, 1357 insertions(+), 793 deletions(-) [+]
line wrap: on
line diff
--- a/make/hotspot_version	Thu May 21 10:00:37 2015 -0700
+++ b/make/hotspot_version	Thu May 21 22:54:21 2015 -0700
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=25
 HS_MINOR_VER=60
-HS_BUILD_NUMBER=16
+HS_BUILD_NUMBER=17
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/src/cpu/ppc/vm/ppc.ad	Thu May 21 10:00:37 2015 -0700
+++ b/src/cpu/ppc/vm/ppc.ad	Thu May 21 22:54:21 2015 -0700
@@ -2264,9 +2264,8 @@
 
 // Do we need to mask the count passed to shift instructions or does
 // the cpu only look at the lower 5/6 bits anyway?
-// Off, as masks are generated in expand rules where required.
-// Constant shift counts are handled in Ideal phase.
-const bool Matcher::need_masked_shift_count = false;
+// PowerPC requires masked shift counts.
+const bool Matcher::need_masked_shift_count = true;
 
 // This affects two different things:
 //  - how Decode nodes are matched
--- a/src/os/aix/vm/os_aix.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/os/aix/vm/os_aix.cpp	Thu May 21 22:54:21 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -3727,6 +3727,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if (os::Aix::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Aix::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Aix::get_our_sigflags(sig));
--- a/src/os/bsd/vm/os_bsd.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/os/bsd/vm/os_bsd.cpp	Thu May 21 22:54:21 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -3551,6 +3551,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if(os::Bsd::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Bsd::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Bsd::get_our_sigflags(sig));
--- a/src/os/linux/vm/os_linux.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/os/linux/vm/os_linux.cpp	Thu May 21 22:54:21 2015 -0700
@@ -4635,6 +4635,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if(os::Linux::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Linux::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Linux::get_our_sigflags(sig));
--- a/src/os/solaris/vm/os_solaris.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/os/solaris/vm/os_solaris.cpp	Thu May 21 22:54:21 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
@@ -4593,6 +4593,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if(os::Solaris::get_our_sigflags(sig) != 0 && act.sa_flags != os::Solaris::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Solaris::get_our_sigflags(sig));
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu May 21 22:54:21 2015 -0700
@@ -2640,24 +2640,41 @@
   _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;
@@ -2665,7 +2682,9 @@
 
  public:
   G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task, bool is_par) :
-    _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(SharedHeap::heap()->strong_roots_parity()), _is_par(is_par) {}
 
   void do_thread(Thread* thread) {
@@ -2681,11 +2700,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(_is_par, _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);
       }
     }
   }
@@ -3059,9 +3078,7 @@
 #ifndef PRODUCT
 enum VerifyNoCSetOopsPhase {
   VerifyNoCSetOopsStack,
-  VerifyNoCSetOopsQueues,
-  VerifyNoCSetOopsSATBCompleted,
-  VerifyNoCSetOopsSATBThread
+  VerifyNoCSetOopsQueues
 };
 
 class VerifyNoCSetOopsClosure : public OopClosure, public ObjectClosure  {
@@ -3074,8 +3091,6 @@
     switch (_phase) {
     case VerifyNoCSetOopsStack:         return "Stack";
     case VerifyNoCSetOopsQueues:        return "Queue";
-    case VerifyNoCSetOopsSATBCompleted: return "Completed SATB Buffers";
-    case VerifyNoCSetOopsSATBThread:    return "Thread SATB Buffers";
     default:                            ShouldNotReachHere();
     }
     return NULL;
@@ -3102,7 +3117,7 @@
 
   virtual void do_oop(narrowOop* p) {
     // We should not come across narrow oops while scanning marking
-    // stacks and SATB buffers.
+    // stacks
     ShouldNotReachHere();
   }
 
@@ -3111,10 +3126,7 @@
   }
 };
 
-void ConcurrentMark::verify_no_cset_oops(bool verify_stacks,
-                                         bool verify_enqueued_buffers,
-                                         bool verify_thread_buffers,
-                                         bool verify_fingers) {
+void ConcurrentMark::verify_no_cset_oops() {
   assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
   if (!G1CollectedHeap::heap()->mark_in_progress()) {
     return;
@@ -3122,65 +3134,47 @@
 
   VerifyNoCSetOopsClosure cl;
 
-  if (verify_stacks) {
-    // Verify entries on the global mark stack
-    cl.set_phase(VerifyNoCSetOopsStack);
-    _markStack.oops_do(&cl);
-
-    // Verify entries on the task queues
-    for (uint i = 0; i < _max_worker_id; i += 1) {
-      cl.set_phase(VerifyNoCSetOopsQueues, i);
-      CMTaskQueue* queue = _task_queues->queue(i);
-      queue->oops_do(&cl);
-    }
-  }
-
-  SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
-
-  // Verify entries on the enqueued SATB buffers
-  if (verify_enqueued_buffers) {
-    cl.set_phase(VerifyNoCSetOopsSATBCompleted);
-    satb_qs.iterate_completed_buffers_read_only(&cl);
-  }
-
-  // Verify entries on the per-thread SATB buffers
-  if (verify_thread_buffers) {
-    cl.set_phase(VerifyNoCSetOopsSATBThread);
-    satb_qs.iterate_thread_buffers_read_only(&cl);
+  // Verify entries on the global mark stack
+  cl.set_phase(VerifyNoCSetOopsStack);
+  _markStack.oops_do(&cl);
+
+  // Verify entries on the task queues
+  for (uint i = 0; i < _max_worker_id; i += 1) {
+    cl.set_phase(VerifyNoCSetOopsQueues, i);
+    CMTaskQueue* queue = _task_queues->queue(i);
+    queue->oops_do(&cl);
   }
 
-  if (verify_fingers) {
-    // Verify the global finger
-    HeapWord* global_finger = finger();
-    if (global_finger != NULL && global_finger < _heap_end) {
-      // The global finger always points to a heap region boundary. We
-      // use heap_region_containing_raw() to get the containing region
-      // given that the global finger could be pointing to a free region
-      // which subsequently becomes continues humongous. If that
-      // happens, heap_region_containing() will return the bottom of the
-      // corresponding starts humongous region and the check below will
-      // not hold any more.
-      // Since we always iterate over all regions, we might get a NULL HeapRegion
-      // here.
-      HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger);
-      guarantee(global_hr == NULL || global_finger == global_hr->bottom(),
-                err_msg("global finger: "PTR_FORMAT" region: "HR_FORMAT,
-                        p2i(global_finger), HR_FORMAT_PARAMS(global_hr)));
-    }
-
-    // Verify the task fingers
-    assert(parallel_marking_threads() <= _max_worker_id, "sanity");
-    for (int i = 0; i < (int) parallel_marking_threads(); i += 1) {
-      CMTask* task = _tasks[i];
-      HeapWord* task_finger = task->finger();
-      if (task_finger != NULL && task_finger < _heap_end) {
-        // See above note on the global finger verification.
-        HeapRegion* task_hr = _g1h->heap_region_containing_raw(task_finger);
-        guarantee(task_hr == NULL || task_finger == task_hr->bottom() ||
-                  !task_hr->in_collection_set(),
-                  err_msg("task finger: "PTR_FORMAT" region: "HR_FORMAT,
-                          p2i(task_finger), HR_FORMAT_PARAMS(task_hr)));
-      }
+  // Verify the global finger
+  HeapWord* global_finger = finger();
+  if (global_finger != NULL && global_finger < _heap_end) {
+    // The global finger always points to a heap region boundary. We
+    // use heap_region_containing_raw() to get the containing region
+    // given that the global finger could be pointing to a free region
+    // which subsequently becomes continues humongous. If that
+    // happens, heap_region_containing() will return the bottom of the
+    // corresponding starts humongous region and the check below will
+    // not hold any more.
+    // Since we always iterate over all regions, we might get a NULL HeapRegion
+    // here.
+    HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger);
+    guarantee(global_hr == NULL || global_finger == global_hr->bottom(),
+              err_msg("global finger: "PTR_FORMAT" region: "HR_FORMAT,
+                      p2i(global_finger), HR_FORMAT_PARAMS(global_hr)));
+  }
+
+  // Verify the task fingers
+  assert(parallel_marking_threads() <= _max_worker_id, "sanity");
+  for (int i = 0; i < (int) parallel_marking_threads(); i += 1) {
+    CMTask* task = _tasks[i];
+    HeapWord* task_finger = task->finger();
+    if (task_finger != NULL && task_finger < _heap_end) {
+      // See above note on the global finger verification.
+      HeapRegion* task_hr = _g1h->heap_region_containing_raw(task_finger);
+      guarantee(task_hr == NULL || task_finger == task_hr->bottom() ||
+                !task_hr->in_collection_set(),
+                err_msg("task finger: "PTR_FORMAT" region: "HR_FORMAT,
+                        p2i(task_finger), HR_FORMAT_PARAMS(task_hr)));
     }
   }
 }
@@ -3510,22 +3504,29 @@
 }
 #endif
 
-void CMTask::scan_object(oop obj) {
+template<bool scan>
+inline void CMTask::process_grey_object(oop obj) {
+  assert(scan || obj->is_typeArray(), "Skipping scan of grey non-typeArray");
   assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant");
 
   if (_cm->verbose_high()) {
-    gclog_or_tty->print_cr("[%u] we're scanning object "PTR_FORMAT,
+    gclog_or_tty->print_cr("[%u] processing grey object " PTR_FORMAT,
                            _worker_id, p2i((void*) obj));
   }
 
   size_t obj_size = obj->size();
   _words_scanned += obj_size;
 
-  obj->oop_iterate(_cm_oop_closure);
+  if (scan) {
+    obj->oop_iterate(_cm_oop_closure);
+  }
   statsOnly( ++_objs_scanned );
   check_limits();
 }
 
+template void CMTask::process_grey_object<true>(oop);
+template void CMTask::process_grey_object<false>(oop);
+
 // Closure for iteration over bitmaps
 class CMBitMapClosure : public BitMapClosure {
 private:
@@ -3994,34 +3995,18 @@
   // 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();
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    satb_mq_set.set_par_closure(_worker_id, &oc);
-  } else {
-    satb_mq_set.set_closure(&oc);
-  }
 
   // This keeps claiming and applying the closure to completed buffers
   // until we run out of buffers or we need to abort.
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    while (!has_aborted() &&
-           satb_mq_set.par_apply_closure_to_completed_buffer(_worker_id)) {
-      if (_cm->verbose_medium()) {
-        gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id);
-      }
-      statsOnly( ++_satb_buffers_processed );
-      regular_clock_call();
+  while (!has_aborted() &&
+         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);
     }
-  } else {
-    while (!has_aborted() &&
-           satb_mq_set.apply_closure_to_completed_buffer()) {
-      if (_cm->verbose_medium()) {
-        gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id);
-      }
-      statsOnly( ++_satb_buffers_processed );
-      regular_clock_call();
-    }
+    statsOnly( ++_satb_buffers_processed );
+    regular_clock_call();
   }
 
   _draining_satb_buffers = false;
@@ -4030,12 +4015,6 @@
          concurrent() ||
          satb_mq_set.completed_buffers_num() == 0, "invariant");
 
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    satb_mq_set.set_par_closure(_worker_id, NULL);
-  } else {
-    satb_mq_set.set_closure(NULL);
-  }
-
   // again, this was a potentially expensive operation, decrease the
   // limits to get the regular clock call early
   decrease_limits();
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Thu May 21 22:54:21 2015 -0700
@@ -793,14 +793,9 @@
   }
 
   // Verify that there are no CSet oops on the stacks (taskqueues /
-  // global mark stack), enqueued SATB buffers, per-thread SATB
-  // buffers, and fingers (global / per-task). The boolean parameters
-  // decide which of the above data structures to verify. If marking
-  // is not in progress, it's a no-op.
-  void verify_no_cset_oops(bool verify_stacks,
-                           bool verify_enqueued_buffers,
-                           bool verify_thread_buffers,
-                           bool verify_fingers) PRODUCT_RETURN;
+  // global mark stack) and fingers (global / per-task).
+  // If marking is not in progress, it's a no-op.
+  void verify_no_cset_oops() PRODUCT_RETURN;
 
   bool isPrevMarked(oop p) const {
     assert(p != NULL && p->is_oop(), "expected an oop");
@@ -1108,6 +1103,12 @@
   void regular_clock_call();
   bool concurrent() { return _concurrent; }
 
+  // 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(oop obj, HeapWord* global_finger) const;
+
+  template<bool scan> void process_grey_object(oop obj);
+
 public:
   // It resets the task; it should be called right at the beginning of
   // a marking phase.
@@ -1155,12 +1156,22 @@
 
   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.
-  void scan_object(oop obj);
+  void scan_object(oop obj) { process_grey_object<true>(obj); }
 
   // It pushes an object on the local queue.
   inline void push(oop obj);
--- a/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Thu May 21 22:54:21 2015 -0700
@@ -259,14 +259,87 @@
              ++_local_pushes );
 }
 
-// This determines whether the method below will check both the local
-// and global fingers when determining whether to push on the stack a
-// gray object (value 1) or whether it will only check the global one
-// (value 0). The tradeoffs are that the former will be a bit more
-// accurate and possibly push less on the stack, but it might also be
-// a little bit slower.
+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 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.
+
+    // Finger and region values are all NULL or all non-NULL.  We
+    // use _finger to check since we immediately use its value.
+    assert(_curr_region != NULL, "invariant");
+    assert(_region_limit != NULL, "invariant");
+    assert(_region_limit <= global_finger, "invariant");
+
+    // True if obj is less than the local finger, or is between
+    // the region limit and the global finger.
+    if (objAddr < _finger) {
+      return true;
+    } else if (objAddr < _region_limit) {
+      return false;
+    } // Else check global finger.
+  }
+  // Check global finger.
+  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));
+    }
 
-#define _CHECK_BOTH_FINGERS_      1
+    // 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()) {
@@ -274,7 +347,7 @@
                            _worker_id, p2i((void*) obj));
   }
 
-  ++_refs_reached;
+  increment_refs_reached();
 
   HeapWord* objAddr = (HeapWord*) obj;
   assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");
@@ -286,62 +359,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();
-
-#if _CHECK_BOTH_FINGERS_
-          // we will check both the local and global fingers
-
-          if (_finger != NULL && objAddr < _finger) {
-            if (_cm->verbose_high()) {
-              gclog_or_tty->print_cr("[%u] below the local finger ("PTR_FORMAT"), "
-                                     "pushing it", _worker_id, p2i(_finger));
-            }
-            push(obj);
-          } else if (_curr_region != NULL && objAddr < _region_limit) {
-            // do nothing
-          } else if (objAddr < global_finger) {
-            // 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
-            // passed 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 (_cm->verbose_high()) {
-              gclog_or_tty->print_cr("[%u] below the global finger "
-                                     "("PTR_FORMAT"), pushing it",
-                                     _worker_id, p2i(global_finger));
-            }
-            push(obj);
-          } else {
-            // do nothing
-          }
-#else // _CHECK_BOTH_FINGERS_
-          // we will only check the global finger
-
-          if (objAddr < global_finger) {
-            // see long comment above
-
-            if (_cm->verbose_high()) {
-              gclog_or_tty->print_cr("[%u] below the global finger "
-                                     "("PTR_FORMAT"), pushing it",
-                                     _worker_id, p2i(global_finger));
-            }
-            push(obj);
-          }
-#endif // _CHECK_BOTH_FINGERS_
-        }
+        make_reference_grey(obj, hr);
       }
     }
   }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu May 21 22:54:21 2015 -0700
@@ -1853,7 +1853,7 @@
   _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()),
   _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()),
   _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()),
-  _humongous_is_live(),
+  _humongous_reclaim_candidates(),
   _has_humongous_reclaim_candidates(false),
   _free_regions_coming(false),
   _young_list(new YoungList(this)),
@@ -2048,8 +2048,14 @@
 
   _g1h = this;
 
-  _in_cset_fast_test.initialize(_hrm.reserved().start(), _hrm.reserved().end(), HeapRegion::GrainBytes);
-  _humongous_is_live.initialize(_hrm.reserved().start(), _hrm.reserved().end(), HeapRegion::GrainBytes);
+  {
+    HeapWord* start = _hrm.reserved().start();
+    HeapWord* end = _hrm.reserved().end();
+    size_t granularity = HeapRegion::GrainBytes;
+
+    _in_cset_fast_test.initialize(start, end, granularity);
+    _humongous_reclaim_candidates.initialize(start, end, granularity);
+  }
 
   // Create the ConcurrentMark data structure and thread.
   // (Must do this late, so that "max_regions" is defined.)
@@ -2141,11 +2147,6 @@
   }
 }
 
-void G1CollectedHeap::clear_humongous_is_live_table() {
-  guarantee(G1ReclaimDeadHumongousObjectsAtYoungGC, "Should only be called if true");
-  _humongous_is_live.clear();
-}
-
 size_t G1CollectedHeap::conservative_max_heap_alignment() {
   return HeapRegion::max_region_size();
 }
@@ -3666,18 +3667,73 @@
   return g1_rem_set()->cardsScanned();
 }
 
-bool G1CollectedHeap::humongous_region_is_always_live(uint index) {
-  HeapRegion* region = region_at(index);
-  assert(region->startsHumongous(), "Must start a humongous object");
-  return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty();
-}
-
 class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
  private:
   size_t _total_humongous;
   size_t _candidate_humongous;
+
+  DirtyCardQueue _dcq;
+
+  // We don't nominate objects with many remembered set entries, on
+  // the assumption that such objects are likely still live.
+  bool is_remset_small(HeapRegion* region) const {
+    HeapRegionRemSet* const rset = region->rem_set();
+    return G1EagerReclaimHumongousObjectsWithStaleRefs
+      ? rset->occupancy_less_or_equal_than(G1RSetSparseRegionEntries)
+      : rset->is_empty();
+  }
+
+  bool is_typeArray_region(HeapRegion* region) const {
+    return oop(region->bottom())->is_typeArray();
+  }
+
+  bool humongous_region_is_candidate(G1CollectedHeap* heap, HeapRegion* region) const {
+    assert(region->startsHumongous(), "Must start a humongous object");
+
+    // Candidate selection must satisfy the following constraints
+    // while concurrent marking is in progress:
+    //
+    // * In order to maintain SATB invariants, an object must not be
+    // reclaimed if it was allocated before the start of marking and
+    // has not had its references scanned.  Such an object must have
+    // its references (including type metadata) scanned to ensure no
+    // live objects are missed by the marking process.  Objects
+    // allocated after the start of concurrent marking don't need to
+    // be scanned.
+    //
+    // * An object must not be reclaimed if it is on the concurrent
+    // mark stack.  Objects allocated after the start of concurrent
+    // marking are never pushed on the mark stack.
+    //
+    // Nominating only objects allocated after the start of concurrent
+    // marking is sufficient to meet both constraints.  This may miss
+    // some objects that satisfy the constraints, but the marking data
+    // structures don't support efficiently performing the needed
+    // additional tests or scrubbing of the mark stack.
+    //
+    // However, we presently only nominate is_typeArray() objects.
+    // A humongous object containing references induces remembered
+    // set entries on other regions.  In order to reclaim such an
+    // object, those remembered sets would need to be cleaned up.
+    //
+    // We also treat is_typeArray() objects specially, allowing them
+    // to be reclaimed even if allocated before the start of
+    // concurrent mark.  For this we rely on mark stack insertion to
+    // exclude is_typeArray() objects, preventing reclaiming an object
+    // that is in the mark stack.  We also rely on the metadata for
+    // such objects to be built-in and so ensured to be kept live.
+    // Frequent allocation and drop of large binary blobs is an
+    // important use case for eager reclaim, and this special handling
+    // may reduce needed headroom.
+
+    return is_typeArray_region(region) && is_remset_small(region);
+  }
+
  public:
-  RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) {
+  RegisterHumongousWithInCSetFastTestClosure()
+  : _total_humongous(0),
+    _candidate_humongous(0),
+    _dcq(&JavaThread::dirty_card_queue_set()) {
   }
 
   virtual bool doHeapRegion(HeapRegion* r) {
@@ -3686,14 +3742,33 @@
     }
     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-    uint region_idx = r->hrm_index();
-    bool is_candidate = !g1h->humongous_region_is_always_live(region_idx);
-    // Is_candidate already filters out humongous regions with some remembered set.
-    // This will not lead to humongous object that we mistakenly keep alive because
-    // during young collection the remembered sets will only be added to.
+    bool is_candidate = humongous_region_is_candidate(g1h, r);
+    uint rindex = r->hrm_index();
+    g1h->set_humongous_reclaim_candidate(rindex, is_candidate);
     if (is_candidate) {
-      g1h->register_humongous_region_with_in_cset_fast_test(region_idx);
       _candidate_humongous++;
+      g1h->register_humongous_region_with_in_cset_fast_test(rindex);
+      // Is_candidate already filters out humongous object with large remembered sets.
+      // If we have a humongous object with a few remembered sets, we simply flush these
+      // remembered set entries into the DCQS. That will result in automatic
+      // re-evaluation of their remembered set entries during the following evacuation
+      // phase.
+      if (!r->rem_set()->is_empty()) {
+        guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries),
+                  "Found a not-small remembered set here. This is inconsistent with previous assumptions.");
+        G1SATBCardTableLoggingModRefBS* bs = g1h->g1_barrier_set();
+        HeapRegionRemSetIterator hrrs(r->rem_set());
+        size_t card_index;
+        while (hrrs.has_next(card_index)) {
+          jbyte* card_ptr = (jbyte*)bs->byte_for_index(card_index);
+          if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
+            *card_ptr = CardTableModRefBS::dirty_card_val();
+            _dcq.enqueue(card_ptr);
+          }
+        }
+        r->rem_set()->clear_locked();
+      }
+      assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty.");
     }
     _total_humongous++;
 
@@ -3702,23 +3777,29 @@
 
   size_t total_humongous() const { return _total_humongous; }
   size_t candidate_humongous() const { return _candidate_humongous; }
+
+  void flush_rem_set_entries() { _dcq.flush(); }
 };
 
 void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() {
-  if (!G1ReclaimDeadHumongousObjectsAtYoungGC) {
-    g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0);
+  if (!G1EagerReclaimHumongousObjects) {
+    g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0);
     return;
   }
-
+  double time = os::elapsed_counter();
+
+  // Collect reclaim candidate information and register candidates with cset.
   RegisterHumongousWithInCSetFastTestClosure cl;
   heap_region_iterate(&cl);
-  g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(),
+
+  time = ((double)(os::elapsed_counter() - time) / os::elapsed_frequency()) * 1000.0;
+  g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(time,
+                                                                  cl.total_humongous(),
                                                                   cl.candidate_humongous());
   _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
 
-  if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
-    clear_humongous_is_live_table();
-  }
+  // Finally flush all remembered set entries to re-check into the global DCQS.
+  cl.flush_rem_set_entries();
 }
 
 void
@@ -4012,14 +4093,9 @@
         assert(check_cset_fast_test(), "Inconsistency in the InCSetState table.");
 
         _cm->note_start_of_gc();
-        // We should not verify the per-thread SATB buffers given that
-        // we have not filtered them yet (we'll do so during the
-        // GC). We also call this after finalize_cset() to
+        // We call this after finalize_cset() to
         // ensure that the CSet has been finalized.
-        _cm->verify_no_cset_oops(true  /* verify_stacks */,
-                                 true  /* verify_enqueued_buffers */,
-                                 false /* verify_thread_buffers */,
-                                 true  /* verify_fingers */);
+        _cm->verify_no_cset_oops();
 
         if (_hr_printer.is_active()) {
           HeapRegion* hr = g1_policy()->collection_set();
@@ -4042,16 +4118,6 @@
         // Actually do the work...
         evacuate_collection_set(evacuation_info);
 
-        // We do this to mainly verify the per-thread SATB buffers
-        // (which have been filtered by now) since we didn't verify
-        // them earlier. No point in re-checking the stacks / enqueued
-        // buffers given that the CSet has not changed since last time
-        // we checked.
-        _cm->verify_no_cset_oops(false /* verify_stacks */,
-                                 false /* verify_enqueued_buffers */,
-                                 true  /* verify_thread_buffers */,
-                                 true  /* verify_fingers */);
-
         free_collection_set(g1_policy()->collection_set(), evacuation_info);
 
         eagerly_reclaim_humongous_regions();
@@ -4134,10 +4200,7 @@
 
         // We redo the verification but now wrt to the new CSet which
         // has just got initialized after the previous CSet was freed.
-        _cm->verify_no_cset_oops(true  /* verify_stacks */,
-                                 true  /* verify_enqueued_buffers */,
-                                 true  /* verify_thread_buffers */,
-                                 true  /* verify_fingers */);
+        _cm->verify_no_cset_oops();
         _cm->note_end_of_gc();
 
         // This timing is only used by the ergonomics to handle our pause target.
@@ -6273,49 +6336,47 @@
     // are completely up-to-date wrt to references to the humongous object.
     //
     // Other implementation considerations:
-    // - never consider object arrays: while they are a valid target, they have not
-    // been observed to be used as temporary objects.
-    // - they would also pose considerable effort for cleaning up the the remembered
-    // sets.
-    // While this cleanup is not strictly necessary to be done (or done instantly),
-    // given that their occurrence is very low, this saves us this additional
-    // complexity.
+    // - never consider object arrays at this time because they would pose
+    // considerable effort for cleaning up the the remembered sets. This is
+    // required because stale remembered sets might reference locations that
+    // are currently allocated into.
     uint region_idx = r->hrm_index();
-    if (g1h->humongous_is_live(region_idx) ||
-        g1h->humongous_region_is_always_live(region_idx)) {
-
-      if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
-        gclog_or_tty->print_cr("Live humongous %d region %d size "SIZE_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
-                               r->isHumongous(),
+    if (!g1h->is_humongous_reclaim_candidate(region_idx) ||
+        !r->rem_set()->is_empty()) {
+
+      if (G1TraceEagerReclaimHumongousObjects) {
+        gclog_or_tty->print_cr("Live humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d reclaim candidate %d type array %d",
                                region_idx,
                                obj->size()*HeapWordSize,
+                               r->bottom(),
+                               r->region_num(),
                                r->rem_set()->occupied(),
                                r->rem_set()->strong_code_roots_list_length(),
                                next_bitmap->isMarked(r->bottom()),
-                               g1h->humongous_is_live(region_idx),
-                               obj->is_objArray()
+                               g1h->is_humongous_reclaim_candidate(region_idx),
+                               obj->is_typeArray()
                               );
       }
 
       return false;
     }
 
-    guarantee(!obj->is_objArray(),
-              err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
+    guarantee(obj->is_typeArray(),
+              err_msg("Only eagerly reclaiming type arrays is supported, but the object "
+                      PTR_FORMAT " is not.",
                       r->bottom()));
 
-    if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
-      gclog_or_tty->print_cr("Reclaim humongous region %d size "SIZE_FORMAT" start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other ",
-                             r->isHumongous(),
+    if (G1TraceEagerReclaimHumongousObjects) {
+      gclog_or_tty->print_cr("Dead humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d reclaim candidate %d type array %d",
+                             region_idx,
                              obj->size()*HeapWordSize,
                              r->bottom(),
-                             region_idx,
                              r->region_num(),
                              r->rem_set()->occupied(),
                              r->rem_set()->strong_code_roots_list_length(),
                              next_bitmap->isMarked(r->bottom()),
-                             g1h->humongous_is_live(region_idx),
-                             obj->is_objArray()
+                             g1h->is_humongous_reclaim_candidate(region_idx),
+                             obj->is_typeArray()
                             );
     }
     // Need to clear mark bit of the humongous object if already set.
@@ -6346,8 +6407,8 @@
 void G1CollectedHeap::eagerly_reclaim_humongous_regions() {
   assert_at_safepoint(true);
 
-  if (!G1ReclaimDeadHumongousObjectsAtYoungGC ||
-      (!_has_humongous_reclaim_candidates && !G1TraceReclaimDeadHumongousObjectsAtYoungGC)) {
+  if (!G1EagerReclaimHumongousObjects ||
+      (!_has_humongous_reclaim_candidates && !G1TraceEagerReclaimHumongousObjects)) {
     g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0);
     return;
   }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu May 21 22:54:21 2015 -0700
@@ -233,7 +233,6 @@
   // It keeps track of the humongous regions.
   HeapRegionSet _humongous_set;
 
-  void clear_humongous_is_live_table();
   void eagerly_reclaim_humongous_regions();
 
   // The number of regions we could create by expansion.
@@ -303,22 +302,26 @@
   // Helper for monitoring and management support.
   G1MonitoringSupport* _g1mm;
 
-  // Records whether the region at the given index is kept live by roots or
-  // references from the young generation.
-  class HumongousIsLiveBiasedMappedArray : public G1BiasedMappedArray<bool> {
+  // Records whether the region at the given index is (still) a
+  // candidate for eager reclaim.  Only valid for humongous start
+  // regions; other regions have unspecified values.  Humongous start
+  // regions are initialized at start of collection pause, with
+  // candidates removed from the set as they are found reachable from
+  // roots or the young generation.
+  class HumongousReclaimCandidates : public G1BiasedMappedArray<bool> {
    protected:
     bool default_value() const { return false; }
    public:
     void clear() { G1BiasedMappedArray<bool>::clear(); }
-    void set_live(uint region) {
-      set_by_index(region, true);
+    void set_candidate(uint region, bool value) {
+      set_by_index(region, value);
     }
-    bool is_live(uint region) {
+    bool is_candidate(uint region) {
       return get_by_index(region);
     }
   };
 
-  HumongousIsLiveBiasedMappedArray _humongous_is_live;
+  HumongousReclaimCandidates _humongous_reclaim_candidates;
   // Stores whether during humongous object registration we found candidate regions.
   // If not, we can skip a few steps.
   bool _has_humongous_reclaim_candidates;
@@ -655,15 +658,15 @@
   virtual void gc_prologue(bool full);
   virtual void gc_epilogue(bool full);
 
+  // Modify the reclaim candidate set and test for presence.
+  // These are only valid for starts_humongous regions.
+  inline void set_humongous_reclaim_candidate(uint region, bool value);
+  inline bool is_humongous_reclaim_candidate(uint region);
+
+  // Remove from the reclaim candidate set.  Also remove from the
+  // collection set so that later encounters avoid the slow path.
   inline void set_humongous_is_live(oop obj);
 
-  bool humongous_is_live(uint region) {
-    return _humongous_is_live.is_live(region);
-  }
-
-  // Returns whether the given region (which must be a humongous (start) region)
-  // is to be considered conservatively live regardless of any other conditions.
-  bool humongous_region_is_always_live(uint index);
   // Register the given region to be part of the collection set.
   inline void register_humongous_region_with_in_cset_fast_test(uint index);
   // Register regions with humongous objects (actually on the start region) in
@@ -1106,6 +1109,10 @@
   // The number of regions that are completely free.
   uint num_free_regions() const { return _hrm.num_free_regions(); }
 
+  MemoryUsage get_auxiliary_data_memory_usage() const {
+    return _hrm.get_auxiliary_data_memory_usage();
+  }
+
   // The number of regions that are not completely free.
   uint num_used_regions() const { return num_regions() - num_free_regions(); }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Thu May 21 22:54:21 2015 -0700
@@ -348,20 +348,30 @@
   return is_obj_ill(obj, heap_region_containing(obj));
 }
 
+inline void G1CollectedHeap::set_humongous_reclaim_candidate(uint region, bool value) {
+  assert(_hrm.at(region)->startsHumongous(), "Must start a humongous object");
+  _humongous_reclaim_candidates.set_candidate(region, value);
+}
+
+inline bool G1CollectedHeap::is_humongous_reclaim_candidate(uint region) {
+  assert(_hrm.at(region)->startsHumongous(), "Must start a humongous object");
+  return _humongous_reclaim_candidates.is_candidate(region);
+}
+
 inline void G1CollectedHeap::set_humongous_is_live(oop obj) {
   uint region = addr_to_region((HeapWord*)obj);
-  // We not only set the "live" flag in the humongous_is_live table, but also
+  // Clear the flag in the humongous_reclaim_candidates table.  Also
   // reset the entry in the _in_cset_fast_test table so that subsequent references
   // to the same humongous object do not go into the slow path again.
   // This is racy, as multiple threads may at the same time enter here, but this
   // is benign.
-  // During collection we only ever set the "live" flag, and only ever clear the
+  // During collection we only ever clear the "candidate" flag, and only ever clear the
   // entry in the in_cset_fast_table.
   // We only ever evaluate the contents of these tables (in the VM thread) after
   // having synchronized the worker threads with the VM thread, or in the same
   // thread (i.e. within the VM thread).
-  if (!_humongous_is_live.is_live(region)) {
-    _humongous_is_live.set_live(region);
+  if (is_humongous_reclaim_candidate(region)) {
+    set_humongous_reclaim_candidate(region, false);
     _in_cset_fast_test.clear_humongous(region);
   }
 }
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Thu May 21 22:54:21 2015 -0700
@@ -552,11 +552,15 @@
   print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
   print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms);
   par_phase_printer.print(RedirtyCards);
-  if (G1ReclaimDeadHumongousObjectsAtYoungGC) {
-    print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
+
+  if (G1EagerReclaimHumongousObjects) {
+    print_stats(2, "Humongous Register", _cur_fast_reclaim_humongous_register_time_ms);
     if (G1Log::finest()) {
       print_stats(3, "Humongous Total", _cur_fast_reclaim_humongous_total);
       print_stats(3, "Humongous Candidate", _cur_fast_reclaim_humongous_candidates);
+    }
+    print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
+    if (G1Log::finest()) {
       print_stats(3, "Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed);
     }
   }
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Thu May 21 22:54:21 2015 -0700
@@ -107,6 +107,7 @@
   double _recorded_non_young_free_cset_time_ms;
 
   double _cur_fast_reclaim_humongous_time_ms;
+  double _cur_fast_reclaim_humongous_register_time_ms;
   size_t _cur_fast_reclaim_humongous_total;
   size_t _cur_fast_reclaim_humongous_candidates;
   size_t _cur_fast_reclaim_humongous_reclaimed;
@@ -202,7 +203,8 @@
     _recorded_non_young_free_cset_time_ms = time_ms;
   }
 
-  void record_fast_reclaim_humongous_stats(size_t total, size_t candidates) {
+  void record_fast_reclaim_humongous_stats(double time_ms, size_t total, size_t candidates) {
+    _cur_fast_reclaim_humongous_register_time_ms = time_ms;
     _cur_fast_reclaim_humongous_total = total;
     _cur_fast_reclaim_humongous_candidates = candidates;
   }
--- a/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp	Thu May 21 22:54:21 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
@@ -57,6 +57,9 @@
  public:
   MemRegion reserved() { return _storage.reserved(); }
 
+  size_t reserved_size() { return _storage.reserved_size(); }
+  size_t committed_size() { return _storage.committed_size(); }
+
   void set_mapping_changed_listener(G1MappingChangedListener* listener) { _listener = listener; }
 
   virtual ~G1RegionToSpaceMapper() {
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu May 21 22:54:21 2015 -0700
@@ -274,10 +274,14 @@
   product(uintx, G1MixedGCCountTarget, 8,                                   \
           "The target number of mixed GCs after a marking cycle.")          \
                                                                             \
-  experimental(bool, G1ReclaimDeadHumongousObjectsAtYoungGC, true,          \
+  experimental(bool, G1EagerReclaimHumongousObjects, true,                  \
           "Try to reclaim dead large objects at every young GC.")           \
                                                                             \
-  experimental(bool, G1TraceReclaimDeadHumongousObjectsAtYoungGC, false,    \
+  experimental(bool, G1EagerReclaimHumongousObjectsWithStaleRefs, true,     \
+          "Try to reclaim dead large objects that have a few stale "        \
+          "references at every young GC.")                                  \
+                                                                            \
+  experimental(bool, G1TraceEagerReclaimHumongousObjects, false,            \
           "Print some information about large object liveness "             \
           "at every young GC.")                                             \
                                                                             \
--- a/src/share/vm/gc_implementation/g1/heapRegionManager.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionManager.cpp	Thu May 21 22:54:21 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
@@ -145,6 +145,24 @@
   }
 }
 
+MemoryUsage HeapRegionManager::get_auxiliary_data_memory_usage() const {
+  size_t used_sz =
+    _prev_bitmap_mapper->committed_size() +
+    _next_bitmap_mapper->committed_size() +
+    _bot_mapper->committed_size() +
+    _cardtable_mapper->committed_size() +
+    _card_counts_mapper->committed_size();
+
+  size_t committed_sz =
+    _prev_bitmap_mapper->reserved_size() +
+    _next_bitmap_mapper->reserved_size() +
+    _bot_mapper->reserved_size() +
+    _cardtable_mapper->reserved_size() +
+    _card_counts_mapper->reserved_size();
+
+  return MemoryUsage(0, used_sz, committed_sz, committed_sz);
+}
+
 uint HeapRegionManager::expand_by(uint num_regions) {
   return expand_at(0, num_regions);
 }
--- a/src/share/vm/gc_implementation/g1/heapRegionManager.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionManager.hpp	Thu May 21 22:54:21 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
@@ -28,6 +28,7 @@
 #include "gc_implementation/g1/g1BiasedArray.hpp"
 #include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
 #include "gc_implementation/g1/heapRegionSet.hpp"
+#include "services/memoryUsage.hpp"
 
 class HeapRegion;
 class HeapRegionClosure;
@@ -197,6 +198,8 @@
   // Return the maximum number of regions in the heap.
   uint max_length() const { return (uint)_regions.length(); }
 
+  MemoryUsage get_auxiliary_data_memory_usage() const;
+
   MemRegion reserved() const { return MemRegion(heap_bottom(), heap_end()); }
 
   // Expand the sequence to reflect that the heap has grown. Either create new
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Thu May 21 22:54:21 2015 -0700
@@ -694,6 +694,18 @@
   clear_fcc();
 }
 
+bool OtherRegionsTable::occupancy_less_or_equal_than(size_t limit) const {
+  if (limit <= (size_t)G1RSetSparseRegionEntries) {
+    return occ_coarse() == 0 && _first_all_fine_prts == NULL && occ_sparse() <= limit;
+  } else {
+    // Current uses of this method may only use values less than G1RSetSparseRegionEntries
+    // for the limit. The solution, comparing against occupied() would be too slow
+    // at this time.
+    Unimplemented();
+    return false;
+  }
+}
+
 bool OtherRegionsTable::is_empty() const {
   return occ_sparse() == 0 && occ_coarse() == 0 && _first_all_fine_prts == NULL;
 }
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Thu May 21 22:54:21 2015 -0700
@@ -181,6 +181,10 @@
   // sense.
   void add_reference(OopOrNarrowOopStar from, int tid);
 
+  // Returns whether this remembered set (and all sub-sets) have an occupancy
+  // that is less or equal than the given occupancy.
+  bool occupancy_less_or_equal_than(size_t limit) const;
+
   // Removes any entries shown by the given bitmaps to contain only dead
   // objects.
   void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
@@ -276,6 +280,10 @@
     return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
   }
 
+  bool occupancy_less_or_equal_than(size_t occ) const {
+    return (strong_code_roots_list_length() == 0) && _other_regions.occupancy_less_or_equal_than(occ);
+  }
+
   size_t occupied() {
     MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
     return occupied_locked();
--- a/src/share/vm/gc_implementation/g1/satbQueue.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/satbQueue.cpp	Thu May 21 22:54:21 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
@@ -29,36 +29,74 @@
 #include "memory/sharedHeap.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
 void ObjPtrQueue::flush() {
-  // The buffer might contain refs into the CSet. We have to filter it
-  // first before we flush it, otherwise we might end up with an
-  // enqueued buffer with refs into the CSet which breaks our invariants.
+  // Filter now to possibly save work later.  If filtering empties the
+  // buffer then flush_impl can deallocate the buffer.
   filter();
   flush_impl();
 }
 
-// This method removes entries from an SATB buffer that will not be
-// useful to the concurrent marking threads. An entry is removed if it
-// satisfies one of the following conditions:
+// Return true if a SATB buffer entry refers to an object that
+// requires marking.
+//
+// The entry must point into the G1 heap.  In particular, it must not
+// be a NULL pointer.  NULL pointers are pre-filtered and never
+// inserted into a SATB buffer.
+//
+// An entry that is below the NTAMS pointer for the containing heap
+// region requires marking. Such an entry must point to a valid object.
+//
+// An entry that is at least the NTAMS pointer for the containing heap
+// region might be any of the following, none of which should be marked.
+//
+// * A reference to an object allocated since marking started.
+//   According to SATB, such objects are implicitly kept live and do
+//   not need to be dealt with via SATB buffer processing.
+//
+// * A reference to a young generation object. Young objects are
+//   handled separately and are not marked by concurrent marking.
+//
+// * A stale reference to a young generation object. If a young
+//   generation object reference is recorded and not filtered out
+//   before being moved by a young collection, the reference becomes
+//   stale.
 //
-// * it points to an object outside the G1 heap (G1's concurrent
-//     marking only visits objects inside the G1 heap),
-// * it points to an object that has been allocated since marking
-//     started (according to SATB those objects do not need to be
-//     visited during marking), or
-// * it points to an object that has already been marked (no need to
-//     process it again).
+// * A stale reference to an eagerly reclaimed humongous object.  If a
+//   humongous object is recorded and then reclaimed, the reference
+//   becomes stale.
 //
-// The rest of the entries will be retained and are compacted towards
-// the top of the buffer. Note that, because we do not allow old
-// regions in the CSet during marking, all objects on the CSet regions
-// are young (eden or survivors) and therefore implicitly live. So any
-// references into the CSet will be removed during filtering.
+// The stale reference cases are implicitly handled by the NTAMS
+// comparison. Because of the possibility of stale references, buffer
+// processing must be somewhat circumspect and not assume entries
+// in an unfiltered buffer refer to valid objects.
+
+inline bool requires_marking(const void* entry, G1CollectedHeap* heap) {
+  // Includes rejection of NULL pointers.
+  assert(heap->is_in_reserved(entry),
+         err_msg("Non-heap pointer in SATB buffer: " PTR_FORMAT, p2i(entry)));
+
+  HeapRegion* region = heap->heap_region_containing_raw(entry);
+  assert(region != NULL, err_msg("No region for " PTR_FORMAT, p2i(entry)));
+  if (entry >= region->next_top_at_mark_start()) {
+    return false;
+  }
+
+  assert(((oop)entry)->is_oop(true /* ignore mark word */),
+         err_msg("Invalid oop in SATB buffer: " PTR_FORMAT, p2i(entry)));
+
+  return true;
+}
+
+// This method removes entries from a SATB buffer that will not be
+// useful to the concurrent marking threads.  Entries are retained if
+// they require marking and are not already marked. Retained entries
+// are compacted toward the top of the buffer.
 
 void ObjPtrQueue::filter() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
@@ -80,26 +118,25 @@
     assert(i > 0, "we should have at least one more entry to process");
     i -= oopSize;
     debug_only(entries += 1;)
-    oop* p = (oop*) &buf[byte_index_to_index((int) i)];
-    oop obj = *p;
+    void** p = &buf[byte_index_to_index((int) i)];
+    void* entry = *p;
     // NULL the entry so that unused parts of the buffer contain NULLs
     // at the end. If we are going to retain it we will copy it to its
     // final place. If we have retained all entries we have visited so
     // far, we'll just end up copying it to the same place.
     *p = NULL;
 
-    bool retain = g1h->is_obj_ill(obj);
-    if (retain) {
+    if (requires_marking(entry, g1h) && !g1h->isMarkedNext((oop)entry)) {
       assert(new_index > 0, "we should not have already filled up the buffer");
       new_index -= oopSize;
       assert(new_index >= i,
              "new_index should never be below i, as we alwaysr compact 'up'");
-      oop* new_p = (oop*) &buf[byte_index_to_index((int) new_index)];
+      void** new_p = &buf[byte_index_to_index((int) new_index)];
       assert(new_p >= p, "the destination location should never be below "
              "the source as we always compact 'up'");
       assert(*new_p == NULL,
              "we should have already cleared the destination location");
-      *new_p = obj;
+      *new_p = entry;
       debug_only(retained += 1;)
     }
   }
@@ -126,10 +163,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.
@@ -146,31 +180,19 @@
   return should_enqueue;
 }
 
-void ObjPtrQueue::apply_closure(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);
-  }
-}
-
-void ObjPtrQueue::apply_closure_and_empty(ObjectClosure* cl) {
-  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
 
@@ -186,23 +208,12 @@
 }
 #endif // PRODUCT
 
-#ifdef ASSERT
-void ObjPtrQueue::verify_oops_in_buffer() {
-  if (_buf == NULL) return;
-  for (size_t i = _index; i < _sz; i += oopSize) {
-    oop obj = (oop)_buf[byte_index_to_index((int)i)];
-    assert(obj != NULL && obj->is_oop(true /* ignore mark word */),
-           "Not an oop");
-  }
-}
-#endif
-
 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
 #endif // _MSC_VER
 
 SATBMarkQueueSet::SATBMarkQueueSet() :
-  PtrQueueSet(), _closure(NULL), _par_closures(NULL),
+  PtrQueueSet(),
   _shared_satb_queue(this, true /*perm*/) { }
 
 void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
@@ -210,13 +221,9 @@
                                   Mutex* lock) {
   PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1);
   _shared_satb_queue.set_lock(lock);
-  if (ParallelGCThreads > 0) {
-    _par_closures = NEW_C_HEAP_ARRAY(ObjectClosure*, ParallelGCThreads, mtGC);
-  }
 }
 
 void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) {
-  DEBUG_ONLY(t->satb_mark_queue().verify_oops_in_buffer();)
   t->satb_mark_queue().handle_zero_index();
 }
 
@@ -276,17 +283,7 @@
   shared_satb_queue()->filter();
 }
 
-void SATBMarkQueueSet::set_closure(ObjectClosure* closure) {
-  _closure = closure;
-}
-
-void SATBMarkQueueSet::set_par_closure(int i, ObjectClosure* par_closure) {
-  assert(ParallelGCThreads > 0 && _par_closures != NULL, "Precondition");
-  _par_closures[i] = par_closure;
-}
-
-bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par,
-                                                              uint worker) {
+bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
   BufferNode* nd = NULL;
   {
     MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
@@ -298,10 +295,20 @@
       if (_n_completed_buffers == 0) _process_completed = false;
     }
   }
-  ObjectClosure* cl = (par ? _par_closures[worker] : _closure);
   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 {
@@ -309,28 +316,6 @@
   }
 }
 
-void SATBMarkQueueSet::iterate_completed_buffers_read_only(ObjectClosure* cl) {
-  assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-  assert(cl != NULL, "pre-condition");
-
-  BufferNode* nd = _completed_buffers_head;
-  while (nd != NULL) {
-    void** buf = BufferNode::make_buffer_from_node(nd);
-    ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz);
-    nd = nd->next();
-  }
-}
-
-void SATBMarkQueueSet::iterate_thread_buffers_read_only(ObjectClosure* cl) {
-  assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-  assert(cl != NULL, "pre-condition");
-
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
-    t->satb_mark_queue().apply_closure(cl);
-  }
-  shared_satb_queue()->apply_closure(cl);
-}
-
 #ifndef PRODUCT
 // Helpful for debugging
 
--- a/src/share/vm/gc_implementation/g1/satbQueue.hpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/gc_implementation/g1/satbQueue.hpp	Thu May 21 22:54:21 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
@@ -25,32 +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.
-  void apply_closure(ObjectClosure* cl);
-
-  // 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
@@ -63,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();
@@ -72,21 +74,11 @@
   void print(const char* name);
   static void print(const char* name, void** buf, size_t index, size_t sz);
 #endif // PRODUCT
-
-  void verify_oops_in_buffer() NOT_DEBUG_RETURN;
 };
 
 class SATBMarkQueueSet: public PtrQueueSet {
-  ObjectClosure* _closure;
-  ObjectClosure** _par_closures;  // One per ParGCThread.
-
   ObjPtrQueue _shared_satb_queue;
 
-  // Utility function to support sequential and parallel versions.  If
-  // "par" is true, then "worker" is the par thread id; if "false", worker
-  // is ignored.
-  bool apply_closure_to_completed_buffer_work(bool par, uint worker);
-
 #ifdef ASSERT
   void dump_active_states(bool expected_active);
   void verify_active_states(bool expected_active);
@@ -110,32 +102,12 @@
   // Filter all the currently-active SATB buffers.
   void filter_thread_buffers();
 
-  // Register "blk" as "the closure" for all queues.  Only one such closure
-  // is allowed.  The "apply_closure_to_completed_buffer" method will apply
-  // this closure to a completed buffer, and "iterate_closure_all_threads"
-  // applies it to partially-filled buffers (the latter should only be done
-  // with the world stopped).
-  void set_closure(ObjectClosure* closure);
-  // Set the parallel closures: pointer is an array of pointers to
-  // closures, one for each parallel GC thread.
-  void set_par_closure(int i, ObjectClosure* closure);
-
-  // If there exists some completed buffer, pop it, then apply the
-  // registered closure to all its elements, and return true.  If no
-  // completed buffers exist, return false.
-  bool apply_closure_to_completed_buffer() {
-    return apply_closure_to_completed_buffer_work(false, 0);
-  }
-  // Parallel version of the above.
-  bool par_apply_closure_to_completed_buffer(uint worker) {
-    return apply_closure_to_completed_buffer_work(true, worker);
-  }
-
-  // Apply the given closure on enqueued and currently-active buffers
-  // respectively. Both methods are read-only, i.e., they do not
-  // modify any of the buffers.
-  void iterate_completed_buffers_read_only(ObjectClosure* cl);
-  void iterate_thread_buffers_read_only(ObjectClosure* cl);
+  // 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/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu May 21 22:54:21 2015 -0700
@@ -3980,8 +3980,8 @@
            the_class->get_cached_class_file_bytes()) {
     // The same class can be present twice in the scratch classes list or there
     // are multiple concurrent RetransformClasses calls on different threads.
-    // In such cases we have to deallocate scratch_class cached_class_file_bytes.
-    os::free(scratch_class->get_cached_class_file_bytes());
+    // In such cases we have to deallocate scratch_class cached_class_file.
+    os::free(scratch_class->get_cached_class_file());
   }
 
   // NULL out in scratch class to not delete twice.  The class to be redefined
--- a/src/share/vm/prims/whitebox.cpp	Thu May 21 10:00:37 2015 -0700
+++ b/src/share/vm/prims/whitebox.cpp	Thu May 21 22:54:21 2015 -0700
@@ -309,6 +309,12 @@
   return hr->isHumongous();
 WB_END
 
+WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
+  G1CollectedHeap* g1 = G1CollectedHeap::heap();
+  size_t nr = g1->max_regions();
+  return (jlong)nr;
+WB_END
+
 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
   size_t nr = g1->num_free_regions();
@@ -324,6 +330,14 @@
 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
   return (jint)HeapRegion::GrainBytes;
 WB_END
+
+WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
+  ResourceMark rm(THREAD);
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
+  Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
+  return JNIHandles::make_local(env, h());
+WB_END
 #endif // INCLUDE_ALL_GCS
 
 #if INCLUDE_NMT
@@ -1014,8 +1028,11 @@
 #if INCLUDE_ALL_GCS
   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
   {CC"g1IsHumongous",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
+  {CC"g1NumMaxRegions",    CC"()J",                   (void*)&WB_G1NumMaxRegions  },
   {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
   {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
+  {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
+                                                      (void*)&WB_G1AuxiliaryMemoryUsage  },
 #endif // INCLUDE_ALL_GCS
 #if INCLUDE_NMT
   {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
--- a/test/TEST.groups	Thu May 21 10:00:37 2015 -0700
+++ b/test/TEST.groups	Thu May 21 22:54:21 2015 -0700
@@ -132,7 +132,8 @@
   sanity/ExecuteInternalVMTests.java
 
 hotspot_gc = \
-  sanity/ExecuteInternalVMTests.java
+  sanity/ExecuteInternalVMTests.java \
+  -gc/g1/TestGreyReclaimedHumongousObjects.java
 
 hotspot_runtime = \
   sanity/ExecuteInternalVMTests.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/codegen/IntRotateWithImmediate.java	Thu May 21 22:54:21 2015 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 SAP AG.  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.
+ */
+
+/*
+ * @test
+ * @bug 8080190
+ * @key regression
+ * @summary Test that the rotate distance used in the rotate instruction is properly masked with 0x1f
+ * @run main/othervm -Xbatch -XX:-UseOnStackReplacement IntRotateWithImmediate
+ * @author volker.simonis@gmail.com
+ */
+
+public class IntRotateWithImmediate {
+
+  // This is currently the same as Integer.rotateRight()
+  static int rotateRight(int i, int distance) {
+    // On some architectures (i.e. x86_64 and ppc64) the following computation is
+    // matched in the .ad file into a single MachNode which emmits a single rotate
+    // machine instruction. It is important that the shift amount is masked to match
+    // corresponding immediate width in the native instruction. On x86_64 the rotate
+    // left instruction ('rol') encodes an 8-bit immediate while the corresponding
+    // 'rotlwi' instruction on Power only encodes a 5-bit immediate.
+    return ((i >>> distance) | (i << -distance));
+  }
+
+  static int compute(int x) {
+    return rotateRight(x, 3);
+  }
+
+  public static void main(String args[]) {
+    int val = 4096;
+
+    int firstResult = compute(val);
+
+    for (int i = 0; i < 100000; i++) {
+      int newResult = compute(val);
+      if (firstResult != newResult) {
+        throw new InternalError(firstResult + " != " + newResult);
+      }
+    }
+    System.out.println("OK");
+  }
+
+}
--- a/test/gc/g1/TestEagerReclaimHumongousRegions2.java	Thu May 21 10:00:37 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2014, 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.
- */
-
-/*
- * @test TestEagerReclaimHumongousRegions2
- * @bug 8051973
- * @summary Test to make sure that eager reclaim of humongous objects correctly clears
- * mark bitmaps at reclaim.
- * @key gc
- * @library /testlibrary
- */
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Random;
-
-import com.oracle.java.testlibrary.OutputAnalyzer;
-import com.oracle.java.testlibrary.ProcessTools;
-
-// An object that has a few references to other instances to slow down marking.
-class ObjectWithSomeRefs {
-    public ObjectWithSomeRefs other1;
-    public ObjectWithSomeRefs other2;
-    public ObjectWithSomeRefs other3;
-    public ObjectWithSomeRefs other4;
-}
-
-class ReclaimRegionFast {
-    public static final long MAX_MILLIS_FOR_RUN = 50 * 1000; // The maximum runtime for the actual test.
-
-    public static final int M = 1024*1024;
-
-    public static LinkedList<Object> garbageList = new LinkedList<Object>();
-
-    public static void genGarbage(Object large) {
-        for (int i = 0; i < 64*1024; i++) {
-            Object[] garbage = new Object[50];
-            garbage[0] = large;
-            garbageList.add(garbage);
-        }
-        garbageList.clear();
-    }
-
-    public static ArrayList<ObjectWithSomeRefs> longList = new ArrayList<ObjectWithSomeRefs>();
-
-    public static void main(String[] args) {
-
-        for (int i = 0; i < 16*1024; i++) {
-             longList.add(new ObjectWithSomeRefs());
-        }
-
-        Random rnd = new Random();
-        for (int i = 0; i < longList.size(); i++) {
-             int len = longList.size();
-             longList.get(i).other1 = longList.get(rnd.nextInt(len));
-             longList.get(i).other2 = longList.get(rnd.nextInt(len));
-             longList.get(i).other3 = longList.get(rnd.nextInt(len));
-             longList.get(i).other4 = longList.get(rnd.nextInt(len));
-        }
-
-        int[] large1 = new int[M];
-        int[] large2 = null;
-        int[] large3 = null;
-        int[] large4 = null;
-
-        Object ref_from_stack = large1;
-
-        long start_millis = System.currentTimeMillis();
-
-        for (int i = 0; i < 20; i++) {
-            long current_millis = System.currentTimeMillis();
-            if ((current_millis - start_millis) > MAX_MILLIS_FOR_RUN) {
-              System.out.println("Finishing test because maximum runtime exceeded");
-              break;
-            }
-            // A set of large objects that will be reclaimed eagerly - and hopefully marked.
-            large1 = new int[M - 20];
-            large2 = new int[M - 20];
-            large3 = new int[M - 20];
-            large4 = new int[M - 20];
-            genGarbage(large1);
-            // Make sure that the compiler cannot completely remove
-            // the allocation of the large object until here.
-            System.out.println(large1 + " " + large2 + " " + large3 + " " + large4);
-        }
-
-        // Keep the reference to the first object alive.
-        System.out.println(ref_from_stack);
-    }
-}
-
-public class TestEagerReclaimHumongousRegions2 {
-    public static void main(String[] args) throws Exception {
-        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-            "-XX:+UseG1GC",
-            "-Xms128M",
-            "-Xmx128M",
-            "-Xmn2M",
-            "-XX:G1HeapRegionSize=1M",
-            "-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible initial marks.
-            "-XX:+PrintGC",
-            "-XX:+VerifyAfterGC",
-            "-XX:ConcGCThreads=1", // Want to make marking as slow as possible.
-            "-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only.
-            "-XX:+G1VerifyBitmaps",
-            ReclaimRegionFast.class.getName());
-        OutputAnalyzer output = new OutputAnalyzer(pb.start());
-        output.shouldHaveExitValue(0);
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java	Thu May 21 22:54:21 2015 -0700
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * @test TestEagerReclaimHumongousRegionsClearMarkBits
+ * @bug 8051973
+ * @summary Test to make sure that eager reclaim of humongous objects correctly clears
+ * mark bitmaps at reclaim.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Random;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+// An object that has a few references to other instances to slow down marking.
+class ObjectWithSomeRefs {
+    public ObjectWithSomeRefs other1;
+    public ObjectWithSomeRefs other2;
+    public ObjectWithSomeRefs other3;
+    public ObjectWithSomeRefs other4;
+}
+
+class ReclaimRegionFast {
+    public static final long MAX_MILLIS_FOR_RUN = 50 * 1000; // The maximum runtime for the actual test.
+
+    public static final int M = 1024*1024;
+
+    public static LinkedList<Object> garbageList = new LinkedList<Object>();
+
+    public static void genGarbage(Object large) {
+        for (int i = 0; i < 64*1024; i++) {
+            Object[] garbage = new Object[50];
+            garbage[0] = large;
+            garbageList.add(garbage);
+        }
+        garbageList.clear();
+    }
+
+    public static ArrayList<ObjectWithSomeRefs> longList = new ArrayList<ObjectWithSomeRefs>();
+
+    public static void main(String[] args) {
+
+        for (int i = 0; i < 16*1024; i++) {
+             longList.add(new ObjectWithSomeRefs());
+        }
+
+        Random rnd = new Random();
+        for (int i = 0; i < longList.size(); i++) {
+             int len = longList.size();
+             longList.get(i).other1 = longList.get(rnd.nextInt(len));
+             longList.get(i).other2 = longList.get(rnd.nextInt(len));
+             longList.get(i).other3 = longList.get(rnd.nextInt(len));
+             longList.get(i).other4 = longList.get(rnd.nextInt(len));
+        }
+
+        int[] large1 = new int[M];
+        int[] large2 = null;
+        int[] large3 = null;
+        int[] large4 = null;
+
+        Object ref_from_stack = large1;
+
+        long start_millis = System.currentTimeMillis();
+
+        for (int i = 0; i < 20; i++) {
+            long current_millis = System.currentTimeMillis();
+            if ((current_millis - start_millis) > MAX_MILLIS_FOR_RUN) {
+              System.out.println("Finishing test because maximum runtime exceeded");
+              break;
+            }
+            // A set of large objects that will be reclaimed eagerly - and hopefully marked.
+            large1 = new int[M - 20];
+            large2 = new int[M - 20];
+            large3 = new int[M - 20];
+            large4 = new int[M - 20];
+            genGarbage(large1);
+            // Make sure that the compiler cannot completely remove
+            // the allocation of the large object until here.
+            System.out.println(large1 + " " + large2 + " " + large3 + " " + large4);
+        }
+
+        // Keep the reference to the first object alive.
+        System.out.println(ref_from_stack);
+    }
+}
+
+public class TestEagerReclaimHumongousRegionsClearMarkBits {
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UseG1GC",
+            "-Xms128M",
+            "-Xmx128M",
+            "-Xmn2M",
+            "-XX:G1HeapRegionSize=1M",
+            "-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible initial marks.
+            "-XX:+PrintGC",
+            "-XX:+VerifyAfterGC",
+            "-XX:ConcGCThreads=1", // Want to make marking as slow as possible.
+            "-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only.
+            "-XX:+G1VerifyBitmaps",
+            ReclaimRegionFast.class.getName());
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldHaveExitValue(0);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java	Thu May 21 22:54:21 2015 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * @test TestEagerReclaimHumongousRegionsWithRefs
+ * @bug 8048179
+ * @summary Test to make sure that eager reclaim of humongous objects that have previously
+ * been referenced by other old gen regions work. We simply try to fill
+ * up the heap with humongous objects and create a remembered set entry from an object by
+ * referencing that we know is in the old gen. After changing this reference, the object
+ * should still be eagerly reclaimable to avoid Full GC.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.LinkedList;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+class RefHolder {
+  Object ref;
+}
+
+class ReclaimRegionFast {
+
+    public static final int M = 1024*1024;
+
+    public static LinkedList<Object> garbageList = new LinkedList<Object>();
+
+    public static void genGarbage() {
+        for (int i = 0; i < 32*1024; i++) {
+            garbageList.add(new int[100]);
+        }
+        garbageList.clear();
+    }
+
+
+    // A large object referenced by a static.
+    static int[] filler = new int[10 * M];
+
+    // Old gen object referencing the large object, generating remembered
+    // set entries.
+    static RefHolder fromOld = new RefHolder();
+
+    public static void main(String[] args) {
+
+        int[] large = new int[M];
+
+        Object ref_from_stack = large;
+
+        for (int i = 0; i < 100; i++) {
+            // A large object that will be reclaimed eagerly.
+            large = new int[6*M];
+            fromOld.ref = large;
+            genGarbage();
+        }
+
+        // Keep the reference to the first object alive.
+        System.out.println(ref_from_stack);
+    }
+}
+
+public class TestEagerReclaimHumongousRegionsWithRefs {
+
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UseG1GC",
+            "-Xms128M",
+            "-Xmx128M",
+            "-Xmn16M",
+            "-XX:+PrintGC",
+            ReclaimRegionFast.class.getName());
+
+        Pattern p = Pattern.compile("Full GC");
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+        int found = 0;
+        Matcher m = p.matcher(output.getStdout());
+        while (m.find()) {
+            found++;
+        }
+        System.out.println("Issued " + found + " Full GCs");
+
+        assertLessThan(found, 10, "Found that " + found + " Full GCs were issued. This is larger than the bound. Eager reclaim of objects once referenced from old gen seems to not work at all");
+        output.shouldHaveExitValue(0);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java	Thu May 21 22:54:21 2015 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * @test TestG1TraceEagerReclaimHumongousObjects
+ * @bug 8058801 8048179
+ * @summary Ensure that the output for a G1TraceEagerReclaimHumongousObjects
+ * includes the expected necessary messages.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import java.util.LinkedList;
+
+public class TestG1TraceEagerReclaimHumongousObjects {
+  public static void main(String[] args) throws Exception {
+    testGCLogs();
+    testHumongousObjectGCLogs();
+  }
+
+  private static void testGCLogs() throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-Xms128M",
+                                               "-Xmx128M",
+                                               "-Xmn16M",
+                                               "-XX:G1HeapRegionSize=1M",
+                                               "-XX:+PrintGC",
+                                               "-XX:+UnlockExperimentalVMOptions",
+                                               "-XX:G1LogLevel=finest",
+                                               "-XX:+G1TraceEagerReclaimHumongousObjects",
+                                               GCTest.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    // As G1EagerReclaimHumongousObjects is set(default), below logs should be displayed.
+    // And GCTest doesn't have humongous objects, so values should be zero.
+    output.shouldContain("[Humongous Reclaim");
+    output.shouldContain("[Humongous Total: 0]");
+    output.shouldContain("[Humongous Candidate: 0]");
+    output.shouldContain("[Humongous Reclaimed: 0]");
+
+    output.shouldHaveExitValue(0);
+  }
+
+  private static void testHumongousObjectGCLogs() throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-Xms128M",
+                                               "-Xmx128M",
+                                               "-Xmn16M",
+                                               "-XX:G1HeapRegionSize=1M",
+                                               "-XX:+PrintGC",
+                                               "-XX:+UnlockExperimentalVMOptions",
+                                               "-XX:G1LogLevel=finest",
+                                               "-XX:+G1TraceEagerReclaimHumongousObjects",
+                                               GCWithHumongousObjectTest.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed.
+    output.shouldContain("[Humongous Reclaim");
+    output.shouldContain("[Humongous Total");
+    output.shouldContain("[Humongous Candidate");
+    output.shouldContain("[Humongous Reclaimed");
+
+    // As G1TraceReclaimDeadHumongousObjectsAtYoungGC is set and GCWithHumongousObjectTest has humongous objects,
+    // these logs should be displayed.
+    output.shouldContain("Live humongous");
+    output.shouldContain("Dead humongous region");
+    output.shouldHaveExitValue(0);
+  }
+
+  static class GCTest {
+    private static byte[] garbage;
+
+    public static void main(String [] args) {
+      System.out.println("Creating garbage");
+      // create 128MB of garbage. This should result in at least one GC
+      for (int i = 0; i < 1024; i++) {
+        garbage = new byte[128 * 1024];
+      }
+      System.out.println("Done");
+    }
+  }
+
+  static class GCWithHumongousObjectTest {
+
+    public static final int M = 1024*1024;
+    public static LinkedList<Object> garbageList = new LinkedList<Object>();
+    // A large object referenced by a static.
+    static int[] filler = new int[10 * M];
+
+    public static void genGarbage() {
+      for (int i = 0; i < 32*1024; i++) {
+        garbageList.add(new int[100]);
+      }
+      garbageList.clear();
+    }
+
+    public static void main(String[] args) {
+
+      int[] large = new int[M];
+      Object ref = large;
+
+      System.out.println("Creating garbage");
+      for (int i = 0; i < 100; i++) {
+        // A large object that will be reclaimed eagerly.
+        large = new int[6*M];
+        genGarbage();
+        // Make sure that the compiler cannot completely remove
+        // the allocation of the large object until here.
+        System.out.println(large);
+      }
+
+      // Keep the reference to the first object alive.
+      System.out.println(ref);
+      System.out.println("Done");
+    }
+  }
+}
--- a/test/gc/g1/TestG1TraceReclaimDeadHumongousObjectsAtYoungGC.java	Thu May 21 10:00:37 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2014, 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.
- */
-
-/*
- * @test TestG1TraceReclaimDeadHumongousObjectsAtYoungGC
- * @bug 8058801
- * @summary Ensure that the output for a G1TraceReclaimDeadHumongousObjectsAtYoungGC
- * includes the expected necessary messages.
- * @key gc
- * @library /testlibrary
- */
-
-import com.oracle.java.testlibrary.ProcessTools;
-import com.oracle.java.testlibrary.OutputAnalyzer;
-import java.util.LinkedList;
-
-public class TestG1TraceReclaimDeadHumongousObjectsAtYoungGC {
-  public static void main(String[] args) throws Exception {
-    testGCLogs();
-    testHumongousObjectGCLogs();
-  }
-
-  private static void testGCLogs() throws Exception {
-
-    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
-                                               "-Xms128M",
-                                               "-Xmx128M",
-                                               "-Xmn16M",
-                                               "-XX:G1HeapRegionSize=1M",
-                                               "-XX:+PrintGC",
-                                               "-XX:+UnlockExperimentalVMOptions",
-                                               "-XX:G1LogLevel=finest",
-                                               "-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC",
-                                               GCTest.class.getName());
-
-    OutputAnalyzer output = new OutputAnalyzer(pb.start());
-
-    // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed.
-    // And GCTest doesn't have humongous objects, so values should be zero.
-    output.shouldContain("[Humongous Reclaim");
-    output.shouldContain("[Humongous Total: 0]");
-    output.shouldContain("[Humongous Candidate: 0]");
-    output.shouldContain("[Humongous Reclaimed: 0]");
-
-    output.shouldHaveExitValue(0);
-  }
-
-  private static void testHumongousObjectGCLogs() throws Exception {
-    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
-                                               "-Xms128M",
-                                               "-Xmx128M",
-                                               "-Xmn16M",
-                                               "-XX:G1HeapRegionSize=1M",
-                                               "-XX:+PrintGC",
-                                               "-XX:+UnlockExperimentalVMOptions",
-                                               "-XX:G1LogLevel=finest",
-                                               "-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC",
-                                               GCWithHumongousObjectTest.class.getName());
-
-    OutputAnalyzer output = new OutputAnalyzer(pb.start());
-
-    // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed.
-    output.shouldContain("[Humongous Reclaim");
-    output.shouldContain("[Humongous Total");
-    output.shouldContain("[Humongous Candidate");
-    output.shouldContain("[Humongous Reclaimed");
-
-    // As G1TraceReclaimDeadHumongousObjectsAtYoungGC is set and GCWithHumongousObjectTest has humongous objects,
-    // these logs should be displayed.
-    output.shouldContain("Live humongous");
-    output.shouldContain("Reclaim humongous region");
-    output.shouldHaveExitValue(0);
-  }
-
-  static class GCTest {
-    private static byte[] garbage;
-
-    public static void main(String [] args) {
-      System.out.println("Creating garbage");
-      // create 128MB of garbage. This should result in at least one GC
-      for (int i = 0; i < 1024; i++) {
-        garbage = new byte[128 * 1024];
-      }
-      System.out.println("Done");
-    }
-  }
-
-  static class GCWithHumongousObjectTest {
-
-    public static final int M = 1024*1024;
-    public static LinkedList<Object> garbageList = new LinkedList<Object>();
-    // A large object referenced by a static.
-    static int[] filler = new int[10 * M];
-
-    public static void genGarbage() {
-      for (int i = 0; i < 32*1024; i++) {
-        garbageList.add(new int[100]);
-      }
-      garbageList.clear();
-    }
-
-    public static void main(String[] args) {
-
-      int[] large = new int[M];
-      Object ref = large;
-
-      System.out.println("Creating garbage");
-      for (int i = 0; i < 100; i++) {
-        // A large object that will be reclaimed eagerly.
-        large = new int[6*M];
-        genGarbage();
-        // Make sure that the compiler cannot completely remove
-        // the allocation of the large object until here.
-        System.out.println(large);
-      }
-
-      // Keep the reference to the first object alive.
-      System.out.println(ref);
-      System.out.println("Done");
-    }
-  }
-}
--- a/test/gc/g1/TestGCLogMessages.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestGCLogMessages.java	Thu May 21 22:54:21 2015 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test TestGCLogMessages
- * @bug 8035406 8027295 8035398 8019342 8027959 8027962
+ * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962
  * @summary Ensure that the PrintGCDetails output for a minor GC with G1
  * includes the expected necessary messages.
  * @key gc
@@ -81,6 +81,7 @@
         new LogMessageWithLevel("Non-Young Free CSet", Level.FINEST),
         // Humongous Eager Reclaim
         new LogMessageWithLevel("Humongous Reclaim", Level.FINER),
+        new LogMessageWithLevel("Humongous Register", Level.FINER),
     };
 
     void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/TestGreyReclaimedHumongousObjects.java	Thu May 21 22:54:21 2015 -0700
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test TestGreyReclaimedHumongousObjects.java
+ * @bug 8069367
+ * @requires vm.gc == "G1" | vm.gc == "null"
+ * @summary Test handling of marked but unscanned reclaimed humongous objects.
+ * @key gc
+ * @run main/othervm -XX:+UseG1GC -Xss32m -Xmx128m -XX:G1HeapRegionSize=1m
+ *      -XX:+UnlockExperimentalVMOptions
+ *          -XX:+G1EagerReclaimHumongousObjects
+ *          -XX:+G1EagerReclaimHumongousObjectsWithStaleRefs
+ *      TestGreyReclaimedHumongousObjects 1048576 90
+ */
+
+// This test spawns a bunch of threads, each of them rapidly
+// allocating large objects and storing them into a circular buffer
+// associated with the thread.  The circular buffer results in these
+// objects becoming dead in fairly short order.
+//
+// The situation we're trying to provoke is
+//
+// (1) A humongous object H is marked and added to the mark stack.
+//
+// (2) An evacuation pause determines H is no longer live, and
+// reclaims it.  This occurs before concurrent marking has gotten
+// around to processing the mark stack entry for H.
+//
+// (3) Concurrent marking processes the mark stack entry for H.  The
+// bug is that it would attempt to scan the now dead object.
+//
+// Unfortunately, this test is *very* sensitive to configuration.
+// Among the parameters that affect whether / how often we'll get into
+// the desired situation within a reasonable amount of time are:
+//
+// - THREAD_COUNT: The number of allocating threads.
+//
+// - OLD_COUNT: The number of objects each thread keeps.
+//
+// - MAX_MEMORY: The maximum heap size.
+//
+// - G1HeapRegionSize
+//
+// - The size of the objects being allocated.
+//
+// The parameter values specified here:
+//
+// - THREAD_COUNT = 12
+// - OLD_COUNT == 4
+// - MAX_MEMORY == 128m
+// - G1HeapRegionSize = 1m
+// - Object size = 1048576 (2 regions after header overhead and roundup)
+//
+// seems to work well at provoking the desired state fairly quickly.
+// Even relatively small perturbations may change that.  The key
+// factors seem to be keeping the heap mostly full of live objects but
+// having them become dead fairly quickly.
+
+import java.util.Date;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import sun.management.ManagementFactoryHelper;
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+
+public class TestGreyReclaimedHumongousObjects {
+
+    static class NamedThreadFactory implements ThreadFactory {
+       private int threadNum = 0;
+
+       @Override
+       public Thread newThread(Runnable r) {
+         return new Thread(r, THREAD_NAME + (threadNum++));
+       }
+    }
+
+    static class Runner extends Thread {
+        private final Date startDate = new Date();
+        private final int obj_size;
+        private final Object[] old_garbage;
+        private int old_index = 0;
+
+        public Runner(int obj_size) {
+            this.obj_size = obj_size;
+            old_garbage = new Object[OLD_COUNT];
+        }
+
+        private void allocate_garbage() {
+            byte[] garbage = new byte[obj_size];
+            old_garbage[Math.abs(++old_index % OLD_COUNT)] = garbage;
+        }
+
+        @Override
+        public void run() {
+            try {
+                while (!isInterrupted()) {
+                    allocate_garbage();
+                    Thread.sleep(0); // Yield, to ensure interruptable.
+                }
+            } catch (InterruptedException e) {
+                System.out.println("Aborted after "
+                                   + (new Date().getTime() - startDate.getTime())
+                                   + " ms");
+                interrupt();
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
+
+        System.out.println("Max memory= " + MAX_MEMORY + " bytes");
+
+        int obj_size = 0;
+        long seconds_to_run = 0;
+        if (args.length != 2) {
+            throw new RuntimeException("Object size argument must be supplied");
+        } else {
+            obj_size = Integer.parseInt(args[0]);
+            seconds_to_run = Integer.parseInt(args[1]);
+        }
+        System.out.println("Objects size= " + obj_size + " bytes");
+        System.out.println("Seconds to run=" + seconds_to_run);
+
+        int region_size =
+            Integer.parseInt(diagnostic.getVMOption("G1HeapRegionSize").getValue());
+        if (obj_size < (region_size / 2)) {
+            throw new RuntimeException("Object size " + obj_size +
+                                       " is not humongous with region size " + region_size);
+        }
+
+        ExecutorService executor =
+            Executors.newFixedThreadPool(THREAD_COUNT, new NamedThreadFactory());
+        System.out.println("Starting " + THREAD_COUNT + " threads");
+
+        for (int i = 0; i < THREAD_COUNT; i++) {
+            executor.execute(new Runner(obj_size));
+        }
+
+        Thread.sleep(seconds_to_run * 1000);
+        executor.shutdownNow();
+
+        if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
+            System.err.println("Thread pool did not terminate after 10 seconds after shutdown");
+        }
+    }
+
+    private static final long MAX_MEMORY = Runtime.getRuntime().maxMemory();
+    private static final int OLD_COUNT = 4;
+    private static final int THREAD_COUNT = 12;
+    private static final String THREAD_NAME = "TestGreyRH-";
+}
+
--- a/test/gc/g1/TestShrinkAuxiliaryData.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData.java	Thu May 21 22:54:21 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,7 +21,7 @@
  * questions.
  */
 
-import static com.oracle.java.testlibrary.Asserts.assertLessThanOrEqual;
+import com.oracle.java.testlibrary.Asserts;
 import com.oracle.java.testlibrary.OutputAnalyzer;
 import com.oracle.java.testlibrary.Platform;
 import com.oracle.java.testlibrary.ProcessTools;
@@ -36,23 +36,29 @@
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-import sun.misc.Unsafe;
+import sun.misc.Unsafe; // for ADDRESS_SIZE
+import sun.hotspot.WhiteBox;
 
 public class TestShrinkAuxiliaryData {
 
+    private static final int REGION_SIZE = 1024 * 1024;
+
     private final static String[] initialOpts = new String[]{
         "-XX:MinHeapFreeRatio=10",
         "-XX:MaxHeapFreeRatio=11",
         "-XX:+UseG1GC",
-        "-XX:G1HeapRegionSize=1m",
+        "-XX:G1HeapRegionSize=" + REGION_SIZE,
         "-XX:-ExplicitGCInvokesConcurrent",
-        "-XX:+PrintGCDetails"
+        "-XX:+PrintGCDetails",
+        "-XX:+UnlockDiagnosticVMOptions",
+        "-XX:+WhiteBoxAPI",
+        "-Xbootclasspath/a:.",
     };
 
-    private final int RSetCacheSize;
+    private final int hotCardTableSize;
 
-    protected TestShrinkAuxiliaryData(int RSetCacheSize) {
-        this.RSetCacheSize = RSetCacheSize;
+    protected TestShrinkAuxiliaryData(int hotCardTableSize) {
+        this.hotCardTableSize = hotCardTableSize;
     }
 
     protected void test() throws Exception {
@@ -60,16 +66,16 @@
         Collections.addAll(vmOpts, initialOpts);
 
         int maxCacheSize = Math.max(0, Math.min(31, getMaxCacheSize()));
-        if (maxCacheSize < RSetCacheSize) {
+        if (maxCacheSize < hotCardTableSize) {
             System.out.format("Skiping test for %d cache size due max cache size %d",
-                    RSetCacheSize, maxCacheSize
+                    hotCardTableSize, maxCacheSize
             );
             return;
         }
 
         printTestInfo(maxCacheSize);
 
-        vmOpts.add("-XX:G1ConcRSLogCacheSize=" + RSetCacheSize);
+        vmOpts.add("-XX:G1ConcRSLogCacheSize=" + hotCardTableSize);
         vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
 
         // for 32 bits ObjectAlignmentInBytes is not a option
@@ -92,11 +98,13 @@
 
     private void performTest(List<String> opts) throws Exception {
         ProcessBuilder pb
-                       = ProcessTools.createJavaProcessBuilder(
-                opts.toArray(new String[opts.size()])
-        );
+                = ProcessTools.createJavaProcessBuilder(
+                        opts.toArray(new String[opts.size()])
+                );
 
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        System.out.println(output.getStdout());
+        System.err.println(output.getStderr());
         output.shouldHaveExitValue(0);
     }
 
@@ -107,12 +115,13 @@
         formatSymbols.setGroupingSeparator(' ');
         grouped.setDecimalFormatSymbols(formatSymbols);
 
-        System.out.format("Test will use %s bytes of memory of %s available%n"
+        System.out.format(
+                "Test will use %s bytes of memory of %s available%n"
                 + "Available memory is %s with %d bytes pointer size - can save %s pointers%n"
                 + "Max cache size: 2^%d = %s elements%n",
                 grouped.format(ShrinkAuxiliaryDataTest.getMemoryUsedByTest()),
-                grouped.format(Runtime.getRuntime().freeMemory()),
-                grouped.format(Runtime.getRuntime().freeMemory()
+                grouped.format(Runtime.getRuntime().maxMemory()),
+                grouped.format(Runtime.getRuntime().maxMemory()
                         - ShrinkAuxiliaryDataTest.getMemoryUsedByTest()),
                 Unsafe.ADDRESS_SIZE,
                 grouped.format((Runtime.getRuntime().freeMemory()
@@ -135,6 +144,7 @@
         if (availableMemory <= 0) {
             return 0;
         }
+
         long availablePointersCount = availableMemory / Unsafe.ADDRESS_SIZE;
         return (63 - (int) Long.numberOfLeadingZeros(availablePointersCount));
     }
@@ -142,17 +152,48 @@
     static class ShrinkAuxiliaryDataTest {
 
         public static void main(String[] args) throws IOException {
-            int iterateCount = DEFAULT_ITERATION_COUNT;
+
+            ShrinkAuxiliaryDataTest testCase = new ShrinkAuxiliaryDataTest();
 
-            if (args.length > 0) {
-                try {
-                    iterateCount = Integer.parseInt(args[0]);
-                } catch (NumberFormatException e) {
-                    //num_iterate remains default
-                }
+            if (!testCase.checkEnvApplicability()) {
+                return;
             }
 
-            new ShrinkAuxiliaryDataTest().test(iterateCount);
+            testCase.test();
+        }
+
+        /**
+         * Checks is this environment suitable to run this test
+         * - memory is enough to decommit (page size is not big)
+         * - RSet cache size is not too big
+         *
+         * @return true if test could run, false if test should be skipped
+         */
+        protected boolean checkEnvApplicability() {
+
+            int pageSize = WhiteBox.getWhiteBox().getVMPageSize();
+            System.out.println( "Page size = " + pageSize
+                    + " region size = " + REGION_SIZE
+                    + " aux data ~= " + (REGION_SIZE * 3 / 100));
+            // If auxdata size will be less than page size it wouldn't decommit.
+            // Auxiliary data size is about ~3.6% of heap size.
+            if (pageSize >= REGION_SIZE * 3 / 100) {
+                System.out.format("Skipping test for too large page size = %d",
+                       pageSize
+                );
+                return false;
+            }
+
+            if (REGION_SIZE * REGIONS_TO_ALLOCATE > Runtime.getRuntime().maxMemory()) {
+                System.out.format("Skipping test for too low available memory. "
+                        + "Need %d, available %d",
+                        REGION_SIZE * REGIONS_TO_ALLOCATE,
+                        Runtime.getRuntime().maxMemory()
+                );
+                return false;
+            }
+
+            return true;
         }
 
         class GarbageObject {
@@ -177,41 +218,54 @@
 
         private final List<GarbageObject> garbage = new ArrayList();
 
-        public void test(int num_iterate) throws IOException {
+        public void test() throws IOException {
+
+            MemoryUsage muFull, muFree, muAuxDataFull, muAuxDataFree;
+            float auxFull, auxFree;
 
             allocate();
             link();
             mutate();
-            deallocate();
+
+            muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+            long numUsedRegions = WhiteBox.getWhiteBox().g1NumMaxRegions()
+                    - WhiteBox.getWhiteBox().g1NumFreeRegions();
+            muAuxDataFull = WhiteBox.getWhiteBox().g1AuxiliaryMemoryUsage();
+            auxFull = (float)muAuxDataFull.getUsed() / numUsedRegions;
 
-            MemoryUsage muBeforeHeap
-                        = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
-            MemoryUsage muBeforeNonHeap
-                        = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
+            System.out.format("Full aux data  ratio= %f, regions max= %d, used= %d\n",
+                    auxFull, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions
+            );
+
+            deallocate();
+            System.gc();
 
-            for (int i = 0; i < num_iterate; i++) {
-                allocate();
-                link();
-                mutate();
-                deallocate();
-            }
+            muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+            muAuxDataFree = WhiteBox.getWhiteBox().g1AuxiliaryMemoryUsage();
+
+            numUsedRegions = WhiteBox.getWhiteBox().g1NumMaxRegions()
+                    - WhiteBox.getWhiteBox().g1NumFreeRegions();
+            auxFree = (float)muAuxDataFree.getUsed() / numUsedRegions;
 
-            System.gc();
-            MemoryUsage muAfterHeap
-                        = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
-            MemoryUsage muAfterNonHeap
-                        = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
+            System.out.format("Free aux data ratio= %f, regions max= %d, used= %d\n",
+                    auxFree, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions
+            );
 
-            assertLessThanOrEqual(muAfterHeap.getCommitted(), muBeforeHeap.getCommitted(),
-                    String.format("heap decommit failed - after > before: %d > %d",
-                            muAfterHeap.getCommitted(), muBeforeHeap.getCommitted()
+            Asserts.assertLessThanOrEqual(muFree.getCommitted(), muFull.getCommitted(),
+                    String.format("heap decommit failed - full > free: %d > %d",
+                            muFree.getCommitted(), muFull.getCommitted()
                     )
             );
 
-            if (muAfterHeap.getCommitted() < muBeforeHeap.getCommitted()) {
-                assertLessThanOrEqual(muAfterNonHeap.getCommitted(), muBeforeNonHeap.getCommitted(),
-                        String.format("non-heap decommit failed - after > before: %d > %d",
-                                muAfterNonHeap.getCommitted(), muBeforeNonHeap.getCommitted()
+            System.out.format("State               used   committed\n");
+            System.out.format("Full aux data: %10d %10d\n", muAuxDataFull.getUsed(), muAuxDataFull.getCommitted());
+            System.out.format("Free aux data: %10d %10d\n", muAuxDataFree.getUsed(), muAuxDataFree.getCommitted());
+
+            // if decommited check that aux data has same ratio
+            if (muFree.getCommitted() < muFull.getCommitted()) {
+                Asserts.assertLessThanOrEqual(auxFree, auxFull,
+                        String.format("auxiliary data decommit failed - full > free: %f > %f",
+                                auxFree, auxFull
                         )
                 );
             }
@@ -238,8 +292,7 @@
                 for (int i = 0; i < NUM_LINKS; i++) {
                     int regionToLink;
                     do {
-                        regionToLink = (int) (Math.random()
-                                * REGIONS_TO_ALLOCATE);
+                        regionToLink = (int) (Math.random() * REGIONS_TO_ALLOCATE);
                     } while (regionToLink == regionNumber);
 
                     // get random garbage object from random region
@@ -265,9 +318,7 @@
             return REGIONS_TO_ALLOCATE * REGION_SIZE;
         }
 
-        private static final int REGION_SIZE = 1024 * 1024;
-        private static final int DEFAULT_ITERATION_COUNT = 1;   // iterate main scenario
-        private static final int REGIONS_TO_ALLOCATE = 5;
+        private static final int REGIONS_TO_ALLOCATE = 100;
         private static final int NUM_OBJECTS_PER_REGION = 10;
         private static final int NUM_LINKS = 20; // how many links create for each object
     }
--- a/test/gc/g1/TestShrinkAuxiliaryData00.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData00.java	Thu May 21 22:54:21 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
@@ -23,11 +23,15 @@
 
 /**
  * @test TestShrinkAuxiliaryData00
- * @bug 8038423
+ * @bug 8038423 8061715
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
+ * @requires vm.gc=="G1" | vm.gc=="null"
  * @library /testlibrary /testlibrary/whitebox
- * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData00
+ * @build com.oracle.java.testlibrary.* sun.hotspot.WhiteBox
+ *        TestShrinkAuxiliaryData TestShrinkAuxiliaryData00
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run driver/timeout=720 TestShrinkAuxiliaryData00
  */
 public class TestShrinkAuxiliaryData00 {
--- a/test/gc/g1/TestShrinkAuxiliaryData05.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData05.java	Thu May 21 22:54:21 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
@@ -23,12 +23,15 @@
 
 /**
  * @test TestShrinkAuxiliaryData05
- * @bug 8038423
+ * @bug 8038423 8061715
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
  * @library /testlibrary /testlibrary/whitebox
- * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData05
+ * @build com.oracle.java.testlibrary.* sun.hotspot.WhiteBox
+ *        TestShrinkAuxiliaryData TestShrinkAuxiliaryData05
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run driver/timeout=720 TestShrinkAuxiliaryData05
  */
 public class TestShrinkAuxiliaryData05 {
--- a/test/gc/g1/TestShrinkAuxiliaryData10.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData10.java	Thu May 21 22:54:21 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
@@ -23,12 +23,15 @@
 
 /**
  * @test TestShrinkAuxiliaryData10
- * @bug 8038423
+ * @bug 8038423 8061715
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
  * @library /testlibrary /testlibrary/whitebox
+ * @build com.oracle.java.testlibrary.* sun.hotspot.WhiteBox
  * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData10
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run driver/timeout=720 TestShrinkAuxiliaryData10
  */
 public class TestShrinkAuxiliaryData10 {
--- a/test/gc/g1/TestShrinkAuxiliaryData15.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData15.java	Thu May 21 22:54:21 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
@@ -23,12 +23,15 @@
 
 /**
  * @test TestShrinkAuxiliaryData15
- * @bug 8038423
+ * @bug 8038423 8061715
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
  * @library /testlibrary /testlibrary/whitebox
+ * @build com.oracle.java.testlibrary.* sun.hotspot.WhiteBox
  * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData15
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run driver/timeout=720 TestShrinkAuxiliaryData15
  */
 public class TestShrinkAuxiliaryData15 {
--- a/test/gc/g1/TestShrinkAuxiliaryData20.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData20.java	Thu May 21 22:54:21 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
@@ -23,12 +23,15 @@
 
 /**
  * @test TestShrinkAuxiliaryData20
- * @bug 8038423
+ * @bug 8038423 8061715
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
  * @library /testlibrary /testlibrary/whitebox
+ * @build com.oracle.java.testlibrary.* sun.hotspot.WhiteBox
  * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData20
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run driver/timeout=720 TestShrinkAuxiliaryData20
  */
 public class TestShrinkAuxiliaryData20 {
--- a/test/gc/g1/TestShrinkAuxiliaryData25.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData25.java	Thu May 21 22:54:21 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
@@ -23,12 +23,15 @@
 
 /**
  * @test TestShrinkAuxiliaryData25
- * @bug 8038423
+ * @bug 8038423 8061715
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
  * @library /testlibrary /testlibrary/whitebox
+ * @build com.oracle.java.testlibrary.* sun.hotspot.WhiteBox
  * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData25
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run driver/timeout=720 TestShrinkAuxiliaryData25
  */
 public class TestShrinkAuxiliaryData25 {
--- a/test/gc/g1/TestShrinkAuxiliaryData30.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/gc/g1/TestShrinkAuxiliaryData30.java	Thu May 21 22:54:21 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
@@ -23,12 +23,15 @@
 
 /**
  * @test TestShrinkAuxiliaryData30
- * @bug 8038423
+ * @bug 8038423 8061715
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
  * @library /testlibrary /testlibrary/whitebox
+ * @build com.oracle.java.testlibrary.* sun.hotspot.WhiteBox
  * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData30
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run driver/timeout=720 TestShrinkAuxiliaryData30
  */
 public class TestShrinkAuxiliaryData30 {
--- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Thu May 21 10:00:37 2015 -0700
+++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Thu May 21 22:54:21 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, 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
@@ -24,6 +24,7 @@
 
 package sun.hotspot;
 
+import java.lang.management.MemoryUsage;
 import java.lang.reflect.Executable;
 import java.util.Arrays;
 import java.util.List;
@@ -102,8 +103,10 @@
   // G1
   public native boolean g1InConcurrentMark();
   public native boolean g1IsHumongous(Object o);
+  public native long    g1NumMaxRegions();
   public native long    g1NumFreeRegions();
   public native int     g1RegionSize();
+  public native MemoryUsage g1AuxiliaryMemoryUsage();
   public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
 
   // NMT