diff -r 0b27f3512f9e -r 37f87013dfd8 src/share/vm/memory/space.hpp --- a/src/share/vm/memory/space.hpp Wed Jun 04 13:51:09 2008 -0700 +++ b/src/share/vm/memory/space.hpp Thu Jun 05 15:57:56 2008 -0700 @@ -105,7 +105,7 @@ virtual void set_bottom(HeapWord* value) { _bottom = value; } virtual void set_end(HeapWord* value) { _end = value; } - HeapWord* saved_mark_word() const { return _saved_mark_word; } + virtual HeapWord* saved_mark_word() const { return _saved_mark_word; } void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; } MemRegionClosure* preconsumptionDirtyCardClosure() const { @@ -131,8 +131,18 @@ return MemRegion(bottom(), saved_mark_word()); } - // Initialization + // Initialization. + // "initialize" should be called once on a space, before it is used for + // any purpose. The "mr" arguments gives the bounds of the space, and + // the "clear_space" argument should be true unless the memory in "mr" is + // known to be zeroed. virtual void initialize(MemRegion mr, bool clear_space); + + // Sets the bounds (bottom and end) of the current space to those of "mr." + void set_bounds(MemRegion mr); + + // The "clear" method must be called on a region that may have + // had allocation performed in it, but is now to be considered empty. virtual void clear(); // For detecting GC bugs. Should only be called at GC boundaries, since @@ -216,7 +226,13 @@ // "block" that contains "p". We say "block" instead of "object" since // some heaps may not pack objects densely; a chunk may either be an // object or a non-object. If "p" is not in the space, return NULL. - virtual HeapWord* block_start(const void* p) const = 0; + virtual HeapWord* block_start_const(const void* p) const = 0; + + // The non-const version may have benevolent side effects on the data + // structure supporting these calls, possibly speeding up future calls. + // The default implementation, however, is simply to call the const + // version. + inline virtual HeapWord* block_start(const void* p); // Requires "addr" to be the start of a chunk, and returns its size. // "addr + size" is required to be the start of a new chunk, or the end @@ -282,12 +298,13 @@ CardTableModRefBS::PrecisionStyle _precision; HeapWord* _boundary; // If non-NULL, process only non-NULL oops // pointing below boundary. - HeapWord* _min_done; // ObjHeadPreciseArray precision requires + HeapWord* _min_done; // ObjHeadPreciseArray precision requires // a downwards traversal; 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;) + NOT_PRODUCT(HeapWord* _last_explicit_min_done;) // 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 @@ -311,13 +328,15 @@ HeapWord* boundary) : _sp(sp), _cl(cl), _precision(precision), _boundary(boundary), _min_done(NULL) { - NOT_PRODUCT(_last_bottom = NULL;) + NOT_PRODUCT(_last_bottom = NULL); + NOT_PRODUCT(_last_explicit_min_done = NULL); } void do_MemRegion(MemRegion mr); void set_min_done(HeapWord* min_done) { _min_done = min_done; + NOT_PRODUCT(_last_explicit_min_done = _min_done); } #ifndef PRODUCT void set_last_bottom(HeapWord* last_bottom) { @@ -355,6 +374,7 @@ public: virtual void initialize(MemRegion mr, bool clear_space); + virtual void clear(); // Used temporarily during a compaction phase to hold the value // top should have when compaction is complete. @@ -511,7 +531,7 @@ /* prefetch beyond q */ \ Prefetch::write(q, interval); \ /* size_t size = oop(q)->size(); changing this for cms for perm gen */\ - size_t size = block_size(q); \ + size_t size = block_size(q); \ compact_top = cp->space->forward(oop(q), size, cp, compact_top); \ q += size; \ end_of_live = q; \ @@ -575,68 +595,68 @@ cp->space->set_compaction_top(compact_top); \ } -#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \ - /* adjust all the interior pointers to point at the new locations of objects \ - * Used by MarkSweep::mark_sweep_phase3() */ \ +#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \ + /* adjust all the interior pointers to point at the new locations of objects \ + * Used by MarkSweep::mark_sweep_phase3() */ \ \ - HeapWord* q = bottom(); \ - HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \ + HeapWord* q = bottom(); \ + HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \ \ - assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \ + assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \ \ - if (q < t && _first_dead > q && \ + if (q < t && _first_dead > q && \ !oop(q)->is_gc_marked()) { \ /* we have a chunk of the space which hasn't moved and we've \ * reinitialized the mark word during the previous pass, so we can't \ - * use is_gc_marked for the traversal. */ \ + * use is_gc_marked for the traversal. */ \ HeapWord* end = _first_dead; \ \ - while (q < end) { \ - /* I originally tried to conjoin "block_start(q) == q" to the \ - * assertion below, but that doesn't work, because you can't \ - * accurately traverse previous objects to get to the current one \ - * after their pointers (including pointers into permGen) have been \ - * updated, until the actual compaction is done. dld, 4/00 */ \ - assert(block_is_obj(q), \ - "should be at block boundaries, and should be looking at objs"); \ + while (q < end) { \ + /* I originally tried to conjoin "block_start(q) == q" to the \ + * assertion below, but that doesn't work, because you can't \ + * accurately traverse previous objects to get to the current one \ + * after their pointers (including pointers into permGen) have been \ + * updated, until the actual compaction is done. dld, 4/00 */ \ + assert(block_is_obj(q), \ + "should be at block boundaries, and should be looking at objs"); \ \ VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \ \ - /* point all the oops to the new location */ \ - size_t size = oop(q)->adjust_pointers(); \ - size = adjust_obj_size(size); \ + /* point all the oops to the new location */ \ + size_t size = oop(q)->adjust_pointers(); \ + size = adjust_obj_size(size); \ \ VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \ - \ + \ VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \ - \ + \ q += size; \ - } \ + } \ \ - if (_first_dead == t) { \ - q = t; \ - } else { \ - /* $$$ This is funky. Using this to read the previously written \ - * LiveRange. See also use below. */ \ + if (_first_dead == t) { \ + q = t; \ + } else { \ + /* $$$ This is funky. Using this to read the previously written \ + * LiveRange. See also use below. */ \ q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); \ - } \ - } \ + } \ + } \ \ const intx interval = PrefetchScanIntervalInBytes; \ \ - debug_only(HeapWord* prev_q = NULL); \ - while (q < t) { \ - /* prefetch beyond q */ \ + debug_only(HeapWord* prev_q = NULL); \ + while (q < t) { \ + /* prefetch beyond q */ \ Prefetch::write(q, interval); \ - if (oop(q)->is_gc_marked()) { \ - /* q is alive */ \ + if (oop(q)->is_gc_marked()) { \ + /* q is alive */ \ VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \ - /* point all the oops to the new location */ \ - size_t size = oop(q)->adjust_pointers(); \ - size = adjust_obj_size(size); \ - VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \ + /* point all the oops to the new location */ \ + size_t size = oop(q)->adjust_pointers(); \ + size = adjust_obj_size(size); \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \ VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \ - debug_only(prev_q = q); \ + debug_only(prev_q = q); \ q += size; \ } else { \ /* q is not a live object, so its mark should point at the next \ @@ -716,6 +736,8 @@ } \ } \ \ + /* Let's remember if we were empty before we did the compaction. */ \ + bool was_empty = used_region().is_empty(); \ /* Reset space after compaction is complete */ \ reset_after_compaction(); \ /* We do this clear, below, since it has overloaded meanings for some */ \ @@ -723,8 +745,8 @@ /* compacted into will have had their offset table thresholds updated */ \ /* continuously, but those that weren't need to have their thresholds */ \ /* re-initialized. Also mangles unused area for debugging. */ \ - if (is_empty()) { \ - clear(); \ + if (used_region().is_empty()) { \ + if (!was_empty) clear(); \ } else { \ if (ZapUnusedHeapArea) mangle_unused_area(); \ } \ @@ -750,8 +772,8 @@ HeapWord* top() const { return _top; } void set_top(HeapWord* value) { _top = value; } - void set_saved_mark() { _saved_mark_word = top(); } - void reset_saved_mark() { _saved_mark_word = bottom(); } + virtual void set_saved_mark() { _saved_mark_word = top(); } + void reset_saved_mark() { _saved_mark_word = bottom(); } virtual void clear(); @@ -843,7 +865,7 @@ virtual void object_iterate_from(WaterMark mark, ObjectClosure* blk); // Very inefficient implementation. - virtual HeapWord* block_start(const void* p) const; + virtual HeapWord* block_start_const(const void* p) const; size_t block_size(const HeapWord* p) const; // If a block is in the allocated area, it is an object. bool block_is_obj(const HeapWord* p) const { return p < top(); } @@ -1000,9 +1022,10 @@ void set_bottom(HeapWord* value); void set_end(HeapWord* value); + virtual void initialize(MemRegion mr, bool clear_space); void clear(); - inline HeapWord* block_start(const void* p) const; + inline HeapWord* block_start_const(const void* p) const; // Add offset table update. virtual inline HeapWord* allocate(size_t word_size);