changeset 37129:af29e306e50b

8151601: Cleanup locking of the Reference pending list Reviewed-by: brutisso, stefank
author pliden
date Thu, 17 Mar 2016 08:07:53 +0100
parents ea9e0371b8e6
children a530aaacd7c5
files hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js hotspot/src/share/vm/ci/ciReplay.cpp hotspot/src/share/vm/compiler/compileBroker.cpp hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp hotspot/src/share/vm/gc/shared/collectedHeap.hpp hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp hotspot/src/share/vm/gc/shared/vmGCOperations.cpp hotspot/src/share/vm/gc/shared/vmGCOperations.hpp hotspot/src/share/vm/oops/instanceRefKlass.cpp hotspot/src/share/vm/oops/instanceRefKlass.hpp hotspot/src/share/vm/oops/method.cpp hotspot/src/share/vm/runtime/mutexLocker.cpp hotspot/src/share/vm/runtime/mutexLocker.hpp hotspot/src/share/vm/runtime/thread.cpp hotspot/src/share/vm/runtime/vmStructs.cpp
diffstat 29 files changed, 401 insertions(+), 353 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -130,7 +130,7 @@
             virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class);
         }
         // for now, use JavaThread itself. fix it later with appropriate class if needed
-        virtualConstructor.addMapping("SurrogateLockerThread", JavaThread.class);
+        virtualConstructor.addMapping("ReferencePendingListLockerThread", JavaThread.class);
         virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class);
         virtualConstructor.addMapping("ServiceThread", ServiceThread.class);
     }
@@ -172,7 +172,7 @@
             return thread;
         } catch (Exception e) {
             throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr +
-            " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, SurrogateLockerThread, or CodeCacheSweeperThread)", e);
+            " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, ReferencePendingListLockerThread, or CodeCacheSweeperThread)", e);
         }
     }
 
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -837,7 +837,7 @@
 vmType2Class["JavaThread"] = sapkg.runtime.JavaThread;
 vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread;
 vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread;
-vmType2Class["SurrogateLockerThread"] = sapkg.runtime.JavaThread;
+vmType2Class["ReferencePendingListLockerThread"] = sapkg.runtime.JavaThread;
 vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread;
 
 // gc
--- a/hotspot/src/share/vm/ci/ciReplay.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciReplay.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,4 +1,5 @@
-/* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+/*
+ * Copyright (c) 2013, 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
@@ -28,6 +29,7 @@
 #include "ci/ciKlass.hpp"
 #include "ci/ciUtilities.hpp"
 #include "compiler/compileBroker.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -574,7 +576,7 @@
     Method* method = parse_method(CHECK);
     if (had_error()) return;
     /* just copied from Method, to build interpret data*/
-    if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
+    if (ReferencePendingListLocker::is_locked_by_self()) {
       return;
     }
     // To be properly initialized, some profiling in the MDO needs the
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -32,6 +32,7 @@
 #include "compiler/compileLog.hpp"
 #include "compiler/compilerOracle.hpp"
 #include "compiler/directivesParser.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.inline.hpp"
 #include "oops/methodData.hpp"
@@ -904,7 +905,7 @@
   // the pending list lock or a 3-way deadlock may occur
   // between the reference handler thread, a GC (instigated
   // by a compiler thread), and compiled method registration.
-  if (InstanceRefKlass::owns_pending_list_lock(JavaThread::current())) {
+  if (ReferencePendingListLocker::is_locked_by_self()) {
     return;
   }
 
@@ -1309,7 +1310,7 @@
  * has been fulfilled?
  */
 bool CompileBroker::is_compile_blocking() {
-  assert(!InstanceRefKlass::owns_pending_list_lock(JavaThread::current()), "possible deadlock");
+  assert(!ReferencePendingListLocker::is_locked_by_self(), "possible deadlock");
   return !BackgroundCompilation;
 }
 
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -28,7 +28,7 @@
 #include "gc/cms/concurrentMarkSweepThread.hpp"
 #include "gc/shared/gcId.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
-#include "oops/instanceRefKlass.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.hpp"
@@ -46,11 +46,6 @@
 
 volatile jint ConcurrentMarkSweepThread::_pending_yields    = 0;
 
-SurrogateLockerThread* ConcurrentMarkSweepThread::_slt      = NULL;
-SurrogateLockerThread::SLT_msg_type
-     ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty;
-Monitor* ConcurrentMarkSweepThread::_sltMonitor             = NULL;
-
 ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
   : ConcurrentGCThread() {
   assert(UseConcMarkSweepGC,  "UseConcMarkSweepGC should be set");
@@ -73,8 +68,6 @@
   // That won't happen on Solaris for various reasons,
   // but may well happen on non-Solaris platforms.
   create_and_start(UseCriticalCMSThreadPriority ? CriticalPriority : NearMaxPriority);
-
-  _sltMonitor = SLT_lock;
 }
 
 void ConcurrentMarkSweepThread::run_service() {
@@ -94,7 +87,7 @@
     // We cannot start the SLT thread ourselves since we need
     // to be a JavaThread to do so.
     CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2);
-    while (_slt == NULL && !should_terminate()) {
+    while (!ReferencePendingListLocker::is_initialized() && !should_terminate()) {
       CGC_lock->wait(true, 200);
       loopY.tick();
     }
@@ -337,15 +330,3 @@
     // and wait some more
   }
 }
