Merge
authorstefank
Fri, 11 Aug 2017 21:33:56 +0000
changeset 46801 4a0c196dd796
parent 46800 498d81a49f6b (current diff)
parent 46795 623a5e42deb6 (diff)
child 46802 cf78889c7590
Merge
hotspot/src/share/vm/gc/g1/workerDataArray.cpp
hotspot/src/share/vm/gc/g1/workerDataArray.hpp
hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp
hotspot/test/native/gc/g1/test_workerDataArray.cpp
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -2027,7 +2027,7 @@
   inline void vperm(    VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c);
   inline void vsel(     VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c);
   inline void vsl(      VectorRegister d, VectorRegister a, VectorRegister b);
-  inline void vsldoi(   VectorRegister d, VectorRegister a, VectorRegister b, int si4);
+  inline void vsldoi(   VectorRegister d, VectorRegister a, VectorRegister b, int ui4);
   inline void vslo(     VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vsr(      VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vsro(     VectorRegister d, VectorRegister a, VectorRegister b);
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -800,7 +800,7 @@
 inline void Assembler::vperm(   VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VPERM_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
 inline void Assembler::vsel(    VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VSEL_OPCODE  | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
 inline void Assembler::vsl(     VectorRegister d, VectorRegister a, VectorRegister b)                  { emit_int32( VSL_OPCODE   | vrt(d) | vra(a) | vrb(b)); }
-inline void Assembler::vsldoi(  VectorRegister d, VectorRegister a, VectorRegister b, int si4)         { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(simm(si4,4))); }
+inline void Assembler::vsldoi(  VectorRegister d, VectorRegister a, VectorRegister b, int ui4)         { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(uimm(ui4,4))); }
 inline void Assembler::vslo(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSLO_OPCODE    | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vsr(     VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSR_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vsro(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRO_OPCODE    | vrt(d) | vra(a) | vrb(b)); }
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -4576,12 +4576,12 @@
   vspltisw(VR0, -1);
 
   vsldoi(mask_32bit, zeroes, VR0, 4);
-  vsldoi(mask_64bit, zeroes, VR0, -8);
+  vsldoi(mask_64bit, zeroes, VR0, 8);
 
   // Get the initial value into v8
   vxor(VR8, VR8, VR8);
   mtvrd(VR8, crc);
-  vsldoi(VR8, zeroes, VR8, -8); // shift into bottom 32 bits
+  vsldoi(VR8, zeroes, VR8, 8); // shift into bottom 32 bits
 
   li (rLoaded, 0);
 
@@ -4930,7 +4930,7 @@
   addi(barretConstants, barretConstants, 16);
   lvx(const2, barretConstants);
 
-  vsldoi(VR1, VR0, VR0, -8);
+  vsldoi(VR1, VR0, VR0, 8);
   vxor(VR0, VR0, VR1);    // xor two 64 bit results together
 
   // shift left one bit
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -2729,7 +2729,7 @@
     __ vspltisb        (vTmp2, -16);
     __ vrld            (keyPerm, keyPerm, vTmp2);
     __ vrld            (keyPerm, keyPerm, vTmp2);
-    __ vsldoi          (keyPerm, keyPerm, keyPerm, -8);
+    __ vsldoi          (keyPerm, keyPerm, keyPerm, 8);
 
     // load the 1st round key to vKey1
     __ li              (keypos, 0);
@@ -2929,7 +2929,7 @@
     __ vspltisb        (vTmp2, -16);
     __ vrld            (keyPerm, keyPerm, vTmp2);
     __ vrld            (keyPerm, keyPerm, vTmp2);
-    __ vsldoi          (keyPerm, keyPerm, keyPerm, -8);
+    __ vsldoi          (keyPerm, keyPerm, keyPerm, 8);
 
     __ cmpwi           (CCR0, keylen, 44);
     __ beq             (CCR0, L_do44);
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -108,13 +108,16 @@
 
     public Object next() {
       Address addr;
-      if (index > 0) {
-        addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
-      } else {
+      if (index == 0) {
+        // advance to next block
         blockAddr = block.freeNext();
+        if (blockAddr == null) {
+          throw new NoSuchElementException();
+        }
+        block = new ObjectMonitor(blockAddr);
         index = blockSize - 1;
-        addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
       }
+      addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
       index --;
       return new ObjectMonitor(addr);
     }
--- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Fri Aug 11 21:33:56 2017 +0000
@@ -39,7 +39,7 @@
     private Set<SpeculationReason> failedSpeculations;
 
     /** Strong references to all reasons embedded in the current nmethod. */
-    private volatile Collection<SpeculationReason> speculations;
+    private Collection<SpeculationReason> speculations;
 
     @Override
     public synchronized void collectFailedSpeculations() {
@@ -70,14 +70,12 @@
          * reason objects that are embedded in nmethods, so we add them to the speculations
          * collection.
          */
-        if (speculations == null) {
-            synchronized (this) {
-                if (speculations == null) {
-                    speculations = new ConcurrentLinkedQueue<>();
-                }
+        synchronized (this) {
+            if (speculations == null) {
+                speculations = new ConcurrentLinkedQueue<>();
             }
+            speculations.add(reason);
         }
-        speculations.add(reason);
 
         return HotSpotObjectConstantImpl.forObject(reason);
     }
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -387,7 +387,7 @@
     intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!
     address pc = (address)stk.AddrPC.Offset;
 
-    if (pc != NULL && sp != NULL && fp != NULL) {
+    if (pc != NULL) {
       if (count == 2 && lastpc == pc) {
         // Skip it -- StackWalk64() may return the same PC
         // (but different SP) on the first try.
@@ -399,8 +399,6 @@
         st->cr();
       }
       lastpc = pc;
-    } else {
-      break;
     }
 
     PVOID p = WindowsDbgHelp::SymFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -5185,6 +5185,7 @@
   CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
                                 _span, &_markBitMap, &_markStack,
                                 &cmsKeepAliveClosure, false /* !preclean */);
+  ReferenceProcessorPhaseTimes pt(_gc_timer_cm, rp->num_q());
   {
     GCTraceTime(Debug, gc, phases) t("Reference Processing", _gc_timer_cm);
 
@@ -5211,16 +5212,16 @@
                                         &cmsKeepAliveClosure,
                                         &cmsDrainMarkingStackClosure,
                                         &task_executor,
-                                        _gc_timer_cm);
+                                        &pt);
     } else {
       stats = rp->process_discovered_references(&_is_alive_closure,
                                         &cmsKeepAliveClosure,
                                         &cmsDrainMarkingStackClosure,
                                         NULL,
-                                        _gc_timer_cm);
+                                        &pt);
     }
     _gc_tracer_cm->report_gc_reference_stats(stats);
-
+    pt.print_all_references();
   }
 
   // This is the point where the entire marking should have completed.
@@ -5261,11 +5262,12 @@
   if (rp->processing_is_mt()) {
     rp->balance_all_queues();
     CMSRefProcTaskExecutor task_executor(*this);
-    rp->enqueue_discovered_references(&task_executor);
+    rp->enqueue_discovered_references(&task_executor, &pt);
   } else {
-    rp->enqueue_discovered_references(NULL);
+    rp->enqueue_discovered_references(NULL, &pt);
   }
   rp->verify_no_references_recorded();
+  pt.print_enqueue_phase();
   assert(!rp->discovery_enabled(), "should have been disabled");
 }
 
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -984,20 +984,22 @@
   // Can  the mt_degree be set later (at run_task() time would be best)?
   rp->set_active_mt_degree(active_workers);
   ReferenceProcessorStats stats;
+  ReferenceProcessorPhaseTimes pt(_gc_timer, rp->num_q());
   if (rp->processing_is_mt()) {
     ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set);
     stats = rp->process_discovered_references(&is_alive, &keep_alive,
                                               &evacuate_followers, &task_executor,
-                                              _gc_timer);
+                                              &pt);
   } else {
     thread_state_set.flush();
     gch->save_marks();
     stats = rp->process_discovered_references(&is_alive, &keep_alive,
                                               &evacuate_followers, NULL,
-                                              _gc_timer);
+                                              &pt);
   }
   _gc_tracer.report_gc_reference_stats(stats);
   _gc_tracer.report_tenuring_threshold(tenuring_threshold());
+  pt.print_all_references();
 
   if (!promotion_failed()) {
     // Swap the survivor spaces.
@@ -1049,14 +1051,16 @@
   rp->set_enqueuing_is_done(true);
   if (rp->processing_is_mt()) {
     ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set);
-    rp->enqueue_discovered_references(&task_executor);
+    rp->enqueue_discovered_references(&task_executor, &pt);
   } else {
-    rp->enqueue_discovered_references(NULL);
+    rp->enqueue_discovered_references(NULL, &pt);
   }
   rp->verify_no_references_recorded();
 
   gch->trace_heap_after_gc(gc_tracer());
 
+  pt.print_enqueue_phase();
+
   _gc_timer->register_gc_end();
 
   _gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1260,9 +1260,13 @@
       assert(num_free_regions() == 0, "we should not have added any free regions");
       rebuild_region_sets(false /* free_list_only */);
 
+      ReferenceProcessorPhaseTimes pt(NULL, ref_processor_stw()->num_q());
+
       // Enqueue any discovered reference objects that have
       // not been removed from the discovered lists.
-      ref_processor_stw()->enqueue_discovered_references();
+      ref_processor_stw()->enqueue_discovered_references(NULL, &pt);
+
+      pt.print_enqueue_phase();
 
 #if defined(COMPILER2) || INCLUDE_JVMCI
       DerivedPointerTable::update_pointers();
@@ -1667,7 +1671,9 @@
 G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
   CollectedHeap(),
   _collector_policy(collector_policy),
-  _g1_policy(create_g1_policy()),
+  _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
+  _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()),
+  _g1_policy(create_g1_policy(_gc_timer_stw)),
   _collection_set(this, _g1_policy),
   _dirty_card_queue_set(false),
   _is_alive_closure_cm(this),
@@ -1694,9 +1700,7 @@
   _expand_heap_after_alloc_failure(true),
   _old_marking_cycles_started(0),
   _old_marking_cycles_completed(0),
-  _in_cset_fast_test(),
-  _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
-  _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()) {
+  _in_cset_fast_test() {
 
   _workers = new WorkGang("GC Thread", ParallelGCThreads,
                           /* are_GC_task_threads */true,
@@ -2015,10 +2019,12 @@
 
   MemRegion mr = reserved_region();
 
+  bool mt_processing = ParallelRefProcEnabled && (ParallelGCThreads > 1);
+
   // Concurrent Mark ref processor
   _ref_processor_cm =
     new ReferenceProcessor(mr,    // span
-                           ParallelRefProcEnabled && (ParallelGCThreads > 1),
+                           mt_processing,
                                 // mt processing
                            ParallelGCThreads,
                                 // degree of mt processing
@@ -2035,7 +2041,7 @@
   // STW ref processor
   _ref_processor_stw =
     new ReferenceProcessor(mr,    // span
-                           ParallelRefProcEnabled && (ParallelGCThreads > 1),
+                           mt_processing,
                                 // mt processing
                            ParallelGCThreads,
                                 // degree of mt processing
@@ -4313,6 +4319,8 @@
   // Setup the soft refs policy...
   rp->setup_policy(false);
 
+  ReferenceProcessorPhaseTimes* pt = g1_policy()->phase_times()->ref_phase_times();
+
   ReferenceProcessorStats stats;
   if (!rp->processing_is_mt()) {
     // Serial reference processing...
@@ -4320,7 +4328,7 @@
                                               &keep_alive,
                                               &drain_queue,
                                               NULL,
-                                              _gc_timer_stw);
+                                              pt);
   } else {
     uint no_of_gc_workers = workers()->active_workers();
 
@@ -4334,7 +4342,7 @@
                                               &keep_alive,
                                               &drain_queue,
                                               &par_task_executor,
-                                              _gc_timer_stw);
+                                              pt);
   }
 
   _gc_tracer_stw->report_gc_reference_stats(stats);
@@ -4353,11 +4361,13 @@
   ReferenceProcessor* rp = _ref_processor_stw;
   assert(!rp->discovery_enabled(), "should have been disabled as part of processing");
 
+  ReferenceProcessorPhaseTimes* pt = g1_policy()->phase_times()->ref_phase_times();
+
   // Now enqueue any remaining on the discovered lists on to
   // the pending list.
   if (!rp->processing_is_mt()) {
     // Serial reference processing...
-    rp->enqueue_discovered_references();
+    rp->enqueue_discovered_references(NULL, pt);
   } else {
     // Parallel reference enqueueing
 
@@ -4368,7 +4378,7 @@
            n_workers,  rp->max_num_q());
 
     G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues, n_workers);
-    rp->enqueue_discovered_references(&par_task_executor);
+    rp->enqueue_discovered_references(&par_task_executor, pt);
   }
 
   rp->verify_no_references_recorded();
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -298,7 +298,7 @@
                                                          size_t size,
                                                          size_t translation_factor);
 
-  static G1Policy* create_g1_policy();
+  static G1Policy* create_g1_policy(STWGCTimer* gc_timer);
 
   void trace_heap(GCWhen::Type when, const GCTracer* tracer);
 
@@ -370,6 +370,10 @@
   G1EdenRegions _eden;
   G1SurvivorRegions _survivor;
 
+  STWGCTimer* _gc_timer_stw;
+
+  G1NewTracer* _gc_tracer_stw;
+
   // The current policy object for the collector.
   G1Policy* _g1_policy;
   G1HeapSizingPolicy* _heap_sizing_policy;
@@ -901,10 +905,6 @@
   // The (stw) reference processor...
   ReferenceProcessor* _ref_processor_stw;
 
-  STWGCTimer* _gc_timer_stw;
-
-  G1NewTracer* _gc_tracer_stw;
-
   // During reference object discovery, the _is_alive_non_header
   // closure (if non-null) is applied to the referent object to
   // determine whether the referent is live. If so then the
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -28,6 +28,8 @@
 #include "gc/g1/g1ParScanThreadState.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 
+class STWGCTimer;
+
 bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts,
                                                     jlong* totals,
                                                     jbyte* accuracy,
@@ -40,6 +42,6 @@
   return new HeapRegion(hrs_index, bot(), mr);
 }
 
-G1Policy* G1CollectedHeap::create_g1_policy() {
-  return new G1DefaultPolicy();
+G1Policy* G1CollectedHeap::create_g1_policy(STWGCTimer* gc_timer) {
+  return new G1DefaultPolicy(gc_timer);
 }
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1660,14 +1660,17 @@
     // Reference lists are balanced (see balance_all_queues() and balance_queues()).
     rp->set_active_mt_degree(active_workers);
 
+    ReferenceProcessorPhaseTimes pt(_gc_timer_cm, rp->num_q());
+
     // Process the weak references.
     const ReferenceProcessorStats& stats =
         rp->process_discovered_references(&g1_is_alive,
                                           &g1_keep_alive,
                                           &g1_drain_mark_stack,
                                           executor,
-                                          _gc_timer_cm);
+                                          &pt);
     _gc_tracer_cm->report_gc_reference_stats(stats);
+    pt.print_all_references();
 
     // The do_oop work routines of the keep_alive and drain_marking_stack
     // oop closures will set the has_overflown flag if we overflow the
@@ -1678,9 +1681,12 @@
 
     assert(rp->num_q() == active_workers, "why not");
 
-    rp->enqueue_discovered_references(executor);
+    rp->enqueue_discovered_references(executor, &pt);
 
     rp->verify_no_references_recorded();
+
+    pt.print_enqueue_phase();
+
     assert(!rp->discovery_enabled(), "Post condition");
   }
 
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -47,7 +47,7 @@
 #include "utilities/growableArray.hpp"
 #include "utilities/pair.hpp"
 
-G1DefaultPolicy::G1DefaultPolicy() :
+G1DefaultPolicy::G1DefaultPolicy(STWGCTimer* gc_timer) :
   _predictor(G1ConfidencePercent / 100.0),
   _analytics(new G1Analytics(&_predictor)),
   _mmu_tracker(new G1MMUTrackerQueue(GCPauseIntervalMillis / 1000.0, MaxGCPauseMillis / 1000.0)),
@@ -63,7 +63,7 @@
   _initial_mark_to_mixed(),
   _collection_set(NULL),
   _g1(NULL),
-  _phase_times(new G1GCPhaseTimes(ParallelGCThreads)),
+  _phase_times(new G1GCPhaseTimes(gc_timer, ParallelGCThreads)),
   _tenuring_threshold(MaxTenuringThreshold),
   _max_survivor_regions(0),
   _survivors_age_table(true),
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -44,6 +44,7 @@
 class G1SurvivorRegions;
 class G1YoungGenSizer;
 class GCPolicyCounters;
+class STWGCTimer;
 
 class G1DefaultPolicy: public G1Policy {
  private:
@@ -264,7 +265,7 @@
   void abort_time_to_mixed_tracking();
 public:
 
-  G1DefaultPolicy();
+  G1DefaultPolicy(STWGCTimer* gc_timer);
 
   virtual ~G1DefaultPolicy();
 
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -27,7 +27,7 @@
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1HotCardCache.hpp"
 #include "gc/g1/g1StringDedup.hpp"
-#include "gc/g1/workerDataArray.inline.hpp"
+#include "gc/shared/workerDataArray.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
@@ -37,10 +37,11 @@
 
 static const char* Indents[5] = {"", "  ", "    ", "      ", "        "};
 
-G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
+G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
   _max_gc_threads(max_gc_threads),
   _gc_start_counter(0),
-  _gc_pause_time_ms(0.0)
+  _gc_pause_time_ms(0.0),
+  _ref_phase_times((GCTimer*)gc_timer, max_gc_threads)
 {
   assert(max_gc_threads > 0, "Must have some GC threads");
 
@@ -156,6 +157,8 @@
       _gc_par_phases[i]->reset();
     }
   }
+
+  _ref_phase_times.reset();
 }
 
 void G1GCPhaseTimes::note_gc_start() {
@@ -288,6 +291,19 @@
   log_debug(gc, phases)("%s%s: " TIME_FORMAT, Indents[2], name, value);
 }
 
+void G1GCPhaseTimes::debug_time_for_reference(const char* name, double value) const {
+  LogTarget(Debug, gc, phases) lt;
+  LogTarget(Debug, gc, phases, ref) lt2;
+
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print_cr("%s%s: " TIME_FORMAT, Indents[2], name, value);
+  } else if (lt2.is_enabled()) {
+    LogStream ls(lt2);
+    ls.print_cr("%s%s: " TIME_FORMAT, Indents[2], name, value);
+  }
+}
+
 void G1GCPhaseTimes::trace_time(const char* name, double value) const {
   log_trace(gc, phases)("%s%s: " TIME_FORMAT, Indents[3], name, value);
 }
@@ -374,7 +390,8 @@
   debug_time("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms);
   trace_phase(_gc_par_phases[PreserveCMReferents]);
 
-  debug_time("Reference Processing", _cur_ref_proc_time_ms);
+  debug_time_for_reference("Reference Processing", _cur_ref_proc_time_ms);
+  _ref_phase_times.print_all_references(2, false);
 
   if (G1StringDedup::is_enabled()) {
     debug_time("String Dedup Fixup", _cur_string_dedup_fixup_time_ms);
@@ -390,7 +407,8 @@
     trace_time("Remove Self Forwards",_cur_evac_fail_remove_self_forwards);
   }
 
-  debug_time("Reference Enqueuing", _cur_ref_enq_time_ms);
+  debug_time_for_reference("Reference Enqueuing", _cur_ref_enq_time_ms);
+  _ref_phase_times.print_enqueue_phase(2, false);
 
   debug_time("Merge Per-Thread State", _recorded_merge_pss_time_ms);
   debug_time("Code Roots Purge", _cur_strong_code_root_purge_time_ms);
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -25,11 +25,13 @@
 #ifndef SHARE_VM_GC_G1_G1GCPHASETIMES_HPP
 #define SHARE_VM_GC_G1_G1GCPHASETIMES_HPP
 
+#include "gc/shared/referenceProcessorPhaseTimes.hpp"
 #include "logging/logLevel.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/macros.hpp"
 
 class LineBuffer;
+class STWGCTimer;
 
 template <class T> class WorkerDataArray;
 
@@ -159,6 +161,8 @@
   double _cur_verify_before_time_ms;
   double _cur_verify_after_time_ms;
 
+  ReferenceProcessorPhaseTimes _ref_phase_times;
+
   double worker_time(GCParPhases phase, uint worker);
   void note_gc_end();
   void reset();
@@ -172,6 +176,8 @@
 
   void info_time(const char* name, double value) const;
   void debug_time(const char* name, double value) const;
+  // This will print logs for both 'gc+phases' and 'gc+phases+ref'.
+  void debug_time_for_reference(const char* name, double value) const;
   void trace_time(const char* name, double value) const;
   void trace_count(const char* name, size_t value) const;
 
@@ -181,7 +187,7 @@
   void print_other(double accounted_ms) const;
 
  public:
-  G1GCPhaseTimes(uint max_gc_threads);
+  G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads);
   void note_gc_start();
   void print();
 
@@ -354,6 +360,8 @@
   double fast_reclaim_humongous_time_ms() {
     return _cur_fast_reclaim_humongous_time_ms;
   }
+
+  ReferenceProcessorPhaseTimes* ref_phase_times() { return &_ref_phase_times; }
 };
 
 class G1GCParPhaseTimesTracker : public StackObj {
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -149,13 +149,16 @@
     assert(rp == g1h->ref_processor_stw(), "Sanity");
 
     rp->setup_policy(clear_all_softrefs);
+    ReferenceProcessorPhaseTimes pt(gc_timer(), rp->num_q());
+
     const ReferenceProcessorStats& stats =
         rp->process_discovered_references(&GenMarkSweep::is_alive,
                                           &GenMarkSweep::keep_alive,
                                           &GenMarkSweep::follow_stack_closure,
                                           NULL,
-                                          gc_timer());
+                                          &pt);
     gc_tracer()->report_gc_reference_stats(stats);
+    pt.print_all_references();
   }
 
   // This is the point where the entire marking should have completed.
--- a/hotspot/src/share/vm/gc/g1/workerDataArray.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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/g1/workerDataArray.inline.hpp"
-#include "utilities/ostream.hpp"
-
-template <>
-size_t WorkerDataArray<size_t>::uninitialized() {
-  return (size_t)-1;
-}
-
-template <>
-double WorkerDataArray<double>::uninitialized() {
-  return -1.0;
-}
-
-template <>
-void WorkerDataArray<double>::WDAPrinter::summary(outputStream* out, double min, double avg, double max, double diff, double sum, bool print_sum) {
-  out->print(" Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS);
-  if (print_sum) {
-    out->print(", Sum: %4.1lf", sum * MILLIUNITS);
-  }
-}
-
-template <>
-void WorkerDataArray<size_t>::WDAPrinter::summary(outputStream* out, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum) {
-  out->print(" Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT, min, avg, max, diff);
-  if (print_sum) {
-    out->print(", Sum: " SIZE_FORMAT, sum);
-  }
-}
-
-template <>
-void WorkerDataArray<double>::WDAPrinter::details(const WorkerDataArray<double>* phase, outputStream* out) {
-  out->print("%-25s", "");
-  for (uint i = 0; i < phase->_length; ++i) {
-    double value = phase->get(i);
-    if (value != phase->uninitialized()) {
-      out->print(" %4.1lf", phase->get(i) * 1000.0);
-    } else {
-      out->print(" -");
-    }
-  }
-  out->cr();
-}
-
-template <>
-void WorkerDataArray<size_t>::WDAPrinter::details(const WorkerDataArray<size_t>* phase, outputStream* out) {
-  out->print("%-25s", "");
-  for (uint i = 0; i < phase->_length; ++i) {
-    size_t value = phase->get(i);
-    if (value != phase->uninitialized()) {
-      out->print("  " SIZE_FORMAT, phase->get(i));
-    } else {
-      out->print(" -");
-    }
-  }
-  out->cr();
-}
--- a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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_G1_WORKERDATAARRAY_HPP
-#define SHARE_VM_GC_G1_WORKERDATAARRAY_HPP
-
-#include "memory/allocation.hpp"
-#include "utilities/debug.hpp"
-
-class outputStream;
-
-template <class T>
-class WorkerDataArray  : public CHeapObj<mtGC> {
-  friend class WDAPrinter;
-public:
-  static const uint MaxThreadWorkItems = 3;
-private:
-  T*          _data;
-  uint        _length;
-  const char* _title;
-
-  WorkerDataArray<size_t>* _thread_work_items[MaxThreadWorkItems];
-
- public:
-  WorkerDataArray(uint length, const char* title);
-  ~WorkerDataArray();
-
-  void link_thread_work_items(WorkerDataArray<size_t>* thread_work_items, uint index = 0);
-  void set_thread_work_item(uint worker_i, size_t value, uint index = 0);
-  void add_thread_work_item(uint worker_i, size_t value, uint index = 0);
-  WorkerDataArray<size_t>* thread_work_items(uint index = 0) const {
-    assert(index < MaxThreadWorkItems, "Tried to access thread work item %u max %u", index, MaxThreadWorkItems);
-    return _thread_work_items[index];
-  }
-
-  static T uninitialized();
-
-  void set(uint worker_i, T value);
-  T get(uint worker_i) const;
-
-  void add(uint worker_i, T value);
-
-  // The sum() and average() methods below consider uninitialized slots to be 0.
-  double average() const;
-  T sum() const;
-
-  const char* title() const {
-    return _title;
-  }
-
-  void reset();
-  void set_all(T value);
-
-
- private:
-  class WDAPrinter {
-  public:
-    static void summary(outputStream* out, double min, double avg, double max, double diff, double sum, bool print_sum);
-    static void summary(outputStream* out, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum);
-
-    static void details(const WorkerDataArray<double>* phase, outputStream* out);
-    static void details(const WorkerDataArray<size_t>* phase, outputStream* out);
-  };
-
- public:
-  void print_summary_on(outputStream* out, bool print_sum = true) const;
-  void print_details_on(outputStream* out) const;
-};
-
-#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_HPP
--- a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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_G1_WORKERDATAARRAY_INLINE_HPP
-#define SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP
-
-#include "gc/g1/workerDataArray.hpp"
-#include "memory/allocation.inline.hpp"
-#include "utilities/ostream.hpp"
-
-template <typename T>
-WorkerDataArray<T>::WorkerDataArray(uint length, const char* title) :
- _title(title),
- _length(0) {
-  assert(length > 0, "Must have some workers to store data for");
-  _length = length;
-  _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
-  for (uint i = 0; i < MaxThreadWorkItems; i++) {
-    _thread_work_items[i] = NULL;
-  }
-  reset();
-}
-
-template <typename T>
-void WorkerDataArray<T>::set(uint worker_i, T value) {
-  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
-  assert(_data[worker_i] == uninitialized(), "Overwriting data for worker %d in %s", worker_i, _title);
-  _data[worker_i] = value;
-}
-
-template <typename T>
-T WorkerDataArray<T>::get(uint worker_i) const {
-  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
-  return _data[worker_i];
-}
-
-template <typename T>
-WorkerDataArray<T>::~WorkerDataArray() {
-  FREE_C_HEAP_ARRAY(T, _data);
-}
-
-template <typename T>
-void WorkerDataArray<T>::link_thread_work_items(WorkerDataArray<size_t>* thread_work_items, uint index) {
-  assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems);
-  _thread_work_items[index] = thread_work_items;
-}
-
-template <typename T>
-void WorkerDataArray<T>::set_thread_work_item(uint worker_i, size_t value, uint index) {
-  assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems);
-  assert(_thread_work_items[index] != NULL, "No sub count");
-  _thread_work_items[index]->set(worker_i, value);
-}
-
-template <typename T>
-void WorkerDataArray<T>::add_thread_work_item(uint worker_i, size_t value, uint index) {
-  assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems);
-  assert(_thread_work_items[index] != NULL, "No sub count");
-  _thread_work_items[index]->add(worker_i, value);
-}
-
-template <typename T>
-void WorkerDataArray<T>::add(uint worker_i, T value) {
-  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
-  assert(_data[worker_i] != uninitialized(), "No data to add to for worker %d", worker_i);
-  _data[worker_i] += value;
-}
-
-template <typename T>
-double WorkerDataArray<T>::average() const {
-  uint contributing_threads = 0;
-  for (uint i = 0; i < _length; ++i) {
-    if (get(i) != uninitialized()) {
-      contributing_threads++;
-    }
-  }
-  if (contributing_threads == 0) {
-    return 0.0;
-  }
-  return sum() / (double) contributing_threads;
-}
-
-template <typename T>
-T WorkerDataArray<T>::sum() const {
-  T s = 0;
-  for (uint i = 0; i < _length; ++i) {
-    if (get(i) != uninitialized()) {
-      s += get(i);
-    }
-  }
-  return s;
-}
-
-template <typename T>
-void WorkerDataArray<T>::set_all(T value) {
-  for (uint i = 0; i < _length; i++) {
-    _data[i] = value;
-  }
-}
-
-template <class T>
-void WorkerDataArray<T>::print_summary_on(outputStream* out, bool print_sum) const {
-  out->print("%-25s", title());
-  uint start = 0;
-  while (start < _length && get(start) == uninitialized()) {
-    start++;
-  }
-  if (start < _length) {
-    T min = get(start);
-    T max = min;
-    T sum = 0;
-    uint contributing_threads = 0;
-    for (uint i = start; i < _length; ++i) {
-      T value = get(i);
-      if (value != uninitialized()) {
-        max = MAX2(max, value);
-        min = MIN2(min, value);
-        sum += value;
-        contributing_threads++;
-      }
-    }
-    T diff = max - min;
-    assert(contributing_threads != 0, "Must be since we found a used value for the start index");
-    double avg = sum / (double) contributing_threads;
-    WDAPrinter::summary(out, min, avg, max, diff, sum, print_sum);
-    out->print_cr(", Workers: %d", contributing_threads);
-  } else {
-    // No data for this phase.
-    out->print_cr(" skipped");
-  }
-}
-
-template <class T>
-void WorkerDataArray<T>::print_details_on(outputStream* out) const {
-  WDAPrinter::details(this, out);
-}
-
-template <typename T>
-void WorkerDataArray<T>::reset() {
-  set_all(uninitialized());
-  for (uint i = 0; i < MaxThreadWorkItems; i++) {
-    if (_thread_work_items[i] != NULL) {
-      _thread_work_items[i]->reset();
-    }
-  }
-}
-
-#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -254,7 +254,11 @@
     DerivedPointerTable::update_pointers();
 #endif
 
-    ref_processor()->enqueue_discovered_references(NULL);
+    ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->num_q());
+
+    ref_processor()->enqueue_discovered_references(NULL, &pt);
+
+    pt.print_enqueue_phase();
 
     // Update time of last GC
     reset_millis_since_last_gc();
@@ -528,10 +532,12 @@
     GCTraceTime(Debug, gc, phases) t("Reference Processing", _gc_timer);
 
     ref_processor()->setup_policy(clear_all_softrefs);
+    ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->num_q());
     const ReferenceProcessorStats& stats =
       ref_processor()->process_discovered_references(
-        is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, _gc_timer);
+        is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, &pt);
     gc_tracer()->report_gc_reference_stats(stats);
+    pt.print_all_references();
   }
 
   // This is the point where the entire marking should have completed.
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1041,7 +1041,11 @@
   DerivedPointerTable::update_pointers();
 #endif
 
-  ref_processor()->enqueue_discovered_references(NULL);
+  ReferenceProcessorPhaseTimes pt(&_gc_timer, ref_processor()->num_q());
+
+  ref_processor()->enqueue_discovered_references(NULL, &pt);
+
+  pt.print_enqueue_phase();
 
   if (ZapUnusedHeapArea) {
     heap->gen_mangle_unused_area();
@@ -2103,18 +2107,20 @@
     GCTraceTime(Debug, gc, phases) tm("Reference Processing", &_gc_timer);
 
     ReferenceProcessorStats stats;
+    ReferenceProcessorPhaseTimes pt(&_gc_timer, ref_processor()->num_q());
     if (ref_processor()->processing_is_mt()) {
       RefProcTaskExecutor task_executor;
       stats = ref_processor()->process_discovered_references(
         is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
-        &task_executor, &_gc_timer);
+        &task_executor, &pt);
     } else {
       stats = ref_processor()->process_discovered_references(
         is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL,
-        &_gc_timer);
+        &pt);
     }
 
     gc_tracer->report_gc_reference_stats(stats);
+    pt.print_all_references();
   }
 
   // This is the point where the entire marking should have completed.
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -415,25 +415,29 @@
       PSKeepAliveClosure keep_alive(promotion_manager);
       PSEvacuateFollowersClosure evac_followers(promotion_manager);
       ReferenceProcessorStats stats;
+      ReferenceProcessorPhaseTimes pt(&_gc_timer, reference_processor()->num_q());
       if (reference_processor()->processing_is_mt()) {
         PSRefProcTaskExecutor task_executor;
         stats = reference_processor()->process_discovered_references(
           &_is_alive_closure, &keep_alive, &evac_followers, &task_executor,
-          &_gc_timer);
+          &pt);
       } else {
         stats = reference_processor()->process_discovered_references(
-          &_is_alive_closure, &keep_alive, &evac_followers, NULL, &_gc_timer);
+          &_is_alive_closure, &keep_alive, &evac_followers, NULL, &pt);
       }
 
       _gc_tracer.report_gc_reference_stats(stats);
+      pt.print_all_references();
 
       // Enqueue reference objects discovered during scavenge.
       if (reference_processor()->processing_is_mt()) {
         PSRefProcTaskExecutor task_executor;
-        reference_processor()->enqueue_discovered_references(&task_executor);
+        reference_processor()->enqueue_discovered_references(&task_executor, &pt);
       } else {
-        reference_processor()->enqueue_discovered_references(NULL);
+        reference_processor()->enqueue_discovered_references(NULL, &pt);
       }
+
+      pt.print_enqueue_phase();
     }
 
     {
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -661,11 +661,13 @@
   FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
   ReferenceProcessor* rp = ref_processor();
   rp->setup_policy(clear_all_soft_refs);
+  ReferenceProcessorPhaseTimes pt(_gc_timer, rp->num_q());
   const ReferenceProcessorStats& stats =
   rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
-                                    NULL, _gc_timer);
+                                    NULL, &pt);
   gc_tracer.report_gc_reference_stats(stats);
   gc_tracer.report_tenuring_threshold(tenuring_threshold());
+  pt.print_all_references();
 
   if (!_promotion_failed) {
     // Swap the survivor spaces.
--- a/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -210,9 +210,11 @@
     GCTraceTime(Debug, gc, phases) tm_m("Reference Processing", gc_timer());
 
     ref_processor()->setup_policy(clear_all_softrefs);
+    ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->num_q());
     const ReferenceProcessorStats& stats =
       ref_processor()->process_discovered_references(
-        &is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer);
+        &is_alive, &keep_alive, &follow_stack_closure, NULL, &pt);
+    pt.print_all_references();
     gc_tracer()->report_gc_reference_stats(stats);
   }
 
