Mercurial > hg > truffle
comparison src/share/vm/runtime/virtualspace.cpp @ 12355:cefad50507d8
Merge with hs25-b53
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Fri, 11 Oct 2013 10:38:03 +0200 |
parents | 8c5e6482cbfc |
children | 04b18a42c2f3 |
comparison
equal
deleted
inserted
replaced
12058:ccb4f2af2319 | 12355:cefad50507d8 |
---|---|
40 # include "os_bsd.inline.hpp" | 40 # include "os_bsd.inline.hpp" |
41 #endif | 41 #endif |
42 | 42 |
43 | 43 |
44 // ReservedSpace | 44 // ReservedSpace |
45 | |
46 // Dummy constructor | |
47 ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0), | |
48 _alignment(0), _special(false), _executable(false) { | |
49 } | |
50 | |
45 ReservedSpace::ReservedSpace(size_t size) { | 51 ReservedSpace::ReservedSpace(size_t size) { |
46 initialize(size, 0, false, NULL, 0, false); | 52 size_t page_size = os::page_size_for_region(size, size, 1); |
53 bool large_pages = page_size != (size_t)os::vm_page_size(); | |
54 // Don't force the alignment to be large page aligned, | |
55 // since that will waste memory. | |
56 size_t alignment = os::vm_allocation_granularity(); | |
57 initialize(size, alignment, large_pages, NULL, 0, false); | |
47 } | 58 } |
48 | 59 |
49 ReservedSpace::ReservedSpace(size_t size, size_t alignment, | 60 ReservedSpace::ReservedSpace(size_t size, size_t alignment, |
50 bool large, | 61 bool large, |
51 char* requested_address, | 62 char* requested_address, |
127 assert(requested_address != NULL, "huge noaccess prefix?"); | 138 assert(requested_address != NULL, "huge noaccess prefix?"); |
128 } | 139 } |
129 | 140 |
130 if (special) { | 141 if (special) { |
131 | 142 |
132 base = os::reserve_memory_special(size, requested_address, executable); | 143 base = os::reserve_memory_special(size, alignment, requested_address, executable); |
133 | 144 |
134 if (base != NULL) { | 145 if (base != NULL) { |
135 if (failed_to_reserve_as_requested(base, requested_address, size, true)) { | 146 if (failed_to_reserve_as_requested(base, requested_address, size, true)) { |
136 // OS ignored requested address. Try different address. | 147 // OS ignored requested address. Try different address. |
137 return; | 148 return; |
138 } | 149 } |
139 // Check alignment constraints | 150 // Check alignment constraints. |
140 assert((uintptr_t) base % alignment == 0, | 151 assert((uintptr_t) base % alignment == 0, |
141 "Large pages returned a non-aligned address"); | 152 err_msg("Large pages returned a non-aligned address, base: " |
153 PTR_FORMAT " alignment: " PTR_FORMAT, | |
154 base, (void*)(uintptr_t)alignment)); | |
142 _special = true; | 155 _special = true; |
143 } else { | 156 } else { |
144 // failed; try to reserve regular memory below | 157 // failed; try to reserve regular memory below |
145 if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || | 158 if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || |
146 !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { | 159 !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { |
438 | 451 |
439 size_t VirtualSpace::uncommitted_size() const { | 452 size_t VirtualSpace::uncommitted_size() const { |
440 return reserved_size() - committed_size(); | 453 return reserved_size() - committed_size(); |
441 } | 454 } |
442 | 455 |
456 size_t VirtualSpace::actual_committed_size() const { | |
457 // Special VirtualSpaces commit all reserved space up front. | |
458 if (special()) { | |
459 return reserved_size(); | |
460 } | |
461 | |
462 size_t committed_low = pointer_delta(_lower_high, _low_boundary, sizeof(char)); | |
463 size_t committed_middle = pointer_delta(_middle_high, _lower_high_boundary, sizeof(char)); | |
464 size_t committed_high = pointer_delta(_upper_high, _middle_high_boundary, sizeof(char)); | |
465 | |
466 #ifdef ASSERT | |
467 size_t lower = pointer_delta(_lower_high_boundary, _low_boundary, sizeof(char)); | |
468 size_t middle = pointer_delta(_middle_high_boundary, _lower_high_boundary, sizeof(char)); | |
469 size_t upper = pointer_delta(_upper_high_boundary, _middle_high_boundary, sizeof(char)); | |
470 | |
471 if (committed_high > 0) { | |
472 assert(committed_low == lower, "Must be"); | |
473 assert(committed_middle == middle, "Must be"); | |
474 } | |
475 | |
476 if (committed_middle > 0) { | |
477 assert(committed_low == lower, "Must be"); | |
478 } | |
479 if (committed_middle < middle) { | |
480 assert(committed_high == 0, "Must be"); | |
481 } | |
482 | |
483 if (committed_low < lower) { | |
484 assert(committed_high == 0, "Must be"); | |
485 assert(committed_middle == 0, "Must be"); | |
486 } | |
487 #endif | |
488 | |
489 return committed_low + committed_middle + committed_high; | |
490 } | |
491 | |
443 | 492 |
444 bool VirtualSpace::contains(const void* p) const { | 493 bool VirtualSpace::contains(const void* p) const { |
445 return low() <= (const char*) p && (const char*) p < high(); | 494 return low() <= (const char*) p && (const char*) p < high(); |
446 } | 495 } |
447 | 496 |
703 assert(low_boundary() <= lower_high_boundary(), "lower high boundary"); | 752 assert(low_boundary() <= lower_high_boundary(), "lower high boundary"); |
704 assert(upper_high_boundary() <= high_boundary(), "upper high boundary"); | 753 assert(upper_high_boundary() <= high_boundary(), "upper high boundary"); |
705 assert(high() <= upper_high(), "upper high"); | 754 assert(high() <= upper_high(), "upper high"); |
706 } | 755 } |
707 | 756 |
757 void VirtualSpace::print_on(outputStream* out) { | |
758 out->print ("Virtual space:"); | |
759 if (special()) out->print(" (pinned in memory)"); | |
760 out->cr(); | |
761 out->print_cr(" - committed: " SIZE_FORMAT, committed_size()); | |
762 out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); | |
763 out->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); | |
764 out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); | |
765 } | |
766 | |
708 void VirtualSpace::print() { | 767 void VirtualSpace::print() { |
709 tty->print ("Virtual space:"); | 768 print_on(tty); |
710 if (special()) tty->print(" (pinned in memory)"); | 769 } |
711 tty->cr(); | 770 |
712 tty->print_cr(" - committed: " SIZE_FORMAT, committed_size()); | 771 /////////////// Unit tests /////////////// |
713 tty->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); | 772 |
714 tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); | 773 #ifndef PRODUCT |
715 tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); | 774 |
716 } | 775 #define test_log(...) \ |
776 do {\ | |
777 if (VerboseInternalVMTests) { \ | |
778 tty->print_cr(__VA_ARGS__); \ | |
779 tty->flush(); \ | |
780 }\ | |
781 } while (false) | |
782 | |
783 class TestReservedSpace : AllStatic { | |
784 public: | |
785 static void small_page_write(void* addr, size_t size) { | |
786 size_t page_size = os::vm_page_size(); | |
787 | |
788 char* end = (char*)addr + size; | |
789 for (char* p = (char*)addr; p < end; p += page_size) { | |
790 *p = 1; | |
791 } | |
792 } | |
793 | |
794 static void release_memory_for_test(ReservedSpace rs) { | |
795 if (rs.special()) { | |
796 guarantee(os::release_memory_special(rs.base(), rs.size()), "Shouldn't fail"); | |
797 } else { | |
798 guarantee(os::release_memory(rs.base(), rs.size()), "Shouldn't fail"); | |
799 } | |
800 } | |
801 | |
802 static void test_reserved_space1(size_t size, size_t alignment) { | |
803 test_log("test_reserved_space1(%p)", (void*) (uintptr_t) size); | |
804 | |
805 assert(is_size_aligned(size, alignment), "Incorrect input parameters"); | |
806 | |
807 ReservedSpace rs(size, // size | |
808 alignment, // alignment | |
809 UseLargePages, // large | |
810 NULL, // requested_address | |
811 0); // noacces_prefix | |
812 | |
813 test_log(" rs.special() == %d", rs.special()); | |
814 | |
815 assert(rs.base() != NULL, "Must be"); | |
816 assert(rs.size() == size, "Must be"); | |
817 | |
818 assert(is_ptr_aligned(rs.base(), alignment), "aligned sizes should always give aligned addresses"); | |
819 assert(is_size_aligned(rs.size(), alignment), "aligned sizes should always give aligned addresses"); | |
820 | |
821 if (rs.special()) { | |
822 small_page_write(rs.base(), size); | |
823 } | |
824 | |
825 release_memory_for_test(rs); | |
826 } | |
827 | |
828 static void test_reserved_space2(size_t size) { | |
829 test_log("test_reserved_space2(%p)", (void*)(uintptr_t)size); | |
830 | |
831 assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned"); | |
832 | |
833 ReservedSpace rs(size); | |
834 | |
835 test_log(" rs.special() == %d", rs.special()); | |
836 | |
837 assert(rs.base() != NULL, "Must be"); | |
838 assert(rs.size() == size, "Must be"); | |
839 | |
840 if (rs.special()) { | |
841 small_page_write(rs.base(), size); | |
842 } | |
843 | |
844 release_memory_for_test(rs); | |
845 } | |
846 | |
847 static void test_reserved_space3(size_t size, size_t alignment, bool maybe_large) { | |
848 test_log("test_reserved_space3(%p, %p, %d)", | |
849 (void*)(uintptr_t)size, (void*)(uintptr_t)alignment, maybe_large); | |
850 | |
851 assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned"); | |
852 assert(is_size_aligned(size, alignment), "Must be at least aligned against alignment"); | |
853 | |
854 bool large = maybe_large && UseLargePages && size >= os::large_page_size(); | |
855 | |
856 ReservedSpace rs(size, alignment, large, false); | |
857 | |
858 test_log(" rs.special() == %d", rs.special()); | |
859 | |
860 assert(rs.base() != NULL, "Must be"); | |
861 assert(rs.size() == size, "Must be"); | |
862 | |
863 if (rs.special()) { | |
864 small_page_write(rs.base(), size); | |
865 } | |
866 | |
867 release_memory_for_test(rs); | |
868 } | |
869 | |
870 | |
871 static void test_reserved_space1() { | |
872 size_t size = 2 * 1024 * 1024; | |
873 size_t ag = os::vm_allocation_granularity(); | |
874 | |
875 test_reserved_space1(size, ag); | |
876 test_reserved_space1(size * 2, ag); | |
877 test_reserved_space1(size * 10, ag); | |
878 } | |
879 | |
880 static void test_reserved_space2() { | |
881 size_t size = 2 * 1024 * 1024; | |
882 size_t ag = os::vm_allocation_granularity(); | |
883 | |
884 test_reserved_space2(size * 1); | |
885 test_reserved_space2(size * 2); | |
886 test_reserved_space2(size * 10); | |
887 test_reserved_space2(ag); | |
888 test_reserved_space2(size - ag); | |
889 test_reserved_space2(size); | |
890 test_reserved_space2(size + ag); | |
891 test_reserved_space2(size * 2); | |
892 test_reserved_space2(size * 2 - ag); | |
893 test_reserved_space2(size * 2 + ag); | |
894 test_reserved_space2(size * 3); | |
895 test_reserved_space2(size * 3 - ag); | |
896 test_reserved_space2(size * 3 + ag); | |
897 test_reserved_space2(size * 10); | |
898 test_reserved_space2(size * 10 + size / 2); | |
899 } | |
900 | |
901 static void test_reserved_space3() { | |
902 size_t ag = os::vm_allocation_granularity(); | |
903 | |
904 test_reserved_space3(ag, ag , false); | |
905 test_reserved_space3(ag * 2, ag , false); | |
906 test_reserved_space3(ag * 3, ag , false); | |
907 test_reserved_space3(ag * 2, ag * 2, false); | |
908 test_reserved_space3(ag * 4, ag * 2, false); | |
909 test_reserved_space3(ag * 8, ag * 2, false); | |
910 test_reserved_space3(ag * 4, ag * 4, false); | |
911 test_reserved_space3(ag * 8, ag * 4, false); | |
912 test_reserved_space3(ag * 16, ag * 4, false); | |
913 | |
914 if (UseLargePages) { | |
915 size_t lp = os::large_page_size(); | |
916 | |
917 // Without large pages | |
918 test_reserved_space3(lp, ag * 4, false); | |
919 test_reserved_space3(lp * 2, ag * 4, false); | |
920 test_reserved_space3(lp * 4, ag * 4, false); | |
921 test_reserved_space3(lp, lp , false); | |
922 test_reserved_space3(lp * 2, lp , false); | |
923 test_reserved_space3(lp * 3, lp , false); | |
924 test_reserved_space3(lp * 2, lp * 2, false); | |
925 test_reserved_space3(lp * 4, lp * 2, false); | |
926 test_reserved_space3(lp * 8, lp * 2, false); | |
927 | |
928 // With large pages | |
929 test_reserved_space3(lp, ag * 4 , true); | |
930 test_reserved_space3(lp * 2, ag * 4, true); | |
931 test_reserved_space3(lp * 4, ag * 4, true); | |
932 test_reserved_space3(lp, lp , true); | |
933 test_reserved_space3(lp * 2, lp , true); | |
934 test_reserved_space3(lp * 3, lp , true); | |
935 test_reserved_space3(lp * 2, lp * 2, true); | |
936 test_reserved_space3(lp * 4, lp * 2, true); | |
937 test_reserved_space3(lp * 8, lp * 2, true); | |
938 } | |
939 } | |
940 | |
941 static void test_reserved_space() { | |
942 test_reserved_space1(); | |
943 test_reserved_space2(); | |
944 test_reserved_space3(); | |
945 } | |
946 }; | |
947 | |
948 void TestReservedSpace_test() { | |
949 TestReservedSpace::test_reserved_space(); | |
950 } | |
951 | |
952 #define assert_equals(actual, expected) \ | |
953 assert(actual == expected, \ | |
954 err_msg("Got " SIZE_FORMAT " expected " \ | |
955 SIZE_FORMAT, actual, expected)); | |
956 | |
957 #define assert_ge(value1, value2) \ | |
958 assert(value1 >= value2, \ | |
959 err_msg("'" #value1 "': " SIZE_FORMAT " '" \ | |
960 #value2 "': " SIZE_FORMAT, value1, value2)); | |
961 | |
962 #define assert_lt(value1, value2) \ | |
963 assert(value1 < value2, \ | |
964 err_msg("'" #value1 "': " SIZE_FORMAT " '" \ | |
965 #value2 "': " SIZE_FORMAT, value1, value2)); | |
966 | |
967 | |
968 class TestVirtualSpace : AllStatic { | |
969 public: | |
970 static void test_virtual_space_actual_committed_space(size_t reserve_size, size_t commit_size) { | |
971 size_t granularity = os::vm_allocation_granularity(); | |
972 size_t reserve_size_aligned = align_size_up(reserve_size, granularity); | |
973 | |
974 ReservedSpace reserved(reserve_size_aligned); | |
975 | |
976 assert(reserved.is_reserved(), "Must be"); | |
977 | |
978 VirtualSpace vs; | |
979 bool initialized = vs.initialize(reserved, 0); | |
980 assert(initialized, "Failed to initialize VirtualSpace"); | |
981 | |
982 vs.expand_by(commit_size, false); | |
983 | |
984 if (vs.special()) { | |
985 assert_equals(vs.actual_committed_size(), reserve_size_aligned); | |
986 } else { | |
987 assert_ge(vs.actual_committed_size(), commit_size); | |
988 // Approximate the commit granularity. | |
989 size_t commit_granularity = UseLargePages ? os::large_page_size() : os::vm_page_size(); | |
990 assert_lt(vs.actual_committed_size(), commit_size + commit_granularity); | |
991 } | |
992 | |
993 reserved.release(); | |
994 } | |
995 | |
996 static void test_virtual_space_actual_committed_space_one_large_page() { | |
997 if (!UseLargePages) { | |
998 return; | |
999 } | |
1000 | |
1001 size_t large_page_size = os::large_page_size(); | |
1002 | |
1003 ReservedSpace reserved(large_page_size, large_page_size, true, false); | |
1004 | |
1005 assert(reserved.is_reserved(), "Must be"); | |
1006 | |
1007 VirtualSpace vs; | |
1008 bool initialized = vs.initialize(reserved, 0); | |
1009 assert(initialized, "Failed to initialize VirtualSpace"); | |
1010 | |
1011 vs.expand_by(large_page_size, false); | |
1012 | |
1013 assert_equals(vs.actual_committed_size(), large_page_size); | |
1014 | |
1015 reserved.release(); | |
1016 } | |
1017 | |
1018 static void test_virtual_space_actual_committed_space() { | |
1019 test_virtual_space_actual_committed_space(4 * K, 0); | |
1020 test_virtual_space_actual_committed_space(4 * K, 4 * K); | |
1021 test_virtual_space_actual_committed_space(8 * K, 0); | |
1022 test_virtual_space_actual_committed_space(8 * K, 4 * K); | |
1023 test_virtual_space_actual_committed_space(8 * K, 8 * K); | |
1024 test_virtual_space_actual_committed_space(12 * K, 0); | |
1025 test_virtual_space_actual_committed_space(12 * K, 4 * K); | |
1026 test_virtual_space_actual_committed_space(12 * K, 8 * K); | |
1027 test_virtual_space_actual_committed_space(12 * K, 12 * K); | |
1028 test_virtual_space_actual_committed_space(64 * K, 0); | |
1029 test_virtual_space_actual_committed_space(64 * K, 32 * K); | |
1030 test_virtual_space_actual_committed_space(64 * K, 64 * K); | |
1031 test_virtual_space_actual_committed_space(2 * M, 0); | |
1032 test_virtual_space_actual_committed_space(2 * M, 4 * K); | |
1033 test_virtual_space_actual_committed_space(2 * M, 64 * K); | |
1034 test_virtual_space_actual_committed_space(2 * M, 1 * M); | |
1035 test_virtual_space_actual_committed_space(2 * M, 2 * M); | |
1036 test_virtual_space_actual_committed_space(10 * M, 0); | |
1037 test_virtual_space_actual_committed_space(10 * M, 4 * K); | |
1038 test_virtual_space_actual_committed_space(10 * M, 8 * K); | |
1039 test_virtual_space_actual_committed_space(10 * M, 1 * M); | |
1040 test_virtual_space_actual_committed_space(10 * M, 2 * M); | |
1041 test_virtual_space_actual_committed_space(10 * M, 5 * M); | |
1042 test_virtual_space_actual_committed_space(10 * M, 10 * M); | |
1043 } | |
1044 | |
1045 static void test_virtual_space() { | |
1046 test_virtual_space_actual_committed_space(); | |
1047 test_virtual_space_actual_committed_space_one_large_page(); | |
1048 } | |
1049 }; | |
1050 | |
1051 void TestVirtualSpace_test() { | |
1052 TestVirtualSpace::test_virtual_space(); | |
1053 } | |
1054 | |
1055 #endif // PRODUCT | |
717 | 1056 |
718 #endif | 1057 #endif |