1 /* 2 * Copyright (c) 2015, 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 #ifndef SHARE_VM_GC_SHENANDOAH_BROOKSPOINTER_INLINE_HPP 25 #define SHARE_VM_GC_SHENANDOAH_BROOKSPOINTER_INLINE_HPP 26 27 #include "gc/shenandoah/brooksPointer.hpp" 28 #include "gc/shenandoah/shenandoahHeapRegion.hpp" 29 #include "runtime/atomic.hpp" 30 31 inline HeapWord** BrooksPointer::brooks_ptr_addr(oop obj) { 32 return (HeapWord**)((HeapWord*) obj + word_offset()); 33 } 34 35 inline void BrooksPointer::initialize(oop obj) { 36 #ifdef ASSERT 37 log_develop_trace(gc)("Init forwardee for "PTR_FORMAT" to self", p2i(obj)); 38 39 assert(UseShenandoahGC, "must only be called when Shenandoah is used."); 40 assert(obj != NULL, "oop is not NULL"); 41 assert(ShenandoahHeap::heap()->is_in(obj), "oop must point to a heap address"); 42 #endif 43 44 *brooks_ptr_addr(obj) = (HeapWord*) obj; 45 } 46 47 inline void BrooksPointer::set_forwardee(oop holder, oop update) { 48 #ifdef ASSERT 49 log_develop_trace(gc)("Setting forwardee to "PTR_FORMAT" = "PTR_FORMAT, p2i(holder), p2i(update)); 50 51 assert(UseShenandoahGC, "must only be called when Shenandoah is used."); 52 assert(holder != NULL, "holder should not be NULL"); 53 assert(update != NULL, "update should not be NULL"); 54 assert(ShenandoahHeap::heap()->is_in(holder), "holder must point to a heap address"); 55 assert(ShenandoahHeap::heap()->is_in(update), "update must point to a heap address"); 56 57 assert (holder->klass() == update->klass(), "klasses should match"); 58 59 assert(!oopDesc::unsafe_equals(holder, update), "forwarding should make progress"); 60 assert(ShenandoahHeap::heap()->heap_region_containing(holder) != 61 ShenandoahHeap::heap()->heap_region_containing(update), "forwarding should be across regions"); 62 assert( ShenandoahHeap::heap()->in_cset_fast_test((HeapWord*) holder), "holder should be in collection set"); 63 assert(!ShenandoahHeap::heap()->in_cset_fast_test((HeapWord*) update), "update should not be in collection set"); 64 #endif 65 66 *brooks_ptr_addr(holder) = (HeapWord*) update; 67 } 68 69 inline void BrooksPointer::set_raw(oop holder, HeapWord* update) { 70 log_develop_trace(gc)("Setting RAW forwardee for "PTR_FORMAT" = "PTR_FORMAT, p2i(holder), p2i(update)); 71 assert(UseShenandoahGC, "must only be called when Shenandoah is used."); 72 *brooks_ptr_addr(holder) = update; 73 } 74 75 inline HeapWord* BrooksPointer::get_raw(oop holder) { 76 assert(UseShenandoahGC, "must only be called when Shenandoah is used."); 77 HeapWord* res = *brooks_ptr_addr(holder); 78 log_develop_trace(gc)("Getting RAW forwardee for "PTR_FORMAT" = "PTR_FORMAT, p2i(holder), p2i(res)); 79 return res; 80 } 81 82 inline oop BrooksPointer::forwardee(oop obj) { 83 #ifdef ASSERT 84 assert(UseShenandoahGC, "must only be called when Shenandoah is used."); 85 assert(Universe::heap()->is_in(obj), "We shouldn't be calling this on objects not in the heap: "PTR_FORMAT, p2i(obj)); 86 87 oop forwardee; 88 if (ShenandoahVerifyReadsToFromSpace) { 89 ShenandoahHeap* heap = (ShenandoahHeap *) Universe::heap(); 90 ShenandoahHeapRegion* region = heap->heap_region_containing(obj); 91 { 92 region->memProtectionOff(); 93 forwardee = oop(*brooks_ptr_addr(obj)); 94 region->memProtectionOn(); 95 } 96 } else { 97 forwardee = oop(*brooks_ptr_addr(obj)); 98 } 99 100 assert(forwardee != NULL, "forwardee is not NULL"); 101 assert(ShenandoahHeap::heap()->is_in(forwardee), "forwardee must point to a heap address"); 102 assert((oopDesc::unsafe_equals(forwardee, obj) || 103 (ShenandoahHeap::heap()->heap_region_containing(forwardee) != 104 ShenandoahHeap::heap()->heap_region_containing(obj))), "forwardee should be self, or another region"); 105 106 if (!oopDesc::unsafe_equals(obj, forwardee)) { 107 oop second_forwardee = oop(*brooks_ptr_addr(forwardee)); 108 if (!oopDesc::unsafe_equals(forwardee, second_forwardee)) { 109 // We should never be forwarded more than once. 110 fatal("Multiple forwardings: "PTR_FORMAT" -> "PTR_FORMAT" -> "PTR_FORMAT, p2i(obj), p2i(forwardee), p2i(second_forwardee)); 111 } 112 } 113 #else 114 oop forwardee = oop(*brooks_ptr_addr(obj)); 115 #endif 116 117 log_develop_trace(gc)("Forwardee for "PTR_FORMAT" = "PTR_FORMAT, p2i(obj), p2i(forwardee)); 118 119 return forwardee; 120 } 121 122 inline oop BrooksPointer::try_update_forwardee(oop holder, oop update) { 123 #ifdef ASSERT 124 assert(holder != NULL, "holder should not be NULL"); 125 assert(update != NULL, "update should not be NULL"); 126 assert(!oopDesc::unsafe_equals(holder, update), "forwarding should make progress"); 127 assert(ShenandoahHeap::heap()->is_in(holder), "holder must point to a heap address"); 128 assert(ShenandoahHeap::heap()->is_in(update), "update must point to a heap address"); 129 assert(ShenandoahHeap::heap()->heap_region_containing(holder) != 130 ShenandoahHeap::heap()->heap_region_containing(update), "forwarding should be across regions"); 131 assert( ShenandoahHeap::heap()->in_cset_fast_test((HeapWord*) holder), "holder should be in collection set"); 132 assert(!ShenandoahHeap::heap()->in_cset_fast_test((HeapWord*) update), "update should not be in collection set"); 133 assert (holder->klass() == update->klass(), "klasses should match"); 134 135 oop result; 136 if (ShenandoahVerifyWritesToFromSpace || ShenandoahVerifyReadsToFromSpace) { 137 ShenandoahHeap* sh = (ShenandoahHeap*) Universe::heap(); 138 ShenandoahHeapRegion* hr = sh->heap_region_containing(holder); 139 140 { 141 hr->memProtectionOff(); 142 result = (oop) Atomic::cmpxchg_ptr(update, brooks_ptr_addr(holder), holder); 143 hr->memProtectionOn(); 144 } 145 } else { 146 result = (oop) Atomic::cmpxchg_ptr(update, brooks_ptr_addr(holder), holder); 147 } 148 149 assert(result != NULL, "CAS result is not NULL"); 150 assert(ShenandoahHeap::heap()->is_in(result), "CAS result must point to a heap address"); 151 152 if (oopDesc::unsafe_equals(result, holder)) { 153 log_develop_trace(gc)("Updated forwardee for "PTR_FORMAT" to "PTR_FORMAT, p2i(holder), p2i(update)); 154 } else { 155 log_develop_trace(gc)("Failed to set forwardee for "PTR_FORMAT" to "PTR_FORMAT", was already "PTR_FORMAT, p2i(holder), p2i(update), p2i(result)); 156 } 157 #else 158 oop result = (oop) Atomic::cmpxchg_ptr(update, brooks_ptr_addr(holder), holder); 159 #endif 160 161 return result; 162 } 163 164 #endif // SHARE_VM_GC_SHENANDOAH_BROOKSPOINTER_INLINE_HPP