--- a/hotspot/src/share/vm/gc/shared/gcTimer.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/gcTimer.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -78,8 +78,8 @@
 
 class PhasesStack {
  public:
-  // Set to 5, since Reference processing needs it.
-  static const int PHASE_LEVELS = 5;
+  // Set to 6, since Reference processing needs it.
+  static const int PHASE_LEVELS = 6;
 
  private:
   int _phase_indices[PHASE_LEVELS];
--- a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -428,6 +428,7 @@
       case 1: send_phase<EventGCPhasePauseLevel1>(phase); break;
       case 2: send_phase<EventGCPhasePauseLevel2>(phase); break;
       case 3: send_phase<EventGCPhasePauseLevel3>(phase); break;
+      case 4: send_phase<EventGCPhasePauseLevel4>(phase); break;
       default: /* Ignore sending this phase */ break;
     }
   }
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -387,7 +387,9 @@
     }
     gen->collect(full, clear_soft_refs, size, is_tlab);
     if (!rp->enqueuing_is_done()) {
-      rp->enqueue_discovered_references();
+      ReferenceProcessorPhaseTimes pt(NULL, rp->num_q());
+      rp->enqueue_discovered_references(NULL, &pt);
+      pt.print_enqueue_phase();
     } else {
       rp->set_enqueuing_is_done(false);
     }
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -179,7 +179,7 @@
   // past clock value.
 }
 
-size_t ReferenceProcessor::total_count(DiscoveredList lists[]) {
+size_t ReferenceProcessor::total_count(DiscoveredList lists[]) const {
   size_t total = 0;
   for (uint i = 0; i < _max_num_q; ++i) {
     total += lists[i].length();
@@ -188,11 +188,13 @@
 }
 
 ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
-  BoolObjectClosure*           is_alive,
-  OopClosure*                  keep_alive,
-  VoidClosure*                 complete_gc,
-  AbstractRefProcTaskExecutor* task_executor,
-  GCTimer*                     gc_timer) {
+  BoolObjectClosure*            is_alive,
+  OopClosure*                   keep_alive,
+  VoidClosure*                  complete_gc,
+  AbstractRefProcTaskExecutor*  task_executor,
+  ReferenceProcessorPhaseTimes* phase_times) {
+
+  double start_time = os::elapsedTime();
 
   assert(!enqueuing_is_done(), "If here enqueuing should not be complete");
   // Stop treating discovered references specially.
@@ -208,40 +210,39 @@
 
   _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock();
 
-  ReferenceProcessorStats stats(
-      total_count(_discoveredSoftRefs),
-      total_count(_discoveredWeakRefs),
-      total_count(_discoveredFinalRefs),
-      total_count(_discoveredPhantomRefs));
+  ReferenceProcessorStats stats(total_count(_discoveredSoftRefs),
+                                total_count(_discoveredWeakRefs),
+                                total_count(_discoveredFinalRefs),
+                                total_count(_discoveredPhantomRefs));
 
   // Soft references
   {
-    GCTraceTime(Debug, gc, ref) tt("SoftReference", gc_timer);
+    RefProcPhaseTimesTracker tt(REF_SOFT, phase_times, this);
     process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, phase_times);
   }
 
   update_soft_ref_master_clock();
 
   // Weak references
   {
-    GCTraceTime(Debug, gc, ref) tt("WeakReference", gc_timer);
+    RefProcPhaseTimesTracker tt(REF_WEAK, phase_times, this);
     process_discovered_reflist(_discoveredWeakRefs, NULL, true,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, phase_times);
   }
 
   // Final references
   {
-    GCTraceTime(Debug, gc, ref) tt("FinalReference", gc_timer);
+    RefProcPhaseTimesTracker tt(REF_FINAL, phase_times, this);
     process_discovered_reflist(_discoveredFinalRefs, NULL, false,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, phase_times);
   }
 
   // Phantom references
   {
-    GCTraceTime(Debug, gc, ref) tt("PhantomReference", gc_timer);
+    RefProcPhaseTimesTracker tt(REF_PHANTOM, phase_times, this);
     process_discovered_reflist(_discoveredPhantomRefs, NULL, true,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, phase_times);
   }
 
   // Weak global JNI references. It would make more sense (semantically) to
@@ -250,15 +251,15 @@
   // thus use JNI weak references to circumvent the phantom references and
   // resurrect a "post-mortem" object.
   {
-    GCTraceTime(Debug, gc, ref) tt("JNI Weak Reference", gc_timer);
+    GCTraceTime(Debug, gc, ref) tt("JNI Weak Reference", phase_times->gc_timer());
     if (task_executor != NULL) {
       task_executor->set_single_threaded_mode();
     }
     process_phaseJNI(is_alive, keep_alive, complete_gc);
   }
 
-  log_debug(gc, ref)("Ref Counts: Soft: " SIZE_FORMAT " Weak: " SIZE_FORMAT " Final: " SIZE_FORMAT " Phantom: " SIZE_FORMAT,
-                     stats.soft_count(), stats.weak_count(), stats.final_count(), stats.phantom_count());
+  phase_times->set_total_time_ms((os::elapsedTime() - start_time) * 1000);
+
   log_develop_trace(gc, ref)("JNI Weak Reference count: " SIZE_FORMAT, count_jni_refs());
 
   return stats;
@@ -289,10 +290,11 @@
   complete_gc->do_void();
 }
 
-void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) {
+void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor*  task_executor,
+                                                       ReferenceProcessorPhaseTimes* phase_times) {
   // Enqueue references that are not made active again, and
   // clear the decks for the next collection (cycle).
-  enqueue_discovered_reflists(task_executor);
+  enqueue_discovered_reflists(task_executor, phase_times);
 
   // Stop treating discovered references specially.
   disable_discovery();
@@ -343,13 +345,16 @@
 // Parallel enqueue task
 class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask {
 public:
-  RefProcEnqueueTask(ReferenceProcessor& ref_processor,
-                     DiscoveredList      discovered_refs[],
-                     int                 n_queues)
-    : EnqueueTask(ref_processor, discovered_refs, n_queues)
+  RefProcEnqueueTask(ReferenceProcessor&           ref_processor,
+                     DiscoveredList                discovered_refs[],
+                     int                           n_queues,
+                     ReferenceProcessorPhaseTimes* phase_times)
+    : EnqueueTask(ref_processor, discovered_refs, n_queues, phase_times)
   { }
 
   virtual void work(unsigned int work_id) {
+    RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefEnqueue, _phase_times, work_id);
+
     assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds");
     // Simplest first cut: static partitioning.
     int index = work_id;
@@ -369,10 +374,19 @@
 };
 
 // Enqueue references that are not made active again
-void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor) {
+void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor*  task_executor,
+                                                     ReferenceProcessorPhaseTimes* phase_times) {
+
+  ReferenceProcessorStats stats(total_count(_discoveredSoftRefs),
+                                total_count(_discoveredWeakRefs),
+                                total_count(_discoveredFinalRefs),
+                                total_count(_discoveredPhantomRefs));
+
+  RefProcEnqueueTimeTracker tt(phase_times, stats);
+
   if (_processing_is_mt && task_executor != NULL) {
     // Parallel code
-    RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q);
+    RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q, phase_times);
     task_executor->execute(tsk);
   } else {
     // Serial code: call the parent class's implementation
@@ -469,7 +483,7 @@
   complete_gc->do_void();
   log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " dead Refs out of " SIZE_FORMAT " discovered Refs by policy, from list " INTPTR_FORMAT,
                              iter.removed(), iter.processed(), p2i(&refs_list));
-    }
+}
 
 // Traverse the list and remove any Refs that are not active, or
 // whose referents are either alive or NULL.
@@ -598,19 +612,46 @@
   }
 }
 
+size_t ReferenceProcessor::total_reference_count(ReferenceType type) const {
+  DiscoveredList* list = NULL;
+
+  switch (type) {
+    case REF_SOFT:
+      list = _discoveredSoftRefs;
+      break;
+    case REF_WEAK:
+      list = _discoveredWeakRefs;
+      break;
+    case REF_FINAL:
+      list = _discoveredFinalRefs;
+      break;
+    case REF_PHANTOM:
+      list = _discoveredPhantomRefs;
+      break;
+    case REF_OTHER:
+    case REF_NONE:
+    default:
+      ShouldNotReachHere();
+  }
+  return total_count(list);
+}
+
 class RefProcPhase1Task: public AbstractRefProcTaskExecutor::ProcessTask {
 public:
-  RefProcPhase1Task(ReferenceProcessor& ref_processor,
-                    DiscoveredList      refs_lists[],
-                    ReferencePolicy*    policy,
-                    bool                marks_oops_alive)
-    : ProcessTask(ref_processor, refs_lists, marks_oops_alive),
+  RefProcPhase1Task(ReferenceProcessor&           ref_processor,
+                    DiscoveredList                refs_lists[],
+                    ReferencePolicy*              policy,
+                    bool                          marks_oops_alive,
+                    ReferenceProcessorPhaseTimes* phase_times)
+    : ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times),
       _policy(policy)
   { }
   virtual void work(unsigned int i, BoolObjectClosure& is_alive,
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
+    RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase1, _phase_times, i);
+
     _ref_processor.process_phase1(_refs_lists[i], _policy,
                                   &is_alive, &keep_alive, &complete_gc);
   }
@@ -620,15 +661,18 @@
 
 class RefProcPhase2Task: public AbstractRefProcTaskExecutor::ProcessTask {
 public:
-  RefProcPhase2Task(ReferenceProcessor& ref_processor,
-                    DiscoveredList      refs_lists[],
-                    bool                marks_oops_alive)
-    : ProcessTask(ref_processor, refs_lists, marks_oops_alive)
+  RefProcPhase2Task(ReferenceProcessor&           ref_processor,
+                    DiscoveredList                refs_lists[],
+                    bool                          marks_oops_alive,
+                    ReferenceProcessorPhaseTimes* phase_times)
+    : ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times)
   { }
   virtual void work(unsigned int i, BoolObjectClosure& is_alive,
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
+    RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase2, _phase_times, i);
+
     _ref_processor.process_phase2(_refs_lists[i],
                                   &is_alive, &keep_alive, &complete_gc);
   }
@@ -636,17 +680,20 @@
 
 class RefProcPhase3Task: public AbstractRefProcTaskExecutor::ProcessTask {
 public:
-  RefProcPhase3Task(ReferenceProcessor& ref_processor,
-                    DiscoveredList      refs_lists[],
-                    bool                clear_referent,
-                    bool                marks_oops_alive)
-    : ProcessTask(ref_processor, refs_lists, marks_oops_alive),
+  RefProcPhase3Task(ReferenceProcessor&           ref_processor,
+                    DiscoveredList                refs_lists[],
+                    bool                         clear_referent,
+                    bool                          marks_oops_alive,
+                    ReferenceProcessorPhaseTimes* phase_times)
+    : ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times),
       _clear_referent(clear_referent)
   { }
   virtual void work(unsigned int i, BoolObjectClosure& is_alive,
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
+    RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase3, _phase_times, i);
+
     _ref_processor.process_phase3(_refs_lists[i], _clear_referent,
                                   &is_alive, &keep_alive, &complete_gc);
   }
@@ -770,15 +817,19 @@
 }
 
 void ReferenceProcessor::process_discovered_reflist(
-  DiscoveredList               refs_lists[],
-  ReferencePolicy*             policy,
-  bool                         clear_referent,
-  BoolObjectClosure*           is_alive,
-  OopClosure*                  keep_alive,
-  VoidClosure*                 complete_gc,
-  AbstractRefProcTaskExecutor* task_executor)
+  DiscoveredList                refs_lists[],
+  ReferencePolicy*              policy,
+  bool                          clear_referent,
+  BoolObjectClosure*            is_alive,
+  OopClosure*                   keep_alive,
+  VoidClosure*                  complete_gc,
+  AbstractRefProcTaskExecutor*  task_executor,
+  ReferenceProcessorPhaseTimes* phase_times)
 {
   bool mt_processing = task_executor != NULL && _processing_is_mt;
+
+  phase_times->set_processing_is_mt(mt_processing);
+
   // If discovery used MT and a dynamic number of GC threads, then
   // the queues must be balanced for correctness if fewer than the
   // maximum number of queues were used.  The number of queue used
@@ -789,6 +840,7 @@
 
   if ((mt_processing && ParallelRefProcBalancingEnabled) ||
       must_balance) {
+    RefProcBalanceQueuesTimeTracker tt(phase_times);
     balance_queues(refs_lists);
   }
 
@@ -798,8 +850,10 @@
   //   policy reasons. Keep alive the transitive closure of all
   //   such referents.
   if (policy != NULL) {
+    RefProcParPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase1, phase_times);
+
     if (mt_processing) {
-      RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
+      RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/, phase_times);
       task_executor->execute(phase1);
     } else {
       for (uint i = 0; i < _max_num_q; i++) {
@@ -814,24 +868,32 @@
 
   // Phase 2:
   // . Traverse the list and remove any refs whose referents are alive.
-  if (mt_processing) {
-    RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
-    task_executor->execute(phase2);
-  } else {
-    for (uint i = 0; i < _max_num_q; i++) {
-      process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
+  {
+    RefProcParPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase2, phase_times);
+
+    if (mt_processing) {
+      RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/, phase_times);
+      task_executor->execute(phase2);
+    } else {
+      for (uint i = 0; i < _max_num_q; i++) {
+        process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
+      }
     }
   }
 
   // Phase 3:
   // . Traverse the list and process referents as appropriate.
-  if (mt_processing) {
-    RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
-    task_executor->execute(phase3);
-  } else {
-    for (uint i = 0; i < _max_num_q; i++) {
-      process_phase3(refs_lists[i], clear_referent,
-                     is_alive, keep_alive, complete_gc);
+  {
+    RefProcParPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase3, phase_times);
+
+    if (mt_processing) {
+      RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/, phase_times);
+      task_executor->execute(phase3);
+    } else {
+      for (uint i = 0; i < _max_num_q; i++) {
+        process_phase3(refs_lists[i], clear_referent,
+                       is_alive, keep_alive, complete_gc);
+      }
     }
   }
 }
@@ -1196,4 +1258,3 @@
    ShouldNotReachHere();
    return NULL;
 }
-
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
 
 #include "gc/shared/referencePolicy.hpp"
+#include "gc/shared/referenceProcessorPhaseTimes.hpp"
 #include "gc/shared/referenceProcessorStats.hpp"
 #include "memory/referenceType.hpp"
 #include "oops/instanceRefKlass.hpp"
@@ -168,7 +169,7 @@
 class ReferenceProcessor : public CHeapObj<mtGC> {
 
  private:
-  size_t total_count(DiscoveredList lists[]);
+  size_t total_count(DiscoveredList lists[]) const;
 
  protected:
   // The SoftReference master timestamp clock
@@ -236,13 +237,14 @@
   }
 
   // Process references with a certain reachability level.
-  void process_discovered_reflist(DiscoveredList               refs_lists[],
-                                  ReferencePolicy*             policy,
-                                  bool                         clear_referent,
-                                  BoolObjectClosure*           is_alive,
-                                  OopClosure*                  keep_alive,
-                                  VoidClosure*                 complete_gc,
-                                  AbstractRefProcTaskExecutor* task_executor);
+  void process_discovered_reflist(DiscoveredList                refs_lists[],
+                                  ReferencePolicy*              policy,
+                                  bool                          clear_referent,
+                                  BoolObjectClosure*            is_alive,
+                                  OopClosure*                   keep_alive,
+                                  VoidClosure*                  complete_gc,
+                                  AbstractRefProcTaskExecutor*  task_executor,
+                                  ReferenceProcessorPhaseTimes* phase_times);
 
   void process_phaseJNI(BoolObjectClosure* is_alive,
                         OopClosure*        keep_alive,
@@ -310,7 +312,8 @@
   // occupying the i / _num_q slot.
   const char* list_name(uint i);
 
-  void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor);
+  void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor,
+                                   ReferenceProcessorPhaseTimes* phase_times);
 
  protected:
   // "Preclean" the given discovered reference list
@@ -416,20 +419,23 @@
 
   // Process references found during GC (called by the garbage collector)
   ReferenceProcessorStats
-  process_discovered_references(BoolObjectClosure*           is_alive,
-                                OopClosure*                  keep_alive,
-                                VoidClosure*                 complete_gc,
-                                AbstractRefProcTaskExecutor* task_executor,
-                                GCTimer *gc_timer);
+  process_discovered_references(BoolObjectClosure*            is_alive,
+                                OopClosure*                   keep_alive,
+                                VoidClosure*                  complete_gc,
+                                AbstractRefProcTaskExecutor*  task_executor,
+                                ReferenceProcessorPhaseTimes* phase_times);
 
   // Enqueue references at end of GC (called by the garbage collector)
-  void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL);
+  void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor,
+                                     ReferenceProcessorPhaseTimes* phase_times);
 
   // If a discovery is in process that is being superceded, abandon it: all
   // the discovered lists will be empty, and all the objects on them will
   // have NULL discovered fields.  Must be called only at a safepoint.
   void abandon_partial_discovery();
 
+  size_t total_reference_count(ReferenceType rt) const;
+
   // debugging
   void verify_no_references_recorded() PRODUCT_RETURN;
   void verify_referent(oop obj)        PRODUCT_RETURN;
