91 // |
91 // |
92 |
92 |
93 // Local to this file. |
93 // Local to this file. |
94 |
94 |
95 class RefineCardTableEntryClosure: public CardTableEntryClosure { |
95 class RefineCardTableEntryClosure: public CardTableEntryClosure { |
96 G1RemSet* _g1rs; |
|
97 ConcurrentG1Refine* _cg1r; |
|
98 bool _concurrent; |
96 bool _concurrent; |
99 public: |
97 public: |
100 RefineCardTableEntryClosure(G1RemSet* g1rs, |
98 RefineCardTableEntryClosure() : _concurrent(true) { } |
101 ConcurrentG1Refine* cg1r) : |
99 |
102 _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) |
|
103 {} |
|
104 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
100 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
105 bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false); |
101 bool oops_into_cset = G1CollectedHeap::heap()->g1_rem_set()->refine_card(card_ptr, worker_i, false); |
106 // This path is executed by the concurrent refine or mutator threads, |
102 // This path is executed by the concurrent refine or mutator threads, |
107 // concurrently, and so we do not care if card_ptr contains references |
103 // concurrently, and so we do not care if card_ptr contains references |
108 // that point into the collection set. |
104 // that point into the collection set. |
109 assert(!oops_into_cset, "should be"); |
105 assert(!oops_into_cset, "should be"); |
110 |
106 |
476 ct_bs->mod_card_iterate(&count1); |
473 ct_bs->mod_card_iterate(&count1); |
477 int orig_count = count1.n(); |
474 int orig_count = count1.n(); |
478 |
475 |
479 // First clear the logged cards. |
476 // First clear the logged cards. |
480 ClearLoggedCardTableEntryClosure clear; |
477 ClearLoggedCardTableEntryClosure clear; |
481 dcqs.set_closure(&clear); |
478 dcqs.apply_closure_to_all_completed_buffers(&clear); |
482 dcqs.apply_closure_to_all_completed_buffers(); |
479 dcqs.iterate_closure_all_threads(&clear, false); |
483 dcqs.iterate_closure_all_threads(false); |
|
484 clear.print_histo(); |
480 clear.print_histo(); |
485 |
481 |
486 // Now ensure that there's no dirty cards. |
482 // Now ensure that there's no dirty cards. |
487 CountNonCleanMemRegionClosure count2(this); |
483 CountNonCleanMemRegionClosure count2(this); |
488 ct_bs->mod_card_iterate(&count2); |
484 ct_bs->mod_card_iterate(&count2); |
491 count2.n(), orig_count); |
487 count2.n(), orig_count); |
492 } |
488 } |
493 guarantee(count2.n() == 0, "Card table should be clean."); |
489 guarantee(count2.n() == 0, "Card table should be clean."); |
494 |
490 |
495 RedirtyLoggedCardTableEntryClosure redirty; |
491 RedirtyLoggedCardTableEntryClosure redirty; |
496 JavaThread::dirty_card_queue_set().set_closure(&redirty); |
492 dcqs.apply_closure_to_all_completed_buffers(&redirty); |
497 dcqs.apply_closure_to_all_completed_buffers(); |
493 dcqs.iterate_closure_all_threads(&redirty, false); |
498 dcqs.iterate_closure_all_threads(false); |
|
499 gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.", |
494 gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.", |
500 clear.calls(), orig_count); |
495 clear.calls(), orig_count); |
501 guarantee(redirty.calls() == clear.calls(), |
496 guarantee(redirty.calls() == clear.calls(), |
502 "Or else mechanism is broken."); |
497 "Or else mechanism is broken."); |
503 |
498 |
506 if (count3.n() != orig_count) { |
501 if (count3.n() != orig_count) { |
507 gclog_or_tty->print_cr("Should have restored them all: orig = %d, final = %d.", |
502 gclog_or_tty->print_cr("Should have restored them all: orig = %d, final = %d.", |
508 orig_count, count3.n()); |
503 orig_count, count3.n()); |
509 guarantee(count3.n() >= orig_count, "Should have restored them all."); |
504 guarantee(count3.n() >= orig_count, "Should have restored them all."); |
510 } |
505 } |
511 |
|
512 JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); |
|
513 } |
506 } |
514 |
507 |
515 // Private class members. |
508 // Private class members. |
516 |
509 |
517 G1CollectedHeap* G1CollectedHeap::_g1h; |
510 G1CollectedHeap* G1CollectedHeap::_g1h; |
2001 // Ensure that the sizes are properly aligned. |
1994 // Ensure that the sizes are properly aligned. |
2002 Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap"); |
1995 Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap"); |
2003 Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap"); |
1996 Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap"); |
2004 Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap"); |
1997 Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap"); |
2005 |
1998 |
2006 _cg1r = new ConcurrentG1Refine(this); |
1999 _refine_cte_cl = new RefineCardTableEntryClosure(); |
|
2000 |
|
2001 _cg1r = new ConcurrentG1Refine(this, _refine_cte_cl); |
2007 |
2002 |
2008 // Reserve the maximum. |
2003 // Reserve the maximum. |
2009 |
2004 |
2010 // When compressed oops are enabled, the preferred heap base |
2005 // When compressed oops are enabled, the preferred heap base |
2011 // is calculated by subtracting the requested size from the |
2006 // is calculated by subtracting the requested size from the |
2096 } |
2091 } |
2097 |
2092 |
2098 // Perform any initialization actions delegated to the policy. |
2093 // Perform any initialization actions delegated to the policy. |
2099 g1_policy()->init(); |
2094 g1_policy()->init(); |
2100 |
2095 |
2101 _refine_cte_cl = |
|
2102 new RefineCardTableEntryClosure(g1_rem_set(), |
|
2103 concurrent_g1_refine()); |
|
2104 JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); |
|
2105 |
|
2106 JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, |
2096 JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, |
2107 SATB_Q_FL_lock, |
2097 SATB_Q_FL_lock, |
2108 G1SATBProcessCompletedThreshold, |
2098 G1SATBProcessCompletedThreshold, |
2109 Shared_SATB_Q_lock); |
2099 Shared_SATB_Q_lock); |
2110 |
2100 |
2111 JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, |
2101 JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl, |
|
2102 DirtyCardQ_CBL_mon, |
2112 DirtyCardQ_FL_lock, |
2103 DirtyCardQ_FL_lock, |
2113 concurrent_g1_refine()->yellow_zone(), |
2104 concurrent_g1_refine()->yellow_zone(), |
2114 concurrent_g1_refine()->red_zone(), |
2105 concurrent_g1_refine()->red_zone(), |
2115 Shared_DirtyCardQ_lock); |
2106 Shared_DirtyCardQ_lock); |
2116 |
2107 |
2117 if (G1DeferredRSUpdate) { |
2108 if (G1DeferredRSUpdate) { |
2118 dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, |
2109 dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code |
|
2110 DirtyCardQ_CBL_mon, |
2119 DirtyCardQ_FL_lock, |
2111 DirtyCardQ_FL_lock, |
2120 -1, // never trigger processing |
2112 -1, // never trigger processing |
2121 -1, // no limit on length |
2113 -1, // no limit on length |
2122 Shared_DirtyCardQ_lock, |
2114 Shared_DirtyCardQ_lock, |
2123 &JavaThread::dirty_card_queue_set()); |
2115 &JavaThread::dirty_card_queue_set()); |
2124 } |
2116 } |
2125 |
2117 |
2126 // Initialize the card queue set used to hold cards containing |
2118 // Initialize the card queue set used to hold cards containing |
2127 // references into the collection set. |
2119 // references into the collection set. |
2128 _into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon, |
2120 _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code |
|
2121 DirtyCardQ_CBL_mon, |
2129 DirtyCardQ_FL_lock, |
2122 DirtyCardQ_FL_lock, |
2130 -1, // never trigger processing |
2123 -1, // never trigger processing |
2131 -1, // no limit on length |
2124 -1, // no limit on length |
2132 Shared_DirtyCardQ_lock, |
2125 Shared_DirtyCardQ_lock, |
2133 &JavaThread::dirty_card_queue_set()); |
2126 &JavaThread::dirty_card_queue_set()); |
5261 G1StringDedup::unlink(is_alive); |
5254 G1StringDedup::unlink(is_alive); |
5262 } |
5255 } |
5263 } |
5256 } |
5264 |
5257 |
5265 class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { |
5258 class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { |
5266 public: |
5259 private: |
|
5260 size_t _num_processed; |
|
5261 |
|
5262 public: |
|
5263 RedirtyLoggedCardTableEntryFastClosure() : CardTableEntryClosure(), _num_processed(0) { } |
|
5264 |
5267 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
5265 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
5268 *card_ptr = CardTableModRefBS::dirty_card_val(); |
5266 *card_ptr = CardTableModRefBS::dirty_card_val(); |
|
5267 _num_processed++; |
5269 return true; |
5268 return true; |
|
5269 } |
|
5270 |
|
5271 size_t num_processed() const { return _num_processed; } |
|
5272 }; |
|
5273 |
|
5274 class G1RedirtyLoggedCardsTask : public AbstractGangTask { |
|
5275 private: |
|
5276 DirtyCardQueueSet* _queue; |
|
5277 public: |
|
5278 G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { } |
|
5279 |
|
5280 virtual void work(uint worker_id) { |
|
5281 double start_time = os::elapsedTime(); |
|
5282 |
|
5283 RedirtyLoggedCardTableEntryFastClosure cl; |
|
5284 if (G1CollectedHeap::heap()->use_parallel_gc_threads()) { |
|
5285 _queue->par_apply_closure_to_all_completed_buffers(&cl); |
|
5286 } else { |
|
5287 _queue->apply_closure_to_all_completed_buffers(&cl); |
|
5288 } |
|
5289 |
|
5290 G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times(); |
|
5291 timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0); |
|
5292 timer->record_redirty_logged_cards_processed_cards(worker_id, cl.num_processed()); |
5270 } |
5293 } |
5271 }; |
5294 }; |
5272 |
5295 |
5273 void G1CollectedHeap::redirty_logged_cards() { |
5296 void G1CollectedHeap::redirty_logged_cards() { |
5274 guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates."); |
5297 guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates."); |
5275 double redirty_logged_cards_start = os::elapsedTime(); |
5298 double redirty_logged_cards_start = os::elapsedTime(); |
5276 |
5299 |
5277 RedirtyLoggedCardTableEntryFastClosure redirty; |
5300 uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? |
5278 dirty_card_queue_set().set_closure(&redirty); |
5301 _g1h->workers()->active_workers() : 1); |
5279 dirty_card_queue_set().apply_closure_to_all_completed_buffers(); |
5302 |
|
5303 G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set()); |
|
5304 dirty_card_queue_set().reset_for_par_iteration(); |
|
5305 if (use_parallel_gc_threads()) { |
|
5306 set_par_threads(n_workers); |
|
5307 workers()->run_task(&redirty_task); |
|
5308 set_par_threads(0); |
|
5309 } else { |
|
5310 redirty_task.work(0); |
|
5311 } |
5280 |
5312 |
5281 DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); |
5313 DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); |
5282 dcq.merge_bufferlists(&dirty_card_queue_set()); |
5314 dcq.merge_bufferlists(&dirty_card_queue_set()); |
5283 assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); |
5315 assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); |
5284 |
5316 |