1 /*
  2  * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 #ifndef SHARE_GC_Z_ZLIVEMAP_INLINE_HPP
 25 #define SHARE_GC_Z_ZLIVEMAP_INLINE_HPP
 26 
 27 #include "gc/z/zLiveMap.hpp"
 28 
 29 #include "gc/z/zAddress.inline.hpp"
 30 #include "gc/z/zBitMap.inline.hpp"
 31 #include "gc/z/zGeneration.inline.hpp"
 32 #include "gc/z/zMark.hpp"
 33 #include "gc/z/zUtils.inline.hpp"
 34 #include "utilities/bitMap.inline.hpp"
 35 #include "utilities/debug.hpp"
 36 
 37 inline void ZLiveMap::reset() {
 38   _seqnum.store_relaxed(0u);
 39 }
 40 
 41 inline bool ZLiveMap::is_marked(ZGenerationId id) const {
 42   return _seqnum.load_acquire() == ZGeneration::generation(id)->seqnum();
 43 }
 44 
 45 inline uint32_t ZLiveMap::live_objects() const {
 46   return _live_objects.load_relaxed();
 47 }
 48 
 49 inline size_t ZLiveMap::live_bytes() const {
 50   return _live_bytes.load_relaxed();
 51 }
 52 
 53 inline const BitMapView ZLiveMap::segment_live_bits() const {
 54   return BitMapView(const_cast<BitMap::bm_word_t*>(&_segment_live_bits), NumSegments);
 55 }
 56 
 57 inline const BitMapView ZLiveMap::segment_claim_bits() const {
 58   return BitMapView(const_cast<BitMap::bm_word_t*>(&_segment_claim_bits), NumSegments);
 59 }
 60 
 61 inline BitMapView ZLiveMap::segment_live_bits() {
 62   return BitMapView(&_segment_live_bits, NumSegments);
 63 }
 64 
 65 inline BitMapView ZLiveMap::segment_claim_bits() {
 66   return BitMapView(&_segment_claim_bits, NumSegments);
 67 }
 68 
 69 inline bool ZLiveMap::is_segment_live(BitMap::idx_t segment) const {
 70   return segment_live_bits().par_at(segment);
 71 }
 72 
 73 inline bool ZLiveMap::set_segment_live(BitMap::idx_t segment) {
 74   return segment_live_bits().par_set_bit(segment, memory_order_release);
 75 }
 76 
 77 inline bool ZLiveMap::claim_segment(BitMap::idx_t segment) {
 78   return segment_claim_bits().par_set_bit(segment, memory_order_acq_rel);
 79 }
 80 
 81 inline BitMap::idx_t ZLiveMap::first_live_segment() const {
 82   return segment_live_bits().find_first_set_bit(0, NumSegments);
 83 }
 84 
 85 inline BitMap::idx_t ZLiveMap::next_live_segment(BitMap::idx_t segment) const {
 86   return segment_live_bits().find_first_set_bit(segment + 1, NumSegments);
 87 }
 88 
 89 inline BitMap::idx_t ZLiveMap::index_to_segment(BitMap::idx_t index) const {
 90   return index >> _segment_shift;
 91 }
 92 
 93 inline bool ZLiveMap::get(ZGenerationId id, BitMap::idx_t index) const {
 94   const BitMap::idx_t segment = index_to_segment(index);
 95   return is_marked(id) &&                             // Page is marked
 96          is_segment_live(segment) &&                  // Segment is marked
 97          _bitmap.par_at(index, memory_order_relaxed); // Object is marked
 98 }
 99 
100 inline bool ZLiveMap::set(ZGenerationId id, BitMap::idx_t index, bool finalizable, bool& inc_live) {
101   if (!is_marked(id)) {
102     // First object to be marked during this
103     // cycle, reset marking information.
104     reset(id);
105   }
106 
107   const BitMap::idx_t segment = index_to_segment(index);
108   if (!is_segment_live(segment)) {
109     // First object to be marked in this segment during
110     // this cycle, reset segment bitmap.
111     reset_segment(segment);
112   }
113 
114   return _bitmap.par_set_bit_pair(index, finalizable, inc_live);
115 }
116 
117 inline void ZLiveMap::inc_live(uint32_t objects, size_t bytes) {
118   _live_objects.add_then_fetch(objects);
119   _live_bytes.add_then_fetch(bytes);
120 }
121 
122 inline BitMap::idx_t ZLiveMap::segment_start(BitMap::idx_t segment) const {
123   return segment * _segment_size;
124 }
125 
126 inline BitMap::idx_t ZLiveMap::segment_end(BitMap::idx_t segment) const {
127   return segment_start(segment) + _segment_size;
128 }
129 
130 inline size_t ZLiveMap::do_object(ObjectClosure* cl, zaddress addr) const {
131   // Get the size of the object before calling the closure, which
132   // might overwrite the object in case we are relocating in-place.
133   const size_t size = ZUtils::object_size(addr);
134 
135   // Apply closure
136   cl->do_object(to_oop(addr));
137 
138   return size;
139 }
140 
141 template <typename Function>
142 inline void ZLiveMap::iterate_segment(BitMap::idx_t segment, Function function) {
143   assert(is_segment_live(segment), "Must be");
144 
145   const BitMap::idx_t start_index = segment_start(segment);
146   const BitMap::idx_t end_index   = segment_end(segment);
147 
148   _bitmap.iterate(function, start_index, end_index);
149 }
150 
151 template <typename Function>
152 inline void ZLiveMap::iterate(ZGenerationId id, Function function) {
153   if (!is_marked(id)) {
154     return;
155   }
156 
157   auto live_only = [&](BitMap::idx_t index) -> bool {
158     if ((index & 1) == 0) {
159       return function(index);
160     }
161     // Don't visit the finalizable bits
162     return true;
163   };
164 
165   for (BitMap::idx_t segment = first_live_segment(); segment < NumSegments; segment = next_live_segment(segment)) {
166     // For each live segment
167     iterate_segment(segment, live_only);
168   }
169 }
170 
171 // Find the bit index that correspond the start of the object that is lower,
172 // or equal, to the given index (index is inclusive).
173 //
174 // Typically used to find the start of an object when there's only a field
175 // address available. Note that it's not guaranteed that the found index
176 // corresponds to an object that spans the given index. This function just
177 // looks at the bits. The calling code is responsible to check the object
178 // at the returned index.
179 //
180 // returns -1 if no bit was found
181 inline BitMap::idx_t ZLiveMap::find_base_bit(BitMap::idx_t index) {
182   // Check first segment
183   const BitMap::idx_t start_segment = index_to_segment(index);
184   if (is_segment_live(start_segment)) {
185     const BitMap::idx_t res = find_base_bit_in_segment(segment_start(start_segment), index);
186     if (res != BitMap::idx_t(-1)) {
187       return res;
188     }
189   }
190 
191   // Search earlier segments
192   for (BitMap::idx_t segment = start_segment; segment-- > 0; ) {
193     if (is_segment_live(segment)) {
194       const BitMap::idx_t res = find_base_bit_in_segment(segment_start(segment), segment_end(segment) - 1);
195       if (res != BitMap::idx_t(-1)) {
196         return res;
197       }
198     }
199   }
200 
201   // Not found
202   return BitMap::idx_t(-1);
203 }
204 
205 // Find the bit index that correspond the start of the object that is lower,
206 // or equal, to the given index (index is inclusive). Stopping when reaching
207 // start.
208 inline BitMap::idx_t ZLiveMap::find_base_bit_in_segment(BitMap::idx_t start, BitMap::idx_t index) {
209   assert(index_to_segment(start) == index_to_segment(index), "Only supports searches within segments start: %zu index: %zu", start, index);
210   assert(is_segment_live(index_to_segment(start)), "Must be live");
211 
212   // Search backwards - + 1 to make an exclusive index.
213   const BitMap::idx_t end = index + 1;
214   const BitMap::idx_t bit = _bitmap.find_last_set_bit(start, end);
215   if (bit == end) {
216     return BitMap::idx_t(-1);
217   }
218 
219   // The bitmaps contain pairs of bits to deal with strongly marked vs only
220   // finalizable marked. Align down to get the first bit position.
221   return bit & ~BitMap::idx_t(1);
222 }
223 
224 #endif // SHARE_GC_Z_ZLIVEMAP_INLINE_HPP