diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index b77f6f6c1b3..42b7aec2723 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -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, diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index c9606e7fdbb..54cddfe96fc 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -226,15 +226,18 @@ class Space: public CHeapObj { 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