142 } |
142 } |
143 } |
143 } |
144 #endif // ASSERT |
144 #endif // ASSERT |
145 |
145 |
146 void G1ParScanThreadState::trim_queue() { |
146 void G1ParScanThreadState::trim_queue() { |
147 assert(_evac_failure_cl != NULL, "not set"); |
|
148 |
|
149 StarTask ref; |
147 StarTask ref; |
150 do { |
148 do { |
151 // Drain the overflow stack first, so other threads can steal. |
149 // Drain the overflow stack first, so other threads can steal. |
152 while (_refs->pop_overflow(ref)) { |
150 while (_refs->pop_overflow(ref)) { |
153 dispatch_reference(ref); |
151 dispatch_reference(ref); |
220 if (obj_ptr == NULL) { |
218 if (obj_ptr == NULL) { |
221 obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context); |
219 obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context); |
222 if (obj_ptr == NULL) { |
220 if (obj_ptr == NULL) { |
223 // This will either forward-to-self, or detect that someone else has |
221 // This will either forward-to-self, or detect that someone else has |
224 // installed a forwarding pointer. |
222 // installed a forwarding pointer. |
225 return _g1h->handle_evacuation_failure_par(this, old); |
223 return handle_evacuation_failure_par(old, old_mark); |
226 } |
224 } |
227 } |
225 } |
228 } |
226 } |
229 |
227 |
230 assert(obj_ptr != NULL, "when we get here, allocation should have succeeded"); |
228 assert(obj_ptr != NULL, "when we get here, allocation should have succeeded"); |
234 // Should this evacuation fail? |
232 // Should this evacuation fail? |
235 if (_g1h->evacuation_should_fail()) { |
233 if (_g1h->evacuation_should_fail()) { |
236 // Doing this after all the allocation attempts also tests the |
234 // Doing this after all the allocation attempts also tests the |
237 // undo_allocation() method too. |
235 // undo_allocation() method too. |
238 _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); |
236 _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); |
239 return _g1h->handle_evacuation_failure_par(this, old); |
237 return handle_evacuation_failure_par(old, old_mark); |
240 } |
238 } |
241 #endif // !PRODUCT |
239 #endif // !PRODUCT |
242 |
240 |
243 // We're going to allocate linearly, so might as well prefetch ahead. |
241 // We're going to allocate linearly, so might as well prefetch ahead. |
244 Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes); |
242 Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes); |
299 } else { |
297 } else { |
300 _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); |
298 _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); |
301 return forward_ptr; |
299 return forward_ptr; |
302 } |
300 } |
303 } |
301 } |
|
302 |
|
303 oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) { |
|
304 assert(_g1h->obj_in_cs(old), |
|
305 err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old))); |
|
306 |
|
307 oop forward_ptr = old->forward_to_atomic(old); |
|
308 if (forward_ptr == NULL) { |
|
309 // Forward-to-self succeeded. We are the "owner" of the object. |
|
310 HeapRegion* r = _g1h->heap_region_containing(old); |
|
311 |
|
312 if (!r->evacuation_failed()) { |
|
313 r->set_evacuation_failed(true); |
|
314 _g1h->hr_printer()->evac_failure(r); |
|
315 } |
|
316 |
|
317 _g1h->preserve_mark_during_evac_failure(_queue_num, old, m); |
|
318 |
|
319 _scanner.set_region(r); |
|
320 old->oop_iterate_backwards(&_scanner); |
|
321 |
|
322 return old; |
|
323 } else { |
|
324 // Forward-to-self failed. Either someone else managed to allocate |
|
325 // space for this object (old != forward_ptr) or they beat us in |
|
326 // self-forwarding it (old == forward_ptr). |
|
327 assert(old == forward_ptr || !_g1h->obj_in_cs(forward_ptr), |
|
328 err_msg("Object " PTR_FORMAT " forwarded to: " PTR_FORMAT " " |
|
329 "should not be in the CSet", |
|
330 p2i(old), p2i(forward_ptr))); |
|
331 return forward_ptr; |
|
332 } |
|
333 } |
|
334 |