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 _heap_start = heap.start(); 49 50 // If the heap is small enough to fit directly into the available offset bits, 51 // and we are running Serial GC, we can treat the whole heap as a single region 52 // if it happens to be aligned to allow biasing. 53 size_t rounded_heap_size = round_up_power_of_2(heap.byte_size()); 54 55 if (UseSerialGC && (heap.word_size() <= (1 << NUM_OFFSET_BITS)) && 56 is_aligned((uintptr_t)_heap_start, rounded_heap_size)) { 57 _num_regions = 1; 58 _region_size_words = heap.word_size(); 59 _region_size_bytes_shift = log2i_exact(rounded_heap_size); 60 } else { 61 _num_regions = align_up(pointer_delta(heap.end(), heap.start()), region_size_words) / region_size_words; 62 _region_size_words = region_size_words; 63 _region_size_bytes_shift = log2i_exact(_region_size_words) + LogHeapWordSize; 64 } 65 _heap_start_region_bias = (uintptr_t)_heap_start >> _region_size_bytes_shift; 66 _region_mask = ~((uintptr_t(1) << _region_size_bytes_shift) - 1); 67 68 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)); 69 70 assert(_region_size_words >= 1, "regions must be at least a word large"); 71 assert(_bases_table == nullptr, "should not be initialized yet"); 72 assert(_fallback_table == nullptr, "should not be initialized yet"); 73 #endif 74 } 75 76 void SlidingForwarding::begin() { 77 #ifdef _LP64 78 assert(_bases_table == nullptr, "should not be initialized yet"); 79 assert(_fallback_table == nullptr, "should not be initialized yet"); 80 81 size_t max = _num_regions * NUM_TARGET_REGIONS; 82 _bases_table = NEW_C_HEAP_ARRAY(HeapWord*, max, mtGC); 83 HeapWord** biased_start = _bases_table - _heap_start_region_bias; 84 _biased_bases[0] = biased_start; 85 _biased_bases[1] = biased_start + _num_regions; 86 for (size_t i = 0; i < max; i++) { 87 _bases_table[i] = UNUSED_BASE; 88 } 89 #endif 90 } 91 92 void SlidingForwarding::end() { 93 #ifdef _LP64 94 assert(_bases_table != nullptr, "should be initialized"); 95 FREE_C_HEAP_ARRAY(HeapWord*, _bases_table); 96 _bases_table = nullptr; 97 delete _fallback_table; 98 _fallback_table = nullptr; 99 #endif 100 } 101 102 void SlidingForwarding::fallback_forward_to(HeapWord* from, HeapWord* to) { 103 if (_fallback_table == nullptr) { 104 _fallback_table = new (mtGC) FallbackTable(); 105 } 106 _fallback_table->put_when_absent(from, to); 107 } 108 109 HeapWord* SlidingForwarding::fallback_forwardee(HeapWord* from) { 110 assert(_fallback_table != nullptr, "fallback table must be present"); 111 HeapWord** found = _fallback_table->get(from); 112 if (found != nullptr) { 113 return *found; 114 } else { 115 return nullptr; 116 } 117 }