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 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
26
27 #include "gc/shared/barrierSet.hpp"
28 #include "gc/shenandoah/brooksPointer.inline.hpp"
29 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
30 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
31
32 bool ShenandoahBarrierSet::need_update_refs_barrier() {
33 return _heap->is_update_refs_in_progress() ||
34 _heap->is_concurrent_traversal_in_progress() ||
35 (_heap->is_concurrent_mark_in_progress() && _heap->has_forwarded_objects());
36 }
37
38 inline oop ShenandoahBarrierSet::resolve_forwarded_not_null(oop p) {
39 return BrooksPointer::forwardee(p);
40 }
41
42 inline oop ShenandoahBarrierSet::resolve_forwarded(oop p) {
43 if (((HeapWord*) p) != NULL) {
44 return resolve_forwarded_not_null(p);
45 } else {
46 return p;
47 }
48 }
49
50 template <DecoratorSet decorators, typename BarrierSetT>
51 template <typename T>
52 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value) {
53 oop res;
54 oop expected = compare_value;
55 do {
56 compare_value = expected;
57 res = Raw::oop_atomic_cmpxchg(new_value, addr, compare_value);
58 expected = res;
59 } while ((! oopDesc::unsafe_equals(compare_value, expected)) && oopDesc::unsafe_equals(resolve_forwarded(compare_value), resolve_forwarded(expected)));
60 if (oopDesc::unsafe_equals(expected, compare_value)) {
61 if (ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value)) {
62 ShenandoahBarrierSet::barrier_set()->enqueue(compare_value);
63 }
64 }
65 return res;
66 }
67
68 template <DecoratorSet decorators, typename BarrierSetT>
69 template <typename T>
74 ShenandoahBarrierSet::barrier_set()->enqueue(previous);
75 }
76 }
77 return previous;
78 }
79
80 template <DecoratorSet decorators, typename BarrierSetT>
81 template <typename T>
82 void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
83 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
84 size_t length) {
85 if (!CompressedOops::is_null(src_obj)) {
86 src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj));
87 }
88 if (!CompressedOops::is_null(dst_obj)) {
89 dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj));
90 }
91 Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
92 }
93
94 template <typename T>
95 bool ShenandoahBarrierSet::arraycopy_loop_1(T* src, T* dst, size_t length, Klass* bound,
96 bool checkcast, bool satb, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
97 if (checkcast) {
98 return arraycopy_loop_2<T, true>(src, dst, length, bound, satb, storeval_mode);
99 } else {
100 return arraycopy_loop_2<T, false>(src, dst, length, bound, satb, storeval_mode);
101 }
102 }
103
104 template <typename T, bool CHECKCAST>
105 bool ShenandoahBarrierSet::arraycopy_loop_2(T* src, T* dst, size_t length, Klass* bound,
106 bool satb, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
107 if (satb) {
108 return arraycopy_loop_3<T, CHECKCAST, true>(src, dst, length, bound, storeval_mode);
109 } else {
110 return arraycopy_loop_3<T, CHECKCAST, false>(src, dst, length, bound, storeval_mode);
111 }
112 }
113
114 template <typename T, bool CHECKCAST, bool SATB>
115 bool ShenandoahBarrierSet::arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound,
116 ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
117 switch (storeval_mode) {
118 case NONE:
119 return arraycopy_loop<T, CHECKCAST, SATB, NONE>(src, dst, length, bound);
120 case READ_BARRIER:
121 return arraycopy_loop<T, CHECKCAST, SATB, READ_BARRIER>(src, dst, length, bound);
122 case WRITE_BARRIER:
123 return arraycopy_loop<T, CHECKCAST, SATB, WRITE_BARRIER>(src, dst, length, bound);
124 default:
125 ShouldNotReachHere();
126 return true; // happy compiler
127 }
128 }
129
130 template <typename T, bool CHECKCAST, bool SATB, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE>
131 bool ShenandoahBarrierSet::arraycopy_loop(T* src, T* dst, size_t length, Klass* bound) {
132 Thread* thread = Thread::current();
133
134 ShenandoahEvacOOMScope oom_evac_scope;
135
136 // We need to handle four cases:
137 //
138 // a) src < dst, intersecting, can only copy backward only
139 // [...src...]
140 // [...dst...]
141 //
142 // b) src < dst, non-intersecting, can copy forward/backward
143 // [...src...]
144 // [...dst...]
145 //
146 // c) src > dst, intersecting, can copy forward only
147 // [...src...]
148 // [...dst...]
149 //
150 // d) src > dst, non-intersecting, can copy forward/backward
151 // [...src...]
152 // [...dst...]
153 //
154 if (src > dst) {
155 // copy forward:
156 T* cur_src = src;
157 T* cur_dst = dst;
158 T* src_end = src + length;
159 for (; cur_src < src_end; cur_src++, cur_dst++) {
160 if (!arraycopy_element<T, CHECKCAST, SATB, STOREVAL_MODE>(cur_src, cur_dst, bound, thread)) {
161 return false;
162 }
163 }
164 } else {
165 // copy backward:
166 T* cur_src = src + length - 1;
167 T* cur_dst = dst + length - 1;
168 for (; cur_src >= src; cur_src--, cur_dst--) {
169 if (!arraycopy_element<T, CHECKCAST, SATB, STOREVAL_MODE>(cur_src, cur_dst, bound, thread)) {
170 return false;
171 }
172 }
173 }
174 return true;
175 }
176
177 template <typename T, bool CHECKCAST, bool SATB, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE>
178 bool ShenandoahBarrierSet::arraycopy_element(T* cur_src, T* cur_dst, Klass* bound, Thread* thread) {
179 T o = RawAccess<>::oop_load(cur_src);
180
181 if (SATB) {
182 T prev = RawAccess<>::oop_load(cur_dst);
183 if (!CompressedOops::is_null(prev)) {
184 oop prev_obj = CompressedOops::decode_not_null(prev);
185 enqueue(prev_obj);
186 }
187 }
188
189 if (!CompressedOops::is_null(o)) {
190 oop obj = CompressedOops::decode_not_null(o);
191
192 if (CHECKCAST) {
193 assert(bound != NULL, "need element klass for checkcast");
194 if (!oopDesc::is_instanceof_or_null(obj, bound)) {
195 return false;
196 }
197 }
198
199 switch (STOREVAL_MODE) {
200 case NONE:
201 break;
202 case READ_BARRIER:
203 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
204 break;
205 case WRITE_BARRIER:
206 if (_heap->in_collection_set(obj)) {
207 oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
208 if (oopDesc::unsafe_equals(forw, obj)) {
209 forw = _heap->evacuate_object(forw, thread);
210 }
211 obj = forw;
212 }
213 enqueue(obj);
214 break;
215 default:
216 ShouldNotReachHere();
217 }
218
219 RawAccess<IS_NOT_NULL>::oop_store(cur_dst, obj);
220 } else {
221 // Store null.
222 RawAccess<>::oop_store(cur_dst, o);
223 }
224 return true;
225 }
226
227 // Clone barrier support
228 template <DecoratorSet decorators, typename BarrierSetT>
229 void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
230 src = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src));
231 dst = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst));
232 Raw::clone(src, dst, size);
233 ShenandoahBarrierSet::barrier_set()->write_region(MemRegion((HeapWord*) dst, size));
234 }
235
236
237 template <DecoratorSet decorators, typename BarrierSetT>
238 template <typename T>
239 bool ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
240 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
241 size_t length) {
242 ShenandoahHeap* heap = ShenandoahHeap::heap();
243 if (!CompressedOops::is_null(src_obj)) {
244 src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj));
245 }
246 if (!CompressedOops::is_null(dst_obj)) {
247 dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj));
248 }
249
250 bool satb = ShenandoahSATBBarrier && heap->is_concurrent_mark_in_progress();
251 bool checkcast = HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value;
252 ArrayCopyStoreValMode storeval_mode;
253 if (heap->has_forwarded_objects()) {
254 if (heap->is_concurrent_traversal_in_progress()) {
255 storeval_mode = WRITE_BARRIER;
256 } else if (heap->is_concurrent_mark_in_progress() || heap->is_update_refs_in_progress()) {
257 storeval_mode = READ_BARRIER;
258 } else {
259 assert(heap->is_idle() || heap->is_evacuation_in_progress(), "must not have anything in progress");
260 storeval_mode = NONE; // E.g. during evac or outside cycle
261 }
262 } else {
263 assert(heap->is_stable() || heap->is_concurrent_mark_in_progress(), "must not have anything in progress");
264 storeval_mode = NONE;
265 }
266
267 if (!satb && !checkcast && storeval_mode == NONE) {
268 // Short-circuit to bulk copy.
269 return Raw::oop_arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
270 }
271
272 src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw);
273 dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw);
274
275 Klass* bound = objArrayOop(dst_obj)->element_klass();
276 ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
277 return bs->arraycopy_loop_1(src_raw, dst_raw, length, bound, checkcast, satb, storeval_mode);
278 }
279
280 #endif //SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
|
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 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
26
27 #include "gc/shared/barrierSet.hpp"
28 #include "gc/shenandoah/brooksPointer.inline.hpp"
29 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
30 #include "gc/shenandoah/shenandoahBaseBarrierSet.inline.hpp"
31 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
32
33 template <DecoratorSet decorators, typename BarrierSetT>
34 template <typename T>
35 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value) {
36 oop res;
37 oop expected = compare_value;
38 do {
39 compare_value = expected;
40 res = Raw::oop_atomic_cmpxchg(new_value, addr, compare_value);
41 expected = res;
42 } while ((! oopDesc::unsafe_equals(compare_value, expected)) && oopDesc::unsafe_equals(resolve_forwarded(compare_value), resolve_forwarded(expected)));
43 if (oopDesc::unsafe_equals(expected, compare_value)) {
44 if (ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value)) {
45 ShenandoahBarrierSet::barrier_set()->enqueue(compare_value);
46 }
47 }
48 return res;
49 }
50
51 template <DecoratorSet decorators, typename BarrierSetT>
52 template <typename T>
57 ShenandoahBarrierSet::barrier_set()->enqueue(previous);
58 }
59 }
60 return previous;
61 }
62
63 template <DecoratorSet decorators, typename BarrierSetT>
64 template <typename T>
65 void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
66 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
67 size_t length) {
68 if (!CompressedOops::is_null(src_obj)) {
69 src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj));
70 }
71 if (!CompressedOops::is_null(dst_obj)) {
72 dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj));
73 }
74 Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
75 }
76
77 // Clone barrier support
78 template <DecoratorSet decorators, typename BarrierSetT>
79 void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
80 src = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src));
81 dst = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst));
82 Raw::clone(src, dst, size);
83 ShenandoahBarrierSet::barrier_set()->write_region(MemRegion((HeapWord*) dst, size));
84 }
85
86
87 template <DecoratorSet decorators, typename BarrierSetT>
88 template <typename T>
89 bool ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
90 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
91 size_t length) {
92 ShenandoahHeap* heap = ShenandoahHeap::heap();
93 if (!CompressedOops::is_null(src_obj)) {
94 src_obj = arrayOop(ShenandoahBaseBarrierSet::barrier_set()->read_barrier(src_obj));
95 }
96 if (!CompressedOops::is_null(dst_obj)) {
97 dst_obj = arrayOop(ShenandoahBaseBarrierSet::barrier_set()->write_barrier(dst_obj));
98 }
99
100 bool satb = ShenandoahSATBBarrier && heap->is_concurrent_mark_in_progress();
101 bool checkcast = HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value;
102 ArrayCopyStoreValMode storeval_mode;
103 if (heap->has_forwarded_objects()) {
104 if (heap->is_concurrent_traversal_in_progress()) {
105 storeval_mode = WRITE_BARRIER;
106 } else if (heap->is_concurrent_mark_in_progress() || heap->is_update_refs_in_progress()) {
107 storeval_mode = READ_BARRIER;
108 } else {
109 assert(heap->is_idle() || heap->is_evacuation_in_progress(), "must not have anything in progress");
110 storeval_mode = NONE; // E.g. during evac or outside cycle
111 }
112 } else {
113 assert(heap->is_stable() || heap->is_concurrent_mark_in_progress(), "must not have anything in progress");
114 storeval_mode = NONE;
115 }
116
117 if (!satb && !checkcast && storeval_mode == NONE) {
118 // Short-circuit to bulk copy.
119 return Raw::oop_arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
120 }
121
122 src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw);
123 dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw);
124
125 Klass* bound = objArrayOop(dst_obj)->element_klass();
126 ShenandoahBaseBarrierSet* bs = ShenandoahBaseBarrierSet::barrier_set();
127 return bs->arraycopy_loop_1(src_raw, dst_raw, length, bound, checkcast, satb, storeval_mode);
128 }
129
130 #endif //SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
|