71 assert(_cset_rs_update_cl[i] == NULL, "it should be"); |
71 assert(_cset_rs_update_cl[i] == NULL, "it should be"); |
72 } |
72 } |
73 FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl); |
73 FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl); |
74 } |
74 } |
75 |
75 |
76 class ScanRSClosure : public HeapRegionClosure { |
76 ScanRSClosure::ScanRSClosure(G1ParPushHeapRSClosure* oc, |
77 size_t _cards_done, _cards; |
77 CodeBlobClosure* code_root_cl, |
78 G1CollectedHeap* _g1h; |
78 uint worker_i) : |
79 |
|
80 G1ParPushHeapRSClosure* _oc; |
|
81 CodeBlobClosure* _code_root_cl; |
|
82 |
|
83 G1BlockOffsetSharedArray* _bot_shared; |
|
84 G1SATBCardTableModRefBS *_ct_bs; |
|
85 |
|
86 double _strong_code_root_scan_time_sec; |
|
87 uint _worker_i; |
|
88 size_t _block_size; |
|
89 bool _try_claimed; |
|
90 |
|
91 public: |
|
92 ScanRSClosure(G1ParPushHeapRSClosure* oc, |
|
93 CodeBlobClosure* code_root_cl, |
|
94 uint worker_i) : |
|
95 _oc(oc), |
79 _oc(oc), |
96 _code_root_cl(code_root_cl), |
80 _code_root_cl(code_root_cl), |
97 _strong_code_root_scan_time_sec(0.0), |
81 _strong_code_root_scan_time_sec(0.0), |
98 _cards(0), |
82 _cards(0), |
99 _cards_done(0), |
83 _cards_done(0), |
100 _worker_i(worker_i), |
84 _worker_i(worker_i), |
101 _try_claimed(false) |
85 _try_claimed(false) { |
102 { |
86 _g1h = G1CollectedHeap::heap(); |
103 _g1h = G1CollectedHeap::heap(); |
87 _bot_shared = _g1h->bot_shared(); |
104 _bot_shared = _g1h->bot_shared(); |
88 _ct_bs = _g1h->g1_barrier_set(); |
105 _ct_bs = _g1h->g1_barrier_set(); |
89 _block_size = MAX2<size_t>(G1RSetScanBlockSize, 1); |
106 _block_size = MAX2<size_t>(G1RSetScanBlockSize, 1); |
90 } |
107 } |
91 |
108 |
92 void ScanRSClosure::scanCard(size_t index, HeapRegion *r) { |
109 void set_try_claimed() { _try_claimed = true; } |
93 // Stack allocate the DirtyCardToOopClosure instance |
110 |
94 HeapRegionDCTOC cl(_g1h, r, _oc, |
111 void scanCard(size_t index, HeapRegion *r) { |
95 CardTableModRefBS::Precise); |
112 // Stack allocate the DirtyCardToOopClosure instance |
96 |
113 HeapRegionDCTOC cl(_g1h, r, _oc, |
97 // Set the "from" region in the closure. |
114 CardTableModRefBS::Precise); |
98 _oc->set_region(r); |
115 |
99 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words); |
116 // Set the "from" region in the closure. |
100 MemRegion pre_gc_allocated(r->bottom(), r->scan_top()); |
117 _oc->set_region(r); |
101 MemRegion mr = pre_gc_allocated.intersection(card_region); |
118 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words); |
102 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) { |
119 MemRegion pre_gc_allocated(r->bottom(), r->scan_top()); |
103 // We make the card as "claimed" lazily (so races are possible |
120 MemRegion mr = pre_gc_allocated.intersection(card_region); |
104 // but they're benign), which reduces the number of duplicate |
121 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) { |
105 // scans (the rsets of the regions in the cset can intersect). |
122 // We make the card as "claimed" lazily (so races are possible |
106 _ct_bs->set_card_claimed(index); |
123 // but they're benign), which reduces the number of duplicate |
107 _cards_done++; |
124 // scans (the rsets of the regions in the cset can intersect). |
108 cl.do_MemRegion(mr); |
125 _ct_bs->set_card_claimed(index); |
109 } |
126 _cards_done++; |
110 } |
127 cl.do_MemRegion(mr); |
111 |
128 } |
112 void ScanRSClosure::printCard(HeapRegion* card_region, size_t card_index, |
129 } |
113 HeapWord* card_start) { |
130 |
114 gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") " |
131 void printCard(HeapRegion* card_region, size_t card_index, |
115 "RS names card " SIZE_FORMAT_HEX ": " |
132 HeapWord* card_start) { |
116 "[" PTR_FORMAT ", " PTR_FORMAT ")", |
133 gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") " |
117 _worker_i, |
134 "RS names card " SIZE_FORMAT_HEX ": " |
118 p2i(card_region->bottom()), p2i(card_region->end()), |
135 "[" PTR_FORMAT ", " PTR_FORMAT ")", |
119 card_index, |
136 _worker_i, |
120 p2i(card_start), p2i(card_start + G1BlockOffsetSharedArray::N_words)); |
137 p2i(card_region->bottom()), p2i(card_region->end()), |
121 } |
138 card_index, |
122 |
139 p2i(card_start), p2i(card_start + G1BlockOffsetSharedArray::N_words)); |
123 void ScanRSClosure::scan_strong_code_roots(HeapRegion* r) { |
140 } |
124 double scan_start = os::elapsedTime(); |
141 |
125 r->strong_code_roots_do(_code_root_cl); |
142 void scan_strong_code_roots(HeapRegion* r) { |
126 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start); |
143 double scan_start = os::elapsedTime(); |
127 } |
144 r->strong_code_roots_do(_code_root_cl); |
128 |
145 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start); |
129 bool ScanRSClosure::doHeapRegion(HeapRegion* r) { |
146 } |
130 assert(r->in_collection_set(), "should only be called on elements of CS."); |
147 |
131 HeapRegionRemSet* hrrs = r->rem_set(); |
148 bool doHeapRegion(HeapRegion* r) { |
132 if (hrrs->iter_is_complete()) return false; // All done. |
149 assert(r->in_collection_set(), "should only be called on elements of CS."); |
133 if (!_try_claimed && !hrrs->claim_iter()) return false; |
150 HeapRegionRemSet* hrrs = r->rem_set(); |
134 // If we ever free the collection set concurrently, we should also |
151 if (hrrs->iter_is_complete()) return false; // All done. |
135 // clear the card table concurrently therefore we won't need to |
152 if (!_try_claimed && !hrrs->claim_iter()) return false; |
136 // add regions of the collection set to the dirty cards region. |
153 // If we ever free the collection set concurrently, we should also |
137 _g1h->push_dirty_cards_region(r); |
154 // clear the card table concurrently therefore we won't need to |
138 // If we didn't return above, then |
155 // add regions of the collection set to the dirty cards region. |
139 // _try_claimed || r->claim_iter() |
156 _g1h->push_dirty_cards_region(r); |
140 // is true: either we're supposed to work on claimed-but-not-complete |
157 // If we didn't return above, then |
141 // regions, or we successfully claimed the region. |
158 // _try_claimed || r->claim_iter() |
142 |
159 // is true: either we're supposed to work on claimed-but-not-complete |
143 HeapRegionRemSetIterator iter(hrrs); |
160 // regions, or we successfully claimed the region. |
144 size_t card_index; |
161 |
145 |
162 HeapRegionRemSetIterator iter(hrrs); |
146 // We claim cards in block so as to reduce the contention. The block size is determined by |
163 size_t card_index; |
147 // the G1RSetScanBlockSize parameter. |
164 |
148 size_t jump_to_card = hrrs->iter_claimed_next(_block_size); |
165 // We claim cards in block so as to reduce the contention. The block size is determined by |
149 for (size_t current_card = 0; iter.has_next(card_index); current_card++) { |
166 // the G1RSetScanBlockSize parameter. |
150 if (current_card >= jump_to_card + _block_size) { |
167 size_t jump_to_card = hrrs->iter_claimed_next(_block_size); |
151 jump_to_card = hrrs->iter_claimed_next(_block_size); |
168 for (size_t current_card = 0; iter.has_next(card_index); current_card++) { |
152 } |
169 if (current_card >= jump_to_card + _block_size) { |
153 if (current_card < jump_to_card) continue; |
170 jump_to_card = hrrs->iter_claimed_next(_block_size); |
154 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index); |
171 } |
|
172 if (current_card < jump_to_card) continue; |
|
173 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index); |
|
174 #if 0 |
155 #if 0 |
175 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n", |
156 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n", |
176 card_start, card_start + CardTableModRefBS::card_size_in_words); |
157 card_start, card_start + CardTableModRefBS::card_size_in_words); |
177 #endif |
158 #endif |
178 |
159 |
179 HeapRegion* card_region = _g1h->heap_region_containing(card_start); |
160 HeapRegion* card_region = _g1h->heap_region_containing(card_start); |
180 _cards++; |
161 _cards++; |
181 |
162 |
182 if (!card_region->is_on_dirty_cards_region_list()) { |
163 if (!card_region->is_on_dirty_cards_region_list()) { |
183 _g1h->push_dirty_cards_region(card_region); |
164 _g1h->push_dirty_cards_region(card_region); |
184 } |
165 } |
185 |
166 |
186 // If the card is dirty, then we will scan it during updateRS. |
167 // If the card is dirty, then we will scan it during updateRS. |
187 if (!card_region->in_collection_set() && |
168 if (!card_region->in_collection_set() && |
188 !_ct_bs->is_card_dirty(card_index)) { |
169 !_ct_bs->is_card_dirty(card_index)) { |
189 scanCard(card_index, card_region); |
170 scanCard(card_index, card_region); |
190 } |
171 } |
191 } |
172 } |
192 if (!_try_claimed) { |
173 if (!_try_claimed) { |
193 // Scan the strong code root list attached to the current region |
174 // Scan the strong code root list attached to the current region |
194 scan_strong_code_roots(r); |
175 scan_strong_code_roots(r); |
195 |
176 |
196 hrrs->set_iter_complete(); |
177 hrrs->set_iter_complete(); |
197 } |
178 } |
198 return false; |
179 return false; |
199 } |
180 } |
200 |
|
201 double strong_code_root_scan_time_sec() { |
|
202 return _strong_code_root_scan_time_sec; |
|
203 } |
|
204 |
|
205 size_t cards_done() { return _cards_done;} |
|
206 size_t cards_looked_up() { return _cards;} |
|
207 }; |
|
208 |
181 |
209 size_t G1RemSet::scanRS(G1ParPushHeapRSClosure* oc, |
182 size_t G1RemSet::scanRS(G1ParPushHeapRSClosure* oc, |
210 CodeBlobClosure* heap_region_codeblobs, |
183 CodeBlobClosure* heap_region_codeblobs, |
211 uint worker_i) { |
184 uint worker_i) { |
212 double rs_time_start = os::elapsedTime(); |
185 double rs_time_start = os::elapsedTime(); |