changeset 57795:ee29fd484961

8236236: Eliminate CDS md region and consolidate c++ vtable patching code Reviewed-by: ccheung
author iklam
date Wed, 22 Jan 2020 11:52:27 -0800
parents 20cb5d43dc2d
children 63d5ef4e3e74
files src/hotspot/share/include/cds.h src/hotspot/share/memory/dynamicArchive.cpp src/hotspot/share/memory/filemap.cpp src/hotspot/share/memory/filemap.hpp src/hotspot/share/memory/metaspaceShared.cpp src/hotspot/share/memory/metaspaceShared.hpp src/hotspot/share/runtime/vmStructs.cpp src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java test/hotspot/jtreg/runtime/cds/SpaceUtilizationCheck.java test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java
diffstat 11 files changed, 236 insertions(+), 236 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/include/cds.h	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/hotspot/share/include/cds.h	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
 //
 // Also, this is a C header file. Do not use C++ here.
 
-#define NUM_CDS_REGIONS 9 // this must be the same as MetaspaceShared::n_regions
+#define NUM_CDS_REGIONS 8 // this must be the same as MetaspaceShared::n_regions
 #define CDS_ARCHIVE_MAGIC 0xf00baba2
 #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
 #define CURRENT_CDS_ARCHIVE_VERSION 9
--- a/src/hotspot/share/memory/dynamicArchive.cpp	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/hotspot/share/memory/dynamicArchive.cpp	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -500,18 +500,26 @@
   void sort_methods(InstanceKlass* ik) const;
   void set_symbols_permanent();
   void relocate_buffer_to_target();
-  void write_archive(char* serialized_data_start);
-  void write_regions(FileMapInfo* dynamic_info);
+  void write_archive(char* serialized_data);
 
   void init_first_dump_space(address reserved_bottom) {
     address first_space_base = reserved_bottom;
+    DumpRegion* mc_space = MetaspaceShared::misc_code_dump_space();
     DumpRegion* rw_space = MetaspaceShared::read_write_dump_space();
-    MetaspaceShared::init_shared_dump_space(rw_space, first_space_base);
-    _current_dump_space = rw_space;
+
+    // Use the same MC->RW->RO ordering as in the base archive.
+    MetaspaceShared::init_shared_dump_space(mc_space, first_space_base);
+    _current_dump_space = mc_space;
     _last_verified_top = first_space_base;
     _num_dump_regions_used = 1;
   }
 
