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 }