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* top_obj) {
if (top_obj != NULL) {
if (_sp->block_is_obj(top_obj)) {
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.
top = top_obj + cast_to_oop(top_obj)->size();
}
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 {
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 {
assert(top == _sp->end(), "only case where top_obj == NULL");
top = (_sp->toContiguousSpace())->top();
}
return top;
}
@ -72,25 +70,21 @@ HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
void DirtyCardToOopClosure::walk_mem_region(MemRegion mr,
HeapWord* bottom,
HeapWord* top) {
// 1. Blocks may or may not be objects.
// 2. Even when a block_is_obj(), it may not entirely
// occupy the block if the block quantum is larger than
// the object size.
// We can and should try to optimize by calling the non-MemRegion
// version of oop_iterate() for all but the extremal objects
// (for which we need to call the MemRegion version of
// oop_iterate()) To be done post-beta XXX
for (; bottom < top; bottom += _sp->block_size(bottom)) {
// As in the case of contiguous space above, we'd like to
// just use the value returned by oop_iterate to increment the
// current pointer; unfortunately, that won't work in CMS because
// we'd need an interface change (it seems) to have the space
// "adjust the object size" (for instance pad it up to its
// block alignment or minimum block size restrictions. XXX
if (_sp->block_is_obj(bottom) &&
!_sp->obj_allocated_since_save_marks(cast_to_oop(bottom))) {
cast_to_oop(bottom)->oop_iterate(_cl, mr);
}
// 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);
}
}
@ -146,80 +140,38 @@ void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) {
_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"
// (see above) is apparent at the oop_iterate calls.
#define ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(ClosureType) \
void ContiguousSpaceDCTOC::walk_mem_region_with_cl(MemRegion mr, \
HeapWord* bottom, \
HeapWord* top, \
ClosureType* 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); \
} \
#define DirtyCardToOopClosure__walk_mem_region_with_cl_DEFN(ClosureType) \
void DirtyCardToOopClosure::walk_mem_region_with_cl(MemRegion mr, \
HeapWord* bottom, \
HeapWord* top, \
ClosureType* 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); \
} \
}
// (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
// impl of this abstraction.)
ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure)
ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure)
DirtyCardToOopClosure__walk_mem_region_with_cl_DEFN(OopIterateClosure)
DirtyCardToOopClosure__walk_mem_region_with_cl_DEFN(FilteringClosure)
DirtyCardToOopClosure*
ContiguousSpace::new_dcto_cl(OopIterateClosure* cl,
HeapWord* boundary) {
return new ContiguousSpaceDCTOC(this, cl, boundary);
return new DirtyCardToOopClosure(this, cl, boundary);
}
void Space::initialize(MemRegion mr,

View File

@ -226,15 +226,18 @@ class Space: public CHeapObj<mtGC> {
virtual void verify() const = 0;
};
// A MemRegionClosure (ResourceObj) whose "do_MemRegion" function applies an
// OopClosure to (the addresses of) all the ref-containing fields that could
// be modified by virtue of the given MemRegion being dirty. (Note that
// because of the imprecise nature of the write barrier, this may 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
// to support other space types. See ContiguousDCTOC for a sub-class
// that works with ContiguousSpaces.
// 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 MemRegionClosureRO {
protected:
@ -255,7 +258,7 @@ protected:
// 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.
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
// 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-
// classes should override this to provide more accurate
// 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:
DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl,
@ -508,45 +525,6 @@ class ContiguousSpace: public CompactibleSpace {
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
// Class TenuredSpace is used by TenuredGeneration; it supports an efficient