# HG changeset patch # User tschatzl # Date 1574413418 -3600 # Node ID a1155217a563d53d226d56c4ec582fb6a4655c42 # Parent 82db5000a84549741c3b859514b9db6c539c4664 8233306: Sort members in G1's HeapRegion after removal of Space dependency Reviewed-by: sangheki, sjohanss diff -r 82db5000a845 -r a1155217a563 src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp --- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp Mon Nov 18 16:49:39 2019 +0100 +++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp Fri Nov 22 10:03:38 2019 +0100 @@ -53,7 +53,7 @@ assert(current->is_empty(), "Should have been cleared in phase 2."); } } - current->reset_during_compaction(); + current->reset_humongous_during_compaction(); } return false; } diff -r 82db5000a845 -r a1155217a563 src/hotspot/share/gc/g1/heapRegion.cpp --- a/src/hotspot/share/gc/g1/heapRegion.cpp Mon Nov 18 16:49:39 2019 +0100 +++ b/src/hotspot/share/gc/g1/heapRegion.cpp Fri Nov 22 10:03:38 2019 +0100 @@ -245,14 +245,15 @@ _type(), _humongous_start_region(NULL), _evacuation_failed(false), + _index_in_opt_cset(InvalidCSetIndex), _next(NULL), _prev(NULL), #ifdef ASSERT _containing_set(NULL), #endif - _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), - _index_in_opt_cset(InvalidCSetIndex), _young_index_in_cset(-1), - _surv_rate_group(NULL), _age_index(-1), _prev_top_at_mark_start(NULL), _next_top_at_mark_start(NULL), + _prev_marked_bytes(0), _next_marked_bytes(0), + _young_index_in_cset(-1), + _surv_rate_group(NULL), _age_index(-1), _gc_efficiency(0.0), _recorded_rs_length(0), _predicted_elapsed_time_ms(0), _node_index(G1NUMA::UnknownNodeIndex) { @@ -755,7 +756,7 @@ if (p < the_end) { // Look up top HeapWord* addr_1 = p; - HeapWord* b_start_1 = _bot_part.block_start_const(addr_1); + HeapWord* b_start_1 = block_start_const(addr_1); if (b_start_1 != p) { log_error(gc, verify)("BOT look up for top: " PTR_FORMAT " " " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, @@ -767,7 +768,7 @@ // Look up top + 1 HeapWord* addr_2 = p + 1; if (addr_2 < the_end) { - HeapWord* b_start_2 = _bot_part.block_start_const(addr_2); + HeapWord* b_start_2 = block_start_const(addr_2); if (b_start_2 != p) { log_error(gc, verify)("BOT look up for top + 1: " PTR_FORMAT " " " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, @@ -781,7 +782,7 @@ size_t diff = pointer_delta(the_end, p) / 2; HeapWord* addr_3 = p + diff; if (addr_3 < the_end) { - HeapWord* b_start_3 = _bot_part.block_start_const(addr_3); + HeapWord* b_start_3 = block_start_const(addr_3); if (b_start_3 != p) { log_error(gc, verify)("BOT look up for top + diff: " PTR_FORMAT " " " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, @@ -793,7 +794,7 @@ // Look up end - 1 HeapWord* addr_4 = the_end - 1; - HeapWord* b_start_4 = _bot_part.block_start_const(addr_4); + HeapWord* b_start_4 = block_start_const(addr_4); if (b_start_4 != p) { log_error(gc, verify)("BOT look up for end - 1: " PTR_FORMAT " " " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, diff -r 82db5000a845 -r a1155217a563 src/hotspot/share/gc/g1/heapRegion.hpp --- a/src/hotspot/share/gc/g1/heapRegion.hpp Mon Nov 18 16:49:39 2019 +0100 +++ b/src/hotspot/share/gc/g1/heapRegion.hpp Fri Nov 22 10:03:38 2019 +0100 @@ -96,6 +96,15 @@ void set_top(HeapWord* value) { _top = value; } HeapWord* top() const { return _top; } + // See the comment above in the declaration of _pre_dummy_top for an + // explanation of what it is. + void set_pre_dummy_top(HeapWord* pre_dummy_top) { + assert(is_in(pre_dummy_top) && pre_dummy_top <= top(), "pre-condition"); + _pre_dummy_top = pre_dummy_top; + } + HeapWord* pre_dummy_top() { return (_pre_dummy_top == NULL) ? top() : _pre_dummy_top; } + void reset_pre_dummy_top() { _pre_dummy_top = NULL; } + // Returns true iff the given the heap region contains the // given address as part of an allocated object. This may // be a potentially, so we restrict its use to assertion checks only. @@ -118,6 +127,12 @@ private: void reset_after_compaction() { set_top(compaction_top()); } + void clear(bool mangle_space); + + HeapWord* block_start_const(const void* p) const; + + void mangle_unused_area() PRODUCT_RETURN; + // Try to allocate at least min_word_size and up to desired_size from this region. // Returns NULL if not possible, otherwise sets actual_word_size to the amount of // space allocated. @@ -130,27 +145,10 @@ // This version synchronizes with other calls to par_allocate_impl(). inline HeapWord* par_allocate_impl(size_t min_word_size, size_t desired_word_size, size_t* actual_word_size); - void mangle_unused_area() PRODUCT_RETURN; - public: - void object_iterate(ObjectClosure* blk); + HeapWord* block_start(const void* p); - // See the comment above in the declaration of _pre_dummy_top for an - // explanation of what it is. - void set_pre_dummy_top(HeapWord* pre_dummy_top) { - assert(is_in(pre_dummy_top) && pre_dummy_top <= top(), "pre-condition"); - _pre_dummy_top = pre_dummy_top; - } - - HeapWord* pre_dummy_top() { - return (_pre_dummy_top == NULL) ? top() : _pre_dummy_top; - } - void reset_pre_dummy_top() { _pre_dummy_top = NULL; } - - void clear(bool mangle_space); - - HeapWord* block_start(const void* p); - HeapWord* block_start_const(const void* p) const; + void object_iterate(ObjectClosure* blk); // Allocation (return NULL if full). Assumes the caller has established // mutually exclusive access to the HeapRegion. @@ -161,34 +159,49 @@ HeapWord* allocate(size_t word_size); HeapWord* par_allocate(size_t word_size); - HeapWord* saved_mark_word() const { ShouldNotReachHere(); return NULL; } + inline HeapWord* par_allocate_no_bot_updates(size_t min_word_size, size_t desired_word_size, size_t* word_size); + inline HeapWord* allocate_no_bot_updates(size_t word_size); + inline HeapWord* allocate_no_bot_updates(size_t min_word_size, size_t desired_word_size, size_t* actual_size); - // MarkSweep support phase3 + // Full GC support methods. + HeapWord* initialize_threshold(); HeapWord* cross_threshold(HeapWord* start, HeapWord* end); + // Update heap region to be consistent after Full GC compaction. + void reset_humongous_during_compaction() { + assert(is_humongous(), + "should only be called for humongous regions"); + + zero_marked_bytes(); + init_top_at_mark_start(); + } + // Update heap region to be consistent after Full GC compaction. + void complete_compaction(); + + // All allocated blocks are occupied by objects in a HeapRegion + bool block_is_obj(const HeapWord* p) const; + + // Returns whether the given object is dead based on TAMS and bitmap. + bool is_obj_dead(const oop obj, const G1CMBitMap* const prev_bitmap) const; + + // Returns the object size for all valid block starts + // and the amount of unallocated words if called on top() + size_t block_size(const HeapWord* p) const; + + // Scans through the region using the bitmap to determine what + // objects to call size_t ApplyToMarkedClosure::apply(oop) for. + template + inline void apply_to_marked_objects(G1CMBitMap* bitmap, ApplyToMarkedClosure* closure); void reset_bot() { _bot_part.reset_bot(); } - void print_bot_on(outputStream* out) { - _bot_part.print_on(out); - } - private: // The remembered set for this region. HeapRegionRemSet* _rem_set; - void report_region_type_change(G1HeapRegionTraceType::Type to); - - // Returns whether the given object address refers to a dead object, and either the - // size of the object (if live) or the size of the block (if dead) in size. - // May - // - only called with obj < top() - // - not called on humongous objects or archive regions - inline bool is_obj_dead_with_size(const oop obj, const G1CMBitMap* const prev_bitmap, size_t* size) const; - - // The index of this region in the heap region sequence. + // Cached index of this region in the heap region sequence. uint _hrm_index; HeapRegionType _type; @@ -199,6 +212,12 @@ // True iff an attempt to evacuate an object in the region failed. bool _evacuation_failed; + static const uint InvalidCSetIndex = UINT_MAX; + + // The index in the optional regions array, if this region + // is considered optional during a mixed collections. + uint _index_in_opt_cset; + // Fields used by the HeapRegionSetBase class and subclasses. HeapRegion* _next; HeapRegion* _prev; @@ -206,25 +225,6 @@ HeapRegionSetBase* _containing_set; #endif // ASSERT - // We use concurrent marking to determine the amount of live data - // in each heap region. - size_t _prev_marked_bytes; // Bytes known to be live via last completed marking. - size_t _next_marked_bytes; // Bytes known to be live via in-progress marking. - - // The calculated GC efficiency of the region. - double _gc_efficiency; - - static const uint InvalidCSetIndex = UINT_MAX; - - // The index in the optional regions array, if this region - // is considered optional during a mixed collections. - uint _index_in_opt_cset; - - // Data for young region survivor prediction. - uint _young_index_in_cset; - SurvRateGroup* _surv_rate_group; - int _age_index; - // The start of the unmarked area. The unmarked area extends from this // word until the top and/or end of the region, and is the part // of the region for which no marking was done, i.e. objects may @@ -234,18 +234,29 @@ HeapWord* _prev_top_at_mark_start; HeapWord* _next_top_at_mark_start; + // We use concurrent marking to determine the amount of live data + // in each heap region. + size_t _prev_marked_bytes; // Bytes known to be live via last completed marking. + size_t _next_marked_bytes; // Bytes known to be live via in-progress marking. + void init_top_at_mark_start() { assert(_prev_marked_bytes == 0 && _next_marked_bytes == 0, "Must be called after zero_marked_bytes."); - HeapWord* bot = bottom(); - _prev_top_at_mark_start = bot; - _next_top_at_mark_start = bot; + _prev_top_at_mark_start = _next_top_at_mark_start = bottom(); } + // Data for young region survivor prediction. + uint _young_index_in_cset; + SurvRateGroup* _surv_rate_group; + int _age_index; + // Cached attributes used in the collection set policy information - // The RSet length that was added to the total value + // The calculated GC efficiency of the region. + double _gc_efficiency; + + // The remembered set length that was added to the total value // for the collection set. size_t _recorded_rs_length; @@ -255,6 +266,15 @@ uint _node_index; + void report_region_type_change(G1HeapRegionTraceType::Type to); + + // Returns whether the given object address refers to a dead object, and either the + // size of the object (if live) or the size of the block (if dead) in size. + // May + // - only called with obj < top() + // - not called on humongous objects or archive regions + inline bool is_obj_dead_with_size(const oop obj, const G1CMBitMap* const prev_bitmap, size_t* size) const; + // Iterate over the references covered by the given MemRegion in a humongous // object and apply the given closure to them. // Humongous objects are allocated directly in the old-gen. So we need special @@ -273,6 +293,10 @@ public: HeapRegion(uint hrm_index, G1BlockOffsetTable* bot, MemRegion mr); + // If this region is a member of a HeapRegionManager, the index in that + // sequence, otherwise -1. + uint hrm_index() const { return _hrm_index; } + // Initializing the HeapRegion not only resets the data structure, but also // resets the BOT for that heap region. // The default values for clear_space means that we will do the clearing if @@ -292,7 +316,6 @@ ~((1 << (size_t) LogOfHRGrainBytes) - 1); } - // Returns whether a field is in the same region as the obj it points to. template static bool is_in_same_region(T* p, oop obj) { @@ -312,31 +335,6 @@ // up once during initialization time. static void setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size); - // All allocated blocks are occupied by objects in a HeapRegion - bool block_is_obj(const HeapWord* p) const; - - // Returns whether the given object is dead based on TAMS and bitmap. - bool is_obj_dead(const oop obj, const G1CMBitMap* const prev_bitmap) const; - - // Returns the object size for all valid block starts - // and the amount of unallocated words if called on top() - size_t block_size(const HeapWord* p) const; - - // Scans through the region using the bitmap to determine what - // objects to call size_t ApplyToMarkedClosure::apply(oop) for. - template - inline void apply_to_marked_objects(G1CMBitMap* bitmap, ApplyToMarkedClosure* closure); - // Update heap region to be consistent after compaction. - void complete_compaction(); - - inline HeapWord* par_allocate_no_bot_updates(size_t min_word_size, size_t desired_word_size, size_t* word_size); - inline HeapWord* allocate_no_bot_updates(size_t word_size); - inline HeapWord* allocate_no_bot_updates(size_t min_word_size, size_t desired_word_size, size_t* actual_size); - - // If this region is a member of a HeapRegionManager, the index in that - // sequence, otherwise -1. - uint hrm_index() const { return _hrm_index; } - // The number of bytes marked live in the region in the last marking phase. size_t marked_bytes() { return _prev_marked_bytes; } size_t live_bytes() { @@ -378,6 +376,22 @@ void zero_marked_bytes() { _prev_marked_bytes = _next_marked_bytes = 0; } + // Get the start of the unmarked area in this region. + HeapWord* prev_top_at_mark_start() const { return _prev_top_at_mark_start; } + HeapWord* next_top_at_mark_start() const { return _next_top_at_mark_start; } + + // Note the start or end of marking. This tells the heap region + // that the collector is about to start or has finished (concurrently) + // marking the heap. + + // Notify the region that concurrent marking is starting. Initialize + // all fields related to the next marking info. + inline void note_start_of_marking(); + + // Notify the region that concurrent marking has finished. Copy the + // (now finalized) next marking info fields into the prev marking + // info fields. + inline void note_end_of_marking(); const char* get_type_str() const { return _type.get_str(); } const char* get_short_type_str() const { return _type.get_short_str(); } @@ -410,6 +424,18 @@ bool is_open_archive() const { return _type.is_open_archive(); } bool is_closed_archive() const { return _type.is_closed_archive(); } + void set_free(); + + void set_eden(); + void set_eden_pre_gc(); + void set_survivor(); + + void move_to_old(); + void set_old(); + + void set_open_archive(); + void set_closed_archive(); + // For a humongous region, region in which it starts. HeapRegion* humongous_start_region() const { return _humongous_start_region; @@ -442,11 +468,11 @@ // Getter and setter for the next and prev fields used to link regions into // linked lists. + void set_next(HeapRegion* next) { _next = next; } HeapRegion* next() { return _next; } - HeapRegion* prev() { return _prev; } - void set_next(HeapRegion* next) { _next = next; } void set_prev(HeapRegion* prev) { _prev = prev; } + HeapRegion* prev() { return _prev; } // Every region added to a set is tagged with a reference to that // set. This is used for doing consistency checking to make sure that @@ -480,22 +506,17 @@ // Clear the card table corresponding to this region. void clear_cardtable(); - // Get the start of the unmarked area in this region. - HeapWord* prev_top_at_mark_start() const { return _prev_top_at_mark_start; } - HeapWord* next_top_at_mark_start() const { return _next_top_at_mark_start; } - - // Note the start or end of marking. This tells the heap region - // that the collector is about to start or has finished (concurrently) - // marking the heap. + // Returns the "evacuation_failed" property of the region. + bool evacuation_failed() { return _evacuation_failed; } - // Notify the region that concurrent marking is starting. Initialize - // all fields related to the next marking info. - inline void note_start_of_marking(); + // Sets the "evacuation_failed" property of the region. + void set_evacuation_failed(bool b) { + _evacuation_failed = b; - // Notify the region that concurrent marking has finished. Copy the - // (now finalized) next marking info fields into the prev marking - // info fields. - inline void note_end_of_marking(); + if (b) { + _next_marked_bytes = 0; + } + } // Notify the region that we are about to start processing // self-forwarded objects during evac failure handling. @@ -506,17 +527,6 @@ // objects during evac failure handling. void note_self_forwarding_removal_end(size_t marked_bytes); - void reset_during_compaction() { - assert(is_humongous(), - "should only be called for humongous regions"); - - zero_marked_bytes(); - init_top_at_mark_start(); - } - - void calc_gc_efficiency(void); - double gc_efficiency() const { return _gc_efficiency;} - uint index_in_opt_cset() const { assert(has_index_in_opt_cset(), "Opt cset index not set."); return _index_in_opt_cset; @@ -525,6 +535,9 @@ void set_index_in_opt_cset(uint index) { _index_in_opt_cset = index; } void clear_index_in_opt_cset() { _index_in_opt_cset = InvalidCSetIndex; } + void calc_gc_efficiency(void); + double gc_efficiency() const { return _gc_efficiency;} + uint young_index_in_cset() const { return _young_index_in_cset; } void clear_young_index_in_cset() { _young_index_in_cset = 0; } void set_young_index_in_cset(uint index) { @@ -579,18 +592,6 @@ } } - void set_free(); - - void set_eden(); - void set_eden_pre_gc(); - void set_survivor(); - - void move_to_old(); - void set_old(); - - void set_open_archive(); - void set_closed_archive(); - // Determine if an object has been allocated since the last // mark performed by the collector. This returns true iff the object // is within the unmarked area of the region. @@ -601,18 +602,6 @@ return (HeapWord *) obj >= next_top_at_mark_start(); } - // Returns the "evacuation_failed" property of the region. - bool evacuation_failed() { return _evacuation_failed; } - - // Sets the "evacuation_failed" property of the region. - void set_evacuation_failed(bool b) { - _evacuation_failed = b; - - if (b) { - _next_marked_bytes = 0; - } - } - // Iterate over the objects overlapping the given memory region, applying cl // to all references in the region. This is a helper for // G1RemSet::refine_card*, and is tightly coupled with them. diff -r 82db5000a845 -r a1155217a563 src/hotspot/share/gc/g1/heapRegion.inline.hpp --- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp Mon Nov 18 16:49:39 2019 +0100 +++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp Fri Nov 22 10:03:38 2019 +0100 @@ -304,7 +304,7 @@ template HeapWord* HeapRegion::oops_on_memregion_seq_iterate_careful(MemRegion mr, - Closure* cl) { + Closure* cl) { assert(MemRegion(bottom(), end()).contains(mr), "Card region not in heap region"); G1CollectedHeap* g1h = G1CollectedHeap::heap();