--- old/src/share/vm/gc/g1/g1ConcurrentMark.cpp 2017-08-03 17:38:22.016678327 +0200 +++ new/src/share/vm/gc/g1/g1ConcurrentMark.cpp 2017-08-03 17:38:21.919675278 +0200 @@ -60,41 +60,7 @@ #include "utilities/align.hpp" #include "utilities/growableArray.hpp" -// Concurrent marking bit map wrapper - -G1CMBitMapRO::G1CMBitMapRO(int shifter) : - _bm(), - _shifter(shifter) { - _bmStartWord = 0; - _bmWordSize = 0; -} - -HeapWord* G1CMBitMapRO::getNextMarkedWordAddress(const HeapWord* addr, - const HeapWord* limit) const { - // First we must round addr *up* to a possible object boundary. - addr = align_up(addr, HeapWordSize << _shifter); - size_t addrOffset = heapWordToOffset(addr); - assert(limit != NULL, "limit must not be NULL"); - size_t limitOffset = heapWordToOffset(limit); - size_t nextOffset = _bm.get_next_one_offset(addrOffset, limitOffset); - HeapWord* nextAddr = offsetToHeapWord(nextOffset); - assert(nextAddr >= addr, "get_next_one postcondition"); - assert(nextAddr == limit || isMarked(nextAddr), - "get_next_one postcondition"); - return nextAddr; -} - -#ifndef PRODUCT -bool G1CMBitMapRO::covers(MemRegion heap_rs) const { - // assert(_bm.map() == _virtual_space.low(), "map inconsistency"); - assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize, - "size inconsistency"); - return _bmStartWord == (HeapWord*)(heap_rs.start()) && - _bmWordSize == heap_rs.word_size(); -} -#endif - -void G1CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const { +void G1CMBitMap::print_on_error(outputStream* st, const char* prefix) const { _bm.print_on_error(st, prefix); } @@ -107,10 +73,9 @@ } void G1CMBitMap::initialize(MemRegion heap, G1RegionToSpaceMapper* storage) { - _bmStartWord = heap.start(); - _bmWordSize = heap.word_size(); + _covered = heap; - _bm = BitMapView((BitMap::bm_word_t*) storage->reserved().start(), _bmWordSize >> _shifter); + _bm = BitMapView((BitMap::bm_word_t*) storage->reserved().start(), _covered.word_size() >> _shifter); storage->set_mapping_changed_listener(&_listener); } @@ -125,11 +90,13 @@ } void G1CMBitMap::clear_range(MemRegion mr) { - mr.intersection(MemRegion(_bmStartWord, _bmWordSize)); - assert(!mr.is_empty(), "unexpected empty region"); + MemRegion intersection = mr.intersection(_covered); + assert(!intersection.is_empty(), + "Given range from " PTR_FORMAT " to " PTR_FORMAT " is completely outside the heap", + p2i(mr.start()), p2i(mr.end())); // convert address range into offset range - _bm.at_put_range(heapWordToOffset(mr.start()), - heapWordToOffset(mr.end()), false); + _bm.at_put_range(addr_to_offset(intersection.start()), + addr_to_offset(intersection.end()), false); } G1CMMarkStack::G1CMMarkStack() : @@ -438,8 +405,6 @@ } assert(CGC_lock != NULL, "Where's the CGC_lock?"); - assert(_markBitMap1.covers(g1h->reserved_region()), "_markBitMap1 inconsistency"); - assert(_markBitMap2.covers(g1h->reserved_region()), "_markBitMap2 inconsistency"); SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); satb_qs.set_buffer_size(G1SATBBufferSize); @@ -753,7 +718,7 @@ void G1ConcurrentMark::clear_prev_bitmap(WorkGang* workers) { assert(SafepointSynchronize::is_at_safepoint(), "Should only clear the entire prev bitmap at a safepoint."); - clear_bitmap((G1CMBitMap*)_prevMarkBitMap, workers, false); + clear_bitmap(_prevMarkBitMap, workers, false); } class CheckBitmapClearHRClosure : public HeapRegionClosure { @@ -769,7 +734,7 @@ // value passed to it as limit to detect any found bits. // end never changes in G1. HeapWord* end = r->end(); - return _bitmap->getNextMarkedWordAddress(r->bottom(), end) != end; + return _bitmap->get_next_marked_addr(r->bottom(), end) != end; } }; @@ -789,7 +754,6 @@ void G1ConcurrentMark::checkpointRootsInitialPre() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - G1Policy* g1p = g1h->g1_policy(); _has_aborted = false; @@ -1764,9 +1728,9 @@ } void G1ConcurrentMark::swapMarkBitMaps() { - G1CMBitMapRO* temp = _prevMarkBitMap; - _prevMarkBitMap = (G1CMBitMapRO*)_nextMarkBitMap; - _nextMarkBitMap = (G1CMBitMap*) temp; + G1CMBitMap* temp = _prevMarkBitMap; + _prevMarkBitMap = _nextMarkBitMap; + _nextMarkBitMap = temp; } // Closure for marking entries in SATB buffers. @@ -1911,9 +1875,7 @@ } void G1ConcurrentMark::clearRangePrevBitmap(MemRegion mr) { - // Note we are overriding the read-only view of the prev map here, via - // the cast. - ((G1CMBitMap*)_prevMarkBitMap)->clear_range(mr); + _prevMarkBitMap->clear_range(mr); } HeapRegion* @@ -2160,37 +2122,22 @@ _nextMarkBitMap->print_on_error(st, " Next Bits: "); } -// Closure for iteration over bitmaps -class G1CMBitMapClosure : public BitMapClosure { -private: - // the bitmap that is being iterated over - G1CMBitMap* _nextMarkBitMap; - G1ConcurrentMark* _cm; - G1CMTask* _task; - -public: - G1CMBitMapClosure(G1CMTask *task, G1ConcurrentMark* cm, G1CMBitMap* nextMarkBitMap) : - _task(task), _cm(cm), _nextMarkBitMap(nextMarkBitMap) { } - - bool do_bit(size_t offset) { - HeapWord* addr = _nextMarkBitMap->offsetToHeapWord(offset); - assert(_nextMarkBitMap->isMarked(addr), "invariant"); - assert( addr < _cm->finger(), "invariant"); - assert(addr >= _task->finger(), "invariant"); - - // We move that task's local finger along. - _task->move_finger_to(addr); - - _task->scan_task_entry(G1TaskQueueEntry::from_oop(oop(addr))); - // we only partially drain the local queue and global stack - _task->drain_local_queue(true); - _task->drain_global_stack(true); - - // if the has_aborted flag has been raised, we need to bail out of - // the iteration - return !_task->has_aborted(); - } -}; +bool G1CMBitMapClosure::do_addr(HeapWord* const addr) { + assert(addr < _cm->finger(), "invariant"); + assert(addr >= _task->finger(), "invariant"); + + // We move that task's local finger along. + _task->move_finger_to(addr); + + _task->scan_task_entry(G1TaskQueueEntry::from_oop(oop(addr))); + // we only partially drain the local queue and global stack + _task->drain_local_queue(true); + _task->drain_global_stack(true); + + // if the has_aborted flag has been raised, we need to bail out of + // the iteration + return !_task->has_aborted(); +} static ReferenceProcessor* get_cm_oop_closure_ref_processor(G1CollectedHeap* g1h) { ReferenceProcessor* result = g1h->ref_processor_cm(); @@ -2691,7 +2638,7 @@ // Set up the bitmap and oop closures. Anything that uses them is // eventually called from this method, so it is OK to allocate these // statically. - G1CMBitMapClosure bitmap_closure(this, _cm, _nextMarkBitMap); + G1CMBitMapClosure bitmap_closure(this, _cm); G1CMOopClosure cm_oop_closure(_g1h, _cm, this); set_cm_oop_closure(&cm_oop_closure); @@ -2747,10 +2694,9 @@ giveup_current_region(); regular_clock_call(); } else if (_curr_region->is_humongous() && mr.start() == _curr_region->bottom()) { - if (_nextMarkBitMap->isMarked(mr.start())) { + if (_nextMarkBitMap->is_marked(mr.start())) { // The object is marked - apply the closure - BitMap::idx_t offset = _nextMarkBitMap->heapWordToOffset(mr.start()); - bitmap_closure.do_bit(offset); + bitmap_closure.do_addr(mr.start()); } // Even if this task aborted while scanning the humongous object // we can (and should) give up the current region. @@ -2772,11 +2718,9 @@ // points to the address of the object we last scanned. If we // leave it there, when we restart this task, we will rescan // the object. It is easy to avoid this. We move the finger by - // enough to point to the next possible object header (the - // bitmap knows by how much we need to move it as it knows its - // granularity). + // enough to point to the next possible object header. assert(_finger < _region_limit, "invariant"); - HeapWord* new_finger = _nextMarkBitMap->nextObject(_finger); + HeapWord* const new_finger = _finger + ((oop)_finger)->size(); // Check if bitmap iteration was aborted while scanning the last object if (new_finger >= _region_limit) { giveup_current_region();