< prev index next >

src/hotspot/share/gc/g1/g1CollectedHeap.cpp

Print this page
rev 49944 : imported patch 8201492-properly-implement-non-contiguous-reference-processing

*** 1397,1410 **** _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()), _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()), _g1_policy(new G1Policy(_gc_timer_stw)), _collection_set(this, _g1_policy), _dirty_card_queue_set(false), ! _is_alive_closure_cm(this), _is_alive_closure_stw(this), _ref_processor_cm(NULL), ! _ref_processor_stw(NULL), _bot(NULL), _hot_card_cache(NULL), _g1_rem_set(NULL), _cr(NULL), _g1mm(NULL), --- 1397,1412 ---- _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()), _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()), _g1_policy(new G1Policy(_gc_timer_stw)), _collection_set(this, _g1_policy), _dirty_card_queue_set(false), ! _ref_processor_stw(NULL), _is_alive_closure_stw(this), + _is_subject_to_discovery_stw(this), _ref_processor_cm(NULL), ! _is_alive_closure_cm(this), ! _is_subject_to_discovery_cm(this), _bot(NULL), _hot_card_cache(NULL), _g1_rem_set(NULL), _cr(NULL), _g1mm(NULL),
*** 1773,1819 **** // * References are processed near the end of a STW evacuation pause. // * For both types of GC: // * Discovery is atomic - i.e. not concurrent. // * Reference discovery will not need a barrier. - MemRegion mr = reserved_region(); - bool mt_processing = ParallelRefProcEnabled && (ParallelGCThreads > 1); // Concurrent Mark ref processor _ref_processor_cm = ! new ReferenceProcessor(mr, // span ! mt_processing, ! // mt processing ! ParallelGCThreads, ! // degree of mt processing ! (ParallelGCThreads > 1) || (ConcGCThreads > 1), ! // mt discovery ! MAX2(ParallelGCThreads, ConcGCThreads), ! // degree of mt discovery ! false, ! // Reference discovery is not atomic ! &_is_alive_closure_cm); ! // is alive closure ! // (for efficiency/performance) // STW ref processor _ref_processor_stw = ! new ReferenceProcessor(mr, // span ! mt_processing, ! // mt processing ! ParallelGCThreads, ! // degree of mt processing ! (ParallelGCThreads > 1), ! // mt discovery ! ParallelGCThreads, ! // degree of mt discovery ! true, ! // Reference discovery is atomic ! &_is_alive_closure_stw); ! // is alive closure ! // (for efficiency/performance) } CollectorPolicy* G1CollectedHeap::collector_policy() const { return _collector_policy; } --- 1775,1805 ---- // * References are processed near the end of a STW evacuation pause. // * For both types of GC: // * Discovery is atomic - i.e. not concurrent. // * Reference discovery will not need a barrier. bool mt_processing = ParallelRefProcEnabled && (ParallelGCThreads > 1); // Concurrent Mark ref processor _ref_processor_cm = ! new ReferenceProcessor(&_is_subject_to_discovery_cm, ! mt_processing, // mt processing ! ParallelGCThreads, // degree of mt processing ! (ParallelGCThreads > 1) || (ConcGCThreads > 1), // mt discovery ! MAX2(ParallelGCThreads, ConcGCThreads), // degree of mt discovery ! false, // Reference discovery is not atomic ! &_is_alive_closure_cm); // is alive closure // STW ref processor _ref_processor_stw = ! new ReferenceProcessor(&_is_subject_to_discovery_stw, ! mt_processing, // mt processing ! ParallelGCThreads, // degree of mt processing ! (ParallelGCThreads > 1), // mt discovery ! ParallelGCThreads, // degree of mt discovery ! true, // Reference discovery is atomic ! &_is_alive_closure_stw); // is alive closure } CollectorPolicy* G1CollectedHeap::collector_policy() const { return _collector_policy; }
*** 3629,3658 **** g1_policy()->phase_times()->record_redirty_logged_cards_time_ms((os::elapsedTime() - redirty_logged_cards_start) * 1000.0); } // Weak Reference Processing support - // An always "is_alive" closure that is used to preserve referents. - // If the object is non-null then it's alive. Used in the preservation - // of referent objects that are pointed to by reference objects - // discovered by the CM ref processor. - class G1AlwaysAliveClosure: public BoolObjectClosure { - public: - bool do_object_b(oop p) { - if (p != NULL) { - return true; - } - return false; - } - }; - bool G1STWIsAliveClosure::do_object_b(oop p) { // An object is reachable if it is outside the collection set, // or is inside and copied. return !_g1h->is_in_cset(p) || p->is_forwarded(); } // Non Copying Keep Alive closure class G1KeepAliveClosure: public OopClosure { G1CollectedHeap*_g1h; public: G1KeepAliveClosure(G1CollectedHeap* g1h) :_g1h(g1h) {} --- 3615,3639 ---- g1_policy()->phase_times()->record_redirty_logged_cards_time_ms((os::elapsedTime() - redirty_logged_cards_start) * 1000.0); } // Weak Reference Processing support bool G1STWIsAliveClosure::do_object_b(oop p) { // An object is reachable if it is outside the collection set, // or is inside and copied. return !_g1h->is_in_cset(p) || p->is_forwarded(); } + bool G1STWSubjectToDiscoveryClosure::do_object_b(oop obj) { + assert(obj != NULL, "must not be NULL"); + assert(_g1h->is_in_reserved(obj), "Trying to discover obj " PTR_FORMAT " not in heap", p2i(obj)); + // The areas the CM and STW ref processor manage must be disjoint. The is_in_cset() below + // may falsely indicate that this is not the case here: however the collection set only + // contains old regions when concurrent mark is not running. + return _g1h->is_in_cset(obj) || _g1h->heap_region_containing(obj)->is_survivor(); + } + // Non Copying Keep Alive closure class G1KeepAliveClosure: public OopClosure { G1CollectedHeap*_g1h; public: G1KeepAliveClosure(G1CollectedHeap* g1h) :_g1h(g1h) {}
*** 3879,4008 **** _workers->run_task(&enq_task_proxy); } // End of weak reference support closures - // Abstract task used to preserve (i.e. copy) any referent objects - // that are in the collection set and are pointed to by reference - // objects discovered by the CM ref processor. - - class G1ParPreserveCMReferentsTask: public AbstractGangTask { - protected: - G1CollectedHeap* _g1h; - G1ParScanThreadStateSet* _pss; - RefToScanQueueSet* _queues; - ParallelTaskTerminator _terminator; - uint _n_workers; - - public: - G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, int workers, RefToScanQueueSet *task_queues) : - AbstractGangTask("ParPreserveCMReferents"), - _g1h(g1h), - _pss(per_thread_states), - _queues(task_queues), - _terminator(workers, _queues), - _n_workers(workers) - { - g1h->ref_processor_cm()->set_active_mt_degree(workers); - } - - void work(uint worker_id) { - G1GCParPhaseTimesTracker x(_g1h->g1_policy()->phase_times(), G1GCPhaseTimes::PreserveCMReferents, worker_id); - - ResourceMark rm; - HandleMark hm; - - G1ParScanThreadState* pss = _pss->state_for_worker(worker_id); - pss->set_ref_discoverer(NULL); - assert(pss->queue_is_empty(), "both queue and overflow should be empty"); - - // Is alive closure - G1AlwaysAliveClosure always_alive; - - // Copying keep alive closure. Applied to referent objects that need - // to be copied. - G1CopyingKeepAliveClosure keep_alive(_g1h, pss->closures()->raw_strong_oops(), pss); - - ReferenceProcessor* rp = _g1h->ref_processor_cm(); - - uint limit = ReferenceProcessor::number_of_subclasses_of_ref() * rp->max_num_q(); - uint stride = MIN2(MAX2(_n_workers, 1U), limit); - - // limit is set using max_num_q() - which was set using ParallelGCThreads. - // So this must be true - but assert just in case someone decides to - // change the worker ids. - assert(worker_id < limit, "sanity"); - assert(!rp->discovery_is_atomic(), "check this code"); - - // Select discovered lists [i, i+stride, i+2*stride,...,limit) - for (uint idx = worker_id; idx < limit; idx += stride) { - DiscoveredList& ref_list = rp->discovered_refs()[idx]; - - DiscoveredListIterator iter(ref_list, &keep_alive, &always_alive); - while (iter.has_next()) { - // Since discovery is not atomic for the CM ref processor, we - // can see some null referent objects. - iter.load_ptrs(DEBUG_ONLY(true)); - oop ref = iter.obj(); - - // This will filter nulls. - if (iter.is_referent_alive()) { - iter.make_referent_alive(); - } - iter.move_to_next(); - } - } - - // Drain the queue - which may cause stealing - G1ParEvacuateFollowersClosure drain_queue(_g1h, pss, _queues, &_terminator); - drain_queue.do_void(); - // Allocation buffers were retired at the end of G1ParEvacuateFollowersClosure - assert(pss->queue_is_empty(), "should be"); - } - }; - - void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) { - // Any reference objects, in the collection set, that were 'discovered' - // by the CM ref processor should have already been copied (either by - // applying the external root copy closure to the discovered lists, or - // by following an RSet entry). - // - // But some of the referents, that are in the collection set, that these - // reference objects point to may not have been copied: the STW ref - // processor would have seen that the reference object had already - // been 'discovered' and would have skipped discovering the reference, - // but would not have treated the reference object as a regular oop. - // As a result the copy closure would not have been applied to the - // referent object. - // - // We need to explicitly copy these referent objects - the references - // will be processed at the end of remarking. - // - // We also need to do this copying before we process the reference - // objects discovered by the STW ref processor in case one of these - // referents points to another object which is also referenced by an - // object discovered by the STW ref processor. - double preserve_cm_referents_time = 0.0; - - // To avoid spawning task when there is no work to do, check that - // a concurrent cycle is active and that some references have been - // discovered. - if (concurrent_mark()->cm_thread()->during_cycle() && - ref_processor_cm()->has_discovered_references()) { - double preserve_cm_referents_start = os::elapsedTime(); - uint no_of_gc_workers = workers()->active_workers(); - G1ParPreserveCMReferentsTask keep_cm_referents(this, - per_thread_states, - no_of_gc_workers, - _task_queues); - workers()->run_task(&keep_cm_referents); - preserve_cm_referents_time = os::elapsedTime() - preserve_cm_referents_start; - } - - g1_policy()->phase_times()->record_preserve_cm_referents_time_ms(preserve_cm_referents_time * 1000.0); - } - // Weak Reference processing during an evacuation pause (part 1). void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { double ref_proc_start = os::elapsedTime(); ReferenceProcessor* rp = _ref_processor_stw; --- 3860,3869 ----
*** 4184,4194 **** // Process any discovered reference objects - we have // to do this _before_ we retire the GC alloc regions // as we may have to copy some 'reachable' referent // objects (and their reachable sub-graphs) that were // not copied during the pause. - preserve_cm_referents(per_thread_states); process_discovered_references(per_thread_states); G1STWIsAliveClosure is_alive(this); G1KeepAliveClosure keep_alive(this); --- 4045,4054 ----
< prev index next >