Skip to content

Commit

Permalink
8317354: Serial: Move DirtyCardToOopClosure to gc/serial folder
Browse files Browse the repository at this point in the history
Reviewed-by: tschatzl, iwalulya
  • Loading branch information
albertnetymk committed Oct 4, 2023
1 parent 0a3a925 commit 4195246
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 181 deletions.
181 changes: 181 additions & 0 deletions src/hotspot/share/gc/serial/cardTableRS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,187 @@
#include "runtime/os.hpp"
#include "utilities/macros.hpp"

// A dirty card to oop closure for contiguous spaces (ContiguousSpace and
// sub-classes). It knows how to filter out objects that are outside of the
// _boundary.
// (Note that because of the imprecise nature of the write barrier, this may
// iterate over oops beyond the region.)
//
// Assumptions:
// 1. That the actual top of any area in a memory region
// contained by the space is bounded by the end of the contiguous
// region of the space.
// 2. That the space is really made up of objects and not just
// blocks.

class DirtyCardToOopClosure: public MemRegionClosure {
protected:
OopIterateClosure* _cl;
Space* _sp;
HeapWord* _min_done; // Need a downwards traversal to compensate
// imprecise write barrier; this is the
// lowest location already done (or,
// alternatively, the lowest address that
// shouldn't be done again. null means infinity.)
NOT_PRODUCT(HeapWord* _last_bottom;)

// Get the actual top of the area on which the closure will
// operate, given where the top is assumed to be (the end of the
// memory region passed to do_MemRegion) and where the object
// at the top is assumed to start. For example, an object may
// start at the top but actually extend past the assumed top,
// in which case the top becomes the end of the object.
HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj);

// Walk the given memory region from bottom to (actual) top
// looking for objects and applying the oop closure (_cl) to
// them. The base implementation of this treats the area as
// blocks, where a block may or may not be an object. Sub-
// classes should override this to provide more accurate
// or possibly more efficient walking.
void walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top);

// Walk the given memory region, from bottom to top, applying
// the given oop closure to (possibly) all objects found. The
// given oop closure may or may not be the same as the oop
// closure with which this closure was created, as it may
// be a filtering closure which makes use of the _boundary.
// We offer two signatures, so the FilteringClosure static type is
// apparent.
void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
OopIterateClosure* cl);
public:
DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl) :
_cl(cl), _sp(sp), _min_done(nullptr) {
NOT_PRODUCT(_last_bottom = nullptr);
}

void do_MemRegion(MemRegion mr) override;
};

HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
HeapWord* top_obj) {
if (top_obj != nullptr && top_obj < (_sp->toContiguousSpace())->top()) {
if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) {
// An arrayOop is starting on the dirty card - since we do exact
// store checks for objArrays we are done.
} else {
// Otherwise, it is possible that the object starting on the dirty
// card spans the entire card, and that the store happened on a
// later card. Figure out where the object ends.
assert(_sp->block_size(top_obj) == cast_to_oop(top_obj)->size(),
"Block size and object size mismatch");
top = top_obj + cast_to_oop(top_obj)->size();
}
} else {
top = (_sp->toContiguousSpace())->top();
}
return top;
}

void DirtyCardToOopClosure::walk_mem_region(MemRegion mr,
HeapWord* bottom,
HeapWord* top) {
// Note that this assumption won't hold if we have a concurrent
// collector in this space, which may have freed up objects after
// they were dirtied and before the stop-the-world GC that is
// examining cards here.
assert(bottom < top, "ought to be at least one obj on a dirty card.");

walk_mem_region_with_cl(mr, bottom, top, _cl);
}

// We get called with "mr" representing the dirty region
// that we want to process. Because of imprecise marking,
// we may need to extend the incoming "mr" to the right,
// and scan more. However, because we may already have
// scanned some of that extended region, we may need to
// trim its right-end back some so we do not scan what
// we (or another worker thread) may already have scanned
// or planning to scan.
void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) {
HeapWord* bottom = mr.start();
HeapWord* last = mr.last();
HeapWord* top = mr.end();
HeapWord* bottom_obj;
HeapWord* top_obj;

assert(_last_bottom == nullptr || top <= _last_bottom,
"Not decreasing");
NOT_PRODUCT(_last_bottom = mr.start());

bottom_obj = _sp->block_start(bottom);
top_obj = _sp->block_start(last);

assert(bottom_obj <= bottom, "just checking");
assert(top_obj <= top, "just checking");

// Given what we think is the top of the memory region and
// the start of the object at the top, get the actual
// value of the top.
top = get_actual_top(top, top_obj);

// If the previous call did some part of this region, don't redo.
if (_min_done != nullptr && _min_done < top) {
top = _min_done;
}

// Top may have been reset, and in fact may be below bottom,
// e.g. the dirty card region is entirely in a now free object
// -- something that could happen with a concurrent sweeper.
bottom = MIN2(bottom, top);
MemRegion extended_mr = MemRegion(bottom, top);
assert(bottom <= top &&
(_min_done == nullptr || top <= _min_done),
"overlap!");

// Walk the region if it is not empty; otherwise there is nothing to do.
if (!extended_mr.is_empty()) {
walk_mem_region(extended_mr, bottom_obj, top);
}

_min_done = bottom;
}