-
-// Note: this method, although exported by the ConcurrentMarkSweepThread,
-// which is a non-JavaThread, can only be called by a JavaThread.
-// Currently this is done at vm creation time (post-vm-init) by the
-// main/Primordial (Java)Thread.
-// XXX Consider changing this in the future to allow the CMS thread
-// itself to create this thread?
-void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) {
-  assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC");
-  assert(_slt == NULL, "SLT already created");
-  _slt = SurrogateLockerThread::make(THREAD);
-}
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -39,11 +39,8 @@
   friend class CMSCollector;
 
  private:
-  static ConcurrentMarkSweepThread*     _cmst;
-  static CMSCollector*                  _collector;
-  static SurrogateLockerThread*         _slt;
-  static SurrogateLockerThread::SLT_msg_type _sltBuffer;
-  static Monitor*                       _sltMonitor;
+  static ConcurrentMarkSweepThread* _cmst;
+  static CMSCollector*              _collector;
 
   enum CMS_flag_type {
     CMS_nil             = NoBits,
@@ -75,9 +72,6 @@
   // Constructor
   ConcurrentMarkSweepThread(CMSCollector* collector);
 
-  static void makeSurrogateLockerThread(TRAPS);
-  static SurrogateLockerThread* slt() { return _slt; }
-
   static void threads_do(ThreadClosure* tc);
 
   // Printing
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -38,21 +38,11 @@
 // Methods in abstract class VM_CMS_Operation
 //////////////////////////////////////////////////////////
 void VM_CMS_Operation::acquire_pending_list_lock() {
-  // The caller may block while communicating
-  // with the SLT thread in order to acquire/release the PLL.
-  SurrogateLockerThread* slt = ConcurrentMarkSweepThread::slt();
-  if (slt != NULL) {
-    slt->manipulatePLL(SurrogateLockerThread::acquirePLL);
-  } else {
-    SurrogateLockerThread::report_missing_slt();
-  }
+  _pending_list_locker.lock();
 }
 
 void VM_CMS_Operation::release_and_notify_pending_list_lock() {
-  // The caller may block while communicating
-  // with the SLT thread in order to acquire/release the PLL.
-  ConcurrentMarkSweepThread::slt()->
-    manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
+  _pending_list_locker.unlock();
 }
 
 void VM_CMS_Operation::verify_before_gc() {
@@ -95,7 +85,7 @@
   assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
          "Possible deadlock");
 
-  if (needs_pll()) {
+  if (needs_pending_list_lock()) {
     acquire_pending_list_lock();
   }
   // Get the Heap_lock after the pending_list_lock.
@@ -103,7 +93,7 @@
   if (lost_race()) {
     assert(_prologue_succeeded == false, "Initialized in c'tor");
     Heap_lock->unlock();
-    if (needs_pll()) {
+    if (needs_pending_list_lock()) {
       release_and_notify_pending_list_lock();
     }
   } else {
@@ -120,7 +110,7 @@
 
   // Release the Heap_lock first.
   Heap_lock->unlock();
-  if (needs_pll()) {
+  if (needs_pending_list_lock()) {
     release_and_notify_pending_list_lock();
   }
 }
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -28,6 +28,7 @@
 #include "gc/cms/concurrentMarkSweepGeneration.hpp"
 #include "gc/shared/gcCause.hpp"
 #include "gc/shared/gcId.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "gc/shared/vmGCOperations.hpp"
 #include "runtime/vm_operations.hpp"
 
@@ -51,6 +52,9 @@
 class CMSCollector;
 
 class VM_CMS_Operation: public VM_Operation {
+ private:
+  ReferencePendingListLocker _pending_list_locker;
+
  protected:
   CMSCollector*  _collector;                 // associated collector
   bool           _prologue_succeeded;     // whether doit_prologue succeeded
@@ -73,7 +77,7 @@
   virtual const CMSCollector::CollectorState legal_state() const = 0;
 
   // Whether the pending list lock needs to be held
-  virtual const bool needs_pll() const = 0;
+  virtual const bool needs_pending_list_lock() const = 0;
 
   // Execute operations in the context of the caller,
   // prior to execution of the vm operation itself.
@@ -105,7 +109,7 @@
     return CMSCollector::InitialMarking;
   }
 
-  virtual const bool needs_pll() const {
+  virtual const bool needs_pending_list_lock() const {
     return false;
   }
 };
@@ -122,7 +126,7 @@
     return CMSCollector::FinalMarking;
   }
 
-  virtual const bool needs_pll() const {
+  virtual const bool needs_pending_list_lock() const {
     return true;
   }
 };
--- a/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -51,14 +51,12 @@
            declare_type(ConcurrentMarkSweepGeneration,CardGeneration)     \
            declare_type(CompactibleFreeListSpace,     CompactibleSpace)   \
            declare_type(ConcurrentMarkSweepThread,    NamedThread)        \
-           declare_type(SurrogateLockerThread, JavaThread)                \
   declare_toplevel_type(CMSCollector)                                     \
   declare_toplevel_type(CMSBitMap)                                        \
   declare_toplevel_type(FreeChunk)                                        \
   declare_toplevel_type(Metablock)                                        \
   declare_toplevel_type(ConcurrentMarkSweepThread*)                       \
   declare_toplevel_type(ConcurrentMarkSweepGeneration*)                   \
-  declare_toplevel_type(SurrogateLockerThread*)                           \
   declare_toplevel_type(CompactibleFreeListSpace*)                        \
   declare_toplevel_type(CMSCollector*)                                    \
   declare_toplevel_type(AFLBinaryTreeDictionary)                          \
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -41,9 +41,6 @@
 
 // The CM thread is created when the G1 garbage collector is used
 
-SurrogateLockerThread*
-     ConcurrentMarkThread::_slt = NULL;
-
 ConcurrentMarkThread::ConcurrentMarkThread(G1ConcurrentMark* cm) :
   ConcurrentGCThread(),
   _cm(cm),
@@ -305,16 +302,3 @@
     set_in_progress();
   }
 }
-
-// Note: As is the case with CMS - this method, although exported
-// by the ConcurrentMarkThread, which is a non-JavaThread, can only
-// be called by a JavaThread. Currently this is done at vm creation
-// time (post-vm-init) by the main/Primordial (Java)Thread.
-// XXX Consider changing this in the future to allow the CM thread
-// itself to create this thread?
-void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
-  assert(UseG1GC, "SLT thread needed only for concurrent GC");
-  assert(THREAD->is_Java_thread(), "must be a Java thread");
-  assert(_slt == NULL, "SLT already created");
-  _slt = SurrogateLockerThread::make(THREAD);
-}
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -56,15 +56,10 @@
   void run_service();
   void stop_service();
 
