src/share/vm/gc_implementation/g1/concurrentMark.hpp
Print this page
rev 2896 : 6484965: G1: piggy-back liveness accounting phase on marking
Summary: Remove the separate counting phase of concurrent marking by tracking the amount of marked bytes and the cards spanned by marked objects in marking task/worker thread local data structures, which are updated as individual objects are marked.
Reviewed-by: brutisso
@@ -428,11 +428,10 @@
// structures (local and global) have been re-initialised. When they
// exit it, they are free to start working again.
WorkGangBarrierSync _first_overflow_barrier_sync;
WorkGangBarrierSync _second_overflow_barrier_sync;
-
// this is set by any task, when an overflow on the global data
// structures is detected.
volatile bool _has_overflown;
// true: marking is concurrent, false: we're in remark
volatile bool _concurrent;
@@ -580,10 +579,31 @@
} else {
return force_overflow_stw();
}
}
+ // Live Data Counting data structures...
+ // These data structures are initialized at the start of
+ // marking. They are written to while marking is active.
+ // They are aggregated during remark; the aggregated values
+ // are then used to populate the _region_bm, _card_bm, and
+ // the total live bytes, which are then subsequently updated
+ // during cleanup.
+
+ // An array of bitmaps (one bit map per task). Each bitmap
+ // is used to record the cards spanned by the live objects
+ // marked by that task/worker.
+ BitMap* _count_card_bitmaps;
+
+ // Used to record the number of marked live bytes
+ // (for each region, by worker thread).
+ size_t** _count_marked_bytes;
+
+ // Card index of the bottom of the G1 heap. Used for biasing indices into
+ // the card bitmaps.
+ intptr_t _heap_bottom_card_num;
+
public:
// Manipulation of the global mark stack.
// Notice that the first mark_stack_push is CAS-based, whereas the
// two below are Mutex-based. This is OK since the first one is only
// called during evacuation pauses and doesn't compete with the
@@ -701,14 +721,14 @@
return _task_queues->steal(task_num, hash_seed, obj);
}
// It grays an object by first marking it. Then, if it's behind the
// global finger, it also pushes it on the global stack.
- void deal_with_reference(oop obj);
+ void deal_with_reference(oop obj, int worker_i);
ConcurrentMark(ReservedSpace rs, int max_regions);
- ~ConcurrentMark();
+
ConcurrentMarkThread* cmThread() { return _cmThread; }
CMBitMapRO* prevMarkBitMap() const { return _prevMarkBitMap; }
CMBitMap* nextMarkBitMap() const { return _nextMarkBitMap; }
@@ -725,25 +745,27 @@
// This notifies CM that a root during initial-mark needs to be
// grayed and it's MT-safe. Currently, we just mark it. But, in the
// future, we can experiment with pushing it on the stack and we can
// do this without changing G1CollectedHeap.
- void grayRoot(oop p);
+ void grayRoot(oop p, int worker_i);
+
// It's used during evacuation pauses to gray a region, if
// necessary, and it's MT-safe. It assumes that the caller has
// marked any objects on that region. If _should_gray_objects is
// true and we're still doing concurrent marking, the region is
// pushed on the region stack, if it is located below the global
// finger, otherwise we do nothing.
void grayRegionIfNecessary(MemRegion mr);
+
// It's used during evacuation pauses to mark and, if necessary,
// gray a single object and it's MT-safe. It assumes the caller did
// not mark the object. If _should_gray_objects is true and we're
// still doing concurrent marking, the objects is pushed on the
// global stack, if it is located below the global finger, otherwise
// we do nothing.
- void markAndGrayObjectIfNecessary(oop p);
+ void markAndGrayObjectIfNecessary(oop p, int worker_i);
// It iterates over the heap and for each object it comes across it
// will dump the contents of its reference fields, as well as
// liveness information for the object and its referents. The dump
// will be written to a file with the following name:
@@ -783,18 +805,20 @@
// beginning of an evacuation pause.
void drainAllSATBBuffers();
void checkpointRootsFinal(bool clear_all_soft_refs);
void checkpointRootsFinalWork();
- void calcDesiredRegions();
void cleanup();
void completeCleanup();
// Mark in the previous bitmap. NB: this is usually read-only, so use
// this carefully!
void markPrev(oop p);
- void clear(oop p);
+
+ // Clears the mark in the next bitmap for the given object.
+ void clear_mark(oop p);
+
// Clears marks for all objects in the given range, for both prev and
// next bitmaps. NB: the previous bitmap is usually read-only, so use
// this carefully!
void clearRangeBothMaps(MemRegion mr);
@@ -899,10 +923,102 @@
return _MARKING_VERBOSE_ && _verbose_level >= medium_verbose;
}
bool verbose_high() {
return _MARKING_VERBOSE_ && _verbose_level >= high_verbose;
}
+
+ // Counting data structure accessors
+
+ // Returns the card number of the bottom of the G1 heap.
+ // Used in biasing indices into accounting card bitmaps.
+ intptr_t heap_bottom_card_num() const {
+ return _heap_bottom_card_num;
+ }
+
+ // Returns the card bitmap for a given task or worker id.
+ BitMap* count_card_bitmap_for(int worker_i) {
+ assert(0 <= worker_i && (size_t) worker_i < _max_task_num, "oob");
+ assert(_count_card_bitmaps != NULL, "uninitialized");
+ BitMap* task_card_bm = &_count_card_bitmaps[worker_i];
+ assert(task_card_bm->size() == _card_bm.size(), "size mismatch");
+ return task_card_bm;
+ }
+
+ // Returns the array containing the marked bytes for each region,
+ // for the given worker or task id.
+ size_t* count_marked_bytes_array_for(int worker_i) {
+ assert(0 <= worker_i && (size_t) worker_i < _max_task_num, "oob");
+ assert(_count_marked_bytes != NULL, "uninitialized");
+ size_t* marked_bytes_array = _count_marked_bytes[worker_i];
+ assert(marked_bytes_array != NULL, "uninitialized");
+ return marked_bytes_array;
+ }
+
+ // Counts the size of the given memory region in the the given
+ // marked_bytes array slot for the given HeapRegion.
+ // Sets the bits in the given card bitmap that are associated with the
+ // cards that are spanned by the memory region.
+ inline void count_region(MemRegion mr, HeapRegion* hr,
+ size_t* marked_bytes_array,
+ BitMap* task_card_bm);
+
+ // Counts the given memory region in the ask/worker counting
+ // data structures for the given worker id.
+ inline void count_region(MemRegion mr, int worker_i);
+
+ // Counts the given object in the given task/worker counting
+ // data structures.
+ inline void count_object(oop obj, HeapRegion* hr,
+ size_t* marked_bytes_array,
+ BitMap* task_card_bm);
+
+ // Counts the given object in the task/worker counting data
+ // structures for the given worker id.
+ inline void count_object(oop obj, HeapRegion* hr, int worker_i);
+
+ // Attempts to mark the given object and, if successful, counts
+ // the object in the given task/worker counting structures.
+ inline bool par_mark_and_count(oop obj, HeapRegion* hr,
+ size_t* marked_bytes_array,
+ BitMap* task_card_bm);
+
+ // Attempts to mark the given object and, if successful, counts
+ // the object in the task/worker counting structures for the
+ // given worker id.
+ inline bool par_mark_and_count(oop obj, HeapRegion* hr, int worker_i);
+
+ // Similar to the above routine but we don't know the heap region that
+ // contains the object to be marked/counted, which this routine looks up.
+ inline bool par_mark_and_count(oop obj, int worker_i);
+
+ // Unconditionally mark the given object, and unconditinally count
+ // the object in the counting structures for worker id 0.
+ // Should *not* be called from parallel code.
+ inline bool mark_and_count(oop obj, HeapRegion* hr);
+
+ // Similar to the above routine but we don't know the heap region that
+ // contains the object to be marked/counted, which this routine looks up.
+ // Should *not* be called from parallel code.
+ inline bool mark_and_count(oop obj);
+
+ // Clears the count data for the given region from _all_ of
+ // the per-task counting data structures.
+ void clear_count_data_for_heap_region(HeapRegion* hr);
+
+protected:
+ // Clear all the per-task bitmaps and arrays used to store the
+ // counting data.
+ void clear_all_count_data();
+
+ // Aggregates the counting data for each worker/task
+ // that was constructed while marking. Also sets
+ // the amount of marked bytes for each region and
+ // the top at concurrent mark count.
+ void aggregate_and_clear_count_data();
+
+ // Verification routine
+ void verify_count_data();
};
// A class representing a marking task.
class CMTask : public TerminatorTerminator {
private:
@@ -1017,10 +1133,16 @@
// phase, i.e. SATB buffer availability...)
bool _concurrent;
TruncatedSeq _marking_step_diffs_ms;
+ // Counting data structures. Embedding the task's marked_bytes_array
+ // and card bitmap into the actual task saves having to go through
+ // the ConcurrentMark object.
+ size_t* _marked_bytes_array;
+ BitMap* _card_bm;
+
// LOTS of statistics related with this task
#if _MARKING_STATS_
NumberSeq _all_clock_intervals_ms;
double _interval_start_time_ms;
@@ -1181,10 +1303,11 @@
assert(new_finger < _cm->finger(), "invariant");
_region_finger = new_finger;
}
CMTask(int task_num, ConcurrentMark *cm,
+ size_t* marked_bytes, BitMap* card_bm,
CMTaskQueue* task_queue, CMTaskQueueSet* task_queues);
// it prints statistics associated with this task
void print_stats();