119 }
120
121 template <typename T, bool CHECKCAST, bool SATB>
122 bool ShenandoahBarrierSet::arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound,
123 bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
124 if (matrix) {
125 return arraycopy_loop_4<T, CHECKCAST, SATB, true>(src, dst, length, bound, storeval_mode);
126 } else {
127 return arraycopy_loop_4<T, CHECKCAST, SATB, false>(src, dst, length, bound, storeval_mode);
128 }
129 }
130
131 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX>
132 bool ShenandoahBarrierSet::arraycopy_loop_4(T* src, T* dst, size_t length, Klass* bound,
133 ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
134 switch (storeval_mode) {
135 case NONE:
136 return arraycopy_loop<T, CHECKCAST, SATB, MATRIX, NONE>(src, dst, length, bound);
137 case READ_BARRIER:
138 return arraycopy_loop<T, CHECKCAST, SATB, MATRIX, READ_BARRIER>(src, dst, length, bound);
139 case WRITE_BARRIER_MAYBE_ENQUEUE:
140 return arraycopy_loop<T, CHECKCAST, SATB, MATRIX, WRITE_BARRIER_MAYBE_ENQUEUE>(src, dst, length, bound);
141 case WRITE_BARRIER_ALWAYS_ENQUEUE:
142 return arraycopy_loop<T, CHECKCAST, SATB, MATRIX, WRITE_BARRIER_ALWAYS_ENQUEUE>(src, dst, length, bound);
143 default:
144 ShouldNotReachHere();
145 return true; // happy compiler
146 }
147 }
148
149 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE>
150 bool ShenandoahBarrierSet::arraycopy_loop(T* src, T* dst, size_t length, Klass* bound) {
151 Thread* thread = Thread::current();
152
153 ShenandoahEvacOOMScope oom_evac_scope;
154
155 // We need to handle four cases:
156 //
157 // a) src < dst, intersecting, can only copy backward only
158 // [...src...]
159 // [...dst...]
160 //
161 // b) src < dst, non-intersecting, can copy forward/backward
162 // [...src...]
204 enqueue(prev_obj);
205 }
206 }
207
208 if (!CompressedOops::is_null(o)) {
209 oop obj = CompressedOops::decode_not_null(o);
210
211 if (CHECKCAST) {
212 assert(bound != NULL, "need element klass for checkcast");
213 if (!oopDesc::is_instanceof_or_null(obj, bound)) {
214 return false;
215 }
216 }
217
218 switch (STOREVAL_MODE) {
219 case NONE:
220 break;
221 case READ_BARRIER:
222 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
223 break;
224 case WRITE_BARRIER_MAYBE_ENQUEUE:
225 if (_heap->in_collection_set(obj)) {
226 oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
227 if (oopDesc::unsafe_equals(forw, obj)) {
228 bool evac;
229 forw = _heap->evacuate_object(forw, thread, evac);
230 if (evac) {
231 enqueue(forw);
232 }
233 }
234 obj = forw;
235 }
236 break;
237 case WRITE_BARRIER_ALWAYS_ENQUEUE:
238 if (_heap->in_collection_set(obj)) {
239 oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
240 if (oopDesc::unsafe_equals(forw, obj)) {
241 bool evac;
242 forw = _heap->evacuate_object(forw, thread, evac);
243 }
244 obj = forw;
245 }
246 enqueue(obj);
247 break;
248 default:
249 ShouldNotReachHere();
250 }
251
252 if (MATRIX) {
253 _heap->connection_matrix()->set_connected(cur_dst, obj);
254 }
255
256 RawAccess<OOP_NOT_NULL>::oop_store(cur_dst, obj);
257 } else {
258 // Store null.
259 RawAccess<>::oop_store(cur_dst, o);
260 }
261 return true;
262 }
273
274 template <DecoratorSet decorators, typename BarrierSetT>
275 template <typename T>
276 bool ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) {
277 assert(((HeapWord*)(void*) src_obj) <= (HeapWord*) src && (HeapWord*) src < (((HeapWord*)(void*) src_obj) + src_obj->size()), "pointer out of object bounds src_obj: %p, src: %p, size: %ul", (void*) src_obj, src, src_obj->size());
278 assert(((HeapWord*)(void*) dst_obj) <= (HeapWord*) dst && (HeapWord*) dst < (((HeapWord*)(void*) dst_obj) + dst_obj->size()), "pointer out of object bounds dst_obj: "/*POINTER_FORMAT", dst: "POINTER_FORMAT", length: "SIZE_FORMAT, p2i(dst_obj), p2i(dst), length*/);
279
280 ShenandoahHeap* heap = ShenandoahHeap::heap();
281
282 if (!CompressedOops::is_null(src_obj)) {
283 size_t src_offset = pointer_delta((void*) src, (void*) src_obj, sizeof(T));
284 src_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->read_barrier(src_obj));
285 src = ((T*)(void*) src_obj) + src_offset;
286 }
287 if (!CompressedOops::is_null(dst_obj)) {
288 size_t dst_offset = pointer_delta((void*) dst, (void*) dst_obj, sizeof(T));
289 dst_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(dst_obj));
290 dst = ((T*)(void*) dst_obj) + dst_offset;
291 }
292
293 bool satb = (ShenandoahSATBBarrier || ShenandoahConditionalSATBBarrier) && heap->is_concurrent_mark_in_progress();
294 bool checkcast = HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value;
295 ArrayCopyStoreValMode storeval_mode;
296 if (heap->has_forwarded_objects()) {
297 if (heap->is_concurrent_partial_in_progress()) {
298 storeval_mode = WRITE_BARRIER_MAYBE_ENQUEUE;
299 } else if (heap->is_concurrent_traversal_in_progress()) {
300 storeval_mode = WRITE_BARRIER_ALWAYS_ENQUEUE;
301 } else if (heap->is_concurrent_mark_in_progress() || heap->is_update_refs_in_progress()) {
302 storeval_mode = READ_BARRIER;
303 } else {
304 assert(heap->is_idle() || heap->is_evacuation_in_progress(), "must not have anything in progress");
305 storeval_mode = NONE; // E.g. during evac or outside cycle
306 }
307 } else {
308 assert(heap->is_stable() || heap->is_concurrent_mark_in_progress(), "must not have anything in progress");
309 storeval_mode = NONE;
310 }
311
312 if (!satb && !checkcast && !UseShenandoahMatrix && storeval_mode == NONE) {
313 // Short-circuit to bulk copy.
314 return Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length);
315 }
316
317 Klass* bound = objArrayOop(dst_obj)->element_klass();
318 ShenandoahBarrierSet* bs = (ShenandoahBarrierSet*) BarrierSet::barrier_set();
319 return bs->arraycopy_loop_1(src, dst, length, bound, checkcast, satb, UseShenandoahMatrix, storeval_mode);
320 }
|
119 }
120
121 template <typename T, bool CHECKCAST, bool SATB>
122 bool ShenandoahBarrierSet::arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound,
123 bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
124 if (matrix) {
125 return arraycopy_loop_4<T, CHECKCAST, SATB, true>(src, dst, length, bound, storeval_mode);
126 } else {
127 return arraycopy_loop_4<T, CHECKCAST, SATB, false>(src, dst, length, bound, storeval_mode);
128 }
129 }
130
131 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX>
132 bool ShenandoahBarrierSet::arraycopy_loop_4(T* src, T* dst, size_t length, Klass* bound,
133 ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
134 switch (storeval_mode) {
135 case NONE:
136 return arraycopy_loop<T, CHECKCAST, SATB, MATRIX, NONE>(src, dst, length, bound);
137 case READ_BARRIER:
138 return arraycopy_loop<T, CHECKCAST, SATB, MATRIX, READ_BARRIER>(src, dst, length, bound);
139 case WRITE_BARRIER:
140 return arraycopy_loop<T, CHECKCAST, SATB, MATRIX, WRITE_BARRIER>(src, dst, length, bound);
141 default:
142 ShouldNotReachHere();
143 return true; // happy compiler
144 }
145 }
146
147 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE>
148 bool ShenandoahBarrierSet::arraycopy_loop(T* src, T* dst, size_t length, Klass* bound) {
149 Thread* thread = Thread::current();
150
151 ShenandoahEvacOOMScope oom_evac_scope;
152
153 // We need to handle four cases:
154 //
155 // a) src < dst, intersecting, can only copy backward only
156 // [...src...]
157 // [...dst...]
158 //
159 // b) src < dst, non-intersecting, can copy forward/backward
160 // [...src...]
202 enqueue(prev_obj);
203 }
204 }
205
206 if (!CompressedOops::is_null(o)) {
207 oop obj = CompressedOops::decode_not_null(o);
208
209 if (CHECKCAST) {
210 assert(bound != NULL, "need element klass for checkcast");
211 if (!oopDesc::is_instanceof_or_null(obj, bound)) {
212 return false;
213 }
214 }
215
216 switch (STOREVAL_MODE) {
217 case NONE:
218 break;
219 case READ_BARRIER:
220 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
221 break;
222 case WRITE_BARRIER:
223 if (_heap->in_collection_set(obj)) {
224 oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
225 if (oopDesc::unsafe_equals(forw, obj)) {
226 bool evac;
227 forw = _heap->evacuate_object(forw, thread);
228 }
229 obj = forw;
230 }
231 enqueue(obj);
232 break;
233 default:
234 ShouldNotReachHere();
235 }
236
237 if (MATRIX) {
238 _heap->connection_matrix()->set_connected(cur_dst, obj);
239 }
240
241 RawAccess<OOP_NOT_NULL>::oop_store(cur_dst, obj);
242 } else {
243 // Store null.
244 RawAccess<>::oop_store(cur_dst, o);
245 }
246 return true;
247 }
258
259 template <DecoratorSet decorators, typename BarrierSetT>
260 template <typename T>
261 bool ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) {
262 assert(((HeapWord*)(void*) src_obj) <= (HeapWord*) src && (HeapWord*) src < (((HeapWord*)(void*) src_obj) + src_obj->size()), "pointer out of object bounds src_obj: %p, src: %p, size: %ul", (void*) src_obj, src, src_obj->size());
263 assert(((HeapWord*)(void*) dst_obj) <= (HeapWord*) dst && (HeapWord*) dst < (((HeapWord*)(void*) dst_obj) + dst_obj->size()), "pointer out of object bounds dst_obj: "/*POINTER_FORMAT", dst: "POINTER_FORMAT", length: "SIZE_FORMAT, p2i(dst_obj), p2i(dst), length*/);
264
265 ShenandoahHeap* heap = ShenandoahHeap::heap();
266
267 if (!CompressedOops::is_null(src_obj)) {
268 size_t src_offset = pointer_delta((void*) src, (void*) src_obj, sizeof(T));
269 src_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->read_barrier(src_obj));
270 src = ((T*)(void*) src_obj) + src_offset;
271 }
272 if (!CompressedOops::is_null(dst_obj)) {
273 size_t dst_offset = pointer_delta((void*) dst, (void*) dst_obj, sizeof(T));
274 dst_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(dst_obj));
275 dst = ((T*)(void*) dst_obj) + dst_offset;
276 }
277
278 bool satb = ShenandoahSATBBarrier && heap->is_concurrent_mark_in_progress();
279 bool checkcast = HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value;
280 ArrayCopyStoreValMode storeval_mode;
281 if (heap->has_forwarded_objects()) {
282 if (heap->is_concurrent_traversal_in_progress()) {
283 storeval_mode = WRITE_BARRIER;
284 } else if (heap->is_concurrent_mark_in_progress() || heap->is_update_refs_in_progress()) {
285 storeval_mode = READ_BARRIER;
286 } else {
287 assert(heap->is_idle() || heap->is_evacuation_in_progress(), "must not have anything in progress");
288 storeval_mode = NONE; // E.g. during evac or outside cycle
289 }
290 } else {
291 assert(heap->is_stable() || heap->is_concurrent_mark_in_progress(), "must not have anything in progress");
292 storeval_mode = NONE;
293 }
294
295 if (!satb && !checkcast && !UseShenandoahMatrix && storeval_mode == NONE) {
296 // Short-circuit to bulk copy.
297 return Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length);
298 }
299
300 Klass* bound = objArrayOop(dst_obj)->element_klass();
301 ShenandoahBarrierSet* bs = (ShenandoahBarrierSet*) BarrierSet::barrier_set();
302 return bs->arraycopy_loop_1(src, dst, length, bound, checkcast, satb, UseShenandoahMatrix, storeval_mode);
303 }
|