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 }