< prev index next >

src/share/vm/memory/universe.cpp

Print this page
rev 7602 : 8064457: Introduce compressed oops mode disjoint base and improve compressed heap handling.


 677     SymbolTable::create_table();
 678     StringTable::create_table();
 679     ClassLoader::create_package_info_table();
 680 
 681     if (DumpSharedSpaces) {
 682       MetaspaceShared::prepare_for_dumping();
 683     }
 684   }
 685 
 686   return JNI_OK;
 687 }
 688 
 689 // Choose the heap base address and oop encoding mode
 690 // when compressed oops are used:
 691 // Unscaled  - Use 32-bits oops without encoding when
 692 //     NarrowOopHeapBaseMin + heap_size < 4Gb
 693 // ZeroBased - Use zero based compressed oops with encoding when
 694 //     NarrowOopHeapBaseMin + heap_size < 32Gb
 695 // HeapBased - Use compressed oops with heap base + encoding.
 696 
 697 // 4Gb
 698 static const uint64_t UnscaledOopHeapMax = (uint64_t(max_juint) + 1);
 699 // 32Gb
 700 // OopEncodingHeapMax == UnscaledOopHeapMax << LogMinObjAlignmentInBytes;
 701 
 702 char* Universe::preferred_heap_base(size_t heap_size, size_t alignment, NARROW_OOP_MODE mode) {
 703   assert(is_size_aligned((size_t)OopEncodingHeapMax, alignment), "Must be");
 704   assert(is_size_aligned((size_t)UnscaledOopHeapMax, alignment), "Must be");
 705   assert(is_size_aligned(heap_size, alignment), "Must be");
 706 
 707   uintx heap_base_min_address_aligned = align_size_up(HeapBaseMinAddress, alignment);
 708 
 709   size_t base = 0;
 710 #ifdef _LP64
 711   if (UseCompressedOops) {
 712     assert(mode == UnscaledNarrowOop  ||
 713            mode == ZeroBasedNarrowOop ||
 714            mode == HeapBasedNarrowOop, "mode is invalid");
 715     const size_t total_size = heap_size + heap_base_min_address_aligned;
 716     // Return specified base for the first request.
 717     if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
 718       base = heap_base_min_address_aligned;
 719 
 720     // If the total size is small enough to allow UnscaledNarrowOop then
 721     // just use UnscaledNarrowOop.
 722     } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop)) {
 723       if ((total_size <= UnscaledOopHeapMax) && (mode == UnscaledNarrowOop) &&
 724           (Universe::narrow_oop_shift() == 0)) {
 725         // Use 32-bits oops without encoding and
 726         // place heap's top on the 4Gb boundary
 727         base = (UnscaledOopHeapMax - heap_size);
 728       } else {
 729         // Can't reserve with NarrowOopShift == 0
 730         Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
 731 
 732         if (mode == UnscaledNarrowOop ||
 733             mode == ZeroBasedNarrowOop && total_size <= UnscaledOopHeapMax) {
 734 
 735           // Use zero based compressed oops with encoding and
 736           // place heap's top on the 32Gb boundary in case
 737           // total_size > 4Gb or failed to reserve below 4Gb.
 738           uint64_t heap_top = OopEncodingHeapMax;
 739 
 740           // For small heaps, save some space for compressed class pointer
 741           // space so it can be decoded with no base.
 742           if (UseCompressedClassPointers && !UseSharedSpaces &&
 743               OopEncodingHeapMax <= 32*G) {
 744 
 745             uint64_t class_space = align_size_up(CompressedClassSpaceSize, alignment);
 746             assert(is_size_aligned((size_t)OopEncodingHeapMax-class_space,
 747                    alignment), "difference must be aligned too");
 748             uint64_t new_top = OopEncodingHeapMax-class_space;
 749 
 750             if (total_size <= new_top) {
 751               heap_top = new_top;
 752             }
 753           }
 754 
 755           // Align base to the adjusted top of the heap
 756           base = heap_top - heap_size;
 757         }
 758       }
 759     } else {
 760       // UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or
 761       // HeapBasedNarrowOop encoding was requested.  So, can't reserve below 32Gb.
 762       Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
 763     }
 764 
 765     // Set narrow_oop_base and narrow_oop_use_implicit_null_checks
 766     // used in ReservedHeapSpace() constructors.
 767     // The final values will be set in initialize_heap() below.
 768     if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax)) {
 769       // Use zero based compressed oops
 770       Universe::set_narrow_oop_base(NULL);
 771       // Don't need guard page for implicit checks in indexed
 772       // addressing mode with zero based Compressed Oops.
 773       Universe::set_narrow_oop_use_implicit_null_checks(true);
 774     } else {
 775       // Set to a non-NULL value so the ReservedSpace ctor computes
 776       // the correct no-access prefix.
 777       // The final value will be set in initialize_heap() below.
 778       Universe::set_narrow_oop_base((address)UnscaledOopHeapMax);
 779 #if defined(_WIN64) || defined(AIX)
 780       if (UseLargePages) {
 781         // Cannot allocate guard pages for implicit checks in indexed
 782         // addressing mode when large pages are specified on windows.
 783         Universe::set_narrow_oop_use_implicit_null_checks(false);
 784       }
 785 #endif //  _WIN64
 786     }
 787   }
 788 #endif
 789 
 790   assert(is_ptr_aligned((char*)base, alignment), "Must be");
 791   return (char*)base; // also return NULL (don't care) for 32-bit VM
 792 }
 793 
 794 jint Universe::initialize_heap() {
 795 
 796   if (UseParallelGC) {
 797 #if INCLUDE_ALL_GCS
 798     Universe::_collectedHeap = new ParallelScavengeHeap();
 799 #else  // INCLUDE_ALL_GCS
 800     fatal("UseParallelGC not supported in this VM.");
 801 #endif // INCLUDE_ALL_GCS
 802 
 803   } else if (UseG1GC) {
 804 #if INCLUDE_ALL_GCS
 805     G1CollectorPolicyExt* g1p = new G1CollectorPolicyExt();
 806     g1p->initialize_all();
 807     G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
 808     Universe::_collectedHeap = g1h;
 809 #else  // INCLUDE_ALL_GCS
 810     fatal("UseG1GC not supported in java kernel vm.");
 811 #endif // INCLUDE_ALL_GCS
 812 
 813   } else {


 827     gc_policy->initialize_all();
 828 
 829     Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
 830   }
 831 
 832   ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size());
 833 
 834   jint status = Universe::heap()->initialize();
 835   if (status != JNI_OK) {
 836     return status;
 837   }
 838 
 839 #ifdef _LP64
 840   if (UseCompressedOops) {
 841     // Subtract a page because something can get allocated at heap base.
 842     // This also makes implicit null checking work, because the
 843     // memory+1 page below heap_base needs to cause a signal.
 844     // See needs_explicit_null_check.
 845     // Only set the heap base for compressed oops because it indicates
 846     // compressed oops for pstack code.
 847     if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax)) {
 848       // Can't reserve heap below 32Gb.
 849       // keep the Universe::narrow_oop_base() set in Universe::reserve_heap()
 850       Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
 851 #ifdef AIX
 852       // There is no protected page before the heap. This assures all oops
 853       // are decoded so that NULL is preserved, so this page will not be accessed.
 854       Universe::set_narrow_oop_use_implicit_null_checks(false);
 855 #endif
 856     } else {
 857       Universe::set_narrow_oop_base(0);
 858 #ifdef _WIN64
 859       if (!Universe::narrow_oop_use_implicit_null_checks()) {
 860         // Don't need guard page for implicit checks in indexed addressing
 861         // mode with zero based Compressed Oops.
 862         Universe::set_narrow_oop_use_implicit_null_checks(true);
 863       }
 864 #endif //  _WIN64
 865       if((uint64_t)Universe::heap()->reserved_region().end() > UnscaledOopHeapMax) {
 866         // Can't reserve heap below 4Gb.
 867         Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
 868       } else {
 869         Universe::set_narrow_oop_shift(0);
 870       }



 871     }
 872 
 873     Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
 874 
 875     if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) {
 876       Universe::print_compressed_oops_mode();
 877     }





 878   }
 879   // Universe::narrow_oop_base() is one page below the heap.
 880   assert((intptr_t)Universe::narrow_oop_base() <= (intptr_t)(Universe::heap()->base() -
 881          os::vm_page_size()) ||
 882          Universe::narrow_oop_base() == NULL, "invalid value");
 883   assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes ||
 884          Universe::narrow_oop_shift() == 0, "invalid value");
 885 #endif
 886 
 887   // We will never reach the CATCH below since Exceptions::_throw will cause
 888   // the VM to exit if an exception is thrown during initialization
 889 
 890   if (UseTLAB) {
 891     assert(Universe::heap()->supports_tlab_allocation(),
 892            "Should support thread-local allocation buffers");
 893     ThreadLocalAllocBuffer::startup_initialization();
 894   }
 895   return JNI_OK;
 896 }
 897 
 898 void Universe::print_compressed_oops_mode() {
 899   tty->cr();
 900   tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
 901               Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M);
 902 
 903   tty->print(", Compressed Oops mode: %s", narrow_oop_mode_to_string(narrow_oop_mode()));
 904 
 905   if (Universe::narrow_oop_base() != 0) {
 906     tty->print(":" PTR_FORMAT, Universe::narrow_oop_base());
 907   }
 908 
 909   if (Universe::narrow_oop_shift() != 0) {
 910     tty->print(", Oop shift amount: %d", Universe::narrow_oop_shift());
 911   }
 912 




 913   tty->cr();
 914   tty->cr();
 915 }
 916 
 917 // Reserve the Java heap, which is now the same for all GCs.
 918 ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {

 919   assert(alignment <= Arguments::conservative_max_heap_alignment(),
 920       err_msg("actual alignment "SIZE_FORMAT" must be within maximum heap alignment "SIZE_FORMAT,
 921           alignment, Arguments::conservative_max_heap_alignment()));

 922   size_t total_reserved = align_size_up(heap_size, alignment);
 923   assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())),
 924       "heap size is too big for compressed oops");
 925 
 926   bool use_large_pages = UseLargePages && is_size_aligned(alignment, os::large_page_size());
 927   assert(!UseLargePages
 928       || UseParallelGC
 929       || use_large_pages, "Wrong alignment to use large pages");
 930 
 931   char* addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::UnscaledNarrowOop);

 932 
 933   ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages, addr);



 934 
 935   if (UseCompressedOops) {
 936     if (addr != NULL && !total_rs.is_reserved()) {
 937       // Failed to reserve at specified address - the requested memory
 938       // region is taken already, for example, by 'java' launcher.
 939       // Try again to reserver heap higher.
 940       addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::ZeroBasedNarrowOop);
 941 
 942       ReservedHeapSpace total_rs0(total_reserved, alignment,
 943           use_large_pages, addr);
 944 
 945       if (addr != NULL && !total_rs0.is_reserved()) {
 946         // Failed to reserve at specified address again - give up.
 947         addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::HeapBasedNarrowOop);
 948         assert(addr == NULL, "");
 949 
 950         ReservedHeapSpace total_rs1(total_reserved, alignment,
 951             use_large_pages, addr);
 952         total_rs = total_rs1;
 953       } else {
 954         total_rs = total_rs0;
 955       }
 956     }
 957   }
 958 
 959   if (!total_rs.is_reserved()) {
 960     vm_exit_during_initialization(err_msg("Could not reserve enough space for " SIZE_FORMAT "KB object heap", total_reserved/K));
 961     return total_rs;
 962   }
 963 
 964   if (UseCompressedOops) {
 965     // Universe::initialize_heap() will reset this to NULL if unscaled
 966     // or zero-based narrow oops are actually used.
 967     address base = (address)(total_rs.base() - os::vm_page_size());
 968     Universe::set_narrow_oop_base(base);
 969   }
 970   return total_rs;
 971 }
 972 
 973 
 974 // It's the caller's responsibility to ensure glitch-freedom
 975 // (if required).
 976 void Universe::update_heap_info_at_gc() {
 977   _heap_capacity_at_last_gc = heap()->capacity();
 978   _heap_used_at_last_gc     = heap()->used();
 979 }
 980 
 981 
 982 const char* Universe::narrow_oop_mode_to_string(Universe::NARROW_OOP_MODE mode) {
 983   switch (mode) {
 984     case UnscaledNarrowOop:
 985       return "32-bit";
 986     case ZeroBasedNarrowOop:
 987       return "Zero based";


 988     case HeapBasedNarrowOop:
 989       return "Non-zero based";
 990   }
 991 
 992   ShouldNotReachHere();
 993   return "";
 994 }
 995 
 996 
 997 Universe::NARROW_OOP_MODE Universe::narrow_oop_mode() {




 998   if (narrow_oop_base() != 0) {
 999     return HeapBasedNarrowOop;
1000   }
1001 
1002   if (narrow_oop_shift() != 0) {
1003     return ZeroBasedNarrowOop;
1004   }
1005 
1006   return UnscaledNarrowOop;
1007 }
1008 
1009 
1010 void universe2_init() {
1011   EXCEPTION_MARK;
1012   Universe::genesis(CATCH);
1013 }
1014 
1015 
1016 bool universe_post_init() {
1017   assert(!is_init_completed(), "Error: initialization not yet completed!");




 677     SymbolTable::create_table();
 678     StringTable::create_table();
 679     ClassLoader::create_package_info_table();
 680 
 681     if (DumpSharedSpaces) {
 682       MetaspaceShared::prepare_for_dumping();
 683     }
 684   }
 685 
 686   return JNI_OK;
 687 }
 688 
 689 // Choose the heap base address and oop encoding mode
 690 // when compressed oops are used:
 691 // Unscaled  - Use 32-bits oops without encoding when
 692 //     NarrowOopHeapBaseMin + heap_size < 4Gb
 693 // ZeroBased - Use zero based compressed oops with encoding when
 694 //     NarrowOopHeapBaseMin + heap_size < 32Gb
 695 // HeapBased - Use compressed oops with heap base + encoding.
 696 

































































































 697 jint Universe::initialize_heap() {
 698 
 699   if (UseParallelGC) {
 700 #if INCLUDE_ALL_GCS
 701     Universe::_collectedHeap = new ParallelScavengeHeap();
 702 #else  // INCLUDE_ALL_GCS
 703     fatal("UseParallelGC not supported in this VM.");
 704 #endif // INCLUDE_ALL_GCS
 705 
 706   } else if (UseG1GC) {
 707 #if INCLUDE_ALL_GCS
 708     G1CollectorPolicyExt* g1p = new G1CollectorPolicyExt();
 709     g1p->initialize_all();
 710     G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
 711     Universe::_collectedHeap = g1h;
 712 #else  // INCLUDE_ALL_GCS
 713     fatal("UseG1GC not supported in java kernel vm.");
 714 #endif // INCLUDE_ALL_GCS
 715 
 716   } else {


 730     gc_policy->initialize_all();
 731 
 732     Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
 733   }
 734 
 735   ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size());
 736 
 737   jint status = Universe::heap()->initialize();
 738   if (status != JNI_OK) {
 739     return status;
 740   }
 741 
 742 #ifdef _LP64
 743   if (UseCompressedOops) {
 744     // Subtract a page because something can get allocated at heap base.
 745     // This also makes implicit null checking work, because the
 746     // memory+1 page below heap_base needs to cause a signal.
 747     // See needs_explicit_null_check.
 748     // Only set the heap base for compressed oops because it indicates
 749     // compressed oops for pstack code.
 750     if ((uint64_t)Universe::heap()->reserved_region().end() > UnscaledOopHeapMax) {
 751       // Didn't reserve heap below 4Gb.  Must shift.

 752       Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);



















 753     }
 754     if ((uint64_t)Universe::heap()->reserved_region().end() <= OopEncodingHeapMax) {
 755       // Did reserve heap below 32Gb. Can use base == 0;
 756       Universe::set_narrow_oop_base(0);
 757     }
 758 
 759     Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
 760 
 761     if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) {
 762       Universe::print_compressed_oops_mode();
 763     }
 764 
 765     // Tell tests in which mode we run.
 766     Arguments::PropertyList_add(new SystemProperty("java.vm.compressedOopsMode",
 767                                                    narrow_oop_mode_to_string(narrow_oop_mode()),
 768                                                    false));
 769   }
 770   // Universe::narrow_oop_base() is one page below the heap.
 771   assert((intptr_t)Universe::narrow_oop_base() <= (intptr_t)(Universe::heap()->base() -
 772          os::vm_page_size()) ||
 773          Universe::narrow_oop_base() == NULL, "invalid value");
 774   assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes ||
 775          Universe::narrow_oop_shift() == 0, "invalid value");
 776 #endif
 777 
 778   // We will never reach the CATCH below since Exceptions::_throw will cause
 779   // the VM to exit if an exception is thrown during initialization
 780 
 781   if (UseTLAB) {
 782     assert(Universe::heap()->supports_tlab_allocation(),
 783            "Should support thread-local allocation buffers");
 784     ThreadLocalAllocBuffer::startup_initialization();
 785   }
 786   return JNI_OK;
 787 }
 788 
 789 void Universe::print_compressed_oops_mode() {
 790   tty->cr();
 791   tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
 792               Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M);
 793 
 794   tty->print(", Compressed Oops mode: %s", narrow_oop_mode_to_string(narrow_oop_mode()));
 795 
 796   if (Universe::narrow_oop_base() != 0) {
 797     tty->print(": " PTR_FORMAT, Universe::narrow_oop_base());
 798   }
 799 
 800   if (Universe::narrow_oop_shift() != 0) {
 801     tty->print(", Oop shift amount: %d", Universe::narrow_oop_shift());
 802   }
 803 
 804   if (!Universe::narrow_oop_use_implicit_null_checks()) {
 805     tty->print(", no protected page in front of the heap");
 806   }
 807 
 808   tty->cr();
 809   tty->cr();
 810 }
 811 

 812 ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {
 813 
 814   assert(alignment <= Arguments::conservative_max_heap_alignment(),
 815       err_msg("actual alignment "SIZE_FORMAT" must be within maximum heap alignment "SIZE_FORMAT,
 816           alignment, Arguments::conservative_max_heap_alignment()));
 817 
 818   size_t total_reserved = align_size_up(heap_size, alignment);
 819   assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())),
 820       "heap size is too big for compressed oops");
 821 
 822   bool use_large_pages = UseLargePages && is_size_aligned(alignment, os::large_page_size());
 823   assert(!UseLargePages
 824       || UseParallelGC
 825       || use_large_pages, "Wrong alignment to use large pages");
 826 
 827   // Now create the space.
 828   ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages);
 829 
 830   if (total_rs.is_reserved()) {
 831     assert((total_reserved == total_rs.size()) && ((uintptr_t)total_rs.base() % alignment == 0),
 832            "must be exactly of required size and alignment");
 833     // We are good.
 834 
 835     if (UseCompressedOops) {
 836       // Universe::initialize_heap() will reset this to NULL if unscaled
 837       // or zero-based narrow oops are actually used.
 838       // Else heap start and base MUST differ, so that NULL can be encoded nonambigous.
 839       Universe::set_narrow_oop_base((address)total_rs.compressed_oop_base());

















 840     }
 841 


 842     return total_rs;
 843   }
 844 
 845   vm_exit_during_initialization(
 846     err_msg("Could not reserve enough space for " SIZE_FORMAT "KB object heap",
 847             total_reserved/K));
 848 
 849   // satisfy compiler
 850   ShouldNotReachHere();
 851   return ReservedHeapSpace(0, 0, false);
 852 }
 853 
 854 
 855 // It's the caller's responsibility to ensure glitch-freedom
 856 // (if required).
 857 void Universe::update_heap_info_at_gc() {
 858   _heap_capacity_at_last_gc = heap()->capacity();
 859   _heap_used_at_last_gc     = heap()->used();
 860 }
 861 
 862 
 863 const char* Universe::narrow_oop_mode_to_string(Universe::NARROW_OOP_MODE mode) {
 864   switch (mode) {
 865     case UnscaledNarrowOop:
 866       return "32-bit";
 867     case ZeroBasedNarrowOop:
 868       return "Zero based";
 869     case DisjointBaseNarrowOop:
 870       return "Non-zero disjoint base";
 871     case HeapBasedNarrowOop:
 872       return "Non-zero based";
 873   }
 874 
 875   ShouldNotReachHere();
 876   return "";
 877 }
 878 
 879 
 880 Universe::NARROW_OOP_MODE Universe::narrow_oop_mode() {
 881   if (narrow_oop_base_disjoint()) {
 882     return DisjointBaseNarrowOop;
 883   }
 884 
 885   if (narrow_oop_base() != 0) {
 886     return HeapBasedNarrowOop;
 887   }
 888 
 889   if (narrow_oop_shift() != 0) {
 890     return ZeroBasedNarrowOop;
 891   }
 892 
 893   return UnscaledNarrowOop;
 894 }
 895 
 896 
 897 void universe2_init() {
 898   EXCEPTION_MARK;
 899   Universe::genesis(CATCH);
 900 }
 901 
 902 
 903 bool universe_post_init() {
 904   assert(!is_init_completed(), "Error: initialization not yet completed!");


< prev index next >