8174986: CDS archived java heap region may not compatible with AOT
authorjiangli
Fri, 06 Oct 2017 19:33:27 -0400
changeset 47599 0fb1d501c408
parent 47598 92aab488afdc
child 47600 5c8607bb3d2d
8174986: CDS archived java heap region may not compatible with AOT Summary: Always uses LogKlassAlignmentInBytes for narrow_klass_shift when CDS is enabled. Reviewed-by: iklam, ccheung
src/hotspot/share/memory/filemap.cpp
src/hotspot/share/memory/filemap.hpp
src/hotspot/share/memory/metaspace.cpp
src/hotspot/share/memory/metaspace.hpp
src/hotspot/share/memory/metaspaceShared.cpp
src/hotspot/share/memory/metaspaceShared.hpp
--- a/src/hotspot/share/memory/filemap.cpp	Fri Oct 06 13:00:18 2017 -0700
+++ b/src/hotspot/share/memory/filemap.cpp	Fri Oct 06 19:33:27 2017 -0400
@@ -182,6 +182,7 @@
   _obj_alignment = ObjectAlignmentInBytes;
   _compact_strings = CompactStrings;
   _narrow_oop_mode = Universe::narrow_oop_mode();
+  _narrow_oop_base = Universe::narrow_oop_base();
   _narrow_oop_shift = Universe::narrow_oop_shift();
   _max_heap_size = MaxHeapSize;
   _narrow_klass_base = Universe::narrow_klass_base();
@@ -687,8 +688,14 @@
 // open archive objects.
 void FileMapInfo::map_heap_regions() {
   if (MetaspaceShared::is_heap_object_archiving_allowed()) {
+      log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
+                    narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
+      log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
+                    p2i(narrow_klass_base()), narrow_klass_shift());
+
     // Check that all the narrow oop and klass encodings match the archive
     if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
+        narrow_oop_base() != Universe::narrow_oop_base() ||
         narrow_oop_shift() != Universe::narrow_oop_shift() ||
         narrow_klass_base() != Universe::narrow_klass_base() ||
         narrow_klass_shift() != Universe::narrow_klass_shift()) {
@@ -697,6 +704,11 @@
                       "The current CompressedOops/CompressedClassPointers encoding differs from "
                       "that archived due to heap size change. The archive was dumped using max heap "
                       "size " UINTX_FORMAT "M.", max_heap_size()/M);
+        log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
+                      Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()),
+                      Universe::narrow_oop_shift());
+        log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
+                      p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
       }
     } else {
       // First, map string regions as closed archive heap regions.
--- a/src/hotspot/share/memory/filemap.hpp	Fri Oct 06 13:00:18 2017 -0700
+++ b/src/hotspot/share/memory/filemap.hpp	Fri Oct 06 19:33:27 2017 -0400
@@ -112,6 +112,7 @@
     int    _version;                  // (from enum, above.)
     size_t _alignment;                // how shared archive should be aligned
     int    _obj_alignment;            // value of ObjectAlignmentInBytes
+    address _narrow_oop_base;         // compressed oop encoding base
     int    _narrow_oop_shift;         // compressed oop encoding shift
     bool   _compact_strings;          // value of CompactStrings
     uintx  _max_heap_size;            // java max heap size during dumping
@@ -203,12 +204,13 @@
   int    version()                    { return _header->_version; }
   size_t alignment()                  { return _header->_alignment; }
   Universe::NARROW_OOP_MODE narrow_oop_mode() { return _header->_narrow_oop_mode; }
-  int    narrow_oop_shift()           { return _header->_narrow_oop_shift; }
-  uintx  max_heap_size()              { return _header->_max_heap_size; }
-  address narrow_klass_base() const   { return _header->_narrow_klass_base; }
+  address narrow_oop_base()    const  { return _header->_narrow_oop_base; }
+  int     narrow_oop_shift()   const  { return _header->_narrow_oop_shift; }
+  uintx   max_heap_size()      const  { return _header->_max_heap_size; }
+  address narrow_klass_base()  const  { return _header->_narrow_klass_base; }
   int     narrow_klass_shift() const  { return _header->_narrow_klass_shift; }
-  struct FileMapHeader* header()      { return _header; }
-  char* misc_data_patching_start()            { return _header->_misc_data_patching_start; }
+  struct  FileMapHeader* header()     { return _header; }
+  char*   misc_data_patching_start()          { return _header->_misc_data_patching_start; }
   void set_misc_data_patching_start(char* p)  { _header->_misc_data_patching_start = p; }
   char* read_only_tables_start()              { return _header->_read_only_tables_start; }
   void set_read_only_tables_start(char* p)    { _header->_read_only_tables_start = p; }
--- a/src/hotspot/share/memory/metaspace.cpp	Fri Oct 06 13:00:18 2017 -0700
+++ b/src/hotspot/share/memory/metaspace.cpp	Fri Oct 06 19:33:27 2017 -0400
@@ -3103,10 +3103,16 @@
 
   Universe::set_narrow_klass_base(lower_base);
 
-  if ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax) {
+  // CDS uses LogKlassAlignmentInBytes for narrow_klass_shift. See
+  // MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() for
+  // how dump time narrow_klass_shift is set. Although, CDS can work
+  // with zero-shift mode also, to be consistent with AOT it uses
+  // LogKlassAlignmentInBytes for klass shift so archived java heap objects
+  // can be used at same time as AOT code.
+  if (!UseSharedSpaces
+      && (uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax) {
     Universe::set_narrow_klass_shift(0);
   } else {
-    assert(!UseSharedSpaces, "Cannot shift with UseSharedSpaces");
     Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
   }
   AOTLoader::set_narrow_klass_shift();
@@ -3325,50 +3331,25 @@
 
 #if INCLUDE_CDS
   if (DumpSharedSpaces) {
-    MetaspaceShared::initialize_shared_rs();
+    MetaspaceShared::initialize_dumptime_shared_and_meta_spaces();
   } else if (UseSharedSpaces) {
-    // If using shared space, open the file that contains the shared space
-    // and map in the memory before initializing the rest of metaspace (so
-    // the addresses don't conflict)
-    address cds_address = NULL;
-    FileMapInfo* mapinfo = new FileMapInfo();
-
-    // Open the shared archive file, read and validate the header. If
-    // initialization fails, shared spaces [UseSharedSpaces] are
-    // disabled and the file is closed.
-    // Map in spaces now also
-    if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
-      size_t cds_total = MetaspaceShared::core_spaces_size();
-      cds_address = (address)mapinfo->header()->region_addr(0);
+    // If any of the archived space fails to map, UseSharedSpaces
+    // is reset to false. Fall through to the
+    // (!DumpSharedSpaces && !UseSharedSpaces) case to set up class
+    // metaspace.
+    MetaspaceShared::initialize_runtime_shared_and_meta_spaces();
+  }
+
+  if (!DumpSharedSpaces && !UseSharedSpaces)
+#endif // INCLUDE_CDS
+  {
 #ifdef _LP64
-      if (using_class_space()) {
-        char* cds_end = (char*)(cds_address + cds_total);
-        cds_end = (char *)align_up(cds_end, _reserve_alignment);
-        // If UseCompressedClassPointers is set then allocate the metaspace area
-        // above the heap and above the CDS area (if it exists).
-        allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
-        // map_heap_regions() compares the current narrow oop and klass encodings
-        // with the archived ones, so it must be done after all encodings are determined.
-        mapinfo->map_heap_regions();
-      }
-#endif // _LP64
-    } else {
-      assert(!mapinfo->is_open() && !UseSharedSpaces,
-             "archive file not closed or shared spaces not disabled.");
-    }
-  }
-#endif // INCLUDE_CDS
-
-#ifdef _LP64
-  if (!UseSharedSpaces && using_class_space()) {
-    if (DumpSharedSpaces) {
-      // Already initialized inside MetaspaceShared::initialize_shared_rs()
-    } else {
+    if (using_class_space()) {
       char* base = (char*)align_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
       allocate_metaspace_compressed_klass_ptrs(base, 0);
     }
+#endif // _LP64
   }
-#endif // _LP64
 
   // Initialize these before initializing the VirtualSpaceList
   _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord;
--- a/src/hotspot/share/memory/metaspace.hpp	Fri Oct 06 13:00:18 2017 -0700
+++ b/src/hotspot/share/memory/metaspace.hpp	Fri Oct 06 19:33:27 2017 -0400
@@ -179,6 +179,10 @@
     assert(DumpSharedSpaces, "sanity");
     DEBUG_ONLY(_frozen = true;)
   }
+#ifdef _LP64
+  static void allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base);
+#endif
+
  private:
 
 #ifdef _LP64
@@ -187,8 +191,6 @@
   // Returns true if can use CDS with metaspace allocated as specified address.
   static bool can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base);
 