void DirtyCardToOopClosure::walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom,
HeapWord* top,
OopIterateClosure* cl) {
bottom += cast_to_oop(bottom)->oop_iterate_size(cl, mr);
if (bottom < top) {
HeapWord* next_obj = bottom + cast_to_oop(bottom)->size();
while (next_obj < top) {
/* Bottom lies entirely below top, so we can call the */
/* non-memRegion version of oop_iterate below. */
cast_to_oop(bottom)->oop_iterate(cl);
bottom = next_obj;
next_obj = bottom + cast_to_oop(bottom)->size();
}
/* Last object. */
cast_to_oop(bottom)->oop_iterate(cl, mr);
}
}

class ClearNoncleanCardWrapper: public MemRegionClosure {
DirtyCardToOopClosure* _dirty_card_closure;
CardTableRS* _ct;

public:

typedef CardTable::CardValue CardValue;
private:
// Clears the given card, return true if the corresponding card should be
// processed.
inline bool clear_card(CardValue* entry);
// check alignment of pointer
bool is_word_aligned(CardValue* entry);

public:
ClearNoncleanCardWrapper(DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct);
void do_MemRegion(MemRegion mr) override;
};

inline bool ClearNoncleanCardWrapper::clear_card(CardValue* entry) {
assert(*entry == CardTableRS::dirty_card_val(), "Only look at dirty cards.");
*entry = CardTableRS::clean_card_val();
Expand Down
19 changes: 0 additions & 19 deletions src/hotspot/share/gc/serial/cardTableRS.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,4 @@ class CardTableRS : public CardTable {
bool is_in_young(const void* p) const override;
};

class ClearNoncleanCardWrapper: public MemRegionClosure {
DirtyCardToOopClosure* _dirty_card_closure;
CardTableRS* _ct;

public:

typedef CardTable::CardValue CardValue;
private:
// Clears the given card, return true if the corresponding card should be
// processed.
inline bool clear_card(CardValue* entry);
// check alignment of pointer
bool is_word_aligned(CardValue* entry);

public:
ClearNoncleanCardWrapper(DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct);
void do_MemRegion(MemRegion mr) override;
};

#endif // SHARE_GC_SERIAL_CARDTABLERS_HPP
103 changes: 0 additions & 103 deletions src/hotspot/share/gc/shared/space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,109 +46,6 @@
#include "gc/serial/defNewGeneration.hpp"
#endif

HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
HeapWord* top_obj) {
if (top_obj != nullptr && top_obj < (_sp->toContiguousSpace())->top()) {
if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) {
// An arrayOop is starting on the dirty card - since we do exact
// store checks for objArrays we are done.
} else {
// Otherwise, it is possible that the object starting on the dirty
// card spans the entire card, and that the store happened on a
// later card. Figure out where the object ends.
assert(_sp->block_size(top_obj) == cast_to_oop(top_obj)->size(),
"Block size and object size mismatch");
top = top_obj + cast_to_oop(top_obj)->size();
}
} else {
top = (_sp->toContiguousSpace())->top();
}
return top;
}

void DirtyCardToOopClosure::walk_mem_region(MemRegion mr,
HeapWord* bottom,
HeapWord* top) {
// Note that this assumption won't hold if we have a concurrent
// collector in this space, which may have freed up objects after
// they were dirtied and before the stop-the-world GC that is
// examining cards here.
assert(bottom < top, "ought to be at least one obj on a dirty card.");

walk_mem_region_with_cl(mr, bottom, top, _cl);
}

