Merge
authoramurillo
Fri, 25 Apr 2014 09:59:44 -0700
changeset 24112 3d9b5fbd157c
parent 24077 0809c9a4d36e (current diff)
parent 24111 47f5725e0d7c (diff)
child 24113 db0b706c8253
child 24241 cddb46f7b7fa
child 24244 2c7a1e5649bd
Merge
hotspot/test/runtime/6925573/SortMethodsTest.java
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -2003,7 +2003,7 @@
       }
     } else {
       assert(MethodData::profile_return(), "either profile call args or call ret");
-      update_mdp_by_constant(in_bytes(ReturnTypeEntry::size()));
+      update_mdp_by_constant(in_bytes(TypeEntriesAtCall::return_only_size()));
     }
 
     // mdp points right after the end of the
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -137,7 +137,7 @@
       movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
     } else {
       assert(MethodData::profile_return(), "either profile call args or call ret");
-      update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size()));
+      update_mdp_by_constant(mdp, in_bytes(TypeEntriesAtCall::return_only_size()));
     }
 
     // mdp points right after the end of the
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -3188,8 +3188,8 @@
 #ifdef ASSERT
       Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
       int n = x->nb_profiled_args();
-      assert(MethodData::profile_parameters() && x->inlined() &&
-             ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)),
+      assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
+                                                  (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
              "only at JSR292 bytecodes");
 #endif
     }
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -2831,7 +2831,6 @@
     }
   }
 
-  assert(operand_fill_index == operands->length(), "exact fill");
   assert(ConstantPool::operand_array_length(operands) == attribute_array_length, "correct decode");
 
   u1* current_end = cfs->current();
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -564,11 +564,11 @@
                       "--------------------------------\n");
   size_t total_size = totalSizeInIndexedFreeLists();
   size_t   free_blocks = numFreeBlocksInIndexedFreeLists();
-  gclog_or_tty->print("Total Free Space: %d\n", total_size);
-  gclog_or_tty->print("Max   Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists());
-  gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
+  gclog_or_tty->print("Total Free Space: " SIZE_FORMAT "\n", total_size);
+  gclog_or_tty->print("Max   Chunk Size: " SIZE_FORMAT "\n", maxChunkSizeInIndexedFreeLists());
+  gclog_or_tty->print("Number of Blocks: " SIZE_FORMAT "\n", free_blocks);
   if (free_blocks != 0) {
-    gclog_or_tty->print("Av.  Block  Size: %d\n", total_size/free_blocks);
+    gclog_or_tty->print("Av.  Block  Size: " SIZE_FORMAT "\n", total_size/free_blocks);
   }
 }
 
@@ -2152,7 +2152,7 @@
   for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
     AdaptiveFreeList<FreeChunk>* fl    = &_indexedFreeList[i];
     if (PrintFLSStatistics > 1) {
-      gclog_or_tty->print("size[%d] : ", i);
+      gclog_or_tty->print("size[" SIZE_FORMAT "] : ", i);
     }
     fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
     fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
@@ -2683,7 +2683,8 @@
       _global_num_workers[i] = 0;
       _global_num_blocks[i] = 0;
       if (PrintOldPLAB) {
-        gclog_or_tty->print_cr("[%d]: %d", i, (size_t)_blocks_to_claim[i].average());
+        gclog_or_tty->print_cr("[" SIZE_FORMAT "]: " SIZE_FORMAT,
+                               i, (size_t)_blocks_to_claim[i].average());
       }
     }
   }
@@ -2722,7 +2723,7 @@
         }
       }
       if (PrintOldPLAB) {
-        gclog_or_tty->print_cr("%d[%d]: %d/%d/%d",
+        gclog_or_tty->print_cr("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT,
                                tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
       }
       // Reset stats for next round
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -1512,6 +1512,8 @@
     gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate());
     gclog_or_tty->print_cr("occupancy=%3.7f", _cmsGen->occupancy());
     gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy());
+    gclog_or_tty->print_cr("cms_time_since_begin=%3.7f", stats().cms_time_since_begin());
+    gclog_or_tty->print_cr("cms_time_since_end=%3.7f", stats().cms_time_since_end());
     gclog_or_tty->print_cr("metadata initialized %d",
       MetaspaceGC::should_concurrent_collect());
   }
@@ -1574,6 +1576,28 @@
       return true;
     }
 
+  // CMSTriggerInterval starts a CMS cycle if enough time has passed.
+  if (CMSTriggerInterval >= 0) {
+    if (CMSTriggerInterval == 0) {
+      // Trigger always
+      return true;
+    }
+
+    // Check the CMS time since begin (we do not check the stats validity
+    // as we want to be able to trigger the first CMS cycle as well)
+    if (stats().cms_time_since_begin() >= (CMSTriggerInterval / ((double) MILLIUNITS))) {
+      if (Verbose && PrintGCDetails) {
+        if (stats().valid()) {
+          gclog_or_tty->print_cr("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)",
+                                 stats().cms_time_since_begin());
+        } else {
+          gclog_or_tty->print_cr("CMSCollector: collect because of trigger interval (first collection)");
+        }
+      }
+      return true;
+    }
+  }
+
   return false;
 }
 
@@ -2894,13 +2918,13 @@
 
   // Clear the marking bit map array before starting, but, just
   // for kicks, first report if the given address is already marked
-  gclog_or_tty->print_cr("Start: Address 0x%x is%s marked", addr,
+  gclog_or_tty->print_cr("Start: Address " PTR_FORMAT " is%s marked", addr,
                 _markBitMap.isMarked(addr) ? "" : " not");
 
   if (verify_after_remark()) {
     MutexLockerEx x(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
     bool result = verification_mark_bm()->isMarked(addr);
-    gclog_or_tty->print_cr("TransitiveMark: Address 0x%x %s marked", addr,
+    gclog_or_tty->print_cr("TransitiveMark: Address " PTR_FORMAT " %s marked", addr,
                            result ? "IS" : "is NOT");
     return result;
   } else {
@@ -4569,7 +4593,7 @@
       }
     }
     if (PrintCMSStatistics > 0) {
-      gclog_or_tty->print(" [%d iterations, %d waits, %d cards)] ",
+      gclog_or_tty->print(" [" SIZE_FORMAT " iterations, " SIZE_FORMAT " waits, " SIZE_FORMAT " cards)] ",
                           loops, waited, cumworkdone);
     }
   }
@@ -4721,7 +4745,7 @@
        numIter++, lastNumCards = curNumCards, cumNumCards += curNumCards) {
     curNumCards  = preclean_mod_union_table(_cmsGen, &smoac_cl);
     if (Verbose && PrintGCDetails) {
-      gclog_or_tty->print(" (modUnionTable: %d cards)", curNumCards);
+      gclog_or_tty->print(" (modUnionTable: " SIZE_FORMAT " cards)", curNumCards);
     }
     // Either there are very few dirty cards, so re-mark
     // pause will be small anyway, or our pre-cleaning isn't
@@ -4743,7 +4767,7 @@
   curNumCards = preclean_card_table(_cmsGen, &smoac_cl);
   cumNumCards += curNumCards;
   if (PrintGCDetails && PrintCMSStatistics != 0) {
-    gclog_or_tty->print_cr(" (cardTable: %d cards, re-scanned %d cards, %d iterations)",
+    gclog_or_tty->print_cr(" (cardTable: " SIZE_FORMAT " cards, re-scanned " SIZE_FORMAT " cards, " SIZE_FORMAT " iterations)",
                   curNumCards, cumNumCards, numIter);
   }
   return cumNumCards;   // as a measure of useful work done
@@ -8205,7 +8229,7 @@
 void SweepClosure::initialize_free_range(HeapWord* freeFinger,
     bool freeRangeInFreeLists) {
   if (CMSTraceSweeper) {
-    gclog_or_tty->print("---- Start free range at 0x%x with free block (%d)\n",
+    gclog_or_tty->print("---- Start free range at " PTR_FORMAT " with free block (%d)\n",
                freeFinger, freeRangeInFreeLists);
   }
   assert(!inFreeRange(), "Trampling existing free range");
@@ -8275,10 +8299,10 @@
                            pointer_delta(addr, freeFinger()));
       if (CMSTraceSweeper) {
         gclog_or_tty->print("Sweep: last chunk: ");
-        gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") "
-                   "[coalesced:"SIZE_FORMAT"]\n",
+        gclog_or_tty->print("put_free_blk " PTR_FORMAT " ("SIZE_FORMAT") "
+                   "[coalesced:%d]\n",
                    freeFinger(), pointer_delta(addr, freeFinger()),
-                   lastFreeRangeCoalesced());
+                   lastFreeRangeCoalesced() ? 1 : 0);
       }
     }
 
@@ -8421,7 +8445,7 @@
         // the midst of a free range, we are coalescing
         print_free_block_coalesced(fc);
         if (CMSTraceSweeper) {
-          gclog_or_tty->print("  -- pick up free block 0x%x (%d)\n", fc, size);
+          gclog_or_tty->print("  -- pick up free block " PTR_FORMAT " (" SIZE_FORMAT ")\n", fc, size);
         }
         // remove it from the free lists
         _sp->removeFreeChunkFromFreeLists(fc);
@@ -8483,7 +8507,7 @@
       // this will be swept up when we hit the end of the
       // free range
       if (CMSTraceSweeper) {
-        gclog_or_tty->print("  -- pick up garbage 0x%x (%d) \n", fc, size);
+        gclog_or_tty->print("  -- pick up garbage " PTR_FORMAT " (" SIZE_FORMAT ")\n", fc, size);
       }
       // If the chunk is being coalesced and the current free range is
       // in the free lists, remove the current free range so that it
@@ -8576,7 +8600,7 @@
   }
 
   if (CMSTraceSweeper) {
-    gclog_or_tty->print_cr("  -- pick up another chunk at 0x%x (%d)", fc, chunkSize);
+    gclog_or_tty->print_cr("  -- pick up another chunk at " PTR_FORMAT " (" SIZE_FORMAT ")", fc, chunkSize);
   }
 
   HeapWord* const fc_addr = (HeapWord*) fc;
@@ -8705,7 +8729,7 @@
         "chunk should not be in free lists yet");
     }
     if (CMSTraceSweeper) {
-      gclog_or_tty->print_cr(" -- add free block 0x%x (%d) to free lists",
+      gclog_or_tty->print_cr(" -- add free block " PTR_FORMAT " (" SIZE_FORMAT ") to free lists",
                     chunk, size);
     }
     // A new free range is going to be starting.  The current
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -265,7 +265,7 @@
     slots += _spoolHead->bufferSize - 1;
     blocks++;
   }
-  gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ",
+  gclog_or_tty->print_cr(" [worker %d] promo_blocks = " SIZE_FORMAT ", promo_slots = " SIZE_FORMAT,
                          worker_id, blocks, slots);
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -29,7 +29,7 @@
 #include "gc_implementation/g1/g1HotCardCache.hpp"
 #include "runtime/java.hpp"
 
-ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
+ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure) :
   _threads(NULL), _n_threads(0),
   _hot_card_cache(g1h)
 {
@@ -61,7 +61,7 @@
 
   ConcurrentG1RefineThread *next = NULL;
   for (uint i = _n_threads - 1; i != UINT_MAX; i--) {
-    ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
+    ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, refine_closure, worker_id_offset, i);
     assert(t != NULL, "Conc refine should have been created");
     if (t->osthread() == NULL) {
         vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -71,7 +71,7 @@
   void reset_threshold_step();
 
  public:
-  ConcurrentG1Refine(G1CollectedHeap* g1h);
+  ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure);
   ~ConcurrentG1Refine();
 
   void init(); // Accomplish some initialization that has to wait.
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -33,8 +33,10 @@
 
 ConcurrentG1RefineThread::
 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
+                         CardTableEntryClosure* refine_closure,
                          uint worker_id_offset, uint worker_id) :
   ConcurrentGCThread(),
+  _refine_closure(refine_closure),
   _worker_id_offset(worker_id_offset),
   _worker_id(worker_id),
   _active(false),
@@ -71,6 +73,7 @@
 }
 
 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
+  SuspendibleThreadSetJoiner sts;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1p = g1h->g1_policy();
   if (g1p->adaptive_young_list_length()) {
@@ -82,8 +85,8 @@
 
       // we try to yield every time we visit 10 regions
       if (regions_visited == 10) {
-        if (_sts.should_yield()) {
-          _sts.yield("G1 refine");
+        if (sts.should_yield()) {
+          sts.yield();
           // we just abandon the iteration
           break;
         }
@@ -99,9 +102,7 @@
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   _vtime_start = os::elapsedVTime();
   while(!_should_terminate) {
-    _sts.join();
     sample_young_list_rs_lengths();
-    _sts.leave();
 
     if (os::supports_vtime()) {
       _vtime_accum = (os::elapsedVTime() - _vtime_start);
@@ -182,37 +183,37 @@
       break;
     }
 
-    _sts.join();
+    {
+      SuspendibleThreadSetJoiner sts;
+
+      do {
+        int curr_buffer_num = (int)dcqs.completed_buffers_num();
+        // If the number of the buffers falls down into the yellow zone,
+        // that means that the transition period after the evacuation pause has ended.
+        if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
+          dcqs.set_completed_queue_padding(0);
+        }
 
-    do {
-      int curr_buffer_num = (int)dcqs.completed_buffers_num();
-      // If the number of the buffers falls down into the yellow zone,
-      // that means that the transition period after the evacuation pause has ended.
-      if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
-        dcqs.set_completed_queue_padding(0);
-      }
+        if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
+          // If the number of the buffer has fallen below our threshold
+          // we should deactivate. The predecessor will reactivate this
+          // thread should the number of the buffers cross the threshold again.
+          deactivate();
+          break;
+        }
 
-      if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
-        // If the number of the buffer has fallen below our threshold
-        // we should deactivate. The predecessor will reactivate this
-        // thread should the number of the buffers cross the threshold again.
+        // Check if we need to activate the next thread.
+        if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
+          _next->activate();
+        }
+      } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, cg1r()->green_zone()));
+
+      // We can exit the loop above while being active if there was a yield request.
+      if (is_active()) {
         deactivate();
-        break;
       }
-
-      // Check if we need to activate the next thread.
-      if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
-        _next->activate();
-      }
-    } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone()));
-
-    // We can exit the loop above while being active if there was a yield request.
-    if (is_active()) {
-      deactivate();
     }
 
-    _sts.leave();
-
     if (os::supports_vtime()) {
       _vtime_accum = (os::elapsedVTime() - _vtime_start);
     } else {
@@ -223,17 +224,6 @@
   terminate();
 }
 
-
-void ConcurrentG1RefineThread::yield() {
-  if (G1TraceConcRefinement) {
-    gclog_or_tty->print_cr("G1-Refine-yield");
-  }
-  _sts.yield("G1 refine");
-  if (G1TraceConcRefinement) {
-    gclog_or_tty->print_cr("G1-Refine-yield-end");
-  }
-}
-
 void ConcurrentG1RefineThread::stop() {
   // it is ok to take late safepoints here, if needed
   {
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -28,6 +28,7 @@
 #include "gc_implementation/shared/concurrentGCThread.hpp"
 
 // Forward Decl.
+class CardTableEntryClosure;
 class ConcurrentG1Refine;
 
 // The G1 Concurrent Refinement Thread (could be several in the future).
@@ -49,6 +50,9 @@
   Monitor* _monitor;
   ConcurrentG1Refine* _cg1r;
 
+  // The closure applied to completed log buffers.
+  CardTableEntryClosure* _refine_closure;
+
   int _thread_threshold_step;
   // This thread activation threshold
   int _threshold;
@@ -64,13 +68,11 @@
   void activate();
   void deactivate();
 
-  // For use by G1CollectedHeap, which is a friend.
-  static SuspendibleThreadSet* sts() { return &_sts; }
-
 public:
   virtual void run();
   // Constructor
   ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
+                           CardTableEntryClosure* refine_closure,
                            uint worker_id_offset, uint worker_id);
 
   void initialize();
@@ -84,8 +86,6 @@
 
   ConcurrentG1Refine* cg1r() { return _cg1r;     }
 
-  // Yield for GC
-  void yield();
   // shutdown
   void stop();
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -976,11 +976,11 @@
   }
 
   if (concurrent()) {
-    ConcurrentGCThread::stsLeave();
+    SuspendibleThreadSet::leave();
   }
   _first_overflow_barrier_sync.enter();
   if (concurrent()) {
-    ConcurrentGCThread::stsJoin();
+    SuspendibleThreadSet::join();
   }
   // at this point everyone should have synced up and not be doing any
   // more work
@@ -1024,11 +1024,11 @@
   }
 
   if (concurrent()) {
-    ConcurrentGCThread::stsLeave();
+    SuspendibleThreadSet::leave();
   }
   _second_overflow_barrier_sync.enter();
   if (concurrent()) {
-    ConcurrentGCThread::stsJoin();
+    SuspendibleThreadSet::join();
   }
   // at this point everything should be re-initialized and ready to go
 
@@ -1076,7 +1076,7 @@
 
     double start_vtime = os::elapsedVTime();
 
-    ConcurrentGCThread::stsJoin();
+    SuspendibleThreadSet::join();
 
     assert(worker_id < _cm->active_tasks(), "invariant");
     CMTask* the_task = _cm->task(worker_id);
@@ -1103,9 +1103,9 @@
         if (!_cm->has_aborted() && the_task->has_aborted()) {
           sleep_time_ms =
             (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
-          ConcurrentGCThread::stsLeave();
+          SuspendibleThreadSet::leave();
           os::sleep(Thread::current(), sleep_time_ms, false);
-          ConcurrentGCThread::stsJoin();
+          SuspendibleThreadSet::join();
         }
         double end_time2_sec = os::elapsedTime();
         double elapsed_time2_sec = end_time2_sec - start_time_sec;
@@ -1123,7 +1123,7 @@
     the_task->record_end_time();
     guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
 
-    ConcurrentGCThread::stsLeave();
+    SuspendibleThreadSet::leave();
 
     double end_vtime = os::elapsedVTime();
     _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime);