-  static SurrogateLockerThread*         _slt;
-
  public:
   // Constructor
   ConcurrentMarkThread(G1ConcurrentMark* cm);
 
-  static void makeSurrogateLockerThread(TRAPS);
-  static SurrogateLockerThread* slt() { return _slt; }
-
   // Total virtual time so far for this thread and concurrent marking tasks.
   double vtime_accum();
   // Marking virtual time so far this thread and concurrent marking tasks.
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1292,6 +1292,12 @@
     return true;
   }
 
+  // The reference pending list lock is acquired from from the
+  // ConcurrentMarkThread.
+  virtual bool needs_reference_pending_list_locker_thread() const {
+    return true;
+  }
+
   inline bool is_in_young(const oop obj);
 
   virtual bool is_scavengable(const void* addr);
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -205,23 +205,11 @@
 }
 
 void VM_CGC_Operation::acquire_pending_list_lock() {
-  assert(_needs_pll, "don't call this otherwise");
-  // The caller may block while communicating
-  // with the SLT thread in order to acquire/release the PLL.
-  SurrogateLockerThread* slt = ConcurrentMarkThread::slt();
-  if (slt != NULL) {
-    slt->manipulatePLL(SurrogateLockerThread::acquirePLL);
-  } else {
-    SurrogateLockerThread::report_missing_slt();
-  }
+  _pending_list_locker.lock();
 }
 
 void VM_CGC_Operation::release_and_notify_pending_list_lock() {
-  assert(_needs_pll, "don't call this otherwise");
-  // The caller may block while communicating
-  // with the SLT thread in order to acquire/release the PLL.
-  ConcurrentMarkThread::slt()->
-    manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
+  _pending_list_locker.unlock();
 }
 
 void VM_CGC_Operation::doit() {
@@ -236,10 +224,9 @@
 bool VM_CGC_Operation::doit_prologue() {
   // Note the relative order of the locks must match that in
   // VM_GC_Operation::doit_prologue() or deadlocks can occur
-  if (_needs_pll) {
+  if (_needs_pending_list_lock) {
     acquire_pending_list_lock();
   }
-
   Heap_lock->lock();
   return true;
 }
@@ -248,7 +235,7 @@
   // Note the relative order of the unlocks must match that in
   // VM_GC_Operation::doit_epilogue()
   Heap_lock->unlock();
-  if (_needs_pll) {
+  if (_needs_pending_list_lock) {
     release_and_notify_pending_list_lock();
   }
 }
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -27,6 +27,7 @@
 
 #include "gc/g1/g1AllocationContext.hpp"
 #include "gc/shared/gcId.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "gc/shared/vmGCOperations.hpp"
 
 // VM_operations for the G1 collector.
@@ -102,10 +103,11 @@
 // Concurrent GC stop-the-world operations such as remark and cleanup;
 // consider sharing these with CMS's counterparts.
 class VM_CGC_Operation: public VM_Operation {
-  VoidClosure* _cl;
-  const char* _printGCMessage;
-  bool _needs_pll;
-  uint _gc_id;
+  VoidClosure*               _cl;
+  const char*                _printGCMessage;
+  bool                       _needs_pending_list_lock;
+  ReferencePendingListLocker _pending_list_locker;
+  uint                       _gc_id;
 
 protected:
   // java.lang.ref.Reference support
@@ -113,8 +115,8 @@
   void release_and_notify_pending_list_lock();
 
 public:
-  VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pll)
-    : _cl(cl), _printGCMessage(printGCMsg), _needs_pll(needs_pll), _gc_id(GCId::current()) { }
+  VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pending_list_lock)
+    : _cl(cl), _printGCMessage(printGCMsg), _needs_pending_list_lock(needs_pending_list_lock), _gc_id(GCId::current()) {}
   virtual VMOp_Type type() const { return VMOp_CGC_Operation; }
   virtual void doit();
   virtual bool doit_prologue();
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -438,6 +438,12 @@
   // remembered set.
   virtual void flush_deferred_store_barrier(JavaThread* thread);
 
+  // Should return true if the reference pending list lock is
+  // acquired from non-Java threads, such as a concurrent GC thread.
+  virtual bool needs_reference_pending_list_locker_thread() const {
+    return false;
+  }
+
   // Perform a collection of the heap; intended for use in implementing
   // "System.gc".  This probably implies as full a collection as the
   // "CollectedHeap" supports.
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -102,131 +102,3 @@
     }
   }
 }