// We get called with "mr" representing the dirty region
// that we want to process. Because of imprecise marking,
// we may need to extend the incoming "mr" to the right,
// and scan more. However, because we may already have
// scanned some of that extended region, we may need to
// trim its right-end back some so we do not scan what
// we (or another worker thread) may already have scanned
// or planning to scan.
void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) {
HeapWord* bottom = mr.start();
HeapWord* last = mr.last();
HeapWord* top = mr.end();
HeapWord* bottom_obj;
HeapWord* top_obj;

assert(_last_bottom == nullptr || top <= _last_bottom,
"Not decreasing");
NOT_PRODUCT(_last_bottom = mr.start());

bottom_obj = _sp->block_start(bottom);
top_obj = _sp->block_start(last);

assert(bottom_obj <= bottom, "just checking");
assert(top_obj <= top, "just checking");

// Given what we think is the top of the memory region and
// the start of the object at the top, get the actual
// value of the top.
top = get_actual_top(top, top_obj);

// If the previous call did some part of this region, don't redo.
if (_min_done != nullptr && _min_done < top) {
top = _min_done;
}

// Top may have been reset, and in fact may be below bottom,
// e.g. the dirty card region is entirely in a now free object
// -- something that could happen with a concurrent sweeper.
bottom = MIN2(bottom, top);
MemRegion extended_mr = MemRegion(bottom, top);
assert(bottom <= top &&
(_min_done == nullptr || top <= _min_done),
"overlap!");

// Walk the region if it is not empty; otherwise there is nothing to do.
if (!extended_mr.is_empty()) {
walk_mem_region(extended_mr, bottom_obj, top);
}

_min_done = bottom;
}

void DirtyCardToOopClosure::walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom,
HeapWord* top,
OopIterateClosure* cl) {
bottom += cast_to_oop(bottom)->oop_iterate_size(cl, mr);
if (bottom < top) {
HeapWord* next_obj = bottom + cast_to_oop(bottom)->size();
while (next_obj < top) {
/* Bottom lies entirely below top, so we can call the */
/* non-memRegion version of oop_iterate below. */
cast_to_oop(bottom)->oop_iterate(cl);
bottom = next_obj;
next_obj = bottom + cast_to_oop(bottom)->size();
}
/* Last object. */
cast_to_oop(bottom)->oop_iterate(cl, mr);
}
}

void Space::initialize(MemRegion mr,
bool clear_space,
bool mangle_space) {
Expand Down
59 changes: 0 additions & 59 deletions src/hotspot/share/gc/shared/space.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,65 +221,6 @@ class Space: public CHeapObj<mtGC> {
virtual void verify() const = 0;
};

// A dirty card to oop closure for contiguous spaces (ContiguousSpace and
// sub-classes). It knows how to filter out objects that are outside of the
// _boundary.
// (Note that because of the imprecise nature of the write barrier, this may
// iterate over oops beyond the region.)
//
// Assumptions:
// 1. That the actual top of any area in a memory region
// contained by the space is bounded by the end of the contiguous
// region of the space.
// 2. That the space is really made up of objects and not just
// blocks.

class DirtyCardToOopClosure: public MemRegionClosure {
protected:
OopIterateClosure* _cl;
Space* _sp;
HeapWord* _min_done; // Need a downwards traversal to compensate
// imprecise write barrier; this is the
// lowest location already done (or,
// alternatively, the lowest address that
// shouldn't be done again. null means infinity.)
NOT_PRODUCT(HeapWord* _last_bottom;)

// Get the actual top of the area on which the closure will
// operate, given where the top is assumed to be (the end of the
// memory region passed to do_MemRegion) and where the object
// at the top is assumed to start. For example, an object may
// start at the top but actually extend past the assumed top,
// in which case the top becomes the end of the object.
HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj);

// Walk the given memory region from bottom to (actual) top
// looking for objects and applying the oop closure (_cl) to
// them. The base implementation of this treats the area as
// blocks, where a block may or may not be an object. Sub-
// classes should override this to provide more accurate
// or possibly more efficient walking.
void walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top);

// Walk the given memory region, from bottom to top, applying
// the given oop closure to (possibly) all objects found. The
// given oop closure may or may not be the same as the oop
// closure with which this closure was created, as it may
// be a filtering closure which makes use of the _boundary.
// We offer two signatures, so the FilteringClosure static type is
// apparent.
void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
OopIterateClosure* cl);
public:
DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl) :
_cl(cl), _sp(sp), _min_done(nullptr) {
NOT_PRODUCT(_last_bottom = nullptr);
}

void do_MemRegion(MemRegion mr) override;
};

// A structure to represent a point at which objects are being copied
// during compaction.
class CompactPoint : public StackObj {
Expand Down

1 comment on commit 4195246

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.