提交 1c7f20f7 编写于 作者: J jcoomes

Merge

...@@ -1258,7 +1258,6 @@ class BacktraceBuilder: public StackObj { ...@@ -1258,7 +1258,6 @@ class BacktraceBuilder: public StackObj {
objArrayOop _methods; objArrayOop _methods;
typeArrayOop _bcis; typeArrayOop _bcis;
int _index; int _index;
bool _dirty;
No_Safepoint_Verifier _nsv; No_Safepoint_Verifier _nsv;
public: public:
...@@ -1272,37 +1271,13 @@ class BacktraceBuilder: public StackObj { ...@@ -1272,37 +1271,13 @@ class BacktraceBuilder: public StackObj {
}; };
// constructor for new backtrace // constructor for new backtrace
BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _dirty(false) { BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL) {
expand(CHECK); expand(CHECK);
_backtrace = _head; _backtrace = _head;
_index = 0; _index = 0;
} }
void flush() {
// The following appears to have been an optimization to save from
// doing a barrier for each individual store into the _methods array,
// but rather to do it for the entire array after the series of writes.
// That optimization seems to have been lost when compressed oops was
// implemented. However, the extra card-marks below was left in place,
// but is now redundant because the individual stores into the
// _methods array already execute the barrier code. CR 6918185 has
// been filed so the original code may be restored by deferring the
// barriers until after the entire sequence of stores, thus re-enabling
// the intent of the original optimization. In the meantime the redundant
// card mark below is now disabled.
if (_dirty && _methods != NULL) {
#if 0
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
bs->write_ref_array((HeapWord*)_methods->base(), _methods->length());
#endif
_dirty = false;
}
}
void expand(TRAPS) { void expand(TRAPS) {
flush();
objArrayHandle old_head(THREAD, _head); objArrayHandle old_head(THREAD, _head);
Pause_No_Safepoint_Verifier pnsv(&_nsv); Pause_No_Safepoint_Verifier pnsv(&_nsv);
...@@ -1328,7 +1303,6 @@ class BacktraceBuilder: public StackObj { ...@@ -1328,7 +1303,6 @@ class BacktraceBuilder: public StackObj {
} }
oop backtrace() { oop backtrace() {
flush();
return _backtrace(); return _backtrace();
} }
...@@ -1342,7 +1316,6 @@ class BacktraceBuilder: public StackObj { ...@@ -1342,7 +1316,6 @@ class BacktraceBuilder: public StackObj {
_methods->obj_at_put(_index, method); _methods->obj_at_put(_index, method);
_bcis->ushort_at_put(_index, bci); _bcis->ushort_at_put(_index, bci);
_index++; _index++;
_dirty = true;
} }
methodOop current_method() { methodOop current_method() {
......
...@@ -1833,8 +1833,6 @@ CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) { ...@@ -1833,8 +1833,6 @@ CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) {
} }
) )
_indexedFreeList[size].removeChunk(fc); _indexedFreeList[size].removeChunk(fc);
debug_only(fc->clearNext());
debug_only(fc->clearPrev());
NOT_PRODUCT( NOT_PRODUCT(
if (FLSVerifyIndexTable) { if (FLSVerifyIndexTable) {
verifyIndexedFreeList(size); verifyIndexedFreeList(size);
......
...@@ -114,17 +114,11 @@ class FreeChunk VALUE_OBJ_CLASS_SPEC { ...@@ -114,17 +114,11 @@ class FreeChunk VALUE_OBJ_CLASS_SPEC {
linkNext(ptr); linkNext(ptr);
if (ptr != NULL) ptr->linkPrev(this); if (ptr != NULL) ptr->linkPrev(this);
} }
void linkAfterNonNull(FreeChunk* ptr) {
assert(ptr != NULL, "precondition violation");
linkNext(ptr);
ptr->linkPrev(this);
}
void linkNext(FreeChunk* ptr) { _next = ptr; } void linkNext(FreeChunk* ptr) { _next = ptr; }
void linkPrev(FreeChunk* ptr) { void linkPrev(FreeChunk* ptr) {
LP64_ONLY(if (UseCompressedOops) _prev = ptr; else) LP64_ONLY(if (UseCompressedOops) _prev = ptr; else)
_prev = (FreeChunk*)((intptr_t)ptr | 0x1); _prev = (FreeChunk*)((intptr_t)ptr | 0x1);
} }
void clearPrev() { _prev = NULL; }
void clearNext() { _next = NULL; } void clearNext() { _next = NULL; }
void markNotFree() { void markNotFree() {
// Set _prev (klass) to null before (if) clearing the mark word below // Set _prev (klass) to null before (if) clearing the mark word below
......
...@@ -300,8 +300,21 @@ void FreeList::verify_stats() const { ...@@ -300,8 +300,21 @@ void FreeList::verify_stats() const {
// dictionary for example, this might be the first block and // dictionary for example, this might be the first block and
// in that case there would be no place that we could record // in that case there would be no place that we could record
// the stats (which are kept in the block itself). // the stats (which are kept in the block itself).
assert(_allocation_stats.prevSweep() + _allocation_stats.splitBirths() + 1 // Total Stock + 1 assert((_allocation_stats.prevSweep() + _allocation_stats.splitBirths()
>= _allocation_stats.splitDeaths() + (ssize_t)count(), "Conservation Principle"); + _allocation_stats.coalBirths() + 1) // Total Production Stock + 1
>= (_allocation_stats.splitDeaths() + _allocation_stats.coalDeaths()
+ (ssize_t)count()), // Total Current Stock + depletion
err_msg("FreeList " PTR_FORMAT " of size " SIZE_FORMAT
" violates Conservation Principle: "
"prevSweep(" SIZE_FORMAT ")"
" + splitBirths(" SIZE_FORMAT ")"
" + coalBirths(" SIZE_FORMAT ") + 1 >= "
" splitDeaths(" SIZE_FORMAT ")"
" coalDeaths(" SIZE_FORMAT ")"
" + count(" SSIZE_FORMAT ")",
this, _size, _allocation_stats.prevSweep(), _allocation_stats.splitBirths(),
_allocation_stats.splitBirths(), _allocation_stats.splitDeaths(),
_allocation_stats.coalDeaths(), count()));
} }
void FreeList::assert_proper_lock_protection_work() const { void FreeList::assert_proper_lock_protection_work() const {
......
...@@ -131,22 +131,22 @@ class CMBitMap : public CMBitMapRO { ...@@ -131,22 +131,22 @@ class CMBitMap : public CMBitMapRO {
void mark(HeapWord* addr) { void mark(HeapWord* addr) {
assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
"outside underlying space?"); "outside underlying space?");
_bm.at_put(heapWordToOffset(addr), true); _bm.set_bit(heapWordToOffset(addr));
} }
void clear(HeapWord* addr) { void clear(HeapWord* addr) {
assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
"outside underlying space?"); "outside underlying space?");
_bm.at_put(heapWordToOffset(addr), false); _bm.clear_bit(heapWordToOffset(addr));
} }
bool parMark(HeapWord* addr) { bool parMark(HeapWord* addr) {
assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
"outside underlying space?"); "outside underlying space?");
return _bm.par_at_put(heapWordToOffset(addr), true); return _bm.par_set_bit(heapWordToOffset(addr));
} }
bool parClear(HeapWord* addr) { bool parClear(HeapWord* addr) {
assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
"outside underlying space?"); "outside underlying space?");
return _bm.par_at_put(heapWordToOffset(addr), false); return _bm.par_clear_bit(heapWordToOffset(addr));
} }
void markRange(MemRegion mr); void markRange(MemRegion mr);
void clearAll(); void clearAll();
...@@ -736,12 +736,14 @@ public: ...@@ -736,12 +736,14 @@ public:
// will dump the contents of its reference fields, as well as // will dump the contents of its reference fields, as well as
// liveness information for the object and its referents. The dump // liveness information for the object and its referents. The dump
// will be written to a file with the following name: // will be written to a file with the following name:
// G1PrintReachableBaseFile + "." + str. use_prev_marking decides // G1PrintReachableBaseFile + "." + str.
// whether the prev (use_prev_marking == true) or next // vo decides whether the prev (vo == UsePrevMarking), the next
// (use_prev_marking == false) marking information will be used to // (vo == UseNextMarking) marking information, or the mark word
// determine the liveness of each object / referent. If all is true, // (vo == UseMarkWord) will be used to determine the liveness of
// all objects in the heap will be dumped, otherwise only the live // each object / referent.
// ones. In the dump the following symbols / abbreviations are used: // If all is true, all objects in the heap will be dumped, otherwise
// only the live ones. In the dump the following symbols / breviations
// are used:
// M : an explicitly live object (its bitmap bit is set) // M : an explicitly live object (its bitmap bit is set)
// > : an implicitly live object (over tams) // > : an implicitly live object (over tams)
// O : an object outside the G1 heap (typically: in the perm gen) // O : an object outside the G1 heap (typically: in the perm gen)
...@@ -749,7 +751,7 @@ public: ...@@ -749,7 +751,7 @@ public:
// AND MARKED : indicates that an object is both explicitly and // AND MARKED : indicates that an object is both explicitly and
// implicitly live (it should be one or the other, not both) // implicitly live (it should be one or the other, not both)
void print_reachable(const char* str, void print_reachable(const char* str,
bool use_prev_marking, bool all) PRODUCT_RETURN; VerifyOption vo, bool all) PRODUCT_RETURN;
// Clear the next marking bitmap (will be called concurrently). // Clear the next marking bitmap (will be called concurrently).
void clearNextBitmap(); void clearNextBitmap();
...@@ -831,9 +833,10 @@ public: ...@@ -831,9 +833,10 @@ public:
// _min_finger then we need to gray objects. // _min_finger then we need to gray objects.
// This routine is like registerCSetRegion but for an entire // This routine is like registerCSetRegion but for an entire
// collection of regions. // collection of regions.
if (max_finger > _min_finger) if (max_finger > _min_finger) {
_should_gray_objects = true; _should_gray_objects = true;
} }
}
// Returns "true" if at least one mark has been completed. // Returns "true" if at least one mark has been completed.
bool at_least_one_mark_complete() { return _at_least_one_mark_complete; } bool at_least_one_mark_complete() { return _at_least_one_mark_complete; }
...@@ -878,14 +881,18 @@ public: ...@@ -878,14 +881,18 @@ public:
// The following indicate whether a given verbose level has been // The following indicate whether a given verbose level has been
// set. Notice that anything above stats is conditional to // set. Notice that anything above stats is conditional to
// _MARKING_VERBOSE_ having been set to 1 // _MARKING_VERBOSE_ having been set to 1
bool verbose_stats() bool verbose_stats() {
{ return _verbose_level >= stats_verbose; } return _verbose_level >= stats_verbose;
bool verbose_low() }
{ return _MARKING_VERBOSE_ && _verbose_level >= low_verbose; } bool verbose_low() {
bool verbose_medium() return _MARKING_VERBOSE_ && _verbose_level >= low_verbose;
{ return _MARKING_VERBOSE_ && _verbose_level >= medium_verbose; } }
bool verbose_high() bool verbose_medium() {
{ return _MARKING_VERBOSE_ && _verbose_level >= high_verbose; } return _MARKING_VERBOSE_ && _verbose_level >= medium_verbose;
}
bool verbose_high() {
return _MARKING_VERBOSE_ && _verbose_level >= high_verbose;
}
}; };
// A class representing a marking task. // A class representing a marking task.
...@@ -928,7 +935,7 @@ private: ...@@ -928,7 +935,7 @@ private:
double _start_time_ms; double _start_time_ms;
// the oop closure used for iterations over oops // the oop closure used for iterations over oops
OopClosure* _oop_closure; G1CMOopClosure* _cm_oop_closure;
// the region this task is scanning, NULL if we're not scanning any // the region this task is scanning, NULL if we're not scanning any
HeapRegion* _curr_region; HeapRegion* _curr_region;
...@@ -1061,9 +1068,10 @@ private: ...@@ -1061,9 +1068,10 @@ private:
// respective limit and calls reached_limit() if they have // respective limit and calls reached_limit() if they have
void check_limits() { void check_limits() {
if (_words_scanned >= _words_scanned_limit || if (_words_scanned >= _words_scanned_limit ||
_refs_reached >= _refs_reached_limit) _refs_reached >= _refs_reached_limit) {
reached_limit(); reached_limit();
} }
}
// this is supposed to be called regularly during a marking step as // this is supposed to be called regularly during a marking step as
// it checks a bunch of conditions that might cause the marking step // it checks a bunch of conditions that might cause the marking step
// to abort // to abort
...@@ -1122,32 +1130,17 @@ public: ...@@ -1122,32 +1130,17 @@ public:
// Clears any recorded partially scanned region // Clears any recorded partially scanned region
void clear_aborted_region() { set_aborted_region(MemRegion()); } void clear_aborted_region() { set_aborted_region(MemRegion()); }
void set_oop_closure(OopClosure* oop_closure) { void set_cm_oop_closure(G1CMOopClosure* cm_oop_closure);
_oop_closure = oop_closure;
}
// It grays the object by marking it and, if necessary, pushing it // It grays the object by marking it and, if necessary, pushing it
// on the local queue // on the local queue
void deal_with_reference(oop obj); inline void deal_with_reference(oop obj);
// It scans an object and visits its children. // It scans an object and visits its children.
void scan_object(oop obj) { void scan_object(oop obj);
assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant");
if (_cm->verbose_high())
gclog_or_tty->print_cr("[%d] we're scanning object "PTR_FORMAT,
_task_id, (void*) obj);
size_t obj_size = obj->size();
_words_scanned += obj_size;
obj->oop_iterate(_oop_closure);
statsOnly( ++_objs_scanned );
check_limits();
}
// It pushes an object on the local queue. // It pushes an object on the local queue.
void push(oop obj); inline void push(oop obj);
// These two move entries to/from the global stack. // These two move entries to/from the global stack.
void move_entries_to_global_stack(); void move_entries_to_global_stack();
......
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP
#include "gc_implementation/g1/concurrentMark.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
inline void CMTask::push(oop obj) {
HeapWord* objAddr = (HeapWord*) obj;
assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
assert(!_g1h->is_on_master_free_list(
_g1h->heap_region_containing((HeapWord*) objAddr)), "invariant");
assert(!_g1h->is_obj_ill(obj), "invariant");
assert(_nextMarkBitMap->isMarked(objAddr), "invariant");
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%d] pushing "PTR_FORMAT, _task_id, (void*) obj);
}
if (!_task_queue->push(obj)) {
// The local task queue looks full. We need to push some entries
// to the global stack.
if (_cm->verbose_medium()) {
gclog_or_tty->print_cr("[%d] task queue overflow, "
"moving entries to the global stack",
_task_id);
}
move_entries_to_global_stack();
// this should succeed since, even if we overflow the global
// stack, we should have definitely removed some entries from the
// local queue. So, there must be space on it.
bool success = _task_queue->push(obj);
assert(success, "invariant");
}
statsOnly( int tmp_size = _task_queue->size();
if (tmp_size > _local_max_size) {
_local_max_size = tmp_size;
}
++_local_pushes );
}
// This determines whether the method below will check both the local
// and global fingers when determining whether to push on the stack a
// gray object (value 1) or whether it will only check the global one
// (value 0). The tradeoffs are that the former will be a bit more
// accurate and possibly push less on the stack, but it might also be
// a little bit slower.
#define _CHECK_BOTH_FINGERS_ 1
inline void CMTask::deal_with_reference(oop obj) {
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%d] we're dealing with reference = "PTR_FORMAT,
_task_id, (void*) obj);
}
++_refs_reached;
HeapWord* objAddr = (HeapWord*) obj;
assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");
if (_g1h->is_in_g1_reserved(objAddr)) {
assert(obj != NULL, "null check is implicit");
if (!_nextMarkBitMap->isMarked(objAddr)) {
// Only get the containing region if the object is not marked on the
// bitmap (otherwise, it's a waste of time since we won't do
// anything with it).
HeapRegion* hr = _g1h->heap_region_containing_raw(obj);
if (!hr->obj_allocated_since_next_marking(obj)) {
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%d] "PTR_FORMAT" is not considered marked",
_task_id, (void*) obj);
}
// we need to mark it first
if (_nextMarkBitMap->parMark(objAddr)) {
// No OrderAccess:store_load() is needed. It is implicit in the
// CAS done in parMark(objAddr) above
HeapWord* global_finger = _cm->finger();
#if _CHECK_BOTH_FINGERS_
// we will check both the local and global fingers
if (_finger != NULL && objAddr < _finger) {
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%d] below the local finger ("PTR_FORMAT"), "
"pushing it", _task_id, _finger);
}
push(obj);
} else if (_curr_region != NULL && objAddr < _region_limit) {
// do nothing
} else if (objAddr < global_finger) {
// Notice that the global finger might be moving forward
// concurrently. This is not a problem. In the worst case, we
// mark the object while it is above the global finger and, by
// the time we read the global finger, it has moved forward
// passed this object. In this case, the object will probably
// be visited when a task is scanning the region and will also
// be pushed on the stack. So, some duplicate work, but no
// correctness problems.
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%d] below the global finger "
"("PTR_FORMAT"), pushing it",
_task_id, global_finger);
}
push(obj);
} else {
// do nothing
}
#else // _CHECK_BOTH_FINGERS_
// we will only check the global finger
if (objAddr < global_finger) {
// see long comment above
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%d] below the global finger "
"("PTR_FORMAT"), pushing it",
_task_id, global_finger);
}
push(obj);
}
#endif // _CHECK_BOTH_FINGERS_
}
}
}
}
}
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP
...@@ -27,8 +27,10 @@ ...@@ -27,8 +27,10 @@
#include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/concurrentMark.hpp"
#include "gc_implementation/g1/g1AllocRegion.hpp" #include "gc_implementation/g1/g1AllocRegion.hpp"
#include "gc_implementation/g1/g1HRPrinter.hpp"
#include "gc_implementation/g1/g1RemSet.hpp" #include "gc_implementation/g1/g1RemSet.hpp"
#include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "gc_implementation/g1/g1MonitoringSupport.hpp"
#include "gc_implementation/g1/heapRegionSeq.hpp"
#include "gc_implementation/g1/heapRegionSets.hpp" #include "gc_implementation/g1/heapRegionSets.hpp"
#include "gc_implementation/shared/hSpaceCounters.hpp" #include "gc_implementation/shared/hSpaceCounters.hpp"
#include "gc_implementation/parNew/parGCAllocBuffer.hpp" #include "gc_implementation/parNew/parGCAllocBuffer.hpp"
...@@ -42,7 +44,6 @@ ...@@ -42,7 +44,6 @@
// heap subsets that will yield large amounts of garbage. // heap subsets that will yield large amounts of garbage.
class HeapRegion; class HeapRegion;
class HeapRegionSeq;
class HRRSCleanupTask; class HRRSCleanupTask;
class PermanentGenerationSpec; class PermanentGenerationSpec;
class GenerationSpec; class GenerationSpec;
...@@ -103,6 +104,19 @@ public: ...@@ -103,6 +104,19 @@ public:
size_t length() { return _length; } size_t length() { return _length; }
size_t survivor_length() { return _survivor_length; } size_t survivor_length() { return _survivor_length; }
// Currently we do not keep track of the used byte sum for the
// young list and the survivors and it'd be quite a lot of work to
// do so. When we'll eventually replace the young list with
// instances of HeapRegionLinkedList we'll get that for free. So,
// we'll report the more accurate information then.
size_t eden_used_bytes() {
assert(length() >= survivor_length(), "invariant");
return (length() - survivor_length()) * HeapRegion::GrainBytes;
}
size_t survivor_used_bytes() {
return survivor_length() * HeapRegion::GrainBytes;
}
void rs_length_sampling_init(); void rs_length_sampling_init();
bool rs_length_sampling_more(); bool rs_length_sampling_more();
void rs_length_sampling_next(); void rs_length_sampling_next();
...@@ -183,9 +197,6 @@ private: ...@@ -183,9 +197,6 @@ private:
// The part of _g1_storage that is currently committed. // The part of _g1_storage that is currently committed.
MemRegion _g1_committed; MemRegion _g1_committed;
// The maximum part of _g1_storage that has ever been committed.
MemRegion _g1_max_committed;
// The master free list. It will satisfy all new region allocations. // The master free list. It will satisfy all new region allocations.
MasterFreeRegionList _free_list; MasterFreeRegionList _free_list;
...@@ -209,7 +220,7 @@ private: ...@@ -209,7 +220,7 @@ private:
void rebuild_region_lists(); void rebuild_region_lists();
// The sequence of all heap regions in the heap. // The sequence of all heap regions in the heap.
HeapRegionSeq* _hrs; HeapRegionSeq _hrs;
// Alloc region used to satisfy mutator allocation requests. // Alloc region used to satisfy mutator allocation requests.
MutatorAllocRegion _mutator_alloc_region; MutatorAllocRegion _mutator_alloc_region;
...@@ -288,6 +299,8 @@ private: ...@@ -288,6 +299,8 @@ private:
size_t* _surviving_young_words; size_t* _surviving_young_words;
G1HRPrinter _hr_printer;
void setup_surviving_young_words(); void setup_surviving_young_words();
void update_surviving_young_words(size_t* surv_young_words); void update_surviving_young_words(size_t* surv_young_words);
void cleanup_surviving_young_words(); void cleanup_surviving_young_words();
...@@ -408,13 +421,15 @@ protected: ...@@ -408,13 +421,15 @@ protected:
// Attempt to satisfy a humongous allocation request of the given // Attempt to satisfy a humongous allocation request of the given
// size by finding a contiguous set of free regions of num_regions // size by finding a contiguous set of free regions of num_regions
// length and remove them from the master free list. Return the // length and remove them from the master free list. Return the
// index of the first region or -1 if the search was unsuccessful. // index of the first region or G1_NULL_HRS_INDEX if the search
int humongous_obj_allocate_find_first(size_t num_regions, size_t word_size); // was unsuccessful.
size_t humongous_obj_allocate_find_first(size_t num_regions,
size_t word_size);
// Initialize a contiguous set of free regions of length num_regions // Initialize a contiguous set of free regions of length num_regions
// and starting at index first so that they appear as a single // and starting at index first so that they appear as a single
// humongous region. // humongous region.
HeapWord* humongous_obj_allocate_initialize_regions(int first, HeapWord* humongous_obj_allocate_initialize_regions(size_t first,
size_t num_regions, size_t num_regions,
size_t word_size); size_t word_size);
...@@ -434,8 +449,7 @@ protected: ...@@ -434,8 +449,7 @@ protected:
// * All allocation requests for new TLABs should go to // * All allocation requests for new TLABs should go to
// allocate_new_tlab(). // allocate_new_tlab().
// //
// * All non-TLAB allocation requests should go to mem_allocate() // * All non-TLAB allocation requests should go to mem_allocate().
// and mem_allocate() should never be called with is_tlab == true.
// //
// * If either call cannot satisfy the allocation request using the // * If either call cannot satisfy the allocation request using the
// current allocating region, they will try to get a new one. If // current allocating region, they will try to get a new one. If
...@@ -455,8 +469,6 @@ protected: ...@@ -455,8 +469,6 @@ protected:
virtual HeapWord* allocate_new_tlab(size_t word_size); virtual HeapWord* allocate_new_tlab(size_t word_size);
virtual HeapWord* mem_allocate(size_t word_size, virtual HeapWord* mem_allocate(size_t word_size,
bool is_noref,
bool is_tlab, /* expected to be false */
bool* gc_overhead_limit_was_exceeded); bool* gc_overhead_limit_was_exceeded);
// The following three methods take a gc_count_before_ret // The following three methods take a gc_count_before_ret
...@@ -574,8 +586,8 @@ public: ...@@ -574,8 +586,8 @@ public:
void register_region_with_in_cset_fast_test(HeapRegion* r) { void register_region_with_in_cset_fast_test(HeapRegion* r) {
assert(_in_cset_fast_test_base != NULL, "sanity"); assert(_in_cset_fast_test_base != NULL, "sanity");
assert(r->in_collection_set(), "invariant"); assert(r->in_collection_set(), "invariant");
int index = r->hrs_index(); size_t index = r->hrs_index();
assert(0 <= index && (size_t) index < _in_cset_fast_test_length, "invariant"); assert(index < _in_cset_fast_test_length, "invariant");
assert(!_in_cset_fast_test_base[index], "invariant"); assert(!_in_cset_fast_test_base[index], "invariant");
_in_cset_fast_test_base[index] = true; _in_cset_fast_test_base[index] = true;
} }
...@@ -626,6 +638,8 @@ public: ...@@ -626,6 +638,8 @@ public:
return _full_collections_completed; return _full_collections_completed;
} }
G1HRPrinter* hr_printer() { return &_hr_printer; }
protected: protected:
// Shrink the garbage-first heap by at most the given size (in bytes!). // Shrink the garbage-first heap by at most the given size (in bytes!).
...@@ -741,6 +755,11 @@ protected: ...@@ -741,6 +755,11 @@ protected:
HumongousRegionSet* humongous_proxy_set, HumongousRegionSet* humongous_proxy_set,
bool par); bool par);
// Notifies all the necessary spaces that the committed space has
// been updated (either expanded or shrunk). It should be called
// after _g1_storage is updated.
void update_committed_space(HeapWord* old_end, HeapWord* new_end);
// The concurrent marker (and the thread it runs in.) // The concurrent marker (and the thread it runs in.)
ConcurrentMark* _cm; ConcurrentMark* _cm;
ConcurrentMarkThread* _cmThread; ConcurrentMarkThread* _cmThread;
...@@ -803,7 +822,6 @@ protected: ...@@ -803,7 +822,6 @@ protected:
oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj); oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj);
void handle_evacuation_failure_common(oop obj, markOop m); void handle_evacuation_failure_common(oop obj, markOop m);
// Ensure that the relevant gc_alloc regions are set. // Ensure that the relevant gc_alloc regions are set.
void get_gc_alloc_regions(); void get_gc_alloc_regions();
// We're done with GC alloc regions. We are going to tear down the // We're done with GC alloc regions. We are going to tear down the
...@@ -954,15 +972,13 @@ public: ...@@ -954,15 +972,13 @@ public:
} }
// The total number of regions in the heap. // The total number of regions in the heap.
size_t n_regions(); size_t n_regions() { return _hrs.length(); }
// The number of regions that are completely free. // The max number of regions in the heap.
size_t max_regions(); size_t max_regions() { return _hrs.max_length(); }
// The number of regions that are completely free. // The number of regions that are completely free.
size_t free_regions() { size_t free_regions() { return _free_list.length(); }
return _free_list.length();
}
// The number of regions that are not completely free. // The number of regions that are not completely free.
size_t used_regions() { return n_regions() - free_regions(); } size_t used_regions() { return n_regions() - free_regions(); }
...@@ -970,6 +986,10 @@ public: ...@@ -970,6 +986,10 @@ public:
// The number of regions available for "regular" expansion. // The number of regions available for "regular" expansion.
size_t expansion_regions() { return _expansion_regions; } size_t expansion_regions() { return _expansion_regions; }
// Factory method for HeapRegion instances. It will return NULL if
// the allocation fails.
HeapRegion* new_heap_region(size_t hrs_index, HeapWord* bottom);
void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN; void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN; void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN; void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN;
...@@ -1131,17 +1151,15 @@ public: ...@@ -1131,17 +1151,15 @@ public:
// Iterate over heap regions, in address order, terminating the // Iterate over heap regions, in address order, terminating the
// iteration early if the "doHeapRegion" method returns "true". // iteration early if the "doHeapRegion" method returns "true".
void heap_region_iterate(HeapRegionClosure* blk); void heap_region_iterate(HeapRegionClosure* blk) const;
// Iterate over heap regions starting with r (or the first region if "r" // Iterate over heap regions starting with r (or the first region if "r"
// is NULL), in address order, terminating early if the "doHeapRegion" // is NULL), in address order, terminating early if the "doHeapRegion"
// method returns "true". // method returns "true".
void heap_region_iterate_from(HeapRegion* r, HeapRegionClosure* blk); void heap_region_iterate_from(HeapRegion* r, HeapRegionClosure* blk) const;
// As above but starting from the region at index idx.
void heap_region_iterate_from(int idx, HeapRegionClosure* blk);
HeapRegion* region_at(size_t idx); // Return the region with the given index. It assumes the index is valid.
HeapRegion* region_at(size_t index) const { return _hrs.at(index); }
// Divide the heap region sequence into "chunks" of some size (the number // Divide the heap region sequence into "chunks" of some size (the number
// of regions divided by the number of parallel threads times some // of regions divided by the number of parallel threads times some
...@@ -1182,12 +1200,14 @@ public: ...@@ -1182,12 +1200,14 @@ public:
// A G1CollectedHeap will contain some number of heap regions. This // A G1CollectedHeap will contain some number of heap regions. This
// finds the region containing a given address, or else returns NULL. // finds the region containing a given address, or else returns NULL.
HeapRegion* heap_region_containing(const void* addr) const; template <class T>
inline HeapRegion* heap_region_containing(const T addr) const;
// Like the above, but requires "addr" to be in the heap (to avoid a // Like the above, but requires "addr" to be in the heap (to avoid a
// null-check), and unlike the above, may return an continuing humongous // null-check), and unlike the above, may return an continuing humongous
// region. // region.
HeapRegion* heap_region_containing_raw(const void* addr) const; template <class T>
inline HeapRegion* heap_region_containing_raw(const T addr) const;
// A CollectedHeap is divided into a dense sequence of "blocks"; that is, // A CollectedHeap is divided into a dense sequence of "blocks"; that is,
// each address in the (reserved) heap is a member of exactly // each address in the (reserved) heap is a member of exactly
...@@ -1249,7 +1269,7 @@ public: ...@@ -1249,7 +1269,7 @@ public:
return true; return true;
} }
bool is_in_young(oop obj) { bool is_in_young(const oop obj) {
HeapRegion* hr = heap_region_containing(obj); HeapRegion* hr = heap_region_containing(obj);
return hr != NULL && hr->is_young(); return hr != NULL && hr->is_young();
} }
...@@ -1286,10 +1306,6 @@ public: ...@@ -1286,10 +1306,6 @@ public:
return true; return true;
} }
// The boundary between a "large" and "small" array of primitives, in
// words.
virtual size_t large_typearray_limit();
// Returns "true" iff the given word_size is "very large". // Returns "true" iff the given word_size is "very large".
static bool isHumongous(size_t word_size) { static bool isHumongous(size_t word_size) {
// Note this has to be strictly greater-than as the TLABs // Note this has to be strictly greater-than as the TLABs
...@@ -1329,14 +1345,20 @@ public: ...@@ -1329,14 +1345,20 @@ public:
// Perform verification. // Perform verification.
// use_prev_marking == true -> use "prev" marking information, // vo == UsePrevMarking -> use "prev" marking information,
// use_prev_marking == false -> use "next" marking information // vo == UseNextMarking -> use "next" marking information
// vo == UseMarkWord -> use the mark word in the object header
//
// NOTE: Only the "prev" marking information is guaranteed to be // NOTE: Only the "prev" marking information is guaranteed to be
// consistent most of the time, so most calls to this should use // consistent most of the time, so most calls to this should use
// use_prev_marking == true. Currently, there is only one case where // vo == UsePrevMarking.
// this is called with use_prev_marking == false, which is to verify // Currently, there is only one case where this is called with
// the "next" marking information at the end of remark. // vo == UseNextMarking, which is to verify the "next" marking
void verify(bool allow_dirty, bool silent, bool use_prev_marking); // information at the end of remark.
// Currently there is only one place where this is called with
// vo == UseMarkWord, which is to verify the marking during a
// full GC.
void verify(bool allow_dirty, bool silent, VerifyOption vo);
// Override; it uses the "prev" marking information // Override; it uses the "prev" marking information
virtual void verify(bool allow_dirty, bool silent); virtual void verify(bool allow_dirty, bool silent);
...@@ -1355,10 +1377,9 @@ public: ...@@ -1355,10 +1377,9 @@ public:
// Override // Override
void print_tracing_info() const; void print_tracing_info() const;
// If "addr" is a pointer into the (reserved?) heap, returns a positive // The following two methods are helpful for debugging RSet issues.
// number indicating the "arena" within the heap in which "addr" falls. void print_cset_rsets() PRODUCT_RETURN;
// Or else returns 0. void print_all_rsets() PRODUCT_RETURN;
virtual int addr_to_arena_id(void* addr) const;
// Convenience function to be used in situations where the heap type can be // Convenience function to be used in situations where the heap type can be
// asserted to be this type. // asserted to be this type.
...@@ -1389,24 +1410,27 @@ public: ...@@ -1389,24 +1410,27 @@ public:
// bitmap off to the side. // bitmap off to the side.
void doConcurrentMark(); void doConcurrentMark();
// This is called from the marksweep collector which then does // Do a full concurrent marking, synchronously.
// a concurrent mark and verifies that the results agree with
// the stop the world marking.
void checkConcurrentMark();
void do_sync_mark(); void do_sync_mark();
bool isMarkedPrev(oop obj) const; bool isMarkedPrev(oop obj) const;
bool isMarkedNext(oop obj) const; bool isMarkedNext(oop obj) const;
// use_prev_marking == true -> use "prev" marking information, // vo == UsePrevMarking -> use "prev" marking information,
// use_prev_marking == false -> use "next" marking information // vo == UseNextMarking -> use "next" marking information,
// vo == UseMarkWord -> use mark word from object header
bool is_obj_dead_cond(const oop obj, bool is_obj_dead_cond(const oop obj,
const HeapRegion* hr, const HeapRegion* hr,
const bool use_prev_marking) const { const VerifyOption vo) const {
if (use_prev_marking) {
switch (vo) {
case VerifyOption_G1UsePrevMarking:
return is_obj_dead(obj, hr); return is_obj_dead(obj, hr);
} else { case VerifyOption_G1UseNextMarking:
return is_obj_ill(obj, hr); return is_obj_ill(obj, hr);
default:
assert(vo == VerifyOption_G1UseMarkWord, "must be");
return !obj->is_gc_marked();
} }
} }
...@@ -1447,18 +1471,24 @@ public: ...@@ -1447,18 +1471,24 @@ public:
// Added if it is in permanent gen it isn't dead. // Added if it is in permanent gen it isn't dead.
// Added if it is NULL it isn't dead. // Added if it is NULL it isn't dead.
// use_prev_marking == true -> use "prev" marking information, // vo == UsePrevMarking -> use "prev" marking information,
// use_prev_marking == false -> use "next" marking information // vo == UseNextMarking -> use "next" marking information,
// vo == UseMarkWord -> use mark word from object header
bool is_obj_dead_cond(const oop obj, bool is_obj_dead_cond(const oop obj,
const bool use_prev_marking) { const VerifyOption vo) const {
if (use_prev_marking) {
switch (vo) {
case VerifyOption_G1UsePrevMarking:
return is_obj_dead(obj); return is_obj_dead(obj);
} else { case VerifyOption_G1UseNextMarking:
return is_obj_ill(obj); return is_obj_ill(obj);
default:
assert(vo == VerifyOption_G1UseMarkWord, "must be");
return !obj->is_gc_marked();
} }
} }
bool is_obj_dead(const oop obj) { bool is_obj_dead(const oop obj) const {
const HeapRegion* hr = heap_region_containing(obj); const HeapRegion* hr = heap_region_containing(obj);
if (hr == NULL) { if (hr == NULL) {
if (Universe::heap()->is_in_permanent(obj)) if (Universe::heap()->is_in_permanent(obj))
...@@ -1469,7 +1499,7 @@ public: ...@@ -1469,7 +1499,7 @@ public:
else return is_obj_dead(obj, hr); else return is_obj_dead(obj, hr);
} }
bool is_obj_ill(const oop obj) { bool is_obj_ill(const oop obj) const {
const HeapRegion* hr = heap_region_containing(obj); const HeapRegion* hr = heap_region_containing(obj);
if (hr == NULL) { if (hr == NULL) {
if (Universe::heap()->is_in_permanent(obj)) if (Universe::heap()->is_in_permanent(obj))
......
...@@ -34,9 +34,10 @@ ...@@ -34,9 +34,10 @@
// Inline functions for G1CollectedHeap // Inline functions for G1CollectedHeap
template <class T>
inline HeapRegion* inline HeapRegion*
G1CollectedHeap::heap_region_containing(const void* addr) const { G1CollectedHeap::heap_region_containing(const T addr) const {
HeapRegion* hr = _hrs->addr_to_region(addr); HeapRegion* hr = _hrs.addr_to_region((HeapWord*) addr);
// hr can be null if addr in perm_gen // hr can be null if addr in perm_gen
if (hr != NULL && hr->continuesHumongous()) { if (hr != NULL && hr->continuesHumongous()) {
hr = hr->humongous_start_region(); hr = hr->humongous_start_region();
...@@ -44,19 +45,16 @@ G1CollectedHeap::heap_region_containing(const void* addr) const { ...@@ -44,19 +45,16 @@ G1CollectedHeap::heap_region_containing(const void* addr) const {
return hr; return hr;
} }
template <class T>
inline HeapRegion* inline HeapRegion*
G1CollectedHeap::heap_region_containing_raw(const void* addr) const { G1CollectedHeap::heap_region_containing_raw(const T addr) const {
assert(_g1_reserved.contains(addr), "invariant"); assert(_g1_reserved.contains((const void*) addr), "invariant");
size_t index = pointer_delta(addr, _g1_reserved.start(), 1) HeapRegion* res = _hrs.addr_to_region_unsafe((HeapWord*) addr);
>> HeapRegion::LogOfHRGrainBytes;
HeapRegion* res = _hrs->at(index);
assert(res == _hrs->addr_to_region(addr), "sanity");
return res; return res;
} }
inline bool G1CollectedHeap::obj_in_cs(oop obj) { inline bool G1CollectedHeap::obj_in_cs(oop obj) {
HeapRegion* r = _hrs->addr_to_region(obj); HeapRegion* r = _hrs.addr_to_region((HeapWord*) obj);
return r != NULL && r->in_collection_set(); return r != NULL && r->in_collection_set();
} }
......
...@@ -239,6 +239,10 @@ G1CollectorPolicy::G1CollectorPolicy() : ...@@ -239,6 +239,10 @@ G1CollectorPolicy::G1CollectorPolicy() :
_should_revert_to_full_young_gcs(false), _should_revert_to_full_young_gcs(false),
_last_full_young_gc(false), _last_full_young_gc(false),
_eden_bytes_before_gc(0),
_survivor_bytes_before_gc(0),
_capacity_before_gc(0),
_prev_collection_pause_used_at_end_bytes(0), _prev_collection_pause_used_at_end_bytes(0),
_collection_set(NULL), _collection_set(NULL),
...@@ -897,6 +901,11 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, ...@@ -897,6 +901,11 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
_bytes_in_to_space_after_gc = 0; _bytes_in_to_space_after_gc = 0;
_bytes_in_collection_set_before_gc = 0; _bytes_in_collection_set_before_gc = 0;
YoungList* young_list = _g1->young_list();
_eden_bytes_before_gc = young_list->eden_used_bytes();
_survivor_bytes_before_gc = young_list->survivor_used_bytes();
_capacity_before_gc = _g1->capacity();
#ifdef DEBUG #ifdef DEBUG
// initialise these to something well known so that we can spot // initialise these to something well known so that we can spot
// if they are not set properly // if they are not set properly
...@@ -1460,14 +1469,6 @@ void G1CollectorPolicy::record_collection_pause_end() { ...@@ -1460,14 +1469,6 @@ void G1CollectorPolicy::record_collection_pause_end() {
} }
} }
} }
if (PrintGCDetails)
gclog_or_tty->print(" [");
if (PrintGC || PrintGCDetails)
_g1->print_size_transition(gclog_or_tty,
_cur_collection_pause_used_at_start_bytes,
_g1->used(), _g1->capacity());
if (PrintGCDetails)
gclog_or_tty->print_cr("]");
_all_pause_times_ms->add(elapsed_ms); _all_pause_times_ms->add(elapsed_ms);
if (update_stats) { if (update_stats) {
...@@ -1672,6 +1673,40 @@ void G1CollectorPolicy::record_collection_pause_end() { ...@@ -1672,6 +1673,40 @@ void G1CollectorPolicy::record_collection_pause_end() {
// </NEW PREDICTION> // </NEW PREDICTION>
} }
#define EXT_SIZE_FORMAT "%d%s"
#define EXT_SIZE_PARAMS(bytes) \
byte_size_in_proper_unit((bytes)), \
proper_unit_for_byte_size((bytes))
void G1CollectorPolicy::print_heap_transition() {
if (PrintGCDetails) {
YoungList* young_list = _g1->young_list();
size_t eden_bytes = young_list->eden_used_bytes();
size_t survivor_bytes = young_list->survivor_used_bytes();
size_t used_before_gc = _cur_collection_pause_used_at_start_bytes;
size_t used = _g1->used();
size_t capacity = _g1->capacity();
gclog_or_tty->print_cr(
" [Eden: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
"Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
"Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"
EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]",
EXT_SIZE_PARAMS(_eden_bytes_before_gc),
EXT_SIZE_PARAMS(eden_bytes),
EXT_SIZE_PARAMS(_survivor_bytes_before_gc),
EXT_SIZE_PARAMS(survivor_bytes),
EXT_SIZE_PARAMS(used_before_gc),
EXT_SIZE_PARAMS(_capacity_before_gc),
EXT_SIZE_PARAMS(used),
EXT_SIZE_PARAMS(capacity));
} else if (PrintGC) {
_g1->print_size_transition(gclog_or_tty,
_cur_collection_pause_used_at_start_bytes,
_g1->used(), _g1->capacity());
}
}
// <NEW PREDICTION> // <NEW PREDICTION>
void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
...@@ -2435,21 +2470,6 @@ record_collection_pause_start(double start_time_sec, size_t start_used) { ...@@ -2435,21 +2470,6 @@ record_collection_pause_start(double start_time_sec, size_t start_used) {
G1CollectorPolicy::record_collection_pause_start(start_time_sec, start_used); G1CollectorPolicy::record_collection_pause_start(start_time_sec, start_used);
} }
class NextNonCSElemFinder: public HeapRegionClosure {
HeapRegion* _res;
public:
NextNonCSElemFinder(): _res(NULL) {}
bool doHeapRegion(HeapRegion* r) {
if (!r->in_collection_set()) {
_res = r;
return true;
} else {
return false;
}
}
HeapRegion* res() { return _res; }
};
class KnownGarbageClosure: public HeapRegionClosure { class KnownGarbageClosure: public HeapRegionClosure {
CollectionSetChooser* _hrSorted; CollectionSetChooser* _hrSorted;
...@@ -2618,14 +2638,6 @@ add_to_collection_set(HeapRegion* hr) { ...@@ -2618,14 +2638,6 @@ add_to_collection_set(HeapRegion* hr) {
assert(_inc_cset_build_state == Active, "Precondition"); assert(_inc_cset_build_state == Active, "Precondition");
assert(!hr->is_young(), "non-incremental add of young region"); assert(!hr->is_young(), "non-incremental add of young region");
if (G1PrintHeapRegions) {
gclog_or_tty->print_cr("added region to cset "
"%d:["PTR_FORMAT", "PTR_FORMAT"], "
"top "PTR_FORMAT", %s",
hr->hrs_index(), hr->bottom(), hr->end(),
hr->top(), hr->is_young() ? "YOUNG" : "NOT_YOUNG");
}
if (_g1->mark_in_progress()) if (_g1->mark_in_progress())
_g1->concurrent_mark()->registerCSetRegion(hr); _g1->concurrent_mark()->registerCSetRegion(hr);
...@@ -2791,14 +2803,6 @@ void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) { ...@@ -2791,14 +2803,6 @@ void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) {
_inc_cset_tail->set_next_in_collection_set(hr); _inc_cset_tail->set_next_in_collection_set(hr);
} }
_inc_cset_tail = hr; _inc_cset_tail = hr;
if (G1PrintHeapRegions) {
gclog_or_tty->print_cr(" added region to incremental cset (RHS) "
"%d:["PTR_FORMAT", "PTR_FORMAT"], "
"top "PTR_FORMAT", young %s",
hr->hrs_index(), hr->bottom(), hr->end(),
hr->top(), (hr->is_young()) ? "YES" : "NO");
}
} }
// Add the region to the LHS of the incremental cset // Add the region to the LHS of the incremental cset
...@@ -2816,14 +2820,6 @@ void G1CollectorPolicy::add_region_to_incremental_cset_lhs(HeapRegion* hr) { ...@@ -2816,14 +2820,6 @@ void G1CollectorPolicy::add_region_to_incremental_cset_lhs(HeapRegion* hr) {
_inc_cset_tail = hr; _inc_cset_tail = hr;
} }
_inc_cset_head = hr; _inc_cset_head = hr;
if (G1PrintHeapRegions) {
gclog_or_tty->print_cr(" added region to incremental cset (LHS) "
"%d:["PTR_FORMAT", "PTR_FORMAT"], "
"top "PTR_FORMAT", young %s",
hr->hrs_index(), hr->bottom(), hr->end(),
hr->top(), (hr->is_young()) ? "YES" : "NO");
}
} }
#ifndef PRODUCT #ifndef PRODUCT
......
...@@ -891,6 +891,7 @@ public: ...@@ -891,6 +891,7 @@ public:
virtual void record_collection_pause_end_G1_strong_roots(); virtual void record_collection_pause_end_G1_strong_roots();
virtual void record_collection_pause_end(); virtual void record_collection_pause_end();
void print_heap_transition();
// Record the fact that a full collection occurred. // Record the fact that a full collection occurred.
virtual void record_full_collection_start(); virtual void record_full_collection_start();
...@@ -1179,6 +1180,11 @@ protected: ...@@ -1179,6 +1180,11 @@ protected:
// The limit on the number of regions allocated for survivors. // The limit on the number of regions allocated for survivors.
size_t _max_survivor_regions; size_t _max_survivor_regions;
// For reporting purposes.
size_t _eden_bytes_before_gc;
size_t _survivor_bytes_before_gc;
size_t _capacity_before_gc;
// The amount of survor regions after a collection. // The amount of survor regions after a collection.
size_t _recorded_survivor_regions; size_t _recorded_survivor_regions;
// List of survivor regions. // List of survivor regions.
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc_implementation/g1/g1HRPrinter.hpp"
#include "gc_implementation/g1/heapRegion.hpp"
#include "utilities/ostream.hpp"
const char* G1HRPrinter::action_name(ActionType action) {
switch(action) {
case Alloc: return "ALLOC";
case AllocForce: return "ALLOC-FORCE";
case Retire: return "RETIRE";
case Reuse: return "REUSE";
case CSet: return "CSET";
case EvacFailure: return "EVAC-FAILURE";
case Cleanup: return "CLEANUP";
case PostCompaction: return "POST-COMPACTION";
case Commit: return "COMMIT";
case Uncommit: return "UNCOMMIT";
default: ShouldNotReachHere();
}
// trying to keep the Windows compiler happy
return NULL;
}
const char* G1HRPrinter::region_type_name(RegionType type) {
switch (type) {
case Unset: return NULL;
case Eden: return "Eden";
case Survivor: return "Survivor";
case Old: return "Old";
case SingleHumongous: return "SingleH";
case StartsHumongous: return "StartsH";
case ContinuesHumongous: return "ContinuesH";
default: ShouldNotReachHere();
}
// trying to keep the Windows compiler happy
return NULL;
}
const char* G1HRPrinter::phase_name(PhaseType phase) {
switch (phase) {
case StartGC: return "StartGC";
case EndGC: return "EndGC";
case StartFullGC: return "StartFullGC";
case EndFullGC: return "EndFullGC";
default: ShouldNotReachHere();
}
// trying to keep the Windows compiler happy
return NULL;
}
#define G1HR_PREFIX " G1HR"
void G1HRPrinter::print(ActionType action, RegionType type,
HeapRegion* hr, HeapWord* top) {
const char* action_str = action_name(action);
const char* type_str = region_type_name(type);
HeapWord* bottom = hr->bottom();
if (type_str != NULL) {
if (top != NULL) {
gclog_or_tty->print_cr(G1HR_PREFIX" %s(%s) "PTR_FORMAT" "PTR_FORMAT,
action_str, type_str, bottom, top);
} else {
gclog_or_tty->print_cr(G1HR_PREFIX" %s(%s) "PTR_FORMAT,
action_str, type_str, bottom);
}
} else {
if (top != NULL) {
gclog_or_tty->print_cr(G1HR_PREFIX" %s "PTR_FORMAT" "PTR_FORMAT,
action_str, bottom, top);
} else {
gclog_or_tty->print_cr(G1HR_PREFIX" %s "PTR_FORMAT,
action_str, bottom);
}
}
}
void G1HRPrinter::print(ActionType action, HeapWord* bottom, HeapWord* end) {
const char* action_str = action_name(action);
gclog_or_tty->print_cr(G1HR_PREFIX" %s ["PTR_FORMAT","PTR_FORMAT"]",
action_str, bottom, end);
}
void G1HRPrinter::print(PhaseType phase, size_t phase_num) {
const char* phase_str = phase_name(phase);
gclog_or_tty->print_cr(G1HR_PREFIX" #%s "SIZE_FORMAT, phase_str, phase_num);
}
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1HRPRINTER_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1HRPRINTER_HPP
#include "memory/allocation.hpp"
#include "gc_implementation/g1/heapRegion.hpp"
#define SKIP_RETIRED_FULL_REGIONS 1
class G1HRPrinter VALUE_OBJ_CLASS_SPEC {
public:
typedef enum {
Alloc,
AllocForce,
Retire,
Reuse,
CSet,
EvacFailure,
Cleanup,
PostCompaction,
Commit,
Uncommit
} ActionType;
typedef enum {
Unset,
Eden,
Survivor,
Old,
SingleHumongous,
StartsHumongous,
ContinuesHumongous
} RegionType;
typedef enum {
StartGC,
EndGC,
StartFullGC,
EndFullGC
} PhaseType;
private:
bool _active;
static const char* action_name(ActionType action);
static const char* region_type_name(RegionType type);
static const char* phase_name(PhaseType phase);
// Print an action event. This version is used in most scenarios and
// only prints the region's bottom. The parameters type and top are
// optional (the "not set" values are Unset and NULL).
static void print(ActionType action, RegionType type,
HeapRegion* hr, HeapWord* top);
// Print an action event. This version prints both the region's
// bottom and end. Used for Commit / Uncommit events.
static void print(ActionType action, HeapWord* bottom, HeapWord* end);
// Print a phase event.
static void print(PhaseType phase, size_t phase_num);
public:
// In some places we iterate over a list in order to generate output
// for the list's elements. By exposing this we can avoid this
// iteration if the printer is not active.
const bool is_active() { return _active; }
// Have to set this explicitly as we have to do this during the
// heap's initialize() method, not in the constructor.
void set_active(bool active) { _active = active; }
// The methods below are convenient wrappers for the print() methods.
void alloc(HeapRegion* hr, RegionType type, bool force = false) {
if (is_active()) {
print((!force) ? Alloc : AllocForce, type, hr, NULL);
}
}
void alloc(RegionType type, HeapRegion* hr, HeapWord* top) {
if (is_active()) {
print(Alloc, type, hr, top);
}
}
void retire(HeapRegion* hr) {
if (is_active()) {
if (!SKIP_RETIRED_FULL_REGIONS || hr->top() < hr->end()) {
print(Retire, Unset, hr, hr->top());
}
}
}
void reuse(HeapRegion* hr) {
if (is_active()) {
print(Reuse, Unset, hr, NULL);
}
}
void cset(HeapRegion* hr) {
if (is_active()) {
print(CSet, Unset, hr, NULL);
}
}
void evac_failure(HeapRegion* hr) {
if (is_active()) {
print(EvacFailure, Unset, hr, NULL);
}
}
void cleanup(HeapRegion* hr) {
if (is_active()) {
print(Cleanup, Unset, hr, NULL);
}
}
void post_compaction(HeapRegion* hr, RegionType type) {
if (is_active()) {
print(PostCompaction, type, hr, hr->top());
}
}
void commit(HeapWord* bottom, HeapWord* end) {
if (is_active()) {
print(Commit, bottom, end);
}
}
void uncommit(HeapWord* bottom, HeapWord* end) {
if (is_active()) {
print(Uncommit, bottom, end);
}
}
void start_gc(bool full, size_t gc_num) {
if (is_active()) {
if (!full) {
print(StartGC, gc_num);
} else {
print(StartFullGC, gc_num);
}
}
}
void end_gc(bool full, size_t gc_num) {
if (is_active()) {
if (!full) {
print(EndGC, gc_num);
} else {
print(EndFullGC, gc_num);
}
}
}
G1HRPrinter() : _active(false) { }
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1HRPRINTER_HPP
...@@ -84,11 +84,6 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, ...@@ -84,11 +84,6 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
mark_sweep_phase1(marked_for_unloading, clear_all_softrefs); mark_sweep_phase1(marked_for_unloading, clear_all_softrefs);
if (VerifyDuringGC) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
g1h->checkConcurrentMark();
}
mark_sweep_phase2(); mark_sweep_phase2();
// Don't add any more derived pointers during phase3 // Don't add any more derived pointers during phase3
...@@ -179,6 +174,29 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, ...@@ -179,6 +174,29 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
assert(GenMarkSweep::_marking_stack.is_empty(), assert(GenMarkSweep::_marking_stack.is_empty(),
"stack should be empty by now"); "stack should be empty by now");
if (VerifyDuringGC) {
HandleMark hm; // handle scope
COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact);
gclog_or_tty->print(" VerifyDuringGC:(full)[Verifying ");
Universe::heap()->prepare_for_verify();
// Note: we can verify only the heap here. When an object is
// marked, the previous value of the mark word (including
// identity hash values, ages, etc) is preserved, and the mark
// word is set to markOop::marked_value - effectively removing
// any hash values from the mark word. These hash values are
// used when verifying the dictionaries and so removing them
// from the mark word can make verification of the dictionaries
// fail. At the end of the GC, the orginal mark word values
// (including hash values) are restored to the appropriate
// objects.
Universe::heap()->verify(/* allow dirty */ true,
/* silent */ false,
/* option */ VerifyOption_G1UseMarkWord);
G1CollectedHeap* g1h = G1CollectedHeap::heap();
gclog_or_tty->print_cr("]");
}
} }
class G1PrepareCompactClosure: public HeapRegionClosure { class G1PrepareCompactClosure: public HeapRegionClosure {
......
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -33,6 +33,7 @@ class DirtyCardToOopClosure; ...@@ -33,6 +33,7 @@ class DirtyCardToOopClosure;
class CMBitMap; class CMBitMap;
class CMMarkStack; class CMMarkStack;
class G1ParScanThreadState; class G1ParScanThreadState;
class CMTask;
// A class that scans oops in a given heap region (much as OopsInGenClosure // A class that scans oops in a given heap region (much as OopsInGenClosure
// scans oops in a generation.) // scans oops in a generation.)
...@@ -40,7 +41,7 @@ class OopsInHeapRegionClosure: public OopsInGenClosure { ...@@ -40,7 +41,7 @@ class OopsInHeapRegionClosure: public OopsInGenClosure {
protected: protected:
HeapRegion* _from; HeapRegion* _from;
public: public:
virtual void set_region(HeapRegion* from) { _from = from; } void set_region(HeapRegion* from) { _from = from; }
}; };
class G1ParClosureSuper : public OopsInHeapRegionClosure { class G1ParClosureSuper : public OopsInHeapRegionClosure {
...@@ -161,44 +162,6 @@ public: ...@@ -161,44 +162,6 @@ public:
bool do_header() { return false; } bool do_header() { return false; }
}; };
class FilterInHeapRegionAndIntoCSClosure : public OopsInHeapRegionClosure {
G1CollectedHeap* _g1;
OopsInHeapRegionClosure* _oc;
public:
FilterInHeapRegionAndIntoCSClosure(G1CollectedHeap* g1,
OopsInHeapRegionClosure* oc) :
_g1(g1), _oc(oc)
{}
template <class T> void do_oop_nv(T* p);
virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
bool apply_to_weak_ref_discovered_field() { return true; }
bool do_header() { return false; }
void set_region(HeapRegion* from) {
_oc->set_region(from);
}
};
class FilterAndMarkInHeapRegionAndIntoCSClosure : public OopsInHeapRegionClosure {
G1CollectedHeap* _g1;
ConcurrentMark* _cm;
OopsInHeapRegionClosure* _oc;
public:
FilterAndMarkInHeapRegionAndIntoCSClosure(G1CollectedHeap* g1,
OopsInHeapRegionClosure* oc,
ConcurrentMark* cm)
: _g1(g1), _oc(oc), _cm(cm) { }
template <class T> void do_oop_nv(T* p);
virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
bool apply_to_weak_ref_discovered_field() { return true; }
bool do_header() { return false; }
void set_region(HeapRegion* from) {
_oc->set_region(from);
}
};
class FilterOutOfRegionClosure: public OopClosure { class FilterOutOfRegionClosure: public OopClosure {
HeapWord* _r_bottom; HeapWord* _r_bottom;
HeapWord* _r_end; HeapWord* _r_end;
...@@ -214,4 +177,16 @@ public: ...@@ -214,4 +177,16 @@ public:
int out_of_region() { return _out_of_region; } int out_of_region() { return _out_of_region; }
}; };
// Closure for iterating over object fields during concurrent marking
class G1CMOopClosure : public OopClosure {
G1CollectedHeap* _g1h;
ConcurrentMark* _cm;
CMTask* _task;
public:
G1CMOopClosure(G1CollectedHeap* g1h, ConcurrentMark* cm, CMTask* task);
template <class T> void do_oop_nv(T* p);
virtual void do_oop( oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP
#include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/concurrentMark.inline.hpp"
#include "gc_implementation/g1/g1CollectedHeap.hpp" #include "gc_implementation/g1/g1CollectedHeap.hpp"
#include "gc_implementation/g1/g1OopClosures.hpp" #include "gc_implementation/g1/g1OopClosures.hpp"
#include "gc_implementation/g1/g1RemSet.hpp" #include "gc_implementation/g1/g1RemSet.hpp"
...@@ -66,27 +66,6 @@ template <class T> inline void FilterOutOfRegionClosure::do_oop_nv(T* p) { ...@@ -66,27 +66,6 @@ template <class T> inline void FilterOutOfRegionClosure::do_oop_nv(T* p) {
} }
} }
template <class T> inline void FilterInHeapRegionAndIntoCSClosure::do_oop_nv(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop) &&
_g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop)))
_oc->do_oop(p);
}
template <class T> inline void FilterAndMarkInHeapRegionAndIntoCSClosure::do_oop_nv(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
HeapRegion* hr = _g1->heap_region_containing((HeapWord*) obj);
if (hr != NULL) {
if (hr->in_collection_set())
_oc->do_oop(p);
else if (!hr->is_young())
_cm->grayRoot(obj);
}
}
}
// This closure is applied to the fields of the objects that have just been copied. // This closure is applied to the fields of the objects that have just been copied.
template <class T> inline void G1ParScanClosure::do_oop_nv(T* p) { template <class T> inline void G1ParScanClosure::do_oop_nv(T* p) {
T heap_oop = oopDesc::load_heap_oop(p); T heap_oop = oopDesc::load_heap_oop(p);
...@@ -129,5 +108,18 @@ template <class T> inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) { ...@@ -129,5 +108,18 @@ template <class T> inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) {
} }
} }
template <class T> inline void G1CMOopClosure::do_oop_nv(T* p) {
assert(_g1h->is_in_g1_reserved((HeapWord*) p), "invariant");
assert(!_g1h->is_on_master_free_list(
_g1h->heap_region_containing((HeapWord*) p)), "invariant");
oop obj = oopDesc::load_decode_heap_oop(p);
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%d] we're looking at location "
"*"PTR_FORMAT" = "PTR_FORMAT,
_task->task_id(), p, (void*) obj);
}
_task->deal_with_reference(obj);
}
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP
...@@ -66,41 +66,6 @@ void ct_freq_update_histo_and_reset() { ...@@ -66,41 +66,6 @@ void ct_freq_update_histo_and_reset() {
} }
#endif #endif
class IntoCSOopClosure: public OopsInHeapRegionClosure {
OopsInHeapRegionClosure* _blk;
G1CollectedHeap* _g1;
public:
IntoCSOopClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* blk) :
_g1(g1), _blk(blk) {}
void set_region(HeapRegion* from) {
_blk->set_region(from);
}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop( oop* p) { do_oop_work(p); }
template <class T> void do_oop_work(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p);
if (_g1->obj_in_cs(obj)) _blk->do_oop(p);
}
bool apply_to_weak_ref_discovered_field() { return true; }
bool idempotent() { return true; }
};
class VerifyRSCleanCardOopClosure: public OopClosure {
G1CollectedHeap* _g1;
public:
VerifyRSCleanCardOopClosure(G1CollectedHeap* g1) : _g1(g1) {}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop( oop* p) { do_oop_work(p); }
template <class T> void do_oop_work(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p);
HeapRegion* to = _g1->heap_region_containing(obj);
guarantee(to == NULL || !to->in_collection_set(),
"Missed a rem set member.");
}
};
G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs) G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
: _g1(g1), _conc_refine_cards(0), : _g1(g1), _conc_refine_cards(0),
_ct_bs(ct_bs), _g1p(_g1->g1_policy()), _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
...@@ -332,31 +297,6 @@ void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) { ...@@ -332,31 +297,6 @@ void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
_g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0); _g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
} }
#ifndef PRODUCT
class PrintRSClosure : public HeapRegionClosure {
int _count;
public:
PrintRSClosure() : _count(0) {}
bool doHeapRegion(HeapRegion* r) {
HeapRegionRemSet* hrrs = r->rem_set();
_count += (int) hrrs->occupied();
if (hrrs->occupied() == 0) {
gclog_or_tty->print("Heap Region [" PTR_FORMAT ", " PTR_FORMAT ") "
"has no remset entries\n",
r->bottom(), r->end());
} else {
gclog_or_tty->print("Printing rem set for heap region [" PTR_FORMAT ", " PTR_FORMAT ")\n",
r->bottom(), r->end());
r->print();
hrrs->print();
gclog_or_tty->print("\nDone printing rem set\n");
}
return false;
}
int occupied() {return _count;}
};
#endif
class CountRSSizeClosure: public HeapRegionClosure { class CountRSSizeClosure: public HeapRegionClosure {
size_t _n; size_t _n;
size_t _tot; size_t _tot;
...@@ -482,10 +422,6 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, ...@@ -482,10 +422,6 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
} }
void G1RemSet::prepare_for_oops_into_collection_set_do() { void G1RemSet::prepare_for_oops_into_collection_set_do() {
#if G1_REM_SET_LOGGING
PrintRSClosure cl;
_g1->collection_set_iterate(&cl);
#endif
cleanupHRRS(); cleanupHRRS();
ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine(); ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
_g1->set_refine_cte_cl_concurrency(false); _g1->set_refine_cte_cl_concurrency(false);
...@@ -504,14 +440,6 @@ void G1RemSet::prepare_for_oops_into_collection_set_do() { ...@@ -504,14 +440,6 @@ void G1RemSet::prepare_for_oops_into_collection_set_do() {
} }
class cleanUpIteratorsClosure : public HeapRegionClosure {
bool doHeapRegion(HeapRegion *r) {
HeapRegionRemSet* hrrs = r->rem_set();
hrrs->init_for_par_iteration();
return false;
}
};
// This closure, applied to a DirtyCardQueueSet, is used to immediately // This closure, applied to a DirtyCardQueueSet, is used to immediately
// update the RSets for the regions in the CSet. For each card it iterates // update the RSets for the regions in the CSet. For each card it iterates
// through the oops which coincide with that card. It scans the reference // through the oops which coincide with that card. It scans the reference
...@@ -572,18 +500,13 @@ public: ...@@ -572,18 +500,13 @@ public:
void G1RemSet::cleanup_after_oops_into_collection_set_do() { void G1RemSet::cleanup_after_oops_into_collection_set_do() {
guarantee( _cards_scanned != NULL, "invariant" ); guarantee( _cards_scanned != NULL, "invariant" );
_total_cards_scanned = 0; _total_cards_scanned = 0;
for (uint i = 0; i < n_workers(); ++i) for (uint i = 0; i < n_workers(); ++i) {
_total_cards_scanned += _cards_scanned[i]; _total_cards_scanned += _cards_scanned[i];
}
FREE_C_HEAP_ARRAY(size_t, _cards_scanned); FREE_C_HEAP_ARRAY(size_t, _cards_scanned);
_cards_scanned = NULL; _cards_scanned = NULL;
// Cleanup after copy // Cleanup after copy
#if G1_REM_SET_LOGGING
PrintRSClosure cl;
_g1->heap_region_iterate(&cl);
#endif
_g1->set_refine_cte_cl_concurrency(true); _g1->set_refine_cte_cl_concurrency(true);
cleanUpIteratorsClosure iterClosure;
_g1->collection_set_iterate(&iterClosure);
// Set all cards back to clean. // Set all cards back to clean.
_g1->cleanUpCardTable(); _g1->cleanUpCardTable();
......
...@@ -142,8 +142,6 @@ public: ...@@ -142,8 +142,6 @@ public:
virtual void prepare_for_verify(); virtual void prepare_for_verify();
}; };
#define G1_REM_SET_LOGGING 0
class CountNonCleanMemRegionClosure: public MemRegionClosure { class CountNonCleanMemRegionClosure: public MemRegionClosure {
G1CollectedHeap* _g1; G1CollectedHeap* _g1;
int _n; int _n;
......
...@@ -65,12 +65,6 @@ inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) { ...@@ -65,12 +65,6 @@ inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) {
HeapRegion* to = _g1->heap_region_containing(obj); HeapRegion* to = _g1->heap_region_containing(obj);
if (to != NULL && from != to) { if (to != NULL && from != to) {
#if G1_REM_SET_LOGGING
gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS"
" for region [" PTR_FORMAT ", " PTR_FORMAT ")",
p, obj,
to->bottom(), to->end());
#endif
assert(to->rem_set() != NULL, "Need per-region 'into' remsets."); assert(to->rem_set() != NULL, "Need per-region 'into' remsets.");
to->rem_set()->add_reference(p, tid); to->rem_set()->add_reference(p, tid);
} }
......
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -45,8 +45,7 @@ typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacClosure; ...@@ -45,8 +45,7 @@ typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacClosure;
class FilterIntoCSClosure; class FilterIntoCSClosure;
class FilterOutOfRegionClosure; class FilterOutOfRegionClosure;
class FilterInHeapRegionAndIntoCSClosure; class G1CMOopClosure;
class FilterAndMarkInHeapRegionAndIntoCSClosure;
#ifdef FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES #ifdef FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES
#error "FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES already defined." #error "FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES already defined."
...@@ -58,8 +57,7 @@ class FilterAndMarkInHeapRegionAndIntoCSClosure; ...@@ -58,8 +57,7 @@ class FilterAndMarkInHeapRegionAndIntoCSClosure;
f(G1ParPushHeapRSClosure,_nv) \ f(G1ParPushHeapRSClosure,_nv) \
f(FilterIntoCSClosure,_nv) \ f(FilterIntoCSClosure,_nv) \
f(FilterOutOfRegionClosure,_nv) \ f(FilterOutOfRegionClosure,_nv) \
f(FilterInHeapRegionAndIntoCSClosure,_nv) \ f(G1CMOopClosure,_nv)
f(FilterAndMarkInHeapRegionAndIntoCSClosure,_nv)
#ifdef FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES #ifdef FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES
#error "FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES already defined." #error "FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES already defined."
......
...@@ -60,13 +60,14 @@ private: ...@@ -60,13 +60,14 @@ private:
oop _containing_obj; oop _containing_obj;
bool _failures; bool _failures;
int _n_failures; int _n_failures;
bool _use_prev_marking; VerifyOption _vo;
public: public:
// use_prev_marking == true -> use "prev" marking information, // _vo == UsePrevMarking -> use "prev" marking information,
// use_prev_marking == false -> use "next" marking information // _vo == UseNextMarking -> use "next" marking information,
VerifyLiveClosure(G1CollectedHeap* g1h, bool use_prev_marking) : // _vo == UseMarkWord -> use mark word from object header.
VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) :
_g1h(g1h), _bs(NULL), _containing_obj(NULL), _g1h(g1h), _bs(NULL), _containing_obj(NULL),
_failures(false), _n_failures(0), _use_prev_marking(use_prev_marking) _failures(false), _n_failures(0), _vo(vo)
{ {
BarrierSet* bs = _g1h->barrier_set(); BarrierSet* bs = _g1h->barrier_set();
if (bs->is_a(BarrierSet::CardTableModRef)) if (bs->is_a(BarrierSet::CardTableModRef))
...@@ -95,14 +96,14 @@ public: ...@@ -95,14 +96,14 @@ public:
template <class T> void do_oop_work(T* p) { template <class T> void do_oop_work(T* p) {
assert(_containing_obj != NULL, "Precondition"); assert(_containing_obj != NULL, "Precondition");
assert(!_g1h->is_obj_dead_cond(_containing_obj, _use_prev_marking), assert(!_g1h->is_obj_dead_cond(_containing_obj, _vo),
"Precondition"); "Precondition");
T heap_oop = oopDesc::load_heap_oop(p); T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) { if (!oopDesc::is_null(heap_oop)) {
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
bool failed = false; bool failed = false;
if (!_g1h->is_in_closed_subset(obj) || if (!_g1h->is_in_closed_subset(obj) ||
_g1h->is_obj_dead_cond(obj, _use_prev_marking)) { _g1h->is_obj_dead_cond(obj, _vo)) {
if (!_failures) { if (!_failures) {
gclog_or_tty->print_cr(""); gclog_or_tty->print_cr("");
gclog_or_tty->print_cr("----------"); gclog_or_tty->print_cr("----------");
...@@ -159,20 +160,16 @@ public: ...@@ -159,20 +160,16 @@ public:
gclog_or_tty->print_cr("----------"); gclog_or_tty->print_cr("----------");
} }
gclog_or_tty->print_cr("Missing rem set entry:"); gclog_or_tty->print_cr("Missing rem set entry:");
gclog_or_tty->print_cr("Field "PTR_FORMAT gclog_or_tty->print_cr("Field "PTR_FORMAT" "
" of obj "PTR_FORMAT "of obj "PTR_FORMAT", "
", in region %d ["PTR_FORMAT "in region "HR_FORMAT,
", "PTR_FORMAT"),",
p, (void*) _containing_obj, p, (void*) _containing_obj,
from->hrs_index(), HR_FORMAT_PARAMS(from));
from->bottom(),
from->end());
_containing_obj->print_on(gclog_or_tty); _containing_obj->print_on(gclog_or_tty);
gclog_or_tty->print_cr("points to obj "PTR_FORMAT gclog_or_tty->print_cr("points to obj "PTR_FORMAT" "
" in region %d ["PTR_FORMAT "in region "HR_FORMAT,
", "PTR_FORMAT").", (void*) obj,
(void*) obj, to->hrs_index(), HR_FORMAT_PARAMS(to));
to->bottom(), to->end());
obj->print_on(gclog_or_tty); obj->print_on(gclog_or_tty);
gclog_or_tty->print_cr("Obj head CTE = %d, field CTE = %d.", gclog_or_tty->print_cr("Obj head CTE = %d, field CTE = %d.",
cv_obj, cv_field); cv_obj, cv_field);
...@@ -484,11 +481,10 @@ void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) { ...@@ -484,11 +481,10 @@ void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
HeapRegion:: HeapRegion::
HeapRegion(G1BlockOffsetSharedArray* sharedOffsetArray, HeapRegion(size_t hrs_index, G1BlockOffsetSharedArray* sharedOffsetArray,
MemRegion mr, bool is_zeroed) MemRegion mr, bool is_zeroed)
: G1OffsetTableContigSpace(sharedOffsetArray, mr, is_zeroed), : G1OffsetTableContigSpace(sharedOffsetArray, mr, is_zeroed),
_next_fk(HeapRegionDCTOC::NoFilterKind), _next_fk(HeapRegionDCTOC::NoFilterKind), _hrs_index(hrs_index),
_hrs_index(-1),
_humongous_type(NotHumongous), _humongous_start_region(NULL), _humongous_type(NotHumongous), _humongous_start_region(NULL),
_in_collection_set(false), _is_gc_alloc_region(false), _in_collection_set(false), _is_gc_alloc_region(false),
_next_in_special_set(NULL), _orig_end(NULL), _next_in_special_set(NULL), _orig_end(NULL),
...@@ -740,20 +736,20 @@ void HeapRegion::print_on(outputStream* st) const { ...@@ -740,20 +736,20 @@ void HeapRegion::print_on(outputStream* st) const {
void HeapRegion::verify(bool allow_dirty) const { void HeapRegion::verify(bool allow_dirty) const {
bool dummy = false; bool dummy = false;
verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy); verify(allow_dirty, VerifyOption_G1UsePrevMarking, /* failures */ &dummy);
} }
// This really ought to be commoned up into OffsetTableContigSpace somehow. // This really ought to be commoned up into OffsetTableContigSpace somehow.
// We would need a mechanism to make that code skip dead objects. // We would need a mechanism to make that code skip dead objects.
void HeapRegion::verify(bool allow_dirty, void HeapRegion::verify(bool allow_dirty,
bool use_prev_marking, VerifyOption vo,
bool* failures) const { bool* failures) const {
G1CollectedHeap* g1 = G1CollectedHeap::heap(); G1CollectedHeap* g1 = G1CollectedHeap::heap();
*failures = false; *failures = false;
HeapWord* p = bottom(); HeapWord* p = bottom();
HeapWord* prev_p = NULL; HeapWord* prev_p = NULL;
VerifyLiveClosure vl_cl(g1, use_prev_marking); VerifyLiveClosure vl_cl(g1, vo);
bool is_humongous = isHumongous(); bool is_humongous = isHumongous();
bool do_bot_verify = !is_young(); bool do_bot_verify = !is_young();
size_t object_num = 0; size_t object_num = 0;
...@@ -778,7 +774,7 @@ void HeapRegion::verify(bool allow_dirty, ...@@ -778,7 +774,7 @@ void HeapRegion::verify(bool allow_dirty,
return; return;
} }
if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) { if (!g1->is_obj_dead_cond(obj, this, vo)) {
if (obj->is_oop()) { if (obj->is_oop()) {
klassOop klass = obj->klass(); klassOop klass = obj->klass();
if (!klass->is_perm()) { if (!klass->is_perm()) {
......
...@@ -52,9 +52,11 @@ class HeapRegionRemSetIterator; ...@@ -52,9 +52,11 @@ class HeapRegionRemSetIterator;
class HeapRegion; class HeapRegion;
class HeapRegionSetBase; class HeapRegionSetBase;
#define HR_FORMAT "%d:["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]" #define HR_FORMAT SIZE_FORMAT":(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
#define HR_FORMAT_PARAMS(_hr_) (_hr_)->hrs_index(), (_hr_)->bottom(), \ #define HR_FORMAT_PARAMS(_hr_) \
(_hr_)->top(), (_hr_)->end() (_hr_)->hrs_index(), \
(_hr_)->is_survivor() ? "S" : (_hr_)->is_young() ? "E" : "-", \
(_hr_)->bottom(), (_hr_)->top(), (_hr_)->end()
// A dirty card to oop closure for heap regions. It // A dirty card to oop closure for heap regions. It
// knows how to get the G1 heap and how to use the bitmap // knows how to get the G1 heap and how to use the bitmap
...@@ -237,9 +239,8 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -237,9 +239,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
G1BlockOffsetArrayContigSpace* offsets() { return &_offsets; } G1BlockOffsetArrayContigSpace* offsets() { return &_offsets; }
protected: protected:
// If this region is a member of a HeapRegionSeq, the index in that // The index of this region in the heap region sequence.
// sequence, otherwise -1. size_t _hrs_index;
int _hrs_index;
HumongousType _humongous_type; HumongousType _humongous_type;
// For a humongous region, region in which it starts. // For a humongous region, region in which it starts.
...@@ -296,8 +297,7 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -296,8 +297,7 @@ class HeapRegion: public G1OffsetTableContigSpace {
enum YoungType { enum YoungType {
NotYoung, // a region is not young NotYoung, // a region is not young
Young, // a region is young Young, // a region is young
Survivor // a region is young and it contains Survivor // a region is young and it contains survivors
// survivor
}; };
volatile YoungType _young_type; volatile YoungType _young_type;
...@@ -351,7 +351,8 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -351,7 +351,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
public: public:
// If "is_zeroed" is "true", the region "mr" can be assumed to contain zeros. // If "is_zeroed" is "true", the region "mr" can be assumed to contain zeros.
HeapRegion(G1BlockOffsetSharedArray* sharedOffsetArray, HeapRegion(size_t hrs_index,
G1BlockOffsetSharedArray* sharedOffsetArray,
MemRegion mr, bool is_zeroed); MemRegion mr, bool is_zeroed);
static int LogOfHRGrainBytes; static int LogOfHRGrainBytes;
...@@ -393,8 +394,7 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -393,8 +394,7 @@ class HeapRegion: public G1OffsetTableContigSpace {
// If this region is a member of a HeapRegionSeq, the index in that // If this region is a member of a HeapRegionSeq, the index in that
// sequence, otherwise -1. // sequence, otherwise -1.
int hrs_index() const { return _hrs_index; } size_t hrs_index() const { return _hrs_index; }
void set_hrs_index(int index) { _hrs_index = index; }
// The number of bytes marked live in the region in the last marking phase. // The number of bytes marked live in the region in the last marking phase.
size_t marked_bytes() { return _prev_marked_bytes; } size_t marked_bytes() { return _prev_marked_bytes; }
...@@ -579,6 +579,8 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -579,6 +579,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
void set_next_dirty_cards_region(HeapRegion* hr) { _next_dirty_cards_region = hr; } void set_next_dirty_cards_region(HeapRegion* hr) { _next_dirty_cards_region = hr; }
bool is_on_dirty_cards_region_list() const { return get_next_dirty_cards_region() != NULL; } bool is_on_dirty_cards_region_list() const { return get_next_dirty_cards_region() != NULL; }
HeapWord* orig_end() { return _orig_end; }
// Allows logical separation between objects allocated before and after. // Allows logical separation between objects allocated before and after.
void save_marks(); void save_marks();
...@@ -853,14 +855,20 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -853,14 +855,20 @@ class HeapRegion: public G1OffsetTableContigSpace {
void print() const; void print() const;
void print_on(outputStream* st) const; void print_on(outputStream* st) const;
// use_prev_marking == true -> use "prev" marking information, // vo == UsePrevMarking -> use "prev" marking information,
// use_prev_marking == false -> use "next" marking information // vo == UseNextMarking -> use "next" marking information
// vo == UseMarkWord -> use the mark word in the object header
//
// NOTE: Only the "prev" marking information is guaranteed to be // NOTE: Only the "prev" marking information is guaranteed to be
// consistent most of the time, so most calls to this should use // consistent most of the time, so most calls to this should use
// use_prev_marking == true. Currently, there is only one case where // vo == UsePrevMarking.
// this is called with use_prev_marking == false, which is to verify // Currently, there is only one case where this is called with
// the "next" marking information at the end of remark. // vo == UseNextMarking, which is to verify the "next" marking
void verify(bool allow_dirty, bool use_prev_marking, bool *failures) const; // information at the end of remark.
// Currently there is only one place where this is called with
// vo == UseMarkWord, which is to verify the marking during a
// full GC.
void verify(bool allow_dirty, VerifyOption vo, bool *failures) const;
// Override; it uses the "prev" marking information // Override; it uses the "prev" marking information
virtual void verify(bool allow_dirty) const; virtual void verify(bool allow_dirty) const;
......
...@@ -834,7 +834,7 @@ PosParPRT* OtherRegionsTable::delete_region_table() { ...@@ -834,7 +834,7 @@ PosParPRT* OtherRegionsTable::delete_region_table() {
#endif #endif
// Set the corresponding coarse bit. // Set the corresponding coarse bit.
int max_hrs_index = max->hr()->hrs_index(); size_t max_hrs_index = max->hr()->hrs_index();
if (!_coarse_map.at(max_hrs_index)) { if (!_coarse_map.at(max_hrs_index)) {
_coarse_map.at_put(max_hrs_index, true); _coarse_map.at_put(max_hrs_index, true);
_n_coarse_entries++; _n_coarse_entries++;
...@@ -860,7 +860,8 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, ...@@ -860,7 +860,8 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
BitMap* region_bm, BitMap* card_bm) { BitMap* region_bm, BitMap* card_bm) {
// First eliminated garbage regions from the coarse map. // First eliminated garbage regions from the coarse map.
if (G1RSScrubVerbose) if (G1RSScrubVerbose)
gclog_or_tty->print_cr("Scrubbing region %d:", hr()->hrs_index()); gclog_or_tty->print_cr("Scrubbing region "SIZE_FORMAT":",
hr()->hrs_index());
assert(_coarse_map.size() == region_bm->size(), "Precondition"); assert(_coarse_map.size() == region_bm->size(), "Precondition");
if (G1RSScrubVerbose) if (G1RSScrubVerbose)
...@@ -878,7 +879,8 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, ...@@ -878,7 +879,8 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
PosParPRT* nxt = cur->next(); PosParPRT* nxt = cur->next();
// If the entire region is dead, eliminate. // If the entire region is dead, eliminate.
if (G1RSScrubVerbose) if (G1RSScrubVerbose)
gclog_or_tty->print_cr(" For other region %d:", cur->hr()->hrs_index()); gclog_or_tty->print_cr(" For other region "SIZE_FORMAT":",
cur->hr()->hrs_index());
if (!region_bm->at(cur->hr()->hrs_index())) { if (!region_bm->at(cur->hr()->hrs_index())) {
*prev = nxt; *prev = nxt;
cur->set_next(NULL); cur->set_next(NULL);
...@@ -994,7 +996,7 @@ void OtherRegionsTable::clear() { ...@@ -994,7 +996,7 @@ void OtherRegionsTable::clear() {
void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) { void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) {
MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
size_t hrs_ind = (size_t)from_hr->hrs_index(); size_t hrs_ind = from_hr->hrs_index();
size_t ind = hrs_ind & _mod_max_fine_entries_mask; size_t ind = hrs_ind & _mod_max_fine_entries_mask;
if (del_single_region_table(ind, from_hr)) { if (del_single_region_table(ind, from_hr)) {
assert(!_coarse_map.at(hrs_ind), "Inv"); assert(!_coarse_map.at(hrs_ind), "Inv");
...@@ -1002,7 +1004,7 @@ void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) { ...@@ -1002,7 +1004,7 @@ void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) {
_coarse_map.par_at_put(hrs_ind, 0); _coarse_map.par_at_put(hrs_ind, 0);
} }
// Check to see if any of the fcc entries come from here. // Check to see if any of the fcc entries come from here.
int hr_ind = hr()->hrs_index(); size_t hr_ind = hr()->hrs_index();
for (int tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) { for (int tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) {
int fcc_ent = _from_card_cache[tid][hr_ind]; int fcc_ent = _from_card_cache[tid][hr_ind];
if (fcc_ent != -1) { if (fcc_ent != -1) {
...@@ -1083,8 +1085,9 @@ int HeapRegionRemSet::num_par_rem_sets() { ...@@ -1083,8 +1085,9 @@ int HeapRegionRemSet::num_par_rem_sets() {
HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
HeapRegion* hr) HeapRegion* hr)
: _bosa(bosa), _other_regions(hr), _iter_state(Unclaimed) { } : _bosa(bosa), _other_regions(hr) {
reset_for_par_iteration();
}
void HeapRegionRemSet::setup_remset_size() { void HeapRegionRemSet::setup_remset_size() {
// Setup sparse and fine-grain tables sizes. // Setup sparse and fine-grain tables sizes.
...@@ -1099,10 +1102,6 @@ void HeapRegionRemSet::setup_remset_size() { ...@@ -1099,10 +1102,6 @@ void HeapRegionRemSet::setup_remset_size() {
guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity"); guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity");
} }
void HeapRegionRemSet::init_for_par_iteration() {
_iter_state = Unclaimed;
}
bool HeapRegionRemSet::claim_iter() { bool HeapRegionRemSet::claim_iter() {
if (_iter_state != Unclaimed) return false; if (_iter_state != Unclaimed) return false;
jint res = Atomic::cmpxchg(Claimed, (jint*)(&_iter_state), Unclaimed); jint res = Atomic::cmpxchg(Claimed, (jint*)(&_iter_state), Unclaimed);
...@@ -1117,7 +1116,6 @@ bool HeapRegionRemSet::iter_is_complete() { ...@@ -1117,7 +1116,6 @@ bool HeapRegionRemSet::iter_is_complete() {
return _iter_state == Complete; return _iter_state == Complete;
} }
void HeapRegionRemSet::init_iterator(HeapRegionRemSetIterator* iter) const { void HeapRegionRemSet::init_iterator(HeapRegionRemSetIterator* iter) const {
iter->initialize(this); iter->initialize(this);
} }
...@@ -1130,7 +1128,7 @@ void HeapRegionRemSet::print() const { ...@@ -1130,7 +1128,7 @@ void HeapRegionRemSet::print() const {
while (iter.has_next(card_index)) { while (iter.has_next(card_index)) {
HeapWord* card_start = HeapWord* card_start =
G1CollectedHeap::heap()->bot_shared()->address_for_index(card_index); G1CollectedHeap::heap()->bot_shared()->address_for_index(card_index);
gclog_or_tty->print_cr(" Card " PTR_FORMAT ".", card_start); gclog_or_tty->print_cr(" Card " PTR_FORMAT, card_start);
} }
// XXX // XXX
if (iter.n_yielded() != occupied()) { if (iter.n_yielded() != occupied()) {
...@@ -1157,6 +1155,14 @@ void HeapRegionRemSet::par_cleanup() { ...@@ -1157,6 +1155,14 @@ void HeapRegionRemSet::par_cleanup() {
void HeapRegionRemSet::clear() { void HeapRegionRemSet::clear() {
_other_regions.clear(); _other_regions.clear();
assert(occupied() == 0, "Should be clear."); assert(occupied() == 0, "Should be clear.");
reset_for_par_iteration();
}
void HeapRegionRemSet::reset_for_par_iteration() {
_iter_state = Unclaimed;
_iter_claimed = 0;
// It's good to check this to make sure that the two methods are in sync.
assert(verify_ready_for_par_iteration(), "post-condition");
} }
void HeapRegionRemSet::scrub(CardTableModRefBS* ctbs, void HeapRegionRemSet::scrub(CardTableModRefBS* ctbs,
......
...@@ -262,8 +262,6 @@ public: ...@@ -262,8 +262,6 @@ public:
virtual void cleanup() = 0; virtual void cleanup() = 0;
#endif #endif
// Should be called from single-threaded code.
void init_for_par_iteration();
// Attempt to claim the region. Returns true iff this call caused an // Attempt to claim the region. Returns true iff this call caused an
// atomic transition from Unclaimed to Claimed. // atomic transition from Unclaimed to Claimed.
bool claim_iter(); bool claim_iter();
...@@ -273,7 +271,6 @@ public: ...@@ -273,7 +271,6 @@ public:
bool iter_is_complete(); bool iter_is_complete();
// Support for claiming blocks of cards during iteration // Support for claiming blocks of cards during iteration
void set_iter_claimed(size_t x) { _iter_claimed = (jlong)x; }
size_t iter_claimed() const { return (size_t)_iter_claimed; } size_t iter_claimed() const { return (size_t)_iter_claimed; }
// Claim the next block of cards // Claim the next block of cards
size_t iter_claimed_next(size_t step) { size_t iter_claimed_next(size_t step) {
...@@ -284,6 +281,11 @@ public: ...@@ -284,6 +281,11 @@ public:
} while (Atomic::cmpxchg((jlong)next, &_iter_claimed, (jlong)current) != (jlong)current); } while (Atomic::cmpxchg((jlong)next, &_iter_claimed, (jlong)current) != (jlong)current);
return current; return current;
} }
void reset_for_par_iteration();
bool verify_ready_for_par_iteration() {
return (_iter_state == Unclaimed) && (_iter_claimed == 0);
}
// Initialize the given iterator to iterate over this rem set. // Initialize the given iterator to iterate over this rem set.
void init_iterator(HeapRegionRemSetIterator* iter) const; void init_iterator(HeapRegionRemSetIterator* iter) const;
......
...@@ -25,92 +25,143 @@ ...@@ -25,92 +25,143 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP
#include "gc_implementation/g1/heapRegion.hpp"
#include "utilities/growableArray.hpp"
class HeapRegion; class HeapRegion;
class HeapRegionClosure; class HeapRegionClosure;
class FreeRegionList;
#define G1_NULL_HRS_INDEX ((size_t) -1)
// This class keeps track of the region metadata (i.e., HeapRegion
// instances). They are kept in the _regions array in address
// order. A region's index in the array corresponds to its index in
// the heap (i.e., 0 is the region at the bottom of the heap, 1 is
// the one after it, etc.). Two regions that are consecutive in the
// array should also be adjacent in the address space (i.e.,
// region(i).end() == region(i+1).bottom().
//
// We create a HeapRegion when we commit the region's address space
// for the first time. When we uncommit the address space of a
// region we retain the HeapRegion to be able to re-use it in the
// future (in case we recommit it).
//
// We keep track of three lengths:
//
// * _length (returned by length()) is the number of currently
// committed regions.
// * _allocated_length (not exposed outside this class) is the
// number of regions for which we have HeapRegions.
// * _max_length (returned by max_length()) is the maximum number of
// regions the heap can have.
//
// and maintain that: _length <= _allocated_length <= _max_length
class HeapRegionSeq: public CHeapObj { class HeapRegionSeq: public CHeapObj {
// _regions is kept sorted by start address order, and no two regions are // The array that holds the HeapRegions.
// overlapping. HeapRegion** _regions;
GrowableArray<HeapRegion*> _regions;
// The index in "_regions" at which to start the next allocation search. // Version of _regions biased to address 0
// (For efficiency only; private to obj_allocate after initialization.) HeapRegion** _regions_biased;
int _alloc_search_start;
// Finds a contiguous set of empty regions of length num, starting // The number of regions committed in the heap.
// from a given index. size_t _length;
int find_contiguous_from(int from, size_t num);
// Currently, we're choosing collection sets in a round-robin fashion, // The address of the first reserved word in the heap.
// starting here. HeapWord* _heap_bottom;
int _next_rr_candidate;
// The bottom address of the bottom-most region, or else NULL if there // The address of the last reserved word in the heap - 1.
// are no regions in the sequence. HeapWord* _heap_end;
char* _seq_bottom;
public: // The log of the region byte size.
// Initializes "this" to the empty sequence of regions. size_t _region_shift;
HeapRegionSeq(const size_t max_size);
// Adds "hr" to "this" sequence. Requires "hr" not to overlap with // A hint for which index to start searching from for humongous
// any region already in "this". (Will perform better if regions are // allocations.
// inserted in ascending address order.) size_t _next_search_index;
void insert(HeapRegion* hr);
// Given a HeapRegion*, returns its index within _regions, // The number of regions for which we have allocated HeapRegions for.
// or returns -1 if not found. size_t _allocated_length;
int find(HeapRegion* hr);
// Requires the index to be valid, and return the region at the index. // The maximum number of regions in the heap.
HeapRegion* at(size_t i) { return _regions.at((int)i); } size_t _max_length;
// Return the number of regions in the sequence. // Find a contiguous set of empty regions of length num, starting
size_t length(); // from the given index.
size_t find_contiguous_from(size_t from, size_t num);
// Returns the number of contiguous regions at the end of the sequence // Map a heap address to a biased region index. Assume that the
// that are available for allocation. // address is valid.
size_t free_suffix(); inline size_t addr_to_index_biased(HeapWord* addr) const;
// Find a contiguous set of empty regions of length num and return void increment_length(size_t* length) {
// the index of the first region or -1 if the search was unsuccessful. assert(*length < _max_length, "pre-condition");
int find_contiguous(size_t num); *length += 1;
}
void decrement_length(size_t* length) {
assert(*length > 0, "pre-condition");
*length -= 1;
}
// Apply the "doHeapRegion" method of "blk" to all regions in "this", public:
// in address order, terminating the iteration early // Empty contructor, we'll initialize it with the initialize() method.
// if the "doHeapRegion" method returns "true". HeapRegionSeq() { }
void iterate(HeapRegionClosure* blk);
void initialize(HeapWord* bottom, HeapWord* end, size_t max_length);
// Return the HeapRegion at the given index. Assume that the index
// is valid.
inline HeapRegion* at(size_t index) const;
// Apply the "doHeapRegion" method of "blk" to all regions in "this", // If addr is within the committed space return its corresponding
// starting at "r" (or first region, if "r" is NULL), in a circular // HeapRegion, otherwise return NULL.
// manner, terminating the iteration early if the "doHeapRegion" method inline HeapRegion* addr_to_region(HeapWord* addr) const;
// returns "true".
void iterate_from(HeapRegion* r, HeapRegionClosure* blk);
// As above, but start from a given index in the sequence // Return the HeapRegion that corresponds to the given
// instead of a given heap region. // address. Assume the address is valid.
void iterate_from(int idx, HeapRegionClosure* blk); inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const;
// Requires "shrink_bytes" to be a multiple of the page size and heap // Return the number of regions that have been committed in the heap.
// region granularity. Deletes as many "rightmost" completely free heap size_t length() const { return _length; }
// regions from the sequence as comprise shrink_bytes bytes. Returns the
// MemRegion indicating the region those regions comprised, and sets
// "num_regions_deleted" to the number of regions deleted.
MemRegion shrink_by(size_t shrink_bytes, size_t& num_regions_deleted);
// If "addr" falls within a region in the sequence, return that region, // Return the maximum number of regions in the heap.
// or else NULL. size_t max_length() const { return _max_length; }
inline HeapRegion* addr_to_region(const void* addr);
void print(); // Expand the sequence to reflect that the heap has grown from
// old_end to new_end. Either create new HeapRegions, or re-use
// existing ones, and return them in the given list. Returns the
// memory region that covers the newly-created regions. If a
// HeapRegion allocation fails, the result memory region might be
// smaller than the desired one.
MemRegion expand_by(HeapWord* old_end, HeapWord* new_end,
FreeRegionList* list);
// Prints out runs of empty regions. // Return the number of contiguous regions at the end of the sequence
void print_empty_runs(); // that are available for allocation.
size_t free_suffix();
// Find a contiguous set of empty regions of length num and return
// the index of the first region or G1_NULL_HRS_INDEX if the
// search was unsuccessful.
size_t find_contiguous(size_t num);
// Apply blk->doHeapRegion() on all committed regions in address order,
// terminating the iteration early if doHeapRegion() returns true.
void iterate(HeapRegionClosure* blk) const;
// As above, but start the iteration from hr and loop around. If hr
// is NULL, we start from the first region in the heap.
void iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const;
// Tag as uncommitted as many regions that are completely free as
// possible, up to shrink_bytes, from the suffix of the committed
// sequence. Return a MemRegion that corresponds to the address
// range of the uncommitted regions. Assume shrink_bytes is page and
// heap region aligned.
MemRegion shrink_by(size_t shrink_bytes, size_t* num_regions_deleted);
// Do some sanity checking.
void verify_optional() PRODUCT_RETURN;
}; };
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP
/* /*
* copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "gc_implementation/g1/heapRegionSets.hpp" #include "gc_implementation/g1/heapRegionSets.hpp"
//////////////////// FreeRegionList //////////////////// //////////////////// FreeRegionList ////////////////////
...@@ -38,6 +39,16 @@ const char* FreeRegionList::verify_region_extra(HeapRegion* hr) { ...@@ -38,6 +39,16 @@ const char* FreeRegionList::verify_region_extra(HeapRegion* hr) {
//////////////////// MasterFreeRegionList //////////////////// //////////////////// MasterFreeRegionList ////////////////////
const char* MasterFreeRegionList::verify_region_extra(HeapRegion* hr) {
// We should reset the RSet for parallel iteration before we add it
// to the master free list so that it is ready when the region is
// re-allocated.
if (!hr->rem_set()->verify_ready_for_par_iteration()) {
return "the region's RSet should be ready for parallel iteration";
}
return FreeRegionList::verify_region_extra(hr);
}
bool MasterFreeRegionList::check_mt_safety() { bool MasterFreeRegionList::check_mt_safety() {
// Master Free List MT safety protocol: // Master Free List MT safety protocol:
// (a) If we're at a safepoint, operations on the master free list // (a) If we're at a safepoint, operations on the master free list
......
/* /*
* copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -44,6 +44,7 @@ public: ...@@ -44,6 +44,7 @@ public:
class MasterFreeRegionList : public FreeRegionList { class MasterFreeRegionList : public FreeRegionList {
protected: protected:
virtual const char* verify_region_extra(HeapRegion* hr);
virtual bool check_mt_safety(); virtual bool check_mt_safety();
public: public:
......
...@@ -481,7 +481,8 @@ size_t SparsePRT::mem_size() const { ...@@ -481,7 +481,8 @@ size_t SparsePRT::mem_size() const {
bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) { bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) {
#if SPARSE_PRT_VERBOSE #if SPARSE_PRT_VERBOSE
gclog_or_tty->print_cr(" Adding card %d from region %d to region %d sparse.", gclog_or_tty->print_cr(" Adding card %d from region %d to region "
SIZE_FORMAT" sparse.",
card_index, region_id, _hr->hrs_index()); card_index, region_id, _hr->hrs_index());
#endif #endif
if (_next->occupied_entries() * 2 > _next->capacity()) { if (_next->occupied_entries() * 2 > _next->capacity()) {
...@@ -533,7 +534,7 @@ void SparsePRT::expand() { ...@@ -533,7 +534,7 @@ void SparsePRT::expand() {
_next = new RSHashTable(last->capacity() * 2); _next = new RSHashTable(last->capacity() * 2);
#if SPARSE_PRT_VERBOSE #if SPARSE_PRT_VERBOSE
gclog_or_tty->print_cr(" Expanded sparse table for %d to %d.", gclog_or_tty->print_cr(" Expanded sparse table for "SIZE_FORMAT" to %d.",
_hr->hrs_index(), _next->capacity()); _hr->hrs_index(), _next->capacity());
#endif #endif
for (size_t i = 0; i < last->capacity(); i++) { for (size_t i = 0; i < last->capacity(); i++) {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册