mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
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:
parent
39463bb3fc
commit
18f3386a98
215 changed files with 36088 additions and 1249 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue