--- old/src/hotspot/share/gc/z/zDriver.cpp 2018-01-22 20:21:10.043852104 +0100 +++ new/src/hotspot/share/gc/z/zDriver.cpp 2018-01-22 20:21:09.715840763 +0100 @@ -41,7 +41,7 @@ static const ZStatPhaseConcurrent ZPhaseConcurrentMark("Concurrent Mark"); static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue"); static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End"); -static const ZStatPhaseConcurrent ZPhaseConcurrentReferencesProcessing("Concurrent References Processing"); +static const ZStatPhaseConcurrent ZPhaseConcurrentWeakProcessing("Concurrent Weak Processing"); static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set"); static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages"); static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set"); @@ -325,8 +325,8 @@ // Phase 4: Concurrent Reference Processing { - ZStatTimer timer(ZPhaseConcurrentReferencesProcessing); - ZHeap::heap()->process_and_enqueue_references(); + ZStatTimer timer(ZPhaseConcurrentWeakProcessing); + ZHeap::heap()->concurrent_weak_processing(); } // Phase 5: Concurrent Reset Relocation Set --- old/src/hotspot/share/gc/z/zHeap.cpp 2018-01-22 20:21:10.475867043 +0100 +++ new/src/hotspot/share/gc/z/zHeap.cpp 2018-01-22 20:21:10.151855839 +0100 @@ -22,6 +22,7 @@ */ #include "precompiled.hpp" +#include "gc/shared/oopStorage.hpp" #include "gc/z/zAddress.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zHeap.inline.hpp" @@ -48,12 +49,14 @@ #include "utilities/align.hpp" #include "utilities/debug.hpp" -static const ZStatSampler ZSamplerHeapUsedBeforeMark("Memory", "Heap Used Before Mark", ZStatUnitBytes); -static const ZStatSampler ZSamplerHeapUsedAfterMark("Memory", "Heap Used After Mark", ZStatUnitBytes); -static const ZStatSampler ZSamplerHeapUsedBeforeRelocation("Memory", "Heap Used Before Relocation", ZStatUnitBytes); -static const ZStatSampler ZSamplerHeapUsedAfterRelocation("Memory", "Heap Used After Relocation", ZStatUnitBytes); -static const ZStatCounter ZCounterUndoPageAllocation("Memory", "Undo Page Allocation", ZStatUnitOpsPerSecond); -static const ZStatCounter ZCounterOutOfMemory("Memory", "Out Of Memory", ZStatUnitOpsPerSecond); +static const ZStatSampler ZSamplerHeapUsedBeforeMark("Memory", "Heap Used Before Mark", ZStatUnitBytes); +static const ZStatSampler ZSamplerHeapUsedAfterMark("Memory", "Heap Used After Mark", ZStatUnitBytes); +static const ZStatSampler ZSamplerHeapUsedBeforeRelocation("Memory", "Heap Used Before Relocation", ZStatUnitBytes); +static const ZStatSampler ZSamplerHeapUsedAfterRelocation("Memory", "Heap Used After Relocation", ZStatUnitBytes); +static const ZStatCounter ZCounterUndoPageAllocation("Memory", "Undo Page Allocation", ZStatUnitOpsPerSecond); +static const ZStatCounter ZCounterOutOfMemory("Memory", "Out Of Memory", ZStatUnitOpsPerSecond); +static const ZStatSubPhase ZPhaseConcurrentReferencesProcessing("Concurrent References Processing"); +static const ZStatSubPhase ZPhaseConcurrentWeakRootsProcessing("Concurrent Weak Roots Processing"); ZHeap* ZHeap::_heap = NULL; @@ -65,6 +68,7 @@ _pagetable(), _mark(&_workers, &_pagetable), _reference_processor(&_workers), + _weak_roots_processor(&_workers), _relocate(&_workers), _relocation_set(), _serviceability(heap_min_size(), heap_max_size()) { @@ -314,27 +318,6 @@ _workers.run_parallel(&task); } -class ZProcessWeakRootsTask : public ZTask { -private: - ZWeakRootsIterator _weak_roots; - -public: - ZProcessWeakRootsTask() : - ZTask("ZProcessWeakRootsTask"), - _weak_roots() {} - - virtual void work() { - ZPhantomIsAliveObjectClosure is_alive; - ZPhantomKeepAliveOopClosure keep_alive; - _weak_roots.unlink_or_oops_do(&is_alive, &keep_alive); - } -}; - -void ZHeap::process_weak_roots() { - ZProcessWeakRootsTask task; - _workers.run_parallel(&task); -} - bool ZHeap::mark_end() { assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); @@ -364,7 +347,7 @@ ZResurrection::block(); // Clean weak roots - process_weak_roots(); + _weak_roots_processor.process_weak_roots(); // Verification if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) { @@ -378,9 +361,16 @@ _reference_processor.set_soft_reference_policy(clear); } -void ZHeap::process_and_enqueue_references() { - // Process and enqueue discovered references - _reference_processor.process_and_enqueue_references(); +void ZHeap::concurrent_weak_processing() { + { + ZStatTimer timer(ZPhaseConcurrentReferencesProcessing); + _reference_processor.process_and_enqueue_references(); + } + + { + ZStatTimer timer(ZPhaseConcurrentWeakRootsProcessing); + _weak_roots_processor.process_concurrent_weak_roots(); + } // Unblock resurrection of weak/phantom references ZResurrection::unblock(); --- old/src/hotspot/share/gc/z/zHeap.hpp 2018-01-22 20:21:10.915882257 +0100 +++ new/src/hotspot/share/gc/z/zHeap.hpp 2018-01-22 20:21:10.587870915 +0100 @@ -40,6 +40,7 @@ #include "gc/z/zRelocationSet.hpp" #include "gc/z/zRelocationSetSelector.hpp" #include "gc/z/zRootsIterator.hpp" +#include "gc/z/zWeakRootsProcessor.hpp" #include "gc/z/zServiceability.hpp" #include "gc/z/zWorkers.hpp" #include "memory/allocation.hpp" @@ -57,6 +58,7 @@ ZPageTable _pagetable; ZMark _mark; ZReferenceProcessor _reference_processor; + ZWeakRootsProcessor _weak_roots_processor; ZRelocate _relocate; ZRelocationSet _relocation_set; ZServiceability _serviceability; @@ -68,7 +70,6 @@ void out_of_memory(); void flip_views(); void fixup_partial_loads(); - void process_weak_roots(); public: static ZHeap* heap(); @@ -111,7 +112,9 @@ // Reference processing ReferenceDiscoverer* reference_discoverer(); void set_soft_reference_policy(bool clear); - void process_and_enqueue_references(); + + // Weak handles/references processing + void concurrent_weak_processing(); // Page allocation ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags); --- old/src/hotspot/share/gc/z/zOopClosures.hpp 2018-01-22 20:21:11.347897196 +0100 +++ new/src/hotspot/share/gc/z/zOopClosures.hpp 2018-01-22 20:21:11.019885854 +0100 @@ -82,6 +82,15 @@ virtual void do_oop(narrowOop* p); }; +class ZPhantomCleanOopClosure : public OopClosure { +private: + void clean(volatile oop* p); + +public: + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); +}; + class ZVerifyHeapOopClosure : public ExtendedOopClosure { private: const oop _base; --- old/src/hotspot/share/gc/z/zOopClosures.inline.hpp 2018-01-22 20:21:11.775911996 +0100 +++ new/src/hotspot/share/gc/z/zOopClosures.inline.hpp 2018-01-22 20:21:11.451900791 +0100 @@ -29,6 +29,7 @@ #include "gc/z/zOop.inline.hpp" #include "gc/z/zOopClosures.hpp" #include "oops/oop.inline.hpp" +#include "runtime/atomic.hpp" #include "utilities/debug.hpp" inline void ZLoadBarrierOopClosure::do_oop_nv(oop* p) { @@ -99,4 +100,21 @@ ShouldNotReachHere(); } +inline void ZPhantomCleanOopClosure::clean(volatile oop* p) { + oop obj = *p; + if (ZBarrier::is_alive_barrier_on_phantom_oop(obj)) { + ZBarrier::keep_alive_barrier_on_phantom_oop_field(p); + } else { + Atomic::cmpxchg(oop(NULL), p, obj); + } +} + +inline void ZPhantomCleanOopClosure::do_oop(oop* p) { + clean(p); +} + +inline void ZPhantomCleanOopClosure::do_oop(narrowOop* p) { + ShouldNotReachHere(); +} + #endif // SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP --- old/src/hotspot/share/gc/z/zRootsIterator.cpp 2018-01-22 20:21:12.223927487 +0100 +++ new/src/hotspot/share/gc/z/zRootsIterator.cpp 2018-01-22 20:21:11.875915454 +0100 @@ -69,6 +69,9 @@ static const ZStatSubPhase ZSubPhasePauseWeakRootsSymbolTable("Pause Weak Roots SymbolTable"); static const ZStatSubPhase ZSubPhasePauseWeakRootsStringTable("Pause Weak Roots StringTable"); +static const ZStatSubPhase ZSubPhaseConcurrentWeakRoots("Concurrent Weak Roots"); +static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsJNIWeakHandles("Concurrent Weak Roots JNIWeakHandles"); + template ZSerialOopsDo::ZSerialOopsDo(T* iter) : _iter(iter), @@ -296,7 +299,9 @@ ZStatTimer timer(ZSubPhasePauseWeakRoots); _symbol_table.unlink_or_oops_do(is_alive, cl); if (ZWeakRoots) { - _jni_weak_handles.unlink_or_oops_do(is_alive, cl); + if (!ZConcurrentJNIWeakGlobalHandles) { + _jni_weak_handles.unlink_or_oops_do(is_alive, cl); + } _jvmti_weak_export.unlink_or_oops_do(is_alive, cl); _trace.unlink_or_oops_do(is_alive, cl); _string_table.unlink_or_oops_do(is_alive, cl); @@ -308,6 +313,28 @@ unlink_or_oops_do(&always_alive, cl); } +void ZConcurrentWeakRootsIterator::do_jni_weak_handles(OopClosure* cl) { + ZStatTimer timer(ZSubPhaseConcurrentWeakRootsJNIWeakHandles); + _par_state.oops_do(cl); +} + +ZConcurrentWeakRootsIterator::ZConcurrentWeakRootsIterator() : + _par_state(JNIHandles::weak_global_handles()), + _jni_weak_handles(this) { +} + +ZConcurrentWeakRootsIterator::~ZConcurrentWeakRootsIterator() { +} + +void ZConcurrentWeakRootsIterator::oops_do(OopClosure* cl) { + ZStatTimer timer(ZSubPhaseConcurrentWeakRoots); + if (ZWeakRoots) { + if (ZConcurrentJNIWeakGlobalHandles) { + _jni_weak_handles.oops_do(cl); + } + } +} + ZThreadRootsIterator::ZThreadRootsIterator() : _threads(this) { assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); --- old/src/hotspot/share/gc/z/zRootsIterator.hpp 2018-01-22 20:21:12.679943254 +0100 +++ new/src/hotspot/share/gc/z/zRootsIterator.hpp 2018-01-22 20:21:12.343931636 +0100 @@ -24,6 +24,7 @@ #ifndef SHARE_GC_Z_ZROOTSITERATOR_HPP #define SHARE_GC_Z_ZROOTSITERATOR_HPP +#include "gc/shared/oopStorage.hpp" #include "memory/allocation.hpp" #include "memory/iterator.hpp" #include "utilities/globalDefinitions.hpp" @@ -131,6 +132,21 @@ void oops_do(OopClosure* cl); }; +class ZConcurrentWeakRootsIterator VALUE_OBJ_CLASS_SPEC { +private: + OopStorage::ParState _par_state; + + void do_jni_weak_handles(OopClosure* cl); + + ZParallelOopsDo _jni_weak_handles; + +public: + ZConcurrentWeakRootsIterator(); + ~ZConcurrentWeakRootsIterator(); + + void oops_do(OopClosure* cl); +}; + class ZThreadRootsIterator VALUE_OBJ_CLASS_SPEC { private: void do_threads(OopClosure* cl); --- old/src/hotspot/share/runtime/globals.hpp 2018-01-22 20:21:13.123958607 +0100 +++ new/src/hotspot/share/runtime/globals.hpp 2018-01-22 20:21:12.779946712 +0100 @@ -1440,6 +1440,9 @@ product(bool, ZWeakRoots, true, \ "Treat JNI WeakGlobalRefs and StringTable as weak roots") \ \ + product(bool, ZConcurrentJNIWeakGlobalHandles, true, \ + "Clean JNI WeakGlobalRefs concurrently") \ + \ product(size_t, ZMarkStacksMax, NOT_LP64(512*M) LP64_ONLY(8*G), \ "Maximum number of bytes allocated for marking stacks") \ range(32*M, NOT_LP64(512*M) LP64_ONLY(1024*G)) \ --- old/src/hotspot/share/runtime/jniHandles.cpp 2018-01-22 20:21:13.635976312 +0100 +++ new/src/hotspot/share/runtime/jniHandles.cpp 2018-01-22 20:21:13.299964694 +0100 @@ -191,6 +191,11 @@ } +OopStorage* JNIHandles::weak_global_handles() { + return _weak_global_handles; +} + + void JNIHandles::initialize() { _global_handles = new OopStorage("JNI Global", JNIGlobalAlloc_lock, --- old/src/hotspot/share/runtime/jniHandles.hpp 2018-01-22 20:21:14.075991526 +0100 +++ new/src/hotspot/share/runtime/jniHandles.hpp 2018-01-22 20:21:13.743980047 +0100 @@ -116,6 +116,8 @@ static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); // Traversal of weak global handles. static void weak_oops_do(OopClosure* f); + // Expose the _weak_globa_handles to the GCs that want to do more exotic iterations. + static OopStorage* weak_global_handles(); }; --- /dev/null 2018-01-12 12:14:44.065206906 +0100 +++ new/src/hotspot/share/gc/z/zWeakRootsProcessor.cpp 2018-01-22 20:21:14.183995261 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zHeap.inline.hpp" +#include "gc/z/zOopClosures.inline.hpp" +#include "gc/z/zStat.hpp" +#include "gc/z/zTask.hpp" +#include "gc/z/zThread.hpp" +#include "runtime/jniHandles.hpp" + +ZWeakRootsProcessor::ZWeakRootsProcessor(ZWorkers* workers) : + _workers(workers) {} + +class ZProcessWeakRootsTask : public ZTask { +private: + ZWeakRootsIterator _weak_roots; + +public: + ZProcessWeakRootsTask() : + ZTask("ZProcessWeakRootsTask"), + _weak_roots() {} + + virtual void work() { + ZPhantomIsAliveObjectClosure is_alive; + ZPhantomKeepAliveOopClosure keep_alive; + _weak_roots.unlink_or_oops_do(&is_alive, &keep_alive); + } +}; + +void ZWeakRootsProcessor::process_weak_roots() { + ZProcessWeakRootsTask task; + _workers->run_parallel(&task); +} + +class ZProcessConcurrentWeakRootsTask : public ZTask { +private: + ZConcurrentWeakRootsIterator _concurrent_weak_roots; + +public: + ZProcessConcurrentWeakRootsTask() : + ZTask("ZProcessConccurentWeakRootsTask"), + _concurrent_weak_roots() {} + + virtual void work() { + ZPhantomCleanOopClosure cleaning_closure; + _concurrent_weak_roots.oops_do(&cleaning_closure); + } +}; + +void ZWeakRootsProcessor::process_concurrent_weak_roots() { + ZProcessConcurrentWeakRootsTask task; + _workers->run_concurrent(&task); +} --- /dev/null 2018-01-12 12:14:44.065206906 +0100 +++ new/src/hotspot/share/gc/z/zWeakRootsProcessor.hpp 2018-01-22 20:21:14.656011582 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_VM_GC_Z_ZWEAKROOTSPROCESSOR_HPP +#define SHARE_VM_GC_Z_ZWEAKROOTSPROCESSOR_HPP + +#include "gc/z/zValue.hpp" + +class ZWorkers; + +class ZWeakRootsProcessor { +private: + ZWorkers* const _workers; + +public: + ZWeakRootsProcessor(ZWorkers* workers); + + void process_weak_roots(); + void process_concurrent_weak_roots(); +}; + +#endif // SHARE_VM_GC_Z_ZWEAKROOTSPROCESSOR_HPP