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 33 class DictionaryEntry; 34 35 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36 // The data structure for the system dictionary (and the shared system 37 // dictionary). 38 39 class Dictionary : public TwoOopHashtable { 40 friend class VMStructs; 41 private: 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 symbolHandle name, Handle loader); 49 50 DictionaryEntry* bucket(int i) { 51 return (DictionaryEntry*)Hashtable::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::bucket_addr(i); 57 } 58 59 void add_entry(int index, DictionaryEntry* new_entry) { 60 Hashtable::add_entry(index, (HashtableEntry*)new_entry); 61 } 62 63 64 public: 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(symbolHandle class_name, Handle class_loader,KlassHandle obj); 75 76 klassOop find_class(int index, unsigned int hash, 77 symbolHandle name, Handle loader); 78 79 klassOop find_shared_class(int index, unsigned int hash, symbolHandle 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, oop 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, symbolHandle name, 109 Handle loader, Handle protection_domain, TRAPS); 110 bool is_valid_protection_domain(int index, unsigned int hash, 111 symbolHandle 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 132 class 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 150 class DictionaryEntry : public HashtableEntry { 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::next(); 170 } 171 172 DictionaryEntry** next_addr() { 173 return (DictionaryEntry**)HashtableEntry::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(symbolOop 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 symbolOop 230 // to a managed and an unmanaged pointer. 231 class SymbolPropertyEntry : public HashtableEntry { 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 symbolOop symbol() const { return (symbolOop) 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::next(); 252 } 253 254 SymbolPropertyEntry** next_addr() { 255 return (SymbolPropertyEntry**)HashtableEntry::next_addr(); 256 } 257 258 oop* symbol_addr() { return literal_addr(); } 259 oop* property_oop_addr() { return &_property_oop; } 260 261 void print_on(outputStream* st) const { 262 symbol()->print_value_on(st); 263 st->print("/mode="INTX_FORMAT, symbol_mode()); 264 st->print(" -> "); 265 bool printed = false; 266 if (property_oop() != NULL) { 267 property_oop()->print_value_on(st); 268 printed = true; 269 } 270 if (property_data() != NULL) { 271 if (printed) st->print(" and "); 272 st->print(INTPTR_FORMAT, property_data()); 273 printed = true; 274 } 275 st->print_cr(printed ? "" : "(empty)"); 276 } 277 }; 278 279 // A system-internal mapping of symbols to pointers, both managed 280 // and unmanaged. Used to record the auto-generation of each method 281 // MethodHandle.invoke(S)T, for all signatures (S)T. 282 class SymbolPropertyTable : public Hashtable { 283 friend class VMStructs; 284 private: 285 SymbolPropertyEntry* bucket(int i) { 286 return (SymbolPropertyEntry*) Hashtable::bucket(i); 287 } 288 289 // The following method is not MT-safe and must be done under lock. 290 SymbolPropertyEntry** bucket_addr(int i) { 291 return (SymbolPropertyEntry**) Hashtable::bucket_addr(i); 292 } 293 294 void add_entry(int index, SymbolPropertyEntry* new_entry) { 295 ShouldNotReachHere(); 296 } 297 void set_entry(int index, SymbolPropertyEntry* new_entry) { 298 ShouldNotReachHere(); 299 } 300 301 SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol, intptr_t symbol_mode) { 302 SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol); 303 entry->set_symbol_mode(symbol_mode); 304 entry->set_property_oop(NULL); 305 entry->set_property_data(NULL); 306 return entry; 307 } 308 309 public: 310 SymbolPropertyTable(int table_size); 311 SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries); 312 313 void free_entry(SymbolPropertyEntry* entry) { 314 Hashtable::free_entry(entry); 315 } 316 317 unsigned int compute_hash(symbolHandle sym, intptr_t symbol_mode) { 318 // Use the regular identity_hash. 319 return Hashtable::compute_hash(sym) ^ symbol_mode; 320 } 321 322 int index_for(symbolHandle name, intptr_t symbol_mode) { 323 return hash_to_index(compute_hash(name, symbol_mode)); 324 } 325 326 // need not be locked; no state change 327 SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode); 328 329 // must be done under SystemDictionary_lock 330 SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode); 331 332 // GC support 333 void oops_do(OopClosure* f); 334 void methods_do(void f(methodOop)); 335 336 // Sharing support 337 void dump(SerializeOopClosure* soc); 338 void restore(SerializeOopClosure* soc); 339 void reorder_dictionary(); 340 341 #ifndef PRODUCT 342 void print(); 343 #endif 344 void verify(); 345 }; 346 347 348 #endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP