dictionary.cpp revision 2273:1d1603768966
1251877Speter/* 2251877Speter * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 3251877Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4251877Speter * 5251877Speter * This code is free software; you can redistribute it and/or modify it 6251877Speter * under the terms of the GNU General Public License version 2 only, as 7251877Speter * published by the Free Software Foundation. 8251877Speter * 9251877Speter * This code is distributed in the hope that it will be useful, but WITHOUT 10251877Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11251877Speter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12251877Speter * version 2 for more details (a copy is included in the LICENSE file that 13251877Speter * accompanied this code). 14251877Speter * 15251877Speter * You should have received a copy of the GNU General Public License version 16251877Speter * 2 along with this work; if not, write to the Free Software Foundation, 17251877Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18251877Speter * 19251877Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20251877Speter * or visit www.oracle.com if you need additional information or have any 21251877Speter * questions. 22251877Speter * 23251877Speter */ 24251877Speter 25251877Speter#include "precompiled.hpp" 26251877Speter#include "classfile/dictionary.hpp" 27251877Speter#include "classfile/systemDictionary.hpp" 28251877Speter#include "oops/oop.inline.hpp" 29251877Speter#include "prims/jvmtiRedefineClassesTrace.hpp" 30251877Speter#include "services/classLoadingService.hpp" 31251877Speter#include "utilities/hashtable.inline.hpp" 32251877Speter 33251877Speter 34251877SpeterDictionaryEntry* Dictionary::_current_class_entry = NULL; 35251877Speterint Dictionary::_current_class_index = 0; 36251877Speter 37251877Speter 38251877SpeterDictionary::Dictionary(int table_size) 39251877Speter : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry)) { 40251877Speter _current_class_index = 0; 41251877Speter _current_class_entry = NULL; 42251877Speter}; 43251877Speter 44251877Speter 45251877Speter 46251877SpeterDictionary::Dictionary(int table_size, HashtableBucket* t, 47251877Speter int number_of_entries) 48251877Speter : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry), t, number_of_entries) { 49251877Speter _current_class_index = 0; 50251877Speter _current_class_entry = NULL; 51251877Speter}; 52251877Speter 53251877Speter 54251877SpeterDictionaryEntry* Dictionary::new_entry(unsigned int hash, klassOop klass, 55251877Speter oop loader) { 56251877Speter DictionaryEntry* entry; 57251877Speter entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(hash, klass); 58251877Speter entry->set_loader(loader); 59251877Speter entry->set_pd_set(NULL); 60251877Speter return entry; 61251877Speter} 62251877Speter 63251877Speter 64251877SpeterDictionaryEntry* Dictionary::new_entry() { 65251877Speter DictionaryEntry* entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(0L, NULL); 66251877Speter entry->set_loader(NULL); 67251877Speter entry->set_pd_set(NULL); 68251877Speter return entry; 69251877Speter} 70251877Speter 71251877Speter 72251877Spetervoid Dictionary::free_entry(DictionaryEntry* entry) { 73251877Speter // avoid recursion when deleting linked list 74251877Speter while (entry->pd_set() != NULL) { 75251877Speter ProtectionDomainEntry* to_delete = entry->pd_set(); 76251877Speter entry->set_pd_set(to_delete->next()); 77251877Speter delete to_delete; 78251877Speter } 79251877Speter Hashtable<klassOop>::free_entry(entry); 80251877Speter} 81251877Speter 82251877Speter 83251877Speterbool DictionaryEntry::contains_protection_domain(oop protection_domain) const { 84251877Speter#ifdef ASSERT 85251877Speter if (protection_domain == instanceKlass::cast(klass())->protection_domain()) { 86251877Speter // Ensure this doesn't show up in the pd_set (invariant) 87251877Speter bool in_pd_set = false; 88251877Speter for (ProtectionDomainEntry* current = _pd_set; 89251877Speter current != NULL; 90251877Speter current = current->next()) { 91251877Speter if (current->protection_domain() == protection_domain) { 92251877Speter in_pd_set = true; 93251877Speter break; 94251877Speter } 95251877Speter } 96251877Speter if (in_pd_set) { 97251877Speter assert(false, "A klass's protection domain should not show up " 98251877Speter "in its sys. dict. PD set"); 99251877Speter } 100251877Speter } 101251877Speter#endif /* ASSERT */ 102251877Speter 103251877Speter if (protection_domain == instanceKlass::cast(klass())->protection_domain()) { 104251877Speter // Succeeds trivially 105251877Speter return true; 106251877Speter } 107251877Speter 108251877Speter for (ProtectionDomainEntry* current = _pd_set; 109251877Speter current != NULL; 110251877Speter current = current->next()) { 111251877Speter if (current->protection_domain() == protection_domain) return true; 112251877Speter } 113251877Speter return false; 114251877Speter} 115251877Speter 116251877Speter 117251877Spetervoid DictionaryEntry::add_protection_domain(oop protection_domain) { 118251877Speter assert_locked_or_safepoint(SystemDictionary_lock); 119251877Speter if (!contains_protection_domain(protection_domain)) { 120251877Speter ProtectionDomainEntry* new_head = 121251877Speter new ProtectionDomainEntry(protection_domain, _pd_set); 122251877Speter // Warning: Preserve store ordering. The SystemDictionary is read 123251877Speter // without locks. The new ProtectionDomainEntry must be 124251877Speter // complete before other threads can be allowed to see it 125251877Speter // via a store to _pd_set. 126251877Speter OrderAccess::release_store_ptr(&_pd_set, new_head); 127251877Speter } 128251877Speter if (TraceProtectionDomainVerification && WizardMode) { 129251877Speter print(); 130251877Speter } 131251877Speter} 132251877Speter 133251877Speter 134251877Speterbool Dictionary::do_unloading(BoolObjectClosure* is_alive) { 135251877Speter assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); 136251877Speter bool class_was_unloaded = false; 137251877Speter int index = 0; // Defined here for portability! Do not move 138251877Speter 139251877Speter // Remove unloadable entries and classes from system dictionary 140251877Speter // The placeholder array has been handled in always_strong_oops_do. 141251877Speter DictionaryEntry* probe = NULL; 142251877Speter for (index = 0; index < table_size(); index++) { 143251877Speter for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) { 144251877Speter probe = *p; 145251877Speter klassOop e = probe->klass(); 146251877Speter oop class_loader = probe->loader(); 147251877Speter 148251877Speter instanceKlass* ik = instanceKlass::cast(e); 149251877Speter if (ik->previous_versions() != NULL) { 150251877Speter // This klass has previous versions so see what we can cleanup 151251877Speter // while it is safe to do so. 152251877Speter 153251877Speter int gc_count = 0; // leave debugging breadcrumbs 154251877Speter int live_count = 0; 155251877Speter 156251877Speter // RC_TRACE macro has an embedded ResourceMark 157251877Speter RC_TRACE(0x00000200, ("unload: %s: previous version length=%d", 158251877Speter ik->external_name(), ik->previous_versions()->length())); 159251877Speter 160251877Speter for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) { 161251877Speter // check the previous versions array for GC'ed weak refs 162251877Speter PreviousVersionNode * pv_node = ik->previous_versions()->at(i); 163251877Speter jobject cp_ref = pv_node->prev_constant_pool(); 164251877Speter assert(cp_ref != NULL, "cp ref was unexpectedly cleared"); 165251877Speter if (cp_ref == NULL) { 166251877Speter delete pv_node; 167251877Speter ik->previous_versions()->remove_at(i); 168251877Speter // Since we are traversing the array backwards, we don't have to 169251877Speter // do anything special with the index. 170251877Speter continue; // robustness 171251877Speter } 172251877Speter 173251877Speter constantPoolOop pvcp = (constantPoolOop)JNIHandles::resolve(cp_ref); 174251877Speter if (pvcp == NULL) { 175251877Speter // this entry has been GC'ed so remove it 176251877Speter delete pv_node; 177251877Speter ik->previous_versions()->remove_at(i); 178251877Speter // Since we are traversing the array backwards, we don't have to 179251877Speter // do anything special with the index. 180251877Speter gc_count++; 181251877Speter continue; 182251877Speter } else { 183251877Speter RC_TRACE(0x00000200, ("unload: previous version @%d is alive", i)); 184251877Speter if (is_alive->do_object_b(pvcp)) { 185251877Speter live_count++; 186251877Speter } else { 187251877Speter guarantee(false, "sanity check"); 188251877Speter } 189251877Speter } 190251877Speter 191251877Speter GrowableArray<jweak>* method_refs = pv_node->prev_EMCP_methods(); 192251877Speter if (method_refs != NULL) { 193251877Speter RC_TRACE(0x00000200, ("unload: previous methods length=%d", 194251877Speter method_refs->length())); 195251877Speter for (int j = method_refs->length() - 1; j >= 0; j--) { 196251877Speter jweak method_ref = method_refs->at(j); 197251877Speter assert(method_ref != NULL, "weak method ref was unexpectedly cleared"); 198251877Speter if (method_ref == NULL) { 199251877Speter method_refs->remove_at(j); 200251877Speter // Since we are traversing the array backwards, we don't have to 201251877Speter // do anything special with the index. 202251877Speter continue; // robustness 203251877Speter } 204251877Speter 205251877Speter methodOop method = (methodOop)JNIHandles::resolve(method_ref); 206251877Speter if (method == NULL) { 207251877Speter // this method entry has been GC'ed so remove it 208251877Speter JNIHandles::destroy_weak_global(method_ref); 209251877Speter method_refs->remove_at(j); 210251877Speter } else { 211251877Speter // RC_TRACE macro has an embedded ResourceMark 212251877Speter RC_TRACE(0x00000200, 213251877Speter ("unload: %s(%s): prev method @%d in version @%d is alive", 214251877Speter method->name()->as_C_string(), 215251877Speter method->signature()->as_C_string(), j, i)); 216251877Speter } 217251877Speter } 218251877Speter } 219251877Speter } 220251877Speter assert(ik->previous_versions()->length() == live_count, "sanity check"); 221251877Speter RC_TRACE(0x00000200, 222251877Speter ("unload: previous version stats: live=%d, GC'ed=%d", live_count, 223251877Speter gc_count)); 224251877Speter } 225251877Speter 226251877Speter // Non-unloadable classes were handled in always_strong_oops_do 227251877Speter if (!is_strongly_reachable(class_loader, e)) { 228251877Speter // Entry was not visited in phase1 (negated test from phase1) 229251877Speter assert(class_loader != NULL, "unloading entry with null class loader"); 230251877Speter oop k_def_class_loader = ik->class_loader(); 231251877Speter 232251877Speter // Do we need to delete this system dictionary entry? 233251877Speter bool purge_entry = false; 234251877Speter 235251877Speter // Do we need to delete this system dictionary entry? 236251877Speter if (!is_alive->do_object_b(class_loader)) { 237251877Speter // If the loader is not live this entry should always be 238251877Speter // removed (will never be looked up again). Note that this is 239251877Speter // not the same as unloading the referred class. 240251877Speter if (k_def_class_loader == class_loader) { 241251877Speter // This is the defining entry, so the referred class is about 242251877Speter // to be unloaded. 243251877Speter // Notify the debugger and clean up the class. 244251877Speter guarantee(!is_alive->do_object_b(e), 245251877Speter "klass should not be live if defining loader is not"); 246251877Speter class_was_unloaded = true; 247251877Speter // notify the debugger 248251877Speter if (JvmtiExport::should_post_class_unload()) { 249251877Speter JvmtiExport::post_class_unload(ik->as_klassOop()); 250251877Speter } 251251877Speter 252251877Speter // notify ClassLoadingService of class unload 253251877Speter ClassLoadingService::notify_class_unloaded(ik); 254251877Speter 255251877Speter // Clean up C heap 256251877Speter ik->release_C_heap_structures(); 257251877Speter } 258251877Speter // Also remove this system dictionary entry. 259251877Speter purge_entry = true; 260251877Speter 261251877Speter } else { 262251877Speter // The loader in this entry is alive. If the klass is dead, 263251877Speter // the loader must be an initiating loader (rather than the 264251877Speter // defining loader). Remove this entry. 265251877Speter if (!is_alive->do_object_b(e)) { 266251877Speter guarantee(!is_alive->do_object_b(k_def_class_loader), 267251877Speter "defining loader should not be live if klass is not"); 268251877Speter // If we get here, the class_loader must not be the defining 269251877Speter // loader, it must be an initiating one. 270251877Speter assert(k_def_class_loader != class_loader, 271251877Speter "cannot have live defining loader and unreachable klass"); 272251877Speter 273251877Speter // Loader is live, but class and its defining loader are dead. 274251877Speter // Remove the entry. The class is going away. 275251877Speter purge_entry = true; 276251877Speter } 277251877Speter } 278251877Speter 279251877Speter if (purge_entry) { 280251877Speter *p = probe->next(); 281251877Speter if (probe == _current_class_entry) { 282251877Speter _current_class_entry = NULL; 283251877Speter } 284251877Speter free_entry(probe); 285251877Speter continue; 286251877Speter } 287251877Speter } 288251877Speter p = probe->next_addr(); 289251877Speter } 290251877Speter } 291251877Speter return class_was_unloaded; 292251877Speter} 293251877Speter 294251877Speter 295251877Spetervoid Dictionary::always_strong_classes_do(OopClosure* blk) { 296251877Speter // Follow all system classes and temporary placeholders in dictionary 297251877Speter for (int index = 0; index < table_size(); index++) { 298251877Speter for (DictionaryEntry *probe = bucket(index); 299251877Speter probe != NULL; 300251877Speter probe = probe->next()) { 301251877Speter klassOop e = probe->klass(); 302251877Speter oop class_loader = probe->loader(); 303251877Speter if (is_strongly_reachable(class_loader, e)) { 304251877Speter blk->do_oop((oop*)probe->klass_addr()); 305251877Speter if (class_loader != NULL) { 306251877Speter blk->do_oop(probe->loader_addr()); 307251877Speter } 308251877Speter probe->protection_domain_set_oops_do(blk); 309251877Speter } 310251877Speter } 311251877Speter } 312251877Speter} 313251877Speter 314251877Speter 315251877Speter// Just the classes from defining class loaders 316251877Spetervoid Dictionary::classes_do(void f(klassOop)) { 317251877Speter for (int index = 0; index < table_size(); index++) { 318251877Speter for (DictionaryEntry* probe = bucket(index); 319251877Speter probe != NULL; 320251877Speter probe = probe->next()) { 321251877Speter klassOop k = probe->klass(); 322251877Speter if (probe->loader() == instanceKlass::cast(k)->class_loader()) { 323251877Speter f(k); 324251877Speter } 325251877Speter } 326251877Speter } 327251877Speter} 328251877Speter 329251877Speter// Added for initialize_itable_for_klass to handle exceptions 330251877Speter// Just the classes from defining class loaders 331251877Spetervoid Dictionary::classes_do(void f(klassOop, TRAPS), TRAPS) { 332251877Speter for (int index = 0; index < table_size(); index++) { 333251877Speter for (DictionaryEntry* probe = bucket(index); 334251877Speter probe != NULL; 335251877Speter probe = probe->next()) { 336251877Speter klassOop k = probe->klass(); 337251877Speter if (probe->loader() == instanceKlass::cast(k)->class_loader()) { 338251877Speter f(k, CHECK); 339251877Speter } 340251877Speter } 341251877Speter } 342251877Speter} 343251877Speter 344251877Speter 345251877Speter// All classes, and their class loaders 346251877Speter// (added for helpers that use HandleMarks and ResourceMarks) 347251877Speter// Don't iterate over placeholders 348251877Spetervoid Dictionary::classes_do(void f(klassOop, oop, TRAPS), TRAPS) { 349251877Speter for (int index = 0; index < table_size(); index++) { 350251877Speter for (DictionaryEntry* probe = bucket(index); 351251877Speter probe != NULL; 352251877Speter probe = probe->next()) { 353251877Speter klassOop k = probe->klass(); 354251877Speter f(k, probe->loader(), CHECK); 355251877Speter } 356251877Speter } 357251877Speter} 358251877Speter 359251877Speter 360251877Speter// All classes, and their class loaders 361251877Speter// Don't iterate over placeholders 362251877Spetervoid Dictionary::classes_do(void f(klassOop, oop)) { 363251877Speter for (int index = 0; index < table_size(); index++) { 364251877Speter for (DictionaryEntry* probe = bucket(index); 365251877Speter probe != NULL; 366251877Speter probe = probe->next()) { 367251877Speter klassOop k = probe->klass(); 368251877Speter f(k, probe->loader()); 369251877Speter } 370251877Speter } 371251877Speter} 372251877Speter 373251877Speter 374251877Spetervoid Dictionary::oops_do(OopClosure* f) { 375251877Speter for (int index = 0; index < table_size(); index++) { 376251877Speter for (DictionaryEntry* probe = bucket(index); 377251877Speter probe != NULL; 378251877Speter probe = probe->next()) { 379251877Speter f->do_oop((oop*)probe->klass_addr()); 380251877Speter if (probe->loader() != NULL) { 381251877Speter f->do_oop(probe->loader_addr()); 382251877Speter } 383251877Speter probe->protection_domain_set_oops_do(f); 384251877Speter } 385251877Speter } 386251877Speter} 387251877Speter 388251877Speter 389251877Spetervoid Dictionary::methods_do(void f(methodOop)) { 390251877Speter for (int index = 0; index < table_size(); index++) { 391251877Speter for (DictionaryEntry* probe = bucket(index); 392251877Speter probe != NULL; 393251877Speter probe = probe->next()) { 394251877Speter klassOop k = probe->klass(); 395251877Speter if (probe->loader() == instanceKlass::cast(k)->class_loader()) { 396251877Speter // only take klass is we have the entry with the defining class loader 397251877Speter instanceKlass::cast(k)->methods_do(f); 398251877Speter } 399251877Speter } 400251877Speter } 401251877Speter} 402251877Speter 403251877Speter 404251877SpeterklassOop Dictionary::try_get_next_class() { 405251877Speter while (true) { 406251877Speter if (_current_class_entry != NULL) { 407251877Speter klassOop k = _current_class_entry->klass(); 408251877Speter _current_class_entry = _current_class_entry->next(); 409251877Speter return k; 410251877Speter } 411251877Speter _current_class_index = (_current_class_index + 1) % table_size(); 412251877Speter _current_class_entry = bucket(_current_class_index); 413251877Speter } 414251877Speter // never reached 415251877Speter} 416251877Speter 417251877Speter 418251877Speter// Add a loaded class to the system dictionary. 419251877Speter// Readers of the SystemDictionary aren't always locked, so _buckets 420251877Speter// is volatile. The store of the next field in the constructor is 421251877Speter// also cast to volatile; we do this to ensure store order is maintained 422251877Speter// by the compilers. 423251877Speter 424251877Spetervoid Dictionary::add_klass(Symbol* class_name, Handle class_loader, 425251877Speter KlassHandle obj) { 426251877Speter assert_locked_or_safepoint(SystemDictionary_lock); 427251877Speter assert(obj() != NULL, "adding NULL obj"); 428251877Speter assert(Klass::cast(obj())->name() == class_name, "sanity check on name"); 429251877Speter 430251877Speter unsigned int hash = compute_hash(class_name, class_loader); 431251877Speter int index = hash_to_index(hash); 432251877Speter DictionaryEntry* entry = new_entry(hash, obj(), class_loader()); 433251877Speter add_entry(index, entry); 434251877Speter} 435251877Speter 436251877Speter 437251877Speter// This routine does not lock the system dictionary. 438251877Speter// 439251877Speter// Since readers don't hold a lock, we must make sure that system 440251877Speter// dictionary entries are only removed at a safepoint (when only one 441251877Speter// thread is running), and are added to in a safe way (all links must 442251877Speter// be updated in an MT-safe manner). 443251877Speter// 444251877Speter// Callers should be aware that an entry could be added just after 445251877Speter// _buckets[index] is read here, so the caller will not see the new entry. 446251877SpeterDictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, 447251877Speter Symbol* class_name, 448251877Speter Handle class_loader) { 449251877Speter oop loader = class_loader(); 450251877Speter debug_only(_lookup_count++); 451251877Speter for (DictionaryEntry* entry = bucket(index); 452251877Speter entry != NULL; 453251877Speter entry = entry->next()) { 454251877Speter if (entry->hash() == hash && entry->equals(class_name, loader)) { 455251877Speter return entry; 456251877Speter } 457251877Speter debug_only(_lookup_length++); 458251877Speter } 459251877Speter return NULL; 460251877Speter} 461251877Speter 462251877Speter 463251877SpeterklassOop Dictionary::find(int index, unsigned int hash, Symbol* name, 464251877Speter Handle loader, Handle protection_domain, TRAPS) { 465251877Speter DictionaryEntry* entry = get_entry(index, hash, name, loader); 466251877Speter if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) { 467251877Speter return entry->klass(); 468251877Speter } else { 469251877Speter return NULL; 470251877Speter } 471251877Speter} 472251877Speter 473251877Speter 474251877SpeterklassOop Dictionary::find_class(int index, unsigned int hash, 475251877Speter Symbol* name, Handle loader) { 476251877Speter assert_locked_or_safepoint(SystemDictionary_lock); 477251877Speter assert (index == index_for(name, loader), "incorrect index?"); 478251877Speter 479251877Speter DictionaryEntry* entry = get_entry(index, hash, name, loader); 480251877Speter return (entry != NULL) ? entry->klass() : (klassOop)NULL; 481251877Speter} 482251877Speter 483251877Speter 484251877Speter// Variant of find_class for shared classes. No locking required, as 485251877Speter// that table is static. 486251877Speter 487251877SpeterklassOop Dictionary::find_shared_class(int index, unsigned int hash, 488251877Speter Symbol* name) { 489251877Speter assert (index == index_for(name, Handle()), "incorrect index?"); 490251877Speter 491251877Speter DictionaryEntry* entry = get_entry(index, hash, name, Handle()); 492251877Speter return (entry != NULL) ? entry->klass() : (klassOop)NULL; 493251877Speter} 494251877Speter 495251877Speter 496251877Spetervoid Dictionary::add_protection_domain(int index, unsigned int hash, 497251877Speter instanceKlassHandle klass, 498251877Speter Handle loader, Handle protection_domain, 499251877Speter TRAPS) { 500251877Speter Symbol* klass_name = klass->name(); 501251877Speter DictionaryEntry* entry = get_entry(index, hash, klass_name, loader); 502251877Speter 503251877Speter assert(entry != NULL,"entry must be present, we just created it"); 504251877Speter assert(protection_domain() != NULL, 505251877Speter "real protection domain should be present"); 506251877Speter 507251877Speter entry->add_protection_domain(protection_domain()); 508251877Speter 509251877Speter assert(entry->contains_protection_domain(protection_domain()), 510251877Speter "now protection domain should be present"); 511251877Speter} 512251877Speter 513251877Speter 514251877Speterbool Dictionary::is_valid_protection_domain(int index, unsigned int hash, 515251877Speter Symbol* name, 516251877Speter Handle loader, 517251877Speter Handle protection_domain) { 518251877Speter DictionaryEntry* entry = get_entry(index, hash, name, loader); 519251877Speter return entry->is_valid_protection_domain(protection_domain); 520251877Speter} 521251877Speter 522251877Speter 523251877Spetervoid Dictionary::reorder_dictionary() { 524251877Speter 525251877Speter // Copy all the dictionary entries into a single master list. 526251877Speter 527251877Speter DictionaryEntry* master_list = NULL; 528251877Speter for (int i = 0; i < table_size(); ++i) { 529251877Speter DictionaryEntry* p = bucket(i); 530251877Speter while (p != NULL) { 531251877Speter DictionaryEntry* tmp; 532251877Speter tmp = p->next(); 533251877Speter p->set_next(master_list); 534251877Speter master_list = p; 535251877Speter p = tmp; 536251877Speter } 537251877Speter set_entry(i, NULL); 538251877Speter } 539251877Speter 540251877Speter // Add the dictionary entries back to the list in the correct buckets. 541251877Speter Thread *thread = Thread::current(); 542251877Speter 543251877Speter while (master_list != NULL) { 544251877Speter DictionaryEntry* p = master_list; 545251877Speter master_list = master_list->next(); 546251877Speter p->set_next(NULL); 547251877Speter Symbol* class_name = instanceKlass::cast((klassOop)(p->klass()))->name(); 548251877Speter unsigned int hash = compute_hash(class_name, Handle(thread, p->loader())); 549251877Speter int index = hash_to_index(hash); 550251877Speter p->set_hash(hash); 551251877Speter p->set_next(bucket(index)); 552251877Speter set_entry(index, p); 553251877Speter } 554251877Speter} 555251877Speter 556251877SpeterSymbolPropertyTable::SymbolPropertyTable(int table_size) 557251877Speter : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry)) 558251877Speter{ 559251877Speter} 560251877SpeterSymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t, 561251877Speter int number_of_entries) 562251877Speter : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries) 563251877Speter{ 564251877Speter} 565251877Speter 566251877Speter 567251877SpeterSymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash, 568251877Speter Symbol* sym, 569251877Speter intptr_t sym_mode) { 570251877Speter assert(index == index_for(sym, sym_mode), "incorrect index?"); 571251877Speter for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { 572251877Speter if (p->hash() == hash && p->symbol() == sym && p->symbol_mode() == sym_mode) { 573251877Speter return p; 574251877Speter } 575251877Speter } 576251877Speter return NULL; 577251877Speter} 578251877Speter 579251877Speter 580251877SpeterSymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash, 581251877Speter Symbol* sym, intptr_t sym_mode) { 582251877Speter assert_locked_or_safepoint(SystemDictionary_lock); 583251877Speter assert(index == index_for(sym, sym_mode), "incorrect index?"); 584251877Speter assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry"); 585251877Speter 586251877Speter SymbolPropertyEntry* p = new_entry(hash, sym, sym_mode); 587251877Speter Hashtable<Symbol*>::add_entry(index, p); 588251877Speter return p; 589251877Speter} 590251877Speter 591251877Speter 592251877Spetervoid SymbolPropertyTable::oops_do(OopClosure* f) { 593251877Speter for (int index = 0; index < table_size(); index++) { 594251877Speter for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { 595251877Speter if (p->property_oop() != NULL) { 596251877Speter f->do_oop(p->property_oop_addr()); 597 } 598 } 599 } 600} 601 602void SymbolPropertyTable::methods_do(void f(methodOop)) { 603 for (int index = 0; index < table_size(); index++) { 604 for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { 605 oop prop = p->property_oop(); 606 if (prop != NULL && prop->is_method()) { 607 f((methodOop)prop); 608 } 609 } 610 } 611} 612 613 614// ---------------------------------------------------------------------------- 615#ifndef PRODUCT 616 617void Dictionary::print() { 618 ResourceMark rm; 619 HandleMark hm; 620 621 tty->print_cr("Java system dictionary (classes=%d)", number_of_entries()); 622 tty->print_cr("^ indicates that initiating loader is different from " 623 "defining loader"); 624 625 for (int index = 0; index < table_size(); index++) { 626 for (DictionaryEntry* probe = bucket(index); 627 probe != NULL; 628 probe = probe->next()) { 629 if (Verbose) tty->print("%4d: ", index); 630 klassOop e = probe->klass(); 631 oop class_loader = probe->loader(); 632 bool is_defining_class = 633 (class_loader == instanceKlass::cast(e)->class_loader()); 634 tty->print("%s%s", is_defining_class ? " " : "^", 635 Klass::cast(e)->external_name()); 636 if (class_loader != NULL) { 637 tty->print(", loader "); 638 class_loader->print_value(); 639 } 640 tty->cr(); 641 } 642 } 643} 644 645#endif 646 647void Dictionary::verify() { 648 guarantee(number_of_entries() >= 0, "Verify of system dictionary failed"); 649 int element_count = 0; 650 for (int index = 0; index < table_size(); index++) { 651 for (DictionaryEntry* probe = bucket(index); 652 probe != NULL; 653 probe = probe->next()) { 654 klassOop e = probe->klass(); 655 oop class_loader = probe->loader(); 656 guarantee(Klass::cast(e)->oop_is_instance(), 657 "Verify of system dictionary failed"); 658 // class loader must be present; a null class loader is the 659 // boostrap loader 660 guarantee(class_loader == NULL || class_loader->is_instance(), 661 "checking type of class_loader"); 662 e->verify(); 663 probe->verify_protection_domain_set(); 664 element_count++; 665 } 666 } 667 guarantee(number_of_entries() == element_count, 668 "Verify of system dictionary failed"); 669 debug_only(verify_lookup_length((double)number_of_entries() / table_size())); 670} 671