+  void reserve_buffers_for_trampolines() {
+    size_t n = _estimated_trampoline_bytes;
+    assert(n >= SharedRuntime::trampoline_size(), "dont want to be empty");
+    MetaspaceShared::misc_code_space_alloc(n);
+  }
+
 public:
   DynamicArchiveBuilder() {
     _klasses = new (ResourceObj::C_HEAP, mtClass) GrowableArray<InstanceKlass*>(100, true, mtInternal);
@@ -584,7 +592,10 @@
     CHeapBitMap ptrmap;
     ArchivePtrMarker::initialize(&ptrmap, (address*)reserved_bottom, (address*)current_dump_space()->top());
 
-    verify_estimate_size(sizeof(DynamicArchiveHeader), "header");
+    reserve_buffers_for_trampolines();
+    verify_estimate_size(_estimated_trampoline_bytes, "Trampolines");
+
+    start_dump_space(MetaspaceShared::read_write_dump_space());
 
     log_info(cds, dynamic)("Copying %d klasses and %d symbols",
                            _klasses->length(), _symbols->length());
@@ -625,7 +636,7 @@
 
     verify_estimate_size(_estimated_metsapceobj_bytes, "MetaspaceObjs");
 
-    char* serialized_data_start;
+    char* serialized_data;
     {
       set_symbols_permanent();
 
@@ -638,7 +649,7 @@
       SymbolTable::write_to_archive(false);
       SystemDictionaryShared::write_to_archive(false);
 
-      serialized_data_start = ro_space->top();
+      serialized_data = ro_space->top();
       WriteClosure wc(ro_space);
       SymbolTable::serialize_shared_table_header(&wc, false);
       SystemDictionaryShared::serialize_dictionary_headers(&wc, false);
@@ -646,14 +657,7 @@
 
     verify_estimate_size(_estimated_hashtable_bytes, "Hashtables");
 
-    // mc space starts ...
-    {
-      start_dump_space(MetaspaceShared::misc_code_dump_space());
-      make_trampolines();
-    }
-
-    verify_estimate_size(_estimated_trampoline_bytes, "Trampolines");
-
+    make_trampolines();
     make_klasses_shareable();
 
     {
@@ -664,7 +668,7 @@
       relocate_buffer_to_target();
     }
 
-    write_archive(serialized_data_start);
+    write_archive(serialized_data);
     release_header();
 
     assert(_num_dump_regions_used == _total_dump_regions, "must be");
@@ -801,25 +805,27 @@
 }
 
 void DynamicArchiveBuilder::make_trampolines() {
+  DumpRegion* mc_space = MetaspaceShared::misc_code_dump_space();
+  char* p = mc_space->base();
   for (int i = 0; i < _klasses->length(); i++) {
     InstanceKlass* ik = _klasses->at(i);
     Array<Method*>* methods = ik->methods();
     for (int j = 0; j < methods->length(); j++) {
       Method* m = methods->at(j);
-      address c2i_entry_trampoline =
-        (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
+      address c2i_entry_trampoline = (address)p;
+      p += SharedRuntime::trampoline_size();
+      assert(p >= mc_space->base() && p <= mc_space->top(), "must be");
       m->set_from_compiled_entry(to_target(c2i_entry_trampoline));
-      AdapterHandlerEntry** adapter_trampoline =
-        (AdapterHandlerEntry**)MetaspaceShared::misc_code_space_alloc(sizeof(AdapterHandlerEntry*));
+
+      AdapterHandlerEntry** adapter_trampoline =(AdapterHandlerEntry**)p;
+      p += sizeof(AdapterHandlerEntry*);
+      assert(p >= mc_space->base() && p <= mc_space->top(), "must be");
       *adapter_trampoline = NULL;
       m->set_adapter_trampoline(to_target(adapter_trampoline));
     }
   }
 
-  if (MetaspaceShared::misc_code_dump_space()->used() == 0) {
-    // We have nothing to archive, but let's avoid having an empty region.
-    MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
-  }
+  guarantee(p <= mc_space->top(), "Estimate of trampoline size is insufficient");
 }
 
 void DynamicArchiveBuilder::make_klasses_shareable() {
@@ -1002,27 +1008,11 @@
   }
 }
 
-void DynamicArchiveBuilder::write_regions(FileMapInfo* dynamic_info) {
-  dynamic_info->write_region(MetaspaceShared::rw,
-                             MetaspaceShared::read_write_dump_space()->base(),
-                             MetaspaceShared::read_write_dump_space()->used(),
-                             /*read_only=*/false,/*allow_exec=*/false);
-  dynamic_info->write_region(MetaspaceShared::ro,
-                             MetaspaceShared::read_only_dump_space()->base(),
-                             MetaspaceShared::read_only_dump_space()->used(),
-                             /*read_only=*/true, /*allow_exec=*/false);
-  dynamic_info->write_region(MetaspaceShared::mc,
-                             MetaspaceShared::misc_code_dump_space()->base(),
-                             MetaspaceShared::misc_code_dump_space()->used(),
-                             /*read_only=*/false,/*allow_exec=*/true);
-  dynamic_info->write_bitmap_region(ArchivePtrMarker::ptrmap());
-}
-
-void DynamicArchiveBuilder::write_archive(char* serialized_data_start) {
+void DynamicArchiveBuilder::write_archive(char* serialized_data) {
   int num_klasses = _klasses->length();
   int num_symbols = _symbols->length();
 
-  _header->set_serialized_data_start(to_target(serialized_data_start));
+  _header->set_serialized_data(to_target(serialized_data));
 
   FileMapInfo* dynamic_info = FileMapInfo::dynamic_info();
   assert(dynamic_info != NULL, "Sanity");
@@ -1030,7 +1020,7 @@
   // Now write the archived data including the file offsets.
   const char* archive_name = Arguments::GetSharedDynamicArchivePath();
   dynamic_info->open_for_write(archive_name);
-  write_regions(dynamic_info);
+  MetaspaceShared::write_core_archive_regions(dynamic_info);
   dynamic_info->set_final_requested_base((char*)Arguments::default_SharedBaseAddress());
   dynamic_info->set_header_crc(dynamic_info->compute_header_crc());
   dynamic_info->write_header();
--- a/src/hotspot/share/memory/filemap.cpp	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/hotspot/share/memory/filemap.cpp	Wed Jan 22 11:52:27 2020 -0800
@@ -1355,7 +1355,7 @@
 }
 
 // Memory map a region in the address space.
-static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "Bitmap",
+static const char* shared_region_name[] = { "MiscCode", "ReadWrite", "ReadOnly", "Bitmap",
                                             "String1", "String2", "OpenArchive1", "OpenArchive2" };
 
 MapArchiveResult FileMapInfo::map_regions(int regions[], int num_regions, char* mapped_base_address, ReservedSpace rs) {
@@ -1972,12 +1972,13 @@
   }
 }
 
+// The 3 core spaces are MC->RW->RO
 FileMapRegion* FileMapInfo::first_core_space() const {
-  return is_static() ? space_at(MetaspaceShared::mc) : space_at(MetaspaceShared::rw);
+  return space_at(MetaspaceShared::mc);
 }
 
 FileMapRegion* FileMapInfo::last_core_space() const {
-  return is_static() ? space_at(MetaspaceShared::md) : space_at(MetaspaceShared::mc);
+  return space_at(MetaspaceShared::ro);
 }
 
 int FileMapHeader::compute_crc() {
@@ -2051,8 +2052,7 @@
 bool FileMapInfo::is_in_shared_region(const void* p, int idx) {
   assert(idx == MetaspaceShared::ro ||
          idx == MetaspaceShared::rw ||
-         idx == MetaspaceShared::mc ||
-         idx == MetaspaceShared::md, "invalid region index");
+         idx == MetaspaceShared::mc, "invalid region index");
   char* base = region_addr(idx);
   if (p >= base && p < base + space_at(idx)->used()) {
     return true;
--- a/src/hotspot/share/memory/filemap.hpp	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/hotspot/share/memory/filemap.hpp	Wed Jan 22 11:52:27 2020 -0800
@@ -187,7 +187,7 @@
   uintx  _max_heap_size;            // java max heap size during dumping
   CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode
   int     _narrow_klass_shift;      // save narrow klass base and shift
-  size_t  _misc_data_patching_offset;
+  size_t  _cloned_vtables_offset;   // The address of the first cloned vtable
   size_t  _serialized_data_offset;  // Data accessed using {ReadClosure,WriteClosure}::serialize()
   size_t  _i2i_entry_code_buffers_offset;
   size_t  _i2i_entry_code_buffers_size;
@@ -252,8 +252,8 @@
   CompressedOops::Mode narrow_oop_mode()   const { return _narrow_oop_mode; }
   int narrow_klass_shift()                 const { return _narrow_klass_shift; }
   address narrow_klass_base()              const { return (address)mapped_base_address(); }
-  char* misc_data_patching_start()         const { return from_mapped_offset(_misc_data_patching_offset); }
-  char* serialized_data_start()            const { return from_mapped_offset(_serialized_data_offset); }
+  char* cloned_vtables()                   const { return from_mapped_offset(_cloned_vtables_offset); }
+  char* serialized_data()                  const { return from_mapped_offset(_serialized_data_offset); }
   address i2i_entry_code_buffers()         const { return (address)from_mapped_offset(_i2i_entry_code_buffers_offset); }
   size_t i2i_entry_code_buffers_size()     const { return _i2i_entry_code_buffers_size; }
   address heap_end()                       const { return _heap_end; }
@@ -272,8 +272,8 @@
   jshort num_module_paths()                const { return _num_module_paths; }
 
   void set_has_platform_or_app_classes(bool v)   { _has_platform_or_app_classes = v; }
-  void set_misc_data_patching_start(char* p)     { set_mapped_offset(p, &_misc_data_patching_offset); }
-  void set_serialized_data_start(char* p)        { set_mapped_offset(p, &_serialized_data_offset); }
+  void set_cloned_vtables(char* p)               { set_mapped_offset(p, &_cloned_vtables_offset); }
+  void set_serialized_data(char* p)              { set_mapped_offset(p, &_serialized_data_offset); }
   void set_base_archive_name_size(size_t s)      { _base_archive_name_size = s; }
   void set_base_archive_is_default(bool b)       { _base_archive_is_default = b; }
   void set_header_size(size_t s)                 { _header_size = s; }
@@ -382,10 +382,10 @@
   jshort app_module_paths_start_index()       const { return header()->app_module_paths_start_index(); }
   jshort app_class_paths_start_index()        const { return header()->app_class_paths_start_index(); }
 
-  char* misc_data_patching_start()            const { return header()->misc_data_patching_start(); }
-  void  set_misc_data_patching_start(char* p) const { header()->set_misc_data_patching_start(p); }
-  char* serialized_data_start()               const { return header()->serialized_data_start(); }
-  void  set_serialized_data_start(char* p)    const { header()->set_serialized_data_start(p); }
+  char* cloned_vtables()                      const { return header()->cloned_vtables(); }
+  void  set_cloned_vtables(char* p)           const { header()->set_cloned_vtables(p); }
+  char* serialized_data()                     const { return header()->serialized_data(); }
+  void  set_serialized_data(char* p)          const { header()->set_serialized_data(p); }
 
   bool  is_file_position_aligned() const;
   void  align_file_position();
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,29 +87,28 @@
 intx MetaspaceShared::_relocation_delta;
 
 // The CDS archive is divided into the following regions:
-//     mc  - misc code (the method entry trampolines)
+//     mc  - misc code (the method entry trampolines, c++ vtables)
 //     rw  - read-write metadata
 //     ro  - read-only metadata and read-only tables
-//     md  - misc data (the c++ vtables)
 //
 //     ca0 - closed archive heap space #0
 //     ca1 - closed archive heap space #1 (may be empty)
 //     oa0 - open archive heap space #0
 //     oa1 - open archive heap space #1 (may be empty)
 //
-// The mc, rw, ro, and md regions are linearly allocated, starting from
-// SharedBaseAddress, in the order of mc->rw->ro->md. The size of these 4 regions
+// The mc, rw, and ro regions are linearly allocated, starting from
+// SharedBaseAddress, in the order of mc->rw->ro. The size of these 3 regions
 // are page-aligned, and there's no gap between any consecutive regions.
 //
-// These 4 regions are populated in the following steps:
+// These 3 regions are populated in the following steps:
 // [1] All classes are loaded in MetaspaceShared::preload_classes(). All metadata are
 //     temporarily allocated outside of the shared regions. Only the method entry
 //     trampolines are written into the mc region.
-// [2] ArchiveCompactor copies RW metadata into the rw region.
-// [3] ArchiveCompactor copies RO metadata into the ro region.
-// [4] SymbolTable, StringTable, SystemDictionary, and a few other read-only data
+// [2] C++ vtables are copied into the mc region.
+// [3] ArchiveCompactor copies RW metadata into the rw region.
+// [4] ArchiveCompactor copies RO metadata into the ro region.
+// [5] SymbolTable, StringTable, SystemDictionary, and a few other read-only data
 //     are copied into the ro region as read-only tables.
-// [5] C++ vtables are copied into the md region.
 //
 // The s0/s1 and oa0/oa1 regions are populated inside HeapShared::archive_java_heap_objects.
 // Their layout is independent of the other 4 regions.
@@ -183,7 +182,7 @@
   }
 }
 
-static DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _md_region("md");
+static DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw");
 static size_t _total_closed_archive_region_size = 0, _total_open_archive_region_size = 0;
 
 void MetaspaceShared::init_shared_dump_space(DumpRegion* first_space, address first_space_bottom) {
@@ -253,9 +252,9 @@
   //
   //                              +-- SharedBaseAddress (default = 0x800000000)
   //                              v
-  // +-..---------+---------+ ... +----+----+----+----+---------------+
-  // |    Heap    | Archive |     | MC | RW | RO | MD | class space   |
-  // +-..---------+---------+ ... +----+----+----+----+---------------+
+  // +-..---------+---------+ ... +----+----+----+--------------------+
+  // |    Heap    | Archive |     | MC | RW | RO |    class space     |
+  // +-..---------+---------+ ... +----+----+----+--------------------+
   // |<--   MaxHeapSize  -->|     |<-- UnscaledClassSpaceMax = 4GB -->|
   //
   const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1);
@@ -684,14 +683,6 @@
     _info->zero();
   }
 
-  // Switch the vtable pointer to point to the cloned vtable.
-  static void patch(Metadata* obj) {
-    assert(DumpSharedSpaces, "dump-time only");
-    assert(MetaspaceShared::is_in_output_space(obj), "must be");
-    *(void**)obj = (void*)(_info->cloned_vtable());
-    ArchivePtrMarker::mark_pointer(obj);
-  }
-
   static bool is_valid_shared_object(const T* obj) {
     intptr_t* vptr = *(intptr_t**)obj;
     return vptr == _info->cloned_vtable();
@@ -702,13 +693,13 @@
 
 template <class T>
 intptr_t* CppVtableCloner<T>::allocate(const char* name) {
-  assert(is_aligned(_md_region.top(), sizeof(intptr_t)), "bad alignment");
+  assert(is_aligned(_mc_region.top(), sizeof(intptr_t)), "bad alignment");
   int n = get_vtable_length(name);
-  _info = (CppVtableInfo*)_md_region.allocate(CppVtableInfo::byte_size(n), sizeof(intptr_t));
+  _info = (CppVtableInfo*)_mc_region.allocate(CppVtableInfo::byte_size(n), sizeof(intptr_t));
   _info->set_vtable_size(n);
 
   intptr_t* p = clone_vtable(name, _info);
-  assert((char*)p == _md_region.top(), "must be");
+  assert((char*)p == _mc_region.top(), "must be");
 
   return _info->cloned_vtable();
 }
@@ -796,18 +787,31 @@
 #define DECLARE_CLONED_VTABLE_KIND(c) c ## _Kind,
 
 enum {
+  // E.g., ConstantPool_Kind == 0, InstanceKlass == 1, etc.
   CPP_VTABLE_PATCH_TYPES_DO(DECLARE_CLONED_VTABLE_KIND)
   _num_cloned_vtable_kinds
 };
 
+// This is the index of all the cloned vtables. E.g., for
+//     ConstantPool* cp = ....; // an archived constant pool
+//     InstanceKlass* ik = ....;// an archived class
+// the following holds true:
+//     _cloned_cpp_vtptrs[ConstantPool_Kind]  == ((intptr_t**)cp)[0]
+//     _cloned_cpp_vtptrs[InstanceKlass_Kind] == ((intptr_t**)ik)[0]
 static intptr_t** _cloned_cpp_vtptrs = NULL;
 
+void MetaspaceShared::allocate_cloned_cpp_vtptrs() {
+  assert(DumpSharedSpaces, "must");
+  size_t vtptrs_bytes = _num_cloned_vtable_kinds * sizeof(intptr_t*);
+  _cloned_cpp_vtptrs = (intptr_t**)_mc_region.allocate(vtptrs_bytes, sizeof(intptr_t*));
+}
+
 void MetaspaceShared::serialize_cloned_cpp_vtptrs(SerializeClosure* soc) {
   soc->do_ptr((void**)&_cloned_cpp_vtptrs);
 }
 
 intptr_t* MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type msotype, address obj) {
-  assert(DynamicDumpSharedSpaces, "must");
+  Arguments::assert_is_dumping_archive();
   int kind = -1;
   switch (msotype) {
   case MetaspaceObj::SymbolType:
@@ -828,10 +832,20 @@
       Klass* k = (Klass*)obj;
       assert(k->is_klass(), "must be");
       if (k->is_instance_klass()) {
-        kind = InstanceKlass_Kind;
+        InstanceKlass* ik = InstanceKlass::cast(k);
+        if (ik->is_class_loader_instance_klass()) {
+          kind = InstanceClassLoaderKlass_Kind;
+        } else if (ik->is_reference_instance_klass()) {
+          kind = InstanceRefKlass_Kind;
+        } else if (ik->is_mirror_instance_klass()) {
+          kind = InstanceMirrorKlass_Kind;
+        } else {
+          kind = InstanceKlass_Kind;
+        }
+      } else if (k->is_typeArray_klass()) {
+        kind = TypeArrayKlass_Kind;
       } else {
-        assert(k->is_objArray_klass(),
-               "We shouldn't archive any other klasses in DynamicDumpSharedSpaces");
+        assert(k->is_objArray_klass(), "must be");
         kind = ObjArrayKlass_Kind;
       }
     }
@@ -872,11 +886,12 @@
 
 //------------------------------ for DynamicDumpSharedSpaces - end
 
-// This can be called at both dump time and run time.
-intptr_t* MetaspaceShared::clone_cpp_vtables(intptr_t* p) {
+// This can be called at both dump time and run time:
+// - clone the contents of the c++ vtables into the space
+//   allocated by allocate_cpp_vtable_clones()
+void MetaspaceShared::clone_cpp_vtables(intptr_t* p) {
   assert(DumpSharedSpaces || UseSharedSpaces, "sanity");
   CPP_VTABLE_PATCH_TYPES_DO(CLONE_CPP_VTABLE);
-  return p;
 }
 
 void MetaspaceShared::zero_cpp_vtable_clones_for_writing() {
@@ -885,7 +900,9 @@
 }
 
 // Allocate and initialize the C++ vtables, starting from top, but do not go past end.
-void MetaspaceShared::allocate_cpp_vtable_clones() {
+char* MetaspaceShared::allocate_cpp_vtable_clones() {
+  char* cloned_vtables = _mc_region.top(); // This is the beginning of all the cloned vtables
+
   assert(DumpSharedSpaces, "dump-time only");
   // Layout (each slot is a intptr_t):
   //   [number of slots in the first vtable = n1]
@@ -895,39 +912,8 @@
   //   ...
   // The order of the vtables is the same as the CPP_VTAB_PATCH_TYPES_DO macro.
   CPP_VTABLE_PATCH_TYPES_DO(ALLOC_CPP_VTABLE_CLONE);
-}
 
-// Switch the vtable pointer to point to the cloned vtable. We assume the
-// vtable pointer is in first slot in object.
-void MetaspaceShared::patch_cpp_vtable_pointers() {
-  int n = _global_klass_objects->length();
-  for (int i = 0; i < n; i++) {
-    Klass* obj = _global_klass_objects->at(i);
-    if (obj->is_instance_klass()) {
-      InstanceKlass* ik = InstanceKlass::cast(obj);
-      if (ik->is_class_loader_instance_klass()) {
-        CppVtableCloner<InstanceClassLoaderKlass>::patch(ik);
-      } else if (ik->is_reference_instance_klass()) {
-        CppVtableCloner<InstanceRefKlass>::patch(ik);
-      } else if (ik->is_mirror_instance_klass()) {
-        CppVtableCloner<InstanceMirrorKlass>::patch(ik);
-      } else {
-        CppVtableCloner<InstanceKlass>::patch(ik);
-      }
-      ConstantPool* cp = ik->constants();
-      CppVtableCloner<ConstantPool>::patch(cp);
-      for (int j = 0; j < ik->methods()->length(); j++) {
-        Method* m = ik->methods()->at(j);
-        CppVtableCloner<Method>::patch(m);
-        assert(CppVtableCloner<Method>::is_valid_shared_object(m), "must be");
-      }
-    } else if (obj->is_objArray_klass()) {
-      CppVtableCloner<ObjArrayKlass>::patch(obj);
-    } else {
-      assert(obj->is_typeArray_klass(), "sanity");
-      CppVtableCloner<TypeArrayKlass>::patch(obj);
-    }
-  }
+  return cloned_vtables;
 }
 
 bool MetaspaceShared::is_valid_shared_method(const Method* m) {
@@ -1008,10 +994,10 @@
     int which = (read_only) ? RO : RW;
     _bytes [which][OtherType] += byte_size;
   }
-  void print_stats(int ro_all, int rw_all, int mc_all, int md_all);
+  void print_stats(int ro_all, int rw_all, int mc_all);
 };
 
-void DumpAllocStats::print_stats(int ro_all, int rw_all, int mc_all, int md_all) {
+void DumpAllocStats::print_stats(int ro_all, int rw_all, int mc_all) {
   // Calculate size of data that was not allocated by Metaspace::allocate()
   MetaspaceSharedStats *stats = MetaspaceShared::stats();
 
@@ -1030,8 +1016,8 @@
   _bytes [RO][StringBucketType] = stats->string.bucket_bytes;
 
   // TODO: count things like dictionary, vtable, etc
-  _bytes[RW][OtherType] += mc_all + md_all;
-  rw_all += mc_all + md_all; // mc/md are mapped Read/Write
+  _bytes[RW][OtherType] += mc_all;
+  rw_all += mc_all; // mc is mapped Read/Write
 
   // prevent divide-by-zero
   if (ro_all < 1) {
@@ -1053,7 +1039,7 @@
 
   LogMessage(cds) msg;
 
-  msg.debug("Detailed metadata info (excluding st regions; rw stats include md/mc regions):");
+  msg.debug("Detailed metadata info (excluding st regions; rw stats include mc regions):");
   msg.debug("%s", hdr);
   msg.debug("%s", sep);
   for (int type = 0; type < int(_number_of_types); type ++) {
@@ -1126,9 +1112,6 @@
 
   VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
   void doit();   // outline because gdb sucks
-  static void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only,  bool allow_exec) {
-    mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec);
-  }
   bool allow_nested_vm_operations() const { return true; }
 }; // class VM_PopulateDumpSharedSpace
 
@@ -1227,6 +1210,13 @@
       newtop = _rw_region.top();
     }
     memcpy(p, obj, bytes);
+
+    intptr_t* cloned_vtable = MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(ref->msotype(), (address)p);
+    if (cloned_vtable != NULL) {
+      *(address*)p = (address)cloned_vtable;
+      ArchivePtrMarker::mark_pointer((address*)p);
+    }
+
     assert(_new_loc_table->lookup(obj) == NULL, "each object can be relocated at most once");
     _new_loc_table->add(obj, (address)p);
     log_trace(cds)("Copy: " PTR_FORMAT " ==> " PTR_FORMAT " %d", p2i(obj), p2i(p), bytes);
@@ -1426,9 +1416,6 @@
 
   SystemDictionaryShared::write_to_archive();
 
-  size_t vtptrs_bytes = _num_cloned_vtable_kinds * sizeof(intptr_t*);
-  _cloned_cpp_vtptrs = (intptr_t**)_ro_region.allocate(vtptrs_bytes, sizeof(intptr_t*));
-
   // Write the other data to the output array.
   char* start = _ro_region.top();
   WriteClosure wc(&_ro_region);
@@ -1464,7 +1451,7 @@
 void VM_PopulateDumpSharedSpace::relocate_to_default_base_address(CHeapBitMap* ptrmap) {
   intx addr_delta = MetaspaceShared::final_delta();
   if (addr_delta == 0) {
-    ArchivePtrMarker::compact((address)SharedBaseAddress, (address)_md_region.top());
+    ArchivePtrMarker::compact((address)SharedBaseAddress, (address)_ro_region.top());
   } else {
     // We are not able to reserve space at Arguments::default_SharedBaseAddress() (due to ASLR).
     // This means that the current content of the archive is based on a random
@@ -1477,7 +1464,7 @@
     // Patch all pointers that are marked by ptrmap within this region,
     // where we have just dumped all the metaspace data.
     address patch_base = (address)SharedBaseAddress;
-    address patch_end  = (address)_md_region.top();
+    address patch_end  = (address)_ro_region.top();
     size_t size = patch_end - patch_base;
 
     // the current value of the pointers to be patched must be within this
@@ -1548,6 +1535,10 @@
   remove_unshareable_in_classes();
   log_info(cds)("done. ");
 
+  MetaspaceShared::allocate_cloned_cpp_vtptrs();
+  char* cloned_vtables = _mc_region.top();
+  MetaspaceShared::allocate_cpp_vtable_clones();
+
   ArchiveCompactor::initialize();
   ArchiveCompactor::copy_and_compact();
 
@@ -1560,16 +1551,8 @@
 
   ArchiveCompactor::relocate_well_known_klasses();
 
-  char* serialized_data_start = dump_read_only_tables();
-  _ro_region.pack(&_md_region);
-
-  char* vtbl_list = _md_region.top();
-  MetaspaceShared::allocate_cpp_vtable_clones();
-  _md_region.pack();
-
-  // During patching, some virtual methods may be called, so at this point
-  // the vtables must contain valid methods (as filled in by CppVtableCloner::allocate).
-  MetaspaceShared::patch_cpp_vtable_pointers();
+  char* serialized_data = dump_read_only_tables();
+  _ro_region.pack();
 
   // The vtable clones contain addresses of the current process.
   // We don't want to write these addresses into the archive.
@@ -1583,21 +1566,12 @@
 
   FileMapInfo* mapinfo = new FileMapInfo(true);
   mapinfo->populate_header(os::vm_allocation_granularity());
-  mapinfo->set_serialized_data_start(serialized_data_start);
-  mapinfo->set_misc_data_patching_start(vtbl_list);
+  mapinfo->set_serialized_data(serialized_data);
+  mapinfo->set_cloned_vtables(cloned_vtables);
   mapinfo->set_i2i_entry_code_buffers(MetaspaceShared::i2i_entry_code_buffers(),
                                       MetaspaceShared::i2i_entry_code_buffers_size());
   mapinfo->open_for_write();
-
-  // NOTE: md contains the trampoline code for method entries, which are patched at run time,
-  // so it needs to be read/write.
-  write_region(mapinfo, MetaspaceShared::mc, &_mc_region, /*read_only=*/false,/*allow_exec=*/true);
-  write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
-  write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
-  write_region(mapinfo, MetaspaceShared::md, &_md_region, /*read_only=*/false,/*allow_exec=*/false);
-
-  mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap());
-
+  MetaspaceShared::write_core_archive_regions(mapinfo);
   _total_closed_archive_region_size = mapinfo->write_archive_heap_regions(
                                         _closed_archive_heap_regions,
                                         _closed_archive_heap_oopmaps,
@@ -1614,14 +1588,11 @@
   mapinfo->write_header();
   mapinfo->close();
 
-  // Restore the vtable in case we invoke any virtual methods.
-  MetaspaceShared::clone_cpp_vtables((intptr_t*)vtbl_list);
-
   print_region_stats();
 
   if (log_is_enabled(Info, cds)) {
     ArchiveCompactor::alloc_stats()->print_stats(int(_ro_region.used()), int(_rw_region.used()),
-                                                 int(_mc_region.used()), int(_md_region.used()));
+                                                 int(_mc_region.used()));
   }
 
   if (PrintSystemDictionaryAtExit) {
@@ -1644,12 +1615,12 @@
   const size_t bitmap_used = ArchivePtrMarker::ptrmap()->size_in_bytes();
   const size_t bitmap_reserved = align_up(bitmap_used, Metaspace::reserve_alignment());
   const size_t total_reserved = _ro_region.reserved()  + _rw_region.reserved() +
-                                _mc_region.reserved()  + _md_region.reserved() +
+                                _mc_region.reserved()  +
                                 bitmap_reserved +
                                 _total_closed_archive_region_size +
                                 _total_open_archive_region_size;
   const size_t total_bytes = _ro_region.used()  + _rw_region.used() +
-                             _mc_region.used()  + _md_region.used() +
+                             _mc_region.used()  +
                              bitmap_used +
                              _total_closed_archive_region_size +
                              _total_open_archive_region_size;
@@ -1658,7 +1629,6 @@
   _mc_region.print(total_reserved);
   _rw_region.print(total_reserved);
   _ro_region.print(total_reserved);
-  _md_region.print(total_reserved);
   print_bitmap_region_stats(bitmap_reserved, total_reserved);
   print_heap_region_stats(_closed_archive_heap_regions, "ca", total_reserved);
   print_heap_region_stats(_open_archive_heap_regions, "oa", total_reserved);
@@ -1685,6 +1655,23 @@
   }
 }
 
+void MetaspaceShared::write_core_archive_regions(FileMapInfo* mapinfo) {
+  // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
+  // MetaspaceShared::n_regions (internal to hotspot).
+  assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
+
+  // mc contains the trampoline code for method entries, which are patched at run time,
+  // so it needs to be read/write.
+  write_region(mapinfo, mc, &_mc_region, /*read_only=*/false,/*allow_exec=*/true);
+  write_region(mapinfo, rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
+  write_region(mapinfo, ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
+  mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap());
+}
+
+void MetaspaceShared::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only,  bool allow_exec) {
+  mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec);
+}
+
 // Update a Java object to point its Klass* to the new location after
 // shared archive has been compacted.
 void MetaspaceShared::relocate_klass_ptr(oop o) {
@@ -2300,15 +2287,10 @@
   }
 }
 
-static int static_regions[]  = {MetaspaceShared::mc,
-                                MetaspaceShared::rw,
-                                MetaspaceShared::ro,
-                                MetaspaceShared::md};
-static int dynamic_regions[] = {MetaspaceShared::rw,
-                                MetaspaceShared::ro,
-                                MetaspaceShared::mc};
-static int static_regions_count  = 4;
-static int dynamic_regions_count = 3;
+static int archive_regions[]  = {MetaspaceShared::mc,
+                                 MetaspaceShared::rw,
+                                 MetaspaceShared::ro};
+static int archive_regions_count  = 3;
 
 MapArchiveResult MetaspaceShared::map_archive(FileMapInfo* mapinfo, char* mapped_base_address, ReservedSpace rs) {
   assert(UseSharedSpaces, "must be runtime");
@@ -2324,9 +2306,8 @@
     return MAP_ARCHIVE_OTHER_FAILURE;
   }
 
-  MapArchiveResult result = mapinfo->is_static() ?
-    mapinfo->map_regions(static_regions, static_regions_count, mapped_base_address, rs) :
-    mapinfo->map_regions(dynamic_regions, dynamic_regions_count, mapped_base_address, rs);
+  MapArchiveResult result =
+    mapinfo->map_regions(archive_regions, archive_regions_count, mapped_base_address, rs);
 
   if (result != MAP_ARCHIVE_SUCCESS) {
     unmap_archive(mapinfo);
@@ -2352,11 +2333,7 @@
 void MetaspaceShared::unmap_archive(FileMapInfo* mapinfo) {
   assert(UseSharedSpaces, "must be runtime");
   if (mapinfo != NULL) {
-    if (mapinfo->is_static()) {
-      mapinfo->unmap_regions(static_regions, static_regions_count);
-    } else {
-      mapinfo->unmap_regions(dynamic_regions, dynamic_regions_count);
-    }
+    mapinfo->unmap_regions(archive_regions, archive_regions_count);
     mapinfo->set_is_mapped(false);
   }
 }
@@ -2368,12 +2345,12 @@
   FileMapInfo *static_mapinfo = FileMapInfo::current_info();
   _i2i_entry_code_buffers = static_mapinfo->i2i_entry_code_buffers();
   _i2i_entry_code_buffers_size = static_mapinfo->i2i_entry_code_buffers_size();
-  char* buffer = static_mapinfo->misc_data_patching_start();
+  char* buffer = static_mapinfo->cloned_vtables();
   clone_cpp_vtables((intptr_t*)buffer);
 
   // Verify various attributes of the archive, plus initialize the
   // shared string/symbol tables
-  buffer = static_mapinfo->serialized_data_start();
+  buffer = static_mapinfo->serialized_data();
   intptr_t* array = (intptr_t*)buffer;
   ReadClosure rc(&array);
   serialize(&rc);
@@ -2388,7 +2365,7 @@
 
   FileMapInfo *dynamic_mapinfo = FileMapInfo::dynamic_info();
   if (dynamic_mapinfo != NULL) {
-    intptr_t* buffer = (intptr_t*)dynamic_mapinfo->serialized_data_start();
+    intptr_t* buffer = (intptr_t*)dynamic_mapinfo->serialized_data();
     ReadClosure rc(&buffer);
     SymbolTable::serialize_shared_table_header(&rc, false);
     SystemDictionaryShared::serialize_dictionary_headers(&rc, false);
@@ -2438,7 +2415,6 @@
   _mc_region.print_out_of_space_msg(name, needed_bytes);
   _rw_region.print_out_of_space_msg(name, needed_bytes);
   _ro_region.print_out_of_space_msg(name, needed_bytes);
-  _md_region.print_out_of_space_msg(name, needed_bytes);
 
   vm_exit_during_initialization(err_msg("Unable to allocate from '%s' region", name),
                                 "Please reduce the number of shared classes.");
--- a/src/hotspot/share/memory/metaspaceShared.hpp	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/hotspot/share/memory/metaspaceShared.hpp	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -193,10 +193,9 @@
     mc = 0,  // miscellaneous code for method trampolines
     rw = 1,  // read-write shared space in the heap
     ro = 2,  // read-only shared space in the heap
-    md = 3,  // miscellaneous data for initializing tables, etc.
-    bm = 4,  // relocation bitmaps (freed after file mapping is finished)
-    num_core_region = 4,
-    num_non_heap_spaces = 5,
+    bm = 3,  // relocation bitmaps (freed after file mapping is finished)
+    num_core_region = 3,
+    num_non_heap_spaces = 4,
 
     // mapped java heap regions
     first_closed_archive_heap_region = bm + 1,
@@ -271,8 +270,8 @@
 
   static bool is_shared_dynamic(void* p) NOT_CDS_RETURN_(false);
 
-  static void allocate_cpp_vtable_clones();
-  static intptr_t* clone_cpp_vtables(intptr_t* p);
+  static char* allocate_cpp_vtable_clones();
+  static void clone_cpp_vtables(intptr_t* p);
   static void zero_cpp_vtable_clones_for_writing();
   static void patch_cpp_vtable_pointers();
   static void serialize_cloned_cpp_vtptrs(SerializeClosure* sc);
@@ -346,6 +345,7 @@
 
   static Klass* get_relocated_klass(Klass *k, bool is_final=false);
 
+  static void allocate_cloned_cpp_vtptrs();
   static intptr_t* fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type msotype, address obj);
   static void initialize_ptr_marker(CHeapBitMap* ptrmap);
 
@@ -357,7 +357,11 @@
     //const bool is_windows = true; // enable this to allow testing the windows mmap semantics on Linux, etc.
     return is_windows;
   }
+
+  static void write_core_archive_regions(FileMapInfo* mapinfo);
 private:
+  static void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region,
+                           bool read_only,  bool allow_exec);
   static void read_extra_data(const char* filename, TRAPS) NOT_CDS_RETURN;
   static FileMapInfo* open_static_archive();
   static FileMapInfo* open_dynamic_archive();
--- a/src/hotspot/share/runtime/vmStructs.cpp	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1105,6 +1105,8 @@
   CDS_ONLY(nonstatic_field(FileMapInfo,        _header,                   FileMapHeader*))                                           \
   CDS_ONLY(   static_field(FileMapInfo,        _current_info,             FileMapInfo*))                                             \
   CDS_ONLY(nonstatic_field(FileMapHeader,      _space[0],                 CDSFileMapRegion))                                         \
+  CDS_ONLY(nonstatic_field(FileMapHeader,      _cloned_vtables_offset,    size_t))                                                   \
+  CDS_ONLY(nonstatic_field(FileMapHeader,      _mapped_base_address,      char*))                                                    \
   CDS_ONLY(nonstatic_field(CDSFileMapRegion,   _mapped_base,              char*))                                                    \
   CDS_ONLY(nonstatic_field(CDSFileMapRegion,   _used,                     size_t))                                                   \
                                                                                                                                      \
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java	Wed Jan 22 14:27:13 2020 -0500
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,15 +32,14 @@
 import sun.jvm.hotspot.types.*;
 
 public class FileMapInfo {
-  private static FileMapHeader header;
-  private static Address headerValue;
+  private static FileMapHeader headerObj;
 
-  // Fields for class FileMapHeader
-  private static Address mdSpaceValue;
-  private static Address mdRegionBaseAddress;
-  private static Address mdRegionEndAddress;
+  // Fields for handling the copied C++ vtables
+  private static Address mcRegionBaseAddress;
+  private static Address mcRegionEndAddress;
+  private static Address vtablesStartAddress;
 
-  // HashMap created by mapping the vTable addresses in the md region with
+  // HashMap created by mapping the vTable addresses in the mc region with
   // the corresponding metadata type.
   private static Map<Address, Type> vTableTypeMap;
 
@@ -54,27 +53,59 @@
       });
   }
 
