1 /*
2 * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2020, Red Hat, Inc. and/or its affiliates.
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/shenandoah/shenandoahMarkBitMap.inline.hpp"
28 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
29 #include "utilities/globalDefinitions.hpp"
30
31 ShenandoahMarkBitMap::ShenandoahMarkBitMap(MemRegion heap, MemRegion storage) :
32 _shift(LogMinObjAlignment),
33 _covered(heap),
34 _map((BitMap::bm_word_t*) storage.start()),
35 _size((heap.word_size() * 2) >> _shift) {
36 }
37
38 size_t ShenandoahMarkBitMap::compute_size(size_t heap_size) {
39 return ReservedSpace::allocation_align_size_up(heap_size / mark_distance());
40 }
41
42 size_t ShenandoahMarkBitMap::mark_distance() {
43 return MinObjAlignmentInBytes * BitsPerByte / 2;
44 }
45
46 HeapWord* ShenandoahMarkBitMap::get_next_marked_addr(const HeapWord* addr,
47 const HeapWord* limit) const {
48 assert(limit != nullptr, "limit must not be null");
49 // Round addr up to a possible object boundary to be safe.
50 size_t const addr_offset = address_to_index(align_up(addr, HeapWordSize << LogMinObjAlignment));
51 size_t const limit_offset = address_to_index(limit);
52 size_t const nextOffset = get_next_one_offset(addr_offset, limit_offset);
53 return index_to_address(nextOffset);
54 }
55
56 void ShenandoahMarkBitMap::clear_range_within_word(idx_t beg, idx_t end) {
57 // With a valid range (beg <= end), this test ensures that end != 0, as
58 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
59 if (beg != end) {
60 bm_word_t mask = inverted_bit_mask_for_range(beg, end);
61 *word_addr(beg) &= mask;
62 }
63 }
64
65 void ShenandoahMarkBitMap::clear_range(idx_t beg, idx_t end) {
66 verify_range(beg, end);
67
68 idx_t beg_full_word = to_words_align_up(beg);
69 idx_t end_full_word = to_words_align_down(end);
70
71 if (beg_full_word < end_full_word) {
72 // The range includes at least one full word.
73 clear_range_within_word(beg, bit_index(beg_full_word));
74 clear_range_of_words(beg_full_word, end_full_word);
75 clear_range_within_word(bit_index(end_full_word), end);
76 } else {
77 // The range spans at most 2 partial words.
78 idx_t boundary = MIN2(bit_index(beg_full_word), end);
79 clear_range_within_word(beg, boundary);
80 clear_range_within_word(boundary, end);
81 }
82 }
83
84 bool ShenandoahMarkBitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) {
85 // There is little point to call large version on small ranges.
86 // Need to check carefully, keeping potential idx_t over/underflow in mind,
87 // because beg_full_word > end_full_word can occur when beg and end are in
88 // the same word.
89 // The threshold should be at least one word.
90 STATIC_ASSERT(small_range_words >= 1);
91 return beg_full_word + small_range_words >= end_full_word;
92 }
93
94
95 void ShenandoahMarkBitMap::clear_large_range(idx_t beg, idx_t end) {
96 verify_range(beg, end);
97
98 idx_t beg_full_word = to_words_align_up(beg);
99 idx_t end_full_word = to_words_align_down(end);
100
101 if (is_small_range_of_words(beg_full_word, end_full_word)) {
102 clear_range(beg, end);
103 return;
104 }
105
106 // The range includes at least one full word.
107 clear_range_within_word(beg, bit_index(beg_full_word));
108 clear_large_range_of_words(beg_full_word, end_full_word);
109 clear_range_within_word(bit_index(end_full_word), end);
110 }
111
112 void ShenandoahMarkBitMap::clear_range_large(MemRegion mr) {
113 MemRegion intersection = mr.intersection(_covered);
114 assert(!intersection.is_empty(),
115 "Given range from " PTR_FORMAT " to " PTR_FORMAT " is completely outside the heap",
116 p2i(mr.start()), p2i(mr.end()));
117 // convert address range into offset range
118 size_t beg = address_to_index(intersection.start());
119 size_t end = address_to_index(intersection.end());
120 clear_large_range(beg, end);
121 }
122
123 #ifdef ASSERT
124 void ShenandoahMarkBitMap::check_mark(HeapWord* addr) const {
125 assert(ShenandoahHeap::heap()->is_in_reserved(addr),
126 "Trying to access bitmap " PTR_FORMAT " for address " PTR_FORMAT " not in the heap.",
127 p2i(this), p2i(addr));
128 }
129
130 void ShenandoahMarkBitMap::verify_index(idx_t bit) const {
131 assert(bit < _size,
132 "BitMap index out of bounds: " SIZE_FORMAT " >= " SIZE_FORMAT,
133 bit, _size);
134 }
135
136 void ShenandoahMarkBitMap::verify_limit(idx_t bit) const {
137 assert(bit <= _size,
138 "BitMap limit out of bounds: " SIZE_FORMAT " > " SIZE_FORMAT,
139 bit, _size);
140 }
141
142 void ShenandoahMarkBitMap::verify_range(idx_t beg, idx_t end) const {
143 assert(beg <= end,
144 "BitMap range error: " SIZE_FORMAT " > " SIZE_FORMAT, beg, end);
145 verify_limit(end);
146 }
147 #endif