8150752: Share Class Data
authoriklam
Wed, 06 Apr 2016 21:53:44 -0700
changeset 39713 29ece76096cb
parent 39712 dccb9af07ee1
child 39714 976b97b59d87
8150752: Share Class Data Reviewed-by: acorn, hseigel, mschoene
hotspot/src/share/vm/classfile/compactHashtable.hpp
hotspot/src/share/vm/classfile/symbolTable.cpp
hotspot/src/share/vm/classfile/symbolTable.hpp
hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
hotspot/src/share/vm/classfile/verificationType.cpp
hotspot/src/share/vm/classfile/verificationType.hpp
hotspot/src/share/vm/memory/metaspaceShared.cpp
hotspot/src/share/vm/oops/instanceKlass.cpp
--- a/hotspot/src/share/vm/classfile/compactHashtable.hpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp	Wed Apr 06 21:53:44 2016 -0700
@@ -270,6 +270,10 @@
 
   // For reading from/writing to the CDS archive
   void serialize(SerializeClosure* soc);
+
+  uintx base_address() {
+    return (uintx) _base_address;
+  }
 };
 
 ////////////////////////////////////////////////////////////////////////
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Apr 06 21:53:44 2016 -0700
@@ -238,6 +238,29 @@
   }
 }
 
+u4 SymbolTable::encode_shared(Symbol* sym) {
+  assert(DumpSharedSpaces, "called only during dump time");
+  uintx base_address = uintx(MetaspaceShared::shared_rs()->base());
+  uintx offset = uintx(sym) - base_address;
+  assert(offset < 0x7fffffff, "sanity");
+  return u4(offset);
+}
+
+Symbol* SymbolTable::decode_shared(u4 offset) {
+  assert(!DumpSharedSpaces, "called only during runtime");
+  uintx base_address = _shared_table.base_address();
+  Symbol* sym = (Symbol*)(base_address + offset);
+
+#ifndef PRODUCT
+  const char* s = (const char*)sym->bytes();
+  int len = sym->utf8_length();
+  unsigned int hash = hash_symbol(s, len);
+  assert(sym == lookup_shared(s, len, hash), "must be shared symbol");
+#endif
+
+  return sym;
+}
+
 // Pick hashing algorithm.
 unsigned int SymbolTable::hash_symbol(const char* s, int len) {
   return use_alternate_hashcode() ?
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Apr 06 21:53:44 2016 -0700
@@ -253,6 +253,8 @@
 
   // Sharing
   static void serialize(SerializeClosure* soc);
+  static u4 encode_shared(Symbol* sym);
+  static Symbol* decode_shared(u4 offset);
 
   // Rehash the symbol table if it gets out of balance
   static void rehash_table();
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp	Wed Apr 06 21:53:44 2016 -0700
@@ -78,7 +78,19 @@
                                            TRAPS) {
     return NULL;
   }
+
   static void serialize(SerializeClosure* soc) {}
+
+  // The (non-application) CDS implementation supports only classes in the boot
+  // class loader, which ensures that the verification constraints are the same
+  // during archive creation time and runtime. Thus we can do the constraint checks
+  // entirely during archive creation time.
+  static bool add_verification_constraint(Klass* k, Symbol* name,
+                  Symbol* from_name, bool from_field_is_protected,
+                  bool from_is_array, bool from_is_object) {return false;}
+  static void finalize_verification_constraints() {}
+  static void check_verification_constraints(instanceKlassHandle klass,
+                                              TRAPS) {}
 };
 
 #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
--- a/hotspot/src/share/vm/classfile/verificationType.cpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/classfile/verificationType.cpp	Wed Apr 06 21:53:44 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionaryShared.hpp"
 #include "classfile/verificationType.hpp"
 #include "classfile/verifier.hpp"
 
@@ -41,6 +42,39 @@
   }
 }
 
+bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name,
+         Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object, TRAPS) {
+  Klass* obj = SystemDictionary::resolve_or_fail(
+      name, Handle(THREAD, klass->class_loader()),
+      Handle(THREAD, klass->protection_domain()), true, CHECK_false);
+  if (log_is_enabled(Debug, class, resolve)) {
+    Verifier::trace_class_resolution(obj, klass());
+  }
+
+  KlassHandle this_class(THREAD, obj);
+
+  if (this_class->is_interface() && (!from_field_is_protected ||
+      from_name != vmSymbols::java_lang_Object())) {
+    // If we are not trying to access a protected field or method in
+    // java.lang.Object then, for arrays, we only allow assignability
+    // to interfaces java.lang.Cloneable and java.io.Serializable.
+    // Otherwise, we treat interfaces as java.lang.Object.
+    return !from_is_array ||
+      this_class == SystemDictionary::Cloneable_klass() ||
+      this_class == SystemDictionary::Serializable_klass();
+  } else if (from_is_object) {
+    Klass* from_class = SystemDictionary::resolve_or_fail(
+        from_name, Handle(THREAD, klass->class_loader()),
+        Handle(THREAD, klass->protection_domain()), true, CHECK_false);
+    if (log_is_enabled(Debug, class, resolve)) {
+      Verifier::trace_class_resolution(from_class, klass());
+    }
+    return InstanceKlass::cast(from_class)->is_subclass_of(this_class());
+  }
+
+  return false;
+}
+
 bool VerificationType::is_reference_assignable_from(
     const VerificationType& from, ClassVerifier* context,
     bool from_field_is_protected, TRAPS) const {
@@ -58,33 +92,17 @@
       // any object or array is assignable to java.lang.Object
       return true;
     }
-    Klass* obj = SystemDictionary::resolve_or_fail(
-        name(), Handle(THREAD, klass->class_loader()),
-        Handle(THREAD, klass->protection_domain()), true, CHECK_false);
-    if (log_is_enabled(Debug, class, resolve)) {
-      Verifier::trace_class_resolution(obj, klass());
+
+    if (DumpSharedSpaces && SystemDictionaryShared::add_verification_constraint(klass(),
+              name(), from.name(), from_field_is_protected, from.is_array(),
+              from.is_object())) {
+      // If add_verification_constraint() returns true, the resolution/check should be
+      // delayed until runtime.
+      return true;
     }
 
-    KlassHandle this_class(THREAD, obj);
-
-    if (this_class->is_interface() && (!from_field_is_protected ||
-        from.name() != vmSymbols::java_lang_Object())) {
-      // If we are not trying to access a protected field or method in
-      // java.lang.Object then, for arrays, we only allow assignability
-      // to interfaces java.lang.Cloneable and java.io.Serializable.
-      // Otherwise, we treat interfaces as java.lang.Object.
-      return !from.is_array() ||
-        this_class == SystemDictionary::Cloneable_klass() ||
-        this_class == SystemDictionary::Serializable_klass();
-    } else if (from.is_object()) {
-      Klass* from_class = SystemDictionary::resolve_or_fail(
-          from.name(), Handle(THREAD, klass->class_loader()),
-          Handle(THREAD, klass->protection_domain()), true, CHECK_false);
-      if (log_is_enabled(Debug, class, resolve)) {
-        Verifier::trace_class_resolution(from_class, klass());
-      }
-      return InstanceKlass::cast(from_class)->is_subclass_of(this_class());
-    }
+    return resolve_and_check_assignability(klass(), name(), from.name(),
+          from_field_is_protected, from.is_array(), from.is_object(), THREAD);
   } else if (is_array() && from.is_array()) {
     VerificationType comp_this = get_component(context, CHECK_false);
     VerificationType comp_from = from.get_component(context, CHECK_false);
--- a/hotspot/src/share/vm/classfile/verificationType.hpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/classfile/verificationType.hpp	Wed Apr 06 21:53:44 2016 -0700
@@ -333,6 +333,12 @@
   bool is_reference_assignable_from(
     const VerificationType&, ClassVerifier*, bool from_field_is_protected,
     TRAPS) const;
+
+ public:
+  static bool resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name,
+                                              Symbol* from_name, bool from_field_is_protected,
+                                              bool from_is_array, bool from_is_object,
+                                              TRAPS);
 };
 
 #endif // SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Apr 06 21:53:44 2016 -0700
@@ -806,6 +806,10 @@
       exit(1);
     }
   }
+
+  // Copy the verification constraints from C_HEAP-alloced GrowableArrays to RO-alloced
+  // Arrays
+  SystemDictionaryShared::finalize_verification_constraints();
 }
 
 void MetaspaceShared::prepare_for_dumping() {
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Apr 06 07:55:32 2016 -0400
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Apr 06 21:53:44 2016 -0700
@@ -27,6 +27,7 @@
 #include "classfile/classFileStream.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "classfile/systemDictionaryShared.hpp"
 #include "classfile/verifier.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/dependencyContext.hpp"
@@ -597,6 +598,8 @@
 
         // also sets rewritten
         this_k->rewrite_class(CHECK_false);
+      } else if (this_k->is_shared()) {
+        SystemDictionaryShared::check_verification_constraints(this_k, CHECK_false);
       }
 
       // relocate jsrs and link methods after they are all rewritten