+  static Address getStatic_AddressField(Type type, String fieldName) {
+    AddressField field = type.getAddressField(fieldName);
+    return field.getValue();
+  }
+
+  static Address get_AddressField(Type type, Address instance, String fieldName) {
+    AddressField field = type.getAddressField(fieldName);
+    return field.getValue(instance);
+  }
+
+  static long get_CIntegerField(Type type, Address instance, String fieldName) {
+    CIntegerField field = type.getCIntegerField(fieldName);
+    return field.getValue(instance);
+  }
+
+  // C equivalent:   return &header->_space[index];
+  static Address get_CDSFileMapRegion(Type FileMapHeader_type, Address header, int index) {
+    AddressField spaceField = FileMapHeader_type.getAddressField("_space[0]");
+
+    // size_t offset = offsetof(FileMapHeader, _space[0]);
+    // CDSFileMapRegion* space_0 = ((char*)header) + offset; // space_0 = &header->_space[index];
+    // return ((char*)space_0) + index * sizeof(CDSFileMapRegion);
+    long offset = spaceField.getOffset();
+    Address space_0 = header.addOffsetTo(offset);
+    return space_0.addOffsetTo(index * spaceField.getSize());
+  }
+
   private static void initialize(TypeDataBase db) {
-    // FileMapInfo
-    Type type = db.lookupType("FileMapInfo");
-    AddressField currentInfoField = type.getAddressField("_current_info");
-    long headerFieldOffset = type.getField("_header").getOffset();
-    Address headerAddress = currentInfoField.getValue().addOffsetTo(headerFieldOffset);
-    headerValue = headerAddress.getAddressAt(0);
+    Type FileMapInfo_type = db.lookupType("FileMapInfo");
+    Type FileMapHeader_type = db.lookupType("FileMapHeader");
+    Type CDSFileMapRegion_type = db.lookupType("CDSFileMapRegion");
 
-    // FileMapHeader
-    type = db.lookupType("FileMapHeader");
-    AddressField spaceField = type.getAddressField("_space[0]");
-    Address spaceValue = headerValue.addOffsetTo(type.getField("_space[0]").getOffset());
-    mdSpaceValue = spaceValue.addOffsetTo(3 * spaceField.getSize());
+    // FileMapInfo * info = FileMapInfo::_current_info;
+    // FileMapHeader* header = info->_header
+    Address info = getStatic_AddressField(FileMapInfo_type, "_current_info");
+    Address header = get_AddressField(FileMapInfo_type, info, "_header");
+    headerObj = (FileMapHeader) VMObjectFactory.newObject(FileMapInfo.FileMapHeader.class, header);
 
-    // SpaceInfo
-    type = db.lookupType("CDSFileMapRegion");
-    long mdRegionBaseAddressOffset = type.getField("_mapped_base").getOffset();
-    mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
-    long mdRegionSizeOffset = type.getField("_used").getOffset();
-    long mdRegionSize = (mdSpaceValue.addOffsetTo(mdRegionSizeOffset)).getAddressAt(0).asLongValue();
-    mdRegionEndAddress = mdRegionBaseAddress.addOffsetTo(mdRegionSize);
+    // char* mapped_base_address = header->_mapped_base_address
+    // size_t cloned_vtable_offset = header->_cloned_vtable_offset
+    // char* vtablesStartAddress = mapped_base_address + cloned_vtable_offset;
+    Address mapped_base_address = get_AddressField(FileMapHeader_type, header, "_mapped_base_address");
+    long cloned_vtable_offset = get_CIntegerField(FileMapHeader_type, header, "_cloned_vtables_offset");
+    vtablesStartAddress = mapped_base_address.addOffsetTo(cloned_vtable_offset);
+
+    // CDSFileMapRegion* mc_space = &header->_space[mc];
+    // char* mcRegionBaseAddress = mc_space->_mapped_base;
+    // size_t used = mc_space->_used;
+    // char* mcRegionEndAddress = mcRegionBaseAddress + used;
+    Address mc_space = get_CDSFileMapRegion(FileMapHeader_type, header, 0);
+    mcRegionBaseAddress = get_AddressField(CDSFileMapRegion_type, mc_space, "_mapped_base");
+    long used = get_CIntegerField(CDSFileMapRegion_type, mc_space, "_used");
+    mcRegionEndAddress = mcRegionBaseAddress.addOffsetTo(used);
 
     populateMetadataTypeArray(db);
   }
