1 /* 2 * Copyright (c) 2017, 2018, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 25 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP 26 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP 27 28 #include "code/codeCache.hpp" 29 #include "memory/allocation.hpp" 30 #include "memory/iterator.hpp" 31 #include "gc_implementation/shenandoah/shenandoahSharedVariables.hpp" 32 33 class ShenandoahHeap; 34 class ShenandoahHeapRegion; 35 class ShenandoahCodeRootsLock; 36 37 class ShenandoahCodeRootsIterator VALUE_OBJ_CLASS_SPEC { 38 friend class ShenandoahCodeRoots; 39 protected: 40 ShenandoahHeap* _heap; 41 ParallelCodeCacheIterator _par_iterator; 42 ShenandoahSharedFlag _seq_claimed; 43 volatile jlong _claimed; 44 protected: 45 ShenandoahCodeRootsIterator(); 46 ~ShenandoahCodeRootsIterator(); 47 48 template<bool CSET_FILTER> 49 void dispatch_parallel_blobs_do(CodeBlobClosure *f); 50 51 template<bool CSET_FILTER> 52 void fast_parallel_blobs_do(CodeBlobClosure *f); 53 }; 54 55 class ShenandoahAllCodeRootsIterator : public ShenandoahCodeRootsIterator { 56 public: 57 ShenandoahAllCodeRootsIterator() : ShenandoahCodeRootsIterator() {}; 58 void possibly_parallel_blobs_do(CodeBlobClosure *f); 59 }; 60 61 class ShenandoahCsetCodeRootsIterator : public ShenandoahCodeRootsIterator { 62 public: 63 ShenandoahCsetCodeRootsIterator() : ShenandoahCodeRootsIterator() {}; 64 void possibly_parallel_blobs_do(CodeBlobClosure* f); 65 }; 66 67 class ShenandoahCodeRoots : public CHeapObj<mtGC> { 68 friend class ShenandoahHeap; 69 friend class ShenandoahCodeRootsLock; 70 friend class ShenandoahCodeRootsIterator; 71 72 public: 73 static void initialize(); 74 static void add_nmethod(nmethod* nm); 75 static void remove_nmethod(nmethod* nm); 76 77 /** 78 * Provides the iterator over all nmethods in the code cache that have oops. 79 * @return 80 */ 81 static ShenandoahAllCodeRootsIterator iterator(); 82 83 /** 84 * Provides the iterator over nmethods that have at least one oop in collection set. 85 * @return 86 */ 87 static ShenandoahCsetCodeRootsIterator cset_iterator(); 88 89 private: 90 static volatile jint _recorded_nmethods_lock; 91 static GrowableArray<nmethod*>* _recorded_nmethods; 92 93 static void fast_add_nmethod(nmethod* nm); 94 static void fast_remove_nmethod(nmethod* nm); 95 96 static void acquire_lock(bool write) { 97 volatile jint* loc = &_recorded_nmethods_lock; 98 if (write) { 99 while ((OrderAccess::load_acquire(loc) != 0) || 100 Atomic::cmpxchg(-1, loc, 0) != 0) { 101 SpinPause(); 102 } 103 assert (*loc == -1, "acquired for write"); 104 } else { 105 while (true) { 106 jint cur = OrderAccess::load_acquire(loc); 107 if (cur >= 0) { 108 if (Atomic::cmpxchg(cur + 1, loc, cur) == cur) { 109 // Success! 110 return; 111 } 112 } 113 SpinPause(); 114 } 115 assert (*loc > 1, "acquired for read"); 116 } 117 } 118 119 static void release_lock(bool write) { 120 volatile jint* loc = &ShenandoahCodeRoots::_recorded_nmethods_lock; 121 if (write) { 122 OrderAccess::release_store_fence(loc, 0); 123 } else { 124 Atomic::dec(loc); 125 } 126 } 127 }; 128 129 // Very simple unranked read-write lock 130 class ShenandoahCodeRootsLock : public StackObj { 131 friend class ShenandoahCodeRoots; 132 private: 133 const bool _write; 134 public: 135 ShenandoahCodeRootsLock(bool write) : _write(write) { 136 ShenandoahCodeRoots::acquire_lock(write); 137 } 138 139 ~ShenandoahCodeRootsLock() { 140 ShenandoahCodeRoots::release_lock(_write); 141 } 142 }; 143 144 #endif //SHARE_VM_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP