1 /* 2 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #ifndef SHARE_GC_SHARED_FULLGCFORWARDING_INLINE_HPP 25 #define SHARE_GC_SHARED_FULLGCFORWARDING_INLINE_HPP 26 27 #include "gc/shared/gc_globals.hpp" 28 #include "gc/shared/fullGCForwarding.hpp" 29 #include "oops/markWord.hpp" 30 #include "oops/oop.inline.hpp" 31 #include "utilities/macros.hpp" 32 33 inline bool FullGCForwarding::is_forwarded(oop obj) { 34 return obj->is_forwarded(); 35 } 36 37 size_t FullGCForwarding::biased_region_index_containing(HeapWord* addr) { 38 return (uintptr_t)addr >> BLOCK_SIZE_BYTES_SHIFT; 39 } 40 41 bool FullGCForwarding::is_fallback(uintptr_t encoded) { 42 return (encoded & OFFSET_MASK) == FALLBACK_PATTERN_IN_PLACE; 43 } 44 45 uintptr_t FullGCForwarding::encode_forwarding(HeapWord* from, HeapWord* to) { 46 size_t from_block_idx = biased_region_index_containing(from); 47 48 HeapWord* to_region_base = _biased_bases[from_block_idx]; 49 if (to_region_base == UNUSED_BASE) { 50 _biased_bases[from_block_idx] = to_region_base = to; 51 } 52 53 // Avoid pointer_delta() on purpose: using an unsigned subtraction, 54 // we get an underflow when to < to_region_base, which means 55 // we can use a single comparison instead of: 56 // if (to_region_base > to || (to - to_region_base) > MAX_OFFSET) { .. } 57 size_t offset = size_t(to - to_region_base); 58 if (offset > MAX_OFFSET) { 59 offset = FALLBACK_PATTERN; 60 } 61 uintptr_t encoded = (offset << OFFSET_BITS_SHIFT) | markWord::marked_value; 62 63 assert(is_fallback(encoded) || to == decode_forwarding(from, encoded), "must be reversible"); 64 assert((encoded & ~AVAILABLE_BITS_MASK) == 0, "must encode to available bits"); 65 return encoded; 66 } 67 68 HeapWord* FullGCForwarding::decode_forwarding(HeapWord* from, uintptr_t encoded) { 69 assert(!is_fallback(encoded), "must not be fallback-forwarded, encoded: " INTPTR_FORMAT ", OFFSET_MASK: " INTPTR_FORMAT ", FALLBACK_PATTERN_IN_PLACE: " INTPTR_FORMAT, encoded, OFFSET_MASK, FALLBACK_PATTERN_IN_PLACE); 70 assert((encoded & ~AVAILABLE_BITS_MASK) == 0, "must decode from available bits, encoded: " INTPTR_FORMAT, encoded); 71 uintptr_t offset = (encoded >> OFFSET_BITS_SHIFT); 72 73 size_t from_idx = biased_region_index_containing(from); 74 HeapWord* base = _biased_bases[from_idx]; 75 assert(base != UNUSED_BASE, "must not be unused base: encoded: " INTPTR_FORMAT, encoded); 76 HeapWord* decoded = base + offset; 77 assert(decoded >= _heap_start, 78 "Address must be above heap start. encoded: " INTPTR_FORMAT ", base: " PTR_FORMAT, 79 encoded, p2i(base)); 80 81 return decoded; 82 } 83 84 inline void FullGCForwarding::forward_to_impl(oop from, oop to) { 85 assert(_bases_table != nullptr, "call begin() before forwarding"); 86 87 markWord from_header = from->mark(); 88 HeapWord* from_hw = cast_from_oop<HeapWord*>(from); 89 HeapWord* to_hw = cast_from_oop<HeapWord*>(to); 90 uintptr_t encoded = encode_forwarding(from_hw, to_hw); 91 markWord new_header = markWord((from_header.value() & ~OFFSET_MASK) | encoded); 92 from->set_mark(new_header); 93 94 if (is_fallback(encoded)) { 95 fallback_forward_to(from_hw, to_hw); 96 } 97 NOT_PRODUCT(Atomic::inc(&_num_forwardings);) 98 } 99 100 inline void FullGCForwarding::forward_to(oop obj, oop fwd) { 101 assert(fwd != nullptr, "no null forwarding"); 102 #ifdef _LP64 103 assert(_bases_table != nullptr, "expect sliding forwarding initialized"); 104 forward_to_impl(obj, fwd); 105 assert(forwardee(obj) == fwd, "must be forwarded to correct forwardee, obj: " PTR_FORMAT ", forwardee(obj): " PTR_FORMAT ", fwd: " PTR_FORMAT ", mark: " INTPTR_FORMAT, p2i(obj), p2i(forwardee(obj)), p2i(fwd), obj->mark().value()); 106 #else 107 obj->forward_to(fwd); 108 #endif 109 } 110 111 inline oop FullGCForwarding::forwardee_impl(oop from) { 112 assert(_bases_table != nullptr, "call begin() before asking for forwarding"); 113 114 markWord header = from->mark(); 115 HeapWord* from_hw = cast_from_oop<HeapWord*>(from); 116 if (is_fallback(header.value())) { 117 HeapWord* to = fallback_forwardee(from_hw); 118 return cast_to_oop(to); 119 } 120 uintptr_t encoded = header.value() & OFFSET_MASK; 121 HeapWord* to = decode_forwarding(from_hw, encoded); 122 return cast_to_oop(to); 123 } 124 125 inline oop FullGCForwarding::forwardee(oop obj) { 126 #ifdef _LP64 127 assert(_bases_table != nullptr, "expect sliding forwarding initialized"); 128 return forwardee_impl(obj); 129 #else 130 return obj->forwardee(); 131 #endif 132 } 133 134 #endif // SHARE_GC_SHARED_FULLGCFORWARDING_INLINE_HPP