Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 4784:02838862dec8
7121623: G1: always be able to reliably calculate the length of a forwarded chunked array
Summary: Store the "next chunk start index" in the length field of the to-space object, instead of the from-space object, so that we can always reliably read the size of all from-space objects.
Reviewed-by: johnc, ysr, jmasa
author | tonyp |
---|---|
date | Sat, 07 Jan 2012 00:43:59 -0500 |
parents | 023652e49ac0 |
children | 97c00e21fecb |
comparison
equal
deleted
inserted
replaced
4783:023652e49ac0 | 4784:02838862dec8 |
---|---|
4414 | 4414 |
4415 size_t* surv_young_words = _par_scan_state->surviving_young_words(); | 4415 size_t* surv_young_words = _par_scan_state->surviving_young_words(); |
4416 surv_young_words[young_index] += word_sz; | 4416 surv_young_words[young_index] += word_sz; |
4417 | 4417 |
4418 if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { | 4418 if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { |
4419 arrayOop(old)->set_length(0); | 4419 // We keep track of the next start index in the length field of |
4420 // the to-space object. The actual length can be found in the | |
4421 // length field of the from-space object. | |
4422 arrayOop(obj)->set_length(0); | |
4420 oop* old_p = set_partial_array_mask(old); | 4423 oop* old_p = set_partial_array_mask(old); |
4421 _par_scan_state->push_on_queue(old_p); | 4424 _par_scan_state->push_on_queue(old_p); |
4422 } else { | 4425 } else { |
4423 // No point in using the slower heap_region_containing() method, | 4426 // No point in using the slower heap_region_containing() method, |
4424 // given that we know obj is in the heap. | 4427 // given that we know obj is in the heap. |
4518 template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(oop* p); | 4521 template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(oop* p); |
4519 template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(narrowOop* p); | 4522 template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(narrowOop* p); |
4520 | 4523 |
4521 template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { | 4524 template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { |
4522 assert(has_partial_array_mask(p), "invariant"); | 4525 assert(has_partial_array_mask(p), "invariant"); |
4523 oop old = clear_partial_array_mask(p); | 4526 oop from_obj = clear_partial_array_mask(p); |
4524 assert(old->is_objArray(), "must be obj array"); | 4527 |
4525 assert(old->is_forwarded(), "must be forwarded"); | 4528 assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap."); |
4526 assert(Universe::heap()->is_in_reserved(old), "must be in heap."); | 4529 assert(from_obj->is_objArray(), "must be obj array"); |
4527 | 4530 objArrayOop from_obj_array = objArrayOop(from_obj); |
4528 objArrayOop obj = objArrayOop(old->forwardee()); | 4531 // The from-space object contains the real length. |
4529 assert((void*)old != (void*)old->forwardee(), "self forwarding here?"); | 4532 int length = from_obj_array->length(); |
4530 // Process ParGCArrayScanChunk elements now | 4533 |
4531 // and push the remainder back onto queue | 4534 assert(from_obj->is_forwarded(), "must be forwarded"); |
4532 int start = arrayOop(old)->length(); | 4535 oop to_obj = from_obj->forwardee(); |
4533 int end = obj->length(); | 4536 assert(from_obj != to_obj, "should not be chunking self-forwarded objects"); |
4534 int remainder = end - start; | 4537 objArrayOop to_obj_array = objArrayOop(to_obj); |
4535 assert(start <= end, "just checking"); | 4538 // We keep track of the next start index in the length field of the |
4539 // to-space object. | |
4540 int next_index = to_obj_array->length(); | |
4541 assert(0 <= next_index && next_index < length, | |
4542 err_msg("invariant, next index: %d, length: %d", next_index, length)); | |
4543 | |
4544 int start = next_index; | |
4545 int end = length; | |
4546 int remainder = end - start; | |
4547 // We'll try not to push a range that's smaller than ParGCArrayScanChunk. | |
4536 if (remainder > 2 * ParGCArrayScanChunk) { | 4548 if (remainder > 2 * ParGCArrayScanChunk) { |
4537 // Test above combines last partial chunk with a full chunk | |
4538 end = start + ParGCArrayScanChunk; | 4549 end = start + ParGCArrayScanChunk; |
4539 arrayOop(old)->set_length(end); | 4550 to_obj_array->set_length(end); |
4540 // Push remainder. | 4551 // Push the remainder before we process the range in case another |
4541 oop* old_p = set_partial_array_mask(old); | 4552 // worker has run out of things to do and can steal it. |
4542 assert(arrayOop(old)->length() < obj->length(), "Empty push?"); | 4553 oop* from_obj_p = set_partial_array_mask(from_obj); |
4543 _par_scan_state->push_on_queue(old_p); | 4554 _par_scan_state->push_on_queue(from_obj_p); |
4544 } else { | 4555 } else { |
4545 // Restore length so that the heap remains parsable in | 4556 assert(length == end, "sanity"); |
4546 // case of evacuation failure. | 4557 // We'll process the final range for this object. Restore the length |
4547 arrayOop(old)->set_length(end); | 4558 // so that the heap remains parsable in case of evacuation failure. |
4548 } | 4559 to_obj_array->set_length(end); |
4549 _scanner.set_region(_g1->heap_region_containing_raw(obj)); | 4560 } |
4550 // process our set of indices (include header in first chunk) | 4561 _scanner.set_region(_g1->heap_region_containing_raw(to_obj)); |
4551 obj->oop_iterate_range(&_scanner, start, end); | 4562 // Process indexes [start,end). It will also process the header |
4563 // along with the first chunk (i.e., the chunk with start == 0). | |
4564 // Note that at this point the length field of to_obj_array is not | |
4565 // correct given that we are using it to keep track of the next | |
4566 // start index. oop_iterate_range() (thankfully!) ignores the length | |
4567 // field and only relies on the start / end parameters. It does | |
4568 // however return the size of the object which will be incorrect. So | |
4569 // we have to ignore it even if we wanted to use it. | |
4570 to_obj_array->oop_iterate_range(&_scanner, start, end); | |
4552 } | 4571 } |
4553 | 4572 |
4554 class G1ParEvacuateFollowersClosure : public VoidClosure { | 4573 class G1ParEvacuateFollowersClosure : public VoidClosure { |
4555 protected: | 4574 protected: |
4556 G1CollectedHeap* _g1h; | 4575 G1CollectedHeap* _g1h; |