@@ -2655,7 +2655,6 @@
       str = " O";
     } else {
       HeapRegion* hr  = _g1h->heap_region_containing(obj);
-      guarantee(hr != NULL, "invariant");
       bool over_tams = _g1h->allocated_since_marking(obj, hr, _vo);
       bool marked = _g1h->is_marked(obj, _vo);
 
@@ -3302,21 +3301,17 @@
 
 // We take a break if someone is trying to stop the world.
 bool ConcurrentMark::do_yield_check(uint worker_id) {
-  if (should_yield()) {
+  if (SuspendibleThreadSet::should_yield()) {
     if (worker_id == 0) {
       _g1h->g1_policy()->record_concurrent_pause();
     }
-    cmThread()->yield();
+    SuspendibleThreadSet::yield();
     return true;
   } else {
     return false;
   }
 }
 
-bool ConcurrentMark::should_yield() {
-  return cmThread()->should_yield();
-}
-
 bool ConcurrentMark::containing_card_is_marked(void* p) {
   size_t offset = pointer_delta(p, _g1h->reserved_region().start(), 1);
   return _card_bm.at(offset >> CardTableModRefBS::card_shift);
@@ -3417,9 +3412,8 @@
 }
 
 void CMTask::setup_for_region(HeapRegion* hr) {
-  // Separated the asserts so that we know which one fires.
   assert(hr != NULL,
-        "claim_region() should have filtered out continues humongous regions");
+        "claim_region() should have filtered out NULL regions");
   assert(!hr->continuesHumongous(),
         "claim_region() should have filtered out continues humongous regions");
 
@@ -3605,7 +3599,7 @@
 #endif // _MARKING_STATS_
 
   // (4) We check whether we should yield. If we have to, then we abort.
-  if (_cm->should_yield()) {
+  if (SuspendibleThreadSet::should_yield()) {
     // We should yield. To do this we abort the task. The caller is
     // responsible for yielding.
     set_has_aborted();
@@ -3754,7 +3748,7 @@
 
   if (_task_queue->size() > target_size) {
     if (_cm->verbose_high()) {
-      gclog_or_tty->print_cr("[%u] draining local queue, target size = %d",
+      gclog_or_tty->print_cr("[%u] draining local queue, target size = " SIZE_FORMAT,
                              _worker_id, target_size);
     }
 
@@ -3782,7 +3776,7 @@
     }
 
     if (_cm->verbose_high()) {
-      gclog_or_tty->print_cr("[%u] drained local queue, size = %d",
+      gclog_or_tty->print_cr("[%u] drained local queue, size = %u",
                              _worker_id, _task_queue->size());
     }
   }
@@ -3810,7 +3804,7 @@
 
   if (_cm->mark_stack_size() > target_size) {
     if (_cm->verbose_low()) {
-      gclog_or_tty->print_cr("[%u] draining global_stack, target size %d",
+      gclog_or_tty->print_cr("[%u] draining global_stack, target size " SIZE_FORMAT,
                              _worker_id, target_size);
     }
 
@@ -3820,7 +3814,7 @@
     }
 
     if (_cm->verbose_low()) {
-      gclog_or_tty->print_cr("[%u] drained global stack, size = %d",
+      gclog_or_tty->print_cr("[%u] drained global stack, size = " SIZE_FORMAT,
                              _worker_id, _cm->mark_stack_size());
     }
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -814,7 +814,6 @@
   }
 
   inline bool do_yield_check(uint worker_i = 0);
-  inline bool should_yield();
 
   // Called to abort the marking cycle after a Full GC takes place.
   void abort();
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -89,6 +89,10 @@
   while (!_should_terminate) {
     // wait until started is set.
     sleepBeforeNextCycle();
+    if (_should_terminate) {
+      break;
+    }
+
     {
       ResourceMark rm;
       HandleMark   hm;
@@ -190,9 +194,8 @@
       } else {
         // We don't want to update the marking status if a GC pause
         // is already underway.
-        _sts.join();
+        SuspendibleThreadSetJoiner sts;
         g1h->set_marking_complete();
-        _sts.leave();
       }
 
       // Check if cleanup set the free_regions_coming flag. If it
@@ -262,11 +265,12 @@
       // record_concurrent_mark_cleanup_completed() (and, in fact, it's
       // not needed any more as the concurrent mark state has been
       // already reset).
-      _sts.join();
-      if (!cm()->has_aborted()) {
-        g1_policy->record_concurrent_mark_cleanup_completed();
+      {
+        SuspendibleThreadSetJoiner sts;
+        if (!cm()->has_aborted()) {
+          g1_policy->record_concurrent_mark_cleanup_completed();
+        }
       }
-      _sts.leave();
 
       if (cm()->has_aborted()) {
         if (G1Log::fine()) {
@@ -278,36 +282,43 @@
 
       // We now want to allow clearing of the marking bitmap to be
       // suspended by a collection pause.
-      _sts.join();
-      _cm->clearNextBitmap();
-      _sts.leave();
+      {
+        SuspendibleThreadSetJoiner sts;
+        _cm->clearNextBitmap();
+      }
     }
 
     // Update the number of full collections that have been
     // completed. This will also notify the FullGCCount_lock in case a
     // Java thread is waiting for a full GC to happen (e.g., it
     // called System.gc() with +ExplicitGCInvokesConcurrent).
-    _sts.join();
-    g1h->increment_old_marking_cycles_completed(true /* concurrent */);
-    g1h->register_concurrent_cycle_end();
-    _sts.leave();
+    {
+      SuspendibleThreadSetJoiner sts;
+      g1h->increment_old_marking_cycles_completed(true /* concurrent */);
+      g1h->register_concurrent_cycle_end();
+    }
   }
   assert(_should_terminate, "just checking");
 
   terminate();
 }
 
-
-void ConcurrentMarkThread::yield() {
-  _sts.yield("Concurrent Mark");
-}
+void ConcurrentMarkThread::stop() {
+  {
+    MutexLockerEx ml(Terminator_lock);
+    _should_terminate = true;
+  }
 
-void ConcurrentMarkThread::stop() {
-  // it is ok to take late safepoints here, if needed
-  MutexLockerEx mu(Terminator_lock);
-  _should_terminate = true;
-  while (!_has_terminated) {
-    Terminator_lock->wait();
+  {
+    MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag);
+    CGC_lock->notify_all();
+  }
+
+  {
+    MutexLockerEx ml(Terminator_lock);
+    while (!_has_terminated) {
+      Terminator_lock->wait();
+    }
   }
 }
 
@@ -327,11 +338,14 @@
   assert(!in_progress(), "should have been cleared");
 
   MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
-  while (!started()) {
+  while (!started() && !_should_terminate) {
     CGC_lock->wait(Mutex::_no_safepoint_check_flag);
   }
-  set_in_progress();
-  clear_started();
+
+  if (started()) {
+    set_in_progress();
+    clear_started();
+  }
 }
 
 // Note: As is the case with CMS - this method, although exported
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -89,9 +89,6 @@
   // that started() is set and set in_progress().
   bool during_cycle()      { return started() || in_progress(); }
 
-  // Yield for GC
-  void            yield();
-
   // shutdown
   void stop();
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -70,7 +70,7 @@
 
 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
   PtrQueueSet(notify_when_complete),
-  _closure(NULL),
+  _mut_process_closure(NULL),
   _shared_dirty_card_queue(this, true /*perm*/),
   _free_ids(NULL),
   _processed_buffers_mut(0), _processed_buffers_rs_thread(0)
@@ -83,10 +83,11 @@
   return (uint)os::processor_count();
 }
 
-void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
+void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
                                    int process_completed_threshold,
                                    int max_completed_queue,
                                    Mutex* lock, PtrQueueSet* fl_owner) {
+  _mut_process_closure = cl;
   PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold,
                           max_completed_queue, fl_owner);
   set_buffer_size(G1UpdateBufferSize);
@@ -98,18 +99,15 @@
   t->dirty_card_queue().handle_zero_index();
 }
 
-void DirtyCardQueueSet::set_closure(CardTableEntryClosure* closure) {
-  _closure = closure;
-}
-
-void DirtyCardQueueSet::iterate_closure_all_threads(bool consume,
+void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl,
+                                                    bool consume,
                                                     uint worker_i) {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   for(JavaThread* t = Threads::first(); t; t = t->next()) {
-    bool b = t->dirty_card_queue().apply_closure(_closure, consume);
+    bool b = t->dirty_card_queue().apply_closure(cl, consume);
     guarantee(b, "Should not be interrupted.");
   }
-  bool b = shared_dirty_card_queue()->apply_closure(_closure,
+  bool b = shared_dirty_card_queue()->apply_closure(cl,
                                                     consume,
                                                     worker_i);
   guarantee(b, "Should not be interrupted.");
@@ -143,7 +141,7 @@
 
   bool b = false;
   if (worker_i != UINT_MAX) {
-    b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0,
+    b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0,
                                                 _sz, true, worker_i);
     if (b) Atomic::inc(&_processed_buffers_mut);
 
@@ -218,18 +216,11 @@
   return res;
 }
 
-bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i,
-                                                          int stop_at,
-                                                          bool during_pause) {
-  return apply_closure_to_completed_buffer(_closure, worker_i,
-                                           stop_at, during_pause);
-}
-
-void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() {
+void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
   BufferNode* nd = _completed_buffers_head;
   while (nd != NULL) {
     bool b =
-      DirtyCardQueue::apply_closure_to_buffer(_closure,
+      DirtyCardQueue::apply_closure_to_buffer(cl,
                                               BufferNode::make_buffer_from_node(nd),
                                               0, _sz, false);
     guarantee(b, "Should not stop early.");
@@ -237,6 +228,24 @@
   }
 }
 
+void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
+  BufferNode* nd = _cur_par_buffer_node;
+  while (nd != NULL) {
+    BufferNode* next = (BufferNode*)nd->next();
+    BufferNode* actual = (BufferNode*)Atomic::cmpxchg_ptr((void*)next, (volatile void*)&_cur_par_buffer_node, (void*)nd);
+    if (actual == nd) {
+      bool b =
+        DirtyCardQueue::apply_closure_to_buffer(cl,
+                                                BufferNode::make_buffer_from_node(actual),
+                                                0, _sz, false);
+      guarantee(b, "Should not stop early.");
+      nd = next;
+    } else {
+      nd = actual;
+    }
+  }
+}
+
 // Deallocates any completed log buffers
 void DirtyCardQueueSet::clear() {
   BufferNode* buffers_to_delete = NULL;
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -73,7 +73,8 @@
 
 
 class DirtyCardQueueSet: public PtrQueueSet {
-  CardTableEntryClosure* _closure;
+  // The closure used in mut_process_buffer().
+  CardTableEntryClosure* _mut_process_closure;
 
   DirtyCardQueue _shared_dirty_card_queue;
 
@@ -88,10 +89,12 @@
   jint _processed_buffers_mut;
   jint _processed_buffers_rs_thread;
 
+  // Current buffer node used for parallel iteration.
+  BufferNode* volatile _cur_par_buffer_node;
 public:
   DirtyCardQueueSet(bool notify_when_complete = true);
 
-  void initialize(Monitor* cbl_mon, Mutex* fl_lock,
+  void initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
                   int process_completed_threshold,
                   int max_completed_queue,
                   Mutex* lock, PtrQueueSet* fl_owner = NULL);
@@ -102,33 +105,15 @@
 
   static void handle_zero_index_for_thread(JavaThread* t);
 
-  // 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(CardTableEntryClosure* closure);
-
-  // If there is a registered closure for buffers, apply it to all entries
-  // in all currently-active buffers.  This should only be applied at a
-  // safepoint.  (Currently must not be called in parallel; this should
-  // change in the future.)  If "consume" is true, processed entries are
-  // discarded.
-  void iterate_closure_all_threads(bool consume = true,
+  // Apply the given closure to all entries in all currently-active buffers.
+  // This should only be applied at a safepoint. (Currently must not be called
+  // in parallel; this should change in the future.)  If "consume" is true,
+  // processed entries are discarded.
+  void iterate_closure_all_threads(CardTableEntryClosure* cl,
+                                   bool consume = true,
                                    uint worker_i = 0);
 
   // If there exists some completed buffer, pop it, then apply the
-  // registered closure to all its elements, nulling out those elements
-  // processed.  If all elements are processed, returns "true".  If no
-  // completed buffers exist, returns false.  If a completed buffer exists,
-  // but is only partially completed before a "yield" happens, the
-  // partially completed buffer (with its processed elements set to NULL)
-  // is returned to the completed buffer set, and this call returns false.
-  bool apply_closure_to_completed_buffer(uint worker_i = 0,
-                                         int stop_at = 0,
-                                         bool during_pause = false);
-
-  // If there exists some completed buffer, pop it, then apply the
   // specified closure to all its elements, nulling out those elements
   // processed.  If all elements are processed, returns "true".  If no
   // completed buffers exist, returns false.  If a completed buffer exists,
@@ -149,7 +134,12 @@
 
   // Applies the current closure to all completed buffers,
   // non-consumptively.
-  void apply_closure_to_all_completed_buffers();
+  void apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
+
+  void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; }
+  // Applies the current closure to all completed buffers, non-consumptively.
+  // Parallel version.
+  void par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
 
   DirtyCardQueue* shared_dirty_card_queue() {
     return &_shared_dirty_card_queue;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -45,32 +45,27 @@
   }
 }
 
-FreeList<G1CodeRootChunk> G1CodeRootSet::_free_list;
-size_t G1CodeRootSet::_num_chunks_handed_out = 0;
-
-G1CodeRootChunk* G1CodeRootSet::new_chunk() {
-  G1CodeRootChunk* result = _free_list.get_chunk_at_head();
-  if (result == NULL) {
-    result = new G1CodeRootChunk();
-  }
-  G1CodeRootSet::_num_chunks_handed_out++;
-  result->reset();
-  return result;
+G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
+  _free_list.initialize();
+  _free_list.set_size(G1CodeRootChunk::word_size());
 }
 
-void G1CodeRootSet::free_chunk(G1CodeRootChunk* chunk) {
-  _free_list.return_chunk_at_head(chunk);
-  G1CodeRootSet::_num_chunks_handed_out--;
+size_t G1CodeRootChunkManager::fl_mem_size() {
+  return _free_list.count() * _free_list.size();
 }
 
-void G1CodeRootSet::free_all_chunks(FreeList<G1CodeRootChunk>* list) {
-  G1CodeRootSet::_num_chunks_handed_out -= list->count();
+void G1CodeRootChunkManager::free_all_chunks(FreeList<G1CodeRootChunk>* list) {
+  _num_chunks_handed_out -= list->count();
   _free_list.prepend(list);
 }
 
-void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
-  size_t keep = G1CodeRootSet::_num_chunks_handed_out * keep_ratio / 100;
+void G1CodeRootChunkManager::free_chunk(G1CodeRootChunk* chunk) {
+  _free_list.return_chunk_at_head(chunk);
+  _num_chunks_handed_out--;
+}
 
+void G1CodeRootChunkManager::purge_chunks(size_t keep_ratio) {
+  size_t keep = _num_chunks_handed_out * keep_ratio / 100;
   if (keep >= (size_t)_free_list.count()) {
     return;
   }
@@ -88,20 +83,51 @@
   }
 }
 
-size_t G1CodeRootSet::static_mem_size() {
-  return sizeof(_free_list) + sizeof(_num_chunks_handed_out);
+size_t G1CodeRootChunkManager::static_mem_size() {
+  return sizeof(G1CodeRootChunkManager);
+}
+
+
+G1CodeRootChunk* G1CodeRootChunkManager::new_chunk() {
+  G1CodeRootChunk* result = _free_list.get_chunk_at_head();
+  if (result == NULL) {
+    result = new G1CodeRootChunk();
+  }
+  _num_chunks_handed_out++;
+  result->reset();
+  return result;
+}
+
+#ifndef PRODUCT
+
+size_t G1CodeRootChunkManager::num_chunks_handed_out() const {
+  return _num_chunks_handed_out;
 }
 
-size_t G1CodeRootSet::fl_mem_size() {
-  return _free_list.count() * _free_list.size();
+size_t G1CodeRootChunkManager::num_free_chunks() const {
+  return (size_t)_free_list.count();
+}
+
+#endif
+
+G1CodeRootChunkManager G1CodeRootSet::_default_chunk_manager;
+
+void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
+  _default_chunk_manager.purge_chunks(keep_ratio);
 }
 
-void G1CodeRootSet::initialize() {
-  _free_list.initialize();
-  _free_list.set_size(G1CodeRootChunk::word_size());
+size_t G1CodeRootSet::free_chunks_static_mem_size() {
+  return _default_chunk_manager.static_mem_size();
 }
 
-G1CodeRootSet::G1CodeRootSet() : _list(), _length(0) {
+size_t G1CodeRootSet::free_chunks_mem_size() {
+  return _default_chunk_manager.fl_mem_size();
+}
+
+G1CodeRootSet::G1CodeRootSet(G1CodeRootChunkManager* manager) : _manager(manager), _list(), _length(0) {
+  if (_manager == NULL) {
+    _manager = &_default_chunk_manager;
+  }
   _list.initialize();
   _list.set_size(G1CodeRootChunk::word_size());
 }
@@ -187,28 +213,38 @@
   }
 }
 
+size_t G1CodeRootSet::static_mem_size() {
+  return sizeof(G1CodeRootSet);
+}
+
 size_t G1CodeRootSet::mem_size() {
-  return sizeof(this) + _list.count() * _list.size();
+  return G1CodeRootSet::static_mem_size() + _list.count() * _list.size();
 }
 
 #ifndef PRODUCT
 
 void G1CodeRootSet::test() {
-  initialize();
+  G1CodeRootChunkManager mgr;
 
-  assert(_free_list.count() == 0, "Free List must be empty");
-  assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet");
+  assert(mgr.num_chunks_handed_out() == 0, "Must not have handed out chunks yet");
+
+  assert(G1CodeRootChunkManager::static_mem_size() > sizeof(void*),
+         err_msg("The chunk manager's static memory usage seems too small, is only "SIZE_FORMAT" bytes.", G1CodeRootChunkManager::static_mem_size()));
 
   // The number of chunks that we allocate for purge testing.
   size_t const num_chunks = 10;
+
   {
-    G1CodeRootSet set1;
+    G1CodeRootSet set1(&mgr);
     assert(set1.is_empty(), "Code root set must be initially empty but is not.");
 
+    assert(G1CodeRootSet::static_mem_size() > sizeof(void*),
+           err_msg("The code root set's static memory usage seems too small, is only "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
+
     set1.add((nmethod*)1);
-    assert(_num_chunks_handed_out == 1,
+    assert(mgr.num_chunks_handed_out() == 1,
            err_msg("Must have allocated and handed out one chunk, but handed out "
-                   SIZE_FORMAT" chunks", _num_chunks_handed_out));
+                   SIZE_FORMAT" chunks", mgr.num_chunks_handed_out()));
     assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
                                        SIZE_FORMAT" elements", set1.length()));
 
@@ -217,19 +253,19 @@
     for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) {
       set1.add((nmethod*)1);
     }
-    assert(_num_chunks_handed_out == 1,
+    assert(mgr.num_chunks_handed_out() == 1,
            err_msg("Duplicate detection must have prevented allocation of further "
-                   "chunks but contains "SIZE_FORMAT, _num_chunks_handed_out));
+                   "chunks but allocated "SIZE_FORMAT, mgr.num_chunks_handed_out()));
     assert(set1.length() == 1,
            err_msg("Duplicate detection should not have increased the set size but "
                    "is "SIZE_FORMAT, set1.length()));
 
     size_t num_total_after_add = G1CodeRootChunk::word_size() + 1;
     for (size_t i = 0; i < num_total_after_add - 1; i++) {
-      set1.add((nmethod*)(2 + i));
+      set1.add((nmethod*)(uintptr_t)(2 + i));
     }
-    assert(_num_chunks_handed_out > 1,
-           "After adding more code roots, more than one chunks should have been handed out");
+    assert(mgr.num_chunks_handed_out() > 1,
+           "After adding more code roots, more than one additional chunk should have been handed out");
     assert(set1.length() == num_total_after_add,
            err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
                    "need to be in the set, but there are only "SIZE_FORMAT,
@@ -242,27 +278,27 @@
     assert(num_popped == num_total_after_add,
            err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
                    "were added", num_popped, num_total_after_add));
-    assert(_num_chunks_handed_out == 0,
+    assert(mgr.num_chunks_handed_out() == 0,
            err_msg("After popping all elements, all chunks must have been returned "
-                   "but are still "SIZE_FORMAT, _num_chunks_handed_out));
+                   "but there are still "SIZE_FORMAT" additional", mgr.num_chunks_handed_out()));
 
-    purge_chunks(0);
-    assert(_free_list.count() == 0,
+    mgr.purge_chunks(0);
+    assert(mgr.num_free_chunks() == 0,
            err_msg("After purging everything, the free list must be empty but still "
-                   "contains "SIZE_FORMAT" chunks", _free_list.count()));
+                   "contains "SIZE_FORMAT" chunks", mgr.num_free_chunks()));
 
     // Add some more handed out chunks.
     size_t i = 0;
-    while (_num_chunks_handed_out < num_chunks) {
+    while (mgr.num_chunks_handed_out() < num_chunks) {
       set1.add((nmethod*)i);
       i++;
     }
 
     {
       // Generate chunks on the free list.
-      G1CodeRootSet set2;
+      G1CodeRootSet set2(&mgr);
       size_t i = 0;
-      while (_num_chunks_handed_out < num_chunks * 2) {
+      while (mgr.num_chunks_handed_out() < (num_chunks * 2)) {
         set2.add((nmethod*)i);
         i++;
       }
@@ -270,45 +306,45 @@
       // num_chunks elements on the free list.
     }
 
-    assert(_num_chunks_handed_out == num_chunks,
+    assert(mgr.num_chunks_handed_out() == num_chunks,
            err_msg("Deletion of the second set must have resulted in giving back "
-                   "those, but there is still "SIZE_FORMAT" handed out, expecting "
-                   SIZE_FORMAT, _num_chunks_handed_out, num_chunks));
-    assert((size_t)_free_list.count() == num_chunks,
+                   "those, but there are still "SIZE_FORMAT" additional handed out, expecting "
+                   SIZE_FORMAT, mgr.num_chunks_handed_out(), num_chunks));
+    assert(mgr.num_free_chunks() == num_chunks,
            err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
-                   "but there are only "SIZE_FORMAT, num_chunks, _free_list.count()));
+                   "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
 
     size_t const test_percentage = 50;
-    purge_chunks(test_percentage);
-    assert(_num_chunks_handed_out == num_chunks,
+    mgr.purge_chunks(test_percentage);
+    assert(mgr.num_chunks_handed_out() == num_chunks,
            err_msg("Purging must not hand out chunks but there are "SIZE_FORMAT,
-                   _num_chunks_handed_out));
-    assert((size_t)_free_list.count() == (ssize_t)(num_chunks * test_percentage / 100),
+                   mgr.num_chunks_handed_out()));
+    assert(mgr.num_free_chunks() == (size_t)(mgr.num_chunks_handed_out() * test_percentage / 100),
            err_msg("Must have purged "SIZE_FORMAT" percent of "SIZE_FORMAT" chunks"
-                   "but there are "SSIZE_FORMAT, test_percentage, num_chunks,
-                   _free_list.count()));
+                   "but there are "SIZE_FORMAT, test_percentage, num_chunks,
+                   mgr.num_free_chunks()));
     // Purge the remainder of the chunks on the free list.
-    purge_chunks(0);
-    assert(_free_list.count() == 0, "Free List must be empty");
-    assert(_num_chunks_handed_out == num_chunks,
+    mgr.purge_chunks(0);
+    assert(mgr.num_free_chunks() == 0, "Free List must be empty");
+    assert(mgr.num_chunks_handed_out() == num_chunks,
            err_msg("Expected to be "SIZE_FORMAT" chunks handed out from the first set "
-                   "but there are "SIZE_FORMAT, num_chunks, _num_chunks_handed_out));
+                   "but there are "SIZE_FORMAT, num_chunks, mgr.num_chunks_handed_out()));
 
     // Exit of the scope of the set1 object will call the destructor that generates
     // num_chunks additional elements on the free list.
-  }
+   }
 
-  assert(_num_chunks_handed_out == 0,
+  assert(mgr.num_chunks_handed_out() == 0,
          err_msg("Deletion of the only set must have resulted in no chunks handed "
-                 "out, but there is still "SIZE_FORMAT" handed out", _num_chunks_handed_out));
-  assert((size_t)_free_list.count() == num_chunks,
+                 "out, but there is still "SIZE_FORMAT" handed out", mgr.num_chunks_handed_out()));
+  assert(mgr.num_free_chunks() == num_chunks,
          err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
-                 "but there are only "SSIZE_FORMAT, num_chunks, _free_list.count()));
+                 "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
 
   // Restore initial state.
-  purge_chunks(0);
-  assert(_free_list.count() == 0, "Free List must be empty");
-  assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet");
+  mgr.purge_chunks(0);
+  assert(mgr.num_free_chunks() == 0, "Free List must be empty");
+  assert(mgr.num_chunks_handed_out() == 0, "No additional elements must have been handed out yet");
 }
 
 void TestCodeCacheRemSet_test() {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -128,19 +128,45 @@
   }
 };
 
+// Manages free chunks.
+class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC {
+ private:
+  // Global free chunk list management
+  FreeList<G1CodeRootChunk> _free_list;
+  // Total number of chunks handed out
+  size_t _num_chunks_handed_out;
+
+ public:
+  G1CodeRootChunkManager();
+
+  G1CodeRootChunk* new_chunk();
+  void free_chunk(G1CodeRootChunk* chunk);
+  // Free all elements of the given list.
+  void free_all_chunks(FreeList<G1CodeRootChunk>* list);
+
+  void initialize();
+  void purge_chunks(size_t keep_ratio);
+
+  static size_t static_mem_size();
+  size_t fl_mem_size();
+
+#ifndef PRODUCT
+  size_t num_chunks_handed_out() const;
+  size_t num_free_chunks() const;
+#endif
+};
+
 // Implements storage for a set of code roots.
 // All methods that modify the set are not thread-safe except if otherwise noted.
 class G1CodeRootSet VALUE_OBJ_CLASS_SPEC {
  private:
-  // Global free chunk list management
-  static FreeList<G1CodeRootChunk> _free_list;
-  // Total number of chunks handed out
-  static size_t _num_chunks_handed_out;
+  // Global default free chunk manager instance.
+  static G1CodeRootChunkManager _default_chunk_manager;
 
-  static G1CodeRootChunk* new_chunk();
-  static void free_chunk(G1CodeRootChunk* chunk);
+  G1CodeRootChunk* new_chunk() { return _manager->new_chunk(); }
+  void free_chunk(G1CodeRootChunk* chunk) { _manager->free_chunk(chunk); }
   // Free all elements of the given list.
-  static void free_all_chunks(FreeList<G1CodeRootChunk>* list);
+  void free_all_chunks(FreeList<G1CodeRootChunk>* list) { _manager->free_all_chunks(list); }
 
   // Return the chunk that contains the given nmethod, NULL otherwise.
   // Scans the list of chunks backwards, as this method is used to add new
@@ -150,16 +176,18 @@
 
   size_t _length;
   FreeList<G1CodeRootChunk> _list;
+  G1CodeRootChunkManager* _manager;
 
  public:
-  G1CodeRootSet();
+  // If an instance is initialized with a chunk manager of NULL, use the global
+  // default one.
+  G1CodeRootSet(G1CodeRootChunkManager* manager = NULL);
   ~G1CodeRootSet();
 
-  static void initialize();
   static void purge_chunks(size_t keep_ratio);
 
-  static size_t static_mem_size();
-  static size_t fl_mem_size();
+  static size_t free_chunks_static_mem_size();
+  static size_t free_chunks_mem_size();
 
   // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this
   // method is likely to be repeatedly called with the same nmethod.
@@ -179,6 +207,8 @@
   // Length in elements
   size_t length() const { return _length; }
 
+  // Static data memory size in bytes of this set.
+  static size_t static_mem_size();
   // Memory size in bytes taken by this set.
   size_t mem_size();
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -57,6 +57,7 @@
 #include "oops/oop.inline.hpp"
 #include "oops/oop.pcgc.inline.hpp"
 #include "runtime/vmThread.hpp"
+#include "utilities/globalDefinitions.hpp"
 #include "utilities/ticks.hpp"
 
 size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
@@ -92,56 +93,54 @@
 // Local to this file.
 
 class RefineCardTableEntryClosure: public CardTableEntryClosure {
-  SuspendibleThreadSet* _sts;
-  G1RemSet* _g1rs;
-  ConcurrentG1Refine* _cg1r;
   bool _concurrent;
 public:
-  RefineCardTableEntryClosure(SuspendibleThreadSet* sts,
-                              G1RemSet* g1rs,
-                              ConcurrentG1Refine* cg1r) :
-    _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true)
-  {}
+  RefineCardTableEntryClosure() : _concurrent(true) { }
+
   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false);
