hotspot/src/share/vm/oops/constantPool.cpp
changeset 46810 7dad333205cd
parent 46746 ea379ebb9447
child 46816 f64eb2bfb250
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Mon Aug 14 16:48:44 2017 +0200
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Mon Aug 14 14:32:17 2017 -0400
@@ -33,6 +33,7 @@
 #include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceClosure.hpp"
+#include "memory/metaspaceShared.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/constantPool.hpp"
@@ -47,6 +48,9 @@
 #include "runtime/signature.hpp"
 #include "runtime/vframe.hpp"
 #include "utilities/copy.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1SATBCardTableModRefBS.hpp"
+#endif // INCLUDE_ALL_GCS
 
 ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
   Array<u1>* tags = MetadataFactory::new_array<u1>(loader_data, length, 0, CHECK_NULL);
@@ -238,11 +242,53 @@
   release_tag_at_put(class_index, JVM_CONSTANT_Class);
 }
 
+#if INCLUDE_CDS_JAVA_HEAP
+// Archive the resolved references
+void ConstantPool::archive_resolved_references(Thread* THREAD) {
+  if (_cache == NULL) {
+    return; // nothing to do
+  }
+
+  InstanceKlass *ik = pool_holder();
+  if (!(ik->is_shared_boot_class() || ik->is_shared_platform_class() ||
+        ik->is_shared_app_class())) {
+    // Archiving resolved references for classes from non-builtin loaders
+    // is not yet supported.
+    set_resolved_references(NULL);
+    return;
+  }
+
+  objArrayOop rr = resolved_references();
+  if (rr != NULL) {
+    for (int i = 0; i < rr->length(); i++) {
+      oop p = rr->obj_at(i);
+      if (p != NULL) {
+        int index = object_to_cp_index(i);
+        if (tag_at(index).is_string()) {
+          oop op = StringTable::create_archived_string(p, THREAD);
+          // If the String object is not archived (possibly too large),
+          // NULL is returned. Also set it in the array, so we won't
+          // have a 'bad' reference in the archived resolved_reference
+          // array.
+          rr->obj_at_put(i, op);
+        } else {
+          rr->obj_at_put(i, NULL);
+        }
+      }
+    }
+    oop archived = MetaspaceShared::archive_heap_object(rr, THREAD);
+    _cache->set_archived_references(archived);
+    set_resolved_references(NULL);
+  }
+}
+#endif
+
 // CDS support. Create a new resolved_references array.
 void ConstantPool::restore_unshareable_info(TRAPS) {
   assert(is_constantPool(), "ensure C++ vtable is restored");
   assert(on_stack(), "should always be set for shared constant pools");
   assert(is_shared(), "should always be set for shared constant pools");
+  assert(_cache != NULL, "constant pool _cache should not be NULL");
 
   // Only create the new resolved references array if it hasn't been attempted before
   if (resolved_references() != NULL) return;
@@ -251,14 +297,30 @@
   restore_vtable();
 
   if (SystemDictionary::Object_klass_loaded()) {
-    // Recreate the object array and add to ClassLoaderData.
-    int map_length = resolved_reference_length();
-    if (map_length > 0) {
-      objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
-      Handle refs_handle (THREAD, (oop)stom);  // must handleize.
-
-      ClassLoaderData* loader_data = pool_holder()->class_loader_data();
+    ClassLoaderData* loader_data = pool_holder()->class_loader_data();
+#if INCLUDE_CDS_JAVA_HEAP
+    if (MetaspaceShared::open_archive_heap_region_mapped() &&
+        _cache->archived_references() != NULL) {
+      oop archived = _cache->archived_references();
+      // Make sure GC knows the cached object is now live. This is necessary after
+      // initial GC marking and during concurrent marking as strong roots are only
+      // scanned during initial marking (at the start of the GC marking).
+      assert(UseG1GC, "Requires G1 GC");
+      G1SATBCardTableModRefBS::enqueue(archived);
+      // Create handle for the archived resolved reference array object
+      Handle refs_handle(THREAD, (oop)archived);
       set_resolved_references(loader_data->add_handle(refs_handle));
+    } else
+#endif
+    {
+      // No mapped archived resolved reference array
+      // Recreate the object array and add to ClassLoaderData.
+      int map_length = resolved_reference_length();
+      if (map_length > 0) {
+        objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
+        Handle refs_handle(THREAD, (oop)stom);  // must handleize.
+        set_resolved_references(loader_data->add_handle(refs_handle));
+      }
     }
   }
 }
@@ -266,10 +328,18 @@
 void ConstantPool::remove_unshareable_info() {
   // Resolved references are not in the shared archive.
   // Save the length for restoration.  It is not necessarily the same length
-  // as reference_map.length() if invokedynamic is saved.
+  // as reference_map.length() if invokedynamic is saved. It is needed when
+  // re-creating the resolved reference array if archived heap data cannot be map
+  // at runtime.
   set_resolved_reference_length(
     resolved_references() != NULL ? resolved_references()->length() : 0);
-  set_resolved_references(NULL);
+
+  // If archiving heap objects is not allowed, clear the resolved references.
+  // Otherwise, it is cleared after the resolved references array is cached
+  // (see archive_resolved_references()).
+  if (!MetaspaceShared::is_heap_object_archiving_allowed()) {
+    set_resolved_references(NULL);
+  }
 
   // Shared ConstantPools are in the RO region, so the _flags cannot be modified.
   // The _on_stack flag is used to prevent ConstantPools from deallocation during
@@ -619,19 +689,19 @@
   }
 }
 
-// Resolve all the classes in the constant pool.  If they are all resolved,
-// the constant pool is read-only.  Enhancement: allocate cp entries to
-// another metaspace, and copy to read-only or read-write space if this
-// bit is set.
 bool ConstantPool::resolve_class_constants(TRAPS) {
   constantPoolHandle cp(THREAD, this);
   for (int index = 1; index < length(); index++) { // Index 0 is unused
-    if (tag_at(index).is_unresolved_klass() &&
-        klass_at_if_loaded(cp, index) == NULL) {
-      return false;
+    if (tag_at(index).is_string()) {
+      Symbol* sym = cp->unresolved_string_at(index);
+      // Look up only. Only resolve references to already interned strings.
+      oop str = StringTable::lookup(sym);
+      if (str != NULL) {
+        int cache_index = cp->cp_to_object_index(index);
+        cp->string_at_put(index, cache_index, str);
+      }
+    }
   }
-  }
-  // set_preresolution(); or some bit for future use
   return true;
 }