-  static void allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base);
-
   static void initialize_class_space(ReservedSpace rs);
 #endif
   size_t class_chunk_size(size_t word_size);
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Fri Oct 06 13:00:18 2017 -0700
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Fri Oct 06 19:33:27 2017 -0400
@@ -214,7 +214,42 @@
   return _ro_region.allocate(num_bytes);
 }
 
-void MetaspaceShared::initialize_shared_rs() {
+void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
+  assert(UseSharedSpaces, "Must be called when UseSharedSpaces is enabled");
+
+  // If using shared space, open the file that contains the shared space
+  // and map in the memory before initializing the rest of metaspace (so
+  // the addresses don't conflict)
+  address cds_address = NULL;
+  FileMapInfo* mapinfo = new FileMapInfo();
+
+  // Open the shared archive file, read and validate the header. If
+  // initialization fails, shared spaces [UseSharedSpaces] are
+  // disabled and the file is closed.
+  // Map in spaces now also
+  if (mapinfo->initialize() && map_shared_spaces(mapinfo)) {
+    size_t cds_total = core_spaces_size();
+    cds_address = (address)mapinfo->header()->region_addr(0);
+#ifdef _LP64
+    if (Metaspace::using_class_space()) {
+      char* cds_end = (char*)(cds_address + cds_total);
+      cds_end = (char *)align_up(cds_end, Metaspace::reserve_alignment());
+      // If UseCompressedClassPointers is set then allocate the metaspace area
+      // above the heap and above the CDS area (if it exists).
+      Metaspace::allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
+      // map_heap_regions() compares the current narrow oop and klass encodings
+      // with the archived ones, so it must be done after all encodings are determined.
+      mapinfo->map_heap_regions();
+    }
+#endif // _LP64
+  } else {
+    assert(!mapinfo->is_open() && !UseSharedSpaces,
+           "archive file not closed or shared spaces not disabled.");
+  }
+}
+
+void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
+  assert(DumpSharedSpaces, "should be called for dump time only");
   const size_t reserve_alignment = Metaspace::reserve_alignment();
   bool large_pages = false; // No large pages when dumping the CDS archive.
   char* shared_base = (char*)align_up((char*)SharedBaseAddress, reserve_alignment);
@@ -223,12 +258,12 @@
   // On 64-bit VM, the heap and class space layout will be the same as if
   // you're running in -Xshare:on mode:
   //
-  //                         +-- SharedBaseAddress (default = 0x800000000)
-  //                         v
-  // +-..---------+----+ ... +----+----+----+----+----+---------------+
-  // |    Heap    | ST |     | MC | RW | RO | MD | OD | class space   |
-  // +-..---------+----+ ... +----+----+----+----+----+---------------+
-  // |<--MaxHeapSize->|     |<-- UnscaledClassSpaceMax = 4GB ------->|
+  //                              +-- SharedBaseAddress (default = 0x800000000)
+  //                              v
+  // +-..---------+---------+ ... +----+----+----+----+----+---------------+
+  // |    Heap    | Archive |     | MC | RW | RO | MD | OD | class space   |
+  // +-..---------+---------+ ... +----+----+----+----+----+---------------+
+  // |<--   MaxHeapSize  -->|     |<-- UnscaledClassSpaceMax = 4GB ------->|
   //
   const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1);
   const size_t cds_total = align_down(UnscaledClassSpaceMax, reserve_alignment);
@@ -268,12 +303,9 @@
 
   // Set up compress class pointers.
   Universe::set_narrow_klass_base((address)_shared_rs.base());
-  if (UseAOT || cds_total > UnscaledClassSpaceMax) {
-    // AOT forces narrow_klass_shift=LogKlassAlignmentInBytes
-    Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
-  } else {
-    Universe::set_narrow_klass_shift(0);
-  }
+  // Set narrow_klass_shift to be LogKlassAlignmentInBytes. This is consistent
+  // with AOT.
+  Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
 
   Metaspace::initialize_class_space(tmp_class_space);
   tty->print_cr("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
--- a/src/hotspot/share/memory/metaspaceShared.hpp	Fri Oct 06 13:00:18 2017 -0700
+++ b/src/hotspot/share/memory/metaspaceShared.hpp	Fri Oct 06 19:33:27 2017 -0400
@@ -146,7 +146,8 @@
   static size_t core_spaces_size() {
     return _core_spaces_size;
   }
-  static void initialize_shared_rs() NOT_CDS_RETURN;
+  static void initialize_dumptime_shared_and_meta_spaces() NOT_CDS_RETURN;
+  static void initialize_runtime_shared_and_meta_spaces() NOT_CDS_RETURN;
 
   // Delta of this object from the bottom of the archive.
   static uintx object_delta(void* obj) {