-
-static void _sltLoop(JavaThread* thread, TRAPS) {
-  SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
-  slt->loop();
-}
-
-SurrogateLockerThread::SurrogateLockerThread() :
-  JavaThread(&_sltLoop),
-  _monitor(Mutex::nonleaf, "SLTMonitor", false,
-           Monitor::_safepoint_check_sometimes),
-  _buffer(empty)
-{}
-
-SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
-  Klass* k =
-    SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
-                                      true, CHECK_NULL);
-  instanceKlassHandle klass (THREAD, k);
-  instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
-
-  const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)";
-  Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);
-
-  // Initialize thread_oop to put it into the system threadGroup
-  Handle thread_group (THREAD, Universe::system_thread_group());
-  JavaValue result(T_VOID);
-  JavaCalls::call_special(&result, thread_oop,
-                          klass,
-                          vmSymbols::object_initializer_name(),
-                          vmSymbols::threadgroup_string_void_signature(),
-                          thread_group,
-                          string,
-                          CHECK_NULL);
-
-  SurrogateLockerThread* res;
-  {
-    MutexLocker mu(Threads_lock);
-    res = new SurrogateLockerThread();
-
-    // At this point it may be possible that no osthread was created for the
-    // JavaThread due to lack of memory. We would have to throw an exception
-    // in that case. However, since this must work and we do not allow
-    // exceptions anyway, check and abort if this fails.
-    if (res == NULL || res->osthread() == NULL) {
-      vm_exit_during_initialization("java.lang.OutOfMemoryError",
-                                    os::native_thread_creation_failed_msg());
-    }
-    java_lang_Thread::set_thread(thread_oop(), res);
-    java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
-    java_lang_Thread::set_daemon(thread_oop());
-
-    res->set_threadObj(thread_oop());
-    Threads::add(res);
-    Thread::start(res);
-  }
-  os::naked_yield(); // This seems to help with initial start-up of SLT
-  return res;
-}
-
-void SurrogateLockerThread::report_missing_slt() {
-  vm_exit_during_initialization(
-    "GC before GC support fully initialized: "
-    "SLT is needed but has not yet been created.");
-  ShouldNotReachHere();
-}
-
-void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
-  MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
-  assert(_buffer == empty, "Should be empty");
-  assert(msg != empty, "empty message");
-  assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
-
-  _buffer = msg;
-  while (_buffer != empty) {
-    _monitor.notify();
-    _monitor.wait(Mutex::_no_safepoint_check_flag);
-  }
-}
-
-// ======= Surrogate Locker Thread =============
-
-void SurrogateLockerThread::loop() {
-  BasicLock pll_basic_lock;
-  SLT_msg_type msg;
-  debug_only(unsigned int owned = 0;)
-
-  while (/* !isTerminated() */ 1) {
-    {
-      MutexLocker x(&_monitor);
-      // Since we are a JavaThread, we can't be here at a safepoint.
-      assert(!SafepointSynchronize::is_at_safepoint(),
-             "SLT is a JavaThread");
-      // wait for msg buffer to become non-empty
-      while (_buffer == empty) {
-        _monitor.notify();
-        _monitor.wait();
-      }
-      msg = _buffer;
-    }
-    switch(msg) {
-      case acquirePLL: {
-        InstanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
-        debug_only(owned++;)
-        break;
-      }
-      case releaseAndNotifyPLL: {
-        assert(owned > 0, "Don't have PLL");
-        InstanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
-        debug_only(owned--;)
-        break;
-      }
-      case empty:
-      default: {
-        guarantee(false,"Unexpected message in _buffer");
-        break;
-      }
-    }
-    {
-      MutexLocker x(&_monitor);
-      // Since we are a JavaThread, we can't be here at a safepoint.
-      assert(!SafepointSynchronize::is_at_safepoint(),
-             "SLT is a JavaThread");
-      _buffer = empty;
-      _monitor.notify();
-    }
-  }
-  assert(!_monitor.owned_by_self(), "Should unlock before exit.");
-}
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -70,37 +70,4 @@
   bool has_terminated()   { return _has_terminated; }
 };
 
-// The SurrogateLockerThread is used by concurrent GC threads for
-// manipulating Java monitors, in particular, currently for
-// manipulating the pending_list_lock. XXX
-class SurrogateLockerThread: public JavaThread {
-  friend class VMStructs;
- public:
-  enum SLT_msg_type {
-    empty = 0,           // no message
-    acquirePLL,          // acquire pending list lock
-    releaseAndNotifyPLL  // notify and release pending list lock
-  };
- private:
-  // the following are shared with the CMSThread
-  SLT_msg_type  _buffer;  // communication buffer
-  Monitor       _monitor; // monitor controlling buffer
-  BasicLock     _basicLock; // used for PLL locking
-
- public:
-  static SurrogateLockerThread* make(TRAPS);
-
-  // Terminate VM with error message that SLT needed but not yet created.
-  static void report_missing_slt();
-
-  SurrogateLockerThread();
-
-  bool is_hidden_from_external_view() const     { return true; }
-
-  void loop(); // main method
-
-  void manipulatePLL(SLT_msg_type msg);
-
-};
-
 #endif // SHARE_VM_GC_SHARED_CONCURRENTGCTHREAD_HPP
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -281,6 +281,10 @@
     return UseConcMarkSweepGC;
   }
 
+  virtual bool needs_reference_pending_list_locker_thread() const {
+    return UseConcMarkSweepGC;
+  }
+
   // We don't need barriers for stores to objects in the
   // young gen and, a fortiori, for initializing stores to
   // objects therein. This applies to DefNew+Tenured and ParNew+CMS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -0,0 +1,226 @@
