comparison src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @ 190:d1635bf93939

6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk Summary: The fix takes care of three issues that can create a hole less a minimal object in the lgrp chunk Reviewed-by: ysr, apetrusenko
author iveresov
date Mon, 09 Jun 2008 07:18:59 -0700
parents e3729351c946
children d1605aabd0a1 12eea04c8b06
comparison
equal deleted inserted replaced
189:0b27f3512f9e 190:d1635bf93939
597 597
598 // Set the top of the whole space. 598 // Set the top of the whole space.
599 // Mark the the holes in chunks below the top() as invalid. 599 // Mark the the holes in chunks below the top() as invalid.
600 void MutableNUMASpace::set_top(HeapWord* value) { 600 void MutableNUMASpace::set_top(HeapWord* value) {
601 bool found_top = false; 601 bool found_top = false;
602 for (int i = 0; i < lgrp_spaces()->length(); i++) { 602 for (int i = 0; i < lgrp_spaces()->length();) {
603 LGRPSpace *ls = lgrp_spaces()->at(i); 603 LGRPSpace *ls = lgrp_spaces()->at(i);
604 MutableSpace *s = ls->space(); 604 MutableSpace *s = ls->space();
605 HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom()); 605 HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
606 606
607 if (s->contains(value)) { 607 if (s->contains(value)) {
608 // Check if setting the chunk's top to a given value would create a hole less than
609 // a minimal object; assuming that's not the last chunk in which case we don't care.
610 if (i < lgrp_spaces()->length() - 1) {
611 size_t remainder = pointer_delta(s->end(), value);
612 const size_t minimal_object_size = oopDesc::header_size();
613 if (remainder < minimal_object_size && remainder > 0) {
614 // Add a filler object of a minimal size, it will cross the chunk boundary.
615 SharedHeap::fill_region_with_object(MemRegion(value, minimal_object_size));
616 value += minimal_object_size;
617 assert(!s->contains(value), "Should be in the next chunk");
618 // Restart the loop from the same chunk, since the value has moved
619 // to the next one.
620 continue;
621 }
622 }
623
608 if (!os::numa_has_static_binding() && top < value && top < s->end()) { 624 if (!os::numa_has_static_binding() && top < value && top < s->end()) {
609 ls->add_invalid_region(MemRegion(top, value)); 625 ls->add_invalid_region(MemRegion(top, value));
610 } 626 }
611 s->set_top(value); 627 s->set_top(value);
612 found_top = true; 628 found_top = true;
618 ls->add_invalid_region(MemRegion(top, s->end())); 634 ls->add_invalid_region(MemRegion(top, s->end()));
619 } 635 }
620 s->set_top(s->end()); 636 s->set_top(s->end());
621 } 637 }
622 } 638 }
639 i++;
623 } 640 }
624 MutableSpace::set_top(value); 641 MutableSpace::set_top(value);
625 } 642 }
626 643
627 void MutableNUMASpace::clear() { 644 void MutableNUMASpace::clear() {
698 i = os::random() % lgrp_spaces()->length(); 715 i = os::random() % lgrp_spaces()->length();
699 } 716 }
700 MutableSpace *s = lgrp_spaces()->at(i)->space(); 717 MutableSpace *s = lgrp_spaces()->at(i)->space();
701 HeapWord *p = s->cas_allocate(size); 718 HeapWord *p = s->cas_allocate(size);
702 if (p != NULL) { 719 if (p != NULL) {
703 size_t remainder = pointer_delta(s->end(), p); 720 size_t remainder = pointer_delta(s->end(), p + size);
704 if (remainder < (size_t)oopDesc::header_size() && remainder > 0) { 721 if (remainder < (size_t)oopDesc::header_size() && remainder > 0) {
705 if (s->cas_deallocate(p, size)) { 722 if (s->cas_deallocate(p, size)) {
706 // We were the last to allocate and created a fragment less than 723 // We were the last to allocate and created a fragment less than
707 // a minimal object. 724 // a minimal object.
708 p = NULL; 725 p = NULL;
726 } else {
727 guarantee(false, "Deallocation should always succeed");
709 } 728 }
710 } 729 }
711 } 730 }
712 if (p != NULL) { 731 if (p != NULL) {
713 HeapWord* cur_top, *cur_chunk_top = p + size; 732 HeapWord* cur_top, *cur_chunk_top = p + size;
759 ls->space_stats()->_small_pages); 778 ls->space_stats()->_small_pages);
760 } 779 }
761 } 780 }
762 } 781 }
763 782
764 void MutableNUMASpace::verify(bool allow_dirty) const { 783 void MutableNUMASpace::verify(bool allow_dirty) {
765 for (int i = 0; i < lgrp_spaces()->length(); i++) { 784 // This can be called after setting an arbitary value to the space's top,
766 lgrp_spaces()->at(i)->space()->verify(allow_dirty); 785 // so an object can cross the chunk boundary. We ensure the parsablity
767 } 786 // of the space and just walk the objects in linear fashion.
787 ensure_parsability();
788 MutableSpace::verify(allow_dirty);
768 } 789 }
769 790
770 // Scan pages and gather stats about page placement and size. 791 // Scan pages and gather stats about page placement and size.
771 void MutableNUMASpace::LGRPSpace::accumulate_statistics(size_t page_size) { 792 void MutableNUMASpace::LGRPSpace::accumulate_statistics(size_t page_size) {
772 clear_space_stats(); 793 clear_space_stats();