src/share/vm/gc_implementation/g1/concurrentMark.hpp

Print this page
rev 2724 : 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:

*** 426,436 **** // 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; --- 426,435 ----
*** 577,586 **** --- 576,602 ---- } 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; + 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
*** 714,738 **** // 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); // 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); // 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: --- 730,756 ---- // 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, 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, 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:
*** 772,789 **** // 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 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); --- 790,809 ---- // beginning of an evacuation pause. void drainAllSATBBuffers(); void checkpointRootsFinal(bool clear_all_soft_refs); void checkpointRootsFinalWork(); void cleanup(); void completeCleanup(); // Mark in the previous bitmap. NB: this is usually read-only, so use // this carefully! void markPrev(oop p); + + // Clears the mark in the next bitmap for the given object. void clear(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);
*** 888,897 **** --- 908,981 ---- return _MARKING_VERBOSE_ && _verbose_level >= medium_verbose; } bool verbose_high() { return _MARKING_VERBOSE_ && _verbose_level >= high_verbose; } + + // Counting data structure accessors + + // Returns the card bitmap for a given task or worker id. + BitMap& count_card_bitmap_for(int worker_i) { + assert(0 <= worker_i && 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_for(int worker_i) { + assert(0 <= worker_i && 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; + } + + // Add the given region's size to the # marked bytes for + // the given worker and region. Set the bits in the + // worker's/task's card bitmap that are associated + // with the range of cards spanned by the region. + // Note the memory region could be just one object. + void add_to_count_data_for(MemRegion mr, int worker_i); + + // As above, but for a single object + void add_to_count_data_for(oop obj, int worker_i); + + // As above but when we have already been given the heap + // region. + void add_to_count_data_for(MemRegion mr, HeapRegion* hr, int worker_i); + + // As above, but for a single object + void add_to_count_data_for(oop obj, HeapRegion* hr, int worker_i); + + // Updates the counting data with liveness info recorded for a + // region (typically a GCLab). + void add_to_count_data_for_region(MemRegion lab_mr, + BitMap* lab_card_bm, + intptr_t lab_bottom_card_num, + size_t lab_marked_bytes, + int worker_i); + + // 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_all_count_data(); + + // Verification routine + void verify_count_data(); }; // A class representing a marking task. class CMTask : public TerminatorTerminator { private: