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 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 * 25 */ 26 27 #include "precompiled.hpp" 28 #include "gc/shenandoah/shenandoahMarkBitMap.inline.hpp" 29 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 30 #include "utilities/globalDefinitions.hpp" 31 32 ShenandoahMarkBitMap::ShenandoahMarkBitMap(MemRegion heap, MemRegion storage) : 33 _shift(LogMinObjAlignment), 34 _covered(heap), 35 _map((BitMap::bm_word_t*) storage.start()), 36 _size((heap.word_size() * 2) >> _shift) { 37 } 38 39 size_t ShenandoahMarkBitMap::compute_size(size_t heap_size) { 40 return ReservedSpace::allocation_align_size_up(heap_size / mark_distance()); 41 } 42 43 size_t ShenandoahMarkBitMap::mark_distance() { 44 return MinObjAlignmentInBytes * BitsPerByte / 2; 45 } 46 47 bool ShenandoahMarkBitMap::is_bitmap_clear_range(const HeapWord* start, const HeapWord* end) const { 48 // Similar to get_next_marked_addr(), without assertion. 49 // Round addr up to a possible object boundary to be safe. 50 if (start == end) { 51 return true; 52 } 53 size_t const addr_offset = address_to_index(align_up(start, HeapWordSize << LogMinObjAlignment)); 54 size_t const limit_offset = address_to_index(end); 55 size_t const next_offset = get_next_one_offset(addr_offset, limit_offset); 56 HeapWord* result = index_to_address(next_offset); 57 return (result == end); 58 } 59 60 61 HeapWord* ShenandoahMarkBitMap::get_next_marked_addr(const HeapWord* addr, 62 const HeapWord* limit) const { 63 #ifdef ASSERT 64 ShenandoahHeap* heap = ShenandoahHeap::heap(); 65 ShenandoahHeapRegion* r = heap->heap_region_containing(addr); 66 ShenandoahMarkingContext* ctx = heap->marking_context(); 67 HeapWord* tams = ctx->top_at_mark_start(r); 68 assert(limit != nullptr, "limit must not be null"); 69 assert(limit <= r->top(), "limit must be less than top"); 70 assert(addr <= tams, "addr must be less than TAMS"); 71 #endif 72 73 // Round addr up to a possible object boundary to be safe. 74 size_t const addr_offset = address_to_index(align_up(addr, HeapWordSize << LogMinObjAlignment)); 75 size_t const limit_offset = address_to_index(limit); 76 size_t const nextOffset = get_next_one_offset(addr_offset, limit_offset); 77 return index_to_address(nextOffset); 78 } 79 80 void ShenandoahMarkBitMap::clear_range_within_word(idx_t beg, idx_t end) { 81 // With a valid range (beg <= end), this test ensures that end != 0, as 82 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. 83 if (beg != end) { 84 bm_word_t mask = inverted_bit_mask_for_range(beg, end); 85 *word_addr(beg) &= mask; 86 } 87 } 88 89 void ShenandoahMarkBitMap::clear_range(idx_t beg, idx_t end) { 90 verify_range(beg, end); 91 92 idx_t beg_full_word = to_words_align_up(beg); 93 idx_t end_full_word = to_words_align_down(end); 94 95 if (beg_full_word < end_full_word) { 96 // The range includes at least one full word. 97 clear_range_within_word(beg, bit_index(beg_full_word)); 98 clear_range_of_words(beg_full_word, end_full_word); 99 clear_range_within_word(bit_index(end_full_word), end); 100 } else { 101 // The range spans at most 2 partial words. 102 idx_t boundary = MIN2(bit_index(beg_full_word), end); 103 clear_range_within_word(beg, boundary); 104 clear_range_within_word(boundary, end); 105 } 106 } 107 108 bool ShenandoahMarkBitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) { 109 // There is little point to call large version on small ranges. 110 // Need to check carefully, keeping potential idx_t over/underflow in mind, 111 // because beg_full_word > end_full_word can occur when beg and end are in 112 // the same word. 113 // The threshold should be at least one word. 114 STATIC_ASSERT(small_range_words >= 1); 115 return beg_full_word + small_range_words >= end_full_word; 116 } 117 118 119 void ShenandoahMarkBitMap::clear_large_range(idx_t beg, idx_t end) { 120 verify_range(beg, end); 121 122 idx_t beg_full_word = to_words_align_up(beg); 123 idx_t end_full_word = to_words_align_down(end); 124 125 if (is_small_range_of_words(beg_full_word, end_full_word)) { 126 clear_range(beg, end); 127 return; 128 } 129 130 // The range includes at least one full word. 131 clear_range_within_word(beg, bit_index(beg_full_word)); 132 clear_large_range_of_words(beg_full_word, end_full_word); 133 clear_range_within_word(bit_index(end_full_word), end); 134 } 135 136 void ShenandoahMarkBitMap::clear_range_large(MemRegion mr) { 137 MemRegion intersection = mr.intersection(_covered); 138 assert(!intersection.is_empty(), 139 "Given range from " PTR_FORMAT " to " PTR_FORMAT " is completely outside the heap", 140 p2i(mr.start()), p2i(mr.end())); 141 // convert address range into offset range 142 size_t beg = address_to_index(intersection.start()); 143 size_t end = address_to_index(intersection.end()); 144 clear_large_range(beg, end); 145 } 146 147 #ifdef ASSERT 148 void ShenandoahMarkBitMap::check_mark(HeapWord* addr) const { 149 assert(ShenandoahHeap::heap()->is_in(addr), 150 "Trying to access bitmap " PTR_FORMAT " for address " PTR_FORMAT " not in the heap.", 151 p2i(this), p2i(addr)); 152 } 153 154 void ShenandoahMarkBitMap::verify_index(idx_t bit) const { 155 assert(bit < _size, 156 "BitMap index out of bounds: " SIZE_FORMAT " >= " SIZE_FORMAT, 157 bit, _size); 158 } 159 160 void ShenandoahMarkBitMap::verify_limit(idx_t bit) const { 161 assert(bit <= _size, 162 "BitMap limit out of bounds: " SIZE_FORMAT " > " SIZE_FORMAT, 163 bit, _size); 164 } 165 166 void ShenandoahMarkBitMap::verify_range(idx_t beg, idx_t end) const { 167 assert(beg <= end, 168 "BitMap range error: " SIZE_FORMAT " > " SIZE_FORMAT, beg, end); 169 verify_limit(end); 170 } 171 #endif