1 /* 2 * Copyright (c) 2021, Red Hat, Inc. All rights reserved. 3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 #include "gc/shared/gc_globals.hpp" 28 #include "gc/shared/slidingForwarding.hpp" 29 #include "utilities/ostream.hpp" 30 #include "utilities/powerOfTwo.hpp" 31 32 // We cannot use 0, because that may already be a valid base address in zero-based heaps. 33 // 0x1 is safe because heap base addresses must be aligned by much larger alignment 34 HeapWord* const SlidingForwarding::UNUSED_BASE = reinterpret_cast<HeapWord*>(0x1); 35 36 HeapWord* SlidingForwarding::_heap_start = nullptr; 37 size_t SlidingForwarding::_region_size_words = 0; 38 size_t SlidingForwarding::_heap_start_region_bias = 0; 39 size_t SlidingForwarding::_num_regions = 0; 40 uint SlidingForwarding::_region_size_bytes_shift = 0; 41 uintptr_t SlidingForwarding::_region_mask = 0; 42 HeapWord** SlidingForwarding::_biased_bases[SlidingForwarding::NUM_TARGET_REGIONS] = { nullptr, nullptr }; 43 HeapWord** SlidingForwarding::_bases_table = nullptr; 44 SlidingForwarding::FallbackTable* SlidingForwarding::_fallback_table = nullptr; 45 46 void SlidingForwarding::initialize(MemRegion heap, size_t region_size_words) { 47 #ifdef _LP64 48 if (UseAltGCForwarding) { 49 _heap_start = heap.start(); 50 51 // If the heap is small enough to fit directly into the available offset bits, 52 // and we are running Serial GC, we can treat the whole heap as a single region 53 // if it happens to be aligned to allow biasing. 54 size_t rounded_heap_size = round_up_power_of_2(heap.byte_size()); 55 56 if (UseSerialGC && (heap.word_size() <= (1 << NUM_OFFSET_BITS)) && 57 is_aligned((uintptr_t)_heap_start, rounded_heap_size)) { 58 _num_regions = 1; 59 _region_size_words = heap.word_size(); 60 _region_size_bytes_shift = log2i_exact(rounded_heap_size); 61 } else { 62 _num_regions = align_up(pointer_delta(heap.end(), heap.start()), region_size_words) / region_size_words; 63 _region_size_words = region_size_words; 64 _region_size_bytes_shift = log2i_exact(_region_size_words) + LogHeapWordSize; 65 } 66 _heap_start_region_bias = (uintptr_t)_heap_start >> _region_size_bytes_shift; 67 _region_mask = ~((uintptr_t(1) << _region_size_bytes_shift) - 1); 68 69 guarantee((_heap_start_region_bias << _region_size_bytes_shift) == (uintptr_t)_heap_start, "must be aligned: _heap_start_region_bias: " SIZE_FORMAT ", _region_size_byte_shift: %u, _heap_start: " PTR_FORMAT, _heap_start_region_bias, _region_size_bytes_shift, p2i(_heap_start)); 70 71 assert(_region_size_words >= 1, "regions must be at least a word large"); 72 assert(_bases_table == nullptr, "should not be initialized yet"); 73 assert(_fallback_table == nullptr, "should not be initialized yet"); 74 } 75 #endif 76 } 77 78 void SlidingForwarding::begin() { 79 #ifdef _LP64 80 if (UseAltGCForwarding) { 81 assert(_bases_table == nullptr, "should not be initialized yet"); 82 assert(_fallback_table == nullptr, "should not be initialized yet"); 83 84 size_t max = _num_regions * NUM_TARGET_REGIONS; 85 _bases_table = NEW_C_HEAP_ARRAY(HeapWord*, max, mtGC); 86 HeapWord** biased_start = _bases_table - _heap_start_region_bias; 87 _biased_bases[0] = biased_start; 88 _biased_bases[1] = biased_start + _num_regions; 89 for (size_t i = 0; i < max; i++) { 90 _bases_table[i] = UNUSED_BASE; 91 } 92 } 93 #endif 94 } 95 96 void SlidingForwarding::end() { 97 #ifdef _LP64 98 if (UseAltGCForwarding) { 99 assert(_bases_table != nullptr, "should be initialized"); 100 FREE_C_HEAP_ARRAY(HeapWord*, _bases_table); 101 _bases_table = nullptr; 102 delete _fallback_table; 103 _fallback_table = nullptr; 104 } 105 #endif 106 } 107 108 void SlidingForwarding::fallback_forward_to(HeapWord* from, HeapWord* to) { 109 if (_fallback_table == nullptr) { 110 _fallback_table = new (mtGC) FallbackTable(); 111 } 112 _fallback_table->put_when_absent(from, to); 113 } 114 115 HeapWord* SlidingForwarding::fallback_forwardee(HeapWord* from) { 116 assert(_fallback_table != nullptr, "fallback table must be present"); 117 HeapWord** found = _fallback_table->get(from); 118 if (found != nullptr) { 119 return *found; 120 } else { 121 return nullptr; 122 } 123 }