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;