dictionary.hpp revision 2062:3582bf76420e
1/* 2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25#ifndef SHARE_VM_CLASSFILE_DICTIONARY_HPP 26#define SHARE_VM_CLASSFILE_DICTIONARY_HPP 27 28#include "classfile/systemDictionary.hpp" 29#include "oops/instanceKlass.hpp" 30#include "oops/oop.hpp" 31#include "utilities/hashtable.hpp" 32 33class DictionaryEntry; 34 35//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36// The data structure for the system dictionary (and the shared system 37// dictionary). 38 39class Dictionary : public TwoOopHashtable<klassOop> { 40 friend class VMStructs; 41private: 42 // current iteration index. 43 static int _current_class_index; 44 // pointer to the current hash table entry. 45 static DictionaryEntry* _current_class_entry; 46 47 DictionaryEntry* get_entry(int index, unsigned int hash, 48 Symbol* name, Handle loader); 49 50 DictionaryEntry* bucket(int i) { 51 return (DictionaryEntry*)Hashtable<klassOop>::bucket(i); 52 } 53 54 // The following method is not MT-safe and must be done under lock. 55 DictionaryEntry** bucket_addr(int i) { 56 return (DictionaryEntry**)Hashtable<klassOop>::bucket_addr(i); 57 } 58 59 void add_entry(int index, DictionaryEntry* new_entry) { 60 Hashtable<klassOop>::add_entry(index, (HashtableEntry<oop>*)new_entry); 61 } 62 63 64public: 65 Dictionary(int table_size); 66 Dictionary(int table_size, HashtableBucket* t, int number_of_entries); 67 68 DictionaryEntry* new_entry(unsigned int hash, klassOop klass, oop loader); 69 70 DictionaryEntry* new_entry(); 71 72 void free_entry(DictionaryEntry* entry); 73 74 void add_klass(Symbol* class_name, Handle class_loader,KlassHandle obj); 75 76 klassOop find_class(int index, unsigned int hash, 77 Symbol* name, Handle loader); 78 79 klassOop find_shared_class(int index, unsigned int hash, Symbol* name); 80 81 // Compiler support 82 klassOop try_get_next_class(); 83 84 // GC support 85 86 void oops_do(OopClosure* f); 87 void always_strong_classes_do(OopClosure* blk); 88 void classes_do(void f(klassOop)); 89 void classes_do(void f(klassOop, TRAPS), TRAPS); 90 void classes_do(void f(klassOop, oop)); 91 void classes_do(void f(klassOop, oop, TRAPS), TRAPS); 92 93 void methods_do(void f(methodOop)); 94 95 96 // Classes loaded by the bootstrap loader are always strongly reachable. 97 // If we're not doing class unloading, all classes are strongly reachable. 98 static bool is_strongly_reachable(oop class_loader, klassOop klass) { 99 assert (klass != NULL, "should have non-null klass"); 100 return (class_loader == NULL || !ClassUnloading); 101 } 102 103 // Unload (that is, break root links to) all unmarked classes and 104 // loaders. Returns "true" iff something was unloaded. 105 bool do_unloading(BoolObjectClosure* is_alive); 106 107 // Protection domains 108 klassOop find(int index, unsigned int hash, Symbol* name, 109 Handle loader, Handle protection_domain, TRAPS); 110 bool is_valid_protection_domain(int index, unsigned int hash, 111 Symbol* name, Handle class_loader, 112 Handle protection_domain); 113 void add_protection_domain(int index, unsigned int hash, 114 instanceKlassHandle klass, Handle loader, 115 Handle protection_domain, TRAPS); 116 117 // Sharing support 118 void dump(SerializeOopClosure* soc); 119 void restore(SerializeOopClosure* soc); 120 void reorder_dictionary(); 121 122 123#ifndef PRODUCT 124 void print(); 125#endif 126 void verify(); 127}; 128 129// The following classes can be in dictionary.cpp, but we need these 130// to be in header file so that SA's vmStructs can access. 131 132class ProtectionDomainEntry :public CHeapObj { 133 friend class VMStructs; 134 public: 135 ProtectionDomainEntry* _next; 136 oop _protection_domain; 137 138 ProtectionDomainEntry(oop protection_domain, ProtectionDomainEntry* next) { 139 _protection_domain = protection_domain; 140 _next = next; 141 } 142 143 ProtectionDomainEntry* next() { return _next; } 144 oop protection_domain() { return _protection_domain; } 145}; 146 147// An entry in the system dictionary, this describes a class as 148// { klassOop, loader, protection_domain }. 149 150class DictionaryEntry : public HashtableEntry<klassOop> { 151 friend class VMStructs; 152 private: 153 // Contains the set of approved protection domains that can access 154 // this system dictionary entry. 155 ProtectionDomainEntry* _pd_set; 156 oop _loader; 157 158 159 public: 160 // Tells whether a protection is in the approved set. 161 bool contains_protection_domain(oop protection_domain) const; 162 // Adds a protection domain to the approved set. 163 void add_protection_domain(oop protection_domain); 164 165 klassOop klass() const { return (klassOop)literal(); } 166 klassOop* klass_addr() { return (klassOop*)literal_addr(); } 167 168 DictionaryEntry* next() const { 169 return (DictionaryEntry*)HashtableEntry<klassOop>::next(); 170 } 171 172 DictionaryEntry** next_addr() { 173 return (DictionaryEntry**)HashtableEntry<klassOop>::next_addr(); 174 } 175 176 oop loader() const { return _loader; } 177 void set_loader(oop loader) { _loader = loader; } 178 oop* loader_addr() { return &_loader; } 179 180 ProtectionDomainEntry* pd_set() const { return _pd_set; } 181 void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; } 182 183 bool has_protection_domain() { return _pd_set != NULL; } 184 185 // Tells whether the initiating class' protection can access the this _klass 186 bool is_valid_protection_domain(Handle protection_domain) { 187 if (!ProtectionDomainVerification) return true; 188 if (!SystemDictionary::has_checkPackageAccess()) return true; 189 190 return protection_domain() == NULL 191 ? true 192 : contains_protection_domain(protection_domain()); 193 } 194 195 196 void protection_domain_set_oops_do(OopClosure* f) { 197 for (ProtectionDomainEntry* current = _pd_set; 198 current != NULL; 199 current = current->_next) { 200 f->do_oop(&(current->_protection_domain)); 201 } 202 } 203 204 void verify_protection_domain_set() { 205 for (ProtectionDomainEntry* current = _pd_set; 206 current != NULL; 207 current = current->_next) { 208 current->_protection_domain->verify(); 209 } 210 } 211 212 bool equals(Symbol* class_name, oop class_loader) const { 213 klassOop klass = (klassOop)literal(); 214 return (instanceKlass::cast(klass)->name() == class_name && 215 _loader == class_loader); 216 } 217 218 void print() { 219 int count = 0; 220 for (ProtectionDomainEntry* current = _pd_set; 221 current != NULL; 222 current = current->_next) { 223 count++; 224 } 225 tty->print_cr("pd set = #%d", count); 226 } 227}; 228 229// Entry in a SymbolPropertyTable, mapping a single Symbol* 230// to a managed and an unmanaged pointer. 231class SymbolPropertyEntry : public HashtableEntry<Symbol*> { 232 friend class VMStructs; 233 private: 234 intptr_t _symbol_mode; // secondary key 235 oop _property_oop; 236 address _property_data; 237 238 public: 239 Symbol* symbol() const { return literal(); } 240 241 intptr_t symbol_mode() const { return _symbol_mode; } 242 void set_symbol_mode(intptr_t m) { _symbol_mode = m; } 243 244 oop property_oop() const { return _property_oop; } 245 void set_property_oop(oop p) { _property_oop = p; } 246 247 address property_data() const { return _property_data; } 248 void set_property_data(address p) { _property_data = p; } 249 250 SymbolPropertyEntry* next() const { 251 return (SymbolPropertyEntry*)HashtableEntry<Symbol*>::next(); 252 } 253 254 SymbolPropertyEntry** next_addr() { 255 return (SymbolPropertyEntry**)HashtableEntry<Symbol*>::next_addr(); 256 } 257 258 oop* property_oop_addr() { return &_property_oop; } 259 260 void print_on(outputStream* st) const { 261 symbol()->print_value_on(st); 262 st->print("/mode="INTX_FORMAT, symbol_mode()); 263 st->print(" -> "); 264 bool printed = false; 265 if (property_oop() != NULL) { 266 property_oop()->print_value_on(st); 267 printed = true; 268 } 269 if (property_data() != NULL) { 270 if (printed) st->print(" and "); 271 st->print(INTPTR_FORMAT, property_data()); 272 printed = true; 273 } 274 st->print_cr(printed ? "" : "(empty)"); 275 } 276}; 277 278// A system-internal mapping of symbols to pointers, both managed 279// and unmanaged. Used to record the auto-generation of each method 280// MethodHandle.invoke(S)T, for all signatures (S)T. 281class SymbolPropertyTable : public Hashtable<Symbol*> { 282 friend class VMStructs; 283private: 284 SymbolPropertyEntry* bucket(int i) { 285 return (SymbolPropertyEntry*) Hashtable<Symbol*>::bucket(i); 286 } 287 288 // The following method is not MT-safe and must be done under lock. 289 SymbolPropertyEntry** bucket_addr(int i) { 290 return (SymbolPropertyEntry**) Hashtable<Symbol*>::bucket_addr(i); 291 } 292 293 void add_entry(int index, SymbolPropertyEntry* new_entry) { 294 ShouldNotReachHere(); 295 } 296 void set_entry(int index, SymbolPropertyEntry* new_entry) { 297 ShouldNotReachHere(); 298 } 299 300 SymbolPropertyEntry* new_entry(unsigned int hash, Symbol* symbol, intptr_t symbol_mode) { 301 SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable<Symbol*>::new_entry(hash, symbol); 302 // Hashtable with Symbol* literal must increment and decrement refcount. 303 symbol->increment_refcount(); 304 entry->set_symbol_mode(symbol_mode); 305 entry->set_property_oop(NULL); 306 entry->set_property_data(NULL); 307 return entry; 308 } 309 310public: 311 SymbolPropertyTable(int table_size); 312 SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries); 313 314 void free_entry(SymbolPropertyEntry* entry) { 315 // decrement Symbol refcount here because hashtable doesn't. 316 entry->literal()->decrement_refcount(); 317 Hashtable<Symbol*>::free_entry(entry); 318 } 319 320 unsigned int compute_hash(Symbol* sym, intptr_t symbol_mode) { 321 // Use the regular identity_hash. 322 return Hashtable<Symbol*>::compute_hash(sym) ^ symbol_mode; 323 } 324 325 int index_for(Symbol* name, intptr_t symbol_mode) { 326 return hash_to_index(compute_hash(name, symbol_mode)); 327 } 328 329 // need not be locked; no state change 330 SymbolPropertyEntry* find_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode); 331 332 // must be done under SystemDictionary_lock 333 SymbolPropertyEntry* add_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode); 334 335 // GC support 336 void oops_do(OopClosure* f); 337 void methods_do(void f(methodOop)); 338 339 // Sharing support 340 void dump(SerializeOopClosure* soc); 341 void restore(SerializeOopClosure* soc); 342 void reorder_dictionary(); 343 344#ifndef PRODUCT 345 void print(); 346#endif 347 void verify(); 348}; 349#endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP 350