1 /* 2 * Copyright (c) 2021, Red Hat, Inc. 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_SLIDINGFORWARDING_INLINE_HPP 25 #define SHARE_GC_SHARED_SLIDINGFORWARDING_INLINE_HPP 26 27 #include "gc/shared/slidingForwarding.hpp" 28 #include "oops/markWord.hpp" 29 #include "oops/oop.inline.hpp" 30 31 #ifdef _LP64 32 size_t SlidingForwarding::region_index_containing(HeapWord* addr) const { 33 assert(addr >= _heap_start, "sanity: addr: " PTR_FORMAT " heap base: " PTR_FORMAT, p2i(addr), p2i(_heap_start)); 34 size_t index = ((size_t) (addr - _heap_start)) >> _region_size_words_shift; 35 assert(index < _num_regions, "Region index is in bounds: " PTR_FORMAT, p2i(addr)); 36 return index; 37 } 38 39 bool SlidingForwarding::region_contains(HeapWord* region_base, HeapWord* addr) const { 40 return uintptr_t(addr - region_base) < (ONE << _region_size_words_shift); 41 } 42 43 44 uintptr_t SlidingForwarding::encode_forwarding(HeapWord* original, HeapWord* target) { 45 size_t orig_idx = region_index_containing(original); 46 size_t base_table_idx = orig_idx * 2; 47 size_t target_idx = region_index_containing(target); 48 HeapWord* encode_base; 49 uintptr_t region_idx; 50 for (region_idx = 0; region_idx < NUM_REGIONS; region_idx++) { 51 encode_base = _target_base_table[base_table_idx + region_idx]; 52 if (encode_base == UNUSED_BASE) { 53 encode_base = _heap_start + target_idx * (ONE << _region_size_words_shift); 54 _target_base_table[base_table_idx + region_idx] = encode_base; 55 break; 56 } else if (region_contains(encode_base, target)) { 57 break; 58 } 59 } 60 if (region_idx >= NUM_REGIONS) { 61 tty->print_cr("target: " PTR_FORMAT, p2i(target)); 62 for (region_idx = 0; region_idx < NUM_REGIONS; region_idx++) { 63 tty->print_cr("region_idx: " INTPTR_FORMAT ", encode_base: " PTR_FORMAT, region_idx, p2i(_target_base_table[base_table_idx + region_idx])); 64 } 65 } 66 assert(region_idx < NUM_REGIONS, "need to have found an encoding base"); 67 assert(target >= encode_base, "target must be above encode base, target:" PTR_FORMAT ", encoded_base: " PTR_FORMAT ", target_idx: " SIZE_FORMAT ", heap start: " PTR_FORMAT ", region_idx: " INTPTR_FORMAT, 68 p2i(target), p2i(encode_base), target_idx, p2i(_heap_start), region_idx); 69 assert(region_contains(encode_base, target), "region must contain target: original: " PTR_FORMAT ", target: " PTR_FORMAT ", encode_base: " PTR_FORMAT ", region_idx: " INTPTR_FORMAT, p2i(original), p2i(target), p2i(encode_base), region_idx); 70 uintptr_t encoded = (((uintptr_t)(target - encode_base)) << COMPRESSED_BITS_SHIFT) | 71 (region_idx << BASE_SHIFT) | markWord::marked_value; 72 assert(target == decode_forwarding(original, encoded), "must be reversible"); 73 return encoded; 74 } 75 76 HeapWord* SlidingForwarding::decode_forwarding(HeapWord* original, uintptr_t encoded) const { 77 assert((encoded & markWord::marked_value) == markWord::marked_value, "must be marked as forwarded"); 78 size_t orig_idx = region_index_containing(original); 79 size_t region_idx = (encoded >> BASE_SHIFT) & right_n_bits(NUM_REGION_BITS); 80 size_t base_table_idx = orig_idx * 2 + region_idx; 81 HeapWord* decoded = _target_base_table[base_table_idx] + (encoded >> COMPRESSED_BITS_SHIFT); 82 assert(decoded >= _heap_start, "must be above heap start, encoded: " INTPTR_FORMAT ", region_idx: " SIZE_FORMAT ", base: " PTR_FORMAT, encoded, region_idx, p2i(_target_base_table[base_table_idx])); 83 return decoded; 84 } 85 #endif 86 87 void SlidingForwarding::forward_to(oop original, oop target) { 88 #ifdef _LP64 89 markWord header = original->mark(); 90 if (header.has_displaced_mark_helper()) { 91 header = header.displaced_mark_helper(); 92 } 93 uintptr_t encoded = encode_forwarding(cast_from_oop<HeapWord*>(original), cast_from_oop<HeapWord*>(target)); 94 assert((encoded & markWord::klass_mask_in_place) == 0, "encoded forwardee must not overlap with Klass*: " PTR_FORMAT, encoded); 95 header = markWord((header.value() & markWord::klass_mask_in_place) | encoded); 96 original->set_mark(header); 97 #else 98 original->forward_to(target); 99 #endif 100 } 101 102 oop SlidingForwarding::forwardee(oop original) const { 103 #ifdef _LP64 104 markWord header = original->mark(); 105 uintptr_t encoded = header.value() & ~markWord::klass_mask_in_place; 106 HeapWord* forwardee = decode_forwarding(cast_from_oop<HeapWord*>(original), encoded); 107 return cast_to_oop(forwardee); 108 #else 109 return original->forwardee(); 110 #endif 111 } 112 113 #endif // SHARE_GC_SHARED_SLIDINGFORWARDING_INLINE_HPP