8299953: Merge ContiguousSpaceDCTOC into DirtyCardToOopClosure

Reviewed-by: tschatzl, iwalulya
This commit is contained in:
Albert Mingkun Yang 2023-01-26 11:40:16 +00:00
parent a9b8acb643
commit 7725fe845b
2 changed files with 75 additions and 145 deletions

View File

@ -49,22 +49,20 @@
HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top, HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
HeapWord* top_obj) { HeapWord* top_obj) {
if (top_obj != NULL) { if (top_obj != NULL && top_obj < (_sp->toContiguousSpace())->top()) {
if (_sp->block_is_obj(top_obj)) { if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) {
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
// An arrayOop is starting on the dirty card - since we do exact // store checks for objArrays we are done.
// 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.
top = top_obj + cast_to_oop(top_obj)->size();
}
} else { } else {
top = top_obj; // 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 { } else {
assert(top == _sp->end(), "only case where top_obj == NULL"); top = (_sp->toContiguousSpace())->top();
} }
return top; return top;
} }
@ -72,25 +70,21 @@ HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
void DirtyCardToOopClosure::walk_mem_region(MemRegion mr, void DirtyCardToOopClosure::walk_mem_region(MemRegion mr,
HeapWord* bottom, HeapWord* bottom,
HeapWord* top) { HeapWord* top) {
// 1. Blocks may or may not be objects. // Note that this assumption won't hold if we have a concurrent
// 2. Even when a block_is_obj(), it may not entirely // collector in this space, which may have freed up objects after
// occupy the block if the block quantum is larger than // they were dirtied and before the stop-the-world GC that is
// the object size. // examining cards here.
// We can and should try to optimize by calling the non-MemRegion assert(bottom < top, "ought to be at least one obj on a dirty card.");
// version of oop_iterate() for all but the extremal objects
// (for which we need to call the MemRegion version of if (_boundary != NULL) {
// oop_iterate()) To be done post-beta XXX // We have a boundary outside of which we don't want to look
for (; bottom < top; bottom += _sp->block_size(bottom)) { // at objects, so create a filtering closure around the
// As in the case of contiguous space above, we'd like to // oop closure before walking the region.
// just use the value returned by oop_iterate to increment the FilteringClosure filter(_boundary, _cl);
// current pointer; unfortunately, that won't work in CMS because walk_mem_region_with_cl(mr, bottom, top, &filter);
// we'd need an interface change (it seems) to have the space } else {
// "adjust the object size" (for instance pad it up to its // No boundary, simply walk the heap with the oop closure.
// block alignment or minimum block size restrictions. XXX walk_mem_region_with_cl(mr, bottom, top, _cl);
if (_sp->block_is_obj(bottom) &&
!_sp->obj_allocated_since_save_marks(cast_to_oop(bottom))) {
cast_to_oop(bottom)->oop_iterate(_cl, mr);
}
} }
} }
@ -146,80 +140,38 @@ void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) {
_min_done = bottom; _min_done = bottom;
} }
HeapWord* ContiguousSpaceDCTOC::get_actual_top(HeapWord* top,
HeapWord* top_obj) {
if (top_obj != NULL && 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 ContiguousSpaceDCTOC::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.");
if (_boundary != NULL) {
// We have a boundary outside of which we don't want to look
// at objects, so create a filtering closure around the
// oop closure before walking the region.
FilteringClosure filter(_boundary, _cl);
walk_mem_region_with_cl(mr, bottom, top, &filter);
} else {
// No boundary, simply walk the heap with the oop closure.
walk_mem_region_with_cl(mr, bottom, top, _cl);
}
}
// We must replicate this so that the static type of "FilteringClosure" // We must replicate this so that the static type of "FilteringClosure"
// (see above) is apparent at the oop_iterate calls. // (see above) is apparent at the oop_iterate calls.
#define ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(ClosureType) \ #define DirtyCardToOopClosure__walk_mem_region_with_cl_DEFN(ClosureType) \
void ContiguousSpaceDCTOC::walk_mem_region_with_cl(MemRegion mr, \ void DirtyCardToOopClosure::walk_mem_region_with_cl(MemRegion mr, \
HeapWord* bottom, \ HeapWord* bottom, \
HeapWord* top, \ HeapWord* top, \
ClosureType* cl) { \ ClosureType* cl) { \
bottom += cast_to_oop(bottom)->oop_iterate_size(cl, mr); \ bottom += cast_to_oop(bottom)->oop_iterate_size(cl, mr); \
if (bottom < top) { \ if (bottom < top) { \
HeapWord* next_obj = bottom + cast_to_oop(bottom)->size(); \ HeapWord* next_obj = bottom + cast_to_oop(bottom)->size(); \
while (next_obj < top) { \ while (next_obj < top) { \
/* Bottom lies entirely below top, so we can call the */ \ /* Bottom lies entirely below top, so we can call the */ \
/* non-memRegion version of oop_iterate below. */ \ /* non-memRegion version of oop_iterate below. */ \
cast_to_oop(bottom)->oop_iterate(cl); \ cast_to_oop(bottom)->oop_iterate(cl); \
bottom = next_obj; \ bottom = next_obj; \
next_obj = bottom + cast_to_oop(bottom)->size(); \ next_obj = bottom + cast_to_oop(bottom)->size(); \
} \ } \
/* Last object. */ \ /* Last object. */ \
cast_to_oop(bottom)->oop_iterate(cl, mr); \ cast_to_oop(bottom)->oop_iterate(cl, mr); \
} \ } \
} }
// (There are only two of these, rather than N, because the split is due // (There are only two of these, rather than N, because the split is due
// only to the introduction of the FilteringClosure, a local part of the // only to the introduction of the FilteringClosure, a local part of the
// impl of this abstraction.) // impl of this abstraction.)
ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure) DirtyCardToOopClosure__walk_mem_region_with_cl_DEFN(OopIterateClosure)
ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure) DirtyCardToOopClosure__walk_mem_region_with_cl_DEFN(FilteringClosure)
DirtyCardToOopClosure* DirtyCardToOopClosure*
ContiguousSpace::new_dcto_cl(OopIterateClosure* cl, ContiguousSpace::new_dcto_cl(OopIterateClosure* cl,
HeapWord* boundary) { HeapWord* boundary) {
return new ContiguousSpaceDCTOC(this, cl, boundary); return new DirtyCardToOopClosure(this, cl, boundary);
} }
void Space::initialize(MemRegion mr, void Space::initialize(MemRegion mr,

View File

@ -226,15 +226,18 @@ class Space: public CHeapObj<mtGC> {
virtual void verify() const = 0; virtual void verify() const = 0;
}; };
// A MemRegionClosure (ResourceObj) whose "do_MemRegion" function applies an // A dirty card to oop closure for contiguous spaces (ContiguousSpace and
// OopClosure to (the addresses of) all the ref-containing fields that could // sub-classes). It knows how to filter out objects that are outside of the
// be modified by virtue of the given MemRegion being dirty. (Note that // _boundary.
// because of the imprecise nature of the write barrier, this may iterate // (Note that because of the imprecise nature of the write barrier, this may
// over oops beyond the region.) // iterate over oops beyond the region.)
// This base type for dirty card to oop closures handles memory regions //
// in non-contiguous spaces with no boundaries, and should be sub-classed // Assumptions:
// to support other space types. See ContiguousDCTOC for a sub-class // 1. That the actual top of any area in a memory region
// that works with ContiguousSpaces. // 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 MemRegionClosureRO { class DirtyCardToOopClosure: public MemRegionClosureRO {
protected: protected:
@ -255,7 +258,7 @@ protected:
// at the top is assumed to start. For example, an object may // at the top is assumed to start. For example, an object may
// start at the top but actually extend past the assumed top, // start at the top but actually extend past the assumed top,
// in which case the top becomes the end of the object. // in which case the top becomes the end of the object.
virtual HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj); HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj);
// Walk the given memory region from bottom to (actual) top // Walk the given memory region from bottom to (actual) top
// looking for objects and applying the oop closure (_cl) to // looking for objects and applying the oop closure (_cl) to
@ -263,7 +266,21 @@ protected:
// blocks, where a block may or may not be an object. Sub- // blocks, where a block may or may not be an object. Sub-
// classes should override this to provide more accurate // classes should override this to provide more accurate
// or possibly more efficient walking. // or possibly more efficient walking.
virtual void walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top); 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);
void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
FilteringClosure* cl);
public: public:
DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl, DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl,
@ -508,45 +525,6 @@ class ContiguousSpace: public CompactibleSpace {
void verify() const override; void verify() const override;
}; };
// 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.
//
// 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 ContiguousSpaceDCTOC : public DirtyCardToOopClosure {
// Overrides.
void walk_mem_region(MemRegion mr,
HeapWord* bottom, HeapWord* top) override;
HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj) override;
// 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);
void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
FilteringClosure* cl);
public:
ContiguousSpaceDCTOC(ContiguousSpace* sp, OopIterateClosure* cl,
HeapWord* boundary) :
DirtyCardToOopClosure(sp, cl, boundary)
{}
};
#if INCLUDE_SERIALGC #if INCLUDE_SERIALGC
// Class TenuredSpace is used by TenuredGeneration; it supports an efficient // Class TenuredSpace is used by TenuredGeneration; it supports an efficient