@@ -93,10 +124,7 @@
   }
 
   public FileMapHeader getHeader() {
-    if (header == null) {
-      header = (FileMapHeader) VMObjectFactory.newObject(FileMapInfo.FileMapHeader.class, headerValue);
-    }
-    return header;
+    return headerObj;
   }
 
   public boolean inCopiedVtableSpace(Address vptrAddress) {
@@ -121,8 +149,8 @@
     }
 
     public boolean inCopiedVtableSpace(Address vptrAddress) {
-      if (vptrAddress.greaterThan(mdRegionBaseAddress) &&
-          vptrAddress.lessThanOrEqual(mdRegionEndAddress)) {
+      if (vptrAddress.greaterThan(mcRegionBaseAddress) &&
+          vptrAddress.lessThanOrEqual(mcRegionEndAddress)) {
         return true;
       }
       return false;
@@ -133,7 +161,7 @@
       long metadataVTableSize = 0;
       long addressSize = VM.getVM().getAddressSize();
 
-      Address copiedVtableAddress = mdRegionBaseAddress;
+      Address copiedVtableAddress = vtablesStartAddress;
       for (int i=0; i < metadataTypeArray.length; i++) {
         // The first entry denotes the vtable size.
         metadataVTableSize = copiedVtableAddress.getAddressAt(0).asLongValue();
--- a/test/hotspot/jtreg/runtime/cds/SpaceUtilizationCheck.java	Wed Jan 22 14:27:13 2020 -0500
+++ b/test/hotspot/jtreg/runtime/cds/SpaceUtilizationCheck.java	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -104,8 +104,8 @@
                 }
             }
         }
-        if (checked.size() != 4) {
-          throw new RuntimeException("Must have 4 consecutive, fully utilized regions");
+        if (checked.size() != 3) {
+          throw new RuntimeException("Must have 3 consecutive, fully utilized regions"); // MC,RW,RO
         }
     }
 }
--- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java	Wed Jan 22 14:27:13 2020 -0500
+++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,7 +74,7 @@
         "mc",          // MiscCode
         "rw",          // ReadWrite
         "ro",          // ReadOnly
-        "md",          // MiscData
+        "bm",          // relocation bitmaps
         "first_closed_archive",
         "last_closed_archive",
         "first_open_archive",
--- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java	Wed Jan 22 14:27:13 2020 -0500
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java	Wed Jan 22 11:52:27 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@
 public class ArchiveConsistency extends DynamicArchiveTestBase {
     public static WhiteBox wb;
     public static int int_size;        // size of int
-    public static String[] shared_region_name = {"MiscCode", "ReadWrite", "ReadOnly", "MiscData"};
+    public static String[] shared_region_name = {"MiscCode", "ReadWrite", "ReadOnly", "BitMap"};
     public static int num_regions = shared_region_name.length;
 
     public static void main(String[] args) throws Exception {