# HG changeset patch # User iklam # Date 1460004824 25200 # Node ID 29ece76096cb003b51c6633d6da83915bd014143 # Parent dccb9af07ee157221765c2136ee4f177fda458db 8150752: Share Class Data Reviewed-by: acorn, hseigel, mschoene diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/classfile/compactHashtable.hpp --- 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; + } }; //////////////////////////////////////////////////////////////////////// diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/classfile/symbolTable.cpp --- 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() ? diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/classfile/symbolTable.hpp --- 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(); diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/classfile/systemDictionaryShared.hpp --- 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 diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/classfile/verificationType.cpp --- 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); diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/classfile/verificationType.hpp --- 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 diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/memory/metaspaceShared.cpp --- 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() { diff -r dccb9af07ee1 -r 29ece76096cb hotspot/src/share/vm/oops/instanceKlass.cpp --- 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