提交 eca458f8 编写于 作者: J jmasa

6798898: CMS: bugs related to class unloading

Summary: Override should_remember_klasses() and remember_klass() as needed.
Reviewed-by: ysr, jcoomes
上级 a6d1e5a0
...@@ -92,17 +92,50 @@ class MarkRefsIntoVerifyClosure: public OopsInGenClosure { ...@@ -92,17 +92,50 @@ class MarkRefsIntoVerifyClosure: public OopsInGenClosure {
} }
}; };
// KlassRememberingOopClosure is used when marking of the permanent generation
// is being done. It adds fields to support revisiting of klasses
// for class unloading. _should_remember_klasses should be set to
// indicate if klasses should be remembered. Currently that is whenever
// CMS class unloading is turned on. The _revisit_stack is used
// to save the klasses for later processing.
class KlassRememberingOopClosure : public OopClosure {
protected:
CMSCollector* _collector;
CMSMarkStack* _revisit_stack;
bool const _should_remember_klasses;
public:
void check_remember_klasses() const PRODUCT_RETURN;
virtual const bool should_remember_klasses() const {
check_remember_klasses();
return _should_remember_klasses;
}
virtual void remember_klass(Klass* k);
KlassRememberingOopClosure(CMSCollector* collector,
ReferenceProcessor* rp,
CMSMarkStack* revisit_stack);
};
// Similar to KlassRememberingOopClosure for use when multiple
// GC threads will execute the closure.
class Par_KlassRememberingOopClosure : public KlassRememberingOopClosure {
public:
Par_KlassRememberingOopClosure(CMSCollector* collector,
ReferenceProcessor* rp,
CMSMarkStack* revisit_stack):
KlassRememberingOopClosure(collector, rp, revisit_stack) {}
virtual void remember_klass(Klass* k);
};
// The non-parallel version (the parallel version appears further below). // The non-parallel version (the parallel version appears further below).
class PushAndMarkClosure: public OopClosure { class PushAndMarkClosure: public KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
MemRegion _span; MemRegion _span;
CMSBitMap* _bit_map; CMSBitMap* _bit_map;
CMSBitMap* _mod_union_table; CMSBitMap* _mod_union_table;
CMSMarkStack* _mark_stack; CMSMarkStack* _mark_stack;
CMSMarkStack* _revisit_stack;
bool _concurrent_precleaning; bool _concurrent_precleaning;
bool const _should_remember_klasses;
protected: protected:
DO_OOP_WORK_DEFN DO_OOP_WORK_DEFN
public: public:
...@@ -122,10 +155,6 @@ class PushAndMarkClosure: public OopClosure { ...@@ -122,10 +155,6 @@ class PushAndMarkClosure: public OopClosure {
Prefetch::style prefetch_style() { Prefetch::style prefetch_style() {
return Prefetch::do_read; return Prefetch::do_read;
} }
virtual const bool should_remember_klasses() const {
return _should_remember_klasses;
}
virtual void remember_klass(Klass* k);
}; };
// In the parallel case, the revisit stack, the bit map and the // In the parallel case, the revisit stack, the bit map and the
...@@ -134,14 +163,11 @@ class PushAndMarkClosure: public OopClosure { ...@@ -134,14 +163,11 @@ class PushAndMarkClosure: public OopClosure {
// synchronization (for instance, via CAS). The marking stack // synchronization (for instance, via CAS). The marking stack
// used in the non-parallel case above is here replaced with // used in the non-parallel case above is here replaced with
// an OopTaskQueue structure to allow efficient work stealing. // an OopTaskQueue structure to allow efficient work stealing.
class Par_PushAndMarkClosure: public OopClosure { class Par_PushAndMarkClosure: public Par_KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
MemRegion _span; MemRegion _span;
CMSBitMap* _bit_map; CMSBitMap* _bit_map;
OopTaskQueue* _work_queue; OopTaskQueue* _work_queue;
CMSMarkStack* _revisit_stack;
bool const _should_remember_klasses;
protected: protected:
DO_OOP_WORK_DEFN DO_OOP_WORK_DEFN
public: public:
...@@ -159,10 +185,6 @@ class Par_PushAndMarkClosure: public OopClosure { ...@@ -159,10 +185,6 @@ class Par_PushAndMarkClosure: public OopClosure {
Prefetch::style prefetch_style() { Prefetch::style prefetch_style() {
return Prefetch::do_read; return Prefetch::do_read;
} }
virtual const bool should_remember_klasses() const {
return _should_remember_klasses;
}
virtual void remember_klass(Klass* k);
}; };
// The non-parallel version (the parallel version appears further below). // The non-parallel version (the parallel version appears further below).
...@@ -201,6 +223,12 @@ class MarkRefsIntoAndScanClosure: public OopsInGenClosure { ...@@ -201,6 +223,12 @@ class MarkRefsIntoAndScanClosure: public OopsInGenClosure {
void set_freelistLock(Mutex* m) { void set_freelistLock(Mutex* m) {
_freelistLock = m; _freelistLock = m;
} }
virtual const bool should_remember_klasses() const {
return _pushAndMarkClosure.should_remember_klasses();
}
virtual void remember_klass(Klass* k) {
_pushAndMarkClosure.remember_klass(k);
}
private: private:
inline void do_yield_check(); inline void do_yield_check();
...@@ -234,6 +262,16 @@ class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure { ...@@ -234,6 +262,16 @@ class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure {
inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
bool do_header() { return true; } bool do_header() { return true; }
virtual const bool do_nmethods() const { return true; } virtual const bool do_nmethods() const { return true; }
// When ScanMarkedObjectsAgainClosure is used,
// it passes [Par_]MarkRefsIntoAndScanClosure to oop_oop_iterate(),
// and this delegation is used.
virtual const bool should_remember_klasses() const {
return _par_pushAndMarkClosure.should_remember_klasses();
}
// See comment on should_remember_klasses() above.
virtual void remember_klass(Klass* k) {
_par_pushAndMarkClosure.remember_klass(k);
}
Prefetch::style prefetch_style() { Prefetch::style prefetch_style() {
return Prefetch::do_read; return Prefetch::do_read;
} }
...@@ -243,17 +281,14 @@ class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure { ...@@ -243,17 +281,14 @@ class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure {
// This closure is used during the concurrent marking phase // This closure is used during the concurrent marking phase
// following the first checkpoint. Its use is buried in // following the first checkpoint. Its use is buried in
// the closure MarkFromRootsClosure. // the closure MarkFromRootsClosure.
class PushOrMarkClosure: public OopClosure { class PushOrMarkClosure: public KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
MemRegion _span; MemRegion _span;
CMSBitMap* _bitMap; CMSBitMap* _bitMap;
CMSMarkStack* _markStack; CMSMarkStack* _markStack;
CMSMarkStack* _revisitStack;
HeapWord* const _finger; HeapWord* const _finger;
MarkFromRootsClosure* const MarkFromRootsClosure* const
_parent; _parent;
bool const _should_remember_klasses;
protected: protected:
DO_OOP_WORK_DEFN DO_OOP_WORK_DEFN
public: public:
...@@ -268,10 +303,6 @@ class PushOrMarkClosure: public OopClosure { ...@@ -268,10 +303,6 @@ class PushOrMarkClosure: public OopClosure {
virtual void do_oop(narrowOop* p); virtual void do_oop(narrowOop* p);
inline void do_oop_nv(oop* p) { PushOrMarkClosure::do_oop_work(p); } inline void do_oop_nv(oop* p) { PushOrMarkClosure::do_oop_work(p); }
inline void do_oop_nv(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); } inline void do_oop_nv(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); }
virtual const bool should_remember_klasses() const {
return _should_remember_klasses;
}
virtual void remember_klass(Klass* k);
// Deal with a stack overflow condition // Deal with a stack overflow condition
void handle_stack_overflow(HeapWord* lost); void handle_stack_overflow(HeapWord* lost);
private: private:
...@@ -282,20 +313,17 @@ class PushOrMarkClosure: public OopClosure { ...@@ -282,20 +313,17 @@ class PushOrMarkClosure: public OopClosure {
// This closure is used during the concurrent marking phase // This closure is used during the concurrent marking phase
// following the first checkpoint. Its use is buried in // following the first checkpoint. Its use is buried in
// the closure Par_MarkFromRootsClosure. // the closure Par_MarkFromRootsClosure.
class Par_PushOrMarkClosure: public OopClosure { class Par_PushOrMarkClosure: public Par_KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
MemRegion _whole_span; MemRegion _whole_span;
MemRegion _span; // local chunk MemRegion _span; // local chunk
CMSBitMap* _bit_map; CMSBitMap* _bit_map;
OopTaskQueue* _work_queue; OopTaskQueue* _work_queue;
CMSMarkStack* _overflow_stack; CMSMarkStack* _overflow_stack;
CMSMarkStack* _revisit_stack;
HeapWord* const _finger; HeapWord* const _finger;
HeapWord** const _global_finger_addr; HeapWord** const _global_finger_addr;
Par_MarkFromRootsClosure* const Par_MarkFromRootsClosure* const
_parent; _parent;
bool const _should_remember_klasses;
protected: protected:
DO_OOP_WORK_DEFN DO_OOP_WORK_DEFN
public: public:
...@@ -312,10 +340,6 @@ class Par_PushOrMarkClosure: public OopClosure { ...@@ -312,10 +340,6 @@ class Par_PushOrMarkClosure: public OopClosure {
virtual void do_oop(narrowOop* p); virtual void do_oop(narrowOop* p);
inline void do_oop_nv(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); } inline void do_oop_nv(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); }
inline void do_oop_nv(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); } inline void do_oop_nv(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); }
virtual const bool should_remember_klasses() const {
return _should_remember_klasses;
}
virtual void remember_klass(Klass* k);
// Deal with a stack overflow condition // Deal with a stack overflow condition
void handle_stack_overflow(HeapWord* lost); void handle_stack_overflow(HeapWord* lost);
private: private:
...@@ -328,9 +352,8 @@ class Par_PushOrMarkClosure: public OopClosure { ...@@ -328,9 +352,8 @@ class Par_PushOrMarkClosure: public OopClosure {
// processing phase of the CMS final checkpoint step, as // processing phase of the CMS final checkpoint step, as
// well as during the concurrent precleaning of the discovered // well as during the concurrent precleaning of the discovered
// reference lists. // reference lists.
class CMSKeepAliveClosure: public OopClosure { class CMSKeepAliveClosure: public KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
const MemRegion _span; const MemRegion _span;
CMSMarkStack* _mark_stack; CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map; CMSBitMap* _bit_map;
...@@ -340,14 +363,7 @@ class CMSKeepAliveClosure: public OopClosure { ...@@ -340,14 +363,7 @@ class CMSKeepAliveClosure: public OopClosure {
public: public:
CMSKeepAliveClosure(CMSCollector* collector, MemRegion span, CMSKeepAliveClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack, CMSBitMap* bit_map, CMSMarkStack* mark_stack,
bool cpc): CMSMarkStack* revisit_stack, bool cpc);
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
_concurrent_precleaning(cpc) {
assert(!_span.is_empty(), "Empty span could spell trouble");
}
bool concurrent_precleaning() const { return _concurrent_precleaning; } bool concurrent_precleaning() const { return _concurrent_precleaning; }
virtual void do_oop(oop* p); virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p); virtual void do_oop(narrowOop* p);
...@@ -355,9 +371,8 @@ class CMSKeepAliveClosure: public OopClosure { ...@@ -355,9 +371,8 @@ class CMSKeepAliveClosure: public OopClosure {
inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); } inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); }
}; };
class CMSInnerParMarkAndPushClosure: public OopClosure { class CMSInnerParMarkAndPushClosure: public Par_KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
MemRegion _span; MemRegion _span;
OopTaskQueue* _work_queue; OopTaskQueue* _work_queue;
CMSBitMap* _bit_map; CMSBitMap* _bit_map;
...@@ -366,11 +381,8 @@ class CMSInnerParMarkAndPushClosure: public OopClosure { ...@@ -366,11 +381,8 @@ class CMSInnerParMarkAndPushClosure: public OopClosure {
public: public:
CMSInnerParMarkAndPushClosure(CMSCollector* collector, CMSInnerParMarkAndPushClosure(CMSCollector* collector,
MemRegion span, CMSBitMap* bit_map, MemRegion span, CMSBitMap* bit_map,
OopTaskQueue* work_queue): CMSMarkStack* revisit_stack,
_collector(collector), OopTaskQueue* work_queue);
_span(span),
_bit_map(bit_map),
_work_queue(work_queue) { }
virtual void do_oop(oop* p); virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p); virtual void do_oop(narrowOop* p);
inline void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } inline void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); }
...@@ -380,9 +392,8 @@ class CMSInnerParMarkAndPushClosure: public OopClosure { ...@@ -380,9 +392,8 @@ class CMSInnerParMarkAndPushClosure: public OopClosure {
// A parallel (MT) version of the above, used when // A parallel (MT) version of the above, used when
// reference processing is parallel; the only difference // reference processing is parallel; the only difference
// is in the do_oop method. // is in the do_oop method.
class CMSParKeepAliveClosure: public OopClosure { class CMSParKeepAliveClosure: public Par_KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
MemRegion _span; MemRegion _span;
OopTaskQueue* _work_queue; OopTaskQueue* _work_queue;
CMSBitMap* _bit_map; CMSBitMap* _bit_map;
...@@ -394,7 +405,8 @@ class CMSParKeepAliveClosure: public OopClosure { ...@@ -394,7 +405,8 @@ class CMSParKeepAliveClosure: public OopClosure {
DO_OOP_WORK_DEFN DO_OOP_WORK_DEFN
public: public:
CMSParKeepAliveClosure(CMSCollector* collector, MemRegion span, CMSParKeepAliveClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, OopTaskQueue* work_queue); CMSBitMap* bit_map, CMSMarkStack* revisit_stack,
OopTaskQueue* work_queue);
virtual void do_oop(oop* p); virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p); virtual void do_oop(narrowOop* p);
inline void do_oop_nv(oop* p) { CMSParKeepAliveClosure::do_oop_work(p); } inline void do_oop_nv(oop* p) { CMSParKeepAliveClosure::do_oop_work(p); }
......
...@@ -37,16 +37,25 @@ inline void Par_MarkRefsIntoAndScanClosure::trim_queue(uint max) { ...@@ -37,16 +37,25 @@ inline void Par_MarkRefsIntoAndScanClosure::trim_queue(uint max) {
} }
} }
inline void PushOrMarkClosure::remember_klass(Klass* k) { #ifndef PRODUCT
if (!_revisitStack->push(oop(k))) { void KlassRememberingOopClosure::check_remember_klasses() const {
assert(_should_remember_klasses == must_remember_klasses(),
"Should remember klasses in this context.");
}
#endif
void KlassRememberingOopClosure::remember_klass(Klass* k) {
if (!_revisit_stack->push(oop(k))) {
fatal("Revisit stack overflow in PushOrMarkClosure"); fatal("Revisit stack overflow in PushOrMarkClosure");
} }
check_remember_klasses();
} }
inline void Par_PushOrMarkClosure::remember_klass(Klass* k) { void Par_KlassRememberingOopClosure::remember_klass(Klass* k) {
if (!_revisit_stack->par_push(oop(k))) { if (!_revisit_stack->par_push(oop(k))) {
fatal("Revisit stack overflow in PushOrMarkClosure"); fatal("Revisit stack overflow in PushOrMarkClosure");
} }
check_remember_klasses();
} }
inline void PushOrMarkClosure::do_yield_check() { inline void PushOrMarkClosure::do_yield_check() {
......
...@@ -3499,6 +3499,7 @@ void CMSCollector::checkpointRootsInitialWork(bool asynch) { ...@@ -3499,6 +3499,7 @@ void CMSCollector::checkpointRootsInitialWork(bool asynch) {
ref_processor()->set_enqueuing_is_done(false); ref_processor()->set_enqueuing_is_done(false);
{ {
// This is not needed. DEBUG_ONLY(RememberKlassesChecker imx(true);)
COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;) COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
gch->gen_process_strong_roots(_cmsGen->level(), gch->gen_process_strong_roots(_cmsGen->level(),
...@@ -3623,6 +3624,8 @@ bool CMSCollector::markFromRootsWork(bool asynch) { ...@@ -3623,6 +3624,8 @@ bool CMSCollector::markFromRootsWork(bool asynch) {
verify_overflow_empty(); verify_overflow_empty();
assert(_revisitStack.isEmpty(), "tabula rasa"); assert(_revisitStack.isEmpty(), "tabula rasa");
DEBUG_ONLY(RememberKlassesChecker cmx(CMSClassUnloadingEnabled);)
bool result = false; bool result = false;
if (CMSConcurrentMTEnabled && ParallelCMSThreads > 0) { if (CMSConcurrentMTEnabled && ParallelCMSThreads > 0) {
result = do_marking_mt(asynch); result = do_marking_mt(asynch);
...@@ -3958,24 +3961,24 @@ void CMSConcMarkingTask::do_scan_and_mark(int i, CompactibleFreeListSpace* sp) { ...@@ -3958,24 +3961,24 @@ void CMSConcMarkingTask::do_scan_and_mark(int i, CompactibleFreeListSpace* sp) {
pst->all_tasks_completed(); pst->all_tasks_completed();
} }
class Par_ConcMarkingClosure: public OopClosure { class Par_ConcMarkingClosure: public Par_KlassRememberingOopClosure {
private: private:
CMSCollector* _collector;
MemRegion _span; MemRegion _span;
CMSBitMap* _bit_map; CMSBitMap* _bit_map;
CMSMarkStack* _overflow_stack; CMSMarkStack* _overflow_stack;
CMSMarkStack* _revisit_stack; // XXXXXX Check proper use
OopTaskQueue* _work_queue; OopTaskQueue* _work_queue;
protected: protected:
DO_OOP_WORK_DEFN DO_OOP_WORK_DEFN
public: public:
Par_ConcMarkingClosure(CMSCollector* collector, OopTaskQueue* work_queue, Par_ConcMarkingClosure(CMSCollector* collector, OopTaskQueue* work_queue,
CMSBitMap* bit_map, CMSMarkStack* overflow_stack): CMSBitMap* bit_map, CMSMarkStack* overflow_stack,
_collector(collector), CMSMarkStack* revisit_stack):
Par_KlassRememberingOopClosure(collector, NULL, revisit_stack),
_span(_collector->_span), _span(_collector->_span),
_work_queue(work_queue), _work_queue(work_queue),
_bit_map(bit_map), _bit_map(bit_map),
_overflow_stack(overflow_stack) { } // need to initialize revisit stack etc. _overflow_stack(overflow_stack)
{ }
virtual void do_oop(oop* p); virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p); virtual void do_oop(narrowOop* p);
void trim_queue(size_t max); void trim_queue(size_t max);
...@@ -4063,8 +4066,9 @@ void CMSConcMarkingTask::do_work_steal(int i) { ...@@ -4063,8 +4066,9 @@ void CMSConcMarkingTask::do_work_steal(int i) {
oop obj_to_scan; oop obj_to_scan;
CMSBitMap* bm = &(_collector->_markBitMap); CMSBitMap* bm = &(_collector->_markBitMap);
CMSMarkStack* ovflw = &(_collector->_markStack); CMSMarkStack* ovflw = &(_collector->_markStack);
CMSMarkStack* revisit = &(_collector->_revisitStack);
int* seed = _collector->hash_seed(i); int* seed = _collector->hash_seed(i);
Par_ConcMarkingClosure cl(_collector, work_q, bm, ovflw); Par_ConcMarkingClosure cl(_collector, work_q, bm, ovflw, revisit);
while (true) { while (true) {
cl.trim_queue(0); cl.trim_queue(0);
assert(work_q->size() == 0, "Should have been emptied above"); assert(work_q->size() == 0, "Should have been emptied above");
...@@ -4089,6 +4093,7 @@ void CMSConcMarkingTask::coordinator_yield() { ...@@ -4089,6 +4093,7 @@ void CMSConcMarkingTask::coordinator_yield() {
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"CMS thread should hold CMS token"); "CMS thread should hold CMS token");
DEBUG_ONLY(RememberKlassesChecker mux(false);)
// First give up the locks, then yield, then re-lock // First give up the locks, then yield, then re-lock
// We should probably use a constructor/destructor idiom to // We should probably use a constructor/destructor idiom to
// do this unlock/lock or modify the MutexUnlocker class to // do this unlock/lock or modify the MutexUnlocker class to
...@@ -4165,6 +4170,8 @@ bool CMSCollector::do_marking_mt(bool asynch) { ...@@ -4165,6 +4170,8 @@ bool CMSCollector::do_marking_mt(bool asynch) {
// multi-threaded marking phase. // multi-threaded marking phase.
ReferenceProcessorMTMutator mt(ref_processor(), num_workers > 1); ReferenceProcessorMTMutator mt(ref_processor(), num_workers > 1);
DEBUG_ONLY(RememberKlassesChecker cmx(CMSClassUnloadingEnabled);)
conc_workers()->start_task(&tsk); conc_workers()->start_task(&tsk);
while (tsk.yielded()) { while (tsk.yielded()) {
tsk.coordinator_yield(); tsk.coordinator_yield();
...@@ -4404,7 +4411,8 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) { ...@@ -4404,7 +4411,8 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
CMSPrecleanRefsYieldClosure yield_cl(this); CMSPrecleanRefsYieldClosure yield_cl(this);
assert(rp->span().equals(_span), "Spans should be equal"); assert(rp->span().equals(_span), "Spans should be equal");
CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap, CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap,
&_markStack, true /* preclean */); &_markStack, &_revisitStack,
true /* preclean */);
CMSDrainMarkingStackClosure complete_trace(this, CMSDrainMarkingStackClosure complete_trace(this,
_span, &_markBitMap, &_markStack, _span, &_markBitMap, &_markStack,
&keep_alive, true /* preclean */); &keep_alive, true /* preclean */);
...@@ -4424,6 +4432,7 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) { ...@@ -4424,6 +4432,7 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
bitMapLock()); bitMapLock());
startTimer(); startTimer();
sample_eden(); sample_eden();
// The following will yield to allow foreground // The following will yield to allow foreground
// collection to proceed promptly. XXX YSR: // collection to proceed promptly. XXX YSR:
// The code in this method may need further // The code in this method may need further
...@@ -4453,6 +4462,7 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) { ...@@ -4453,6 +4462,7 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
SurvivorSpacePrecleanClosure SurvivorSpacePrecleanClosure
sss_cl(this, _span, &_markBitMap, &_markStack, sss_cl(this, _span, &_markBitMap, &_markStack,
&pam_cl, before_count, CMSYield); &pam_cl, before_count, CMSYield);
DEBUG_ONLY(RememberKlassesChecker mx(CMSClassUnloadingEnabled);)
dng->from()->object_iterate_careful(&sss_cl); dng->from()->object_iterate_careful(&sss_cl);
dng->to()->object_iterate_careful(&sss_cl); dng->to()->object_iterate_careful(&sss_cl);
} }
...@@ -4554,6 +4564,13 @@ size_t CMSCollector::preclean_mod_union_table( ...@@ -4554,6 +4564,13 @@ size_t CMSCollector::preclean_mod_union_table(
verify_work_stacks_empty(); verify_work_stacks_empty();
verify_overflow_empty(); verify_overflow_empty();
// Turn off checking for this method but turn it back on
// selectively. There are yield points in this method
// but it is difficult to turn the checking off just around
// the yield points. It is simpler to selectively turn
// it on.
DEBUG_ONLY(RememberKlassesChecker mux(false);)
// strategy: starting with the first card, accumulate contiguous // strategy: starting with the first card, accumulate contiguous
// ranges of dirty cards; clear these cards, then scan the region // ranges of dirty cards; clear these cards, then scan the region
// covered by these cards. // covered by these cards.
...@@ -4582,6 +4599,7 @@ size_t CMSCollector::preclean_mod_union_table( ...@@ -4582,6 +4599,7 @@ size_t CMSCollector::preclean_mod_union_table(
MemRegion dirtyRegion; MemRegion dirtyRegion;
{ {
stopTimer(); stopTimer();
// Potential yield point
CMSTokenSync ts(true); CMSTokenSync ts(true);
startTimer(); startTimer();
sample_eden(); sample_eden();
...@@ -4607,6 +4625,7 @@ size_t CMSCollector::preclean_mod_union_table( ...@@ -4607,6 +4625,7 @@ size_t CMSCollector::preclean_mod_union_table(
assert(numDirtyCards > 0, "consistency check"); assert(numDirtyCards > 0, "consistency check");
HeapWord* stop_point = NULL; HeapWord* stop_point = NULL;
stopTimer(); stopTimer();
// Potential yield point
CMSTokenSyncWithLocks ts(true, gen->freelistLock(), CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
bitMapLock()); bitMapLock());
startTimer(); startTimer();
...@@ -4614,6 +4633,7 @@ size_t CMSCollector::preclean_mod_union_table( ...@@ -4614,6 +4633,7 @@ size_t CMSCollector::preclean_mod_union_table(
verify_work_stacks_empty(); verify_work_stacks_empty();
verify_overflow_empty(); verify_overflow_empty();
sample_eden(); sample_eden();
DEBUG_ONLY(RememberKlassesChecker mx(CMSClassUnloadingEnabled);)
stop_point = stop_point =
gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl); gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
} }
...@@ -4701,6 +4721,7 @@ size_t CMSCollector::preclean_card_table(ConcurrentMarkSweepGeneration* gen, ...@@ -4701,6 +4721,7 @@ size_t CMSCollector::preclean_card_table(ConcurrentMarkSweepGeneration* gen,
sample_eden(); sample_eden();
verify_work_stacks_empty(); verify_work_stacks_empty();
verify_overflow_empty(); verify_overflow_empty();
DEBUG_ONLY(RememberKlassesChecker mx(CMSClassUnloadingEnabled);)
HeapWord* stop_point = HeapWord* stop_point =
gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl); gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
if (stop_point != NULL) { if (stop_point != NULL) {
...@@ -4800,6 +4821,7 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch, ...@@ -4800,6 +4821,7 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch,
assert(haveFreelistLocks(), "must have free list locks"); assert(haveFreelistLocks(), "must have free list locks");
assert_lock_strong(bitMapLock()); assert_lock_strong(bitMapLock());
DEBUG_ONLY(RememberKlassesChecker fmx(CMSClassUnloadingEnabled);)
if (!init_mark_was_synchronous) { if (!init_mark_was_synchronous) {
// We might assume that we need not fill TLAB's when // We might assume that we need not fill TLAB's when
// CMSScavengeBeforeRemark is set, because we may have just done // CMSScavengeBeforeRemark is set, because we may have just done
...@@ -4903,6 +4925,9 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch, ...@@ -4903,6 +4925,9 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch,
_markStack._hit_limit = 0; _markStack._hit_limit = 0;
_markStack._failed_double = 0; _markStack._failed_double = 0;
// Check that all the klasses have been checked
assert(_revisitStack.isEmpty(), "Not all klasses revisited");
if ((VerifyAfterGC || VerifyDuringGC) && if ((VerifyAfterGC || VerifyDuringGC) &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
verify_after_remark(); verify_after_remark();
...@@ -5574,9 +5599,13 @@ public: ...@@ -5574,9 +5599,13 @@ public:
void CMSRefProcTaskProxy::work(int i) { void CMSRefProcTaskProxy::work(int i) {
assert(_collector->_span.equals(_span), "Inconsistency in _span"); assert(_collector->_span.equals(_span), "Inconsistency in _span");
CMSParKeepAliveClosure par_keep_alive(_collector, _span, CMSParKeepAliveClosure par_keep_alive(_collector, _span,
_mark_bit_map, work_queue(i)); _mark_bit_map,
&_collector->_revisitStack,
work_queue(i));
CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span, CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span,
_mark_bit_map, work_queue(i)); _mark_bit_map,
&_collector->_revisitStack,
work_queue(i));
CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map); CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map);
_task.work(i, is_alive_closure, par_keep_alive, par_drain_stack); _task.work(i, is_alive_closure, par_keep_alive, par_drain_stack);
if (_task.marks_oops_alive()) { if (_task.marks_oops_alive()) {
...@@ -5604,12 +5633,13 @@ public: ...@@ -5604,12 +5633,13 @@ public:
}; };
CMSParKeepAliveClosure::CMSParKeepAliveClosure(CMSCollector* collector, CMSParKeepAliveClosure::CMSParKeepAliveClosure(CMSCollector* collector,
MemRegion span, CMSBitMap* bit_map, OopTaskQueue* work_queue): MemRegion span, CMSBitMap* bit_map, CMSMarkStack* revisit_stack,
_collector(collector), OopTaskQueue* work_queue):
Par_KlassRememberingOopClosure(collector, NULL, revisit_stack),
_span(span), _span(span),
_bit_map(bit_map), _bit_map(bit_map),
_work_queue(work_queue), _work_queue(work_queue),
_mark_and_push(collector, span, bit_map, work_queue), _mark_and_push(collector, span, bit_map, revisit_stack, work_queue),
_low_water_mark(MIN2((uint)(work_queue->max_elems()/4), _low_water_mark(MIN2((uint)(work_queue->max_elems()/4),
(uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads))) (uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads)))
{ } { }
...@@ -5696,7 +5726,8 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) { ...@@ -5696,7 +5726,8 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
verify_work_stacks_empty(); verify_work_stacks_empty();
CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap, CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
&_markStack, false /* !preclean */); &_markStack, &_revisitStack,
false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this, CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
_span, &_markBitMap, &_markStack, _span, &_markBitMap, &_markStack,
&cmsKeepAliveClosure, false /* !preclean */); &cmsKeepAliveClosure, false /* !preclean */);
...@@ -6531,6 +6562,7 @@ void MarkRefsIntoAndScanClosure::do_yield_work() { ...@@ -6531,6 +6562,7 @@ void MarkRefsIntoAndScanClosure::do_yield_work() {
assert_lock_strong(_freelistLock); assert_lock_strong(_freelistLock);
assert_lock_strong(_bit_map->lock()); assert_lock_strong(_bit_map->lock());
// relinquish the free_list_lock and bitMaplock() // relinquish the free_list_lock and bitMaplock()
DEBUG_ONLY(RememberKlassesChecker mux(false);)
_bit_map->lock()->unlock(); _bit_map->lock()->unlock();
_freelistLock->unlock(); _freelistLock->unlock();
ConcurrentMarkSweepThread::desynchronize(true); ConcurrentMarkSweepThread::desynchronize(true);
...@@ -6703,6 +6735,7 @@ void ScanMarkedObjectsAgainCarefullyClosure::do_yield_work() { ...@@ -6703,6 +6735,7 @@ void ScanMarkedObjectsAgainCarefullyClosure::do_yield_work() {
"CMS thread should hold CMS token"); "CMS thread should hold CMS token");
assert_lock_strong(_freelistLock); assert_lock_strong(_freelistLock);
assert_lock_strong(_bitMap->lock()); assert_lock_strong(_bitMap->lock());
DEBUG_ONLY(RememberKlassesChecker mux(false);)
// relinquish the free_list_lock and bitMaplock() // relinquish the free_list_lock and bitMaplock()
_bitMap->lock()->unlock(); _bitMap->lock()->unlock();
_freelistLock->unlock(); _freelistLock->unlock();
...@@ -6779,6 +6812,7 @@ void SurvivorSpacePrecleanClosure::do_yield_work() { ...@@ -6779,6 +6812,7 @@ void SurvivorSpacePrecleanClosure::do_yield_work() {
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"CMS thread should hold CMS token"); "CMS thread should hold CMS token");
assert_lock_strong(_bit_map->lock()); assert_lock_strong(_bit_map->lock());
DEBUG_ONLY(RememberKlassesChecker smx(false);)
// Relinquish the bit map lock // Relinquish the bit map lock
_bit_map->lock()->unlock(); _bit_map->lock()->unlock();
ConcurrentMarkSweepThread::desynchronize(true); ConcurrentMarkSweepThread::desynchronize(true);
...@@ -6941,6 +6975,7 @@ void MarkFromRootsClosure::do_yield_work() { ...@@ -6941,6 +6975,7 @@ void MarkFromRootsClosure::do_yield_work() {
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"CMS thread should hold CMS token"); "CMS thread should hold CMS token");
assert_lock_strong(_bitMap->lock()); assert_lock_strong(_bitMap->lock());
DEBUG_ONLY(RememberKlassesChecker mux(false);)
_bitMap->lock()->unlock(); _bitMap->lock()->unlock();
ConcurrentMarkSweepThread::desynchronize(true); ConcurrentMarkSweepThread::desynchronize(true);
ConcurrentMarkSweepThread::acknowledge_yield_request(); ConcurrentMarkSweepThread::acknowledge_yield_request();
...@@ -7295,15 +7330,12 @@ PushOrMarkClosure::PushOrMarkClosure(CMSCollector* collector, ...@@ -7295,15 +7330,12 @@ PushOrMarkClosure::PushOrMarkClosure(CMSCollector* collector,
CMSBitMap* bitMap, CMSMarkStack* markStack, CMSBitMap* bitMap, CMSMarkStack* markStack,
CMSMarkStack* revisitStack, CMSMarkStack* revisitStack,
HeapWord* finger, MarkFromRootsClosure* parent) : HeapWord* finger, MarkFromRootsClosure* parent) :
OopClosure(collector->ref_processor()), KlassRememberingOopClosure(collector, collector->ref_processor(), revisitStack),
_collector(collector),
_span(span), _span(span),
_bitMap(bitMap), _bitMap(bitMap),
_markStack(markStack), _markStack(markStack),
_revisitStack(revisitStack),
_finger(finger), _finger(finger),
_parent(parent), _parent(parent)
_should_remember_klasses(collector->should_unload_classes())
{ } { }
Par_PushOrMarkClosure::Par_PushOrMarkClosure(CMSCollector* collector, Par_PushOrMarkClosure::Par_PushOrMarkClosure(CMSCollector* collector,
...@@ -7315,18 +7347,17 @@ Par_PushOrMarkClosure::Par_PushOrMarkClosure(CMSCollector* collector, ...@@ -7315,18 +7347,17 @@ Par_PushOrMarkClosure::Par_PushOrMarkClosure(CMSCollector* collector,
HeapWord* finger, HeapWord* finger,
HeapWord** global_finger_addr, HeapWord** global_finger_addr,
Par_MarkFromRootsClosure* parent) : Par_MarkFromRootsClosure* parent) :
OopClosure(collector->ref_processor()), Par_KlassRememberingOopClosure(collector,
_collector(collector), collector->ref_processor(),
revisit_stack),
_whole_span(collector->_span), _whole_span(collector->_span),
_span(span), _span(span),
_bit_map(bit_map), _bit_map(bit_map),
_work_queue(work_queue), _work_queue(work_queue),
_overflow_stack(overflow_stack), _overflow_stack(overflow_stack),
_revisit_stack(revisit_stack),
_finger(finger), _finger(finger),
_global_finger_addr(global_finger_addr), _global_finger_addr(global_finger_addr),
_parent(parent), _parent(parent)
_should_remember_klasses(collector->should_unload_classes())
{ } { }
// Assumes thread-safe access by callers, who are // Assumes thread-safe access by callers, who are
...@@ -7456,6 +7487,14 @@ void Par_PushOrMarkClosure::do_oop(oop obj) { ...@@ -7456,6 +7487,14 @@ void Par_PushOrMarkClosure::do_oop(oop obj) {
void Par_PushOrMarkClosure::do_oop(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); } void Par_PushOrMarkClosure::do_oop(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); }
void Par_PushOrMarkClosure::do_oop(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); } void Par_PushOrMarkClosure::do_oop(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); }
KlassRememberingOopClosure::KlassRememberingOopClosure(CMSCollector* collector,
ReferenceProcessor* rp,
CMSMarkStack* revisit_stack) :
OopClosure(rp),
_collector(collector),
_revisit_stack(revisit_stack),
_should_remember_klasses(collector->should_unload_classes()) {}
PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector, PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
MemRegion span, MemRegion span,
ReferenceProcessor* rp, ReferenceProcessor* rp,
...@@ -7464,15 +7503,12 @@ PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector, ...@@ -7464,15 +7503,12 @@ PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
CMSMarkStack* mark_stack, CMSMarkStack* mark_stack,
CMSMarkStack* revisit_stack, CMSMarkStack* revisit_stack,
bool concurrent_precleaning): bool concurrent_precleaning):
OopClosure(rp), KlassRememberingOopClosure(collector, rp, revisit_stack),
_collector(collector),
_span(span), _span(span),
_bit_map(bit_map), _bit_map(bit_map),
_mod_union_table(mod_union_table), _mod_union_table(mod_union_table),
_mark_stack(mark_stack), _mark_stack(mark_stack),
_revisit_stack(revisit_stack), _concurrent_precleaning(concurrent_precleaning)
_concurrent_precleaning(concurrent_precleaning),
_should_remember_klasses(collector->should_unload_classes())
{ {
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL"); assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
} }
...@@ -7540,13 +7576,10 @@ Par_PushAndMarkClosure::Par_PushAndMarkClosure(CMSCollector* collector, ...@@ -7540,13 +7576,10 @@ Par_PushAndMarkClosure::Par_PushAndMarkClosure(CMSCollector* collector,
CMSBitMap* bit_map, CMSBitMap* bit_map,
OopTaskQueue* work_queue, OopTaskQueue* work_queue,
CMSMarkStack* revisit_stack): CMSMarkStack* revisit_stack):
OopClosure(rp), Par_KlassRememberingOopClosure(collector, rp, revisit_stack),
_collector(collector),
_span(span), _span(span),
_bit_map(bit_map), _bit_map(bit_map),
_work_queue(work_queue), _work_queue(work_queue)
_revisit_stack(revisit_stack),
_should_remember_klasses(collector->should_unload_classes())
{ {
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL"); assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
} }
...@@ -7599,19 +7632,8 @@ void Par_PushAndMarkClosure::do_oop(oop obj) { ...@@ -7599,19 +7632,8 @@ void Par_PushAndMarkClosure::do_oop(oop obj) {
void Par_PushAndMarkClosure::do_oop(oop* p) { Par_PushAndMarkClosure::do_oop_work(p); } void Par_PushAndMarkClosure::do_oop(oop* p) { Par_PushAndMarkClosure::do_oop_work(p); }
void Par_PushAndMarkClosure::do_oop(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); } void Par_PushAndMarkClosure::do_oop(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); }
void PushAndMarkClosure::remember_klass(Klass* k) {
if (!_revisit_stack->push(oop(k))) {
fatal("Revisit stack overflowed in PushAndMarkClosure");
}
}
void Par_PushAndMarkClosure::remember_klass(Klass* k) {
if (!_revisit_stack->par_push(oop(k))) {
fatal("Revist stack overflowed in Par_PushAndMarkClosure");
}
}
void CMSPrecleanRefsYieldClosure::do_yield_work() { void CMSPrecleanRefsYieldClosure::do_yield_work() {
DEBUG_ONLY(RememberKlassesChecker mux(false);)
Mutex* bml = _collector->bitMapLock(); Mutex* bml = _collector->bitMapLock();
assert_lock_strong(bml); assert_lock_strong(bml);
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
...@@ -8302,6 +8324,19 @@ bool CMSIsAliveClosure::do_object_b(oop obj) { ...@@ -8302,6 +8324,19 @@ bool CMSIsAliveClosure::do_object_b(oop obj) {
(!_span.contains(addr) || _bit_map->isMarked(addr)); (!_span.contains(addr) || _bit_map->isMarked(addr));
} }
CMSKeepAliveClosure::CMSKeepAliveClosure( CMSCollector* collector,
MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
CMSMarkStack* revisit_stack, bool cpc):
KlassRememberingOopClosure(collector, NULL, revisit_stack),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
_concurrent_precleaning(cpc) {
assert(!_span.is_empty(), "Empty span could spell trouble");
}
// CMSKeepAliveClosure: the serial version // CMSKeepAliveClosure: the serial version
void CMSKeepAliveClosure::do_oop(oop obj) { void CMSKeepAliveClosure::do_oop(oop obj) {
HeapWord* addr = (HeapWord*)obj; HeapWord* addr = (HeapWord*)obj;
...@@ -8385,6 +8420,16 @@ void CMSParKeepAliveClosure::trim_queue(uint max) { ...@@ -8385,6 +8420,16 @@ void CMSParKeepAliveClosure::trim_queue(uint max) {
} }
} }
CMSInnerParMarkAndPushClosure::CMSInnerParMarkAndPushClosure(
CMSCollector* collector,
MemRegion span, CMSBitMap* bit_map,
CMSMarkStack* revisit_stack,
OopTaskQueue* work_queue):
Par_KlassRememberingOopClosure(collector, NULL, revisit_stack),
_span(span),
_bit_map(bit_map),
_work_queue(work_queue) { }
void CMSInnerParMarkAndPushClosure::do_oop(oop obj) { void CMSInnerParMarkAndPushClosure::do_oop(oop obj) {
HeapWord* addr = (HeapWord*)obj; HeapWord* addr = (HeapWord*)obj;
if (_span.contains(addr) && if (_span.contains(addr) &&
......
...@@ -1790,12 +1790,13 @@ class CMSParDrainMarkingStackClosure: public VoidClosure { ...@@ -1790,12 +1790,13 @@ class CMSParDrainMarkingStackClosure: public VoidClosure {
public: public:
CMSParDrainMarkingStackClosure(CMSCollector* collector, CMSParDrainMarkingStackClosure(CMSCollector* collector,
MemRegion span, CMSBitMap* bit_map, MemRegion span, CMSBitMap* bit_map,
CMSMarkStack* revisit_stack,
OopTaskQueue* work_queue): OopTaskQueue* work_queue):
_collector(collector), _collector(collector),
_span(span), _span(span),
_bit_map(bit_map), _bit_map(bit_map),
_work_queue(work_queue), _work_queue(work_queue),
_mark_and_push(collector, span, bit_map, work_queue) { } _mark_and_push(collector, span, bit_map, revisit_stack, work_queue) { }
public: public:
void trim_queue(uint max); void trim_queue(uint max);
......
...@@ -145,6 +145,7 @@ concurrentMarkSweepGeneration.cpp genOopClosures.inline.hpp ...@@ -145,6 +145,7 @@ concurrentMarkSweepGeneration.cpp genOopClosures.inline.hpp
concurrentMarkSweepGeneration.cpp globals_extension.hpp concurrentMarkSweepGeneration.cpp globals_extension.hpp
concurrentMarkSweepGeneration.cpp handles.inline.hpp concurrentMarkSweepGeneration.cpp handles.inline.hpp
concurrentMarkSweepGeneration.cpp isGCActiveMark.hpp concurrentMarkSweepGeneration.cpp isGCActiveMark.hpp
concurrentMarkSweepGeneration.cpp iterator.hpp
concurrentMarkSweepGeneration.cpp java.hpp concurrentMarkSweepGeneration.cpp java.hpp
concurrentMarkSweepGeneration.cpp jvmtiExport.hpp concurrentMarkSweepGeneration.cpp jvmtiExport.hpp
concurrentMarkSweepGeneration.cpp oop.inline.hpp concurrentMarkSweepGeneration.cpp oop.inline.hpp
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
# include "incls/_precompiled.incl" # include "incls/_precompiled.incl"
# include "incls/_iterator.cpp.incl" # include "incls/_iterator.cpp.incl"
#ifdef ASSERT
bool OopClosure::_must_remember_klasses = false;
#endif
void ObjectToOopClosure::do_object(oop obj) { void ObjectToOopClosure::do_object(oop obj) {
obj->oop_iterate(_cl); obj->oop_iterate(_cl);
} }
...@@ -32,3 +36,13 @@ void ObjectToOopClosure::do_object(oop obj) { ...@@ -32,3 +36,13 @@ void ObjectToOopClosure::do_object(oop obj) {
void VoidClosure::do_void() { void VoidClosure::do_void() {
ShouldNotCallThis(); ShouldNotCallThis();
} }
#ifdef ASSERT
bool OopClosure::must_remember_klasses() {
return _must_remember_klasses;
}
void OopClosure::set_must_remember_klasses(bool v) {
_must_remember_klasses = v;
}
#endif
...@@ -54,7 +54,12 @@ class OopClosure : public Closure { ...@@ -54,7 +54,12 @@ class OopClosure : public Closure {
// In support of post-processing of weak links of KlassKlass objects; // In support of post-processing of weak links of KlassKlass objects;
// see KlassKlass::oop_oop_iterate(). // see KlassKlass::oop_oop_iterate().
virtual const bool should_remember_klasses() const { return false; }
virtual const bool should_remember_klasses() const {
assert(!must_remember_klasses(), "Should have overriden this method.");
return false;
}
virtual void remember_klass(Klass* k) { /* do nothing */ } virtual void remember_klass(Klass* k) { /* do nothing */ }
// If "true", invoke on nmethods (when scanning compiled frames). // If "true", invoke on nmethods (when scanning compiled frames).
...@@ -74,6 +79,12 @@ class OopClosure : public Closure { ...@@ -74,6 +79,12 @@ class OopClosure : public Closure {
// location without an intervening "major reset" (like the end of a GC). // location without an intervening "major reset" (like the end of a GC).
virtual bool idempotent() { return false; } virtual bool idempotent() { return false; }
virtual bool apply_to_weak_ref_discovered_field() { return false; } virtual bool apply_to_weak_ref_discovered_field() { return false; }
#ifdef ASSERT
static bool _must_remember_klasses;
static bool must_remember_klasses();
static void set_must_remember_klasses(bool v);
#endif
}; };
// ObjectClosure is used for iterating through an object space // ObjectClosure is used for iterating through an object space
...@@ -219,3 +230,38 @@ public: ...@@ -219,3 +230,38 @@ public:
// correct length. // correct length.
virtual void do_tag(int tag) = 0; virtual void do_tag(int tag) = 0;
}; };
#ifdef ASSERT
// This class is used to flag phases of a collection that
// can unload classes and which should override the
// should_remember_klasses() and remember_klass() of OopClosure.
// The _must_remember_klasses is set in the contructor and restored
// in the destructor. _must_remember_klasses is checked in assertions
// in the OopClosure implementations of should_remember_klasses() and
// remember_klass() and the expectation is that the OopClosure
// implementation should not be in use if _must_remember_klasses is set.
// Instances of RememberKlassesChecker can be place in
// marking phases of collections which can do class unloading.
// RememberKlassesChecker can be passed "false" to turn off checking.
// It is used by CMS when CMS yields to a different collector.
class RememberKlassesChecker: StackObj {
bool _state;
bool _skip;
public:
RememberKlassesChecker(bool checking_on) : _state(false), _skip(false) {
_skip = !(ClassUnloading && !UseConcMarkSweepGC ||
CMSClassUnloadingEnabled && UseConcMarkSweepGC);
if (_skip) {
return;
}
_state = OopClosure::must_remember_klasses();
OopClosure::set_must_remember_klasses(checking_on);
}
~RememberKlassesChecker() {
if (_skip) {
return;
}
OopClosure::set_must_remember_klasses(_state);
}
};
#endif // ASSERT
...@@ -1231,6 +1231,11 @@ void ReferenceProcessor::preclean_discovered_references( ...@@ -1231,6 +1231,11 @@ void ReferenceProcessor::preclean_discovered_references(
NOT_PRODUCT(verify_ok_to_handle_reflists()); NOT_PRODUCT(verify_ok_to_handle_reflists());
#ifdef ASSERT
bool must_remember_klasses = ClassUnloading && !UseConcMarkSweepGC ||
CMSClassUnloadingEnabled && UseConcMarkSweepGC;
RememberKlassesChecker mx(must_remember_klasses);
#endif
// Soft references // Soft references
{ {
TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册