|
37 | 37 | #include "runtime/os.hpp" |
38 | 38 | #include "utilities/macros.hpp" |
39 | 39 |
|
| 40 | +// A dirty card to oop closure for contiguous spaces (ContiguousSpace and |
| 41 | +// sub-classes). It knows how to filter out objects that are outside of the |
| 42 | +// _boundary. |
| 43 | +// (Note that because of the imprecise nature of the write barrier, this may |
| 44 | +// iterate over oops beyond the region.) |
| 45 | +// |
| 46 | +// Assumptions: |
| 47 | +// 1. That the actual top of any area in a memory region |
| 48 | +// contained by the space is bounded by the end of the contiguous |
| 49 | +// region of the space. |
| 50 | +// 2. That the space is really made up of objects and not just |
| 51 | +// blocks. |
| 52 | + |
| 53 | +class DirtyCardToOopClosure: public MemRegionClosure { |
| 54 | +protected: |
| 55 | + OopIterateClosure* _cl; |
| 56 | + Space* _sp; |
| 57 | + HeapWord* _min_done; // Need a downwards traversal to compensate |
| 58 | + // imprecise write barrier; this is the |
| 59 | + // lowest location already done (or, |
| 60 | + // alternatively, the lowest address that |
| 61 | + // shouldn't be done again. null means infinity.) |
| 62 | + NOT_PRODUCT(HeapWord* _last_bottom;) |
| 63 | + |
| 64 | + // Get the actual top of the area on which the closure will |
| 65 | + // operate, given where the top is assumed to be (the end of the |
| 66 | + // memory region passed to do_MemRegion) and where the object |
| 67 | + // at the top is assumed to start. For example, an object may |
| 68 | + // start at the top but actually extend past the assumed top, |
| 69 | + // in which case the top becomes the end of the object. |
| 70 | + HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj); |
| 71 | + |
| 72 | + // Walk the given memory region from bottom to (actual) top |
| 73 | + // looking for objects and applying the oop closure (_cl) to |
| 74 | + // them. The base implementation of this treats the area as |
| 75 | + // blocks, where a block may or may not be an object. Sub- |
| 76 | + // classes should override this to provide more accurate |
| 77 | + // or possibly more efficient walking. |
| 78 | + void walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top); |
| 79 | + |
| 80 | + // Walk the given memory region, from bottom to top, applying |
| 81 | + // the given oop closure to (possibly) all objects found. The |
| 82 | + // given oop closure may or may not be the same as the oop |
| 83 | + // closure with which this closure was created, as it may |
| 84 | + // be a filtering closure which makes use of the _boundary. |
| 85 | + // We offer two signatures, so the FilteringClosure static type is |
| 86 | + // apparent. |
| 87 | + void walk_mem_region_with_cl(MemRegion mr, |
| 88 | + HeapWord* bottom, HeapWord* top, |
| 89 | + OopIterateClosure* cl); |
| 90 | +public: |
| 91 | + DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl) : |
| 92 | + _cl(cl), _sp(sp), _min_done(nullptr) { |
| 93 | + NOT_PRODUCT(_last_bottom = nullptr); |
| 94 | + } |
| 95 | + |
| 96 | + void do_MemRegion(MemRegion mr) override; |
| 97 | +}; |
| 98 | + |
| 99 | +HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top, |
| 100 | + HeapWord* top_obj) { |
| 101 | + if (top_obj != nullptr && top_obj < (_sp->toContiguousSpace())->top()) { |
| 102 | + if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) { |
| 103 | + // An arrayOop is starting on the dirty card - since we do exact |
| 104 | + // store checks for objArrays we are done. |
| 105 | + } else { |
| 106 | + // Otherwise, it is possible that the object starting on the dirty |
| 107 | + // card spans the entire card, and that the store happened on a |
| 108 | + // later card. Figure out where the object ends. |
| 109 | + assert(_sp->block_size(top_obj) == cast_to_oop(top_obj)->size(), |
| 110 | + "Block size and object size mismatch"); |
| 111 | + top = top_obj + cast_to_oop(top_obj)->size(); |
| 112 | + } |
| 113 | + } else { |
| 114 | + top = (_sp->toContiguousSpace())->top(); |
| 115 | + } |
| 116 | + return top; |
| 117 | +} |
| 118 | + |
| 119 | +void DirtyCardToOopClosure::walk_mem_region(MemRegion mr, |
| 120 | + HeapWord* bottom, |
| 121 | + HeapWord* top) { |
| 122 | + // Note that this assumption won't hold if we have a concurrent |
| 123 | + // collector in this space, which may have freed up objects after |
| 124 | + // they were dirtied and before the stop-the-world GC that is |
| 125 | + // examining cards here. |
| 126 | + assert(bottom < top, "ought to be at least one obj on a dirty card."); |
| 127 | + |
| 128 | + walk_mem_region_with_cl(mr, bottom, top, _cl); |
| 129 | +} |
| 130 | + |
| 131 | +// We get called with "mr" representing the dirty region |
| 132 | +// that we want to process. Because of imprecise marking, |
| 133 | +// we may need to extend the incoming "mr" to the right, |
| 134 | +// and scan more. However, because we may already have |
| 135 | +// scanned some of that extended region, we may need to |
| 136 | +// trim its right-end back some so we do not scan what |
| 137 | +// we (or another worker thread) may already have scanned |
| 138 | +// or planning to scan. |
| 139 | +void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) { |
| 140 | + HeapWord* bottom = mr.start(); |
| 141 | + HeapWord* last = mr.last(); |
| 142 | + HeapWord* top = mr.end(); |
| 143 | + HeapWord* bottom_obj; |
| 144 | + HeapWord* top_obj; |
| 145 | + |
| 146 | + assert(_last_bottom == nullptr || top <= _last_bottom, |
| 147 | + "Not decreasing"); |
| 148 | + NOT_PRODUCT(_last_bottom = mr.start()); |
| 149 | + |
| 150 | + bottom_obj = _sp->block_start(bottom); |
| 151 | + top_obj = _sp->block_start(last); |
| 152 | + |
| 153 | + assert(bottom_obj <= bottom, "just checking"); |
| 154 | + assert(top_obj <= top, "just checking"); |
| 155 | + |
| 156 | + // Given what we think is the top of the memory region and |
| 157 | + // the start of the object at the top, get the actual |
| 158 | + // value of the top. |
| 159 | + top = get_actual_top(top, top_obj); |
| 160 | + |
| 161 | + // If the previous call did some part of this region, don't redo. |
| 162 | + if (_min_done != nullptr && _min_done < top) { |
| 163 | + top = _min_done; |
| 164 | + } |
| 165 | + |
| 166 | + // Top may have been reset, and in fact may be below bottom, |
| 167 | + // e.g. the dirty card region is entirely in a now free object |
| 168 | + // -- something that could happen with a concurrent sweeper. |
| 169 | + bottom = MIN2(bottom, top); |
| 170 | + MemRegion extended_mr = MemRegion(bottom, top); |
| 171 | + assert(bottom <= top && |
| 172 | + (_min_done == nullptr || top <= _min_done), |
| 173 | + "overlap!"); |
| 174 | + |
| 175 | + // Walk the region if it is not empty; otherwise there is nothing to do. |
| 176 | + if (!extended_mr.is_empty()) { |
| 177 | + walk_mem_region(extended_mr, bottom_obj, top); |
| 178 | + } |
| 179 | + |
| 180 | + _min_done = bottom; |
| 181 | +} |
| 182 | + |
| 183 | +void DirtyCardToOopClosure::walk_mem_region_with_cl(MemRegion mr, |
| 184 | + HeapWord* bottom, |
| 185 | + HeapWord* top, |
| 186 | + OopIterateClosure* cl) { |
| 187 | + bottom += cast_to_oop(bottom)->oop_iterate_size(cl, mr); |
| 188 | + if (bottom < top) { |
| 189 | + HeapWord* next_obj = bottom + cast_to_oop(bottom)->size(); |
| 190 | + while (next_obj < top) { |
| 191 | + /* Bottom lies entirely below top, so we can call the */ |
| 192 | + /* non-memRegion version of oop_iterate below. */ |
| 193 | + cast_to_oop(bottom)->oop_iterate(cl); |
| 194 | + bottom = next_obj; |
| 195 | + next_obj = bottom + cast_to_oop(bottom)->size(); |
| 196 | + } |
| 197 | + /* Last object. */ |
| 198 | + cast_to_oop(bottom)->oop_iterate(cl, mr); |
| 199 | + } |
| 200 | +} |
| 201 | + |
| 202 | +class ClearNoncleanCardWrapper: public MemRegionClosure { |
| 203 | + DirtyCardToOopClosure* _dirty_card_closure; |
| 204 | + CardTableRS* _ct; |
| 205 | + |
| 206 | +public: |
| 207 | + |
| 208 | + typedef CardTable::CardValue CardValue; |
| 209 | +private: |
| 210 | + // Clears the given card, return true if the corresponding card should be |
| 211 | + // processed. |
| 212 | + inline bool clear_card(CardValue* entry); |
| 213 | + // check alignment of pointer |
| 214 | + bool is_word_aligned(CardValue* entry); |
| 215 | + |
| 216 | +public: |
| 217 | + ClearNoncleanCardWrapper(DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct); |
| 218 | + void do_MemRegion(MemRegion mr) override; |
| 219 | +}; |
| 220 | + |
40 | 221 | inline bool ClearNoncleanCardWrapper::clear_card(CardValue* entry) { |
41 | 222 | assert(*entry == CardTableRS::dirty_card_val(), "Only look at dirty cards."); |
42 | 223 | *entry = CardTableRS::clean_card_val(); |
|
0 commit comments