111 T o = RawAccess<>::oop_load(p); |
111 T o = RawAccess<>::oop_load(p); |
112 if (!CompressedOops::is_null(o)) { |
112 if (!CompressedOops::is_null(o)) { |
113 oop heap_oop = CompressedOops::decode_not_null(o); |
113 oop heap_oop = CompressedOops::decode_not_null(o); |
114 if (in_collection_set(heap_oop)) { |
114 if (in_collection_set(heap_oop)) { |
115 oop forwarded_oop = ShenandoahBarrierSet::resolve_forwarded_not_null(heap_oop); |
115 oop forwarded_oop = ShenandoahBarrierSet::resolve_forwarded_not_null(heap_oop); |
116 if (oopDesc::equals_raw(forwarded_oop, heap_oop)) { |
116 if (forwarded_oop == heap_oop) { |
117 forwarded_oop = evacuate_object(heap_oop, Thread::current()); |
117 forwarded_oop = evacuate_object(heap_oop, Thread::current()); |
118 } |
118 } |
119 oop prev = cas_oop(forwarded_oop, p, heap_oop); |
119 oop prev = cas_oop(forwarded_oop, p, heap_oop); |
120 if (oopDesc::equals_raw(prev, heap_oop)) { |
120 if (prev == heap_oop) { |
121 return forwarded_oop; |
121 return forwarded_oop; |
122 } else { |
122 } else { |
123 return NULL; |
123 return NULL; |
124 } |
124 } |
125 } |
125 } |
144 shenandoah_assert_not_in_cset_loc_except(p, !is_in(p) || is_full_gc_in_progress() || is_degenerated_gc_in_progress()); |
144 shenandoah_assert_not_in_cset_loc_except(p, !is_in(p) || is_full_gc_in_progress() || is_degenerated_gc_in_progress()); |
145 shenandoah_assert_correct(p, heap_oop); |
145 shenandoah_assert_correct(p, heap_oop); |
146 |
146 |
147 if (in_collection_set(heap_oop)) { |
147 if (in_collection_set(heap_oop)) { |
148 oop forwarded_oop = ShenandoahBarrierSet::resolve_forwarded_not_null(heap_oop); |
148 oop forwarded_oop = ShenandoahBarrierSet::resolve_forwarded_not_null(heap_oop); |
149 if (oopDesc::equals_raw(forwarded_oop, heap_oop)) { |
149 if (forwarded_oop == heap_oop) { |
150 // E.g. during evacuation. |
150 // E.g. during evacuation. |
151 return forwarded_oop; |
151 return forwarded_oop; |
152 } |
152 } |
153 |
153 |
154 shenandoah_assert_forwarded_except(p, heap_oop, is_full_gc_in_progress() || is_degenerated_gc_in_progress()); |
154 shenandoah_assert_forwarded_except(p, heap_oop, is_full_gc_in_progress() || is_degenerated_gc_in_progress()); |
157 |
157 |
158 // If this fails, another thread wrote to p before us, it will be logged in SATB and the |
158 // If this fails, another thread wrote to p before us, it will be logged in SATB and the |
159 // reference be updated later. |
159 // reference be updated later. |
160 oop witness = cas_oop(forwarded_oop, p, heap_oop); |
160 oop witness = cas_oop(forwarded_oop, p, heap_oop); |
161 |
161 |
162 if (!oopDesc::equals_raw(witness, heap_oop)) { |
162 if (witness != heap_oop) { |
163 // CAS failed, someone had beat us to it. Normally, we would return the failure witness, |
163 // CAS failed, someone had beat us to it. Normally, we would return the failure witness, |
164 // because that would be the proper write of to-space object, enforced by strong barriers. |
164 // because that would be the proper write of to-space object, enforced by strong barriers. |
165 // However, there is a corner case with arraycopy. It can happen that a Java thread |
165 // However, there is a corner case with arraycopy. It can happen that a Java thread |
166 // beats us with an arraycopy, which first copies the array, which potentially contains |
166 // beats us with an arraycopy, which first copies the array, which potentially contains |
167 // from-space refs, and only afterwards updates all from-space refs to to-space refs, |
167 // from-space refs, and only afterwards updates all from-space refs to to-space refs, |
277 Copy::aligned_disjoint_words((HeapWord*) p, copy, size); |
277 Copy::aligned_disjoint_words((HeapWord*) p, copy, size); |
278 |
278 |
279 // Try to install the new forwarding pointer. |
279 // Try to install the new forwarding pointer. |
280 oop copy_val = oop(copy); |
280 oop copy_val = oop(copy); |
281 oop result = ShenandoahForwarding::try_update_forwardee(p, copy_val); |
281 oop result = ShenandoahForwarding::try_update_forwardee(p, copy_val); |
282 if (oopDesc::equals_raw(result, copy_val)) { |
282 if (result == copy_val) { |
283 // Successfully evacuated. Our copy is now the public one! |
283 // Successfully evacuated. Our copy is now the public one! |
284 shenandoah_assert_correct(NULL, copy_val); |
284 shenandoah_assert_correct(NULL, copy_val); |
285 return copy_val; |
285 return copy_val; |
286 } else { |
286 } else { |
287 // Failed to evacuate. We need to deal with the object that is left behind. Since this |
287 // Failed to evacuate. We need to deal with the object that is left behind. Since this |