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; |
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(); |