duke@435: /* hseigel@5784: * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_CLASSFILE_DICTIONARY_HPP stefank@2314: #define SHARE_VM_CLASSFILE_DICTIONARY_HPP stefank@2314: stefank@2314: #include "classfile/systemDictionary.hpp" stefank@2314: #include "oops/instanceKlass.hpp" stefank@2314: #include "oops/oop.hpp" stefank@2314: #include "utilities/hashtable.hpp" stefank@2314: duke@435: class DictionaryEntry; coleenp@4037: class PSPromotionManager; duke@435: duke@435: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ duke@435: // The data structure for the system dictionary (and the shared system duke@435: // dictionary). duke@435: coleenp@4037: class Dictionary : public TwoOopHashtable { duke@435: friend class VMStructs; duke@435: private: duke@435: // current iteration index. duke@435: static int _current_class_index; duke@435: // pointer to the current hash table entry. duke@435: static DictionaryEntry* _current_class_entry; duke@435: duke@435: DictionaryEntry* get_entry(int index, unsigned int hash, coleenp@4037: Symbol* name, ClassLoaderData* loader_data); duke@435: duke@435: DictionaryEntry* bucket(int i) { coleenp@4037: return (DictionaryEntry*)Hashtable::bucket(i); duke@435: } duke@435: duke@435: // The following method is not MT-safe and must be done under lock. duke@435: DictionaryEntry** bucket_addr(int i) { coleenp@4037: return (DictionaryEntry**)Hashtable::bucket_addr(i); duke@435: } duke@435: duke@435: void add_entry(int index, DictionaryEntry* new_entry) { coleenp@4037: Hashtable::add_entry(index, (HashtableEntry*)new_entry); duke@435: } duke@435: duke@435: public: duke@435: Dictionary(int table_size); zgu@3900: Dictionary(int table_size, HashtableBucket* t, int number_of_entries); duke@435: coleenp@4037: DictionaryEntry* new_entry(unsigned int hash, Klass* klass, ClassLoaderData* loader_data); duke@435: duke@435: DictionaryEntry* new_entry(); duke@435: duke@435: void free_entry(DictionaryEntry* entry); duke@435: coleenp@4037: void add_klass(Symbol* class_name, ClassLoaderData* loader_data,KlassHandle obj); duke@435: coleenp@4037: Klass* find_class(int index, unsigned int hash, coleenp@4037: Symbol* name, ClassLoaderData* loader_data); duke@435: coleenp@4037: Klass* find_shared_class(int index, unsigned int hash, Symbol* name); duke@435: duke@435: // Compiler support coleenp@4037: Klass* try_get_next_class(); duke@435: duke@435: // GC support coleenp@4037: void oops_do(OopClosure* f); coleenp@4037: void always_strong_oops_do(OopClosure* blk); duke@435: coleenp@4037: void always_strong_classes_do(KlassClosure* closure); duke@435: coleenp@4037: void classes_do(void f(Klass*)); coleenp@4037: void classes_do(void f(Klass*, TRAPS), TRAPS); coleenp@4037: void classes_do(void f(Klass*, ClassLoaderData*)); coleenp@4037: coleenp@4037: void methods_do(void f(Method*)); duke@435: duke@435: duke@435: // Classes loaded by the bootstrap loader are always strongly reachable. duke@435: // If we're not doing class unloading, all classes are strongly reachable. coleenp@4037: static bool is_strongly_reachable(ClassLoaderData* loader_data, Klass* klass) { duke@435: assert (klass != NULL, "should have non-null klass"); coleenp@4037: return (loader_data->is_the_null_class_loader_data() || !ClassUnloading); duke@435: } duke@435: duke@435: // Unload (that is, break root links to) all unmarked classes and duke@435: // loaders. Returns "true" iff something was unloaded. coleenp@4037: bool do_unloading(); duke@435: duke@435: // Protection domains coleenp@4037: Klass* find(int index, unsigned int hash, Symbol* name, coleenp@4037: ClassLoaderData* loader_data, Handle protection_domain, TRAPS); duke@435: bool is_valid_protection_domain(int index, unsigned int hash, coleenp@4037: Symbol* name, ClassLoaderData* loader_data, duke@435: Handle protection_domain); duke@435: void add_protection_domain(int index, unsigned int hash, coleenp@4037: instanceKlassHandle klass, ClassLoaderData* loader_data, duke@435: Handle protection_domain, TRAPS); duke@435: duke@435: // Sharing support duke@435: void reorder_dictionary(); duke@435: duke@435: duke@435: #ifndef PRODUCT duke@435: void print(); duke@435: #endif duke@435: void verify(); duke@435: }; duke@435: duke@435: // The following classes can be in dictionary.cpp, but we need these duke@435: // to be in header file so that SA's vmStructs can access. duke@435: zgu@3900: class ProtectionDomainEntry :public CHeapObj { duke@435: friend class VMStructs; duke@435: public: duke@435: ProtectionDomainEntry* _next; duke@435: oop _protection_domain; duke@435: duke@435: ProtectionDomainEntry(oop protection_domain, ProtectionDomainEntry* next) { duke@435: _protection_domain = protection_domain; duke@435: _next = next; duke@435: } duke@435: duke@435: ProtectionDomainEntry* next() { return _next; } duke@435: oop protection_domain() { return _protection_domain; } duke@435: }; duke@435: duke@435: // An entry in the system dictionary, this describes a class as coleenp@4037: // { Klass*, loader, protection_domain }. duke@435: coleenp@4037: class DictionaryEntry : public HashtableEntry { duke@435: friend class VMStructs; duke@435: private: duke@435: // Contains the set of approved protection domains that can access duke@435: // this system dictionary entry. duke@435: ProtectionDomainEntry* _pd_set; coleenp@4037: ClassLoaderData* _loader_data; duke@435: duke@435: public: duke@435: // Tells whether a protection is in the approved set. duke@435: bool contains_protection_domain(oop protection_domain) const; duke@435: // Adds a protection domain to the approved set. duke@435: void add_protection_domain(oop protection_domain); duke@435: coleenp@4037: Klass* klass() const { return (Klass*)literal(); } coleenp@4037: Klass** klass_addr() { return (Klass**)literal_addr(); } duke@435: duke@435: DictionaryEntry* next() const { coleenp@4037: return (DictionaryEntry*)HashtableEntry::next(); duke@435: } duke@435: duke@435: DictionaryEntry** next_addr() { coleenp@4037: return (DictionaryEntry**)HashtableEntry::next_addr(); duke@435: } duke@435: coleenp@4037: ClassLoaderData* loader_data() const { return _loader_data; } coleenp@4037: void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; } duke@435: duke@435: ProtectionDomainEntry* pd_set() const { return _pd_set; } duke@435: void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; } duke@435: duke@435: bool has_protection_domain() { return _pd_set != NULL; } duke@435: duke@435: // Tells whether the initiating class' protection can access the this _klass duke@435: bool is_valid_protection_domain(Handle protection_domain) { duke@435: if (!ProtectionDomainVerification) return true; duke@435: if (!SystemDictionary::has_checkPackageAccess()) return true; duke@435: duke@435: return protection_domain() == NULL duke@435: ? true duke@435: : contains_protection_domain(protection_domain()); duke@435: } duke@435: duke@435: duke@435: void protection_domain_set_oops_do(OopClosure* f) { duke@435: for (ProtectionDomainEntry* current = _pd_set; duke@435: current != NULL; duke@435: current = current->_next) { duke@435: f->do_oop(&(current->_protection_domain)); duke@435: } duke@435: } duke@435: duke@435: void verify_protection_domain_set() { duke@435: for (ProtectionDomainEntry* current = _pd_set; duke@435: current != NULL; duke@435: current = current->_next) { duke@435: current->_protection_domain->verify(); duke@435: } duke@435: } duke@435: coleenp@4037: bool equals(Symbol* class_name, ClassLoaderData* loader_data) const { coleenp@4037: Klass* klass = (Klass*)literal(); coleenp@4037: return (InstanceKlass::cast(klass)->name() == class_name && coleenp@4037: _loader_data == loader_data); duke@435: } duke@435: duke@435: void print() { duke@435: int count = 0; duke@435: for (ProtectionDomainEntry* current = _pd_set; duke@435: current != NULL; duke@435: current = current->_next) { duke@435: count++; duke@435: } duke@435: tty->print_cr("pd set = #%d", count); duke@435: } duke@435: }; jrose@1145: coleenp@2497: // Entry in a SymbolPropertyTable, mapping a single Symbol* jrose@1145: // to a managed and an unmanaged pointer. zgu@3900: class SymbolPropertyEntry : public HashtableEntry { jrose@1145: friend class VMStructs; jrose@1145: private: jrose@1862: intptr_t _symbol_mode; // secondary key coleenp@4037: Method* _method; coleenp@4037: oop _method_type; jrose@1145: jrose@1145: public: coleenp@2497: Symbol* symbol() const { return literal(); } jrose@1145: jrose@1862: intptr_t symbol_mode() const { return _symbol_mode; } jrose@1862: void set_symbol_mode(intptr_t m) { _symbol_mode = m; } jrose@1862: coleenp@4037: Method* method() const { return _method; } coleenp@4037: void set_method(Method* p) { _method = p; } jrose@1145: coleenp@4037: oop method_type() const { return _method_type; } coleenp@4037: oop* method_type_addr() { return &_method_type; } coleenp@4037: void set_method_type(oop p) { _method_type = p; } jrose@1145: jrose@1145: SymbolPropertyEntry* next() const { zgu@3900: return (SymbolPropertyEntry*)HashtableEntry::next(); jrose@1145: } jrose@1145: jrose@1145: SymbolPropertyEntry** next_addr() { zgu@3900: return (SymbolPropertyEntry**)HashtableEntry::next_addr(); jrose@1145: } jrose@1145: jrose@1145: void print_on(outputStream* st) const { jrose@1145: symbol()->print_value_on(st); jrose@1862: st->print("/mode="INTX_FORMAT, symbol_mode()); jrose@1145: st->print(" -> "); jrose@1145: bool printed = false; coleenp@4037: if (method() != NULL) { coleenp@4037: method()->print_value_on(st); jrose@1145: printed = true; jrose@1145: } coleenp@4037: if (method_type() != NULL) { jrose@1145: if (printed) st->print(" and "); hseigel@5784: st->print(INTPTR_FORMAT, (void *)method_type()); jrose@1145: printed = true; jrose@1145: } jrose@1145: st->print_cr(printed ? "" : "(empty)"); jrose@1145: } jrose@1145: }; jrose@1145: jrose@1145: // A system-internal mapping of symbols to pointers, both managed jrose@1145: // and unmanaged. Used to record the auto-generation of each method jrose@1145: // MethodHandle.invoke(S)T, for all signatures (S)T. zgu@3900: class SymbolPropertyTable : public Hashtable { jrose@1145: friend class VMStructs; jrose@1145: private: jrose@1145: SymbolPropertyEntry* bucket(int i) { zgu@3900: return (SymbolPropertyEntry*) Hashtable::bucket(i); jrose@1145: } jrose@1145: jrose@1145: // The following method is not MT-safe and must be done under lock. jrose@1145: SymbolPropertyEntry** bucket_addr(int i) { zgu@3900: return (SymbolPropertyEntry**) Hashtable::bucket_addr(i); jrose@1145: } jrose@1145: jrose@1145: void add_entry(int index, SymbolPropertyEntry* new_entry) { jrose@1145: ShouldNotReachHere(); jrose@1145: } jrose@1145: void set_entry(int index, SymbolPropertyEntry* new_entry) { jrose@1145: ShouldNotReachHere(); jrose@1145: } jrose@1145: coleenp@2497: SymbolPropertyEntry* new_entry(unsigned int hash, Symbol* symbol, intptr_t symbol_mode) { zgu@3900: SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol); coleenp@2497: // Hashtable with Symbol* literal must increment and decrement refcount. coleenp@2497: symbol->increment_refcount(); jrose@1862: entry->set_symbol_mode(symbol_mode); coleenp@4037: entry->set_method(NULL); coleenp@4037: entry->set_method_type(NULL); jrose@1145: return entry; jrose@1145: } jrose@1145: jrose@1145: public: jrose@1145: SymbolPropertyTable(int table_size); zgu@3900: SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries); jrose@1145: jrose@1145: void free_entry(SymbolPropertyEntry* entry) { coleenp@2497: // decrement Symbol refcount here because hashtable doesn't. coleenp@2497: entry->literal()->decrement_refcount(); zgu@3900: Hashtable::free_entry(entry); jrose@1145: } jrose@1145: coleenp@2497: unsigned int compute_hash(Symbol* sym, intptr_t symbol_mode) { jrose@1145: // Use the regular identity_hash. zgu@3900: return Hashtable::compute_hash(sym) ^ symbol_mode; jrose@1862: } jrose@1862: coleenp@2497: int index_for(Symbol* name, intptr_t symbol_mode) { jrose@1862: return hash_to_index(compute_hash(name, symbol_mode)); jrose@1145: } jrose@1145: jrose@1145: // need not be locked; no state change coleenp@2497: SymbolPropertyEntry* find_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode); jrose@1145: jrose@1145: // must be done under SystemDictionary_lock coleenp@2497: SymbolPropertyEntry* add_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode); jrose@1145: jrose@1145: // GC support jrose@1145: void oops_do(OopClosure* f); coleenp@4037: coleenp@4037: void methods_do(void f(Method*)); jrose@1145: jrose@1145: // Sharing support jrose@1145: void reorder_dictionary(); jrose@1145: jrose@1145: #ifndef PRODUCT jrose@1145: void print(); jrose@1145: #endif jrose@1145: void verify(); jrose@1145: }; stefank@2314: #endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP