# HG changeset patch # User pliden # Date 1458198473 -3600 # Node ID af29e306e50be97ca7c94869f102a6b039682441 # Parent ea9e0371b8e6c057937b744eab4e27300596e2ed 8151601: Cleanup locking of the Reference pending list Reviewed-by: brutisso, stefank diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java --- 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); } } diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js --- 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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/ci/ciReplay.cpp --- 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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/compiler/compileBroker.cpp --- 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; } diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp --- 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); -} diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp --- 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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp --- 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(); } } diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp --- 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; } }; diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp --- 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) \ diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp --- 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); -} diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp --- 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. diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp --- 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); diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp --- 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(); } } diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp --- 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(); diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/collectedHeap.hpp --- 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. diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp --- 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."); -} diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp --- 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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/genCollectedHeap.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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp --- /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(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(); + } +} diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp --- /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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/vmGCOperations.cpp --- 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, diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/gc/shared/vmGCOperations.hpp --- 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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/oops/instanceRefKlass.cpp --- 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; -} diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/oops/instanceRefKlass.hpp --- 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); diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/oops/method.cpp --- 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; } diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/runtime/mutexLocker.cpp --- 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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/runtime/mutexLocker.hpp --- 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. diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/runtime/thread.cpp --- 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 diff -r ea9e0371b8e6 -r af29e306e50b hotspot/src/share/vm/runtime/vmStructs.cpp --- 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) \