@@ -584,11 +590,13 @@
 // Abstract reference processing task to execute.
 class AbstractRefProcTaskExecutor::ProcessTask {
 protected:
-  ProcessTask(ReferenceProcessor& ref_processor,
-              DiscoveredList      refs_lists[],
-              bool                marks_oops_alive)
+  ProcessTask(ReferenceProcessor&           ref_processor,
+              DiscoveredList                refs_lists[],
+              bool                          marks_oops_alive,
+              ReferenceProcessorPhaseTimes* phase_times)
     : _ref_processor(ref_processor),
       _refs_lists(refs_lists),
+      _phase_times(phase_times),
       _marks_oops_alive(marks_oops_alive)
   { }
 
@@ -602,29 +610,33 @@
   { return _marks_oops_alive; }
 
 protected:
-  ReferenceProcessor& _ref_processor;
-  DiscoveredList*     _refs_lists;
-  const bool          _marks_oops_alive;
+  ReferenceProcessor&           _ref_processor;
+  DiscoveredList*               _refs_lists;
+  ReferenceProcessorPhaseTimes* _phase_times;
+  const bool                    _marks_oops_alive;
 };
 
 // Abstract reference processing task to execute.
 class AbstractRefProcTaskExecutor::EnqueueTask {
 protected:
-  EnqueueTask(ReferenceProcessor& ref_processor,
-              DiscoveredList      refs_lists[],
-              int                 n_queues)
+  EnqueueTask(ReferenceProcessor&           ref_processor,
+              DiscoveredList                refs_lists[],
+              int                           n_queues,
+              ReferenceProcessorPhaseTimes* phase_times)
     : _ref_processor(ref_processor),
       _refs_lists(refs_lists),
-      _n_queues(n_queues)
+      _n_queues(n_queues),
+      _phase_times(phase_times)
   { }
 
 public:
   virtual void work(unsigned int work_id) = 0;
 
 protected:
-  ReferenceProcessor& _ref_processor;
-  DiscoveredList*     _refs_lists;
-  int                 _n_queues;
+  ReferenceProcessor&           _ref_processor;
+  DiscoveredList*               _refs_lists;
+  ReferenceProcessorPhaseTimes* _phase_times;
+  int                           _n_queues;
 };
 
 #endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessorPhaseTimes.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2017, 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/shared/gcTimer.hpp"
