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