Mercurial > hg > graal-compiler
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(); |