hotspot/src/share/vm/oops/cpCache.cpp
changeset 47103 a993ec29ec75
parent 47095 9d21da6fe729
--- a/hotspot/src/share/vm/oops/cpCache.cpp	Wed Aug 30 19:18:22 2017 -0400
+++ b/hotspot/src/share/vm/oops/cpCache.cpp	Mon Aug 28 15:34:04 2017 -0700
@@ -23,6 +23,8 @@
  */
 
 #include "precompiled.hpp"
+#include "interpreter/bytecodeStream.hpp"
+#include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/rewriter.hpp"
 #include "logging/log.hpp"
@@ -49,6 +51,24 @@
   assert(constant_pool_index() == index, "");
 }
 
+void ConstantPoolCacheEntry::verify_just_initialized(bool f2_used) {
+  assert((_indices & (~cp_index_mask)) == 0, "sanity");
+  assert(_f1 == NULL, "sanity");
+  assert(_flags == 0, "sanity");
+  if (!f2_used) {
+    assert(_f2 == 0, "sanity");
+  }
+}
+
+void ConstantPoolCacheEntry::reinitialize(bool f2_used) {
+  _indices &= cp_index_mask;
+  _f1 = NULL;
+  _flags = 0;
+  if (!f2_used) {
+    _f2 = 0;
+  }
+}
+
 int ConstantPoolCacheEntry::make_flags(TosState state,
                                        int option_bits,
                                        int field_index_or_method_params) {
@@ -609,6 +629,66 @@
   }
 }
 
+void ConstantPoolCache::verify_just_initialized() {
+  DEBUG_ONLY(walk_entries_for_initialization(/*check_only = */ true));
+}
+
+void ConstantPoolCache::remove_unshareable_info() {
+  walk_entries_for_initialization(/*check_only = */ false);
+}
+
+void ConstantPoolCache::walk_entries_for_initialization(bool check_only) {
+  assert(DumpSharedSpaces, "sanity");
+  // When dumping the archive, we want to clean up the ConstantPoolCache
+  // to remove any effect of linking due to the execution of Java code --
+  // each ConstantPoolCacheEntry will have the same contents as if
+  // ConstantPoolCache::initialize has just returned:
+  //
+  // - We keep the ConstantPoolCache::constant_pool_index() bits for all entries.
+  // - We keep the "f2" field for entries used by invokedynamic and invokehandle
+  // - All other bits in the entries are cleared to zero.
+  ResourceMark rm;
+
+  InstanceKlass* ik = constant_pool()->pool_holder();
+  bool* f2_used = NEW_RESOURCE_ARRAY(bool, length());
+  memset(f2_used, 0, sizeof(bool) * length());
+
+  // Find all the slots that we need to preserve f2
+  for (int i = 0; i < ik->methods()->length(); i++) {
+    Method* m = ik->methods()->at(i);
+    RawBytecodeStream bcs(m);
+    while (!bcs.is_last_bytecode()) {
+      Bytecodes::Code opcode = bcs.raw_next();
+      switch (opcode) {
+      case Bytecodes::_invokedynamic: {
+          int index = Bytes::get_native_u4(bcs.bcp() + 1);
+          int cp_cache_index = constant_pool()->invokedynamic_cp_cache_index(index);
+          f2_used[cp_cache_index] = 1;
+        }
+        break;
+      case Bytecodes::_invokehandle: {
+          int cp_cache_index = Bytes::get_native_u2(bcs.bcp() + 1);
+          f2_used[cp_cache_index] = 1;
+        }
+        break;
+      default:
+        break;
+      }
+    }
+  }
+
+  if (check_only) {
+    DEBUG_ONLY(
+      for (int i=0; i<length(); i++) {
+        entry_at(i)->verify_just_initialized(f2_used[i]);
+      })
+  } else {
+    for (int i=0; i<length(); i++) {
+      entry_at(i)->reinitialize(f2_used[i]);
+    }
+  }
+}
+
 void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
   assert(!is_shared(), "shared caches are not deallocated");
   data->remove_handle(_resolved_references);