1 /* 2 * Copyright (c) 2019, Red Hat, Inc. All rights reserved. 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 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP 24 #define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP 25 26 #include "gc/shared/barrierSetNMethod.hpp" 27 #include "gc/shenandoah/shenandoahAsserts.hpp" 28 #include "gc/shenandoah/shenandoahClosures.hpp" 29 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 30 #include "gc/shenandoah/shenandoahNMethod.inline.hpp" 31 #include "gc/shenandoah/shenandoahSafepoint.hpp" 32 #include "gc/shenandoah/shenandoahTraversalGC.hpp" 33 #include "oops/compressedOops.inline.hpp" 34 #include "runtime/atomic.hpp" 35 #include "runtime/thread.hpp" 36 37 ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() : 38 _heap(ShenandoahHeap::heap()), 39 _mark_context(ShenandoahHeap::heap()->marking_context()) { 40 } 41 42 bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) { 43 if (CompressedOops::is_null(obj)) { 44 return false; 45 } 46 if (_heap->in_collection_set(obj)) { 47 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); 48 } 49 shenandoah_assert_not_forwarded_if(NULL, obj, 50 (ShenandoahHeap::heap()->is_concurrent_mark_in_progress() || 51 ShenandoahHeap::heap()->is_concurrent_traversal_in_progress())); 52 return _mark_context->is_marked(obj); 53 } 54 55 ShenandoahForwardedIsAliveNoCSetCheckClosure::ShenandoahForwardedIsAliveNoCSetCheckClosure() : 56 _mark_context(ShenandoahHeap::heap()->marking_context()) { 57 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only used at a safepoint"); 58 } 59 60 bool ShenandoahForwardedIsAliveNoCSetCheckClosure::do_object_b(oop obj) { 61 if (CompressedOops::is_null(obj)) { 62 return false; 63 } 64 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); 65 return _mark_context->is_marked(obj); 66 } 67 68 ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() : 69 _mark_context(ShenandoahHeap::heap()->marking_context()) { 70 } 71 72 bool ShenandoahIsAliveClosure::do_object_b(oop obj) { 73 if (CompressedOops::is_null(obj)) { 74 return false; 75 } 76 shenandoah_assert_not_forwarded(NULL, obj); 77 return _mark_context->is_marked(obj); 78 } 79 80 BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() { 81 return ShenandoahHeap::heap()->has_forwarded_objects() ? 82 reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl) : 83 reinterpret_cast<BoolObjectClosure*>(&_alive_cl); 84 } 85 86 ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() : 87 _heap(ShenandoahHeap::heap()) { 88 } 89 90 template <class T> 91 void ShenandoahUpdateRefsClosure::do_oop_work(T* p) { 92 T o = RawAccess<>::oop_load(p); 93 if (!CompressedOops::is_null(o)) { 94 oop obj = CompressedOops::decode_not_null(o); 95 _heap->update_with_forwarded_not_null(p, obj); 96 } 97 } 98 99 void ShenandoahUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); } 100 void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); } 101 102 ShenandoahTraversalUpdateRefsClosure::ShenandoahTraversalUpdateRefsClosure() : 103 _heap(ShenandoahHeap::heap()), 104 _traversal_set(ShenandoahHeap::heap()->traversal_gc()->traversal_set()) { 105 assert(_heap->is_traversal_mode(), "Why we here?"); 106 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 107 } 108 109 template <class T> 110 void ShenandoahTraversalUpdateRefsClosure::do_oop_work(T* p) { 111 T o = RawAccess<>::oop_load(p); 112 if (!CompressedOops::is_null(o)) { 113 oop obj = CompressedOops::decode_not_null(o); 114 if (_heap->in_collection_set(obj) || _traversal_set->is_in((HeapWord*)obj)) { 115 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); 116 RawAccess<IS_NOT_NULL>::oop_store(p, obj); 117 } else { 118 shenandoah_assert_not_forwarded(p, obj); 119 } 120 } 121 } 122 123 void ShenandoahTraversalUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); } 124 void ShenandoahTraversalUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); } 125 126 ShenandoahEvacuateUpdateRootsClosure::ShenandoahEvacuateUpdateRootsClosure() : 127 _heap(ShenandoahHeap::heap()), _thread(Thread::current()) { 128 } 129 130 template <class T> 131 void ShenandoahEvacuateUpdateRootsClosure::do_oop_work(T* p) { 132 assert(_heap->is_concurrent_root_in_progress(), "Only do this when evacuation is in progress"); 133 134 T o = RawAccess<>::oop_load(p); 135 if (! CompressedOops::is_null(o)) { 136 oop obj = CompressedOops::decode_not_null(o); 137 if (_heap->in_collection_set(obj)) { 138 assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress"); 139 shenandoah_assert_marked(p, obj); 140 oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); 141 if (resolved == obj) { 142 resolved = _heap->evacuate_object(obj, _thread); 143 } 144 RawAccess<IS_NOT_NULL>::oop_store(p, resolved); 145 } 146 } 147 } 148 void ShenandoahEvacuateUpdateRootsClosure::do_oop(oop* p) { 149 do_oop_work(p); 150 } 151 152 void ShenandoahEvacuateUpdateRootsClosure::do_oop(narrowOop* p) { 153 do_oop_work(p); 154 } 155 156 ShenandoahEvacUpdateOopStorageRootsClosure::ShenandoahEvacUpdateOopStorageRootsClosure() : 157 _heap(ShenandoahHeap::heap()), _thread(Thread::current()) { 158 } 159 160 void ShenandoahEvacUpdateOopStorageRootsClosure::do_oop(oop* p) { 161 assert(_heap->is_concurrent_root_in_progress(), "Only do this when evacuation is in progress"); 162 163 oop obj = RawAccess<>::oop_load(p); 164 if (! CompressedOops::is_null(obj)) { 165 if (_heap->in_collection_set(obj)) { 166 assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress"); 167 shenandoah_assert_marked(p, obj); 168 oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); 169 if (resolved == obj) { 170 resolved = _heap->evacuate_object(obj, _thread); 171 } 172 173 Atomic::cmpxchg(p, obj, resolved); 174 } 175 } 176 } 177 178 void ShenandoahEvacUpdateOopStorageRootsClosure::do_oop(narrowOop* p) { 179 ShouldNotReachHere(); 180 } 181 182 ShenandoahCodeBlobAndDisarmClosure::ShenandoahCodeBlobAndDisarmClosure(OopClosure* cl) : 183 CodeBlobToOopClosure(cl, true /* fix_relocations */), 184 _bs(BarrierSet::barrier_set()->barrier_set_nmethod()) { 185 } 186 187 void ShenandoahCodeBlobAndDisarmClosure::do_code_blob(CodeBlob* cb) { 188 nmethod* const nm = cb->as_nmethod_or_null(); 189 if (nm != NULL && nm->oops_do_try_claim()) { 190 assert(!ShenandoahNMethod::gc_data(nm)->is_unregistered(), "Should not be here"); 191 CodeBlobToOopClosure::do_code_blob(cb); 192 _bs->disarm(nm); 193 } 194 } 195 196 #ifdef ASSERT 197 template <class T> 198 void ShenandoahAssertNotForwardedClosure::do_oop_work(T* p) { 199 T o = RawAccess<>::oop_load(p); 200 if (!CompressedOops::is_null(o)) { 201 oop obj = CompressedOops::decode_not_null(o); 202 shenandoah_assert_not_forwarded(p, obj); 203 } 204 } 205 206 void ShenandoahAssertNotForwardedClosure::do_oop(narrowOop* p) { do_oop_work(p); } 207 void ShenandoahAssertNotForwardedClosure::do_oop(oop* p) { do_oop_work(p); } 208 #endif 209 210 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP