10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
26 #include "gc_implementation/shenandoah/shenandoahAsserts.hpp"
27 #include "gc_implementation/shenandoah/shenandoahBarrierSet.hpp"
28 #include "gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp"
29 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
30 #include "runtime/interfaceSupport.hpp"
31
32 class ShenandoahUpdateRefsForOopClosure: public ExtendedOopClosure {
33 private:
34 ShenandoahHeap* _heap;
35 template <class T>
36 inline void do_oop_work(T* p) {
37 _heap->maybe_update_with_forwarded(p);
38 }
39 public:
40 ShenandoahUpdateRefsForOopClosure() : _heap(ShenandoahHeap::heap()) {
41 assert(UseShenandoahGC && ShenandoahCloneBarrier, "should be enabled");
42 }
43 void do_oop(oop* p) { do_oop_work(p); }
44 void do_oop(narrowOop* p) { do_oop_work(p); }
45 };
46
47 ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
48 BarrierSet(),
49 _heap(heap)
50 {
51 _kind = BarrierSet::ShenandoahBarrierSet;
52 }
53
54 void ShenandoahBarrierSet::print_on(outputStream* st) const {
55 st->print("ShenandoahBarrierSet");
56 }
57
58 bool ShenandoahBarrierSet::is_a(BarrierSet::Name bsn) {
59 return bsn == BarrierSet::ShenandoahBarrierSet;
60 }
137 Unimplemented();
138 }
139
140 void ShenandoahBarrierSet::resize_covered_region(MemRegion mr) {
141 Unimplemented();
142 }
143
144 void ShenandoahBarrierSet::write_prim_array(MemRegion mr) {
145 Unimplemented();
146 }
147
148 void ShenandoahBarrierSet::write_prim_field(HeapWord* hw, size_t s , juint x, juint y) {
149 Unimplemented();
150 }
151
152 bool ShenandoahBarrierSet::write_prim_needs_barrier(HeapWord* hw, size_t s, juint x, juint y) {
153 Unimplemented();
154 return false;
155 }
156
157 bool ShenandoahBarrierSet::need_update_refs_barrier() {
158 if (_heap->shenandoahPolicy()->update_refs()) {
159 return _heap->is_update_refs_in_progress();
160 } else {
161 return _heap->is_concurrent_mark_in_progress() && _heap->has_forwarded_objects();
162 }
163 }
164
165 void ShenandoahBarrierSet::write_ref_array_work(MemRegion r) {
166 ShouldNotReachHere();
167 }
168
169 template <class T>
170 void ShenandoahBarrierSet::write_ref_array_loop(HeapWord* start, size_t count) {
171 assert(UseShenandoahGC && ShenandoahCloneBarrier, "Should be enabled");
172 ShenandoahEvacOOMScope oom_evac_scope;
173 ShenandoahUpdateRefsForOopClosure cl;
174 T* dst = (T*) start;
175 for (size_t i = 0; i < count; i++) {
176 cl.do_oop(dst++);
177 }
178 }
179
180 void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
181 assert(UseShenandoahGC, "should be enabled");
182 if (!ShenandoahCloneBarrier) return;
183 if (!need_update_refs_barrier()) return;
184
185 if (UseCompressedOops) {
186 write_ref_array_loop<narrowOop>(start, count);
187 } else {
188 write_ref_array_loop<oop>(start, count);
189 }
190 }
191
192 template <class T>
193 void ShenandoahBarrierSet::write_ref_array_pre_work(T* dst, size_t count) {
194 assert (UseShenandoahGC && ShenandoahSATBBarrier, "Should be enabled");
195
196 shenandoah_assert_not_in_cset_loc_except(dst, _heap->cancelled_concgc());
197
198 if (! JavaThread::satb_mark_queue_set().is_active()) return;
199 T* elem_ptr = dst;
200 for (size_t i = 0; i < count; i++, elem_ptr++) {
201 T heap_oop = oopDesc::load_heap_oop(elem_ptr);
202 if (!oopDesc::is_null(heap_oop)) {
203 G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
204 }
205 }
206 }
207
208 void ShenandoahBarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
209 if (! dest_uninitialized && ShenandoahSATBBarrier) {
210 write_ref_array_pre_work(dst, (size_t)count);
211 }
212 }
213
214 void ShenandoahBarrierSet::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
215 if (! dest_uninitialized && ShenandoahSATBBarrier) {
216 write_ref_array_pre_work(dst, (size_t)count);
217 }
218 }
219
220 template <class T>
221 void ShenandoahBarrierSet::write_ref_field_pre_static(T* field, oop newVal) {
222 T heap_oop = oopDesc::load_heap_oop(field);
223
224 shenandoah_assert_not_in_cset_loc_except(field, ShenandoahHeap::heap()->cancelled_concgc());
225
226 if (!oopDesc::is_null(heap_oop)) {
227 G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop(heap_oop));
228 }
229 }
230
231 template <class T>
232 inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop newVal) {
233 write_ref_field_pre_static(field, newVal);
234 }
235
236 // These are the more general virtual versions.
237 void ShenandoahBarrierSet::write_ref_field_pre_work(oop* field, oop new_val) {
238 write_ref_field_pre_static(field, new_val);
239 }
240
241 void ShenandoahBarrierSet::write_ref_field_pre_work(narrowOop* field, oop new_val) {
242 write_ref_field_pre_static(field, new_val);
243 }
244
245 void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
246 guarantee(false, "Not needed");
247 }
248
249 void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
250 shenandoah_assert_not_in_cset_loc_except(v, _heap->cancelled_concgc());
251 shenandoah_assert_not_forwarded_except (v, o, o == NULL || _heap->cancelled_concgc() || !_heap->is_concurrent_mark_in_progress());
252 shenandoah_assert_not_in_cset_except (v, o, o == NULL || _heap->cancelled_concgc() || !_heap->is_concurrent_mark_in_progress());
253 }
254
255 void ShenandoahBarrierSet::write_region_work(MemRegion mr) {
256 assert(UseShenandoahGC, "should be enabled");
257 if (!ShenandoahCloneBarrier) return;
258 if (! need_update_refs_barrier()) return;
259
260 // This is called for cloning an object (see jvm.cpp) after the clone
261 // has been made. We are not interested in any 'previous value' because
262 // it would be NULL in any case. But we *are* interested in any oop*
263 // that potentially need to be updated.
264
265 ShenandoahEvacOOMScope oom_evac_scope;
266 oop obj = oop(mr.start());
267 assert(obj->is_oop(), "must be an oop");
268 ShenandoahUpdateRefsForOopClosure cl;
269 obj->oop_iterate(&cl);
270 }
271
272 oop ShenandoahBarrierSet::read_barrier(oop src) {
273 // Check for forwarded objects, because on Full GC path we might deal with
274 // non-trivial fwdptrs that contain Full GC specific metadata. We could check
275 // for is_full_gc_in_progress(), but this also covers the case of stable heap,
276 // which provides a bit of performance improvement.
277 if (ShenandoahReadBarrier && _heap->has_forwarded_objects()) {
278 return ShenandoahBarrierSet::resolve_forwarded(src);
279 } else {
280 return src;
281 }
282 }
283
284 bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) {
285 bool eq = oopDesc::unsafe_equals(obj1, obj2);
286 if (! eq && ShenandoahAcmpBarrier) {
287 OrderAccess::loadload();
288 obj1 = resolve_forwarded(obj1);
289 obj2 = resolve_forwarded(obj2);
290 eq = oopDesc::unsafe_equals(obj1, obj2);
291 }
292 return eq;
293 }
294
295 bool ShenandoahBarrierSet::obj_equals(narrowOop obj1, narrowOop obj2) {
296 return obj_equals(oopDesc::decode_heap_oop(obj1), oopDesc::decode_heap_oop(obj2));
297 }
298
299 JRT_LEAF(oopDesc*, ShenandoahBarrierSet::write_barrier_JRT(oopDesc* src))
300 oop result = ((ShenandoahBarrierSet*)oopDesc::bs())->write_barrier(src);
301 return (oopDesc*) result;
302 JRT_END
303
304 IRT_LEAF(oopDesc*, ShenandoahBarrierSet::write_barrier_IRT(oopDesc* src))
305 oop result = ((ShenandoahBarrierSet*)oopDesc::bs())->write_barrier(src);
306 return (oopDesc*) result;
307 IRT_END
308
309 oop ShenandoahBarrierSet::write_barrier(oop obj) {
310 if (ShenandoahWriteBarrier) {
311 if (!oopDesc::is_null(obj)) {
312 bool evac_in_progress = _heap->is_evacuation_in_progress();
313 oop fwd = resolve_forwarded_not_null(obj);
314 if (evac_in_progress &&
315 _heap->in_collection_set(obj) &&
316 oopDesc::unsafe_equals(obj, fwd)) {
317 ShenandoahEvacOOMScope oom_evac_scope;
318 bool evac;
319 return _heap->evacuate_object(obj, Thread::current(), evac);
320 } else {
321 return fwd;
322 }
323 }
324 }
325 return obj;
326 }
327
328 #ifdef ASSERT
329 void ShenandoahBarrierSet::verify_safe_oop(oop p) {
330 shenandoah_assert_not_in_cset_except(NULL, p, (p == NULL) || ShenandoahHeap::heap()->cancelled_concgc());
331 }
332
333 void ShenandoahBarrierSet::verify_safe_oop(narrowOop p) {
334 verify_safe_oop(oopDesc::decode_heap_oop(p));
335 }
336 #endif
|
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
26 #include "gc_implementation/shenandoah/shenandoahAsserts.hpp"
27 #include "gc_implementation/shenandoah/shenandoahBarrierSet.hpp"
28 #include "gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp"
29 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
30 #include "gc_implementation/shenandoah/shenandoahHeuristics.hpp"
31 #include "runtime/interfaceSupport.hpp"
32
33 class ShenandoahUpdateRefsForOopClosure: public ExtendedOopClosure {
34 private:
35 ShenandoahHeap* _heap;
36 ShenandoahBarrierSet* _bs;
37
38 template <class T>
39 inline void do_oop_work(T* p) {
40 _heap->maybe_update_with_forwarded(p);
41 }
42 public:
43 ShenandoahUpdateRefsForOopClosure() : _heap(ShenandoahHeap::heap()), _bs(ShenandoahBarrierSet::barrier_set()) {
44 assert(UseShenandoahGC && ShenandoahCloneBarrier, "should be enabled");
45 }
46 void do_oop(oop* p) { do_oop_work(p); }
47 void do_oop(narrowOop* p) { do_oop_work(p); }
48 };
49
50 ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
51 BarrierSet(),
52 _heap(heap)
53 {
54 _kind = BarrierSet::ShenandoahBarrierSet;
55 }
56
57 void ShenandoahBarrierSet::print_on(outputStream* st) const {
58 st->print("ShenandoahBarrierSet");
59 }
60
61 bool ShenandoahBarrierSet::is_a(BarrierSet::Name bsn) {
62 return bsn == BarrierSet::ShenandoahBarrierSet;
63 }
140 Unimplemented();
141 }
142
143 void ShenandoahBarrierSet::resize_covered_region(MemRegion mr) {
144 Unimplemented();
145 }
146
147 void ShenandoahBarrierSet::write_prim_array(MemRegion mr) {
148 Unimplemented();
149 }
150
151 void ShenandoahBarrierSet::write_prim_field(HeapWord* hw, size_t s , juint x, juint y) {
152 Unimplemented();
153 }
154
155 bool ShenandoahBarrierSet::write_prim_needs_barrier(HeapWord* hw, size_t s, juint x, juint y) {
156 Unimplemented();
157 return false;
158 }
159
160 void ShenandoahBarrierSet::write_ref_array_work(MemRegion r) {
161 ShouldNotReachHere();
162 }
163
164 template <class T>
165 void ShenandoahBarrierSet::write_ref_array_loop(HeapWord* start, size_t count) {
166 assert(UseShenandoahGC && ShenandoahCloneBarrier, "Should be enabled");
167 ShenandoahUpdateRefsForOopClosure cl;
168 T* dst = (T*) start;
169 for (size_t i = 0; i < count; i++) {
170 cl.do_oop(dst++);
171 }
172 }
173
174 void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
175 assert(UseShenandoahGC, "should be enabled");
176 if (!ShenandoahCloneBarrier) return;
177 if (!need_update_refs_barrier()) return;
178
179 ShenandoahEvacOOMScope oom_evac_scope;
180 if (UseCompressedOops) {
181 write_ref_array_loop<narrowOop>(start, count);
182 } else {
183 write_ref_array_loop<oop>(start, count);
184 }
185 }
186
187 template <class T>
188 void ShenandoahBarrierSet::write_ref_array_pre_work(T* dst, size_t count) {
189 assert (UseShenandoahGC && ShenandoahSATBBarrier, "Should be enabled");
190
191 shenandoah_assert_not_in_cset_loc_except(dst, _heap->cancelled_gc());
192
193 if (! JavaThread::satb_mark_queue_set().is_active()) return;
194 T* elem_ptr = dst;
195 for (size_t i = 0; i < count; i++, elem_ptr++) {
196 T heap_oop = oopDesc::load_heap_oop(elem_ptr);
197 if (!oopDesc::is_null(heap_oop)) {
198 enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
199 }
200 }
201 }
202
203 void ShenandoahBarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
204 if (! dest_uninitialized && ShenandoahSATBBarrier) {
205 write_ref_array_pre_work(dst, (size_t)count);
206 }
207 }
208
209 void ShenandoahBarrierSet::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
210 if (! dest_uninitialized && ShenandoahSATBBarrier) {
211 write_ref_array_pre_work(dst, (size_t)count);
212 }
213 }
214
215 template <class T>
216 void ShenandoahBarrierSet::write_ref_field_pre_static(T* field, oop newVal) {
217 T heap_oop = oopDesc::load_heap_oop(field);
218
219 shenandoah_assert_not_in_cset_loc_except(field, ShenandoahHeap::heap()->cancelled_gc());
220
221 if (!oopDesc::is_null(heap_oop)) {
222 ShenandoahBarrierSet::barrier_set()->enqueue(oopDesc::decode_heap_oop(heap_oop));
223 }
224 }
225
226 template <class T>
227 inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop newVal) {
228 write_ref_field_pre_static(field, newVal);
229 }
230
231 // These are the more general virtual versions.
232 void ShenandoahBarrierSet::write_ref_field_pre_work(oop* field, oop new_val) {
233 write_ref_field_pre_static(field, new_val);
234 }
235
236 void ShenandoahBarrierSet::write_ref_field_pre_work(narrowOop* field, oop new_val) {
237 write_ref_field_pre_static(field, new_val);
238 }
239
240 void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
241 guarantee(false, "Not needed");
242 }
243
244 void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
245 shenandoah_assert_not_in_cset_loc_except(v, _heap->cancelled_gc());
246 shenandoah_assert_not_forwarded_except (v, o, o == NULL || _heap->cancelled_gc() || !_heap->is_concurrent_mark_in_progress());
247 shenandoah_assert_not_in_cset_except (v, o, o == NULL || _heap->cancelled_gc() || !_heap->is_concurrent_mark_in_progress());
248 }
249
250 void ShenandoahBarrierSet::write_region_work(MemRegion mr) {
251 assert(UseShenandoahGC, "should be enabled");
252 if (!ShenandoahCloneBarrier) return;
253 if (! need_update_refs_barrier()) return;
254
255 // This is called for cloning an object (see jvm.cpp) after the clone
256 // has been made. We are not interested in any 'previous value' because
257 // it would be NULL in any case. But we *are* interested in any oop*
258 // that potentially need to be updated.
259
260 ShenandoahEvacOOMScope oom_evac_scope;
261 oop obj = oop(mr.start());
262 shenandoah_assert_correct(NULL, obj);
263 ShenandoahUpdateRefsForOopClosure cl;
264 obj->oop_iterate(&cl);
265 }
266
267 oop ShenandoahBarrierSet::read_barrier(oop src) {
268 // Check for forwarded objects, because on Full GC path we might deal with
269 // non-trivial fwdptrs that contain Full GC specific metadata. We could check
270 // for is_full_gc_in_progress(), but this also covers the case of stable heap,
271 // which provides a bit of performance improvement.
272 if (ShenandoahReadBarrier && _heap->has_forwarded_objects()) {
273 return ShenandoahBarrierSet::resolve_forwarded(src);
274 } else {
275 return src;
276 }
277 }
278
279 bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) {
280 bool eq = oopDesc::unsafe_equals(obj1, obj2);
281 if (! eq && ShenandoahAcmpBarrier) {
282 OrderAccess::loadload();
283 obj1 = resolve_forwarded(obj1);
284 obj2 = resolve_forwarded(obj2);
285 eq = oopDesc::unsafe_equals(obj1, obj2);
286 }
287 return eq;
288 }
289
290 bool ShenandoahBarrierSet::obj_equals(narrowOop obj1, narrowOop obj2) {
291 return obj_equals(oopDesc::decode_heap_oop(obj1), oopDesc::decode_heap_oop(obj2));
292 }
293
294 JRT_LEAF(oopDesc*, ShenandoahBarrierSet::write_barrier_JRT(oopDesc* src))
295 oop result = ShenandoahBarrierSet::barrier_set()->write_barrier_mutator(src);
296 return (oopDesc*) result;
297 JRT_END
298
299 IRT_LEAF(oopDesc*, ShenandoahBarrierSet::write_barrier_IRT(oopDesc* src))
300 oop result = ShenandoahBarrierSet::barrier_set()->write_barrier_mutator(src);
301 return (oopDesc*) result;
302 IRT_END
303
304 oop ShenandoahBarrierSet::write_barrier_mutator(oop obj) {
305 assert(UseShenandoahGC && ShenandoahWriteBarrier, "should be enabled");
306 assert(_heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION), "evac should be in progress");
307 shenandoah_assert_in_cset(NULL, obj);
308
309 oop fwd = resolve_forwarded_not_null(obj);
310 if (oopDesc::unsafe_equals(obj, fwd)) {
311 ShenandoahEvacOOMScope oom_evac_scope;
312 bool evac;
313
314 Thread* thread = Thread::current();
315 oop res_oop = _heap->evacuate_object(obj, thread, evac);
316
317 // Since we are already here and paid the price of getting through runtime call adapters
318 // and acquiring oom-scope, it makes sense to try and evacuate more adjacent objects,
319 // thus amortizing the overhead. For sparsely live heaps, scan costs easily dominate
320 // total assist costs, and can introduce a lot of evacuation latency. This is why we
321 // only scan for _nearest_ N objects, regardless if they are eligible for evac or not.
322 // The scan itself should also avoid touching the non-marked objects below TAMS, because
323 // their metadata (notably, klasses) may be incorrect already.
324
325 size_t max = ShenandoahEvacAssist;
326 if (max > 0) {
327 ShenandoahMarkingContext* ctx = _heap->complete_marking_context();
328
329 ShenandoahHeapRegion* r = _heap->heap_region_containing(obj);
330 assert(r->is_cset(), "sanity");
331
332 HeapWord* cur = (HeapWord*)obj + obj->size() + BrooksPointer::word_size();
333
334 size_t count = 0;
335 while ((cur < r->top()) && ctx->is_marked(oop(cur)) && (count++ < max)) {
336 oop cur_oop = oop(cur);
337 if (oopDesc::unsafe_equals(cur_oop, resolve_forwarded_not_null(cur_oop))) {
338 _heap->evacuate_object(cur_oop, thread, evac);
339 }
340 cur = cur + cur_oop->size() + BrooksPointer::word_size();
341 }
342 }
343
344 return res_oop;
345 }
346 return fwd;
347 }
348
349 oop ShenandoahBarrierSet::write_barrier(oop obj) {
350 if (ShenandoahWriteBarrier) {
351 if (!oopDesc::is_null(obj)) {
352 bool evac_in_progress = _heap->is_evacuation_in_progress();
353 oop fwd = resolve_forwarded_not_null(obj);
354 if (evac_in_progress &&
355 _heap->in_collection_set(obj) &&
356 oopDesc::unsafe_equals(obj, fwd)) {
357 Thread *t = Thread::current();
358 bool evac;
359 if (t->is_Worker_thread()) {
360 return _heap->evacuate_object(obj, t, evac);
361 } else {
362 ShenandoahEvacOOMScope oom_evac_scope;
363 return _heap->evacuate_object(obj, t, evac);
364 }
365 } else {
366 return fwd;
367 }
368 }
369 }
370 return obj;
371 }
372
373 void ShenandoahBarrierSet::enqueue(oop obj) {
374 // Filter marked objects before hitting the SATB queues. The same predicate would
375 // be used by SATBMQ::filter to eliminate already marked objects downstream, but
376 // filtering here helps to avoid wasteful SATB queueing work to begin with.
377 if (!_heap->requires_marking(obj)) return;
378
379 G1SATBCardTableModRefBS::enqueue(obj);
380 }
|