Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp
66644 views
1
/*
2
* Copyright (c) 2015, 2021, Red Hat, Inc. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
26
#define SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
27
28
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
29
30
#include "gc/shared/accessBarrierSupport.inline.hpp"
31
#include "gc/shenandoah/shenandoahAsserts.hpp"
32
#include "gc/shenandoah/shenandoahCollectionSet.inline.hpp"
33
#include "gc/shenandoah/shenandoahEvacOOMHandler.inline.hpp"
34
#include "gc/shenandoah/shenandoahForwarding.inline.hpp"
35
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
36
#include "gc/shenandoah/shenandoahHeapRegion.hpp"
37
#include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
38
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
39
#include "oops/oop.inline.hpp"
40
41
inline oop ShenandoahBarrierSet::resolve_forwarded_not_null(oop p) {
42
return ShenandoahForwarding::get_forwardee(p);
43
}
44
45
inline oop ShenandoahBarrierSet::resolve_forwarded(oop p) {
46
if (p != NULL) {
47
return resolve_forwarded_not_null(p);
48
} else {
49
return p;
50
}
51
}
52
53
inline oop ShenandoahBarrierSet::resolve_forwarded_not_null_mutator(oop p) {
54
return ShenandoahForwarding::get_forwardee_mutator(p);
55
}
56
57
template <class T>
58
inline oop ShenandoahBarrierSet::load_reference_barrier_mutator(oop obj, T* load_addr) {
59
assert(ShenandoahLoadRefBarrier, "should be enabled");
60
shenandoah_assert_in_cset(load_addr, obj);
61
62
oop fwd = resolve_forwarded_not_null_mutator(obj);
63
if (obj == fwd) {
64
assert(_heap->is_evacuation_in_progress(),
65
"evac should be in progress");
66
Thread* const t = Thread::current();
67
ShenandoahEvacOOMScope scope(t);
68
fwd = _heap->evacuate_object(obj, t);
69
}
70
71
if (load_addr != NULL && fwd != obj) {
72
// Since we are here and we know the load address, update the reference.
73
ShenandoahHeap::cas_oop(fwd, load_addr, obj);
74
}
75
76
return fwd;
77
}
78
79
inline oop ShenandoahBarrierSet::load_reference_barrier(oop obj) {
80
if (!ShenandoahLoadRefBarrier) {
81
return obj;
82
}
83
if (_heap->has_forwarded_objects() &&
84
_heap->in_collection_set(obj)) { // Subsumes NULL-check
85
assert(obj != NULL, "cset check must have subsumed NULL-check");
86
oop fwd = resolve_forwarded_not_null(obj);
87
// TODO: It should not be necessary to check evac-in-progress here.
88
// We do it for mark-compact, which may have forwarded objects,
89
// and objects in cset and gets here via runtime barriers.
90
// We can probably fix this as soon as mark-compact has its own
91
// marking phase.
92
if (obj == fwd && _heap->is_evacuation_in_progress()) {
93
Thread* t = Thread::current();
94
ShenandoahEvacOOMScope oom_evac_scope(t);
95
return _heap->evacuate_object(obj, t);
96
}
97
return fwd;
98
}
99
return obj;
100
}
101
102
template <class T>
103
inline oop ShenandoahBarrierSet::load_reference_barrier(DecoratorSet decorators, oop obj, T* load_addr) {
104
if (obj == NULL) {
105
return NULL;
106
}
107
108
// Prevent resurrection of unreachable phantom (i.e. weak-native) references.
109
if ((decorators & ON_PHANTOM_OOP_REF) != 0 &&
110
_heap->is_concurrent_weak_root_in_progress() &&
111
!_heap->marking_context()->is_marked(obj)) {
112
return NULL;
113
}
114
115
// Prevent resurrection of unreachable weak references.
116
if ((decorators & ON_WEAK_OOP_REF) != 0 &&
117
_heap->is_concurrent_weak_root_in_progress() &&
118
!_heap->marking_context()->is_marked_strong(obj)) {
119
return NULL;
120
}
121
122
// Prevent resurrection of unreachable objects that are visited during
123
// concurrent class-unloading.
124
if ((decorators & AS_NO_KEEPALIVE) != 0 &&
125
_heap->is_evacuation_in_progress() &&
126
!_heap->marking_context()->is_marked(obj)) {
127
return obj;
128
}
129
130
oop fwd = load_reference_barrier(obj);
131
if (ShenandoahSelfFixing && load_addr != NULL && fwd != obj) {
132
// Since we are here and we know the load address, update the reference.
133
ShenandoahHeap::cas_oop(fwd, load_addr, obj);
134
}
135
136
return fwd;
137
}
138
139
inline void ShenandoahBarrierSet::enqueue(oop obj) {
140
assert(obj != NULL, "checked by caller");
141
assert(_satb_mark_queue_set.is_active(), "only get here when SATB active");
142
143
// Filter marked objects before hitting the SATB queues. The same predicate would
144
// be used by SATBMQ::filter to eliminate already marked objects downstream, but
145
// filtering here helps to avoid wasteful SATB queueing work to begin with.
146
if (!_heap->requires_marking(obj)) return;
147
148
SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(Thread::current());
149
_satb_mark_queue_set.enqueue_known_active(queue, obj);
150
}
151
152
template <DecoratorSet decorators, typename T>
153
inline void ShenandoahBarrierSet::satb_barrier(T *field) {
154
if (HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value ||
155
HasDecorator<decorators, AS_NO_KEEPALIVE>::value) {
156
return;
157
}
158
if (ShenandoahSATBBarrier && _heap->is_concurrent_mark_in_progress()) {
159
T heap_oop = RawAccess<>::oop_load(field);
160
if (!CompressedOops::is_null(heap_oop)) {
161
enqueue(CompressedOops::decode(heap_oop));
162
}
163
}
164
}
165
166
inline void ShenandoahBarrierSet::satb_enqueue(oop value) {
167
if (value != NULL && ShenandoahSATBBarrier && _heap->is_concurrent_mark_in_progress()) {
168
enqueue(value);
169
}
170
}
171
172
inline void ShenandoahBarrierSet::iu_barrier(oop obj) {
173
if (ShenandoahIUBarrier && obj != NULL && _heap->is_concurrent_mark_in_progress()) {
174
enqueue(obj);
175
}
176
}
177
178
inline void ShenandoahBarrierSet::keep_alive_if_weak(DecoratorSet decorators, oop value) {
179
assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known");
180
const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0;
181
const bool peek = (decorators & AS_NO_KEEPALIVE) != 0;
182
if (!peek && !on_strong_oop_ref) {
183
satb_enqueue(value);
184
}
185
}
186
187
template <typename T>
188
inline oop ShenandoahBarrierSet::oop_load(DecoratorSet decorators, T* addr) {
189
oop value = RawAccess<>::oop_load(addr);
190
value = load_reference_barrier(decorators, value, addr);
191
keep_alive_if_weak(decorators, value);
192
return value;
193
}
194
195
template <typename T>
196
inline oop ShenandoahBarrierSet::oop_cmpxchg(DecoratorSet decorators, T* addr, oop compare_value, oop new_value) {
197
iu_barrier(new_value);
198
oop res;
199
oop expected = compare_value;
200
do {
201
compare_value = expected;
202
res = RawAccess<>::oop_atomic_cmpxchg(addr, compare_value, new_value);
203
expected = res;
204
} while ((compare_value != expected) && (resolve_forwarded(compare_value) == resolve_forwarded(expected)));
205
206
// Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway,
207
// because it must be the previous value.
208
res = load_reference_barrier(decorators, res, reinterpret_cast<T*>(NULL));
209
satb_enqueue(res);
210
return res;
211
}
212
213
template <typename T>
214
inline oop ShenandoahBarrierSet::oop_xchg(DecoratorSet decorators, T* addr, oop new_value) {
215
iu_barrier(new_value);
216
oop previous = RawAccess<>::oop_atomic_xchg(addr, new_value);
217
// Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway,
218
// because it must be the previous value.
219
previous = load_reference_barrier<T>(decorators, previous, reinterpret_cast<T*>(NULL));
220
satb_enqueue(previous);
221
return previous;
222
}
223
224
template <DecoratorSet decorators, typename BarrierSetT>
225
template <typename T>
226
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(T* addr) {
227
assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "must be absent");
228
ShenandoahBarrierSet* const bs = ShenandoahBarrierSet::barrier_set();
229
return bs->oop_load(decorators, addr);
230
}
231
232
template <DecoratorSet decorators, typename BarrierSetT>
233
template <typename T>
234
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap(T* addr) {
235
assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "must be absent");
236
ShenandoahBarrierSet* const bs = ShenandoahBarrierSet::barrier_set();
237
return bs->oop_load(decorators, addr);
238
}
239
240
template <DecoratorSet decorators, typename BarrierSetT>
241
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap_at(oop base, ptrdiff_t offset) {
242
ShenandoahBarrierSet* const bs = ShenandoahBarrierSet::barrier_set();
243
DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset);
244
return bs->oop_load(resolved_decorators, AccessInternal::oop_field_addr<decorators>(base, offset));
245
}
246
247
template <DecoratorSet decorators, typename BarrierSetT>
248
template <typename T>
249
inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_not_in_heap(T* addr, oop value) {
250
shenandoah_assert_marked_if(NULL, value, !CompressedOops::is_null(value) && ShenandoahHeap::heap()->is_evacuation_in_progress());
251
shenandoah_assert_not_in_cset_if(addr, value, value != NULL && !ShenandoahHeap::heap()->cancelled_gc());
252
ShenandoahBarrierSet* const bs = ShenandoahBarrierSet::barrier_set();
253
bs->iu_barrier(value);
254
bs->satb_barrier<decorators>(addr);
255
Raw::oop_store(addr, value);
256
}
257
258
template <DecoratorSet decorators, typename BarrierSetT>
259
template <typename T>
260
inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_in_heap(T* addr, oop value) {
261
shenandoah_assert_not_in_cset_loc_except(addr, ShenandoahHeap::heap()->cancelled_gc());
262
shenandoah_assert_not_forwarded_except (addr, value, value == NULL || ShenandoahHeap::heap()->cancelled_gc() || !ShenandoahHeap::heap()->is_concurrent_mark_in_progress());
263
shenandoah_assert_not_in_cset_except (addr, value, value == NULL || ShenandoahHeap::heap()->cancelled_gc() || !ShenandoahHeap::heap()->is_concurrent_mark_in_progress());
264
265
oop_store_not_in_heap(addr, value);
266
}
267
268
template <DecoratorSet decorators, typename BarrierSetT>
269
inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) {
270
oop_store_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), value);
271
}
272
273
template <DecoratorSet decorators, typename BarrierSetT>
274
template <typename T>
275
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_not_in_heap(T* addr, oop compare_value, oop new_value) {
276
assert((decorators & (AS_NO_KEEPALIVE | ON_UNKNOWN_OOP_REF)) == 0, "must be absent");
277
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
278
return bs->oop_cmpxchg(decorators, addr, compare_value, new_value);
279
}
280
281
template <DecoratorSet decorators, typename BarrierSetT>
282
template <typename T>
283
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(T* addr, oop compare_value, oop new_value) {
284
assert((decorators & (AS_NO_KEEPALIVE | ON_UNKNOWN_OOP_REF)) == 0, "must be absent");
285
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
286
return bs->oop_cmpxchg(decorators, addr, compare_value, new_value);
287
}
288
289
template <DecoratorSet decorators, typename BarrierSetT>
290
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_at(oop base, ptrdiff_t offset, oop compare_value, oop new_value) {
291
assert((decorators & AS_NO_KEEPALIVE) == 0, "must be absent");
292
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
293
DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset);
294
return bs->oop_cmpxchg(resolved_decorators, AccessInternal::oop_field_addr<decorators>(base, offset), compare_value, new_value);
295
}
296
297
template <DecoratorSet decorators, typename BarrierSetT>
298
template <typename T>
299
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_not_in_heap(T* addr, oop new_value) {
300
assert((decorators & (AS_NO_KEEPALIVE | ON_UNKNOWN_OOP_REF)) == 0, "must be absent");
301
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
302
return bs->oop_xchg(decorators, addr, new_value);
303
}
304
305
template <DecoratorSet decorators, typename BarrierSetT>
306
template <typename T>
307
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(T* addr, oop new_value) {
308
assert((decorators & (AS_NO_KEEPALIVE | ON_UNKNOWN_OOP_REF)) == 0, "must be absent");
309
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
310
return bs->oop_xchg(decorators, addr, new_value);
311
}
312
313
template <DecoratorSet decorators, typename BarrierSetT>
314
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_at(oop base, ptrdiff_t offset, oop new_value) {
315
assert((decorators & AS_NO_KEEPALIVE) == 0, "must be absent");
316
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
317
DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset);
318
return bs->oop_xchg(resolved_decorators, AccessInternal::oop_field_addr<decorators>(base, offset), new_value);
319
}
320
321
// Clone barrier support
322
template <DecoratorSet decorators, typename BarrierSetT>
323
void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
324
if (ShenandoahCloneBarrier) {
325
ShenandoahBarrierSet::barrier_set()->clone_barrier_runtime(src);
326
}
327
Raw::clone(src, dst, size);
328
}
329
330
template <DecoratorSet decorators, typename BarrierSetT>
331
template <typename T>
332
bool ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
333
arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
334
size_t length) {
335
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
336
bs->arraycopy_barrier(arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw),
337
arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw),
338
length);
339
return Raw::oop_arraycopy_in_heap(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
340
}
341
342
template <class T, bool HAS_FWD, bool EVAC, bool ENQUEUE>
343
void ShenandoahBarrierSet::arraycopy_work(T* src, size_t count) {
344
assert(HAS_FWD == _heap->has_forwarded_objects(), "Forwarded object status is sane");
345
346
Thread* thread = Thread::current();
347
SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(thread);
348
ShenandoahMarkingContext* ctx = _heap->marking_context();
349
const ShenandoahCollectionSet* const cset = _heap->collection_set();
350
T* end = src + count;
351
for (T* elem_ptr = src; elem_ptr < end; elem_ptr++) {
352
T o = RawAccess<>::oop_load(elem_ptr);
353
if (!CompressedOops::is_null(o)) {
354
oop obj = CompressedOops::decode_not_null(o);
355
if (HAS_FWD && cset->is_in(obj)) {
356
oop fwd = resolve_forwarded_not_null(obj);
357
if (EVAC && obj == fwd) {
358
fwd = _heap->evacuate_object(obj, thread);
359
}
360
assert(obj != fwd || _heap->cancelled_gc(), "must be forwarded");
361
oop witness = ShenandoahHeap::cas_oop(fwd, elem_ptr, o);
362
obj = fwd;
363
}
364
if (ENQUEUE && !ctx->is_marked_strong(obj)) {
365
_satb_mark_queue_set.enqueue_known_active(queue, obj);
366
}
367
}
368
}
369
}
370
371
template <class T>
372
void ShenandoahBarrierSet::arraycopy_barrier(T* src, T* dst, size_t count) {
373
if (count == 0) {
374
return;
375
}
376
int gc_state = _heap->gc_state();
377
if ((gc_state & ShenandoahHeap::MARKING) != 0) {
378
arraycopy_marking(src, dst, count);
379
} else if ((gc_state & ShenandoahHeap::EVACUATION) != 0) {
380
arraycopy_evacuation(src, count);
381
} else if ((gc_state & ShenandoahHeap::UPDATEREFS) != 0) {
382
arraycopy_update(src, count);
383
}
384
}
385
386
template <class T>
387
void ShenandoahBarrierSet::arraycopy_marking(T* src, T* dst, size_t count) {
388
assert(_heap->is_concurrent_mark_in_progress(), "only during marking");
389
T* array = ShenandoahSATBBarrier ? dst : src;
390
if (!_heap->marking_context()->allocated_after_mark_start(reinterpret_cast<HeapWord*>(array))) {
391
arraycopy_work<T, false, false, true>(array, count);
392
}
393
}
394
395
inline bool ShenandoahBarrierSet::need_bulk_update(HeapWord* ary) {
396
return ary < _heap->heap_region_containing(ary)->get_update_watermark();
397
}
398
399
template <class T>
400
void ShenandoahBarrierSet::arraycopy_evacuation(T* src, size_t count) {
401
assert(_heap->is_evacuation_in_progress(), "only during evacuation");
402
if (need_bulk_update(reinterpret_cast<HeapWord*>(src))) {
403
ShenandoahEvacOOMScope oom_evac;
404
arraycopy_work<T, true, true, false>(src, count);
405
}
406
}
407
408
template <class T>
409
void ShenandoahBarrierSet::arraycopy_update(T* src, size_t count) {
410
assert(_heap->is_update_refs_in_progress(), "only during update-refs");
411
if (need_bulk_update(reinterpret_cast<HeapWord*>(src))) {
412
arraycopy_work<T, true, false, false>(src, count);
413
}
414
}
415
416
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
417
418