src/hotspot/share/memory/heapShared.cpp
changeset 51491 187c84a5efe1
parent 51467 12997ebbc0d8
child 51701 9012aeaf993b
--- a/src/hotspot/share/memory/heapShared.cpp	Wed Aug 22 16:06:51 2018 +0100
+++ b/src/hotspot/share/memory/heapShared.cpp	Tue Aug 14 09:59:37 2018 -0700
@@ -29,7 +29,7 @@
 #include "logging/log.hpp"
 #include "logging/logMessage.hpp"
 #include "logging/logStream.hpp"
-#include "memory/heapShared.hpp"
+#include "memory/heapShared.inline.hpp"
 #include "memory/iterator.inline.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceClosure.hpp"
@@ -38,6 +38,7 @@
 #include "oops/compressedOops.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
+#include "utilities/bitMap.inline.hpp"
 
 #if INCLUDE_CDS_JAVA_HEAP
 KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
@@ -72,6 +73,9 @@
   return info;
 }
 
+address   HeapShared::_narrow_oop_base;
+int       HeapShared::_narrow_oop_shift;
+
 int HeapShared::num_of_subgraph_infos() {
   int num = 0;
   KlassSubGraphInfo* info = _subgraph_info_list;
@@ -320,7 +324,7 @@
           // point. All objects in the subgraph reachable from the object are
           // also 'known' by GC.
           oop v = MetaspaceShared::materialize_archived_object(
-            CompressedOops::decode(entry_field_records->at(i+1)));
+            entry_field_records->at(i+1));
           m->obj_field_put(field_offset, v);
           i += 2;
         }
@@ -601,4 +605,96 @@
     archive_reachable_objects_from_static_field(info->klass, info->offset, info->type, CHECK);
   }
 }
+
+// At dump-time, find the location of all the non-null oop pointers in an archived heap
+// region. This way we can quickly relocate all the pointers without using
+// BasicOopIterateClosure at runtime.
+class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
+  narrowOop* _start;
+  BitMap *_oopmap;
+  int _num_total_oops;
+  int _num_null_oops;
+ public:
+  FindEmbeddedNonNullPointers(narrowOop* start, BitMap* oopmap)
+    : _start(start), _oopmap(oopmap), _num_total_oops(0),  _num_null_oops(0) {}
+
+  virtual bool should_verify_oops(void) {
+    return false;
+  }
+  virtual void do_oop(narrowOop* p) {
+    _num_total_oops ++;
+    narrowOop v = *p;
+    if (!CompressedOops::is_null(v)) {
+      size_t idx = p - _start;
+      _oopmap->set_bit(idx);
+    } else {
+      _num_null_oops ++;
+    }
+  }
+  virtual void do_oop(oop *p) {
+    ShouldNotReachHere();
+  }
+  int num_total_oops() const { return _num_total_oops; }
+  int num_null_oops()  const { return _num_null_oops; }
+};
+
+ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
+  assert(UseCompressedOops, "must be");
+  size_t num_bits = region.byte_size() / sizeof(narrowOop);
+  ResourceBitMap oopmap(num_bits);
+
+  HeapWord* p   = region.start();
+  HeapWord* end = region.end();
+  FindEmbeddedNonNullPointers finder((narrowOop*)p, &oopmap);
+
+  int num_objs = 0;
+  while (p < end) {
+    oop o = (oop)p;
+    o->oop_iterate(&finder);
+    p += o->size();
+    ++ num_objs;
+  }
+
+  log_info(cds, heap)("calculate_oopmap: objects = %6d, embedded oops = %7d, nulls = %7d",
+                      num_objs, finder.num_total_oops(), finder.num_null_oops());
+  return oopmap;
+}
+
+void HeapShared::init_narrow_oop_decoding(address base, int shift) {
+  _narrow_oop_base = base;
+  _narrow_oop_shift = shift;
+}
+
+// Patch all the embedded oop pointers inside an archived heap region,
+// to be consistent with the runtime oop encoding.
+class PatchEmbeddedPointers: public BitMapClosure {
+  narrowOop* _start;
+
+ public:
+  PatchEmbeddedPointers(narrowOop* start) : _start(start) {}
+
+  bool do_bit(size_t offset) {
+    narrowOop* p = _start + offset;
+    narrowOop v = *p;
+    assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time");
+    oop o = HeapShared::decode_with_archived_oop_encoding_mode(v);
+    RawAccess<IS_NOT_NULL>::oop_store(p, o);
+    return true;
+  }
+};
+
+void HeapShared::patch_archived_heap_embedded_pointers(MemRegion region, address oopmap,
+                                                       size_t oopmap_size_in_bits) {
+  BitMapView bm((BitMap::bm_word_t*)oopmap, oopmap_size_in_bits);
+
+#ifndef PRODUCT
+  ResourceMark rm;
+  ResourceBitMap checkBm = calculate_oopmap(region);
+  assert(bm.is_same(checkBm), "sanity");
+#endif
+
+  PatchEmbeddedPointers patcher((narrowOop*)region.start());
+  bm.iterate(&patcher);
+}
+
 #endif // INCLUDE_CDS_JAVA_HEAP