+/*
+ * 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 "classfile/javaClasses.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
+#include "memory/universe.hpp"
+#include "runtime/javaCalls.hpp"
+#include "utilities/preserveException.hpp"
+
+ReferencePendingListLockerThread::ReferencePendingListLockerThread() :
+  JavaThread(&start),
+  _monitor(Monitor::nonleaf, "ReferencePendingListLocker", false, Monitor::_safepoint_check_sometimes),
+  _message(NONE) {}
+
+ReferencePendingListLockerThread* ReferencePendingListLockerThread::create(TRAPS) {
+  // Create Java thread objects
+  instanceKlassHandle thread_klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL);
+  instanceHandle thread_object = thread_klass->allocate_instance_handle(CHECK_NULL);
+  Handle thread_name = java_lang_String::create_from_str("Reference Pending List Locker", CHECK_NULL);
+  Handle thread_group = Universe::system_thread_group();
+  JavaValue result(T_VOID);
+  JavaCalls::call_special(&result,
+                          thread_object,
+                          thread_klass,
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::threadgroup_string_void_signature(),
+                          thread_group,
+                          thread_name,
+                          CHECK_NULL);
+
+  {
+    MutexLocker ml(Threads_lock);
+
+    // Allocate thread
+    ReferencePendingListLockerThread* thread = new ReferencePendingListLockerThread();
+    if (thread == NULL || thread->osthread() == NULL) {
+      vm_exit_during_initialization("java.lang.OutOfMemoryError",
+                                    os::native_thread_creation_failed_msg());
+    }
+
+    // Initialize thread
+    java_lang_Thread::set_thread(thread_object(), thread);
+    java_lang_Thread::set_priority(thread_object(), NearMaxPriority);
+    java_lang_Thread::set_daemon(thread_object());
+    thread->set_threadObj(thread_object());
+
+    // Start thread
+    Threads::add(thread);
+    Thread::start(thread);
+
+    return thread;
+  }
+}
+
+void ReferencePendingListLockerThread::start(JavaThread* thread, TRAPS) {
+  ReferencePendingListLockerThread* locker_thread = static_cast<ReferencePendingListLockerThread*>(thread);
+  locker_thread->receive_and_handle_messages();
+}
+
+bool ReferencePendingListLockerThread::is_hidden_from_external_view() const {
+  return true;
+}
+
+void ReferencePendingListLockerThread::send_message(Message message) {
+  assert(message != NONE, "Should not be none");
+  MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+
+  // Wait for completion of current message
+  while (_message != NONE) {
+    ml.wait(Monitor::_no_safepoint_check_flag);
+  }
+
+  // Send new message
+  _message = message;
+  ml.notify_all();
+
+  // Wait for completion of new message
+  while (_message != NONE) {
+    ml.wait(Monitor::_no_safepoint_check_flag);
+  }
+}
+
+void ReferencePendingListLockerThread::receive_and_handle_messages() {
+  ReferencePendingListLocker pending_list_locker;
+  MonitorLockerEx ml(&_monitor);
+
+  // Main loop, never terminates
+  for (;;) {
+    // Wait for message
+    while (_message == NONE) {
+      ml.wait();
+    }
+
+    // Handle message
+    if (_message == LOCK) {
+      pending_list_locker.lock();
+    } else if (_message == UNLOCK) {
+      pending_list_locker.unlock();
+    } else {
+      ShouldNotReachHere();
+    }
+
+    // Clear message
+    _message = NONE;
+    ml.notify_all();
+  }
+}
+
+void ReferencePendingListLockerThread::lock() {
+  send_message(LOCK);
+}
+
+void ReferencePendingListLockerThread::unlock() {
+  send_message(UNLOCK);
+}
+
+bool ReferencePendingListLocker::_is_initialized = false;
+ReferencePendingListLockerThread* ReferencePendingListLocker::_locker_thread = NULL;
+
+void ReferencePendingListLocker::initialize(bool needs_locker_thread, TRAPS) {
+  if (needs_locker_thread) {
+    _locker_thread = ReferencePendingListLockerThread::create(CHECK);
+  }
+
+  _is_initialized = true;
+}
+
+bool ReferencePendingListLocker::is_initialized() {
+  return _is_initialized;
+}
+
+bool ReferencePendingListLocker::is_locked_by_self() {
+  oop pending_list_lock = java_lang_ref_Reference::pending_list_lock();
+  if (pending_list_lock == NULL) {
+    return false;
+  }
+
+  JavaThread* thread = JavaThread::current();
+  Handle handle(thread, pending_list_lock);
+  return ObjectSynchronizer::current_thread_holds_lock(thread, handle);
+}
+
+void ReferencePendingListLocker::lock() {
+  assert(!Heap_lock->owned_by_self(), "Heap_lock must not be owned by requesting thread");
+
+  if (Thread::current()->is_Java_thread()) {
+    assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized");
+
+    // We may enter this with a pending exception
+    PRESERVE_EXCEPTION_MARK;
+
+    HandleMark hm;
+    Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock());
+
+    assert(!is_locked_by_self(), "Should not be locked by self");
+
+    // Lock
+    ObjectSynchronizer::fast_enter(handle, &_basic_lock, false, THREAD);
+
+    assert(is_locked_by_self(), "Locking failed");
+
+    if (HAS_PENDING_EXCEPTION) {
+      CLEAR_PENDING_EXCEPTION;
+    }
+  } else {
+    // Delegate operation to locker thread
+    assert(_locker_thread != NULL, "Locker thread not created");
+    _locker_thread->lock();
+  }
+}
+
+void ReferencePendingListLocker::unlock() {
+  if (Thread::current()->is_Java_thread()) {
+    assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized");
+
+    // We may enter this with a pending exception
+    PRESERVE_EXCEPTION_MARK;
+
+    HandleMark hm;
+    Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock());
+
+    assert(is_locked_by_self(), "Should be locked by self");
+
+    // Notify waiters if the pending list is non-empty
+    if (java_lang_ref_Reference::pending_list() != NULL) {
+      ObjectSynchronizer::notifyall(handle, THREAD);
+    }
+
+    // Unlock
+    ObjectSynchronizer::fast_exit(handle(), &_basic_lock, THREAD);
+
+    assert(!is_locked_by_self(), "Unlocking failed");
+
+    if (HAS_PENDING_EXCEPTION) {
+      CLEAR_PENDING_EXCEPTION;
+    }
+  } else {
+    // Delegate operation to locker thread
+    assert(_locker_thread != NULL, "Locker thread not created");
+    _locker_thread->unlock();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
+#define SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/basicLock.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/exceptions.hpp"
+
+//
+// The ReferencePendingListLockerThread locks and unlocks the reference
+// pending list lock on behalf a non-Java thread, typically a concurrent
+// GC thread. This interface should not be directly accessed. All uses
+// should instead go through the ReferencePendingListLocker, which calls
+// this thread if needed.
+//
+class ReferencePendingListLockerThread : public JavaThread {
+private:
+  enum Message {
+    NONE,
+    LOCK,
+    UNLOCK
+  };
+
+  Monitor _monitor;
+  Message _message;
+
+  ReferencePendingListLockerThread();
+
+  static void start(JavaThread* thread, TRAPS);
+
+  void send_message(Message message);
+  void receive_and_handle_messages();
+
+public:
+  static ReferencePendingListLockerThread* create(TRAPS);
+
+  virtual bool is_hidden_from_external_view() const;
+
+  void lock();
+  void unlock();
+};
+
+//
+// The ReferencePendingListLocker is the main interface for locking and
+// unlocking the reference pending list lock, which needs to be held by
+// the GC when adding references to the pending list. Since this is a
+// Java-level monitor it can only be locked/unlocked by a Java thread.
+// For this reason there is an option to spawn a helper thread, the
+// ReferencePendingListLockerThread, during initialization. If a helper
+// thread is spawned all lock operations from non-Java threads will be
+// delegated to the helper thread. The helper thread is typically needed
+// by concurrent GCs.
+//
+class ReferencePendingListLocker VALUE_OBJ_CLASS_SPEC {
+private:
+  static bool                              _is_initialized;
+  static ReferencePendingListLockerThread* _locker_thread;
+  BasicLock                                _basic_lock;
+
+public:
+  static void initialize(bool needs_locker_thread, TRAPS);
+  static bool is_initialized();
+
+  static bool is_locked_by_self();
+
+  void lock();
+  void unlock();
+};
+
+#endif // SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -30,10 +30,8 @@
 #include "gc/shared/gcLocker.inline.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/vmGCOperations.hpp"
+#include "logging/log.hpp"
 #include "memory/oopFactory.hpp"
-#include "logging/log.hpp"
-#include "oops/instanceKlass.hpp"
-#include "oops/instanceRefKlass.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.hpp"
@@ -64,14 +62,11 @@
 }
 
 void VM_GC_Operation::acquire_pending_list_lock() {
-  // we may enter this with pending exception set
-  InstanceRefKlass::acquire_pending_list_lock(&_pending_list_basic_lock);
+  _pending_list_locker.lock();
 }
 
-
 void VM_GC_Operation::release_and_notify_pending_list_lock() {
-
-  InstanceRefKlass::release_and_notify_pending_list_lock(&_pending_list_basic_lock);
+  _pending_list_locker.unlock();
 }
 
 // Allocations may fail in several threads at about the same time,
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -27,6 +27,7 @@
 
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "memory/heapInspection.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/handles.hpp"
@@ -69,8 +70,10 @@
 //
 
 class VM_GC_Operation: public VM_Operation {
+ private:
+  ReferencePendingListLocker _pending_list_locker;
+
  protected:
-  BasicLock      _pending_list_basic_lock; // for refs pending list notification (PLL)
   uint           _gc_count_before;         // gc count before acquiring PLL
   uint           _full_gc_count_before;    // full gc count before acquiring PLL
   bool           _full;                    // whether a "full" collection
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -25,13 +25,8 @@
 #include "precompiled.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/systemDictionary.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
 #include "oops/instanceRefKlass.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "utilities/macros.hpp"
-#include "utilities/preserveException.hpp"
 
 void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) {
   // Clear the nonstatic oop-map entries corresponding to referent
@@ -87,48 +82,3 @@
     guarantee(InstanceKlass::cast(next->klass())->is_reference_instance_klass(), "next field verify failed");
   }
 }
-
-bool InstanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
-  if (java_lang_ref_Reference::pending_list_lock() == NULL) return false;
-  Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
-  return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
-}
-
-void InstanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
-  // we may enter this with pending exception set
-  PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
-
-  // Create a HandleMark in case we retry a GC multiple times.
-  // Each time we attempt the GC, we allocate the handle below
-  // to hold the pending list lock. We want to free this handle.
-  HandleMark hm;
-
-  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
-  ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
-  assert(ObjectSynchronizer::current_thread_holds_lock(
-           JavaThread::current(), h_lock),
-         "Locking should have succeeded");
-  if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
-}
-
-void InstanceRefKlass::release_and_notify_pending_list_lock(
-  BasicLock *pending_list_basic_lock) {
-  // we may enter this with pending exception set
-  PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
-
-  // Create a HandleMark in case we retry a GC multiple times.
-  // Each time we attempt the GC, we allocate the handle below
-  // to hold the pending list lock. We want to free this handle.
-  HandleMark hm;
-
-  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
-  assert(ObjectSynchronizer::current_thread_holds_lock(
-           JavaThread::current(), h_lock),
-         "Lock should be held");
-  // Notify waiters on pending lists lock if there is any reference.
-  if (java_lang_ref_Reference::pending_list() != NULL) {
-    ObjectSynchronizer::notifyall(h_lock, THREAD);
-  }
-  ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD);
-  if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
-}
--- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -118,10 +118,6 @@
   ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_BACKWARDS)
 #endif // INCLUDE_ALL_GCS
 
-  static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock);
-  static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock);
-  static bool owns_pending_list_lock(JavaThread* thread);
-
   // Update non-static oop maps so 'referent', 'nextPending' and
   // 'discovered' will look like non-oops
   static void update_nonstatic_oop_maps(Klass* k);
--- a/hotspot/src/share/vm/oops/method.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/oops/method.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -30,6 +30,7 @@
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/generation.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/bytecodeTracer.hpp"
 #include "interpreter/bytecodes.hpp"
@@ -374,7 +375,7 @@
 
   // Do not profile method if current thread holds the pending list lock,
   // which avoids deadlock for acquiring the MethodData_lock.
-  if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
+  if (ReferencePendingListLocker::is_locked_by_self()) {
     return;
   }
 
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -70,7 +70,6 @@
 Monitor* Threads_lock                 = NULL;
 Monitor* CGC_lock                     = NULL;
 Monitor* STS_lock                     = NULL;
-Monitor* SLT_lock                     = NULL;
 Monitor* FullGCCount_lock             = NULL;
 Mutex*   SATB_Q_FL_lock               = NULL;
 Monitor* SATB_Q_CBL_mon               = NULL;
@@ -242,9 +241,6 @@
   def(JNIGlobalHandle_lock         , Mutex  , nonleaf,     true,  Monitor::_safepoint_check_always);     // locks JNIHandleBlockFreeList_lock
   def(JNICritical_lock             , Monitor, nonleaf,     true,  Monitor::_safepoint_check_always);     // used for JNI critical regions
   def(AdapterHandlerLibrary_lock   , Mutex  , nonleaf,     true,  Monitor::_safepoint_check_always);
-  if (UseConcMarkSweepGC) {
-    def(SLT_lock                   , Monitor, nonleaf,     false, Monitor::_safepoint_check_never);      // used in CMS GC for locking PLL lock
-  }
 
   def(Heap_lock                    , Monitor, nonleaf+1,   false, Monitor::_safepoint_check_sometimes);
   def(JfieldIdCreation_lock        , Mutex  , nonleaf+1,   true,  Monitor::_safepoint_check_always);     // jfieldID, Used in VM_Operation
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Thu Mar 17 08:07:53 2016 +0100
@@ -65,7 +65,6 @@
 extern Monitor* CGC_lock;                        // used for coordination between
                                                  // fore- & background GC threads.
 extern Monitor* STS_lock;                        // used for joining/leaving SuspendibleThreadSet.
-extern Monitor* SLT_lock;                        // used in CMS GC for acquiring PLL
 extern Monitor* FullGCCount_lock;                // in support of "concurrent" full gc
 extern Mutex*   SATB_Q_FL_lock;                  // Protects SATB Q
                                                  // buffer free list.
--- a/hotspot/src/share/vm/runtime/thread.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -34,6 +34,7 @@
 #include "compiler/compileTask.hpp"
 #include "gc/shared/gcId.hpp"
 #include "gc/shared/gcLocker.inline.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
@@ -3650,18 +3651,9 @@
   // anymore. We call vm_exit_during_initialization directly instead.
   SystemDictionary::compute_java_system_loader(CHECK_(JNI_ERR));
 
-#if INCLUDE_ALL_GCS
-  // Support for ConcurrentMarkSweep. This should be cleaned up
-  // and better encapsulated. The ugly nested if test would go away
-  // once things are properly refactored. XXX YSR
-  if (UseConcMarkSweepGC || UseG1GC) {
-    if (UseConcMarkSweepGC) {
-      ConcurrentMarkSweepThread::makeSurrogateLockerThread(CHECK_JNI_ERR);
-    } else {
-      ConcurrentMarkThread::makeSurrogateLockerThread(CHECK_JNI_ERR);
-    }
-  }
-#endif // INCLUDE_ALL_GCS
+  // Initialize reference pending list locker
+  bool needs_locker_thread = Universe::heap()->needs_reference_pending_list_locker_thread();
+  ReferencePendingListLocker::initialize(needs_locker_thread, CHECK_JNI_ERR);
 
   // Always call even when there are not JVMTI environments yet, since environments
   // may be attached late and JVMTI must track phases of VM execution
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Mar 17 08:07:53 2016 +0100
@@ -54,6 +54,7 @@
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/generation.hpp"
 #include "gc/shared/generationSpec.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "gc/shared/space.hpp"
 #include "interpreter/bytecodeInterpreter.hpp"
 #include "interpreter/bytecodes.hpp"
@@ -1692,6 +1693,7 @@
            declare_type(JavaThread, Thread)                               \
            declare_type(JvmtiAgentThread, JavaThread)                     \
            declare_type(ServiceThread, JavaThread)                        \
+           declare_type(ReferencePendingListLockerThread, JavaThread)     \
   declare_type(CompilerThread, JavaThread)                                \
   declare_type(CodeCacheSweeperThread, JavaThread)                        \
   declare_toplevel_type(OSThread)                                         \