+#include "gc/shared/referenceProcessorPhaseTimes.hpp"
+#include "gc/shared/referenceProcessor.inline.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
+
+RefProcWorkerTimeTracker::RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers number,
+                                                   ReferenceProcessorPhaseTimes* phase_times,
+                                                   uint worker_id) :
+  _worker_time(NULL), _start_time(os::elapsedTime()), _worker_id(worker_id) {
+  assert (phase_times != NULL, "Invariant");
+
+  _worker_time = phase_times->worker_time_sec(phase_times->par_phase(number));
+}
+
+RefProcWorkerTimeTracker::RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcParPhases phase,
+                                                   ReferenceProcessorPhaseTimes* phase_times,
+                                                   uint worker_id) :
+  _worker_time(NULL), _start_time(os::elapsedTime()), _worker_id(worker_id) {
+  assert (phase_times != NULL, "Invariant");
+
+  _worker_time = phase_times->worker_time_sec(phase);
+}
+
+RefProcWorkerTimeTracker::~RefProcWorkerTimeTracker() {
+  _worker_time->set(_worker_id, os::elapsedTime() - _start_time);
+}
+
+RefProcPhaseTimeBaseTracker::RefProcPhaseTimeBaseTracker(const char* title,
+                                                         ReferenceProcessorPhaseTimes* phase_times) :
+  _title(title), _phase_times(phase_times), _start_ticks(), _end_ticks() {
+  assert(_phase_times != NULL, "Invariant");
+
+  _start_ticks.stamp();
+  if (_phase_times->gc_timer() != NULL) {
+    _phase_times->gc_timer()->register_gc_phase_start(_title, _start_ticks);
+  }
+}
+
+static const char* phase_enum_2_phase_string(ReferenceProcessorPhaseTimes::RefProcParPhases phase) {
+  switch(phase) {
+    case ReferenceProcessorPhaseTimes::SoftRefPhase1:
+      return "Phase1";
+    case ReferenceProcessorPhaseTimes::SoftRefPhase2:
+    case ReferenceProcessorPhaseTimes::WeakRefPhase2:
+    case ReferenceProcessorPhaseTimes::FinalRefPhase2:
+    case ReferenceProcessorPhaseTimes::PhantomRefPhase2:
+      return "Phase2";
+    case ReferenceProcessorPhaseTimes::SoftRefPhase3:
+    case ReferenceProcessorPhaseTimes::WeakRefPhase3:
+    case ReferenceProcessorPhaseTimes::FinalRefPhase3:
+    case ReferenceProcessorPhaseTimes::PhantomRefPhase3:
+      return "Phase3";
+    case ReferenceProcessorPhaseTimes::RefEnqueue:
+      return "Reference Enqueuing";
+    default:
+      ShouldNotReachHere();
+      return NULL;
+  }
+}
+
+static const char* Indents[6] = {"", "  ", "    ", "      ", "        ", "          "};
+
+Ticks RefProcPhaseTimeBaseTracker::end_ticks() {
+  // If ASSERT is defined, the default value of Ticks will be -2.
+  if (_end_ticks.value() <= 0) {
+    _end_ticks.stamp();
+  }
+
+  return _end_ticks;
+}
+
+double RefProcPhaseTimeBaseTracker::elapsed_time() {
+  jlong end_value = end_ticks().value();
+
+  return TimeHelper::counter_to_millis(end_value - _start_ticks.value());
+}
+
+RefProcPhaseTimeBaseTracker::~RefProcPhaseTimeBaseTracker() {
+  if (_phase_times->gc_timer() != NULL) {
+    Ticks ticks = end_ticks();
+    _phase_times->gc_timer()->register_gc_phase_end(ticks);
+  }
+}
+
+RefProcBalanceQueuesTimeTracker::RefProcBalanceQueuesTimeTracker(ReferenceProcessorPhaseTimes* phase_times) :
+  RefProcPhaseTimeBaseTracker("Balance queues", phase_times) {}
+
+RefProcBalanceQueuesTimeTracker::~RefProcBalanceQueuesTimeTracker() {
+  double elapsed = elapsed_time();
+  phase_times()->set_balance_queues_time_ms(phase_times()->processing_ref_type(), elapsed);
+}
+
+#define ASSERT_REF_TYPE(ref_type) assert(ref_type >= REF_SOFT && ref_type <= REF_PHANTOM, \
+                                         "Invariant (%d)", (int)ref_type)
+
+#define ASSERT_PHASE_NUMBER(phase_number) assert(phase_number >= ReferenceProcessorPhaseTimes::RefPhase1 && \
+                                                 phase_number <= ReferenceProcessorPhaseTimes::RefPhaseMax, \
+                                                 "Invariant (%d)", phase_number);
+
+static const char* phase_number_2_string(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers phase_number) {
+  ASSERT_PHASE_NUMBER(phase_number);
+
+  switch(phase_number) {
+    case ReferenceProcessorPhaseTimes::RefPhase1:
+      return "Phase1";
+    case ReferenceProcessorPhaseTimes::RefPhase2:
+      return "Phase2";
+    case ReferenceProcessorPhaseTimes::RefPhase3:
+      return "Phase3";
+    default:
+      ShouldNotReachHere();
+      return NULL;
+  }
+}
+
+RefProcParPhaseTimeTracker::RefProcParPhaseTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers phase_number,
+                                                       ReferenceProcessorPhaseTimes* phase_times) :
+  _phase_number(phase_number),
+  RefProcPhaseTimeBaseTracker(phase_number_2_string(phase_number), phase_times) {}
+
+RefProcParPhaseTimeTracker::~RefProcParPhaseTimeTracker() {
+  double elapsed = elapsed_time();
+  ReferenceProcessorPhaseTimes::RefProcParPhases phase = phase_times()->par_phase(_phase_number);
+  phase_times()->set_par_phase_time_ms(phase, elapsed);
+}
+
+static const char* ref_type_2_string(ReferenceType ref_type) {
+  ASSERT_REF_TYPE(ref_type);
+
+  switch(ref_type) {
+    case REF_SOFT:
+      return "SoftReference";
+    case REF_WEAK:
+      return "WeakReference";
+    case REF_FINAL:
+      return "FinalReference";
+    case REF_PHANTOM:
+      return "PhantomReference";
+    default:
+      ShouldNotReachHere();
+      return NULL;
+  }
+}
+
+RefProcPhaseTimesTracker::RefProcPhaseTimesTracker(ReferenceType ref_type,
+                                                   ReferenceProcessorPhaseTimes* phase_times,
+                                                   ReferenceProcessor* rp) :
+  _rp(rp), RefProcPhaseTimeBaseTracker(ref_type_2_string(ref_type), phase_times) {
+  phase_times->set_processing_ref_type(ref_type);
+
+  size_t discovered = rp->total_reference_count(ref_type);
+  phase_times->set_ref_discovered(ref_type, discovered);
+}
+
+RefProcPhaseTimesTracker::~RefProcPhaseTimesTracker() {
+  double elapsed = elapsed_time();
+  ReferenceProcessorPhaseTimes* times = phase_times();
+  ReferenceType ref_type = times->processing_ref_type();
+  times->set_ref_proc_time_ms(ref_type, elapsed);
+
+  size_t after_count = _rp->total_reference_count(ref_type);
+  size_t discovered = times->ref_discovered(ref_type);
+  times->set_ref_cleared(ref_type, discovered - after_count);
+}
+
+RefProcEnqueueTimeTracker::RefProcEnqueueTimeTracker(ReferenceProcessorPhaseTimes* phase_times,
+                                                     ReferenceProcessorStats& stats) :
+  RefProcPhaseTimeBaseTracker("Reference Enqueuing", phase_times) {
+    phase_times->set_ref_enqueued(REF_SOFT, stats.soft_count());
+    phase_times->set_ref_enqueued(REF_WEAK, stats.weak_count());
+    phase_times->set_ref_enqueued(REF_FINAL, stats.final_count());
+    phase_times->set_ref_enqueued(REF_PHANTOM, stats.phantom_count());
+}
+
+RefProcEnqueueTimeTracker::~RefProcEnqueueTimeTracker() {
+  double elapsed = elapsed_time();
+
+  phase_times()->set_par_phase_time_ms(ReferenceProcessorPhaseTimes::RefEnqueue, elapsed);
+}
+
+ReferenceProcessorPhaseTimes::ReferenceProcessorPhaseTimes(GCTimer* gc_timer, uint max_gc_threads) :
+  _gc_timer(gc_timer), _processing_is_mt(false) {
+
+  for (int i = 0; i < RefParPhaseMax; i++) {
+    _worker_time_sec[i] = new WorkerDataArray<double>(max_gc_threads, "Process lists (ms)");
+    _par_phase_time_ms[i] = uninitialized();
+  }
+
+  for (int i = 0; i < number_of_subclasses_of_ref; i++) {
+    _ref_proc_time_ms[i] = uninitialized();
+    _balance_queues_time_ms[i] = uninitialized();
+    _ref_cleared[i] = 0;
+    _ref_discovered[i] = 0;
+    _ref_enqueued[i] = 0;
+  }
+}
+
+inline int ref_type_2_index(ReferenceType ref_type) {
+  return ref_type - REF_SOFT;
+}
+
+#define ASSERT_PAR_PHASE(phase) assert(phase >= ReferenceProcessorPhaseTimes::SoftRefPhase1 && \
+                                       phase < ReferenceProcessorPhaseTimes::RefParPhaseMax, \
+                                       "Invariant (%d)", (int)phase);
+
+WorkerDataArray<double>* ReferenceProcessorPhaseTimes::worker_time_sec(RefProcParPhases par_phase) const {
+  ASSERT_PAR_PHASE(par_phase);
+  return _worker_time_sec[par_phase];
+}
+
+double ReferenceProcessorPhaseTimes::par_phase_time_ms(RefProcParPhases par_phase) const {
+  ASSERT_PAR_PHASE(par_phase);
+  return _par_phase_time_ms[par_phase];
+}
+
+void ReferenceProcessorPhaseTimes::set_par_phase_time_ms(RefProcParPhases par_phase,
+                                                         double par_phase_time_ms) {
+  ASSERT_PAR_PHASE(par_phase);
+  _par_phase_time_ms[par_phase] = par_phase_time_ms;
+}
+
+void ReferenceProcessorPhaseTimes::reset() {
+  for (int i = 0; i < RefParPhaseMax; i++) {
+    _worker_time_sec[i]->reset();
+    _par_phase_time_ms[i] = uninitialized();
+  }
+
+  for (int i = 0; i < number_of_subclasses_of_ref; i++) {
+    _ref_proc_time_ms[i] = uninitialized();
+    _balance_queues_time_ms[i] = uninitialized();
+    _ref_cleared[i] = 0;
+    _ref_discovered[i] = 0;
+    _ref_enqueued[i] = 0;
+  }
+
+  _total_time_ms = uninitialized();
+
+  _processing_is_mt = false;
+}
+
+ReferenceProcessorPhaseTimes::~ReferenceProcessorPhaseTimes() {
+  for (int i = 0; i < RefParPhaseMax; i++) {
+    delete _worker_time_sec[i];
+  }
+}
+
+double ReferenceProcessorPhaseTimes::ref_proc_time_ms(ReferenceType ref_type) const {
+  ASSERT_REF_TYPE(ref_type);
+  return _par_phase_time_ms[ref_type_2_index(ref_type)];
+}
+
+void ReferenceProcessorPhaseTimes::set_ref_proc_time_ms(ReferenceType ref_type,
+                                                        double ref_proc_time_ms) {
+  ASSERT_REF_TYPE(ref_type);
+  _ref_proc_time_ms[ref_type_2_index(ref_type)] = ref_proc_time_ms;
+}
+
+size_t ReferenceProcessorPhaseTimes::ref_cleared(ReferenceType ref_type) const {
+  ASSERT_REF_TYPE(ref_type);
+  return _ref_cleared[ref_type_2_index(ref_type)];
+}
+
+void ReferenceProcessorPhaseTimes::set_ref_cleared(ReferenceType ref_type, size_t count) {
+  ASSERT_REF_TYPE(ref_type);
+  _ref_cleared[ref_type_2_index(ref_type)] = count;
+}
+
+size_t ReferenceProcessorPhaseTimes::ref_discovered(ReferenceType ref_type) const {
+  ASSERT_REF_TYPE(ref_type);
+  return _ref_discovered[ref_type_2_index(ref_type)];
+}
+
+void ReferenceProcessorPhaseTimes::set_ref_discovered(ReferenceType ref_type, size_t count) {
+  ASSERT_REF_TYPE(ref_type);
+  _ref_discovered[ref_type_2_index(ref_type)] = count;
+}
+
+size_t ReferenceProcessorPhaseTimes::ref_enqueued(ReferenceType ref_type) const {
+  ASSERT_REF_TYPE(ref_type);
+  return _ref_enqueued[ref_type_2_index(ref_type)];
+}
+
+void ReferenceProcessorPhaseTimes::set_ref_enqueued(ReferenceType ref_type, size_t count) {
+  ASSERT_REF_TYPE(ref_type);
+  _ref_enqueued[ref_type_2_index(ref_type)] = count;
+}
+
+double ReferenceProcessorPhaseTimes::balance_queues_time_ms(ReferenceType ref_type) const {
+  ASSERT_REF_TYPE(ref_type);
+  return _balance_queues_time_ms[ref_type_2_index(ref_type)];
+}
+
+void ReferenceProcessorPhaseTimes::set_balance_queues_time_ms(ReferenceType ref_type, double time_ms) {
+  ASSERT_REF_TYPE(ref_type);
+  _balance_queues_time_ms[ref_type_2_index(ref_type)] = time_ms;
+}
+
+ReferenceProcessorPhaseTimes::RefProcParPhases
+ReferenceProcessorPhaseTimes::par_phase(RefProcPhaseNumbers phase_number) const {
+  ASSERT_PHASE_NUMBER(phase_number);
+  ASSERT_REF_TYPE(_processing_ref_type);
+
+  int result = SoftRefPhase1;
+
+  switch(_processing_ref_type) {
+    case REF_SOFT:
+      result = (int)SoftRefPhase1;
+      result += phase_number;
+
+      assert((RefProcParPhases)result >= SoftRefPhase1 &&
+             (RefProcParPhases)result <= SoftRefPhase3,
+             "Invariant (%d)", result);
+      break;
+    case REF_WEAK:
+      result = (int)WeakRefPhase2;
+      result += (phase_number - 1);
+      assert((RefProcParPhases)result >= WeakRefPhase2 &&
+             (RefProcParPhases)result <= WeakRefPhase3,
+             "Invariant (%d)", result);
+      break;
+    case REF_FINAL:
+      result = (int)FinalRefPhase2;
+      result += (phase_number - 1);
+      assert((RefProcParPhases)result >= FinalRefPhase2 &&
+             (RefProcParPhases)result <= FinalRefPhase3,
+             "Invariant (%d)", result);
+      break;
+    case REF_PHANTOM:
+      result = (int)PhantomRefPhase2;
+      result += (phase_number - 1);
+      assert((RefProcParPhases)result >= PhantomRefPhase2 &&
+             (RefProcParPhases)result <= PhantomRefPhase3,
+             "Invariant (%d)", result);
+      break;
+    default:
+      ShouldNotReachHere();
+  }
+
+  ASSERT_PAR_PHASE(result);
+
+  return (RefProcParPhases)result;
+}
+
+void ReferenceProcessorPhaseTimes::print_enqueue_phase(uint base_indent, bool print_total) const {
+  if (print_total) {
+    print_phase(RefEnqueue, base_indent);
+  }
+
+  log_debug(gc, phases, ref)("%sReference Counts:  Soft: " SIZE_FORMAT "  Weak: " SIZE_FORMAT
+                             "  Final: " SIZE_FORMAT "  Phantom: " SIZE_FORMAT ,
+                             Indents[base_indent + 1], ref_enqueued(REF_SOFT), ref_enqueued(REF_WEAK),
+                             ref_enqueued(REF_FINAL), ref_enqueued(REF_PHANTOM));
+}
+
+#define TIME_FORMAT "%.1lfms"
+
+void ReferenceProcessorPhaseTimes::print_all_references(uint base_indent, bool print_total) const {
+  if (print_total) {
+    LogTarget(Debug, gc, phases, ref) lt;
+
+    if (lt.is_enabled()) {
+      LogStream ls(lt);
+      ls.print_cr("%s%s: " TIME_FORMAT,
+                  Indents[base_indent], "Reference Processing", total_time_ms());
+    }
+  }
+
+  uint next_indent = base_indent + 1;
+  print_reference(REF_SOFT, next_indent);
+  print_reference(REF_WEAK, next_indent);
+  print_reference(REF_FINAL, next_indent);
+  print_reference(REF_PHANTOM, next_indent);
+}
+
+void ReferenceProcessorPhaseTimes::print_reference(ReferenceType ref_type, uint base_indent) const {
+  LogTarget(Debug, gc, phases, ref) lt;
+
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    uint next_indent = base_indent + 1;
+    ResourceMark rm;
+
+    ls.print_cr("%s%s: " TIME_FORMAT,
+                Indents[base_indent], ref_type_2_string(ref_type), ref_proc_time_ms(ref_type));
+
+    double balance_time = balance_queues_time_ms(ref_type);
+    if (balance_time != uninitialized()) {
+      ls.print_cr("%s%s " TIME_FORMAT, Indents[next_indent], "Balance queues:", balance_time);
+    }
+
+    switch(ref_type) {
+      case REF_SOFT:
+        print_phase(SoftRefPhase1, next_indent);
+        print_phase(SoftRefPhase2, next_indent);
+        print_phase(SoftRefPhase3, next_indent);
+        break;
+
+      case REF_WEAK:
+        print_phase(WeakRefPhase2, next_indent);
+        print_phase(WeakRefPhase3, next_indent);
+        break;
+
+      case REF_FINAL:
+        print_phase(FinalRefPhase2, next_indent);
+        print_phase(FinalRefPhase3, next_indent);
+        break;
+
+      case REF_PHANTOM:
+        print_phase(PhantomRefPhase2, next_indent);
+        print_phase(PhantomRefPhase3, next_indent);
+        break;
+
+      default:
+        ShouldNotReachHere();
+    }
+
+    ls.print_cr("%s%s " SIZE_FORMAT, Indents[next_indent], "Discovered:", ref_discovered(ref_type));
+    ls.print_cr("%s%s " SIZE_FORMAT, Indents[next_indent], "Cleared:", ref_cleared(ref_type));
+  }
+}
+
+void ReferenceProcessorPhaseTimes::print_phase(RefProcParPhases phase, uint indent) const {
+  double phase_time = par_phase_time_ms(phase);
+  if (phase_time != uninitialized()) {
+    LogTarget(Debug, gc, phases, ref) lt;
+
+    LogStream ls(lt);
+
+    ls.print_cr("%s%s%s " TIME_FORMAT,
+                Indents[indent],
+                phase_enum_2_phase_string(phase),
+                indent == 0 ? "" : ":", /* 0 indent logs don't need colon. */
+                phase_time);
+
+    LogTarget(Trace, gc, phases, ref) lt2;
+    if (_processing_is_mt && lt2.is_enabled()) {
+      LogStream ls(lt2);
+
+      ls.print("%s", Indents[indent + 1]);
+      // worker_time_sec is recorded in seconds but it will be printed in milliseconds.
+      worker_time_sec(phase)->print_summary_on(&ls, true);
+    }
+  }
+}
+
+#undef ASSERT_REF_TYPE
+#undef ASSERT_PHASE_NUMBER
+#undef ASSERT_PAR_PHASE
+#undef TIME_FORMAT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessorPhaseTimes.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2017, 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_SHARED_REFERENCEPROCESSORPHASETIMES_HPP
+#define SHARE_VM_GC_SHARED_REFERENCEPROCESSORPHASETIMES_HPP
+
+#include "gc/shared/referenceProcessorStats.hpp"
+#include "gc/shared/workerDataArray.inline.hpp"
+#include "memory/referenceType.hpp"
+#include "utilities/ticks.hpp"
+
+class DiscoveredList;
+class GCTimer;
+
+class ReferenceProcessorPhaseTimes : public CHeapObj<mtGC> {
+public:
+  // Detailed phases that has parallel work.
+  enum RefProcParPhases {
+    SoftRefPhase1,
+    SoftRefPhase2,
+    SoftRefPhase3,
+    WeakRefPhase2,
+    WeakRefPhase3,
+    FinalRefPhase2,
+    FinalRefPhase3,
+    PhantomRefPhase2,
+    PhantomRefPhase3,
+    RefEnqueue,
+    RefParPhaseMax
+  };
+
+  // Sub-phases that are used when processing each j.l.Reference types.
+  // Only SoftReference has RefPhase1.
+  enum RefProcPhaseNumbers {
+    RefPhase1,
+    RefPhase2,
+    RefPhase3,
+    RefPhaseMax
+  };
+
+private:
+  static const int number_of_subclasses_of_ref = REF_PHANTOM - REF_OTHER; // 5 - 1 = 4
+
+  // Records per thread information of each phase.
+  WorkerDataArray<double>* _worker_time_sec[RefParPhaseMax];
+  // Records elapsed time of each phase.
+  double                   _par_phase_time_ms[RefParPhaseMax];
+
+  // Total spent time for references.
+  // e.g. _ref_proc_time_ms[0] = _par_phase_time_ms[SoftRefPhase1] +
+  //                             _par_phase_time_ms[SoftRefPhase2] +
+  //                             _par_phase_time_ms[SoftRefPhase3] + extra time.
+  double                   _ref_proc_time_ms[number_of_subclasses_of_ref];
+
+  double                   _total_time_ms;
+
+  size_t                   _ref_cleared[number_of_subclasses_of_ref];
+  size_t                   _ref_discovered[number_of_subclasses_of_ref];
+  size_t                   _ref_enqueued[number_of_subclasses_of_ref];
+  double                   _balance_queues_time_ms[number_of_subclasses_of_ref];
+
+  bool                     _processing_is_mt;
+
+  // Currently processing reference type.
+  ReferenceType            _processing_ref_type;
+
+  GCTimer*                 _gc_timer;
+
+  double par_phase_time_ms(RefProcParPhases phase) const;
+  double ref_proc_time_ms(ReferenceType ref_type) const;
+
+  double total_time_ms() const { return _total_time_ms; }
+
+  size_t ref_cleared(ReferenceType ref_type) const;
+  size_t ref_enqueued(ReferenceType ref_type) const;
+
+  double balance_queues_time_ms(ReferenceType ref_type) const;
+
+  void print_reference(ReferenceType ref_type, uint base_indent) const;
+  void print_phase(RefProcParPhases phase, uint indent) const;
+
+public:
+  ReferenceProcessorPhaseTimes(GCTimer* gc_timer, uint max_gc_threads);
+  ~ReferenceProcessorPhaseTimes();
+
+  static double uninitialized() { return -1.0; }
+
+  WorkerDataArray<double>* worker_time_sec(RefProcParPhases phase) const;
+  void set_par_phase_time_ms(RefProcParPhases phase, double par_phase_time_ms);
+
+  void set_ref_proc_time_ms(ReferenceType ref_type, double ref_proc_time_ms);
+
+  void set_total_time_ms(double total_time_ms) { _total_time_ms = total_time_ms; }
+
+  void set_ref_cleared(ReferenceType ref_type, size_t count);
+  size_t ref_discovered(ReferenceType ref_type) const;
+  void set_ref_discovered(ReferenceType ref_type, size_t count);
+  void set_ref_enqueued(ReferenceType ref_type, size_t count);
+
+  void set_balance_queues_time_ms(ReferenceType ref_type, double time_ms);
+
+  void set_processing_is_mt(bool processing_is_mt) { _processing_is_mt = processing_is_mt; }
+
+  ReferenceType processing_ref_type() const { return _processing_ref_type; }
+  void set_processing_ref_type(ReferenceType processing_ref_type) { _processing_ref_type = processing_ref_type; }
+
+  // Returns RefProcParPhases calculated from phase_number and _processing_ref_type.
+  RefProcParPhases par_phase(RefProcPhaseNumbers phase_number) const;
+
+  GCTimer* gc_timer() const { return _gc_timer; }
+
+  // Reset all fields. If not reset at next cycle, an assertion will fail.
+  void reset();
+
+  void print_enqueue_phase(uint base_indent = 0, bool print_total = true) const;
+  void print_all_references(uint base_indent = 0, bool print_total = true) const;
+};
+
+// Updates working time of each worker thread.
+class RefProcWorkerTimeTracker : public StackObj {
+protected:
+  WorkerDataArray<double>* _worker_time;
+  double                   _start_time;
+  uint                     _worker_id;
+
+public:
+  RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers number,
+                           ReferenceProcessorPhaseTimes* phase_times,
+                           uint worker_id);
+  RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcParPhases phase,
+                           ReferenceProcessorPhaseTimes* phase_times,
+                           uint worker_id);
+  ~RefProcWorkerTimeTracker();
+};
+
+class RefProcPhaseTimeBaseTracker : public StackObj {
+protected:
+  const char*                   _title;
+  ReferenceProcessorPhaseTimes* _phase_times;
+  Ticks                         _start_ticks;
+  Ticks                         _end_ticks;
+
+  Ticks end_ticks();
+  double elapsed_time();
+  ReferenceProcessorPhaseTimes* phase_times() const { return _phase_times; }
+  // Print phase elapsed time with each worker information if MT processed.
+  void print_phase(ReferenceProcessorPhaseTimes::RefProcParPhases phase, uint indent);
+
+public:
+  RefProcPhaseTimeBaseTracker(const char* title,
+                              ReferenceProcessorPhaseTimes* phase_times);
+  ~RefProcPhaseTimeBaseTracker();
+};
+
+// Updates queue balance time at ReferenceProcessorPhaseTimes and
+// save it into GCTimer.
+class RefProcBalanceQueuesTimeTracker : public RefProcPhaseTimeBaseTracker {
+public:
+  RefProcBalanceQueuesTimeTracker(ReferenceProcessorPhaseTimes* phase_times);
+  ~RefProcBalanceQueuesTimeTracker();
+};
+
+// Updates phase time at ReferenceProcessorPhaseTimes and save it into GCTimer.
+class RefProcParPhaseTimeTracker : public RefProcPhaseTimeBaseTracker {
+  ReferenceProcessorPhaseTimes::RefProcPhaseNumbers _phase_number;
+
+public:
+  RefProcParPhaseTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers phase_number,
+                             ReferenceProcessorPhaseTimes* phase_times);
+  ~RefProcParPhaseTimeTracker();
+};
+
+// Updates phase time related information.
+// - Each phase processing time, cleared/discovered reference counts and stats for each working threads if MT processed.
+class RefProcPhaseTimesTracker : public RefProcPhaseTimeBaseTracker {
+  ReferenceProcessor* _rp;
+
+public:
+  RefProcPhaseTimesTracker(ReferenceType ref_type,
+                           ReferenceProcessorPhaseTimes* phase_times,
+                           ReferenceProcessor* rp);
+  ~RefProcPhaseTimesTracker();
+};
+
+// Updates enqueue time related information.
+// - Enqueueing time, enqueued reference count and stats for each working thread if MT processed.
+class RefProcEnqueueTimeTracker : public RefProcPhaseTimeBaseTracker {
+public:
+  RefProcEnqueueTimeTracker(ReferenceProcessorPhaseTimes* phase_times,
+                            ReferenceProcessorStats& stats);
+  ~RefProcEnqueueTimeTracker();
+};
+
+#endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSORPHASETIMES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/workerDataArray.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2017, 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/shared/workerDataArray.inline.hpp"
+#include "utilities/ostream.hpp"
+
+template <>
+size_t WorkerDataArray<size_t>::uninitialized() {
+  return (size_t)-1;
+}
+
+template <>
+double WorkerDataArray<double>::uninitialized() {
+  return -1.0;
+}
+
+template <>
+void WorkerDataArray<double>::WDAPrinter::summary(outputStream* out, double min, double avg, double max, double diff, double sum, bool print_sum) {
+  out->print(" Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS);
+  if (print_sum) {
+    out->print(", Sum: %4.1lf", sum * MILLIUNITS);
+  }
+}
+
+template <>
+void WorkerDataArray<size_t>::WDAPrinter::summary(outputStream* out, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum) {
+  out->print(" Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT, min, avg, max, diff);
+  if (print_sum) {
+    out->print(", Sum: " SIZE_FORMAT, sum);
+  }
+}
+
+template <>
+void WorkerDataArray<double>::WDAPrinter::details(const WorkerDataArray<double>* phase, outputStream* out) {
+  out->print("%-25s", "");
+  for (uint i = 0; i < phase->_length; ++i) {
+    double value = phase->get(i);
+    if (value != phase->uninitialized()) {
+      out->print(" %4.1lf", phase->get(i) * 1000.0);
+    } else {
+      out->print(" -");
+    }
+  }
+  out->cr();
+}
+
+template <>
+void WorkerDataArray<size_t>::WDAPrinter::details(const WorkerDataArray<size_t>* phase, outputStream* out) {
+  out->print("%-25s", "");
+  for (uint i = 0; i < phase->_length; ++i) {
+    size_t value = phase->get(i);
+    if (value != phase->uninitialized()) {
+      out->print("  " SIZE_FORMAT, phase->get(i));
+    } else {
+      out->print(" -");
+    }
+  }
+  out->cr();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/workerDataArray.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 2017, 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_SHARED_WORKERDATAARRAY_HPP
+#define SHARE_VM_GC_SHARED_WORKERDATAARRAY_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+class outputStream;
+
+template <class T>
+class WorkerDataArray  : public CHeapObj<mtGC> {
+  friend class WDAPrinter;
+public:
+  static const uint MaxThreadWorkItems = 3;
+private:
+  T*          _data;
+  uint        _length;
+  const char* _title;
+
+  WorkerDataArray<size_t>* _thread_work_items[MaxThreadWorkItems];
+
+ public:
+  WorkerDataArray(uint length, const char* title);
+  ~WorkerDataArray();
+
+  void link_thread_work_items(WorkerDataArray<size_t>* thread_work_items, uint index = 0);
+  void set_thread_work_item(uint worker_i, size_t value, uint index = 0);
+  void add_thread_work_item(uint worker_i, size_t value, uint index = 0);
+  WorkerDataArray<size_t>* thread_work_items(uint index = 0) const {
+    assert(index < MaxThreadWorkItems, "Tried to access thread work item %u max %u", index, MaxThreadWorkItems);
+    return _thread_work_items[index];
+  }
+
+  static T uninitialized();
+
+  void set(uint worker_i, T value);
+  T get(uint worker_i) const;
+
+  void add(uint worker_i, T value);
+
+  // The sum() and average() methods below consider uninitialized slots to be 0.
+  double average() const;
+  T sum() const;
+
+  const char* title() const {
+    return _title;
+  }
+
+  void reset();
+  void set_all(T value);
+
+
+ private:
+  class WDAPrinter {
+  public:
+    static void summary(outputStream* out, double min, double avg, double max, double diff, double sum, bool print_sum);
+    static void summary(outputStream* out, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum);
+
+    static void details(const WorkerDataArray<double>* phase, outputStream* out);
+    static void details(const WorkerDataArray<size_t>* phase, outputStream* out);
+  };
+
+ public:
+  void print_summary_on(outputStream* out, bool print_sum = true) const;
+  void print_details_on(outputStream* out) const;
+};
+
+#endif // SHARE_VM_GC_SHARED_WORKERDATAARRAY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/workerDataArray.inline.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015, 2017, 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_SHARED_WORKERDATAARRAY_INLINE_HPP
+#define SHARE_VM_GC_SHARED_WORKERDATAARRAY_INLINE_HPP
+
+#include "gc/shared/workerDataArray.hpp"
+#include "memory/allocation.inline.hpp"
+#include "utilities/ostream.hpp"
+
+template <typename T>
+WorkerDataArray<T>::WorkerDataArray(uint length, const char* title) :
+ _title(title),
+ _length(0) {
+  assert(length > 0, "Must have some workers to store data for");
+  _length = length;
+  _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
+  for (uint i = 0; i < MaxThreadWorkItems; i++) {
+    _thread_work_items[i] = NULL;
+  }
+  reset();
+}
+
+template <typename T>
+void WorkerDataArray<T>::set(uint worker_i, T value) {
+  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
+  assert(_data[worker_i] == uninitialized(), "Overwriting data for worker %d in %s", worker_i, _title);
+  _data[worker_i] = value;
+}
+
+template <typename T>
+T WorkerDataArray<T>::get(uint worker_i) const {
+  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
+  return _data[worker_i];
+}
+
+template <typename T>
+WorkerDataArray<T>::~WorkerDataArray() {
+  FREE_C_HEAP_ARRAY(T, _data);
+}
+
+template <typename T>
+void WorkerDataArray<T>::link_thread_work_items(WorkerDataArray<size_t>* thread_work_items, uint index) {
+  assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems);
+  _thread_work_items[index] = thread_work_items;
+}
+
+template <typename T>
+void WorkerDataArray<T>::set_thread_work_item(uint worker_i, size_t value, uint index) {
+  assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems);
+  assert(_thread_work_items[index] != NULL, "No sub count");
+  _thread_work_items[index]->set(worker_i, value);
+}
+
+template <typename T>
+void WorkerDataArray<T>::add_thread_work_item(uint worker_i, size_t value, uint index) {
+  assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems);
+  assert(_thread_work_items[index] != NULL, "No sub count");
+  _thread_work_items[index]->add(worker_i, value);
+}
+
+template <typename T>
+void WorkerDataArray<T>::add(uint worker_i, T value) {
+  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
+  assert(_data[worker_i] != uninitialized(), "No data to add to for worker %d", worker_i);
+  _data[worker_i] += value;
+}
+
+template <typename T>
+double WorkerDataArray<T>::average() const {
+  uint contributing_threads = 0;
+  for (uint i = 0; i < _length; ++i) {
+    if (get(i) != uninitialized()) {
+      contributing_threads++;
+    }
+  }
+  if (contributing_threads == 0) {
+    return 0.0;
+  }
+  return sum() / (double) contributing_threads;
+}
+
+template <typename T>
+T WorkerDataArray<T>::sum() const {
+  T s = 0;
+  for (uint i = 0; i < _length; ++i) {
+    if (get(i) != uninitialized()) {
+      s += get(i);
+    }
+  }
+  return s;
+}
+
+template <typename T>
+void WorkerDataArray<T>::set_all(T value) {
+  for (uint i = 0; i < _length; i++) {
+    _data[i] = value;
+  }
+}
+
+template <class T>
+void WorkerDataArray<T>::print_summary_on(outputStream* out, bool print_sum) const {
+  out->print("%-25s", title());
+  uint start = 0;
+  while (start < _length && get(start) == uninitialized()) {
+    start++;
+  }
+  if (start < _length) {
+    T min = get(start);
+    T max = min;
+    T sum = 0;
+    uint contributing_threads = 0;
+    for (uint i = start; i < _length; ++i) {
+      T value = get(i);
+      if (value != uninitialized()) {
+        max = MAX2(max, value);
+        min = MIN2(min, value);
+        sum += value;
+        contributing_threads++;
+      }
+    }
+    T diff = max - min;
+    assert(contributing_threads != 0, "Must be since we found a used value for the start index");
+    double avg = sum / (double) contributing_threads;
+    WDAPrinter::summary(out, min, avg, max, diff, sum, print_sum);
+    out->print_cr(", Workers: %d", contributing_threads);
+  } else {
+    // No data for this phase.
+    out->print_cr(" skipped");
+  }
+}
+
+template <class T>
+void WorkerDataArray<T>::print_details_on(outputStream* out) const {
+  WDAPrinter::details(this, out);
+}
+
+template <typename T>
+void WorkerDataArray<T>::reset() {
+  set_all(uninitialized());
+  for (uint i = 0; i < MaxThreadWorkItems; i++) {
+    if (_thread_work_items[i] != NULL) {
+      _thread_work_items[i]->reset();
+    }
+  }
+}
+
+#endif // SHARE_VM_GC_SHARED_WORKERDATAARRAY_INLINE_HPP
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -355,131 +355,124 @@
 
   int nof_jsrs = 0;
   bool has_monitor_bytecodes = false;
