提交 0b5d8ecc 编写于 作者: T tonyp

Merge

......@@ -377,3 +377,11 @@ void ConcurrentG1Refine::clear_and_record_card_counts() {
_g1h->g1_policy()->record_cc_clear_time(elapsed * 1000.0);
#endif
}
void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const {
for (int i = 0; i < _n_threads; ++i) {
_threads[i]->print_on(st);
st->cr();
}
}
......@@ -179,4 +179,6 @@ class ConcurrentG1Refine: public CHeapObj {
void clear_and_record_card_counts();
static size_t thread_num();
void print_worker_threads_on(outputStream* st) const;
};
......@@ -204,8 +204,12 @@ void ConcurrentG1RefineThread::stop() {
if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-stop");
}
void ConcurrentG1RefineThread::print() {
gclog_or_tty->print("\"Concurrent G1 Refinement Thread\" ");
Thread::print();
gclog_or_tty->cr();
void ConcurrentG1RefineThread::print() const {
print_on(tty);
}
void ConcurrentG1RefineThread::print_on(outputStream* st) const {
st->print("\"G1 Concurrent Refinement Thread#%d\" ", _worker_id);
Thread::print_on(st);
st->cr();
}
......@@ -77,7 +77,8 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread {
int worker_id_offset, int worker_id);
// Printing
void print();
void print() const;
void print_on(outputStream* st) const;
// Total virtual time so far.
double vtime_accum() { return _vtime_accum; }
......
......@@ -295,12 +295,6 @@ do { \
} while (0)
#endif // _MARKING_STATS_
// Some extra guarantees that I like to also enable in optimised mode
// when debugging. If you want to enable them, comment out the assert
// macro and uncomment out the guaratee macro
// #define tmp_guarantee_CM(expr, str) guarantee(expr, str)
#define tmp_guarantee_CM(expr, str) assert(expr, str)
typedef enum {
no_verbose = 0, // verbose turned off
stats_verbose, // only prints stats at the end of marking
......@@ -485,15 +479,15 @@ protected:
// Returns the task with the given id
CMTask* task(int id) {
guarantee( 0 <= id && id < (int) _active_tasks, "task id not within "
"active bounds" );
assert(0 <= id && id < (int) _active_tasks,
"task id not within active bounds");
return _tasks[id];
}
// Returns the task queue with the given id
CMTaskQueue* task_queue(int id) {
guarantee( 0 <= id && id < (int) _active_tasks, "task queue id not within "
"active bounds" );
assert(0 <= id && id < (int) _active_tasks,
"task queue id not within active bounds");
return (CMTaskQueue*) _task_queues->queue(id);
}
......@@ -723,6 +717,8 @@ public:
void print_summary_info();
void print_worker_threads_on(outputStream* st) const;
// The following indicate whether a given verbose level has been
// set. Notice that anything above stats is conditional to
// _MARKING_VERBOSE_ having been set to 1
......@@ -959,8 +955,7 @@ public:
// It scans an object and visits its children.
void scan_object(oop obj) {
tmp_guarantee_CM( _nextMarkBitMap->isMarked((HeapWord*) obj),
"invariant" );
assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant");
if (_cm->verbose_high())
gclog_or_tty->print_cr("[%d] we're scanning object "PTR_FORMAT,
......@@ -999,14 +994,13 @@ public:
// moves the local finger to a new location
inline void move_finger_to(HeapWord* new_finger) {
tmp_guarantee_CM( new_finger >= _finger && new_finger < _region_limit,
"invariant" );
assert(new_finger >= _finger && new_finger < _region_limit, "invariant");
_finger = new_finger;
}
// moves the region finger to a new location
inline void move_region_finger_to(HeapWord* new_finger) {
tmp_guarantee_CM( new_finger < _cm->finger(), "invariant" );
assert(new_finger < _cm->finger(), "invariant");
_region_finger = new_finger;
}
......
......@@ -286,10 +286,14 @@ void ConcurrentMarkThread::stop() {
}
}
void ConcurrentMarkThread::print() {
gclog_or_tty->print("\"Concurrent Mark GC Thread\" ");
Thread::print();
gclog_or_tty->cr();
void ConcurrentMarkThread::print() const {
print_on(tty);
}
void ConcurrentMarkThread::print_on(outputStream* st) const {
st->print("\"G1 Main Concurrent Mark GC Thread\" ");
Thread::print_on(st);
st->cr();
}
void ConcurrentMarkThread::sleepBeforeNextCycle() {
......
......@@ -57,7 +57,8 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
static SurrogateLockerThread* slt() { return _slt; }
// Printing
void print();
void print_on(outputStream* st) const;
void print() const;
// Total virtual time so far.
double vtime_accum();
......
......@@ -157,10 +157,14 @@ void ConcurrentZFThread::stop() {
}
}
void ConcurrentZFThread::print() {
gclog_or_tty->print("\"Concurrent ZF Thread\" ");
Thread::print();
gclog_or_tty->cr();
void ConcurrentZFThread::print() const {
print_on(tty);
}
void ConcurrentZFThread::print_on(outputStream* st) const {
st->print("\"G1 Concurrent Zero-Fill Thread\" ");
Thread::print_on(st);
st->cr();
}
......
......@@ -61,7 +61,8 @@ class ConcurrentZFThread: public ConcurrentGCThread {
virtual void run();
// Printing
void print();
void print_on(outputStream* st) const;
void print() const;
// Waits until "r" has been zero-filled. Requires caller to hold the
// ZF_mon.
......
......@@ -2210,40 +2210,58 @@ private:
bool _allow_dirty;
bool _par;
bool _use_prev_marking;
bool _failures;
public:
// use_prev_marking == true -> use "prev" marking information,
// use_prev_marking == false -> use "next" marking information
VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking)
: _allow_dirty(allow_dirty),
_par(par),
_use_prev_marking(use_prev_marking) {}
_use_prev_marking(use_prev_marking),
_failures(false) {}
bool failures() {
return _failures;
}
bool doHeapRegion(HeapRegion* r) {
guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue,
"Should be unclaimed at verify points.");
if (!r->continuesHumongous()) {
VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking);
r->verify(_allow_dirty, _use_prev_marking);
r->object_iterate(&not_dead_yet_cl);
guarantee(r->max_live_bytes() >= not_dead_yet_cl.live_bytes(),
"More live objects than counted in last complete marking.");
bool failures = false;
r->verify(_allow_dirty, _use_prev_marking, &failures);
if (failures) {
_failures = true;
} else {
VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking);
r->object_iterate(&not_dead_yet_cl);
if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) {
gclog_or_tty->print_cr("["PTR_FORMAT","PTR_FORMAT"] "
"max_live_bytes "SIZE_FORMAT" "
"< calculated "SIZE_FORMAT,
r->bottom(), r->end(),
r->max_live_bytes(),
not_dead_yet_cl.live_bytes());
_failures = true;
}
}
}
return false;
return false; // stop the region iteration if we hit a failure
}
};
class VerifyRootsClosure: public OopsInGenClosure {
private:
G1CollectedHeap* _g1h;
bool _failures;
bool _use_prev_marking;
bool _failures;
public:
// use_prev_marking == true -> use "prev" marking information,
// use_prev_marking == false -> use "next" marking information
VerifyRootsClosure(bool use_prev_marking) :
_g1h(G1CollectedHeap::heap()),
_failures(false),
_use_prev_marking(use_prev_marking) { }
_use_prev_marking(use_prev_marking),
_failures(false) { }
bool failures() { return _failures; }
......@@ -2253,7 +2271,7 @@ public:
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) {
gclog_or_tty->print_cr("Root location "PTR_FORMAT" "
"points to dead obj "PTR_FORMAT, p, (void*) obj);
"points to dead obj "PTR_FORMAT, p, (void*) obj);
obj->print_on(gclog_or_tty);
_failures = true;
}
......@@ -2271,6 +2289,7 @@ private:
G1CollectedHeap* _g1h;
bool _allow_dirty;
bool _use_prev_marking;
bool _failures;
public:
// use_prev_marking == true -> use "prev" marking information,
......@@ -2280,13 +2299,21 @@ public:
AbstractGangTask("Parallel verify task"),
_g1h(g1h),
_allow_dirty(allow_dirty),
_use_prev_marking(use_prev_marking) { }
_use_prev_marking(use_prev_marking),
_failures(false) { }
bool failures() {
return _failures;
}
void work(int worker_i) {
HandleMark hm;
VerifyRegionClosure blk(_allow_dirty, true, _use_prev_marking);
_g1h->heap_region_par_iterate_chunked(&blk, worker_i,
HeapRegion::ParVerifyClaimValue);
if (blk.failures()) {
_failures = true;
}
}
};
......@@ -2307,6 +2334,7 @@ void G1CollectedHeap::verify(bool allow_dirty,
&rootsCl,
&blobsCl,
&rootsCl);
bool failures = rootsCl.failures();
rem_set()->invalidate(perm_gen()->used_region(), false);
if (!silent) { gclog_or_tty->print("heapRegions "); }
if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
......@@ -2318,6 +2346,9 @@ void G1CollectedHeap::verify(bool allow_dirty,
set_par_threads(n_workers);
workers()->run_task(&task);
set_par_threads(0);
if (task.failures()) {
failures = true;
}
assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue),
"sanity check");
......@@ -2329,10 +2360,23 @@ void G1CollectedHeap::verify(bool allow_dirty,
} else {
VerifyRegionClosure blk(allow_dirty, false, use_prev_marking);
_hrs->iterate(&blk);
if (blk.failures()) {
failures = true;
}
}
if (!silent) gclog_or_tty->print("remset ");
rem_set()->verify();
guarantee(!rootsCl.failures(), "should not have had failures");
if (failures) {
gclog_or_tty->print_cr("Heap:");
print_on(gclog_or_tty, true /* extended */);
gclog_or_tty->print_cr("");
if (VerifyDuringGC && G1VerifyConcMarkPrintReachable) {
concurrent_mark()->print_prev_bitmap_reachable();
}
gclog_or_tty->flush();
}
guarantee(!failures, "there should not have been any failures");
} else {
if (!silent) gclog_or_tty->print("(SKIPPING roots, heapRegions, remset) ");
}
......@@ -2374,6 +2418,7 @@ void G1CollectedHeap::print_on(outputStream* st, bool extended) const {
st->cr();
perm()->as_gen()->print_on(st);
if (extended) {
st->cr();
print_on_extended(st);
}
}
......@@ -2383,27 +2428,18 @@ void G1CollectedHeap::print_on_extended(outputStream* st) const {
_hrs->iterate(&blk);
}
class PrintOnThreadsClosure : public ThreadClosure {
outputStream* _st;
public:
PrintOnThreadsClosure(outputStream* st) : _st(st) { }
virtual void do_thread(Thread *t) {
t->print_on(_st);
}
};
void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
if (ParallelGCThreads > 0) {
workers()->print_worker_threads();
workers()->print_worker_threads_on(st);
}
st->print("\"G1 concurrent mark GC Thread\" ");
_cmThread->print();
st->cr();
st->print("\"G1 concurrent refinement GC Threads\" ");
PrintOnThreadsClosure p(st);
_cg1r->threads_do(&p);
_cmThread->print_on(st);
st->cr();
st->print("\"G1 zero-fill GC Thread\" ");
_cm->print_worker_threads_on(st);
_cg1r->print_worker_threads_on(st);
_czft->print_on(st);
st->cr();
}
......
......@@ -722,12 +722,13 @@ void HeapRegion::print_on(outputStream* st) const {
st->print(" F");
else
st->print(" ");
st->print(" %d", _gc_time_stamp);
st->print(" %5d", _gc_time_stamp);
G1OffsetTableContigSpace::print_on(st);
}
void HeapRegion::verify(bool allow_dirty) const {
verify(allow_dirty, /* use_prev_marking */ true);
bool dummy = false;
verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy);
}
#define OBJ_SAMPLE_INTERVAL 0
......@@ -736,8 +737,11 @@ void HeapRegion::verify(bool allow_dirty) const {
// This really ought to be commoned up into OffsetTableContigSpace somehow.
// We would need a mechanism to make that code skip dead objects.
void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
void HeapRegion::verify(bool allow_dirty,
bool use_prev_marking,
bool* failures) const {
G1CollectedHeap* g1 = G1CollectedHeap::heap();
*failures = false;
HeapWord* p = bottom();
HeapWord* prev_p = NULL;
int objs = 0;
......@@ -746,8 +750,14 @@ void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
while (p < top()) {
size_t size = oop(p)->size();
if (blocks == BLOCK_SAMPLE_INTERVAL) {
guarantee(p == block_start_const(p + (size/2)),
"check offset computation");
HeapWord* res = block_start_const(p + (size/2));
if (p != res) {
gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and "
SIZE_FORMAT" returned "PTR_FORMAT,
p, size, res);
*failures = true;
return;
}
blocks = 0;
} else {
blocks++;
......@@ -755,11 +765,34 @@ void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
if (objs == OBJ_SAMPLE_INTERVAL) {
oop obj = oop(p);
if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
obj->verify();
vl_cl.set_containing_obj(obj);
obj->oop_iterate(&vl_cl);
if (G1MaxVerifyFailures >= 0
&& vl_cl.n_failures() >= G1MaxVerifyFailures) break;
if (obj->is_oop()) {
klassOop klass = obj->klass();
if (!klass->is_perm()) {
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
"not in perm", klass, obj);
*failures = true;
return;
} else if (!klass->is_klass()) {
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
"not a klass", klass, obj);
*failures = true;
return;
} else {
vl_cl.set_containing_obj(obj);
obj->oop_iterate(&vl_cl);
if (vl_cl.failures()) {
*failures = true;
}
if (G1MaxVerifyFailures >= 0 &&
vl_cl.n_failures() >= G1MaxVerifyFailures) {
return;
}
}
} else {
gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
*failures = true;
return;
}
}
objs = 0;
} else {
......@@ -771,21 +804,22 @@ void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
HeapWord* rend = end();
HeapWord* rtop = top();
if (rtop < rend) {
guarantee(block_start_const(rtop + (rend - rtop) / 2) == rtop,
"check offset computation");
}
if (vl_cl.failures()) {
gclog_or_tty->print_cr("Heap:");
G1CollectedHeap::heap()->print_on(gclog_or_tty, true /* extended */);
gclog_or_tty->print_cr("");
HeapWord* res = block_start_const(rtop + (rend - rtop) / 2);
if (res != rtop) {
gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and "
PTR_FORMAT" returned "PTR_FORMAT,
rtop, rend, res);
*failures = true;
return;
}
}
if (VerifyDuringGC &&
G1VerifyConcMarkPrintReachable &&
vl_cl.failures()) {
g1->concurrent_mark()->print_prev_bitmap_reachable();
if (p != top()) {
gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
"does not match top "PTR_FORMAT, p, top());
*failures = true;
return;
}
guarantee(!vl_cl.failures(), "region verification failed");
guarantee(p == top(), "end of last object must match end of space");
}
// G1OffsetTableContigSpace code; copied from space.cpp. Hope this can go
......
......@@ -569,13 +569,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
// ever evacuated into this region. If we evacuate, allocate, and
// then evacuate we are in deep doodoo.
void note_end_of_copying() {
assert(top() >= _next_top_at_mark_start,
"Increase only");
// Survivor regions will be scanned on the start of concurrent
// marking.
if (!is_survivor()) {
_next_top_at_mark_start = top();
}
assert(top() >= _next_top_at_mark_start, "Increase only");
_next_top_at_mark_start = top();
}
// Returns "false" iff no object in the region was allocated when the
......@@ -798,7 +793,7 @@ class HeapRegion: public G1OffsetTableContigSpace {
// use_prev_marking == true. Currently, there is only one case where
// this is called with use_prev_marking == false, which is to verify
// the "next" marking information at the end of remark.
void verify(bool allow_dirty, bool use_prev_marking) const;
void verify(bool allow_dirty, bool use_prev_marking, bool *failures) const;
// Override; it uses the "prev" marking information
virtual void verify(bool allow_dirty) const;
......
......@@ -207,7 +207,7 @@ bool GenericTaskQueue<E>::push_slow(E t, uint dirty_n_elems) {
// Actually means 0, so do the push.
uint localBot = _bottom;
_elems[localBot] = t;
_bottom = increment_index(localBot);
OrderAccess::release_store(&_bottom, increment_index(localBot));
return true;
}
return false;
......@@ -465,19 +465,7 @@ public:
#endif
};
#define SIMPLE_STACK 0
template<class E> inline bool GenericTaskQueue<E>::push(E t) {
#if SIMPLE_STACK
uint localBot = _bottom;
if (_bottom < max_elems()) {
_elems[localBot] = t;
_bottom = localBot + 1;
return true;
} else {
return false;
}
#else
uint localBot = _bottom;
assert((localBot >= 0) && (localBot < N), "_bottom out of range.");
idx_t top = _age.top();
......@@ -485,23 +473,14 @@ template<class E> inline bool GenericTaskQueue<E>::push(E t) {
assert((dirty_n_elems >= 0) && (dirty_n_elems < N), "n_elems out of range.");
if (dirty_n_elems < max_elems()) {
_elems[localBot] = t;
_bottom = increment_index(localBot);
OrderAccess::release_store(&_bottom, increment_index(localBot));
return true;
} else {
return push_slow(t, dirty_n_elems);
}
#endif
}
template<class E> inline bool GenericTaskQueue<E>::pop_local(E& t) {
#if SIMPLE_STACK
uint localBot = _bottom;
assert(localBot > 0, "precondition.");
localBot--;
t = _elems[localBot];
_bottom = localBot;
return true;
#else
uint localBot = _bottom;
// This value cannot be N-1. That can only occur as a result of
// the assignment to bottom in this method. If it does, this method
......@@ -529,7 +508,6 @@ template<class E> inline bool GenericTaskQueue<E>::pop_local(E& t) {
// path.
return pop_local_slow(localBot, _age.get());
}
#endif
}
typedef oop Task;
......
......@@ -3,7 +3,7 @@
@bug 6845368
@summary ensure gc updates references > 64K bytes from the start of the obj
@author John Coomes
@run main/othervm -Xmx64m bigobj
@run main/othervm/timeout=720 -Xmx64m bigobj
*/
// Allocate an object with a block of reference fields that starts more
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册