+    bool oops_into_cset = G1CollectedHeap::heap()->g1_rem_set()->refine_card(card_ptr, worker_i, false);
     // This path is executed by the concurrent refine or mutator threads,
     // concurrently, and so we do not care if card_ptr contains references
     // that point into the collection set.
     assert(!oops_into_cset, "should be");
 
-    if (_concurrent && _sts->should_yield()) {
+    if (_concurrent && SuspendibleThreadSet::should_yield()) {
       // Caller will actually yield.
       return false;
     }
     // Otherwise, we finished successfully; return true.
     return true;
   }
+
   void set_concurrent(bool b) { _concurrent = b; }
 };
 
 
 class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure {
-  int _calls;
-  G1CollectedHeap* _g1h;
+  size_t _num_processed;
   CardTableModRefBS* _ctbs;
   int _histo[256];
-public:
+
+ public:
   ClearLoggedCardTableEntryClosure() :
-    _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set())
+    _num_processed(0), _ctbs(G1CollectedHeap::heap()->g1_barrier_set())
   {
     for (int i = 0; i < 256; i++) _histo[i] = 0;
   }
+
   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
-      _calls++;
-      unsigned char* ujb = (unsigned char*)card_ptr;
-      int ind = (int)(*ujb);
-      _histo[ind]++;
-      *card_ptr = -1;
-    }
+    unsigned char* ujb = (unsigned char*)card_ptr;
+    int ind = (int)(*ujb);
+    _histo[ind]++;
+
+    *card_ptr = (jbyte)CardTableModRefBS::clean_card_val();
+    _num_processed++;
+
     return true;
   }
-  int calls() { return _calls; }
+
+  size_t num_processed() { return _num_processed; }
+
   void print_histo() {
     gclog_or_tty->print_cr("Card table value histogram:");
     for (int i = 0; i < 256; i++) {
@@ -152,22 +151,20 @@
   }
 };
 
-class RedirtyLoggedCardTableEntryClosure: public CardTableEntryClosure {
-  int _calls;
-  G1CollectedHeap* _g1h;
-  CardTableModRefBS* _ctbs;
-public:
-  RedirtyLoggedCardTableEntryClosure() :
-    _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {}
+class RedirtyLoggedCardTableEntryClosure : public CardTableEntryClosure {
+ private:
+  size_t _num_processed;
+
+ public:
+  RedirtyLoggedCardTableEntryClosure() : CardTableEntryClosure(), _num_processed(0) { }
 
   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
-      _calls++;
-      *card_ptr = 0;
-    }
+    *card_ptr = CardTableModRefBS::dirty_card_val();
+    _num_processed++;
     return true;
   }
-  int calls() { return _calls; }
+
+  size_t num_processed() const { return _num_processed; }
 };
 
 YoungList::YoungList(G1CollectedHeap* g1h) :
@@ -431,6 +428,9 @@
 void G1CollectedHeap::stop_conc_gc_threads() {
   _cg1r->stop();
   _cmThread->stop();
+  if (G1StringDedup::is_enabled()) {
+    G1StringDedup::stop();
+  }
 }
 
 #ifdef ASSERT
@@ -445,24 +445,18 @@
 // implementation of is_scavengable() for G1 will indicate that
 // all nmethods must be scanned during a partial collection.
 bool G1CollectedHeap::is_in_partial_collection(const void* p) {
-  HeapRegion* hr = heap_region_containing(p);
-  return hr != NULL && hr->in_collection_set();
+  if (p == NULL) {
+    return false;
+  }
+  return heap_region_containing(p)->in_collection_set();
 }
 #endif
 
 // Returns true if the reference points to an object that
 // can move in an incremental collection.
 bool G1CollectedHeap::is_scavengable(const void* p) {
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  G1CollectorPolicy* g1p = g1h->g1_policy();
   HeapRegion* hr = heap_region_containing(p);
-  if (hr == NULL) {
-     // null
-     assert(p == NULL, err_msg("Not NULL " PTR_FORMAT ,p));
-     return false;
-  } else {
-    return !hr->isHumongous();
-  }
+  return !hr->isHumongous();
 }
 
 void G1CollectedHeap::check_ct_logs_at_safepoint() {
@@ -476,9 +470,8 @@
 
   // First clear the logged cards.
   ClearLoggedCardTableEntryClosure clear;
-  dcqs.set_closure(&clear);
-  dcqs.apply_closure_to_all_completed_buffers();
-  dcqs.iterate_closure_all_threads(false);
+  dcqs.apply_closure_to_all_completed_buffers(&clear);
+  dcqs.iterate_closure_all_threads(&clear, false);
   clear.print_histo();
 
   // Now ensure that there's no dirty cards.
@@ -491,13 +484,13 @@
   guarantee(count2.n() == 0, "Card table should be clean.");
 
   RedirtyLoggedCardTableEntryClosure redirty;
-  JavaThread::dirty_card_queue_set().set_closure(&redirty);
-  dcqs.apply_closure_to_all_completed_buffers();
-  dcqs.iterate_closure_all_threads(false);
+  dcqs.apply_closure_to_all_completed_buffers(&redirty);
+  dcqs.iterate_closure_all_threads(&redirty, false);
   gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.",
-                         clear.calls(), orig_count);
-  guarantee(redirty.calls() == clear.calls(),
-            "Or else mechanism is broken.");
+                         clear.num_processed(), orig_count);
+  guarantee(redirty.num_processed() == clear.num_processed(),
+            err_msg("Redirtied "SIZE_FORMAT" cards, bug cleared "SIZE_FORMAT,
+                    redirty.num_processed(), clear.num_processed()));
 
   CountNonCleanMemRegionClosure count3(this);
   ct_bs->mod_card_iterate(&count3);
@@ -506,8 +499,6 @@
                            orig_count, count3.n());
     guarantee(count3.n() >= orig_count, "Should have restored them all.");
   }
-
-  JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
 }
 
 // Private class members.
@@ -1512,9 +1503,6 @@
       assert(g1_policy()->collection_set() == NULL, "must be");
       g1_policy()->start_incremental_cset_building();
 
-      // Clear the _cset_fast_test bitmap in anticipation of adding
-      // regions to the incremental collection set for the next
-      // evacuation pause.
       clear_cset_fast_test();
 
       init_mutator_alloc_region();
@@ -1934,8 +1922,7 @@
   _old_marking_cycles_started(0),
   _old_marking_cycles_completed(0),
   _concurrent_cycle_started(false),
-  _in_cset_fast_test(NULL),
-  _in_cset_fast_test_base(NULL),
+  _in_cset_fast_test(),
   _dirty_cards_region_list(NULL),
   _worker_cset_start_region(NULL),
   _worker_cset_start_region_time_stamp(NULL),
@@ -2005,7 +1992,9 @@
   Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
   Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap");
 
-  _cg1r = new ConcurrentG1Refine(this);
+  _refine_cte_cl = new RefineCardTableEntryClosure();
+
+  _cg1r = new ConcurrentG1Refine(this, _refine_cte_cl);
 
   // Reserve the maximum.
 
@@ -2077,20 +2066,7 @@
 
   _g1h = this;
 
-  _in_cset_fast_test_length = max_regions();
-  _in_cset_fast_test_base =
-                   NEW_C_HEAP_ARRAY(bool, (size_t) _in_cset_fast_test_length, mtGC);
-
-  // We're biasing _in_cset_fast_test to avoid subtracting the
-  // beginning of the heap every time we want to index; basically
-  // it's the same with what we do with the card table.
-  _in_cset_fast_test = _in_cset_fast_test_base -
-               ((uintx) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes);
-
-  // Clear the _cset_fast_test bitmap in anticipation of adding
-  // regions to the incremental collection set for the first
-  // evacuation pause.
-  clear_cset_fast_test();
+  _in_cset_fast_test.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes);
 
   // Create the ConcurrentMark data structure and thread.
   // (Must do this late, so that "max_regions" is defined.)
@@ -2113,25 +2089,21 @@
   // Perform any initialization actions delegated to the policy.
   g1_policy()->init();
 
-  _refine_cte_cl =
-    new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(),
-                                    g1_rem_set(),
-                                    concurrent_g1_refine());
-  JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
-
   JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
                                                SATB_Q_FL_lock,
                                                G1SATBProcessCompletedThreshold,
                                                Shared_SATB_Q_lock);
 
-  JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
+  JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl,
+                                                DirtyCardQ_CBL_mon,
                                                 DirtyCardQ_FL_lock,
                                                 concurrent_g1_refine()->yellow_zone(),
                                                 concurrent_g1_refine()->red_zone(),
                                                 Shared_DirtyCardQ_lock);
 
   if (G1DeferredRSUpdate) {
-    dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
+    dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code
+                                      DirtyCardQ_CBL_mon,
                                       DirtyCardQ_FL_lock,
                                       -1, // never trigger processing
                                       -1, // no limit on length
@@ -2141,7 +2113,8 @@
 
   // Initialize the card queue set used to hold cards containing
   // references into the collection set.
-  _into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon,
+  _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code
+                                             DirtyCardQ_CBL_mon,
                                              DirtyCardQ_FL_lock,
                                              -1, // never trigger processing
                                              -1, // no limit on length
@@ -2178,6 +2151,23 @@
   return JNI_OK;
 }
 
+void G1CollectedHeap::stop() {
+#if 0
+  // Stopping concurrent worker threads is currently disabled until
+  // some bugs in concurrent mark has been resolve. Without fixing
+  // those bugs first we risk haning during VM exit when trying to
+  // stop these threads.
+
+  // Abort any ongoing concurrent root region scanning and stop all
+  // concurrent threads. We do this to make sure these threads do
+  // not continue to execute and access resources (e.g. gclog_or_tty)
+  // that are destroyed during shutdown.
+  _cm->root_regions()->abort();
+  _cm->root_regions()->wait_until_scan_finished();
+  stop_conc_gc_threads();
+#endif
+}
+
 size_t G1CollectedHeap::conservative_max_heap_alignment() {
   return HeapRegion::max_region_size();
 }
@@ -2963,21 +2953,16 @@
 
 
 Space* G1CollectedHeap::space_containing(const void* addr) const {
-  Space* res = heap_region_containing(addr);
-  return res;
+  return heap_region_containing(addr);
 }
 
 HeapWord* G1CollectedHeap::block_start(const void* addr) const {
   Space* sp = space_containing(addr);
-  if (sp != NULL) {
-    return sp->block_start(addr);
-  }
-  return NULL;
+  return sp->block_start(addr);
 }
 
 size_t G1CollectedHeap::block_size(const HeapWord* addr) const {
   Space* sp = space_containing(addr);
-  assert(sp != NULL, "block_size of address outside of heap");
   return sp->block_size(addr);
 }
 
@@ -3212,7 +3197,7 @@
     _young_ref_counter_closure.reset_count();
     k->oops_do(&_young_ref_counter_closure);
     if (_young_ref_counter_closure.count() > 0) {
-      guarantee(k->has_modified_oops(), err_msg("Klass %p, has young refs but is not dirty.", k));
+      guarantee(k->has_modified_oops(), err_msg("Klass " PTR_FORMAT ", has young refs but is not dirty.", k));
     }
   }
 };
@@ -3296,7 +3281,7 @@
       int *val;
       for (cur = start; cur < end; cur++) {
         val = (int *) cur;
-        gclog_or_tty->print("\t "PTR_FORMAT":"PTR_FORMAT"\n", val, *val);
+        gclog_or_tty->print("\t "PTR_FORMAT":%d\n", val, *val);
       }
     }
   }
@@ -4125,9 +4110,6 @@
         // Start a new incremental collection set for the next pause.
         g1_policy()->start_incremental_cset_building();
 
-        // Clear the _cset_fast_test bitmap in anticipation of adding
-        // regions to the incremental collection set for the next
-        // evacuation pause.
         clear_cset_fast_test();
 
         _young_list->reset_sampled_info();
@@ -4304,7 +4286,7 @@
     // this point does not assume that we are the only GC thread
     // running. Note: of course, the actual marking work will
     // not start until the safepoint itself is released in
-    // ConcurrentGCThread::safepoint_desynchronize().
+    // SuspendibleThreadSet::desynchronize().
     doConcurrentMark();
   }
 
@@ -4571,7 +4553,7 @@
 }
 
 G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) :
-  ParGCAllocBuffer(gclab_word_size), _retired(false) { }
+  ParGCAllocBuffer(gclab_word_size), _retired(true) { }
 
 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
   : _g1h(g1h),
@@ -4694,30 +4676,19 @@
   _worker_id(par_scan_state->queue_num()) { }
 
 void G1ParCopyHelper::mark_object(oop obj) {
-#ifdef ASSERT
-  HeapRegion* hr = _g1->heap_region_containing(obj);
-  assert(hr != NULL, "sanity");
-  assert(!hr->in_collection_set(), "should not mark objects in the CSet");
-#endif // ASSERT
+  assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet");
 
   // We know that the object is not moving so it's safe to read its size.
   _cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
 }
 
 void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) {
-#ifdef ASSERT
   assert(from_obj->is_forwarded(), "from obj should be forwarded");
   assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee");
   assert(from_obj != to_obj, "should not be self-forwarded");
 
-  HeapRegion* from_hr = _g1->heap_region_containing(from_obj);
-  assert(from_hr != NULL, "sanity");
-  assert(from_hr->in_collection_set(), "from obj should be in the CSet");
-
-  HeapRegion* to_hr = _g1->heap_region_containing(to_obj);
-  assert(to_hr != NULL, "sanity");
-  assert(!to_hr->in_collection_set(), "should not mark objects in the CSet");
-#endif // ASSERT
+  assert(_g1->heap_region_containing(from_obj)->in_collection_set(), "from obj should be in the CSet");
+  assert(!_g1->heap_region_containing(to_obj)->in_collection_set(), "should not mark objects in the CSet");
 
   // The object might be in the process of being copied by another
   // worker so we cannot trust that its to-space image is
@@ -4935,8 +4906,6 @@
       pss->trim_queue();
     }
   } while (!offer_termination());
-
-  pss->retire_alloc_buffers();
 }
 
 class G1KlassScanClosure : public KlassClosure {
@@ -5273,11 +5242,25 @@
   }
 }
 
-class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
-public:
-  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    *card_ptr = CardTableModRefBS::dirty_card_val();
-    return true;
+class G1RedirtyLoggedCardsTask : public AbstractGangTask {
+ private:
+  DirtyCardQueueSet* _queue;
+ public:
+  G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { }
+
+  virtual void work(uint worker_id) {
+    double start_time = os::elapsedTime();
+
+    RedirtyLoggedCardTableEntryClosure cl;
+    if (G1CollectedHeap::heap()->use_parallel_gc_threads()) {
+      _queue->par_apply_closure_to_all_completed_buffers(&cl);
+    } else {
+      _queue->apply_closure_to_all_completed_buffers(&cl);
+    }
+
+    G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times();
+    timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0);
+    timer->record_redirty_logged_cards_processed_cards(worker_id, cl.num_processed());
   }
 };
 
@@ -5285,9 +5268,18 @@
   guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates.");
   double redirty_logged_cards_start = os::elapsedTime();
 
-  RedirtyLoggedCardTableEntryFastClosure redirty;
-  dirty_card_queue_set().set_closure(&redirty);
-  dirty_card_queue_set().apply_closure_to_all_completed_buffers();
+  uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
+                   _g1h->workers()->active_workers() : 1);
+
+  G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set());
+  dirty_card_queue_set().reset_for_par_iteration();
+  if (use_parallel_gc_threads()) {
+    set_par_threads(n_workers);
+    workers()->run_task(&redirty_task);
+    set_par_threads(0);
+  } else {
+    redirty_task.work(0);
+  }
 
   DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
   dcq.merge_bufferlists(&dirty_card_queue_set());
@@ -5762,10 +5754,8 @@
   }
 
   _gc_tracer_stw->report_gc_reference_stats(stats);
-  // We have completed copying any necessary live referent objects
-  // (that were not copied during the actual pause) so we can
-  // retire any active alloc buffers
-  pss.retire_alloc_buffers();
+
+  // We have completed copying any necessary live referent objects.
   assert(pss.refs()->is_empty(), "both queue and overflow should be empty");
 
   double ref_proc_time = os::elapsedTime() - ref_proc_start;
@@ -6456,11 +6446,7 @@
 
 bool G1CollectedHeap::is_in_closed_subset(const void* p) const {
   HeapRegion* hr = heap_region_containing(p);
-  if (hr == NULL) {
-    return false;
-  } else {
-    return hr->is_in(p);
-  }
+  return hr->is_in(p);
 }
 
 // Methods for the mutator alloc region
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -28,6 +28,7 @@
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/evacuationInfo.hpp"
 #include "gc_implementation/g1/g1AllocRegion.hpp"
+#include "gc_implementation/g1/g1BiasedArray.hpp"
 #include "gc_implementation/g1/g1HRPrinter.hpp"
 #include "gc_implementation/g1/g1MonitoringSupport.hpp"
 #include "gc_implementation/g1/g1RemSet.hpp"
@@ -197,6 +198,16 @@
   bool do_object_b(oop p);
 };
 
+// Instances of this class are used for quick tests on whether a reference points
+// into the collection set. Each of the array's elements denotes whether the
+// corresponding region is in the collection set.
+class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray<bool> {
+ protected:
+  bool default_value() const { return false; }
+ public:
+  void clear() { G1BiasedMappedArray<bool>::clear(); }
+};
+
 class RefineCardTableEntryClosure;
 
 class G1CollectedHeap : public SharedHeap {
@@ -353,26 +364,10 @@
   // than the current allocation region.
   size_t _summary_bytes_used;
 
-  // This is used for a quick test on whether a reference points into
-  // the collection set or not. Basically, we have an array, with one
-  // byte per region, and that byte denotes whether the corresponding
-  // region is in the collection set or not. The entry corresponding
-  // the bottom of the heap, i.e., region 0, is pointed to by
-  // _in_cset_fast_test_base.  The _in_cset_fast_test field has been
-  // biased so that it actually points to address 0 of the address
-  // space, to make the test as fast as possible (we can simply shift
-  // the address to address into it, instead of having to subtract the
-  // bottom of the heap from the address before shifting it; basically
-  // it works in the same way the card table works).
-  bool* _in_cset_fast_test;
-
-  // The allocated array used for the fast test on whether a reference
-  // points into the collection set or not. This field is also used to
-  // free the array.
-  bool* _in_cset_fast_test_base;
-
-  // The length of the _in_cset_fast_test_base array.
-  uint _in_cset_fast_test_length;
+  // This array is used for a quick test on whether a reference points into
+  // the collection set or not. Each of the array's elements denotes whether the
+  // corresponding region is in the collection set or not.
+  G1FastCSetBiasedMappedArray _in_cset_fast_test;
 
   volatile unsigned _gc_time_stamp;
 
@@ -695,12 +690,7 @@
   // We register a region with the fast "in collection set" test. We
   // simply set to true the array slot corresponding to this region.
   void register_region_with_in_cset_fast_test(HeapRegion* r) {
-    assert(_in_cset_fast_test_base != NULL, "sanity");
-    assert(r->in_collection_set(), "invariant");
-    uint index = r->hrs_index();
-    assert(index < _in_cset_fast_test_length, "invariant");
-    assert(!_in_cset_fast_test_base[index], "invariant");
-    _in_cset_fast_test_base[index] = true;
+    _in_cset_fast_test.set_by_index(r->hrs_index(), true);
   }
 
   // This is a fast test on whether a reference points into the
@@ -709,9 +699,7 @@
   inline bool in_cset_fast_test(oop obj);
 
   void clear_cset_fast_test() {
-    assert(_in_cset_fast_test_base != NULL, "sanity");
-    memset(_in_cset_fast_test_base, false,
-           (size_t) _in_cset_fast_test_length * sizeof(bool));
+    _in_cset_fast_test.clear();
   }
 
   // This is called at the start of either a concurrent cycle or a Full
@@ -1077,6 +1065,8 @@
   // specified by the policy object.
   jint initialize();
 
+  virtual void stop();
+
   // Return the (conservative) maximum heap alignment for any G1 heap
   static size_t conservative_max_heap_alignment();
 
@@ -1390,17 +1380,15 @@
   // space containing a given address, or else returns NULL.
   virtual Space* space_containing(const void* addr) const;
 
-  // A G1CollectedHeap will contain some number of heap regions.  This
-  // finds the region containing a given address, or else returns NULL.
+  // Returns the HeapRegion that contains addr. addr must not be NULL.
+  template <class T>
+  inline HeapRegion* heap_region_containing_raw(const T addr) const;
+
+  // Returns the HeapRegion that contains addr. addr must not be NULL.
+  // If addr is within a humongous continues region, it returns its humongous start region.
   template <class T>
   inline HeapRegion* heap_region_containing(const T addr) const;
 
-  // Like the above, but requires "addr" to be in the heap (to avoid a
-  // null-check), and unlike the above, may return an continuing humongous
-  // region.
-  template <class T>
-  inline HeapRegion* heap_region_containing_raw(const T addr) const;
-
   // A CollectedHeap is divided into a dense sequence of "blocks"; that is,
   // each address in the (reserved) heap is a member of exactly
   // one block.  The defining characteristic of a block is that it is
@@ -1542,7 +1530,6 @@
   // the region to which the object belongs. An object is dead
   // iff a) it was not allocated since the last mark and b) it
   // is not marked.
-
   bool is_obj_dead(const oop obj, const HeapRegion* hr) const {
     return
       !hr->obj_allocated_since_prev_marking(obj) &&
@@ -1552,7 +1539,6 @@
   // This function returns true when an object has been
   // around since the previous marking and hasn't yet
   // been marked during this marking.
-
   bool is_obj_ill(const oop obj, const HeapRegion* hr) const {
     return
       !hr->obj_allocated_since_next_marking(obj) &&
@@ -1698,15 +1684,19 @@
 
 public:
   G1ParGCAllocBuffer(size_t gclab_word_size);
+  virtual ~G1ParGCAllocBuffer() {
+    guarantee(_retired, "Allocation buffer has not been retired");
+  }
 
-  void set_buf(HeapWord* buf) {
+  virtual void set_buf(HeapWord* buf) {
     ParGCAllocBuffer::set_buf(buf);
     _retired = false;
   }
 
-  void retire(bool end_of_gc, bool retain) {
-    if (_retired)
+  virtual void retire(bool end_of_gc, bool retain) {
+    if (_retired) {
       return;
+    }
     ParGCAllocBuffer::retire(end_of_gc, retain);
     _retired = true;
   }
@@ -1776,6 +1766,7 @@
   G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
 
   ~G1ParScanThreadState() {
+    retire_alloc_buffers();
     FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC);
   }
 
@@ -1886,6 +1877,7 @@
     return _surviving_young_words;
   }
 
+private:
   void retire_alloc_buffers() {
     for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
       size_t waste = _alloc_buffers[ap]->words_remaining();
@@ -1895,8 +1887,8 @@
                                                  false /* retain */);
     }
   }
-private:
-  #define G1_PARTIAL_ARRAY_MASK 0x2
+
+#define G1_PARTIAL_ARRAY_MASK 0x2
 
   inline bool has_partial_array_mask(oop* ref) const {
     return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -42,21 +42,22 @@
 
 template <class T>
 inline HeapRegion*
-G1CollectedHeap::heap_region_containing(const T addr) const {
-  HeapRegion* hr = _hrs.addr_to_region((HeapWord*) addr);
-  // hr can be null if addr in perm_gen
-  if (hr != NULL && hr->continuesHumongous()) {
-    hr = hr->humongous_start_region();
-  }
-  return hr;
+G1CollectedHeap::heap_region_containing_raw(const T addr) const {
+  assert(addr != NULL, "invariant");
+  assert(_g1_reserved.contains((const void*) addr),
+      err_msg("Address "PTR_FORMAT" is outside of the heap ranging from ["PTR_FORMAT" to "PTR_FORMAT")",
+          (void*)addr, _g1_reserved.start(), _g1_reserved.end()));
+  return _hrs.addr_to_region((HeapWord*) addr);
 }
 
 template <class T>
 inline HeapRegion*
-G1CollectedHeap::heap_region_containing_raw(const T addr) const {
-  assert(_g1_reserved.contains((const void*) addr), "invariant");
-  HeapRegion* res = _hrs.addr_to_region_unsafe((HeapWord*) addr);
-  return res;
+G1CollectedHeap::heap_region_containing(const T addr) const {
+  HeapRegion* hr = heap_region_containing_raw(addr);
+  if (hr->continuesHumongous()) {
+    return hr->humongous_start_region();
+  }
+  return hr;
 }
 
 inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) {
@@ -134,8 +135,7 @@
   // have to keep calling heap_region_containing_raw() in the
   // asserts below.
   DEBUG_ONLY(HeapRegion* containing_hr = heap_region_containing_raw(start);)
-  assert(containing_hr != NULL && start != NULL && word_size > 0,
-         "pre-condition");
+  assert(word_size > 0, "pre-condition");
   assert(containing_hr->is_in(start), "it should contain start");
   assert(containing_hr->is_young(), "it should be young");
   assert(!containing_hr->isHumongous(), "it should not be humongous");
@@ -164,12 +164,7 @@
 // collection set or not. Assume that the reference
 // points into the heap.
 inline bool G1CollectedHeap::in_cset_fast_test(oop obj) {
-  assert(_in_cset_fast_test != NULL, "sanity");
-  assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, (HeapWord*)obj));
-  // no need to subtract the bottom of the heap from obj,
-  // _in_cset_fast_test is biased
-  uintx index = cast_from_oop<uintx>(obj) >> HeapRegion::LogOfHRGrainBytes;
-  bool ret = _in_cset_fast_test[index];
+  bool ret = _in_cset_fast_test.get_by_address((HeapWord*)obj);
   // let's make sure the result is consistent with what the slower
   // test returns
   assert( ret || !obj_in_cs(obj), "sanity");
@@ -251,8 +246,10 @@
 #endif  // #ifndef PRODUCT
 
 inline bool G1CollectedHeap::is_in_young(const oop obj) {
-  HeapRegion* hr = heap_region_containing(obj);
-  return hr != NULL && hr->is_young();
+  if (obj == NULL) {
+    return false;
+  }
+  return heap_region_containing(obj)->is_young();
 }
 
 // We don't need barriers for initializing stores to objects
@@ -265,21 +262,17 @@
 }
 
 inline bool G1CollectedHeap::is_obj_dead(const oop obj) const {
-  const HeapRegion* hr = heap_region_containing(obj);
-  if (hr == NULL) {
-    if (obj == NULL) return false;
-    else return true;
+  if (obj == NULL) {
+    return false;
   }
-  else return is_obj_dead(obj, hr);
+  return is_obj_dead(obj, heap_region_containing(obj));
 }
 
 inline bool G1CollectedHeap::is_obj_ill(const oop obj) const {
-  const HeapRegion* hr = heap_region_containing(obj);
-  if (hr == NULL) {
-    if (obj == NULL) return false;
-    else return true;
+  if (obj == NULL) {
+    return false;
   }
-  else return is_obj_ill(obj, hr);
+  return is_obj_ill(obj, heap_region_containing(obj));
 }
 
 template <class T> inline void G1ParScanThreadState::immediate_rs_update(HeapRegion* from, T* p, int tid) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -170,6 +170,8 @@
   _last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false),
   _last_gc_worker_times_ms(_max_gc_threads, "%.1lf"),
   _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf"),
+  _last_redirty_logged_cards_time_ms(_max_gc_threads, "%.1lf"),
+  _last_redirty_logged_cards_processed_cards(_max_gc_threads, SIZE_FORMAT),
   _cur_string_dedup_queue_fixup_worker_times_ms(_max_gc_threads, "%.1lf"),
   _cur_string_dedup_table_fixup_worker_times_ms(_max_gc_threads, "%.1lf")
 {
@@ -195,6 +197,10 @@
   _last_gc_worker_end_times_ms.reset();
   _last_gc_worker_times_ms.reset();
   _last_gc_worker_other_times_ms.reset();
+
+  _last_redirty_logged_cards_time_ms.reset();
+  _last_redirty_logged_cards_processed_cards.reset();
+
 }
 
 void G1GCPhaseTimes::note_gc_end() {
@@ -230,6 +236,9 @@
 
   _last_gc_worker_times_ms.verify();
   _last_gc_worker_other_times_ms.verify();
+
+  _last_redirty_logged_cards_time_ms.verify();
+  _last_redirty_logged_cards_processed_cards.verify();
 }
 
 void G1GCPhaseTimes::note_string_dedup_fixup_start() {
@@ -349,6 +358,10 @@
   print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
   if (G1DeferredRSUpdate) {
     print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms);
+    if (G1Log::finest()) {
+      _last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty");
+      _last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
+    }
   }
   print_stats(2, "Free CSet",
     (_recorded_young_free_cset_time_ms +
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -151,6 +151,8 @@
   double _recorded_young_cset_choice_time_ms;
   double _recorded_non_young_cset_choice_time_ms;
 
+  WorkerDataArray<double> _last_redirty_logged_cards_time_ms;
+  WorkerDataArray<size_t> _last_redirty_logged_cards_processed_cards;
   double _recorded_redirty_logged_cards_time_ms;
 
   double _recorded_young_free_cset_time_ms;
@@ -293,6 +295,14 @@
     _recorded_non_young_cset_choice_time_ms = time_ms;
   }
 
+  void record_redirty_logged_cards_time_ms(uint worker_i, double time_ms) {
+    _last_redirty_logged_cards_time_ms.set(worker_i, time_ms);
+  }
+
+  void record_redirty_logged_cards_processed_cards(uint worker_i, size_t processed_buffers) {
+    _last_redirty_logged_cards_processed_cards.set(worker_i, processed_buffers);
+  }
+
   void record_redirty_logged_cards_time_ms(double time_ms) {
     _recorded_redirty_logged_cards_time_ms = time_ms;
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -125,9 +125,7 @@
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
     HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj);
-    if (hr != NULL) {
-      _cm->grayRoot(obj, obj->size(), _worker_id, hr);
-    }
+    _cm->grayRoot(obj, obj->size(), _worker_id, hr);
   }
 }
 
@@ -154,57 +152,63 @@
 template <class T>
 inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) {
   oop obj = oopDesc::load_decode_heap_oop(p);
+  if (obj == NULL) {
+    return;
+  }
+
 #ifdef ASSERT
   // can't do because of races
   // assert(obj == NULL || obj->is_oop(), "expected an oop");
 
   // Do the safe subset of is_oop
-  if (obj != NULL) {
 #ifdef CHECK_UNHANDLED_OOPS
-    oopDesc* o = obj.obj();
+  oopDesc* o = obj.obj();
 #else
-    oopDesc* o = obj;
+  oopDesc* o = obj;
 #endif // CHECK_UNHANDLED_OOPS
-    assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
-    assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
-  }
+  assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
+  assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
 #endif // ASSERT
 
   assert(_from != NULL, "from region must be non-NULL");
   assert(_from->is_in_reserved(p), "p is not in from");
 
   HeapRegion* to = _g1->heap_region_containing(obj);
-  if (to != NULL && _from != to) {
-    // The _record_refs_into_cset flag is true during the RSet
-    // updating part of an evacuation pause. It is false at all
-    // other times:
-    //  * rebuilding the remembered sets after a full GC
-    //  * during concurrent refinement.
-    //  * updating the remembered sets of regions in the collection
-    //    set in the event of an evacuation failure (when deferred
-    //    updates are enabled).
+  if (_from == to) {
+    // Normally this closure should only be called with cross-region references.
+    // But since Java threads are manipulating the references concurrently and we
+    // reload the values things may have changed.
+    return;
+  }
 
-    if (_record_refs_into_cset && to->in_collection_set()) {
-      // We are recording references that point into the collection
-      // set and this particular reference does exactly that...
-      // If the referenced object has already been forwarded
-      // to itself, we are handling an evacuation failure and
-      // we have already visited/tried to copy this object
-      // there is no need to retry.
-      if (!self_forwarded(obj)) {
-        assert(_push_ref_cl != NULL, "should not be null");
-        // Push the reference in the refs queue of the G1ParScanThreadState
-        // instance for this worker thread.
-        _push_ref_cl->do_oop(p);
-      }
+  // The _record_refs_into_cset flag is true during the RSet
+  // updating part of an evacuation pause. It is false at all
+  // other times:
+  //  * rebuilding the remembered sets after a full GC
+  //  * during concurrent refinement.
+  //  * updating the remembered sets of regions in the collection
+  //    set in the event of an evacuation failure (when deferred
+  //    updates are enabled).
 
-      // Deferred updates to the CSet are either discarded (in the normal case),
-      // or processed (if an evacuation failure occurs) at the end
-      // of the collection.
-      // See G1RemSet::cleanup_after_oops_into_collection_set_do().
-      return;
+  if (_record_refs_into_cset && to->in_collection_set()) {
+    // We are recording references that point into the collection
+    // set and this particular reference does exactly that...
+    // If the referenced object has already been forwarded
+    // to itself, we are handling an evacuation failure and
+    // we have already visited/tried to copy this object
+    // there is no need to retry.
+    if (!self_forwarded(obj)) {
+      assert(_push_ref_cl != NULL, "should not be null");
+      // Push the reference in the refs queue of the G1ParScanThreadState
+      // instance for this worker thread.
+      _push_ref_cl->do_oop(p);
     }
 
+    // Deferred updates to the CSet are either discarded (in the normal case),
+    // or processed (if an evacuation failure occurs) at the end
+    // of the collection.
+    // See G1RemSet::cleanup_after_oops_into_collection_set_do().
+  } else {
     // We either don't care about pushing references that point into the
     // collection set (i.e. we're not during an evacuation pause) _or_
     // the reference doesn't point into the collection set. Either way
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -36,6 +36,7 @@
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "memory/iterator.hpp"
 #include "oops/oop.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
 #include "utilities/intHisto.hpp"
 
 #define CARD_REPEAT_HISTO 0
@@ -163,7 +164,7 @@
   void printCard(HeapRegion* card_region, size_t card_index,
                  HeapWord* card_start) {
     gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
-                           "RS names card %p: "
+                           "RS names card " SIZE_FORMAT_HEX ": "
                            "[" PTR_FORMAT ", " PTR_FORMAT ")",
                            _worker_i,
                            card_region->bottom(), card_region->end(),
@@ -209,7 +210,6 @@
 #endif
 
       HeapRegion* card_region = _g1h->heap_region_containing(card_start);
-      assert(card_region != NULL, "Yielding cards not in the heap?");
       _cards++;
 
       if (!card_region->is_on_dirty_cards_region_list()) {
@@ -404,7 +404,6 @@
     HeapWord* start = _ct_bs->addr_for(card_ptr);
     // And find the region containing it.
     HeapRegion* r = _g1->heap_region_containing(start);
-    assert(r != NULL, "unexpected null");
 
     // Scan oops in the card looking for references into the collection set
     // Don't use addr_for(card_ptr + 1) which can ask for
@@ -566,11 +565,6 @@
   HeapWord* start = _ct_bs->addr_for(card_ptr);
   // And find the region containing it.
   HeapRegion* r = _g1->heap_region_containing(start);
-  if (r == NULL) {
-    // Again no need to return that this card contains refs that
-    // point into the collection set.
-    return false;  // Not in the G1 heap (might be in perm, for example.)
-  }
 
   // Why do we have to check here whether a card is on a young region,
   // given that we dirty young regions and, as a result, the
@@ -623,10 +617,6 @@
 
     start = _ct_bs->addr_for(card_ptr);
     r = _g1->heap_region_containing(start);
-    if (r == NULL) {
-      // Not in the G1 heap
-      return false;
-    }
 
     // Checking whether the region we got back from the cache
     // is young here is inappropriate. The region could have been
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -45,26 +45,28 @@
 template <class T>
 inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) {
   oop obj = oopDesc::load_decode_heap_oop(p);
+  if (obj == NULL) {
+    return;
+  }
+
 #ifdef ASSERT
   // can't do because of races
   // assert(obj == NULL || obj->is_oop(), "expected an oop");
 
   // Do the safe subset of is_oop
-  if (obj != NULL) {
 #ifdef CHECK_UNHANDLED_OOPS
-    oopDesc* o = obj.obj();
+  oopDesc* o = obj.obj();
 #else
-    oopDesc* o = obj;
+  oopDesc* o = obj;
 #endif // CHECK_UNHANDLED_OOPS
-    assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
-    assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
-  }
+  assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
+  assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
 #endif // ASSERT
 
   assert(from == NULL || from->is_in_reserved(p), "p is not in from");
 
   HeapRegion* to = _g1->heap_region_containing(obj);
-  if (to != NULL && from != to) {
+  if (from != to) {
     assert(to->rem_set() != NULL, "Need per-region 'into' remsets.");
     to->rem_set()->add_reference(p, tid);
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -44,6 +44,11 @@
   }
 }
 
+void G1StringDedup::stop() {
+  assert(is_enabled(), "String deduplication not enabled");
+  G1StringDedupThread::stop();
+}
+
 bool G1StringDedup::is_candidate_from_mark(oop obj) {
   if (java_lang_String::is_instance(obj)) {
     bool from_young = G1CollectedHeap::heap()->heap_region_containing_raw(obj)->is_young();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -110,8 +110,12 @@
     return _enabled;
   }
 
+  // Initialize string deduplication.
   static void initialize();
 
+  // Stop the deduplication thread.
+  static void stop();
+
   // Immediately deduplicates the given String object, bypassing the
   // the deduplication queue.
   static void deduplicate(oop java_string);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -35,6 +35,7 @@
 
 G1StringDedupQueue::G1StringDedupQueue() :
   _cursor(0),
+  _cancel(false),
   _empty(true),
   _dropped(0) {
   _nqueues = MAX2(ParallelGCThreads, (size_t)1);
@@ -55,11 +56,17 @@
 
 void G1StringDedupQueue::wait() {
   MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
-  while (_queue->_empty) {
+  while (_queue->_empty && !_queue->_cancel) {
     ml.wait(Mutex::_no_safepoint_check_flag);
   }
 }
 
+void G1StringDedupQueue::cancel_wait() {
+  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+  _queue->_cancel = true;
+  ml.notify();
+}
+
 void G1StringDedupQueue::push(uint worker_id, oop java_string) {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint");
   assert(worker_id < _queue->_nqueues, "Invalid queue");
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -65,6 +65,7 @@
   G1StringDedupWorkerQueue*  _queues;
   size_t                     _nqueues;
   size_t                     _cursor;
+  bool                       _cancel;
   volatile bool              _empty;
 
   // Statistics counter, only used for logging.
@@ -81,6 +82,9 @@
   // Blocks and waits for the queue to become non-empty.
   static void wait();
 
+  // Wakes up any thread blocked waiting for the queue to become non-empty.
+  static void cancel_wait();
+
   // Pushes a deduplication candidate onto a specific GC worker queue.
   static void push(uint worker_id, oop java_string);
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -73,42 +73,60 @@
 
     // Wait for the queue to become non-empty
     G1StringDedupQueue::wait();
+    if (_should_terminate) {
+      break;
+    }
 
-    // Include this thread in safepoints
-    stsJoin();
+    {
+      // Include thread in safepoints
+      SuspendibleThreadSetJoiner sts;
 
-    stat.mark_exec();
+      stat.mark_exec();
 
-    // Process the queue
-    for (;;) {
-      oop java_string = G1StringDedupQueue::pop();
-      if (java_string == NULL) {
-        break;
+      // Process the queue
+      for (;;) {
+        oop java_string = G1StringDedupQueue::pop();
+        if (java_string == NULL) {
+          break;
+        }
+
+        G1StringDedupTable::deduplicate(java_string, stat);
+
+        // Safepoint this thread if needed
+        if (sts.should_yield()) {
+          stat.mark_block();
+          sts.yield();
+          stat.mark_unblock();
+        }
       }
 
-      G1StringDedupTable::deduplicate(java_string, stat);
+      G1StringDedupTable::trim_entry_cache();
 
-      // Safepoint this thread if needed
-      if (stsShouldYield()) {
-        stat.mark_block();
-        stsYield(NULL);
-        stat.mark_unblock();
-      }
-    }
+      stat.mark_done();
 
-    G1StringDedupTable::trim_entry_cache();
-
-    stat.mark_done();
-
-    // Print statistics
-    total_stat.add(stat);
-    print(gclog_or_tty, stat, total_stat);
-
-    // Exclude this thread from safepoints
-    stsLeave();
+      // Print statistics
+      total_stat.add(stat);
+      print(gclog_or_tty, stat, total_stat);
+    }
   }
 
-  ShouldNotReachHere();
+  terminate();
+}
+
+void G1StringDedupThread::stop() {
+  {
+    MonitorLockerEx ml(Terminator_lock);
+    _thread->_should_terminate = true;
+  }
+
+  G1StringDedupQueue::cancel_wait();
+
+  {
+    MonitorLockerEx ml(Terminator_lock);
+    while (!_thread->_has_terminated) {
+      ml.wait();
+    }
+  }
 }
 
 void G1StringDedupThread::print(outputStream* st, const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -47,6 +47,8 @@
 
 public:
   static void create();
+  static void stop();
+
   static G1StringDedupThread* thread();
 
   virtual void run();
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -167,7 +167,7 @@
 
   // Mem size in bytes.
   size_t mem_size() const {
-    return sizeof(this) + _bm.size_in_words() * HeapWordSize;
+    return sizeof(PerRegionTable) + _bm.size_in_words() * HeapWordSize;
   }
 
   // Requires "from" to be in "hr()".
@@ -491,7 +491,7 @@
       } else {
         if (G1TraceHeapRegionRememberedSet) {
           gclog_or_tty->print_cr("   [tid %d] sparse table entry "
-                        "overflow(f: %d, t: %d)",
+                        "overflow(f: %d, t: %u)",
                         tid, from_hrs_ind, cur_hrs_ind);
         }
       }
@@ -610,7 +610,7 @@
     _n_coarse_entries++;
     if (G1TraceHeapRegionRememberedSet) {
       gclog_or_tty->print("Coarsened entry in region [" PTR_FORMAT "...] "
-                 "for region [" PTR_FORMAT "...] (%d coarse entries).\n",
+                 "for region [" PTR_FORMAT "...] (" SIZE_FORMAT " coarse entries).\n",
                  hr()->bottom(),
                  max->hr()->bottom(),
                  _n_coarse_entries);
@@ -733,7 +733,7 @@
   sum += (sizeof(PerRegionTable*) * _max_fine_entries);
   sum += (_coarse_map.size_in_words() * HeapWordSize);
   sum += (_sparse_table.mem_size());
-  sum += sizeof(*this) - sizeof(_sparse_table); // Avoid double counting above.
+  sum += sizeof(OtherRegionsTable) - sizeof(_sparse_table); // Avoid double counting above.
   return sum;
 }
 
@@ -768,30 +768,6 @@
   clear_fcc();
 }
 
-void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) {
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  size_t hrs_ind = (size_t) from_hr->hrs_index();
-  size_t ind = hrs_ind & _mod_max_fine_entries_mask;
-  if (del_single_region_table(ind, from_hr)) {
-    assert(!_coarse_map.at(hrs_ind), "Inv");
-  } else {
-    _coarse_map.par_at_put(hrs_ind, 0);
-  }
-  // Check to see if any of the fcc entries come from here.
-  uint hr_ind = hr()->hrs_index();
-  for (uint tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) {
-    int fcc_ent = FromCardCache::at(tid, hr_ind);
-    if (fcc_ent != FromCardCache::InvalidCard) {
-      HeapWord* card_addr = (HeapWord*)
-        (uintptr_t(fcc_ent) << CardTableModRefBS::card_shift);
-      if (hr()->is_in_reserved(card_addr)) {
-        // Clear the from card cache.
-        FromCardCache::set(tid, hr_ind, FromCardCache::InvalidCard);
-      }
-    }
-  }
-}
-
 bool OtherRegionsTable::del_single_region_table(size_t ind,
                                                 HeapRegion* hr) {
   assert(0 <= ind && ind < _max_fine_entries, "Preconditions.");
@@ -821,7 +797,6 @@
 
 bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const {
   HeapRegion* hr = _g1h->heap_region_containing_raw(from);
-  if (hr == NULL) return false;
   RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index();
   // Is this region in the coarse map?
   if (_coarse_map.at(hr_ind)) return true;
@@ -903,10 +878,12 @@
   }
   if (iter.n_yielded() != occupied()) {
     gclog_or_tty->print_cr("Yielded disagrees with occupied:");
-    gclog_or_tty->print_cr("  %6d yielded (%6d coarse, %6d fine).",
+    gclog_or_tty->print_cr("  " SIZE_FORMAT_W(6) " yielded (" SIZE_FORMAT_W(6)
+                  " coarse, " SIZE_FORMAT_W(6) " fine).",
                   iter.n_yielded(),
                   iter.n_yielded_coarse(), iter.n_yielded_fine());
-    gclog_or_tty->print_cr("  %6d occ     (%6d coarse, %6d fine).",
+    gclog_or_tty->print_cr("  " SIZE_FORMAT_W(6) " occ     (" SIZE_FORMAT_W(6)
+                           " coarse, " SIZE_FORMAT_W(6) " fine).",
                   occupied(), occ_coarse(), occ_fine());
   }
   guarantee(iter.n_yielded() == occupied(),
@@ -1046,20 +1023,16 @@
   return _code_roots.mem_size();
 }
 
-//-------------------- Iteration --------------------
-
 HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) :
   _hrrs(hrrs),
   _g1h(G1CollectedHeap::heap()),
   _coarse_map(&hrrs->_other_regions._coarse_map),
-  _fine_grain_regions(hrrs->_other_regions._fine_grain_regions),
   _bosa(hrrs->bosa()),
   _is(Sparse),
   // Set these values so that we increment to the first region.
   _coarse_cur_region_index(-1),
   _coarse_cur_region_cur_card(HeapRegion::CardsPerRegion-1),
-  _cur_region_cur_card(0),
-  _fine_array_index(-1),
+  _cur_card_in_prt(HeapRegion::CardsPerRegion),
   _fine_cur_prt(NULL),
   _n_yielded_coarse(0),
   _n_yielded_fine(0),
@@ -1091,58 +1064,59 @@
   return true;
 }
 
-void HeapRegionRemSetIterator::fine_find_next_non_null_prt() {
-  // Otherwise, find the next bucket list in the array.
-  _fine_array_index++;
-  while (_fine_array_index < (int) OtherRegionsTable::_max_fine_entries) {
-    _fine_cur_prt = _fine_grain_regions[_fine_array_index];
-    if (_fine_cur_prt != NULL) return;
-    else _fine_array_index++;
-  }
-  assert(_fine_cur_prt == NULL, "Loop post");
-}
-
 bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) {
   if (fine_has_next()) {
-    _cur_region_cur_card =
-      _fine_cur_prt->_bm.get_next_one_offset(_cur_region_cur_card + 1);
+    _cur_card_in_prt =
+      _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1);
   }
-  while (!fine_has_next()) {
-    if (_cur_region_cur_card == (size_t) HeapRegion::CardsPerRegion) {
-      _cur_region_cur_card = 0;
-      _fine_cur_prt = _fine_cur_prt->collision_list_next();
+  if (_cur_card_in_prt == HeapRegion::CardsPerRegion) {
+    // _fine_cur_prt may still be NULL in case if there are not PRTs at all for
+    // the remembered set.
+    if (_fine_cur_prt == NULL || _fine_cur_prt->next() == NULL) {
+      return false;
     }
-    if (_fine_cur_prt == NULL) {
-      fine_find_next_non_null_prt();
-      if (_fine_cur_prt == NULL) return false;
-    }
-    assert(_fine_cur_prt != NULL && _cur_region_cur_card == 0,
-           "inv.");
-    HeapWord* r_bot =
-      _fine_cur_prt->hr()->bottom();
-    _cur_region_card_offset = _bosa->index_for(r_bot);
-    _cur_region_cur_card = _fine_cur_prt->_bm.get_next_one_offset(0);
+    PerRegionTable* next_prt = _fine_cur_prt->next();
+    switch_to_prt(next_prt);
+    _cur_card_in_prt = _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1);
   }
-  assert(fine_has_next(), "Or else we exited the loop via the return.");
-  card_index = _cur_region_card_offset + _cur_region_cur_card;
+
+  card_index = _cur_region_card_offset + _cur_card_in_prt;
+  guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion,
+            err_msg("Card index "SIZE_FORMAT" must be within the region", _cur_card_in_prt));
   return true;
 }
 
 bool HeapRegionRemSetIterator::fine_has_next() {
-  return
-    _fine_cur_prt != NULL &&
-    _cur_region_cur_card < HeapRegion::CardsPerRegion;
+  return _cur_card_in_prt != HeapRegion::CardsPerRegion;
+}
+
+void HeapRegionRemSetIterator::switch_to_prt(PerRegionTable* prt) {
+  assert(prt != NULL, "Cannot switch to NULL prt");
+  _fine_cur_prt = prt;
+
+  HeapWord* r_bot = _fine_cur_prt->hr()->bottom();
+  _cur_region_card_offset = _bosa->index_for(r_bot);
+
+  // The bitmap scan for the PRT always scans from _cur_region_cur_card + 1.
+  // To avoid special-casing this start case, and not miss the first bitmap
+  // entry, initialize _cur_region_cur_card with -1 instead of 0.
+  _cur_card_in_prt = (size_t)-1;
 }
 
 bool HeapRegionRemSetIterator::has_next(size_t& card_index) {
   switch (_is) {
-  case Sparse:
+  case Sparse: {
     if (_sparse_iter.has_next(card_index)) {
       _n_yielded_sparse++;
       return true;
     }
     // Otherwise, deliberate fall-through
     _is = Fine;
+    PerRegionTable* initial_fine_prt = _hrrs->_other_regions._first_all_fine_prts;
+    if (initial_fine_prt != NULL) {
+      switch_to_prt(_hrrs->_other_regions._first_all_fine_prts);
+    }
+  }
   case Fine:
     if (fine_has_next(card_index)) {
       _n_yielded_fine++;
@@ -1274,6 +1248,11 @@
 #ifndef PRODUCT
 void PerRegionTable::test_fl_mem_size() {
   PerRegionTable* dummy = alloc(NULL);
+
+  size_t min_prt_size = sizeof(void*) + dummy->bm()->size_in_words() * HeapWordSize;
+  assert(dummy->mem_size() > min_prt_size,
+         err_msg("PerRegionTable memory usage is suspiciously small, only has "SIZE_FORMAT" bytes. "
+                 "Should be at least "SIZE_FORMAT" bytes.", dummy->mem_size(), min_prt_size));
   free(dummy);
   guarantee(dummy->mem_size() == fl_mem_size(), "fl_mem_size() does not return the correct element size");
   // try to reset the state
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -206,9 +206,6 @@
   // Specifically clear the from_card_cache.
   void clear_fcc();
 
-  // "from_hr" is being cleared; remove any entries from it.
-  void clear_incoming_entry(HeapRegion* from_hr);
-
   void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task);
 
   // Declare the heap size (in # of regions) to the OtherRegionsTable.
@@ -338,20 +335,20 @@
     return _other_regions.mem_size()
       // This correction is necessary because the above includes the second
       // part.
-      + (sizeof(this) - sizeof(OtherRegionsTable))
+      + (sizeof(HeapRegionRemSet) - sizeof(OtherRegionsTable))
       + strong_code_roots_mem_size();
   }
 
   // Returns the memory occupancy of all static data structures associated
   // with remembered sets.
   static size_t static_mem_size() {
-    return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size();
+    return OtherRegionsTable::static_mem_size() + G1CodeRootSet::free_chunks_static_mem_size();
   }
 
   // Returns the memory occupancy of all free_list data structures associated
   // with remembered sets.
   static size_t fl_mem_size() {
-    return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::fl_mem_size();
+    return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::free_chunks_mem_size();
   }
 
   bool contains_reference(OopOrNarrowOopStar from) const {
@@ -396,7 +393,6 @@
   // Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
   // (Uses it to initialize from_card_cache).
   static void init_heap(uint max_regions) {
-    G1CodeRootSet::initialize();
     OtherRegionsTable::init_from_card_cache(max_regions);
   }
 
@@ -429,26 +425,24 @@
 };
 
 class HeapRegionRemSetIterator : public StackObj {
-
-  // The region RSet over which we're iterating.
+ private:
+  // The region RSet over which we are iterating.
   HeapRegionRemSet* _hrrs;
 
   // Local caching of HRRS fields.
   const BitMap*             _coarse_map;
-  PerRegionTable**          _fine_grain_regions;
 
   G1BlockOffsetSharedArray* _bosa;
   G1CollectedHeap*          _g1h;
 
-  // The number yielded since initialization.
+  // The number of cards yielded since initialization.
   size_t _n_yielded_fine;
   size_t _n_yielded_coarse;
   size_t _n_yielded_sparse;
 
-  // Indicates what granularity of table that we're currently iterating over.
+  // Indicates what granularity of table that we are currently iterating over.
   // We start iterating over the sparse table, progress to the fine grain
   // table, and then finish with the coarse table.
-  // See HeapRegionRemSetIterator::has_next().
   enum IterState {
     Sparse,
     Fine,
@@ -456,38 +450,30 @@
   };
   IterState _is;
 
-  // In both kinds of iteration, heap offset of first card of current
-  // region.
+  // For both Coarse and Fine remembered set iteration this contains the
+  // first card number of the heap region we currently iterate over.
   size_t _cur_region_card_offset;
-  // Card offset within cur region.
-  size_t _cur_region_cur_card;
 
-  // Coarse table iteration fields:
-
-  // Current region index;
+  // Current region index for the Coarse remembered set iteration.
   int    _coarse_cur_region_index;
   size_t _coarse_cur_region_cur_card;
 
   bool coarse_has_next(size_t& card_index);
 
-  // Fine table iteration fields:
-
-  // Index of bucket-list we're working on.
-  int _fine_array_index;
+  // The PRT we are currently iterating over.
+  PerRegionTable* _fine_cur_prt;
+  // Card offset within the current PRT.
+  size_t _cur_card_in_prt;
 
-  // Per Region Table we're doing within current bucket list.
-  PerRegionTable* _fine_cur_prt;
-
-  /* SparsePRT::*/ SparsePRTIter _sparse_iter;
-
-  void fine_find_next_non_null_prt();
-
+  // Update internal variables when switching to the given PRT.
+  void switch_to_prt(PerRegionTable* prt);
   bool fine_has_next();
   bool fine_has_next(size_t& card_index);
 
-public:
-  // We require an iterator to be initialized before use, so the
-  // constructor does little.
+  // The Sparse remembered set iterator.
+  SparsePRTIter _sparse_iter;
+
+ public:
   HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
 
   // If there remains one or more cards to be yielded, returns true and
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -240,7 +240,6 @@
       // Asserts will fire if i is >= _length
       HeapWord* addr = hr->bottom();
       guarantee(addr_to_region(addr) == hr, "sanity");
-      guarantee(addr_to_region_unsafe(addr) == hr, "sanity");
     } else {
       guarantee(hr->is_empty(), "sanity");
       guarantee(!hr->isHumongous(), "sanity");
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -110,10 +110,6 @@
   // HeapRegion, otherwise return NULL.
   inline HeapRegion* addr_to_region(HeapWord* addr) const;
 
-  // Return the HeapRegion that corresponds to the given
-  // address. Assume the address is valid.
-  inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const;
-
   // Return the number of regions that have been committed in the heap.
   uint length() const { return _committed_length; }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -28,21 +28,17 @@
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "gc_implementation/g1/heapRegionSeq.hpp"
 
-inline HeapRegion* HeapRegionSeq::addr_to_region_unsafe(HeapWord* addr) const {
+inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const {
+  assert(addr < heap_end(),
+        err_msg("addr: "PTR_FORMAT" end: "PTR_FORMAT, addr, heap_end()));
+  assert(addr >= heap_bottom(),
+        err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, heap_bottom()));
+
   HeapRegion* hr = _regions.get_by_address(addr);
   assert(hr != NULL, "invariant");
   return hr;
 }
 
-inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const {
-  if (addr != NULL && addr < heap_end()) {
-    assert(addr >= heap_bottom(),
-          err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, heap_bottom()));
-    return addr_to_region_unsafe(addr);
-  }
-  return NULL;
-}
-
 inline HeapRegion* HeapRegionSeq::at(uint index) const {
   assert(index < length(), "pre-condition");
   HeapRegion* hr = _regions.get_by_index(index);
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -370,7 +370,7 @@
 }
 
 size_t RSHashTable::mem_size() const {
-  return sizeof(this) +
+  return sizeof(RSHashTable) +
     capacity() * (SparsePRTEntry::size() + sizeof(int));
 }
 
@@ -472,7 +472,7 @@
 size_t SparsePRT::mem_size() const {
   // We ignore "_cur" here, because it either = _next, or else it is
   // on the deleted list.
-  return sizeof(this) + _next->mem_size();
+  return sizeof(SparsePRT) + _next->mem_size();
 }
 
 bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) {
--- a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -187,10 +187,10 @@
 #ifndef PRODUCT
 void
 SurvRateGroup::print() {
-  gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries)",
+  gclog_or_tty->print_cr("Surv Rate Group: %s (" SIZE_FORMAT " entries)",
                 _name, _region_num);
   for (size_t i = 0; i < _region_num; ++i) {
-    gclog_or_tty->print_cr("    age %4d   surv rate %6.2lf %%   pred %6.2lf %%",
+    gclog_or_tty->print_cr("    age " SIZE_FORMAT_W(4) "   surv rate %6.2lf %%   pred %6.2lf %%",
                   i, _surv_rate[i] * 100.0,
                   _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0);
   }
@@ -203,14 +203,15 @@
     return;
 
   gclog_or_tty->print_cr("");
-  gclog_or_tty->print_cr("%s Rate Summary (for up to age %d)", _name, length-1);
+  gclog_or_tty->print_cr("%s Rate Summary (for up to age " SIZE_FORMAT ")", _name, length-1);
   gclog_or_tty->print_cr("      age range     survival rate (avg)      samples (avg)");
   gclog_or_tty->print_cr("  ---------------------------------------------------------");
 
   size_t index = 0;
   size_t limit = MIN2((int) length, 10);
   while (index < limit) {
-    gclog_or_tty->print_cr("           %4d                 %6.2lf%%             %6.2lf",
+    gclog_or_tty->print_cr("           " SIZE_FORMAT_W(4)
+                  "                 %6.2lf%%             %6.2lf",
                   index, _summary_surv_rates[index]->avg() * 100.0,
                   (double) _summary_surv_rates[index]->num());
     ++index;
@@ -228,7 +229,8 @@
     ++index;
 
     if (index == length || num % 10 == 0) {
-      gclog_or_tty->print_cr("   %4d .. %4d                 %6.2lf%%             %6.2lf",
+      gclog_or_tty->print_cr("   " SIZE_FORMAT_W(4) " .. " SIZE_FORMAT_W(4)
+                    "                 %6.2lf%%             %6.2lf",
                     (index-1) / 10 * 10, index-1, sum / (double) num,
                     (double) samples / (double) num);
       sum = 0.0;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -143,7 +143,8 @@
 
   if (TraceAdaptiveGCBoundary) {
     gclog_or_tty->print_cr("Before expansion of old gen with boundary move");
-    gclog_or_tty->print_cr("  Requested change: 0x%x  Attempted change: 0x%x",
+    gclog_or_tty->print_cr("  Requested change: " SIZE_FORMAT_HEX
+                           "  Attempted change: " SIZE_FORMAT_HEX,
       expand_in_bytes, change_in_bytes);
     if (!PrintHeapAtGC) {
       Universe::print_on(gclog_or_tty);
@@ -201,7 +202,7 @@
 
   if (TraceAdaptiveGCBoundary) {
     gclog_or_tty->print_cr("Before expansion of young gen with boundary move");
-    gclog_or_tty->print_cr("  Requested change: 0x%x  Attempted change: 0x%x",
+    gclog_or_tty->print_cr("  Requested change: " SIZE_FORMAT_HEX "  Attempted change: " SIZE_FORMAT_HEX,
       expand_in_bytes, change_in_bytes);
     if (!PrintHeapAtGC) {
       Universe::print_on(gclog_or_tty);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -127,22 +127,22 @@
   size_t result_aligned = align_size_down(result, gen_alignment);
   if (PrintAdaptiveSizePolicy && Verbose) {
     gclog_or_tty->print_cr("\nASPSOldGen::available_for_contraction:"
-      " %d K / 0x%x", result_aligned/K, result_aligned);
-    gclog_or_tty->print_cr(" reserved().byte_size() %d K / 0x%x ",
+      " " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, result_aligned/K, result_aligned);
+    gclog_or_tty->print_cr(" reserved().byte_size() " SIZE_FORMAT " K / " SIZE_FORMAT_HEX,
       reserved().byte_size()/K, reserved().byte_size());
     size_t working_promoted = (size_t) policy->avg_promoted()->padded_average();
-    gclog_or_tty->print_cr(" padded promoted %d K / 0x%x",
+    gclog_or_tty->print_cr(" padded promoted " SIZE_FORMAT " K / " SIZE_FORMAT_HEX,
       working_promoted/K, working_promoted);
-    gclog_or_tty->print_cr(" used %d K / 0x%x",
+    gclog_or_tty->print_cr(" used " SIZE_FORMAT " K / " SIZE_FORMAT_HEX,
       used_in_bytes()/K, used_in_bytes());
-    gclog_or_tty->print_cr(" min_gen_size() %d K / 0x%x",
+    gclog_or_tty->print_cr(" min_gen_size() " SIZE_FORMAT " K / " SIZE_FORMAT_HEX,
       min_gen_size()/K, min_gen_size());
-    gclog_or_tty->print_cr(" max_contraction %d K / 0x%x",
+    gclog_or_tty->print_cr(" max_contraction " SIZE_FORMAT " K / " SIZE_FORMAT_HEX,
       max_contraction/K, max_contraction);
-    gclog_or_tty->print_cr("    without alignment %d K / 0x%x",
+    gclog_or_tty->print_cr("    without alignment " SIZE_FORMAT " K / " SIZE_FORMAT_HEX,
       policy->promo_increment(max_contraction)/K,
       policy->promo_increment(max_contraction));
-    gclog_or_tty->print_cr(" alignment 0x%x", gen_alignment);
+    gclog_or_tty->print_cr(" alignment " SIZE_FORMAT_HEX, gen_alignment);
   }
   assert(result_aligned <= max_contraction, "arithmetic is wrong");
   return result_aligned;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -112,11 +112,11 @@
     size_t result = policy->eden_increment_aligned_down(max_contraction);
     size_t result_aligned = align_size_down(result, gen_alignment);
     if (PrintAdaptiveSizePolicy && Verbose) {
-      gclog_or_tty->print_cr("ASPSYoungGen::available_for_contraction: %d K",
+      gclog_or_tty->print_cr("ASPSYoungGen::available_for_contraction: " SIZE_FORMAT " K",
         result_aligned/K);
-      gclog_or_tty->print_cr("  max_contraction %d K", max_contraction/K);
-      gclog_or_tty->print_cr("  eden_avail %d K", eden_avail/K);
-      gclog_or_tty->print_cr("  gen_avail %d K", gen_avail/K);
+      gclog_or_tty->print_cr("  max_contraction " SIZE_FORMAT " K", max_contraction/K);
+      gclog_or_tty->print_cr("  eden_avail " SIZE_FORMAT " K", eden_avail/K);
+      gclog_or_tty->print_cr("  gen_avail " SIZE_FORMAT " K", gen_avail/K);
     }
     return result_aligned;
   }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -487,7 +487,7 @@
   if (TraceDynamicGCThreads) {
     gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): "
                            "all_workers_active()  %d  workers %d  "
-                           "active  %d  ParallelGCThreads %d ",
+                           "active  %d  ParallelGCThreads " UINTX_FORMAT,
                            all_workers_active(), workers(),  active_workers(),
                            ParallelGCThreads);
   }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -128,8 +128,6 @@
     // When doing MT offsets, we can't assert this.
     //assert(offset > *block, "Found backwards allocation");
     *block = (jbyte)offset;
-
-    // tty->print_cr("[%p]", p);
   }
 
   // Optimized for finding the first object that crosses into
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -264,7 +264,7 @@
   cm->set_region_stack(ParCompactionManager::region_list(which_stack_index));
   if (TraceDynamicGCThreads) {
     gclog_or_tty->print_cr("StealRegionCompactionTask::do_it "
-                           "region_stack_index %d region_stack = 0x%x "
+                           "region_stack_index %d region_stack = " PTR_FORMAT " "
                            " empty (%d) use all workers %d",
     which_stack_index, ParCompactionManager::region_list(which_stack_index),
     cm->region_stack()->is_empty(),
@@ -366,7 +366,7 @@
     if (TraceDynamicGCThreads) {
       void* old_region_stack = (void*) cm->region_stack();
       int old_region_stack_index = cm->region_stack_index();
-      gclog_or_tty->print_cr("Pushing region stack 0x%x/%d",
+      gclog_or_tty->print_cr("Pushing region stack " PTR_FORMAT "/%d",
         old_region_stack, old_region_stack_index);
     }
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -379,7 +379,7 @@
       gclog_or_tty->print_cr(
             "PSAdaptiveSizePolicy::compute_eden_space_size: gc time limit"
             " gc_cost: %f "
-            " GCTimeLimit: %d",
+            " GCTimeLimit: " UINTX_FORMAT,
             gc_cost(), GCTimeLimit);
     }
   }
@@ -586,7 +586,7 @@
       gclog_or_tty->print_cr(
             "PSAdaptiveSizePolicy::compute_old_gen_free_space: gc time limit"
             " gc_cost: %f "
-            " GCTimeLimit: %d",
+            " GCTimeLimit: " UINTX_FORMAT,
             gc_cost(), GCTimeLimit);
     }
   }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -270,7 +270,8 @@
         gclog_or_tty->print_cr(" collection: %d ",
                        heap->total_collections());
         if (Verbose) {
-          gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d",
+          gclog_or_tty->print("old_gen_capacity: " SIZE_FORMAT
+            " young_gen_capacity: " SIZE_FORMAT,
             old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes());
         }
       }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -1428,7 +1428,7 @@
                   "space_cap=" SIZE_FORMAT,
                   space_live, space_used,
                   space_capacity);
-    tty->print_cr("dead_wood_limiter(%6.4f, %d)=%6.4f "
+    tty->print_cr("dead_wood_limiter(%6.4f, " SIZE_FORMAT ")=%6.4f "
                   "dead_wood_max=" SIZE_FORMAT " dead_wood_limit=" SIZE_FORMAT,
                   density, min_percent_free, limiter,
                   dead_wood_max, dead_wood_limit);
@@ -2106,7 +2106,8 @@
         gclog_or_tty->print_cr(" collection: %d ",
                        heap->total_collections());
         if (Verbose) {
-          gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d",
+          gclog_or_tty->print("old_gen_capacity: " SIZE_FORMAT
+            " young_gen_capacity: " SIZE_FORMAT,
             old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes());
         }
       }
@@ -2559,7 +2560,7 @@
 
   if (TraceParallelOldGCCompactionPhase) {
     if (Verbose && (fillable_regions & 7) != 0) gclog_or_tty->cr();
-    gclog_or_tty->print_cr("%u initially fillable regions", fillable_regions);
+    gclog_or_tty->print_cr(SIZE_FORMAT " initially fillable regions", fillable_regions);
   }
 }
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -330,7 +330,7 @@
 
 #ifndef PRODUCT
   if (TraceScavenge) {
-    gclog_or_tty->print_cr("{%s %s 0x%x (%d)}",
+    gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " (%d)}",
                            "promotion-failure",
                            obj->klass()->internal_name(),
                            (void *)obj, obj->size());
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -510,7 +510,8 @@
                          heap->total_collections());
 
           if (Verbose) {
-            gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d",
+            gclog_or_tty->print("old_gen_capacity: " SIZE_FORMAT
+              " young_gen_capacity: " SIZE_FORMAT,
               old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes());
           }
         }
@@ -728,7 +729,7 @@
     young_gen->object_iterate(&unforward_closure);
 
     if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("Restoring %d marks", _preserved_oop_stack.size());
+      gclog_or_tty->print_cr("Restoring " SIZE_FORMAT " marks", _preserved_oop_stack.size());
     }
 
     // Restore any saved marks.
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -31,6 +31,7 @@
 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 #include "memory/iterator.hpp"
+#include "utilities/globalDefinitions.hpp"
 
 inline void PSScavenge::save_to_space_top_before_gc() {
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
@@ -178,7 +179,7 @@
 #ifndef PRODUCT
     if (TraceScavenge) {
       ResourceMark rm;
-      gclog_or_tty->print_cr("PSScavengeKlassClosure::do_klass %p, %s, dirty: %s",
+      gclog_or_tty->print_cr("PSScavengeKlassClosure::do_klass " PTR_FORMAT ", %s, dirty: %s",
                              klass,
                              klass->external_name(),
                              klass->has_modified_oops() ? "true" : "false");
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -168,9 +168,9 @@
 
   if (TraceDynamicGCThreads) {
      gclog_or_tty->print_cr("GCTaskManager::calc_default_active_workers() : "
-       "active_workers(): %d  new_active_workers: %d  "
-       "prev_active_workers: %d\n"
-       " active_workers_by_JT: %d  active_workers_by_heap_size: %d",
+       "active_workers(): " UINTX_FORMAT "  new_active_workers: " UINTX_FORMAT "  "
+       "prev_active_workers: " UINTX_FORMAT "\n"
+       " active_workers_by_JT: " UINTX_FORMAT "  active_workers_by_heap_size: " UINTX_FORMAT,
        active_workers, new_active_workers, prev_active_workers,
        active_workers_by_JT, active_workers_by_heap_size);
   }
@@ -545,12 +545,12 @@
   if (UseGCOverheadLimit && PrintGCDetails && Verbose) {
     if (gc_overhead_limit_exceeded()) {
       gclog_or_tty->print_cr("      GC is exceeding overhead limit "
-        "of %d%%", GCTimeLimit);
+        "of " UINTX_FORMAT "%%", GCTimeLimit);
       reset_gc_overhead_limit_count();
     } else if (print_gc_overhead_limit_would_be_exceeded) {
       assert(gc_overhead_limit_count() > 0, "Should not be printing");
       gclog_or_tty->print_cr("      GC would exceed overhead limit "
-        "of %d%% %d consecutive time(s)",
+        "of " UINTX_FORMAT "%% %d consecutive time(s)",
         GCTimeLimit, gc_overhead_limit_count());
     }
   }
--- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -120,8 +120,9 @@
       float delta_ise = (CMSExtrapolateSweep ? intra_sweep_estimate : 0.0);
       _desired = (ssize_t)(new_rate * (inter_sweep_estimate + delta_ise));
       if (PrintFLSStatistics > 1) {
-        gclog_or_tty->print_cr("demand: %d, old_rate: %f, current_rate: %f, new_rate: %f, old_desired: %d, new_desired: %d",
-                                demand,     old_rate,     rate,             new_rate,     old_desired,     _desired);
+        gclog_or_tty->print_cr("demand: " SSIZE_FORMAT ", old_rate: %f, current_rate: %f, "
+                               "new_rate: %f, old_desired: " SSIZE_FORMAT ", new_desired: " SSIZE_FORMAT,
+                                demand, old_rate, rate, new_rate, old_desired, _desired);
       }
     }
   }
--- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -37,21 +37,10 @@
 
 int  ConcurrentGCThread::_CGC_flag            = CGC_nil;
 
-SuspendibleThreadSet ConcurrentGCThread::_sts;
-
 ConcurrentGCThread::ConcurrentGCThread() :
   _should_terminate(false), _has_terminated(false) {
-  _sts.initialize();
 };
 
-void ConcurrentGCThread::safepoint_synchronize() {
-  _sts.suspend_all();
-}
-
-void ConcurrentGCThread::safepoint_desynchronize() {
-  _sts.resume_all();
-}
-
 void ConcurrentGCThread::create_and_start() {
   if (os::create_thread(this, os::cgc_thread)) {
     // XXX: need to set this to low priority
@@ -92,78 +81,6 @@
   ThreadLocalStorage::set_thread(NULL);
 }
 
-
-void SuspendibleThreadSet::initialize_work() {
-  MutexLocker x(STS_init_lock);
-  if (!_initialized) {
-    _m             = new Monitor(Mutex::leaf,
-                                 "SuspendibleThreadSetLock", true);
-    _async         = 0;
-    _async_stop    = false;
-    _async_stopped = 0;
-    _initialized   = true;
-  }
-}
-
-void SuspendibleThreadSet::join() {
-  initialize();
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
-  _async++;
-  assert(_async > 0, "Huh.");
-}
-
-void SuspendibleThreadSet::leave() {
-  assert(_initialized, "Must be initialized.");
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  _async--;
-  assert(_async >= 0, "Huh.");
-  if (_async_stop) _m->notify_all();
-}
-
-void SuspendibleThreadSet::yield(const char* id) {
-  assert(_initialized, "Must be initialized.");
-  if (_async_stop) {
-    MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-    if (_async_stop) {
-      _async_stopped++;
-      assert(_async_stopped > 0, "Huh.");
-      if (_async_stopped == _async) {
-        if (ConcGCYieldTimeout > 0) {
-          double now = os::elapsedTime();
-          guarantee((now - _suspend_all_start) * 1000.0 <
-                    (double)ConcGCYieldTimeout,
-                    "Long delay; whodunit?");
-        }
-      }
-      _m->notify_all();
-      while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
-      _async_stopped--;
-      assert(_async >= 0, "Huh");
-      _m->notify_all();
-    }
-  }
-}
-
-void SuspendibleThreadSet::suspend_all() {
-  initialize();  // If necessary.
-  if (ConcGCYieldTimeout > 0) {
-    _suspend_all_start = os::elapsedTime();
-  }
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  assert(!_async_stop, "Only one at a time.");
-  _async_stop = true;
-  while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag);
-}
-
-void SuspendibleThreadSet::resume_all() {
-  assert(_initialized, "Must be initialized.");
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  assert(_async_stopped == _async, "Huh.");
-  _async_stop = false;
-  _m->notify_all();
-}
-
 static void _sltLoop(JavaThread* thread, TRAPS) {
   SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
   slt->loop();
@@ -283,30 +200,3 @@
   }
   assert(!_monitor.owned_by_self(), "Should unlock before exit.");
 }
-
-
-// ===== STS Access From Outside CGCT =====
-
-void ConcurrentGCThread::stsYield(const char* id) {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  _sts.yield(id);
-}
-
-bool ConcurrentGCThread::stsShouldYield() {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  return _sts.should_yield();
-}
-
-void ConcurrentGCThread::stsJoin() {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  _sts.join();
-}
-
-void ConcurrentGCThread::stsLeave() {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  _sts.leave();
-}
--- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -26,55 +26,8 @@
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP
 
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
+#include "gc_implementation/shared/suspendibleThreadSet.hpp"
 #include "runtime/thread.hpp"
-#endif // INCLUDE_ALL_GCS
-
-class VoidClosure;
-
-// A SuspendibleThreadSet is (obviously) a set of threads that can be
-// suspended.  A thread can join and later leave the set, and periodically
-// yield.  If some thread (not in the set) requests, via suspend_all, that
-// the threads be suspended, then the requesting thread is blocked until
-// all the threads in the set have yielded or left the set.  (Threads may
-// not enter the set when an attempted suspension is in progress.)  The
-// suspending thread later calls resume_all, allowing the suspended threads
-// to continue.
-
-class SuspendibleThreadSet {
-  Monitor* _m;
-  int      _async;
-  bool     _async_stop;
-  int      _async_stopped;
-  bool     _initialized;
-  double   _suspend_all_start;
-
-  void initialize_work();
-
- public:
-  SuspendibleThreadSet() : _initialized(false) {}
-
-  // Add the current thread to the set.  May block if a suspension
-  // is in progress.
-  void join();
-  // Removes the current thread from the set.
-  void leave();
-  // Returns "true" iff an suspension is in progress.
-  bool should_yield() { return _async_stop; }
-  // Suspends the current thread if a suspension is in progress (for
-  // the duration of the suspension.)
-  void yield(const char* id);
-  // Return when all threads in the set are suspended.
-  void suspend_all();
-  // Allow suspended threads to resume.
-  void resume_all();
-  // Redundant initializations okay.
-  void initialize() {
-    // Double-check dirty read idiom.
-    if (!_initialized) initialize_work();
-  }
-};
-
 
 class ConcurrentGCThread: public NamedThread {
   friend class VMStructs;
@@ -96,9 +49,6 @@
   static int set_CGC_flag(int b)           { return _CGC_flag |= b; }
   static int reset_CGC_flag(int b)         { return _CGC_flag &= ~b; }
 
-  // All instances share this one set.
-  static SuspendibleThreadSet _sts;
-
   // Create and start the thread (setting it's priority high.)
   void create_and_start();
 
@@ -121,25 +71,6 @@
 
   // Tester
   bool is_ConcurrentGC_thread() const          { return true;       }
-
-  static void safepoint_synchronize();
-  static void safepoint_desynchronize();
-
-  // All overridings should probably do _sts::yield, but we allow
-  // overriding for distinguished debugging messages.  Default is to do
-  // nothing.
-  virtual void yield() {}
-
-  bool should_yield() { return _sts.should_yield(); }
-
-  // they are prefixed by sts since there are already yield() and
-  // should_yield() (non-static) methods in this class and it was an
-  // easy way to differentiate them.
-  static void stsYield(const char* id);
-  static bool stsShouldYield();
-  static void stsJoin();
-  static void stsLeave();
-
 };
 
 // The SurrogateLockerThread is used by concurrent GC threads for
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -131,7 +131,7 @@
   assert(_preserved_oop_stack.size() == _preserved_mark_stack.size(),
          "inconsistent preserved oop stacks");
   if (PrintGC && Verbose) {
-    gclog_or_tty->print_cr("Restoring %d marks",
+    gclog_or_tty->print_cr("Restoring " SIZE_FORMAT " marks",
                            _preserved_count + _preserved_oop_stack.size());
   }
 
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -888,7 +888,9 @@
       for (int i = 0; i < lgrp_spaces()->length(); i++) {
         lgrp_spaces()->at(i)->accumulate_statistics(page_size());
       }
-      st->print("    local/remote/unbiased/uncommitted: %dK/%dK/%dK/%dK, large/small pages: %d/%d\n",
+      st->print("    local/remote/unbiased/uncommitted: " SIZE_FORMAT "K/"
+                SIZE_FORMAT "K/" SIZE_FORMAT "K/" SIZE_FORMAT
+                "K, large/small pages: " SIZE_FORMAT "/" SIZE_FORMAT "\n",
                 ls->space_stats()->_local_space / K,
                 ls->space_stats()->_remote_space / K,
                 ls->space_stats()->_unbiased_space / K,
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -27,6 +27,7 @@
 #include "memory/sharedHeap.hpp"
 #include "oops/arrayOop.hpp"
 #include "oops/oop.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
 
 ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) :
   _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
@@ -112,7 +113,7 @@
   }
   _used = _allocated - _wasted - _unused;
   size_t plab_sz = _used/(target_refills*no_of_gc_workers);
-  if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz);
+  if (PrintPLAB) gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT " ", plab_sz);
   // Take historical weighted average
   _filter.sample(plab_sz);
   // Clip from above and below, and align to object boundary
@@ -120,7 +121,7 @@
   plab_sz = MIN2(max_size(), plab_sz);
   plab_sz = align_object_size(plab_sz);
   // Latch the result
-  if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = %d) ", plab_sz);
+  if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = " SIZE_FORMAT ") ", plab_sz);
   _desired_plab_sz = plab_sz;
   // Now clear the accumulators for next round:
   // note this needs to be fixed in the case where we
@@ -132,8 +133,9 @@
 
 #ifndef PRODUCT
 void ParGCAllocBuffer::print() {
-  gclog_or_tty->print("parGCAllocBuffer: _bottom: %p  _top: %p  _end: %p  _hard_end: %p"
-             "_retained: %c _retained_filler: [%p,%p)\n",
+  gclog_or_tty->print("parGCAllocBuffer: _bottom: " PTR_FORMAT "  _top: " PTR_FORMAT
+             "  _end: " PTR_FORMAT "  _hard_end: " PTR_FORMAT " _retained: %c"
+             " _retained_filler: [" PTR_FORMAT "," PTR_FORMAT ")\n",
              _bottom, _top, _end, _hard_end,
              "FT"[_retained], _retained_filler.start(), _retained_filler.end());
 }
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -60,6 +60,7 @@
   // Initializes the buffer to be empty, but with the given "word_sz".
   // Must get initialized with "set_buf" for an allocation to succeed.
   ParGCAllocBuffer(size_t word_sz);
+  virtual ~ParGCAllocBuffer() {}
 
   static const size_t min_size() {
     return ThreadLocalAllocBuffer::min_size();
@@ -113,7 +114,7 @@
   }
 
   // Sets the space of the buffer to be [buf, space+word_sz()).
-  void set_buf(HeapWord* buf) {
+  virtual void set_buf(HeapWord* buf) {
     _bottom   = buf;
     _top      = _bottom;
     _hard_end = _bottom + word_sz();
@@ -158,7 +159,7 @@
   // Fills in the unallocated portion of the buffer with a garbage object.
   // If "end_of_gc" is TRUE, is after the last use in the GC.  IF "retain"
   // is true, attempt to re-use the unused portion in the next GC.
-  void retire(bool end_of_gc, bool retain);
+  virtual void retire(bool end_of_gc, bool retain);
 
   void print() PRODUCT_RETURN;
 };
@@ -238,14 +239,14 @@
 
   void undo_allocation(HeapWord* obj, size_t word_sz);
 
-  void set_buf(HeapWord* buf_start) {
+  virtual void set_buf(HeapWord* buf_start) {
     ParGCAllocBuffer::set_buf(buf_start);
     _true_end = _hard_end;
     _bt.set_region(MemRegion(buf_start, word_sz()));
     _bt.initialize_threshold();
   }
 
-  void retire(bool end_of_gc, bool retain);
+  virtual void retire(bool end_of_gc, bool retain);
 
   MemRegion range() {
     return MemRegion(_top, _true_end);
--- a/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -84,7 +84,7 @@
   assert(ZapUnusedHeapArea, "Mangling should not be in use");
 #ifdef ASSERT
   if(TraceZapUnusedHeapArea) {
-    gclog_or_tty->print("Mangling [0x%x to 0x%x)", mr.start(), mr.end());
+    gclog_or_tty->print("Mangling [" PTR_FORMAT " to " PTR_FORMAT ")", mr.start(), mr.end());
   }
   Copy::fill_to_words(mr.start(), mr.word_size(), badHeapWord);
   if(TraceZapUnusedHeapArea) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/shared/suspendibleThreadSet.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/thread.inline.hpp"
+
+uint   SuspendibleThreadSet::_nthreads          = 0;
+uint   SuspendibleThreadSet::_nthreads_stopped  = 0;
+bool   SuspendibleThreadSet::_suspend_all       = false;
+double SuspendibleThreadSet::_suspend_all_start = 0.0;
+
+void SuspendibleThreadSet::join() {
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  while (_suspend_all) {
+    ml.wait(Mutex::_no_safepoint_check_flag);
+  }
+  _nthreads++;
+}
+
+void SuspendibleThreadSet::leave() {
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  assert(_nthreads > 0, "Invalid");
+  _nthreads--;
+  if (_suspend_all) {
+    ml.notify_all();
+  }
+}
+
+void SuspendibleThreadSet::yield() {
+  if (_suspend_all) {
+    MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+    if (_suspend_all) {
+      _nthreads_stopped++;
+      if (_nthreads_stopped == _nthreads) {
+        if (ConcGCYieldTimeout > 0) {
+          double now = os::elapsedTime();
+          guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay");
+        }
+      }
+      ml.notify_all();
+      while (_suspend_all) {
+        ml.wait(Mutex::_no_safepoint_check_flag);
+      }
+      assert(_nthreads_stopped > 0, "Invalid");
+      _nthreads_stopped--;
+      ml.notify_all();
+    }
+  }
+}
+
+void SuspendibleThreadSet::synchronize() {
+  assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
+  if (ConcGCYieldTimeout > 0) {
+    _suspend_all_start = os::elapsedTime();
+  }
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  assert(!_suspend_all, "Only one at a time");
+  _suspend_all = true;
+  while (_nthreads_stopped < _nthreads) {
+    ml.wait(Mutex::_no_safepoint_check_flag);
+  }
+}
+
+void SuspendibleThreadSet::desynchronize() {
+  assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  assert(_nthreads_stopped == _nthreads, "Invalid");
+  _suspend_all = false;
+  ml.notify_all();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
+
+#include "memory/allocation.hpp"
+
+// A SuspendibleThreadSet is a set of threads that can be suspended.
+// A thread can join and later leave the set, and periodically yield.
+// If some thread (not in the set) requests, via synchronize(), that
+// the threads be suspended, then the requesting thread is blocked
+// until all the threads in the set have yielded or left the set. Threads
+// may not enter the set when an attempted suspension is in progress. The
+// suspending thread later calls desynchronize(), allowing the suspended
+// threads to continue.
+class SuspendibleThreadSet : public AllStatic {
+private:
+  static uint   _nthreads;
+  static uint   _nthreads_stopped;
+  static bool   _suspend_all;
+  static double _suspend_all_start;
+
+public:
+  // Add the current thread to the set. May block if a suspension is in progress.
+  static void join();
+
+  // Removes the current thread from the set.
+  static void leave();
+
+  // Returns true if an suspension is in progress.
+  static bool should_yield() { return _suspend_all; }
+
+  // Suspends the current thread if a suspension is in progress.
+  static void yield();
+
+  // Returns when all threads in the set are suspended.
+  static void synchronize();
+
+  // Resumes all suspended threads in the set.
+  static void desynchronize();
+};
+
+class SuspendibleThreadSetJoiner : public StackObj {
+public:
+  SuspendibleThreadSetJoiner() {
+    SuspendibleThreadSet::join();
+  }
+
+  ~SuspendibleThreadSetJoiner() {
+    SuspendibleThreadSet::leave();
+  }
+
+  bool should_yield() {
+    return SuspendibleThreadSet::should_yield();
+  }
+
+  void yield() {
+    SuspendibleThreadSet::yield();
+  }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -208,6 +208,9 @@
   // This is the correct place to place such initialization methods.
   virtual void post_initialize() = 0;
 
+  // Stop any onging concurrent work and prepare for exit.
+  virtual void stop() {}
+
   MemRegion reserved_region() const { return _reserved; }
   address base() const { return (address)reserved_region().start(); }
 
--- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -1205,13 +1205,13 @@
          "------------------------------------\n");
   size_t total_size = total_chunk_size(debug_only(NULL));
   size_t    free_blocks = num_free_blocks();
-  gclog_or_tty->print("Total Free Space: %d\n", total_size);
-  gclog_or_tty->print("Max   Chunk Size: %d\n", max_chunk_size());
-  gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
+  gclog_or_tty->print("Total Free Space: " SIZE_FORMAT "\n", total_size);
+  gclog_or_tty->print("Max   Chunk Size: " SIZE_FORMAT "\n", max_chunk_size());
+  gclog_or_tty->print("Number of Blocks: " SIZE_FORMAT "\n", free_blocks);
   if (free_blocks > 0) {
-    gclog_or_tty->print("Av.  Block  Size: %d\n", total_size/free_blocks);
+    gclog_or_tty->print("Av.  Block  Size: " SIZE_FORMAT "\n", total_size/free_blocks);
   }
-  gclog_or_tty->print("Tree      Height: %d\n", tree_height());
+  gclog_or_tty->print("Tree      Height: " SIZE_FORMAT "\n", tree_height());
 }
 
 // Print census information - counts, births, deaths, etc.
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -44,6 +44,7 @@
 #include "runtime/java.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/copy.hpp"
+#include "utilities/globalDefinitions.hpp"
 #include "utilities/stack.inline.hpp"
 
 //
@@ -131,7 +132,7 @@
 #ifndef PRODUCT
   if (TraceScavenge) {
     ResourceMark rm;
-    gclog_or_tty->print_cr("KlassScanClosure::do_klass %p, %s, dirty: %s",
+    gclog_or_tty->print_cr("KlassScanClosure::do_klass " PTR_FORMAT ", %s, dirty: %s",
                            klass,
                            klass->external_name(),
                            klass->has_modified_oops() ? "true" : "false");
@@ -511,7 +512,7 @@
 HeapWord* DefNewGeneration::allocate_from_space(size_t size) {
   HeapWord* result = NULL;
   if (Verbose && PrintGCDetails) {
-    gclog_or_tty->print("DefNewGeneration::allocate_from_space(%u):"
+    gclog_or_tty->print("DefNewGeneration::allocate_from_space(" SIZE_FORMAT "):"
                         "  will_fail: %s"
                         "  heap_lock: %s"
                         "  free: " SIZE_FORMAT,
@@ -756,7 +757,7 @@
 
 void DefNewGeneration::handle_promotion_failure(oop old) {
   if (PrintPromotionFailure && !_promotion_failed) {
-    gclog_or_tty->print(" (promotion failure size = " SIZE_FORMAT ") ",
+    gclog_or_tty->print(" (promotion failure size = %d) ",
                         old->size());
   }
   _promotion_failed = true;
--- a/hotspot/src/share/vm/memory/generation.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/memory/generation.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -573,8 +573,8 @@
                       maximum_desired_capacity / (double) K);
         gclog_or_tty->print_cr("  "
                       "  shrink_bytes: %.1fK"
-                      "  current_shrink_factor: %d"
-                      "  new shrink factor: %d"
+                      "  current_shrink_factor: " SIZE_FORMAT
+                      "  new shrink factor: " SIZE_FORMAT
                       "  _min_heap_delta_bytes: %.1fK",
                       shrink_bytes / (double) K,
                       current_shrink_factor,
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/memory/sharedHeap.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -257,7 +257,7 @@
                                        size_t bytes_before,
                                        size_t bytes_after,
                                        size_t capacity) {
-  out->print(" %d%s->%d%s(%d%s)",
+  out->print(" " SIZE_FORMAT "%s->" SIZE_FORMAT "%s(" SIZE_FORMAT "%s)",
              byte_size_in_proper_unit(bytes_before),
              proper_unit_for_byte_size(bytes_before),
              byte_size_in_proper_unit(bytes_after),
--- a/hotspot/src/share/vm/oops/methodData.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -1012,6 +1012,11 @@
   static ByteSize argument_type_offset(int i) {
     return in_ByteSize(argument_type_local_offset(i) * DataLayout::cell_size);
   }
+
+  static ByteSize return_only_size() {
+    return ReturnTypeEntry::size() + in_ByteSize(header_cell_count() * DataLayout::cell_size);
+  }
+
 };
 
 // CallTypeData
@@ -2143,7 +2148,6 @@
 
   static bool profile_jsr292(methodHandle m, int bci);
   static int profile_arguments_flag();
-  static bool profile_arguments_jsr292_only();
   static bool profile_all_arguments();
   static bool profile_arguments_for_invoke(methodHandle m, int bci);
   static int profile_return_flag();
@@ -2442,6 +2446,7 @@
 
   static bool profile_parameters_for_method(methodHandle m);
   static bool profile_arguments();
+  static bool profile_arguments_jsr292_only();
   static bool profile_return();
   static bool profile_parameters();
   static bool profile_return_jsr292_only();
--- a/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/opto/superword.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -1266,8 +1266,9 @@
     memops.clear();
     for (DUIterator i = upper_insert_pt->outs(); upper_insert_pt->has_out(i); i++) {
       Node* use = upper_insert_pt->out(i);
-      if (!use->is_Store())
+      if (use->is_Mem() && !use->is_Store()) {
         memops.push(use);
+      }
     }
 
     MemNode* lower_insert_pt = last;
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -1931,6 +1931,10 @@
           "not just one of the generations (e.g., G1). A value of 0 "       \
           "denotes 'do constant GC cycles'.")                               \
                                                                             \
+  manageable(intx, CMSTriggerInterval, -1,                                  \
+          "Commence a CMS collection cycle (at least) every so many "       \
+          "milliseconds (0 permanently, -1 disabled)")                      \
+                                                                            \
   product(bool, UseCMSInitiatingOccupancyOnly, false,                       \
           "Only use occupancy as a criterion for starting a CMS collection")\
                                                                             \
--- a/hotspot/src/share/vm/runtime/java.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/runtime/java.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -499,6 +499,9 @@
     os::infinite_sleep();
   }
 
+  // Stop any ongoing concurrent GC work
+  Universe::heap()->stop();
+
   // Terminate watcher thread - must before disenrolling any periodic task
   if (PeriodicTask::num_tasks() > 0)
     WatcherThread::stop();
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -69,7 +69,7 @@
 Monitor* SerializePage_lock           = NULL;
 Monitor* Threads_lock                 = NULL;
 Monitor* CGC_lock                     = NULL;
-Mutex*   STS_init_lock                = NULL;
+Monitor* STS_lock                     = NULL;
 Monitor* SLT_lock                     = NULL;
 Monitor* iCMS_lock                    = NULL;
 Monitor* FullGCCount_lock             = NULL;
@@ -173,7 +173,7 @@
   def(tty_lock                     , Mutex  , event,       true ); // allow to lock in VM
 
   def(CGC_lock                   , Monitor, special,     true ); // coordinate between fore- and background GC
-  def(STS_init_lock              , Mutex,   leaf,        true );
+  def(STS_lock                   , Monitor, leaf,        true );
   if (UseConcMarkSweepGC) {
     def(iCMS_lock                  , Monitor, special,     true ); // CMS incremental mode start/stop notification
   }
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -79,7 +79,7 @@
                                                  // (also used by Safepoints too to block threads creation/destruction)
 extern Monitor* CGC_lock;                        // used for coordination between
                                                  // fore- & background GC threads.
-extern Mutex*   STS_init_lock;                   // coordinate initialization of SuspendibleThreadSets.
+extern Monitor* STS_lock;                        // used for joining/leaving SuspendibleThreadSet.
 extern Monitor* SLT_lock;                        // used in CMS GC for acquiring PLL
 extern Monitor* iCMS_lock;                       // CMS incremental mode start/stop notification
 extern Monitor* FullGCCount_lock;                // in support of "concurrent" full gc
--- a/hotspot/src/share/vm/runtime/safepoint.cpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Fri Apr 25 09:59:44 2014 -0700
@@ -75,7 +75,7 @@
 #endif
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
-#include "gc_implementation/shared/concurrentGCThread.hpp"
+#include "gc_implementation/shared/suspendibleThreadSet.hpp"
 #endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
@@ -110,7 +110,7 @@
     // more-general mechanism below.  DLD (01/05).
     ConcurrentMarkSweepThread::synchronize(false);
   } else if (UseG1GC) {
-    ConcurrentGCThread::safepoint_synchronize();
+    SuspendibleThreadSet::synchronize();
   }
 #endif // INCLUDE_ALL_GCS
 
@@ -486,7 +486,7 @@
   if (UseConcMarkSweepGC) {
     ConcurrentMarkSweepThread::desynchronize(false);
   } else if (UseG1GC) {
-    ConcurrentGCThread::safepoint_desynchronize();
+    SuspendibleThreadSet::desynchronize();
   }
 #endif // INCLUDE_ALL_GCS
   // record this time so VMThread can keep track how much time has elapsed
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Fri Apr 25 09:59:44 2014 -0700
@@ -1324,10 +1324,12 @@
 #define PTR_FORMAT    "0x%08"  PRIxPTR
 #endif  // _LP64
 
-#define SSIZE_FORMAT          "%" PRIdPTR
-#define SIZE_FORMAT           "%" PRIuPTR
-#define SSIZE_FORMAT_W(width) "%" #width PRIdPTR
-#define SIZE_FORMAT_W(width)  "%" #width PRIuPTR
+#define SSIZE_FORMAT             "%"   PRIdPTR
+#define SIZE_FORMAT              "%"   PRIuPTR
+#define SIZE_FORMAT_HEX          "0x%" PRIxPTR
+#define SSIZE_FORMAT_W(width)    "%"   #width PRIdPTR
+#define SIZE_FORMAT_W(width)     "%"   #width PRIuPTR
+#define SIZE_FORMAT_HEX_W(width) "0x%" #width PRIxPTR
 
 #define INTX_FORMAT           "%" PRIdPTR
 #define UINTX_FORMAT          "%" PRIuPTR
--- a/hotspot/test/TEST.groups	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/test/TEST.groups	Fri Apr 25 09:59:44 2014 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 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
@@ -127,10 +127,12 @@
   gc/6581734/Test6581734.java \
   gc/7072527/TestFullGCCount.java \
   gc/g1/TestHumongousAllocInitialMark.java \
+  gc/g1/TestHumongousShrinkHeap.java \
   gc/arguments/TestG1HeapRegionSize.java \
   gc/metaspace/TestMetaspaceMemoryPool.java \
   gc/arguments/TestDynMinHeapFreeRatio.java \
   gc/arguments/TestDynMaxHeapFreeRatio.java \
+  gc/parallelScavenge/TestDynShrinkHeap.java \
   runtime/InternalApi/ThreadCpuTimesDeadlock.java \
   serviceability/threads/TestFalseDeadLock.java \
   compiler/tiered/NonTieredLevelsTest.java \
--- a/hotspot/test/gc/g1/TestGCLogMessages.java	Wed Jul 05 19:38:35 2017 +0200
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java	Fri Apr 25 09:59:44 2014 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test TestPrintGCDetails
- * @bug 8035406 8027295 8035398
+ * @bug 8035406 8027295 8035398 8019342
  * @summary Ensure that the PrintGCDetails output for a minor GC with G1
  * includes the expected necessary messages.
  * @key gc
@@ -48,6 +48,8 @@
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
 
     output.shouldNotContain("[Redirty Cards");
+    output.shouldNotContain("[Parallel Redirty");
+    output.shouldNotContain("[Redirtied Cards");
     output.shouldNotContain("[Code Root Purge");
     output.shouldNotContain("[String Dedup Fixup");
     output.shouldNotContain("[Young Free CSet");
@@ -63,6 +65,8 @@
     output = new OutputAnalyzer(pb.start());
 
     output.shouldContain("[Redirty Cards");
+    output.shouldNotContain("[Parallel Redirty");
+    output.shouldNotContain("[Redirtied Cards");
     output.shouldContain("[Code Root Purge");
     output.shouldContain("[String Dedup Fixup");
     output.shouldNotContain("[Young Free CSet");
@@ -80,6 +84,8 @@
     output = new OutputAnalyzer(pb.start());
 
     output.shouldContain("[Redirty Cards");
+    output.shouldContain("[Parallel Redirty");
+    output.shouldContain("[Redirtied Cards");
     output.shouldContain("[Code Root Purge");
     output.shouldContain("[String Dedup Fixup");
     output.shouldContain("[Young Free CSet");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestHumongousShrinkHeap.java	Fri Apr 25 09:59:44 2014 -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 TestHumongousShrinkHeap
+ * @bug 8036025
+ * @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects
+ * @library /testlibrary
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 -XX:+UseG1GC -XX:G1HeapRegionSize=1M -verbose:gc TestHumongousShrinkHeap
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryUsage;
+import java.util.ArrayList;
+import java.util.List;
+import sun.management.ManagementFactoryHelper;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class TestHumongousShrinkHeap {
+
+    public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio";
+    public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio";
+
+    private static final ArrayList<ArrayList<byte[]>> garbage = new ArrayList<>();
+    private static final int PAGE_SIZE = 1024 * 1024; // 1M
+    private static final int PAGES_NUM = 5;
+
+
+    public static void main(String[] args) {
+        new TestHumongousShrinkHeap().test();
+    }
+
+    private final void test() {
+        System.gc();
+        MemoryUsagePrinter.printMemoryUsage("init");
+
+        eat();
+        MemoryUsagePrinter.printMemoryUsage("eaten");
+        MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+
+        free();
+        MemoryUsagePrinter.printMemoryUsage("free");
+        MemoryUsage muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+
+        assertLessThan(muFree.getCommitted(), muFull.getCommitted(), String.format(
+                "committed free heap size is not less than committed full heap size, heap hasn't been shrunk?%n"
+                + "%s = %s%n%s = %s",
+                MIN_FREE_RATIO_FLAG_NAME,
+                ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MIN_FREE_RATIO_FLAG_NAME).getValue(),
+                MAX_FREE_RATIO_FLAG_NAME,
+                ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MAX_FREE_RATIO_FLAG_NAME).getValue()
+        ));
+    }
+
+    private void eat() {
+        int HumongousObjectSize = Math.round(.9f * PAGE_SIZE);
+        System.out.println("Will allocate objects of size=" +
+                MemoryUsagePrinter.humanReadableByteCount(HumongousObjectSize, true));
+
+        for (int i = 0; i < PAGES_NUM; i++) {
+            ArrayList<byte[]> stuff = new ArrayList<>();
+            eatList(stuff, 100, HumongousObjectSize);
+            MemoryUsagePrinter.printMemoryUsage("eat #" + i);
+            garbage.add(stuff);
+        }
+    }
+
+    private void free() {
+        // do not free last one list
+        garbage.subList(0, garbage.size() - 1).clear();
+
+        // do not free last one element from last list
+        ArrayList stuff = garbage.get(garbage.size() - 1);
+        stuff.subList(0, stuff.size() - 1).clear();
+        System.gc();
+    }
+
+    private static void eatList(List garbage, int count, int size) {
+        for (int i = 0; i < count; i++) {
+            garbage.add(new byte[size]);
+        }
+    }
+}
+
+/**
+ * Prints memory usage to standard output
+ */
+class MemoryUsagePrinter {
+
+    public static String humanReadableByteCount(long bytes, boolean si) {
+        int unit = si ? 1000 : 1024;
+        if (bytes < unit) {
+            return bytes + " B";
+        }
+        int exp = (int) (Math.log(bytes) / Math.log(unit));
+        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
+        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
+    }
+
+    public static void printMemoryUsage(String label) {
+        MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+        float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
+        System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
+                label,
+                humanReadableByteCount(memusage.getInit(), true),
+                humanReadableByteCount(memusage.getUsed(), true),
+                humanReadableByteCount(memusage.getCommitted(), true),
+                freeratio * 100
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java	Fri Apr 25 09:59:44 2014 -0700
@@ -0,0 +1,125 @@
+/*
+ * 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 TestDynShrinkHeap
+ * @bug 8016479
+ * @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags
+ * @library /testlibrary
+ * @run main/othervm -XX:+UseAdaptiveSizePolicyWithSystemGC -XX:+UseParallelGC -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 -verbose:gc TestDynShrinkHeap
+ */
+
+import com.oracle.java.testlibrary.TestDynamicVMOption;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryUsage;
+import java.util.ArrayList;
+import sun.management.ManagementFactoryHelper;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class TestDynShrinkHeap {
+
+    public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio";
+    public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio";
+
+    private static ArrayList<byte[]> list = new ArrayList<>(0);
+    private static final int M = 1024 * 1024; // to make heap more manageable by test code
+
+    private final TestDynamicVMOption maxRatioOption;
+    private final TestDynamicVMOption minRatioOption;
+
+    public TestDynShrinkHeap() {
+        minRatioOption = new TestDynamicVMOption(MIN_FREE_RATIO_FLAG_NAME);
+        maxRatioOption = new TestDynamicVMOption(MAX_FREE_RATIO_FLAG_NAME);
+    }
+
+    private final void test() {
+        System.gc();
+        MemoryUsagePrinter.printMemoryUsage("init");
+
+        eat();
+        MemoryUsagePrinter.printMemoryUsage("eaten");
+        MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+
+        free();
+        MemoryUsagePrinter.printMemoryUsage("free");
+        MemoryUsage muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+
+        assertLessThan(muFree.getCommitted(), muFull.getCommitted(), String.format(
+                "committed free heap size is not less than committed full heap size, heap hasn't been shrunk?%n"
+                + "%s = %s%n%s = %s",
+                MIN_FREE_RATIO_FLAG_NAME,
+                ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MIN_FREE_RATIO_FLAG_NAME).getValue(),
+                MAX_FREE_RATIO_FLAG_NAME,
+                ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MAX_FREE_RATIO_FLAG_NAME).getValue()
+        ));
+    }
+
+    private void eat() {
+        for (int i = 0; i < M; i++) {
+            list.add(new byte[1024]);
+        }
+        MemoryUsagePrinter.printMemoryUsage("allocated " + M + " arrays");
+
+        list.subList(0, M / 2).clear();
+        System.gc();
+        MemoryUsagePrinter.printMemoryUsage("array halved");
+    }
+
+    private void free() {
+        maxRatioOption.setIntValue(minRatioOption.getIntValue() + 1);
+        System.gc();
+        MemoryUsagePrinter.printMemoryUsage("under pressure");
+    }
+
+    public static void main(String[] args) {
+        new TestDynShrinkHeap().test();
+    }
+}
+
+/**
+ * Prints memory usage to standard output
+ */
+class MemoryUsagePrinter {
+
+    public static String humanReadableByteCount(long bytes, boolean si) {
+        int unit = si ? 1000 : 1024;
+        if (bytes < unit) {
+            return bytes + " B";
+        }
+        int exp = (int) (Math.log(bytes) / Math.log(unit));
+        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
+        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
+    }
+
+    public static void printMemoryUsage(String label) {
+        MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+        float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
+        System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
+                label,
+                humanReadableByteCount(memusage.getInit(), true),
+                humanReadableByteCount(memusage.getUsed(), true),
+                humanReadableByteCount(memusage.getCommitted(), true),
+                freeratio * 100
+        );
+    }
+}
--- a/hotspot/test/runtime/6925573/SortMethodsTest.java	Wed Jul 05 19:38:35 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, 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.
- *
- */
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Vector;
-
-import javax.tools.Diagnostic;
-import javax.tools.DiagnosticCollector;
-import javax.tools.FileObject;
-import javax.tools.ForwardingJavaFileManager;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaCompiler.CompilationTask;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.JavaFileObject.Kind;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
-/*
- * @ignore 6959423
- * @test SortMethodsTest
- * @bug 6925573
- * @summary verify that class loading does not need quadratic time with regard to the number of class
-methods.
- * @run main SortMethodsTest
- * @author volker.simonis@gmail.com
-*/
-
-public class SortMethodsTest {
-
-  static String createClass(String name, int nrOfMethods) {
-    StringWriter sw = new StringWriter();
-    PrintWriter pw = new PrintWriter(sw);
-    pw.println("public class " + name + "{");
-    for (int i = 0; i < nrOfMethods; i++) {
-      pw.println("  public void m" + i + "() {}");
-    }
-    pw.println("  public static String sayHello() {");
-    pw.println("    return \"Hello from class \" + " + name +
-               ".class.getName() + \" with \" + " + name +
-               ".class.getDeclaredMethods().length + \" methods\";");
-    pw.println("  }");
-    pw.println("}");
-    pw.close();
-    return sw.toString();
-  }
-
-  public static void main(String args[]) {
-
-    JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-    DiagnosticCollector<JavaFileObject> diags = new DiagnosticCollector<JavaFileObject>();
-    final String cName = new String("ManyMethodsClass");
-    Vector<Long> results = new Vector<Long>();
-
-    for (int i = 6; i < 600000; i*=10) {
-      String klass =  createClass(cName, i);
-      JavaMemoryFileObject file = new JavaMemoryFileObject(cName, klass);
-      MemoryFileManager mfm = new MemoryFileManager(comp.getStandardFileManager(diags, null, null), file);
-      CompilationTask task = comp.getTask(null, mfm, diags, null, null, Arrays.asList(file));
-
-      if (task.call()) {
-        try {
-          MemoryClassLoader mcl = new MemoryClassLoader(file);
-          long start = System.nanoTime();
-          Class<? extends Object> c = Class.forName(cName, true, mcl);
-          long end = System.nanoTime();
-          results.add(end - start);
-          Method m = c.getDeclaredMethod("sayHello", new Class[0]);
-          String ret = (String)m.invoke(null, new Object[0]);
-          System.out.println(ret + " (loaded and resloved in " + (end - start) + "ns)");
-        } catch (Exception e) {
-          System.err.println(e);
-        }
-      }
-      else {
-        System.out.println(klass);
-        System.out.println();
-        for (Diagnostic diag : diags.getDiagnostics()) {
-          System.out.println(diag.getCode() + "\n" + diag.getKind() + "\n" + diag.getPosition());
-          System.out.println(diag.getSource() + "\n" + diag.getMessage(null));
-        }
-      }
-    }
-
-    long lastRatio = 0;
-    for (int i = 2; i < results.size(); i++) {
-      long normalized1 = Math.max(results.get(i-1) - results.get(0), 1);
-      long normalized2 = Math.max(results.get(i) - results.get(0), 1);
-      long ratio = normalized2/normalized1;
-      lastRatio = ratio;
-      System.out.println("10 x more methods requires " + ratio + " x more time");
-    }
-    // The following is just vague estimation but seems to work on current x86_64 and sparcv9 machines
-    if (lastRatio > 80) {
-      throw new RuntimeException("ATTENTION: it seems that class loading needs quadratic time with regard to the number of class methods!!!");
-    }
-  }
-}
-
-class JavaMemoryFileObject extends SimpleJavaFileObject {
-
-  private final String code;
-  private ByteArrayOutputStream byteCode;
-
-  JavaMemoryFileObject(String name, String code) {
-    super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE);
-    this.code = code;
-  }
-
-  @Override
-  public CharSequence getCharContent(boolean ignoreEncodingErrors) {
-    return code;
-  }
-
-  @Override
-  public OutputStream openOutputStream() {
-    byteCode = new ByteArrayOutputStream();
-    return byteCode;
-  }
-
-  byte[] getByteCode() {
-    return byteCode.toByteArray();
-   }
-}
-
-class MemoryClassLoader extends ClassLoader {
-
-  private final JavaMemoryFileObject jfo;
-
-  public MemoryClassLoader(JavaMemoryFileObject jfo) {
-    this.jfo = jfo;
-  }
-
-  public Class findClass(String name) {
-    byte[] b = jfo.getByteCode();
-    return defineClass(name, b, 0, b.length);
-  }
-}
-
-class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
-
-  private final JavaFileObject jfo;
-
-  public MemoryFileManager(StandardJavaFileManager jfm, JavaFileObject jfo) {
-    super(jfm);
-    this.jfo = jfo;
-  }
-
-  @Override
-  public FileObject getFileForInput(Location location, String packageName,
-                                    String relativeName) throws IOException {
-    return jfo;
-  }
-
-  @Override
-  public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName,
-                                             Kind kind, FileObject outputFile) throws IOException {
-    return jfo;
-  }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/ClassFileParserBug.java	Fri Apr 25 09:59:44 2014 -0700
@@ -0,0 +1,46 @@
+/*
+ * 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
+ * @bug 8040018
+ * @library /testlibrary
+ * @summary Check for exception instead of assert.
+ * @run main ClassFileParserBug
+ */
+
+import java.io.File;
+import com.oracle.java.testlibrary.*;
+
+public class ClassFileParserBug {
+    public static void main(String args[]) throws Throwable {
+
+        System.out.println("Regression test for bug 8040018");
+        String testsrc = System.getProperty("test.src") + "/";
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-jar", testsrc + File.separator + "test.jar");
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("java.lang.ClassFormatError: Bad length on BootstrapMethods");
+        output.shouldHaveExitValue(1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/LambdaMath.jcod	Fri Apr 25 09:59:44 2014 -0700
@@ -0,0 +1,609 @@
+/*
+ * 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.
+ */
+
+/* 
+ * This test contains a BootstrapMethods attribute with a fuzzied
+ * attribute_length field that is larger than it should be.  This
+ * should cause a java.lang.ClassFormatError exception to be thrown.
+ */
+class LambdaMath {
+  0xCAFEBABE;
+  0; // minor version
+  52; // version
+  [162] { // Constant Pool
+    ; // first element is empty
+    Method #31 #69; // #1     at 0x0A
+    class #70; // #2     at 0x0F
+    Method #2 #71; // #3     at 0x12
+    Method #72 #73; // #4     at 0x17
+    Field #74 #75; // #5     at 0x1C
+    String #76; // #6     at 0x21
+    Method #77 #78; // #7     at 0x24
+    InvokeDynamic 0s #84; // #8     at 0x29
+    Method #30 #85; // #9     at 0x2E
+    String #86; // #10     at 0x33
+    InvokeDynamic 1s #84; // #11     at 0x36
+    String #88; // #12     at 0x3B
+    InvokeDynamic 2s #84; // #13     at 0x3E
+    String #90; // #14     at 0x43
+    InvokeDynamic 3s #84; // #15     at 0x46
+    String #92; // #16     at 0x4B
+    InvokeDynamic 4s #84; // #17     at 0x4E
+    InterfaceMethod #94 #95; // #18     at 0x53
+    InterfaceMethod #96 #97; // #19     at 0x58
+    InterfaceMethod #96 #98; // #20     at 0x5D
+    InterfaceMethod #99 #100; // #21     at 0x62
+    class #101; // #22     at 0x67
+    Method #22 #69; // #23     at 0x6A
+    Method #22 #102; // #24     at 0x6F
+    String #103; // #25     at 0x74
+    Method #22 #104; // #26     at 0x77
+    Method #22 #105; // #27     at 0x7C
+    class #106; // #28     at 0x81
+    Method #2 #107; // #29     at 0x84
+    class #108; // #30     at 0x89
+    class #109; // #31     at 0x8C
+    Utf8 "<init>"; // #32     at 0x8F
+    Utf8 "()V"; // #33     at 0x98
+    Utf8 "Code"; // #34     at 0x9E
+    Utf8 "LineNumberTable"; // #35     at 0xA5
+    Utf8 "LocalVariableTable"; // #36     at 0xB7
+    Utf8 "this"; // #37     at 0xCC
+    Utf8 "LLambdaMath;"; // #38     at 0xD3
+    Utf8 "main"; // #39     at 0xE2
+    Utf8 "([Ljava/lang/String;)V"; // #40     at 0xE9
+    Utf8 "a"; // #41     at 0x0102
+    Utf8 "[Ljava/lang/String;"; // #42     at 0x0106
+    Utf8 "list"; // #43     at 0x011C
+    Utf8 "Ljava/util/List;"; // #44     at 0x0123
+    Utf8 "LocalVariableTypeTable"; // #45     at 0x0136
+    Utf8 "Ljava/util/List<Ljava/lang/Integer;>;"; // #46     at 0x014F
+    Utf8 "evaluate"; // #47     at 0x0177
+    Utf8 "(Ljava/util/List;Ljava/util/function/Predicate;)V"; // #48     at 0x0182
+    Utf8 "n"; // #49     at 0x01B6
+    Utf8 "Ljava/lang/Integer;"; // #50     at 0x01BA
+    Utf8 "e"; // #51     at 0x01D0
+    Utf8 "Ljava/lang/Throwable;"; // #52     at 0x01D4
+    Utf8 "predicate"; // #53     at 0x01EC
+    Utf8 "Ljava/util/function/PrediCate;"; // #54     at 0x01F8
+    Utf8 "Ljava/util/function/Predicate<Ljava/lang/Integer;>;"; // #55     at 0x0219
+    Utf8 "StackMapTable"; // #56     at 0x024F
+    class #110; // #57     at 0x025F
+    class #106; // #58     at 0x0262
+    Utf8 "Signature"; // #59     at 0x0265
+    Utf8 "(Ljava/util/List<Ljava/lang/Integer;>;Ljava/util/function/Predicate<Ljava/lang/Integer;>;)V"; // #60     at 0x0271
+    Utf8 "lambda$main$4"; // #61     at 0x02CF
+    Utf8 "(Ljava/lang/Integer;)Z"; // #62     at 0x02DF
+    Utf8 "lambda$main$3"; // #63     at 0x02F8
+    Utf8 "lambda$main$2"; // #64     at 0x0308
+    Utf8 "lambda$main$1"; // #65     at 0x0318
+    Utf8 "lambda$main$0"; // #66     at 0x0328
+    Utf8 "SourceFile"; // #67     at 0x0338
+    Utf8 "LambdaMath.java"; // #68     at 0x0345
+    NameAndType #32 #33; // #69     at 0x0357
+    Utf8 "java/lang/Integer"; // #70     at 0x035C
+    NameAndType #111 #112; // #71     at 0x0370
+    class #113; // #72     at 0x0375
+    NameAndType #114 #115; // #73     at 0x0378
+    class #116; // #74     at 0x037D
+    NameAndType #117 #118; // #75     at 0x0380
+    Utf8 "Print all numbers:"; // #76     at 0x0385
+    class #119; // #77     at 0x039A
+    NameAndType #120 #121; // #78     at 0x039D
+    Utf8 "BootstrapMethods"; // #79     at 0x03A2
+    MethodHandle 6b #122; // #80     at 0x03B5
+    MethodType #123; // #81     at 0x03B9
+    MethodHandle 6b #124; // #82     at 0x03BC
+    MethodType #62; // #83     at 0x03C0
+    NameAndType #125 #126; // #84     at 0x03C3
+    NameAndType #47 #48; // #85     at 0x03C8
+    Utf8 "Print no numbers:"; // #86     at 0x03CD
+    MethodHandle 6b #127; // #87     at 0x03E1
+    Utf8 "Print even numbers:"; // #88     at 0x03E5
+    MethodHandle 6b #128; // #89     at 0x03FB
+    Utf8 "Print odd numbers:"; // #90     at 0x03FF
+    MethodHandle 6b #129; // #91     at 0x0414
+    Utf8 "Print numbers greater than 5:"; // #92     at 0x0418
+    MethodHandle 6b #130; // #93     at 0x0438
+    class #131; // #94     at 0x043C
+    NameAndType #132 #133; // #95     at 0x043F
+    class #110; // #96     at 0x0444
+    NameAndType #134 #135; // #97     at 0x0447
+    NameAndType #136 #137; // #98     at 0x044C
+    class #138; // #99     at 0x0451
+    NameAndType #125 #123; // #100     at 0x0454
+    Utf8 "java/lang/StringFuilder"; // #101     at 0x0459
+    NameAndType #139 #140; // #102     at 0x0473
+    Utf8 " "; // #103     at 0x0478
+    NameAndType #139 #141; // #104     at 0x047C
+    NameAndType #142 #143; // #105     at 0x0481
+    Utf8 "java/lang/Throwable"; // #106     at 0x0486
+    NameAndType #144 #145; // #107     at 0x049C
+    Utf8 "LambdaMath"; // #108     at 0x04A1
+    Utf8 "java/lang/Object"; // #109     at 0x04AE
+    Utf8 "java/util/Iterator"; // #110     at 0x04C1
+    Utf8 "valueOf"; // #111     at 0x04D6
+    Utf8 "(I)Ljava/lang/Integer;"; // #112     at 0x04E0
+    Utf8 "java/util/Arrays"; // #113     at 0x04F9
+    Utf8 "asList"; // #114     at 0x050C
+    Utf8 "([Ljava/lang/Object;)Ljava/util/List;"; // #115     at 0x0515
+    Utf8 "java/lang/System"; // #116     at 0x053D
+    Utf8 "out"; // #117     at 0x0550
+    Utf8 "Ljava/io/PrintStream;"; // #118     at 0x0556
+    Utf8 "java/io/PrintStream"; // #119     at 0x056E
+    Utf8 "println"; // #120     at 0x0584
+    Utf8 "(Ljava/lang/String;)V"; // #121     at 0x058E
+    Method #146 #147; // #122     at 0x05A6
+    Utf8 "(Ljava/lang/Object;)Z"; // #123     at 0x05AB
+    Method #30 #148; // #124     at 0x05C3
+    Utf8 "test"; // #125     at 0x05C8
+    Utf8 "()Ljava/util/function/Predicate;"; // #126     at 0x05CF
+    Method #30 #149; // #127     at 0x05F2
+    Method #30 #150; // #128     at 0x05F7
+    Method #30 #151; // #129     at 0x05FC
+    Method #30 #152; // #130     at 0x0601
+    Utf8 "java/util/List"; // #131     at 0x0606
+    Utf8 "iterator"; // #132     at 0x0617
+    Utf8 "()Ljava/util/Iterator;"; // #133     at 0x0622
+    Utf8 "hasNext"; // #134     at 0x063B
+    Utf8 "()Z"; // #135     at 0x0645
+    Utf8 "next"; // #136     at 0x064B
+    Utf8 "()Ljava/lang/Object;"; // #137     at 0x0652
+    Utf8 "java/util/function/Predicate"; // #138     at 0x0669
+    Utf8 "append"; // #139     at 0x0688
+    Utf8 "(Ljava/lang/Object;)Ljava/lang/StringBuilder;"; // #140     at 0x0691
+    Utf8 "(Ljava/lang/String;)Ljava/lang/StringBuilder;"; // #141     at 0x06C1
+    Utf8 "toString"; // #142     at 0x06F1
+    Utf8 "()Ljava/lang/String;"; // #143     at 0x06FC
+    Utf8 "intValue"; // #144     at 0x0713
+    Utf8 "()I"; // #145     at 0x071E
+    class #153; // #146     at 0x0724
+    NameAndType #154 #158; // #147     at 0x0727
+    NameAndType #66 #62; // #148     at 0x072C
+    NameAndType #65 #62; // #149     at 0x0731
+    NameAndType #64 #62; // #150     at 0x0736
+    NameAndType #63 #62; // #151     at 0x073B
+    NameAndType #61 #62; // #152     at 0x0740
+    Utf8 "java/lang/invoke/LambdaMetafactory"; // #153     at 0x0745
+    Utf8 "metafactory"; // #154     at 0x076A
+    class #160; // #155     at 0x0778
+    Utf8 "Lookup"; // #156     at 0x077B
+    Utf8 "InnerClasses"; // #157     at 0x0784
+    Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"; // #158     at 0x0793
+    class #161; // #159     at 0x0862
+    Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #160     at 0x0865
+    Utf8 "java/lang/invoke/MethodHandles"; // #161     at 0x088D
+  } // Constant Pool
+
+  0x0021; // access
+  #30;// this_cpx
+  #31;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [8] { // methods
+    { // Member at 0x08BA
+      0x0001; // access
+      #32; // name_cpx
+      #33; // sig_cpx
+      [1] { // Attributes
+        Attr(#34, 47) { // Code at 0x08C2
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [2] { // Attributes
+            Attr(#35, 6) { // LineNumberTable at 0x08D9
+              [1] { // LineNumberTable
+                0  5; //  at 0x08E5
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 12) { // LocalVariableTable at 0x08E5
+              [1] { // LocalVariableTable
+                0 5 37 38 0; //  at 0x08F7
+              }
+            } // end LocalVariableTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x08F7
+      0x0009; // access
+      #39; // name_cpx
+      #40; // sig_cpx
+      [1] { // Attributes
+        Attr(#34, 261) { // Code at 0x08FF
+          4; // max_stack
+          2; // max_locals
+          Bytes[147]{
+            0x1007BD0002590304;
+            0xB8000353590405B8;
+            0x000353590506B800;
+            0x0353590607B80003;
+            0x53590708B8000353;
+            0x59081006B8000353;
+            0x5910061007B80003;
+            0x53B800044CB20005;
+            0x1206B600072BBA00;
+            0x080000B80009B200;
+            0x05120AB600072BBA;
+            0x000B0000B80009B2;
+            0x0005120CB600072B;
+            0xBA000D0000B80009;
+            0xB20005120EB60007;
+            0x2BBA000F0000B800;
+            0x09B200051210B600;
+            0x072BBA00110000B8;
+            0x0009B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [3] { // Attributes
+            Attr(#35, 50) { // LineNumberTable at 0x09A4
+              [12] { // LineNumberTable
+                0  9; //  at 0x09B0
+                61  11; //  at 0x09B4
+                69  12; //  at 0x09B8
+                78  14; //  at 0x09BC
+                86  15; //  at 0x09C0
+                95  17; //  at 0x09C4
+                103  18; //  at 0x09C8
+                112  20; //  at 0x09CC
+                120  21; //  at 0x09D0
+                129  23; //  at 0x09D4
+                137  24; //  at 0x09D8
+                146  26; //  at 0x09DC
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 22) { // LocalVariableTable at 0x09DC
+              [2] { // LocalVariableTable
+                0 147 41 42 0; //  at 0x09EE
+                61 86 43 44 1; //  at 0x09F8
+              }
+            } // end LocalVariableTable
+            ;
+            Attr(#45, 12) { // LocalVariableTypeTable at 0x09F8
+              [1] { // LocalVariableTypeTable
+                61 86 43 46 1; //  at 0x0A0A
+              }
+            } // end LocalVariableTypeTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0A0A
+      0x0009; // access
+      #47; // name_cpx
+      #48; // sig_cpx
+      [2] { // Attributes
+        Attr(#34, 224) { // Code at 0x0A12
+          3; // max_stack
+          4; // max_locals
+          Bytes[69]{
+            0x2AB9001201004D2C;
+            0xB900130100990033;
+            0x2CB900140100C200;
+            0x024E2B2DB9001502;
+            0x0099001CB20005BB;
+            0x001659B700172DB6;
+            0x00181219B6001AB6;
+            0x001BB60007A7FFCA;
+            0xA700044DB1;
+          };
+          [1] { // Traps
+            0 64 67 28; //  at 0x0A6F
+          } // end Traps
+          [4] { // Attributes
+            Attr(#35, 30) { // LineNumberTable at 0x0A71
+              [7] { // LineNumberTable
+                0  30; //  at 0x0A7D
+                26  31; //  at 0x0A81
+                36  32; //  at 0x0A85
+                61  34; //  at 0x0A89
+                64  38; //  at 0x0A8D
+                67  37; //  at 0x0A91
+                68  39; //  at 0x0A95
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 42) { // LocalVariableTable at 0x0A95
+              [4] { // LocalVariableTable
+                26 35 49 50 3; //  at 0x0AA7
+                68 0 51 52 2; //  at 0x0AB1
+                0 69 43 44 0; //  at 0x0ABB
+                0 69 53 54 1; //  at 0x0AC5
+              }
+            } // end LocalVariableTable
+            ;
+            Attr(#45, 22) { // LocalVariableTypeTable at 0x0AC5
+              [2] { // LocalVariableTypeTable
+                0 69 43 46 0; //  at 0x0AD7
+                0 69 53 55 1; //  at 0x0AE1
+              }
+            } // end LocalVariableTypeTable
+            ;
+            Attr(#56, 17) { // StackMapTable at 0x0AE1
+              [5] { // 
+                252b, 7, [1]z{7b,57}; // append_frame 1
+                53b; // same_frame
+                250b, 2; // chop_frame 1
+                66b, [1]z{7b,58}; // same_locals_1_stack_item_frame
+                0b; // same_frame
+              }
+            } // end StackMapTable
+          } // Attributes
+        } // end Code
+        ;
+        Attr(#59, 2) { // Signature at 0x0AF8
+          #60;
+        } // end Signature
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0B00
+      0x100A; // access
+      #61; // name_cpx
+      #62; // sig_cpx
+      [1] { // Attributes
+        Attr(#34, 67) { // Code at 0x0B08
+          2; // max_stack
+          1; // max_locals
+          Bytes[14]{
+            0x2AB6001D08A40007;
+            0x04A7000403AC;
+          };
+          [0] { // Traps
+          } // end Traps
+          [3] { // Attributes
+            Attr(#35, 6) { // LineNumberTable at 0x0B28
+              [1] { // LineNumberTable
+                0  24; //  at 0x0B34
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 12) { // LocalVariableTable at 0x0B34
+              [1] { // LocalVariableTable
+                0 14 49 50 0; //  at 0x0B46
+              }
+            } // end LocalVariableTable
+            ;
+            Attr(#56, 5) { // StackMapTable at 0x0B46
+              [2] { // 
+                12b; // same_frame
+                64b, [1]z{1b}; // same_locals_1_stack_item_frame
+              }
+            } // end StackMapTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0B51
+      0x100A; // access
+      #63; // name_cpx
+      #62; // sig_cpx
+      [1] { // Attributes
+        Attr(#34, 69) { // Code at 0x0B59
+          2; // max_stack
+          1; // max_locals
+          Bytes[16]{
+            0x2AB6001D057004A0;
+            0x000704A7000403AC;
+          };
+          [0] { // Traps
+          } // end Traps
+          [3] { // Attributes
+            Attr(#35, 6) { // LineNumberTable at 0x0B7B
+              [1] { // LineNumberTable
+                0  21; //  at 0x0B87
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 12) { // LocalVariableTable at 0x0B87
+              [1] { // LocalVariableTable
+                0 16 49 50 0; //  at 0x0B99
+              }
+            } // end LocalVariableTable
+            ;
+            Attr(#56, 5) { // StackMapTable at 0x0B99
+              [2] { // 
+                14b; // same_frame
+                64b, [1]z{1b}; // same_locals_1_stack_item_frame
+              }
+            } // end StackMapTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0BA4
+      0x100A; // access
+      #64; // name_cpx
+      #62; // sig_cpx
+      [1] { // Attributes
+        Attr(#34, 68) { // Code at 0x0BAC
+          2; // max_stack
+          1; // max_locals
+          Bytes[15]{
+            0x2AB6001D05709A00;
+            0x0704A7000403AC;
+          };
+          [0] { // Traps
+          } // end Traps
+          [3] { // Attributes
+            Attr(#35, 6) { // LineNumberTable at 0x0BCD
+              [1] { // LineNumberTable
+                0  18; //  at 0x0BD9
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 12) { // LocalVariableTable at 0x0BD9
+              [1] { // LocalVariableTable
+                0 15 49 50 0; //  at 0x0BEB
+              }
+            } // end LocalVariableTable
+            ;
+            Attr(#56, 5) { // StackMapTable at 0x0BEB
+              [2] { // 
+                13b; // same_frame
+                64b, [1]z{1b}; // same_locals_1_stack_item_frame
+              }
+            } // end StackMapTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0BF6
+      0x100A; // access
+      #65; // name_cpx
+      #62; // sig_cpx
+      [1] { // Attributes
+        Attr(#34, 44) { // Code at 0x0BFE
+          1; // max_stack
+          1; // max_locals
+          Bytes[2]{
+            0x03AC;
+          };
+          [0] { // Traps
+          } // end Traps
+          [2] { // Attributes
+            Attr(#35, 6) { // LineNumberTable at 0x0C12
+              [1] { // LineNumberTable
+                0  15; //  at 0x0C1E
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 12) { // LocalVariableTable at 0x0C1E
+              [1] { // LocalVariableTable
+                0 2 49 50 0; //  at 0x0C30
+              }
+            } // end LocalVariableTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0C30
+      0x100A; // access
+      #66; // name_cpx
+      #62; // sig_cpx
+      [1] { // Attributes
+        Attr(#34, 44) { // Code at 0x0C38
+          1; // max_stack
+          1; // max_locals
+          Bytes[2]{
+            0x04AC;
+          };
+          [0] { // Traps
+          } // end Traps
+          [2] { // Attributes
+            Attr(#35, 6) { // LineNumberTable at 0x0C4C
+              [1] { // LineNumberTable
+                0  12; //  at 0x0C58
+              }
+            } // end LineNumberTable
+            ;
+            Attr(#36, 12) { // LocalVariableTable at 0x0C58
+              [1] { // LocalVariableTable
+                0 2 49 50 0; //  at 0x0C6A
+              }
+            } // end LocalVariableTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [3] { // Attributes
+    Attr(#67, 2) { // SourceFile at 0x0C6C
+      #68;
+    } // end SourceFile
+    ;
+    Attr(#157, 10) { // InnerClasses at 0x0C74
+      [1] { // InnerClasses
+        #155 #159 #156 25; //  at 0x0C84
+      }
+    } // end InnerClasses
+    ;
+    Attr(#79, 52) { // BootstrapMethods at 0x0C84
+      [5] { // bootstrap_methods
+        {  //  bootstrap_method
+          #80; // bootstrap_method_ref
+          [3] { // bootstrap_arguments
+            #81; //  at 0x0C92
+            #82; //  at 0x0C94
+            #83; //  at 0x0C96
+          }  //  bootstrap_arguments
+        }  //  bootstrap_method
+        ;
+        {  //  bootstrap_method
+          #80; // bootstrap_method_ref
+          [3] { // bootstrap_arguments
+            #81; //  at 0x0C9C
+            #87; //  at 0x0C9E
+            #83; //  at 0x0CA0
+          }  //  bootstrap_arguments
+        }  //  bootstrap_method
+        ;
+        {  //  bootstrap_method
+          #80; // bootstrap_method_ref
+          [3] { // bootstrap_arguments
+            #81; //  at 0x0CA6
+            #89; //  at 0x0CA8
+            #83; //  at 0x0CAA
+          }  //  bootstrap_arguments
+        }  //  bootstrap_method
+        ;
+        {  //  bootstrap_method
+          #80; // bootstrap_method_ref
+          [3] { // bootstrap_arguments
+            #81; //  at 0x0CB0
+            #91; //  at 0x0CB2
+            #83; //  at 0x0CB4
+          }  //  bootstrap_arguments
+        }  //  bootstrap_method
+        ;
+        {  //  bootstrap_method
+          #80; // bootstrap_method_ref
+          [1] { // bootstrap_arguments
+            #81; //  at 0x0CBA
+          }  //  bootstrap_arguments
+        }  //  bootstrap_method
+      }
+// ======== attribute array started  at 0x0C84 has 4 bytes more:
+      0x005D0053;
+    } // end BootstrapMethods
+  } // Attributes
+} // end class LambdaMath
Binary file hotspot/test/runtime/classFileParserBug/test.jar has changed