+  Bytecodes::Code c;
 
-  {
-    // We cannot tolerate a GC in this block, because we've
-    // cached the bytecodes in 'code_base'. If the Method*
-    // moves, the bytecodes will also move.
-    NoSafepointVerifier nsv;
-    Bytecodes::Code c;
+  // Bytecodes and their length
+  const address code_base = method->code_base();
+  const int code_length = method->code_size();
 
-    // Bytecodes and their length
-    const address code_base = method->code_base();
-    const int code_length = method->code_size();
+  int bc_length;
+  for (int bci = 0; bci < code_length; bci += bc_length) {
+    address bcp = code_base + bci;
+    int prefix_length = 0;
+    c = (Bytecodes::Code)(*bcp);
+
+    // Since we have the code, see if we can get the length
+    // directly. Some more complicated bytecodes will report
+    // a length of zero, meaning we need to make another method
+    // call to calculate the length.
+    bc_length = Bytecodes::length_for(c);
+    if (bc_length == 0) {
+      bc_length = Bytecodes::length_at(method, bcp);
 
-    int bc_length;
-    for (int bci = 0; bci < code_length; bci += bc_length) {
-      address bcp = code_base + bci;
-      int prefix_length = 0;
-      c = (Bytecodes::Code)(*bcp);
+      // length_at will put us at the bytecode after the one modified
+      // by 'wide'. We don't currently examine any of the bytecodes
+      // modified by wide, but in case we do in the future...
+      if (c == Bytecodes::_wide) {
+        prefix_length = 1;
+        c = (Bytecodes::Code)bcp[1];
+      }
+    }
+
+    assert(bc_length != 0, "impossible bytecode length");
 
-      // Since we have the code, see if we can get the length
-      // directly. Some more complicated bytecodes will report
-      // a length of zero, meaning we need to make another method
-      // call to calculate the length.
-      bc_length = Bytecodes::length_for(c);
-      if (bc_length == 0) {
-        bc_length = Bytecodes::length_at(method, bcp);
-
-        // length_at will put us at the bytecode after the one modified
-        // by 'wide'. We don't currently examine any of the bytecodes
-        // modified by wide, but in case we do in the future...
-        if (c == Bytecodes::_wide) {
-          prefix_length = 1;
-          c = (Bytecodes::Code)bcp[1];
-        }
+    switch (c) {
+      case Bytecodes::_lookupswitch   : {
+#ifndef CC_INTERP
+        Bytecode_lookupswitch bc(method, bcp);
+        (*bcp) = (
+          bc.number_of_pairs() < BinarySwitchThreshold
+          ? Bytecodes::_fast_linearswitch
+          : Bytecodes::_fast_binaryswitch
+        );
+#endif
+        break;
+      }
+      case Bytecodes::_fast_linearswitch:
+      case Bytecodes::_fast_binaryswitch: {
+#ifndef CC_INTERP
+        (*bcp) = Bytecodes::_lookupswitch;
+#endif
+        break;
       }
 
-      assert(bc_length != 0, "impossible bytecode length");
-
-      switch (c) {
-        case Bytecodes::_lookupswitch   : {
-#ifndef CC_INTERP
-          Bytecode_lookupswitch bc(method, bcp);
-          (*bcp) = (
-            bc.number_of_pairs() < BinarySwitchThreshold
-            ? Bytecodes::_fast_linearswitch
-            : Bytecodes::_fast_binaryswitch
-          );
-#endif
-          break;
-        }
-        case Bytecodes::_fast_linearswitch:
-        case Bytecodes::_fast_binaryswitch: {
-#ifndef CC_INTERP
-          (*bcp) = Bytecodes::_lookupswitch;
-#endif
-          break;
-        }
-
-        case Bytecodes::_invokespecial  : {
-          rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error);
-          break;
-        }
+      case Bytecodes::_invokespecial  : {
+        rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error);
+        break;
+      }
 
-        case Bytecodes::_putstatic      :
-        case Bytecodes::_putfield       : {
-          if (!reverse) {
-            // Check if any final field of the class given as parameter is modified
-            // outside of initializer methods of the class. Fields that are modified
-            // are marked with a flag. For marked fields, the compilers do not perform
-            // constant folding (as the field can be changed after initialization).
-            //
-            // The check is performed after verification and only if verification has
-            // succeeded. Therefore, the class is guaranteed to be well-formed.
-            InstanceKlass* klass = method->method_holder();
-            u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
-            constantPoolHandle cp(method->constants());
-            Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
+      case Bytecodes::_putstatic      :
+      case Bytecodes::_putfield       : {
+        if (!reverse) {
+          // Check if any final field of the class given as parameter is modified
+          // outside of initializer methods of the class. Fields that are modified
+          // are marked with a flag. For marked fields, the compilers do not perform
+          // constant folding (as the field can be changed after initialization).
+          //
+          // The check is performed after verification and only if verification has
+          // succeeded. Therefore, the class is guaranteed to be well-formed.
+          InstanceKlass* klass = method->method_holder();
+          u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
+          constantPoolHandle cp(method->constants());
+          Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
 
-            if (klass->name() == ref_class_name) {
-              Symbol* field_name = cp->name_ref_at(bc_index);
-              Symbol* field_sig = cp->signature_ref_at(bc_index);
+          if (klass->name() == ref_class_name) {
+            Symbol* field_name = cp->name_ref_at(bc_index);
+            Symbol* field_sig = cp->signature_ref_at(bc_index);
 
-              fieldDescriptor fd;
-              if (klass->find_field(field_name, field_sig, &fd) != NULL) {
-                if (fd.access_flags().is_final()) {
-                  if (fd.access_flags().is_static()) {
-                    if (!method->is_static_initializer()) {
-                      fd.set_has_initialized_final_update(true);
-                    }
-                  } else {
-                    if (!method->is_object_initializer()) {
-                      fd.set_has_initialized_final_update(true);
-                    }
+            fieldDescriptor fd;
+            if (klass->find_field(field_name, field_sig, &fd) != NULL) {
+              if (fd.access_flags().is_final()) {
+                if (fd.access_flags().is_static()) {
+                  if (!method->is_static_initializer()) {
+                    fd.set_has_initialized_final_update(true);
+                  }
+                } else {
+                  if (!method->is_object_initializer()) {
+                    fd.set_has_initialized_final_update(true);
                   }
                 }
               }
             }
           }
         }
-        // fall through
-        case Bytecodes::_getstatic      : // fall through
-        case Bytecodes::_getfield       : // fall through
-        case Bytecodes::_invokevirtual  : // fall through
-        case Bytecodes::_invokestatic   :
-        case Bytecodes::_invokeinterface:
-        case Bytecodes::_invokehandle   : // if reverse=true
-          rewrite_member_reference(bcp, prefix_length+1, reverse);
-          break;
-        case Bytecodes::_invokedynamic:
-          rewrite_invokedynamic(bcp, prefix_length+1, reverse);
-          break;
-        case Bytecodes::_ldc:
-        case Bytecodes::_fast_aldc:  // if reverse=true
-          maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse);
-          break;
-        case Bytecodes::_ldc_w:
-        case Bytecodes::_fast_aldc_w:  // if reverse=true
-          maybe_rewrite_ldc(bcp, prefix_length+1, true, reverse);
-          break;
-        case Bytecodes::_jsr            : // fall through
-        case Bytecodes::_jsr_w          : nof_jsrs++;                   break;
-        case Bytecodes::_monitorenter   : // fall through
-        case Bytecodes::_monitorexit    : has_monitor_bytecodes = true; break;
+      }
+      // fall through
+      case Bytecodes::_getstatic      : // fall through
+      case Bytecodes::_getfield       : // fall through
+      case Bytecodes::_invokevirtual  : // fall through
+      case Bytecodes::_invokestatic   :
+      case Bytecodes::_invokeinterface:
+      case Bytecodes::_invokehandle   : // if reverse=true
+        rewrite_member_reference(bcp, prefix_length+1, reverse);
+        break;
+      case Bytecodes::_invokedynamic:
+        rewrite_invokedynamic(bcp, prefix_length+1, reverse);
+        break;
+      case Bytecodes::_ldc:
+      case Bytecodes::_fast_aldc:  // if reverse=true
+        maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse);
+        break;
+      case Bytecodes::_ldc_w:
+      case Bytecodes::_fast_aldc_w:  // if reverse=true
+        maybe_rewrite_ldc(bcp, prefix_length+1, true, reverse);
+        break;
+      case Bytecodes::_jsr            : // fall through
+      case Bytecodes::_jsr_w          : nof_jsrs++;                   break;
+      case Bytecodes::_monitorenter   : // fall through
+      case Bytecodes::_monitorexit    : has_monitor_bytecodes = true; break;
 
-        default: break;
-      }
+      default: break;
     }
   }
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1365,8 +1365,8 @@
   ResourceMark rm;
 
   if (!thread->has_last_Java_frame()) return NULL;
-  Handle result = HotSpotStackFrameReference::klass()->allocate_instance_handle(thread);
-  HotSpotStackFrameReference::klass()->initialize(thread);
+  Handle result = HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
+  HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
 
   StackFrameStream fst(thread);
   if (hs_frame != NULL) {
@@ -1418,13 +1418,13 @@
             initialSkip --;
           } else {
             ScopeDesc* scope = cvf->scope();
-            // native wrapper do not have a scope
+            // native wrappers do not have a scope
             if (scope != NULL && scope->objects() != NULL) {
-              bool realloc_failures = Deoptimization::realloc_objects(thread, fst.current(), scope->objects(), THREAD);
+              bool realloc_failures = Deoptimization::realloc_objects(thread, fst.current(), scope->objects(), CHECK_NULL);
               Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false);
 
               GrowableArray<ScopeValue*>* local_values = scope->locals();
-              typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), thread);
+              typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), CHECK_NULL);
               typeArrayHandle array(THREAD, array_oop);
               for (int i = 0; i < local_values->length(); i++) {
                 ScopeValue* value = local_values->at(i);
@@ -1543,7 +1543,7 @@
     THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
   }
 
-  HotSpotStackFrameReference::klass()->initialize(thread);
+  HotSpotStackFrameReference::klass()->initialize(CHECK);
 
   // look for the given stack frame
   StackFrameStream fst(thread);
@@ -1601,7 +1601,7 @@
     return;
   }
 
-  bool realloc_failures = Deoptimization::realloc_objects(thread, fstAfterDeopt.current(), objects, THREAD);
+  bool realloc_failures = Deoptimization::realloc_objects(thread, fstAfterDeopt.current(), objects, CHECK);
   Deoptimization::reassign_fields(fstAfterDeopt.current(), fstAfterDeopt.register_map(), objects, realloc_failures, false);
 
   for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) {
--- a/hotspot/src/share/vm/logging/logPrefix.hpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/logging/logPrefix.hpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -66,6 +66,7 @@
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, metaspace)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, mmu)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases)) \
+  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, ref)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, start)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, task)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, plab)) \
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -1700,6 +1700,14 @@
   return StringTable::shared_string_ignored();
 WB_END
 
+WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env))
+#if INCLUDE_CDS
+  return true;
+#else
+  return false;
+#endif
+WB_END
+
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
     Symbol* signature_symbol) {
@@ -1993,6 +2001,7 @@
   {CC"isShared",           CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
   {CC"isSharedClass",      CC"(Ljava/lang/Class;)Z",  (void*)&WB_IsSharedClass },
   {CC"areSharedStringsIgnored",           CC"()Z",    (void*)&WB_AreSharedStringsIgnored },
+  {CC"isCDSIncludedInVmBuild",            CC"()Z",    (void*)&WB_IsCDSIncludedInVmBuild },
   {CC"clearInlineCaches0",  CC"(Z)V",                 (void*)&WB_ClearInlineCaches },
   {CC"addCompilerDirective",    CC"(Ljava/lang/String;)I",
                                                       (void*)&WB_AddCompilerDirective },
--- a/hotspot/src/share/vm/trace/traceevents.xml	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/src/share/vm/trace/traceevents.xml	Fri Aug 11 21:33:56 2017 +0000
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2017, 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
@@ -405,7 +405,7 @@
 
   <!-- Promotion events, Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. -->
   <event id="PromoteObjectInNewPLAB" path="vm/gc/detailed/object_promotion_in_new_PLAB" label="Promotion in new PLAB"
-         description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
+         description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
          has_thread="true" has_stacktrace="false" is_instant="true">
     <value type="UINT" field="gcId" label="GC Identifier" relation="GcId" description="Identifier signifying GC during which the object was promoted"/>
     <value type="CLASS" field="objectClass" label="Object Class" description="Class of promoted object"/>
@@ -414,9 +414,9 @@
     <value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
     <value type="BYTES64" field="plabSize" label="PLAB Size" description="Size of the allocated PLAB to which the object was copied"/>
   </event>
-  
+
   <event id="PromoteObjectOutsidePLAB" path="vm/gc/detailed/object_promotion_outside_PLAB" label="Promotion outside PLAB"
-         description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
+         description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
          has_thread="true" has_stacktrace="false" is_instant="true">
     <value type="UINT" field="gcId" label="GC Identifier" relation="GcId" description="Identifier signifying GC during which the object was promoted"/>
     <value type="CLASS" field="objectClass" label="Object Class" description="Class of promoted object"/>
@@ -463,6 +463,11 @@
     <value type="STRING" field="name" label="Name" />
   </event>
 
+  <event id="GCPhasePauseLevel4" path="vm/gc/phases/pause_level_4" label="GC Phase Pause Level 4" has_thread="true">
+    <value type="UINT" field="gcId" label="GC Identifier" relation="GcId"/>
+    <value type="STRING" field="name" label="Name" />
+  </event>
+
   <event id="GCPhaseConcurrent" path="vm/gc/phases/concurrent" label="GC Phase Concurrent" has_thread="true">
     <value type="UINT" field="gcId" label="GC Identifier" relation="GcId"/>
     <value type="STRING" field="name" label="Name" />
--- a/hotspot/test/ProblemList.txt	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/ProblemList.txt	Fri Aug 11 21:33:56 2017 +0000
@@ -125,7 +125,6 @@
 gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
 gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all
 gc/stress/gclocker/TestGCLockerWithG1.java 8179226 generic-all
-gc/stress/gclocker/TestGCLockerWithSerial.java 8180311 generic-all
 
 #############################################################################
 
--- a/hotspot/test/TEST.ROOT	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/TEST.ROOT	Fri Aug 11 21:33:56 2017 +0000
@@ -51,7 +51,8 @@
     vm.debug \
     vm.rtm.cpu \
     vm.rtm.os \
-    vm.aot
+    vm.aot \
+    vm.cds
 
 # Tests using jtreg 4.2 b07 features
 requiredVersion=4.2 b07
--- a/hotspot/test/gc/g1/TestGCLogMessages.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java	Fri Aug 11 21:33:56 2017 +0000
@@ -142,6 +142,9 @@
         // TLAB handling
         new LogMessageWithLevel("Prepare TLABs", Level.DEBUG),
         new LogMessageWithLevel("Resize TLABs", Level.DEBUG),
+        // Reference Processing
+        new LogMessageWithLevel("Reference Processing", Level.DEBUG),
+        new LogMessageWithLevel("Reference Enqueuing", Level.DEBUG),
 
         new LogMessageWithLevelC2OrJVMCIOnly("DerivedPointerTable Update", Level.DEBUG),
         new LogMessageWithLevel("Start New Collection Set", Level.DEBUG),
--- a/hotspot/test/gc/g1/TestSharedArchiveWithPreTouch.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/gc/g1/TestSharedArchiveWithPreTouch.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,13 +21,13 @@
  * questions.
  */
 
-/*
+/**
  * @test
  * @bug 8169703
  * @summary Verifies that dumping and loading a CDS archive succeeds with AlwaysPreTouch
  * @requires vm.gc.G1
- * @key gc
- * @key regression
+ * @key gc regression
+ * @requires vm.cds
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/hotspot/test/gc/logging/TestPrintReferences.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/gc/logging/TestPrintReferences.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,31 +31,73 @@
  *          java.management
  */
 
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
 
 public class TestPrintReferences {
   public static void main(String[] args) throws Exception {
-    ProcessBuilder pb_enabled =
-      ProcessTools.createJavaProcessBuilder("-Xlog:gc+ref=debug", "-Xmx10M", GCTest.class.getName());
+    ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder("-Xlog:gc+phases+ref=debug",
+                                                                      "-XX:+UseG1GC",
+                                                                      "-Xmx10M",
+                                                                      GCTest.class.getName());
     OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start());
 
-    String countRegex = "[0-9]+ refs";
+    String indent_4 = "    ";
+    String indent_6 = "      ";
+    String indent_8 = "        ";
+    String gcLogTimeRegex = ".* GC\\([0-9]+\\) ";
+    String countRegex = "[0-9]+";
     String timeRegex = "[0-9]+[.,][0-9]+ms";
+    String totalRegex = gcLogTimeRegex + indent_4 + "Reference Processing: " + timeRegex + "\n";
+    String balanceRegex = gcLogTimeRegex + indent_8 + "Balance queues: " + timeRegex + "\n";
+    String softRefRegex = gcLogTimeRegex + indent_6 + "SoftReference: " + timeRegex + "\n";
+    String weakRefRegex = gcLogTimeRegex + indent_6 + "WeakReference: " + timeRegex + "\n";
+    String finalRefRegex = gcLogTimeRegex + indent_6 + "FinalReference: " + timeRegex + "\n";
+    String phantomRefRegex = gcLogTimeRegex + indent_6 + "PhantomReference: " + timeRegex + "\n";
+    String refDetailRegex = gcLogTimeRegex + indent_8 + "Phase2: " + timeRegex + "\n" +
+                            gcLogTimeRegex + indent_8 + "Phase3: " + timeRegex + "\n" +
+                            gcLogTimeRegex + indent_8 + "Discovered: " + countRegex + "\n" +
+                            gcLogTimeRegex + indent_8 + "Cleared: " + countRegex + "\n";
+    String softRefDetailRegex = gcLogTimeRegex + indent_8 + "Phase1: " + timeRegex + "\n" + refDetailRegex;
+    String enqueueRegex = gcLogTimeRegex + indent_4 + "Reference Enqueuing: " + timeRegex + "\n";
+    String enqueueDetailRegex = gcLogTimeRegex + indent_6 + "Reference Counts:  Soft: " + countRegex +
+                                "  Weak: " + countRegex + "  Final: " + countRegex + "  Phantom: " + countRegex + "\n";
 
-    output.shouldMatch(".* GC\\([0-9]+\\) SoftReference " + timeRegex + "\n" +
-                       ".* GC\\([0-9]+\\) WeakReference " + timeRegex + "\n" +
-                       ".* GC\\([0-9]+\\) FinalReference " + timeRegex + "\n" +
-                       ".* GC\\([0-9]+\\) PhantomReference " + timeRegex + "\n" +
-                       ".* GC\\([0-9]+\\) JNI Weak Reference " + timeRegex + "\n" +
-                       ".* GC\\([0-9]+\\) Ref Counts: Soft: [0-9]+ Weak: [0-9]+ Final: [0-9]+ Phantom: [0-9]+\n");
+    output.shouldMatch(/* Total Reference processing time */
+                       totalRegex +
+                       /* SoftReference processing */
+                       softRefRegex + balanceRegex + softRefDetailRegex +
+                       /* WeakReference processing */
+                       weakRefRegex + balanceRegex + refDetailRegex +
+                       /* FinalReference processing */
+                       finalRefRegex + balanceRegex + refDetailRegex +
+                       /* PhantomReference processing */
+                       phantomRefRegex + balanceRegex + refDetailRegex +
+                       /* Total Enqueuing time */
+                       enqueueRegex +
+                         /* Enqueued Stats */
+                       enqueueDetailRegex
+                       );
 
     output.shouldHaveExitValue(0);
   }
 
   static class GCTest {
+    static final int M = 1024 * 1024;
+
     public static void main(String [] args) {
-      System.gc();
+
+      ArrayList arrSoftRefs = new ArrayList();
+
+      // Populate to triger GC and then Reference related logs will be printed.
+      for (int i = 0; i < 10; i++) {
+        byte[] tmp = new byte[M];
+
+        arrSoftRefs.add(new SoftReference(tmp));
+      }
     }
   }
 }
--- a/hotspot/test/gc/stress/gclocker/TestGCLockerWithSerial.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/gc/stress/gclocker/TestGCLockerWithSerial.java	Fri Aug 11 21:33:56 2017 +0000
@@ -26,6 +26,7 @@
  * @test TestGCLockerWithSerial
  * @key gc
  * @requires vm.gc.Serial
+ * @requires vm.flavor != "minimal"
  * @summary Stress Serial's GC locker by calling GetPrimitiveArrayCritical while concurrently filling up old gen.
  * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xmx1500m -Xmx1500m -XX:+UseSerialGC TestGCLockerWithSerial
  */
--- a/hotspot/test/native/gc/g1/test_workerDataArray.cpp	Fri Aug 11 23:29:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,307 +0,0 @@
-/*
- * Copyright (c) 2016, 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/g1/workerDataArray.inline.hpp"
-#include "memory/resourceArea.hpp"
-#include "unittest.hpp"
-#include "utilities/ostream.hpp"
-
-static const double epsilon = 0.0001;
-
-template<typename T>
-class WorkerDataArrayTest : public ::testing::Test {
- protected:
-  WorkerDataArrayTest() :
-    title("Test array"),
-    array(3, title),
-    sub_item_title("Sub item array"),
-    sub_item(3, sub_item_title) {
-
-    array.link_thread_work_items(&sub_item);
-  }
-
-  const char* print_summary() {
-    stringStream out;
-    array.print_summary_on(&out);
-    return out.as_string();
-  }
-
-  const char* print_details() {
-    stringStream out;
-    array.print_details_on(&out);
-    return out.as_string();
-  }
-
-  const char* print_expected_summary() {
-    return prepend_with(title, expected_summary());
-  }
-
-  const char* print_expected_details() {
-    return prepend_with("", expected_details());
-  }
-
-  // returns expected summary for array without uninitialized elements
-  // used it because string representation of double depends on locale
-  static const char* format_summary(
-    T min, double avg, T max, T diff, T sum, size_t workers);
-
-  const char* title;
-  WorkerDataArray<T> array;
-
-  const char* sub_item_title;
-  WorkerDataArray<size_t> sub_item;
-
- private:
-  virtual const char* expected_summary() = 0;
-  virtual const char* expected_details() = 0;
-
-  static const char* prepend_with(const char* str, const char* orig) {
-    stringStream out;
-    out.print("%-25s", str);
-    out.print("%s", orig);
-    return out.as_string();
-  }
-
-  ResourceMark rm;
-};
-
-template<>
-const char* WorkerDataArrayTest<size_t>::format_summary(
-  size_t min, double avg, size_t max, size_t diff, size_t sum, size_t workers) {
-
-  stringStream out;
-  out.print(" Min: " SIZE_FORMAT
-            ", Avg: %4.1lf, Max: " SIZE_FORMAT
-            ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT
-            ", Workers: " SIZE_FORMAT "\n",
-            min, avg, max, diff, sum, workers);
-  return out.as_string();
-}
-
-template<>
-const char* WorkerDataArrayTest<double>::format_summary(
-  double min, double avg, double max, double diff, double sum, size_t workers) {
-
-  stringStream out;
-  out.print(" Min: %4.1lf"
-            ", Avg: %4.1lf, Max: %4.1lf"
-            ", Diff: %4.1lf, Sum: %4.1lf"
-            ", Workers: " SIZE_FORMAT "\n",
-            min, avg, max, diff, sum, workers);
-  return out.as_string();
-}
-
-class BasicWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
- protected:
-  BasicWorkerDataArrayTest() {
-    array.set(0, 5);
-    array.set(1, 3);
-    array.set(2, 7);
-
-    array.set_thread_work_item(0, 1);
-    array.set_thread_work_item(1, 2);
-    array.set_thread_work_item(2, 3);
-  }
-
- private:
-  virtual const char* expected_summary() {
-    return format_summary(3, 5.0, 7, 4, 15, 3);
-  }
-
-  virtual const char* expected_details() {
-    return "  5  3  7\n";
-  }
-};
-
-TEST_VM_F(BasicWorkerDataArrayTest, sum_test) {
-  ASSERT_EQ(15u, array.sum());
-  ASSERT_EQ(6u, array.thread_work_items(0)->sum());
-}
-
-TEST_VM_F(BasicWorkerDataArrayTest, average_test) {
-  ASSERT_NEAR(5.0, array.average(), epsilon);
-  ASSERT_NEAR(2.0, array.thread_work_items(0)->average(), epsilon);
-}
-
-TEST_VM_F(BasicWorkerDataArrayTest, print_summary_on_test) {
-  ASSERT_STREQ(print_expected_summary(), print_summary());
-}
-
-TEST_VM_F(BasicWorkerDataArrayTest, print_details_on_test) {
-  ASSERT_STREQ(print_expected_details(), print_details());
-}
-
-class AddWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
- protected:
-  AddWorkerDataArrayTest() {
-    array.set(0, 5);
-    array.set(1, 3);
-    array.set(2, 7);
-
-    for (uint i = 0; i < 3; i++) {
-      array.add(i, 1);
-    }
-
-    WorkerDataArray<size_t>* sub_items = array.thread_work_items(0);
-
-    sub_items->set(0, 1);
-    sub_items->set(1, 2);
-    sub_items->set(2, 3);
-
-    for (uint i = 0; i < 3; i++) {
-      array.add_thread_work_item(i, 1);
-    }
-  }
-
- private:
-  virtual const char* expected_summary() {
-    return format_summary(4, 6.0, 8, 4, 18, 3);
-  }
-
-  virtual const char* expected_details() {
-    return "  6  4  8\n";
-  }
-};
-
-TEST_VM_F(AddWorkerDataArrayTest, sum_test) {
-  ASSERT_EQ(18u, array.sum());
-  ASSERT_EQ(9u, array.thread_work_items(0)->sum());
-}
-
-TEST_VM_F(AddWorkerDataArrayTest, average_test) {
-  ASSERT_NEAR(6.0, array.average(), epsilon);
-  ASSERT_NEAR(3.0, array.thread_work_items(0)->average(), epsilon);
-}
-
-TEST_VM_F(AddWorkerDataArrayTest, print_summary_on_test) {
-  ASSERT_STREQ(print_expected_summary(), print_summary());
-}
-
-TEST_VM_F(AddWorkerDataArrayTest, print_details_on_test) {
-  ASSERT_STREQ(print_expected_details(), print_details());
-}
-
-class UninitializedElementWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
- protected:
-  UninitializedElementWorkerDataArrayTest() {
-    array.set(0, 5);
-    array.set(1, WorkerDataArray<size_t>::uninitialized());
-    array.set(2, 7);
-  }
-
- private:
-  virtual const char* expected_summary() {
-    return format_summary(5, 6.0, 7, 2, 12, 2);
-  }
-
-  virtual const char* expected_details() {
-    return "  5 -  7\n";
-  }
-};
-
-TEST_VM_F(UninitializedElementWorkerDataArrayTest, sum_test) {
-  ASSERT_EQ(12u, array.sum());
-}
-
-TEST_VM_F(UninitializedElementWorkerDataArrayTest, average_test) {
-  ASSERT_NEAR(6.0, array.average(), epsilon);
-}
-
-TEST_VM_F(UninitializedElementWorkerDataArrayTest, print_summary_on_test) {
-  ASSERT_STREQ(print_expected_summary(), print_summary());
-}
-
-TEST_VM_F(UninitializedElementWorkerDataArrayTest, print_details_on_test) {
-  ASSERT_STREQ(print_expected_details(), print_details());
-}
-
-class UninitializedWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
- protected:
-  UninitializedWorkerDataArrayTest() {
-    array.set(0, WorkerDataArray<size_t>::uninitialized());
-    array.set(1, WorkerDataArray<size_t>::uninitialized());
-    array.set(2, WorkerDataArray<size_t>::uninitialized());
-  }
-
- private:
-  virtual const char* expected_summary() {
-    return " skipped\n";
-  }
-
-  virtual const char* expected_details() {
-    return " - - -\n";
-  }
-};
-
-TEST_VM_F(UninitializedWorkerDataArrayTest, sum_test) {
-  ASSERT_EQ(0u, array.sum());
-}
-
-TEST_VM_F(UninitializedWorkerDataArrayTest, average_test) {
-  ASSERT_NEAR(0.0, array.average(), epsilon);
-}
-
-TEST_VM_F(UninitializedWorkerDataArrayTest, print_summary_on_test) {
-  ASSERT_STREQ(print_expected_summary(), print_summary());
-}
-
-TEST_VM_F(UninitializedWorkerDataArrayTest, print_details_on_test) {
-  ASSERT_STREQ(print_expected_details(), print_details());
-}
-
-class UninitializedDoubleElementWorkerDataArrayTest : public WorkerDataArrayTest<double> {
- protected:
-  UninitializedDoubleElementWorkerDataArrayTest() {
-    array.set(0, 5.1 / MILLIUNITS);
-    array.set(1, WorkerDataArray<double>::uninitialized());
-    array.set(2, 7.2 / MILLIUNITS);
-  }
-
- private:
-  virtual const char* expected_summary() {
-    return format_summary(5.1, 6.1, 7.2, 2.1, 12.3, 2);
-  }
-
-  virtual const char* expected_details() {
-    stringStream out;
-    out.print(" %4.1lf - %4.1lf\n", 5.1, 7.2);
-    return out.as_string();
-  }
-};
-
-TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, sum_test) {
-  ASSERT_NEAR(12.3 / MILLIUNITS, array.sum(), epsilon);
-}
-
-TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, average_test) {
-  ASSERT_NEAR(6.15 / MILLIUNITS, array.average(), epsilon);
-}
-
-TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, print_summary_on_test) {
-  ASSERT_STREQ(print_expected_summary(), print_summary());
-}
-
-TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, print_details_on_test) {
-  ASSERT_STREQ(print_expected_details(), print_details());
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/gc/shared/test_workerDataArray.cpp	Fri Aug 11 21:33:56 2017 +0000
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2016, 2017, 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/shared/workerDataArray.inline.hpp"
+#include "memory/resourceArea.hpp"
+#include "unittest.hpp"
+#include "utilities/ostream.hpp"
+
+static const double epsilon = 0.0001;
+
+template<typename T>
+class WorkerDataArrayTest : public ::testing::Test {
+ protected:
+  WorkerDataArrayTest() :
+    title("Test array"),
+    array(3, title),
+    sub_item_title("Sub item array"),
+    sub_item(3, sub_item_title) {
+
+    array.link_thread_work_items(&sub_item);
+  }
+
+  const char* print_summary() {
+    stringStream out;
+    array.print_summary_on(&out);
+    return out.as_string();
+  }
+
+  const char* print_details() {
+    stringStream out;
+    array.print_details_on(&out);
+    return out.as_string();
+  }
+
+  const char* print_expected_summary() {
+    return prepend_with(title, expected_summary());
+  }
+
+  const char* print_expected_details() {
+    return prepend_with("", expected_details());
+  }
+
+  // returns expected summary for array without uninitialized elements
+  // used it because string representation of double depends on locale
+  static const char* format_summary(
+    T min, double avg, T max, T diff, T sum, size_t workers);
+
+  const char* title;
+  WorkerDataArray<T> array;
+
+  const char* sub_item_title;
+  WorkerDataArray<size_t> sub_item;
+
+ private:
+  virtual const char* expected_summary() = 0;
+  virtual const char* expected_details() = 0;
+
+  static const char* prepend_with(const char* str, const char* orig) {
+    stringStream out;
+    out.print("%-25s", str);
+    out.print("%s", orig);
+    return out.as_string();
+  }
+
+  ResourceMark rm;
+};
+
+template<>
+const char* WorkerDataArrayTest<size_t>::format_summary(
+  size_t min, double avg, size_t max, size_t diff, size_t sum, size_t workers) {
+
+  stringStream out;
+  out.print(" Min: " SIZE_FORMAT
+            ", Avg: %4.1lf, Max: " SIZE_FORMAT
+            ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT
+            ", Workers: " SIZE_FORMAT "\n",
+            min, avg, max, diff, sum, workers);
+  return out.as_string();
+}
+
+template<>
+const char* WorkerDataArrayTest<double>::format_summary(
+  double min, double avg, double max, double diff, double sum, size_t workers) {
+
+  stringStream out;
+  out.print(" Min: %4.1lf"
+            ", Avg: %4.1lf, Max: %4.1lf"
+            ", Diff: %4.1lf, Sum: %4.1lf"
+            ", Workers: " SIZE_FORMAT "\n",
+            min, avg, max, diff, sum, workers);
+  return out.as_string();
+}
+
+class BasicWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
+ protected:
+  BasicWorkerDataArrayTest() {
+    array.set(0, 5);
+    array.set(1, 3);
+    array.set(2, 7);
+
+    array.set_thread_work_item(0, 1);
+    array.set_thread_work_item(1, 2);
+    array.set_thread_work_item(2, 3);
+  }
+
+ private:
+  virtual const char* expected_summary() {
+    return format_summary(3, 5.0, 7, 4, 15, 3);
+  }
+
+  virtual const char* expected_details() {
+    return "  5  3  7\n";
+  }
+};
+
+TEST_VM_F(BasicWorkerDataArrayTest, sum_test) {
+  ASSERT_EQ(15u, array.sum());
+  ASSERT_EQ(6u, array.thread_work_items(0)->sum());
+}
+
+TEST_VM_F(BasicWorkerDataArrayTest, average_test) {
+  ASSERT_NEAR(5.0, array.average(), epsilon);
+  ASSERT_NEAR(2.0, array.thread_work_items(0)->average(), epsilon);
+}
+
+TEST_VM_F(BasicWorkerDataArrayTest, print_summary_on_test) {
+  ASSERT_STREQ(print_expected_summary(), print_summary());
+}
+
+TEST_VM_F(BasicWorkerDataArrayTest, print_details_on_test) {
+  ASSERT_STREQ(print_expected_details(), print_details());
+}
+
+class AddWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
+ protected:
+  AddWorkerDataArrayTest() {
+    array.set(0, 5);
+    array.set(1, 3);
+    array.set(2, 7);
+
+    for (uint i = 0; i < 3; i++) {
+      array.add(i, 1);
+    }
+
+    WorkerDataArray<size_t>* sub_items = array.thread_work_items(0);
+
+    sub_items->set(0, 1);
+    sub_items->set(1, 2);
+    sub_items->set(2, 3);
+
+    for (uint i = 0; i < 3; i++) {
+      array.add_thread_work_item(i, 1);
+    }
+  }
+
+ private:
+  virtual const char* expected_summary() {
+    return format_summary(4, 6.0, 8, 4, 18, 3);
+  }
+
+  virtual const char* expected_details() {
+    return "  6  4  8\n";
+  }
+};
+
+TEST_VM_F(AddWorkerDataArrayTest, sum_test) {
+  ASSERT_EQ(18u, array.sum());
+  ASSERT_EQ(9u, array.thread_work_items(0)->sum());
+}
+
+TEST_VM_F(AddWorkerDataArrayTest, average_test) {
+  ASSERT_NEAR(6.0, array.average(), epsilon);
+  ASSERT_NEAR(3.0, array.thread_work_items(0)->average(), epsilon);
+}
+
+TEST_VM_F(AddWorkerDataArrayTest, print_summary_on_test) {
+  ASSERT_STREQ(print_expected_summary(), print_summary());
+}
+
+TEST_VM_F(AddWorkerDataArrayTest, print_details_on_test) {
+  ASSERT_STREQ(print_expected_details(), print_details());
+}
+
+class UninitializedElementWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
+ protected:
+  UninitializedElementWorkerDataArrayTest() {
+    array.set(0, 5);
+    array.set(1, WorkerDataArray<size_t>::uninitialized());
+    array.set(2, 7);
+  }
+
+ private:
+  virtual const char* expected_summary() {
+    return format_summary(5, 6.0, 7, 2, 12, 2);
+  }
+
+  virtual const char* expected_details() {
+    return "  5 -  7\n";
+  }
+};
+
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, sum_test) {
+  ASSERT_EQ(12u, array.sum());
+}
+
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, average_test) {
+  ASSERT_NEAR(6.0, array.average(), epsilon);
+}
+
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, print_summary_on_test) {
+  ASSERT_STREQ(print_expected_summary(), print_summary());
+}
+
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, print_details_on_test) {
+  ASSERT_STREQ(print_expected_details(), print_details());
+}
+
+class UninitializedWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
+ protected:
+  UninitializedWorkerDataArrayTest() {
+    array.set(0, WorkerDataArray<size_t>::uninitialized());
+    array.set(1, WorkerDataArray<size_t>::uninitialized());
+    array.set(2, WorkerDataArray<size_t>::uninitialized());
+  }
+
+ private:
+  virtual const char* expected_summary() {
+    return " skipped\n";
+  }
+
+  virtual const char* expected_details() {
+    return " - - -\n";
+  }
+};
+
+TEST_VM_F(UninitializedWorkerDataArrayTest, sum_test) {
+  ASSERT_EQ(0u, array.sum());
+}
+
+TEST_VM_F(UninitializedWorkerDataArrayTest, average_test) {
+  ASSERT_NEAR(0.0, array.average(), epsilon);
+}
+
+TEST_VM_F(UninitializedWorkerDataArrayTest, print_summary_on_test) {
+  ASSERT_STREQ(print_expected_summary(), print_summary());
+}
+
+TEST_VM_F(UninitializedWorkerDataArrayTest, print_details_on_test) {
+  ASSERT_STREQ(print_expected_details(), print_details());
+}
+
+class UninitializedDoubleElementWorkerDataArrayTest : public WorkerDataArrayTest<double> {
+ protected:
+  UninitializedDoubleElementWorkerDataArrayTest() {
+    array.set(0, 5.1 / MILLIUNITS);
+    array.set(1, WorkerDataArray<double>::uninitialized());
+    array.set(2, 7.2 / MILLIUNITS);
+  }
+
+ private:
+  virtual const char* expected_summary() {
+    return format_summary(5.1, 6.1, 7.2, 2.1, 12.3, 2);
+  }
+
+  virtual const char* expected_details() {
+    stringStream out;
+    out.print(" %4.1lf - %4.1lf\n", 5.1, 7.2);
+    return out.as_string();
+  }
+};
+
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, sum_test) {
+  ASSERT_NEAR(12.3 / MILLIUNITS, array.sum(), epsilon);
+}
+
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, average_test) {
+  ASSERT_NEAR(6.15 / MILLIUNITS, array.average(), epsilon);
+}
+
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, print_summary_on_test) {
+  ASSERT_STREQ(print_expected_summary(), print_summary());
+}
+
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, print_details_on_test) {
+  ASSERT_STREQ(print_expected_details(), print_details());
+}
--- a/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -47,7 +47,7 @@
 
         ClassFileInstaller.writeClassToDisk("java/lang/Object",
                                         InMemoryJavaCompiler.compile("java.lang.Object", source,
-                                        "-Xmodule:java.base"),
+                                        "--patch-module=java.base"),
                                         "mods/java.base");
 
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.base=mods/java.base", "-version");
--- a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @bug 8003424
  * @summary Testing UseCompressedClassPointers with CDS
  * @library /test/lib
--- a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrsError.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrsError.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @bug 8003424
  * @summary Test that cannot use CDS if UseCompressedClassPointers is turned off.
  * @library /test/lib
--- a/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @bug 8005933
  * @summary Test that -Xshare:auto uses CDS when explicitly specified with -server.
  * @library /test/lib
--- a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -106,6 +106,9 @@
             "-XX:+VerifyBeforeGC",
             "-Xshare:dump");
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        if (output.firstMatch("Shared spaces are not supported in this VM") != null) {
+            return;
+        }
         try {
           output.shouldContain("Loading classes to share");
           output.shouldHaveExitValue(0);
--- a/hotspot/test/runtime/NMT/NMTWithCDS.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/NMT/NMTWithCDS.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,15 +21,17 @@
  * questions.
  */
 
-/*
+/**
  * @test
  * @bug 8055061
  * @key nmt
+ * @requires vm.cds
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
  * @run main NMTWithCDS
  */
+
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
 
--- a/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test ArchiveDoesNotExist
+ * @requires vm.cds
  * @summary Test how VM handles "file does not exist" situation while
  *          attempting to use CDS archive. JVM should exit gracefully
  *          when sharing mode is ON, and continue w/o sharing if sharing
--- a/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java	Fri Aug 11 21:33:56 2017 +0000
@@ -23,6 +23,7 @@
 
 /**
  * @test
+ * @requires vm.cds
  * @summary Testing -Xbootclasspath/a support for CDS
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
  * @library /test/lib
--- a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test CdsDifferentCompactStrings
+ * @requires vm.cds
  * @summary CDS (class data sharing) requires the same -XX:[+-]CompactStrings
  *          setting between archive creation time and load time.
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
--- a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test CdsDifferentObjectAlignment
+ * @requires vm.cds
  * @summary Testing CDS (class data sharing) using varying object alignment.
  *          Using different object alignment for each dump/load pair.
  *          This is a negative test; using  object alignment for loading that
--- a/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test CdsSameObjectAlignment
+ * @requires vm.cds
  * @summary Testing CDS (class data sharing) using varying object alignment.
  *          Using same object alignment for each dump/load pair
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
--- a/hotspot/test/runtime/SharedArchiveFile/DumpSharedDictionary.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/DumpSharedDictionary.java	Fri Aug 11 21:33:56 2017 +0000
@@ -26,6 +26,7 @@
  * @bug 8130072
  * @summary Check that Shared Dictionary is printed out with jcmd
  * Feature support: compressed oops/kptrs, 64-bit os, not on windows
+ * @requires vm.cds
  * @requires (sun.arch.data.model != "32") & (os.family != "windows")
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
  * @library /test/lib
@@ -62,7 +63,9 @@
                     "-Xshare:on", "DumpSharedDictionary", "test");
 
             out = CDSTestUtils.executeAndLog(pb, "exec");
-            out.shouldHaveExitValue(0);
+            if (!CDSTestUtils.isUnableToMap(out)) {
+                out.shouldHaveExitValue(0);
+            }
         } else {
             // Grab my own PID
             String pid = Long.toString(ProcessTools.getProcessId());
--- a/hotspot/test/runtime/SharedArchiveFile/MaxMetaspaceSize.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/MaxMetaspaceSize.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @bug 8067187
  * @summary Testing CDS dumping with the -XX:MaxMetaspaceSize=<size> option
  * @library /test/lib
--- a/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @bug 8066670
  * @summary Testing -XX:+PrintSharedArchiveAndExit option
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
--- a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test SASymbolTableTest
+ * @requires vm.cds
  * @summary Walk symbol table using SA, with and without CDS.
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
  * @library /test/lib
--- a/hotspot/test/runtime/SharedArchiveFile/SharedArchiveFile.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedArchiveFile.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @bug 8014138
  * @summary Testing new -XX:SharedArchiveFile=<file-name> option
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
--- a/hotspot/test/runtime/SharedArchiveFile/SharedBaseAddress.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedBaseAddress.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test SharedBaseAddress
+ * @requires vm.cds
  * @summary Test variety of values for SharedBaseAddress, making sure
  *          VM handles normal values as well as edge values w/o a crash.
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
--- a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @summary Check to make sure that shared strings in the bootstrap CDS archive
  *          are actually shared
  * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
--- a/hotspot/test/runtime/SharedArchiveFile/SharedStringsDedup.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsDedup.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test SharedStringsDedup
+ * @requires vm.cds
  * @summary Test -Xshare:auto with shared strings and -XX:+UseStringDeduplication
  * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
  * @requires (sun.arch.data.model != "32") & (os.family != "windows")
--- a/hotspot/test/runtime/SharedArchiveFile/SharedStringsRunAuto.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsRunAuto.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test SharedStringsAuto
+ * @requires vm.cds
  * @summary Test -Xshare:auto with shared strings.
  * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
  * @requires (sun.arch.data.model != "32") & (os.family != "windows")
--- a/hotspot/test/runtime/SharedArchiveFile/SharedSymbolTableBucketSize.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedSymbolTableBucketSize.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @bug 8059510
  * @summary Test SharedSymbolTableBucketSize option
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
--- a/hotspot/test/runtime/SharedArchiveFile/SpaceUtilizationCheck.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SpaceUtilizationCheck.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test SpaceUtilizationCheck
+ * @requires vm.cds
  * @summary Check if the space utilization for shared spaces is adequate
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
  * @library /test/lib
--- a/hotspot/test/runtime/SharedArchiveFile/TestInterpreterMethodEntries.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/TestInterpreterMethodEntries.java	Fri Aug 11 21:33:56 2017 +0000
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test InterpreterMethodEntries
+ * @requires vm.cds
  * @bug 8169711
  * @summary Test interpreter method entries for intrinsics with CDS (class data sharing)
  *          and different settings of the intrinsic flag during dump/use of the archive.
--- a/hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @summary Exercise initial transformation (ClassFileLoadHook)
  *  with CDS with Interface/Implementor pair
  * @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
--- a/hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperAndSubClasses.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperAndSubClasses.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,9 @@
  */
 
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @summary Exercise initial transformation (ClassFileLoadHook)
  *  with CDS with SubClass and SuperClass
  * @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
--- a/hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperSubTwoPckgs.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperSubTwoPckgs.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,9 @@
  */
 
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @summary Exercise initial transformation (ClassFileLoadHook)
  *  with CDS with SubClass and SuperClass, each lives in own separate package
  * @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
--- a/hotspot/test/runtime/modules/PatchModule/PatchModule2Dirs.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModule2Dirs.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -51,11 +51,11 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source1, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source1, "--patch-module=java.naming"),
              "mods/java.naming");
 
         ClassFileInstaller.writeClassToDisk("java/beans/Encoder",
-             InMemoryJavaCompiler.compile("java.beans.Encoder", source2, "-Xmodule:java.desktop"),
+             InMemoryJavaCompiler.compile("java.beans.Encoder", source2, "--patch-module=java.desktop"),
              "mods2/java.desktop");
 
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @summary test that --patch-module works with CDS
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -61,7 +62,7 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
              System.getProperty("test.classes"));
 
         pb = ProcessTools.createJavaProcessBuilder(
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleClassList.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleClassList.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,9 @@
  * questions.
  */
 
-/*
+/**
  * @test
+ * @requires vm.cds
  * @summary classes which are not useable during run time should not be included in the classlist
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -54,7 +55,7 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk(BOOT_CLASS,
-             InMemoryJavaCompiler.compile(BOOT_CLASS.replace('/', '.'), source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile(BOOT_CLASS.replace('/', '.'), source, "--patch-module=java.naming"),
              System.getProperty("test.classes"));
 
         // Build the jar file that will be used for the module "java.naming".
@@ -87,7 +88,7 @@
                  "}";
 
         ClassFileInstaller.writeClassToDisk(PLATFORM_CLASS,
-             InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "-Xmodule:java.transaction"),
+             InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "--patch-module=java.transaction"),
              System.getProperty("test.classes"));
 
         // Build the jar file that will be used for the module "java.transaction".
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleJavaBase.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleJavaBase.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -46,7 +46,7 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk("java/lang/NewClass",
-             InMemoryJavaCompiler.compile("java.lang.NewClass", source, "-Xmodule:java.base"),
+             InMemoryJavaCompiler.compile("java.lang.NewClass", source, "--patch-module=java.base"),
              "mods/java.base");
 
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.base=mods/java.base",
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleTest.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTest.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -46,7 +46,7 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
              "mods/java.naming");
 
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming",
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJar.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJar.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -50,7 +50,7 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
              System.getProperty("test.classes"));
 
         // Build the jar file that will be used for the module "java.naming".
@@ -70,7 +70,7 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
              System.getProperty("test.classes"));
 
         // Supply --patch-module with the name of the jar file for the module java.naming.
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJarDir.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJarDir.java	Fri Aug 11 21:33:56 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -52,7 +52,7 @@
                         "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "--patch-module=java.naming"),
              System.getProperty("test.classes"));
 
         // Build the jar file that will be used for the module "java.naming".
@@ -72,7 +72,7 @@
                  "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "--patch-module=java.naming"),
              System.getProperty("test.classes"));
 
         // Create a second class file in the module java.naming. This class file
@@ -85,7 +85,7 @@
                  "}";
 
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager2",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager2", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager2", source, "--patch-module=java.naming"),
              (System.getProperty("test.classes") + "/mods/java.naming"));
 
 
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleTraceCL.java	Fri Aug 11 23:29:14 2017 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTraceCL.java	Fri Aug 11 21:33:56 2017 +0000
@@ -48,7 +48,7 @@
 
         // Test -Xlog:class+load=info output for --patch-module
         ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
-             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
              "mods/java.naming");
 
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming",