dictionary.cpp revision 1879:f95d63e2154a
11541Srgrimes/*
222521Sdyson * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
322521Sdyson * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41541Srgrimes *
51541Srgrimes * This code is free software; you can redistribute it and/or modify it
61541Srgrimes * under the terms of the GNU General Public License version 2 only, as
71541Srgrimes * published by the Free Software Foundation.
81541Srgrimes *
91541Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
101541Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111541Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
121541Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
131541Srgrimes * accompanied this code).
141541Srgrimes *
151541Srgrimes * You should have received a copy of the GNU General Public License version
161541Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
171541Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
181541Srgrimes *
191541Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
201541Srgrimes * or visit www.oracle.com if you need additional information or have any
211541Srgrimes * questions.
221541Srgrimes *
231541Srgrimes */
241541Srgrimes
251541Srgrimes#include "precompiled.hpp"
261541Srgrimes#include "classfile/dictionary.hpp"
271541Srgrimes#include "classfile/systemDictionary.hpp"
281541Srgrimes#include "oops/oop.inline.hpp"
291541Srgrimes#include "prims/jvmtiRedefineClassesTrace.hpp"
301541Srgrimes#include "services/classLoadingService.hpp"
311541Srgrimes#include "utilities/hashtable.inline.hpp"
321541Srgrimes
331541Srgrimes
341541SrgrimesDictionaryEntry*  Dictionary::_current_class_entry = NULL;
351541Srgrimesint               Dictionary::_current_class_index =    0;
361541Srgrimes
3722521Sdyson
3850477SpeterDictionary::Dictionary(int table_size)
391541Srgrimes  : TwoOopHashtable(table_size, sizeof(DictionaryEntry)) {
401541Srgrimes  _current_class_index = 0;
411541Srgrimes  _current_class_entry = NULL;
421541Srgrimes};
431541Srgrimes
441541Srgrimes
451541Srgrimes
461541SrgrimesDictionary::Dictionary(int table_size, HashtableBucket* t,
472979Swollman                       int number_of_entries)
4878906Sjhb  : TwoOopHashtable(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
4978906Sjhb  _current_class_index = 0;
501541Srgrimes  _current_class_entry = NULL;
511541Srgrimes};
521541Srgrimes
531541Srgrimes
541541SrgrimesDictionaryEntry* Dictionary::new_entry(unsigned int hash, klassOop klass,
551541Srgrimes                                       oop loader) {
5677031Sru  DictionaryEntry* entry;
571541Srgrimes  entry = (DictionaryEntry*)Hashtable::new_entry(hash, klass);
5830354Sphk  entry->set_loader(loader);
5930354Sphk  entry->set_pd_set(NULL);
6022521Sdyson  return entry;
6131273Sphk}
6212595Sbde
6331273Sphk
6431273SphkDictionaryEntry* Dictionary::new_entry() {
6512595Sbde  DictionaryEntry* entry = (DictionaryEntry*)Hashtable::new_entry(0L, NULL);
6631273Sphk  entry->set_loader(NULL);
6712595Sbde  entry->set_pd_set(NULL);
6812595Sbde  return entry;
691541Srgrimes}
701541Srgrimes
711541Srgrimes
7231273Sphkvoid Dictionary::free_entry(DictionaryEntry* entry) {
731541Srgrimes  // avoid recursion when deleting linked list
741541Srgrimes  while (entry->pd_set() != NULL) {
751541Srgrimes    ProtectionDomainEntry* to_delete = entry->pd_set();
761541Srgrimes    entry->set_pd_set(to_delete->next());
771541Srgrimes    delete to_delete;
781541Srgrimes  }
791541Srgrimes  Hashtable::free_entry(entry);
801541Srgrimes}
811541Srgrimes
821541Srgrimes
831541Srgrimesbool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
8422521Sdyson#ifdef ASSERT
851541Srgrimes  if (protection_domain == instanceKlass::cast(klass())->protection_domain()) {
861549Srgrimes    // Ensure this doesn't show up in the pd_set (invariant)
871541Srgrimes    bool in_pd_set = false;
881541Srgrimes    for (ProtectionDomainEntry* current = _pd_set;
891541Srgrimes                                current != NULL;
9051688Sdillon                                current = current->next()) {
911541Srgrimes      if (current->protection_domain() == protection_domain) {
921541Srgrimes        in_pd_set = true;
9329888Skato        break;
9429888Skato      }
9529888Skato    }
9629888Skato    if (in_pd_set) {
9729888Skato      assert(false, "A klass's protection domain should not show up "
981541Srgrimes                    "in its sys. dict. PD set");
991541Srgrimes    }
1001541Srgrimes  }
1011541Srgrimes#endif /* ASSERT */
1021541Srgrimes
1031541Srgrimes  if (protection_domain == instanceKlass::cast(klass())->protection_domain()) {
1041541Srgrimes    // Succeeds trivially
1051541Srgrimes    return true;
1061541Srgrimes  }
1071541Srgrimes
1081541Srgrimes  for (ProtectionDomainEntry* current = _pd_set;
1091541Srgrimes                              current != NULL;
1101541Srgrimes                              current = current->next()) {
1111541Srgrimes    if (current->protection_domain() == protection_domain) return true;
1121541Srgrimes  }
1133496Sphk  return false;
1143496Sphk}
1151541Srgrimes
1161541Srgrimes
11751688Sdillonvoid DictionaryEntry::add_protection_domain(oop protection_domain) {
11851688Sdillon  assert_locked_or_safepoint(SystemDictionary_lock);
11951688Sdillon  if (!contains_protection_domain(protection_domain)) {
12051688Sdillon    ProtectionDomainEntry* new_head =
12151688Sdillon                new ProtectionDomainEntry(protection_domain, _pd_set);
1221541Srgrimes    // Warning: Preserve store ordering.  The SystemDictionary is read
1231541Srgrimes    //          without locks.  The new ProtectionDomainEntry must be
1241541Srgrimes    //          complete before other threads can be allowed to see it
12551688Sdillon    //          via a store to _pd_set.
1261541Srgrimes    OrderAccess::release_store_ptr(&_pd_set, new_head);
12724921Skato  }
12824921Skato  if (TraceProtectionDomainVerification && WizardMode) {
12932598Skato    print();
13024921Skato  }
13151688Sdillon}
13224921Skato
13324921Skato
13451688Sdillonbool Dictionary::do_unloading(BoolObjectClosure* is_alive) {
13551688Sdillon  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
1361541Srgrimes  bool class_was_unloaded = false;
1371541Srgrimes  int  index = 0; // Defined here for portability! Do not move
1381541Srgrimes
1391541Srgrimes  // Remove unloadable entries and classes from system dictionary
1403496Sphk  // The placeholder array has been handled in always_strong_oops_do.
14151688Sdillon  DictionaryEntry* probe = NULL;
14251688Sdillon  for (index = 0; index < table_size(); index++) {
14332598Skato    for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
14424921Skato      probe = *p;
14551688Sdillon      klassOop e = probe->klass();
1463496Sphk      oop class_loader = probe->loader();
1471541Srgrimes
1481541Srgrimes      instanceKlass* ik = instanceKlass::cast(e);
14954655Seivind      if (ik->previous_versions() != NULL) {
1501541Srgrimes        // This klass has previous versions so see what we can cleanup
1511541Srgrimes        // while it is safe to do so.
1521541Srgrimes
1531541Srgrimes        int gc_count = 0;    // leave debugging breadcrumbs
15454444Seivind        int live_count = 0;
15554444Seivind
15651688Sdillon        // RC_TRACE macro has an embedded ResourceMark
15724921Skato        RC_TRACE(0x00000200, ("unload: %s: previous version length=%d",
15824921Skato          ik->external_name(), ik->previous_versions()->length()));
15951688Sdillon
16024921Skato        for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
16124921Skato          // check the previous versions array for GC'ed weak refs
16225016Skato          PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
16325016Skato          jobject cp_ref = pv_node->prev_constant_pool();
16425016Skato          assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
16524921Skato          if (cp_ref == NULL) {
16624921Skato            delete pv_node;
16724921Skato            ik->previous_versions()->remove_at(i);
16824921Skato            // Since we are traversing the array backwards, we don't have to
1691541Srgrimes            // do anything special with the index.
1701541Srgrimes            continue;  // robustness
1711541Srgrimes          }
1721541Srgrimes
1738876Srgrimes          constantPoolOop pvcp = (constantPoolOop)JNIHandles::resolve(cp_ref);
1741541Srgrimes          if (pvcp == NULL) {
17551688Sdillon            // this entry has been GC'ed so remove it
17651688Sdillon            delete pv_node;
17751688Sdillon            ik->previous_versions()->remove_at(i);
17851688Sdillon            // Since we are traversing the array backwards, we don't have to
17951688Sdillon            // do anything special with the index.
18051688Sdillon            gc_count++;
1811541Srgrimes            continue;
1821541Srgrimes          } else {
18351688Sdillon            RC_TRACE(0x00000200, ("unload: previous version @%d is alive", i));
18469781Sdwmalone            if (is_alive->do_object_b(pvcp)) {
18551688Sdillon              live_count++;
1861541Srgrimes            } else {
18751688Sdillon              guarantee(false, "sanity check");
1881541Srgrimes            }
1891541Srgrimes          }
1901541Srgrimes
1911541Srgrimes          GrowableArray<jweak>* method_refs = pv_node->prev_EMCP_methods();
19251688Sdillon          if (method_refs != NULL) {
19351688Sdillon            RC_TRACE(0x00000200, ("unload: previous methods length=%d",
1941541Srgrimes              method_refs->length()));
1951541Srgrimes            for (int j = method_refs->length() - 1; j >= 0; j--) {
1961541Srgrimes              jweak method_ref = method_refs->at(j);
1971541Srgrimes              assert(method_ref != NULL, "weak method ref was unexpectedly cleared");
1981541Srgrimes              if (method_ref == NULL) {
19951688Sdillon                method_refs->remove_at(j);
20051688Sdillon                // Since we are traversing the array backwards, we don't have to
2011541Srgrimes                // do anything special with the index.
2021541Srgrimes                continue;  // robustness
2031541Srgrimes              }
2041541Srgrimes
20551688Sdillon              methodOop method = (methodOop)JNIHandles::resolve(method_ref);
2061541Srgrimes              if (method == NULL) {
2071541Srgrimes                // this method entry has been GC'ed so remove it
20851688Sdillon                JNIHandles::destroy_weak_global(method_ref);
2091541Srgrimes                method_refs->remove_at(j);
2101541Srgrimes              } else {
2111541Srgrimes                // RC_TRACE macro has an embedded ResourceMark
2121541Srgrimes                RC_TRACE(0x00000200,
2131541Srgrimes                  ("unload: %s(%s): prev method @%d in version @%d is alive",
2141541Srgrimes                  method->name()->as_C_string(),
2151541Srgrimes                  method->signature()->as_C_string(), j, i));
21622521Sdyson              }
21722521Sdyson            }
21822521Sdyson          }
21922521Sdyson        }
22022521Sdyson        assert(ik->previous_versions()->length() == live_count, "sanity check");
22151688Sdillon        RC_TRACE(0x00000200,
22222521Sdyson          ("unload: previous version stats: live=%d, GC'ed=%d", live_count,
22322521Sdyson          gc_count));
22422521Sdyson      }
22522521Sdyson
22622521Sdyson      // Non-unloadable classes were handled in always_strong_oops_do
22722521Sdyson      if (!is_strongly_reachable(class_loader, e)) {
2281541Srgrimes        // Entry was not visited in phase1 (negated test from phase1)
2291541Srgrimes        assert(class_loader != NULL, "unloading entry with null class loader");
2301541Srgrimes        oop k_def_class_loader = ik->class_loader();
2311541Srgrimes
2321541Srgrimes        // Do we need to delete this system dictionary entry?
2331541Srgrimes        bool purge_entry = false;
2341541Srgrimes
2351541Srgrimes        // Do we need to delete this system dictionary entry?
2361541Srgrimes        if (!is_alive->do_object_b(class_loader)) {
2371541Srgrimes          // If the loader is not live this entry should always be
2381541Srgrimes          // removed (will never be looked up again). Note that this is
2391541Srgrimes          // not the same as unloading the referred class.
2401541Srgrimes          if (k_def_class_loader == class_loader) {
2411541Srgrimes            // This is the defining entry, so the referred class is about
2421541Srgrimes            // to be unloaded.
2431541Srgrimes            // Notify the debugger and clean up the class.
2441541Srgrimes            guarantee(!is_alive->do_object_b(e),
2451541Srgrimes                      "klass should not be live if defining loader is not");
2461541Srgrimes            class_was_unloaded = true;
2471541Srgrimes            // notify the debugger
2481541Srgrimes            if (JvmtiExport::should_post_class_unload()) {
24935256Sdes              JvmtiExport::post_class_unload(ik->as_klassOop());
2501541Srgrimes            }
2511541Srgrimes
2521541Srgrimes            // notify ClassLoadingService of class unload
2531541Srgrimes            ClassLoadingService::notify_class_unloaded(ik);
2541541Srgrimes
2551541Srgrimes            // Clean up C heap
25622521Sdyson            ik->release_C_heap_structures();
2571541Srgrimes          }
2581541Srgrimes          // Also remove this system dictionary entry.
2591541Srgrimes          purge_entry = true;
26022521Sdyson
2611541Srgrimes        } else {
2621541Srgrimes          // The loader in this entry is alive. If the klass is dead,
26322521Sdyson          // the loader must be an initiating loader (rather than the
2641541Srgrimes          // defining loader). Remove this entry.
2651541Srgrimes          if (!is_alive->do_object_b(e)) {
2661541Srgrimes            guarantee(!is_alive->do_object_b(k_def_class_loader),
2671541Srgrimes                      "defining loader should not be live if klass is not");
2681541Srgrimes            // If we get here, the class_loader must not be the defining
2691541Srgrimes            // loader, it must be an initiating one.
2701541Srgrimes            assert(k_def_class_loader != class_loader,
2711541Srgrimes                   "cannot have live defining loader and unreachable klass");
2721541Srgrimes
2731541Srgrimes            // Loader is live, but class and its defining loader are dead.
2741541Srgrimes            // Remove the entry. The class is going away.
2751541Srgrimes            purge_entry = true;
2761541Srgrimes          }
2771541Srgrimes        }
2784140Sdg
2794140Sdg        if (purge_entry) {
28051688Sdillon          *p = probe->next();
28151688Sdillon          if (probe == _current_class_entry) {
2821541Srgrimes            _current_class_entry = NULL;
2831541Srgrimes          }
2841541Srgrimes          free_entry(probe);
28551688Sdillon          continue;
28651688Sdillon        }
28751688Sdillon      }
28851688Sdillon      p = probe->next_addr();
28951688Sdillon    }
29051688Sdillon  }
29130354Sphk  return class_was_unloaded;
29251688Sdillon}
2931541Srgrimes
2941541Srgrimes
2951541Srgrimesvoid Dictionary::always_strong_classes_do(OopClosure* blk) {
2961541Srgrimes  // Follow all system classes and temporary placeholders in dictionary
2971541Srgrimes  for (int index = 0; index < table_size(); index++) {
2981541Srgrimes    for (DictionaryEntry *probe = bucket(index);
2991541Srgrimes                          probe != NULL;
3001541Srgrimes                          probe = probe->next()) {
3011541Srgrimes      oop e = probe->klass();
3021541Srgrimes      oop class_loader = probe->loader();
3031541Srgrimes      if (is_strongly_reachable(class_loader, e)) {
3041541Srgrimes        blk->do_oop((oop*)probe->klass_addr());
30531273Sphk        if (class_loader != NULL) {
3061541Srgrimes          blk->do_oop(probe->loader_addr());
3071541Srgrimes        }
3081541Srgrimes        probe->protection_domain_set_oops_do(blk);
3091541Srgrimes      }
3101541Srgrimes    }
3111541Srgrimes  }
3121541Srgrimes}
31322521Sdyson
3141541Srgrimes
3151541Srgrimes//   Just the classes from defining class loaders
31651688Sdillonvoid Dictionary::classes_do(void f(klassOop)) {
3171541Srgrimes  for (int index = 0; index < table_size(); index++) {
31822521Sdyson    for (DictionaryEntry* probe = bucket(index);
31922521Sdyson                          probe != NULL;
32022521Sdyson                          probe = probe->next()) {
32122521Sdyson      klassOop k = probe->klass();
32222521Sdyson      if (probe->loader() == instanceKlass::cast(k)->class_loader()) {
32322521Sdyson        f(k);
32422521Sdyson      }
32522521Sdyson    }
32622521Sdyson  }
32722521Sdyson}
32822521Sdyson
32922521Sdyson// Added for initialize_itable_for_klass to handle exceptions
33076688Siedowse//   Just the classes from defining class loaders
33122521Sdysonvoid Dictionary::classes_do(void f(klassOop, TRAPS), TRAPS) {
33222521Sdyson  for (int index = 0; index < table_size(); index++) {
33322521Sdyson    for (DictionaryEntry* probe = bucket(index);
33422521Sdyson                          probe != NULL;
33578906Sjhb                          probe = probe->next()) {
33676688Siedowse      klassOop k = probe->klass();
33776688Siedowse      if (probe->loader() == instanceKlass::cast(k)->class_loader()) {
33822521Sdyson        f(k, CHECK);
33978906Sjhb      }
34022521Sdyson    }
34122521Sdyson  }
34222521Sdyson}
34322521Sdyson
34422521Sdyson
34522521Sdyson//   All classes, and their class loaders
34622521Sdyson//   (added for helpers that use HandleMarks and ResourceMarks)
3471541Srgrimes// Don't iterate over placeholders
3481541Srgrimesvoid Dictionary::classes_do(void f(klassOop, oop, TRAPS), TRAPS) {
34976688Siedowse  for (int index = 0; index < table_size(); index++) {
35076688Siedowse    for (DictionaryEntry* probe = bucket(index);
35176688Siedowse                          probe != NULL;
3521541Srgrimes                          probe = probe->next()) {
3531541Srgrimes      klassOop k = probe->klass();
3541541Srgrimes      f(k, probe->loader(), CHECK);
3551541Srgrimes    }
3561541Srgrimes  }
3571541Srgrimes}
3581541Srgrimes
3591541Srgrimes
3601541Srgrimes//   All classes, and their class loaders
3611541Srgrimes// Don't iterate over placeholders
3621541Srgrimesvoid Dictionary::classes_do(void f(klassOop, oop)) {
36330354Sphk  for (int index = 0; index < table_size(); index++) {
3641541Srgrimes    for (DictionaryEntry* probe = bucket(index);
3651541Srgrimes                          probe != NULL;
3661541Srgrimes                          probe = probe->next()) {
3671541Srgrimes      klassOop k = probe->klass();
36831273Sphk      f(k, probe->loader());
3691541Srgrimes    }
3701541Srgrimes  }
3711541Srgrimes}
3721541Srgrimes
3731541Srgrimes
3741541Srgrimesvoid Dictionary::oops_do(OopClosure* f) {
3751541Srgrimes  for (int index = 0; index < table_size(); index++) {
3761541Srgrimes    for (DictionaryEntry* probe = bucket(index);
37751688Sdillon                          probe != NULL;
37851688Sdillon                          probe = probe->next()) {
37951688Sdillon      f->do_oop((oop*)probe->klass_addr());
38051688Sdillon      if (probe->loader() != NULL) {
3811541Srgrimes        f->do_oop(probe->loader_addr());
38254444Seivind      }
38354444Seivind      probe->protection_domain_set_oops_do(f);
38451688Sdillon    }
3851541Srgrimes  }
3861541Srgrimes}
3871541Srgrimes
3881541Srgrimes
38951688Sdillonvoid Dictionary::methods_do(void f(methodOop)) {
39051688Sdillon  for (int index = 0; index < table_size(); index++) {
39151688Sdillon    for (DictionaryEntry* probe = bucket(index);
39254444Seivind                          probe != NULL;
39354444Seivind                          probe = probe->next()) {
3941541Srgrimes      klassOop k = probe->klass();
3951541Srgrimes      if (probe->loader() == instanceKlass::cast(k)->class_loader()) {
3961541Srgrimes        // only take klass is we have the entry with the defining class loader
3971541Srgrimes        instanceKlass::cast(k)->methods_do(f);
39831273Sphk      }
3991541Srgrimes    }
4001541Srgrimes  }
4011541Srgrimes}
4021541Srgrimes
4031541Srgrimes
4041541SrgrimesklassOop Dictionary::try_get_next_class() {
4051541Srgrimes  while (true) {
4061541Srgrimes    if (_current_class_entry != NULL) {
4071541Srgrimes      klassOop k = _current_class_entry->klass();
4081541Srgrimes      _current_class_entry = _current_class_entry->next();
40951688Sdillon      return k;
41051688Sdillon    }
4111541Srgrimes    _current_class_index = (_current_class_index + 1) % table_size();
4121541Srgrimes    _current_class_entry = bucket(_current_class_index);
4131541Srgrimes  }
4141541Srgrimes  // never reached
4151541Srgrimes}
4161541Srgrimes
4171541Srgrimes
4181541Srgrimes// Add a loaded class to the system dictionary.
4191541Srgrimes// Readers of the SystemDictionary aren't always locked, so _buckets
4201541Srgrimes// is volatile. The store of the next field in the constructor is
4211541Srgrimes// also cast to volatile;  we do this to ensure store order is maintained
4221541Srgrimes// by the compilers.
4231541Srgrimes
4241541Srgrimesvoid Dictionary::add_klass(symbolHandle class_name, Handle class_loader,
4251541Srgrimes                           KlassHandle obj) {
4261541Srgrimes  assert_locked_or_safepoint(SystemDictionary_lock);
4271541Srgrimes  assert(obj() != NULL, "adding NULL obj");
4281541Srgrimes  assert(Klass::cast(obj())->name() == class_name(), "sanity check on name");
4291541Srgrimes
4301541Srgrimes  unsigned int hash = compute_hash(class_name, class_loader);
4311541Srgrimes  int index = hash_to_index(hash);
4321541Srgrimes  DictionaryEntry* entry = new_entry(hash, obj(), class_loader());
4331541Srgrimes  add_entry(index, entry);
4341541Srgrimes}
4351541Srgrimes
4361541Srgrimes
4371541Srgrimes// This routine does not lock the system dictionary.
4381541Srgrimes//
4391541Srgrimes// Since readers don't hold a lock, we must make sure that system
4401541Srgrimes// dictionary entries are only removed at a safepoint (when only one
4411541Srgrimes// thread is running), and are added to in a safe way (all links must
4421541Srgrimes// be updated in an MT-safe manner).
4431541Srgrimes//
4441541Srgrimes// Callers should be aware that an entry could be added just after
4451541Srgrimes// _buckets[index] is read here, so the caller will not see the new entry.
4461541SrgrimesDictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
4471541Srgrimes                                       symbolHandle class_name,
44822521Sdyson                                       Handle class_loader) {
44925535Skato  symbolOop name_ = class_name();
45022521Sdyson  oop loader_ = class_loader();
45122521Sdyson  debug_only(_lookup_count++);
45222521Sdyson  for (DictionaryEntry* entry = bucket(index);
45322521Sdyson                        entry != NULL;
45422521Sdyson                        entry = entry->next()) {
45522521Sdyson    if (entry->hash() == hash && entry->equals(name_, loader_)) {
45622521Sdyson      return entry;
4571541Srgrimes    }
45822521Sdyson    debug_only(_lookup_length++);
45922521Sdyson  }
4601541Srgrimes  return NULL;
46122521Sdyson}
4621541Srgrimes
4631541Srgrimes
46422521SdysonklassOop Dictionary::find(int index, unsigned int hash, symbolHandle name,
4651541Srgrimes                          Handle loader, Handle protection_domain, TRAPS) {
4661541Srgrimes  DictionaryEntry* entry = get_entry(index, hash, name, loader);
4671541Srgrimes  if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
4681541Srgrimes    return entry->klass();
4691541Srgrimes  } else {
4701541Srgrimes    return NULL;
4711541Srgrimes  }
47231273Sphk}
4731541Srgrimes
47451138Salfred
4751541SrgrimesklassOop Dictionary::find_class(int index, unsigned int hash,
4761541Srgrimes                                symbolHandle name, Handle loader) {
47751068Salfred  assert_locked_or_safepoint(SystemDictionary_lock);
4781541Srgrimes  assert (index == index_for(name, loader), "incorrect index?");
47951068Salfred
48051068Salfred  DictionaryEntry* entry = get_entry(index, hash, name, loader);
48151068Salfred  return (entry != NULL) ? entry->klass() : (klassOop)NULL;
48251138Salfred}
48351068Salfred
4841541Srgrimes
48554803Srwatson// Variant of find_class for shared classes.  No locking required, as
48654803Srwatson// that table is static.
4871541Srgrimes
4882946SwollmanklassOop Dictionary::find_shared_class(int index, unsigned int hash,
48977133Sru                                       symbolHandle name) {
490  assert (index == index_for(name, Handle()), "incorrect index?");
491
492  DictionaryEntry* entry = get_entry(index, hash, name, Handle());
493  return (entry != NULL) ? entry->klass() : (klassOop)NULL;
494}
495
496
497void Dictionary::add_protection_domain(int index, unsigned int hash,
498                                       instanceKlassHandle klass,
499                                       Handle loader, Handle protection_domain,
500                                       TRAPS) {
501  symbolHandle klass_name(THREAD, klass->name());
502  DictionaryEntry* entry = get_entry(index, hash, klass_name, loader);
503
504  assert(entry != NULL,"entry must be present, we just created it");
505  assert(protection_domain() != NULL,
506         "real protection domain should be present");
507
508  entry->add_protection_domain(protection_domain());
509
510  assert(entry->contains_protection_domain(protection_domain()),
511         "now protection domain should be present");
512}
513
514
515bool Dictionary::is_valid_protection_domain(int index, unsigned int hash,
516                                            symbolHandle name,
517                                            Handle loader,
518                                            Handle protection_domain) {
519  DictionaryEntry* entry = get_entry(index, hash, name, loader);
520  return entry->is_valid_protection_domain(protection_domain);
521}
522
523
524void Dictionary::reorder_dictionary() {
525
526  // Copy all the dictionary entries into a single master list.
527
528  DictionaryEntry* master_list = NULL;
529  for (int i = 0; i < table_size(); ++i) {
530    DictionaryEntry* p = bucket(i);
531    while (p != NULL) {
532      DictionaryEntry* tmp;
533      tmp = p->next();
534      p->set_next(master_list);
535      master_list = p;
536      p = tmp;
537    }
538    set_entry(i, NULL);
539  }
540
541  // Add the dictionary entries back to the list in the correct buckets.
542  Thread *thread = Thread::current();
543
544  while (master_list != NULL) {
545    DictionaryEntry* p = master_list;
546    master_list = master_list->next();
547    p->set_next(NULL);
548    symbolHandle class_name (thread, instanceKlass::cast((klassOop)(p->klass()))->name());
549    unsigned int hash = compute_hash(class_name, Handle(thread, p->loader()));
550    int index = hash_to_index(hash);
551    p->set_hash(hash);
552    p->set_next(bucket(index));
553    set_entry(index, p);
554  }
555}
556
557SymbolPropertyTable::SymbolPropertyTable(int table_size)
558  : Hashtable(table_size, sizeof(SymbolPropertyEntry))
559{
560}
561SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t,
562                                         int number_of_entries)
563  : Hashtable(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
564{
565}
566
567
568SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
569                                                     symbolHandle sym,
570                                                     intptr_t sym_mode) {
571  assert(index == index_for(sym, sym_mode), "incorrect index?");
572  for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
573    if (p->hash() == hash && p->symbol() == sym() && p->symbol_mode() == sym_mode) {
574      return p;
575    }
576  }
577  return NULL;
578}
579
580
581SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
582                                                    symbolHandle sym, intptr_t sym_mode) {
583  assert_locked_or_safepoint(SystemDictionary_lock);
584  assert(index == index_for(sym, sym_mode), "incorrect index?");
585  assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry");
586
587  SymbolPropertyEntry* p = new_entry(hash, sym(), sym_mode);
588  Hashtable::add_entry(index, p);
589  return p;
590}
591
592
593void SymbolPropertyTable::oops_do(OopClosure* f) {
594  for (int index = 0; index < table_size(); index++) {
595    for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
596      f->do_oop((oop*) p->symbol_addr());
597      if (p->property_oop() != NULL) {
598        f->do_oop(p->property_oop_addr());
599      }
600    }
601  }
602}
603
604void SymbolPropertyTable::methods_do(void f(methodOop)) {
605  for (int index = 0; index < table_size(); index++) {
606    for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
607      oop prop = p->property_oop();
608      if (prop != NULL && prop->is_method()) {
609        f((methodOop)prop);
610      }
611    }
612  }
613}
614
615
616// ----------------------------------------------------------------------------
617#ifndef PRODUCT
618
619void Dictionary::print() {
620  ResourceMark rm;
621  HandleMark   hm;
622
623  tty->print_cr("Java system dictionary (classes=%d)", number_of_entries());
624  tty->print_cr("^ indicates that initiating loader is different from "
625                "defining loader");
626
627  for (int index = 0; index < table_size(); index++) {
628    for (DictionaryEntry* probe = bucket(index);
629                          probe != NULL;
630                          probe = probe->next()) {
631      if (Verbose) tty->print("%4d: ", index);
632      klassOop e = probe->klass();
633      oop class_loader =  probe->loader();
634      bool is_defining_class =
635         (class_loader == instanceKlass::cast(e)->class_loader());
636      tty->print("%s%s", is_defining_class ? " " : "^",
637                   Klass::cast(e)->external_name());
638      if (class_loader != NULL) {
639        tty->print(", loader ");
640        class_loader->print_value();
641      }
642      tty->cr();
643    }
644  }
645}
646
647#endif
648
649void Dictionary::verify() {
650  guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
651  int element_count = 0;
652  for (int index = 0; index < table_size(); index++) {
653    for (DictionaryEntry* probe = bucket(index);
654                          probe != NULL;
655                          probe = probe->next()) {
656      klassOop e = probe->klass();
657      oop class_loader = probe->loader();
658      guarantee(Klass::cast(e)->oop_is_instance(),
659                              "Verify of system dictionary failed");
660      // class loader must be present;  a null class loader is the
661      // boostrap loader
662      guarantee(class_loader == NULL || class_loader->is_instance(),
663                "checking type of class_loader");
664      e->verify();
665      probe->verify_protection_domain_set();
666      element_count++;
667    }
668  }
669  guarantee(number_of_entries() == element_count,
670            "Verify of system dictionary failed");
671  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
672}
673