6711316: Open source the Garbage-First garbage collector

First mercurial integration of the code for the Garbage-First garbage collector.

Reviewed-by: apetrusenko, iveresov, jmasa, sgoldman, tonyp, ysr
This commit is contained in:
Y. Srinivas Ramakrishna 2008-06-05 15:57:56 -07:00
parent 39463bb3fc
commit 18f3386a98
215 changed files with 36088 additions and 1249 deletions

View file

@ -105,7 +105,7 @@ class Space: public CHeapObj {
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 @@ class Space: public CHeapObj {
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 @@ class Space: public CHeapObj {
// "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 @@ protected:
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 @@ public:
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 @@ private:
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 @@ protected:
/* 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 @@ protected:
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. */ \
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. */ \
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 @@ protected:
} \
} \
\
/* 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 @@ protected:
/* 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 @@ class ContiguousSpace: public CompactibleSpace {
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 @@ class ContiguousSpace: public CompactibleSpace {
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 @@ class OffsetTableContigSpace: public ContiguousSpace {
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);