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 uint32_t ZLiveMap::will_expand_objects() const {
 54   return _will_expand_objects.load_relaxed();
 55 }
 56 
 57 inline const BitMapView ZLiveMap::segment_live_bits() const {
 58   return BitMapView(const_cast<BitMap::bm_word_t*>(&_segment_live_bits), NumSegments);
 59 }
 60 
 61 inline const BitMapView ZLiveMap::segment_claim_bits() const {
 62   return BitMapView(const_cast<BitMap::bm_word_t*>(&_segment_claim_bits), NumSegments);
 63 }
 64 
 65 inline BitMapView ZLiveMap::segment_live_bits() {
 66   return BitMapView(&_segment_live_bits, NumSegments);
 67 }
 68 
 69 inline BitMapView ZLiveMap::segment_claim_bits() {
 70   return BitMapView(&_segment_claim_bits, NumSegments);
 71 }
 72 
 73 inline bool ZLiveMap::is_segment_live(BitMap::idx_t segment) const {
 74   return segment_live_bits().par_at(segment);
 75 }
 76 
 77 inline bool ZLiveMap::set_segment_live(BitMap::idx_t segment) {
 78   return segment_live_bits().par_set_bit(segment, memory_order_release);
 79 }
 80 
 81 inline bool ZLiveMap::claim_segment(BitMap::idx_t segment) {
 82   return segment_claim_bits().par_set_bit(segment, memory_order_acq_rel);
 83 }
 84 
 85 inline BitMap::idx_t ZLiveMap::first_live_segment() const {
 86   return segment_live_bits().find_first_set_bit(0, NumSegments);
 87 }
 88 
 89 inline BitMap::idx_t ZLiveMap::next_live_segment(BitMap::idx_t segment) const {
 90   return segment_live_bits().find_first_set_bit(segment + 1, NumSegments);
 91 }
 92 
 93 inline BitMap::idx_t ZLiveMap::index_to_segment(BitMap::idx_t index) const {
 94   return index >> _segment_shift;
 95 }
 96 
 97 inline bool ZLiveMap::get(ZGenerationId id, BitMap::idx_t index) const {
 98   const BitMap::idx_t segment = index_to_segment(index);
 99   return is_marked(id) &&                             // Page is marked
100          is_segment_live(segment) &&                  // Segment is marked
101          _bitmap.par_at(index, memory_order_relaxed); // Object is marked
102 }
103 
104 inline bool ZLiveMap::set(ZGenerationId id, BitMap::idx_t index, bool finalizable, bool& inc_live) {
105   if (!is_marked(id)) {
106     // First object to be marked during this
107     // cycle, reset marking information.
108     reset(id);
109   }
110 
111   const BitMap::idx_t segment = index_to_segment(index);
112   if (!is_segment_live(segment)) {
113     // First object to be marked in this segment during
114     // this cycle, reset segment bitmap.
115     reset_segment(segment);
116   }
117 
118   return _bitmap.par_set_bit_pair(index, finalizable, inc_live);
119 }
120 
121 inline void ZLiveMap::inc_live(uint32_t objects, size_t bytes) {
122   _live_objects.add_then_fetch(objects);
123   _live_bytes.add_then_fetch(bytes);
124 }
125 
126 inline void ZLiveMap::inc_will_expand(uint32_t objects) {
127   _will_expand_objects.add_then_fetch(objects);
128 }
129 
130 inline BitMap::idx_t ZLiveMap::segment_start(BitMap::idx_t segment) const {
131   return segment * _segment_size;
132 }
133 
134 inline BitMap::idx_t ZLiveMap::segment_end(BitMap::idx_t segment) const {
135   return segment_start(segment) + _segment_size;
136 }
137 
138 inline size_t ZLiveMap::do_object(ObjectClosure* cl, zaddress addr) const {
139   // Get the size of the object before calling the closure, which
140   // might overwrite the object in case we are relocating in-place.
141   const size_t size = ZUtils::object_size(addr);
142 
143   // Apply closure
144   cl->do_object(to_oop(addr));
145 
146   return size;
147 }
148 
149 template <typename Function>
150 inline void ZLiveMap::iterate_segment(BitMap::idx_t segment, Function function) {
151   assert(is_segment_live(segment), "Must be");
152 
153   const BitMap::idx_t start_index = segment_start(segment);
154   const BitMap::idx_t end_index   = segment_end(segment);
155 
156   _bitmap.iterate(function, start_index, end_index);
157 }
158 
159 template <typename Function>
160 inline void ZLiveMap::iterate(ZGenerationId id, Function function) {
161   if (!is_marked(id)) {
162     return;
163   }
164 
165   auto live_only = [&](BitMap::idx_t index) -> bool {
166     if ((index & 1) == 0) {
167       return function(index);
168     }
169     // Don't visit the finalizable bits
170     return true;
171   };
172 
173   for (BitMap::idx_t segment = first_live_segment(); segment < NumSegments; segment = next_live_segment(segment)) {
174     // For each live segment
175     iterate_segment(segment, live_only);
176   }
177 }
178 
179 // Find the bit index that correspond the start of the object that is lower,
180 // or equal, to the given index (index is inclusive).
181 //
182 // Typically used to find the start of an object when there's only a field
183 // address available. Note that it's not guaranteed that the found index
184 // corresponds to an object that spans the given index. This function just
185 // looks at the bits. The calling code is responsible to check the object
186 // at the returned index.
187 //
188 // returns -1 if no bit was found
189 inline BitMap::idx_t ZLiveMap::find_base_bit(BitMap::idx_t index) {
190   // Check first segment
191   const BitMap::idx_t start_segment = index_to_segment(index);
192   if (is_segment_live(start_segment)) {
193     const BitMap::idx_t res = find_base_bit_in_segment(segment_start(start_segment), index);
194     if (res != BitMap::idx_t(-1)) {
195       return res;
196     }
197   }
198 
199   // Search earlier segments
200   for (BitMap::idx_t segment = start_segment; segment-- > 0; ) {
201     if (is_segment_live(segment)) {
202       const BitMap::idx_t res = find_base_bit_in_segment(segment_start(segment), segment_end(segment) - 1);
203       if (res != BitMap::idx_t(-1)) {
204         return res;
205       }
206     }
207   }
208 
209   // Not found
210   return BitMap::idx_t(-1);
211 }
212 
213 // Find the bit index that correspond the start of the object that is lower,
214 // or equal, to the given index (index is inclusive). Stopping when reaching
215 // start.
216 inline BitMap::idx_t ZLiveMap::find_base_bit_in_segment(BitMap::idx_t start, BitMap::idx_t index) {
217   assert(index_to_segment(start) == index_to_segment(index), "Only supports searches within segments start: %zu index: %zu", start, index);
218   assert(is_segment_live(index_to_segment(start)), "Must be live");
219 
220   // Search backwards - + 1 to make an exclusive index.
221   const BitMap::idx_t end = index + 1;
222   const BitMap::idx_t bit = _bitmap.find_last_set_bit(start, end);
223   if (bit == end) {
224     return BitMap::idx_t(-1);
225   }
226 
227   // The bitmaps contain pairs of bits to deal with strongly marked vs only
228   // finalizable marked. Align down to get the first bit position.
229   return bit & ~BitMap::idx_t(1);
230 }
231 
232 #endif // SHARE_GC_Z_ZLIVEMAP_INLINE_HPP